@strapi/content-manager 0.0.0-experimental.d954d57341a6623992a0d211daaec8e245c3517d → 0.0.0-experimental.da85533897155e719d784f0271223c866d2f69ab

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 (117) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-gdUj_t-O.mjs → ComponentConfigurationPage-9lRmRdIr.mjs} +3 -3
  3. package/dist/_chunks/{ComponentConfigurationPage-gdUj_t-O.mjs.map → ComponentConfigurationPage-9lRmRdIr.mjs.map} +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-WRPUXGd6.js → ComponentConfigurationPage-DyDkPajU.js} +3 -3
  5. package/dist/_chunks/{ComponentConfigurationPage-WRPUXGd6.js.map → ComponentConfigurationPage-DyDkPajU.js.map} +1 -1
  6. package/dist/_chunks/{EditConfigurationPage-BwuIPOJG.mjs → EditConfigurationPage-Bk893vVY.mjs} +3 -3
  7. package/dist/_chunks/{EditConfigurationPage-BwuIPOJG.mjs.map → EditConfigurationPage-Bk893vVY.mjs.map} +1 -1
  8. package/dist/_chunks/{EditConfigurationPage-C1vjMBgy.js → EditConfigurationPage-DValmA0m.js} +3 -3
  9. package/dist/_chunks/{EditConfigurationPage-C1vjMBgy.js.map → EditConfigurationPage-DValmA0m.js.map} +1 -1
  10. package/dist/_chunks/{EditViewPage-0MiFkXa8.mjs → EditViewPage-DiNFdFqP.mjs} +19 -8
  11. package/dist/_chunks/EditViewPage-DiNFdFqP.mjs.map +1 -0
  12. package/dist/_chunks/{EditViewPage-DbcGfyqK.js → EditViewPage-Dk7Eaft4.js} +19 -8
  13. package/dist/_chunks/EditViewPage-Dk7Eaft4.js.map +1 -0
  14. package/dist/_chunks/{Field-BG1xu38N.js → Field-DH2OaqUP.js} +458 -128
  15. package/dist/_chunks/Field-DH2OaqUP.js.map +1 -0
  16. package/dist/_chunks/{Field-BDMSCcy5.mjs → Field-Dv_HTFTa.mjs} +460 -130
  17. package/dist/_chunks/Field-Dv_HTFTa.mjs.map +1 -0
  18. package/dist/_chunks/{Form-9BnFyUjy.js → Form-B_dUDizM.js} +26 -12
  19. package/dist/_chunks/Form-B_dUDizM.js.map +1 -0
  20. package/dist/_chunks/{Form-CPVWavB8.mjs → Form-Dy6P4HgH.mjs} +26 -12
  21. package/dist/_chunks/Form-Dy6P4HgH.mjs.map +1 -0
  22. package/dist/_chunks/{History-BWWxLt2Z.js → History-BT4w83Oa.js} +44 -19
  23. package/dist/_chunks/History-BT4w83Oa.js.map +1 -0
  24. package/dist/_chunks/{History-BVpd8LP3.mjs → History-DrwsD1Vc.mjs} +44 -19
  25. package/dist/_chunks/History-DrwsD1Vc.mjs.map +1 -0
  26. package/dist/_chunks/{ListConfigurationPage-DozVMKcR.mjs → ListConfigurationPage-BxIP0jRy.mjs} +20 -8
  27. package/dist/_chunks/ListConfigurationPage-BxIP0jRy.mjs.map +1 -0
  28. package/dist/_chunks/{ListConfigurationPage-6swzjdAZ.js → ListConfigurationPage-CuYrMcW3.js} +20 -8
  29. package/dist/_chunks/ListConfigurationPage-CuYrMcW3.js.map +1 -0
  30. package/dist/_chunks/{ListViewPage-Ds0ulgfG.mjs → ListViewPage-5a1vw-OK.mjs} +40 -34
  31. package/dist/_chunks/ListViewPage-5a1vw-OK.mjs.map +1 -0
  32. package/dist/_chunks/{ListViewPage-BlzfjS2Q.js → ListViewPage-BvpwNur7.js} +38 -32
  33. package/dist/_chunks/ListViewPage-BvpwNur7.js.map +1 -0
  34. package/dist/_chunks/{NoContentTypePage-BH11kaKt.mjs → NoContentTypePage-Bm6tRcd3.mjs} +2 -2
  35. package/dist/_chunks/{NoContentTypePage-BH11kaKt.mjs.map → NoContentTypePage-Bm6tRcd3.mjs.map} +1 -1
  36. package/dist/_chunks/{NoContentTypePage-D2nCCWEl.js → NoContentTypePage-UqEiWKkM.js} +2 -2
  37. package/dist/_chunks/{NoContentTypePage-D2nCCWEl.js.map → NoContentTypePage-UqEiWKkM.js.map} +1 -1
  38. package/dist/_chunks/{NoPermissionsPage-BT2Tn0D_.mjs → NoPermissionsPage-BHPqn_tQ.mjs} +2 -2
  39. package/dist/_chunks/{NoPermissionsPage-BT2Tn0D_.mjs.map → NoPermissionsPage-BHPqn_tQ.mjs.map} +1 -1
  40. package/dist/_chunks/{NoPermissionsPage-DN_JlsU2.js → NoPermissionsPage-C_vGRo8Q.js} +2 -2
  41. package/dist/_chunks/{NoPermissionsPage-DN_JlsU2.js.map → NoPermissionsPage-C_vGRo8Q.js.map} +1 -1
  42. package/dist/_chunks/{Relations-Dnag3fhV.mjs → Relations-C7fPyh5P.mjs} +4 -4
  43. package/dist/_chunks/Relations-C7fPyh5P.mjs.map +1 -0
  44. package/dist/_chunks/{Relations-CcgFTcWo.js → Relations-CznVF6LS.js} +4 -4
  45. package/dist/_chunks/Relations-CznVF6LS.js.map +1 -0
  46. package/dist/_chunks/{en-Ux26r5pl.mjs → en-CbaIuYoB.mjs} +6 -5
  47. package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-CbaIuYoB.mjs.map} +1 -1
  48. package/dist/_chunks/{en-fbKQxLGn.js → en-otD_UBJi.js} +6 -5
  49. package/dist/_chunks/{en-fbKQxLGn.js.map → en-otD_UBJi.js.map} +1 -1
  50. package/dist/_chunks/{index-JNNNKUHs.mjs → index-BJ6uTqLL.mjs} +395 -179
  51. package/dist/_chunks/index-BJ6uTqLL.mjs.map +1 -0
  52. package/dist/_chunks/{index-CWpLBSt0.js → index-D9UmmBcM.js} +388 -172
  53. package/dist/_chunks/index-D9UmmBcM.js.map +1 -0
  54. package/dist/_chunks/{layout--iHdZzRk.js → layout-kfu5Wtix.js} +23 -11
  55. package/dist/_chunks/layout-kfu5Wtix.js.map +1 -0
  56. package/dist/_chunks/{layout-DC503LnF.mjs → layout-uomiIGbG.mjs} +25 -13
  57. package/dist/_chunks/layout-uomiIGbG.mjs.map +1 -0
  58. package/dist/_chunks/{relations-BbHizA5K.js → relations-DKENrxko.js} +2 -2
  59. package/dist/_chunks/{relations-BbHizA5K.js.map → relations-DKENrxko.js.map} +1 -1
  60. package/dist/_chunks/{relations-CTje5t-a.mjs → relations-DiDufGSA.mjs} +2 -2
  61. package/dist/_chunks/{relations-CTje5t-a.mjs.map → relations-DiDufGSA.mjs.map} +1 -1
  62. package/dist/admin/index.js +1 -1
  63. package/dist/admin/index.mjs +1 -1
  64. package/dist/admin/src/history/index.d.ts +3 -0
  65. package/dist/admin/src/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/BlocksInput/utils/constants.d.ts +4 -0
  69. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  70. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  71. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  72. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  73. package/dist/admin/src/services/api.d.ts +1 -1
  74. package/dist/admin/src/services/components.d.ts +2 -2
  75. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  76. package/dist/admin/src/services/documents.d.ts +16 -16
  77. package/dist/admin/src/services/init.d.ts +1 -1
  78. package/dist/admin/src/services/relations.d.ts +2 -2
  79. package/dist/admin/src/services/uid.d.ts +3 -3
  80. package/dist/admin/src/utils/validation.d.ts +4 -1
  81. package/dist/server/index.js +178 -109
  82. package/dist/server/index.js.map +1 -1
  83. package/dist/server/index.mjs +179 -110
  84. package/dist/server/index.mjs.map +1 -1
  85. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  86. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  87. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  88. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  89. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  90. package/dist/server/src/history/services/history.d.ts.map +1 -1
  91. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  92. package/dist/server/src/history/services/utils.d.ts +2 -1
  93. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  94. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  95. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  96. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  97. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  98. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  99. package/package.json +8 -8
  100. package/dist/_chunks/EditViewPage-0MiFkXa8.mjs.map +0 -1
  101. package/dist/_chunks/EditViewPage-DbcGfyqK.js.map +0 -1
  102. package/dist/_chunks/Field-BDMSCcy5.mjs.map +0 -1
  103. package/dist/_chunks/Field-BG1xu38N.js.map +0 -1
  104. package/dist/_chunks/Form-9BnFyUjy.js.map +0 -1
  105. package/dist/_chunks/Form-CPVWavB8.mjs.map +0 -1
  106. package/dist/_chunks/History-BVpd8LP3.mjs.map +0 -1
  107. package/dist/_chunks/History-BWWxLt2Z.js.map +0 -1
  108. package/dist/_chunks/ListConfigurationPage-6swzjdAZ.js.map +0 -1
  109. package/dist/_chunks/ListConfigurationPage-DozVMKcR.mjs.map +0 -1
  110. package/dist/_chunks/ListViewPage-BlzfjS2Q.js.map +0 -1
  111. package/dist/_chunks/ListViewPage-Ds0ulgfG.mjs.map +0 -1
  112. package/dist/_chunks/Relations-CcgFTcWo.js.map +0 -1
  113. package/dist/_chunks/Relations-Dnag3fhV.mjs.map +0 -1
  114. package/dist/_chunks/index-CWpLBSt0.js.map +0 -1
  115. package/dist/_chunks/index-JNNNKUHs.mjs.map +0 -1
  116. package/dist/_chunks/layout--iHdZzRk.js.map +0 -1
  117. package/dist/_chunks/layout-DC503LnF.mjs.map +0 -1
