@strapi/i18n 0.0.0-experimental.5e04dee5c96cd68273df3b3cadf4635e19dc2afc → 0.0.0-experimental.5f6fc3bc1a7d1b7c5fe926a37d4869f00e812287

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 (41) hide show
  1. package/dist/_chunks/{SettingsPage-CbEn7zF5.mjs → SettingsPage-BIZrSFGY.mjs} +2 -2
  2. package/dist/_chunks/{SettingsPage-CbEn7zF5.mjs.map → SettingsPage-BIZrSFGY.mjs.map} +1 -1
  3. package/dist/_chunks/{SettingsPage-C0l7c5fn.js → SettingsPage-kMDCxWLw.js} +2 -2
  4. package/dist/_chunks/{SettingsPage-C0l7c5fn.js.map → SettingsPage-kMDCxWLw.js.map} +1 -1
  5. package/dist/_chunks/{en-BsOU9o5z.js → en-B6327hMz.js} +8 -2
  6. package/dist/_chunks/en-B6327hMz.js.map +1 -0
  7. package/dist/_chunks/{en-CM6Pjfyv.mjs → en-DZXpOMHo.mjs} +8 -2
  8. package/dist/_chunks/en-DZXpOMHo.mjs.map +1 -0
  9. package/dist/_chunks/{index-CkrCiZyq.mjs → index-DXrgAtCA.mjs} +330 -126
  10. package/dist/_chunks/index-DXrgAtCA.mjs.map +1 -0
  11. package/dist/_chunks/{index-C0i3v7QQ.js → index-Dncj9Inq.js} +323 -119
  12. package/dist/_chunks/index-Dncj9Inq.js.map +1 -0
  13. package/dist/admin/index.js +1 -1
  14. package/dist/admin/index.mjs +1 -1
  15. package/dist/admin/src/components/BulkLocaleActionModal.d.ts +2 -1
  16. package/dist/admin/src/components/CMHeaderActions.d.ts +27 -3
  17. package/dist/admin/src/utils/clean.d.ts +4 -0
  18. package/dist/server/index.js +61 -98
  19. package/dist/server/index.js.map +1 -1
  20. package/dist/server/index.mjs +62 -99
  21. package/dist/server/index.mjs.map +1 -1
  22. package/dist/server/src/bootstrap.d.ts +1 -4
  23. package/dist/server/src/bootstrap.d.ts.map +1 -1
  24. package/dist/server/src/index.d.ts +15 -13
  25. package/dist/server/src/index.d.ts.map +1 -1
  26. package/dist/server/src/services/index.d.ts +14 -10
  27. package/dist/server/src/services/index.d.ts.map +1 -1
  28. package/dist/server/src/services/permissions/actions.d.ts +14 -2
  29. package/dist/server/src/services/permissions/actions.d.ts.map +1 -1
  30. package/dist/server/src/services/permissions.d.ts +14 -2
  31. package/dist/server/src/services/permissions.d.ts.map +1 -1
  32. package/dist/server/src/utils/index.d.ts +0 -2
  33. package/dist/server/src/utils/index.d.ts.map +1 -1
  34. package/package.json +9 -9
  35. package/dist/_chunks/en-BsOU9o5z.js.map +0 -1
  36. package/dist/_chunks/en-CM6Pjfyv.mjs.map +0 -1
  37. package/dist/_chunks/index-C0i3v7QQ.js.map +0 -1
  38. package/dist/_chunks/index-CkrCiZyq.mjs.map +0 -1
  39. package/dist/server/src/services/entity-service-decorator.d.ts +0 -29
  40. package/dist/server/src/services/entity-service-decorator.d.ts.map +0 -1
  41. package/strapi-server.js +0 -3
@@ -241,10 +241,93 @@ const relationsApi = i18nApi.injectEndpoints({
241
241
  })
242
242
  });
243
243
  const { useGetManyDraftRelationCountQuery } = relationsApi;
