@strapi/content-manager 0.0.0-experimental.32c4b04580cc12400710050c8198e46b3644cfd4 → 0.0.0-experimental.36632203b17974c18103c138ffbef53a82e448c3

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 (193) hide show
  1. package/dist/_chunks/{ComponentConfigurationPage-5ukroXAh.js → ComponentConfigurationPage-Br8hp2Xt.js} +4 -4
  2. package/dist/_chunks/{ComponentConfigurationPage-5ukroXAh.js.map → ComponentConfigurationPage-Br8hp2Xt.js.map} +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-BAgyHiMm.mjs → ComponentConfigurationPage-DhwMhiRn.mjs} +4 -4
  4. package/dist/_chunks/{ComponentConfigurationPage-BAgyHiMm.mjs.map → ComponentConfigurationPage-DhwMhiRn.mjs.map} +1 -1
  5. package/dist/_chunks/{EditConfigurationPage-Xp7lun0f.js → EditConfigurationPage-BG7rpPjL.js} +4 -4
  6. package/dist/_chunks/{EditConfigurationPage-Xp7lun0f.js.map → EditConfigurationPage-BG7rpPjL.js.map} +1 -1
  7. package/dist/_chunks/{EditConfigurationPage-DmoXawIh.mjs → EditConfigurationPage-CWao3CZ3.mjs} +4 -4
  8. package/dist/_chunks/{EditConfigurationPage-DmoXawIh.mjs.map → EditConfigurationPage-CWao3CZ3.mjs.map} +1 -1
  9. package/dist/_chunks/{EditViewPage-C-ukDOB7.js → EditViewPage-BUtpHsMz.js} +38 -11
  10. package/dist/_chunks/EditViewPage-BUtpHsMz.js.map +1 -0
  11. package/dist/_chunks/{EditViewPage-BLsjc5F-.mjs → EditViewPage-hiwZg61J.mjs} +39 -12
  12. package/dist/_chunks/EditViewPage-hiwZg61J.mjs.map +1 -0
  13. package/dist/_chunks/{Field-Cs7duwWd.mjs → Field-BQQLwyUs.mjs} +174 -102
  14. package/dist/_chunks/Field-BQQLwyUs.mjs.map +1 -0
  15. package/dist/_chunks/{Field-Bfph5SOd.js → Field-DEdug-Ll.js} +176 -104
  16. package/dist/_chunks/Field-DEdug-Ll.js.map +1 -0
  17. package/dist/_chunks/{Form-Dg_GS5TQ.mjs → Form-DwJovCha.mjs} +36 -17
  18. package/dist/_chunks/Form-DwJovCha.mjs.map +1 -0
  19. package/dist/_chunks/{Form-CPYqIWDG.js → Form-v5pkY-X_.js} +36 -17
  20. package/dist/_chunks/Form-v5pkY-X_.js.map +1 -0
  21. package/dist/_chunks/{History-DNQkXANT.js → History-40apIShV.js} +37 -47
  22. package/dist/_chunks/History-40apIShV.js.map +1 -0
  23. package/dist/_chunks/{History-wrnHqf09.mjs → History-B9uJsxZl.mjs} +38 -48
  24. package/dist/_chunks/History-B9uJsxZl.mjs.map +1 -0
  25. package/dist/_chunks/{ListConfigurationPage-DScmJVkW.mjs → ListConfigurationPage-CA4oi4Hj.mjs} +15 -5
  26. package/dist/_chunks/ListConfigurationPage-CA4oi4Hj.mjs.map +1 -0
  27. package/dist/_chunks/{ListConfigurationPage-CUQxfpjT.js → ListConfigurationPage-DAGbWDIL.js} +15 -5
  28. package/dist/_chunks/ListConfigurationPage-DAGbWDIL.js.map +1 -0
  29. package/dist/_chunks/{ListViewPage-C4IvrMgY.mjs → ListViewPage-Ca8F1NL-.mjs} +59 -39
  30. package/dist/_chunks/ListViewPage-Ca8F1NL-.mjs.map +1 -0
  31. package/dist/_chunks/{ListViewPage-BsLiH2-2.js → ListViewPage-CjaHQ2_V.js} +61 -41
  32. package/dist/_chunks/ListViewPage-CjaHQ2_V.js.map +1 -0
  33. package/dist/_chunks/{NoContentTypePage-BZ-PnGAf.js → NoContentTypePage-CGxqLI8j.js} +2 -2
  34. package/dist/_chunks/{NoContentTypePage-BZ-PnGAf.js.map → NoContentTypePage-CGxqLI8j.js.map} +1 -1
  35. package/dist/_chunks/{NoContentTypePage-Djg8nPlj.mjs → NoContentTypePage-CwfnU-aN.mjs} +2 -2
  36. package/dist/_chunks/{NoContentTypePage-Djg8nPlj.mjs.map → NoContentTypePage-CwfnU-aN.mjs.map} +1 -1
  37. package/dist/_chunks/{NoPermissionsPage-_lUqjGW3.js → NoPermissionsPage-CY3_QduF.js} +2 -2
  38. package/dist/_chunks/{NoPermissionsPage-_lUqjGW3.js.map → NoPermissionsPage-CY3_QduF.js.map} +1 -1
  39. package/dist/_chunks/{NoPermissionsPage-DSP7R-hv.mjs → NoPermissionsPage-iPk2lFR6.mjs} +2 -2
  40. package/dist/_chunks/{NoPermissionsPage-DSP7R-hv.mjs.map → NoPermissionsPage-iPk2lFR6.mjs.map} +1 -1
  41. package/dist/_chunks/Preview-DRJhcaIO.mjs +267 -0
  42. package/dist/_chunks/Preview-DRJhcaIO.mjs.map +1 -0
  43. package/dist/_chunks/Preview-V8XOfrQf.js +286 -0
  44. package/dist/_chunks/Preview-V8XOfrQf.js.map +1 -0
  45. package/dist/_chunks/{Relations-CtELXYIK.js → Relations-CGerEwji.js} +72 -36
  46. package/dist/_chunks/Relations-CGerEwji.js.map +1 -0
  47. package/dist/_chunks/{Relations-BZr8tL0R.mjs → Relations-DGWa9W2j.mjs} +73 -37
  48. package/dist/_chunks/Relations-DGWa9W2j.mjs.map +1 -0
  49. package/dist/_chunks/{en-uOUIxfcQ.js → en-CHOp_xJv.js} +23 -13
  50. package/dist/_chunks/{en-uOUIxfcQ.js.map → en-CHOp_xJv.js.map} +1 -1
  51. package/dist/_chunks/{en-BrCTWlZv.mjs → en-D_BMf0hT.mjs} +23 -13
  52. package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-D_BMf0hT.mjs.map} +1 -1
  53. package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
  54. package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
  55. package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
  56. package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
  57. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
  58. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
  59. package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
  60. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
  61. package/dist/_chunks/{index-c_5DdJi-.mjs → index-V8MWkDSd.mjs} +987 -727
  62. package/dist/_chunks/index-V8MWkDSd.mjs.map +1 -0
  63. package/dist/_chunks/{index-OerGjbAN.js → index-tN1hpOMN.js} +968 -707
  64. package/dist/_chunks/index-tN1hpOMN.js.map +1 -0
  65. package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
  66. package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
  67. package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
  68. package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
  69. package/dist/_chunks/{layout-oPBiO7RY.mjs → layout-Bue_C6ui.mjs} +22 -9
  70. package/dist/_chunks/layout-Bue_C6ui.mjs.map +1 -0
  71. package/dist/_chunks/{layout-Ci7qHlFb.js → layout-BzX903CL.js} +21 -8
  72. package/dist/_chunks/layout-BzX903CL.js.map +1 -0
  73. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  74. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  75. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  76. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  77. package/dist/_chunks/{relations-COBpStiF.js → relations-C4HcWYYJ.js} +6 -7
  78. package/dist/_chunks/relations-C4HcWYYJ.js.map +1 -0
  79. package/dist/_chunks/{relations-BIdWFjdq.mjs → relations-C8eyDiIO.mjs} +6 -7
  80. package/dist/_chunks/relations-C8eyDiIO.mjs.map +1 -0
  81. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  82. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  83. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  84. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  85. package/dist/admin/index.js +2 -1
  86. package/dist/admin/index.js.map +1 -1
  87. package/dist/admin/index.mjs +5 -4
  88. package/dist/admin/src/exports.d.ts +1 -1
  89. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  90. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  91. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  92. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  93. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  94. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  95. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  96. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  97. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  98. package/dist/admin/src/preview/constants.d.ts +1 -0
  99. package/dist/admin/src/preview/index.d.ts +4 -0
  100. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  101. package/dist/admin/src/preview/routes.d.ts +3 -0
  102. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  103. package/dist/admin/src/services/api.d.ts +1 -1
  104. package/dist/admin/src/services/components.d.ts +2 -2
  105. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  106. package/dist/admin/src/services/documents.d.ts +19 -17
  107. package/dist/admin/src/services/init.d.ts +1 -1
  108. package/dist/admin/src/services/relations.d.ts +2 -2
  109. package/dist/admin/src/services/uid.d.ts +3 -3
  110. package/dist/admin/src/utils/validation.d.ts +4 -1
  111. package/dist/server/index.js +513 -235
  112. package/dist/server/index.js.map +1 -1
  113. package/dist/server/index.mjs +514 -236
  114. package/dist/server/index.mjs.map +1 -1
  115. package/dist/server/src/bootstrap.d.ts.map +1 -1
  116. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  117. package/dist/server/src/controllers/index.d.ts.map +1 -1
  118. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  119. package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
  120. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  121. package/dist/server/src/history/services/history.d.ts.map +1 -1
  122. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  123. package/dist/server/src/history/services/utils.d.ts +4 -4
  124. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  125. package/dist/server/src/index.d.ts +4 -4
  126. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  127. package/dist/server/src/preview/constants.d.ts +2 -0
  128. package/dist/server/src/preview/constants.d.ts.map +1 -0
  129. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  130. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  131. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  132. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  133. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  134. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  135. package/dist/server/src/preview/index.d.ts +4 -0
  136. package/dist/server/src/preview/index.d.ts.map +1 -0
  137. package/dist/server/src/preview/routes/index.d.ts +8 -0
  138. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  139. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  140. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  141. package/dist/server/src/preview/services/index.d.ts +15 -0
  142. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  143. package/dist/server/src/preview/services/preview-config.d.ts +30 -0
  144. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  145. package/dist/server/src/preview/services/preview.d.ts +12 -0
  146. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  147. package/dist/server/src/preview/utils.d.ts +18 -0
  148. package/dist/server/src/preview/utils.d.ts.map +1 -0
  149. package/dist/server/src/routes/index.d.ts.map +1 -1
  150. package/dist/server/src/services/document-metadata.d.ts +8 -8
  151. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  152. package/dist/server/src/services/index.d.ts +4 -4
  153. package/dist/server/src/services/index.d.ts.map +1 -1
  154. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  155. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  156. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  157. package/dist/server/src/utils/index.d.ts +2 -0
  158. package/dist/server/src/utils/index.d.ts.map +1 -1
  159. package/dist/shared/contracts/collection-types.d.ts +3 -1
  160. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  161. package/dist/shared/contracts/index.d.ts +1 -0
  162. package/dist/shared/contracts/index.d.ts.map +1 -1
  163. package/dist/shared/contracts/preview.d.ts +27 -0
  164. package/dist/shared/contracts/preview.d.ts.map +1 -0
  165. package/dist/shared/index.js +4 -0
  166. package/dist/shared/index.js.map +1 -1
  167. package/dist/shared/index.mjs +4 -0
  168. package/dist/shared/index.mjs.map +1 -1
  169. package/package.json +13 -13
  170. package/dist/_chunks/EditViewPage-BLsjc5F-.mjs.map +0 -1
  171. package/dist/_chunks/EditViewPage-C-ukDOB7.js.map +0 -1
  172. package/dist/_chunks/Field-Bfph5SOd.js.map +0 -1
  173. package/dist/_chunks/Field-Cs7duwWd.mjs.map +0 -1
  174. package/dist/_chunks/Form-CPYqIWDG.js.map +0 -1
  175. package/dist/_chunks/Form-Dg_GS5TQ.mjs.map +0 -1
  176. package/dist/_chunks/History-DNQkXANT.js.map +0 -1
  177. package/dist/_chunks/History-wrnHqf09.mjs.map +0 -1
  178. package/dist/_chunks/ListConfigurationPage-CUQxfpjT.js.map +0 -1
  179. package/dist/_chunks/ListConfigurationPage-DScmJVkW.mjs.map +0 -1
  180. package/dist/_chunks/ListViewPage-BsLiH2-2.js.map +0 -1
  181. package/dist/_chunks/ListViewPage-C4IvrMgY.mjs.map +0 -1
  182. package/dist/_chunks/Relations-BZr8tL0R.mjs.map +0 -1
  183. package/dist/_chunks/Relations-CtELXYIK.js.map +0 -1
  184. package/dist/_chunks/index-OerGjbAN.js.map +0 -1
  185. package/dist/_chunks/index-c_5DdJi-.mjs.map +0 -1
  186. package/dist/_chunks/layout-Ci7qHlFb.js.map +0 -1
  187. package/dist/_chunks/layout-oPBiO7RY.mjs.map +0 -1
  188. package/dist/_chunks/relations-BIdWFjdq.mjs.map +0 -1
  189. package/dist/_chunks/relations-COBpStiF.js.map +0 -1
  190. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  191. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  192. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  193. package/strapi-server.js +0 -3
