@strapi/content-manager 0.0.0-experimental.25e22c6cc9bc6b35392bb55d09f641a0a65e7403 → 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 (97) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-WRPUXGd6.js → ComponentConfigurationPage-5ukroXAh.js} +3 -3
  3. package/dist/_chunks/{ComponentConfigurationPage-WRPUXGd6.js.map → ComponentConfigurationPage-5ukroXAh.js.map} +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-gdUj_t-O.mjs → ComponentConfigurationPage-BAgyHiMm.mjs} +3 -3
  5. package/dist/_chunks/{ComponentConfigurationPage-gdUj_t-O.mjs.map → ComponentConfigurationPage-BAgyHiMm.mjs.map} +1 -1
  6. package/dist/_chunks/{EditConfigurationPage-BwuIPOJG.mjs → EditConfigurationPage-DmoXawIh.mjs} +3 -3
  7. package/dist/_chunks/{EditConfigurationPage-BwuIPOJG.mjs.map → EditConfigurationPage-DmoXawIh.mjs.map} +1 -1
  8. package/dist/_chunks/{EditConfigurationPage-C1vjMBgy.js → EditConfigurationPage-Xp7lun0f.js} +3 -3
  9. package/dist/_chunks/{EditConfigurationPage-C1vjMBgy.js.map → EditConfigurationPage-Xp7lun0f.js.map} +1 -1
  10. package/dist/_chunks/{EditViewPage-0MiFkXa8.mjs → EditViewPage-BLsjc5F-.mjs} +3 -3
  11. package/dist/_chunks/{EditViewPage-0MiFkXa8.mjs.map → EditViewPage-BLsjc5F-.mjs.map} +1 -1
  12. package/dist/_chunks/{EditViewPage-DbcGfyqK.js → EditViewPage-C-ukDOB7.js} +3 -3
  13. package/dist/_chunks/{EditViewPage-DbcGfyqK.js.map → EditViewPage-C-ukDOB7.js.map} +1 -1
  14. package/dist/_chunks/{Field-BG1xu38N.js → Field-Bfph5SOd.js} +348 -56
  15. package/dist/_chunks/Field-Bfph5SOd.js.map +1 -0
  16. package/dist/_chunks/{Field-BDMSCcy5.mjs → Field-Cs7duwWd.mjs} +349 -57
  17. package/dist/_chunks/Field-Cs7duwWd.mjs.map +1 -0
  18. package/dist/_chunks/{Form-9BnFyUjy.js → Form-CPYqIWDG.js} +6 -3
  19. package/dist/_chunks/Form-CPYqIWDG.js.map +1 -0
  20. package/dist/_chunks/{Form-CPVWavB8.mjs → Form-Dg_GS5TQ.mjs} +6 -3
  21. package/dist/_chunks/Form-Dg_GS5TQ.mjs.map +1 -0
  22. package/dist/_chunks/{History-BWWxLt2Z.js → History-DNQkXANT.js} +44 -19
  23. package/dist/_chunks/History-DNQkXANT.js.map +1 -0
  24. package/dist/_chunks/{History-BVpd8LP3.mjs → History-wrnHqf09.mjs} +44 -19
  25. package/dist/_chunks/History-wrnHqf09.mjs.map +1 -0
  26. package/dist/_chunks/{ListConfigurationPage-6swzjdAZ.js → ListConfigurationPage-CUQxfpjT.js} +8 -6
  27. package/dist/_chunks/ListConfigurationPage-CUQxfpjT.js.map +1 -0
  28. package/dist/_chunks/{ListConfigurationPage-DozVMKcR.mjs → ListConfigurationPage-DScmJVkW.mjs} +8 -6
  29. package/dist/_chunks/ListConfigurationPage-DScmJVkW.mjs.map +1 -0
  30. package/dist/_chunks/{ListViewPage-BlzfjS2Q.js → ListViewPage-BsLiH2-2.js} +15 -6
  31. package/dist/_chunks/ListViewPage-BsLiH2-2.js.map +1 -0
  32. package/dist/_chunks/{ListViewPage-Ds0ulgfG.mjs → ListViewPage-C4IvrMgY.mjs} +15 -6
  33. package/dist/_chunks/ListViewPage-C4IvrMgY.mjs.map +1 -0
  34. package/dist/_chunks/{NoContentTypePage-D2nCCWEl.js → NoContentTypePage-BZ-PnGAf.js} +2 -2
  35. package/dist/_chunks/{NoContentTypePage-D2nCCWEl.js.map → NoContentTypePage-BZ-PnGAf.js.map} +1 -1
  36. package/dist/_chunks/{NoContentTypePage-BH11kaKt.mjs → NoContentTypePage-Djg8nPlj.mjs} +2 -2
  37. package/dist/_chunks/{NoContentTypePage-BH11kaKt.mjs.map → NoContentTypePage-Djg8nPlj.mjs.map} +1 -1
  38. package/dist/_chunks/{NoPermissionsPage-BT2Tn0D_.mjs → NoPermissionsPage-DSP7R-hv.mjs} +2 -2
  39. package/dist/_chunks/{NoPermissionsPage-BT2Tn0D_.mjs.map → NoPermissionsPage-DSP7R-hv.mjs.map} +1 -1
  40. package/dist/_chunks/{NoPermissionsPage-DN_JlsU2.js → NoPermissionsPage-_lUqjGW3.js} +2 -2
  41. package/dist/_chunks/{NoPermissionsPage-DN_JlsU2.js.map → NoPermissionsPage-_lUqjGW3.js.map} +1 -1
  42. package/dist/_chunks/{Relations-Dnag3fhV.mjs → Relations-BZr8tL0R.mjs} +3 -3
  43. package/dist/_chunks/Relations-BZr8tL0R.mjs.map +1 -0
  44. package/dist/_chunks/{Relations-CcgFTcWo.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-CWpLBSt0.js → index-OerGjbAN.js} +290 -122
  51. package/dist/_chunks/index-OerGjbAN.js.map +1 -0
  52. package/dist/_chunks/{index-JNNNKUHs.mjs → index-c_5DdJi-.mjs} +305 -137
  53. package/dist/_chunks/index-c_5DdJi-.mjs.map +1 -0
  54. package/dist/_chunks/{layout--iHdZzRk.js → layout-Ci7qHlFb.js} +7 -7
  55. package/dist/_chunks/layout-Ci7qHlFb.js.map +1 -0
  56. package/dist/_chunks/{layout-DC503LnF.mjs → layout-oPBiO7RY.mjs} +8 -8
  57. package/dist/_chunks/layout-oPBiO7RY.mjs.map +1 -0
  58. package/dist/_chunks/{relations-CTje5t-a.mjs → relations-BIdWFjdq.mjs} +2 -2
  59. package/dist/_chunks/{relations-CTje5t-a.mjs.map → relations-BIdWFjdq.mjs.map} +1 -1
  60. package/dist/_chunks/{relations-BbHizA5K.js → relations-COBpStiF.js} +2 -2
  61. package/dist/_chunks/{relations-BbHizA5K.js.map → relations-COBpStiF.js.map} +1 -1
  62. package/dist/admin/index.js +1 -1
  63. package/dist/admin/index.mjs +4 -4
  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/BlocksInput/utils/constants.d.ts +4 -0
  68. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  69. package/dist/server/index.js +41 -34
  70. package/dist/server/index.js.map +1 -1
  71. package/dist/server/index.mjs +41 -34
  72. package/dist/server/index.mjs.map +1 -1
  73. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  74. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  75. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  76. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  77. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  78. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  79. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  80. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  81. package/package.json +8 -8
  82. package/dist/_chunks/Field-BDMSCcy5.mjs.map +0 -1
  83. package/dist/_chunks/Field-BG1xu38N.js.map +0 -1
  84. package/dist/_chunks/Form-9BnFyUjy.js.map +0 -1
  85. package/dist/_chunks/Form-CPVWavB8.mjs.map +0 -1
  86. package/dist/_chunks/History-BVpd8LP3.mjs.map +0 -1
  87. package/dist/_chunks/History-BWWxLt2Z.js.map +0 -1
  88. package/dist/_chunks/ListConfigurationPage-6swzjdAZ.js.map +0 -1
  89. package/dist/_chunks/ListConfigurationPage-DozVMKcR.mjs.map +0 -1
  90. package/dist/_chunks/ListViewPage-BlzfjS2Q.js.map +0 -1
  91. package/dist/_chunks/ListViewPage-Ds0ulgfG.mjs.map +0 -1
  92. package/dist/_chunks/Relations-CcgFTcWo.js.map +0 -1
  93. package/dist/_chunks/Relations-Dnag3fhV.mjs.map +0 -1
  94. package/dist/_chunks/index-CWpLBSt0.js.map +0 -1
  95. package/dist/_chunks/index-JNNNKUHs.mjs.map +0 -1
  96. package/dist/_chunks/layout--iHdZzRk.js.map +0 -1
  97. package/dist/_chunks/layout-DC503LnF.mjs.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";