244
+ const cleanData = (data, schema, components) => {
245
+ const cleanedData = removeFields(data, [
246
+ "createdAt",
247
+ "createdBy",
248
+ "updatedAt",
249
+ "updatedBy",
250
+ "id",
251
+ "documentId",
252
+ "publishedAt",
253
+ "strapi_stage",
254
+ "strapi_assignee",
255
+ "locale"
256
+ ]);
257
+ const cleanedDataWithoutPasswordAndRelation = recursiveRemoveFieldTypes(
258
+ cleanedData,
259
+ schema,
260
+ components,
261
+ ["relation", "password"]
262
+ );
263
+ return cleanedDataWithoutPasswordAndRelation;
264
+ };
265
+ const removeFields = (data, fields) => {
266
+ return Object.keys(data).reduce((acc, current) => {
267
+ if (fields.includes(current)) {
268
+ return acc;
269
+ }
270
+ acc[current] = data[current];
271
+ return acc;
272
+ }, {});
273
+ };
274
+ const recursiveRemoveFieldTypes = (data, schema, components, fields) => {
275
+ return Object.keys(data).reduce((acc, current) => {
276
+ const attribute = schema.attributes[current] ?? { type: void 0 };
277
+ if (fields.includes(attribute.type)) {
278
+ return acc;
279
+ }
280
+ if (attribute.type === "dynamiczone") {
281
+ acc[current] = data[current].map((componentValue, index2) => {
282
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
283
+ componentValue,
284
+ components[componentValue.__component],
285
+ components,
286
+ fields
287
+ );
288
+ return {
289
+ ...rest,
290
+ __temp_key__: index2 + 1
291
+ };
292
+ });
293
+ } else if (attribute.type === "component") {
294
+ const { repeatable, component } = attribute;
295
+ if (repeatable) {
296
+ acc[current] = (data[current] ?? []).map((compoData, index2) => {
297
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
298
+ compoData,
299
+ components[component],
300
+ components,
301
+ fields
302
+ );
303
+ return {
304
+ ...rest,
305
+ __temp_key__: index2 + 1
306
+ };
307
+ });
308
+ } else {
309
+ const { id: _, ...rest } = recursiveRemoveFieldTypes(
310
+ data[current] ?? {},
311
+ components[component],
312
+ components,
313
+ fields
314
+ );
315
+ acc[current] = rest;
316
+ }
317
+ } else {
318
+ acc[current] = data[current];
319
+ }
320
+ return acc;
321
+ }, {});
322
+ };
244
323
  const isErrorMessageDescriptor = (object) => {
245
324
  return typeof object === "object" && object !== null && "id" in object && "defaultMessage" in object;
246
325
  };
247
- const EntryValidationText = ({ status = "draft", validationErrors }) => {
326
+ const EntryValidationText = ({
327
+ status = "draft",
328
+ validationErrors,
329
+ action
330
+ }) => {
248
331
  const { formatMessage } = reactIntl.useIntl();
249
332
  const getErrorStr = (key, value) => {
250
333
  if (typeof value === "string") {
@@ -278,30 +361,63 @@ const EntryValidationText = ({ status = "draft", validationErrors }) => {
278
361
  ) })
279
362
  ] });
280
363
  }
281
- if (status === "published") {
282
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
283
- /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
284
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
285
- id: "content-manager.bulk-publish.already-published",
286
- defaultMessage: "Already Published"
287
- }) })
288
- ] });
289
- }
290
- if (status === "modified") {
291
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
292
- /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowsCounterClockwise, { fill: "alternative600" }),
293
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
294
- id: "app.utils.ready-to-publish-changes",
295
- defaultMessage: "Ready to publish changes"
296
- }) })
297
- ] });
298
- }
364
+ const getStatusMessage = () => {
365
+ if (action === "bulk-publish") {
366
+ if (status === "published") {
367
+ return {
368
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
369
+ text: formatMessage({
370
+ id: "content-manager.bulk-publish.already-published",
371
+ defaultMessage: "Already Published"
372
+ }),
373
+ textColor: "success600",
374
+ fontWeight: "bold"
375
+ };
376
+ } else if (status === "modified") {
377
+ return {
378
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowsCounterClockwise, { fill: "alternative600" }),
379
+ text: formatMessage({
380
+ id: "app.utils.ready-to-publish-changes",
381
+ defaultMessage: "Ready to publish changes"
382
+ })
383
+ };
384
+ } else {
385
+ return {
386
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
387
+ text: formatMessage({
388
+ id: "app.utils.ready-to-publish",
389
+ defaultMessage: "Ready to publish"
390
+ })
391
+ };
392
+ }
393
+ } else {
394
+ if (status === "draft") {
395
+ return {
396
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
397
+ text: formatMessage({
398
+ id: "content-manager.bulk-unpublish.already-unpublished",
399
+ defaultMessage: "Already Unpublished"
400
+ }),
401
+ textColor: "success600",
402
+ fontWeight: "bold"
403
+ };
404
+ } else {
405
+ return {
406
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
407
+ text: formatMessage({
408
+ id: "app.utils.ready-to-unpublish-changes",
409
+ defaultMessage: "Ready to unpublish"
410
+ }),
411
+ textColor: "success600",
412
+ fontWeight: "bold"
413
+ };
414
+ }
415
+ }
416
+ };
417
+ const { icon, text, textColor = "success600", fontWeight = "normal" } = getStatusMessage();
299
418
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
300
- /* @__PURE__ */ jsxRuntime.jsx(icons.CheckCircle, { fill: "success600" }),
301
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
302
- id: "app.utils.ready-to-publish",
303
- defaultMessage: "Ready to publish"
304
- }) })
419
+ icon,
420
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor, fontWeight, children: text })
305
421
  ] });
