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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-CR5XdR33.mjs → ComponentConfigurationPage-DJEJ49QD.mjs} +3 -3
  3. package/dist/_chunks/{ComponentConfigurationPage-CR5XdR33.mjs.map → ComponentConfigurationPage-DJEJ49QD.mjs.map} +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-DJcn1DrO.js → ComponentConfigurationPage-D_g11bYV.js} +3 -3
  5. package/dist/_chunks/{ComponentConfigurationPage-DJcn1DrO.js.map → ComponentConfigurationPage-D_g11bYV.js.map} +1 -1
  6. package/dist/_chunks/{EditConfigurationPage-tDtWj7R2.js → EditConfigurationPage-CeL712KW.js} +3 -3
  7. package/dist/_chunks/{EditConfigurationPage-tDtWj7R2.js.map → EditConfigurationPage-CeL712KW.js.map} +1 -1
  8. package/dist/_chunks/{EditConfigurationPage-DmCIb4kD.mjs → EditConfigurationPage-QBZdUYyG.mjs} +3 -3
  9. package/dist/_chunks/{EditConfigurationPage-DmCIb4kD.mjs.map → EditConfigurationPage-QBZdUYyG.mjs.map} +1 -1
  10. package/dist/_chunks/{EditViewPage-DvaV7U9b.mjs → EditViewPage-CvRUUpVh.mjs} +58 -47
  11. package/dist/_chunks/EditViewPage-CvRUUpVh.mjs.map +1 -0
  12. package/dist/_chunks/{EditViewPage-CoQEnFlC.js → EditViewPage-g5TwrgRY.js} +57 -46
  13. package/dist/_chunks/EditViewPage-g5TwrgRY.js.map +1 -0
  14. package/dist/_chunks/{Field-ZdrmmQ4Y.js → Field-ncdInvxS.js} +521 -203
  15. package/dist/_chunks/Field-ncdInvxS.js.map +1 -0
  16. package/dist/_chunks/{Field-Cz_J9551.mjs → Field-reyvfnop.mjs} +523 -205
  17. package/dist/_chunks/Field-reyvfnop.mjs.map +1 -0
  18. package/dist/_chunks/{Form-Bpig5rch.js → Form-BJ7bYiUx.js} +40 -28
  19. package/dist/_chunks/Form-BJ7bYiUx.js.map +1 -0
  20. package/dist/_chunks/{Form-Dxmihyw8.mjs → Form-DoMGsYxH.mjs} +42 -30
  21. package/dist/_chunks/Form-DoMGsYxH.mjs.map +1 -0
  22. package/dist/_chunks/{History-BZP8n7KT.mjs → History-BseDJOrj.mjs} +141 -37
  23. package/dist/_chunks/History-BseDJOrj.mjs.map +1 -0
  24. package/dist/_chunks/{History-BfX6XmZK.js → History-pbhkxIrf.js} +140 -36
  25. package/dist/_chunks/History-pbhkxIrf.js.map +1 -0
  26. package/dist/_chunks/{ListConfigurationPage-B3CXj8PY.js → ListConfigurationPage-Bna8zfjr.js} +57 -46
  27. package/dist/_chunks/ListConfigurationPage-Bna8zfjr.js.map +1 -0
  28. package/dist/_chunks/{ListConfigurationPage-DxKuVkKz.mjs → ListConfigurationPage-DWE_fr5B.mjs} +58 -48
  29. package/dist/_chunks/ListConfigurationPage-DWE_fr5B.mjs.map +1 -0
  30. package/dist/_chunks/{ListViewPage-Bk9VO__I.js → ListViewPage-Dymsvnv6.js} +82 -93
  31. package/dist/_chunks/ListViewPage-Dymsvnv6.js.map +1 -0
  32. package/dist/_chunks/{ListViewPage-D5D3tVPq.mjs → ListViewPage-lQ-VLV2G.mjs} +84 -95
  33. package/dist/_chunks/ListViewPage-lQ-VLV2G.mjs.map +1 -0
  34. package/dist/_chunks/{NoContentTypePage-DsB2F7Z1.js → NoContentTypePage-B4t_OsDR.js} +2 -2
  35. package/dist/_chunks/{NoContentTypePage-DsB2F7Z1.js.map → NoContentTypePage-B4t_OsDR.js.map} +1 -1
  36. package/dist/_chunks/{NoContentTypePage-DnMeuQCj.mjs → NoContentTypePage-VCQOMwlf.mjs} +2 -2
  37. package/dist/_chunks/{NoContentTypePage-DnMeuQCj.mjs.map → NoContentTypePage-VCQOMwlf.mjs.map} +1 -1
  38. package/dist/_chunks/{NoPermissionsPage-BQDM64_b.js → NoPermissionsPage-BOwB6hki.js} +2 -2
  39. package/dist/_chunks/{NoPermissionsPage-BQDM64_b.js.map → NoPermissionsPage-BOwB6hki.js.map} +1 -1
  40. package/dist/_chunks/{NoPermissionsPage-OyoME_Tf.mjs → NoPermissionsPage-TV830k4P.mjs} +2 -2
  41. package/dist/_chunks/{NoPermissionsPage-OyoME_Tf.mjs.map → NoPermissionsPage-TV830k4P.mjs.map} +1 -1
  42. package/dist/_chunks/{Relations-BOYZmuWy.mjs → Relations-D6NAlnsl.mjs} +4 -4
  43. package/dist/_chunks/Relations-D6NAlnsl.mjs.map +1 -0
  44. package/dist/_chunks/{Relations-B6B3A3mb.js → Relations-DdlstXTu.js} +4 -4
  45. package/dist/_chunks/Relations-DdlstXTu.js.map +1 -0
  46. package/dist/_chunks/{en-BN1bvFK7.js → en-Cf41pH5f.js} +12 -7
  47. package/dist/_chunks/{en-BN1bvFK7.js.map → en-Cf41pH5f.js.map} +1 -1
  48. package/dist/_chunks/{en-Dzv55oQw.mjs → en-DCszE74t.mjs} +12 -7
  49. package/dist/_chunks/{en-Dzv55oQw.mjs.map → en-DCszE74t.mjs.map} +1 -1
  50. package/dist/_chunks/{index-VHviNMeW.mjs → index-BYSWwHBJ.mjs} +515 -463
  51. package/dist/_chunks/index-BYSWwHBJ.mjs.map +1 -0
  52. package/dist/_chunks/{index-DzN3kBgx.js → index-CQos-KS0.js} +495 -443
  53. package/dist/_chunks/index-CQos-KS0.js.map +1 -0
  54. package/dist/_chunks/{layout-CPn1PM6x.mjs → layout-0TY7UtKO.mjs} +39 -22
  55. package/dist/_chunks/layout-0TY7UtKO.mjs.map +1 -0
  56. package/dist/_chunks/{layout-b91XRlD2.js → layout-B4XAqu1v.js} +37 -20
  57. package/dist/_chunks/layout-B4XAqu1v.js.map +1 -0
  58. package/dist/_chunks/{relations-BsqxS6tR.mjs → relations-DFDWfa0s.mjs} +2 -2
  59. package/dist/_chunks/{relations-BsqxS6tR.mjs.map → relations-DFDWfa0s.mjs.map} +1 -1
  60. package/dist/_chunks/{relations-CA7IYmcP.js → relations-xZ2tMj1G.js} +2 -2
  61. package/dist/_chunks/{relations-CA7IYmcP.js.map → relations-xZ2tMj1G.js.map} +1 -1
  62. package/dist/admin/index.js +1 -1
  63. package/dist/admin/index.mjs +5 -5
  64. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
  65. package/dist/admin/src/history/index.d.ts +3 -0
  66. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  67. package/dist/admin/src/index.d.ts +1 -0
  68. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +8 -3
  69. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  70. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  71. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  72. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  73. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +6 -58
  74. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  75. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  76. package/dist/admin/src/services/api.d.ts +1 -1
  77. package/dist/admin/src/services/components.d.ts +2 -2
  78. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  79. package/dist/admin/src/services/documents.d.ts +19 -17
  80. package/dist/admin/src/services/init.d.ts +1 -1
  81. package/dist/admin/src/services/relations.d.ts +2 -2
  82. package/dist/admin/src/services/uid.d.ts +3 -3
  83. package/dist/admin/src/utils/validation.d.ts +4 -1
  84. package/dist/server/index.js +180 -106
  85. package/dist/server/index.js.map +1 -1
  86. package/dist/server/index.mjs +181 -107
  87. package/dist/server/index.mjs.map +1 -1
  88. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  89. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  90. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  91. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  92. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  93. package/dist/server/src/history/services/history.d.ts.map +1 -1
  94. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  95. package/dist/server/src/history/services/utils.d.ts +2 -1
  96. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  97. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  98. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  99. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  100. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  101. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  102. package/dist/shared/contracts/collection-types.d.ts +3 -1
  103. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  104. package/package.json +8 -8
  105. package/dist/_chunks/EditViewPage-CoQEnFlC.js.map +0 -1
  106. package/dist/_chunks/EditViewPage-DvaV7U9b.mjs.map +0 -1
  107. package/dist/_chunks/Field-Cz_J9551.mjs.map +0 -1
  108. package/dist/_chunks/Field-ZdrmmQ4Y.js.map +0 -1
  109. package/dist/_chunks/Form-Bpig5rch.js.map +0 -1
  110. package/dist/_chunks/Form-Dxmihyw8.mjs.map +0 -1
  111. package/dist/_chunks/History-BZP8n7KT.mjs.map +0 -1
  112. package/dist/_chunks/History-BfX6XmZK.js.map +0 -1
  113. package/dist/_chunks/ListConfigurationPage-B3CXj8PY.js.map +0 -1
  114. package/dist/_chunks/ListConfigurationPage-DxKuVkKz.mjs.map +0 -1
  115. package/dist/_chunks/ListViewPage-Bk9VO__I.js.map +0 -1
  116. package/dist/_chunks/ListViewPage-D5D3tVPq.mjs.map +0 -1
  117. package/dist/_chunks/Relations-B6B3A3mb.js.map +0 -1
  118. package/dist/_chunks/Relations-BOYZmuWy.mjs.map +0 -1
  119. package/dist/_chunks/index-DzN3kBgx.js.map +0 -1
  120. package/dist/_chunks/index-VHviNMeW.mjs.map +0 -1
  121. package/dist/_chunks/layout-CPn1PM6x.mjs.map +0 -1
  122. package/dist/_chunks/layout-b91XRlD2.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");
