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

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 (134) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-CO977CPh.js} +4 -4
  3. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-CO977CPh.js.map} +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs → ComponentConfigurationPage-CQroR9Qk.mjs} +4 -4
  5. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-CQroR9Qk.mjs.map} +1 -1
  6. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-BPgoE-kf.js} +4 -4
  7. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-BPgoE-kf.js.map} +1 -1
  8. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs → EditConfigurationPage-tVCJ5vWC.mjs} +4 -4
  9. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-tVCJ5vWC.mjs.map} +1 -1
  10. package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-8mOu02ji.mjs} +30 -9
  11. package/dist/_chunks/EditViewPage-8mOu02ji.mjs.map +1 -0
  12. package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-BMVgUNOX.js} +30 -9
  13. package/dist/_chunks/EditViewPage-BMVgUNOX.js.map +1 -0
  14. package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-CJPYzwD7.mjs} +249 -152
  15. package/dist/_chunks/Field-CJPYzwD7.mjs.map +1 -0
  16. package/dist/_chunks/{Field-Boxf9Ajp.js → Field-CdSLKFQk.js} +251 -154
  17. package/dist/_chunks/Field-CdSLKFQk.js.map +1 -0
  18. package/dist/_chunks/{Form-DHrru2AV.mjs → Form-DJOJ-GF1.mjs} +36 -17
  19. package/dist/_chunks/Form-DJOJ-GF1.mjs.map +1 -0
  20. package/dist/_chunks/{Form-y5g1SRsh.js → Form-eP5bZwap.js} +36 -17
  21. package/dist/_chunks/Form-eP5bZwap.js.map +1 -0
  22. package/dist/_chunks/{History-CqN6K7SX.js → History-B-Mrquzu.js} +63 -25
  23. package/dist/_chunks/History-B-Mrquzu.js.map +1 -0
  24. package/dist/_chunks/{History-Bru_KoeP.mjs → History-MnQLtk1g.mjs} +64 -26
  25. package/dist/_chunks/History-MnQLtk1g.mjs.map +1 -0
  26. package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-BcycI8Lw.mjs} +21 -9
  27. package/dist/_chunks/ListConfigurationPage-BcycI8Lw.mjs.map +1 -0
  28. package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-C0n4rUzH.js} +21 -9
  29. package/dist/_chunks/ListConfigurationPage-C0n4rUzH.js.map +1 -0
  30. package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-CRXONXwZ.mjs} +59 -41
  31. package/dist/_chunks/ListViewPage-CRXONXwZ.mjs.map +1 -0
  32. package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-q0SHVPUS.js} +61 -43
  33. package/dist/_chunks/ListViewPage-q0SHVPUS.js.map +1 -0
  34. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-Bh3komDV.js} +2 -2
  35. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-Bh3komDV.js.map} +1 -1
  36. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-ukzFRF3z.mjs} +2 -2
  37. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-ukzFRF3z.mjs.map} +1 -1
  38. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-B4sD7Ble.mjs} +2 -2
  39. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-B4sD7Ble.mjs.map} +1 -1
  40. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-BGBpj_Y1.js} +2 -2
  41. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-BGBpj_Y1.js.map} +1 -1
  42. package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-B53wYe8g.js} +33 -24
  43. package/dist/_chunks/Relations-B53wYe8g.js.map +1 -0
  44. package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-CIexb8gr.mjs} +33 -24
  45. package/dist/_chunks/Relations-CIexb8gr.mjs.map +1 -0
  46. package/dist/_chunks/{en-fbKQxLGn.js → en-Bm0D0IWz.js} +17 -15
  47. package/dist/_chunks/{en-fbKQxLGn.js.map → en-Bm0D0IWz.js.map} +1 -1
  48. package/dist/_chunks/{en-Ux26r5pl.mjs → en-DKV44jRb.mjs} +17 -15
  49. package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-DKV44jRb.mjs.map} +1 -1
  50. package/dist/_chunks/{index-DJXJw9V5.mjs → index-CJ2vYwuT.mjs} +997 -690
  51. package/dist/_chunks/index-CJ2vYwuT.mjs.map +1 -0
  52. package/dist/_chunks/{index-DVPWZkbS.js → index-DbT2sx-Q.js} +978 -671
  53. package/dist/_chunks/index-DbT2sx-Q.js.map +1 -0
  54. package/dist/_chunks/{layout-Dm6fbiQj.js → layout-CeBSIkmP.js} +24 -11
  55. package/dist/_chunks/layout-CeBSIkmP.js.map +1 -0
  56. package/dist/_chunks/{layout-Bau7ZfLV.mjs → layout-vzKSrr7p.mjs} +25 -12
  57. package/dist/_chunks/layout-vzKSrr7p.mjs.map +1 -0
  58. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  59. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  60. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  61. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  62. package/dist/_chunks/{relations-CKnpRgrN.js → relations-Cl-6t9iz.js} +2 -2
  63. package/dist/_chunks/{relations-CKnpRgrN.js.map → relations-Cl-6t9iz.js.map} +1 -1
  64. package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-DI0lguF0.mjs} +2 -2
  65. package/dist/_chunks/{relations-BH_kBSJ0.mjs.map → relations-DI0lguF0.mjs.map} +1 -1
  66. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  67. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  68. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  69. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  70. package/dist/admin/index.js +2 -1
  71. package/dist/admin/index.js.map +1 -1
  72. package/dist/admin/index.mjs +5 -4
  73. package/dist/admin/src/exports.d.ts +1 -1
  74. package/dist/admin/src/history/index.d.ts +3 -0
  75. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  76. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  77. package/dist/admin/src/index.d.ts +1 -0
  78. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -0
  79. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  80. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  81. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  82. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  83. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  84. package/dist/admin/src/services/api.d.ts +1 -1
  85. package/dist/admin/src/services/components.d.ts +2 -2
  86. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  87. package/dist/admin/src/services/documents.d.ts +19 -17
  88. package/dist/admin/src/services/init.d.ts +1 -1
  89. package/dist/admin/src/services/relations.d.ts +2 -2
  90. package/dist/admin/src/services/uid.d.ts +3 -3
  91. package/dist/admin/src/utils/validation.d.ts +4 -1
  92. package/dist/server/index.js +207 -120
  93. package/dist/server/index.js.map +1 -1
  94. package/dist/server/index.mjs +208 -121
  95. package/dist/server/index.mjs.map +1 -1
  96. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  97. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  98. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  99. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  100. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  101. package/dist/server/src/history/services/history.d.ts.map +1 -1
  102. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  103. package/dist/server/src/history/services/utils.d.ts +2 -1
  104. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  105. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  106. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  107. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  108. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  109. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  110. package/dist/shared/contracts/collection-types.d.ts +3 -1
  111. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  112. package/package.json +12 -12
  113. package/dist/_chunks/EditViewPage-CPj61RMh.mjs.map +0 -1
  114. package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
  115. package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
  116. package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
  117. package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
  118. package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
  119. package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
  120. package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
  121. package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
  122. package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
  123. package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
  124. package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
  125. package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
  126. package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
  127. package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
  128. package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
  129. package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
  130. package/dist/_chunks/layout-Dm6fbiQj.js.map +0 -1
  131. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  132. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  133. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  134. package/strapi-server.js +0 -3
@@ -2,15 +2,15 @@
2
2
  const Icons = require("@strapi/icons");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const strapiAdmin = require("@strapi/admin/strapi-admin");
5
- const qs = require("qs");
6
- const reactIntl = require("react-intl");
7
- const reactRouterDom = require("react-router-dom");
8
5
  const React = require("react");
9
6
  const designSystem = require("@strapi/design-system");
10
- const styledComponents = require("styled-components");
7
+ const reactIntl = require("react-intl");
8
+ const reactRouterDom = require("react-router-dom");
11
9
  const yup = require("yup");
12
10
  const pipe = require("lodash/fp/pipe");
13
11
  const dateFns = require("date-fns");
12
+ const styledComponents = require("styled-components");
13
+ const qs = require("qs");
14
14
  const toolkit = require("@reduxjs/toolkit");
15
15
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
16
16
  function _interopNamespace(e) {
@@ -70,42 +70,6 @@ const useInjectionZone = (area) => {
70
70
  const [page, position] = area.split(".");
71
71
  return contentManagerPlugin.getInjectedComponents(page, position);
72
72
  };
73
- const HistoryAction = ({ model, document }) => {
74
- const { formatMessage } = reactIntl.useIntl();
75
- const [{ query }] = strapiAdmin.useQueryParams();
76
- const navigate = reactRouterDom.useNavigate();
77
- const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
78
- if (!window.strapi.features.isEnabled("cms-content-history")) {
79
- return null;
80
- }
81
- return {
82
- icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
83
- label: formatMessage({
84
- id: "content-manager.history.document-action",
85
- defaultMessage: "Content History"
86
- }),
87
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
88
- disabled: (
89
- /**
90
- * The user is creating a new document.
91
- * It hasn't been saved yet, so there's no history to go to
92
- */
93
- !document || /**
94
- * The document has been created but the current dimension has never been saved.
95
- * For example, the user is creating a new locale in an existing document,
96
- * so there's no history for the document in that locale
97
- */
98
- !document.id || /**
99
- * History is only available for content types created by the user.
100
- * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
101
- * which start with `admin::` or `plugin::`
102
- */
103
- !model.startsWith("api::")
104
- ),
105
- position: "header"
106
- };
107
- };
108
- HistoryAction.type = "history";
109
73
  const ID = "id";
110
74
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
111
75
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -157,6 +121,7 @@ const DocumentRBAC = ({ children, permissions }) => {
157
121
  if (!slug) {
158
122
  throw new Error("Cannot find the slug param in the URL");
159
123
  }
124
+ const [{ rawQuery }] = strapiAdmin.useQueryParams();
160
125
  const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
161
126
  const contentTypePermissions = React__namespace.useMemo(() => {
162
127
  const contentTypePermissions2 = userPermissions.filter(
@@ -167,7 +132,14 @@ const DocumentRBAC = ({ children, permissions }) => {
167
132
  return { ...acc, [action]: [permission] };
168
133
  }, {});
169
134
  }, [slug, userPermissions]);
170
- const { isLoading, allowedActions } = strapiAdmin.useRBAC(contentTypePermissions, permissions ?? void 0);
135
+ const { isLoading, allowedActions } = strapiAdmin.useRBAC(
136
+ contentTypePermissions,
137
+ permissions ?? void 0,
138
+ // TODO: useRBAC context should be typed and built differently
139
+ // We are passing raw query as context to the hook so that it can
140
+ // rely on the locale provided from DocumentRBAC for its permission calculations.
141
+ rawQuery
142
+ );
171
143
  const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
172
144
  const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
173
145
  const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
@@ -215,7 +187,8 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
215
187
  "Document",
216
188
  "InitialData",
217
189
  "HistoryVersion",
218
- "Relations"
190
+ "Relations",
191
+ "UidAvailability"
219
192
  ]
220
193
  });
