@strapi/i18n 0.0.0-experimental.25e22c6cc9bc6b35392bb55d09f641a0a65e7403 → 0.0.0-experimental.31a5317d54179a9ce6225bf1b6e1f9fb6c372fa9
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-Dsi2qGtq.mjs → SettingsPage-BjxjwEOb.mjs} +15 -10
- package/dist/_chunks/SettingsPage-BjxjwEOb.mjs.map +1 -0
- package/dist/_chunks/{SettingsPage-VN7sTzkb.js → SettingsPage-CfTmCkup.js} +15 -10
- package/dist/_chunks/SettingsPage-CfTmCkup.js.map +1 -0
- package/dist/_chunks/{en-18tWw4P6.mjs → en-2xztdZE1.mjs} +9 -1
- package/dist/_chunks/en-2xztdZE1.mjs.map +1 -0
- package/dist/_chunks/{en-Kv6y9zPQ.js → en-DWpfm8h5.js} +9 -1
- package/dist/_chunks/en-DWpfm8h5.js.map +1 -0
- package/dist/_chunks/{index-kedPlCo6.js → index-5XLZwzwx.js} +356 -164
- package/dist/_chunks/index-5XLZwzwx.js.map +1 -0
- package/dist/_chunks/{index-DhtjJYrx.mjs → index-D-qx3tz4.mjs} +352 -160
- 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/contentReleasesHooks/releaseDetailsView.d.ts +9 -5
- 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 +60 -9
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +61 -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-Dsi2qGtq.mjs.map +0 -1
- package/dist/_chunks/SettingsPage-VN7sTzkb.js.map +0 -1
- package/dist/_chunks/en-18tWw4P6.mjs.map +0 -1
- package/dist/_chunks/en-Kv6y9zPQ.js.map +0 -1
- package/dist/_chunks/index-DhtjJYrx.mjs.map +0 -1
- package/dist/_chunks/index-kedPlCo6.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
|
-
const [
|
543
|
-
const { publishMany: publishManyAction } = unstable_useDocumentActions();
|
757
|
+
const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
|
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,23 +873,32 @@ 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([]);
|
653
891
|
};
|
654
892
|
const handleAction = async () => {
|
655
893
|
if (draftRelationsCount > 0) {
|
656
|
-
|
657
|
-
} else {
|
894
|
+
setIsDraftRelationConfirmationOpen(true);
|
895
|
+
} else if (isBulkPublish) {
|
658
896
|
await publish();
|
897
|
+
} else {
|
898
|
+
await unpublish();
|
659
899
|
}
|
660
900
|
};
|
661
|
-
|
662
|
-
if (isUnpublish) {
|
663
|
-
console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
|
664
|
-
}
|
665
|
-
if (isConfirmationOpen) {
|
901
|
+
if (isDraftRelationConfirmationOpen) {
|
666
902
|
return {
|
667
903
|
label: formatMessage({
|
668
904
|
id: "app.components.ConfirmDialog.title",
|
@@ -671,11 +907,11 @@ const BulkLocalePublishAction = ({
|
|
671
907
|
variant: "danger",
|
672
908
|
dialog: {
|
673
909
|
onCancel: () => {
|
674
|
-
|
910
|
+
setIsDraftRelationConfirmationOpen(false);
|
675
911
|
},
|
676
912
|
onConfirm: async () => {
|
677
913
|
await publish();
|
678
|
-
|
914
|
+
setIsDraftRelationConfirmationOpen(false);
|
679
915
|
},
|
680
916
|
type: "dialog",
|
681
917
|
title: formatMessage({
|
@@ -685,27 +921,32 @@ const BulkLocalePublishAction = ({
|
|
685
921
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 2, children: [
|
686
922
|
/* @__PURE__ */ jsx(WarningCircle, { width: "2.4rem", height: "2.4rem", fill: "danger600" }),
|
687
923
|
/* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
|
688
|
-
id: "
|
689
|
-
defaultMessage: "
|
924
|
+
id: getTranslation("CMEditViewBulkLocale.draft-relation-warning"),
|
925
|
+
defaultMessage: "Some locales are related to draft entries. Publishing them could leave broken links in your app."
|
926
|
+
}) }),
|
927
|
+
/* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
|
928
|
+
id: getTranslation("CMEditViewBulkLocale.continue-confirmation"),
|
929
|
+
defaultMessage: "Are you sure you want to continue?"
|
690
930
|
}) })
|
691
931
|
] })
|
692
932
|
}
|
693
933
|
};
|
694
934
|
}
|
935
|
+
const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
|
695
936
|
return {
|
696
937
|
label: formatMessage({
|
697
|
-
id: getTranslation("
|
698
|
-
defaultMessage: "Publish Multiple Locales
|
938
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
939
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
699
940
|
}),
|
700
|
-
|
701
|
-
|
941
|
+
variant: isBulkPublish ? "secondary" : "danger",
|
942
|
+
icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
|
943
|
+
disabled: isOnPublishedTab || canPublish.length === 0,
|
702
944
|
position: ["panel"],
|
703
|
-
variant: "secondary",
|
704
945
|
dialog: {
|
705
946
|
type: "modal",
|
706
947
|
title: formatMessage({
|
707
|
-
id: getTranslation("
|
708
|
-
defaultMessage: "Publish Multiple Locales
|
948
|
+
id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
|
949
|
+
defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
|
709
950
|
}),
|
710
951
|
content: () => {
|
711
952
|
return /* @__PURE__ */ jsx(
|
@@ -724,28 +965,35 @@ const BulkLocalePublishAction = ({
|
|
724
965
|
validationErrors,
|
725
966
|
headers,
|
726
967
|
rows,
|
727
|
-
localesMetadata
|
968
|
+
localesMetadata,
|
969
|
+
action: action ?? "bulk-publish"
|
728
970
|
}
|
729
971
|
)
|
730
972
|
}
|
731
973
|
);
|
732
974
|
},
|
733
|
-
footer: () => /* @__PURE__ */ jsx(
|
734
|
-
Button
|
975
|
+
footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
|
976
|
+
Button,
|
735
977
|
{
|
736
978
|
loading: isDraftRelationsLoading,
|
737
|
-
disabled:
|
979
|
+
disabled: !hasPermission || localesForAction.length === 0,
|
738
980
|
variant: "default",
|
739
981
|
onClick: handleAction,
|
740
982
|
children: formatMessage({
|
741
|
-
id: "app.utils.publish",
|
742
|
-
defaultMessage: "Publish"
|
983
|
+
id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
|
984
|
+
defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
|
743
985
|
})
|
744
986
|
}
|
745
987
|
) })
|
746
988
|
}
|
747
989
|
};
|
748
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
|
+
};
|
749
997
|
const StyledTrash = styled(Trash)`
|
750
998
|
path {
|
751
999
|
fill: currentColor;
|
@@ -802,13 +1050,6 @@ const UnpublishModalAdditionalInfo = () => {
|
|
802
1050
|
}
|
803
1051
|
) });
|
804
1052
|
};
|
805
|
-
const Initializer = ({ setPlugin }) => {
|
806
|
-
const setPluginRef = React.useRef(setPlugin);
|
807
|
-
React.useEffect(() => {
|
808
|
-
setPluginRef.current(pluginId);
|
809
|
-
}, []);
|
810
|
-
return null;
|
811
|
-
};
|
812
1053
|
const LocalePicker = () => {
|
813
1054
|
const { formatMessage } = useIntl();
|
814
1055
|
const [{ query }, setQuery] = useQueryParams();
|
@@ -972,54 +1213,13 @@ const LocaleListCell = ({
|
|
972
1213
|
return locale.name;
|
973
1214
|
}).toSorted((a, b) => formatter.compare(a, b));
|
974
1215
|
return /* @__PURE__ */ jsxs(Popover.Root, { children: [
|
975
|
-
/* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsx(Button, { type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs(
|
976
|
-
|
977
|
-
{
|
978
|
-
|
979
|
-
alignItems: "center",
|
980
|
-
justifyContent: "center",
|
981
|
-
height: "3.2rem",
|
982
|
-
width: "3.2rem",
|
983
|
-
children: [
|
984
|
-
/* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, children: localesForDocument.join(", ") }),
|
985
|
-
/* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, {}) })
|
986
|
-
]
|
987
|
-
}
|
988
|
-
) }) }),
|
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
|
+
] }) }) }),
|
989
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)) }) })
|
990
1221
|
] });
|
991
1222
|
};
|
992
|
-
const Button = styled.button`
|
993
|
-
width: 100%;
|
994
|
-
|
995
|
-
svg {
|
996
|
-
> g,
|
997
|
-
path {
|
998
|
-
fill: ${({ theme }) => theme.colors.neutral500};
|
999
|
-
}
|
1000
|
-
}
|
1001
|
-
&:hover {
|
1002
|
-
svg {
|
1003
|
-
> g,
|
1004
|
-
path {
|
1005
|
-
fill: ${({ theme }) => theme.colors.neutral600};
|
1006
|
-
}
|
1007
|
-
}
|
1008
|
-
}
|
1009
|
-
&:active {
|
1010
|
-
svg {
|
1011
|
-
> g,
|
1012
|
-
path {
|
1013
|
-
fill: ${({ theme }) => theme.colors.neutral400};
|
1014
|
-
}
|
1015
|
-
}
|
1016
|
-
}
|
1017
|
-
`;
|
1018
|
-
const ActionWrapper = styled(Flex)`
|
1019
|
-
svg {
|
1020
|
-
height: 0.4rem;
|
1021
|
-
}
|
1022
|
-
`;
|
1023
1223
|
const addColumnToTableHook = ({ displayedHeaders, layout }) => {
|
1024
1224
|
const { options } = layout;
|
1025
1225
|
const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
|
@@ -1048,18 +1248,11 @@ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
|
|
1048
1248
|
const addLocaleToReleasesHook = ({ displayedHeaders = [] }) => {
|
1049
1249
|
return {
|
1050
1250
|
displayedHeaders: [
|
1051
|
-
|
1052
|
-
// ...displayedHeaders,
|
1251
|
+
...displayedHeaders,
|
1053
1252
|
{
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
label: {
|
1058
|
-
id: "content-releases.page.ReleaseDetails.table.header.label.locale",
|
1059
|
-
defaultMessage: "locale"
|
1060
|
-
},
|
1061
|
-
searchable: false,
|
1062
|
-
sortable: false
|
1253
|
+
label: {
|
1254
|
+
id: "content-releases.page.ReleaseDetails.table.header.label.locale",
|
1255
|
+
defaultMessage: "locale"
|
1063
1256
|
},
|
1064
1257
|
name: "locale"
|
1065
1258
|
}
|
@@ -1207,8 +1400,6 @@ const index = {
|
|
1207
1400
|
app.addRBACMiddleware([localeMiddleware]);
|
1208
1401
|
app.registerPlugin({
|
1209
1402
|
id: pluginId,
|
1210
|
-
initializer: Initializer,
|
1211
|
-
isReady: false,
|
1212
1403
|
name: pluginId
|
1213
1404
|
});
|
1214
1405
|
},
|
@@ -1226,11 +1417,11 @@ const index = {
|
|
1226
1417
|
},
|
1227
1418
|
id: "internationalization",
|
1228
1419
|
to: "internationalization",
|
1229
|
-
Component: () => import("./SettingsPage-
|
1420
|
+
Component: () => import("./SettingsPage-BjxjwEOb.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
|
1230
1421
|
permissions: PERMISSIONS.accessMain
|
1231
1422
|
});
|
1232
1423
|
const contentManager = app.getPlugin("content-manager");
|
1233
|
-
contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
|
1424
|
+
contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
|
1234
1425
|
contentManager.apis.addDocumentAction((actions) => {
|
1235
1426
|
const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
|
1236
1427
|
actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
|
@@ -1238,6 +1429,7 @@ const index = {
|
|
1238
1429
|
});
|
1239
1430
|
contentManager.apis.addDocumentAction((actions) => {
|
1240
1431
|
actions.splice(2, 0, BulkLocalePublishAction);
|
1432
|
+
actions.splice(5, 0, BulkLocaleUnpublishAction);
|
1241
1433
|
return actions;
|
1242
1434
|
});
|
1243
1435
|
contentManager.injectComponent("listView", "actions", {
|
@@ -1343,7 +1535,7 @@ const index = {
|
|
1343
1535
|
async registerTrads({ locales }) {
|
1344
1536
|
const importedTrads = await Promise.all(
|
1345
1537
|
locales.map((locale) => {
|
1346
|
-
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 }) => {
|
1347
1539
|
return {
|
1348
1540
|
data: prefixPluginTranslations(data, pluginId),
|
1349
1541
|
locale
|
@@ -1369,4 +1561,4 @@ export {
|
|
1369
1561
|
index as i,
|
1370
1562
|
useCreateLocaleMutation as u
|
1371
1563
|
};
|
1372
|
-
//# sourceMappingURL=index-
|
1564
|
+
//# sourceMappingURL=index-D-qx3tz4.mjs.map
|