10
- const styledComponents = require("styled-components");
7
+ const reactIntl = require("react-intl");
8
+ const reactRouterDom = require("react-router-dom");
11
9
  const yup = require("yup");
12
10
  const pipe = require("lodash/fp/pipe");
13
11
  const dateFns = require("date-fns");
12
+ const styledComponents = require("styled-components");
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,10 +179,12 @@ 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({
187
+ overrideExisting: true,
222
188
  endpoints: (builder) => ({
223
189
  autoCloneDocument: builder.mutation({
224
190
  query: ({ model, sourceId, query }) => ({
@@ -228,7 +194,12 @@ const documentApi = contentManagerApi.injectEndpoints({
228
194
  params: query
229
195
  }
230
196
  }),
231
- 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
+ }
232
203
  }),
233
204
  cloneDocument: builder.mutation({
234
205
  query: ({ model, sourceId, data, params }) => ({
@@ -239,7 +210,10 @@ const documentApi = contentManagerApi.injectEndpoints({
239
210
  params
240
211
  }
241
212
  }),
242
- 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
+ ]
243
217
  }),
244
218
  /**
245
219
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -256,7 +230,8 @@ const documentApi = contentManagerApi.injectEndpoints({
256
230
  }),
257
231
  invalidatesTags: (result, _error, { model }) => [
258
232
  { type: "Document", id: `${model}_LIST` },
259
- "Relations"
233
+ "Relations",
234
+ { type: "UidAvailability", id: model }
260
235
  ]
261
236
  }),
262
237
  deleteDocument: builder.mutation({
@@ -297,7 +272,8 @@ const documentApi = contentManagerApi.injectEndpoints({
297
272
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
298
273
  },
299
274
  { type: "Document", id: `${model}_LIST` },
300
- "Relations"
275
+ "Relations",
276
+ { type: "UidAvailability", id: model }
301
277
  ];
302
278
  }
303
279
  }),
@@ -315,6 +291,7 @@ const documentApi = contentManagerApi.injectEndpoints({
315
291
  }),
316
292
  providesTags: (result, _error, arg) => {
317
293
  return [
294
+ { type: "Document", id: `ALL_LIST` },
318
295
  { type: "Document", id: `${arg.model}_LIST` },
319
296
  ...result?.results.map(({ documentId }) => ({
320
297
  type: "Document",
@@ -353,6 +330,11 @@ const documentApi = contentManagerApi.injectEndpoints({
353
330
  {
354
331
  type: "Document",
355
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`
356
338
  }
357
339
  ];
358
340
  }
@@ -416,8 +398,21 @@ const documentApi = contentManagerApi.injectEndpoints({
416
398
  type: "Document",
417
399
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
418
400
  },
419
- "Relations"
401
+ "Relations",
402
+ { type: "UidAvailability", id: model }
420
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
+ }
421
416
  }
422
417
  }),
423
418
  unpublishDocument: builder.mutation({
@@ -487,7 +482,7 @@ const buildValidParams = (query) => {
487
482
  const isBaseQueryError = (error) => {
488
483
  return error.name !== void 0;
489
484
  };
490
- const createYupSchema = (attributes = {}, components = {}) => {
485
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
491
486
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
492
487
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
493
488
  if (DOCUMENT_META_FIELDS.includes(name)) {
@@ -500,7 +495,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
500
495
  addMinValidation,
501
496
  addMaxValidation,
502
497
  addRegexValidation
503
- ].map((fn) => fn(attribute));
498
+ ].map((fn) => fn(attribute, options));
504
499
  const transformSchema = pipe__default.default(...validations);
505
500
  switch (attribute.type) {
506
501
  case "component": {
@@ -601,6 +596,14 @@ const createAttributeSchema = (attribute) => {
601
596
  if (!value || typeof value === "string" && value.length === 0) {
602
597
  return true;
603
598
  }
599
+ if (typeof value === "object") {
600
+ try {
601
+ JSON.stringify(value);
602
+ return true;
603
+ } catch (err) {
604
+ return false;
605
+ }
606
+ }
604
607
  try {
605
608
  JSON.parse(value);
606
609
  return true;
@@ -619,13 +622,7 @@ const createAttributeSchema = (attribute) => {
619
622
  return yup__namespace.mixed();
620
623
  }
621
624
  };
622
- 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
- });
628
- }
625
+ const nullableSchema = (schema) => {
629
626
  return schema?.nullable ? schema.nullable() : (
630
627
  // In some cases '.nullable' will not be available on the schema.
631
628
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -633,7 +630,22 @@ const addRequiredValidation = (attribute) => (schema) => {
633
630
  schema
634
631
  );
635
632
  };
636
- 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
+ }
637
649
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
638
650
  return schema.min(attribute.minLength, {
639
651
  ...strapiAdmin.translatedErrors.minLength,
@@ -655,9 +667,31 @@ const addMaxLengthValidation = (attribute) => (schema) => {
655
667
  }
656
668
  return schema;
657
669
  };
658
- const addMinValidation = (attribute) => (schema) => {
670
+ const addMinValidation = (attribute, options) => (schema) => {
659
671
  if ("min" in attribute) {
660
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
+ }
661
695
  if ("min" in schema && min) {
662
696
  return schema.min(min, {
663
697
  ...strapiAdmin.translatedErrors.min,
@@ -784,7 +818,10 @@ const useDocument = (args, opts) => {
784
818
  isLoading: isLoadingDocument,
785
819
  isFetching: isFetchingDocument,
786
820
  error
787
- } = useGetDocumentQuery(args, opts);
821
+ } = useGetDocumentQuery(args, {
822
+ ...opts,
823
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
824
+ });
788
825
  const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
789
826
  React__namespace.useEffect(() => {
790
827
  if (error) {
@@ -870,6 +907,7 @@ const useDocumentActions = () => {
870
907
  const { formatMessage } = reactIntl.useIntl();
871
908
  const { trackUsage } = strapiAdmin.useTracking();
872
909
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
910
+ const navigate = reactRouterDom.useNavigate();
873
911
  const [deleteDocument] = useDeleteDocumentMutation();
874
912
  const _delete = React__namespace.useCallback(
875
913
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -948,12 +986,13 @@ const useDocumentActions = () => {
948
986
  );
949
987
  const [discardDocument] = useDiscardDocumentMutation();
950
988
  const discard = React__namespace.useCallback(
951
- async ({ collectionType, model, documentId }) => {
989
+ async ({ collectionType, model, documentId, params }) => {
952
990
  try {
953
991
  const res = await discardDocument({
954
992
  collectionType,
955
993
  model,
956
- documentId
994
+ documentId,
995
+ params
957
996
  });
958
997
  if ("error" in res) {
959
998
  toggleNotification({
@@ -1204,7 +1243,6 @@ const useDocumentActions = () => {
1204
1243
  sourceId
1205
1244
  });
1206
1245
  if ("error" in res) {
1207
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1208
1246
  return { error: res.error };
1209
1247
  }
1210
1248
  toggleNotification({
@@ -1223,7 +1261,7 @@ const useDocumentActions = () => {
1223
1261
  throw err;
1224
1262
  }
1225
1263
  },
1226
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1264
+ [autoCloneDocument, formatMessage, toggleNotification]
1227
1265
  );
1228
1266
  const [cloneDocument] = useCloneDocumentMutation();
1229
1267
  const clone = React__namespace.useCallback(
@@ -1249,6 +1287,7 @@ const useDocumentActions = () => {
1249
1287
  defaultMessage: "Cloned document"
1250
1288
  })
1251
1289
  });
1290
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1252
1291
  return res.data;
1253
1292
  } catch (err) {
1254
1293
  toggleNotification({
@@ -1259,7 +1298,7 @@ const useDocumentActions = () => {
1259
1298
  throw err;
1260
1299
  }
1261
1300
  },
1262
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1301
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1263
1302
  );
1264
1303
  const [getDoc] = useLazyGetDocumentQuery();
1265
1304
  const getDocument = React__namespace.useCallback(
@@ -1285,7 +1324,7 @@ const useDocumentActions = () => {
1285
1324
  };
1286
1325
  };
1287
1326
  const ProtectedHistoryPage = React.lazy(
1288
- () => Promise.resolve().then(() => require("./History-BfX6XmZK.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1327
+ () => Promise.resolve().then(() => require("./History-pbhkxIrf.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1289
1328
  );
1290
1329
  const routes$1 = [
1291
1330
  {
@@ -1298,31 +1337,31 @@ const routes$1 = [
1298
1337
  }
1299
1338
  ];
1300
1339
  const ProtectedEditViewPage = React.lazy(
1301
- () => Promise.resolve().then(() => require("./EditViewPage-CoQEnFlC.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1340
+ () => Promise.resolve().then(() => require("./EditViewPage-g5TwrgRY.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1302
1341
  );
1303
1342
  const ProtectedListViewPage = React.lazy(
1304
- () => Promise.resolve().then(() => require("./ListViewPage-Bk9VO__I.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1343
+ () => Promise.resolve().then(() => require("./ListViewPage-Dymsvnv6.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1305
1344
  );
1306
1345
  const ProtectedListConfiguration = React.lazy(
1307
- () => Promise.resolve().then(() => require("./ListConfigurationPage-B3CXj8PY.js")).then((mod) => ({
1346
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-Bna8zfjr.js")).then((mod) => ({
1308
1347
  default: mod.ProtectedListConfiguration
1309
1348
  }))
1310
1349
  );
1311
1350
  const ProtectedEditConfigurationPage = React.lazy(
1312
- () => Promise.resolve().then(() => require("./EditConfigurationPage-tDtWj7R2.js")).then((mod) => ({
1351
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-CeL712KW.js")).then((mod) => ({
1313
1352
  default: mod.ProtectedEditConfigurationPage
1314
1353
  }))
1315
1354
  );
1316
1355
  const ProtectedComponentConfigurationPage = React.lazy(
1317
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-DJcn1DrO.js")).then((mod) => ({
1356
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-D_g11bYV.js")).then((mod) => ({
1318
1357
  default: mod.ProtectedComponentConfigurationPage
1319
1358
  }))
1320
1359
  );
1321
1360
  const NoPermissions = React.lazy(
1322
- () => Promise.resolve().then(() => require("./NoPermissionsPage-BQDM64_b.js")).then((mod) => ({ default: mod.NoPermissions }))
1361
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-BOwB6hki.js")).then((mod) => ({ default: mod.NoPermissions }))
1323
1362
  );
1324
1363
  const NoContentType = React.lazy(
1325
- () => Promise.resolve().then(() => require("./NoContentTypePage-DsB2F7Z1.js")).then((mod) => ({ default: mod.NoContentType }))
1364
+ () => Promise.resolve().then(() => require("./NoContentTypePage-B4t_OsDR.js")).then((mod) => ({ default: mod.NoContentType }))
1326
1365
  );
1327
1366
  const CollectionTypePages = () => {
1328
1367
  const { collectionType } = reactRouterDom.useParams();
@@ -1436,12 +1475,14 @@ const DocumentActionButton = (action) => {
1436
1475
  /* @__PURE__ */ jsxRuntime.jsx(
1437
1476
  designSystem.Button,
1438
1477
  {
1439
- flex: 1,
1478
+ flex: "auto",
1440
1479
  startIcon: action.icon,
1441
1480
  disabled: action.disabled,
1442
1481
  onClick: handleClick(action),
1443
1482
  justifyContent: "center",
1444
1483
  variant: action.variant || "default",
1484
+ paddingTop: "7px",
1485
+ paddingBottom: "7px",
1445
1486
  children: action.label
1446
1487
  }
1447
1488
  ),
@@ -1449,7 +1490,7 @@ const DocumentActionButton = (action) => {
1449
1490
  DocumentActionConfirmDialog,
1450
1491
  {
1451
1492
  ...action.dialog,
1452
- variant: action.variant,
1493
+ variant: action.dialog?.variant ?? action.variant,
1453
1494
  isOpen: dialogId === action.id,
1454
1495
  onClose: handleClose
1455
1496
  }
@@ -1506,9 +1547,9 @@ const DocumentActionsMenu = ({
1506
1547
  disabled: isDisabled,
1507
1548
  size: "S",
1508
1549
  endIcon: null,
1509
- paddingTop: "7px",
1510
- paddingLeft: "9px",
1511
- paddingRight: "9px",
1550
+ paddingTop: "4px",
1551
+ paddingLeft: "7px",
1552
+ paddingRight: "7px",
1512
1553
  variant,
1513
1554
  children: [
1514
1555
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
@@ -1528,10 +1569,25 @@ const DocumentActionsMenu = ({
1528
1569
  onSelect: handleClick(action),
1529
1570
  display: "block",
1530
1571
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1531
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1532
- action.icon,
1533
- action.label
1534
- ] }),
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
+ ),
1535
1591
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
1536
1592
  designSystem.Flex,
1537
1593
  {
@@ -1590,6 +1646,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1590
1646
  return "primary600";
1591
1647
  }
1592
1648
  };
1649
+ const convertActionVariantToIconColor = (variant = "secondary") => {
1650
+ switch (variant) {
1651
+ case "danger":
1652
+ return "danger600";
1653
+ case "secondary":
1654
+ return "neutral500";
1655
+ case "success":
1656
+ return "success600";
1657
+ default:
1658
+ return "primary600";
1659
+ }
1660
+ };
1593
1661
  const DocumentActionConfirmDialog = ({
1594
1662
  onClose,
1595
1663
  onCancel,
@@ -1612,22 +1680,20 @@ const DocumentActionConfirmDialog = ({
1612
1680
  }
1613
1681
  onClose();
1614
1682
  };
1615
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog, { isOpen, title, onClose: handleClose, children: [
1616
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.DialogBody, { children: content }),
1617
- /* @__PURE__ */ jsxRuntime.jsx(
1618
- designSystem.DialogFooter,
1619
- {
1620
- startAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", children: formatMessage({
1621
- id: "app.components.Button.cancel",
1622
- defaultMessage: "Cancel"
1623
- }) }),
1624
- endAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
1625
- id: "app.components.Button.confirm",
1626
- defaultMessage: "Confirm"
1627
- }) })
1628
- }
1629
- )
1630
- ] });
1683
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
1684
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
1685
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
1686
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
1687
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
1688
+ id: "app.components.Button.cancel",
1689
+ defaultMessage: "Cancel"
1690
+ }) }) }),
1691
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
1692
+ id: "app.components.Button.confirm",
1693
+ defaultMessage: "Confirm"
1694
+ }) })
1695
+ ] })
1696
+ ] }) });
1631
1697
  };