221
194
  const documentApi = contentManagerApi.injectEndpoints({
@@ -229,7 +202,12 @@ const documentApi = contentManagerApi.injectEndpoints({
229
202
  params: query
230
203
  }
231
204
  }),
232
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
205
+ invalidatesTags: (_result, error, { model }) => {
206
+ if (error) {
207
+ return [];
208
+ }
209
+ return [{ type: "Document", id: `${model}_LIST` }];
210
+ }
233
211
  }),
234
212
  cloneDocument: builder.mutation({
235
213
  query: ({ model, sourceId, data, params }) => ({
@@ -240,7 +218,10 @@ const documentApi = contentManagerApi.injectEndpoints({
240
218
  params
241
219
  }
242
220
  }),
243
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
221
+ invalidatesTags: (_result, _error, { model }) => [
222
+ { type: "Document", id: `${model}_LIST` },
223
+ { type: "UidAvailability", id: model }
224
+ ]
244
225
  }),
245
226
  /**
246
227
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -257,7 +238,8 @@ const documentApi = contentManagerApi.injectEndpoints({
257
238
  }),
258
239
  invalidatesTags: (result, _error, { model }) => [
259
240
  { type: "Document", id: `${model}_LIST` },
260
- "Relations"
241
+ "Relations",
242
+ { type: "UidAvailability", id: model }
261
243
  ]
262
244
  }),
263
245
  deleteDocument: builder.mutation({
@@ -298,7 +280,8 @@ const documentApi = contentManagerApi.injectEndpoints({
298
280
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
299
281
  },
300
282
  { type: "Document", id: `${model}_LIST` },
301
- "Relations"
283
+ "Relations",
284
+ { type: "UidAvailability", id: model }
302
285
  ];
303
286
  }
304
287
  }),
@@ -316,6 +299,7 @@ const documentApi = contentManagerApi.injectEndpoints({
316
299
  }),
317
300
  providesTags: (result, _error, arg) => {
318
301
  return [
302
+ { type: "Document", id: `ALL_LIST` },
319
303
  { type: "Document", id: `${arg.model}_LIST` },
320
304
  ...result?.results.map(({ documentId }) => ({
321
305
  type: "Document",
@@ -354,6 +338,11 @@ const documentApi = contentManagerApi.injectEndpoints({
354
338
  {
355
339
  type: "Document",
356
340
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
341
+ },
342
+ // Make it easy to invalidate all individual documents queries for a model
343
+ {
344
+ type: "Document",
345
+ id: `${model}_ALL_ITEMS`
357
346
  }
358
347
  ];
359
348
  }
@@ -417,8 +406,21 @@ const documentApi = contentManagerApi.injectEndpoints({
417
406
  type: "Document",
418
407
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
419
408
  },
420
- "Relations"
409
+ "Relations",
410
+ { type: "UidAvailability", id: model }
421
411
  ];
412
+ },
413
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
414
+ const patchResult = dispatch(
415
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
416
+ Object.assign(draft.data, data);
417
+ })
418
+ );
419
+ try {
420
+ await queryFulfilled;
421
+ } catch {
422
+ patchResult.undo();
423
+ }
422
424
  }
423
425
  }),
424
426
  unpublishDocument: builder.mutation({
@@ -488,20 +490,39 @@ const buildValidParams = (query) => {
488
490
  const isBaseQueryError = (error) => {
489
491
  return error.name !== void 0;
490
492
  };
491
- const createYupSchema = (attributes = {}, components = {}) => {
493
+ const arrayValidator = (attribute, options) => ({
494
+ message: strapiAdmin.translatedErrors.required,
495
+ test(value) {
496
+ if (options.status === "draft") {
497
+ return true;
498
+ }
499
+ if (!attribute.required) {
500
+ return true;
501
+ }
502
+ if (!value) {
503
+ return false;
504
+ }
505
+ if (Array.isArray(value) && value.length === 0) {
506
+ return false;
507
+ }
508
+ return true;
509
+ }
510
+ });
511
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
492
512
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
493
513
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
494
514
  if (DOCUMENT_META_FIELDS.includes(name)) {
495
515
  return acc;
496
516
  }
497
517
  const validations = [
518
+ addNullableValidation,
498
519
  addRequiredValidation,
499
520
  addMinLengthValidation,
500
521
  addMaxLengthValidation,
501
522
  addMinValidation,
502
523
  addMaxValidation,
503
524
  addRegexValidation
504
- ].map((fn) => fn(attribute));
525
+ ].map((fn) => fn(attribute, options));
505
526
  const transformSchema = pipe__default.default(...validations);
506
527
  switch (attribute.type) {
507
528
  case "component": {
@@ -511,12 +532,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
511
532
  ...acc,
512
533
  [name]: transformSchema(
513
534
  yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
514
- )
535
+ ).test(arrayValidator(attribute, options))
515
536
  };
516
537
  } else {
517
538
  return {
518
539
  ...acc,
519
- [name]: transformSchema(createModelSchema(attributes3))
540
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
520
541
  };
521
542
  }
522
543
  }
@@ -538,7 +559,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
538
559
  }
539
560
  )
540
561
  )
541
- )
562
+ ).test(arrayValidator(attribute, options))
542
563
  };
543
564
  case "relation":
544
565
  return {
@@ -550,7 +571,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
550
571
  } else if (Array.isArray(value)) {
551
572
  return yup__namespace.array().of(
552
573
  yup__namespace.object().shape({
553
- id: yup__namespace.string().required()
574
+ id: yup__namespace.number().required()
554
575
  })
555
576
  );
556
577
  } else if (typeof value === "object") {
@@ -602,6 +623,14 @@ const createAttributeSchema = (attribute) => {
602
623
  if (!value || typeof value === "string" && value.length === 0) {
603
624
  return true;
604
625
  }
626
+ if (typeof value === "object") {
627
+ try {
628
+ JSON.stringify(value);
629
+ return true;
630
+ } catch (err) {
631
+ return false;
632
+ }
633
+ }
605
634
  try {
606
635
  JSON.parse(value);
607
636
  return true;
@@ -620,13 +649,7 @@ const createAttributeSchema = (attribute) => {
620
649
  return yup__namespace.mixed();
621
650
  }
622
651
  };
623
- const addRequiredValidation = (attribute) => (schema) => {
624
- if (attribute.required) {
625
- return schema.required({
626
- id: strapiAdmin.translatedErrors.required.id,
627
- defaultMessage: "This field is required."
628
- });
629
- }
652
+ const nullableSchema = (schema) => {
630
653
  return schema?.nullable ? schema.nullable() : (
631
654
  // In some cases '.nullable' will not be available on the schema.
632
655
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -634,7 +657,22 @@ const addRequiredValidation = (attribute) => (schema) => {
634
657
  schema
635
658
  );
636
659
  };
637
- const addMinLengthValidation = (attribute) => (schema) => {
660
+ const addNullableValidation = () => (schema) => {
661
+ return nullableSchema(schema);
662
+ };
663
+ const addRequiredValidation = (attribute, options) => (schema) => {
664
+ if (options.status === "draft" || !attribute.required) {
665
+ return schema;
666
+ }
667
+ if (attribute.required && "required" in schema) {
668
+ return schema.required(strapiAdmin.translatedErrors.required);
669
+ }
670
+ return schema;
671
+ };
672
+ const addMinLengthValidation = (attribute, options) => (schema) => {
673
+ if (options.status === "draft") {
674
+ return schema;
675
+ }
638
676
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
639
677
  return schema.min(attribute.minLength, {
640
678
  ...strapiAdmin.translatedErrors.minLength,
@@ -656,10 +694,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
656
694
  }
657
695
  return schema;
658
696
  };
659
- const addMinValidation = (attribute) => (schema) => {
660
- if ("min" in attribute) {
697
+ const addMinValidation = (attribute, options) => (schema) => {
698
+ if (options.status === "draft") {
699
+ return schema;
700
+ }
701
+ if ("min" in attribute && "min" in schema) {
661
702
  const min = toInteger(attribute.min);
662
- if ("min" in schema && min) {
703
+ if (min) {
663
704
  return schema.min(min, {
664
705
  ...strapiAdmin.translatedErrors.min,
665
706
  values: {
@@ -777,16 +818,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
777
818
  }, {});
778
819
  return componentsByKey;
779
820
  };
780
- const useDocument = (args, opts) => {
821
+ const HOOKS = {
822
+ /**
823
+ * Hook that allows to mutate the displayed headers of the list view table
824
+ * @constant
825
+ * @type {string}
826
+ */
827
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
828
+ /**
829
+ * Hook that allows to mutate the CM's collection types links pre-set filters
830
+ * @constant
831
+ * @type {string}
832
+ */
833
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
834
+ /**
835
+ * Hook that allows to mutate the CM's edit view layout
836
+ * @constant
837
+ * @type {string}
838
+ */
839
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
840
+ /**
841
+ * Hook that allows to mutate the CM's single types links pre-set filters
842
+ * @constant
843
+ * @type {string}
844
+ */
845
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
846
+ };
847
+ const contentTypesApi = contentManagerApi.injectEndpoints({
848
+ endpoints: (builder) => ({
849
+ getContentTypeConfiguration: builder.query({
850
+ query: (uid) => ({
851
+ url: `/content-manager/content-types/${uid}/configuration`,
852
+ method: "GET"
853
+ }),
854
+ transformResponse: (response) => response.data,
855
+ providesTags: (_result, _error, uid) => [
856
+ { type: "ContentTypesConfiguration", id: uid },
857
+ { type: "ContentTypeSettings", id: "LIST" }
858
+ ]
859
+ }),
860
+ getAllContentTypeSettings: builder.query({
861
+ query: () => "/content-manager/content-types-settings",
862
+ transformResponse: (response) => response.data,
863
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
864
+ }),
865
+ updateContentTypeConfiguration: builder.mutation({
866
+ query: ({ uid, ...body }) => ({
867
+ url: `/content-manager/content-types/${uid}/configuration`,
868
+ method: "PUT",
869
+ data: body
870
+ }),
871
+ transformResponse: (response) => response.data,
872
+ invalidatesTags: (_result, _error, { uid }) => [
873
+ { type: "ContentTypesConfiguration", id: uid },
874
+ { type: "ContentTypeSettings", id: "LIST" },
875
+ // Is this necessary?
876
+ { type: "InitialData" }
877
+ ]
878
+ })
879
+ })
880
+ });
881
+ const {
882
+ useGetContentTypeConfigurationQuery,
883
+ useGetAllContentTypeSettingsQuery,
884
+ useUpdateContentTypeConfigurationMutation
885
+ } = contentTypesApi;
886
+ const checkIfAttributeIsDisplayable = (attribute) => {
887
+ const { type } = attribute;
888
+ if (type === "relation") {
889
+ return !attribute.relation.toLowerCase().includes("morph");
890
+ }
891
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
892
+ };
893
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
894
+ if (!mainFieldName) {
895
+ return void 0;
896
+ }
897
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
898
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
899
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
900
+ );
901
+ return {
902
+ name: mainFieldName,
903
+ type: mainFieldType ?? "string"
904
+ };
905
+ };
906
+ const DEFAULT_SETTINGS = {
907
+ bulkable: false,
908
+ filterable: false,
909
+ searchable: false,
910
+ pagination: false,
911
+ defaultSortBy: "",
912
+ defaultSortOrder: "asc",
913
+ mainField: "id",
914
+ pageSize: 10
915
+ };
916
+ const useDocumentLayout = (model) => {
917
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
918
+ const [{ query }] = strapiAdmin.useQueryParams();
919
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
781
920
  const { toggleNotification } = strapiAdmin.useNotification();
782
921
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
922
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
783
923
  const {
784
- currentData: data,
785
- isLoading: isLoadingDocument,
786
- isFetching: isFetchingDocument,
787
- error
788
- } = useGetDocumentQuery(args, opts);
789
- const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
924
+ data,
925
+ isLoading: isLoadingConfigs,
926
+ error,
927
+ isFetching: isFetchingConfigs
928
+ } = useGetContentTypeConfigurationQuery(model);
929
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
790
930
  React__namespace.useEffect(() => {
791
931
  if (error) {
792
932
  toggleNotification({
@@ -794,68 +934,321 @@ const useDocument = (args, opts) => {
794
934
  message: formatAPIError(error)
795
935
  });
796
936
  }
797
- }, [toggleNotification, error, formatAPIError, args.collectionType]);
798
- const validationSchema = React__namespace.useMemo(() => {
799
- if (!schema) {
800
- return null;
801
- }
802
- return createYupSchema(schema.attributes, components);
803
- }, [schema, components]);
804
- const validate = React__namespace.useCallback(
805
- (document) => {
806
- if (!validationSchema) {
807
- throw new Error(
808
- "There is no validation schema generated, this is likely due to the schema not being loaded yet."
809
- );
810
- }
811
- try {
812
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
813
- return null;
814
- } catch (error2) {
815
- if (error2 instanceof yup.ValidationError) {
816
- return strapiAdmin.getYupValidationErrors(error2);
817
- }
818
- throw error2;
819
- }
937
+ }, [error, formatAPIError, toggleNotification]);
938
+ const editLayout = React__namespace.useMemo(
939
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
940
+ layout: [],
941
+ components: {},
942
+ metadatas: {},
943
+ options: {},
944
+ settings: DEFAULT_SETTINGS
820
945
  },
821
- [validationSchema]
946
+ [data, isLoading, schemas, schema, components]
947
+ );
948
+ const listLayout = React__namespace.useMemo(() => {
949
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
950
+ layout: [],
951
+ metadatas: {},
952
+ options: {},
953
+ settings: DEFAULT_SETTINGS
954
+ };
955
+ }, [data, isLoading, schemas, schema, components]);
956
+ const { layout: edit } = React__namespace.useMemo(
957
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
958
+ layout: editLayout,
959
+ query
960
+ }),
961
+ [editLayout, query, runHookWaterfall]
822
962
  );