@@ -1,16 +1,17 @@
1
- import { CrossCircle, More, WarningCircle, ListPlus, Pencil, Trash, Check, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, Feather } from "@strapi/icons";
1
+ import { More, Cross, WarningCircle, ListPlus, Pencil, Trash, Check, CrossCircle, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, Feather } from "@strapi/icons";
2
2
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
3
- import { useStrapiApp, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useQueryParams, useTracking, useForm, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
3
+ import { useStrapiApp, createContext, useQueryParams, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useForm, useTracking, useGuidedTour, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
4
4
  import * as React from "react";
5
5
  import { lazy } from "react";
6
- import { Button, Menu, VisuallyHidden, Flex, Box, Typography, Dialog, Modal, Radio, Status, SingleSelect, SingleSelectOption, Loader, IconButton, Tooltip, LinkButton } from "@strapi/design-system";
6
+ import { Button, Menu, VisuallyHidden, Flex, Typography, Dialog, Modal, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
7
+ import mapValues from "lodash/fp/mapValues";
7
8
  import { useIntl } from "react-intl";
8
- import { useParams, Navigate, useNavigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
9
- import { styled } from "styled-components";
9
+ import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
10
10
  import * as yup from "yup";
11
11
  import { ValidationError } from "yup";
12
12
  import pipe from "lodash/fp/pipe";
13
13
  import { intervalToDuration, isPast } from "date-fns";
14
+ import { styled } from "styled-components";
14
15
  import { stringify } from "qs";
15
16
  import { createSlice, combineReducers } from "@reduxjs/toolkit";
16
17
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
@@ -100,6 +101,7 @@ const DocumentRBAC = ({ children, permissions }) => {
100
101
  if (!slug) {
101
102
  throw new Error("Cannot find the slug param in the URL");
102
103
  }
104
+ const [{ rawQuery }] = useQueryParams();
103
105
  const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
104
106
  const contentTypePermissions = React.useMemo(() => {
105
107
  const contentTypePermissions2 = userPermissions.filter(
@@ -110,7 +112,14 @@ const DocumentRBAC = ({ children, permissions }) => {
110
112
  return { ...acc, [action]: [permission] };
111
113
  }, {});
112
114
  }, [slug, userPermissions]);
113
- const { isLoading, allowedActions } = useRBAC(contentTypePermissions, permissions ?? void 0);
115
+ const { isLoading, allowedActions } = useRBAC(
116
+ contentTypePermissions,
117
+ permissions ?? void 0,
118
+ // TODO: useRBAC context should be typed and built differently
119
+ // We are passing raw query as context to the hook so that it can
120
+ // rely on the locale provided from DocumentRBAC for its permission calculations.
121
+ rawQuery
122
+ );
114
123
  const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
115
124
  const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
116
125
  const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
@@ -158,7 +167,8 @@ const contentManagerApi = adminApi.enhanceEndpoints({
158
167
  "Document",
159
168
  "InitialData",
160
169
  "HistoryVersion",
161
- "Relations"
170
+ "Relations",
171
+ "UidAvailability"
162
172
  ]
163
173
  });
164
174
  const documentApi = contentManagerApi.injectEndpoints({
@@ -188,7 +198,10 @@ const documentApi = contentManagerApi.injectEndpoints({
188
198
  params
189
199
  }
190
200
  }),
191
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
201
+ invalidatesTags: (_result, _error, { model }) => [
202
+ { type: "Document", id: `${model}_LIST` },
203
+ { type: "UidAvailability", id: model }
204
+ ]
192
205
  }),
193
206
  /**
194
207
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -205,7 +218,8 @@ const documentApi = contentManagerApi.injectEndpoints({
205
218
  }),
206
219
  invalidatesTags: (result, _error, { model }) => [
207
220
  { type: "Document", id: `${model}_LIST` },
208
- "Relations"
221
+ "Relations",
222
+ { type: "UidAvailability", id: model }
209
223
  ]
210
224
  }),
211
225
  deleteDocument: builder.mutation({
@@ -246,7 +260,8 @@ const documentApi = contentManagerApi.injectEndpoints({
246
260
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
247
261
  },
248
262
  { type: "Document", id: `${model}_LIST` },
249
- "Relations"
263
+ "Relations",
264
+ { type: "UidAvailability", id: model }
250
265
  ];
251
266
  }
252
267
  }),
@@ -264,6 +279,7 @@ const documentApi = contentManagerApi.injectEndpoints({
264
279
  }),
265
280
  providesTags: (result, _error, arg) => {
266
281
  return [
282
+ { type: "Document", id: `ALL_LIST` },
267
283
  { type: "Document", id: `${arg.model}_LIST` },
268
284
  ...result?.results.map(({ documentId }) => ({
269
285
  type: "Document",
@@ -302,6 +318,11 @@ const documentApi = contentManagerApi.injectEndpoints({
302
318
  {
303
319
  type: "Document",
304
320
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
321
+ },
322
+ // Make it easy to invalidate all individual documents queries for a model
323
+ {
324
+ type: "Document",
325
+ id: `${model}_ALL_ITEMS`
305
326
  }
306
327
  ];
307
328
  }
@@ -365,7 +386,8 @@ const documentApi = contentManagerApi.injectEndpoints({
365
386
  type: "Document",
366
387
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
367
388
  },
368
- "Relations"
389
+ "Relations",
390
+ { type: "UidAvailability", id: model }
369
391
  ];
370
392
  },
371
393
  async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
@@ -448,20 +470,39 @@ const buildValidParams = (query) => {
448
470
  const isBaseQueryError = (error) => {
449
471
  return error.name !== void 0;
450
472
  };
451
- const createYupSchema = (attributes = {}, components = {}) => {
473
+ const arrayValidator = (attribute, options) => ({
474
+ message: translatedErrors.required,
475
+ test(value) {
476
+ if (options.status === "draft") {
477
+ return true;
478
+ }
479
+ if (!attribute.required) {
480
+ return true;
481
+ }
482
+ if (!value) {
483
+ return false;
484
+ }
485
+ if (Array.isArray(value) && value.length === 0) {
486
+ return false;
487
+ }
488
+ return true;
489
+ }
490
+ });
491
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
452
492
  const createModelSchema = (attributes2) => yup.object().shape(
453
493
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
454
494
  if (DOCUMENT_META_FIELDS.includes(name)) {
455
495
  return acc;
456
496
  }
457
497
  const validations = [
498
+ addNullableValidation,
458
499
  addRequiredValidation,
459
500
  addMinLengthValidation,
460
501
  addMaxLengthValidation,
461
502
  addMinValidation,
462
503
  addMaxValidation,
463
504
  addRegexValidation
464
- ].map((fn) => fn(attribute));
505
+ ].map((fn) => fn(attribute, options));
465
506
  const transformSchema = pipe(...validations);
466
507
  switch (attribute.type) {
467
508
  case "component": {
@@ -471,12 +512,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
471
512
  ...acc,
472
513
  [name]: transformSchema(
473
514
  yup.array().of(createModelSchema(attributes3).nullable(false))
474
- )
515
+ ).test(arrayValidator(attribute, options))
475
516
  };
476
517
  } else {
477
518
  return {
478
519
  ...acc,
479
- [name]: transformSchema(createModelSchema(attributes3))
520
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
480
521
  };
481
522
  }
482
523
  }
@@ -498,7 +539,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
498
539
  }
499
540
  )
500
541
  )
501
- )
542
+ ).test(arrayValidator(attribute, options))
502
543
  };
503
544
  case "relation":
504
545
  return {
@@ -510,7 +551,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
510
551
  } else if (Array.isArray(value)) {
511
552
  return yup.array().of(
512
553
  yup.object().shape({
513
- id: yup.string().required()
554
+ id: yup.number().required()
514
555
  })
515
556
  );
516
557
  } else if (typeof value === "object") {
@@ -562,6 +603,14 @@ const createAttributeSchema = (attribute) => {
562
603
  if (!value || typeof value === "string" && value.length === 0) {
563
604
  return true;
564
605
  }
606
+ if (typeof value === "object") {
607
+ try {
608
+ JSON.stringify(value);
609
+ return true;
610
+ } catch (err) {
611
+ return false;
612
+ }
613
+ }
565
614
  try {
566
615
  JSON.parse(value);
567
616
  return true;
@@ -580,13 +629,7 @@ const createAttributeSchema = (attribute) => {
580
629
  return yup.mixed();
581
630
  }
582
631
  };
583
- const addRequiredValidation = (attribute) => (schema) => {
584
- if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
585
- return schema.min(1, translatedErrors.required);
586
- }
587
- if (attribute.required && attribute.type !== "relation") {
588
- return schema.required(translatedErrors.required);
589
- }
632
+ const nullableSchema = (schema) => {
590
633
  return schema?.nullable ? schema.nullable() : (
591
634
  // In some cases '.nullable' will not be available on the schema.
592
635
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -594,7 +637,22 @@ const addRequiredValidation = (attribute) => (schema) => {
594
637
  schema
595
638
  );
596
639
  };
597
- const addMinLengthValidation = (attribute) => (schema) => {
640
+ const addNullableValidation = () => (schema) => {
641
+ return nullableSchema(schema);
642
+ };
643
+ const addRequiredValidation = (attribute, options) => (schema) => {
644
+ if (options.status === "draft" || !attribute.required) {
645
+ return schema;
646
+ }
647
+ if (attribute.required && "required" in schema) {
648
+ return schema.required(translatedErrors.required);
649
+ }
650
+ return schema;
651
+ };
652
+ const addMinLengthValidation = (attribute, options) => (schema) => {
653
+ if (options.status === "draft") {
654
+ return schema;
655
+ }
598
656
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
599
657
  return schema.min(attribute.minLength, {
600
658
  ...translatedErrors.minLength,
@@ -616,32 +674,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
616
674
  }
617
675
  return schema;
618
676
  };
619
- const addMinValidation = (attribute) => (schema) => {
620
- if ("min" in attribute) {
677
+ const addMinValidation = (attribute, options) => (schema) => {
678
+ if (options.status === "draft") {
679
+ return schema;
680
+ }
681
+ if ("min" in attribute && "min" in schema) {
621
682
  const min = toInteger(attribute.min);
622
- if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
623
- if (!attribute.required && "test" in schema && min) {
624
- return schema.test(
625
- "custom-min",
626
- {
627
- ...translatedErrors.min,
628
- values: {
629
- min: attribute.min
630
- }
631
- },
632
- (value) => {
633
- if (!value) {
634
- return true;
635
- }
636
- if (Array.isArray(value) && value.length === 0) {
637
- return true;
638
- }
639
- return value.length >= min;
640
- }
641
- );
642
- }
643
- }
644
- if ("min" in schema && min) {
683
+ if (min) {
645
684
  return schema.min(min, {
646
685
  ...translatedErrors.min,
647
686
  values: {
@@ -759,19 +798,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
759
798
  }, {});
760
799
  return componentsByKey;
761
800
  };
762
- const useDocument = (args, opts) => {
801
+ const HOOKS = {
802
+ /**
803
+ * Hook that allows to mutate the displayed headers of the list view table
804
+ * @constant
805
+ * @type {string}
806
+ */
807
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
808
+ /**
809
+ * Hook that allows to mutate the CM's collection types links pre-set filters
810
+ * @constant
811
+ * @type {string}
812
+ */
813
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
814
+ /**
815
+ * Hook that allows to mutate the CM's edit view layout
816
+ * @constant
817
+ * @type {string}
818
+ */
819
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
820
+ /**
821
+ * Hook that allows to mutate the CM's single types links pre-set filters
822
+ * @constant
823
+ * @type {string}
824
+ */
825
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
826
+ };
827
+ const contentTypesApi = contentManagerApi.injectEndpoints({
828
+ endpoints: (builder) => ({
829
+ getContentTypeConfiguration: builder.query({
830
+ query: (uid) => ({
831
+ url: `/content-manager/content-types/${uid}/configuration`,
832
+ method: "GET"
833
+ }),
834
+ transformResponse: (response) => response.data,
835
+ providesTags: (_result, _error, uid) => [
836
+ { type: "ContentTypesConfiguration", id: uid },
837
+ { type: "ContentTypeSettings", id: "LIST" }
838
+ ]
839
+ }),
840
+ getAllContentTypeSettings: builder.query({
841
+ query: () => "/content-manager/content-types-settings",
842
+ transformResponse: (response) => response.data,
843
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
844
+ }),
845
+ updateContentTypeConfiguration: builder.mutation({
846
+ query: ({ uid, ...body }) => ({
847
+ url: `/content-manager/content-types/${uid}/configuration`,
848
+ method: "PUT",
849
+ data: body
850
+ }),
851
+ transformResponse: (response) => response.data,
852
+ invalidatesTags: (_result, _error, { uid }) => [
853
+ { type: "ContentTypesConfiguration", id: uid },
854
+ { type: "ContentTypeSettings", id: "LIST" },
855
+ // Is this necessary?
856
+ { type: "InitialData" }
857
+ ]
858
+ })
859
+ })
860
+ });
861
+ const {
862
+ useGetContentTypeConfigurationQuery,
863
+ useGetAllContentTypeSettingsQuery,
864
+ useUpdateContentTypeConfigurationMutation
865
+ } = contentTypesApi;
866
+ const checkIfAttributeIsDisplayable = (attribute) => {
867
+ const { type } = attribute;
868
+ if (type === "relation") {
869
+ return !attribute.relation.toLowerCase().includes("morph");
870
+ }
871
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
872
+ };
873
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
874
+ if (!mainFieldName) {
875
+ return void 0;
876
+ }
877
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
878
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
879
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
880
+ );
881
+ return {
882
+ name: mainFieldName,
883
+ type: mainFieldType ?? "string"
884
+ };
885
+ };
886
+ const DEFAULT_SETTINGS = {
887
+ bulkable: false,
888
+ filterable: false,
889
+ searchable: false,
890
+ pagination: false,
891
+ defaultSortBy: "",
892
+ defaultSortOrder: "asc",
893
+ mainField: "id",
894
+ pageSize: 10
895
+ };
896
+ const useDocumentLayout = (model) => {
897
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
898
+ const [{ query }] = useQueryParams();
899
+ const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
763
900
  const { toggleNotification } = useNotification();
764
901
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
902
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
765
903
  const {
766
- currentData: data,
767
- isLoading: isLoadingDocument,
768
- isFetching: isFetchingDocument,
769
- error
770
- } = useGetDocumentQuery(args, {
771
- ...opts,
772
- skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
773
- });
774
- const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
904
+ data,
905
+ isLoading: isLoadingConfigs,
906
+ error,
907
+ isFetching: isFetchingConfigs
908
+ } = useGetContentTypeConfigurationQuery(model);
909
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
775
910
  React.useEffect(() => {
776
911
  if (error) {
777
912
  toggleNotification({
@@ -779,88 +914,344 @@ const useDocument = (args, opts) => {
779
914
  message: formatAPIError(error)
780
915
  });
781
916
  }
782
- }, [toggleNotification, error, formatAPIError, args.collectionType]);
783
- const validationSchema = React.useMemo(() => {
784
- if (!schema) {
785
- return null;
786
- }
787
- return createYupSchema(schema.attributes, components);
788
- }, [schema, components]);
789
- const validate = React.useCallback(
790
- (document) => {
791
- if (!validationSchema) {
792
- throw new Error(
793
- "There is no validation schema generated, this is likely due to the schema not being loaded yet."
794
- );
795
- }
796
- try {
797
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
798
- return null;
799
- } catch (error2) {
800
- if (error2 instanceof ValidationError) {
801
- return getYupValidationErrors(error2);
802
- }
803
- throw error2;
804
- }
917
+ }, [error, formatAPIError, toggleNotification]);
918
+ const editLayout = React.useMemo(
919
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
920
+ layout: [],
921
+ components: {},
922
+ metadatas: {},
923
+ options: {},
924
+ settings: DEFAULT_SETTINGS
805
925
  },
806
- [validationSchema]
926
+ [data, isLoading, schemas, schema, components]
927
+ );
928
+ const listLayout = React.useMemo(() => {
929
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
930
+ layout: [],
931
+ metadatas: {},
932
+ options: {},
933
+ settings: DEFAULT_SETTINGS
934
+ };
935
+ }, [data, isLoading, schemas, schema, components]);
936
+ const { layout: edit } = React.useMemo(
937
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
938
+ layout: editLayout,
939
+ query
940
+ }),
941
+ [editLayout, query, runHookWaterfall]
807
942
  );