1632
1698
  const DocumentActionModal = ({
1633
1699
  isOpen,
@@ -1637,34 +1703,17 @@ const DocumentActionModal = ({
1637
1703
  content: Content,
1638
1704
  onModalClose
1639
1705
  }) => {
1640
- const id = React__namespace.useId();
1641
- if (!isOpen) {
1642
- return null;
1643
- }
1644
1706
  const handleClose = () => {
1645
1707
  if (onClose) {
1646
1708
  onClose();
1647
1709
  }
1648
1710
  onModalClose();
1649
1711
  };
1650
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { borderRadius: "4px", overflow: "hidden", onClose: handleClose, labelledBy: id, children: [
1651
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: "neutral800", tag: "h2", id, children: title }) }),
1652
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content }),
1653
- /* @__PURE__ */ jsxRuntime.jsx(
1654
- designSystem.Box,
1655
- {
1656
- paddingTop: 4,
1657
- paddingBottom: 4,
1658
- paddingLeft: 5,
1659
- paddingRight: 5,
1660
- borderWidth: "1px 0 0 0",
1661
- borderStyle: "solid",
1662
- borderColor: "neutral150",
1663
- background: "neutral100",
1664
- children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1665
- }
1666
- )
1667
- ] });
1712
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
1713
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
1714
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
1715
+ typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1716
+ ] }) });
1668
1717
  };