823
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
824
963
  return {
825
- components,
826
- document: data?.data,
827
- meta: data?.meta,
964
+ error,
828
965
  isLoading,
829
- schema,
830
- validate
966
+ edit,
967
+ list: listLayout
831
968
  };
832
969
  };
833
- const useDoc = () => {
834
- const { id, slug, collectionType, origin } = reactRouterDom.useParams();
835
- const [{ query }] = strapiAdmin.useQueryParams();
836
- const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
837
- if (!collectionType) {
838
- throw new Error("Could not find collectionType in url params");
839
- }
840
- if (!slug) {
970
+ const useDocLayout = () => {
971
+ const { model } = useDoc();
972
+ return useDocumentLayout(model);
973
+ };
974
+ const formatEditLayout = (data, {
975
+ schemas,
976
+ schema,
977
+ components
978
+ }) => {
979
+ let currentPanelIndex = 0;
980
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
981
+ data.contentType.layouts.edit,
982
+ schema?.attributes,
983
+ data.contentType.metadatas,
984
+ { configurations: data.components, schemas: components },
985
+ schemas
986
+ ).reduce((panels, row) => {
987
+ if (row.some((field) => field.type === "dynamiczone")) {
988
+ panels.push([row]);
989
+ currentPanelIndex += 2;
990
+ } else {
991
+ if (!panels[currentPanelIndex]) {
992
+ panels.push([]);
993
+ }
994
+ panels[currentPanelIndex].push(row);
995
+ }
996
+ return panels;
997
+ }, []);
998
+ const componentEditAttributes = Object.entries(data.components).reduce(
999
+ (acc, [uid, configuration]) => {
1000
+ acc[uid] = {
1001
+ layout: convertEditLayoutToFieldLayouts(
1002
+ configuration.layouts.edit,
1003
+ components[uid].attributes,
1004
+ configuration.metadatas,
1005
+ { configurations: data.components, schemas: components }
1006
+ ),
1007
+ settings: {
1008
+ ...configuration.settings,
1009
+ icon: components[uid].info.icon,
1010
+ displayName: components[uid].info.displayName
1011
+ }
1012
+ };
1013
+ return acc;
1014
+ },
1015
+ {}
1016
+ );
1017
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
1018
+ (acc, [attribute, metadata]) => {
1019
+ return {
1020
+ ...acc,
1021
+ [attribute]: metadata.edit
1022
+ };
1023
+ },
1024
+ {}
1025
+ );
1026
+ return {
1027
+ layout: panelledEditAttributes,
1028
+ components: componentEditAttributes,
1029
+ metadatas: editMetadatas,
1030
+ settings: {
1031
+ ...data.contentType.settings,
1032
+ displayName: schema?.info.displayName
1033
+ },
1034
+ options: {
1035
+ ...schema?.options,
1036
+ ...schema?.pluginOptions,
1037
+ ...data.contentType.options
1038
+ }
1039
+ };
1040
+ };
1041
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1042
+ return rows.map(
1043
+ (row) => row.map((field) => {
1044
+ const attribute = attributes[field.name];
1045
+ if (!attribute) {
1046
+ return null;
1047
+ }
1048
+ const { edit: metadata } = metadatas[field.name];
1049
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1050
+ return {
1051
+ attribute,
1052
+ disabled: !metadata.editable,
1053
+ hint: metadata.description,
1054
+ label: metadata.label ?? "",
1055
+ name: field.name,
1056
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1057
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1058
+ schemas,
1059
+ components: components?.schemas ?? {}
1060
+ }),
1061
+ placeholder: metadata.placeholder ?? "",
1062
+ required: attribute.required ?? false,
1063
+ size: field.size,
1064
+ unique: "unique" in attribute ? attribute.unique : false,
1065
+ visible: metadata.visible ?? true,
1066
+ type: attribute.type
1067
+ };
1068
+ }).filter((field) => field !== null)
1069
+ );
1070
+ };
1071
+ const formatListLayout = (data, {
1072
+ schemas,
1073
+ schema,
1074
+ components
1075
+ }) => {
1076
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1077
+ (acc, [attribute, metadata]) => {
1078
+ return {
1079
+ ...acc,
1080
+ [attribute]: metadata.list
1081
+ };
1082
+ },
1083
+ {}
1084
+ );
1085
+ const listAttributes = convertListLayoutToFieldLayouts(
1086
+ data.contentType.layouts.list,
1087
+ schema?.attributes,
1088
+ listMetadatas,
1089
+ { configurations: data.components, schemas: components },
1090
+ schemas
1091
+ );
1092
+ return {
1093
+ layout: listAttributes,
1094
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1095
+ metadatas: listMetadatas,
1096
+ options: {
1097
+ ...schema?.options,
1098
+ ...schema?.pluginOptions,
1099
+ ...data.contentType.options
1100
+ }
1101
+ };
1102
+ };
1103
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1104
+ return columns.map((name) => {
1105
+ const attribute = attributes[name];
1106
+ if (!attribute) {
1107
+ return null;
1108
+ }
1109
+ const metadata = metadatas[name];
1110
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1111
+ return {
1112
+ attribute,
1113
+ label: metadata.label ?? "",
1114
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1115
+ schemas,
1116
+ components: components?.schemas ?? {}
1117
+ }),
1118
+ name,
1119
+ searchable: metadata.searchable ?? true,
1120
+ sortable: metadata.sortable ?? true
1121
+ };
1122
+ }).filter((field) => field !== null);
1123
+ };
1124
+ const useDocument = (args, opts) => {
1125
+ const { toggleNotification } = strapiAdmin.useNotification();
1126
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1127
+ const {
1128
+ currentData: data,
1129
+ isLoading: isLoadingDocument,
1130
+ isFetching: isFetchingDocument,
1131
+ error
1132
+ } = useGetDocumentQuery(args, {
1133
+ ...opts,
1134
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1135
+ });
1136
+ const {
1137
+ components,
1138
+ schema,
1139
+ schemas,
1140
+ isLoading: isLoadingSchema
1141
+ } = useContentTypeSchema(args.model);
1142
+ React__namespace.useEffect(() => {
1143
+ if (error) {
1144
+ toggleNotification({
1145
+ type: "danger",
1146
+ message: formatAPIError(error)
1147
+ });
1148
+ }
1149
+ }, [toggleNotification, error, formatAPIError, args.collectionType]);
1150
+ const validationSchema = React__namespace.useMemo(() => {
1151
+ if (!schema) {
1152
+ return null;
1153
+ }
1154
+ return createYupSchema(schema.attributes, components);
1155
+ }, [schema, components]);
1156
+ const validate = React__namespace.useCallback(
1157
+ (document) => {
1158
+ if (!validationSchema) {
1159
+ throw new Error(
1160
+ "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1161
+ );
1162
+ }
1163
+ try {
1164
+ validationSchema.validateSync(document, { abortEarly: false, strict: true });
1165
+ return null;
1166
+ } catch (error2) {
1167
+ if (error2 instanceof yup.ValidationError) {
1168
+ return strapiAdmin.getYupValidationErrors(error2);
1169
+ }
1170
+ throw error2;
1171
+ }
1172
+ },
1173
+ [validationSchema]
1174
+ );
1175
+ const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1176
+ const hasError = !!error;
1177
+ return {
1178
+ components,
1179
+ document: data?.data,
1180
+ meta: data?.meta,
1181
+ isLoading,
1182
+ hasError,
1183
+ schema,
1184
+ schemas,
1185
+ validate
1186
+ };
1187
+ };
1188
+ const useDoc = () => {
1189
+ const { id, slug, collectionType, origin } = reactRouterDom.useParams();
1190
+ const [{ query }] = strapiAdmin.useQueryParams();
1191
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1192
+ if (!collectionType) {
1193
+ throw new Error("Could not find collectionType in url params");
1194
+ }
1195
+ if (!slug) {
841
1196
  throw new Error("Could not find model in url params");
842
1197
  }
1198
+ const document = useDocument(
1199
+ { documentId: origin || id, model: slug, collectionType, params },
1200
+ {
1201
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1202
+ }
1203
+ );
1204
+ const returnId = origin || id === "create" ? void 0 : id;
843
1205
  return {
844
1206
  collectionType,
845
1207
  model: slug,
846
- id: origin || id === "create" ? void 0 : id,
847
- ...useDocument(
848
- { documentId: origin || id, model: slug, collectionType, params },
849
- {
850
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
851
- }
852
- )
1208
+ id: returnId,
1209
+ ...document
1210
+ };
1211
+ };
1212
+ const useContentManagerContext = () => {
1213
+ const {
1214
+ collectionType,
1215
+ model,
1216
+ id,
1217
+ components,
1218
+ isLoading: isLoadingDoc,
1219
+ schema,
1220
+ schemas
1221
+ } = useDoc();
1222
+ const layout = useDocumentLayout(model);
1223
+ const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
1224
+ const isSingleType = collectionType === SINGLE_TYPES;
1225
+ const slug = model;
1226
+ const isCreatingEntry = id === "create";
1227
+ useContentTypeSchema();
1228
+ const isLoading = isLoadingDoc || layout.isLoading;
1229
+ const error = layout.error;
1230
+ return {
1231
+ error,
1232
+ isLoading,
1233
+ // Base metadata
1234
+ model,
1235
+ collectionType,
1236
+ id,
1237
+ slug,
1238
+ isCreatingEntry,
1239
+ isSingleType,
1240
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1241
+ // All schema infos
1242
+ components,
1243
+ contentType: schema,
1244
+ contentTypes: schemas,
1245
+ // Form state
1246
+ form,
1247
+ // layout infos
1248
+ layout
853
1249
  };
854
1250
  };
