@strapi/i18n 0.0.0-experimental.826f263c58b6886b849d3f03b81f7a530bc51c91 → 0.0.0-experimental.93181c8b900e97a04bf10785b368657101ec98d8

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.
Files changed (40) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{SettingsPage-DnLLGeBa.js → SettingsPage-C-1h_H38.js} +91 -104
  3. package/dist/_chunks/SettingsPage-C-1h_H38.js.map +1 -0
  4. package/dist/_chunks/{SettingsPage-0FFSTUW2.mjs → SettingsPage-CPNFX0bZ.mjs} +93 -106
  5. package/dist/_chunks/SettingsPage-CPNFX0bZ.mjs.map +1 -0
  6. package/dist/_chunks/{en-18tWw4P6.mjs → en-CtekP_47.mjs} +4 -1
  7. package/dist/_chunks/en-CtekP_47.mjs.map +1 -0
  8. package/dist/_chunks/{en-Kv6y9zPQ.js → en-CwI88-PP.js} +4 -1
  9. package/dist/_chunks/en-CwI88-PP.js.map +1 -0
  10. package/dist/_chunks/{index-BddUXwss.mjs → index-CgjpU2bY.mjs} +191 -188
  11. package/dist/_chunks/index-CgjpU2bY.mjs.map +1 -0
  12. package/dist/_chunks/{index-DtEKsPcR.js → index-jpk39Rxo.js} +201 -198
  13. package/dist/_chunks/index-jpk39Rxo.js.map +1 -0
  14. package/dist/admin/index.js +1 -1
  15. package/dist/admin/index.mjs +1 -1
  16. package/dist/admin/src/components/BulkLocaleActionModal.d.ts +2 -1
  17. package/dist/admin/src/components/CMHeaderActions.d.ts +2 -1
  18. package/dist/admin/src/components/EditLocale.d.ts +5 -4
  19. package/dist/admin/src/contentReleasesHooks/releaseDetailsView.d.ts +9 -5
  20. package/dist/admin/src/utils/schemas.d.ts +1 -0
  21. package/dist/server/index.js +37 -8
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/server/index.mjs +38 -9
  24. package/dist/server/index.mjs.map +1 -1
  25. package/dist/server/src/index.d.ts +14 -2
  26. package/dist/server/src/index.d.ts.map +1 -1
  27. package/dist/server/src/services/index.d.ts +14 -2
  28. package/dist/server/src/services/index.d.ts.map +1 -1
  29. package/dist/server/src/services/permissions/actions.d.ts +14 -2
  30. package/dist/server/src/services/permissions/actions.d.ts.map +1 -1
  31. package/dist/server/src/services/permissions.d.ts +14 -2
  32. package/dist/server/src/services/permissions.d.ts.map +1 -1
  33. package/package.json +9 -9
  34. package/dist/_chunks/SettingsPage-0FFSTUW2.mjs.map +0 -1
  35. package/dist/_chunks/SettingsPage-DnLLGeBa.js.map +0 -1
  36. package/dist/_chunks/en-18tWw4P6.mjs.map +0 -1
  37. package/dist/_chunks/en-Kv6y9zPQ.js.map +0 -1
  38. package/dist/_chunks/index-BddUXwss.mjs.map +0 -1
  39. package/dist/_chunks/index-DtEKsPcR.js.map +0 -1
  40. package/dist/admin/src/components/Initializer.d.ts +0 -5
@@ -1,11 +1,12 @@
1
1
  import get from "lodash/get";
2
2
  import * as yup from "yup";
3
- import { jsxs, Fragment, jsx } from "react/jsx-runtime";
3
+ import { jsxs, jsx } from "react/jsx-runtime";
4
4
  import * as React from "react";
5
- import { Typography, Field, Checkbox, Dialog, DialogBody, Flex, DialogFooter, Button as Button$1, Box, Status, IconButton, Tooltip, SingleSelect, SingleSelectOption, VisuallyHidden, useCollator, Popover } from "@strapi/design-system";
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, ListPlus, Cross, Earth, EarthStriked, CaretDown } from "@strapi/icons";
7
7
  import { useIntl } from "react-intl";
8
8
  import { styled } from "styled-components";