@@ -2,15 +2,15 @@
2
2
  const Icons = require("@strapi/icons");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const strapiAdmin = require("@strapi/admin/strapi-admin");
5
- const qs = require("qs");
6
- const reactIntl = require("react-intl");
7
- const reactRouterDom = require("react-router-dom");
8
5
  const React = require("react");
9
6
  const designSystem = require("@strapi/design-system");
7
+ const reactIntl = require("react-intl");
8
+ const reactRouterDom = require("react-router-dom");
10
9
  const styledComponents = require("styled-components");
11
10
  const yup = require("yup");
12
11
  const pipe = require("lodash/fp/pipe");
13
12
  const dateFns = require("date-fns");
13
+ const qs = require("qs");
14
14
  const toolkit = require("@reduxjs/toolkit");
15
15
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
16
16
  function _interopNamespace(e) {
@@ -70,42 +70,6 @@ const useInjectionZone = (area) => {
70
70
  const [page, position] = area.split(".");
71
71
  return contentManagerPlugin.getInjectedComponents(page, position);
72
72
  };
73
- const HistoryAction = ({ model, document }) => {
74
- const { formatMessage } = reactIntl.useIntl();
75
- const [{ query }] = strapiAdmin.useQueryParams();
76
- const navigate = reactRouterDom.useNavigate();
77
- const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
78
- if (!window.strapi.features.isEnabled("cms-content-history")) {
79
- return null;
80
- }
81
- return {
82
- icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
83
- label: formatMessage({
84
- id: "content-manager.history.document-action",
85
- defaultMessage: "Content History"
86
- }),
87
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
88
- disabled: (
89
- /**
90
- * The user is creating a new document.
91
- * It hasn't been saved yet, so there's no history to go to
92
- */
93
- !document || /**
94
- * The document has been created but the current dimension has never been saved.
95
- * For example, the user is creating a new locale in an existing document,
96
- * so there's no history for the document in that locale
97
- */
98
- !document.id || /**
99
- * History is only available for content types created by the user.
100
- * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
101
- * which start with `admin::` or `plugin::`
102
- */
103
- !model.startsWith("api::")
104
- ),
105
- position: "header"
106
- };
107
- };
108
- HistoryAction.type = "history";
109
73
  const ID = "id";
110
74
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
111
75
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -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) => {
@@ -1205,7 +1243,6 @@ const useDocumentActions = () => {
1205
1243
  sourceId
1206
1244
  });
