@strapi/i18n 0.0.0-experimental.a53a4b1c8f7981a689823cdd719105671e1c6392 → 0.0.0-experimental.a6728ad43ac70ae19dabb624dbfca1f2d9610a86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -3
- package/dist/_chunks/{SettingsPage-B5sTcP82.mjs → SettingsPage-BIZrSFGY.mjs} +6 -6
- package/dist/_chunks/SettingsPage-BIZrSFGY.mjs.map +1 -0
- package/dist/_chunks/{SettingsPage-DT1sxWa2.js → SettingsPage-kMDCxWLw.js} +6 -6
- package/dist/_chunks/SettingsPage-kMDCxWLw.js.map +1 -0
- package/dist/_chunks/{en-BsOU9o5z.js → en-B6327hMz.js} +8 -2
- package/dist/_chunks/en-B6327hMz.js.map +1 -0
- package/dist/_chunks/{en-CM6Pjfyv.mjs → en-DZXpOMHo.mjs} +8 -2
- package/dist/_chunks/en-DZXpOMHo.mjs.map +1 -0
- package/dist/_chunks/{index-DsNqyQKx.mjs → index-DXrgAtCA.mjs} +348 -146
- package/dist/_chunks/index-DXrgAtCA.mjs.map +1 -0
- package/dist/_chunks/{index-jMrzaEb9.js → index-Dncj9Inq.js} +352 -150
- package/dist/_chunks/index-Dncj9Inq.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/BulkLocaleActionModal.d.ts +2 -1
- package/dist/admin/src/components/CMHeaderActions.d.ts +27 -3
- package/dist/admin/src/utils/clean.d.ts +4 -0
- package/dist/admin/src/utils/schemas.d.ts +1 -0
- package/dist/server/index.js +61 -98
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +62 -99
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts +1 -4
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +15 -13
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +14 -10
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permissions/actions.d.ts +14 -2
- package/dist/server/src/services/permissions/actions.d.ts.map +1 -1
- package/dist/server/src/services/permissions.d.ts +14 -2
- package/dist/server/src/services/permissions.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +0 -2
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/package.json +9 -9
- package/dist/_chunks/SettingsPage-B5sTcP82.mjs.map +0 -1
- package/dist/_chunks/SettingsPage-DT1sxWa2.js.map +0 -1
- package/dist/_chunks/en-BsOU9o5z.js.map +0 -1
- package/dist/_chunks/en-CM6Pjfyv.mjs.map +0 -1
- package/dist/_chunks/index-DsNqyQKx.mjs.map +0 -1
- package/dist/_chunks/index-jMrzaEb9.js.map +0 -1
- package/dist/admin/src/components/Initializer.d.ts +0 -5
- package/dist/server/src/services/entity-service-decorator.d.ts +0 -29
- package/dist/server/src/services/entity-service-decorator.d.ts.map +0 -1
- package/strapi-server.js +0 -3
@@ -1,12 +1,13 @@
|
|
1
1
|
import get from "lodash/get";
|
2
2
|
import * as yup from "yup";
|
3
|
-
import { jsxs, jsx } from "react/jsx-runtime";
|
3
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
4
4
|
import * as React from "react";
|
5
|
-
import { Typography, Dialog, Field, Checkbox, Flex, Button
|
6
|
-
import { WarningCircle, Pencil, CrossCircle, CheckCircle, ArrowsCounterClockwise, Trash, ListPlus, Earth, EarthStriked, CaretDown } from "@strapi/icons";
|
5
|
+
import { Typography, Dialog, Field, Checkbox, Flex, Button, Modal, Box, Status, IconButton, Tooltip, SingleSelect, SingleSelectOption, VisuallyHidden, useCollator, Popover } from "@strapi/design-system";
|
6
|
+
import { WarningCircle, Pencil, CrossCircle, CheckCircle, ArrowsCounterClockwise, Trash, Download, ListPlus, Cross, Earth, EarthStriked, CaretDown } from "@strapi/icons";
|
7
7
|
import { useIntl } from "react-intl";
|
8
8
|
import { styled } from "styled-components";
|
9
|
-
import {
|
9
|
+
import { skipToken } from "@reduxjs/toolkit/query";
|
10
|
+
import { useAuth, adminApi, useTable, Table, useQueryParams, useForm, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
|
10
11
|
import { unstable_useDocument, unstable_useDocumentActions, buildValidParams } from "@strapi/content-manager/strapi-admin";
|
11
12
|
import { useParams, Link, useNavigate, matchPath } from "react-router-dom";
|
12
13
|
import * as qs from "qs";
|
@@ -77,11 +78,11 @@ const CheckboxConfirmation = ({
|
|
77
78
|
}) }) })
|
78
79
|
] }) }),
|
79
80
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
80
|
-
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button
|
81
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
81
82
|
id: "components.popUpWarning.button.cancel",
|
82
83
|
defaultMessage: "No, cancel"
|
83
84
|
}) }) }),
|
84
|
-
/* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button
|
85
|
+
/* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
|
85
86
|
id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
|
86
87
|
defaultMessage: "Yes, disable"
|
87
88
|
}) }) })
|
@@ -136,7 +137,7 @@ const useI18n = () => {
|
|
136
137
|
model: params.slug
|
137
138
|
},
|
138
139
|
{
|
139
|
-
skip:
|
140
|
+
skip: true
|
140
141
|
}
|
141
142
|
);
|
142
143
|
if (doesPluginOptionsHaveI18nLocalized(schema?.pluginOptions)) {
|
@@ -216,10 +217,93 @@ const relationsApi = i18nApi.injectEndpoints({
|
|
216
217
|
})
|
217
218
|
});
|
218
219
|
const { useGetManyDraftRelationCountQuery } = relationsApi;
|
220
|
+
const cleanData = (data, schema, components) => {
|
221
|
+
const cleanedData = removeFields(data, [
|
222
|
+
"createdAt",
|
223
|
+
"createdBy",
|
224
|
+
"updatedAt",
|
225
|
+
"updatedBy",
|
226
|
+
"id",
|
227
|
+
"documentId",
|
228
|
+
"publishedAt",
|
229
|
+
"strapi_stage",
|
230
|
+
"strapi_assignee",
|
231
|
+
"locale"
|
232
|
+
]);
|
233
|
+
const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
|
234
|
+
cleanedData,
|
235
|
+
schema,
|
236
|
+
components,
|
237
|
+
["relation", "password"]
|
238
|
+
);
|
239
|
+
return cleanedDataWithoutPasswordAndRelation;
|
240
|
+
};
|
241
|
+
const removeFields = (data, fields) => {
|
242
|
+
return Object.keys(data).reduce((acc, current) => {
|
243
|
+
if (fields.includes(current)) {
|
244
|
+
return acc;
|
245
|
+
}
|
246
|
+
acc[current] = data[current];
|
247
|
+
return acc;
|
248
|
+
}, {});
|
249
|
+
};
|
250
|
+
const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
|
251
|
+
return Object.keys(data).reduce((acc, current) => {
|
252
|
+
const attribute = schema.attributes[current] ?? { type: void 0 };
|
253
|
+
if (fields.includes(attribute.type)) {
|
254
|
+
return acc;
|
255
|
+
}
|
256
|
+
if (attribute.type === "dynamiczone") {
|
257
|
+
acc[current] = data[current].map((componentValue, index2) => {
|
258
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
259
|
+
componentValue,
|
260
|
+
components[componentValue.__component],
|
261
|
+
components,
|
262
|
+
fields
|
263
|
+
);
|
264
|
+
return {
|
265
|
+
...rest,
|
266
|
+
__temp_key__: index2 + 1
|
267
|
+
};
|
268
|
+
});
|
269
|
+
} else if (attribute.type === "component") {
|
270
|
+
const { repeatable, component } = attribute;
|
271
|
+
if (repeatable) {
|
272
|
+
acc[current] = (data[current] ?? []).map((compoData, index2) => {
|
273
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
274
|
+
compoData,
|
275
|
+
components[component],
|
276
|
+
components,
|
277
|
+
fields
|
278
|
+
);
|
279
|
+
return {
|
280
|
+
...rest,
|
281
|
+
__temp_key__: index2 + 1
|
282
|
+
};
|
283
|
+
});
|
284
|
+
} else {
|
285
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
286
|
+
data[current] ?? {},
|
287
|
+
components[component],
|
288
|
+
components,
|
289
|
+
fields
|
290
|
+
);
|
291
|
+
acc[current] = rest;
|
292
|
+
}
|
293
|
+
} else {
|
294
|
+
acc[current] = data[current];
|
295
|
+
}
|
296
|
+
return acc;
|
297
|
+
}, {});
|
298
|
+
};
|
219
299
|
const isErrorMessageDescriptor = (object) => {
|
220
300
|
return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
|
221
301
|
};
|
222
|
-
const EntryValidationText = ({
|
302
|
+
const EntryValidationText = ({
|
303
|
+
status = "draft",
|
304
|
+
validationErrors,
|
305
|
+
action
|
306
|
+
}) => {
|
223
307
|
const { formatMessage } = useIntl();
|
224
308
|
const getErrorStr = (key, value) => {
|
225
309
|
if (typeof value === "string") {
|
@@ -253,30 +337,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
|
|
253
337
|
) })
|
254
338
|
] });
|
255
339
|
}
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
340
|
+
const getStatusMessage = () => {
|
341
|
+
if (action === "bulk-publish") {
|
342
|
+
if (status === "published") {
|
343
|
+
return {
|
344
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
345
|
+
text: formatMessage({
|
346
|
+
id: "content-manager.bulk-publish.already-published",
|
347
|
+
defaultMessage: "Already Published"
|
348
|
+
}),
|
349
|
+
textColor: "success600",
|
350
|
+
fontWeight: "bold"
|
351
|
+
};
|
352
|
+
} else if (status === "modified") {
|
353
|
+
return {
|
354
|
+
icon: /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
|
355
|
+
text: formatMessage({
|
356
|
+
id: "app.utils.ready-to-publish-changes",
|
357
|
+
defaultMessage: "Ready to publish changes"
|
358
|
+
})
|
359
|
+
};
|
360
|
+
} else {
|
361
|
+
return {
|
362
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
363
|
+
text: formatMessage({
|
364
|
+
id: "app.utils.ready-to-publish",
|
365
|
+
defaultMessage: "Ready to publish"
|
366
|
+
})
|
367
|
+
};
|
368
|
+
}
|
369
|
+
} else {
|
370
|
+
if (status === "draft") {
|
371
|
+
return {
|
372
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
373
|
+
text: formatMessage({
|
374
|
+
id: "content-manager.bulk-unpublish.already-unpublished",
|
375
|
+
defaultMessage: "Already Unpublished"
|
376
|
+
}),
|
377
|
+
textColor: "success600",
|
378
|
+
fontWeight: "bold"
|
379
|
+
};
|
380
|
+
} else {
|
381
|
+
return {
|
382
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
383
|
+
text: formatMessage({
|
384
|
+
id: "app.utils.ready-to-unpublish-changes",
|
385
|
+
defaultMessage: "Ready to unpublish"
|
386
|
+
}),
|
387
|
+
textColor: "success600",
|
388
|
+
fontWeight: "bold"
|
389
|
+
};
|
390
|
+
}
|
391
|
+
}
|
392
|
+
};
|
393
|
+
const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
|
274
394
|
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
275
|
-
|
276
|
-
/* @__PURE__ */ jsx(Typography, { children:
|
277
|
-
id: "app.utils.ready-to-publish",
|
278
|
-
defaultMessage: "Ready to publish"
|
279
|
-
}) })
|
395
|
+
icon,
|
396
|
+
/* @__PURE__ */ jsx(Typography, { textColor, fontWeight, children: text })
|
280
397
|
] });
|
281
398
|
};
|
282
399
|
const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
@@ -284,7 +401,8 @@ const BulkLocaleActionModal = ({
|
|
284
401
|
headers,
|
285
402
|
rows,
|
286
403
|
localesMetadata,
|
287
|
-
validationErrors = {}
|
404
|
+
validationErrors = {},
|
405
|
+
action
|
288
406
|
}) => {
|
289
407
|
const { formatMessage } = useIntl();
|
290
408
|
const selectedRows = useTable(
|
@@ -297,27 +415,29 @@ const BulkLocaleActionModal = ({
|
|
297
415
|
return acc;
|
298
416
|
}, {});
|
299
417
|
const localesWithErrors = Object.keys(validationErrors);
|
300
|
-
const
|
418
|
+
const publishedCount = selectedRows.filter(
|
301
419
|
({ locale }) => currentStatusByLocale[locale] === "published"
|
302
420
|
).length;
|
303
|
-
const
|
421
|
+
const draftCount = selectedRows.filter(
|
304
422
|
({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
|
305
423
|
).length;
|
306
424
|
const withErrorsCount = localesWithErrors.length;
|
425
|
+
const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
|
426
|
+
const defaultMessage = action === "bulk-publish" ? "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action." : "<b>{draftCount}</b> {draftCount, plural, =0 {entries} one {entry} other {entries}} already unpublished. <b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} ready to unpublish.";
|
307
427
|
return formatMessage(
|
308
428
|
{
|
309
|
-
id:
|
310
|
-
defaultMessage
|
429
|
+
id: messageId,
|
430
|
+
defaultMessage
|
311
431
|
},
|
312
432
|
{
|
313
433
|
withErrorsCount,
|
314
|
-
|
315
|
-
|
434
|
+
draftCount,
|
435
|
+
publishedCount,
|
316
436
|
b: BoldChunk
|
317
437
|
}
|
318
438
|
);
|
319
439
|
};
|
320
|
-
return /* @__PURE__ */ jsxs(
|
440
|
+
return /* @__PURE__ */ jsxs(Modal.Body, { children: [
|
321
441
|
/* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
|
322
442
|
/* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsxs(Table.Content, { children: [
|
323
443
|
/* @__PURE__ */ jsxs(Table.Head, { children: [
|
@@ -344,7 +464,7 @@ const BulkLocaleActionModal = ({
|
|
344
464
|
children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
|
345
465
|
}
|
346
466
|
) }) }),
|
347
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status }) }),
|
467
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status, action }) }),
|
348
468
|
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
349
469
|
IconButton,
|
350
470
|
{
|
@@ -361,7 +481,7 @@ const BulkLocaleActionModal = ({
|
|
361
481
|
name: locale
|
362
482
|
}
|
363
483
|
),
|
364
|
-
|
484
|
+
variant: "ghost",
|
365
485
|
children: /* @__PURE__ */ jsx(Pencil, {})
|
366
486
|
}
|
367
487
|
) })
|
@@ -381,7 +501,13 @@ const LocalePickerAction = ({
|
|
381
501
|
const [{ query }, setQuery] = useQueryParams();
|
382
502
|
const { hasI18n, canCreate, canRead } = useI18n();
|
383
503
|
const { data: locales = [] } = useGetLocalesQuery();
|
384
|
-
const
|
504
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
505
|
+
const { schema } = unstable_useDocument({
|
506
|
+
model,
|
507
|
+
collectionType,
|
508
|
+
documentId,
|
509
|
+
params: { locale: currentDesiredLocale }
|
510
|
+
});
|
385
511
|
const handleSelect = React.useCallback(
|
386
512
|
(value) => {
|
387
513
|
setQuery({
|
@@ -399,21 +525,20 @@ const LocalePickerAction = ({
|
|
399
525
|
if (!Array.isArray(locales) || !hasI18n) {
|
400
526
|
return;
|
401
527
|
}
|
402
|
-
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
403
528
|
const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
|
404
529
|
const defaultLocale = locales.find((locale) => locale.isDefault);
|
405
530
|
if (!doesLocaleExist && defaultLocale?.code) {
|
406
531
|
handleSelect(defaultLocale.code);
|
407
532
|
}
|
408
|
-
}, [handleSelect, hasI18n, locales,
|
409
|
-
|
410
|
-
return null;
|
411
|
-
}
|
412
|
-
const currentLocale = query.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
|
533
|
+
}, [handleSelect, hasI18n, locales, currentDesiredLocale]);
|
534
|
+
const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale)?.code : void 0;
|
413
535
|
const allCurrentLocales = [
|
414
536
|
{ status: getDocumentStatus(document, meta), locale: currentLocale },
|
415
537
|
...meta?.availableLocales ?? []
|
416
538
|
];
|
539
|
+
if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
|
540
|
+
return null;
|
541
|
+
}
|
417
542
|
return {
|
418
543
|
label: formatMessage({
|
419
544
|
id: getTranslation("Settings.locales.modal.locales.label"),
|
@@ -425,7 +550,7 @@ const LocalePickerAction = ({
|
|
425
550
|
);
|
426
551
|
const status = currentLocaleDoc?.status ?? "draft";
|
427
552
|
const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
|
428
|
-
const statusVariant = status === "draft" ? "
|
553
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
429
554
|
return {
|
430
555
|
disabled: !permissionsToCheck.includes(locale.code),
|
431
556
|
value: locale.code,
|
@@ -461,6 +586,95 @@ const getDocumentStatus = (document, meta) => {
|
|
461
586
|
}
|
462
587
|
return docStatus;
|
463
588
|
};
|
589
|
+
const FillFromAnotherLocaleAction = ({
|
590
|
+
documentId,
|
591
|
+
meta,
|
592
|
+
model,
|
593
|
+
collectionType
|
594
|
+
}) => {
|
595
|
+
const { formatMessage } = useIntl();
|
596
|
+
const [{ query }] = useQueryParams();
|
597
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
598
|
+
const [localeSelected, setLocaleSelected] = React.useState(null);
|
599
|
+
const setValues = useForm("FillFromAnotherLocale", (state) => state.setValues);
|
600
|
+
const { getDocument } = unstable_useDocumentActions();
|
601
|
+
const { schema, components } = unstable_useDocument({
|
602
|
+
model,
|
603
|
+
documentId,
|
604
|
+
collectionType,
|
605
|
+
params: { locale: currentDesiredLocale }
|
606
|
+
});
|
607
|
+
const { data: locales = [] } = useGetLocalesQuery();
|
608
|
+
const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
|
609
|
+
const fillFromLocale = (onClose) => async () => {
|
610
|
+
const response = await getDocument({
|
611
|
+
collectionType,
|
612
|
+
model,
|
613
|
+
documentId,
|
614
|
+
params: { locale: localeSelected }
|
615
|
+
});
|
616
|
+
if (!response || !schema) {
|
617
|
+
return;
|
618
|
+
}
|
619
|
+
const { data } = response;
|
620
|
+
const cleanedData = cleanData(data, schema, components);
|
621
|
+
setValues(cleanedData);
|
622
|
+
onClose();
|
623
|
+
};
|
624
|
+
return {
|
625
|
+
type: "icon",
|
626
|
+
icon: /* @__PURE__ */ jsx(Download, {}),
|
627
|
+
disabled: availableLocales.length === 0,
|
628
|
+
label: formatMessage({
|
629
|
+
id: getTranslation("CMEditViewCopyLocale.copy-text"),
|
630
|
+
defaultMessage: "Fill in from another locale"
|
631
|
+
}),
|
632
|
+
dialog: {
|
633
|
+
type: "dialog",
|
634
|
+
title: formatMessage({
|
635
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.title"),
|
636
|
+
defaultMessage: "Confirmation"
|
637
|
+
}),
|
638
|
+
content: ({ onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
639
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
|
640
|
+
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
641
|
+
/* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
|
642
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.body"),
|
643
|
+
defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
|
644
|
+
}) }),
|
645
|
+
/* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
|
646
|
+
/* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
|
647
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
|
648
|
+
defaultMessage: "Locale"
|
649
|
+
}) }),
|
650
|
+
/* @__PURE__ */ jsx(
|
651
|
+
SingleSelect,
|
652
|
+
{
|
653
|
+
value: localeSelected,
|
654
|
+
placeholder: formatMessage({
|
655
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
|
656
|
+
defaultMessage: "Select one locale..."
|
657
|
+
}),
|
658
|
+
onChange: (value) => setLocaleSelected(value),
|
659
|
+
children: availableLocales.map((locale) => /* @__PURE__ */ jsx(SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
|
660
|
+
}
|
661
|
+
)
|
662
|
+
] })
|
663
|
+
] }) }),
|
664
|
+
/* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, width: "100%", children: [
|
665
|
+
/* @__PURE__ */ jsx(Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
|
666
|
+
id: getTranslation("CMEditViewCopyLocale.cancel-text"),
|
667
|
+
defaultMessage: "No, cancel"
|
668
|
+
}) }),
|
669
|
+
/* @__PURE__ */ jsx(Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
|
670
|
+
id: getTranslation("CMEditViewCopyLocale.submit-text"),
|
671
|
+
defaultMessage: "Yes, fill in"
|
672
|
+
}) })
|
673
|
+
] }) })
|
674
|
+
] })
|
675
|
+
}
|
676
|
+
};
|
677
|
+
};
|
464
678
|
const DeleteLocaleAction = ({
|
465
679
|
document,
|
466
680
|
documentId,
|
@@ -472,16 +686,23 @@ const DeleteLocaleAction = ({
|
|
472
686
|
const { toggleNotification } = useNotification();
|
473
687
|
const { delete: deleteAction } = unstable_useDocumentActions();
|
474
688
|
const { hasI18n, canDelete } = useI18n();
|
689
|
+
const [{ query }] = useQueryParams();
|
690
|
+
const { data: locales = [] } = useGetLocalesQuery();
|
691
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
692
|
+
const locale = !("error" in locales) && locales.find((loc) => loc.code === currentDesiredLocale);
|
475
693
|
if (!hasI18n) {
|
476
694
|
return null;
|
477
695
|
}
|
478
696
|
return {
|
479
697
|
disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
|
480
698
|
position: ["header", "table-row"],
|
481
|
-
label: formatMessage(
|
482
|
-
|
483
|
-
|
484
|
-
|
699
|
+
label: formatMessage(
|
700
|
+
{
|
701
|
+
id: getTranslation("actions.delete.label"),
|
702
|
+
defaultMessage: "Delete entry ({locale})"
|
703
|
+
},
|
704
|
+
{ locale: locale && locale.name }
|
705
|
+
),
|
485
706
|
icon: /* @__PURE__ */ jsx(StyledTrash, {}),
|
486
707
|
variant: "danger",
|
487
708
|
dialog: {
|
@@ -524,37 +745,43 @@ const DeleteLocaleAction = ({
|
|
524
745
|
}
|
525
746
|
};
|
526
747
|
};
|
527
|
-
const
|
748
|
+
const BulkLocaleAction = ({
|
528
749
|
document: baseDocument,
|
529
750
|
documentId,
|
530
751
|
model,
|
531
|
-
collectionType
|
752
|
+
collectionType,
|
753
|
+
action
|
532
754
|
}) => {
|
533
755
|
const baseLocale = baseDocument?.locale ?? null;
|
534
756
|
const [{ query }] = useQueryParams();
|
535
757
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
536
|
-
const
|
758
|
+
const isOnPublishedTab = query.status === "published";
|
537
759
|
const { formatMessage } = useIntl();
|
538
760
|
const { hasI18n, canPublish } = useI18n();
|
539
761
|
const { toggleNotification } = useNotification();
|
540
762
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
541
763
|
const [selectedRows, setSelectedRows] = React.useState([]);
|
542
764
|
const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
|
543
|
-
const { publishMany: publishManyAction } = unstable_useDocumentActions();
|
765
|
+
const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
|
544
766
|
const {
|
545
767
|
document,
|
546
768
|
meta: documentMeta,
|
547
769
|
schema,
|
548
770
|
validate
|
549
|
-
} = unstable_useDocument(
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
771
|
+
} = unstable_useDocument(
|
772
|
+
{
|
773
|
+
model,
|
774
|
+
collectionType,
|
775
|
+
documentId,
|
776
|
+
params: {
|
777
|
+
locale: baseLocale
|
778
|
+
}
|
779
|
+
},
|
780
|
+
{
|
781
|
+
skip: !hasI18n || !baseLocale
|
555
782
|
}
|
556
|
-
|
557
|
-
const { data: localesMetadata = [] } = useGetLocalesQuery();
|
783
|
+
);
|
784
|
+
const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
|
558
785
|
const headers = [
|
559
786
|
{
|
560
787
|
label: formatMessage({
|
@@ -603,12 +830,19 @@ const BulkLocalePublishAction = ({
|
|
603
830
|
}, {});
|
604
831
|
return [rowsFromMeta, errors];
|
605
832
|
}, [document, documentMeta?.availableLocales, validate]);
|
606
|
-
const
|
607
|
-
|
833
|
+
const isBulkPublish = action === "bulk-publish";
|
834
|
+
const localesForAction = selectedRows.reduce((acc, selectedRow) => {
|
835
|
+
const isValidLocale = (
|
836
|
+
// Validation errors are irrelevant if we are trying to unpublish
|
837
|
+
!isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
|
838
|
+
);
|
839
|
+
const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
|
840
|
+
if (shouldAddLocale) {
|
608
841
|
acc.push(selectedRow.locale);
|
609
842
|
}
|
610
843
|
return acc;
|
611
844
|
}, []);
|
845
|
+
const enableDraftRelationsCount = false;
|
612
846
|
const {
|
613
847
|
data: draftRelationsCount = 0,
|
614
848
|
isLoading: isDraftRelationsLoading,
|
@@ -617,10 +851,10 @@ const BulkLocalePublishAction = ({
|
|
617
851
|
{
|
618
852
|
model,
|
619
853
|
documentIds: [documentId],
|
620
|
-
locale:
|
854
|
+
locale: localesForAction
|
621
855
|
},
|
622
856
|
{
|
623
|
-
skip: !
|
857
|
+
skip: !enableDraftRelationsCount
|
624
858
|
}
|
625
859
|
);
|
626
860
|
React.useEffect(() => {
|
@@ -646,7 +880,18 @@ const BulkLocalePublishAction = ({
|
|
646
880
|
documentIds: [documentId],
|
647
881
|
params: {
|
648
882
|
...params,
|
649
|
-
locale:
|
883
|
+
locale: localesForAction
|
884
|
+
}
|
885
|
+
});
|
886
|
+
setSelectedRows([]);
|
887
|
+
};
|
888
|
+
const unpublish = async () => {
|
889
|
+
await unpublishManyAction({
|
890
|
+
model,
|
891
|
+
documentIds: [documentId],
|
892
|
+
params: {
|
893
|
+
...params,
|
894
|
+
locale: localesForAction
|
650
895
|
}
|
651
896
|
});
|
652
897
|
setSelectedRows([]);
|
@@ -654,14 +899,12 @@ const BulkLocalePublishAction = ({
|
|
654
899
|
const handleAction = async () => {
|
655
900
|
if (draftRelationsCount > 0) {
|
656
901
|
setIsDraftRelationConfirmationOpen(true);
|
657
|
-
} else {
|
902
|
+
} else if (isBulkPublish) {
|
658
903
|
await publish();
|
904
|
+
} else {
|
905
|
+
await unpublish();
|
659
906
|
}
|
660
907
|
};
|
661
|
-
const isUnpublish = document?.status === "published";
|
662
|
-
if (isUnpublish) {
|
663
|
-
console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
|
664
|
-
}
|
665
908
|
if (isDraftRelationConfirmationOpen) {
|
666
909
|
return {
|
667
910
|
label: formatMessage({
|
@@ -696,20 +939,21 @@ const BulkLocalePublishAction = ({
|
|
696
939
|
}
|
697
940
|
};
|
698
941
|
}
|
942
|
+
const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
|
699
943
|
return {
|
700
944
|
label: formatMessage({
|
701
|
-
id: getTranslation("
|
702
|
-
defaultMessage: "Publish Multiple Locales
|
945
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
946
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
703
947
|
}),
|
704
|
-
|
705
|
-
|
948
|
+
variant: isBulkPublish ? "secondary" : "danger",
|
949
|
+
icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
|
950
|
+
disabled: isOnPublishedTab || canPublish.length === 0,
|
706
951
|
position: ["panel"],
|
707
|
-
variant: "secondary",
|
708
952
|
dialog: {
|
709
953
|
type: "modal",
|
710
954
|
title: formatMessage({
|
711
|
-
id: getTranslation("
|
712
|
-
defaultMessage: "Publish Multiple Locales
|
955
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
956
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
713
957
|
}),
|
714
958
|
content: () => {
|
715
959
|
return /* @__PURE__ */ jsx(
|
@@ -728,28 +972,35 @@ const BulkLocalePublishAction = ({
|
|
728
972
|
validationErrors,
|
729
973
|
headers,
|
730
974
|
rows,
|
731
|
-
localesMetadata
|
975
|
+
localesMetadata,
|
976
|
+
action: action ?? "bulk-publish"
|
732
977
|
}
|
733
978
|
)
|
734
979
|
}
|
735
980
|
);
|
736
981
|
},
|
737
|
-
footer: () => /* @__PURE__ */ jsx(
|
738
|
-
Button
|
982
|
+
footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
|
983
|
+
Button,
|
739
984
|
{
|
740
985
|
loading: isDraftRelationsLoading,
|
741
|
-
disabled:
|
986
|
+
disabled: !hasPermission || localesForAction.length === 0,
|
742
987
|
variant: "default",
|
743
988
|
onClick: handleAction,
|
744
989
|
children: formatMessage({
|
745
|
-
id: "app.utils.publish",
|
746
|
-
defaultMessage: "Publish"
|
990
|
+
id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
|
991
|
+
defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
|
747
992
|
})
|
748
993
|
}
|
749
994
|
) })
|
750
995
|
}
|
751
996
|
};
|
752
997
|
};
|
998
|
+
const BulkLocalePublishAction = (props) => {
|
999
|
+
return BulkLocaleAction({ action: "bulk-publish", ...props });
|
1000
|
+
};
|
1001
|
+
const BulkLocaleUnpublishAction = (props) => {
|
1002
|
+
return BulkLocaleAction({ action: "bulk-unpublish", ...props });
|
1003
|
+
};
|
753
1004
|
const StyledTrash = styled(Trash)`
|
754
1005
|
path {
|
755
1006
|
fill: currentColor;
|
@@ -806,13 +1057,6 @@ const UnpublishModalAdditionalInfo = () => {
|
|
806
1057
|
}
|
807
1058
|
) });
|
808
1059
|
};
|
809
|
-
const Initializer = ({ setPlugin }) => {
|
810
|
-
const setPluginRef = React.useRef(setPlugin);
|
811
|
-
React.useEffect(() => {
|
812
|
-
setPluginRef.current(pluginId);
|
813
|
-
}, []);
|
814
|
-
return null;
|
815
|
-
};
|
816
1060
|
const LocalePicker = () => {
|
817
1061
|
const { formatMessage } = useIntl();
|
818
1062
|
const [{ query }, setQuery] = useQueryParams();
|
@@ -976,54 +1220,13 @@ const LocaleListCell = ({
|
|
976
1220
|
return locale.name;
|
977
1221
|
}).toSorted((a, b) => formatter.compare(a, b));
|
978
1222
|
return /* @__PURE__ */ jsxs(Popover.Root, { children: [
|
979
|
-
/* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(Button, { type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs(
|
980
|
-
|
981
|
-
{
|
982
|
-
|
983
|
-
alignItems: "center",
|
984
|
-
justifyContent: "center",
|
985
|
-
height: "3.2rem",
|
986
|
-
width: "3.2rem",
|
987
|
-
children: [
|
988
|
-
/* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, children: localesForDocument.join(", ") }),
|
989
|
-
/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, {}) })
|
990
|
-
]
|
991
|
-
}
|
992
|
-
) }) }),
|
1223
|
+
/* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(Button, { variant: "ghost", type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs(Flex, { minWidth: "100%", alignItems: "center", justifyContent: "center", fontWeight: "regular", children: [
|
1224
|
+
/* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
|
1225
|
+
/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) })
|
1226
|
+
] }) }) }),
|
993
1227
|
/* @__PURE__ */ jsx(Popover.Content, { sideOffset: 16, children: /* @__PURE__ */ jsx("ul", { children: localesForDocument.map((name) => /* @__PURE__ */ jsx(Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsx(Typography, { children: name }) }, name)) }) })
|
994
1228
|
] });
|
995
1229
|
};
|
996
|
-
const Button = styled.button`
|
997
|
-
width: 100%;
|
998
|
-
|
999
|
-
svg {
|
1000
|
-
> g,
|
1001
|
-
path {
|
1002
|
-
fill: ${({ theme }) => theme.colors.neutral500};
|
1003
|
-
}
|
1004
|
-
}
|
1005
|
-
&:hover {
|
1006
|
-
svg {
|
1007
|
-
> g,
|
1008
|
-
path {
|
1009
|
-
fill: ${({ theme }) => theme.colors.neutral600};
|
1010
|
-
}
|
1011
|
-
}
|
1012
|
-
}
|
1013
|
-
&:active {
|
1014
|
-
svg {
|
1015
|
-
> g,
|
1016
|
-
path {
|
1017
|
-
fill: ${({ theme }) => theme.colors.neutral400};
|
1018
|
-
}
|
1019
|
-
}
|
1020
|
-
}
|
1021
|
-
`;
|
1022
|
-
const ActionWrapper = styled(Flex)`
|
1023
|
-
svg {
|
1024
|
-
height: 0.4rem;
|
1025
|
-
}
|
1026
|
-
`;
|
1027
1230
|
const addColumnToTableHook = ({ displayedHeaders, layout }) => {
|
1028
1231
|
const { options } = layout;
|
1029
1232
|
const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
|
@@ -1204,8 +1407,6 @@ const index = {
|
|
1204
1407
|
app.addRBACMiddleware([localeMiddleware]);
|
1205
1408
|
app.registerPlugin({
|
1206
1409
|
id: pluginId,
|
1207
|
-
initializer: Initializer,
|
1208
|
-
isReady: false,
|
1209
1410
|
name: pluginId
|
1210
1411
|
});
|
1211
1412
|
},
|
@@ -1223,11 +1424,11 @@ const index = {
|
|
1223
1424
|
},
|
1224
1425
|
id: "internationalization",
|
1225
1426
|
to: "internationalization",
|
1226
|
-
Component: () => import("./SettingsPage-
|
1427
|
+
Component: () => import("./SettingsPage-BIZrSFGY.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
|
1227
1428
|
permissions: PERMISSIONS.accessMain
|
1228
1429
|
});
|
1229
1430
|
const contentManager = app.getPlugin("content-manager");
|
1230
|
-
contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
|
1431
|
+
contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
|
1231
1432
|
contentManager.apis.addDocumentAction((actions) => {
|
1232
1433
|
const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
|
1233
1434
|
actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
|
@@ -1235,6 +1436,7 @@ const index = {
|
|
1235
1436
|
});
|
1236
1437
|
contentManager.apis.addDocumentAction((actions) => {
|
1237
1438
|
actions.splice(2, 0, BulkLocalePublishAction);
|
1439
|
+
actions.splice(5, 0, BulkLocaleUnpublishAction);
|
1238
1440
|
return actions;
|
1239
1441
|
});
|
1240
1442
|
contentManager.injectComponent("listView", "actions", {
|
@@ -1340,7 +1542,7 @@ const index = {
|
|
1340
1542
|
async registerTrads({ locales }) {
|
1341
1543
|
const importedTrads = await Promise.all(
|
1342
1544
|
locales.map((locale) => {
|
1343
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-9eCAqqrB.mjs"), "./translations/dk.json": () => import("./dk-2qBjxt-P.mjs"), "./translations/en.json": () => import("./en-
|
1545
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-9eCAqqrB.mjs"), "./translations/dk.json": () => import("./dk-2qBjxt-P.mjs"), "./translations/en.json": () => import("./en-DZXpOMHo.mjs"), "./translations/es.json": () => import("./es-DlmMVaBG.mjs"), "./translations/fr.json": () => import("./fr-3S6ke71d.mjs"), "./translations/ko.json": () => import("./ko-qTjQ8IMw.mjs"), "./translations/pl.json": () => import("./pl-B67TSHqT.mjs"), "./translations/ru.json": () => import("./ru-hagMa57T.mjs"), "./translations/tr.json": () => import("./tr-Dw_jmkG-.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-Dyc-aR-h.mjs"), "./translations/zh.json": () => import("./zh-57YM4amO.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
|
1344
1546
|
return {
|
1345
1547
|
data: prefixPluginTranslations(data, pluginId),
|
1346
1548
|
locale
|
@@ -1366,4 +1568,4 @@ export {
|
|
1366
1568
|
index as i,
|
1367
1569
|
useCreateLocaleMutation as u
|
1368
1570
|
};
|
1369
|
-
//# sourceMappingURL=index-
|
1571
|
+
//# sourceMappingURL=index-DXrgAtCA.mjs.map
|