9
+ import { skipToken } from "@reduxjs/toolkit/query";
9
10
  import { useAuth, adminApi, useTable, Table, useQueryParams, 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";
@@ -47,9 +48,7 @@ const CheckboxConfirmation = ({
47
48
  };
48
49
  const handleConfirm = () => {
49
50
  onChange({ target: { name, value: false, type: "checkbox" } });
50
- setIsOpen(false);
51
51
  };
52
- const handleToggle = () => setIsOpen((prev) => !prev);
53
52
  const label = intlLabel.id ? formatMessage(
54
53
  { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage },
55
54
  { ...intlLabel.values }
@@ -58,35 +57,36 @@ const CheckboxConfirmation = ({
58
57
  { id: description.id, defaultMessage: description.defaultMessage },
59
58
  { ...description.values }
60
59
  ) : "";
61
- return /* @__PURE__ */ jsxs(Fragment, { children: [
60
+ return /* @__PURE__ */ jsxs(Dialog.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
62
61
  /* @__PURE__ */ jsxs(Field.Root, { hint, name, children: [
63
- /* @__PURE__ */ jsx(Checkbox, { onValueChange: handleChange, value, type: "checkbox", children: label }),
62
+ /* @__PURE__ */ jsx(Checkbox, { onCheckedChange: handleChange, checked: value, children: label }),
64
63
  /* @__PURE__ */ jsx(Field.Hint, {})
65
64
  ] }),
66
- isOpen && /* @__PURE__ */ jsxs(Dialog, { onClose: handleToggle, title: "Confirmation", isOpen, children: [
67
- /* @__PURE__ */ jsx(DialogBody, { icon: /* @__PURE__ */ jsx(WarningCircle, {}), children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
68
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(TextAlignTypography, { id: "confirm-description", children: formatMessage({
65
+ /* @__PURE__ */ jsxs(Dialog.Content, { children: [
66
+ /* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
67
+ id: getTranslation("CheckboxConfirmation.Modal.title"),
68
+ defaultMessage: "Disable localization"
69
+ }) }),
70
+ /* @__PURE__ */ jsx(Dialog.Body, { icon: /* @__PURE__ */ jsx(WarningCircle, {}), children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
71
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(TextAlignTypography, { children: formatMessage({
69
72
  id: getTranslation("CheckboxConfirmation.Modal.content"),
70
73
  defaultMessage: "Disabling localization will engender the deletion of all your content but the one associated to your default locale (if existing)."
71
74
  }) }) }),
72
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", id: "confirm-description", children: formatMessage({
75
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: formatMessage({
73
76
  id: getTranslation("CheckboxConfirmation.Modal.body"),
74
77
  defaultMessage: "Do you want to disable it?"
75
78
  }) }) })
76
79
  ] }) }),
77
- /* @__PURE__ */ jsx(
78
- DialogFooter,
79
- {
80
- startAction: /* @__PURE__ */ jsx(Button$1, { onClick: handleToggle, variant: "tertiary", children: formatMessage({
81
- id: "components.popUpWarning.button.cancel",
82
- defaultMessage: "No, cancel"
83
- }) }),
84
- endAction: /* @__PURE__ */ jsx(Button$1, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
85
- id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
86
- defaultMessage: "Yes, disable"
87
- }) })
88
- }
89
- )
80
+ /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
81
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
82
+ id: "components.popUpWarning.button.cancel",
83
+ defaultMessage: "No, cancel"
84
+ }) }) }),
85
+ /* @__PURE__ */ jsx(Dialog.Action, { children: /* @__PURE__ */ jsx(Button, { variant: "danger-light", onClick: handleConfirm, children: formatMessage({
86
+ id: getTranslation("CheckboxConfirmation.Modal.button-confirm"),
87
+ defaultMessage: "Yes, disable"
88
+ }) }) })
89
+ ] })
90
90
  ] })
91
91
  ] });
92
92
  };
@@ -137,7 +137,7 @@ const useI18n = () => {
137
137
  model: params.slug
138
138
  },
139
139
  {
140
- skip: !params.slug || !params.collectionType
140
+ skip: true
141
141
  }
142
142
  );
143
143
  if (doesPluginOptionsHaveI18nLocalized(schema?.pluginOptions)) {
@@ -220,7 +220,11 @@ const { useGetManyDraftRelationCountQuery } = relationsApi;
220
220
  const isErrorMessageDescriptor = (object) => {
221
221
  return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
222
222
  };
223
- const EntryValidationText = ({ status = "draft", validationErrors }) => {
223
+ const EntryValidationText = ({
224
+ status = "draft",
225
+ validationErrors,
226
+ action
227
+ }) => {
224
228
  const { formatMessage } = useIntl();
225
229
  const getErrorStr = (key, value) => {
226
230
  if (typeof value === "string") {
@@ -254,30 +258,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
254
258
  ) })
255
259
  ] });