1207
1245
  if ("error" in res) {
1208
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1209
1246
  return { error: res.error };
1210
1247
  }
1211
1248
  toggleNotification({
@@ -1224,7 +1261,7 @@ const useDocumentActions = () => {
1224
1261
  throw err;
1225
1262
  }
1226
1263
  },
1227
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1264
+ [autoCloneDocument, formatMessage, toggleNotification]
1228
1265
  );
1229
1266
  const [cloneDocument] = useCloneDocumentMutation();
1230
1267
  const clone = React__namespace.useCallback(
@@ -1250,6 +1287,7 @@ const useDocumentActions = () => {
1250
1287
  defaultMessage: "Cloned document"
1251
1288
  })
1252
1289
  });
1290
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1253
1291
  return res.data;
1254
1292
  } catch (err) {
1255
1293
  toggleNotification({
@@ -1260,7 +1298,7 @@ const useDocumentActions = () => {
1260
1298
  throw err;
1261
1299
  }
1262
1300
  },
1263
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1301
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1264
1302
  );
1265
1303
  const [getDoc] = useLazyGetDocumentQuery();
1266
1304
  const getDocument = React__namespace.useCallback(
@@ -1286,7 +1324,7 @@ const useDocumentActions = () => {
1286
1324
  };
1287
1325
  };
1288
1326
  const ProtectedHistoryPage = React.lazy(
1289
- () => Promise.resolve().then(() => require("./History-BWWxLt2Z.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1327
+ () => Promise.resolve().then(() => require("./History-BT4w83Oa.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1290
1328
  );
1291
1329
  const routes$1 = [
1292
1330
  {
@@ -1299,31 +1337,31 @@ const routes$1 = [
1299
1337
  }
1300
1338
  ];
1301
1339
  const ProtectedEditViewPage = React.lazy(
1302
- () => Promise.resolve().then(() => require("./EditViewPage-DbcGfyqK.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1340
+ () => Promise.resolve().then(() => require("./EditViewPage-Dk7Eaft4.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1303
1341
  );
1304
1342
  const ProtectedListViewPage = React.lazy(
1305
- () => Promise.resolve().then(() => require("./ListViewPage-BlzfjS2Q.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1343
+ () => Promise.resolve().then(() => require("./ListViewPage-BvpwNur7.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1306
1344
  );
1307
1345
  const ProtectedListConfiguration = React.lazy(
1308
- () => Promise.resolve().then(() => require("./ListConfigurationPage-6swzjdAZ.js")).then((mod) => ({
1346
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-CuYrMcW3.js")).then((mod) => ({
1309
1347
  default: mod.ProtectedListConfiguration
1310
1348
  }))
1311
1349
  );
1312
1350
  const ProtectedEditConfigurationPage = React.lazy(
1313
- () => Promise.resolve().then(() => require("./EditConfigurationPage-C1vjMBgy.js")).then((mod) => ({
1351
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-DValmA0m.js")).then((mod) => ({
1314
1352
  default: mod.ProtectedEditConfigurationPage
1315
1353
  }))
1316
1354
  );
1317
1355
  const ProtectedComponentConfigurationPage = React.lazy(
1318
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-WRPUXGd6.js")).then((mod) => ({
1356
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-DyDkPajU.js")).then((mod) => ({
1319
1357
  default: mod.ProtectedComponentConfigurationPage
1320
1358
  }))
1321
1359
  );
1322
1360
  const NoPermissions = React.lazy(
1323
- () => Promise.resolve().then(() => require("./NoPermissionsPage-DN_JlsU2.js")).then((mod) => ({ default: mod.NoPermissions }))
1361
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-C_vGRo8Q.js")).then((mod) => ({ default: mod.NoPermissions }))
1324
1362
  );
1325
1363
  const NoContentType = React.lazy(
1326
- () => Promise.resolve().then(() => require("./NoContentTypePage-D2nCCWEl.js")).then((mod) => ({ default: mod.NoContentType }))
1364
+ () => Promise.resolve().then(() => require("./NoContentTypePage-UqEiWKkM.js")).then((mod) => ({ default: mod.NoContentType }))
1327
1365
  );
1328
1366
  const CollectionTypePages = () => {
1329
1367
  const { collectionType } = reactRouterDom.useParams();
@@ -1437,12 +1475,14 @@ const DocumentActionButton = (action) => {
1437
1475
  /* @__PURE__ */ jsxRuntime.jsx(
1438
1476
  designSystem.Button,
1439
1477
  {
1440
- flex: 1,
1478
+ flex: "auto",
1441
1479
  startIcon: action.icon,
1442
1480
  disabled: action.disabled,
1443
1481
  onClick: handleClick(action),
1444
1482
  justifyContent: "center",
1445
1483
  variant: action.variant || "default",
1484
+ paddingTop: "7px",
1485
+ paddingBottom: "7px",
1446
1486
  children: action.label
1447
1487
  }
1448
1488
  ),
@@ -1450,7 +1490,7 @@ const DocumentActionButton = (action) => {
1450
1490
  DocumentActionConfirmDialog,
1451
1491
  {
1452
1492
  ...action.dialog,
1453
- variant: action.variant,
1493
+ variant: action.dialog?.variant ?? action.variant,
1454
1494
  isOpen: dialogId === action.id,
1455
1495
  onClose: handleClose
1456
1496
  }
@@ -1507,9 +1547,9 @@ const DocumentActionsMenu = ({
1507
1547
  disabled: isDisabled,
1508
1548
  size: "S",
1509
1549
  endIcon: null,
1510
- paddingTop: "7px",
1511
- paddingLeft: "9px",
1512
- paddingRight: "9px",
1550
+ paddingTop: "4px",
1551
+ paddingLeft: "7px",
1552
+ paddingRight: "7px",
1513
1553
  variant,
1514
1554
  children: [
1515
1555
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
@@ -1529,10 +1569,25 @@ const DocumentActionsMenu = ({
1529
1569
  onSelect: handleClick(action),
1530
1570
  display: "block",
1531
1571
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1532
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1533
- action.icon,
1534
- action.label
1535
- ] }),
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
+ ),
1536
1591
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
1537
1592
  designSystem.Flex,
1538
1593
  {
@@ -1591,6 +1646,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1591
1646
  return "primary600";
1592
1647
  }
1593
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
+ };
1594
1661
  const DocumentActionConfirmDialog = ({
1595
1662
  onClose,
1596
1663
  onCancel,
@@ -1660,13 +1727,17 @@ const PublishAction$1 = ({
1660
1727
  const navigate = reactRouterDom.useNavigate();
1661
1728
  const { toggleNotification } = strapiAdmin.useNotification();
1662
1729
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
1730
+ const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
1663
1731
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
1664
1732
  const { formatMessage } = reactIntl.useIntl();
1665
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1666
- "PublishAction",
1667
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1668
- );
1733
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1669
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);
1670
1741
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1671
1742
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1672
1743
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1675,10 +1746,102 @@ const PublishAction$1 = ({
1675
1746
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1676
1747
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1677
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 (documentId && !isListView) {
1786
+ const fetchDraftRelationsCount = async () => {
1787
+ const { data, error } = await countDraftRelations({
1788
+ collectionType,
1789
+ model,
1790
+ documentId,
1791
+ params
1792
+ });
1793
+ if (error) {
1794
+ throw error;
1795
+ }
1796
+ if (data) {
1797
+ setServerCountOfDraftRelations(data.data);
1798
+ }
1799
+ };
1800
+ fetchDraftRelationsCount();
1801
+ }
1802
+ }, [isListView, documentId, countDraftRelations, collectionType, model, params]);
1678
1803
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1679
1804
  if (!schema?.options?.draftAndPublish) {
1680
1805
  return null;
1681
1806
  }
1807
+ const performPublish = async () => {
1808
+ setSubmitting(true);
1809
+ try {
1810
+ const { errors } = await validate();
1811
+ if (errors) {
1812
+ toggleNotification({
1813
+ type: "danger",
1814
+ message: formatMessage({
1815
+ id: "content-manager.validation.error",
1816
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1817
+ })
1818
+ });
1819
+ return;
1820
+ }
1821
+ const res = await publish(
1822
+ {
1823
+ collectionType,
1824
+ model,
1825
+ documentId,
1826
+ params
1827
+ },
1828
+ formValues
1829
+ );
1830
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
1831
+ navigate({
1832
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1833
+ search: rawQuery
1834
+ });
1835
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1836
+ setErrors(formatValidationErrors(res.error));
1837
+ }
1838
+ } finally {
1839
+ setSubmitting(false);
1840
+ }
1841
+ };
1842
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1843
+ const enableDraftRelationsCount = false;
1844
+ const hasDraftRelations = enableDraftRelationsCount;
1682
1845
  return {
1683
1846
  /**
1684
1847
  * Disabled when:
@@ -1688,49 +1851,36 @@ const PublishAction$1 = ({
1688
1851
  * - the document is already published & not modified
1689
1852
  * - the document is being created & not modified
1690
1853
  * - the user doesn't have the permission to publish
1691
- * - the user doesn't have the permission to create a new document
1692
- * - the user doesn't have the permission to update the document
1693
1854
  */
1694
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1855
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1695
1856
  label: formatMessage({
1696
1857
  id: "app.utils.publish",
1697
1858
  defaultMessage: "Publish"
1698
1859
  }),
1699
1860
  onClick: async () => {
1700
- setSubmitting(true);
1701
- try {
1702
- const { errors } = await validate();
1703
- if (errors) {
1704
- toggleNotification({
1705
- type: "danger",
1706
- message: formatMessage({
1707
- id: "content-manager.validation.error",
1708
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1709
- })
1710
- });
1711
- return;
1712
- }
1713
- const res = await publish(
1714
- {
1715
- collectionType,
1716
- model,
1717
- documentId,
1718
- params
1719
- },
1720
- formValues
1721
- );
1722
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1723
- navigate({
1724
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1725
- search: rawQuery
1726
- });
1727
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1728
- setErrors(formatValidationErrors(res.error));
1861
+ await performPublish();
1862
+ },
1863
+ dialog: hasDraftRelations ? {
1864
+ type: "dialog",
1865
+ variant: "danger",
1866
+ footer: null,
1867
+ title: formatMessage({
1868
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
1869
+ defaultMessage: "Confirmation"
1870
+ }),
1871
+ content: formatMessage(
1872
+ {
1873
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
1874
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
1875
+ },
1876
+ {
1877
+ count: totalDraftRelations
1729
1878
  }
1730
- } finally {
1731
- setSubmitting(false);
1879
+ ),
1880
+ onConfirm: async () => {
1881
+ await performPublish();
1732
1882
  }
1733
- }
1883
+ } : void 0
1734
1884
  };
1735
1885
  };
1736
1886
  PublishAction$1.type = "publish";
@@ -1746,10 +1896,6 @@ const UpdateAction = ({
1746
1896
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1747
1897
  const isCloning = cloneMatch !== null;
1748
1898
  const { formatMessage } = reactIntl.useIntl();
1749
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1750
- canCreate: canCreate2,
1751
- canUpdate: canUpdate2
1752
- }));
1753
1899
  const { create, update, clone } = useDocumentActions();
1754
1900
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1755
1901
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1766,10 +1912,8 @@ const UpdateAction = ({
1766
1912
  * - the form is submitting
1767
1913
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1768
1914
  * - the active tab is the published tab
1769
- * - the user doesn't have the permission to create a new document
1770
- * - the user doesn't have the permission to update the document
1771
1915
  */
1772
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
1916
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1773
1917
  label: formatMessage({
1774
1918
  id: "content-manager.containers.Edit.save",
1775
1919
  defaultMessage: "Save"
@@ -1777,16 +1921,18 @@ const UpdateAction = ({
1777
1921
  onClick: async () => {
1778
1922
  setSubmitting(true);
1779
1923
  try {
1780
- const { errors } = await validate();
1781
- if (errors) {
1782
- toggleNotification({
1783
- type: "danger",
1784
- message: formatMessage({
1785
- id: "content-manager.validation.error",
1786
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1787
- })
1788
- });
1789
- return;
1924
+ if (activeTab !== "draft") {
1925
+ const { errors } = await validate();
1926
+ if (errors) {
1927
+ toggleNotification({
1928
+ type: "danger",
1929
+ message: formatMessage({
1930
+ id: "content-manager.validation.error",
1931
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1932
+ })
1933
+ });
1934
+ return;
1935
+ }
1790
1936
  }
1791
1937
  if (isCloning) {
1792
1938
  const res = await clone(
@@ -1798,10 +1944,13 @@ const UpdateAction = ({
1798
1944
  document
1799
1945
  );
1800
1946
  if ("data" in res) {
1801
- navigate({
1802
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1803
- search: rawQuery
1804
- });
1947
+ navigate(
1948
+ {
1949
+ pathname: `../${res.data.documentId}`,
1950
+ search: rawQuery
1951
+ },
1952
+ { relative: "path" }
1953
+ );
1805
1954
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1806
1955
  setErrors(formatValidationErrors(res.error));
1807
1956
  }
@@ -1829,10 +1978,13 @@ const UpdateAction = ({
1829
1978
  document
1830
1979
  );
1831
1980
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1832
- navigate({
1833
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1834
- search: rawQuery
1835
- });
1981
+ navigate(
1982
+ {
1983
+ pathname: `../${res.data.documentId}`,
1984
+ search: rawQuery
1985
+ },
1986
+ { replace: true, relative: "path" }
1987
+ );
1836
1988
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1837
1989
  setErrors(formatValidationErrors(res.error));
1838
1990
  }
@@ -2078,23 +2230,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2078
2230
  id: "content-manager.containers.edit.title.new",
2079
2231
  defaultMessage: "Create an entry"
2080
2232
  }) : documentTitle;
2081
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2233
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2082
2234
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
2083
- /* @__PURE__ */ jsxRuntime.jsxs(
2084
- designSystem.Flex,
2085
- {
2086
- width: "100%",
2087
- justifyContent: "space-between",
2088
- paddingTop: 1,
2089
- gap: "80px",
2090
- alignItems: "flex-start",
2091
- children: [
2092
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2093
- /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2094
- ]
2095
- }
2096
- ),
2097
- status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2235
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2236
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2237
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2238
+ ] }),
2239
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2098
2240
  ] });
2099
2241
  };
2100
2242
  const HeaderToolbar = () => {
@@ -2785,7 +2927,7 @@ const ConfirmBulkActionDialog = ({
2785
2927
  endAction
2786
2928
  }) => {
2787
2929
  const { formatMessage } = reactIntl.useIntl();
2788
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2930
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2789
2931
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2790
2932
  id: "app.components.ConfirmDialog.title",
2791
2933
  defaultMessage: "Confirmation"
@@ -2816,6 +2958,7 @@ const ConfirmDialogPublishAll = ({
2816
2958
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2817
2959
  const { model, schema } = useDoc();
2818
2960
  const [{ query }] = strapiAdmin.useQueryParams();
2961
+ const enableDraftRelationsCount = false;
2819
2962
  const {
2820
2963
  data: countDraftRelations = 0,
2821
2964
  isLoading,
@@ -2827,7 +2970,7 @@ const ConfirmDialogPublishAll = ({
2827
2970
  locale: query?.plugins?.i18n?.locale
2828
2971
  },
2829
2972
  {
2830
- skip: selectedEntries.length === 0
2973
+ skip: !enableDraftRelationsCount
2831
2974
  }
2832
2975
  );
2833
2976
  React__namespace.useEffect(() => {
@@ -2906,7 +3049,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2906
3049
  )
2907
3050
  );
2908
3051
  } else {
2909
- messages.push(...formatErrorMessages(value, currentKey, formatMessage));
3052
+ messages.push(
3053
+ ...formatErrorMessages(
3054
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3055
+ value,
3056
+ currentKey,
3057
+ formatMessage
3058
+ )
3059
+ );
2910
3060
  }
2911
3061
  } else {
2912
3062
  messages.push(
@@ -3005,7 +3155,7 @@ const SelectedEntriesTableContent = ({
3005
3155
  status: row.status
3006
3156
  }
3007
3157
  ) }),
3008
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3158
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
3009
3159
  designSystem.IconButton,
3010
3160
  {
3011
3161
  tag: reactRouterDom.Link,
@@ -3028,9 +3178,10 @@ const SelectedEntriesTableContent = ({
3028
3178
  ),
3029
3179
  target: "_blank",
3030
3180
  marginLeft: "auto",
3031
- children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3181
+ variant: "ghost",
3182
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
3032
3183
  }
3033
- ) })
3184
+ ) }) })
3034
3185
  ] }, row.id)) })
3035
3186
  ] });
3036
3187
  };
@@ -3067,7 +3218,13 @@ const SelectedEntriesModalContent = ({
3067
3218
  );
3068
3219
  const { rows, validationErrors } = React__namespace.useMemo(() => {
3069
3220
  if (data.length > 0 && schema) {
3070
- const validate = createYupSchema(schema.attributes, components);
3221
+ const validate = createYupSchema(
3222
+ schema.attributes,
3223
+ components,
3224
+ // Since this is the "Publish" action, the validation
3225
+ // schema must enforce the rules for published entities
3226
+ { status: "published" }
3227
+ );
3071
3228
  const validationErrors2 = {};
3072
3229
  const rows2 = data.map((entry) => {
3073
3230
  try {
@@ -3417,7 +3574,7 @@ const TableActions = ({ document }) => {
3417
3574
  strapiAdmin.DescriptionComponentRenderer,
3418
3575
  {
3419
3576
  props,
3420
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3577
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
3421
3578
  children: (actions2) => {
3422
3579
  const tableRowActions = actions2.filter((action) => {
3423
3580
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3528,7 +3685,7 @@ const CloneAction = ({ model, documentId }) => {
3528
3685
  }),
3529
3686
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3530
3687
  footer: ({ onClose }) => {
3531
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3688
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3532
3689
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3533
3690
  id: "cancel",
3534
3691
  defaultMessage: "Cancel"
@@ -3569,8 +3726,7 @@ class ContentManagerPlugin {
3569
3726
  documentActions = [
3570
3727
  ...DEFAULT_ACTIONS,
3571
3728
  ...DEFAULT_TABLE_ROW_ACTIONS,
3572
- ...DEFAULT_HEADER_ACTIONS,
3573
- HistoryAction
3729
+ ...DEFAULT_HEADER_ACTIONS
3574
3730
  ];
3575
3731
  editViewSidePanels = [ActionsPanel];
3576
3732
  headerActions = [];
@@ -3659,6 +3815,52 @@ const getPrintableType = (value) => {
3659
3815
  }
3660
3816
  return nativeType;
3661
3817
  };
3818
+ const HistoryAction = ({ model, document }) => {
3819
+ const { formatMessage } = reactIntl.useIntl();
3820
+ const [{ query }] = strapiAdmin.useQueryParams();
3821
+ const navigate = reactRouterDom.useNavigate();
3822
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3823
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3824
+ return null;
3825
+ }
3826
+ return {
3827
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3828
+ label: formatMessage({
3829
+ id: "content-manager.history.document-action",
3830
+ defaultMessage: "Content History"
3831
+ }),
3832
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3833
+ disabled: (
3834
+ /**
3835
+ * The user is creating a new document.
3836
+ * It hasn't been saved yet, so there's no history to go to
3837
+ */
3838
+ !document || /**
3839
+ * The document has been created but the current dimension has never been saved.
3840
+ * For example, the user is creating a new locale in an existing document,
3841
+ * so there's no history for the document in that locale
3842
+ */
3843
+ !document.id || /**
3844
+ * History is only available for content types created by the user.
3845
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3846
+ * which start with `admin::` or `plugin::`
3847
+ */
3848
+ !model.startsWith("api::")
3849
+ ),
3850
+ position: "header"
3851
+ };
3852
+ };
3853
+ HistoryAction.type = "history";
3854
+ const historyAdmin = {
3855
+ bootstrap(app) {
3856
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3857
+ addDocumentAction((actions2) => {
3858
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3859
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3860
+ return actions2;
3861
+ });
3862
+ }
3863
+ };
3662
3864
  const initialState = {
3663
3865
  collectionTypeLinks: [],
3664
3866
  components: [],
@@ -3709,15 +3911,29 @@ const index = {
3709
3911
  defaultMessage: "Content Manager"
3710
3912
  },
3711
3913
  permissions: [],
3712
- Component: () => Promise.resolve().then(() => require("./layout--iHdZzRk.js")).then((mod) => ({ default: mod.Layout })),
3713
3914
  position: 1
3714
3915
  });
3916
+ app.router.addRoute({
3917
+ path: "content-manager/*",
3918
+ lazy: async () => {
3919
+ const { Layout } = await Promise.resolve().then(() => require("./layout-kfu5Wtix.js"));
3920
+ return {
3921
+ Component: Layout
3922
+ };
3923
+ },
3924
+ children: routes
3925
+ });
3715
3926
  app.registerPlugin(cm.config);
3716
3927
  },
3928
+ bootstrap(app) {
3929
+ if (typeof historyAdmin.bootstrap === "function") {
3930
+ historyAdmin.bootstrap(app);
3931
+ }
3932
+ },
3717
3933
  async registerTrads({ locales }) {
3718
3934
  const importedTrads = await Promise.all(
3719
3935
  locales.map((locale) => {
3720
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-fbKQxLGn.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
3936
+ 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-otD_UBJi.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
3721
3937
  return {
3722
3938
  data: prefixPluginTranslations(data, PLUGIN_ID),
3723
3939
  locale
@@ -3735,6 +3951,7 @@ const index = {
3735
3951
  };
3736
3952
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3737
3953
  exports.BulkActionsRenderer = BulkActionsRenderer;
3954
+ exports.CLONE_PATH = CLONE_PATH;
3738
3955
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3739
3956
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3740
3957
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3761,7 +3978,6 @@ exports.getDisplayName = getDisplayName;
3761
3978
  exports.getMainField = getMainField;
3762
3979
  exports.getTranslation = getTranslation;
3763
3980
  exports.index = index;
3764
- exports.routes = routes;
3765
3981
  exports.setInitialData = setInitialData;
3766
3982
  exports.useContentTypeSchema = useContentTypeSchema;
3767
3983
  exports.useDoc = useDoc;
@@ -3775,4 +3991,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3775
3991
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3776
3992
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3777
3993
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3778
- //# sourceMappingURL=index-CWpLBSt0.js.map
3994
+ //# sourceMappingURL=index-D9UmmBcM.js.map