@strapi/content-manager 5.0.0-rc.0 → 5.0.0-rc.10

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 (106) hide show
  1. package/dist/_chunks/{ComponentConfigurationPage-DVY3LwHo.js → ComponentConfigurationPage-BEJqMzZA.js} +3 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-DVY3LwHo.js.map → ComponentConfigurationPage-BEJqMzZA.js.map} +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-Dy9BQQ2V.mjs → ComponentConfigurationPage-C1B5XNIM.mjs} +3 -3
  4. package/dist/_chunks/{ComponentConfigurationPage-Dy9BQQ2V.mjs.map → ComponentConfigurationPage-C1B5XNIM.mjs.map} +1 -1
  5. package/dist/_chunks/{EditConfigurationPage-DbR8mWH5.mjs → EditConfigurationPage-D2DPoQ3j.mjs} +3 -3
  6. package/dist/_chunks/{EditConfigurationPage-DbR8mWH5.mjs.map → EditConfigurationPage-D2DPoQ3j.mjs.map} +1 -1
  7. package/dist/_chunks/{EditConfigurationPage-b6V7YHfo.js → EditConfigurationPage-DOyPS5Tv.js} +3 -3
  8. package/dist/_chunks/{EditConfigurationPage-b6V7YHfo.js.map → EditConfigurationPage-DOyPS5Tv.js.map} +1 -1
  9. package/dist/_chunks/{EditViewPage-CPrukwtO.mjs → EditViewPage-Ymi21g_V.mjs} +19 -8
  10. package/dist/_chunks/EditViewPage-Ymi21g_V.mjs.map +1 -0
  11. package/dist/_chunks/{EditViewPage-DhttErmY.js → EditViewPage-fuASFJIx.js} +19 -8
  12. package/dist/_chunks/EditViewPage-fuASFJIx.js.map +1 -0
  13. package/dist/_chunks/{Field-DrgIgQPw.mjs → Field-BOo2Rz0Z.mjs} +106 -40
  14. package/dist/_chunks/Field-BOo2Rz0Z.mjs.map +1 -0
  15. package/dist/_chunks/{Field-CBRV4uan.js → Field-Ce4O31Zm.js} +104 -38
  16. package/dist/_chunks/Field-Ce4O31Zm.js.map +1 -0
  17. package/dist/_chunks/{Form-Bk3v7Frl.js → Form-CCGDm2PL.js} +22 -11
  18. package/dist/_chunks/Form-CCGDm2PL.js.map +1 -0
  19. package/dist/_chunks/{Form-Dxk4txLJ.mjs → Form-D2_h3W-h.mjs} +22 -11
  20. package/dist/_chunks/Form-D2_h3W-h.mjs.map +1 -0
  21. package/dist/_chunks/{History-xNH_9UuV.js → History-CARFXr5U.js} +21 -11
  22. package/dist/_chunks/History-CARFXr5U.js.map +1 -0
  23. package/dist/_chunks/{History-DSU-y4Hg.mjs → History-KY23tw1N.mjs} +21 -11
  24. package/dist/_chunks/History-KY23tw1N.mjs.map +1 -0
  25. package/dist/_chunks/{ListConfigurationPage-BWwZ-uMJ.mjs → ListConfigurationPage-BrwfEo-f.mjs} +14 -4
  26. package/dist/_chunks/ListConfigurationPage-BrwfEo-f.mjs.map +1 -0
  27. package/dist/_chunks/{ListConfigurationPage-BCPzXk5W.js → ListConfigurationPage-fZjkRyi9.js} +14 -4
  28. package/dist/_chunks/ListConfigurationPage-fZjkRyi9.js.map +1 -0
  29. package/dist/_chunks/{ListViewPage-ZIvstfvl.js → ListViewPage-CY6a70Y-.js} +9 -4
  30. package/dist/_chunks/ListViewPage-CY6a70Y-.js.map +1 -0
  31. package/dist/_chunks/{ListViewPage-D9UmehuA.mjs → ListViewPage-CjkCjT3z.mjs} +10 -5
  32. package/dist/_chunks/ListViewPage-CjkCjT3z.mjs.map +1 -0
  33. package/dist/_chunks/{NoContentTypePage-CstnyWv2.mjs → NoContentTypePage-C8XPPlCu.mjs} +2 -2
  34. package/dist/_chunks/{NoContentTypePage-CstnyWv2.mjs.map → NoContentTypePage-C8XPPlCu.mjs.map} +1 -1
  35. package/dist/_chunks/{NoContentTypePage-h7FcuMjI.js → NoContentTypePage-DId86YmW.js} +2 -2
  36. package/dist/_chunks/{NoContentTypePage-h7FcuMjI.js.map → NoContentTypePage-DId86YmW.js.map} +1 -1
  37. package/dist/_chunks/{NoPermissionsPage-DofU68cO.js → NoPermissionsPage-CT9LmH-v.js} +2 -2
  38. package/dist/_chunks/{NoPermissionsPage-DofU68cO.js.map → NoPermissionsPage-CT9LmH-v.js.map} +1 -1
  39. package/dist/_chunks/{NoPermissionsPage-aFCCLbsf.mjs → NoPermissionsPage-gwaMeI0N.mjs} +2 -2
  40. package/dist/_chunks/{NoPermissionsPage-aFCCLbsf.mjs.map → NoPermissionsPage-gwaMeI0N.mjs.map} +1 -1
  41. package/dist/_chunks/{Relations-7v66IP7b.mjs → Relations-BHyHGiTJ.mjs} +4 -4
  42. package/dist/_chunks/{Relations-7v66IP7b.mjs.map → Relations-BHyHGiTJ.mjs.map} +1 -1
  43. package/dist/_chunks/{Relations-DAS_DKG5.js → Relations-Zqwo0Moa.js} +4 -4
  44. package/dist/_chunks/{Relations-DAS_DKG5.js.map → Relations-Zqwo0Moa.js.map} +1 -1
  45. package/dist/_chunks/{index-CAlLHIrI.js → index-9nr_f9vB.js} +202 -117
  46. package/dist/_chunks/index-9nr_f9vB.js.map +1 -0
  47. package/dist/_chunks/{index-DIQ7Io-l.mjs → index-CS6TpAQJ.mjs} +221 -136
  48. package/dist/_chunks/index-CS6TpAQJ.mjs.map +1 -0
  49. package/dist/_chunks/{layout-DHe2GdT4.mjs → layout-2aGdWAdb.mjs} +20 -8
  50. package/dist/_chunks/layout-2aGdWAdb.mjs.map +1 -0
  51. package/dist/_chunks/{layout-B1ZS-usI.js → layout-BssHa4-L.js} +19 -7
  52. package/dist/_chunks/layout-BssHa4-L.js.map +1 -0
  53. package/dist/_chunks/{relations-yXHkSG1Z.js → relations-BuxzjpZ_.js} +2 -2
  54. package/dist/_chunks/{relations-yXHkSG1Z.js.map → relations-BuxzjpZ_.js.map} +1 -1
  55. package/dist/_chunks/{relations-BUieBWhT.mjs → relations-DBOO7qaP.mjs} +2 -2
  56. package/dist/_chunks/{relations-BUieBWhT.mjs.map → relations-DBOO7qaP.mjs.map} +1 -1
  57. package/dist/admin/index.js +1 -1
  58. package/dist/admin/index.mjs +4 -4
  59. package/dist/admin/src/history/index.d.ts +3 -0
  60. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  61. package/dist/admin/src/index.d.ts +1 -0
  62. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  63. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  64. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +10 -22
  65. package/dist/admin/src/services/api.d.ts +1 -1
  66. package/dist/admin/src/services/components.d.ts +2 -2
  67. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  68. package/dist/admin/src/services/documents.d.ts +16 -16
  69. package/dist/admin/src/services/init.d.ts +1 -1
  70. package/dist/admin/src/services/relations.d.ts +2 -2
  71. package/dist/admin/src/services/uid.d.ts +3 -3
  72. package/dist/admin/src/utils/validation.d.ts +4 -1
  73. package/dist/server/index.js +159 -103
  74. package/dist/server/index.js.map +1 -1
  75. package/dist/server/index.mjs +160 -104
  76. package/dist/server/index.mjs.map +1 -1
  77. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  78. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  79. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  80. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  81. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  82. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  83. package/dist/server/src/history/services/utils.d.ts +1 -1
  84. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  85. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  86. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  87. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  88. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  89. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  90. package/package.json +8 -8
  91. package/dist/_chunks/EditViewPage-CPrukwtO.mjs.map +0 -1
  92. package/dist/_chunks/EditViewPage-DhttErmY.js.map +0 -1
  93. package/dist/_chunks/Field-CBRV4uan.js.map +0 -1
  94. package/dist/_chunks/Field-DrgIgQPw.mjs.map +0 -1
  95. package/dist/_chunks/Form-Bk3v7Frl.js.map +0 -1
  96. package/dist/_chunks/Form-Dxk4txLJ.mjs.map +0 -1
  97. package/dist/_chunks/History-DSU-y4Hg.mjs.map +0 -1
  98. package/dist/_chunks/History-xNH_9UuV.js.map +0 -1
  99. package/dist/_chunks/ListConfigurationPage-BCPzXk5W.js.map +0 -1
  100. package/dist/_chunks/ListConfigurationPage-BWwZ-uMJ.mjs.map +0 -1
  101. package/dist/_chunks/ListViewPage-D9UmehuA.mjs.map +0 -1
  102. package/dist/_chunks/ListViewPage-ZIvstfvl.js.map +0 -1
  103. package/dist/_chunks/index-CAlLHIrI.js.map +0 -1
  104. package/dist/_chunks/index-DIQ7Io-l.mjs.map +0 -1
  105. package/dist/_chunks/layout-B1ZS-usI.js.map +0 -1
  106. package/dist/_chunks/layout-DHe2GdT4.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,7 +179,8 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