256
260
  }
257
- if (status === "published") {
258
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
259
- /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
260
- /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
261
- id: "content-manager.bulk-publish.already-published",
262
- defaultMessage: "Already Published"
263
- }) })
264
- ] });
265
- }
266
- if (status === "modified") {
267
- return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
268
- /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
269
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
270
- id: "app.utils.ready-to-publish-changes",
271
- defaultMessage: "Ready to publish changes"
272
- }) })
273
- ] });
274
- }
261
+ const getStatusMessage = () => {
262
+ if (action === "bulk-publish") {
263
+ if (status === "published") {
264
+ return {
265
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
266
+ text: formatMessage({
267
+ id: "content-manager.bulk-publish.already-published",
268
+ defaultMessage: "Already Published"
269
+ }),
270
+ textColor: "success600",
271
+ fontWeight: "bold"
272
+ };
273
+ } else if (status === "modified") {
274
+ return {
275
+ icon: /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
276
+ text: formatMessage({
277
+ id: "app.utils.ready-to-publish-changes",
278
+ defaultMessage: "Ready to publish changes"
279
+ })
280
+ };
281
+ } else {
282
+ return {
283
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
284
+ text: formatMessage({
285
+ id: "app.utils.ready-to-publish",
286
+ defaultMessage: "Ready to publish"
287
+ })
288
+ };
289
+ }
290
+ } else {
291
+ if (status === "draft") {
292
+ return {
293
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
294
+ text: formatMessage({
295
+ id: "content-manager.bulk-unpublish.already-unpublished",
296
+ defaultMessage: "Already Unpublished"
297
+ }),
298
+ textColor: "success600",
299
+ fontWeight: "bold"
300
+ };
301
+ } else {
302
+ return {
303
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
304
+ text: formatMessage({
305
+ id: "app.utils.ready-to-unpublish-changes",
306
+ defaultMessage: "Ready to unpublish"
307
+ }),
308
+ textColor: "success600",
309
+ fontWeight: "bold"
310
+ };
311
+ }
312
+ }
313
+ };
314
+ const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
275
315
  return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
276
- /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
277
- /* @__PURE__ */ jsx(Typography, { children: formatMessage({
278
- id: "app.utils.ready-to-publish",
279
- defaultMessage: "Ready to publish"
280
- }) })
316
+ icon,
317
+ /* @__PURE__ */ jsx(Typography, { textColor, fontWeight, children: text })
281
318
  ] });
282
319
  };
283
320
  const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
