@strapi/content-manager 0.0.0-experimental.d53e940834bf72ddc725f1d2fd36dac9abec30cb → 0.0.0-experimental.d834c9e658d1fb037e6da1105150593521c667cc

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 (115) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-D_M8iBw5.js} +3 -3
  3. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-D_M8iBw5.js.map} +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs → ComponentConfigurationPage-qemkOlnj.mjs} +3 -3
  5. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-qemkOlnj.mjs.map} +1 -1
  6. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-BePwPuHy.js} +3 -3
  7. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-BePwPuHy.js.map} +1 -1
  8. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs → EditConfigurationPage-CjUrEewK.mjs} +3 -3
  9. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-CjUrEewK.mjs.map} +1 -1
  10. package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-B-RJeiJD.js} +19 -8
  11. package/dist/_chunks/EditViewPage-B-RJeiJD.js.map +1 -0
  12. package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-De8GyU8P.mjs} +19 -8
  13. package/dist/_chunks/EditViewPage-De8GyU8P.mjs.map +1 -0
  14. package/dist/_chunks/{Field-Boxf9Ajp.js → Field-dq8Tg1M_.js} +175 -84
  15. package/dist/_chunks/Field-dq8Tg1M_.js.map +1 -0
  16. package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-pb2o8uBe.mjs} +177 -86
  17. package/dist/_chunks/Field-pb2o8uBe.mjs.map +1 -0
  18. package/dist/_chunks/{Form-y5g1SRsh.js → Form-DGIf4jQU.js} +22 -11
  19. package/dist/_chunks/Form-DGIf4jQU.js.map +1 -0
  20. package/dist/_chunks/{Form-DHrru2AV.mjs → Form-DJn0Dxha.mjs} +22 -11
  21. package/dist/_chunks/Form-DJn0Dxha.mjs.map +1 -0
  22. package/dist/_chunks/{History-Bru_KoeP.mjs → History-BowL3JKP.mjs} +44 -19
  23. package/dist/_chunks/History-BowL3JKP.mjs.map +1 -0
  24. package/dist/_chunks/{History-CqN6K7SX.js → History-Dh2NEHnR.js} +44 -19
  25. package/dist/_chunks/History-Dh2NEHnR.js.map +1 -0
  26. package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-BpVOB-hn.mjs} +20 -8
  27. package/dist/_chunks/ListConfigurationPage-BpVOB-hn.mjs.map +1 -0
  28. package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-BxYCWz9e.js} +20 -8
  29. package/dist/_chunks/ListConfigurationPage-BxYCWz9e.js.map +1 -0
  30. package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-4XsciqHZ.js} +21 -7
  31. package/dist/_chunks/ListViewPage-4XsciqHZ.js.map +1 -0
  32. package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-CXFUjZQC.mjs} +22 -8
  33. package/dist/_chunks/ListViewPage-CXFUjZQC.mjs.map +1 -0
  34. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-C8OpoHeU.js} +2 -2
  35. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-C8OpoHeU.js.map} +1 -1
  36. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-DuhOTp3x.mjs} +2 -2
  37. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-DuhOTp3x.mjs.map} +1 -1
  38. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-DVz3mzDz.mjs} +2 -2
  39. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-DVz3mzDz.mjs.map} +1 -1
  40. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-y_r7DVA2.js} +2 -2
  41. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-y_r7DVA2.js.map} +1 -1
  42. package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-CVNLrn1Y.mjs} +4 -4
  43. package/dist/_chunks/Relations-CVNLrn1Y.mjs.map +1 -0
  44. package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-DPFCAa7b.js} +4 -4
  45. package/dist/_chunks/Relations-DPFCAa7b.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-DVPWZkbS.js → index-C3fJE-1-.js} +368 -168
  51. package/dist/_chunks/index-C3fJE-1-.js.map +1 -0
  52. package/dist/_chunks/{index-DJXJw9V5.mjs → index-DiMrfcfy.mjs} +387 -187
  53. package/dist/_chunks/index-DiMrfcfy.mjs.map +1 -0
  54. package/dist/_chunks/{layout-Dm6fbiQj.js → layout-C788OmNr.js} +22 -10
  55. package/dist/_chunks/layout-C788OmNr.js.map +1 -0
  56. package/dist/_chunks/{layout-Bau7ZfLV.mjs → layout-ls3gxfpH.mjs} +23 -11
  57. package/dist/_chunks/layout-ls3gxfpH.mjs.map +1 -0
  58. package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-CLcOmGO0.mjs} +2 -2
  59. package/dist/_chunks/{relations-BH_kBSJ0.mjs.map → relations-CLcOmGO0.mjs.map} +1 -1
  60. package/dist/_chunks/{relations-CKnpRgrN.js → relations-DYeotliT.js} +2 -2
  61. package/dist/_chunks/{relations-CKnpRgrN.js.map → relations-DYeotliT.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/history/services/historyVersion.d.ts +1 -1
  66. package/dist/admin/src/index.d.ts +1 -0
  67. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -0
  68. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  69. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  70. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  71. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +10 -22
  72. package/dist/admin/src/services/api.d.ts +1 -1
  73. package/dist/admin/src/services/components.d.ts +2 -2
  74. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  75. package/dist/admin/src/services/documents.d.ts +16 -16
  76. package/dist/admin/src/services/init.d.ts +1 -1
  77. package/dist/admin/src/services/relations.d.ts +2 -2
  78. package/dist/admin/src/services/uid.d.ts +3 -3
  79. package/dist/admin/src/utils/validation.d.ts +4 -1
  80. package/dist/server/index.js +165 -105
  81. package/dist/server/index.js.map +1 -1
  82. package/dist/server/index.mjs +166 -106
  83. package/dist/server/index.mjs.map +1 -1
  84. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  85. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  86. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  87. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  88. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  89. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  90. package/dist/server/src/history/services/utils.d.ts +1 -1
  91. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  92. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  93. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  94. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  95. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  96. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  97. package/package.json +8 -8
  98. package/dist/_chunks/EditViewPage-CPj61RMh.mjs.map +0 -1
  99. package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
  100. package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
  101. package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
  102. package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
  103. package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
  104. package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
  105. package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
  106. package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
  107. package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
  108. package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
  109. package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
  110. package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
  111. package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
  112. package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
  113. package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
  114. package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
  115. package/dist/_chunks/layout-Dm6fbiQj.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";
@@ -215,7 +179,8 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
215
179
  "Document",
216
180
  "InitialData",
217
181
  "HistoryVersion",
218
- "Relations"
182
+ "Relations",
183
+ "UidAvailability"
219
184
  ]