215
179
  "Document",
216
180
  "InitialData",
217
181
  "HistoryVersion",
218
- "Relations"
182
+ "Relations",
183
+ "UidAvailability"
219
184
  ]
220
185
  });
221
186
  const documentApi = contentManagerApi.injectEndpoints({
@@ -229,7 +194,12 @@ const documentApi = contentManagerApi.injectEndpoints({
229
194
  params: query
230
195
  }
231
196
  }),
232
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
197
+ invalidatesTags: (_result, error, { model }) => {
198
+ if (error) {
199
+ return [];
200
+ }
201
+ return [{ type: "Document", id: `${model}_LIST` }];
202
+ }
233
203
  }),
234
204
  cloneDocument: builder.mutation({
235
205
  query: ({ model, sourceId, data, params }) => ({
@@ -240,7 +210,10 @@ const documentApi = contentManagerApi.injectEndpoints({
240
210
  params
241
211
  }
242
212
  }),
243
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
213
+ invalidatesTags: (_result, _error, { model }) => [
214
+ { type: "Document", id: `${model}_LIST` },
215
+ { type: "UidAvailability", id: model }
216
+ ]
244
217
  }),
245
218
  /**
246
219
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -257,7 +230,8 @@ const documentApi = contentManagerApi.injectEndpoints({
257
230
  }),
258
231
  invalidatesTags: (result, _error, { model }) => [
259
232
  { type: "Document", id: `${model}_LIST` },
260
- "Relations"
233
+ "Relations",
234
+ { type: "UidAvailability", id: model }
261
235
  ]
262
236
  }),
263
237
  deleteDocument: builder.mutation({
@@ -298,7 +272,8 @@ const documentApi = contentManagerApi.injectEndpoints({
298
272
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
299
273
  },
300
274
  { type: "Document", id: `${model}_LIST` },
301
- "Relations"
275
+ "Relations",
276
+ { type: "UidAvailability", id: model }
302
277
  ];
303
278
  }
304
279
  }),
@@ -316,6 +291,7 @@ const documentApi = contentManagerApi.injectEndpoints({
316
291
  }),
317
292
  providesTags: (result, _error, arg) => {
318
293
  return [
294
+ { type: "Document", id: `ALL_LIST` },
319
295
  { type: "Document", id: `${arg.model}_LIST` },
320
296
  ...result?.results.map(({ documentId }) => ({
321
297
  type: "Document",
@@ -354,6 +330,11 @@ const documentApi = contentManagerApi.injectEndpoints({
354
330
  {
355
331
  type: "Document",
356
332
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
333
+ },
334
+ // Make it easy to invalidate all individual documents queries for a model
335
+ {
336
+ type: "Document",
337
+ id: `${model}_ALL_ITEMS`
357
338
  }
358
339
  ];
359
340
  }
@@ -417,8 +398,21 @@ const documentApi = contentManagerApi.injectEndpoints({
417
398
  type: "Document",
418
399
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
419
400
  },
420
- "Relations"
401
+ "Relations",
402
+ { type: "UidAvailability", id: model }
421
403
  ];
404
+ },
405
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
406
+ const patchResult = dispatch(
407
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
408
+ Object.assign(draft.data, data);
409
+ })
410
+ );
411
+ try {
412
+ await queryFulfilled;
413
+ } catch {
414
+ patchResult.undo();
415
+ }
422
416
  }
423
417
  }),
424
418
  unpublishDocument: builder.mutation({
@@ -488,7 +482,7 @@ const buildValidParams = (query) => {
488
482
  const isBaseQueryError = (error) => {
489
483
  return error.name !== void 0;
490
484
  };
491
- const createYupSchema = (attributes = {}, components = {}) => {
485
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
492
486
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
493
487
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
494
488
  if (DOCUMENT_META_FIELDS.includes(name)) {
@@ -501,7 +495,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
501
495
  addMinValidation,
502
496
  addMaxValidation,
503
497
  addRegexValidation
504
- ].map((fn) => fn(attribute));
498
+ ].map((fn) => fn(attribute, options));
505
499
  const transformSchema = pipe__default.default(...validations);
506
500
  switch (attribute.type) {
507
501
  case "component": {
@@ -602,6 +596,14 @@ const createAttributeSchema = (attribute) => {
602
596
  if (!value || typeof value === "string" && value.length === 0) {
603
597
  return true;
604
598
  }
599
+ if (typeof value === "object") {
600
+ try {
601
+ JSON.stringify(value);
602
+ return true;
603
+ } catch (err) {
604
+ return false;
605
+ }
606
+ }
605
607
  try {
606
608
  JSON.parse(value);
607
609
  return true;
@@ -620,13 +622,7 @@ const createAttributeSchema = (attribute) => {
620
622
  return yup__namespace.mixed();
621
623
  }
622
624
  };
623
- const addRequiredValidation = (attribute) => (schema) => {
624
- if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
625
- return schema.min(1, strapiAdmin.translatedErrors.required);
626
- }
627
- if (attribute.required && attribute.type !== "relation") {
628
- return schema.required(strapiAdmin.translatedErrors.required);
629
- }
625
+ const nullableSchema = (schema) => {
630
626
  return schema?.nullable ? schema.nullable() : (
631
627
  // In some cases '.nullable' will not be available on the schema.
632
628
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -634,7 +630,22 @@ const addRequiredValidation = (attribute) => (schema) => {
634
630
  schema
635
631
  );
636
632
  };
637
- const addMinLengthValidation = (attribute) => (schema) => {
633
+ const addRequiredValidation = (attribute, options) => (schema) => {
634
+ if (options.status === "draft") {
635
+ return nullableSchema(schema);
636
+ }
637
+ if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
638
+ return schema.min(1, strapiAdmin.translatedErrors.required);
639
+ }
640
+ if (attribute.required && attribute.type !== "relation") {
641
+ return schema.required(strapiAdmin.translatedErrors.required);
642
+ }
643
+ return nullableSchema(schema);
644
+ };
645
+ const addMinLengthValidation = (attribute, options) => (schema) => {
646
+ if (options.status === "draft") {
647
+ return schema;
648
+ }
638
649
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
639
650
  return schema.min(attribute.minLength, {
640
651
  ...strapiAdmin.translatedErrors.minLength,
@@ -656,11 +667,11 @@ const addMaxLengthValidation = (attribute) => (schema) => {
656
667
  }
657
668
  return schema;
658
669
  };
659
- const addMinValidation = (attribute) => (schema) => {
670
+ const addMinValidation = (attribute, options) => (schema) => {
660
671
  if ("min" in attribute) {
661
672
  const min = toInteger(attribute.min);
662
673
  if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
663
- if (!attribute.required && "test" in schema && min) {
674
+ if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
664
675
  return schema.test(
665
676
  "custom-min",
666
677
  {
@@ -896,6 +907,7 @@ const useDocumentActions = () => {
896
907
  const { formatMessage } = reactIntl.useIntl();
897
908
  const { trackUsage } = strapiAdmin.useTracking();
898
909
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
910
+ const navigate = reactRouterDom.useNavigate();
899
911
  const [deleteDocument] = useDeleteDocumentMutation();
900
912
  const _delete = React__namespace.useCallback(
901
913
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -1231,7 +1243,6 @@ const useDocumentActions = () => {
1231
1243
  sourceId
1232
1244
  });
1233
1245
  if ("error" in res) {
1234
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1235
1246
  return { error: res.error };
1236
1247
  }
1237
1248
  toggleNotification({
@@ -1250,7 +1261,7 @@ const useDocumentActions = () => {
1250
1261
  throw err;
1251
1262
  }
1252
1263
  },
1253
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1264
+ [autoCloneDocument, formatMessage, toggleNotification]
1254
1265
  );
1255
1266
  const [cloneDocument] = useCloneDocumentMutation();
1256
1267
  const clone = React__namespace.useCallback(
@@ -1276,6 +1287,7 @@ const useDocumentActions = () => {
1276
1287
  defaultMessage: "Cloned document"
1277
1288
  })
1278
1289
  });
1290
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1279
1291
  return res.data;
1280
1292
  } catch (err) {
1281
1293
  toggleNotification({
@@ -1286,7 +1298,7 @@ const useDocumentActions = () => {
1286
1298
  throw err;
1287
1299
  }
1288
1300
  },
1289
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1301
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1290
1302
  );
1291
1303
  const [getDoc] = useLazyGetDocumentQuery();
1292
1304
  const getDocument = React__namespace.useCallback(
@@ -1312,7 +1324,7 @@ const useDocumentActions = () => {
1312
1324
  };
1313
1325
  };
1314
1326
  const ProtectedHistoryPage = React.lazy(
1315
- () => Promise.resolve().then(() => require("./History-xNH_9UuV.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1327
+ () => Promise.resolve().then(() => require("./History-CARFXr5U.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1316
1328
  );
1317
1329
  const routes$1 = [
1318
1330
  {
@@ -1325,31 +1337,31 @@ const routes$1 = [
1325
1337
  }
1326
1338
  ];
1327
1339
  const ProtectedEditViewPage = React.lazy(
1328
- () => Promise.resolve().then(() => require("./EditViewPage-DhttErmY.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1340
+ () => Promise.resolve().then(() => require("./EditViewPage-fuASFJIx.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1329
1341
  );
1330
1342
  const ProtectedListViewPage = React.lazy(
1331
- () => Promise.resolve().then(() => require("./ListViewPage-ZIvstfvl.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1343
+ () => Promise.resolve().then(() => require("./ListViewPage-CY6a70Y-.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1332
1344
  );
1333
1345
  const ProtectedListConfiguration = React.lazy(
1334
- () => Promise.resolve().then(() => require("./ListConfigurationPage-BCPzXk5W.js")).then((mod) => ({
1346
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-fZjkRyi9.js")).then((mod) => ({
1335
1347
  default: mod.ProtectedListConfiguration
1336
1348
  }))
1337
1349
  );
1338
1350
  const ProtectedEditConfigurationPage = React.lazy(
1339
- () => Promise.resolve().then(() => require("./EditConfigurationPage-b6V7YHfo.js")).then((mod) => ({
1351
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-DOyPS5Tv.js")).then((mod) => ({
1340
1352
  default: mod.ProtectedEditConfigurationPage
1341
1353
  }))
1342
1354
  );
1343
1355
  const ProtectedComponentConfigurationPage = React.lazy(
1344
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-DVY3LwHo.js")).then((mod) => ({
1356
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-BEJqMzZA.js")).then((mod) => ({
1345
1357
  default: mod.ProtectedComponentConfigurationPage
1346
1358
  }))
1347
1359
  );
1348
1360
  const NoPermissions = React.lazy(
1349
- () => Promise.resolve().then(() => require("./NoPermissionsPage-DofU68cO.js")).then((mod) => ({ default: mod.NoPermissions }))
1361
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-CT9LmH-v.js")).then((mod) => ({ default: mod.NoPermissions }))
1350
1362
  );
1351
1363
  const NoContentType = React.lazy(
1352
- () => Promise.resolve().then(() => require("./NoContentTypePage-h7FcuMjI.js")).then((mod) => ({ default: mod.NoContentType }))
1364
+ () => Promise.resolve().then(() => require("./NoContentTypePage-DId86YmW.js")).then((mod) => ({ default: mod.NoContentType }))
1353
1365
  );
1354
1366
  const CollectionTypePages = () => {
1355
1367
  const { collectionType } = reactRouterDom.useParams();
@@ -1463,12 +1475,14 @@ const DocumentActionButton = (action) => {
1463
1475
  /* @__PURE__ */ jsxRuntime.jsx(
1464
1476
  designSystem.Button,
1465
1477
  {
1466
- flex: 1,
1478
+ flex: "auto",
1467
1479
  startIcon: action.icon,
1468
1480
  disabled: action.disabled,
1469
1481
  onClick: handleClick(action),
1470
1482
  justifyContent: "center",
1471
1483
  variant: action.variant || "default",
1484
+ paddingTop: "7px",
1485
+ paddingBottom: "7px",
1472
1486
  children: action.label
1473
1487
  }
1474
1488
  ),
@@ -1528,14 +1542,14 @@ const DocumentActionsMenu = ({
1528
1542
  };
1529
1543
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
1530
1544
  /* @__PURE__ */ jsxRuntime.jsxs(
1531
- designSystem.Menu.Trigger,
1545
+ StyledMoreButton,
1532
1546
  {
1533
1547
  disabled: isDisabled,
1534
1548
  size: "S",
1535
1549
  endIcon: null,
1536
- paddingTop: "7px",
1537
- paddingLeft: "9px",
1538
- paddingRight: "9px",
1550
+ paddingTop: "4px",
1551
+ paddingLeft: "7px",
1552
+ paddingRight: "7px",
1539
1553
  variant,
1540
1554
  children: [
1541
1555
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
@@ -1555,10 +1569,25 @@ const DocumentActionsMenu = ({
1555
1569
  onSelect: handleClick(action),
1556
1570
  display: "block",
1557
1571
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1558
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1559
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1560
- action.label
1561
- ] }),
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
+ ),
1562
1591
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
1563
1592
  designSystem.Flex,
1564
1593
  {
@@ -1629,6 +1658,11 @@ const convertActionVariantToIconColor = (variant = "secondary") => {
1629
1658
  return "primary600";
1630
1659
  }
1631
1660
  };
1661
+ const StyledMoreButton = styledComponents.styled(designSystem.Menu.Trigger)`
1662
+ & > span {
1663
+ display: flex;
1664
+ }
1665
+ `;
1632
1666
  const DocumentActionConfirmDialog = ({
1633
1667
  onClose,
1634
1668
  onCancel,
@@ -1682,8 +1716,8 @@ const DocumentActionModal = ({
1682
1716
  };
1683
1717
  return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
1684
1718
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
1685
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content }),
1686
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Footer, { children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer })
1719
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
1720
+ typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1687
1721
  ] }) });