1669
1718
  const PublishAction$1 = ({
1670
1719
  activeTab,
@@ -1678,13 +1727,17 @@ const PublishAction$1 = ({
1678
1727
  const navigate = reactRouterDom.useNavigate();
1679
1728
  const { toggleNotification } = strapiAdmin.useNotification();
1680
1729
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
1730
+ const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
1681
1731
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
1682
1732
  const { formatMessage } = reactIntl.useIntl();
1683
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1684
- "PublishAction",
1685
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1686
- );
1733
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1687
1734
  const { publish } = useDocumentActions();
1735
+ const [
1736
+ countDraftRelations,
1737
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
1738
+ ] = useLazyGetDraftRelationCountQuery();
1739
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
1740
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
1688
1741
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1689
1742
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1690
1743
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1693,10 +1746,103 @@ const PublishAction$1 = ({
1693
1746
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1694
1747
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1695
1748
  const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
1749
+ React__namespace.useEffect(() => {
1750
+ if (isErrorDraftRelations) {
1751
+ toggleNotification({
1752
+ type: "danger",
1753
+ message: formatMessage({
1754
+ id: getTranslation("error.records.fetch-draft-relatons"),
1755
+ defaultMessage: "An error occurred while fetching draft relations on this document."
1756
+ })
1757
+ });
1758
+ }
1759
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
1760
+ React__namespace.useEffect(() => {
1761
+ const localDraftRelations = /* @__PURE__ */ new Set();
1762
+ const extractDraftRelations = (data) => {
1763
+ const relations = data.connect || [];
1764
+ relations.forEach((relation) => {
1765
+ if (relation.status === "draft") {
1766
+ localDraftRelations.add(relation.id);
1767
+ }
1768
+ });
1769
+ };
1770
+ const traverseAndExtract = (data) => {
1771
+ Object.entries(data).forEach(([key, value]) => {
1772
+ if (key === "connect" && Array.isArray(value)) {
1773
+ extractDraftRelations({ connect: value });
1774
+ } else if (typeof value === "object" && value !== null) {
1775
+ traverseAndExtract(value);
1776
+ }
1777
+ });
1778
+ };
1779
+ if (!documentId || modified) {
1780
+ traverseAndExtract(formValues);
1781
+ setLocalCountOfDraftRelations(localDraftRelations.size);
1782
+ }
1783
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
1784
+ React__namespace.useEffect(() => {
1785
+ if (!document || !document.documentId || isListView) {
1786
+ return;
1787
+ }
1788
+ const fetchDraftRelationsCount = async () => {
1789
+ const { data, error } = await countDraftRelations({
1790
+ collectionType,
1791
+ model,
1792
+ documentId,
1793
+ params
1794
+ });
1795
+ if (error) {
1796
+ throw error;
1797
+ }
1798
+ if (data) {
1799
+ setServerCountOfDraftRelations(data.data);
1800
+ }
1801
+ };
1802
+ fetchDraftRelationsCount();
1803
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
1696
1804
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1697
1805
  if (!schema?.options?.draftAndPublish) {
1698
1806
  return null;
1699
1807
  }
1808
+ const performPublish = async () => {
1809
+ setSubmitting(true);
1810
+ try {
1811
+ const { errors } = await validate();
1812
+ if (errors) {
1813
+ toggleNotification({
1814
+ type: "danger",
1815
+ message: formatMessage({
1816
+ id: "content-manager.validation.error",
1817
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1818
+ })
1819
+ });
1820
+ return;
1821
+ }
1822
+ const res = await publish(
1823
+ {
1824
+ collectionType,
1825
+ model,
1826
+ documentId,
1827
+ params
1828
+ },
1829
+ formValues
1830
+ );
1831
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
1832
+ navigate({
1833
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1834
+ search: rawQuery
1835
+ });
1836
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1837
+ setErrors(formatValidationErrors(res.error));
1838
+ }
1839
+ } finally {
1840
+ setSubmitting(false);
1841
+ }
1842
+ };
1843
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1844
+ const enableDraftRelationsCount = false;
1845
+ const hasDraftRelations = enableDraftRelationsCount;
1700
1846
  return {
1701
1847
  /**
1702
1848
  * Disabled when:
@@ -1706,49 +1852,36 @@ const PublishAction$1 = ({
1706
1852
  * - the document is already published & not modified
1707
1853
  * - the document is being created & not modified
1708
1854
  * - the user doesn't have the permission to publish
1709
- * - the user doesn't have the permission to create a new document
1710
- * - the user doesn't have the permission to update the document
1711
1855
  */
1712
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1856
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1713
1857
  label: formatMessage({
1714
1858
  id: "app.utils.publish",
1715
1859
  defaultMessage: "Publish"
1716
1860
  }),
1717
1861
  onClick: async () => {
1718
- setSubmitting(true);
1719
- try {
1720
- const { errors } = await validate();
1721
- if (errors) {
1722
- toggleNotification({
1723
- type: "danger",
1724
- message: formatMessage({
1725
- id: "content-manager.validation.error",
1726
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1727
- })
1728
- });
1729
- return;
1730
- }
1731
- const res = await publish(
1732
- {
1733
- collectionType,
1734
- model,
1735
- documentId,
1736
- params
1737
- },
1738
- formValues
1739
- );
1740
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1741
- navigate({
1742
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1743
- search: rawQuery
1744
- });
1745
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1746
- setErrors(formatValidationErrors(res.error));
1862
+ await performPublish();
1863
+ },
1864
+ dialog: hasDraftRelations ? {
1865
+ type: "dialog",
1866
+ variant: "danger",
1867
+ footer: null,
1868
+ title: formatMessage({
1869
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
1870
+ defaultMessage: "Confirmation"
1871
+ }),
1872
+ content: formatMessage(
1873
+ {
1874
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
1875
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
1876
+ },
1877
+ {
1878
+ count: totalDraftRelations
1747
1879
  }
1748
- } finally {
1749
- setSubmitting(false);
1880
+ ),
1881
+ onConfirm: async () => {
1882
+ await performPublish();
1750
1883
  }
1751
- }
1884
+ } : void 0
1752
1885
  };
1753
1886
  };
1754
1887
  PublishAction$1.type = "publish";
@@ -1764,10 +1897,6 @@ const UpdateAction = ({
1764
1897
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1765
1898
  const isCloning = cloneMatch !== null;
1766
1899
  const { formatMessage } = reactIntl.useIntl();
1767
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1768
- canCreate: canCreate2,
1769
- canUpdate: canUpdate2
1770
- }));
1771
1900
  const { create, update, clone } = useDocumentActions();
1772
1901
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1773
1902
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1784,10 +1913,8 @@ const UpdateAction = ({
1784
1913
  * - the form is submitting
1785
1914
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1786
1915
  * - the active tab is the published tab
1787
- * - the user doesn't have the permission to create a new document
1788
- * - the user doesn't have the permission to update the document
1789
1916
  */
1790
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
1917
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1791
1918
  label: formatMessage({
1792
1919
  id: "content-manager.containers.Edit.save",
1793
1920
  defaultMessage: "Save"
@@ -1795,16 +1922,18 @@ const UpdateAction = ({
1795
1922
  onClick: async () => {
1796
1923
  setSubmitting(true);
1797
1924
  try {
1798
- const { errors } = await validate();
1799
- if (errors) {
1800
- toggleNotification({
1801
- type: "danger",
1802
- message: formatMessage({
1803
- id: "content-manager.validation.error",
1804
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1805
- })
1806
- });
1807
- return;
1925
+ if (activeTab !== "draft") {
1926
+ const { errors } = await validate();
1927
+ if (errors) {
1928
+ toggleNotification({
1929
+ type: "danger",
1930
+ message: formatMessage({
1931
+ id: "content-manager.validation.error",
1932
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1933
+ })
1934
+ });
1935
+ return;
1936
+ }
1808
1937
  }
1809
1938
  if (isCloning) {
1810
1939
  const res = await clone(
@@ -1816,10 +1945,13 @@ const UpdateAction = ({
1816
1945
  document
1817
1946
  );
1818
1947
  if ("data" in res) {
1819
- navigate({
1820
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1821
- search: rawQuery
1822
- });
1948
+ navigate(
1949
+ {
1950
+ pathname: `../${res.data.documentId}`,
1951
+ search: rawQuery
1952
+ },
1953
+ { relative: "path" }
1954
+ );
1823
1955
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1824
1956
  setErrors(formatValidationErrors(res.error));
1825
1957
  }
@@ -1847,10 +1979,13 @@ const UpdateAction = ({
1847
1979
  document
1848
1980
  );
1849
1981
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1850
- navigate({
1851
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1852
- search: rawQuery
1853
- });
1982
+ navigate(
1983
+ {
1984
+ pathname: `../${res.data.documentId}`,
1985
+ search: rawQuery
1986
+ },
1987
+ { replace: true, relative: "path" }
1988
+ );
1854
1989
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1855
1990
  setErrors(formatValidationErrors(res.error));
1856
1991
  }
@@ -1882,10 +2017,8 @@ const UnpublishAction$1 = ({
1882
2017
  const { toggleNotification } = strapiAdmin.useNotification();
1883
2018
  const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
1884
2019
  const isDocumentModified = document?.status === "modified";
1885
- const handleChange = (e) => {
1886
- if ("value" in e.target) {
1887
- setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1888
- }
2020
+ const handleChange = (value) => {
2021
+ setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1889
2022
  };
1890
2023
  if (!schema?.options?.draftAndPublish) {
1891
2024
  return null;
@@ -1896,7 +2029,7 @@ const UnpublishAction$1 = ({
1896
2029
  id: "app.utils.unpublish",
1897
2030
  defaultMessage: "Unpublish"
1898
2031
  }),
1899
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2032
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
1900
2033
  onClick: async () => {
1901
2034
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1902
2035
  if (!documentId) {
@@ -1935,40 +2068,24 @@ const UnpublishAction$1 = ({
1935
2068
  }) })
1936
2069
  ] }),
1937
2070
  /* @__PURE__ */ jsxRuntime.jsxs(
1938
- designSystem.Flex,
2071
+ designSystem.Radio.Group,
1939
2072
  {
1940
- onChange: handleChange,
1941
- direction: "column",
1942
- alignItems: "flex-start",
1943
- tag: "fieldset",
1944
- borderWidth: 0,
1945
- gap: 3,
2073
+ defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
2074
+ name: "discard-options",
2075
+ "aria-label": formatMessage({
2076
+ id: "content-manager.actions.unpublish.dialog.radio-label",
2077
+ defaultMessage: "Choose an option to unpublish the document."
2078
+ }),
2079
+ onValueChange: handleChange,
1946
2080
  children: [
1947
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "legend" }),
1948
- /* @__PURE__ */ jsxRuntime.jsx(
1949
- designSystem.Radio,
1950
- {
1951
- checked: shouldKeepDraft,
1952
- value: UNPUBLISH_DRAFT_OPTIONS.KEEP,
1953
- name: "discard-options",
1954
- children: formatMessage({
1955
- id: "content-manager.actions.unpublish.dialog.option.keep-draft",
1956
- defaultMessage: "Keep draft"
1957
- })
1958
- }
1959
- ),
1960
- /* @__PURE__ */ jsxRuntime.jsx(
1961
- designSystem.Radio,
1962
- {
1963
- checked: !shouldKeepDraft,
1964
- value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
1965
- name: "discard-options",
1966
- children: formatMessage({
1967
- id: "content-manager.actions.unpublish.dialog.option.replace-draft",
1968
- defaultMessage: "Replace draft"
1969
- })
1970
- }
1971
- )
2081
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
2082
+ id: "content-manager.actions.unpublish.dialog.option.keep-draft",
2083
+ defaultMessage: "Keep draft"
2084
+ }) }),
2085
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
2086
+ id: "content-manager.actions.unpublish.dialog.option.replace-draft",
2087
+ defaultMessage: "Replace draft"
2088
+ }) })
1972
2089
  ]
1973
2090
  }
1974
2091
  )
@@ -2024,7 +2141,7 @@ const DiscardAction = ({
2024
2141
  id: "content-manager.actions.discard.label",
2025
2142
  defaultMessage: "Discard changes"
2026
2143
  }),
2027
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2144
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
2028
2145
  position: ["panel", "table-row"],
2029
2146
  variant: "danger",
2030
2147
  dialog: {
@@ -2052,11 +2169,6 @@ const DiscardAction = ({
2052
2169
  };
2053
2170
  };
2054
2171
  DiscardAction.type = "discard";
2055
- const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
2056
- path {
2057
- fill: currentColor;
2058
- }
2059
- `;
2060
2172
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2061
2173
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2062
2174
  const RelativeTime = React__namespace.forwardRef(
@@ -2114,23 +2226,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2114
2226
  id: "content-manager.containers.edit.title.new",
2115
2227
  defaultMessage: "Create an entry"
2116
2228
  }) : documentTitle;
2117
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2229
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2118
2230
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
2119
- /* @__PURE__ */ jsxRuntime.jsxs(
2120
- designSystem.Flex,
2121
- {
2122
- width: "100%",
2123
- justifyContent: "space-between",
2124
- paddingTop: 1,
2125
- gap: "80px",
2126
- alignItems: "flex-start",
2127
- children: [
2128
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2129
- /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2130
- ]
2131
- }
2132
- ),
2133
- status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2231
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2232
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2233
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2234
+ ] }),
2235
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2134
2236
  ] });
2135
2237
  };
2136
2238
  const HeaderToolbar = () => {
@@ -2695,7 +2797,8 @@ const formatEditLayout = (data, {
2695
2797
  layout: convertEditLayoutToFieldLayouts(
2696
2798
  configuration.layouts.edit,
2697
2799
  components[uid].attributes,
2698
- configuration.metadatas
2800
+ configuration.metadatas,
2801
+ { configurations: data.components, schemas: components }
2699
2802
  ),
2700
2803
  settings: {
2701
2804
  ...configuration.settings,
@@ -2821,30 +2924,23 @@ const ConfirmBulkActionDialog = ({
2821
2924
  endAction
2822
2925
  }) => {
2823
2926
  const { formatMessage } = reactIntl.useIntl();
2824
- return /* @__PURE__ */ jsxRuntime.jsxs(
2825
- designSystem.Dialog,
2826
- {
2827
- onClose: onToggleDialog,
2828
- title: formatMessage({
2829
- id: "app.components.ConfirmDialog.title",
2830
- defaultMessage: "Confirmation"
2831
- }),
2832
- isOpen,
2833
- children: [
2834
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.DialogBody, { icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, {}), children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: dialogBody }) }),
2835
- /* @__PURE__ */ jsxRuntime.jsx(
2836
- designSystem.DialogFooter,
2837
- {
2838
- startAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
2839
- id: "app.components.Button.cancel",
2840
- defaultMessage: "Cancel"
2841
- }) }),
2842
- endAction
2843
- }
2844
- )
2845
- ]
2846
- }
2847
- );
2927
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2928
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2929
+ id: "app.components.ConfirmDialog.title",
2930
+ defaultMessage: "Confirmation"
2931
+ }) }),
2932
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
2933
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
2934
+ dialogBody
2935
+ ] }) }),
2936
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
2937
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
2938
+ id: "app.components.Button.cancel",
2939
+ defaultMessage: "Cancel"
2940
+ }) }) }),
2941
+ endAction
2942
+ ] })
2943
+ ] }) });
2848
2944
  };
2849
2945
  const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
2850
2946
  const ConfirmDialogPublishAll = ({
@@ -2859,6 +2955,7 @@ const ConfirmDialogPublishAll = ({
2859
2955
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2860
2956
  const { model, schema } = useDoc();
2861
2957
  const [{ query }] = strapiAdmin.useQueryParams();
2958
+ const enableDraftRelationsCount = false;
2862
2959
  const {
2863
2960
  data: countDraftRelations = 0,
2864
2961
  isLoading,
@@ -2870,7 +2967,7 @@ const ConfirmDialogPublishAll = ({
2870
2967
  locale: query?.plugins?.i18n?.locale
2871
2968
  },
2872
2969
  {
2873
- skip: selectedEntries.length === 0
2970
+ skip: !enableDraftRelationsCount
2874
2971
  }
2875
2972
  );
2876
2973
  React__namespace.useEffect(() => {
@@ -2949,16 +3046,30 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2949
3046
  )
2950
3047
  );
2951
3048
  } else {
2952
- messages.push(...formatErrorMessages(value, currentKey, formatMessage));
3049
+ messages.push(
3050
+ ...formatErrorMessages(
3051
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3052
+ value,
3053
+ currentKey,
3054
+ formatMessage
3055
+ )
3056
+ );
2953
3057
  }
3058
+ } else {
3059
+ messages.push(
3060
+ formatMessage(
3061
+ {
3062
+ id: `${value}.withField`,
3063
+ defaultMessage: value
3064
+ },
3065
+ { field: currentKey }
3066
+ )
3067
+ );
2954
3068
  }
2955
3069
  });
2956
3070
  return messages;
2957
3071
  };
2958
- const EntryValidationText = ({
2959
- validationErrors,
2960
- isPublished = false
2961
- }) => {
3072
+ const EntryValidationText = ({ validationErrors, status }) => {
2962
3073
  const { formatMessage } = reactIntl.useIntl();
2963
3074
  if (validationErrors) {
2964
3075
  const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
@@ -2969,7 +3080,7 @@ const EntryValidationText = ({
2969
3080
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
2970
3081
  ] });
2971
3082
  }
2972
- if (isPublished) {
3083
+ if (status === "published") {
2973
3084
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2974
3085
  /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
2975
3086
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
@@ -2978,6 +3089,15 @@ const EntryValidationText = ({
2978
3089
  }) })
2979
3090
  ] });
2980
3091
  }
3092
+ if (status === "modified") {
3093
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3094
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
3095
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3096
+ id: "content-manager.bulk-publish.modified",
3097
+ defaultMessage: "Ready to publish changes"
3098
+ }) })
3099
+ ] });
3100
+ }
2981
3101
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2982
3102
  /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
2983
3103
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
@@ -3029,10 +3149,10 @@ const SelectedEntriesTableContent = ({
3029
3149
  EntryValidationText,
3030
3150
  {
3031
3151
  validationErrors: validationErrors[row.documentId],
3032
- isPublished: row.status === "published"
3152
+ status: row.status
3033
3153
  }
3034
3154
  ) }),
3035
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3155
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
3036
3156
  designSystem.IconButton,
3037
3157
  {
3038
3158
  tag: reactRouterDom.Link,
@@ -3055,9 +3175,10 @@ const SelectedEntriesTableContent = ({
3055
3175
  ),
3056
3176
  target: "_blank",
3057
3177
  marginLeft: "auto",
3058
- children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3178
+ variant: "ghost",
3179
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
3059
3180
  }
3060
- ) })
3181
+ ) }) })
3061
3182
  ] }, row.id)) })
3062
3183
  ] });
3063
3184
  };
@@ -3094,7 +3215,13 @@ const SelectedEntriesModalContent = ({
3094
3215
  );
3095
3216
  const { rows, validationErrors } = React__namespace.useMemo(() => {
3096
3217
  if (data.length > 0 && schema) {
3097
- const validate = createYupSchema(schema.attributes, components);
3218
+ const validate = createYupSchema(
3219
+ schema.attributes,
3220
+ components,
3221
+ // Since this is the "Publish" action, the validation
3222
+ // schema must enforce the rules for published entities
3223
+ { status: "published" }
3224
+ );
3098
3225
  const validationErrors2 = {};
3099
3226
  const rows2 = data.map((entry) => {
3100
3227
  try {
@@ -3170,7 +3297,7 @@ const SelectedEntriesModalContent = ({
3170
3297
  );
3171
3298
  };
3172
3299
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3173
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalBody, { children: [
3300
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
3174
3301
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
3175
3302
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
3176
3303
  SelectedEntriesTableContent,
@@ -3182,27 +3309,24 @@ const SelectedEntriesModalContent = ({
3182
3309
  }
3183
3310
  ) })
3184
3311
  ] }),
3185
- /* @__PURE__ */ jsxRuntime.jsx(
3186
- designSystem.ModalFooter,
3187
- {
3188
- startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3189
- id: "app.components.Button.cancel",
3190
- defaultMessage: "Cancel"
3191
- }) }),
3192
- endActions: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3193
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3194
- /* @__PURE__ */ jsxRuntime.jsx(
3195
- designSystem.Button,
3196
- {
3197
- onClick: toggleDialog,
3198
- disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3199
- loading: isSubmittingForm,
3200
- children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3201
- }
3202
- )
3203
- ] })
3204
- }
3205
- ),
3312
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3313
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3314
+ id: "app.components.Button.cancel",
3315
+ defaultMessage: "Cancel"
3316
+ }) }),
3317
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3318
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3319
+ /* @__PURE__ */ jsxRuntime.jsx(
3320
+ designSystem.Button,
3321
+ {
3322
+ onClick: toggleDialog,
3323
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3324
+ loading: isSubmittingForm,
3325
+ children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3326
+ }
3327
+ )
3328
+ ] })
3329
+ ] }),
3206
3330
  /* @__PURE__ */ jsxRuntime.jsx(
3207
3331
  ConfirmDialogPublishAll,
3208
3332
  {
@@ -3267,143 +3391,10 @@ const BulkActionsRenderer = () => {
3267
3391
  documents: selectedRows
3268
3392
  },
3269
3393
  descriptions: plugins["content-manager"].apis.getBulkActions(),
3270
- children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(BulkActionAction, { ...action }, action.id))
3394
+ children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...action }, action.id))
3271
3395
  }
3272
3396
  ) });
3273
3397
  };
3274
- const BulkActionAction = (action) => {
3275
- const [dialogId, setDialogId] = React__namespace.useState(null);
3276
- const { toggleNotification } = strapiAdmin.useNotification();
3277
- const handleClick = (action2) => (e) => {
3278
- const { onClick, dialog, id } = action2;
3279
- if (onClick) {
3280
- onClick(e);
3281
- }
3282
- if (dialog) {
3283
- switch (dialog.type) {
3284
- case "notification":
3285
- toggleNotification({
3286
- title: dialog.title,
3287
- message: dialog.content,
3288
- type: dialog.status,
3289
- timeout: dialog.timeout,
3290
- onClose: dialog.onClose
3291
- });
3292
- break;
3293
- case "dialog":
3294
- case "modal": {
3295
- e.preventDefault();
3296
- setDialogId(id);
3297
- }
3298
- }
3299
- }
3300
- };
3301
- const handleClose = () => {
3302
- setDialogId(null);
3303
- if (action.dialog?.type === "modal" && action.dialog?.onClose) {
3304
- action.dialog.onClose();
3305
- }
3306
- };
3307
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3308
- /* @__PURE__ */ jsxRuntime.jsx(
3309
- designSystem.Button,
3310
- {
3311
- disabled: action.disabled,
3312
- startIcon: action.icon,
3313
- variant: action.variant,
3314
- onClick: handleClick(action),
3315
- children: action.label
3316
- }
3317
- ),
3318
- action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
3319
- BulkActionConfirmDialog,
3320
- {
3321
- ...action.dialog,
3322
- variant: action.variant,
3323
- isOpen: dialogId === action.id,
3324
- onClose: handleClose
3325
- }
3326
- ) : null,
3327
- action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
3328
- BulkActionModal,
3329
- {
3330
- ...action.dialog,
3331
- onModalClose: handleClose,
3332
- isOpen: dialogId === action.id
3333
- }
3334
- ) : null
3335
- ] });
3336
- };
3337
- const BulkActionConfirmDialog = ({
3338
- onClose,
3339
- onCancel,
3340
- onConfirm,
3341
- title,
3342
- content,
3343
- confirmButton,
3344
- isOpen,
3345
- variant = "secondary"
3346
- }) => {
3347
- const { formatMessage } = reactIntl.useIntl();
3348
- const handleClose = async () => {
3349
- if (onCancel) {
3350
- await onCancel();
3351
- }
3352
- onClose();
3353
- };
3354
- const handleConfirm = async () => {
3355
- if (onConfirm) {
3356
- await onConfirm();
3357
- }
3358
- onClose();
3359
- };
3360
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog, { isOpen, title, onClose: handleClose, children: [
3361
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.DialogBody, { icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, {}), children: content }),
3362
- /* @__PURE__ */ jsxRuntime.jsx(
3363
- designSystem.DialogFooter,
3364
- {
3365
- startAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", children: formatMessage({
3366
- id: "app.components.Button.cancel",
3367
- defaultMessage: "Cancel"
3368
- }) }),
3369
- endAction: /* @__PURE__ */ jsxRuntime.jsx(
3370
- designSystem.Button,
3371
- {
3372
- onClick: handleConfirm,
3373
- variant: variant === "danger-light" ? variant : "secondary",
3374
- startIcon: variant === "danger-light" ? /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}) : /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
3375
- children: confirmButton ? confirmButton : formatMessage({
3376
- id: "app.components.Button.confirm",
3377
- defaultMessage: "Confirm"
3378
- })
3379
- }
3380
- )
3381
- }
3382
- )
3383
- ] });
3384
- };
3385
- const BulkActionModal = ({
3386
- isOpen,
3387
- title,
3388
- onClose,
3389
- content: Content,
3390
- onModalClose
3391
- }) => {
3392
- const id = React__namespace.useId();
3393
- if (!isOpen) {
3394
- return null;
3395
- }
3396
- const handleClose = () => {
3397
- if (onClose) {
3398
- onClose();
3399
- }
3400
- onModalClose();
3401
- };
3402
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { borderRadius: "4px", overflow: "hidden", onClose: handleClose, labelledBy: id, children: [
3403
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: "neutral800", tag: "h2", id, children: title }) }),
3404
- /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose })
3405
- ] });
3406
- };
3407
3398
  const DeleteAction = ({ documents, model }) => {
3408
3399
  const { formatMessage } = reactIntl.useIntl();
3409
3400
  const { schema: contentType } = useDoc();
@@ -3436,6 +3427,7 @@ const DeleteAction = ({ documents, model }) => {
3436
3427
  defaultMessage: "Confirmation"
3437
3428
  }),
3438
3429
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3430
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3439
3431
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3440
3432
  id: "popUpWarning.bodyMessage.contentType.delete.all",
3441
3433
  defaultMessage: "Are you sure you want to delete these entries?"
@@ -3472,7 +3464,7 @@ const UnpublishAction = ({ documents, model }) => {
3472
3464
  selectRow([]);
3473
3465
  }
3474
3466
  };
3475
- const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published");
3467
+ const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3476
3468
  if (!showUnpublishButton)
3477
3469
  return null;
3478
3470
  return {
@@ -3485,6 +3477,7 @@ const UnpublishAction = ({ documents, model }) => {
3485
3477
  defaultMessage: "Confirmation"
3486
3478
  }),
3487
3479
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3480
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3488
3481
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3489
3482
  id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3490
3483
  defaultMessage: "Are you sure you want to unpublish these entries?"
@@ -3578,7 +3571,7 @@ const TableActions = ({ document }) => {
3578
3571
  strapiAdmin.DescriptionComponentRenderer,
3579
3572
  {
3580
3573
  props,
3581
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3574
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
3582
3575
  children: (actions2) => {
3583
3576
  const tableRowActions = actions2.filter((action) => {
3584
3577
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3689,7 +3682,7 @@ const CloneAction = ({ model, documentId }) => {
3689
3682
  }),
3690
3683
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3691
3684
  footer: ({ onClose }) => {
3692
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3685
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3693
3686
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3694
3687
  id: "cancel",
3695
3688
  defaultMessage: "Cancel"
@@ -3730,8 +3723,7 @@ class ContentManagerPlugin {
3730
3723
  documentActions = [
3731
3724
  ...DEFAULT_ACTIONS,
3732
3725
  ...DEFAULT_TABLE_ROW_ACTIONS,
3733
- ...DEFAULT_HEADER_ACTIONS,
3734
- HistoryAction
3726
+ ...DEFAULT_HEADER_ACTIONS
3735
3727
  ];
3736
3728
  editViewSidePanels = [ActionsPanel];
3737
3729
  headerActions = [];
@@ -3820,6 +3812,52 @@ const getPrintableType = (value) => {
3820
3812
  }
3821
3813
  return nativeType;
3822
3814
  };
3815
+ const HistoryAction = ({ model, document }) => {
3816
+ const { formatMessage } = reactIntl.useIntl();
3817
+ const [{ query }] = strapiAdmin.useQueryParams();
3818
+ const navigate = reactRouterDom.useNavigate();
3819
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3820
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3821
+ return null;
3822
+ }
3823
+ return {
3824
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3825
+ label: formatMessage({
3826
+ id: "content-manager.history.document-action",
3827
+ defaultMessage: "Content History"
3828
+ }),
3829
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3830
+ disabled: (
3831
+ /**
3832
+ * The user is creating a new document.
3833
+ * It hasn't been saved yet, so there's no history to go to
3834
+ */
3835
+ !document || /**
3836
+ * The document has been created but the current dimension has never been saved.
3837
+ * For example, the user is creating a new locale in an existing document,
3838
+ * so there's no history for the document in that locale
3839
+ */
3840
+ !document.id || /**
3841
+ * History is only available for content types created by the user.
3842
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3843
+ * which start with `admin::` or `plugin::`
3844
+ */
3845
+ !model.startsWith("api::")
3846
+ ),
3847
+ position: "header"
3848
+ };
3849
+ };
3850
+ HistoryAction.type = "history";
3851
+ const historyAdmin = {
3852
+ bootstrap(app) {
3853
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3854
+ addDocumentAction((actions2) => {
3855
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3856
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3857
+ return actions2;
3858
+ });
3859
+ }
3860
+ };
3823
3861
  const initialState = {
3824
3862
  collectionTypeLinks: [],
3825
3863
  components: [],
@@ -3870,15 +3908,29 @@ const index = {
3870
3908
  defaultMessage: "Content Manager"
3871
3909
  },
3872
3910
  permissions: [],
3873
- Component: () => Promise.resolve().then(() => require("./layout-b91XRlD2.js")).then((mod) => ({ default: mod.Layout })),
3874
3911
  position: 1
3875
3912
  });
3913
+ app.router.addRoute({
3914
+ path: "content-manager/*",
3915
+ lazy: async () => {
3916
+ const { Layout } = await Promise.resolve().then(() => require("./layout-B4XAqu1v.js"));
3917
+ return {
3918
+ Component: Layout
3919
+ };
3920
+ },
3921
+ children: routes
3922
+ });
3876
3923
  app.registerPlugin(cm.config);
3877
3924
  },
3925
+ bootstrap(app) {
3926
+ if (typeof historyAdmin.bootstrap === "function") {
3927
+ historyAdmin.bootstrap(app);
3928
+ }
3929
+ },
3878
3930
  async registerTrads({ locales }) {
3879
3931
  const importedTrads = await Promise.all(
3880
3932
  locales.map((locale) => {
3881
- 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-BN1bvFK7.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 }) => {
3933
+ 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-Cf41pH5f.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 }) => {
3882
3934
  return {
3883
3935
  data: prefixPluginTranslations(data, PLUGIN_ID),
3884
3936
  locale
@@ -3896,6 +3948,7 @@ const index = {
3896
3948
  };
3897
3949
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3898
3950
  exports.BulkActionsRenderer = BulkActionsRenderer;
3951
+ exports.CLONE_PATH = CLONE_PATH;
3899
3952
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3900
3953
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3901
3954
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3922,7 +3975,6 @@ exports.getDisplayName = getDisplayName;
3922
3975
  exports.getMainField = getMainField;
3923
3976
  exports.getTranslation = getTranslation;
3924
3977
  exports.index = index;
3925
- exports.routes = routes;
3926
3978
  exports.setInitialData = setInitialData;
3927
3979
  exports.useContentTypeSchema = useContentTypeSchema;
3928
3980
  exports.useDoc = useDoc;
@@ -3936,4 +3988,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3936
3988
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3937
3989
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3938
3990
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3939
- //# sourceMappingURL=index-DzN3kBgx.js.map
3991
+ //# sourceMappingURL=index-CQos-KS0.js.map