855
1251
  const prefixPluginTranslations = (trad, pluginId) => {
856
- if (!pluginId) {
857
- throw new TypeError("pluginId can't be empty");
858
- }
859
1252
  return Object.keys(trad).reduce((acc, current) => {
860
1253
  acc[`${pluginId}.${current}`] = trad[current];
861
1254
  return acc;
@@ -871,6 +1264,8 @@ const useDocumentActions = () => {
871
1264
  const { formatMessage } = reactIntl.useIntl();
872
1265
  const { trackUsage } = strapiAdmin.useTracking();
873
1266
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1267
+ const navigate = reactRouterDom.useNavigate();
1268
+ const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
874
1269
  const [deleteDocument] = useDeleteDocumentMutation();
875
1270
  const _delete = React__namespace.useCallback(
876
1271
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -1185,6 +1580,7 @@ const useDocumentActions = () => {
1185
1580
  defaultMessage: "Saved document"
1186
1581
  })
1187
1582
  });
1583
+ setCurrentStep("contentManager.success");
1188
1584
  return res.data;
1189
1585
  } catch (err) {
1190
1586
  toggleNotification({
@@ -1206,7 +1602,6 @@ const useDocumentActions = () => {
1206
1602
  sourceId
1207
1603
  });
1208
1604
  if ("error" in res) {
1209
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1210
1605
  return { error: res.error };
1211
1606
  }
1212
1607
  toggleNotification({
@@ -1225,7 +1620,7 @@ const useDocumentActions = () => {
1225
1620
  throw err;
1226
1621
  }
1227
1622
  },
1228
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1623
+ [autoCloneDocument, formatMessage, toggleNotification]
1229
1624
  );
1230
1625
  const [cloneDocument] = useCloneDocumentMutation();
1231
1626
  const clone = React__namespace.useCallback(
@@ -1251,6 +1646,7 @@ const useDocumentActions = () => {
1251
1646
  defaultMessage: "Cloned document"
1252
1647
  })
1253
1648
  });
1649
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1254
1650
  return res.data;
1255
1651
  } catch (err) {
1256
1652
  toggleNotification({
@@ -1261,7 +1657,7 @@ const useDocumentActions = () => {
1261
1657
  throw err;
1262
1658
  }
1263
1659
  },
1264
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1660
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1265
1661
  );
1266
1662
  const [getDoc] = useLazyGetDocumentQuery();
1267
1663
  const getDocument = React__namespace.useCallback(
@@ -1287,7 +1683,7 @@ const useDocumentActions = () => {
1287
1683
  };
1288
1684
  };
1289
1685
  const ProtectedHistoryPage = React.lazy(
1290
- () => Promise.resolve().then(() => require("./History-CqN6K7SX.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1686
+ () => Promise.resolve().then(() => require("./History-B-Mrquzu.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1291
1687
  );
1292
1688
  const routes$1 = [
1293
1689
  {
@@ -1300,31 +1696,31 @@ const routes$1 = [
1300
1696
  }
1301
1697
  ];
1302
1698
  const ProtectedEditViewPage = React.lazy(
1303
- () => Promise.resolve().then(() => require("./EditViewPage-zT3fBr4Y.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1699
+ () => Promise.resolve().then(() => require("./EditViewPage-BMVgUNOX.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1304
1700
  );
1305
1701
  const ProtectedListViewPage = React.lazy(
1306
- () => Promise.resolve().then(() => require("./ListViewPage-pEw_zug9.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1702
+ () => Promise.resolve().then(() => require("./ListViewPage-q0SHVPUS.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1307
1703
  );
1308
1704
  const ProtectedListConfiguration = React.lazy(
1309
- () => Promise.resolve().then(() => require("./ListConfigurationPage-R_p-SbHZ.js")).then((mod) => ({
1705
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-C0n4rUzH.js")).then((mod) => ({
1310
1706
  default: mod.ProtectedListConfiguration
1311
1707
  }))
1312
1708
  );
1313
1709
  const ProtectedEditConfigurationPage = React.lazy(
1314
- () => Promise.resolve().then(() => require("./EditConfigurationPage-DjFJw56M.js")).then((mod) => ({
1710
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-BPgoE-kf.js")).then((mod) => ({
1315
1711
  default: mod.ProtectedEditConfigurationPage
1316
1712
  }))
1317
1713
  );
1318
1714
  const ProtectedComponentConfigurationPage = React.lazy(
1319
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-C-49MccQ.js")).then((mod) => ({
1715
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-CO977CPh.js")).then((mod) => ({
1320
1716
  default: mod.ProtectedComponentConfigurationPage
1321
1717
  }))
1322
1718
  );
1323
1719
  const NoPermissions = React.lazy(
1324
- () => Promise.resolve().then(() => require("./NoPermissionsPage-BtPrImPP.js")).then((mod) => ({ default: mod.NoPermissions }))
1720
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-BGBpj_Y1.js")).then((mod) => ({ default: mod.NoPermissions }))
1325
1721
  );
1326
1722
  const NoContentType = React.lazy(
1327
- () => Promise.resolve().then(() => require("./NoContentTypePage-C5dcQojD.js")).then((mod) => ({ default: mod.NoContentType }))
1723
+ () => Promise.resolve().then(() => require("./NoContentTypePage-Bh3komDV.js")).then((mod) => ({ default: mod.NoContentType }))
1328
1724
  );
1329
1725
  const CollectionTypePages = () => {
1330
1726
  const { collectionType } = reactRouterDom.useParams();
@@ -1438,12 +1834,14 @@ const DocumentActionButton = (action) => {
1438
1834
  /* @__PURE__ */ jsxRuntime.jsx(
1439
1835
  designSystem.Button,
1440
1836
  {
1441
- flex: 1,
1837
+ flex: "auto",
1442
1838
  startIcon: action.icon,
1443
1839
  disabled: action.disabled,
1444
1840
  onClick: handleClick(action),
1445
1841
  justifyContent: "center",
1446
1842
  variant: action.variant || "default",
1843
+ paddingTop: "7px",
1844
+ paddingBottom: "7px",
1447
1845
  children: action.label
1448
1846
  }
1449
1847
  ),
@@ -1451,7 +1849,7 @@ const DocumentActionButton = (action) => {
1451
1849
  DocumentActionConfirmDialog,
1452
1850
  {
1453
1851
  ...action.dialog,
1454
- variant: action.variant,
1852
+ variant: action.dialog?.variant ?? action.variant,
1455
1853
  isOpen: dialogId === action.id,
1456
1854
  onClose: handleClose
1457
1855
  }
@@ -1508,9 +1906,9 @@ const DocumentActionsMenu = ({
1508
1906
  disabled: isDisabled,
1509
1907
  size: "S",
1510
1908
  endIcon: null,
1511
- paddingTop: "7px",
1512
- paddingLeft: "9px",
1513
- paddingRight: "9px",
1909
+ paddingTop: "4px",
1910
+ paddingLeft: "7px",
1911
+ paddingRight: "7px",
1514
1912
  variant,
1515
1913
  children: [
1516
1914
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
@@ -1521,7 +1919,7 @@ const DocumentActionsMenu = ({
1521
1919
  ]
1522
1920
  }
1523
1921
  ),
1524
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1922
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1525
1923
  actions2.map((action) => {
1526
1924
  return /* @__PURE__ */ jsxRuntime.jsx(
1527
1925
  designSystem.Menu.Item,
@@ -1530,10 +1928,25 @@ const DocumentActionsMenu = ({
1530
1928
  onSelect: handleClick(action),
1531
1929
  display: "block",
1532
1930
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1533
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1534
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1535
- action.label
1536
- ] }),
1931
+ /* @__PURE__ */ jsxRuntime.jsxs(
1932
+ designSystem.Flex,
1933
+ {
1934
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1935
+ gap: 2,
1936
+ tag: "span",
1937
+ children: [
1938
+ /* @__PURE__ */ jsxRuntime.jsx(
1939
+ designSystem.Flex,
1940
+ {
1941
+ tag: "span",
1942
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1943
+ children: action.icon
1944
+ }
1945
+ ),
1946
+ action.label
1947
+ ]
1948
+ }
1949
+ ),
1537
1950
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
1538
1951
  designSystem.Flex,
1539
1952
  {
@@ -1630,11 +2043,11 @@ const DocumentActionConfirmDialog = ({
1630
2043
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
1631
2044
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
1632
2045
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
1633
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
2046
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
1634
2047
  id: "app.components.Button.cancel",
1635
2048
  defaultMessage: "Cancel"
1636
2049
  }) }) }),
1637
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
2050
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
1638
2051
  id: "app.components.Button.confirm",
1639
2052
  defaultMessage: "Confirm"
1640
2053
  }) })
@@ -1673,13 +2086,17 @@ const PublishAction$1 = ({
1673
2086
  const navigate = reactRouterDom.useNavigate();
1674
2087
  const { toggleNotification } = strapiAdmin.useNotification();
1675
2088
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
2089
+ const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
1676
2090
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
1677
2091
  const { formatMessage } = reactIntl.useIntl();
1678
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1679
- "PublishAction",
1680
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1681
- );
2092
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1682
2093
  const { publish } = useDocumentActions();
2094
+ const [
2095
+ countDraftRelations,
2096
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
2097
+ ] = useLazyGetDraftRelationCountQuery();
2098
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
2099
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
1683
2100
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1684
2101
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1685
2102
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1688,62 +2105,144 @@ const PublishAction$1 = ({
1688
2105
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1689
2106
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1690
2107
  const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
1691
- const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1692
- if (!schema?.options?.draftAndPublish) {
1693
- return null;
1694
- }
1695
- return {
1696
- /**
1697
- * Disabled when:
1698
- * - currently if you're cloning a document we don't support publish & clone at the same time.
1699
- * - the form is submitting
1700
- * - the active tab is the published tab
1701
- * - the document is already published & not modified
2108
+ React__namespace.useEffect(() => {
2109
+ if (isErrorDraftRelations) {
2110
+ toggleNotification({
2111
+ type: "danger",
2112
+ message: formatMessage({
2113
+ id: getTranslation("error.records.fetch-draft-relatons"),
2114
+ defaultMessage: "An error occurred while fetching draft relations on this document."
2115
+ })
2116
+ });
2117
+ }
2118
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
2119
+ React__namespace.useEffect(() => {
2120
+ const localDraftRelations = /* @__PURE__ */ new Set();
2121
+ const extractDraftRelations = (data) => {
2122
+ const relations = data.connect || [];
2123
+ relations.forEach((relation) => {
2124
+ if (relation.status === "draft") {
2125
+ localDraftRelations.add(relation.id);
2126
+ }
2127
+ });
2128
+ };
2129
+ const traverseAndExtract = (data) => {
2130
+ Object.entries(data).forEach(([key, value]) => {
2131
+ if (key === "connect" && Array.isArray(value)) {
2132
+ extractDraftRelations({ connect: value });
2133
+ } else if (typeof value === "object" && value !== null) {
2134
+ traverseAndExtract(value);
2135
+ }
2136
+ });
2137
+ };
2138
+ if (!documentId || modified) {
2139
+ traverseAndExtract(formValues);
2140
+ setLocalCountOfDraftRelations(localDraftRelations.size);
2141
+ }
2142
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
2143
+ React__namespace.useEffect(() => {
2144
+ if (!document || !document.documentId || isListView) {
2145
+ return;
2146
+ }
2147
+ const fetchDraftRelationsCount = async () => {
2148
+ const { data, error } = await countDraftRelations({
2149
+ collectionType,
2150
+ model,
2151
+ documentId,
2152
+ params
2153
+ });
2154
+ if (error) {
2155
+ throw error;
2156
+ }
2157
+ if (data) {
2158
+ setServerCountOfDraftRelations(data.data);
2159
+ }
2160
+ };
2161
+ fetchDraftRelationsCount();
2162
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
2163
+ const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
2164
+ if (!schema?.options?.draftAndPublish) {
2165
+ return null;
2166
+ }
2167
+ const performPublish = async () => {
2168
+ setSubmitting(true);
2169
+ try {
2170
+ const { errors } = await validate(true, {
2171
+ status: "published"
2172
+ });
2173
+ if (errors) {
2174
+ toggleNotification({
2175
+ type: "danger",
2176
+ message: formatMessage({
2177
+ id: "content-manager.validation.error",
2178
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2179
+ })
2180
+ });
2181
+ return;
2182
+ }
2183
+ const res = await publish(
2184
+ {
2185
+ collectionType,
2186
+ model,
2187
+ documentId,
2188
+ params
2189
+ },
2190
+ formValues
2191
+ );
2192
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2193
+ navigate({
2194
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2195
+ search: rawQuery
2196
+ });
2197
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2198
+ setErrors(formatValidationErrors(res.error));
2199
+ }
2200
+ } finally {
2201
+ setSubmitting(false);
2202
+ }
2203
+ };
2204
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
2205
+ const enableDraftRelationsCount = false;
2206
+ const hasDraftRelations = enableDraftRelationsCount;
2207
+ return {
2208
+ /**
2209
+ * Disabled when:
2210
+ * - currently if you're cloning a document we don't support publish & clone at the same time.
2211
+ * - the form is submitting
2212
+ * - the active tab is the published tab
2213
+ * - the document is already published & not modified
1702
2214
  * - the document is being created & not modified
1703
2215
  * - the user doesn't have the permission to publish
1704
- * - the user doesn't have the permission to create a new document
1705
- * - the user doesn't have the permission to update the document
1706
2216
  */
1707
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2217
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1708
2218
  label: formatMessage({
1709
2219
  id: "app.utils.publish",
1710
2220
  defaultMessage: "Publish"
1711
2221
  }),
1712
2222
  onClick: async () => {
1713
- setSubmitting(true);
1714
- try {
1715
- const { errors } = await validate();
1716
- if (errors) {
1717
- toggleNotification({
1718
- type: "danger",
1719
- message: formatMessage({
1720
- id: "content-manager.validation.error",
1721
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1722
- })
1723
- });
1724
- return;
1725
- }
1726
- const res = await publish(
1727
- {
1728
- collectionType,
1729
- model,
1730
- documentId,
1731
- params
1732
- },
1733
- formValues
1734
- );
1735
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1736
- navigate({
1737
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1738
- search: rawQuery
1739
- });
1740
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1741
- setErrors(formatValidationErrors(res.error));
2223
+ await performPublish();
2224
+ },
2225
+ dialog: hasDraftRelations ? {
2226
+ type: "dialog",
2227
+ variant: "danger",
2228
+ footer: null,
2229
+ title: formatMessage({
2230
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
2231
+ defaultMessage: "Confirmation"
2232
+ }),
2233
+ content: formatMessage(
2234
+ {
2235
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2236
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
2237
+ },
2238
+ {
2239
+ count: totalDraftRelations
1742
2240
  }
1743
- } finally {
1744
- setSubmitting(false);
2241
+ ),
2242
+ onConfirm: async () => {
2243
+ await performPublish();
1745
2244
  }
1746
- }
2245
+ } : void 0
1747
2246
  };
1748
2247
  };
1749
2248
  PublishAction$1.type = "publish";
@@ -1759,10 +2258,6 @@ const UpdateAction = ({
1759
2258
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1760
2259
  const isCloning = cloneMatch !== null;
1761
2260
  const { formatMessage } = reactIntl.useIntl();
1762
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1763
- canCreate: canCreate2,
1764
- canUpdate: canUpdate2
1765
- }));
1766
2261
  const { create, update, clone } = useDocumentActions();
1767
2262
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1768
2263
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1779,10 +2274,8 @@ const UpdateAction = ({
1779
2274
  * - the form is submitting
1780
2275
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1781
2276
  * - the active tab is the published tab
1782
- * - the user doesn't have the permission to create a new document
1783
- * - the user doesn't have the permission to update the document
1784
2277
  */
1785
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
2278
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1786
2279
  label: formatMessage({
1787
2280
  id: "content-manager.containers.Edit.save",
1788
2281
  defaultMessage: "Save"
@@ -1790,7 +2283,9 @@ const UpdateAction = ({
1790
2283
  onClick: async () => {
1791
2284
  setSubmitting(true);
1792
2285
  try {
1793
- const { errors } = await validate();
2286
+ const { errors } = await validate(true, {
2287
+ status: "draft"
2288
+ });
1794
2289
  if (errors) {
1795
2290
  toggleNotification({
1796
2291
  type: "danger",
@@ -1811,10 +2306,13 @@ const UpdateAction = ({
1811
2306
  document
1812
2307
  );
1813
2308
  if ("data" in res) {
1814
- navigate({
1815
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1816
- search: rawQuery
1817
- });
2309
+ navigate(
2310
+ {
2311
+ pathname: `../${res.data.documentId}`,
2312
+ search: rawQuery
2313
+ },
2314
+ { relative: "path" }
2315
+ );
1818
2316
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1819
2317
  setErrors(formatValidationErrors(res.error));
1820
2318
  }
@@ -1842,10 +2340,13 @@ const UpdateAction = ({
1842
2340
  document
1843
2341
  );
1844
2342
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1845
- navigate({
1846
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1847
- search: rawQuery
1848
- });
2343
+ navigate(
2344
+ {
2345
+ pathname: `../${res.data.documentId}`,
2346
+ search: rawQuery
2347
+ },
2348
+ { replace: true, relative: "path" }
2349
+ );
1849
2350
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1850
2351
  setErrors(formatValidationErrors(res.error));
1851
2352
  }
@@ -1889,7 +2390,7 @@ const UnpublishAction$1 = ({
1889
2390
  id: "app.utils.unpublish",
1890
2391
  defaultMessage: "Unpublish"
1891
2392
  }),
1892
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2393
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
1893
2394
  onClick: async () => {
1894
2395
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1895
2396
  if (!documentId) {
@@ -2001,7 +2502,7 @@ const DiscardAction = ({
2001
2502
  id: "content-manager.actions.discard.label",
2002
2503
  defaultMessage: "Discard changes"
2003
2504
  }),
2004
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2505
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
2005
2506
  position: ["panel", "table-row"],
2006
2507
  variant: "danger",
2007
2508
  dialog: {
@@ -2029,11 +2530,6 @@ const DiscardAction = ({
2029
2530
  };
2030
2531
  };
2031
2532
  DiscardAction.type = "discard";
2032
- const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
2033
- path {
2034
- fill: currentColor;
2035
- }
2036
- `;
2037
2533
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2038
2534
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2039
2535
  const RelativeTime = React__namespace.forwardRef(
@@ -2081,7 +2577,7 @@ const getDisplayName = ({
2081
2577
  };
2082
2578
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2083
2579
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2084
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
2580
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2085
2581
  return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2086
2582
  };
2087
2583
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
@@ -2091,23 +2587,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2091
2587
  id: "content-manager.containers.edit.title.new",
2092
2588
  defaultMessage: "Create an entry"
2093
2589
  }) : documentTitle;
2094
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2590
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2095
2591
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
2096
- /* @__PURE__ */ jsxRuntime.jsxs(
2097
- designSystem.Flex,
2098
- {
2099
- width: "100%",
2100
- justifyContent: "space-between",
2101
- paddingTop: 1,
2102
- gap: "80px",
2103
- alignItems: "flex-start",
2104
- children: [
2105
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2106
- /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2107
- ]
2108
- }
2109
- ),
2110
- status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2592
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2593
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2594
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2595
+ ] }),
2596
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2111
2597
  ] });
2112
2598
  };
2113
2599
  const HeaderToolbar = () => {
@@ -2190,12 +2676,12 @@ const Information = ({ activeTab }) => {
2190
2676
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2191
2677
  label: formatMessage({
2192
2678
  id: "content-manager.containers.edit.information.last-published.label",
2193
- defaultMessage: "Last published"
2679
+ defaultMessage: "Published"
2194
2680
  }),
2195
2681
  value: formatMessage(
2196
2682
  {
2197
2683
  id: "content-manager.containers.edit.information.last-published.value",
2198
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2684
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2199
2685
  },
2200
2686
  {
2201
2687
  time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2208,12 +2694,12 @@ const Information = ({ activeTab }) => {
2208
2694
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2209
2695
  label: formatMessage({
2210
2696
  id: "content-manager.containers.edit.information.last-draft.label",
2211
- defaultMessage: "Last draft"
2697
+ defaultMessage: "Updated"
2212
2698
  }),
2213
2699
  value: formatMessage(
2214
2700
  {
2215
2701
  id: "content-manager.containers.edit.information.last-draft.value",
2216
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2702
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2217
2703
  },
2218
2704
  {
2219
2705
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2231,12 +2717,12 @@ const Information = ({ activeTab }) => {
2231
2717
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2232
2718
  label: formatMessage({
2233
2719
  id: "content-manager.containers.edit.information.document.label",
2234
- defaultMessage: "Document"
2720
+ defaultMessage: "Created"
2235
2721
  }),
2236
2722
  value: formatMessage(
2237
2723
  {
2238
2724
  id: "content-manager.containers.edit.information.document.value",
2239
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2725
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2240
2726
  },
2241
2727
  {
2242
2728
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2274,25 +2760,77 @@ const Information = ({ activeTab }) => {
2274
2760
  );
2275
2761
  };
2276
2762
  const HeaderActions = ({ actions: actions2 }) => {
2277
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: actions2.map((action) => {
2278
- if ("options" in action) {
2763
+ const [dialogId, setDialogId] = React__namespace.useState(null);
2764
+ const handleClick = (action) => async (e) => {
2765
+ if (!("options" in action)) {
2766
+ const { onClick = () => false, dialog, id } = action;
2767
+ const muteDialog = await onClick(e);
2768
+ if (dialog && !muteDialog) {
2769
+ e.preventDefault();
2770
+ setDialogId(id);
2771
+ }
2772
+ }
2773
+ };
2774
+ const handleClose = () => {
2775
+ setDialogId(null);
2776
+ };
2777
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
2778
+ if (action.options) {
2279
2779
  return /* @__PURE__ */ jsxRuntime.jsx(
2280
2780
  designSystem.SingleSelect,
2281
2781
  {
2282
2782
  size: "S",
2283
- disabled: action.disabled,
2284
- "aria-label": action.label,
2285
2783
  onChange: action.onSelect,
2286
- value: action.value,
2784
+ "aria-label": action.label,
2785
+ ...action,
2287
2786
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
2288
2787
  },
2289
2788
  action.id
2290
2789
  );
2291
2790
  } else {
2292
- return null;
2791
+ if (action.type === "icon") {
2792
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
2793
+ /* @__PURE__ */ jsxRuntime.jsx(
2794
+ designSystem.IconButton,
2795
+ {
2796
+ disabled: action.disabled,
2797
+ label: action.label,
2798
+ size: "S",
2799
+ onClick: handleClick(action),
2800
+ children: action.icon
2801
+ }
2802
+ ),
2803
+ action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
2804
+ HeaderActionDialog,
2805
+ {
2806
+ ...action.dialog,
2807
+ isOpen: dialogId === action.id,
2808
+ onClose: handleClose
2809
+ }
2810
+ ) : null
2811
+ ] }, action.id);
2812
+ }
2293
2813
  }
2294
2814
  }) });
2295
2815
  };
2816
+ const HeaderActionDialog = ({
2817
+ onClose,
2818
+ onCancel,
2819
+ title,
2820
+ content: Content,
2821
+ isOpen
2822
+ }) => {
2823
+ const handleClose = async () => {
2824
+ if (onCancel) {
2825
+ await onCancel();
2826
+ }
2827
+ onClose();
2828
+ };
2829
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2830
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
2831
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
2832
+ ] }) });
2833
+ };
2296
2834
  const ConfigureTheViewAction = ({ collectionType, model }) => {
2297
2835
  const navigate = reactRouterDom.useNavigate();
2298
2836
  const { formatMessage } = reactIntl.useIntl();
@@ -2333,12 +2871,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2333
2871
  const { delete: deleteAction } = useDocumentActions();
2334
2872
  const { toggleNotification } = strapiAdmin.useNotification();
2335
2873
  const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
2874
+ const isLocalized = document?.locale != null;
2336
2875
  return {
2337
2876
  disabled: !canDelete || !document,
2338
- label: formatMessage({
2339
- id: "content-manager.actions.delete.label",
2340
- defaultMessage: "Delete document"
2341
- }),
2877
+ label: formatMessage(
2878
+ {
2879
+ id: "content-manager.actions.delete.label",
2880
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2881
+ },
2882
+ { isLocalized }
2883
+ ),
2342
2884
  icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2343
2885
  dialog: {
2344
2886
  type: "dialog",
@@ -2372,425 +2914,123 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2372
2914
  return;
2373
2915
  }
2374
2916
  const res = await deleteAction({
2375
- documentId,
2376
- model,
2377
- collectionType,
2378
- params: {
2379
- locale: "*"
2380
- }
2381
- });
2382
- if (!("error" in res)) {
2383
- navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
2384
- }
2385
- } finally {
2386
- if (!listViewPathMatch) {
2387
- setSubmitting(false);
2388
- }
2389
- }
2390
- }
2391
- },
2392
- variant: "danger",
2393
- position: ["header", "table-row"]
2394
- };
2395
- };
2396
- DeleteAction$1.type = "delete";
2397
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2398
- const Panels = () => {
2399
- const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2400
- const [
2401
- {
2402
- query: { status }
2403
- }
2404
- ] = strapiAdmin.useQueryParams({
2405
- status: "draft"
2406
- });
2407
- const { model, id, document, meta, collectionType } = useDoc();
2408
- const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
2409
- const props = {
2410
- activeTab: status,
2411
- model,
2412
- documentId: id,
2413
- document: isCloning ? void 0 : document,
2414
- meta: isCloning ? void 0 : meta,
2415
- collectionType
2416
- };
2417
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
2418
- strapiAdmin.DescriptionComponentRenderer,
2419
- {
2420
- props,
2421
- descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2422
- children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
2423
- }
2424
- ) });
2425
- };
2426
- const ActionsPanel = () => {
2427
- const { formatMessage } = reactIntl.useIntl();
2428
- return {
2429
- title: formatMessage({
2430
- id: "content-manager.containers.edit.panels.default.title",
2431
- defaultMessage: "Document"
2432
- }),
2433
- content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2434
- };
2435
- };
2436
- ActionsPanel.type = "actions";
2437
- const ActionsPanelContent = () => {
2438
- const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2439
- const [
2440
- {
2441
- query: { status = "draft" }
2442
- }
2443
- ] = strapiAdmin.useQueryParams();
2444
- const { model, id, document, meta, collectionType } = useDoc();
2445
- const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
2446
- const props = {
2447
- activeTab: status,
2448
- model,
2449
- documentId: id,
2450
- document: isCloning ? void 0 : document,
2451
- meta: isCloning ? void 0 : meta,
2452
- collectionType
2453
- };
2454
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
2455
- /* @__PURE__ */ jsxRuntime.jsx(
2456
- strapiAdmin.DescriptionComponentRenderer,
2457
- {
2458
- props,
2459
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2460
- children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
2461
- }
2462
- ),
2463
- /* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
2464
- ] });
2465
- };
2466
- const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2467
- return /* @__PURE__ */ jsxRuntime.jsxs(
2468
- designSystem.Flex,
2469
- {
2470
- ref,
2471
- tag: "aside",
2472
- "aria-labelledby": "additional-information",
2473
- background: "neutral0",
2474
- borderColor: "neutral150",
2475
- hasRadius: true,
2476
- paddingBottom: 4,
2477
- paddingLeft: 4,
2478
- paddingRight: 4,
2479
- paddingTop: 4,
2480
- shadow: "tableShadow",
2481
- gap: 3,
2482
- direction: "column",
2483
- justifyContent: "stretch",
2484
- alignItems: "flex-start",
2485
- children: [
2486
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2487
- children
2488
- ]
2489
- }
2490
- );
2491
- });
2492
- const HOOKS = {
2493
- /**
2494
- * Hook that allows to mutate the displayed headers of the list view table
2495
- * @constant
2496
- * @type {string}
2497
- */
2498
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2499
- /**
2500
- * Hook that allows to mutate the CM's collection types links pre-set filters
2501
- * @constant
2502
- * @type {string}
2503
- */
2504
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2505
- /**
2506
- * Hook that allows to mutate the CM's edit view layout
2507
- * @constant
2508
- * @type {string}
2509
- */
2510
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2511
- /**
2512
- * Hook that allows to mutate the CM's single types links pre-set filters
2513
- * @constant
2514
- * @type {string}
2515
- */
2516
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2517
- };
2518
- const contentTypesApi = contentManagerApi.injectEndpoints({
2519
- endpoints: (builder) => ({
2520
- getContentTypeConfiguration: builder.query({
2521
- query: (uid) => ({
2522
- url: `/content-manager/content-types/${uid}/configuration`,
2523
- method: "GET"
2524
- }),
2525
- transformResponse: (response) => response.data,
2526
- providesTags: (_result, _error, uid) => [
2527
- { type: "ContentTypesConfiguration", id: uid },
2528
- { type: "ContentTypeSettings", id: "LIST" }
2529
- ]
2530
- }),
2531
- getAllContentTypeSettings: builder.query({
2532
- query: () => "/content-manager/content-types-settings",
2533
- transformResponse: (response) => response.data,
2534
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2535
- }),
2536
- updateContentTypeConfiguration: builder.mutation({
2537
- query: ({ uid, ...body }) => ({
2538
- url: `/content-manager/content-types/${uid}/configuration`,
2539
- method: "PUT",
2540
- data: body
2541
- }),
2542
- transformResponse: (response) => response.data,
2543
- invalidatesTags: (_result, _error, { uid }) => [
2544
- { type: "ContentTypesConfiguration", id: uid },
2545
- { type: "ContentTypeSettings", id: "LIST" },
2546
- // Is this necessary?
2547
- { type: "InitialData" }
2548
- ]
2549
- })
2550
- })
2551
- });
2552
- const {
2553
- useGetContentTypeConfigurationQuery,
2554
- useGetAllContentTypeSettingsQuery,
2555
- useUpdateContentTypeConfigurationMutation
2556
- } = contentTypesApi;
2557
- const checkIfAttributeIsDisplayable = (attribute) => {
2558
- const { type } = attribute;
2559
- if (type === "relation") {
2560
- return !attribute.relation.toLowerCase().includes("morph");
2561
- }
2562
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2563
- };
2564
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2565
- if (!mainFieldName) {
2566
- return void 0;
2567
- }
2568
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2569
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2570
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2571
- );
2572
- return {
2573
- name: mainFieldName,
2574
- type: mainFieldType ?? "string"
2575
- };
2576
- };
2577
- const DEFAULT_SETTINGS = {
2578
- bulkable: false,
2579
- filterable: false,
2580
- searchable: false,
2581
- pagination: false,
2582
- defaultSortBy: "",
2583
- defaultSortOrder: "asc",
2584
- mainField: "id",
2585
- pageSize: 10
2586
- };
2587
- const useDocumentLayout = (model) => {
2588
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2589
- const [{ query }] = strapiAdmin.useQueryParams();
2590
- const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2591
- const { toggleNotification } = strapiAdmin.useNotification();
2592
- const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2593
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2594
- const {
2595
- data,
2596
- isLoading: isLoadingConfigs,
2597
- error,
2598
- isFetching: isFetchingConfigs
2599
- } = useGetContentTypeConfigurationQuery(model);
2600
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2601
- React__namespace.useEffect(() => {
2602
- if (error) {
2603
- toggleNotification({
2604
- type: "danger",
2605
- message: formatAPIError(error)
2606
- });
2607
- }
2608
- }, [error, formatAPIError, toggleNotification]);
2609
- const editLayout = React__namespace.useMemo(
2610
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2611
- layout: [],
2612
- components: {},
2613
- metadatas: {},
2614
- options: {},
2615
- settings: DEFAULT_SETTINGS
2616
- },
2617
- [data, isLoading, schemas, schema, components]
2618
- );
2619
- const listLayout = React__namespace.useMemo(() => {
2620
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2621
- layout: [],
2622
- metadatas: {},
2623
- options: {},
2624
- settings: DEFAULT_SETTINGS
2625
- };
2626
- }, [data, isLoading, schemas, schema, components]);
2627
- const { layout: edit } = React__namespace.useMemo(
2628
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2629
- layout: editLayout,
2630
- query
2631
- }),
2632
- [editLayout, query, runHookWaterfall]
2633
- );
2634
- return {
2635
- error,
2636
- isLoading,
2637
- edit,
2638
- list: listLayout
2639
- };
2640
- };
2641
- const useDocLayout = () => {
2642
- const { model } = useDoc();
2643
- return useDocumentLayout(model);
2644
- };
2645
- const formatEditLayout = (data, {
2646
- schemas,
2647
- schema,
2648
- components
2649
- }) => {
2650
- let currentPanelIndex = 0;
2651
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2652
- data.contentType.layouts.edit,
2653
- schema?.attributes,
2654
- data.contentType.metadatas,
2655
- { configurations: data.components, schemas: components },
2656
- schemas
2657
- ).reduce((panels, row) => {
2658
- if (row.some((field) => field.type === "dynamiczone")) {
2659
- panels.push([row]);
2660
- currentPanelIndex += 2;
2661
- } else {
2662
- if (!panels[currentPanelIndex]) {
2663
- panels.push([]);
2664
- }
2665
- panels[currentPanelIndex].push(row);
2666
- }
2667
- return panels;
2668
- }, []);
2669
- const componentEditAttributes = Object.entries(data.components).reduce(
2670
- (acc, [uid, configuration]) => {
2671
- acc[uid] = {
2672
- layout: convertEditLayoutToFieldLayouts(
2673
- configuration.layouts.edit,
2674
- components[uid].attributes,
2675
- configuration.metadatas
2676
- ),
2677
- settings: {
2678
- ...configuration.settings,
2679
- icon: components[uid].info.icon,
2680
- displayName: components[uid].info.displayName
2917
+ documentId,
2918
+ model,
2919
+ collectionType,
2920
+ params: {
2921
+ locale: "*"
2922
+ }
2923
+ });
2924
+ if (!("error" in res)) {
2925
+ navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
2926
+ }
2927
+ } finally {
2928
+ if (!listViewPathMatch) {
2929
+ setSubmitting(false);
2930
+ }
2681
2931
  }
2682
- };
2683
- return acc;
2684
- },
2685
- {}
2686
- );
2687
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2688
- (acc, [attribute, metadata]) => {
2689
- return {
2690
- ...acc,
2691
- [attribute]: metadata.edit
2692
- };
2693
- },
2694
- {}
2695
- );
2696
- return {
2697
- layout: panelledEditAttributes,
2698
- components: componentEditAttributes,
2699
- metadatas: editMetadatas,
2700
- settings: {
2701
- ...data.contentType.settings,
2702
- displayName: schema?.info.displayName
2932
+ }
2703
2933
  },
2704
- options: {
2705
- ...schema?.options,
2706
- ...schema?.pluginOptions,
2707
- ...data.contentType.options
2708
- }
2934
+ variant: "danger",
2935
+ position: ["header", "table-row"]
2709
2936
  };
2710
2937
  };
2711
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2712
- return rows.map(
2713
- (row) => row.map((field) => {
2714
- const attribute = attributes[field.name];
2715
- if (!attribute) {
2716
- return null;
2717
- }
2718
- const { edit: metadata } = metadatas[field.name];
2719
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2720
- return {
2721
- attribute,
2722
- disabled: !metadata.editable,
2723
- hint: metadata.description,
2724
- label: metadata.label ?? "",
2725
- name: field.name,
2726
- // @ts-expect-error – mainField does exist on the metadata for a relation.
2727
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2728
- schemas,
2729
- components: components?.schemas ?? {}
2730
- }),
2731
- placeholder: metadata.placeholder ?? "",
2732
- required: attribute.required ?? false,
2733
- size: field.size,
2734
- unique: "unique" in attribute ? attribute.unique : false,
2735
- visible: metadata.visible ?? true,
2736
- type: attribute.type
2737
- };
2738
- }).filter((field) => field !== null)
2739
- );
2938
+ DeleteAction$1.type = "delete";
2939
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2940
+ const Panels = () => {
2941
+ const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2942
+ const [
2943
+ {
2944
+ query: { status }
2945
+ }
2946
+ ] = strapiAdmin.useQueryParams({
2947
+ status: "draft"
2948
+ });
2949
+ const { model, id, document, meta, collectionType } = useDoc();
2950
+ const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
2951
+ const props = {
2952
+ activeTab: status,
2953
+ model,
2954
+ documentId: id,
2955
+ document: isCloning ? void 0 : document,
2956
+ meta: isCloning ? void 0 : meta,
2957
+ collectionType
2958
+ };
2959
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
2960
+ strapiAdmin.DescriptionComponentRenderer,
2961
+ {
2962
+ props,
2963
+ descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2964
+ children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
2965
+ }
2966
+ ) });
2740
2967
  };
2741
- const formatListLayout = (data, {
2742
- schemas,
2743
- schema,
2744
- components
2745
- }) => {
2746
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2747
- (acc, [attribute, metadata]) => {
2748
- return {
2749
- ...acc,
2750
- [attribute]: metadata.list
2751
- };
2752
- },
2753
- {}
2754
- );
2755
- const listAttributes = convertListLayoutToFieldLayouts(
2756
- data.contentType.layouts.list,
2757
- schema?.attributes,
2758
- listMetadatas,
2759
- { configurations: data.components, schemas: components },
2760
- schemas
2761
- );
2968
+ const ActionsPanel = () => {
2969
+ const { formatMessage } = reactIntl.useIntl();
2762
2970
  return {
2763
- layout: listAttributes,
2764
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2765
- metadatas: listMetadatas,
2766
- options: {
2767
- ...schema?.options,
2768
- ...schema?.pluginOptions,
2769
- ...data.contentType.options
2770
- }
2971
+ title: formatMessage({
2972
+ id: "content-manager.containers.edit.panels.default.title",
2973
+ defaultMessage: "Entry"
2974
+ }),
2975
+ content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2771
2976
  };
2772
2977
  };
2773
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2774
- return columns.map((name) => {
2775
- const attribute = attributes[name];
2776
- if (!attribute) {
2777
- return null;
2978
+ ActionsPanel.type = "actions";
2979
+ const ActionsPanelContent = () => {
2980
+ const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2981
+ const [
2982
+ {
2983
+ query: { status = "draft" }
2778
2984
  }
2779
- const metadata = metadatas[name];
2780
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2781
- return {
2782
- attribute,
2783
- label: metadata.label ?? "",
2784
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2785
- schemas,
2786
- components: components?.schemas ?? {}
2787
- }),
2788
- name,
2789
- searchable: metadata.searchable ?? true,
2790
- sortable: metadata.sortable ?? true
2791
- };
2792
- }).filter((field) => field !== null);
2985
+ ] = strapiAdmin.useQueryParams();
2986
+ const { model, id, document, meta, collectionType } = useDoc();
2987
+ const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
2988
+ const props = {
2989
+ activeTab: status,
2990
+ model,
2991
+ documentId: id,
2992
+ document: isCloning ? void 0 : document,
2993
+ meta: isCloning ? void 0 : meta,
2994
+ collectionType
2995
+ };
2996
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
2997
+ /* @__PURE__ */ jsxRuntime.jsx(
2998
+ strapiAdmin.DescriptionComponentRenderer,
2999
+ {
3000
+ props,
3001
+ descriptions: plugins["content-manager"].apis.getDocumentActions(),
3002
+ children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
3003
+ }
3004
+ ),
3005
+ /* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
3006
+ ] });
2793
3007
  };
3008
+ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
3009
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3010
+ designSystem.Flex,
3011
+ {
3012
+ ref,
3013
+ tag: "aside",
3014
+ "aria-labelledby": "additional-information",
3015
+ background: "neutral0",
3016
+ borderColor: "neutral150",
3017
+ hasRadius: true,
3018
+ paddingBottom: 4,
3019
+ paddingLeft: 4,
3020
+ paddingRight: 4,
3021
+ paddingTop: 4,
3022
+ shadow: "tableShadow",
3023
+ gap: 3,
3024
+ direction: "column",
3025
+ justifyContent: "stretch",
3026
+ alignItems: "flex-start",
3027
+ children: [
3028
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
3029
+ children
3030
+ ]
3031
+ }
3032
+ );
3033
+ });
2794
3034
  const ConfirmBulkActionDialog = ({
2795
3035
  onToggleDialog,
2796
3036
  isOpen = false,
@@ -2798,7 +3038,7 @@ const ConfirmBulkActionDialog = ({
2798
3038
  endAction
2799
3039
  }) => {
2800
3040
  const { formatMessage } = reactIntl.useIntl();
2801
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
3041
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2802
3042
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2803
3043
  id: "app.components.ConfirmDialog.title",
2804
3044
  defaultMessage: "Confirmation"
@@ -2829,6 +3069,7 @@ const ConfirmDialogPublishAll = ({
2829
3069
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2830
3070
  const { model, schema } = useDoc();
2831
3071
  const [{ query }] = strapiAdmin.useQueryParams();
3072
+ const enableDraftRelationsCount = false;
2832
3073
  const {
2833
3074
  data: countDraftRelations = 0,
2834
3075
  isLoading,
@@ -2840,7 +3081,7 @@ const ConfirmDialogPublishAll = ({
2840
3081
  locale: query?.plugins?.i18n?.locale
2841
3082
  },
2842
3083
  {
2843
- skip: selectedEntries.length === 0
3084
+ skip: !enableDraftRelationsCount
2844
3085
  }
2845
3086
  );
2846
3087
  React__namespace.useEffect(() => {
@@ -2919,7 +3160,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2919
3160
  )
2920
3161
  );
2921
3162
  } else {
2922
- messages.push(...formatErrorMessages(value, currentKey, formatMessage));
3163
+ messages.push(
3164
+ ...formatErrorMessages(
3165
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3166
+ value,
3167
+ currentKey,
3168
+ formatMessage
3169
+ )
3170
+ );
2923
3171
  }
2924
3172
  } else {
2925
3173
  messages.push(
@@ -3018,7 +3266,7 @@ const SelectedEntriesTableContent = ({
3018
3266
  status: row.status
3019
3267
  }
3020
3268
  ) }),
3021
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3269
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
3022
3270
  designSystem.IconButton,
3023
3271
  {
3024
3272
  tag: reactRouterDom.Link,
@@ -3041,9 +3289,10 @@ const SelectedEntriesTableContent = ({
3041
3289
  ),
3042
3290
  target: "_blank",
3043
3291
  marginLeft: "auto",
3044
- children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3292
+ variant: "ghost",
3293
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
3045
3294
  }
3046
- ) })
3295
+ ) }) })
3047
3296
  ] }, row.id)) })
3048
3297
  ] });
3049
3298
  };
@@ -3080,7 +3329,13 @@ const SelectedEntriesModalContent = ({
3080
3329
  );
3081
3330
  const { rows, validationErrors } = React__namespace.useMemo(() => {
3082
3331
  if (data.length > 0 && schema) {
3083
- const validate = createYupSchema(schema.attributes, components);
3332
+ const validate = createYupSchema(
3333
+ schema.attributes,
3334
+ components,
3335
+ // Since this is the "Publish" action, the validation
3336
+ // schema must enforce the rules for published entities
3337
+ { status: "published" }
3338
+ );
3084
3339
  const validationErrors2 = {};
3085
3340
  const rows2 = data.map((entry) => {
3086
3341
  try {
@@ -3430,7 +3685,7 @@ const TableActions = ({ document }) => {
3430
3685
  strapiAdmin.DescriptionComponentRenderer,
3431
3686
  {
3432
3687
  props,
3433
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3688
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
3434
3689
  children: (actions2) => {
3435
3690
  const tableRowActions = actions2.filter((action) => {
3436
3691
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3541,7 +3796,7 @@ const CloneAction = ({ model, documentId }) => {
3541
3796
  }),
3542
3797
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3543
3798
  footer: ({ onClose }) => {
3544
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3799
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3545
3800
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3546
3801
  id: "cancel",
3547
3802
  defaultMessage: "Cancel"
@@ -3582,8 +3837,7 @@ class ContentManagerPlugin {
3582
3837
  documentActions = [
3583
3838
  ...DEFAULT_ACTIONS,
3584
3839
  ...DEFAULT_TABLE_ROW_ACTIONS,
3585
- ...DEFAULT_HEADER_ACTIONS,
3586
- HistoryAction
3840
+ ...DEFAULT_HEADER_ACTIONS
3587
3841
  ];
3588
3842
  editViewSidePanels = [ActionsPanel];
3589
3843
  headerActions = [];
@@ -3672,6 +3926,52 @@ const getPrintableType = (value) => {
3672
3926
  }
3673
3927
  return nativeType;
3674
3928
  };
3929
+ const HistoryAction = ({ model, document }) => {
3930
+ const { formatMessage } = reactIntl.useIntl();
3931
+ const [{ query }] = strapiAdmin.useQueryParams();
3932
+ const navigate = reactRouterDom.useNavigate();
3933
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3934
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3935
+ return null;
3936
+ }
3937
+ return {
3938
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3939
+ label: formatMessage({
3940
+ id: "content-manager.history.document-action",
3941
+ defaultMessage: "Content History"
3942
+ }),
3943
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3944
+ disabled: (
3945
+ /**
3946
+ * The user is creating a new document.
3947
+ * It hasn't been saved yet, so there's no history to go to
3948
+ */
3949
+ !document || /**
3950
+ * The document has been created but the current dimension has never been saved.
3951
+ * For example, the user is creating a new locale in an existing document,
3952
+ * so there's no history for the document in that locale
3953
+ */
3954
+ !document.id || /**
3955
+ * History is only available for content types created by the user.
3956
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3957
+ * which start with `admin::` or `plugin::`
3958
+ */
3959
+ !model.startsWith("api::")
3960
+ ),
3961
+ position: "header"
3962
+ };
3963
+ };
3964
+ HistoryAction.type = "history";
3965
+ const historyAdmin = {
3966
+ bootstrap(app) {
3967
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3968
+ addDocumentAction((actions2) => {
3969
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3970
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3971
+ return actions2;
3972
+ });
3973
+ }
3974
+ };
3675
3975
  const initialState = {
3676
3976
  collectionTypeLinks: [],
3677
3977
  components: [],
@@ -3727,7 +4027,7 @@ const index = {
3727
4027
  app.router.addRoute({
3728
4028
  path: "content-manager/*",
3729
4029
  lazy: async () => {
3730
- const { Layout } = await Promise.resolve().then(() => require("./layout-Dm6fbiQj.js"));
4030
+ const { Layout } = await Promise.resolve().then(() => require("./layout-CeBSIkmP.js"));
3731
4031
  return {
3732
4032
  Component: Layout
3733
4033
  };
@@ -3736,10 +4036,15 @@ const index = {
3736
4036
  });
3737
4037
  app.registerPlugin(cm.config);
3738
4038
  },
4039
+ bootstrap(app) {
4040
+ if (typeof historyAdmin.bootstrap === "function") {
4041
+ historyAdmin.bootstrap(app);
4042
+ }
4043
+ },
3739
4044
  async registerTrads({ locales }) {
3740
4045
  const importedTrads = await Promise.all(
3741
4046
  locales.map((locale) => {
3742
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-fbKQxLGn.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
4047
+ 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-Bm0D0IWz.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
3743
4048
  return {
3744
4049
  data: prefixPluginTranslations(data, PLUGIN_ID),
3745
4050
  locale
@@ -3757,6 +4062,7 @@ const index = {
3757
4062
  };
3758
4063
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3759
4064
  exports.BulkActionsRenderer = BulkActionsRenderer;
4065
+ exports.CLONE_PATH = CLONE_PATH;
3760
4066
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3761
4067
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3762
4068
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3784,6 +4090,7 @@ exports.getMainField = getMainField;
3784
4090
  exports.getTranslation = getTranslation;
3785
4091
  exports.index = index;
3786
4092
  exports.setInitialData = setInitialData;
4093
+ exports.useContentManagerContext = useContentManagerContext;
3787
4094
  exports.useContentTypeSchema = useContentTypeSchema;
3788
4095
  exports.useDoc = useDoc;
3789
4096
  exports.useDocLayout = useDocLayout;
@@ -3796,4 +4103,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3796
4103
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3797
4104
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3798
4105
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3799
- //# sourceMappingURL=index-DVPWZkbS.js.map
4106
+ //# sourceMappingURL=index-DbT2sx-Q.js.map