@strapi/i18n 5.0.0-rc.2 → 5.0.0-rc.20
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/dist/_chunks/{SettingsPage-CsGvujny.mjs → SettingsPage-BIZrSFGY.mjs} +6 -6
- package/dist/_chunks/SettingsPage-BIZrSFGY.mjs.map +1 -0
- package/dist/_chunks/{SettingsPage-DA9haizZ.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-CCZJF_EJ.mjs → index-DXrgAtCA.mjs} +331 -127
- package/dist/_chunks/index-DXrgAtCA.mjs.map +1 -0
- package/dist/_chunks/{index-DIzVXZoE.js → index-Dncj9Inq.js} +324 -120
- 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/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-CsGvujny.mjs.map +0 -1
- package/dist/_chunks/SettingsPage-DA9haizZ.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-CCZJF_EJ.mjs.map +0 -1
- package/dist/_chunks/index-DIzVXZoE.js.map +0 -1
- 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,13 +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
9
|
import { skipToken } from "@reduxjs/toolkit/query";
|
10
|
-
import { useAuth, adminApi, useTable, Table, useQueryParams, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
|
10
|
+
import { useAuth, adminApi, useTable, Table, useQueryParams, useForm, useNotification, useAPIErrorHandler } from "@strapi/admin/strapi-admin";
|
11
11
|
import { unstable_useDocument, unstable_useDocumentActions, buildValidParams } from "@strapi/content-manager/strapi-admin";
|
12
12
|
import { useParams, Link, useNavigate, matchPath } from "react-router-dom";
|
13
13
|
import * as qs from "qs";
|
@@ -78,11 +78,11 @@ const CheckboxConfirmation = ({
|
|
78
78
|
}) }) })
|
79
79
|
] }) }),
|
80
80
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
81
|
-
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button
|
81
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
82
82
|
id: "components.popUpWarning.button.cancel",
|
83
83
|
defaultMessage: "No, cancel"
|
84
84
|
}) }) }),
|
85
|
-
/* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button
|
85
|
+
/* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
|
86
86
|
id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
|
87
87
|
defaultMessage: "Yes, disable"
|
88
88
|
}) }) })
|
@@ -217,10 +217,93 @@ const relationsApi = i18nApi.injectEndpoints({
|
|
217
217
|
})
|
218
218
|
});
|
219
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
|
+
};
|
220
299
|
const isErrorMessageDescriptor = (object) => {
|
221
300
|
return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
|
222
301
|
};
|
223
|
-
const EntryValidationText = ({
|
302
|
+
const EntryValidationText = ({
|
303
|
+
status = "draft",
|
304
|
+
validationErrors,
|
305
|
+
action
|
306
|
+
}) => {
|
224
307
|
const { formatMessage } = useIntl();
|
225
308
|
const getErrorStr = (key, value) => {
|
226
309
|
if (typeof value === "string") {
|
@@ -254,30 +337,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
|
|
254
337
|
) })
|
255
338
|
] });
|
256
339
|
}
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
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();
|
275
394
|
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
276
|
-
|
277
|
-
/* @__PURE__ */ jsx(Typography, { children:
|
278
|
-
id: "app.utils.ready-to-publish",
|
279
|
-
defaultMessage: "Ready to publish"
|
280
|
-
}) })
|
395
|
+
icon,
|
396
|
+
/* @__PURE__ */ jsx(Typography, { textColor, fontWeight, children: text })
|
281
397
|
] });
|
282
398
|
};
|
283
399
|
const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
@@ -285,7 +401,8 @@ const BulkLocaleActionModal = ({
|
|
285
401
|
headers,
|
286
402
|
rows,
|
287
403
|
localesMetadata,
|
288
|
-
validationErrors = {}
|
404
|
+
validationErrors = {},
|
405
|
+
action
|
289
406
|
}) => {
|
290
407
|
const { formatMessage } = useIntl();
|
291
408
|
const selectedRows = useTable(
|
@@ -298,22 +415,24 @@ const BulkLocaleActionModal = ({
|
|
298
415
|
return acc;
|
299
416
|
}, {});
|
300
417
|
const localesWithErrors = Object.keys(validationErrors);
|
301
|
-
const
|
418
|
+
const publishedCount = selectedRows.filter(
|
302
419
|
({ locale }) => currentStatusByLocale[locale] === "published"
|
303
420
|
).length;
|
304
|
-
const
|
421
|
+
const draftCount = selectedRows.filter(
|
305
422
|
({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
|
306
423
|
).length;
|
307
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.";
|
308
427
|
return formatMessage(
|
309
428
|
{
|
310
|
-
id:
|
311
|
-
defaultMessage
|
429
|
+
id: messageId,
|
430
|
+
defaultMessage
|
312
431
|
},
|
313
432
|
{
|
314
433
|
withErrorsCount,
|
315
|
-
|
316
|
-
|
434
|
+
draftCount,
|
435
|
+
publishedCount,
|
317
436
|
b: BoldChunk
|
318
437
|
}
|
319
438
|
);
|
@@ -345,7 +464,7 @@ const BulkLocaleActionModal = ({
|
|
345
464
|
children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
|
346
465
|
}
|
347
466
|
) }) }),
|
348
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status }) }),
|
467
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status, action }) }),
|
349
468
|
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
350
469
|
IconButton,
|
351
470
|
{
|
@@ -362,7 +481,7 @@ const BulkLocaleActionModal = ({
|
|
362
481
|
name: locale
|
363
482
|
}
|
364
483
|
),
|
365
|
-
|
484
|
+
variant: "ghost",
|
366
485
|
children: /* @__PURE__ */ jsx(Pencil, {})
|
367
486
|
}
|
368
487
|
) })
|
@@ -382,7 +501,13 @@ const LocalePickerAction = ({
|
|
382
501
|
const [{ query }, setQuery] = useQueryParams();
|
383
502
|
const { hasI18n, canCreate, canRead } = useI18n();
|
384
503
|
const { data: locales = [] } = useGetLocalesQuery();
|
385
|
-
const
|
504
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
505
|
+
const { schema } = unstable_useDocument({
|
506
|
+
model,
|
507
|
+
collectionType,
|
508
|
+
documentId,
|
509
|
+
params: { locale: currentDesiredLocale }
|
510
|
+
});
|
386
511
|
const handleSelect = React.useCallback(
|
387
512
|
(value) => {
|
388
513
|
setQuery({
|
@@ -400,21 +525,20 @@ const LocalePickerAction = ({
|
|
400
525
|
if (!Array.isArray(locales) || !hasI18n) {
|
401
526
|
return;
|
402
527
|
}
|
403
|
-
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
404
528
|
const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
|
405
529
|
const defaultLocale = locales.find((locale) => locale.isDefault);
|
406
530
|
if (!doesLocaleExist && defaultLocale?.code) {
|
407
531
|
handleSelect(defaultLocale.code);
|
408
532
|
}
|
409
|
-
}, [handleSelect, hasI18n, locales,
|
410
|
-
|
411
|
-
return null;
|
412
|
-
}
|
413
|
-
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;
|
414
535
|
const allCurrentLocales = [
|
415
536
|
{ status: getDocumentStatus(document, meta), locale: currentLocale },
|
416
537
|
...meta?.availableLocales ?? []
|
417
538
|
];
|
539
|
+
if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
|
540
|
+
return null;
|
541
|
+
}
|
418
542
|
return {
|
419
543
|
label: formatMessage({
|
420
544
|
id: getTranslation("Settings.locales.modal.locales.label"),
|
@@ -426,7 +550,7 @@ const LocalePickerAction = ({
|
|
426
550
|
);
|
427
551
|
const status = currentLocaleDoc?.status ?? "draft";
|
428
552
|
const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
|
429
|
-
const statusVariant = status === "draft" ? "
|
553
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
430
554
|
return {
|
431
555
|
disabled: !permissionsToCheck.includes(locale.code),
|
432
556
|
value: locale.code,
|
@@ -462,6 +586,95 @@ const getDocumentStatus = (document, meta) => {
|
|
462
586
|
}
|
463
587
|
return docStatus;
|
464
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
|
+
};
|
465
678
|
const DeleteLocaleAction = ({
|
466
679
|
document,
|
467
680
|
documentId,
|
@@ -473,16 +686,23 @@ const DeleteLocaleAction = ({
|
|
473
686
|
const { toggleNotification } = useNotification();
|
474
687
|
const { delete: deleteAction } = unstable_useDocumentActions();
|
475
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);
|
476
693
|
if (!hasI18n) {
|
477
694
|
return null;
|
478
695
|
}
|
479
696
|
return {
|
480
697
|
disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
|
481
698
|
position: ["header", "table-row"],
|
482
|
-
label: formatMessage(
|
483
|
-
|
484
|
-
|
485
|
-
|
699
|
+
label: formatMessage(
|
700
|
+
{
|
701
|
+
id: getTranslation("actions.delete.label"),
|
702
|
+
defaultMessage: "Delete entry ({locale})"
|
703
|
+
},
|
704
|
+
{ locale: locale && locale.name }
|
705
|
+
),
|
486
706
|
icon: /* @__PURE__ */ jsx(StyledTrash, {}),
|
487
707
|
variant: "danger",
|
488
708
|
dialog: {
|
@@ -525,23 +745,24 @@ const DeleteLocaleAction = ({
|
|
525
745
|
}
|
526
746
|
};
|
527
747
|
};
|
528
|
-
const
|
748
|
+
const BulkLocaleAction = ({
|
529
749
|
document: baseDocument,
|
530
750
|
documentId,
|
531
751
|
model,
|
532
|
-
collectionType
|
752
|
+
collectionType,
|
753
|
+
action
|
533
754
|
}) => {
|
534
755
|
const baseLocale = baseDocument?.locale ?? null;
|
535
756
|
const [{ query }] = useQueryParams();
|
536
757
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
537
|
-
const
|
758
|
+
const isOnPublishedTab = query.status === "published";
|
538
759
|
const { formatMessage } = useIntl();
|
539
760
|
const { hasI18n, canPublish } = useI18n();
|
540
761
|
const { toggleNotification } = useNotification();
|
541
762
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
542
763
|
const [selectedRows, setSelectedRows] = React.useState([]);
|
543
764
|
const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
|
544
|
-
const { publishMany: publishManyAction } = unstable_useDocumentActions();
|
765
|
+
const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
|
545
766
|
const {
|
546
767
|
document,
|
547
768
|
meta: documentMeta,
|
@@ -557,7 +778,7 @@ const BulkLocalePublishAction = ({
|
|
557
778
|
}
|
558
779
|
},
|
559
780
|
{
|
560
|
-
skip: !hasI18n
|
781
|
+
skip: !hasI18n || !baseLocale
|
561
782
|
}
|
562
783
|
);
|
563
784
|
const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
|
@@ -609,12 +830,19 @@ const BulkLocalePublishAction = ({
|
|
609
830
|
}, {});
|
610
831
|
return [rowsFromMeta, errors];
|
611
832
|
}, [document, documentMeta?.availableLocales, validate]);
|
612
|
-
const
|
613
|
-
|
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) {
|
614
841
|
acc.push(selectedRow.locale);
|
615
842
|
}
|
616
843
|
return acc;
|
617
844
|
}, []);
|
845
|
+
const enableDraftRelationsCount = false;
|
618
846
|
const {
|
619
847
|
data: draftRelationsCount = 0,
|
620
848
|
isLoading: isDraftRelationsLoading,
|
@@ -623,10 +851,10 @@ const BulkLocalePublishAction = ({
|
|
623
851
|
{
|
624
852
|
model,
|
625
853
|
documentIds: [documentId],
|
626
|
-
locale:
|
854
|
+
locale: localesForAction
|
627
855
|
},
|
628
856
|
{
|
629
|
-
skip: !
|
857
|
+
skip: !enableDraftRelationsCount
|
630
858
|
}
|
631
859
|
);
|
632
860
|
React.useEffect(() => {
|
@@ -652,7 +880,18 @@ const BulkLocalePublishAction = ({
|
|
652
880
|
documentIds: [documentId],
|
653
881
|
params: {
|
654
882
|
...params,
|
655
|
-
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
|
656
895
|
}
|
657
896
|
});
|
658
897
|
setSelectedRows([]);
|
@@ -660,14 +899,12 @@ const BulkLocalePublishAction = ({
|
|
660
899
|
const handleAction = async () => {
|
661
900
|
if (draftRelationsCount > 0) {
|
662
901
|
setIsDraftRelationConfirmationOpen(true);
|
663
|
-
} else {
|
902
|
+
} else if (isBulkPublish) {
|
664
903
|
await publish();
|
904
|
+
} else {
|
905
|
+
await unpublish();
|
665
906
|
}
|
666
907
|
};
|
667
|
-
const isUnpublish = document?.status === "published";
|
668
|
-
if (isUnpublish) {
|
669
|
-
console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
|
670
|
-
}
|
671
908
|
if (isDraftRelationConfirmationOpen) {
|
672
909
|
return {
|
673
910
|
label: formatMessage({
|
@@ -705,18 +942,18 @@ const BulkLocalePublishAction = ({
|
|
705
942
|
const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
|
706
943
|
return {
|
707
944
|
label: formatMessage({
|
708
|
-
id: getTranslation("
|
709
|
-
defaultMessage: "Publish Multiple Locales
|
945
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
946
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
710
947
|
}),
|
711
|
-
|
712
|
-
|
948
|
+
variant: isBulkPublish ? "secondary" : "danger",
|
949
|
+
icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
|
950
|
+
disabled: isOnPublishedTab || canPublish.length === 0,
|
713
951
|
position: ["panel"],
|
714
|
-
variant: "secondary",
|
715
952
|
dialog: {
|
716
953
|
type: "modal",
|
717
954
|
title: formatMessage({
|
718
|
-
id: getTranslation("
|
719
|
-
defaultMessage: "Publish Multiple Locales
|
955
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
956
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
720
957
|
}),
|
721
958
|
content: () => {
|
722
959
|
return /* @__PURE__ */ jsx(
|
@@ -735,28 +972,35 @@ const BulkLocalePublishAction = ({
|
|
735
972
|
validationErrors,
|
736
973
|
headers,
|
737
974
|
rows,
|
738
|
-
localesMetadata
|
975
|
+
localesMetadata,
|
976
|
+
action: action ?? "bulk-publish"
|
739
977
|
}
|
740
978
|
)
|
741
979
|
}
|
742
980
|
);
|
743
981
|
},
|
744
982
|
footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
|
745
|
-
Button
|
983
|
+
Button,
|
746
984
|
{
|
747
985
|
loading: isDraftRelationsLoading,
|
748
|
-
disabled: !hasPermission ||
|
986
|
+
disabled: !hasPermission || localesForAction.length === 0,
|
749
987
|
variant: "default",
|
750
988
|
onClick: handleAction,
|
751
989
|
children: formatMessage({
|
752
|
-
id: "app.utils.publish",
|
753
|
-
defaultMessage: "Publish"
|
990
|
+
id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
|
991
|
+
defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
|
754
992
|
})
|
755
993
|
}
|
756
994
|
) })
|
757
995
|
}
|
758
996
|
};
|
759
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
|
+
};
|
760
1004
|
const StyledTrash = styled(Trash)`
|
761
1005
|
path {
|
762
1006
|
fill: currentColor;
|
@@ -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;
|
@@ -1221,11 +1424,11 @@ const index = {
|
|
1221
1424
|
},
|
1222
1425
|
id: "internationalization",
|
1223
1426
|
to: "internationalization",
|
1224
|
-
Component: () => import("./SettingsPage-
|
1427
|
+
Component: () => import("./SettingsPage-BIZrSFGY.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
|
1225
1428
|
permissions: PERMISSIONS.accessMain
|
1226
1429
|
});
|
1227
1430
|
const contentManager = app.getPlugin("content-manager");
|
1228
|
-
contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
|
1431
|
+
contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
|
1229
1432
|
contentManager.apis.addDocumentAction((actions) => {
|
1230
1433
|
const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
|
1231
1434
|
actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
|
@@ -1233,6 +1436,7 @@ const index = {
|
|
1233
1436
|
});
|
1234
1437
|
contentManager.apis.addDocumentAction((actions) => {
|
1235
1438
|
actions.splice(2, 0, BulkLocalePublishAction);
|
1439
|
+
actions.splice(5, 0, BulkLocaleUnpublishAction);
|
1236
1440
|
return actions;
|
1237
1441
|
});
|
1238
1442
|
contentManager.injectComponent("listView", "actions", {
|
@@ -1338,7 +1542,7 @@ const index = {
|
|
1338
1542
|
async registerTrads({ locales }) {
|
1339
1543
|
const importedTrads = await Promise.all(
|
1340
1544
|
locales.map((locale) => {
|
1341
|
-
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 }) => {
|
1342
1546
|
return {
|
1343
1547
|
data: prefixPluginTranslations(data, pluginId),
|
1344
1548
|
locale
|
@@ -1364,4 +1568,4 @@ export {
|
|
1364
1568
|
index as i,
|
1365
1569
|
useCreateLocaleMutation as u
|
1366
1570
|
};
|
1367
|
-
//# sourceMappingURL=index-
|
1571
|
+
//# sourceMappingURL=index-DXrgAtCA.mjs.map
|