306
422
  };
307
423
  const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
@@ -309,7 +425,8 @@ const BulkLocaleActionModal = ({
309
425
  headers,
310
426
  rows,
311
427
  localesMetadata,
312
- validationErrors = {}
428
+ validationErrors = {},
429
+ action
313
430
  }) => {
314
431
  const { formatMessage } = reactIntl.useIntl();
315
432
  const selectedRows = strapiAdmin.useTable(
@@ -322,22 +439,24 @@ const BulkLocaleActionModal = ({
322
439
  return acc;
323
440
  }, {});
324
441
  const localesWithErrors = Object.keys(validationErrors);
325
- const alreadyPublishedCount = selectedRows.filter(
442
+ const publishedCount = selectedRows.filter(
326
443
  ({ locale }) => currentStatusByLocale[locale] === "published"
327
444
  ).length;
328
- const readyToPublishCount = selectedRows.filter(
445
+ const draftCount = selectedRows.filter(
329
446
  ({ locale }) => (currentStatusByLocale[locale] === "draft" || currentStatusByLocale[locale] === "modified") && !localesWithErrors.includes(locale)
330
447
  ).length;
331
448
  const withErrorsCount = localesWithErrors.length;
449
+ const messageId = action === "bulk-publish" ? "content-manager.containers.list.selectedEntriesModal.selectedCount.publish" : "content-manager.containers.list.selectedEntriesModal.selectedCount.unpublish";
450
+ 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.";
332
451
  return formatMessage(
333
452
  {
334
- id: "content-manager.containers.list.selectedEntriesModal.selectedCount",
335
- 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."
453
+ id: messageId,
454
+ defaultMessage
336
455
  },
337
456
  {
338
457
  withErrorsCount,
339
- readyToPublishCount,
340
- alreadyPublishedCount,
458
+ draftCount,
459
+ publishedCount,
341
460
  b: BoldChunk
342
461
  }
343
462
  );
@@ -369,7 +488,7 @@ const BulkLocaleActionModal = ({
369
488
  children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "pi", fontWeight: "bold", children: capitalize(status) })
370
489
  }
371
490
  ) }) }),
372
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(EntryValidationText, { validationErrors: error, status }) }),
491
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(EntryValidationText, { validationErrors: error, status, action }) }),
373
492
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
374
493
  designSystem.IconButton,
