@strapi/content-manager 0.0.0-experimental.2a7cb5ff33df35e8ccde5ef918f9f9a4a3ee9a08 → 0.0.0-experimental.32c4b04580cc12400710050c8198e46b3644cfd4

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 (90) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js → ComponentConfigurationPage-5ukroXAh.js} +3 -3
  3. package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js.map → ComponentConfigurationPage-5ukroXAh.js.map} +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs → ComponentConfigurationPage-BAgyHiMm.mjs} +3 -3
  5. package/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs.map → ComponentConfigurationPage-BAgyHiMm.mjs.map} +1 -1
  6. package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs → EditConfigurationPage-DmoXawIh.mjs} +3 -3
  7. package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs.map → EditConfigurationPage-DmoXawIh.mjs.map} +1 -1
  8. package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js → EditConfigurationPage-Xp7lun0f.js} +3 -3
  9. package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js.map → EditConfigurationPage-Xp7lun0f.js.map} +1 -1
  10. package/dist/_chunks/{EditViewPage-BtkEx339.mjs → EditViewPage-BLsjc5F-.mjs} +3 -3
  11. package/dist/_chunks/{EditViewPage-BtkEx339.mjs.map → EditViewPage-BLsjc5F-.mjs.map} +1 -1
  12. package/dist/_chunks/{EditViewPage-BqNpC6hO.js → EditViewPage-C-ukDOB7.js} +3 -3
  13. package/dist/_chunks/{EditViewPage-BqNpC6hO.js.map → EditViewPage-C-ukDOB7.js.map} +1 -1
  14. package/dist/_chunks/{Field-lsPFnAmH.js → Field-Bfph5SOd.js} +79 -54
  15. package/dist/_chunks/Field-Bfph5SOd.js.map +1 -0
  16. package/dist/_chunks/{Field-R5NbffTB.mjs → Field-Cs7duwWd.mjs} +79 -54
  17. package/dist/_chunks/Field-Cs7duwWd.mjs.map +1 -0
  18. package/dist/_chunks/{Form-CcGboku8.js → Form-CPYqIWDG.js} +2 -2
  19. package/dist/_chunks/{Form-CcGboku8.js.map → Form-CPYqIWDG.js.map} +1 -1
  20. package/dist/_chunks/{Form-BHmXSfyy.mjs → Form-Dg_GS5TQ.mjs} +2 -2
  21. package/dist/_chunks/{Form-BHmXSfyy.mjs.map → Form-Dg_GS5TQ.mjs.map} +1 -1
  22. package/dist/_chunks/{History-Bsud8jwh.js → History-DNQkXANT.js} +28 -18
  23. package/dist/_chunks/History-DNQkXANT.js.map +1 -0
  24. package/dist/_chunks/{History-ByUPL3T3.mjs → History-wrnHqf09.mjs} +28 -18
  25. package/dist/_chunks/History-wrnHqf09.mjs.map +1 -0
  26. package/dist/_chunks/{ListConfigurationPage-DiT463qx.js → ListConfigurationPage-CUQxfpjT.js} +8 -6
  27. package/dist/_chunks/ListConfigurationPage-CUQxfpjT.js.map +1 -0
  28. package/dist/_chunks/{ListConfigurationPage-Bm5HACXf.mjs → ListConfigurationPage-DScmJVkW.mjs} +8 -6
  29. package/dist/_chunks/ListConfigurationPage-DScmJVkW.mjs.map +1 -0
  30. package/dist/_chunks/{ListViewPage-CsrC9L_d.js → ListViewPage-BsLiH2-2.js} +3 -3
  31. package/dist/_chunks/{ListViewPage-CsrC9L_d.js.map → ListViewPage-BsLiH2-2.js.map} +1 -1
  32. package/dist/_chunks/{ListViewPage-JSyNAAYu.mjs → ListViewPage-C4IvrMgY.mjs} +3 -3
  33. package/dist/_chunks/{ListViewPage-JSyNAAYu.mjs.map → ListViewPage-C4IvrMgY.mjs.map} +1 -1
  34. package/dist/_chunks/{NoContentTypePage-Bsvng4II.js → NoContentTypePage-BZ-PnGAf.js} +2 -2
  35. package/dist/_chunks/{NoContentTypePage-Bsvng4II.js.map → NoContentTypePage-BZ-PnGAf.js.map} +1 -1
  36. package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs → NoContentTypePage-Djg8nPlj.mjs} +2 -2
  37. package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs.map → NoContentTypePage-Djg8nPlj.mjs.map} +1 -1
  38. package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs → NoPermissionsPage-DSP7R-hv.mjs} +2 -2
  39. package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs.map → NoPermissionsPage-DSP7R-hv.mjs.map} +1 -1
  40. package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js → NoPermissionsPage-_lUqjGW3.js} +2 -2
  41. package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js.map → NoPermissionsPage-_lUqjGW3.js.map} +1 -1
  42. package/dist/_chunks/{Relations-u8-37jK0.mjs → Relations-BZr8tL0R.mjs} +3 -3
  43. package/dist/_chunks/Relations-BZr8tL0R.mjs.map +1 -0
  44. package/dist/_chunks/{Relations-CghaPv2D.js → Relations-CtELXYIK.js} +3 -3
  45. package/dist/_chunks/Relations-CtELXYIK.js.map +1 -0
  46. package/dist/_chunks/{en-Ux26r5pl.mjs → en-BrCTWlZv.mjs} +5 -4
  47. package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-BrCTWlZv.mjs.map} +1 -1
  48. package/dist/_chunks/{en-fbKQxLGn.js → en-uOUIxfcQ.js} +5 -4
  49. package/dist/_chunks/{en-fbKQxLGn.js.map → en-uOUIxfcQ.js.map} +1 -1
  50. package/dist/_chunks/{index-BOZx6IMg.js → index-OerGjbAN.js} +251 -117
  51. package/dist/_chunks/index-OerGjbAN.js.map +1 -0
  52. package/dist/_chunks/{index-CaE6NG4a.mjs → index-c_5DdJi-.mjs} +253 -119
  53. package/dist/_chunks/index-c_5DdJi-.mjs.map +1 -0
  54. package/dist/_chunks/{layout-Ciz224q5.js → layout-Ci7qHlFb.js} +4 -4
  55. package/dist/_chunks/layout-Ci7qHlFb.js.map +1 -0
  56. package/dist/_chunks/{layout-Bx7svTbY.mjs → layout-oPBiO7RY.mjs} +4 -4
  57. package/dist/_chunks/layout-oPBiO7RY.mjs.map +1 -0
  58. package/dist/_chunks/{relations-Cxc1cEv3.mjs → relations-BIdWFjdq.mjs} +2 -2
  59. package/dist/_chunks/{relations-Cxc1cEv3.mjs.map → relations-BIdWFjdq.mjs.map} +1 -1
  60. package/dist/_chunks/{relations-CP8sB2YZ.js → relations-COBpStiF.js} +2 -2
  61. package/dist/_chunks/{relations-CP8sB2YZ.js.map → relations-COBpStiF.js.map} +1 -1
  62. package/dist/admin/index.js +1 -1
  63. package/dist/admin/index.mjs +1 -1
  64. package/dist/admin/src/history/index.d.ts +3 -0
  65. package/dist/admin/src/index.d.ts +1 -0
  66. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -0
  67. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  68. package/dist/server/index.js +33 -28
  69. package/dist/server/index.js.map +1 -1
  70. package/dist/server/index.mjs +33 -28
  71. package/dist/server/index.mjs.map +1 -1
  72. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  73. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  74. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  75. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  76. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  77. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  78. package/package.json +6 -6
  79. package/dist/_chunks/Field-R5NbffTB.mjs.map +0 -1
  80. package/dist/_chunks/Field-lsPFnAmH.js.map +0 -1
  81. package/dist/_chunks/History-Bsud8jwh.js.map +0 -1
  82. package/dist/_chunks/History-ByUPL3T3.mjs.map +0 -1
  83. package/dist/_chunks/ListConfigurationPage-Bm5HACXf.mjs.map +0 -1
  84. package/dist/_chunks/ListConfigurationPage-DiT463qx.js.map +0 -1
  85. package/dist/_chunks/Relations-CghaPv2D.js.map +0 -1
  86. package/dist/_chunks/Relations-u8-37jK0.mjs.map +0 -1
  87. package/dist/_chunks/index-BOZx6IMg.js.map +0 -1
  88. package/dist/_chunks/index-CaE6NG4a.mjs.map +0 -1
  89. package/dist/_chunks/layout-Bx7svTbY.mjs.map +0 -1
  90. package/dist/_chunks/layout-Ciz224q5.js.map +0 -1