@@ -285,7 +322,8 @@ const BulkLocaleActionModal = ({
285
322
  headers,
286
323
  rows,
287
324
  localesMetadata,
288
- validationErrors = {}
325
+ validationErrors = {},
326
+ action
289
327
  }) => {
290
328
  const { formatMessage } = useIntl();
291
329
  const selectedRows = useTable(
@@ -298,27 +336,29 @@ const BulkLocaleActionModal = ({
298
336
  return acc;
299
337
  }, {});
300
338
  const localesWithErrors = Object.keys(validationErrors);
301
- const alreadyPublishedCount = selectedRows.filter(
339
+ const publishedCount = selectedRows.filter(
302
340
  ({ locale }) => currentStatusByLocale[locale] === "published"
303
341
  ).length;
304
- const readyToPublishCount = selectedRows.filter(
342
+ const draftCount = selectedRows.filter(
305
343
  ({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
306
344
  ).length;
307
345
  const withErrorsCount = localesWithErrors.length;
346
+ const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
347
+ 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
348
  return formatMessage(
309
349
  {
310
- id: "content-manager.containers.list.selectedEntriesModal.selectedCount",
311
- defaultMessage: "<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
350
+ id: messageId,
351
+ defaultMessage
312
352
  },
313
353
  {
314
354
  withErrorsCount,
315
- readyToPublishCount,
316
- alreadyPublishedCount,
355
+ draftCount,
356
+ publishedCount,
317
357
  b: BoldChunk
318
358
  }
319
359
  );
320
360
  };
321
- return /* @__PURE__ */ jsxs(React.Fragment, { children: [
361
+ return /* @__PURE__ */ jsxs(Modal.Body, { children: [
322
362
  /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
323
363
  /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsxs(Table.Content, { children: [
324
364
  /* @__PURE__ */ jsxs(Table.Head, { children: [
@@ -345,7 +385,7 @@ const BulkLocaleActionModal = ({
345
385
  children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
346
386
  }
347
387
  ) }) }),
348
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status }) }),
388
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(EntryValidationText, { validationErrors: error, status, action }) }),
349
389
  /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
350
390
  IconButton,
351
391
  {
@@ -362,7 +402,7 @@ const BulkLocaleActionModal = ({
362
402
  name: locale
363
403
  }
364
404
  ),
365
- borderWidth: 0,
405
+ variant: "ghost",
366
406
  children: /* @__PURE__ */ jsx(Pencil, {})
367
407
  }
368
408
  ) })
@@ -525,37 +565,43 @@ const DeleteLocaleAction = ({
525
565
  }
526
566
  };
527
567
  };
528
- const BulkLocalePublishAction = ({
568
+ const BulkLocaleAction = ({
529
569
  document: baseDocument,
530
570
  documentId,
531
571
  model,
532
- collectionType
572
+ collectionType,
573
+ action
533
574
  }) => {
534
575
  const baseLocale = baseDocument?.locale ?? null;
535
576
  const [{ query }] = useQueryParams();
536
577
  const params = React.useMemo(() => buildValidParams(query), [query]);
537
- const isPublishedTab = query.status === "published";
578
+ const isOnPublishedTab = query.status === "published";
538
579
  const { formatMessage } = useIntl();
539
580
  const { hasI18n, canPublish } = useI18n();
540
581
  const { toggleNotification } = useNotification();
541
582
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
542
583
  const [selectedRows, setSelectedRows] = React.useState([]);
543
- const [isConfirmationOpen, setIsConfirmationOpen] = React.useState(false);
544
- const { publishMany: publishManyAction } = unstable_useDocumentActions();
584
+ const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React.useState(false);
585
+ const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = unstable_useDocumentActions();
545
586
  const {
546
587
  document,
547
588
  meta: documentMeta,
548
589
  schema,
549
590
  validate
550
- } = unstable_useDocument({
551
- model,
552
- collectionType,
553
- documentId,
554
- params: {
555
- locale: baseLocale
591
+ } = unstable_useDocument(
592
+ {
593
+ model,
594
+ collectionType,
595
+ documentId,
596
+ params: {
597
+ locale: baseLocale
598
+ }
599
+ },
600
+ {
601
+ skip: !hasI18n
556
602
  }
557
- });
558
- const { data: localesMetadata = [] } = useGetLocalesQuery();
603
+ );
604
+ const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : skipToken);
559
605
  const headers = [
560
606
  {
561
607
  label: formatMessage({
@@ -604,12 +650,19 @@ const BulkLocalePublishAction = ({
604
650
  }, {});
605
651
  return [rowsFromMeta, errors];
606
652
  }, [document, documentMeta?.availableLocales, validate]);
607
- const localesToPublish = selectedRows.reduce((acc, selectedRow) => {
608
- if (selectedRow.status !== "published" && !Object.keys(validationErrors).includes(selectedRow.locale)) {
653
+ const isBulkPublish = action === "bulk-publish";
654
+ const localesForAction = selectedRows.reduce((acc, selectedRow) => {
655
+ const isValidLocale = (
656
+ // Validation errors are irrelevant if we are trying to unpublish
657
+ !isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
658
+ );
659
+ const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
660
+ if (shouldAddLocale) {
609
661
  acc.push(selectedRow.locale);
610
662
  }
611
663
  return acc;
612
664
  }, []);
665
+ const enableDraftRelationsCount = false;
613
666
  const {
614
667
  data: draftRelationsCount = 0,
615
668
  isLoading: isDraftRelationsLoading,
@@ -618,10 +671,10 @@ const BulkLocalePublishAction = ({
618
671
  {
619
672
  model,
620
673
  documentIds: [documentId],
621
- locale: localesToPublish
674
+ locale: localesForAction
622
675
  },
623
676
  {
624
- skip: !documentId || localesToPublish.length === 0
677
+ skip: !enableDraftRelationsCount
625
678
  }
626
679
  );
627
680
  React.useEffect(() => {
@@ -647,23 +700,32 @@ const BulkLocalePublishAction = ({
647
700
  documentIds: [documentId],
648
701
  params: {
649
702
  ...params,
650
- locale: localesToPublish
703
+ locale: localesForAction
704
+ }
705
+ });
706
+ setSelectedRows([]);
707
+ };
708
+ const unpublish = async () => {
709
+ await unpublishManyAction({
710
+ model,
711
+ documentIds: [documentId],
712
+ params: {
713
+ ...params,
714
+ locale: localesForAction
651
715
  }
652
716
  });
653
717
  setSelectedRows([]);
654
718
  };
655
719
  const handleAction = async () => {
656
720
  if (draftRelationsCount > 0) {
657
- setIsConfirmationOpen(true);
658
- } else {
721
+ setIsDraftRelationConfirmationOpen(true);
722
+ } else if (isBulkPublish) {
659
723
  await publish();
724
+ } else {
725
+ await unpublish();
660
726
  }
661
727
  };
662
- const isUnpublish = document?.status === "published";
663
- if (isUnpublish) {
664
- console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
665
- }
666
- if (isConfirmationOpen) {
728
+ if (isDraftRelationConfirmationOpen) {
667
729
  return {
668
730
  label: formatMessage({
669
731
  id: "app.components.ConfirmDialog.title",
@@ -672,11 +734,11 @@ const BulkLocalePublishAction = ({
672
734
  variant: "danger",
673
735
  dialog: {
674
736
  onCancel: () => {
675
- setIsConfirmationOpen(false);
737
+ setIsDraftRelationConfirmationOpen(false);
676
738
  },
677
739
  onConfirm: async () => {
678
740
  await publish();
679
- setIsConfirmationOpen(false);
741
+ setIsDraftRelationConfirmationOpen(false);
680
742
  },
681
743
  type: "dialog",
682
744
  title: formatMessage({
@@ -686,27 +748,32 @@ const BulkLocalePublishAction = ({
686
748
  content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 2, children: [
687
749
  /* @__PURE__ */ jsx(WarningCircle, { width: "2.4rem", height: "2.4rem", fill: "danger600" }),
688
750
  /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
689
- id: "content-manager.actions.discard.dialog.body",
690
- defaultMessage: "Are you sure you want to discard the changes? This action is irreversible."
751
+ id: getTranslation("CMEditViewBulkLocale.draft-relation-warning"),
752
+ defaultMessage: "Some locales are related to draft entries. Publishing them could leave broken links in your app."
753
+ }) }),
754
+ /* @__PURE__ */ jsx(Typography, { textAlign: "center", children: formatMessage({
755
+ id: getTranslation("CMEditViewBulkLocale.continue-confirmation"),
756
+ defaultMessage: "Are you sure you want to continue?"
691
757
  }) })
692
758
  ] })
693
759
  }
694
760
  };
695
761
  }
762
+ const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
696
763
  return {
697
764
  label: formatMessage({
698
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
699
- defaultMessage: "Publish Multiple Locales"
765
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
766
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
700
767
  }),
701
- icon: /* @__PURE__ */ jsx(ListPlus, {}),
702
- disabled: isPublishedTab || !canPublish,
768
+ variant: isBulkPublish ? "secondary" : "danger",
769
+ icon: isBulkPublish ? /* @__PURE__ */ jsx(ListPlus, {}) : /* @__PURE__ */ jsx(Cross, {}),
770
+ disabled: isOnPublishedTab || canPublish.length === 0,
703
771
  position: ["panel"],
704
- variant: "secondary",
705
772
  dialog: {
706
773
  type: "modal",
707
774
  title: formatMessage({
708
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
709
- defaultMessage: "Publish Multiple Locales"
775
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
776
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
710
777
  }),
711
778
  content: () => {
712
779
  return /* @__PURE__ */ jsx(
@@ -725,28 +792,35 @@ const BulkLocalePublishAction = ({
725
792
  validationErrors,
726
793
  headers,
727
794
  rows,
728
- localesMetadata
795
+ localesMetadata,
796
+ action: action ?? "bulk-publish"
729
797
  }
730
798
  )
731
799
  }
732
800
  );
733
801
  },
734
- footer: () => /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
735
- Button$1,
802
+ footer: () => /* @__PURE__ */ jsx(Modal.Footer, { justifyContent: "flex-end", children: /* @__PURE__ */ jsx(
803
+ Button,
736
804
  {
737
805
  loading: isDraftRelationsLoading,
738
- disabled: localesToPublish.length === 0,
806
+ disabled: !hasPermission || localesForAction.length === 0,
739
807
  variant: "default",
740
808
  onClick: handleAction,
741
809
  children: formatMessage({
742
- id: "app.utils.publish",
743
- defaultMessage: "Publish"
810
+ id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
811
+ defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
744
812
  })
745
813
  }
746
814
  ) })
747
815
  }
748
816
  };
749
817
  };
818
+ const BulkLocalePublishAction = (props) => {
819
+ return BulkLocaleAction({ action: "bulk-publish", ...props });
820
+ };
821
+ const BulkLocaleUnpublishAction = (props) => {
822
+ return BulkLocaleAction({ action: "bulk-unpublish", ...props });
823
+ };
750
824
  const StyledTrash = styled(Trash)`
751
825
  path {
752
826
  fill: currentColor;
@@ -803,13 +877,6 @@ const UnpublishModalAdditionalInfo = () => {
803
877
  }
804
878
  ) });
805
879
  };
806
- const Initializer = ({ setPlugin }) => {
807
- const setPluginRef = React.useRef(setPlugin);
808
- React.useEffect(() => {
809
- setPluginRef.current(pluginId);
810
- }, []);
811
- return null;
812
- };
813
880
  const LocalePicker = () => {
814
881
  const { formatMessage } = useIntl();
815
882
  const [{ query }, setQuery] = useQueryParams();
@@ -869,7 +936,7 @@ const PERMISSIONS = {
869
936
  read: [{ action: "plugin::i18n.locale.read", subject: null }]
870
937
  };
871
938
  const mutateEditViewHook = ({ layout }) => {
872
- if ("i18n" in layout.options && typeof layout.options.i18n === "object" && layout.options.i18n !== null && "localized" in layout.options.i18n && !layout.options.i18n.localized) {
939
+ if (!("i18n" in layout.options) || typeof layout.options.i18n === "object" && layout.options.i18n !== null && "localized" in layout.options.i18n && !layout.options.i18n.localized) {
873
940
  return { layout };
874
941
  }
875
942
  const components = Object.entries(layout.components).reduce(
@@ -915,7 +982,7 @@ const doesFieldHaveI18nPluginOpt = (pluginOpts) => {
915
982
  const LabelAction = ({ title, icon }) => {
916
983
  const { formatMessage } = useIntl();
917
984
  return /* @__PURE__ */ jsxs(Span, { tag: "span", children: [
918
- /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: `(${formatMessage(title)})` }),
985
+ /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: formatMessage(title) }),
919
986
  React.cloneElement(icon, {
920
987
  "aria-hidden": true,
921
988
  focusable: false
@@ -950,13 +1017,7 @@ const LocaleListCell = ({
950
1017
  }
951
1018
  });
952
1019
  const { locale: language } = useIntl();
953
- const [visible, setVisible] = React.useState(false);
954
- const buttonRef = React.useRef(null);
955
1020
  const { data: locales = [] } = useGetLocalesQuery();
956
- const handleTogglePopover = (e) => {
957
- e.stopPropagation();
958
- setVisible((prev) => !prev);
959
- };
960
1021
  const formatter = useCollator(language, {
961
1022
  sensitivity: "base"
962
1023
  });
@@ -978,64 +1039,14 @@ const LocaleListCell = ({
978
1039
  }
979
1040
  return locale.name;
980
1041
  }).toSorted((a, b) => formatter.compare(a, b));
981
- return /* @__PURE__ */ jsxs(Button, { type: "button", onClick: handleTogglePopover, ref: buttonRef, children: [
982
- /* @__PURE__ */ jsxs(
983
- ActionWrapper,
984
- {
985
- minWidth: "100%",
986
- alignItems: "center",
987
- justifyContent: "center",
988
- height: "3.2rem",
989
- width: "3.2rem",
990
- children: [
991
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, children: localesForDocument.join(", ") }),
992
- /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, {}) })
993
- ]
994
- }
995
- ),
996
- visible && /* @__PURE__ */ jsx(
997
- Popover,
998
- {
999
- onDismiss: () => setVisible(false),
1000
- source: buttonRef,
1001
- spacing: 16,
1002
- centered: true,
1003
- children: /* @__PURE__ */ jsx("ul", { children: localesForDocument.map((name) => /* @__PURE__ */ jsx(Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsx(Typography, { children: name }) }, name)) })
1004
- }
1005
- )
1042
+ return /* @__PURE__ */ jsxs(Popover.Root, { children: [
1043
+ /* @__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: [
1044
+ /* @__PURE__ */ jsx(Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
1045
+ /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(CaretDown, { width: "1.2rem", height: "1.2rem" }) })
1046
+ ] }) }) }),
1047
+ /* @__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)) }) })
1006
1048
  ] });
1007
1049
  };
1008
- const Button = styled.button`
1009
- width: 100%;
1010
-
1011
- svg {
1012
- > g,
1013
- path {
1014
- fill: ${({ theme }) => theme.colors.neutral500};
1015
- }
1016
- }
1017
- &:hover {
1018
- svg {
1019
- > g,
1020
- path {
1021
- fill: ${({ theme }) => theme.colors.neutral600};
1022
- }
1023
- }
1024
- }
1025
- &:active {
1026
- svg {
1027
- > g,
1028
- path {
1029
- fill: ${({ theme }) => theme.colors.neutral400};
1030
- }
1031
- }
1032
- }
1033
- `;
1034
- const ActionWrapper = styled(Flex)`
1035
- svg {
1036
- height: 0.4rem;
1037
- }
1038
- `;
1039
1050
  const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1040
1051
  const { options } = layout;
1041
1052
  const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
@@ -1064,18 +1075,11 @@ const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1064
1075
  const addLocaleToReleasesHook = ({ displayedHeaders = [] }) => {
1065
1076
  return {
1066
1077
  displayedHeaders: [
1067
- // TODO: Fix when migrating to v5
1068
- // ...displayedHeaders,
1078
+ ...displayedHeaders,
1069
1079
  {
1070
- key: "__locale__",
1071
- fieldSchema: { type: "string" },
1072
- metadatas: {
1073
- label: {
1074
- id: "content-releases.page.ReleaseDetails.table.header.label.locale",
1075
- defaultMessage: "locale"
1076
- },
1077
- searchable: false,
1078
- sortable: false
1080
+ label: {
1081
+ id: "content-releases.page.ReleaseDetails.table.header.label.locale",
1082
+ defaultMessage: "locale"
1079
1083
  },
1080
1084
  name: "locale"
1081
1085
  }
@@ -1223,8 +1227,6 @@ const index = {
1223
1227
  app.addRBACMiddleware([localeMiddleware]);
1224
1228
  app.registerPlugin({
1225
1229
  id: pluginId,
1226
- initializer: Initializer,
1227
- isReady: false,
1228
1230
  name: pluginId
1229
1231
  });
1230
1232
  },
@@ -1242,7 +1244,7 @@ const index = {
1242
1244
  },
1243
1245
  id: "internationalization",
1244
1246
  to: "internationalization",
1245
- Component: () => import("./SettingsPage-0FFSTUW2.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
1247
+ Component: () => import("./SettingsPage-CPNFX0bZ.mjs").then((mod) => ({ default: mod.ProtectedSettingsPage })),
1246
1248
  permissions: PERMISSIONS.accessMain
1247
1249
  });
1248
1250
  const contentManager = app.getPlugin("content-manager");
@@ -1254,6 +1256,7 @@ const index = {
1254
1256
  });
1255
1257
  contentManager.apis.addDocumentAction((actions) => {
1256
1258
  actions.splice(2, 0, BulkLocalePublishAction);
1259
+ actions.splice(5, 0, BulkLocaleUnpublishAction);
1257
1260
  return actions;
1258
1261
  });
1259
1262
  contentManager.injectComponent("listView", "actions", {
@@ -1359,7 +1362,7 @@ const index = {
1359
1362
  async registerTrads({ locales }) {
1360
1363
  const importedTrads = await Promise.all(
1361
1364
  locales.map((locale) => {
1362
- 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-18tWw4P6.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 }) => {
1365
+ 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-CtekP_47.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 }) => {
1363
1366
  return {
1364
1367
  data: prefixPluginTranslations(data, pluginId),
1365
1368
  locale
@@ -1385,4 +1388,4 @@ export {
1385
1388
  index as i,
1386
1389
  useCreateLocaleMutation as u
1387
1390
  };
1388
- //# sourceMappingURL=index-BddUXwss.mjs.map
1391
+ //# sourceMappingURL=index-CgjpU2bY.mjs.map