@strapi/i18n 0.0.0-experimental.60f3ded53a22a24d208ebf6df9b84c118aa97abf → 0.0.0-experimental.65ad956ae83ac65d866b9bb3e8c022c34b85468f
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-BjxjwEOb.mjs} +6 -6
- package/dist/_chunks/SettingsPage-BjxjwEOb.mjs.map +1 -0
- package/dist/_chunks/{SettingsPage-DT1sxWa2.js → SettingsPage-CfTmCkup.js} +6 -6
- package/dist/_chunks/SettingsPage-CfTmCkup.js.map +1 -0
- package/dist/_chunks/{en-CM6Pjfyv.mjs → en-2xztdZE1.mjs} +7 -1
- package/dist/_chunks/en-2xztdZE1.mjs.map +1 -0
- package/dist/_chunks/{en-BsOU9o5z.js → en-DWpfm8h5.js} +7 -1
- package/dist/_chunks/en-DWpfm8h5.js.map +1 -0
- package/dist/_chunks/{index-jMrzaEb9.js → index-5XLZwzwx.js} +341 -146
- package/dist/_chunks/index-5XLZwzwx.js.map +1 -0
- package/dist/_chunks/{index-DsNqyQKx.mjs → index-D-qx3tz4.mjs} +337 -142
- package/dist/_chunks/index-D-qx3tz4.mjs.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 +38 -9
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +39 -10
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +14 -2
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +14 -2
- 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/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
@@ -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,
|
@@ -524,37 +738,43 @@ const DeleteLocaleAction = ({
|
|
524
738
|
}
|
525
739
|
};
|
526
740
|
};
|
527
|
-
const
|
741
|
+
const BulkLocaleAction = ({
|
528
742
|
document: baseDocument,
|
529
743
|
documentId,
|
530
744
|
model,
|
531
|
-
collectionType
|
745
|
+
collectionType,
|
746
|
+
action
|
532
747
|
}) => {
|
533
748
|
const baseLocale = baseDocument?.locale ?? null;
|
534
749
|
const [{ query }] = useQueryParams();
|
535
750
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
536
|
-
const
|
751
|
+
const isOnPublishedTab = query.status === "published";
|
537
752
|
const { formatMessage } = useIntl();
|
538
753
|
const { hasI18n, canPublish } = useI18n();
|
539
754
|
const { toggleNotification } = useNotification();
|
540
755
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
541
756
|
const [selectedRows, setSelectedRows] = React.useState([]);
|
542
757
|
const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
|
543
|
-
const { publishMany: publishManyAction } = unstable_useDocumentActions();
|
758
|
+
const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
|
544
759
|
const {
|
545
760
|
document,
|
546
761
|
meta: documentMeta,
|
547
762
|
schema,
|
548
763
|
validate
|
549
|
-
} = unstable_useDocument(
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
764
|
+
} = unstable_useDocument(
|
765
|
+
{
|
766
|
+
model,
|
767
|
+
collectionType,
|
768
|
+
documentId,
|
769
|
+
params: {
|
770
|
+
locale: baseLocale
|
771
|
+
}
|
772
|
+
},
|
773
|
+
{
|
774
|
+
skip: !hasI18n || !baseLocale
|
555
775
|
}
|
556
|
-
|
557
|
-
const { data: localesMetadata = [] } = useGetLocalesQuery();
|
776
|
+
);
|
777
|
+
const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
|
558
778
|
const headers = [
|
559
779
|
{
|
560
780
|
label: formatMessage({
|
@@ -603,12 +823,19 @@ const BulkLocalePublishAction = ({
|
|
603
823
|
}, {});
|
604
824
|
return [rowsFromMeta, errors];
|
605
825
|
}, [document, documentMeta?.availableLocales, validate]);
|
606
|
-
const
|
607
|
-
|
826
|
+
const isBulkPublish = action === "bulk-publish";
|
827
|
+
const localesForAction = selectedRows.reduce((acc, selectedRow) => {
|
828
|
+
const isValidLocale = (
|
829
|
+
// Validation errors are irrelevant if we are trying to unpublish
|
830
|
+
!isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
|
831
|
+
);
|
832
|
+
const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
|
833
|
+
if (shouldAddLocale) {
|
608
834
|
acc.push(selectedRow.locale);
|
609
835
|
}
|
610
836
|
return acc;
|
611
837
|
}, []);
|
838
|
+
const enableDraftRelationsCount = false;
|
612
839
|
const {
|
613
840
|
data: draftRelationsCount = 0,
|
614
841
|
isLoading: isDraftRelationsLoading,
|
@@ -617,10 +844,10 @@ const BulkLocalePublishAction = ({
|
|
617
844
|
{
|
618
845
|
model,
|
619
846
|
documentIds: [documentId],
|
620
|
-
locale:
|
847
|
+
locale: localesForAction
|
621
848
|
},
|
622
849
|
{
|
623
|
-
skip: !
|
850
|
+
skip: !enableDraftRelationsCount
|
624
851
|
}
|
625
852
|
);
|
626
853
|
React.useEffect(() => {
|
@@ -646,7 +873,18 @@ const BulkLocalePublishAction = ({
|
|
646
873
|
documentIds: [documentId],
|
647
874
|
params: {
|
648
875
|
...params,
|
649
|
-
locale:
|
876
|
+
locale: localesForAction
|
877
|
+
}
|
878
|
+
});
|
879
|
+
setSelectedRows([]);
|
880
|
+
};
|
881
|
+
const unpublish = async () => {
|
882
|
+
await unpublishManyAction({
|
883
|
+
model,
|
884
|
+
documentIds: [documentId],
|
885
|
+
params: {
|
886
|
+
...params,
|
887
|
+
locale: localesForAction
|
650
888
|
}
|
651
889
|
});
|
652
890
|
setSelectedRows([]);
|
@@ -654,14 +892,12 @@ const BulkLocalePublishAction = ({
|
|
654
892
|
const handleAction = async () => {
|
655
893
|
if (draftRelationsCount > 0) {
|
656
894
|
setIsDraftRelationConfirmationOpen(true);
|
657
|
-
} else {
|
895
|
+
} else if (isBulkPublish) {
|
658
896
|
await publish();
|
897
|
+
} else {
|
898
|
+
await unpublish();
|
659
899
|
}
|
660
900
|
};
|
661
|
-
const isUnpublish = document?.status === "published";
|
662
|
-
if (isUnpublish) {
|
663
|
-
console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
|
664
|
-
}
|
665
901
|
if (isDraftRelationConfirmationOpen) {
|
666
902
|
return {
|
667
903
|
label: formatMessage({
|
@@ -696,20 +932,21 @@ const BulkLocalePublishAction = ({
|
|
696
932
|
}
|
697
933
|
};
|
698
934
|
}
|
935
|
+
const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
|
699
936
|
return {
|
700
937
|
label: formatMessage({
|
701
|
-
id: getTranslation("
|
702
|
-
defaultMessage: "Publish Multiple Locales
|
938
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
939
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
703
940
|
}),
|
704
|
-
|
705
|
-
|
941
|
+
variant: isBulkPublish ? "secondary" : "danger",
|
942
|
+
icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
|
943
|
+
disabled: isOnPublishedTab || canPublish.length === 0,
|
706
944
|
position: ["panel"],
|
707
|
-
variant: "secondary",
|
708
945
|
dialog: {
|
709
946
|
type: "modal",
|
710
947
|
title: formatMessage({
|
711
|
-
id: getTranslation("
|
712
|
-
defaultMessage: "Publish Multiple Locales
|
948
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
949
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
713
950
|
}),
|
714
951
|
content: () => {
|
715
952
|
return /* @__PURE__ */ jsx(
|
@@ -728,28 +965,35 @@ const BulkLocalePublishAction = ({
|
|
728
965
|
validationErrors,
|
729
966
|
headers,
|
730
967
|
rows,
|
731
|
-
localesMetadata
|
968
|
+
localesMetadata,
|
969
|
+
action: action ?? "bulk-publish"
|
732
970
|
}
|
733
971
|
)
|
734
972
|
}
|
735
973
|
);
|
736
974
|
},
|
737
|
-
footer: () => /* @__PURE__ */ jsx(
|
738
|
-
Button
|
975
|
+
footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
|
976
|
+
Button,
|
739
977
|
{
|
740
978
|
loading: isDraftRelationsLoading,
|
741
|
-
disabled:
|
979
|
+
disabled: !hasPermission || localesForAction.length === 0,
|
742
980
|
variant: "default",
|
743
981
|
onClick: handleAction,
|
744
982
|
children: formatMessage({
|
745
|
-
id: "app.utils.publish",
|
746
|
-
defaultMessage: "Publish"
|
983
|
+
id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
|
984
|
+
defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
|
747
985
|
})
|
748
986
|
}
|
749
987
|
) })
|
750
988
|
}
|
751
989
|
};
|
752
990
|
};
|
991
|
+
const BulkLocalePublishAction = (props) => {
|
992
|
+
return BulkLocaleAction({ action: "bulk-publish", ...props });
|
993
|
+
};
|
994
|
+
const BulkLocaleUnpublishAction = (props) => {
|
995
|
+
return BulkLocaleAction({ action: "bulk-unpublish", ...props });
|
996
|
+
};
|
753
997
|
const StyledTrash = styled(Trash)`
|
754
998
|
path {
|
755
999
|
fill: currentColor;
|
@@ -806,13 +1050,6 @@ const UnpublishModalAdditionalInfo = () => {
|
|
806
1050
|
}
|
807
1051
|
) });
|
808
1052
|
};
|
809
|
-
const Initializer = ({ setPlugin }) => {
|
810
|
-
const setPluginRef = React.useRef(setPlugin);
|
811
|
-
React.useEffect(() => {
|
812
|
-
setPluginRef.current(pluginId);
|
813
|
-
}, []);
|
814
|
-
return null;
|
815
|
-
};
|
816
1053
|
const LocalePicker = () => {
|
817
1054
|
const { formatMessage } = useIntl();
|
818
1055
|
const [{ query }, setQuery] = useQueryParams();
|
@@ -976,54 +1213,13 @@ const LocaleListCell = ({
|
|
976
1213
|
return locale.name;
|
977
1214
|
}).toSorted((a, b) => formatter.compare(a, b));
|
978
1215
|
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
|
-
) }) }),
|
1216
|
+
/* @__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: [
|
1217
|
+
/* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
|
1218
|
+
/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) })
|
1219
|
+
] }) }) }),
|
993
1220
|
/* @__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
1221
|
] });
|
995
1222
|
};
|
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
1223
|
const addColumnToTableHook = ({ displayedHeaders, layout }) => {
|
1028
1224
|
const { options } = layout;
|
1029
1225
|
const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
|
@@ -1204,8 +1400,6 @@ const index = {
|
|
1204
1400
|
app.addRBACMiddleware([localeMiddleware]);
|
1205
1401
|
app.registerPlugin({
|
1206
1402
|
id: pluginId,
|
1207
|
-
initializer: Initializer,
|
1208
|
-
isReady: false,
|
1209
1403
|
name: pluginId
|
1210
1404
|
});
|
1211
1405
|
},
|
@@ -1223,11 +1417,11 @@ const index = {
|
|
1223
1417
|
},
|
1224
1418
|
id: "internationalization",
|
1225
1419
|
to: "internationalization",
|
1226
|
-
Component: () => import("./SettingsPage-
|
1420
|
+
Component: () => import("./SettingsPage-BjxjwEOb.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
|
1227
1421
|
permissions: PERMISSIONS.accessMain
|
1228
1422
|
});
|
1229
1423
|
const contentManager = app.getPlugin("content-manager");
|
1230
|
-
contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
|
1424
|
+
contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
|
1231
1425
|
contentManager.apis.addDocumentAction((actions) => {
|
1232
1426
|
const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
|
1233
1427
|
actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
|
@@ -1235,6 +1429,7 @@ const index = {
|
|
1235
1429
|
});
|
1236
1430
|
contentManager.apis.addDocumentAction((actions) => {
|
1237
1431
|
actions.splice(2, 0, BulkLocalePublishAction);
|
1432
|
+
actions.splice(5, 0, BulkLocaleUnpublishAction);
|
1238
1433
|
return actions;
|
1239
1434
|
});
|
1240
1435
|
contentManager.injectComponent("listView", "actions", {
|
@@ -1340,7 +1535,7 @@ const index = {
|
|
1340
1535
|
async registerTrads({ locales }) {
|
1341
1536
|
const importedTrads = await Promise.all(
|
1342
1537
|
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-
|
1538
|
+
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-2xztdZE1.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
1539
|
return {
|
1345
1540
|
data: prefixPluginTranslations(data, pluginId),
|
1346
1541
|
locale
|
@@ -1366,4 +1561,4 @@ export {
|
|
1366
1561
|
index as i,
|
1367
1562
|
useCreateLocaleMutation as u
|
1368
1563
|
};
|
1369
|
-
//# sourceMappingURL=index-
|
1564
|
+
//# sourceMappingURL=index-D-qx3tz4.mjs.map
|