@@ -2,15 +2,15 @@
2
2
  const Icons = require("@strapi/icons");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const strapiAdmin = require("@strapi/admin/strapi-admin");
5
- const qs = require("qs");
6
- const reactIntl = require("react-intl");
7
- const reactRouterDom = require("react-router-dom");
8
5
  const React = require("react");
9
6
  const designSystem = require("@strapi/design-system");
7
+ const reactIntl = require("react-intl");
8
+ const reactRouterDom = require("react-router-dom");
10
9
  const styledComponents = require("styled-components");
11
10
  const yup = require("yup");
12
11
  const pipe = require("lodash/fp/pipe");
13
12
  const dateFns = require("date-fns");
13
+ const qs = require("qs");
14
14
  const toolkit = require("@reduxjs/toolkit");
15
15
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
16
16
  function _interopNamespace(e) {
@@ -70,42 +70,6 @@ const useInjectionZone = (area) => {
70
70
  const [page, position] = area.split(".");
71
71
  return contentManagerPlugin.getInjectedComponents(page, position);
72
72
  };
73
- const HistoryAction = ({ model, document }) => {
74
- const { formatMessage } = reactIntl.useIntl();
75
- const [{ query }] = strapiAdmin.useQueryParams();
76
- const navigate = reactRouterDom.useNavigate();
77
- const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
78
- if (!window.strapi.features.isEnabled("cms-content-history")) {
79
- return null;
80
- }
81
- return {
82
- icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
83
- label: formatMessage({
84
- id: "content-manager.history.document-action",
85
- defaultMessage: "Content History"
86
- }),
87
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
88
- disabled: (
89
- /**
90
- * The user is creating a new document.
91
- * It hasn't been saved yet, so there's no history to go to
92
- */
93
- !document || /**
94
- * The document has been created but the current dimension has never been saved.
95
- * For example, the user is creating a new locale in an existing document,
96
- * so there's no history for the document in that locale
97
- */
98
- !document.id || /**
99
- * History is only available for content types created by the user.
100
- * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
101
- * which start with `admin::` or `plugin::`
102
- */
103
- !model.startsWith("api::")
104
- ),
105
- position: "header"
106
- };
107
- };
108
- HistoryAction.type = "history";
109
73
  const ID = "id";
110
74
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
111
75
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -229,7 +193,12 @@ const documentApi = contentManagerApi.injectEndpoints({
229
193
  params: query
230
194
  }
231
195
  }),