@@ -219,6 +183,7 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
219
183
  ]
220
184
  });
221
185
  const documentApi = contentManagerApi.injectEndpoints({
186
+ overrideExisting: true,
222
187
  endpoints: (builder) => ({
223
188
  autoCloneDocument: builder.mutation({
224
189
  query: ({ model, sourceId, query }) => ({
@@ -228,7 +193,12 @@ const documentApi = contentManagerApi.injectEndpoints({
228
193
  params: query
229
194
  }
230
195
  }),
231
- 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
+ }
232
202
  }),
233
203
  cloneDocument: builder.mutation({
234
204
  query: ({ model, sourceId, data, params }) => ({
@@ -418,6 +388,18 @@ const documentApi = contentManagerApi.injectEndpoints({
418
388
  },
419
389
  "Relations"
420
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
+ }
421
403
  }
422
404
  }),
423
405
  unpublishDocument: builder.mutation({
@@ -620,11 +602,11 @@ const createAttributeSchema = (attribute) => {
620
602
  }
621
603
  };
622
604
  const addRequiredValidation = (attribute) => (schema) => {
623
- if (attribute.required) {
624
- return schema.required({
625
- id: strapiAdmin.translatedErrors.required.id,
626
- defaultMessage: "This field is required."
627
- });
605
+ if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
606
+ return schema.min(1, strapiAdmin.translatedErrors.required);
607
+ }
608
+ if (attribute.required && attribute.type !== "relation") {
609
+ return schema.required(strapiAdmin.translatedErrors.required);
628
610
  }
629
611
  return schema?.nullable ? schema.nullable() : (
630
612
  // In some cases '.nullable' will not be available on the schema.
@@ -658,6 +640,28 @@ const addMaxLengthValidation = (attribute) => (schema) => {
658
640
  const addMinValidation = (attribute) => (schema) => {
659
641
  if ("min" in attribute) {
660
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
+ }
661
665
  if ("min" in schema && min) {
662
666
  return schema.min(min, {
663
667
  ...strapiAdmin.translatedErrors.min,
@@ -784,7 +788,10 @@ const useDocument = (args, opts) => {
784
788
  isLoading: isLoadingDocument,
785
789
  isFetching: isFetchingDocument,
786
790
  error
787
- } = useGetDocumentQuery(args, opts);
791
+ } = useGetDocumentQuery(args, {
792
+ ...opts,
793
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
794
+ });
788
795
  const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
789
796
  React__namespace.useEffect(() => {
790
797
  if (error) {
@@ -1205,7 +1212,6 @@ const useDocumentActions = () => {
1205
1212
  sourceId
1206
1213
  });
1207
1214
  if ("error" in res) {
1208
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1209
1215
  return { error: res.error };
1210
1216
  }
1211
1217
  toggleNotification({
@@ -1286,7 +1292,7 @@ const useDocumentActions = () => {
1286
1292
  };
1287
1293
  };
1288
1294
  const ProtectedHistoryPage = React.lazy(
1289
- () => Promise.resolve().then(() => require("./History-BWWxLt2Z.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1295
+ () => Promise.resolve().then(() => require("./History-DNQkXANT.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1290
1296
  );
1291
1297
  const routes$1 = [
1292
1298
  {
@@ -1299,31 +1305,31 @@ const routes$1 = [
1299
1305
  }
1300
1306
  ];
1301
1307
  const ProtectedEditViewPage = React.lazy(
1302
- () => Promise.resolve().then(() => require("./EditViewPage-DbcGfyqK.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1308
+ () => Promise.resolve().then(() => require("./EditViewPage-C-ukDOB7.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1303
1309
  );
1304
1310
  const ProtectedListViewPage = React.lazy(
1305
- () => Promise.resolve().then(() => require("./ListViewPage-BlzfjS2Q.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1311
+ () => Promise.resolve().then(() => require("./ListViewPage-BsLiH2-2.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1306
1312
  );
1307
1313
  const ProtectedListConfiguration = React.lazy(
1308
- () => Promise.resolve().then(() => require("./ListConfigurationPage-6swzjdAZ.js")).then((mod) => ({
1314
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-CUQxfpjT.js")).then((mod) => ({
1309
1315
  default: mod.ProtectedListConfiguration
1310
1316
  }))
1311
1317
  );
1312
1318
  const ProtectedEditConfigurationPage = React.lazy(
1313
- () => Promise.resolve().then(() => require("./EditConfigurationPage-C1vjMBgy.js")).then((mod) => ({
1319
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-Xp7lun0f.js")).then((mod) => ({
1314
1320
  default: mod.ProtectedEditConfigurationPage
1315
1321
  }))
1316
1322
  );
1317
1323
  const ProtectedComponentConfigurationPage = React.lazy(
1318
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-WRPUXGd6.js")).then((mod) => ({
1324
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-5ukroXAh.js")).then((mod) => ({
1319
1325
  default: mod.ProtectedComponentConfigurationPage
1320
1326
  }))
1321
1327
  );
1322
1328
  const NoPermissions = React.lazy(
1323
- () => Promise.resolve().then(() => require("./NoPermissionsPage-DN_JlsU2.js")).then((mod) => ({ default: mod.NoPermissions }))
1329
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-_lUqjGW3.js")).then((mod) => ({ default: mod.NoPermissions }))
1324
1330
  );
1325
1331
  const NoContentType = React.lazy(
1326
- () => Promise.resolve().then(() => require("./NoContentTypePage-D2nCCWEl.js")).then((mod) => ({ default: mod.NoContentType }))
1332
+ () => Promise.resolve().then(() => require("./NoContentTypePage-BZ-PnGAf.js")).then((mod) => ({ default: mod.NoContentType }))
1327
1333
  );
1328
1334
  const CollectionTypePages = () => {
1329
1335
  const { collectionType } = reactRouterDom.useParams();
@@ -1450,7 +1456,7 @@ const DocumentActionButton = (action) => {
1450
1456
  DocumentActionConfirmDialog,
1451
1457
  {
1452
1458
  ...action.dialog,
1453
- variant: action.variant,
1459
+ variant: action.dialog?.variant ?? action.variant,
1454
1460
  isOpen: dialogId === action.id,
1455
1461
  onClose: handleClose
1456
1462
  }
@@ -1530,7 +1536,7 @@ const DocumentActionsMenu = ({
1530
1536
  display: "block",
1531
1537
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1532
1538
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1533
- action.icon,
1539
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1534
1540
  action.label
1535
1541
  ] }),
1536
1542
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
@@ -1591,6 +1597,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1591
1597
  return "primary600";
1592
1598
  }
1593
1599
  };
1600
+ const convertActionVariantToIconColor = (variant = "secondary") => {
1601
+ switch (variant) {
1602
+ case "danger":
1603
+ return "danger600";
1604
+ case "secondary":
1605
+ return "neutral500";
1606
+ case "success":
1607
+ return "success600";
1608
+ default:
1609
+ return "primary600";
1610
+ }
1611
+ };
1594
1612
  const DocumentActionConfirmDialog = ({
1595
1613
  onClose,
1596
1614
  onCancel,
@@ -1667,6 +1685,12 @@ const PublishAction$1 = ({
1667
1685
  ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1668
1686
  );
1669
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);
1670
1694
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1671
1695
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1672
1696
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1675,10 +1699,101 @@ const PublishAction$1 = ({
1675
1699
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1676
1700
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1677
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]);
1678
1756
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1679
1757
  if (!schema?.options?.draftAndPublish) {
1680
1758
  return null;
1681
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;
1682
1797
  return {
1683
1798
  /**
1684
1799
  * Disabled when:
@@ -1691,46 +1806,38 @@ const PublishAction$1 = ({
1691
1806
  * - the user doesn't have the permission to create a new document
1692
1807
  * - the user doesn't have the permission to update the document
1693
1808
  */
1694
- 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),
1695
1810
  label: formatMessage({
1696
1811
  id: "app.utils.publish",
1697
1812
  defaultMessage: "Publish"
1698
1813
  }),
1699
1814
  onClick: async () => {
1700
- setSubmitting(true);
1701
- try {
1702
- const { errors } = await validate();
1703
- if (errors) {
1704
- toggleNotification({
1705
- type: "danger",
1706
- message: formatMessage({
1707
- id: "content-manager.validation.error",
1708
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1709
- })
1710
- });
1711
- return;
1712
- }
1713
- const res = await publish(
1714
- {
1715
- collectionType,
1716
- model,
1717
- documentId,
1718
- params
1719
- },
1720
- formValues
1721
- );
1722
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1723
- navigate({
1724
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1725
- search: rawQuery
1726
- });
1727
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1728
- 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
1729
1835
  }
1730
- } finally {
1731
- setSubmitting(false);
1836
+ ),
1837
+ onConfirm: async () => {
1838
+ await performPublish();
1732
1839
  }
1733
- }
1840
+ } : void 0
1734
1841
  };
1735
1842
  };
1736
1843
  PublishAction$1.type = "publish";
@@ -1798,10 +1905,13 @@ const UpdateAction = ({
1798
1905
  document
1799
1906
  );
1800
1907
  if ("data" in res) {
1801
- navigate({
1802
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1803
- search: rawQuery
1804
- });
1908
+ navigate(
1909
+ {
1910
+ pathname: `../${res.data.documentId}`,
1911
+ search: rawQuery
1912
+ },
1913
+ { relative: "path" }
1914
+ );
1805
1915
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1806
1916
  setErrors(formatValidationErrors(res.error));
1807
1917
  }
@@ -1829,10 +1939,13 @@ const UpdateAction = ({
1829
1939
  document
1830
1940
  );
1831
1941
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1832
- navigate({
1833
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1834
- search: rawQuery
1835
- });
1942
+ navigate(
1943
+ {
1944
+ pathname: `../${res.data.documentId}`,
1945
+ search: rawQuery
1946
+ },
1947
+ { replace: true, relative: "path" }
1948
+ );
1836
1949
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1837
1950
  setErrors(formatValidationErrors(res.error));
1838
1951
  }
@@ -2078,23 +2191,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2078
2191
  id: "content-manager.containers.edit.title.new",
2079
2192
  defaultMessage: "Create an entry"
2080
2193
  }) : documentTitle;
2081
- 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: [
2082
2195
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
2083
- /* @__PURE__ */ jsxRuntime.jsxs(
2084
- designSystem.Flex,
2085
- {
2086
- width: "100%",
2087
- justifyContent: "space-between",
2088
- paddingTop: 1,
2089
- gap: "80px",
2090
- alignItems: "flex-start",
2091
- children: [
2092
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2093
- /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2094
- ]
2095
- }
2096
- ),
2097
- 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
2098
2201
  ] });
2099
2202
  };
2100
2203
  const HeaderToolbar = () => {
@@ -2785,7 +2888,7 @@ const ConfirmBulkActionDialog = ({
2785
2888
  endAction
2786
2889
  }) => {
2787
2890
  const { formatMessage } = reactIntl.useIntl();
2788
- 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: [
2789
2892
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2790
2893
  id: "app.components.ConfirmDialog.title",
2791
2894
  defaultMessage: "Confirmation"
@@ -2906,7 +3009,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2906
3009
  )
2907
3010
  );
2908
3011
  } else {
2909
- messages.push(...formatErrorMessages(value, currentKey, formatMessage));
3012
+ messages.push(
3013
+ ...formatErrorMessages(
3014
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3015
+ value,
3016
+ currentKey,
3017
+ formatMessage
3018
+ )
3019
+ );
2910
3020
  }
2911
3021
  } else {
2912
3022
  messages.push(
@@ -3569,8 +3679,7 @@ class ContentManagerPlugin {
3569
3679
  documentActions = [
3570
3680
  ...DEFAULT_ACTIONS,
3571
3681
  ...DEFAULT_TABLE_ROW_ACTIONS,
3572
- ...DEFAULT_HEADER_ACTIONS,
3573
- HistoryAction
3682
+ ...DEFAULT_HEADER_ACTIONS
3574
3683
  ];
3575
3684
  editViewSidePanels = [ActionsPanel];
3576
3685
  headerActions = [];
@@ -3659,6 +3768,52 @@ const getPrintableType = (value) => {
3659
3768
  }
3660
3769
  return nativeType;
3661
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
+ };
3662
3817
  const initialState = {
3663
3818
  collectionTypeLinks: [],
3664
3819
  components: [],
@@ -3709,15 +3864,29 @@ const index = {
3709
3864
  defaultMessage: "Content Manager"
3710
3865
  },
3711
3866
  permissions: [],
3712
- Component: () => Promise.resolve().then(() => require("./layout--iHdZzRk.js")).then((mod) => ({ default: mod.Layout })),
3713
3867
  position: 1
3714
3868
  });
3869
+ app.router.addRoute({
3870
+ path: "content-manager/*",
3871
+ lazy: async () => {
3872
+ const { Layout } = await Promise.resolve().then(() => require("./layout-Ci7qHlFb.js"));
3873
+ return {
3874
+ Component: Layout
3875
+ };
3876
+ },
3877
+ children: routes
3878
+ });
3715
3879
  app.registerPlugin(cm.config);
3716
3880
  },
3881
+ bootstrap(app) {
3882
+ if (typeof historyAdmin.bootstrap === "function") {
3883
+ historyAdmin.bootstrap(app);
3884
+ }
3885
+ },
3717
3886
  async registerTrads({ locales }) {
3718
3887
  const importedTrads = await Promise.all(
3719
3888
  locales.map((locale) => {
3720
- 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 }) => {
3721
3890
  return {
3722
3891
  data: prefixPluginTranslations(data, PLUGIN_ID),
3723
3892
  locale
@@ -3761,7 +3930,6 @@ exports.getDisplayName = getDisplayName;
3761
3930
  exports.getMainField = getMainField;
3762
3931
  exports.getTranslation = getTranslation;
3763
3932
  exports.index = index;
3764
- exports.routes = routes;
3765
3933
  exports.setInitialData = setInitialData;
3766
3934
  exports.useContentTypeSchema = useContentTypeSchema;
3767
3935
  exports.useDoc = useDoc;
@@ -3775,4 +3943,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3775
3943
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3776
3944
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3777
3945
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3778
- //# sourceMappingURL=index-CWpLBSt0.js.map
3946
+ //# sourceMappingURL=index-OerGjbAN.js.map