1688
1722
  };
1689
1723
  const PublishAction$1 = ({
@@ -1700,10 +1734,7 @@ const PublishAction$1 = ({
1700
1734
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
1701
1735
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
1702
1736
  const { formatMessage } = reactIntl.useIntl();
1703
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1704
- "PublishAction",
1705
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1706
- );
1737
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1707
1738
  const { publish } = useDocumentActions();
1708
1739
  const [
1709
1740
  countDraftRelations,
@@ -1823,10 +1854,8 @@ const PublishAction$1 = ({
1823
1854
  * - the document is already published & not modified
1824
1855
  * - the document is being created & not modified
1825
1856
  * - the user doesn't have the permission to publish
1826
- * - the user doesn't have the permission to create a new document
1827
- * - the user doesn't have the permission to update the document
1828
1857
  */
1829
- disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1858
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1830
1859
  label: formatMessage({
1831
1860
  id: "app.utils.publish",
1832
1861
  defaultMessage: "Publish"
@@ -1873,10 +1902,6 @@ const UpdateAction = ({
1873
1902
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1874
1903
  const isCloning = cloneMatch !== null;
1875
1904
  const { formatMessage } = reactIntl.useIntl();
1876
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1877
- canCreate: canCreate2,
1878
- canUpdate: canUpdate2
1879
- }));
1880
1905
  const { create, update, clone } = useDocumentActions();
1881
1906
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1882
1907
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1893,10 +1918,8 @@ const UpdateAction = ({
1893
1918
  * - the form is submitting
1894
1919
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1895
1920
  * - the active tab is the published tab
1896
- * - the user doesn't have the permission to create a new document
1897
- * - the user doesn't have the permission to update the document
1898
1921
  */
1899
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
1922
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1900
1923
  label: formatMessage({
1901
1924
  id: "content-manager.containers.Edit.save",
1902
1925
  defaultMessage: "Save"
@@ -1904,16 +1927,18 @@ const UpdateAction = ({
1904
1927
  onClick: async () => {
1905
1928
  setSubmitting(true);
1906
1929
  try {
1907
- const { errors } = await validate();
1908
- if (errors) {
1909
- toggleNotification({
1910
- type: "danger",
1911
- message: formatMessage({
1912
- id: "content-manager.validation.error",
1913
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1914
- })
1915
- });
1916
- return;
1930
+ if (activeTab !== "draft") {
1931
+ const { errors } = await validate();
1932
+ if (errors) {
1933
+ toggleNotification({
1934
+ type: "danger",
1935
+ message: formatMessage({
1936
+ id: "content-manager.validation.error",
1937
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1938
+ })
1939
+ });
1940
+ return;
1941
+ }
1917
1942
  }
1918
1943
  if (isCloning) {
1919
1944
  const res = await clone(
@@ -1925,10 +1950,13 @@ const UpdateAction = ({
1925
1950
  document
1926
1951
  );
1927
1952
  if ("data" in res) {
1928
- navigate({
1929
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1930
- search: rawQuery
1931
- });
1953
+ navigate(
1954
+ {
1955
+ pathname: `../${res.data.documentId}`,
1956
+ search: rawQuery
1957
+ },
1958
+ { relative: "path" }
1959
+ );
1932
1960
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1933
1961
  setErrors(formatValidationErrors(res.error));
1934
1962
  }
@@ -1958,10 +1986,10 @@ const UpdateAction = ({
1958
1986
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1959
1987
  navigate(
1960
1988
  {
1961
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1989
+ pathname: `../${res.data.documentId}`,
1962
1990
  search: rawQuery
1963
1991
  },
1964
- { replace: true }
1992
+ { replace: true, relative: "path" }
1965
1993
  );
1966
1994
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1967
1995
  setErrors(formatValidationErrors(res.error));
@@ -2905,7 +2933,7 @@ const ConfirmBulkActionDialog = ({
2905
2933
  endAction
2906
2934
  }) => {
2907
2935
  const { formatMessage } = reactIntl.useIntl();
2908
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2936
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2909
2937
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2910
2938
  id: "app.components.ConfirmDialog.title",
2911
2939
  defaultMessage: "Confirmation"
@@ -3194,7 +3222,13 @@ const SelectedEntriesModalContent = ({
3194
3222
  );
3195
3223
  const { rows, validationErrors } = React__namespace.useMemo(() => {
3196
3224
  if (data.length > 0 && schema) {
3197
- const validate = createYupSchema(schema.attributes, components);
3225
+ const validate = createYupSchema(
3226
+ schema.attributes,
3227
+ components,
3228
+ // Since this is the "Publish" action, the validation
3229
+ // schema must enforce the rules for published entities
3230
+ { status: "published" }
3231
+ );
3198
3232
  const validationErrors2 = {};
3199
3233
  const rows2 = data.map((entry) => {
3200
3234
  try {
@@ -3544,7 +3578,7 @@ const TableActions = ({ document }) => {
3544
3578
  strapiAdmin.DescriptionComponentRenderer,
3545
3579
  {
3546
3580
  props,
3547
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3581
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
3548
3582
  children: (actions2) => {
3549
3583
  const tableRowActions = actions2.filter((action) => {
3550
3584
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3655,7 +3689,7 @@ const CloneAction = ({ model, documentId }) => {
3655
3689
  }),
3656
3690
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3657
3691
  footer: ({ onClose }) => {
3658
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3692
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3659
3693
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3660
3694
  id: "cancel",
3661
3695
  defaultMessage: "Cancel"
@@ -3696,8 +3730,7 @@ class ContentManagerPlugin {
3696
3730
  documentActions = [
3697
3731
  ...DEFAULT_ACTIONS,
3698
3732
  ...DEFAULT_TABLE_ROW_ACTIONS,
3699
- ...DEFAULT_HEADER_ACTIONS,
3700
- HistoryAction
3733
+ ...DEFAULT_HEADER_ACTIONS
3701
3734
  ];
3702
3735
  editViewSidePanels = [ActionsPanel];
3703
3736
  headerActions = [];
@@ -3786,6 +3819,52 @@ const getPrintableType = (value) => {
3786
3819
  }
3787
3820
  return nativeType;
3788
3821
  };
3822
+ const HistoryAction = ({ model, document }) => {
3823
+ const { formatMessage } = reactIntl.useIntl();
3824
+ const [{ query }] = strapiAdmin.useQueryParams();
3825
+ const navigate = reactRouterDom.useNavigate();
3826
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3827
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3828
+ return null;
3829
+ }
3830
+ return {
3831
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3832
+ label: formatMessage({
3833
+ id: "content-manager.history.document-action",
3834
+ defaultMessage: "Content History"
3835
+ }),
3836
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3837
+ disabled: (
3838
+ /**
3839
+ * The user is creating a new document.
3840
+ * It hasn't been saved yet, so there's no history to go to
3841
+ */
3842
+ !document || /**
3843
+ * The document has been created but the current dimension has never been saved.
3844
+ * For example, the user is creating a new locale in an existing document,
3845
+ * so there's no history for the document in that locale
3846
+ */
3847
+ !document.id || /**
3848
+ * History is only available for content types created by the user.
3849
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3850
+ * which start with `admin::` or `plugin::`
3851
+ */
3852
+ !model.startsWith("api::")
3853
+ ),
3854
+ position: "header"
3855
+ };
3856
+ };
3857
+ HistoryAction.type = "history";
3858
+ const historyAdmin = {
3859
+ bootstrap(app) {
3860
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3861
+ addDocumentAction((actions2) => {
3862
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3863
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3864
+ return actions2;
3865
+ });
3866
+ }
3867
+ };
3789
3868
  const initialState = {
3790
3869
  collectionTypeLinks: [],
3791
3870
  components: [],
@@ -3841,7 +3920,7 @@ const index = {
3841
3920
  app.router.addRoute({
3842
3921
  path: "content-manager/*",
3843
3922
  lazy: async () => {
3844
- const { Layout } = await Promise.resolve().then(() => require("./layout-B1ZS-usI.js"));
3923
+ const { Layout } = await Promise.resolve().then(() => require("./layout-BssHa4-L.js"));
3845
3924
  return {
3846
3925
  Component: Layout
3847
3926
  };
@@ -3850,6 +3929,11 @@ const index = {
3850
3929
  });
3851
3930
  app.registerPlugin(cm.config);
3852
3931
  },
3932
+ bootstrap(app) {
3933
+ if (typeof historyAdmin.bootstrap === "function") {
3934
+ historyAdmin.bootstrap(app);
3935
+ }
3936
+ },
3853
3937
  async registerTrads({ locales }) {
3854
3938
  const importedTrads = await Promise.all(
3855
3939
  locales.map((locale) => {
@@ -3871,6 +3955,7 @@ const index = {
3871
3955
  };
3872
3956
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3873
3957
  exports.BulkActionsRenderer = BulkActionsRenderer;
3958
+ exports.CLONE_PATH = CLONE_PATH;
3874
3959
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3875
3960
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3876
3961
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3910,4 +3995,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3910
3995
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3911
3996
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3912
3997
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3913
- //# sourceMappingURL=index-CAlLHIrI.js.map
3998
+ //# sourceMappingURL=index-9nr_f9vB.js.map