232
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
196
+ invalidatesTags: (_result, error, { model }) => {
197
+ if (error) {
198
+ return [];
199
+ }
200
+ return [{ type: "Document", id: `${model}_LIST` }];
201
+ }
233
202
  }),
234
203
  cloneDocument: builder.mutation({
235
204
  query: ({ model, sourceId, data, params }) => ({
@@ -419,6 +388,18 @@ const documentApi = contentManagerApi.injectEndpoints({
419
388
  },
420
389
  "Relations"
421
390
  ];
391
+ },
392
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
393
+ const patchResult = dispatch(
394
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
395
+ Object.assign(draft.data, data);
396
+ })
397
+ );
398
+ try {
399
+ await queryFulfilled;
400
+ } catch {
401
+ patchResult.undo();
402
+ }
422
403
  }
423
404
  }),
424
405
  unpublishDocument: builder.mutation({
@@ -621,11 +602,11 @@ const createAttributeSchema = (attribute) => {
621
602
  }
622
603
  };
623
604
  const addRequiredValidation = (attribute) => (schema) => {
605
+ if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
606
+ return schema.min(1, strapiAdmin.translatedErrors.required);
607
+ }
624
608
  if (attribute.required && attribute.type !== "relation") {
625
- return schema.required({
626
- id: strapiAdmin.translatedErrors.required.id,
627
- defaultMessage: "This field is required."
628
- });
609
+ return schema.required(strapiAdmin.translatedErrors.required);
629
610
  }
630
611
  return schema?.nullable ? schema.nullable() : (
631
612
  // In some cases '.nullable' will not be available on the schema.
@@ -659,6 +640,28 @@ const addMaxLengthValidation = (attribute) => (schema) => {
659
640
  const addMinValidation = (attribute) => (schema) => {
660
641
  if ("min" in attribute) {
661
642
  const min = toInteger(attribute.min);
643
+ if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
644
+ if (!attribute.required && "test" in schema && min) {
645
+ return schema.test(
646
+ "custom-min",
647
+ {
648
+ ...strapiAdmin.translatedErrors.min,
649
+ values: {
650
+ min: attribute.min
651
+ }
652
+ },
653
+ (value) => {
654
+ if (!value) {
655
+ return true;
656
+ }
657
+ if (Array.isArray(value) && value.length === 0) {
658
+ return true;
659
+ }
660
+ return value.length >= min;
661
+ }
662
+ );
663
+ }
664
+ }
662
665
  if ("min" in schema && min) {
663
666
  return schema.min(min, {
664
667
  ...strapiAdmin.translatedErrors.min,
@@ -1209,7 +1212,6 @@ const useDocumentActions = () => {
1209
1212
  sourceId
1210
1213
  });
1211
1214
  if ("error" in res) {
1212
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1213
1215
  return { error: res.error };
1214
1216
  }
1215
1217
  toggleNotification({
@@ -1290,7 +1292,7 @@ const useDocumentActions = () => {
1290
1292
  };
1291
1293
  };
1292
1294
  const ProtectedHistoryPage = React.lazy(
1293
- () => Promise.resolve().then(() => require("./History-Bsud8jwh.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1295
+ () => Promise.resolve().then(() => require("./History-DNQkXANT.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1294
1296
  );
1295
1297
  const routes$1 = [
1296
1298
  {
@@ -1303,31 +1305,31 @@ const routes$1 = [
1303
1305
  }
1304
1306
  ];
1305
1307
  const ProtectedEditViewPage = React.lazy(
1306
- () => Promise.resolve().then(() => require("./EditViewPage-BqNpC6hO.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1308
+ () => Promise.resolve().then(() => require("./EditViewPage-C-ukDOB7.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1307
1309
  );
1308
1310
  const ProtectedListViewPage = React.lazy(
1309
- () => Promise.resolve().then(() => require("./ListViewPage-CsrC9L_d.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1311
+ () => Promise.resolve().then(() => require("./ListViewPage-BsLiH2-2.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1310
1312
  );
1311
1313
  const ProtectedListConfiguration = React.lazy(
1312
- () => Promise.resolve().then(() => require("./ListConfigurationPage-DiT463qx.js")).then((mod) => ({
1314
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-CUQxfpjT.js")).then((mod) => ({
1313
1315
  default: mod.ProtectedListConfiguration
1314
1316
  }))
1315
1317
  );
1316
1318
  const ProtectedEditConfigurationPage = React.lazy(
1317
- () => Promise.resolve().then(() => require("./EditConfigurationPage-DOmfCEMo.js")).then((mod) => ({
1319
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-Xp7lun0f.js")).then((mod) => ({
1318
1320
  default: mod.ProtectedEditConfigurationPage
1319
1321
  }))
1320
1322
  );
1321
1323
  const ProtectedComponentConfigurationPage = React.lazy(
1322
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-BvHtG7uH.js")).then((mod) => ({
1324
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-5ukroXAh.js")).then((mod) => ({
1323
1325
  default: mod.ProtectedComponentConfigurationPage
1324
1326
  }))
1325
1327
  );
1326
1328
  const NoPermissions = React.lazy(
1327
- () => Promise.resolve().then(() => require("./NoPermissionsPage-CdHNJtEf.js")).then((mod) => ({ default: mod.NoPermissions }))
1329
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-_lUqjGW3.js")).then((mod) => ({ default: mod.NoPermissions }))
1328
1330
  );
1329
1331
  const NoContentType = React.lazy(
1330
- () => Promise.resolve().then(() => require("./NoContentTypePage-Bsvng4II.js")).then((mod) => ({ default: mod.NoContentType }))
1332
+ () => Promise.resolve().then(() => require("./NoContentTypePage-BZ-PnGAf.js")).then((mod) => ({ default: mod.NoContentType }))
1331
1333
  );
1332
1334
  const CollectionTypePages = () => {
1333
1335
  const { collectionType } = reactRouterDom.useParams();
@@ -1454,7 +1456,7 @@ const DocumentActionButton = (action) => {
1454
1456
  DocumentActionConfirmDialog,
1455
1457
  {
1456
1458
  ...action.dialog,
1457
- variant: action.variant,
1459
+ variant: action.dialog?.variant ?? action.variant,
1458
1460
  isOpen: dialogId === action.id,
1459
1461
  onClose: handleClose
1460
1462
  }
@@ -1660,8 +1662,8 @@ const DocumentActionModal = ({
1660
1662
  };
1661
1663
  return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
1662
1664
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
1663
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content }),
1664
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Footer, { children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer })
1665
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
1666
+ typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1665
1667
  ] }) });
1666
1668
  };
1667
1669
  const PublishAction$1 = ({
@@ -1683,6 +1685,12 @@ const PublishAction$1 = ({
1683
1685
  ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1684
1686
  );
1685
1687
  const { publish } = useDocumentActions();
1688
+ const [
1689
+ countDraftRelations,
1690
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
1691
+ ] = useLazyGetDraftRelationCountQuery();
1692
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
1693
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
1686
1694
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1687
1695
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1688
1696
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1691,10 +1699,101 @@ const PublishAction$1 = ({
1691
1699
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1692
1700
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1693
1701
  const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
1702
+ React__namespace.useEffect(() => {
1703
+ if (isErrorDraftRelations) {
1704
+ toggleNotification({
1705
+ type: "danger",
1706
+ message: formatMessage({
1707
+ id: getTranslation("error.records.fetch-draft-relatons"),
1708
+ defaultMessage: "An error occurred while fetching draft relations on this document."
1709
+ })
1710
+ });
1711
+ }
1712
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
1713
+ React__namespace.useEffect(() => {
1714
+ const localDraftRelations = /* @__PURE__ */ new Set();
1715
+ const extractDraftRelations = (data) => {
1716
+ const relations = data.connect || [];
1717
+ relations.forEach((relation) => {
1718
+ if (relation.status === "draft") {
1719
+ localDraftRelations.add(relation.id);
1720
+ }
1721
+ });
1722
+ };
1723
+ const traverseAndExtract = (data) => {
1724
+ Object.entries(data).forEach(([key, value]) => {
1725
+ if (key === "connect" && Array.isArray(value)) {
1726
+ extractDraftRelations({ connect: value });
1727
+ } else if (typeof value === "object" && value !== null) {
1728
+ traverseAndExtract(value);
1729
+ }
1730
+ });
1731
+ };
1732
+ if (!documentId || modified) {
1733
+ traverseAndExtract(formValues);
1734
+ setLocalCountOfDraftRelations(localDraftRelations.size);
1735
+ }
1736
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
1737
+ React__namespace.useEffect(() => {
1738
+ if (documentId) {
1739
+ const fetchDraftRelationsCount = async () => {
1740
+ const { data, error } = await countDraftRelations({
1741
+ collectionType,
1742
+ model,
1743
+ documentId,
1744
+ params
1745
+ });
1746
+ if (error) {
1747
+ throw error;
1748
+ }
1749
+ if (data) {
1750
+ setServerCountOfDraftRelations(data.data);
1751
+ }
1752
+ };
1753
+ fetchDraftRelationsCount();
1754
+ }
1755
+ }, [documentId, countDraftRelations, collectionType, model, params]);
1694
1756
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1695
1757
  if (!schema?.options?.draftAndPublish) {
1696
1758
  return null;
1697
1759
  }
1760
+ const performPublish = async () => {
1761
+ setSubmitting(true);
1762
+ try {
1763
+ const { errors } = await validate();
1764
+ if (errors) {
1765
+ toggleNotification({
1766
+ type: "danger",
1767
+ message: formatMessage({
1768
+ id: "content-manager.validation.error",
1769
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1770
+ })
1771
+ });
1772
+ return;
1773
+ }
1774
+ const res = await publish(
1775
+ {
1776
+ collectionType,
1777
+ model,
1778
+ documentId,
1779
+ params
1780
+ },
1781
+ formValues
1782
+ );
1783
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
1784
+ navigate({
1785
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1786
+ search: rawQuery
1787
+ });
1788
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1789
+ setErrors(formatValidationErrors(res.error));
1790
+ }
1791
+ } finally {
1792
+ setSubmitting(false);
1793
+ }
1794
+ };
1795
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1796
+ const hasDraftRelations = totalDraftRelations > 0;
1698
1797
  return {
1699
1798
  /**
1700
1799
  * Disabled when:
@@ -1707,46 +1806,38 @@ const PublishAction$1 = ({
1707
1806
  * - the user doesn't have the permission to create a new document
1708
1807
  * - the user doesn't have the permission to update the document
1709
1808
  */
1710
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1809
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1711
1810
  label: formatMessage({
1712
1811
  id: "app.utils.publish",
1713
1812
  defaultMessage: "Publish"
1714
1813
  }),
1715
1814
  onClick: async () => {
1716
- setSubmitting(true);
1717
- try {
1718
- const { errors } = await validate();
1719
- if (errors) {
1720
- toggleNotification({
1721
- type: "danger",
1722
- message: formatMessage({
1723
- id: "content-manager.validation.error",
1724
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1725
- })
1726
- });
1727
- return;
1728
- }
1729
- const res = await publish(
1730
- {
1731
- collectionType,
1732
- model,
1733
- documentId,
1734
- params
1735
- },
1736
- formValues
1737
- );
1738
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1739
- navigate({
1740
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1741
- search: rawQuery
1742
- });
1743
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1744
- setErrors(formatValidationErrors(res.error));
1815
+ if (hasDraftRelations) {
1816
+ return;
1817
+ }
1818
+ await performPublish();
1819
+ },
1820
+ dialog: hasDraftRelations ? {
1821
+ type: "dialog",
1822
+ variant: "danger",
1823
+ footer: null,
1824
+ title: formatMessage({
1825
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
1826
+ defaultMessage: "Confirmation"
1827
+ }),
1828
+ content: formatMessage(
1829
+ {
1830
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
1831
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
1832
+ },
1833
+ {
1834
+ count: totalDraftRelations
1745
1835
  }
1746
- } finally {
1747
- setSubmitting(false);
1836
+ ),
1837
+ onConfirm: async () => {
1838
+ await performPublish();
1748
1839
  }
1749
- }
1840
+ } : void 0
1750
1841
  };
1751
1842
  };
1752
1843
  PublishAction$1.type = "publish";
@@ -1814,10 +1905,13 @@ const UpdateAction = ({
1814
1905
  document
1815
1906
  );
1816
1907
  if ("data" in res) {
1817
- navigate({
1818
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1819
- search: rawQuery
1820
- });
1908
+ navigate(
1909
+ {
1910
+ pathname: `../${res.data.documentId}`,
1911
+ search: rawQuery
1912
+ },
1913
+ { relative: "path" }
1914
+ );
1821
1915
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1822
1916
  setErrors(formatValidationErrors(res.error));
1823
1917
  }
@@ -1847,10 +1941,10 @@ const UpdateAction = ({
1847
1941
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1848
1942
  navigate(
1849
1943
  {
1850
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1944
+ pathname: `../${res.data.documentId}`,
1851
1945
  search: rawQuery
1852
1946
  },
1853
- { replace: true }
1947
+ { replace: true, relative: "path" }
1854
1948
  );
1855
1949
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1856
1950
  setErrors(formatValidationErrors(res.error));
@@ -2097,23 +2191,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2097
2191
  id: "content-manager.containers.edit.title.new",
2098
2192
  defaultMessage: "Create an entry"
2099
2193
  }) : documentTitle;
2100
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2194
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2101
2195
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
2102
- /* @__PURE__ */ jsxRuntime.jsxs(
2103
- designSystem.Flex,
2104
- {
2105
- width: "100%",
2106
- justifyContent: "space-between",
2107
- paddingTop: 1,
2108
- gap: "80px",
2109
- alignItems: "flex-start",
2110
- children: [
2111
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2112
- /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2113
- ]
2114
- }
2115
- ),
2116
- status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2196
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2197
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2198
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2199
+ ] }),
2200
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2117
2201
  ] });
2118
2202
  };
2119
2203
  const HeaderToolbar = () => {
@@ -2804,7 +2888,7 @@ const ConfirmBulkActionDialog = ({
2804
2888
  endAction
2805
2889
  }) => {
2806
2890
  const { formatMessage } = reactIntl.useIntl();
2807
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2891
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2808
2892
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2809
2893
  id: "app.components.ConfirmDialog.title",
2810
2894
  defaultMessage: "Confirmation"
@@ -3595,8 +3679,7 @@ class ContentManagerPlugin {
3595
3679
  documentActions = [
3596
3680
  ...DEFAULT_ACTIONS,
3597
3681
  ...DEFAULT_TABLE_ROW_ACTIONS,
3598
- ...DEFAULT_HEADER_ACTIONS,
3599
- HistoryAction
3682
+ ...DEFAULT_HEADER_ACTIONS
3600
3683
  ];
3601
3684
  editViewSidePanels = [ActionsPanel];
3602
3685
  headerActions = [];
@@ -3685,6 +3768,52 @@ const getPrintableType = (value) => {
3685
3768
  }
3686
3769
  return nativeType;
3687
3770
  };
3771
+ const HistoryAction = ({ model, document }) => {
3772
+ const { formatMessage } = reactIntl.useIntl();
3773
+ const [{ query }] = strapiAdmin.useQueryParams();
3774
+ const navigate = reactRouterDom.useNavigate();
3775
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3776
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3777
+ return null;
3778
+ }
3779
+ return {
3780
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3781
+ label: formatMessage({
3782
+ id: "content-manager.history.document-action",
3783
+ defaultMessage: "Content History"
3784
+ }),
3785
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3786
+ disabled: (
3787
+ /**
3788
+ * The user is creating a new document.
3789
+ * It hasn't been saved yet, so there's no history to go to
3790
+ */
3791
+ !document || /**
3792
+ * The document has been created but the current dimension has never been saved.
3793
+ * For example, the user is creating a new locale in an existing document,
3794
+ * so there's no history for the document in that locale
3795
+ */
3796
+ !document.id || /**
3797
+ * History is only available for content types created by the user.
3798
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3799
+ * which start with `admin::` or `plugin::`
3800
+ */
3801
+ !model.startsWith("api::")
3802
+ ),
3803
+ position: "header"
3804
+ };
3805
+ };
3806
+ HistoryAction.type = "history";
3807
+ const historyAdmin = {
3808
+ bootstrap(app) {
3809
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3810
+ addDocumentAction((actions2) => {
3811
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3812
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3813
+ return actions2;
3814
+ });
3815
+ }
3816
+ };
3688
3817
  const initialState = {
3689
3818
  collectionTypeLinks: [],
3690
3819
  components: [],
@@ -3740,7 +3869,7 @@ const index = {
3740
3869
  app.router.addRoute({
3741
3870
  path: "content-manager/*",
3742
3871
  lazy: async () => {
3743
- const { Layout } = await Promise.resolve().then(() => require("./layout-Ciz224q5.js"));
3872
+ const { Layout } = await Promise.resolve().then(() => require("./layout-Ci7qHlFb.js"));
3744
3873
  return {
3745
3874
  Component: Layout
3746
3875
  };
@@ -3749,10 +3878,15 @@ const index = {
3749
3878
  });
3750
3879
  app.registerPlugin(cm.config);
3751
3880
  },
3881
+ bootstrap(app) {
3882
+ if (typeof historyAdmin.bootstrap === "function") {
3883
+ historyAdmin.bootstrap(app);
3884
+ }
3885
+ },
3752
3886
  async registerTrads({ locales }) {
3753
3887
  const importedTrads = await Promise.all(
3754
3888
  locales.map((locale) => {
3755
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-fbKQxLGn.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
3889
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-uOUIxfcQ.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
3756
3890
  return {
3757
3891
  data: prefixPluginTranslations(data, PLUGIN_ID),
3758
3892
  locale
@@ -3809,4 +3943,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3809
3943
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3810
3944
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3811
3945
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3812
- //# sourceMappingURL=index-BOZx6IMg.js.map
3946
+ //# sourceMappingURL=index-OerGjbAN.js.map