220
185
  });
221
186
  const documentApi = contentManagerApi.injectEndpoints({
@@ -229,7 +194,12 @@ const documentApi = contentManagerApi.injectEndpoints({
229
194
  params: query
230
195
  }
231
196
  }),
232
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
197
+ invalidatesTags: (_result, error, { model }) => {
198
+ if (error) {
199
+ return [];
200
+ }
201
+ return [{ type: "Document", id: `${model}_LIST` }];
202
+ }
233
203
  }),
234
204
  cloneDocument: builder.mutation({
235
205
  query: ({ model, sourceId, data, params }) => ({
@@ -240,7 +210,10 @@ const documentApi = contentManagerApi.injectEndpoints({
240
210
  params
241
211
  }
242
212
  }),
243
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
213
+ invalidatesTags: (_result, _error, { model }) => [
214
+ { type: "Document", id: `${model}_LIST` },
215
+ { type: "UidAvailability", id: model }
216
+ ]
244
217
  }),
245
218
  /**
246
219
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -257,7 +230,8 @@ const documentApi = contentManagerApi.injectEndpoints({
257
230
  }),
258
231
  invalidatesTags: (result, _error, { model }) => [
259
232
  { type: "Document", id: `${model}_LIST` },
260
- "Relations"
233
+ "Relations",
234
+ { type: "UidAvailability", id: model }
261
235
  ]
262
236
  }),
263
237
  deleteDocument: builder.mutation({
@@ -298,7 +272,8 @@ const documentApi = contentManagerApi.injectEndpoints({
298
272
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
299
273
  },
300
274
  { type: "Document", id: `${model}_LIST` },
301
- "Relations"
275
+ "Relations",
276
+ { type: "UidAvailability", id: model }
302
277
  ];
303
278
  }
304
279
  }),
@@ -316,6 +291,7 @@ const documentApi = contentManagerApi.injectEndpoints({
316
291
  }),
317
292
  providesTags: (result, _error, arg) => {
318
293
  return [
294
+ { type: "Document", id: `ALL_LIST` },
319
295
  { type: "Document", id: `${arg.model}_LIST` },
320
296
  ...result?.results.map(({ documentId }) => ({
321
297
  type: "Document",
@@ -354,6 +330,11 @@ const documentApi = contentManagerApi.injectEndpoints({
354
330
  {
355
331
  type: "Document",
356
332
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
333
+ },
334
+ // Make it easy to invalidate all individual documents queries for a model
335
+ {
336
+ type: "Document",
337
+ id: `${model}_ALL_ITEMS`
357
338
  }
358
339
  ];
359
340
  }
@@ -417,8 +398,21 @@ const documentApi = contentManagerApi.injectEndpoints({
417
398
  type: "Document",
418
399
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
419
400
  },
420
- "Relations"
401
+ "Relations",
402
+ { type: "UidAvailability", id: model }
421
403
  ];
404
+ },
405
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
406
+ const patchResult = dispatch(
407
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
408
+ Object.assign(draft.data, data);
409
+ })
410
+ );
411
+ try {
412
+ await queryFulfilled;
413
+ } catch {
414
+ patchResult.undo();
415
+ }
422
416
  }
423
417
  }),
424
418
  unpublishDocument: builder.mutation({
@@ -488,7 +482,7 @@ const buildValidParams = (query) => {
488
482
  const isBaseQueryError = (error) => {
489
483
  return error.name !== void 0;
490
484
  };
491
- const createYupSchema = (attributes = {}, components = {}) => {
485
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
492
486
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
493
487
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
494
488
  if (DOCUMENT_META_FIELDS.includes(name)) {
@@ -501,7 +495,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
501
495
  addMinValidation,
502
496
  addMaxValidation,
503
497
  addRegexValidation
504
- ].map((fn) => fn(attribute));
498
+ ].map((fn) => fn(attribute, options));
505
499
  const transformSchema = pipe__default.default(...validations);
506
500
  switch (attribute.type) {
507
501
  case "component": {
@@ -602,6 +596,14 @@ const createAttributeSchema = (attribute) => {
602
596
  if (!value || typeof value === "string" && value.length === 0) {
603
597
  return true;
604
598
  }
599
+ if (typeof value === "object") {
600
+ try {
601
+ JSON.stringify(value);
602
+ return true;
603
+ } catch (err) {
604
+ return false;
605
+ }
606
+ }
605
607
  try {
606
608
  JSON.parse(value);
607
609
  return true;
@@ -620,13 +622,7 @@ const createAttributeSchema = (attribute) => {
620
622
  return yup__namespace.mixed();
621
623
  }
622
624
  };
623
- const addRequiredValidation = (attribute) => (schema) => {
624
- if (attribute.required) {
625
- return schema.required({
626
- id: strapiAdmin.translatedErrors.required.id,
627
- defaultMessage: "This field is required."
628
- });
629
- }
625
+ const nullableSchema = (schema) => {
630
626
  return schema?.nullable ? schema.nullable() : (
631
627
  // In some cases '.nullable' will not be available on the schema.
632
628
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -634,7 +630,22 @@ const addRequiredValidation = (attribute) => (schema) => {
634
630
  schema
635
631
  );
636
632
  };
637
- const addMinLengthValidation = (attribute) => (schema) => {
633
+ const addRequiredValidation = (attribute, options) => (schema) => {
634
+ if (options.status === "draft") {
635
+ return nullableSchema(schema);
636
+ }
637
+ if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
638
+ return schema.min(1, strapiAdmin.translatedErrors.required);
639
+ }
640
+ if (attribute.required && attribute.type !== "relation") {
641
+ return schema.required(strapiAdmin.translatedErrors.required);
642
+ }
643
+ return nullableSchema(schema);
644
+ };
645
+ const addMinLengthValidation = (attribute, options) => (schema) => {
646
+ if (options.status === "draft") {
647
+ return schema;
648
+ }
638
649
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
639
650
  return schema.min(attribute.minLength, {
640
651
  ...strapiAdmin.translatedErrors.minLength,
@@ -656,9 +667,31 @@ const addMaxLengthValidation = (attribute) => (schema) => {
656
667
  }
657
668
  return schema;
658
669
  };
659
- const addMinValidation = (attribute) => (schema) => {
670
+ const addMinValidation = (attribute, options) => (schema) => {
660
671
  if ("min" in attribute) {
661
672
  const min = toInteger(attribute.min);
673
+ if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
674
+ if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
675
+ return schema.test(
676
+ "custom-min",
677
+ {
678
+ ...strapiAdmin.translatedErrors.min,
679
+ values: {
680
+ min: attribute.min
681
+ }
682
+ },
683
+ (value) => {
684
+ if (!value) {
685
+ return true;
686
+ }
687
+ if (Array.isArray(value) && value.length === 0) {
688
+ return true;
689
+ }
690
+ return value.length >= min;
691
+ }
692
+ );
693
+ }
694
+ }
662
695
  if ("min" in schema && min) {
663
696
  return schema.min(min, {
664
697
  ...strapiAdmin.translatedErrors.min,
@@ -785,7 +818,10 @@ const useDocument = (args, opts) => {
785
818
  isLoading: isLoadingDocument,
786
819
  isFetching: isFetchingDocument,
787
820
  error
788
- } = useGetDocumentQuery(args, opts);
821
+ } = useGetDocumentQuery(args, {
822
+ ...opts,
823
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
824
+ });
789
825
  const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
790
826
  React__namespace.useEffect(() => {
791
827
  if (error) {
@@ -871,6 +907,7 @@ const useDocumentActions = () => {
871
907
  const { formatMessage } = reactIntl.useIntl();
872
908
  const { trackUsage } = strapiAdmin.useTracking();
873
909
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
910
+ const navigate = reactRouterDom.useNavigate();
874
911
  const [deleteDocument] = useDeleteDocumentMutation();
875
912
  const _delete = React__namespace.useCallback(
876
913
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -1206,7 +1243,6 @@ const useDocumentActions = () => {
1206
1243
  sourceId
1207
1244
  });
1208
1245
  if ("error" in res) {
1209
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1210
1246
  return { error: res.error };
1211
1247
  }
1212
1248
  toggleNotification({
@@ -1225,7 +1261,7 @@ const useDocumentActions = () => {
1225
1261
  throw err;
1226
1262
  }
1227
1263
  },
1228
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1264
+ [autoCloneDocument, formatMessage, toggleNotification]
1229
1265
  );
1230
1266
  const [cloneDocument] = useCloneDocumentMutation();
1231
1267
  const clone = React__namespace.useCallback(
@@ -1251,6 +1287,7 @@ const useDocumentActions = () => {
1251
1287
  defaultMessage: "Cloned document"
1252
1288
  })
1253
1289
  });
1290
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1254
1291
  return res.data;
1255
1292
  } catch (err) {
1256
1293
  toggleNotification({
@@ -1261,7 +1298,7 @@ const useDocumentActions = () => {
1261
1298
  throw err;
1262
1299
  }
1263
1300
  },
1264
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1301
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1265
1302
  );
1266
1303
  const [getDoc] = useLazyGetDocumentQuery();
1267
1304
  const getDocument = React__namespace.useCallback(
@@ -1287,7 +1324,7 @@ const useDocumentActions = () => {
1287
1324
  };
1288
1325
  };
1289
1326
  const ProtectedHistoryPage = React.lazy(
1290
- () => Promise.resolve().then(() => require("./History-CqN6K7SX.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1327
+ () => Promise.resolve().then(() => require("./History-Dh2NEHnR.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1291
1328
  );
1292
1329
  const routes$1 = [
1293
1330
  {
@@ -1300,31 +1337,31 @@ const routes$1 = [
1300
1337
  }
1301
1338
  ];
1302
1339
  const ProtectedEditViewPage = React.lazy(
1303
- () => Promise.resolve().then(() => require("./EditViewPage-zT3fBr4Y.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1340
+ () => Promise.resolve().then(() => require("./EditViewPage-B-RJeiJD.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1304
1341
  );
1305
1342
  const ProtectedListViewPage = React.lazy(
1306
- () => Promise.resolve().then(() => require("./ListViewPage-pEw_zug9.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1343
+ () => Promise.resolve().then(() => require("./ListViewPage-4XsciqHZ.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1307
1344
  );
1308
1345
  const ProtectedListConfiguration = React.lazy(
1309
- () => Promise.resolve().then(() => require("./ListConfigurationPage-R_p-SbHZ.js")).then((mod) => ({
1346
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-BxYCWz9e.js")).then((mod) => ({
1310
1347
  default: mod.ProtectedListConfiguration
1311
1348
  }))
1312
1349
  );
1313
1350
  const ProtectedEditConfigurationPage = React.lazy(
1314
- () => Promise.resolve().then(() => require("./EditConfigurationPage-DjFJw56M.js")).then((mod) => ({
1351
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-BePwPuHy.js")).then((mod) => ({
1315
1352
  default: mod.ProtectedEditConfigurationPage
1316
1353
  }))
1317
1354
  );
1318
1355
  const ProtectedComponentConfigurationPage = React.lazy(
1319
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-C-49MccQ.js")).then((mod) => ({
1356
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-D_M8iBw5.js")).then((mod) => ({
1320
1357
  default: mod.ProtectedComponentConfigurationPage
1321
1358
  }))
1322
1359
  );
1323
1360
  const NoPermissions = React.lazy(
1324
- () => Promise.resolve().then(() => require("./NoPermissionsPage-BtPrImPP.js")).then((mod) => ({ default: mod.NoPermissions }))
1361
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-y_r7DVA2.js")).then((mod) => ({ default: mod.NoPermissions }))
1325
1362
  );
1326
1363
  const NoContentType = React.lazy(
1327
- () => Promise.resolve().then(() => require("./NoContentTypePage-C5dcQojD.js")).then((mod) => ({ default: mod.NoContentType }))
1364
+ () => Promise.resolve().then(() => require("./NoContentTypePage-C8OpoHeU.js")).then((mod) => ({ default: mod.NoContentType }))
1328
1365
  );
1329
1366
  const CollectionTypePages = () => {
1330
1367
  const { collectionType } = reactRouterDom.useParams();
@@ -1438,12 +1475,14 @@ const DocumentActionButton = (action) => {
1438
1475
  /* @__PURE__ */ jsxRuntime.jsx(
1439
1476
  designSystem.Button,
1440
1477
  {
1441
- flex: 1,
1478
+ flex: "auto",
1442
1479
  startIcon: action.icon,
1443
1480
  disabled: action.disabled,
1444
1481
  onClick: handleClick(action),
1445
1482
  justifyContent: "center",
1446
1483
  variant: action.variant || "default",
1484
+ paddingTop: "7px",
1485
+ paddingBottom: "7px",
1447
1486
  children: action.label
1448
1487
  }
1449
1488
  ),
@@ -1451,7 +1490,7 @@ const DocumentActionButton = (action) => {
1451
1490
  DocumentActionConfirmDialog,
1452
1491
  {
1453
1492
  ...action.dialog,
1454
- variant: action.variant,
1493
+ variant: action.dialog?.variant ?? action.variant,
1455
1494
  isOpen: dialogId === action.id,
1456
1495
  onClose: handleClose
1457
1496
  }
@@ -1503,14 +1542,14 @@ const DocumentActionsMenu = ({
1503
1542
  };
1504
1543
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
1505
1544
  /* @__PURE__ */ jsxRuntime.jsxs(
1506
- designSystem.Menu.Trigger,
1545
+ StyledMoreButton,
1507
1546
  {
1508
1547
  disabled: isDisabled,
1509
1548
  size: "S",
1510
1549
  endIcon: null,
1511
- paddingTop: "7px",
1512
- paddingLeft: "9px",
1513
- paddingRight: "9px",
1550
+ paddingTop: "4px",
1551
+ paddingLeft: "7px",
1552
+ paddingRight: "7px",
1514
1553
  variant,
1515
1554
  children: [
1516
1555
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
@@ -1530,10 +1569,25 @@ const DocumentActionsMenu = ({
1530
1569
  onSelect: handleClick(action),
1531
1570
  display: "block",
1532
1571
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1533
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1534
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1535
- action.label
1536
- ] }),
1572
+ /* @__PURE__ */ jsxRuntime.jsxs(
1573
+ designSystem.Flex,
1574
+ {
1575
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1576
+ gap: 2,
1577
+ tag: "span",
1578
+ children: [
1579
+ /* @__PURE__ */ jsxRuntime.jsx(
1580
+ designSystem.Flex,
1581
+ {
1582
+ tag: "span",
1583
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1584
+ children: action.icon
1585
+ }
1586
+ ),
1587
+ action.label
1588
+ ]
1589
+ }
1590
+ ),
1537
1591
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
1538
1592
  designSystem.Flex,
1539
1593
  {
@@ -1604,6 +1658,11 @@ const convertActionVariantToIconColor = (variant = "secondary") => {
1604
1658
  return "primary600";
1605
1659
  }
1606
1660
  };
1661
+ const StyledMoreButton = styledComponents.styled(designSystem.Menu.Trigger)`
1662
+ & > span {
1663
+ display: flex;
1664
+ }
1665
+ `;
1607
1666
  const DocumentActionConfirmDialog = ({
1608
1667
  onClose,
1609
1668
  onCancel,
@@ -1673,13 +1732,17 @@ const PublishAction$1 = ({
1673
1732
  const navigate = reactRouterDom.useNavigate();
1674
1733
  const { toggleNotification } = strapiAdmin.useNotification();
1675
1734
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
1735
+ const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
1676
1736
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
1677
1737
  const { formatMessage } = reactIntl.useIntl();
1678
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1679
- "PublishAction",
1680
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1681
- );
1738
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1682
1739
  const { publish } = useDocumentActions();
1740
+ const [
1741
+ countDraftRelations,
1742
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
1743
+ ] = useLazyGetDraftRelationCountQuery();
1744
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
1745
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
1683
1746
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1684
1747
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1685
1748
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1688,10 +1751,101 @@ const PublishAction$1 = ({
1688
1751
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1689
1752
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1690
1753
  const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
1754
+ React__namespace.useEffect(() => {
1755
+ if (isErrorDraftRelations) {
1756
+ toggleNotification({
1757
+ type: "danger",
1758
+ message: formatMessage({
1759
+ id: getTranslation("error.records.fetch-draft-relatons"),
1760
+ defaultMessage: "An error occurred while fetching draft relations on this document."
1761
+ })
1762
+ });
1763
+ }
1764
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
1765
+ React__namespace.useEffect(() => {
1766
+ const localDraftRelations = /* @__PURE__ */ new Set();
1767
+ const extractDraftRelations = (data) => {
1768
+ const relations = data.connect || [];
1769
+ relations.forEach((relation) => {
1770
+ if (relation.status === "draft") {
1771
+ localDraftRelations.add(relation.id);
1772
+ }
1773
+ });
1774
+ };
1775
+ const traverseAndExtract = (data) => {
1776
+ Object.entries(data).forEach(([key, value]) => {
1777
+ if (key === "connect" && Array.isArray(value)) {
1778
+ extractDraftRelations({ connect: value });
1779
+ } else if (typeof value === "object" && value !== null) {
1780
+ traverseAndExtract(value);
1781
+ }
1782
+ });
1783
+ };
1784
+ if (!documentId || modified) {
1785
+ traverseAndExtract(formValues);
1786
+ setLocalCountOfDraftRelations(localDraftRelations.size);
1787
+ }
1788
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
1789
+ React__namespace.useEffect(() => {
1790
+ if (documentId && !isListView) {
1791
+ const fetchDraftRelationsCount = async () => {
1792
+ const { data, error } = await countDraftRelations({
1793
+ collectionType,
1794
+ model,
1795
+ documentId,
1796
+ params
1797
+ });
1798
+ if (error) {
1799
+ throw error;
1800
+ }
1801
+ if (data) {
1802
+ setServerCountOfDraftRelations(data.data);
1803
+ }
1804
+ };
1805
+ fetchDraftRelationsCount();
1806
+ }
1807
+ }, [isListView, documentId, countDraftRelations, collectionType, model, params]);
1691
1808
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1692
1809
  if (!schema?.options?.draftAndPublish) {
1693
1810
  return null;
1694
1811
  }
1812
+ const performPublish = async () => {
1813
+ setSubmitting(true);
1814
+ try {
1815
+ const { errors } = await validate();
1816
+ if (errors) {
1817
+ toggleNotification({
1818
+ type: "danger",
1819
+ message: formatMessage({
1820
+ id: "content-manager.validation.error",
1821
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1822
+ })
1823
+ });
1824
+ return;
1825
+ }
1826
+ const res = await publish(
1827
+ {
1828
+ collectionType,
1829
+ model,
1830
+ documentId,
1831
+ params
1832
+ },
1833
+ formValues
1834
+ );
1835
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
1836
+ navigate({
1837
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1838
+ search: rawQuery
1839
+ });
1840
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1841
+ setErrors(formatValidationErrors(res.error));
1842
+ }
1843
+ } finally {
1844
+ setSubmitting(false);
1845
+ }
1846
+ };
1847
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1848
+ const hasDraftRelations = totalDraftRelations > 0;
1695
1849
  return {
1696
1850
  /**
1697
1851
  * Disabled when:
@@ -1701,49 +1855,39 @@ const PublishAction$1 = ({
1701
1855
  * - the document is already published & not modified
1702
1856
  * - the document is being created & not modified
1703
1857
  * - the user doesn't have the permission to publish
1704
- * - the user doesn't have the permission to create a new document
1705
- * - the user doesn't have the permission to update the document
1706
1858
  */
1707
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1859
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1708
1860
  label: formatMessage({
1709
1861
  id: "app.utils.publish",
1710
1862
  defaultMessage: "Publish"
1711
1863
  }),
1712
1864
  onClick: async () => {
1713
- setSubmitting(true);
1714
- try {
1715
- const { errors } = await validate();
1716
- if (errors) {
1717
- toggleNotification({
1718
- type: "danger",
1719
- message: formatMessage({
1720
- id: "content-manager.validation.error",
1721
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1722
- })
1723
- });
1724
- return;
1725
- }
1726
- const res = await publish(
1727
- {
1728
- collectionType,
1729
- model,
1730
- documentId,
1731
- params
1732
- },
1733
- formValues
1734
- );
1735
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1736
- navigate({
1737
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1738
- search: rawQuery
1739
- });
1740
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1741
- setErrors(formatValidationErrors(res.error));
1865
+ if (hasDraftRelations) {
1866
+ return;
1867
+ }
1868
+ await performPublish();
1869
+ },
1870
+ dialog: hasDraftRelations ? {
1871
+ type: "dialog",
1872
+ variant: "danger",
1873
+ footer: null,
1874
+ title: formatMessage({
1875
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
1876
+ defaultMessage: "Confirmation"
1877
+ }),
1878
+ content: formatMessage(
1879
+ {
1880
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
1881
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
1882
+ },
1883
+ {
1884
+ count: totalDraftRelations
1742
1885
  }
1743
- } finally {
1744
- setSubmitting(false);
1886
+ ),
1887
+ onConfirm: async () => {
1888
+ await performPublish();
1745
1889
  }
1746
- }
1890
+ } : void 0
1747
1891
  };
1748
1892
  };
1749
1893
  PublishAction$1.type = "publish";
@@ -1759,10 +1903,6 @@ const UpdateAction = ({
1759
1903
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1760
1904
  const isCloning = cloneMatch !== null;
1761
1905
  const { formatMessage } = reactIntl.useIntl();
1762
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1763
- canCreate: canCreate2,
1764
- canUpdate: canUpdate2
1765
- }));
1766
1906
  const { create, update, clone } = useDocumentActions();
1767
1907
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1768
1908
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1779,10 +1919,8 @@ const UpdateAction = ({
1779
1919
  * - the form is submitting
1780
1920
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1781
1921
  * - the active tab is the published tab
1782
- * - the user doesn't have the permission to create a new document
1783
- * - the user doesn't have the permission to update the document
1784
1922
  */
1785
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
1923
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1786
1924
  label: formatMessage({
1787
1925
  id: "content-manager.containers.Edit.save",
1788
1926
  defaultMessage: "Save"
@@ -1790,16 +1928,18 @@ const UpdateAction = ({
1790
1928
  onClick: async () => {
1791
1929
  setSubmitting(true);
1792
1930
  try {
1793
- const { errors } = await validate();
1794
- if (errors) {
1795
- toggleNotification({
1796
- type: "danger",
1797
- message: formatMessage({
1798
- id: "content-manager.validation.error",
1799
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1800
- })
1801
- });
1802
- return;
1931
+ if (activeTab !== "draft") {
1932
+ const { errors } = await validate();
1933
+ if (errors) {
1934
+ toggleNotification({
1935
+ type: "danger",
1936
+ message: formatMessage({
1937
+ id: "content-manager.validation.error",
1938
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1939
+ })
1940
+ });
1941
+ return;
1942
+ }
1803
1943
  }
1804
1944
  if (isCloning) {
1805
1945
  const res = await clone(
@@ -1811,10 +1951,13 @@ const UpdateAction = ({
1811
1951
  document
1812
1952
  );
1813
1953
  if ("data" in res) {
1814
- navigate({
1815
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1816
- search: rawQuery
1817
- });
1954
+ navigate(
1955
+ {
1956
+ pathname: `../${res.data.documentId}`,
1957
+ search: rawQuery
1958
+ },
1959
+ { relative: "path" }
1960
+ );
1818
1961
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1819
1962
  setErrors(formatValidationErrors(res.error));
1820
1963
  }
@@ -1842,10 +1985,13 @@ const UpdateAction = ({
1842
1985
  document
1843
1986
  );
1844
1987
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1845
- navigate({
1846
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1847
- search: rawQuery
1848
- });
1988
+ navigate(
1989
+ {
1990
+ pathname: `../${res.data.documentId}`,
1991
+ search: rawQuery
1992
+ },
1993
+ { replace: true, relative: "path" }
1994
+ );
1849
1995
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1850
1996
  setErrors(formatValidationErrors(res.error));
1851
1997
  }
@@ -2091,23 +2237,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2091
2237
  id: "content-manager.containers.edit.title.new",
2092
2238
  defaultMessage: "Create an entry"
2093
2239
  }) : documentTitle;
2094
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2240
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2095
2241
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
2096
- /* @__PURE__ */ jsxRuntime.jsxs(
2097
- designSystem.Flex,
2098
- {
2099
- width: "100%",
2100
- justifyContent: "space-between",
2101
- paddingTop: 1,
2102
- gap: "80px",
2103
- alignItems: "flex-start",
2104
- children: [
2105
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2106
- /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2107
- ]
2108
- }
2109
- ),
2110
- status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2242
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2243
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2244
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2245
+ ] }),
2246
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2111
2247
  ] });
2112
2248
  };
2113
2249
  const HeaderToolbar = () => {
@@ -2798,7 +2934,7 @@ const ConfirmBulkActionDialog = ({
2798
2934
  endAction
2799
2935
  }) => {
2800
2936
  const { formatMessage } = reactIntl.useIntl();
2801
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2937
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2802
2938
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2803
2939
  id: "app.components.ConfirmDialog.title",
2804
2940
  defaultMessage: "Confirmation"
@@ -2919,7 +3055,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2919
3055
  )
2920
3056
  );
2921
3057
  } else {
2922
- messages.push(...formatErrorMessages(value, currentKey, formatMessage));
3058
+ messages.push(
3059
+ ...formatErrorMessages(
3060
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3061
+ value,
3062
+ currentKey,
3063
+ formatMessage
3064
+ )
3065
+ );
2923
3066
  }
2924
3067
  } else {
2925
3068
  messages.push(
@@ -3080,7 +3223,13 @@ const SelectedEntriesModalContent = ({
3080
3223
  );
3081
3224
  const { rows, validationErrors } = React__namespace.useMemo(() => {
3082
3225
  if (data.length > 0 && schema) {
3083
- const validate = createYupSchema(schema.attributes, components);
3226
+ const validate = createYupSchema(
3227
+ schema.attributes,
3228
+ components,
3229
+ // Since this is the "Publish" action, the validation
3230
+ // schema must enforce the rules for published entities
3231
+ { status: "published" }
3232
+ );
3084
3233
  const validationErrors2 = {};
3085
3234
  const rows2 = data.map((entry) => {
3086
3235
  try {
@@ -3430,7 +3579,7 @@ const TableActions = ({ document }) => {
3430
3579
  strapiAdmin.DescriptionComponentRenderer,
3431
3580
  {
3432
3581
  props,
3433
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3582
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
3434
3583
  children: (actions2) => {
3435
3584
  const tableRowActions = actions2.filter((action) => {
3436
3585
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3541,7 +3690,7 @@ const CloneAction = ({ model, documentId }) => {
3541
3690
  }),
3542
3691
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3543
3692
  footer: ({ onClose }) => {
3544
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3693
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3545
3694
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3546
3695
  id: "cancel",
3547
3696
  defaultMessage: "Cancel"
@@ -3582,8 +3731,7 @@ class ContentManagerPlugin {
3582
3731
  documentActions = [
3583
3732
  ...DEFAULT_ACTIONS,
3584
3733
  ...DEFAULT_TABLE_ROW_ACTIONS,
3585
- ...DEFAULT_HEADER_ACTIONS,
3586
- HistoryAction
3734
+ ...DEFAULT_HEADER_ACTIONS
3587
3735
  ];
3588
3736
  editViewSidePanels = [ActionsPanel];
3589
3737
  headerActions = [];
@@ -3672,6 +3820,52 @@ const getPrintableType = (value) => {
3672
3820
  }
3673
3821
  return nativeType;
3674
3822
  };
3823
+ const HistoryAction = ({ model, document }) => {
3824
+ const { formatMessage } = reactIntl.useIntl();
3825
+ const [{ query }] = strapiAdmin.useQueryParams();
3826
+ const navigate = reactRouterDom.useNavigate();
3827
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3828
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3829
+ return null;
3830
+ }
3831
+ return {
3832
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3833
+ label: formatMessage({
3834
+ id: "content-manager.history.document-action",
3835
+ defaultMessage: "Content History"
3836
+ }),
3837
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3838
+ disabled: (
3839
+ /**
3840
+ * The user is creating a new document.
3841
+ * It hasn't been saved yet, so there's no history to go to
3842
+ */
3843
+ !document || /**
3844
+ * The document has been created but the current dimension has never been saved.
3845
+ * For example, the user is creating a new locale in an existing document,
3846
+ * so there's no history for the document in that locale
3847
+ */
3848
+ !document.id || /**
3849
+ * History is only available for content types created by the user.
3850
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3851
+ * which start with `admin::` or `plugin::`
3852
+ */
3853
+ !model.startsWith("api::")
3854
+ ),
3855
+ position: "header"
3856
+ };
3857
+ };
3858
+ HistoryAction.type = "history";
3859
+ const historyAdmin = {
3860
+ bootstrap(app) {
3861
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3862
+ addDocumentAction((actions2) => {
3863
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3864
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3865
+ return actions2;
3866
+ });
3867
+ }
3868
+ };
3675
3869
  const initialState = {
3676
3870
  collectionTypeLinks: [],
3677
3871
  components: [],
@@ -3727,7 +3921,7 @@ const index = {
3727
3921
  app.router.addRoute({
3728
3922
  path: "content-manager/*",
3729
3923
  lazy: async () => {
3730
- const { Layout } = await Promise.resolve().then(() => require("./layout-Dm6fbiQj.js"));
3924
+ const { Layout } = await Promise.resolve().then(() => require("./layout-C788OmNr.js"));
3731
3925
  return {
3732
3926
  Component: Layout
3733
3927
  };
@@ -3736,10 +3930,15 @@ const index = {
3736
3930
  });
3737
3931
  app.registerPlugin(cm.config);
3738
3932
  },
3933
+ bootstrap(app) {
3934
+ if (typeof historyAdmin.bootstrap === "function") {
3935
+ historyAdmin.bootstrap(app);
3936
+ }
3937
+ },
3739
3938
  async registerTrads({ locales }) {
3740
3939
  const importedTrads = await Promise.all(
3741
3940
  locales.map((locale) => {
3742
- 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 }) => {
3941
+ 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 }) => {
3743
3942
  return {
3744
3943
  data: prefixPluginTranslations(data, PLUGIN_ID),
3745
3944
  locale
@@ -3757,6 +3956,7 @@ const index = {
3757
3956
  };
3758
3957
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3759
3958
  exports.BulkActionsRenderer = BulkActionsRenderer;
3959
+ exports.CLONE_PATH = CLONE_PATH;
3760
3960
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3761
3961
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3762
3962
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3796,4 +3996,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3796
3996
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3797
3997
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3798
3998
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3799
- //# sourceMappingURL=index-DVPWZkbS.js.map
3999
+ //# sourceMappingURL=index-C3fJE-1-.js.map