@strapi/i18n 5.0.0-rc.2 → 5.0.0-rc.21
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-4-K93FBe.mjs} +6 -6
- package/dist/_chunks/SettingsPage-4-K93FBe.mjs.map +1 -0
- package/dist/_chunks/{SettingsPage-DA9haizZ.js → SettingsPage-Cfi_zf_I.js} +6 -6
- package/dist/_chunks/SettingsPage-Cfi_zf_I.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-B2uG3lvD.mjs} +332 -127
- package/dist/_chunks/index-B2uG3lvD.mjs.map +1 -0
- package/dist/_chunks/{index-DIzVXZoE.js → index-DpT683lz.js} +325 -120
- package/dist/_chunks/index-DpT683lz.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,94 @@ 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
|
+
"status"
|
233
|
+
]);
|
234
|
+
const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
|
235
|
+
cleanedData,
|
236
|
+
schema,
|
237
|
+
components,
|
238
|
+
["relation", "password"]
|
239
|
+
);
|
240
|
+
return cleanedDataWithoutPasswordAndRelation;
|
241
|
+
};
|
242
|
+
const removeFields = (data, fields) => {
|
243
|
+
return Object.keys(data).reduce((acc, current) => {
|
244
|
+
if (fields.includes(current)) {
|
245
|
+
return acc;
|
246
|
+
}
|
247
|
+
acc[current] = data[current];
|
248
|
+
return acc;
|
249
|
+
}, {});
|
250
|
+
};
|
251
|
+
const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
|
252
|
+
return Object.keys(data).reduce((acc, current) => {
|
253
|
+
const attribute = schema.attributes[current] ?? { type: void 0 };
|
254
|
+
if (fields.includes(attribute.type)) {
|
255
|
+
return acc;
|
256
|
+
}
|
257
|
+
if (attribute.type === "dynamiczone") {
|
258
|
+
acc[current] = data[current].map((componentValue, index2) => {
|
259
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
260
|
+
componentValue,
|
261
|
+
components[componentValue.__component],
|
262
|
+
components,
|
263
|
+
fields
|
264
|
+
);
|
265
|
+
return {
|
266
|
+
...rest,
|
267
|
+
__temp_key__: index2 + 1
|
268
|
+
};
|
269
|
+
});
|
270
|
+
} else if (attribute.type === "component") {
|
271
|
+
const { repeatable, component } = attribute;
|
272
|
+
if (repeatable) {
|
273
|
+
acc[current] = (data[current] ?? []).map((compoData, index2) => {
|
274
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
275
|
+
compoData,
|
276
|
+
components[component],
|
277
|
+
components,
|
278
|
+
fields
|
279
|
+
);
|
280
|
+
return {
|
281
|
+
...rest,
|
282
|
+
__temp_key__: index2 + 1
|
283
|
+
};
|
284
|
+
});
|
285
|
+
} else {
|
286
|
+
const { id: _, ...rest } = recursiveRemoveFieldTypes(
|
287
|
+
data[current] ?? {},
|
288
|
+
components[component],
|
289
|
+
components,
|
290
|
+
fields
|
291
|
+
);
|
292
|
+
acc[current] = rest;
|
293
|
+
}
|
294
|
+
} else {
|
295
|
+
acc[current] = data[current];
|
296
|
+
}
|
297
|
+
return acc;
|
298
|
+
}, {});
|
299
|
+
};
|
220
300
|
const isErrorMessageDescriptor = (object) => {
|
221
301
|
return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
|
222
302
|
};
|
223
|
-
const EntryValidationText = ({
|
303
|
+
const EntryValidationText = ({
|
304
|
+
status = "draft",
|
305
|
+
validationErrors,
|
306
|
+
action
|
307
|
+
}) => {
|
224
308
|
const { formatMessage } = useIntl();
|
225
309
|
const getErrorStr = (key, value) => {
|
226
310
|
if (typeof value === "string") {
|
@@ -254,30 +338,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
|
|
254
338
|
) })
|
255
339
|
] });
|
256
340
|
}
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
341
|
+
const getStatusMessage = () => {
|
342
|
+
if (action === "bulk-publish") {
|
343
|
+
if (status === "published") {
|
344
|
+
return {
|
345
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
346
|
+
text: formatMessage({
|
347
|
+
id: "content-manager.bulk-publish.already-published",
|
348
|
+
defaultMessage: "Already Published"
|
349
|
+
}),
|
350
|
+
textColor: "success600",
|
351
|
+
fontWeight: "bold"
|
352
|
+
};
|
353
|
+
} else if (status === "modified") {
|
354
|
+
return {
|
355
|
+
icon: /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
|
356
|
+
text: formatMessage({
|
357
|
+
id: "app.utils.ready-to-publish-changes",
|
358
|
+
defaultMessage: "Ready to publish changes"
|
359
|
+
})
|
360
|
+
};
|
361
|
+
} else {
|
362
|
+
return {
|
363
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
364
|
+
text: formatMessage({
|
365
|
+
id: "app.utils.ready-to-publish",
|
366
|
+
defaultMessage: "Ready to publish"
|
367
|
+
})
|
368
|
+
};
|
369
|
+
}
|
370
|
+
} else {
|
371
|
+
if (status === "draft") {
|
372
|
+
return {
|
373
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
374
|
+
text: formatMessage({
|
375
|
+
id: "content-manager.bulk-unpublish.already-unpublished",
|
376
|
+
defaultMessage: "Already Unpublished"
|
377
|
+
}),
|
378
|
+
textColor: "success600",
|
379
|
+
fontWeight: "bold"
|
380
|
+
};
|
381
|
+
} else {
|
382
|
+
return {
|
383
|
+
icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
384
|
+
text: formatMessage({
|
385
|
+
id: "app.utils.ready-to-unpublish-changes",
|
386
|
+
defaultMessage: "Ready to unpublish"
|
387
|
+
}),
|
388
|
+
textColor: "success600",
|
389
|
+
fontWeight: "bold"
|
390
|
+
};
|
391
|
+
}
|
392
|
+
}
|
393
|
+
};
|
394
|
+
const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
|
275
395
|
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
|
-
}) })
|
396
|
+
icon,
|
397
|
+
/* @__PURE__ */ jsx(Typography, { textColor, fontWeight, children: text })
|
281
398
|
] });
|
282
399
|
};
|
283
400
|
const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
@@ -285,7 +402,8 @@ const BulkLocaleActionModal = ({
|
|
285
402
|
headers,
|
286
403
|
rows,
|
287
404
|
localesMetadata,
|
288
|
-
validationErrors = {}
|
405
|
+
validationErrors = {},
|
406
|
+
action
|
289
407
|
}) => {
|
290
408
|
const { formatMessage } = useIntl();
|
291
409
|
const selectedRows = useTable(
|
@@ -298,22 +416,24 @@ const BulkLocaleActionModal = ({
|
|
298
416
|
return acc;
|
299
417
|
}, {});
|
300
418
|
const localesWithErrors = Object.keys(validationErrors);
|
301
|
-
const
|
419
|
+
const publishedCount = selectedRows.filter(
|
302
420
|
({ locale }) => currentStatusByLocale[locale] === "published"
|
303
421
|
).length;
|
304
|
-
const
|
422
|
+
const draftCount = selectedRows.filter(
|
305
423
|
({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
|
306
424
|
).length;
|
307
425
|
const withErrorsCount = localesWithErrors.length;
|
426
|
+
const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
|
427
|
+
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
428
|
return formatMessage(
|
309
429
|
{
|
310
|
-
id:
|
311
|
-
defaultMessage
|
430
|
+
id: messageId,
|
431
|
+
defaultMessage
|
312
432
|
},
|
313
433
|
{
|
314
434
|
withErrorsCount,
|
315
|
-
|
316
|
-
|
435
|
+
draftCount,
|
436
|
+
publishedCount,
|
317
437
|
b: BoldChunk
|
318
438
|
}
|
319
439
|
);
|
@@ -345,7 +465,7 @@ const BulkLocaleActionModal = ({
|
|
345
465
|
children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
|
346
466
|
}
|
347
467
|
) }) }),
|
348
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status }) }),
|
468
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status, action }) }),
|
349
469
|
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
350
470
|
IconButton,
|
351
471
|
{
|
@@ -362,7 +482,7 @@ const BulkLocaleActionModal = ({
|
|
362
482
|
name: locale
|
363
483
|
}
|
364
484
|
),
|
365
|
-
|
485
|
+
variant: "ghost",
|
366
486
|
children: /* @__PURE__ */ jsx(Pencil, {})
|
367
487
|
}
|
368
488
|
) })
|
@@ -382,7 +502,13 @@ const LocalePickerAction = ({
|
|
382
502
|
const [{ query }, setQuery] = useQueryParams();
|
383
503
|
const { hasI18n, canCreate, canRead } = useI18n();
|
384
504
|
const { data: locales = [] } = useGetLocalesQuery();
|
385
|
-
const
|
505
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
506
|
+
const { schema } = unstable_useDocument({
|
507
|
+
model,
|
508
|
+
collectionType,
|
509
|
+
documentId,
|
510
|
+
params: { locale: currentDesiredLocale }
|
511
|
+
});
|
386
512
|
const handleSelect = React.useCallback(
|
387
513
|
(value) => {
|
388
514
|
setQuery({
|
@@ -400,21 +526,20 @@ const LocalePickerAction = ({
|
|
400
526
|
if (!Array.isArray(locales) || !hasI18n) {
|
401
527
|
return;
|
402
528
|
}
|
403
|
-
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
404
529
|
const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
|
405
530
|
const defaultLocale = locales.find((locale) => locale.isDefault);
|
406
531
|
if (!doesLocaleExist && defaultLocale?.code) {
|
407
532
|
handleSelect(defaultLocale.code);
|
408
533
|
}
|
409
|
-
}, [handleSelect, hasI18n, locales,
|
410
|
-
|
411
|
-
return null;
|
412
|
-
}
|
413
|
-
const currentLocale = query.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
|
534
|
+
}, [handleSelect, hasI18n, locales, currentDesiredLocale]);
|
535
|
+
const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale)?.code : void 0;
|
414
536
|
const allCurrentLocales = [
|
415
537
|
{ status: getDocumentStatus(document, meta), locale: currentLocale },
|
416
538
|
...meta?.availableLocales ?? []
|
417
539
|
];
|
540
|
+
if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
|
541
|
+
return null;
|
542
|
+
}
|
418
543
|
return {
|
419
544
|
label: formatMessage({
|
420
545
|
id: getTranslation("Settings.locales.modal.locales.label"),
|
@@ -426,7 +551,7 @@ const LocalePickerAction = ({
|
|
426
551
|
);
|
427
552
|
const status = currentLocaleDoc?.status ?? "draft";
|
428
553
|
const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
|
429
|
-
const statusVariant = status === "draft" ? "
|
554
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
430
555
|
return {
|
431
556
|
disabled: !permissionsToCheck.includes(locale.code),
|
432
557
|
value: locale.code,
|
@@ -462,6 +587,95 @@ const getDocumentStatus = (document, meta) => {
|
|
462
587
|
}
|
463
588
|
return docStatus;
|
464
589
|
};
|
590
|
+
const FillFromAnotherLocaleAction = ({
|
591
|
+
documentId,
|
592
|
+
meta,
|
593
|
+
model,
|
594
|
+
collectionType
|
595
|
+
}) => {
|
596
|
+
const { formatMessage } = useIntl();
|
597
|
+
const [{ query }] = useQueryParams();
|
598
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
599
|
+
const [localeSelected, setLocaleSelected] = React.useState(null);
|
600
|
+
const setValues = useForm("FillFromAnotherLocale", (state) => state.setValues);
|
601
|
+
const { getDocument } = unstable_useDocumentActions();
|
602
|
+
const { schema, components } = unstable_useDocument({
|
603
|
+
model,
|
604
|
+
documentId,
|
605
|
+
collectionType,
|
606
|
+
params: { locale: currentDesiredLocale }
|
607
|
+
});
|
608
|
+
const { data: locales = [] } = useGetLocalesQuery();
|
609
|
+
const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
|
610
|
+
const fillFromLocale = (onClose) => async () => {
|
611
|
+
const response = await getDocument({
|
612
|
+
collectionType,
|
613
|
+
model,
|
614
|
+
documentId,
|
615
|
+
params: { locale: localeSelected }
|
616
|
+
});
|
617
|
+
if (!response || !schema) {
|
618
|
+
return;
|
619
|
+
}
|
620
|
+
const { data } = response;
|
621
|
+
const cleanedData = cleanData(data, schema, components);
|
622
|
+
setValues(cleanedData);
|
623
|
+
onClose();
|
624
|
+
};
|
625
|
+
return {
|
626
|
+
type: "icon",
|
627
|
+
icon: /* @__PURE__ */ jsx(Download, {}),
|
628
|
+
disabled: availableLocales.length === 0,
|
629
|
+
label: formatMessage({
|
630
|
+
id: getTranslation("CMEditViewCopyLocale.copy-text"),
|
631
|
+
defaultMessage: "Fill in from another locale"
|
632
|
+
}),
|
633
|
+
dialog: {
|
634
|
+
type: "dialog",
|
635
|
+
title: formatMessage({
|
636
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.title"),
|
637
|
+
defaultMessage: "Confirmation"
|
638
|
+
}),
|
639
|
+
content: ({ onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
640
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
|
641
|
+
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
642
|
+
/* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
|
643
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.body"),
|
644
|
+
defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
|
645
|
+
}) }),
|
646
|
+
/* @__PURE__ */ jsxs(Field.Root, { width: "100%", children: [
|
647
|
+
/* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
|
648
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
|
649
|
+
defaultMessage: "Locale"
|
650
|
+
}) }),
|
651
|
+
/* @__PURE__ */ jsx(
|
652
|
+
SingleSelect,
|
653
|
+
{
|
654
|
+
value: localeSelected,
|
655
|
+
placeholder: formatMessage({
|
656
|
+
id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
|
657
|
+
defaultMessage: "Select one locale..."
|
658
|
+
}),
|
659
|
+
onChange: (value) => setLocaleSelected(value),
|
660
|
+
children: availableLocales.map((locale) => /* @__PURE__ */ jsx(SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
|
661
|
+
}
|
662
|
+
)
|
663
|
+
] })
|
664
|
+
] }) }),
|
665
|
+
/* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, width: "100%", children: [
|
666
|
+
/* @__PURE__ */ jsx(Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
|
667
|
+
id: getTranslation("CMEditViewCopyLocale.cancel-text"),
|
668
|
+
defaultMessage: "No, cancel"
|
669
|
+
}) }),
|
670
|
+
/* @__PURE__ */ jsx(Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
|
671
|
+
id: getTranslation("CMEditViewCopyLocale.submit-text"),
|
672
|
+
defaultMessage: "Yes, fill in"
|
673
|
+
}) })
|
674
|
+
] }) })
|
675
|
+
] })
|
676
|
+
}
|
677
|
+
};
|
678
|
+
};
|
465
679
|
const DeleteLocaleAction = ({
|
466
680
|
document,
|
467
681
|
documentId,
|
@@ -473,16 +687,23 @@ const DeleteLocaleAction = ({
|
|
473
687
|
const { toggleNotification } = useNotification();
|
474
688
|
const { delete: deleteAction } = unstable_useDocumentActions();
|
475
689
|
const { hasI18n, canDelete } = useI18n();
|
690
|
+
const [{ query }] = useQueryParams();
|
691
|
+
const { data: locales = [] } = useGetLocalesQuery();
|
692
|
+
const currentDesiredLocale = query.plugins?.i18n?.locale;
|
693
|
+
const locale = !("error" in locales) && locales.find((loc) => loc.code === currentDesiredLocale);
|
476
694
|
if (!hasI18n) {
|
477
695
|
return null;
|
478
696
|
}
|
479
697
|
return {
|
480
698
|
disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
|
481
699
|
position: ["header", "table-row"],
|
482
|
-
label: formatMessage(
|
483
|
-
|
484
|
-
|
485
|
-
|
700
|
+
label: formatMessage(
|
701
|
+
{
|
702
|
+
id: getTranslation("actions.delete.label"),
|
703
|
+
defaultMessage: "Delete entry ({locale})"
|
704
|
+
},
|
705
|
+
{ locale: locale && locale.name }
|
706
|
+
),
|
486
707
|
icon: /* @__PURE__ */ jsx(StyledTrash, {}),
|
487
708
|
variant: "danger",
|
488
709
|
dialog: {
|
@@ -525,23 +746,24 @@ const DeleteLocaleAction = ({
|
|
525
746
|
}
|
526
747
|
};
|
527
748
|
};
|
528
|
-
const
|
749
|
+
const BulkLocaleAction = ({
|
529
750
|
document: baseDocument,
|
530
751
|
documentId,
|
531
752
|
model,
|
532
|
-
collectionType
|
753
|
+
collectionType,
|
754
|
+
action
|
533
755
|
}) => {
|
534
756
|
const baseLocale = baseDocument?.locale ?? null;
|
535
757
|
const [{ query }] = useQueryParams();
|
536
758
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
537
|
-
const
|
759
|
+
const isOnPublishedTab = query.status === "published";
|
538
760
|
const { formatMessage } = useIntl();
|
539
761
|
const { hasI18n, canPublish } = useI18n();
|
540
762
|
const { toggleNotification } = useNotification();
|
541
763
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
542
764
|
const [selectedRows, setSelectedRows] = React.useState([]);
|
543
765
|
const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
|
544
|
-
const { publishMany: publishManyAction } = unstable_useDocumentActions();
|
766
|
+
const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
|
545
767
|
const {
|
546
768
|
document,
|
547
769
|
meta: documentMeta,
|
@@ -557,7 +779,7 @@ const BulkLocalePublishAction = ({
|
|
557
779
|
}
|
558
780
|
},
|
559
781
|
{
|
560
|
-
skip: !hasI18n
|
782
|
+
skip: !hasI18n || !baseLocale
|
561
783
|
}
|
562
784
|
);
|
563
785
|
const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
|
@@ -609,12 +831,19 @@ const BulkLocalePublishAction = ({
|
|
609
831
|
}, {});
|
610
832
|
return [rowsFromMeta, errors];
|
611
833
|
}, [document, documentMeta?.availableLocales, validate]);
|
612
|
-
const
|
613
|
-
|
834
|
+
const isBulkPublish = action === "bulk-publish";
|
835
|
+
const localesForAction = selectedRows.reduce((acc, selectedRow) => {
|
836
|
+
const isValidLocale = (
|
837
|
+
// Validation errors are irrelevant if we are trying to unpublish
|
838
|
+
!isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
|
839
|
+
);
|
840
|
+
const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
|
841
|
+
if (shouldAddLocale) {
|
614
842
|
acc.push(selectedRow.locale);
|
615
843
|
}
|
616
844
|
return acc;
|
617
845
|
}, []);
|
846
|
+
const enableDraftRelationsCount = false;
|
618
847
|
const {
|
619
848
|
data: draftRelationsCount = 0,
|
620
849
|
isLoading: isDraftRelationsLoading,
|
@@ -623,10 +852,10 @@ const BulkLocalePublishAction = ({
|
|
623
852
|
{
|
624
853
|
model,
|
625
854
|
documentIds: [documentId],
|
626
|
-
locale:
|
855
|
+
locale: localesForAction
|
627
856
|
},
|
628
857
|
{
|
629
|
-
skip: !
|
858
|
+
skip: !enableDraftRelationsCount
|
630
859
|
}
|
631
860
|
);
|
632
861
|
React.useEffect(() => {
|
@@ -652,7 +881,18 @@ const BulkLocalePublishAction = ({
|
|
652
881
|
documentIds: [documentId],
|
653
882
|
params: {
|
654
883
|
...params,
|
655
|
-
locale:
|
884
|
+
locale: localesForAction
|
885
|
+
}
|
886
|
+
});
|
887
|
+
setSelectedRows([]);
|
888
|
+
};
|
889
|
+
const unpublish = async () => {
|
890
|
+
await unpublishManyAction({
|
891
|
+
model,
|
892
|
+
documentIds: [documentId],
|
893
|
+
params: {
|
894
|
+
...params,
|
895
|
+
locale: localesForAction
|
656
896
|
}
|
657
897
|
});
|
658
898
|
setSelectedRows([]);
|
@@ -660,14 +900,12 @@ const BulkLocalePublishAction = ({
|
|
660
900
|
const handleAction = async () => {
|
661
901
|
if (draftRelationsCount > 0) {
|
662
902
|
setIsDraftRelationConfirmationOpen(true);
|
663
|
-
} else {
|
903
|
+
} else if (isBulkPublish) {
|
664
904
|
await publish();
|
905
|
+
} else {
|
906
|
+
await unpublish();
|
665
907
|
}
|
666
908
|
};
|
667
|
-
const isUnpublish = document?.status === "published";
|
668
|
-
if (isUnpublish) {
|
669
|
-
console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
|
670
|
-
}
|
671
909
|
if (isDraftRelationConfirmationOpen) {
|
672
910
|
return {
|
673
911
|
label: formatMessage({
|
@@ -705,18 +943,18 @@ const BulkLocalePublishAction = ({
|
|
705
943
|
const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
|
706
944
|
return {
|
707
945
|
label: formatMessage({
|
708
|
-
id: getTranslation("
|
709
|
-
defaultMessage: "Publish Multiple Locales
|
946
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
947
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
710
948
|
}),
|
711
|
-
|
712
|
-
|
949
|
+
variant: isBulkPublish ? "secondary" : "danger",
|
950
|
+
icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
|
951
|
+
disabled: isOnPublishedTab || canPublish.length === 0,
|
713
952
|
position: ["panel"],
|
714
|
-
variant: "secondary",
|
715
953
|
dialog: {
|
716
954
|
type: "modal",
|
717
955
|
title: formatMessage({
|
718
|
-
id: getTranslation("
|
719
|
-
defaultMessage: "Publish Multiple Locales
|
956
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
957
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
720
958
|
}),
|
721
959
|
content: () => {
|
722
960
|
return /* @__PURE__ */ jsx(
|
@@ -735,28 +973,35 @@ const BulkLocalePublishAction = ({
|
|
735
973
|
validationErrors,
|
736
974
|
headers,
|
737
975
|
rows,
|
738
|
-
localesMetadata
|
976
|
+
localesMetadata,
|
977
|
+
action: action ?? "bulk-publish"
|
739
978
|
}
|
740
979
|
)
|
741
980
|
}
|
742
981
|
);
|
743
982
|
},
|
744
983
|
footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
|
745
|
-
Button
|
984
|
+
Button,
|
746
985
|
{
|
747
986
|
loading: isDraftRelationsLoading,
|
748
|
-
disabled: !hasPermission ||
|
987
|
+
disabled: !hasPermission || localesForAction.length === 0,
|
749
988
|
variant: "default",
|
750
989
|
onClick: handleAction,
|
751
990
|
children: formatMessage({
|
752
|
-
id: "app.utils.publish",
|
753
|
-
defaultMessage: "Publish"
|
991
|
+
id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
|
992
|
+
defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
|
754
993
|
})
|
755
994
|
}
|
756
995
|
) })
|
757
996
|
}
|
758
997
|
};
|
759
998
|
};
|
999
|
+
const BulkLocalePublishAction = (props) => {
|
1000
|
+
return BulkLocaleAction({ action: "bulk-publish", ...props });
|
1001
|
+
};
|
1002
|
+
const BulkLocaleUnpublishAction = (props) => {
|
1003
|
+
return BulkLocaleAction({ action: "bulk-unpublish", ...props });
|
1004
|
+
};
|
760
1005
|
const StyledTrash = styled(Trash)`
|
761
1006
|
path {
|
762
1007
|
fill: currentColor;
|
@@ -976,54 +1221,13 @@ const LocaleListCell = ({
|
|
976
1221
|
return locale.name;
|
977
1222
|
}).toSorted((a, b) => formatter.compare(a, b));
|
978
1223
|
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
|
-
) }) }),
|
1224
|
+
/* @__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: [
|
1225
|
+
/* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
|
1226
|
+
/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) })
|
1227
|
+
] }) }) }),
|
993
1228
|
/* @__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
1229
|
] });
|
995
1230
|
};
|
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
1231
|
const addColumnToTableHook = ({ displayedHeaders, layout }) => {
|
1028
1232
|
const { options } = layout;
|
1029
1233
|
const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
|
@@ -1221,11 +1425,11 @@ const index = {
|
|
1221
1425
|
},
|
1222
1426
|
id: "internationalization",
|
1223
1427
|
to: "internationalization",
|
1224
|
-
Component: () => import("./SettingsPage-
|
1428
|
+
Component: () => import("./SettingsPage-4-K93FBe.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
|
1225
1429
|
permissions: PERMISSIONS.accessMain
|
1226
1430
|
});
|
1227
1431
|
const contentManager = app.getPlugin("content-manager");
|
1228
|
-
contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
|
1432
|
+
contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
|
1229
1433
|
contentManager.apis.addDocumentAction((actions) => {
|
1230
1434
|
const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
|
1231
1435
|
actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
|
@@ -1233,6 +1437,7 @@ const index = {
|
|
1233
1437
|
});
|
1234
1438
|
contentManager.apis.addDocumentAction((actions) => {
|
1235
1439
|
actions.splice(2, 0, BulkLocalePublishAction);
|
1440
|
+
actions.splice(5, 0, BulkLocaleUnpublishAction);
|
1236
1441
|
return actions;
|
1237
1442
|
});
|
1238
1443
|
contentManager.injectComponent("listView", "actions", {
|
@@ -1338,7 +1543,7 @@ const index = {
|
|
1338
1543
|
async registerTrads({ locales }) {
|
1339
1544
|
const importedTrads = await Promise.all(
|
1340
1545
|
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-
|
1546
|
+
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
1547
|
return {
|
1343
1548
|
data: prefixPluginTranslations(data, pluginId),
|
1344
1549
|
locale
|
@@ -1364,4 +1569,4 @@ export {
|
|
1364
1569
|
index as i,
|
1365
1570
|
useCreateLocaleMutation as u
|
1366
1571
|
};
|
1367
|
-
//# sourceMappingURL=index-
|
1572
|
+
//# sourceMappingURL=index-B2uG3lvD.mjs.map
|