375
494
  {
@@ -406,7 +525,13 @@ const LocalePickerAction = ({
406
525
  const [{ query: query2 }, setQuery] = strapiAdmin.useQueryParams();
407
526
  const { hasI18n, canCreate, canRead } = useI18n();
408
527
  const { data: locales = [] } = useGetLocalesQuery();
409
- const { schema } = strapiAdmin$1.unstable_useDocument({ model, collectionType, documentId });
528
+ const currentDesiredLocale = query2.plugins?.i18n?.locale;
529
+ const { schema } = strapiAdmin$1.unstable_useDocument({
530
+ model,
531
+ collectionType,
532
+ documentId,
533
+ params: { locale: currentDesiredLocale }
534
+ });
410
535
  const handleSelect = React__namespace.useCallback(
411
536
  (value) => {
412
537
  setQuery({
@@ -424,21 +549,20 @@ const LocalePickerAction = ({
424
549
  if (!Array.isArray(locales) || !hasI18n) {
425
550
  return;
426
551
  }
427
- const currentDesiredLocale = query2.plugins?.i18n?.locale;
428
552
  const doesLocaleExist = locales.find((loc) => loc.code === currentDesiredLocale);
429
553
  const defaultLocale = locales.find((locale) => locale.isDefault);
430
554
  if (!doesLocaleExist && defaultLocale?.code) {
431
555
  handleSelect(defaultLocale.code);
432
556
  }
433
- }, [handleSelect, hasI18n, locales, query2.plugins?.i18n?.locale]);
434
- if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
435
- return null;
436
- }
437
- const currentLocale = query2.plugins?.i18n?.locale || locales.find((loc) => loc.isDefault)?.code;
557
+ }, [handleSelect, hasI18n, locales, currentDesiredLocale]);
558
+ const currentLocale = Array.isArray(locales) ? locales.find((locale) => locale.code === currentDesiredLocale)?.code : void 0;
438
559
  const allCurrentLocales = [
439
560
  { status: getDocumentStatus(document, meta), locale: currentLocale },
440
561
  ...meta?.availableLocales ?? []
441
562
  ];
563
+ if (!hasI18n || !Array.isArray(locales) || locales.length === 0) {
564
+ return null;
565
+ }
442
566
  return {
443
567
  label: formatMessage({
444
568
  id: getTranslation("Settings.locales.modal.locales.label"),
@@ -450,7 +574,7 @@ const LocalePickerAction = ({
450
574
  );
451
575
  const status = currentLocaleDoc?.status ?? "draft";
452
576
  const permissionsToCheck = currentLocaleDoc ? canCreate : canRead;
453
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
577
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
454
578
  return {
455
579
  disabled: !permissionsToCheck.includes(locale.code),
456
580
  value: locale.code,
@@ -486,6 +610,95 @@ const getDocumentStatus = (document, meta) => {
486
610
  }
487
611
  return docStatus;
488
612
  };
613
+ const FillFromAnotherLocaleAction = ({
614
+ documentId,
615
+ meta,
616
+ model,
617
+ collectionType
618
+ }) => {
619
+ const { formatMessage } = reactIntl.useIntl();
620
+ const [{ query: query2 }] = strapiAdmin.useQueryParams();
621
+ const currentDesiredLocale = query2.plugins?.i18n?.locale;
622
+ const [localeSelected, setLocaleSelected] = React__namespace.useState(null);
623
+ const setValues = strapiAdmin.useForm("FillFromAnotherLocale", (state) => state.setValues);
624
+ const { getDocument } = strapiAdmin$1.unstable_useDocumentActions();
625
+ const { schema, components } = strapiAdmin$1.unstable_useDocument({
626
+ model,
627
+ documentId,
628
+ collectionType,
629
+ params: { locale: currentDesiredLocale }
630
+ });
631
+ const { data: locales = [] } = useGetLocalesQuery();
632
+ const availableLocales = Array.isArray(locales) ? locales.filter((locale) => meta?.availableLocales.some((l) => l.locale === locale.code)) : [];
633
+ const fillFromLocale = (onClose) => async () => {
634
+ const response = await getDocument({
635
+ collectionType,
636
+ model,
637
+ documentId,
638
+ params: { locale: localeSelected }
639
+ });
640
+ if (!response || !schema) {
641
+ return;
642
+ }
643
+ const { data } = response;
644
+ const cleanedData = cleanData(data, schema, components);
645
+ setValues(cleanedData);
646
+ onClose();
647
+ };
648
+ return {
649
+ type: "icon",
650
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Download, {}),
651
+ disabled: availableLocales.length === 0,
652
+ label: formatMessage({
653
+ id: getTranslation("CMEditViewCopyLocale.copy-text"),
654
+ defaultMessage: "Fill in from another locale"
655
+ }),
656
+ dialog: {
657
+ type: "dialog",
658
+ title: formatMessage({
659
+ id: getTranslation("CMEditViewCopyLocale.dialog.title"),
660
+ defaultMessage: "Confirmation"
661
+ }),
662
+ content: ({ onClose }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
663
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 3, children: [
664
+ /* @__PURE__ */ jsxRuntime.jsx(icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
665
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textAlign: "center", children: formatMessage({
666
+ id: getTranslation("CMEditViewCopyLocale.dialog.body"),
667
+ defaultMessage: "Your current content will be erased and filled by the content of the selected locale:"
668
+ }) }),
669
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { width: "100%", children: [
670
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
671
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.label"),
672
+ defaultMessage: "Locale"
673
+ }) }),
674
+ /* @__PURE__ */ jsxRuntime.jsx(
675
+ designSystem.SingleSelect,
676
+ {
677
+ value: localeSelected,
678
+ placeholder: formatMessage({
679
+ id: getTranslation("CMEditViewCopyLocale.dialog.field.placeholder"),
680
+ defaultMessage: "Select one locale..."
681
+ }),
682
+ onChange: (value) => setLocaleSelected(value),
683
+ children: availableLocales.map((locale) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: locale.code, children: locale.name }, locale.code))
684
+ }
685
+ )
686
+ ] })
687
+ ] }) }),
688
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Footer, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, width: "100%", children: [
689
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { flex: "auto", variant: "tertiary", onClick: onClose, children: formatMessage({
690
+ id: getTranslation("CMEditViewCopyLocale.cancel-text"),
691
+ defaultMessage: "No, cancel"
692
+ }) }),
693
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { flex: "auto", variant: "success", onClick: fillFromLocale(onClose), children: formatMessage({
694
+ id: getTranslation("CMEditViewCopyLocale.submit-text"),
695
+ defaultMessage: "Yes, fill in"
696
+ }) })
697
+ ] }) })
698
+ ] })
699
+ }
700
+ };
701
+ };
489
702
  const DeleteLocaleAction = ({
490
703
  document,
491
704
  documentId,
@@ -497,16 +710,23 @@ const DeleteLocaleAction = ({
497
710
  const { toggleNotification } = strapiAdmin.useNotification();
498
711
  const { delete: deleteAction } = strapiAdmin$1.unstable_useDocumentActions();
499
712
  const { hasI18n, canDelete } = useI18n();
713
+ const [{ query: query2 }] = strapiAdmin.useQueryParams();
714
+ const { data: locales = [] } = useGetLocalesQuery();
715
+ const currentDesiredLocale = query2.plugins?.i18n?.locale;
716
+ const locale = !("error" in locales) && locales.find((loc) => loc.code === currentDesiredLocale);
500
717
  if (!hasI18n) {
501
718
  return null;
502
719
  }
503
720
  return {
504
721
  disabled: document?.locale && !canDelete.includes(document.locale) || !document || !document.id,
505
722
  position: ["header", "table-row"],
506
- label: formatMessage({
507
- id: getTranslation("actions.delete.label"),
508
- defaultMessage: "Delete locale"
509
- }),
723
+ label: formatMessage(
724
+ {
725
+ id: getTranslation("actions.delete.label"),
726
+ defaultMessage: "Delete entry ({locale})"
727
+ },
728
+ { locale: locale && locale.name }
729
+ ),
510
730
  icon: /* @__PURE__ */ jsxRuntime.jsx(StyledTrash, {}),
511
731
  variant: "danger",
512
732
  dialog: {
@@ -549,23 +769,24 @@ const DeleteLocaleAction = ({
549
769
  }
550
770
  };
551
771
  };
552
- const BulkLocalePublishAction = ({
772
+ const BulkLocaleAction = ({
553
773
  document: baseDocument,
554
774
  documentId,
555
775
  model,
556
- collectionType
776
+ collectionType,
777
+ action
557
778
  }) => {
558
779
  const baseLocale = baseDocument?.locale ?? null;
559
780
  const [{ query: query$1 }] = strapiAdmin.useQueryParams();
560
781
  const params = React__namespace.useMemo(() => strapiAdmin$1.buildValidParams(query$1), [query$1]);
561
- const isPublishedTab = query$1.status === "published";
782
+ const isOnPublishedTab = query$1.status === "published";
562
783
  const { formatMessage } = reactIntl.useIntl();
563
784
  const { hasI18n, canPublish } = useI18n();
564
785
  const { toggleNotification } = strapiAdmin.useNotification();
565
786
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
566
787
  const [selectedRows, setSelectedRows] = React__namespace.useState([]);
567
788
  const [isDraftRelationConfirmationOpen, setIsDraftRelationConfirmationOpen] = React__namespace.useState(false);
568
- const { publishMany: publishManyAction } = strapiAdmin$1.unstable_useDocumentActions();
789
+ const { publishMany: publishManyAction, unpublishMany: unpublishManyAction } = strapiAdmin$1.unstable_useDocumentActions();
569
790
  const {
570
791
  document,
571
792
  meta: documentMeta,
@@ -581,7 +802,7 @@ const BulkLocalePublishAction = ({
581
802
  }
582
803
  },
583
804
  {
584
- skip: !hasI18n
805
+ skip: !hasI18n || !baseLocale
585
806
  }
586
807
  );
587
808
  const { data: localesMetadata = [] } = useGetLocalesQuery(hasI18n ? void 0 : query.skipToken);
@@ -633,12 +854,19 @@ const BulkLocalePublishAction = ({
633
854
  }, {});
634
855
  return [rowsFromMeta, errors];
635
856
  }, [document, documentMeta?.availableLocales, validate]);
636
- const localesToPublish = selectedRows.reduce((acc, selectedRow) => {
637
- if (selectedRow.status !== "published" && !Object.keys(validationErrors).includes(selectedRow.locale)) {
857
+ const isBulkPublish = action === "bulk-publish";
858
+ const localesForAction = selectedRows.reduce((acc, selectedRow) => {
859
+ const isValidLocale = (
860
+ // Validation errors are irrelevant if we are trying to unpublish
861
+ !isBulkPublish || !Object.keys(validationErrors).includes(selectedRow.locale)
862
+ );
863
+ const shouldAddLocale = isBulkPublish ? selectedRow.status !== "published" && isValidLocale : selectedRow.status !== "draft" && isValidLocale;
864
+ if (shouldAddLocale) {
638
865
  acc.push(selectedRow.locale);
639
866
  }
640
867
  return acc;
641
868
  }, []);
869
+ const enableDraftRelationsCount = false;
642
870
  const {
643
871
  data: draftRelationsCount = 0,
644
872
  isLoading: isDraftRelationsLoading,
@@ -647,10 +875,10 @@ const BulkLocalePublishAction = ({
647
875
  {
648
876
  model,
649
877
  documentIds: [documentId],
650
- locale: localesToPublish
878
+ locale: localesForAction
651
879
  },
652
880
  {
653
- skip: !documentId || localesToPublish.length === 0
881
+ skip: !enableDraftRelationsCount
654
882
  }
655
883
  );
656
884
  React__namespace.useEffect(() => {
@@ -676,7 +904,18 @@ const BulkLocalePublishAction = ({
676
904
  documentIds: [documentId],
677
905
  params: {
678
906
  ...params,
679
- locale: localesToPublish
907
+ locale: localesForAction
908
+ }
909
+ });
910
+ setSelectedRows([]);
911
+ };
912
+ const unpublish = async () => {
913
+ await unpublishManyAction({
914
+ model,
915
+ documentIds: [documentId],
916
+ params: {
917
+ ...params,
918
+ locale: localesForAction
680
919
  }
681
920
  });
682
921
  setSelectedRows([]);
@@ -684,14 +923,12 @@ const BulkLocalePublishAction = ({
684
923
  const handleAction = async () => {
685
924
  if (draftRelationsCount > 0) {
686
925
  setIsDraftRelationConfirmationOpen(true);
687
- } else {
926
+ } else if (isBulkPublish) {
688
927
  await publish();
928
+ } else {
929
+ await unpublish();
689
930
  }
690
931
  };
691
- const isUnpublish = document?.status === "published";
692
- if (isUnpublish) {
693
- console.warn(["I18N"], "Bulk locale unpublish modal not implemented");
694
- }
695
932
  if (isDraftRelationConfirmationOpen) {
696
933
  return {
697
934
  label: formatMessage({
@@ -729,18 +966,18 @@ const BulkLocalePublishAction = ({
729
966
  const hasPermission = selectedRows.map(({ locale }) => locale).every((locale) => canPublish.includes(locale));
730
967
  return {
731
968
  label: formatMessage({
732
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
733
- defaultMessage: "Publish Multiple Locales"
969
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
970
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
734
971
  }),
735
- icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ListPlus, {}),
736
- disabled: isPublishedTab || canPublish.length === 0,
972
+ variant: isBulkPublish ? "secondary" : "danger",
973
+ icon: isBulkPublish ? /* @__PURE__ */ jsxRuntime.jsx(icons.ListPlus, {}) : /* @__PURE__ */ jsxRuntime.jsx(icons.Cross, {}),
974
+ disabled: isOnPublishedTab || canPublish.length === 0,
737
975
  position: ["panel"],
738
- variant: "secondary",
739
976
  dialog: {
740
977
  type: "modal",
741
978
  title: formatMessage({
742
- id: getTranslation("CMEditViewBulkLocale.publish-title"),
743
- defaultMessage: "Publish Multiple Locales"
979
+ id: getTranslation(`CMEditViewBulkLocale.${isBulkPublish ? "publish" : "unpublish"}-title`),
980
+ defaultMessage: `${isBulkPublish ? "Publish" : "Unpublish"} Multiple Locales`
744
981
  }),
745
982
  content: () => {
746
983
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -759,7 +996,8 @@ const BulkLocalePublishAction = ({
759
996
  validationErrors,
760
997
  headers,
761
998
  rows,
762
- localesMetadata
999
+ localesMetadata,
1000
+ action: action ?? "bulk-publish"
763
1001
  }
764
1002
  )
765
1003
  }
@@ -769,18 +1007,24 @@ const BulkLocalePublishAction = ({
769
1007
  designSystem.Button,
770
1008
  {
771
1009
  loading: isDraftRelationsLoading,
772
- disabled: !hasPermission || localesToPublish.length === 0,
1010
+ disabled: !hasPermission || localesForAction.length === 0,
773
1011
  variant: "default",
774
1012
  onClick: handleAction,
775
1013
  children: formatMessage({
776
- id: "app.utils.publish",
777
- defaultMessage: "Publish"
1014
+ id: isBulkPublish ? "app.utils.publish" : "app.utils.unpublish",
1015
+ defaultMessage: isBulkPublish ? "Publish" : "Unpublish"
778
1016
  })
779
1017
  }
780
1018
  ) })
781
1019
  }
782
1020
  };
783
1021
  };
1022
+ const BulkLocalePublishAction = (props) => {
1023
+ return BulkLocaleAction({ action: "bulk-publish", ...props });
1024
+ };
1025
+ const BulkLocaleUnpublishAction = (props) => {
1026
+ return BulkLocaleAction({ action: "bulk-unpublish", ...props });
1027
+ };
784
1028
  const StyledTrash = styledComponents.styled(icons.Trash)`
785
1029
  path {
786
1030
  fill: currentColor;
@@ -1000,54 +1244,13 @@ const LocaleListCell = ({
1000
1244
  return locale.name;
1001
1245
  }).toSorted((a, b) => formatter.compare(a, b));
1002
1246
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Popover.Root, { children: [
1003
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Popover.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsxs(
1004
- ActionWrapper,
1005
- {
1006
- minWidth: "100%",
1007
- alignItems: "center",
1008
- justifyContent: "center",
1009
- height: "3.2rem",
1010
- width: "3.2rem",
1011
- children: [
1012
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", ellipsis: true, children: localesForDocument.join(", ") }),
1013
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(icons.CaretDown, {}) })
1014
- ]
1015
- }
1016
- ) }) }),
1247
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Popover.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "ghost", type: "button", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { minWidth: "100%", alignItems: "center", justifyContent: "center", fontWeight: "regular", children: [
1248
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", ellipsis: true, marginRight: 2, children: localesForDocument.join(", ") }),
1249
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(icons.CaretDown, { width: "1.2rem", height: "1.2rem" }) })
1250
+ ] }) }) }),
1017
1251
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Popover.Content, { sideOffset: 16, children: /* @__PURE__ */ jsxRuntime.jsx("ul", { children: localesForDocument.map((name) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 3, tag: "li", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: name }) }, name)) }) })
1018
1252
  ] });
1019
1253
  };
1020
- const Button = styledComponents.styled.button`
1021
- width: 100%;
1022
-
1023
- svg {
1024
- > g,
1025
- path {
1026
- fill: ${({ theme }) => theme.colors.neutral500};
1027
- }
1028
- }
1029
- &:hover {
1030
- svg {
1031
- > g,
1032
- path {
1033
- fill: ${({ theme }) => theme.colors.neutral600};
1034
- }
1035
- }
1036
- }
1037
- &:active {
1038
- svg {
1039
- > g,
1040
- path {
1041
- fill: ${({ theme }) => theme.colors.neutral400};
1042
- }
1043
- }
1044
- }
1045
- `;
1046
- const ActionWrapper = styledComponents.styled(designSystem.Flex)`
1047
- svg {
1048
- height: 0.4rem;
1049
- }
1050
- `;
1051
1254
  const addColumnToTableHook = ({ displayedHeaders, layout }) => {
1052
1255
  const { options } = layout;
1053
1256
  const isFieldLocalized = doesPluginOptionsHaveI18nLocalized(options) ? options.i18n.localized : false;
@@ -1245,11 +1448,11 @@ const index = {
1245
1448
  },
1246
1449
  id: "internationalization",
1247
1450
  to: "internationalization",
1248
- Component: () => Promise.resolve().then(() => require("./SettingsPage-C0l7c5fn.js")).then((mod) => ({ default: mod.ProtectedSettingsPage })),
1451
+ Component: () => Promise.resolve().then(() => require("./SettingsPage-kMDCxWLw.js")).then((mod) => ({ default: mod.ProtectedSettingsPage })),
1249
1452
  permissions: PERMISSIONS.accessMain
1250
1453
  });
1251
1454
  const contentManager = app.getPlugin("content-manager");
1252
- contentManager.apis.addDocumentHeaderAction([LocalePickerAction]);
1455
+ contentManager.apis.addDocumentHeaderAction([LocalePickerAction, FillFromAnotherLocaleAction]);
1253
1456
  contentManager.apis.addDocumentAction((actions) => {
1254
1457
  const indexOfDeleteAction = actions.findIndex((action) => action.type === "delete");
1255
1458
  actions.splice(indexOfDeleteAction, 0, DeleteLocaleAction);
@@ -1257,6 +1460,7 @@ const index = {
1257
1460
  });
1258
1461
  contentManager.apis.addDocumentAction((actions) => {
1259
1462
  actions.splice(2, 0, BulkLocalePublishAction);
1463
+ actions.splice(5, 0, BulkLocaleUnpublishAction);
1260
1464
  return actions;
1261
1465
  });
1262
1466
  contentManager.injectComponent("listView", "actions", {
@@ -1362,7 +1566,7 @@ const index = {
1362
1566
  async registerTrads({ locales }) {
1363
1567
  const importedTrads = await Promise.all(
1364
1568
  locales.map((locale) => {
1365
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => Promise.resolve().then(() => require("./de-DtWiGdHl.js")), "./translations/dk.json": () => Promise.resolve().then(() => require("./dk-D8C-casx.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-BsOU9o5z.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-DS-XFGSw.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-BTjekDpq.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-DmcGUBQ3.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-Cn5RYonZ.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BMBgVL3s.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-CarUU76c.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-DSHIXAa3.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CukOviB0.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
1569
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => Promise.resolve().then(() => require("./de-DtWiGdHl.js")), "./translations/dk.json": () => Promise.resolve().then(() => require("./dk-D8C-casx.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-B6327hMz.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-DS-XFGSw.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-BTjekDpq.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-DmcGUBQ3.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-Cn5RYonZ.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BMBgVL3s.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-CarUU76c.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-DSHIXAa3.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CukOviB0.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
1366
1570
  return {
1367
1571
  data: prefixPluginTranslations(data, pluginId),
1368
1572
  locale
@@ -1386,4 +1590,4 @@ exports.useDeleteLocaleMutation = useDeleteLocaleMutation;
1386
1590
  exports.useGetDefaultLocalesQuery = useGetDefaultLocalesQuery;
1387
1591
  exports.useGetLocalesQuery = useGetLocalesQuery;
1388
1592
  exports.useUpdateLocaleMutation = useUpdateLocaleMutation;
1389
- //# sourceMappingURL=index-C0i3v7QQ.js.map
1593
+ //# sourceMappingURL=index-Dncj9Inq.js.map