808
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
809
943
  return {
810
- components,
811
- document: data?.data,
812
- meta: data?.meta,
944
+ error,
813
945
  isLoading,
814
- schema,
815
- validate
816
- };
817
- };
818
- const useDoc = () => {
819
- const { id, slug, collectionType, origin } = useParams();
820
- const [{ query }] = useQueryParams();
821
- const params = React.useMemo(() => buildValidParams(query), [query]);
822
- if (!collectionType) {
823
- throw new Error("Could not find collectionType in url params");
824
- }
825
- if (!slug) {
826
- throw new Error("Could not find model in url params");
827
- }
828
- return {
829
- collectionType,
830
- model: slug,
831
- id: origin || id === "create" ? void 0 : id,
832
- ...useDocument(
833
- { documentId: origin || id, model: slug, collectionType, params },
834
- {
835
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
836
- }
837
- )
946
+ edit,
947
+ list: listLayout
838
948
  };
839
949
  };
840
- const prefixPluginTranslations = (trad, pluginId) => {
841
- if (!pluginId) {
842
- throw new TypeError("pluginId can't be empty");
843
- }
844
- return Object.keys(trad).reduce((acc, current) => {
845
- acc[`${pluginId}.${current}`] = trad[current];
846
- return acc;
847
- }, {});
848
- };
849
- const getTranslation = (id) => `content-manager.${id}`;
850
- const DEFAULT_UNEXPECTED_ERROR_MSG = {
851
- id: "notification.error",
852
- defaultMessage: "An error occurred, please try again"
950
+ const useDocLayout = () => {
951
+ const { model } = useDoc();
952
+ return useDocumentLayout(model);
853
953
  };
854
- const useDocumentActions = () => {
855
- const { toggleNotification } = useNotification();
856
- const { formatMessage } = useIntl();
857
- const { trackUsage } = useTracking();
858
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
859
- const [deleteDocument] = useDeleteDocumentMutation();
860
- const _delete = React.useCallback(
861
- async ({ collectionType, model, documentId, params }, trackerProperty) => {
862
- try {
863
- trackUsage("willDeleteEntry", trackerProperty);
954
+ const formatEditLayout = (data, {
955
+ schemas,
956
+ schema,
957
+ components
958
+ }) => {
959
+ let currentPanelIndex = 0;
960
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
961
+ data.contentType.layouts.edit,
962
+ schema?.attributes,
963
+ data.contentType.metadatas,
964
+ { configurations: data.components, schemas: components },
965
+ schemas
966
+ ).reduce((panels, row) => {
967
+ if (row.some((field) => field.type === "dynamiczone")) {
968
+ panels.push([row]);
969
+ currentPanelIndex += 2;
970
+ } else {
971
+ if (!panels[currentPanelIndex]) {
972
+ panels.push([row]);
973
+ } else {
974
+ panels[currentPanelIndex].push(row);
975
+ }
976
+ }
977
+ return panels;
978
+ }, []);
979
+ const componentEditAttributes = Object.entries(data.components).reduce(
980
+ (acc, [uid, configuration]) => {
981
+ acc[uid] = {
982
+ layout: convertEditLayoutToFieldLayouts(
983
+ configuration.layouts.edit,
984
+ components[uid].attributes,
985
+ configuration.metadatas,
986
+ { configurations: data.components, schemas: components }
987
+ ),
988
+ settings: {
989
+ ...configuration.settings,
990
+ icon: components[uid].info.icon,
991
+ displayName: components[uid].info.displayName
992
+ }
993
+ };
994
+ return acc;
995
+ },
996
+ {}
997
+ );
998
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
999
+ (acc, [attribute, metadata]) => {
1000
+ return {
1001
+ ...acc,
1002
+ [attribute]: metadata.edit
1003
+ };
1004
+ },
1005
+ {}
1006
+ );
1007
+ return {
1008
+ layout: panelledEditAttributes,
1009
+ components: componentEditAttributes,
1010
+ metadatas: editMetadatas,
1011
+ settings: {
1012
+ ...data.contentType.settings,
1013
+ displayName: schema?.info.displayName
1014
+ },
1015
+ options: {
1016
+ ...schema?.options,
1017
+ ...schema?.pluginOptions,
1018
+ ...data.contentType.options
1019
+ }
1020
+ };
1021
+ };
1022
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1023
+ return rows.map(
1024
+ (row) => row.map((field) => {
1025
+ const attribute = attributes[field.name];
1026
+ if (!attribute) {
1027
+ return null;
1028
+ }
1029
+ const { edit: metadata } = metadatas[field.name];
1030
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1031
+ return {
1032
+ attribute,
1033
+ disabled: !metadata.editable,
1034
+ hint: metadata.description,
1035
+ label: metadata.label ?? "",
1036
+ name: field.name,
1037
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1038
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1039
+ schemas,
1040
+ components: components?.schemas ?? {}
1041
+ }),
1042
+ placeholder: metadata.placeholder ?? "",
1043
+ required: attribute.required ?? false,
1044
+ size: field.size,
1045
+ unique: "unique" in attribute ? attribute.unique : false,
1046
+ visible: metadata.visible ?? true,
1047
+ type: attribute.type
1048
+ };
1049
+ }).filter((field) => field !== null)
1050
+ );
1051
+ };
1052
+ const formatListLayout = (data, {
1053
+ schemas,
1054
+ schema,
1055
+ components
1056
+ }) => {
1057
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1058
+ (acc, [attribute, metadata]) => {
1059
+ return {
1060
+ ...acc,
1061
+ [attribute]: metadata.list
1062
+ };
1063
+ },
1064
+ {}
1065
+ );
1066
+ const listAttributes = convertListLayoutToFieldLayouts(
1067
+ data.contentType.layouts.list,
1068
+ schema?.attributes,
1069
+ listMetadatas,
1070
+ { configurations: data.components, schemas: components },
1071
+ schemas
1072
+ );
1073
+ return {
1074
+ layout: listAttributes,
1075
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1076
+ metadatas: listMetadatas,
1077
+ options: {
1078
+ ...schema?.options,
1079
+ ...schema?.pluginOptions,
1080
+ ...data.contentType.options
1081
+ }
1082
+ };
1083
+ };
1084
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1085
+ return columns.map((name) => {
1086
+ const attribute = attributes[name];
1087
+ if (!attribute) {
1088
+ return null;
1089
+ }
1090
+ const metadata = metadatas[name];
1091
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1092
+ return {
1093
+ attribute,
1094
+ label: metadata.label ?? "",
1095
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1096
+ schemas,
1097
+ components: components?.schemas ?? {}
1098
+ }),
1099
+ name,
1100
+ searchable: metadata.searchable ?? true,
1101
+ sortable: metadata.sortable ?? true
1102
+ };
1103
+ }).filter((field) => field !== null);
1104
+ };
1105
+ const useDocument = (args, opts) => {
1106
+ const { toggleNotification } = useNotification();
1107
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
1108
+ const {
1109
+ currentData: data,
1110
+ isLoading: isLoadingDocument,
1111
+ isFetching: isFetchingDocument,
1112
+ error
1113
+ } = useGetDocumentQuery(args, {
1114
+ ...opts,
1115
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1116
+ });
1117
+ const {
1118
+ components,
1119
+ schema,
1120
+ schemas,
1121
+ isLoading: isLoadingSchema
1122
+ } = useContentTypeSchema(args.model);
1123
+ React.useEffect(() => {
1124
+ if (error) {
1125
+ toggleNotification({
1126
+ type: "danger",
1127
+ message: formatAPIError(error)
1128
+ });
1129
+ }
1130
+ }, [toggleNotification, error, formatAPIError, args.collectionType]);
1131
+ const validationSchema = React.useMemo(() => {
1132
+ if (!schema) {
1133
+ return null;
1134
+ }
1135
+ return createYupSchema(schema.attributes, components);
1136
+ }, [schema, components]);
1137
+ const validate = React.useCallback(
1138
+ (document) => {
1139
+ if (!validationSchema) {
1140
+ throw new Error(
1141
+ "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1142
+ );
1143
+ }
1144
+ try {
1145
+ validationSchema.validateSync(document, { abortEarly: false, strict: true });
1146
+ return null;
1147
+ } catch (error2) {
1148
+ if (error2 instanceof ValidationError) {
1149
+ return getYupValidationErrors(error2);
1150
+ }
1151
+ throw error2;
1152
+ }
1153
+ },
1154
+ [validationSchema]
1155
+ );
1156
+ const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1157
+ const hasError = !!error;
1158
+ return {
1159
+ components,
1160
+ document: data?.data,
1161
+ meta: data?.meta,
1162
+ isLoading,
1163
+ hasError,
1164
+ schema,
1165
+ schemas,
1166
+ validate
1167
+ };
1168
+ };
1169
+ const useDoc = () => {
1170
+ const { id, slug, collectionType, origin } = useParams();
1171
+ const [{ query }] = useQueryParams();
1172
+ const params = React.useMemo(() => buildValidParams(query), [query]);
1173
+ if (!collectionType) {
1174
+ throw new Error("Could not find collectionType in url params");
1175
+ }
1176
+ if (!slug) {
1177
+ throw new Error("Could not find model in url params");
1178
+ }
1179
+ const document = useDocument(
1180
+ { documentId: origin || id, model: slug, collectionType, params },
1181
+ {
1182
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1183
+ }
1184
+ );
1185
+ const returnId = origin || id === "create" ? void 0 : id;
1186
+ return {
1187
+ collectionType,
1188
+ model: slug,
1189
+ id: returnId,
1190
+ ...document
1191
+ };
1192
+ };
1193
+ const useContentManagerContext = () => {
1194
+ const {
1195
+ collectionType,
1196
+ model,
1197
+ id,
1198
+ components,
1199
+ isLoading: isLoadingDoc,
1200
+ schema,
1201
+ schemas
1202
+ } = useDoc();
1203
+ const layout = useDocumentLayout(model);
1204
+ const form = useForm("useContentManagerContext", (state) => state);
1205
+ const isSingleType = collectionType === SINGLE_TYPES;
1206
+ const slug = model;
1207
+ const isCreatingEntry = id === "create";
1208
+ useContentTypeSchema();
1209
+ const isLoading = isLoadingDoc || layout.isLoading;
1210
+ const error = layout.error;
1211
+ return {
1212
+ error,
1213
+ isLoading,
1214
+ // Base metadata
1215
+ model,
1216
+ collectionType,
1217
+ id,
1218
+ slug,
1219
+ isCreatingEntry,
1220
+ isSingleType,
1221
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1222
+ // All schema infos
1223
+ components,
1224
+ contentType: schema,
1225
+ contentTypes: schemas,
1226
+ // Form state
1227
+ form,
1228
+ // layout infos
1229
+ layout
1230
+ };
1231
+ };
1232
+ const prefixPluginTranslations = (trad, pluginId) => {
1233
+ return Object.keys(trad).reduce((acc, current) => {
1234
+ acc[`${pluginId}.${current}`] = trad[current];
1235
+ return acc;
1236
+ }, {});
1237
+ };
1238
+ const getTranslation = (id) => `content-manager.${id}`;
1239
+ const DEFAULT_UNEXPECTED_ERROR_MSG = {
1240
+ id: "notification.error",
1241
+ defaultMessage: "An error occurred, please try again"
1242
+ };
1243
+ const useDocumentActions = () => {
1244
+ const { toggleNotification } = useNotification();
1245
+ const { formatMessage } = useIntl();
1246
+ const { trackUsage } = useTracking();
1247
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
1248
+ const navigate = useNavigate();
1249
+ const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
1250
+ const [deleteDocument] = useDeleteDocumentMutation();
1251
+ const _delete = React.useCallback(
1252
+ async ({ collectionType, model, documentId, params }, trackerProperty) => {
1253
+ try {
1254
+ trackUsage("willDeleteEntry", trackerProperty);
864
1255
  const res = await deleteDocument({
865
1256
  collectionType,
866
1257
  model,
@@ -1170,6 +1561,7 @@ const useDocumentActions = () => {
1170
1561
  defaultMessage: "Saved document"
1171
1562
  })
1172
1563
  });
1564
+ setCurrentStep("contentManager.success");
1173
1565
  return res.data;
1174
1566
  } catch (err) {
1175
1567
  toggleNotification({
@@ -1209,7 +1601,7 @@ const useDocumentActions = () => {
1209
1601
  throw err;
1210
1602
  }
1211
1603
  },
1212
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1604
+ [autoCloneDocument, formatMessage, toggleNotification]
1213
1605
  );
1214
1606
  const [cloneDocument] = useCloneDocumentMutation();
1215
1607
  const clone = React.useCallback(
@@ -1235,6 +1627,7 @@ const useDocumentActions = () => {
1235
1627
  defaultMessage: "Cloned document"
1236
1628
  })
1237
1629
  });
1630
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1238
1631
  return res.data;
1239
1632
  } catch (err) {
1240
1633
  toggleNotification({
@@ -1245,7 +1638,7 @@ const useDocumentActions = () => {
1245
1638
  throw err;
1246
1639
  }
1247
1640
  },
1248
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1641
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1249
1642
  );
1250
1643
  const [getDoc] = useLazyGetDocumentQuery();
1251
1644
  const getDocument = React.useCallback(
@@ -1270,10 +1663,10 @@ const useDocumentActions = () => {
1270
1663
  update
1271
1664
  };
1272
1665
  };
1273
- const ProtectedHistoryPage = lazy(
1274
- () => import("./History-wrnHqf09.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1666
+ const ProtectedHistoryPage = React.lazy(
1667
+ () => import("./History-B9uJsxZl.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1275
1668
  );
1276
- const routes$1 = [
1669
+ const routes$2 = [
1277
1670
  {
1278
1671
  path: ":collectionType/:slug/:id/history",
1279
1672
  Component: ProtectedHistoryPage
@@ -1283,32 +1676,45 @@ const routes$1 = [
1283
1676
  Component: ProtectedHistoryPage
1284
1677
  }
1285
1678
  ];
1679
+ const ProtectedPreviewPage = React.lazy(
1680
+ () => import("./Preview-DRJhcaIO.mjs").then((mod) => ({ default: mod.ProtectedPreviewPage }))
1681
+ );
1682
+ const routes$1 = [
1683
+ {
1684
+ path: ":collectionType/:slug/:id/preview",
1685
+ Component: ProtectedPreviewPage
1686
+ },
1687
+ {
1688
+ path: ":collectionType/:slug/preview",
1689
+ Component: ProtectedPreviewPage
1690
+ }
1691
+ ];
1286
1692
  const ProtectedEditViewPage = lazy(
1287
- () => import("./EditViewPage-BLsjc5F-.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1693
+ () => import("./EditViewPage-hiwZg61J.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1288
1694
  );
1289
1695
  const ProtectedListViewPage = lazy(
1290
- () => import("./ListViewPage-C4IvrMgY.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1696
+ () => import("./ListViewPage-Ca8F1NL-.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1291
1697
  );
1292
1698
  const ProtectedListConfiguration = lazy(
1293
- () => import("./ListConfigurationPage-DScmJVkW.mjs").then((mod) => ({
1699
+ () => import("./ListConfigurationPage-CA4oi4Hj.mjs").then((mod) => ({
1294
1700
  default: mod.ProtectedListConfiguration
1295
1701
  }))
1296
1702
  );
1297
1703
  const ProtectedEditConfigurationPage = lazy(
1298
- () => import("./EditConfigurationPage-DmoXawIh.mjs").then((mod) => ({
1704
+ () => import("./EditConfigurationPage-CWao3CZ3.mjs").then((mod) => ({
1299
1705
  default: mod.ProtectedEditConfigurationPage
1300
1706
  }))
1301
1707
  );
1302
1708
  const ProtectedComponentConfigurationPage = lazy(
1303
- () => import("./ComponentConfigurationPage-BAgyHiMm.mjs").then((mod) => ({
1709
+ () => import("./ComponentConfigurationPage-DhwMhiRn.mjs").then((mod) => ({
1304
1710
  default: mod.ProtectedComponentConfigurationPage
1305
1711
  }))
1306
1712
  );
1307
1713
  const NoPermissions = lazy(
1308
- () => import("./NoPermissionsPage-DSP7R-hv.mjs").then((mod) => ({ default: mod.NoPermissions }))
1714
+ () => import("./NoPermissionsPage-iPk2lFR6.mjs").then((mod) => ({ default: mod.NoPermissions }))
1309
1715
  );
1310
1716
  const NoContentType = lazy(
1311
- () => import("./NoContentTypePage-Djg8nPlj.mjs").then((mod) => ({ default: mod.NoContentType }))
1717
+ () => import("./NoContentTypePage-CwfnU-aN.mjs").then((mod) => ({ default: mod.NoContentType }))
1312
1718
  );
1313
1719
  const CollectionTypePages = () => {
1314
1720
  const { collectionType } = useParams();
@@ -1354,6 +1760,7 @@ const routes = [
1354
1760
  path: "no-content-types",
1355
1761
  Component: NoContentType
1356
1762
  },
1763
+ ...routes$2,
1357
1764
  ...routes$1
1358
1765
  ];
1359
1766
  const DocumentActions = ({ actions: actions2 }) => {
@@ -1422,12 +1829,14 @@ const DocumentActionButton = (action) => {
1422
1829
  /* @__PURE__ */ jsx(
1423
1830
  Button,
1424
1831
  {
1425
- flex: 1,
1832
+ flex: "auto",
1426
1833
  startIcon: action.icon,
1427
1834
  disabled: action.disabled,
1428
1835
  onClick: handleClick(action),
1429
1836
  justifyContent: "center",
1430
1837
  variant: action.variant || "default",
1838
+ paddingTop: "7px",
1839
+ paddingBottom: "7px",
1431
1840
  children: action.label
1432
1841
  }
1433
1842
  ),
@@ -1492,9 +1901,9 @@ const DocumentActionsMenu = ({
1492
1901
  disabled: isDisabled,
1493
1902
  size: "S",
1494
1903
  endIcon: null,
1495
- paddingTop: "7px",
1496
- paddingLeft: "9px",
1497
- paddingRight: "9px",
1904
+ paddingTop: "4px",
1905
+ paddingLeft: "7px",
1906
+ paddingRight: "7px",
1498
1907
  variant,
1499
1908
  children: [
1500
1909
  /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
@@ -1505,7 +1914,7 @@ const DocumentActionsMenu = ({
1505
1914
  ]
1506
1915
  }
1507
1916
  ),
1508
- /* @__PURE__ */ jsxs(Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1917
+ /* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1509
1918
  actions2.map((action) => {
1510
1919
  return /* @__PURE__ */ jsx(
1511
1920
  Menu.Item,
@@ -1514,10 +1923,25 @@ const DocumentActionsMenu = ({
1514
1923
  onSelect: handleClick(action),
1515
1924
  display: "block",
1516
1925
  children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
1517
- /* @__PURE__ */ jsxs(Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1518
- /* @__PURE__ */ jsx(Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1519
- action.label
1520
- ] }),
1926
+ /* @__PURE__ */ jsxs(
1927
+ Flex,
1928
+ {
1929
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1930
+ gap: 2,
1931
+ tag: "span",
1932
+ children: [
1933
+ /* @__PURE__ */ jsx(
1934
+ Flex,
1935
+ {
1936
+ tag: "span",
1937
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1938
+ children: action.icon
1939
+ }
1940
+ ),
1941
+ action.label
1942
+ ]
1943
+ }
1944
+ ),
1521
1945
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
1522
1946
  Flex,
1523
1947
  {
@@ -1614,11 +2038,11 @@ const DocumentActionConfirmDialog = ({
1614
2038
  /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
1615
2039
  /* @__PURE__ */ jsx(Dialog.Body, { children: content }),
1616
2040
  /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
1617
- /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
2041
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
1618
2042
  id: "app.components.Button.cancel",
1619
2043
  defaultMessage: "Cancel"
1620
2044
  }) }) }),
1621
- /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
2045
+ /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
1622
2046
  id: "app.components.Button.confirm",
1623
2047
  defaultMessage: "Confirm"
1624
2048
  }) })
@@ -1645,6 +2069,18 @@ const DocumentActionModal = ({
1645
2069
  typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
1646
2070
  ] }) });
1647
2071
  };
2072
+ const transformData = (data) => {
2073
+ if (Array.isArray(data)) {
2074
+ return data.map(transformData);
2075
+ }
2076
+ if (typeof data === "object" && data !== null) {
2077
+ if ("apiData" in data) {
2078
+ return data.apiData;
2079
+ }
2080
+ return mapValues(transformData)(data);
2081
+ }
2082
+ return data;
2083
+ };
1648
2084
  const PublishAction$1 = ({
1649
2085
  activeTab,
1650
2086
  documentId,
@@ -1657,12 +2093,10 @@ const PublishAction$1 = ({
1657
2093
  const navigate = useNavigate();
1658
2094
  const { toggleNotification } = useNotification();
1659
2095
  const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
2096
+ const isListView = useMatch(LIST_PATH) !== null;
1660
2097
  const isCloning = useMatch(CLONE_PATH) !== null;
1661
2098
  const { formatMessage } = useIntl();
1662
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1663
- "PublishAction",
1664
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1665
- );
2099
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1666
2100
  const { publish } = useDocumentActions();
1667
2101
  const [
1668
2102
  countDraftRelations,
@@ -1714,24 +2148,25 @@ const PublishAction$1 = ({
1714
2148
  }
1715
2149
  }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
1716
2150
  React.useEffect(() => {
1717
- if (documentId) {
1718
- const fetchDraftRelationsCount = async () => {
1719
- const { data, error } = await countDraftRelations({
1720
- collectionType,
1721
- model,
1722
- documentId,
1723
- params
1724
- });
1725
- if (error) {
1726
- throw error;
1727
- }
1728
- if (data) {
1729
- setServerCountOfDraftRelations(data.data);
1730
- }
1731
- };
1732
- fetchDraftRelationsCount();
2151
+ if (!document || !document.documentId || isListView) {
2152
+ return;
1733
2153
  }
1734
- }, [documentId, countDraftRelations, collectionType, model, params]);
2154
+ const fetchDraftRelationsCount = async () => {
2155
+ const { data, error } = await countDraftRelations({
2156
+ collectionType,
2157
+ model,
2158
+ documentId,
2159
+ params
2160
+ });
2161
+ if (error) {
2162
+ throw error;
2163
+ }
2164
+ if (data) {
2165
+ setServerCountOfDraftRelations(data.data);
2166
+ }
2167
+ };
2168
+ fetchDraftRelationsCount();
2169
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
1735
2170
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1736
2171
  if (!schema?.options?.draftAndPublish) {
1737
2172
  return null;
@@ -1739,7 +2174,9 @@ const PublishAction$1 = ({
1739
2174
  const performPublish = async () => {
1740
2175
  setSubmitting(true);
1741
2176
  try {
1742
- const { errors } = await validate();
2177
+ const { errors } = await validate(true, {
2178
+ status: "published"
2179
+ });
1743
2180
  if (errors) {
1744
2181
  toggleNotification({
1745
2182
  type: "danger",
@@ -1757,7 +2194,7 @@ const PublishAction$1 = ({
1757
2194
  documentId,
1758
2195
  params
1759
2196
  },
1760
- formValues
2197
+ transformData(formValues)
1761
2198
  );
1762
2199
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1763
2200
  navigate({
@@ -1772,7 +2209,8 @@ const PublishAction$1 = ({
1772
2209
  }
1773
2210
  };
1774
2211
  const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1775
- const hasDraftRelations = totalDraftRelations > 0;
2212
+ const enableDraftRelationsCount = false;
2213
+ const hasDraftRelations = enableDraftRelationsCount;
1776
2214
  return {
1777
2215
  /**
1778
2216
  * Disabled when:
@@ -1782,18 +2220,13 @@ const PublishAction$1 = ({
1782
2220
  * - the document is already published & not modified
1783
2221
  * - the document is being created & not modified
1784
2222
  * - the user doesn't have the permission to publish
1785
- * - the user doesn't have the permission to create a new document
1786
- * - the user doesn't have the permission to update the document
1787
2223
  */
1788
- disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2224
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1789
2225
  label: formatMessage({
1790
2226
  id: "app.utils.publish",
1791
2227
  defaultMessage: "Publish"
1792
2228
  }),
1793
2229
  onClick: async () => {
1794
- if (hasDraftRelations) {
1795
- return;
1796
- }
1797
2230
  await performPublish();
1798
2231
  },
1799
2232
  dialog: hasDraftRelations ? {
@@ -1832,10 +2265,6 @@ const UpdateAction = ({
1832
2265
  const cloneMatch = useMatch(CLONE_PATH);
1833
2266
  const isCloning = cloneMatch !== null;
1834
2267
  const { formatMessage } = useIntl();
1835
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1836
- canCreate: canCreate2,
1837
- canUpdate: canUpdate2
1838
- }));
1839
2268
  const { create, update, clone } = useDocumentActions();
1840
2269
  const [{ query, rawQuery }] = useQueryParams();
1841
2270
  const params = React.useMemo(() => buildValidParams(query), [query]);
@@ -1852,10 +2281,8 @@ const UpdateAction = ({
1852
2281
  * - the form is submitting
1853
2282
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1854
2283
  * - the active tab is the published tab
1855
- * - the user doesn't have the permission to create a new document
1856
- * - the user doesn't have the permission to update the document
1857
2284
  */
1858
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
2285
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1859
2286
  label: formatMessage({
1860
2287
  id: "content-manager.containers.Edit.save",
1861
2288
  defaultMessage: "Save"
@@ -1863,7 +2290,9 @@ const UpdateAction = ({
1863
2290
  onClick: async () => {
1864
2291
  setSubmitting(true);
1865
2292
  try {
1866
- const { errors } = await validate();
2293
+ const { errors } = await validate(true, {
2294
+ status: "draft"
2295
+ });
1867
2296
  if (errors) {
1868
2297
  toggleNotification({
1869
2298
  type: "danger",
@@ -1881,7 +2310,7 @@ const UpdateAction = ({
1881
2310
  documentId: cloneMatch.params.origin,
1882
2311
  params
1883
2312
  },
1884
- document
2313
+ transformData(document)
1885
2314
  );
1886
2315
  if ("data" in res) {
1887
2316
  navigate(
@@ -1902,7 +2331,7 @@ const UpdateAction = ({
1902
2331
  documentId,
1903
2332
  params
1904
2333
  },
1905
- document
2334
+ transformData(document)
1906
2335
  );
1907
2336
  if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1908
2337
  setErrors(formatValidationErrors(res.error));
@@ -1915,7 +2344,7 @@ const UpdateAction = ({
1915
2344
  model,
1916
2345
  params
1917
2346
  },
1918
- document
2347
+ transformData(document)
1919
2348
  );
1920
2349
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1921
2350
  navigate(
@@ -1968,7 +2397,7 @@ const UnpublishAction$1 = ({
1968
2397
  id: "app.utils.unpublish",
1969
2398
  defaultMessage: "Unpublish"
1970
2399
  }),
1971
- icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
2400
+ icon: /* @__PURE__ */ jsx(Cross, {}),
1972
2401
  onClick: async () => {
1973
2402
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1974
2403
  if (!documentId) {
@@ -2080,7 +2509,7 @@ const DiscardAction = ({
2080
2509
  id: "content-manager.actions.discard.label",
2081
2510
  defaultMessage: "Discard changes"
2082
2511
  }),
2083
- icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
2512
+ icon: /* @__PURE__ */ jsx(Cross, {}),
2084
2513
  position: ["panel", "table-row"],
2085
2514
  variant: "danger",
2086
2515
  dialog: {
@@ -2108,11 +2537,6 @@ const DiscardAction = ({
2108
2537
  };
2109
2538
  };
2110
2539
  DiscardAction.type = "discard";
2111
- const StyledCrossCircle = styled(CrossCircle)`
2112
- path {
2113
- fill: currentColor;
2114
- }
2115
- `;
2116
2540
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2117
2541
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2118
2542
  const RelativeTime = React.forwardRef(
@@ -2160,8 +2584,12 @@ const getDisplayName = ({
2160
2584
  };
2161
2585
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2162
2586
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2163
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
2164
- return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2587
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2588
+ const { formatMessage } = useIntl();
2589
+ return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
2590
+ id: `content-manager.containers.List.${status}`,
2591
+ defaultMessage: capitalise(status)
2592
+ }) }) });
2165
2593
  };
2166
2594
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2167
2595
  const { formatMessage } = useIntl();
@@ -2259,12 +2687,12 @@ const Information = ({ activeTab }) => {
2259
2687
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2260
2688
  label: formatMessage({
2261
2689
  id: "content-manager.containers.edit.information.last-published.label",
2262
- defaultMessage: "Last published"
2690
+ defaultMessage: "Published"
2263
2691
  }),
2264
2692
  value: formatMessage(
2265
2693
  {
2266
2694
  id: "content-manager.containers.edit.information.last-published.value",
2267
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2695
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2268
2696
  },
2269
2697
  {
2270
2698
  time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2277,12 +2705,12 @@ const Information = ({ activeTab }) => {
2277
2705
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2278
2706
  label: formatMessage({
2279
2707
  id: "content-manager.containers.edit.information.last-draft.label",
2280
- defaultMessage: "Last draft"
2708
+ defaultMessage: "Updated"
2281
2709
  }),
2282
2710
  value: formatMessage(
2283
2711
  {
2284
2712
  id: "content-manager.containers.edit.information.last-draft.value",
2285
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2713
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2286
2714
  },
2287
2715
  {
2288
2716
  time: /* @__PURE__ */ jsx(
@@ -2300,12 +2728,12 @@ const Information = ({ activeTab }) => {
2300
2728
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2301
2729
  label: formatMessage({
2302
2730
  id: "content-manager.containers.edit.information.document.label",
2303
- defaultMessage: "Document"
2731
+ defaultMessage: "Created"
2304
2732
  }),
2305
2733
  value: formatMessage(
2306
2734
  {
2307
2735
  id: "content-manager.containers.edit.information.document.value",
2308
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2736
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2309
2737
  },
2310
2738
  {
2311
2739
  time: /* @__PURE__ */ jsx(
@@ -2343,523 +2771,277 @@ const Information = ({ activeTab }) => {
2343
2771
  );
2344
2772
  };
2345
2773
  const HeaderActions = ({ actions: actions2 }) => {
2346
- return /* @__PURE__ */ jsx(Flex, { children: actions2.map((action) => {
2347
- if ("options" in action) {
2774
+ const [dialogId, setDialogId] = React.useState(null);
2775
+ const handleClick = (action) => async (e) => {
2776
+ if (!("options" in action)) {
2777
+ const { onClick = () => false, dialog, id } = action;
2778
+ const muteDialog = await onClick(e);
2779
+ if (dialog && !muteDialog) {
2780
+ e.preventDefault();
2781
+ setDialogId(id);
2782
+ }
2783
+ }
2784
+ };
2785
+ const handleClose = () => {
2786
+ setDialogId(null);
2787
+ };
2788
+ return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
2789
+ if (action.options) {
2348
2790
  return /* @__PURE__ */ jsx(
2349
2791
  SingleSelect,
2350
2792
  {
2351
2793
  size: "S",
2352
- disabled: action.disabled,
2353
- "aria-label": action.label,
2354
2794
  onChange: action.onSelect,
2355
- value: action.value,
2795
+ "aria-label": action.label,
2796
+ ...action,
2356
2797
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
2357
2798
  },
2358
2799
  action.id
2359
2800
  );
2360
2801
  } else {
2361
- return null;
2362
- }
2363
- }) });
2364
- };
2365
- const ConfigureTheViewAction = ({ collectionType, model }) => {
2366
- const navigate = useNavigate();
2367
- const { formatMessage } = useIntl();
2368
- return {
2369
- label: formatMessage({
2370
- id: "app.links.configure-view",
2371
- defaultMessage: "Configure the view"
2372
- }),
2373
- icon: /* @__PURE__ */ jsx(ListPlus, {}),
2374
- onClick: () => {
2375
- navigate(`../${collectionType}/${model}/configurations/edit`);
2376
- },
2377
- position: "header"
2378
- };
2379
- };
2380
- ConfigureTheViewAction.type = "configure-the-view";
2381
- const EditTheModelAction = ({ model }) => {
2382
- const navigate = useNavigate();
2383
- const { formatMessage } = useIntl();
2384
- return {
2385
- label: formatMessage({
2386
- id: "content-manager.link-to-ctb",
2387
- defaultMessage: "Edit the model"
2388
- }),
2389
- icon: /* @__PURE__ */ jsx(Pencil, {}),
2390
- onClick: () => {
2391
- navigate(`/plugins/content-type-builder/content-types/${model}`);
2392
- },
2393
- position: "header"
2394
- };
2395
- };
2396
- EditTheModelAction.type = "edit-the-model";
2397
- const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2398
- const navigate = useNavigate();
2399
- const { formatMessage } = useIntl();
2400
- const listViewPathMatch = useMatch(LIST_PATH);
2401
- const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
2402
- const { delete: deleteAction } = useDocumentActions();
2403
- const { toggleNotification } = useNotification();
2404
- const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
2405
- return {
2406
- disabled: !canDelete || !document,
2407
- label: formatMessage({
2408
- id: "content-manager.actions.delete.label",
2409
- defaultMessage: "Delete document"
2410
- }),
2411
- icon: /* @__PURE__ */ jsx(Trash, {}),
2412
- dialog: {
2413
- type: "dialog",
2414
- title: formatMessage({
2415
- id: "app.components.ConfirmDialog.title",
2416
- defaultMessage: "Confirmation"
2417
- }),
2418
- content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2419
- /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2420
- /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2421
- id: "content-manager.actions.delete.dialog.body",
2422
- defaultMessage: "Are you sure?"
2423
- }) })
2424
- ] }),
2425
- onConfirm: async () => {
2426
- if (!listViewPathMatch) {
2427
- setSubmitting(true);
2428
- }
2429
- try {
2430
- if (!documentId && collectionType !== SINGLE_TYPES) {
2431
- console.error(
2432
- "You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
2433
- );
2434
- toggleNotification({
2435
- message: formatMessage({
2436
- id: "content-manager.actions.delete.error",
2437
- defaultMessage: "An error occurred while trying to delete the document."
2438
- }),
2439
- type: "danger"
2440
- });
2441
- return;
2442
- }
2443
- const res = await deleteAction({
2444
- documentId,
2445
- model,
2446
- collectionType,
2447
- params: {
2448
- locale: "*"
2802
+ if (action.type === "icon") {
2803
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
2804
+ /* @__PURE__ */ jsx(
2805
+ IconButton,
2806
+ {
2807
+ disabled: action.disabled,
2808
+ label: action.label,
2809
+ size: "S",
2810
+ onClick: handleClick(action),
2811
+ children: action.icon
2449
2812
  }
2450
- });
2451
- if (!("error" in res)) {
2452
- navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
2453
- }
2454
- } finally {
2455
- if (!listViewPathMatch) {
2456
- setSubmitting(false);
2457
- }
2458
- }
2459
- }
2460
- },
2461
- variant: "danger",
2462
- position: ["header", "table-row"]
2463
- };
2464
- };
2465
- DeleteAction$1.type = "delete";
2466
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2467
- const Panels = () => {
2468
- const isCloning = useMatch(CLONE_PATH) !== null;
2469
- const [
2470
- {
2471
- query: { status }
2472
- }
2473
- ] = useQueryParams({
2474
- status: "draft"
2475
- });
2476
- const { model, id, document, meta, collectionType } = useDoc();
2477
- const plugins = useStrapiApp("Panels", (state) => state.plugins);
2478
- const props = {
2479
- activeTab: status,
2480
- model,
2481
- documentId: id,
2482
- document: isCloning ? void 0 : document,
2483
- meta: isCloning ? void 0 : meta,
2484
- collectionType
2485
- };
2486
- return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
2487
- DescriptionComponentRenderer,
2488
- {
2489
- props,
2490
- descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2491
- children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
2492
- }
2493
- ) });
2494
- };
2495
- const ActionsPanel = () => {
2496
- const { formatMessage } = useIntl();
2497
- return {
2498
- title: formatMessage({
2499
- id: "content-manager.containers.edit.panels.default.title",
2500
- defaultMessage: "Document"
2501
- }),
2502
- content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
2503
- };
2504
- };
2505
- ActionsPanel.type = "actions";
2506
- const ActionsPanelContent = () => {
2507
- const isCloning = useMatch(CLONE_PATH) !== null;
2508
- const [
2509
- {
2510
- query: { status = "draft" }
2511
- }
2512
- ] = useQueryParams();
2513
- const { model, id, document, meta, collectionType } = useDoc();
2514
- const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
2515
- const props = {
2516
- activeTab: status,
2517
- model,
2518
- documentId: id,
2519
- document: isCloning ? void 0 : document,
2520
- meta: isCloning ? void 0 : meta,
2521
- collectionType
2522
- };
2523
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
2524
- /* @__PURE__ */ jsx(
2525
- DescriptionComponentRenderer,
2526
- {
2527
- props,
2528
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2529
- children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
2530
- }
2531
- ),
2532
- /* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
2533
- ] });
2534
- };
2535
- const Panel = React.forwardRef(({ children, title }, ref) => {
2536
- return /* @__PURE__ */ jsxs(
2537
- Flex,
2538
- {
2539
- ref,
2540
- tag: "aside",
2541
- "aria-labelledby": "additional-information",
2542
- background: "neutral0",
2543
- borderColor: "neutral150",
2544
- hasRadius: true,
2545
- paddingBottom: 4,
2546
- paddingLeft: 4,
2547
- paddingRight: 4,
2548
- paddingTop: 4,
2549
- shadow: "tableShadow",
2550
- gap: 3,
2551
- direction: "column",
2552
- justifyContent: "stretch",
2553
- alignItems: "flex-start",
2554
- children: [
2555
- /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2556
- children
2557
- ]
2813
+ ),
2814
+ action.dialog ? /* @__PURE__ */ jsx(
2815
+ HeaderActionDialog,
2816
+ {
2817
+ ...action.dialog,
2818
+ isOpen: dialogId === action.id,
2819
+ onClose: handleClose
2820
+ }
2821
+ ) : null
2822
+ ] }, action.id);
2823
+ }
2558
2824
  }
2559
- );
2560
- });
2561
- const HOOKS = {
2562
- /**
2563
- * Hook that allows to mutate the displayed headers of the list view table
2564
- * @constant
2565
- * @type {string}
2566
- */
2567
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2568
- /**
2569
- * Hook that allows to mutate the CM's collection types links pre-set filters
2570
- * @constant
2571
- * @type {string}
2572
- */
2573
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2574
- /**
2575
- * Hook that allows to mutate the CM's edit view layout
2576
- * @constant
2577
- * @type {string}
2578
- */
2579
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2580
- /**
2581
- * Hook that allows to mutate the CM's single types links pre-set filters
2582
- * @constant
2583
- * @type {string}
2584
- */
2585
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2825
+ }) });
2586
2826
  };
2587
- const contentTypesApi = contentManagerApi.injectEndpoints({
2588
- endpoints: (builder) => ({
2589
- getContentTypeConfiguration: builder.query({
2590
- query: (uid) => ({
2591
- url: `/content-manager/content-types/${uid}/configuration`,
2592
- method: "GET"
2593
- }),
2594
- transformResponse: (response) => response.data,
2595
- providesTags: (_result, _error, uid) => [
2596
- { type: "ContentTypesConfiguration", id: uid },
2597
- { type: "ContentTypeSettings", id: "LIST" }
2598
- ]
2599
- }),
2600
- getAllContentTypeSettings: builder.query({
2601
- query: () => "/content-manager/content-types-settings",
2602
- transformResponse: (response) => response.data,
2603
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2604
- }),
2605
- updateContentTypeConfiguration: builder.mutation({
2606
- query: ({ uid, ...body }) => ({
2607
- url: `/content-manager/content-types/${uid}/configuration`,
2608
- method: "PUT",
2609
- data: body
2610
- }),
2611
- transformResponse: (response) => response.data,
2612
- invalidatesTags: (_result, _error, { uid }) => [
2613
- { type: "ContentTypesConfiguration", id: uid },
2614
- { type: "ContentTypeSettings", id: "LIST" },
2615
- // Is this necessary?
2616
- { type: "InitialData" }
2617
- ]
2618
- })
2619
- })
2620
- });
2621
- const {
2622
- useGetContentTypeConfigurationQuery,
2623
- useGetAllContentTypeSettingsQuery,
2624
- useUpdateContentTypeConfigurationMutation
2625
- } = contentTypesApi;
2626
- const checkIfAttributeIsDisplayable = (attribute) => {
2627
- const { type } = attribute;
2628
- if (type === "relation") {
2629
- return !attribute.relation.toLowerCase().includes("morph");
2630
- }
2631
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2827
+ const HeaderActionDialog = ({
2828
+ onClose,
2829
+ onCancel,
2830
+ title,
2831
+ content: Content,
2832
+ isOpen
2833
+ }) => {
2834
+ const handleClose = async () => {
2835
+ if (onCancel) {
2836
+ await onCancel();
2837
+ }
2838
+ onClose();
2839
+ };
2840
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2841
+ /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
2842
+ typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
2843
+ ] }) });
2632
2844
  };
2633
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2634
- if (!mainFieldName) {
2635
- return void 0;
2636
- }
2637
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2638
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2639
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2640
- );
2845
+ const ConfigureTheViewAction = ({ collectionType, model }) => {
2846
+ const navigate = useNavigate();
2847
+ const { formatMessage } = useIntl();
2641
2848
  return {
2642
- name: mainFieldName,
2643
- type: mainFieldType ?? "string"
2849
+ label: formatMessage({
2850
+ id: "app.links.configure-view",
2851
+ defaultMessage: "Configure the view"
2852
+ }),
2853
+ icon: /* @__PURE__ */ jsx(ListPlus, {}),
2854
+ onClick: () => {
2855
+ navigate(`../${collectionType}/${model}/configurations/edit`);
2856
+ },
2857
+ position: "header"
2644
2858
  };
2645
2859
  };
2646
- const DEFAULT_SETTINGS = {
2647
- bulkable: false,
2648
- filterable: false,
2649
- searchable: false,
2650
- pagination: false,
2651
- defaultSortBy: "",
2652
- defaultSortOrder: "asc",
2653
- mainField: "id",
2654
- pageSize: 10
2655
- };
2656
- const useDocumentLayout = (model) => {
2657
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2658
- const [{ query }] = useQueryParams();
2659
- const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2660
- const { toggleNotification } = useNotification();
2661
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
2662
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2663
- const {
2664
- data,
2665
- isLoading: isLoadingConfigs,
2666
- error,
2667
- isFetching: isFetchingConfigs
2668
- } = useGetContentTypeConfigurationQuery(model);
2669
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2670
- React.useEffect(() => {
2671
- if (error) {
2672
- toggleNotification({
2673
- type: "danger",
2674
- message: formatAPIError(error)
2675
- });
2676
- }
2677
- }, [error, formatAPIError, toggleNotification]);
2678
- const editLayout = React.useMemo(
2679
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2680
- layout: [],
2681
- components: {},
2682
- metadatas: {},
2683
- options: {},
2684
- settings: DEFAULT_SETTINGS
2685
- },
2686
- [data, isLoading, schemas, schema, components]
2687
- );
2688
- const listLayout = React.useMemo(() => {
2689
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2690
- layout: [],
2691
- metadatas: {},
2692
- options: {},
2693
- settings: DEFAULT_SETTINGS
2694
- };
2695
- }, [data, isLoading, schemas, schema, components]);
2696
- const { layout: edit } = React.useMemo(
2697
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2698
- layout: editLayout,
2699
- query
2700
- }),
2701
- [editLayout, query, runHookWaterfall]
2702
- );
2860
+ ConfigureTheViewAction.type = "configure-the-view";
2861
+ const EditTheModelAction = ({ model }) => {
2862
+ const navigate = useNavigate();
2863
+ const { formatMessage } = useIntl();
2703
2864
  return {
2704
- error,
2705
- isLoading,
2706
- edit,
2707
- list: listLayout
2865
+ label: formatMessage({
2866
+ id: "content-manager.link-to-ctb",
2867
+ defaultMessage: "Edit the model"
2868
+ }),
2869
+ icon: /* @__PURE__ */ jsx(Pencil, {}),
2870
+ onClick: () => {
2871
+ navigate(`/plugins/content-type-builder/content-types/${model}`);
2872
+ },
2873
+ position: "header"
2708
2874
  };
2709
2875
  };
2710
- const useDocLayout = () => {
2711
- const { model } = useDoc();
2712
- return useDocumentLayout(model);
2713
- };
2714
- const formatEditLayout = (data, {
2715
- schemas,
2716
- schema,
2717
- components
2718
- }) => {
2719
- let currentPanelIndex = 0;
2720
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2721
- data.contentType.layouts.edit,
2722
- schema?.attributes,
2723
- data.contentType.metadatas,
2724
- { configurations: data.components, schemas: components },
2725
- schemas
2726
- ).reduce((panels, row) => {
2727
- if (row.some((field) => field.type === "dynamiczone")) {
2728
- panels.push([row]);
2729
- currentPanelIndex += 2;
2730
- } else {
2731
- if (!panels[currentPanelIndex]) {
2732
- panels.push([]);
2733
- }
2734
- panels[currentPanelIndex].push(row);
2735
- }
2736
- return panels;
2737
- }, []);
2738
- const componentEditAttributes = Object.entries(data.components).reduce(
2739
- (acc, [uid, configuration]) => {
2740
- acc[uid] = {
2741
- layout: convertEditLayoutToFieldLayouts(
2742
- configuration.layouts.edit,
2743
- components[uid].attributes,
2744
- configuration.metadatas
2745
- ),
2746
- settings: {
2747
- ...configuration.settings,
2748
- icon: components[uid].info.icon,
2749
- displayName: components[uid].info.displayName
2876
+ EditTheModelAction.type = "edit-the-model";
2877
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2878
+ const navigate = useNavigate();
2879
+ const { formatMessage } = useIntl();
2880
+ const listViewPathMatch = useMatch(LIST_PATH);
2881
+ const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
2882
+ const { delete: deleteAction } = useDocumentActions();
2883
+ const { toggleNotification } = useNotification();
2884
+ const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
2885
+ const isLocalized = document?.locale != null;
2886
+ return {
2887
+ disabled: !canDelete || !document,
2888
+ label: formatMessage(
2889
+ {
2890
+ id: "content-manager.actions.delete.label",
2891
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2892
+ },
2893
+ { isLocalized }
2894
+ ),
2895
+ icon: /* @__PURE__ */ jsx(Trash, {}),
2896
+ dialog: {
2897
+ type: "dialog",
2898
+ title: formatMessage({
2899
+ id: "app.components.ConfirmDialog.title",
2900
+ defaultMessage: "Confirmation"
2901
+ }),
2902
+ content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2903
+ /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2904
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2905
+ id: "content-manager.actions.delete.dialog.body",
2906
+ defaultMessage: "Are you sure?"
2907
+ }) })
2908
+ ] }),
2909
+ onConfirm: async () => {
2910
+ if (!listViewPathMatch) {
2911
+ setSubmitting(true);
2912
+ }
2913
+ try {
2914
+ if (!documentId && collectionType !== SINGLE_TYPES) {
2915
+ console.error(
2916
+ "You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
2917
+ );
2918
+ toggleNotification({
2919
+ message: formatMessage({
2920
+ id: "content-manager.actions.delete.error",
2921
+ defaultMessage: "An error occurred while trying to delete the document."
2922
+ }),
2923
+ type: "danger"
2924
+ });
2925
+ return;
2926
+ }
2927
+ const res = await deleteAction({
2928
+ documentId,
2929
+ model,
2930
+ collectionType,
2931
+ params: {
2932
+ locale: "*"
2933
+ }
2934
+ });
2935
+ if (!("error" in res)) {
2936
+ navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
2937
+ }
2938
+ } finally {
2939
+ if (!listViewPathMatch) {
2940
+ setSubmitting(false);
2941
+ }
2750
2942
  }
2751
- };
2752
- return acc;
2753
- },
2754
- {}
2755
- );
2756
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2757
- (acc, [attribute, metadata]) => {
2758
- return {
2759
- ...acc,
2760
- [attribute]: metadata.edit
2761
- };
2762
- },
2763
- {}
2764
- );
2765
- return {
2766
- layout: panelledEditAttributes,
2767
- components: componentEditAttributes,
2768
- metadatas: editMetadatas,
2769
- settings: {
2770
- ...data.contentType.settings,
2771
- displayName: schema?.info.displayName
2943
+ }
2772
2944
  },
2773
- options: {
2774
- ...schema?.options,
2775
- ...schema?.pluginOptions,
2776
- ...data.contentType.options
2777
- }
2945
+ variant: "danger",
2946
+ position: ["header", "table-row"]
2778
2947
  };
2779
2948
  };
2780
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2781
- return rows.map(
2782
- (row) => row.map((field) => {
2783
- const attribute = attributes[field.name];
2784
- if (!attribute) {
2785
- return null;
2786
- }
2787
- const { edit: metadata } = metadatas[field.name];
2788
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2789
- return {
2790
- attribute,
2791
- disabled: !metadata.editable,
2792
- hint: metadata.description,
2793
- label: metadata.label ?? "",
2794
- name: field.name,
2795
- // @ts-expect-error – mainField does exist on the metadata for a relation.
2796
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2797
- schemas,
2798
- components: components?.schemas ?? {}
2799
- }),
2800
- placeholder: metadata.placeholder ?? "",
2801
- required: attribute.required ?? false,
2802
- size: field.size,
2803
- unique: "unique" in attribute ? attribute.unique : false,
2804
- visible: metadata.visible ?? true,
2805
- type: attribute.type
2806
- };
2807
- }).filter((field) => field !== null)
2808
- );
2949
+ DeleteAction$1.type = "delete";
2950
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2951
+ const Panels = () => {
2952
+ const isCloning = useMatch(CLONE_PATH) !== null;
2953
+ const [
2954
+ {
2955
+ query: { status }
2956
+ }
2957
+ ] = useQueryParams({
2958
+ status: "draft"
2959
+ });
2960
+ const { model, id, document, meta, collectionType } = useDoc();
2961
+ const plugins = useStrapiApp("Panels", (state) => state.plugins);
2962
+ const props = {
2963
+ activeTab: status,
2964
+ model,
2965
+ documentId: id,
2966
+ document: isCloning ? void 0 : document,
2967
+ meta: isCloning ? void 0 : meta,
2968
+ collectionType
2969
+ };
2970
+ return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
2971
+ DescriptionComponentRenderer,
2972
+ {
2973
+ props,
2974
+ descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2975
+ children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
2976
+ }
2977
+ ) });
2809
2978
  };
2810
- const formatListLayout = (data, {
2811
- schemas,
2812
- schema,
2813
- components
2814
- }) => {
2815
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2816
- (acc, [attribute, metadata]) => {
2817
- return {
2818
- ...acc,
2819
- [attribute]: metadata.list
2820
- };
2821
- },
2822
- {}
2823
- );
2824
- const listAttributes = convertListLayoutToFieldLayouts(
2825
- data.contentType.layouts.list,
2826
- schema?.attributes,
2827
- listMetadatas,
2828
- { configurations: data.components, schemas: components },
2829
- schemas
2830
- );
2979
+ const ActionsPanel = () => {
2980
+ const { formatMessage } = useIntl();
2831
2981
  return {
2832
- layout: listAttributes,
2833
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2834
- metadatas: listMetadatas,
2835
- options: {
2836
- ...schema?.options,
2837
- ...schema?.pluginOptions,
2838
- ...data.contentType.options
2839
- }
2982
+ title: formatMessage({
2983
+ id: "content-manager.containers.edit.panels.default.title",
2984
+ defaultMessage: "Entry"
2985
+ }),
2986
+ content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
2840
2987
  };
2841
2988
  };
2842
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2843
- return columns.map((name) => {
2844
- const attribute = attributes[name];
2845
- if (!attribute) {
2846
- return null;
2989
+ ActionsPanel.type = "actions";
2990
+ const ActionsPanelContent = () => {
2991
+ const isCloning = useMatch(CLONE_PATH) !== null;
2992
+ const [
2993
+ {
2994
+ query: { status = "draft" }
2847
2995
  }
2848
- const metadata = metadatas[name];
2849
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2850
- return {
2851
- attribute,
2852
- label: metadata.label ?? "",
2853
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2854
- schemas,
2855
- components: components?.schemas ?? {}
2856
- }),
2857
- name,
2858
- searchable: metadata.searchable ?? true,
2859
- sortable: metadata.sortable ?? true
2860
- };
2861
- }).filter((field) => field !== null);
2996
+ ] = useQueryParams();
2997
+ const { model, id, document, meta, collectionType } = useDoc();
2998
+ const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
2999
+ const props = {
3000
+ activeTab: status,
3001
+ model,
3002
+ documentId: id,
3003
+ document: isCloning ? void 0 : document,
3004
+ meta: isCloning ? void 0 : meta,
3005
+ collectionType
3006
+ };
3007
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
3008
+ /* @__PURE__ */ jsx(
3009
+ DescriptionComponentRenderer,
3010
+ {
3011
+ props,
3012
+ descriptions: plugins["content-manager"].apis.getDocumentActions(),
3013
+ children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
3014
+ }
3015
+ ),
3016
+ /* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
3017
+ ] });
2862
3018
  };
3019
+ const Panel = React.forwardRef(({ children, title }, ref) => {
3020
+ return /* @__PURE__ */ jsxs(
3021
+ Flex,
3022
+ {
3023
+ ref,
3024
+ tag: "aside",
3025
+ "aria-labelledby": "additional-information",
3026
+ background: "neutral0",
3027
+ borderColor: "neutral150",
3028
+ hasRadius: true,
3029
+ paddingBottom: 4,
3030
+ paddingLeft: 4,
3031
+ paddingRight: 4,
3032
+ paddingTop: 4,
3033
+ shadow: "tableShadow",
3034
+ gap: 3,
3035
+ direction: "column",
3036
+ justifyContent: "stretch",
3037
+ alignItems: "flex-start",
3038
+ children: [
3039
+ /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
3040
+ children
3041
+ ]
3042
+ }
3043
+ );
3044
+ });
2863
3045
  const ConfirmBulkActionDialog = ({
2864
3046
  onToggleDialog,
2865
3047
  isOpen = false,
@@ -2898,6 +3080,7 @@ const ConfirmDialogPublishAll = ({
2898
3080
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
2899
3081
  const { model, schema } = useDoc();
2900
3082
  const [{ query }] = useQueryParams();
3083
+ const enableDraftRelationsCount = false;
2901
3084
  const {
2902
3085
  data: countDraftRelations = 0,
2903
3086
  isLoading,
@@ -2909,7 +3092,7 @@ const ConfirmDialogPublishAll = ({
2909
3092
  locale: query?.plugins?.i18n?.locale
2910
3093
  },
2911
3094
  {
2912
- skip: selectedEntries.length === 0
3095
+ skip: !enableDraftRelationsCount
2913
3096
  }
2914
3097
  );
2915
3098
  React.useEffect(() => {
@@ -3094,7 +3277,7 @@ const SelectedEntriesTableContent = ({
3094
3277
  status: row.status
3095
3278
  }
3096
3279
  ) }),
3097
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
3280
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
3098
3281
  IconButton,
3099
3282
  {
3100
3283
  tag: Link,
@@ -3117,9 +3300,10 @@ const SelectedEntriesTableContent = ({
3117
3300
  ),
3118
3301
  target: "_blank",
3119
3302
  marginLeft: "auto",
3120
- children: /* @__PURE__ */ jsx(Pencil, {})
3303
+ variant: "ghost",
3304
+ children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
3121
3305
  }
3122
- ) })
3306
+ ) }) })
3123
3307
  ] }, row.id)) })
3124
3308
  ] });
3125
3309
  };
@@ -3156,7 +3340,13 @@ const SelectedEntriesModalContent = ({
3156
3340
  );
3157
3341
  const { rows, validationErrors } = React.useMemo(() => {
3158
3342
  if (data.length > 0 && schema) {
3159
- const validate = createYupSchema(schema.attributes, components);
3343
+ const validate = createYupSchema(
3344
+ schema.attributes,
3345
+ components,
3346
+ // Since this is the "Publish" action, the validation
3347
+ // schema must enforce the rules for published entities
3348
+ { status: "published" }
3349
+ );
3160
3350
  const validationErrors2 = {};
3161
3351
  const rows2 = data.map((entry) => {
3162
3352
  try {
@@ -3506,7 +3696,7 @@ const TableActions = ({ document }) => {
3506
3696
  DescriptionComponentRenderer,
3507
3697
  {
3508
3698
  props,
3509
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3699
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
3510
3700
  children: (actions2) => {
3511
3701
  const tableRowActions = actions2.filter((action) => {
3512
3702
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3617,7 +3807,7 @@ const CloneAction = ({ model, documentId }) => {
3617
3807
  }),
3618
3808
  content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3619
3809
  footer: ({ onClose }) => {
3620
- return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
3810
+ return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
3621
3811
  /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3622
3812
  id: "cancel",
3623
3813
  defaultMessage: "Cancel"
@@ -3829,6 +4019,70 @@ const { setInitialData } = actions;
3829
4019
  const reducer = combineReducers({
3830
4020
  app: reducer$1
3831
4021
  });
4022
+ const previewApi = contentManagerApi.injectEndpoints({
4023
+ endpoints: (builder) => ({
4024
+ getPreviewUrl: builder.query({
4025
+ query({ query, params }) {
4026
+ return {
4027
+ url: `/content-manager/preview/url/${params.contentType}`,
4028
+ method: "GET",
4029
+ config: {
4030
+ params: query
4031
+ }
4032
+ };
4033
+ }
4034
+ })
4035
+ })
4036
+ });
4037
+ const { useGetPreviewUrlQuery } = previewApi;
4038
+ const PreviewSidePanel = ({ model, documentId, document }) => {
4039
+ const { formatMessage } = useIntl();
4040
+ const { trackUsage } = useTracking();
4041
+ const [{ query }] = useQueryParams();
4042
+ const { data, error } = useGetPreviewUrlQuery({
4043
+ params: {
4044
+ contentType: model
4045
+ },
4046
+ query: {
4047
+ documentId,
4048
+ locale: document?.locale,
4049
+ status: document?.status
4050
+ }
4051
+ });
4052
+ if (!data?.data?.url || error) {
4053
+ return null;
4054
+ }
4055
+ const handleClick = () => {
4056
+ trackUsage("willOpenPreview");
4057
+ };
4058
+ return {
4059
+ title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
4060
+ content: /* @__PURE__ */ jsx(Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsx(
4061
+ Button,
4062
+ {
4063
+ variant: "tertiary",
4064
+ tag: Link,
4065
+ to: { pathname: "preview", search: stringify(query, { encode: false }) },
4066
+ onClick: handleClick,
4067
+ flex: "auto",
4068
+ children: formatMessage({
4069
+ id: "content-manager.preview.panel.button",
4070
+ defaultMessage: "Open preview"
4071
+ })
4072
+ }
4073
+ ) })
4074
+ };
4075
+ };
4076
+ const FEATURE_ID = "preview";
4077
+ const previewAdmin = {
4078
+ bootstrap(app) {
4079
+ if (!window.strapi.future.isEnabled(FEATURE_ID)) {
4080
+ return;
4081
+ }
4082
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
4083
+ contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
4084
+ }
4085
+ };
3832
4086
  const index = {
3833
4087
  register(app) {
3834
4088
  const cm = new ContentManagerPlugin();
@@ -3848,7 +4102,7 @@ const index = {
3848
4102
  app.router.addRoute({
3849
4103
  path: "content-manager/*",
3850
4104
  lazy: async () => {
3851
- const { Layout } = await import("./layout-oPBiO7RY.mjs");
4105
+ const { Layout } = await import("./layout-Bue_C6ui.mjs");
3852
4106
  return {
3853
4107
  Component: Layout
3854
4108
  };
@@ -3861,11 +4115,14 @@ const index = {
3861
4115
  if (typeof historyAdmin.bootstrap === "function") {
3862
4116
  historyAdmin.bootstrap(app);
3863
4117
  }
4118
+ if (typeof previewAdmin.bootstrap === "function") {
4119
+ previewAdmin.bootstrap(app);
4120
+ }
3864
4121
  },
3865
4122
  async registerTrads({ locales }) {
3866
4123
  const importedTrads = await Promise.all(
3867
4124
  locales.map((locale) => {
3868
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-BrCTWlZv.mjs"), "./translations/es.json": () => import("./es-CeXiYflN.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr-CD9VFbPM.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-CtsUxOvk.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
4125
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-D_BMf0hT.mjs"), "./translations/es.json": () => import("./es-D34tqjMw.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr--pg5jUbt.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-BHqhDq4V.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
3869
4126
  return {
3870
4127
  data: prefixPluginTranslations(data, PLUGIN_ID),
3871
4128
  locale
@@ -3886,13 +4143,16 @@ export {
3886
4143
  BulkActionsRenderer as B,
3887
4144
  COLLECTION_TYPES as C,
3888
4145
  DocumentStatus as D,
3889
- DEFAULT_SETTINGS as E,
3890
- convertEditLayoutToFieldLayouts as F,
3891
- useDocument as G,
4146
+ extractContentTypeComponents as E,
4147
+ DEFAULT_SETTINGS as F,
4148
+ convertEditLayoutToFieldLayouts as G,
3892
4149
  HOOKS as H,
3893
4150
  InjectionZone as I,
3894
- index as J,
3895
- useDocumentActions as K,
4151
+ useDocument as J,
4152
+ useGetPreviewUrlQuery as K,
4153
+ index as L,
4154
+ useContentManagerContext as M,
4155
+ useDocumentActions as N,
3896
4156
  Panels as P,
3897
4157
  RelativeTime as R,
3898
4158
  SINGLE_TYPES as S,
@@ -3910,18 +4170,18 @@ export {
3910
4170
  PERMISSIONS as k,
3911
4171
  DocumentRBAC as l,
3912
4172
  DOCUMENT_META_FIELDS as m,
3913
- useDocLayout as n,
3914
- useGetContentTypeConfigurationQuery as o,
3915
- CREATOR_FIELDS as p,
3916
- getMainField as q,
3917
- getDisplayName as r,
4173
+ CLONE_PATH as n,
4174
+ useDocLayout as o,
4175
+ useGetContentTypeConfigurationQuery as p,
4176
+ CREATOR_FIELDS as q,
4177
+ getMainField as r,
3918
4178
  setInitialData as s,
3919
- checkIfAttributeIsDisplayable as t,
4179
+ getDisplayName as t,
3920
4180
  useContentTypeSchema as u,
3921
- useGetAllDocumentsQuery as v,
3922
- convertListLayoutToFieldLayouts as w,
3923
- capitalise as x,
3924
- useUpdateContentTypeConfigurationMutation as y,
3925
- extractContentTypeComponents as z
4181
+ checkIfAttributeIsDisplayable as v,
4182
+ useGetAllDocumentsQuery as w,
4183
+ convertListLayoutToFieldLayouts as x,
4184
+ capitalise as y,
4185
+ useUpdateContentTypeConfigurationMutation as z
3926
4186
  };
3927
- //# sourceMappingURL=index-c_5DdJi-.mjs.map
4187
+ //# sourceMappingURL=index-V8MWkDSd.mjs.map