@strapi/content-manager 0.0.0-experimental.f31889311d753b5f7d95198ae84d8fce1d156cd6 → 0.0.0-experimental.f49f46a1c17445a39e8af3f63124bcccf73842e6

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 (197) hide show
  1. package/dist/_chunks/{ComponentConfigurationPage-BNxtMIfV.js → ComponentConfigurationPage-ClKl_TA2.js} +4 -4
  2. package/dist/_chunks/{ComponentConfigurationPage-BNxtMIfV.js.map → ComponentConfigurationPage-ClKl_TA2.js.map} +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-BWOQWCv2.mjs → ComponentConfigurationPage-D3ZWDAHG.mjs} +4 -4
  4. package/dist/_chunks/{ComponentConfigurationPage-BWOQWCv2.mjs.map → ComponentConfigurationPage-D3ZWDAHG.mjs.map} +1 -1
  5. package/dist/_chunks/{EditConfigurationPage-GTp-Ucnw.mjs → EditConfigurationPage-BYCBSJxP.mjs} +4 -4
  6. package/dist/_chunks/{EditConfigurationPage-GTp-Ucnw.mjs.map → EditConfigurationPage-BYCBSJxP.mjs.map} +1 -1
  7. package/dist/_chunks/{EditConfigurationPage-D340bYlT.js → EditConfigurationPage-OWez0Kxp.js} +4 -4
  8. package/dist/_chunks/{EditConfigurationPage-D340bYlT.js.map → EditConfigurationPage-OWez0Kxp.js.map} +1 -1
  9. package/dist/_chunks/{EditViewPage-BVMS5hT-.mjs → EditViewPage-5pdbvsO_.mjs} +63 -12
  10. package/dist/_chunks/EditViewPage-5pdbvsO_.mjs.map +1 -0
  11. package/dist/_chunks/{EditViewPage-CXkmnAvI.js → EditViewPage-BEs5iGDi.js} +62 -11
  12. package/dist/_chunks/EditViewPage-BEs5iGDi.js.map +1 -0
  13. package/dist/_chunks/{Field-Ibi32diw.js → Field-DNHm4wHx.js} +210 -119
  14. package/dist/_chunks/Field-DNHm4wHx.js.map +1 -0
  15. package/dist/_chunks/{Field-nNgv5bpd.mjs → Field-DcKuFHYK.mjs} +208 -117
  16. package/dist/_chunks/Field-DcKuFHYK.mjs.map +1 -0
  17. package/dist/_chunks/{Form-DodJsI2A.mjs → Form-CGwM_-5c.mjs} +36 -17
  18. package/dist/_chunks/Form-CGwM_-5c.mjs.map +1 -0
  19. package/dist/_chunks/{Form-Dhnh34ym.js → Form-CoRxWJOz.js} +36 -17
  20. package/dist/_chunks/Form-CoRxWJOz.js.map +1 -0
  21. package/dist/_chunks/{History-C9auUkDi.js → History-BcUTQrfG.js} +40 -97
  22. package/dist/_chunks/History-BcUTQrfG.js.map +1 -0
  23. package/dist/_chunks/{History-CKCSQXz_.mjs → History-DEvr3Q_V.mjs} +42 -99
  24. package/dist/_chunks/History-DEvr3Q_V.mjs.map +1 -0
  25. package/dist/_chunks/{ListConfigurationPage-Bg4rWUjX.js → ListConfigurationPage-BE_Ho7tV.js} +17 -6
  26. package/dist/_chunks/ListConfigurationPage-BE_Ho7tV.js.map +1 -0
  27. package/dist/_chunks/{ListConfigurationPage-CKEC4ttG.mjs → ListConfigurationPage-BM4zZZcM.mjs} +18 -7
  28. package/dist/_chunks/ListConfigurationPage-BM4zZZcM.mjs.map +1 -0
  29. package/dist/_chunks/{ListViewPage-B7_WJUjG.mjs → ListViewPage-BK2mkrql.mjs} +65 -39
  30. package/dist/_chunks/ListViewPage-BK2mkrql.mjs.map +1 -0
  31. package/dist/_chunks/{ListViewPage-C2gIeYHG.js → ListViewPage-BkT8Eao0.js} +68 -42
  32. package/dist/_chunks/ListViewPage-BkT8Eao0.js.map +1 -0
  33. package/dist/_chunks/{NoContentTypePage-Ckem6Ll6.mjs → NoContentTypePage-BvcAutu9.mjs} +2 -2
  34. package/dist/_chunks/{NoContentTypePage-Ckem6Ll6.mjs.map → NoContentTypePage-BvcAutu9.mjs.map} +1 -1
  35. package/dist/_chunks/{NoContentTypePage-DqgdUfyn.js → NoContentTypePage-C8mtyc4H.js} +2 -2
  36. package/dist/_chunks/{NoContentTypePage-DqgdUfyn.js.map → NoContentTypePage-C8mtyc4H.js.map} +1 -1
  37. package/dist/_chunks/{NoPermissionsPage-CF29Q-sW.js → NoPermissionsPage-B5Y9Y78B.js} +2 -2
  38. package/dist/_chunks/{NoPermissionsPage-CF29Q-sW.js.map → NoPermissionsPage-B5Y9Y78B.js.map} +1 -1
  39. package/dist/_chunks/{NoPermissionsPage-BO-GEjA4.mjs → NoPermissionsPage-BmbRz7PR.mjs} +2 -2
  40. package/dist/_chunks/{NoPermissionsPage-BO-GEjA4.mjs.map → NoPermissionsPage-BmbRz7PR.mjs.map} +1 -1
  41. package/dist/_chunks/Preview-BF8ZDYqS.js +286 -0
  42. package/dist/_chunks/Preview-BF8ZDYqS.js.map +1 -0
  43. package/dist/_chunks/Preview-DcexhKJE.mjs +267 -0
  44. package/dist/_chunks/Preview-DcexhKJE.mjs.map +1 -0
  45. package/dist/_chunks/{Relations-C0uC9J4f.js → Relations-BKnoK1R0.js} +72 -36
  46. package/dist/_chunks/Relations-BKnoK1R0.js.map +1 -0
  47. package/dist/_chunks/{Relations-DItV5eow.mjs → Relations-BjIzc4EK.mjs} +73 -37
  48. package/dist/_chunks/Relations-BjIzc4EK.mjs.map +1 -0
  49. package/dist/_chunks/{en-BrCTWlZv.mjs → en-CfIXaZf9.mjs} +26 -14
  50. package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-CfIXaZf9.mjs.map} +1 -1
  51. package/dist/_chunks/{en-uOUIxfcQ.js → en-DTWPCdTS.js} +26 -14
  52. package/dist/_chunks/{en-uOUIxfcQ.js.map → en-DTWPCdTS.js.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-DrNe6ctw.mjs → index-BW-rXkjn.mjs} +1027 -761
  62. package/dist/_chunks/index-BW-rXkjn.mjs.map +1 -0
  63. package/dist/_chunks/{index-Dd0nXyJF.js → index-DOzAG2cq.js} +1008 -741
  64. package/dist/_chunks/index-DOzAG2cq.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-B3ez7kvr.mjs → layout-DFVbgjp2.mjs} +8 -7
  70. package/dist/_chunks/layout-DFVbgjp2.mjs.map +1 -0
  71. package/dist/_chunks/{layout-CLLtt_5O.js → layout-RC3W2obV.js} +8 -7
  72. package/dist/_chunks/layout-RC3W2obV.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-B0hlsUU_.mjs → relations-Dogh8HWI.mjs} +6 -7
  78. package/dist/_chunks/relations-Dogh8HWI.mjs.map +1 -0
  79. package/dist/_chunks/{relations-bRxcNv1q.js → relations-zam7-5H7.js} +6 -7
  80. package/dist/_chunks/relations-zam7-5H7.js.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/DocumentStatus.d.ts +2 -2
  93. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  94. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  95. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  96. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  97. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  98. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  99. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  100. package/dist/admin/src/preview/constants.d.ts +1 -0
  101. package/dist/admin/src/preview/index.d.ts +4 -0
  102. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  103. package/dist/admin/src/preview/routes.d.ts +3 -0
  104. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  105. package/dist/admin/src/router.d.ts +1 -1
  106. package/dist/admin/src/services/api.d.ts +1 -1
  107. package/dist/admin/src/services/components.d.ts +2 -2
  108. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  109. package/dist/admin/src/services/documents.d.ts +19 -17
  110. package/dist/admin/src/services/init.d.ts +1 -1
  111. package/dist/admin/src/services/relations.d.ts +2 -2
  112. package/dist/admin/src/services/uid.d.ts +3 -3
  113. package/dist/admin/src/utils/validation.d.ts +4 -1
  114. package/dist/server/index.js +421 -183
  115. package/dist/server/index.js.map +1 -1
  116. package/dist/server/index.mjs +421 -183
  117. package/dist/server/index.mjs.map +1 -1
  118. package/dist/server/src/bootstrap.d.ts.map +1 -1
  119. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  120. package/dist/server/src/controllers/index.d.ts.map +1 -1
  121. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  122. package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
  123. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  124. package/dist/server/src/history/services/history.d.ts.map +1 -1
  125. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  126. package/dist/server/src/history/services/utils.d.ts +3 -3
  127. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  128. package/dist/server/src/index.d.ts +4 -4
  129. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  130. package/dist/server/src/preview/constants.d.ts +2 -0
  131. package/dist/server/src/preview/constants.d.ts.map +1 -0
  132. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  133. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  134. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  135. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  136. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  137. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  138. package/dist/server/src/preview/index.d.ts +4 -0
  139. package/dist/server/src/preview/index.d.ts.map +1 -0
  140. package/dist/server/src/preview/routes/index.d.ts +8 -0
  141. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  142. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  143. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  144. package/dist/server/src/preview/services/index.d.ts +15 -0
  145. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  146. package/dist/server/src/preview/services/preview-config.d.ts +30 -0
  147. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  148. package/dist/server/src/preview/services/preview.d.ts +12 -0
  149. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  150. package/dist/server/src/preview/utils.d.ts +18 -0
  151. package/dist/server/src/preview/utils.d.ts.map +1 -0
  152. package/dist/server/src/routes/index.d.ts.map +1 -1
  153. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  154. package/dist/server/src/services/document-metadata.d.ts +8 -8
  155. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  156. package/dist/server/src/services/index.d.ts +4 -4
  157. package/dist/server/src/services/index.d.ts.map +1 -1
  158. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  159. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  160. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  161. package/dist/server/src/utils/index.d.ts +2 -0
  162. package/dist/server/src/utils/index.d.ts.map +1 -1
  163. package/dist/shared/contracts/collection-types.d.ts +3 -1
  164. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  165. package/dist/shared/contracts/index.d.ts +1 -0
  166. package/dist/shared/contracts/index.d.ts.map +1 -1
  167. package/dist/shared/contracts/preview.d.ts +27 -0
  168. package/dist/shared/contracts/preview.d.ts.map +1 -0
  169. package/dist/shared/index.js +4 -0
  170. package/dist/shared/index.js.map +1 -1
  171. package/dist/shared/index.mjs +4 -0
  172. package/dist/shared/index.mjs.map +1 -1
  173. package/package.json +14 -14
  174. package/dist/_chunks/EditViewPage-BVMS5hT-.mjs.map +0 -1
  175. package/dist/_chunks/EditViewPage-CXkmnAvI.js.map +0 -1
  176. package/dist/_chunks/Field-Ibi32diw.js.map +0 -1
  177. package/dist/_chunks/Field-nNgv5bpd.mjs.map +0 -1
  178. package/dist/_chunks/Form-Dhnh34ym.js.map +0 -1
  179. package/dist/_chunks/Form-DodJsI2A.mjs.map +0 -1
  180. package/dist/_chunks/History-C9auUkDi.js.map +0 -1
  181. package/dist/_chunks/History-CKCSQXz_.mjs.map +0 -1
  182. package/dist/_chunks/ListConfigurationPage-Bg4rWUjX.js.map +0 -1
  183. package/dist/_chunks/ListConfigurationPage-CKEC4ttG.mjs.map +0 -1
  184. package/dist/_chunks/ListViewPage-B7_WJUjG.mjs.map +0 -1
  185. package/dist/_chunks/ListViewPage-C2gIeYHG.js.map +0 -1
  186. package/dist/_chunks/Relations-C0uC9J4f.js.map +0 -1
  187. package/dist/_chunks/Relations-DItV5eow.mjs.map +0 -1
  188. package/dist/_chunks/index-Dd0nXyJF.js.map +0 -1
  189. package/dist/_chunks/index-DrNe6ctw.mjs.map +0 -1
  190. package/dist/_chunks/layout-B3ez7kvr.mjs.map +0 -1
  191. package/dist/_chunks/layout-CLLtt_5O.js.map +0 -1
  192. package/dist/_chunks/relations-B0hlsUU_.mjs.map +0 -1
  193. package/dist/_chunks/relations-bRxcNv1q.js.map +0 -1
  194. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  195. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  196. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  197. package/strapi-server.js +0 -3
@@ -1,11 +1,12 @@
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, Typography, Dialog, Modal, Radio, Status, Box, SingleSelect, SingleSelectOption, Loader, IconButton, Tooltip, LinkButton } from "@strapi/design-system";
6
+ import { Menu, Button, VisuallyHidden, Flex, Dialog, Modal, Typography, 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 { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
9
10
  import { styled } from "styled-components";
10
11
  import * as yup from "yup";
11
12
  import { ValidationError } from "yup";
@@ -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
  }),
@@ -303,6 +318,11 @@ const documentApi = contentManagerApi.injectEndpoints({
303
318
  {
304
319
  type: "Document",
305
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`
306
326
  }
307
327
  ];
308
328
  }
@@ -366,7 +386,8 @@ const documentApi = contentManagerApi.injectEndpoints({
366
386
  type: "Document",
367
387
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
368
388
  },
369
- "Relations"
389
+ "Relations",
390
+ { type: "UidAvailability", id: model }
370
391
  ];
371
392
  },
372
393
  async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
@@ -449,20 +470,39 @@ const buildValidParams = (query) => {
449
470
  const isBaseQueryError = (error) => {
450
471
  return error.name !== void 0;
451
472
  };
452
- 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 }) => {
453
492
  const createModelSchema = (attributes2) => yup.object().shape(
454
493
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
455
494
  if (DOCUMENT_META_FIELDS.includes(name)) {
456
495
  return acc;
457
496
  }
458
497
  const validations = [
498
+ addNullableValidation,
459
499
  addRequiredValidation,
460
500
  addMinLengthValidation,
461
501
  addMaxLengthValidation,
462
502
  addMinValidation,
463
503
  addMaxValidation,
464
504
  addRegexValidation
465
- ].map((fn) => fn(attribute));
505
+ ].map((fn) => fn(attribute, options));
466
506
  const transformSchema = pipe(...validations);
467
507
  switch (attribute.type) {
468
508
  case "component": {
@@ -472,12 +512,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
472
512
  ...acc,
473
513
  [name]: transformSchema(
474
514
  yup.array().of(createModelSchema(attributes3).nullable(false))
475
- )
515
+ ).test(arrayValidator(attribute, options))
476
516
  };
477
517
  } else {
478
518
  return {
479
519
  ...acc,
480
- [name]: transformSchema(createModelSchema(attributes3))
520
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
481
521
  };
482
522
  }
483
523
  }
@@ -499,7 +539,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
499
539
  }
500
540
  )
501
541
  )
502
- )
542
+ ).test(arrayValidator(attribute, options))
503
543
  };
504
544
  case "relation":
505
545
  return {
@@ -511,7 +551,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
511
551
  } else if (Array.isArray(value)) {
512
552
  return yup.array().of(
513
553
  yup.object().shape({
514
- id: yup.string().required()
554
+ id: yup.number().required()
515
555
  })
516
556
  );
517
557
  } else if (typeof value === "object") {
@@ -563,6 +603,14 @@ const createAttributeSchema = (attribute) => {
563
603
  if (!value || typeof value === "string" && value.length === 0) {
564
604
  return true;
565
605
  }
606
+ if (typeof value === "object") {
607
+ try {
608
+ JSON.stringify(value);
609
+ return true;
610
+ } catch (err) {
611
+ return false;
612
+ }
613
+ }
566
614
  try {
567
615
  JSON.parse(value);
568
616
  return true;
@@ -581,13 +629,7 @@ const createAttributeSchema = (attribute) => {
581
629
  return yup.mixed();
582
630
  }
583
631
  };
584
- const addRequiredValidation = (attribute) => (schema) => {
585
- if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
586
- return schema.min(1, translatedErrors.required);
587
- }
588
- if (attribute.required && attribute.type !== "relation") {
589
- return schema.required(translatedErrors.required);
590
- }
632
+ const nullableSchema = (schema) => {
591
633
  return schema?.nullable ? schema.nullable() : (
592
634
  // In some cases '.nullable' will not be available on the schema.
593
635
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -595,7 +637,22 @@ const addRequiredValidation = (attribute) => (schema) => {
595
637
  schema
596
638
  );
597
639
  };
598
- 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
+ }
599
656
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
600
657
  return schema.min(attribute.minLength, {
601
658
  ...translatedErrors.minLength,
@@ -617,32 +674,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
617
674
  }
618
675
  return schema;
619
676
  };
620
- const addMinValidation = (attribute) => (schema) => {
621
- 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) {
622
682
  const min = toInteger(attribute.min);
623
- if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
624
- if (!attribute.required && "test" in schema && min) {
625
- return schema.test(
626
- "custom-min",
627
- {
628
- ...translatedErrors.min,
629
- values: {
630
- min: attribute.min
631
- }
632
- },
633
- (value) => {
634
- if (!value) {
635
- return true;
636
- }
637
- if (Array.isArray(value) && value.length === 0) {
638
- return true;
639
- }
640
- return value.length >= min;
641
- }
642
- );
643
- }
644
- }
645
- if ("min" in schema && min) {
683
+ if (min) {
646
684
  return schema.min(min, {
647
685
  ...translatedErrors.min,
648
686
  values: {
@@ -760,19 +798,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
760
798
  }, {});
761
799
  return componentsByKey;
762
800
  };
763
- 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);
764
900
  const { toggleNotification } = useNotification();
765
901
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
902
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
766
903
  const {
767
- currentData: data,
768
- isLoading: isLoadingDocument,
769
- isFetching: isFetchingDocument,
770
- error
771
- } = useGetDocumentQuery(args, {
772
- ...opts,
773
- skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
774
- });
775
- 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;
776
910
  React.useEffect(() => {
777
911
  if (error) {
778
912
  toggleNotification({
@@ -780,90 +914,346 @@ const useDocument = (args, opts) => {
780
914
  message: formatAPIError(error)
781
915
  });
782
916
  }
783
- }, [toggleNotification, error, formatAPIError, args.collectionType]);
784
- const validationSchema = React.useMemo(() => {
785
- if (!schema) {
786
- return null;
787
- }
788
- return createYupSchema(schema.attributes, components);
789
- }, [schema, components]);
790
- const validate = React.useCallback(
791
- (document) => {
792
- if (!validationSchema) {
793
- throw new Error(
794
- "There is no validation schema generated, this is likely due to the schema not being loaded yet."
795
- );
796
- }
797
- try {
798
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
799
- return null;
800
- } catch (error2) {
801
- if (error2 instanceof ValidationError) {
802
- return getYupValidationErrors(error2);
803
- }
804
- throw error2;
805
- }
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
806
925
  },
807
- [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]
808
942
  );
809
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
810
943
  return {
811
- components,
812
- document: data?.data,
813
- meta: data?.meta,
944
+ error,
814
945
  isLoading,
815
- schema,
816
- validate
817
- };
818
- };
819
- const useDoc = () => {
820
- const { id, slug, collectionType, origin } = useParams();
821
- const [{ query }] = useQueryParams();
822
- const params = React.useMemo(() => buildValidParams(query), [query]);
823
- if (!collectionType) {
824
- throw new Error("Could not find collectionType in url params");
825
- }
826
- if (!slug) {
827
- throw new Error("Could not find model in url params");
828
- }
829
- return {
830
- collectionType,
831
- model: slug,
832
- id: origin || id === "create" ? void 0 : id,
833
- ...useDocument(
834
- { documentId: origin || id, model: slug, collectionType, params },
835
- {
836
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
837
- }
838
- )
946
+ edit,
947
+ list: listLayout
839
948
  };
840
949
  };
841
- const prefixPluginTranslations = (trad, pluginId) => {
842
- if (!pluginId) {
843
- throw new TypeError("pluginId can't be empty");
844
- }
845
- return Object.keys(trad).reduce((acc, current) => {
846
- acc[`${pluginId}.${current}`] = trad[current];
847
- return acc;
848
- }, {});
849
- };
850
- const getTranslation = (id) => `content-manager.${id}`;
851
- const DEFAULT_UNEXPECTED_ERROR_MSG = {
852
- id: "notification.error",
853
- defaultMessage: "An error occurred, please try again"
950
+ const useDocLayout = () => {
951
+ const { model } = useDoc();
952
+ return useDocumentLayout(model);
854
953
  };
855
- const useDocumentActions = () => {
856
- const { toggleNotification } = useNotification();
857
- const { formatMessage } = useIntl();
858
- const { trackUsage } = useTracking();
859
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
860
- const [deleteDocument] = useDeleteDocumentMutation();
861
- const _delete = React.useCallback(
862
- async ({ collectionType, model, documentId, params }, trackerProperty) => {
863
- try {
864
- trackUsage("willDeleteEntry", trackerProperty);
865
- const res = await deleteDocument({
866
- collectionType,
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);
1255
+ const res = await deleteDocument({
1256
+ collectionType,
867
1257
  model,
868
1258
  documentId,
869
1259
  params
@@ -1171,6 +1561,7 @@ const useDocumentActions = () => {
1171
1561
  defaultMessage: "Saved document"
1172
1562
  })
1173
1563
  });
1564
+ setCurrentStep("contentManager.success");
1174
1565
  return res.data;
1175
1566
  } catch (err) {
1176
1567
  toggleNotification({
@@ -1210,7 +1601,7 @@ const useDocumentActions = () => {
1210
1601
  throw err;
1211
1602
  }
1212
1603
  },
1213
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1604
+ [autoCloneDocument, formatMessage, toggleNotification]
1214
1605
  );
1215
1606
  const [cloneDocument] = useCloneDocumentMutation();
1216
1607
  const clone = React.useCallback(
@@ -1236,6 +1627,7 @@ const useDocumentActions = () => {
1236
1627
  defaultMessage: "Cloned document"
1237
1628
  })
1238
1629
  });
1630
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1239
1631
  return res.data;
1240
1632
  } catch (err) {
1241
1633
  toggleNotification({
@@ -1246,7 +1638,7 @@ const useDocumentActions = () => {
1246
1638
  throw err;
1247
1639
  }
1248
1640
  },
1249
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1641
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1250
1642
  );
1251
1643
  const [getDoc] = useLazyGetDocumentQuery();
1252
1644
  const getDocument = React.useCallback(
@@ -1271,10 +1663,10 @@ const useDocumentActions = () => {
1271
1663
  update
1272
1664
  };
1273
1665
  };
1274
- const ProtectedHistoryPage = lazy(
1275
- () => import("./History-CKCSQXz_.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1666
+ const ProtectedHistoryPage = React.lazy(
1667
+ () => import("./History-DEvr3Q_V.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1276
1668
  );
1277
- const routes$1 = [
1669
+ const routes$2 = [
1278
1670
  {
1279
1671
  path: ":collectionType/:slug/:id/history",
1280
1672
  Component: ProtectedHistoryPage
@@ -1284,32 +1676,45 @@ const routes$1 = [
1284
1676
  Component: ProtectedHistoryPage
1285
1677
  }
1286
1678
  ];
1679
+ const ProtectedPreviewPage = React.lazy(
1680
+ () => import("./Preview-DcexhKJE.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
+ ];
1287
1692
  const ProtectedEditViewPage = lazy(
1288
- () => import("./EditViewPage-BVMS5hT-.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1693
+ () => import("./EditViewPage-5pdbvsO_.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1289
1694
  );
1290
1695
  const ProtectedListViewPage = lazy(
1291
- () => import("./ListViewPage-B7_WJUjG.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1696
+ () => import("./ListViewPage-BK2mkrql.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1292
1697
  );
1293
1698
  const ProtectedListConfiguration = lazy(
1294
- () => import("./ListConfigurationPage-CKEC4ttG.mjs").then((mod) => ({
1699
+ () => import("./ListConfigurationPage-BM4zZZcM.mjs").then((mod) => ({
1295
1700
  default: mod.ProtectedListConfiguration
1296
1701
  }))
1297
1702
  );
1298
1703
  const ProtectedEditConfigurationPage = lazy(
1299
- () => import("./EditConfigurationPage-GTp-Ucnw.mjs").then((mod) => ({
1704
+ () => import("./EditConfigurationPage-BYCBSJxP.mjs").then((mod) => ({
1300
1705
  default: mod.ProtectedEditConfigurationPage
1301
1706
  }))
1302
1707
  );
1303
1708
  const ProtectedComponentConfigurationPage = lazy(
1304
- () => import("./ComponentConfigurationPage-BWOQWCv2.mjs").then((mod) => ({
1709
+ () => import("./ComponentConfigurationPage-D3ZWDAHG.mjs").then((mod) => ({
1305
1710
  default: mod.ProtectedComponentConfigurationPage
1306
1711
  }))
1307
1712
  );
1308
1713
  const NoPermissions = lazy(
1309
- () => import("./NoPermissionsPage-BO-GEjA4.mjs").then((mod) => ({ default: mod.NoPermissions }))
1714
+ () => import("./NoPermissionsPage-BmbRz7PR.mjs").then((mod) => ({ default: mod.NoPermissions }))
1310
1715
  );
1311
1716
  const NoContentType = lazy(
1312
- () => import("./NoContentTypePage-Ckem6Ll6.mjs").then((mod) => ({ default: mod.NoContentType }))
1717
+ () => import("./NoContentTypePage-BvcAutu9.mjs").then((mod) => ({ default: mod.NoContentType }))
1313
1718
  );
1314
1719
  const CollectionTypePages = () => {
1315
1720
  const { collectionType } = useParams();
@@ -1321,7 +1726,7 @@ const CollectionTypePages = () => {
1321
1726
  const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
1322
1727
  const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
1323
1728
  const LIST_RELATIVE_PATH = ":collectionType/:slug";
1324
- const LIST_PATH = `/content-manager/${LIST_RELATIVE_PATH}`;
1729
+ const LIST_PATH = `/content-manager/collection-types/:slug`;
1325
1730
  const routes = [
1326
1731
  {
1327
1732
  path: LIST_RELATIVE_PATH,
@@ -1355,6 +1760,7 @@ const routes = [
1355
1760
  path: "no-content-types",
1356
1761
  Component: NoContentType
1357
1762
  },
1763
+ ...routes$2,
1358
1764
  ...routes$1
1359
1765
  ];
1360
1766
  const DocumentActions = ({ actions: actions2 }) => {
@@ -1423,12 +1829,14 @@ const DocumentActionButton = (action) => {
1423
1829
  /* @__PURE__ */ jsx(
1424
1830
  Button,
1425
1831
  {
1426
- flex: 1,
1832
+ flex: "auto",
1427
1833
  startIcon: action.icon,
1428
1834
  disabled: action.disabled,
1429
1835
  onClick: handleClick(action),
1430
1836
  justifyContent: "center",
1431
1837
  variant: action.variant || "default",
1838
+ paddingTop: "7px",
1839
+ paddingBottom: "7px",
1432
1840
  children: action.label
1433
1841
  }
1434
1842
  ),
@@ -1451,6 +1859,11 @@ const DocumentActionButton = (action) => {
1451
1859
  ) : null
1452
1860
  ] });
1453
1861
  };
1862
+ const MenuItem = styled(Menu.Item)`
1863
+ &:hover {
1864
+ background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
1865
+ }
1866
+ `;
1454
1867
  const DocumentActionsMenu = ({
1455
1868
  actions: actions2,
1456
1869
  children,
@@ -1506,44 +1919,35 @@ const DocumentActionsMenu = ({
1506
1919
  ]
1507
1920
  }
1508
1921
  ),
1509
- /* @__PURE__ */ jsxs(Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1922
+ /* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1510
1923
  actions2.map((action) => {
1511
1924
  return /* @__PURE__ */ jsx(
1512
- Menu.Item,
1925
+ MenuItem,
1513
1926
  {
1514
1927
  disabled: action.disabled,
1515
1928
  onSelect: handleClick(action),
1516
1929
  display: "block",
1517
- children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
1518
- /* @__PURE__ */ jsxs(
1519
- Flex,
1520
- {
1521
- color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1522
- gap: 2,
1523
- tag: "span",
1524
- children: [
1525
- /* @__PURE__ */ jsx("span", { children: action.icon }),
1526
- action.label
1527
- ]
1528
- }
1529
- ),
1530
- action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
1531
- Flex,
1532
- {
1533
- alignItems: "center",
1534
- background: "alternative100",
1535
- borderStyle: "solid",
1536
- borderColor: "alternative200",
1537
- borderWidth: "1px",
1538
- height: 5,
1539
- paddingLeft: 2,
1540
- paddingRight: 2,
1541
- hasRadius: true,
1542
- color: "alternative600",
1543
- children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
1544
- }
1545
- )
1546
- ] })
1930
+ isVariantDanger: action.variant === "danger",
1931
+ isDisabled: action.disabled,
1932
+ children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxs(
1933
+ Flex,
1934
+ {
1935
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1936
+ gap: 2,
1937
+ tag: "span",
1938
+ children: [
1939
+ /* @__PURE__ */ jsx(
1940
+ Flex,
1941
+ {
1942
+ tag: "span",
1943
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1944
+ children: action.icon
1945
+ }
1946
+ ),
1947
+ action.label
1948
+ ]
1949
+ }
1950
+ ) })
1547
1951
  },
1548
1952
  action.id
1549
1953
  );
@@ -1585,6 +1989,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1585
1989
  return "primary600";
1586
1990
  }
1587
1991
  };
1992
+ const convertActionVariantToIconColor = (variant = "secondary") => {
1993
+ switch (variant) {
1994
+ case "danger":
1995
+ return "danger600";
1996
+ case "secondary":
1997
+ return "neutral500";
1998
+ case "success":
1999
+ return "success600";
2000
+ default:
2001
+ return "primary600";
2002
+ }
2003
+ };
1588
2004
  const DocumentActionConfirmDialog = ({
1589
2005
  onClose,
1590
2006
  onCancel,
@@ -1611,11 +2027,11 @@ const DocumentActionConfirmDialog = ({
1611
2027
  /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
1612
2028
  /* @__PURE__ */ jsx(Dialog.Body, { children: content }),
1613
2029
  /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
1614
- /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
2030
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
1615
2031
  id: "app.components.Button.cancel",
1616
2032
  defaultMessage: "Cancel"
1617
2033
  }) }) }),
1618
- /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
2034
+ /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
1619
2035
  id: "app.components.Button.confirm",
1620
2036
  defaultMessage: "Confirm"
1621
2037
  }) })
@@ -1642,6 +2058,18 @@ const DocumentActionModal = ({
1642
2058
  typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
1643
2059
  ] }) });
1644
2060
  };
2061
+ const transformData = (data) => {
2062
+ if (Array.isArray(data)) {
2063
+ return data.map(transformData);
2064
+ }
2065
+ if (typeof data === "object" && data !== null) {
2066
+ if ("apiData" in data) {
2067
+ return data.apiData;
2068
+ }
2069
+ return mapValues(transformData)(data);
2070
+ }
2071
+ return data;
2072
+ };
1645
2073
  const PublishAction$1 = ({
1646
2074
  activeTab,
1647
2075
  documentId,
@@ -1654,12 +2082,10 @@ const PublishAction$1 = ({
1654
2082
  const navigate = useNavigate();
1655
2083
  const { toggleNotification } = useNotification();
1656
2084
  const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
2085
+ const isListView = useMatch(LIST_PATH) !== null;
1657
2086
  const isCloning = useMatch(CLONE_PATH) !== null;
1658
2087
  const { formatMessage } = useIntl();
1659
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1660
- "PublishAction",
1661
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1662
- );
2088
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1663
2089
  const { publish } = useDocumentActions();
1664
2090
  const [
1665
2091
  countDraftRelations,
@@ -1711,24 +2137,25 @@ const PublishAction$1 = ({
1711
2137
  }
1712
2138
  }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
1713
2139
  React.useEffect(() => {
1714
- if (documentId) {
1715
- const fetchDraftRelationsCount = async () => {
1716
- const { data, error } = await countDraftRelations({
1717
- collectionType,
1718
- model,
1719
- documentId,
1720
- params
1721
- });
1722
- if (error) {
1723
- throw error;
1724
- }
1725
- if (data) {
1726
- setServerCountOfDraftRelations(data.data);
1727
- }
1728
- };
1729
- fetchDraftRelationsCount();
2140
+ if (!document || !document.documentId || isListView) {
2141
+ return;
1730
2142
  }
1731
- }, [documentId, countDraftRelations, collectionType, model, params]);
2143
+ const fetchDraftRelationsCount = async () => {
2144
+ const { data, error } = await countDraftRelations({
2145
+ collectionType,
2146
+ model,
2147
+ documentId,
2148
+ params
2149
+ });
2150
+ if (error) {
2151
+ throw error;
2152
+ }
2153
+ if (data) {
2154
+ setServerCountOfDraftRelations(data.data);
2155
+ }
2156
+ };
2157
+ fetchDraftRelationsCount();
2158
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
1732
2159
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1733
2160
  if (!schema?.options?.draftAndPublish) {
1734
2161
  return null;
@@ -1736,7 +2163,9 @@ const PublishAction$1 = ({
1736
2163
  const performPublish = async () => {
1737
2164
  setSubmitting(true);
1738
2165
  try {
1739
- const { errors } = await validate();
2166
+ const { errors } = await validate(true, {
2167
+ status: "published"
2168
+ });
1740
2169
  if (errors) {
1741
2170
  toggleNotification({
1742
2171
  type: "danger",
@@ -1754,7 +2183,7 @@ const PublishAction$1 = ({
1754
2183
  documentId,
1755
2184
  params
1756
2185
  },
1757
- formValues
2186
+ transformData(formValues)
1758
2187
  );
1759
2188
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1760
2189
  navigate({
@@ -1769,7 +2198,8 @@ const PublishAction$1 = ({
1769
2198
  }
1770
2199
  };
1771
2200
  const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1772
- const hasDraftRelations = totalDraftRelations > 0;
2201
+ const enableDraftRelationsCount = false;
2202
+ const hasDraftRelations = enableDraftRelationsCount;
1773
2203
  return {
1774
2204
  /**
1775
2205
  * Disabled when:
@@ -1786,9 +2216,6 @@ const PublishAction$1 = ({
1786
2216
  defaultMessage: "Publish"
1787
2217
  }),
1788
2218
  onClick: async () => {
1789
- if (hasDraftRelations) {
1790
- return;
1791
- }
1792
2219
  await performPublish();
1793
2220
  },
1794
2221
  dialog: hasDraftRelations ? {
@@ -1827,10 +2254,6 @@ const UpdateAction = ({
1827
2254
  const cloneMatch = useMatch(CLONE_PATH);
1828
2255
  const isCloning = cloneMatch !== null;
1829
2256
  const { formatMessage } = useIntl();
1830
- useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1831
- canCreate: canCreate2,
1832
- canUpdate: canUpdate2
1833
- }));
1834
2257
  const { create, update, clone } = useDocumentActions();
1835
2258
  const [{ query, rawQuery }] = useQueryParams();
1836
2259
  const params = React.useMemo(() => buildValidParams(query), [query]);
@@ -1850,13 +2273,15 @@ const UpdateAction = ({
1850
2273
  */
1851
2274
  disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1852
2275
  label: formatMessage({
1853
- id: "content-manager.containers.Edit.save",
2276
+ id: "global.save",
1854
2277
  defaultMessage: "Save"
1855
2278
  }),
1856
2279
  onClick: async () => {
1857
2280
  setSubmitting(true);
1858
2281
  try {
1859
- const { errors } = await validate();
2282
+ const { errors } = await validate(true, {
2283
+ status: "draft"
2284
+ });
1860
2285
  if (errors) {
1861
2286
  toggleNotification({
1862
2287
  type: "danger",
@@ -1874,7 +2299,7 @@ const UpdateAction = ({
1874
2299
  documentId: cloneMatch.params.origin,
1875
2300
  params
1876
2301
  },
1877
- document
2302
+ transformData(document)
1878
2303
  );
1879
2304
  if ("data" in res) {
1880
2305
  navigate(
@@ -1895,7 +2320,7 @@ const UpdateAction = ({
1895
2320
  documentId,
1896
2321
  params
1897
2322
  },
1898
- document
2323
+ transformData(document)
1899
2324
  );
1900
2325
  if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1901
2326
  setErrors(formatValidationErrors(res.error));
@@ -1908,7 +2333,7 @@ const UpdateAction = ({
1908
2333
  model,
1909
2334
  params
1910
2335
  },
1911
- document
2336
+ transformData(document)
1912
2337
  );
1913
2338
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1914
2339
  navigate(
@@ -1961,7 +2386,7 @@ const UnpublishAction$1 = ({
1961
2386
  id: "app.utils.unpublish",
1962
2387
  defaultMessage: "Unpublish"
1963
2388
  }),
1964
- icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
2389
+ icon: /* @__PURE__ */ jsx(Cross, {}),
1965
2390
  onClick: async () => {
1966
2391
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1967
2392
  if (!documentId) {
@@ -2073,7 +2498,7 @@ const DiscardAction = ({
2073
2498
  id: "content-manager.actions.discard.label",
2074
2499
  defaultMessage: "Discard changes"
2075
2500
  }),
2076
- icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
2501
+ icon: /* @__PURE__ */ jsx(Cross, {}),
2077
2502
  position: ["panel", "table-row"],
2078
2503
  variant: "danger",
2079
2504
  dialog: {
@@ -2101,11 +2526,6 @@ const DiscardAction = ({
2101
2526
  };
2102
2527
  };
2103
2528
  DiscardAction.type = "discard";
2104
- const StyledCrossCircle = styled(CrossCircle)`
2105
- path {
2106
- fill: currentColor;
2107
- }
2108
- `;
2109
2529
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2110
2530
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2111
2531
  const RelativeTime = React.forwardRef(
@@ -2118,7 +2538,7 @@ const RelativeTime = React.forwardRef(
2118
2538
  });
2119
2539
  const unit = intervals.find((intervalUnit) => {
2120
2540
  return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
2121
- });
2541
+ }) ?? "seconds";
2122
2542
  const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
2123
2543
  const customInterval = customIntervals.find(
2124
2544
  (custom) => interval[custom.unit] < custom.threshold
@@ -2152,19 +2572,29 @@ const getDisplayName = ({
2152
2572
  return email ?? "";
2153
2573
  };
2154
2574
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2155
- const DocumentStatus = ({ status = "draft", ...restProps }) => {
2156
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
2157
- return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2575
+ const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
2576
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2577
+ const { formatMessage } = useIntl();
2578
+ return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
2579
+ id: `content-manager.containers.List.${status}`,
2580
+ defaultMessage: capitalise(status)
2581
+ }) }) });
2158
2582
  };
2159
2583
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2160
2584
  const { formatMessage } = useIntl();
2161
2585
  const isCloning = useMatch(CLONE_PATH) !== null;
2586
+ const params = useParams();
2162
2587
  const title = isCreating ? formatMessage({
2163
2588
  id: "content-manager.containers.edit.title.new",
2164
2589
  defaultMessage: "Create an entry"
2165
2590
  }) : documentTitle;
2166
2591
  return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2167
- /* @__PURE__ */ jsx(BackButton, {}),
2592
+ /* @__PURE__ */ jsx(
2593
+ BackButton,
2594
+ {
2595
+ fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
2596
+ }
2597
+ ),
2168
2598
  /* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2169
2599
  /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
2170
2600
  /* @__PURE__ */ jsx(HeaderToolbar, {})
@@ -2252,12 +2682,12 @@ const Information = ({ activeTab }) => {
2252
2682
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2253
2683
  label: formatMessage({
2254
2684
  id: "content-manager.containers.edit.information.last-published.label",
2255
- defaultMessage: "Last published"
2685
+ defaultMessage: "Published"
2256
2686
  }),
2257
2687
  value: formatMessage(
2258
2688
  {
2259
2689
  id: "content-manager.containers.edit.information.last-published.value",
2260
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2690
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2261
2691
  },
2262
2692
  {
2263
2693
  time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2270,12 +2700,12 @@ const Information = ({ activeTab }) => {
2270
2700
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2271
2701
  label: formatMessage({
2272
2702
  id: "content-manager.containers.edit.information.last-draft.label",
2273
- defaultMessage: "Last draft"
2703
+ defaultMessage: "Updated"
2274
2704
  }),
2275
2705
  value: formatMessage(
2276
2706
  {
2277
2707
  id: "content-manager.containers.edit.information.last-draft.value",
2278
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2708
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2279
2709
  },
2280
2710
  {
2281
2711
  time: /* @__PURE__ */ jsx(
@@ -2293,12 +2723,12 @@ const Information = ({ activeTab }) => {
2293
2723
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2294
2724
  label: formatMessage({
2295
2725
  id: "content-manager.containers.edit.information.document.label",
2296
- defaultMessage: "Document"
2726
+ defaultMessage: "Created"
2297
2727
  }),
2298
2728
  value: formatMessage(
2299
2729
  {
2300
2730
  id: "content-manager.containers.edit.information.document.value",
2301
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2731
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2302
2732
  },
2303
2733
  {
2304
2734
  time: /* @__PURE__ */ jsx(
@@ -2336,523 +2766,277 @@ const Information = ({ activeTab }) => {
2336
2766
  );
2337
2767
  };
2338
2768
  const HeaderActions = ({ actions: actions2 }) => {
2339
- return /* @__PURE__ */ jsx(Flex, { children: actions2.map((action) => {
2340
- if ("options" in action) {
2769
+ const [dialogId, setDialogId] = React.useState(null);
2770
+ const handleClick = (action) => async (e) => {
2771
+ if (!("options" in action)) {
2772
+ const { onClick = () => false, dialog, id } = action;
2773
+ const muteDialog = await onClick(e);
2774
+ if (dialog && !muteDialog) {
2775
+ e.preventDefault();
2776
+ setDialogId(id);
2777
+ }
2778
+ }
2779
+ };
2780
+ const handleClose = () => {
2781
+ setDialogId(null);
2782
+ };
2783
+ return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
2784
+ if (action.options) {
2341
2785
  return /* @__PURE__ */ jsx(
2342
2786
  SingleSelect,
2343
2787
  {
2344
2788
  size: "S",
2345
- disabled: action.disabled,
2346
- "aria-label": action.label,
2347
2789
  onChange: action.onSelect,
2348
- value: action.value,
2790
+ "aria-label": action.label,
2791
+ ...action,
2349
2792
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
2350
2793
  },
2351
2794
  action.id
2352
2795
  );
2353
2796
  } else {
2354
- return null;
2355
- }
2356
- }) });
2357
- };
2358
- const ConfigureTheViewAction = ({ collectionType, model }) => {
2359
- const navigate = useNavigate();
2360
- const { formatMessage } = useIntl();
2361
- return {
2362
- label: formatMessage({
2363
- id: "app.links.configure-view",
2364
- defaultMessage: "Configure the view"
2365
- }),
2366
- icon: /* @__PURE__ */ jsx(ListPlus, {}),
2367
- onClick: () => {
2368
- navigate(`../${collectionType}/${model}/configurations/edit`);
2369
- },
2370
- position: "header"
2371
- };
2372
- };
2373
- ConfigureTheViewAction.type = "configure-the-view";
2374
- const EditTheModelAction = ({ model }) => {
2375
- const navigate = useNavigate();
2376
- const { formatMessage } = useIntl();
2377
- return {
2378
- label: formatMessage({
2379
- id: "content-manager.link-to-ctb",
2380
- defaultMessage: "Edit the model"
2381
- }),
2382
- icon: /* @__PURE__ */ jsx(Pencil, {}),
2383
- onClick: () => {
2384
- navigate(`/plugins/content-type-builder/content-types/${model}`);
2385
- },
2386
- position: "header"
2387
- };
2388
- };
2389
- EditTheModelAction.type = "edit-the-model";
2390
- const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2391
- const navigate = useNavigate();
2392
- const { formatMessage } = useIntl();
2393
- const listViewPathMatch = useMatch(LIST_PATH);
2394
- const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
2395
- const { delete: deleteAction } = useDocumentActions();
2396
- const { toggleNotification } = useNotification();
2397
- const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
2398
- return {
2399
- disabled: !canDelete || !document,
2400
- label: formatMessage({
2401
- id: "content-manager.actions.delete.label",
2402
- defaultMessage: "Delete document"
2403
- }),
2404
- icon: /* @__PURE__ */ jsx(Trash, {}),
2405
- dialog: {
2406
- type: "dialog",
2407
- title: formatMessage({
2408
- id: "app.components.ConfirmDialog.title",
2409
- defaultMessage: "Confirmation"
2410
- }),
2411
- content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2412
- /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2413
- /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2414
- id: "content-manager.actions.delete.dialog.body",
2415
- defaultMessage: "Are you sure?"
2416
- }) })
2417
- ] }),
2418
- onConfirm: async () => {
2419
- if (!listViewPathMatch) {
2420
- setSubmitting(true);
2421
- }
2422
- try {
2423
- if (!documentId && collectionType !== SINGLE_TYPES) {
2424
- console.error(
2425
- "You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
2426
- );
2427
- toggleNotification({
2428
- message: formatMessage({
2429
- id: "content-manager.actions.delete.error",
2430
- defaultMessage: "An error occurred while trying to delete the document."
2431
- }),
2432
- type: "danger"
2433
- });
2434
- return;
2435
- }
2436
- const res = await deleteAction({
2437
- documentId,
2438
- model,
2439
- collectionType,
2440
- params: {
2441
- locale: "*"
2797
+ if (action.type === "icon") {
2798
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
2799
+ /* @__PURE__ */ jsx(
2800
+ IconButton,
2801
+ {
2802
+ disabled: action.disabled,
2803
+ label: action.label,
2804
+ size: "S",
2805
+ onClick: handleClick(action),
2806
+ children: action.icon
2442
2807
  }
2443
- });
2444
- if (!("error" in res)) {
2445
- navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
2446
- }
2447
- } finally {
2448
- if (!listViewPathMatch) {
2449
- setSubmitting(false);
2450
- }
2451
- }
2808
+ ),
2809
+ action.dialog ? /* @__PURE__ */ jsx(
2810
+ HeaderActionDialog,
2811
+ {
2812
+ ...action.dialog,
2813
+ isOpen: dialogId === action.id,
2814
+ onClose: handleClose
2815
+ }
2816
+ ) : null
2817
+ ] }, action.id);
2452
2818
  }
2453
- },
2454
- variant: "danger",
2455
- position: ["header", "table-row"]
2456
- };
2457
- };
2458
- DeleteAction$1.type = "delete";
2459
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2460
- const Panels = () => {
2461
- const isCloning = useMatch(CLONE_PATH) !== null;
2462
- const [
2463
- {
2464
- query: { status }
2465
- }
2466
- ] = useQueryParams({
2467
- status: "draft"
2468
- });
2469
- const { model, id, document, meta, collectionType } = useDoc();
2470
- const plugins = useStrapiApp("Panels", (state) => state.plugins);
2471
- const props = {
2472
- activeTab: status,
2473
- model,
2474
- documentId: id,
2475
- document: isCloning ? void 0 : document,
2476
- meta: isCloning ? void 0 : meta,
2477
- collectionType
2478
- };
2479
- return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
2480
- DescriptionComponentRenderer,
2481
- {
2482
- props,
2483
- descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2484
- children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
2485
- }
2486
- ) });
2487
- };
2488
- const ActionsPanel = () => {
2489
- const { formatMessage } = useIntl();
2490
- return {
2491
- title: formatMessage({
2492
- id: "content-manager.containers.edit.panels.default.title",
2493
- defaultMessage: "Document"
2494
- }),
2495
- content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
2496
- };
2497
- };
2498
- ActionsPanel.type = "actions";
2499
- const ActionsPanelContent = () => {
2500
- const isCloning = useMatch(CLONE_PATH) !== null;
2501
- const [
2502
- {
2503
- query: { status = "draft" }
2504
2819
  }
2505
- ] = useQueryParams();
2506
- const { model, id, document, meta, collectionType } = useDoc();
2507
- const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
2508
- const props = {
2509
- activeTab: status,
2510
- model,
2511
- documentId: id,
2512
- document: isCloning ? void 0 : document,
2513
- meta: isCloning ? void 0 : meta,
2514
- collectionType
2515
- };
2516
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
2517
- /* @__PURE__ */ jsx(
2518
- DescriptionComponentRenderer,
2519
- {
2520
- props,
2521
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2522
- children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
2523
- }
2524
- ),
2525
- /* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
2526
- ] });
2820
+ }) });
2527
2821
  };
2528
- const Panel = React.forwardRef(({ children, title }, ref) => {
2529
- return /* @__PURE__ */ jsxs(
2530
- Flex,
2531
- {
2532
- ref,
2533
- tag: "aside",
2534
- "aria-labelledby": "additional-information",
2535
- background: "neutral0",
2536
- borderColor: "neutral150",
2537
- hasRadius: true,
2538
- paddingBottom: 4,
2539
- paddingLeft: 4,
2540
- paddingRight: 4,
2541
- paddingTop: 4,
2542
- shadow: "tableShadow",
2543
- gap: 3,
2544
- direction: "column",
2545
- justifyContent: "stretch",
2546
- alignItems: "flex-start",
2547
- children: [
2548
- /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2549
- children
2550
- ]
2822
+ const HeaderActionDialog = ({
2823
+ onClose,
2824
+ onCancel,
2825
+ title,
2826
+ content: Content,
2827
+ isOpen
2828
+ }) => {
2829
+ const handleClose = async () => {
2830
+ if (onCancel) {
2831
+ await onCancel();
2551
2832
  }
2552
- );
2553
- });
2554
- const HOOKS = {
2555
- /**
2556
- * Hook that allows to mutate the displayed headers of the list view table
2557
- * @constant
2558
- * @type {string}
2559
- */
2560
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2561
- /**
2562
- * Hook that allows to mutate the CM's collection types links pre-set filters
2563
- * @constant
2564
- * @type {string}
2565
- */
2566
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2567
- /**
2568
- * Hook that allows to mutate the CM's edit view layout
2569
- * @constant
2570
- * @type {string}
2571
- */
2572
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2573
- /**
2574
- * Hook that allows to mutate the CM's single types links pre-set filters
2575
- * @constant
2576
- * @type {string}
2577
- */
2578
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2833
+ onClose();
2834
+ };
2835
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2836
+ /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
2837
+ typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
2838
+ ] }) });
2579
2839
  };
2580
- const contentTypesApi = contentManagerApi.injectEndpoints({
2581
- endpoints: (builder) => ({
2582
- getContentTypeConfiguration: builder.query({
2583
- query: (uid) => ({
2584
- url: `/content-manager/content-types/${uid}/configuration`,
2585
- method: "GET"
2586
- }),
2587
- transformResponse: (response) => response.data,
2588
- providesTags: (_result, _error, uid) => [
2589
- { type: "ContentTypesConfiguration", id: uid },
2590
- { type: "ContentTypeSettings", id: "LIST" }
2591
- ]
2592
- }),
2593
- getAllContentTypeSettings: builder.query({
2594
- query: () => "/content-manager/content-types-settings",
2595
- transformResponse: (response) => response.data,
2596
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2840
+ const ConfigureTheViewAction = ({ collectionType, model }) => {
2841
+ const navigate = useNavigate();
2842
+ const { formatMessage } = useIntl();
2843
+ return {
2844
+ label: formatMessage({
2845
+ id: "app.links.configure-view",
2846
+ defaultMessage: "Configure the view"
2597
2847
  }),
2598
- updateContentTypeConfiguration: builder.mutation({
2599
- query: ({ uid, ...body }) => ({
2600
- url: `/content-manager/content-types/${uid}/configuration`,
2601
- method: "PUT",
2602
- data: body
2603
- }),
2604
- transformResponse: (response) => response.data,
2605
- invalidatesTags: (_result, _error, { uid }) => [
2606
- { type: "ContentTypesConfiguration", id: uid },
2607
- { type: "ContentTypeSettings", id: "LIST" },
2608
- // Is this necessary?
2609
- { type: "InitialData" }
2610
- ]
2611
- })
2612
- })
2613
- });
2614
- const {
2615
- useGetContentTypeConfigurationQuery,
2616
- useGetAllContentTypeSettingsQuery,
2617
- useUpdateContentTypeConfigurationMutation
2618
- } = contentTypesApi;
2619
- const checkIfAttributeIsDisplayable = (attribute) => {
2620
- const { type } = attribute;
2621
- if (type === "relation") {
2622
- return !attribute.relation.toLowerCase().includes("morph");
2623
- }
2624
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2848
+ icon: /* @__PURE__ */ jsx(ListPlus, {}),
2849
+ onClick: () => {
2850
+ navigate(`../${collectionType}/${model}/configurations/edit`);
2851
+ },
2852
+ position: "header"
2853
+ };
2625
2854
  };
2626
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2627
- if (!mainFieldName) {
2628
- return void 0;
2629
- }
2630
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2631
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2632
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2633
- );
2855
+ ConfigureTheViewAction.type = "configure-the-view";
2856
+ const EditTheModelAction = ({ model }) => {
2857
+ const navigate = useNavigate();
2858
+ const { formatMessage } = useIntl();
2634
2859
  return {
2635
- name: mainFieldName,
2636
- type: mainFieldType ?? "string"
2860
+ label: formatMessage({
2861
+ id: "content-manager.link-to-ctb",
2862
+ defaultMessage: "Edit the model"
2863
+ }),
2864
+ icon: /* @__PURE__ */ jsx(Pencil, {}),
2865
+ onClick: () => {
2866
+ navigate(`/plugins/content-type-builder/content-types/${model}`);
2867
+ },
2868
+ position: "header"
2637
2869
  };
2638
2870
  };
2639
- const DEFAULT_SETTINGS = {
2640
- bulkable: false,
2641
- filterable: false,
2642
- searchable: false,
2643
- pagination: false,
2644
- defaultSortBy: "",
2645
- defaultSortOrder: "asc",
2646
- mainField: "id",
2647
- pageSize: 10
2648
- };
2649
- const useDocumentLayout = (model) => {
2650
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2651
- const [{ query }] = useQueryParams();
2652
- const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2871
+ EditTheModelAction.type = "edit-the-model";
2872
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2873
+ const navigate = useNavigate();
2874
+ const { formatMessage } = useIntl();
2875
+ const listViewPathMatch = useMatch(LIST_PATH);
2876
+ const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
2877
+ const { delete: deleteAction } = useDocumentActions();
2653
2878
  const { toggleNotification } = useNotification();
2654
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
2655
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2656
- const {
2657
- data,
2658
- isLoading: isLoadingConfigs,
2659
- error,
2660
- isFetching: isFetchingConfigs
2661
- } = useGetContentTypeConfigurationQuery(model);
2662
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2663
- React.useEffect(() => {
2664
- if (error) {
2665
- toggleNotification({
2666
- type: "danger",
2667
- message: formatAPIError(error)
2668
- });
2669
- }
2670
- }, [error, formatAPIError, toggleNotification]);
2671
- const editLayout = React.useMemo(
2672
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2673
- layout: [],
2674
- components: {},
2675
- metadatas: {},
2676
- options: {},
2677
- settings: DEFAULT_SETTINGS
2678
- },
2679
- [data, isLoading, schemas, schema, components]
2680
- );
2681
- const listLayout = React.useMemo(() => {
2682
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2683
- layout: [],
2684
- metadatas: {},
2685
- options: {},
2686
- settings: DEFAULT_SETTINGS
2687
- };
2688
- }, [data, isLoading, schemas, schema, components]);
2689
- const { layout: edit } = React.useMemo(
2690
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2691
- layout: editLayout,
2692
- query
2693
- }),
2694
- [editLayout, query, runHookWaterfall]
2695
- );
2879
+ const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
2880
+ const isLocalized = document?.locale != null;
2696
2881
  return {
2697
- error,
2698
- isLoading,
2699
- edit,
2700
- list: listLayout
2701
- };
2702
- };
2703
- const useDocLayout = () => {
2704
- const { model } = useDoc();
2705
- return useDocumentLayout(model);
2706
- };
2707
- const formatEditLayout = (data, {
2708
- schemas,
2709
- schema,
2710
- components
2711
- }) => {
2712
- let currentPanelIndex = 0;
2713
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2714
- data.contentType.layouts.edit,
2715
- schema?.attributes,
2716
- data.contentType.metadatas,
2717
- { configurations: data.components, schemas: components },
2718
- schemas
2719
- ).reduce((panels, row) => {
2720
- if (row.some((field) => field.type === "dynamiczone")) {
2721
- panels.push([row]);
2722
- currentPanelIndex += 2;
2723
- } else {
2724
- if (!panels[currentPanelIndex]) {
2725
- panels.push([]);
2726
- }
2727
- panels[currentPanelIndex].push(row);
2728
- }
2729
- return panels;
2730
- }, []);
2731
- const componentEditAttributes = Object.entries(data.components).reduce(
2732
- (acc, [uid, configuration]) => {
2733
- acc[uid] = {
2734
- layout: convertEditLayoutToFieldLayouts(
2735
- configuration.layouts.edit,
2736
- components[uid].attributes,
2737
- configuration.metadatas
2738
- ),
2739
- settings: {
2740
- ...configuration.settings,
2741
- icon: components[uid].info.icon,
2742
- displayName: components[uid].info.displayName
2882
+ disabled: !canDelete || !document,
2883
+ label: formatMessage(
2884
+ {
2885
+ id: "content-manager.actions.delete.label",
2886
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2887
+ },
2888
+ { isLocalized }
2889
+ ),
2890
+ icon: /* @__PURE__ */ jsx(Trash, {}),
2891
+ dialog: {
2892
+ type: "dialog",
2893
+ title: formatMessage({
2894
+ id: "app.components.ConfirmDialog.title",
2895
+ defaultMessage: "Confirmation"
2896
+ }),
2897
+ content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2898
+ /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2899
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2900
+ id: "content-manager.actions.delete.dialog.body",
2901
+ defaultMessage: "Are you sure?"
2902
+ }) })
2903
+ ] }),
2904
+ onConfirm: async () => {
2905
+ if (!listViewPathMatch) {
2906
+ setSubmitting(true);
2907
+ }
2908
+ try {
2909
+ if (!documentId && collectionType !== SINGLE_TYPES) {
2910
+ console.error(
2911
+ "You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
2912
+ );
2913
+ toggleNotification({
2914
+ message: formatMessage({
2915
+ id: "content-manager.actions.delete.error",
2916
+ defaultMessage: "An error occurred while trying to delete the document."
2917
+ }),
2918
+ type: "danger"
2919
+ });
2920
+ return;
2921
+ }
2922
+ const res = await deleteAction({
2923
+ documentId,
2924
+ model,
2925
+ collectionType,
2926
+ params: {
2927
+ locale: "*"
2928
+ }
2929
+ });
2930
+ if (!("error" in res)) {
2931
+ navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
2932
+ }
2933
+ } finally {
2934
+ if (!listViewPathMatch) {
2935
+ setSubmitting(false);
2936
+ }
2743
2937
  }
2744
- };
2745
- return acc;
2746
- },
2747
- {}
2748
- );
2749
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2750
- (acc, [attribute, metadata]) => {
2751
- return {
2752
- ...acc,
2753
- [attribute]: metadata.edit
2754
- };
2755
- },
2756
- {}
2757
- );
2758
- return {
2759
- layout: panelledEditAttributes,
2760
- components: componentEditAttributes,
2761
- metadatas: editMetadatas,
2762
- settings: {
2763
- ...data.contentType.settings,
2764
- displayName: schema?.info.displayName
2938
+ }
2765
2939
  },
2766
- options: {
2767
- ...schema?.options,
2768
- ...schema?.pluginOptions,
2769
- ...data.contentType.options
2770
- }
2940
+ variant: "danger",
2941
+ position: ["header", "table-row"]
2771
2942
  };
2772
2943
  };
2773
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2774
- return rows.map(
2775
- (row) => row.map((field) => {
2776
- const attribute = attributes[field.name];
2777
- if (!attribute) {
2778
- return null;
2779
- }
2780
- const { edit: metadata } = metadatas[field.name];
2781
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2782
- return {
2783
- attribute,
2784
- disabled: !metadata.editable,
2785
- hint: metadata.description,
2786
- label: metadata.label ?? "",
2787
- name: field.name,
2788
- // @ts-expect-error – mainField does exist on the metadata for a relation.
2789
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2790
- schemas,
2791
- components: components?.schemas ?? {}
2792
- }),
2793
- placeholder: metadata.placeholder ?? "",
2794
- required: attribute.required ?? false,
2795
- size: field.size,
2796
- unique: "unique" in attribute ? attribute.unique : false,
2797
- visible: metadata.visible ?? true,
2798
- type: attribute.type
2799
- };
2800
- }).filter((field) => field !== null)
2801
- );
2944
+ DeleteAction$1.type = "delete";
2945
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2946
+ const Panels = () => {
2947
+ const isCloning = useMatch(CLONE_PATH) !== null;
2948
+ const [
2949
+ {
2950
+ query: { status }
2951
+ }
2952
+ ] = useQueryParams({
2953
+ status: "draft"
2954
+ });
2955
+ const { model, id, document, meta, collectionType } = useDoc();
2956
+ const plugins = useStrapiApp("Panels", (state) => state.plugins);
2957
+ const props = {
2958
+ activeTab: status,
2959
+ model,
2960
+ documentId: id,
2961
+ document: isCloning ? void 0 : document,
2962
+ meta: isCloning ? void 0 : meta,
2963
+ collectionType
2964
+ };
2965
+ return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
2966
+ DescriptionComponentRenderer,
2967
+ {
2968
+ props,
2969
+ descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2970
+ children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
2971
+ }
2972
+ ) });
2802
2973
  };
2803
- const formatListLayout = (data, {
2804
- schemas,
2805
- schema,
2806
- components
2807
- }) => {
2808
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2809
- (acc, [attribute, metadata]) => {
2810
- return {
2811
- ...acc,
2812
- [attribute]: metadata.list
2813
- };
2814
- },
2815
- {}
2816
- );
2817
- const listAttributes = convertListLayoutToFieldLayouts(
2818
- data.contentType.layouts.list,
2819
- schema?.attributes,
2820
- listMetadatas,
2821
- { configurations: data.components, schemas: components },
2822
- schemas
2823
- );
2974
+ const ActionsPanel = () => {
2975
+ const { formatMessage } = useIntl();
2824
2976
  return {
2825
- layout: listAttributes,
2826
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2827
- metadatas: listMetadatas,
2828
- options: {
2829
- ...schema?.options,
2830
- ...schema?.pluginOptions,
2831
- ...data.contentType.options
2832
- }
2977
+ title: formatMessage({
2978
+ id: "content-manager.containers.edit.panels.default.title",
2979
+ defaultMessage: "Entry"
2980
+ }),
2981
+ content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
2833
2982
  };
2834
2983
  };
2835
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2836
- return columns.map((name) => {
2837
- const attribute = attributes[name];
2838
- if (!attribute) {
2839
- return null;
2984
+ ActionsPanel.type = "actions";
2985
+ const ActionsPanelContent = () => {
2986
+ const isCloning = useMatch(CLONE_PATH) !== null;
2987
+ const [
2988
+ {
2989
+ query: { status = "draft" }
2840
2990
  }
2841
- const metadata = metadatas[name];
2842
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2843
- return {
2844
- attribute,
2845
- label: metadata.label ?? "",
2846
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2847
- schemas,
2848
- components: components?.schemas ?? {}
2849
- }),
2850
- name,
2851
- searchable: metadata.searchable ?? true,
2852
- sortable: metadata.sortable ?? true
2853
- };
2854
- }).filter((field) => field !== null);
2991
+ ] = useQueryParams();
2992
+ const { model, id, document, meta, collectionType } = useDoc();
2993
+ const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
2994
+ const props = {
2995
+ activeTab: status,
2996
+ model,
2997
+ documentId: id,
2998
+ document: isCloning ? void 0 : document,
2999
+ meta: isCloning ? void 0 : meta,
3000
+ collectionType
3001
+ };
3002
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
3003
+ /* @__PURE__ */ jsx(
3004
+ DescriptionComponentRenderer,
3005
+ {
3006
+ props,
3007
+ descriptions: plugins["content-manager"].apis.getDocumentActions(),
3008
+ children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
3009
+ }
3010
+ ),
3011
+ /* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
3012
+ ] });
2855
3013
  };
3014
+ const Panel = React.forwardRef(({ children, title }, ref) => {
3015
+ return /* @__PURE__ */ jsxs(
3016
+ Flex,
3017
+ {
3018
+ ref,
3019
+ tag: "aside",
3020
+ "aria-labelledby": "additional-information",
3021
+ background: "neutral0",
3022
+ borderColor: "neutral150",
3023
+ hasRadius: true,
3024
+ paddingBottom: 4,
3025
+ paddingLeft: 4,
3026
+ paddingRight: 4,
3027
+ paddingTop: 4,
3028
+ shadow: "tableShadow",
3029
+ gap: 3,
3030
+ direction: "column",
3031
+ justifyContent: "stretch",
3032
+ alignItems: "flex-start",
3033
+ children: [
3034
+ /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
3035
+ children
3036
+ ]
3037
+ }
3038
+ );
3039
+ });
2856
3040
  const ConfirmBulkActionDialog = ({
2857
3041
  onToggleDialog,
2858
3042
  isOpen = false,
@@ -2891,6 +3075,7 @@ const ConfirmDialogPublishAll = ({
2891
3075
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
2892
3076
  const { model, schema } = useDoc();
2893
3077
  const [{ query }] = useQueryParams();
3078
+ const enableDraftRelationsCount = false;
2894
3079
  const {
2895
3080
  data: countDraftRelations = 0,
2896
3081
  isLoading,
@@ -2902,7 +3087,7 @@ const ConfirmDialogPublishAll = ({
2902
3087
  locale: query?.plugins?.i18n?.locale
2903
3088
  },
2904
3089
  {
2905
- skip: selectedEntries.length === 0
3090
+ skip: !enableDraftRelationsCount
2906
3091
  }
2907
3092
  );
2908
3093
  React.useEffect(() => {
@@ -3087,7 +3272,7 @@ const SelectedEntriesTableContent = ({
3087
3272
  status: row.status
3088
3273
  }
3089
3274
  ) }),
3090
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
3275
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
3091
3276
  IconButton,
3092
3277
  {
3093
3278
  tag: Link,
@@ -3096,23 +3281,16 @@ const SelectedEntriesTableContent = ({
3096
3281
  search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3097
3282
  },
3098
3283
  state: { from: pathname },
3099
- label: formatMessage(
3100
- { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3101
- {
3102
- target: formatMessage(
3103
- {
3104
- id: "content-manager.components.ListViewHelperPluginTable.row-line",
3105
- defaultMessage: "item line {number}"
3106
- },
3107
- { number: index2 + 1 }
3108
- )
3109
- }
3110
- ),
3284
+ label: formatMessage({
3285
+ id: "content-manager.bulk-publish.edit",
3286
+ defaultMessage: "Edit"
3287
+ }),
3111
3288
  target: "_blank",
3112
3289
  marginLeft: "auto",
3113
- children: /* @__PURE__ */ jsx(Pencil, {})
3290
+ variant: "ghost",
3291
+ children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
3114
3292
  }
3115
- ) })
3293
+ ) }) })
3116
3294
  ] }, row.id)) })
3117
3295
  ] });
3118
3296
  };
@@ -3149,7 +3327,13 @@ const SelectedEntriesModalContent = ({
3149
3327
  );
3150
3328
  const { rows, validationErrors } = React.useMemo(() => {
3151
3329
  if (data.length > 0 && schema) {
3152
- const validate = createYupSchema(schema.attributes, components);
3330
+ const validate = createYupSchema(
3331
+ schema.attributes,
3332
+ components,
3333
+ // Since this is the "Publish" action, the validation
3334
+ // schema must enforce the rules for published entities
3335
+ { status: "published" }
3336
+ );
3153
3337
  const validationErrors2 = {};
3154
3338
  const rows2 = data.map((entry) => {
3155
3339
  try {
@@ -3499,7 +3683,7 @@ const TableActions = ({ document }) => {
3499
3683
  DescriptionComponentRenderer,
3500
3684
  {
3501
3685
  props,
3502
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3686
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
3503
3687
  children: (actions2) => {
3504
3688
  const tableRowActions = actions2.filter((action) => {
3505
3689
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3610,7 +3794,7 @@ const CloneAction = ({ model, documentId }) => {
3610
3794
  }),
3611
3795
  content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3612
3796
  footer: ({ onClose }) => {
3613
- return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
3797
+ return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
3614
3798
  /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3615
3799
  id: "cancel",
3616
3800
  defaultMessage: "Cancel"
@@ -3744,17 +3928,27 @@ const HistoryAction = ({ model, document }) => {
3744
3928
  const { formatMessage } = useIntl();
3745
3929
  const [{ query }] = useQueryParams();
3746
3930
  const navigate = useNavigate();
3931
+ const { trackUsage } = useTracking();
3932
+ const { pathname } = useLocation();
3747
3933
  const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
3748
3934
  if (!window.strapi.features.isEnabled("cms-content-history")) {
3749
3935
  return null;
3750
3936
  }
3937
+ const handleOnClick = () => {
3938
+ const destination = { pathname: "history", search: pluginsQueryParams };
3939
+ trackUsage("willNavigate", {
3940
+ from: pathname,
3941
+ to: `${pathname}/${destination.pathname}`
3942
+ });
3943
+ navigate(destination);
3944
+ };
3751
3945
  return {
3752
3946
  icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
3753
3947
  label: formatMessage({
3754
3948
  id: "content-manager.history.document-action",
3755
3949
  defaultMessage: "Content History"
3756
3950
  }),
3757
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3951
+ onClick: handleOnClick,
3758
3952
  disabled: (
3759
3953
  /**
3760
3954
  * The user is creating a new document.
@@ -3822,6 +4016,72 @@ const { setInitialData } = actions;
3822
4016
  const reducer = combineReducers({
3823
4017
  app: reducer$1
3824
4018
  });
4019
+ const previewApi = contentManagerApi.injectEndpoints({
4020
+ endpoints: (builder) => ({
4021
+ getPreviewUrl: builder.query({
4022
+ query({ query, params }) {
4023
+ return {
4024
+ url: `/content-manager/preview/url/${params.contentType}`,
4025
+ method: "GET",
4026
+ config: {
4027
+ params: query
4028
+ }
4029
+ };
4030
+ }
4031
+ })
4032
+ })
4033
+ });
4034
+ const { useGetPreviewUrlQuery } = previewApi;
4035
+ const PreviewSidePanel = ({ model, documentId, document }) => {
4036
+ const { formatMessage } = useIntl();
4037
+ const { trackUsage } = useTracking();
4038
+ const { pathname } = useLocation();
4039
+ const [{ query }] = useQueryParams();
4040
+ const { data, error } = useGetPreviewUrlQuery({
4041
+ params: {
4042
+ contentType: model
4043
+ },
4044
+ query: {
4045
+ documentId,
4046
+ locale: document?.locale,
4047
+ status: document?.status
4048
+ }
4049
+ });
4050
+ if (!data?.data?.url || error) {
4051
+ return null;
4052
+ }
4053
+ const trackNavigation = () => {
4054
+ const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
4055
+ trackUsage("willNavigate", { from: pathname, to: destinationPathname });
4056
+ };
4057
+ return {
4058
+ title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
4059
+ content: /* @__PURE__ */ jsx(Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsx(
4060
+ Button,
4061
+ {
4062
+ variant: "tertiary",
4063
+ tag: Link,
4064
+ to: { pathname: "preview", search: stringify(query, { encode: false }) },
4065
+ onClick: trackNavigation,
4066
+ flex: "auto",
4067
+ children: formatMessage({
4068
+ id: "content-manager.preview.panel.button",
4069
+ defaultMessage: "Open preview"
4070
+ })
4071
+ }
4072
+ ) })
4073
+ };
4074
+ };
4075
+ const FEATURE_ID = "preview";
4076
+ const previewAdmin = {
4077
+ bootstrap(app) {
4078
+ if (!window.strapi.future.isEnabled(FEATURE_ID)) {
4079
+ return;
4080
+ }
4081
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
4082
+ contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
4083
+ }
4084
+ };
3825
4085
  const index = {
3826
4086
  register(app) {
3827
4087
  const cm = new ContentManagerPlugin();
@@ -3841,7 +4101,7 @@ const index = {
3841
4101
  app.router.addRoute({
3842
4102
  path: "content-manager/*",
3843
4103
  lazy: async () => {
3844
- const { Layout } = await import("./layout-B3ez7kvr.mjs");
4104
+ const { Layout } = await import("./layout-DFVbgjp2.mjs");
3845
4105
  return {
3846
4106
  Component: Layout
3847
4107
  };
@@ -3854,11 +4114,14 @@ const index = {
3854
4114
  if (typeof historyAdmin.bootstrap === "function") {
3855
4115
  historyAdmin.bootstrap(app);
3856
4116
  }
4117
+ if (typeof previewAdmin.bootstrap === "function") {
4118
+ previewAdmin.bootstrap(app);
4119
+ }
3857
4120
  },
3858
4121
  async registerTrads({ locales }) {
3859
4122
  const importedTrads = await Promise.all(
3860
4123
  locales.map((locale) => {
3861
- 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 }) => {
4124
+ 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-CfIXaZf9.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 }) => {
3862
4125
  return {
3863
4126
  data: prefixPluginTranslations(data, PLUGIN_ID),
3864
4127
  locale
@@ -3879,13 +4142,16 @@ export {
3879
4142
  BulkActionsRenderer as B,
3880
4143
  COLLECTION_TYPES as C,
3881
4144
  DocumentStatus as D,
3882
- DEFAULT_SETTINGS as E,
3883
- convertEditLayoutToFieldLayouts as F,
3884
- useDocument as G,
4145
+ extractContentTypeComponents as E,
4146
+ DEFAULT_SETTINGS as F,
4147
+ convertEditLayoutToFieldLayouts as G,
3885
4148
  HOOKS as H,
3886
4149
  InjectionZone as I,
3887
- index as J,
3888
- useDocumentActions as K,
4150
+ useDocument as J,
4151
+ useGetPreviewUrlQuery as K,
4152
+ index as L,
4153
+ useContentManagerContext as M,
4154
+ useDocumentActions as N,
3889
4155
  Panels as P,
3890
4156
  RelativeTime as R,
3891
4157
  SINGLE_TYPES as S,
@@ -3903,18 +4169,18 @@ export {
3903
4169
  PERMISSIONS as k,
3904
4170
  DocumentRBAC as l,
3905
4171
  DOCUMENT_META_FIELDS as m,
3906
- useDocLayout as n,
3907
- useGetContentTypeConfigurationQuery as o,
3908
- CREATOR_FIELDS as p,
3909
- getMainField as q,
3910
- getDisplayName as r,
4172
+ CLONE_PATH as n,
4173
+ useDocLayout as o,
4174
+ useGetContentTypeConfigurationQuery as p,
4175
+ CREATOR_FIELDS as q,
4176
+ getMainField as r,
3911
4177
  setInitialData as s,
3912
- checkIfAttributeIsDisplayable as t,
4178
+ getDisplayName as t,
3913
4179
  useContentTypeSchema as u,
3914
- useGetAllDocumentsQuery as v,
3915
- convertListLayoutToFieldLayouts as w,
3916
- capitalise as x,
3917
- useUpdateContentTypeConfigurationMutation as y,
3918
- extractContentTypeComponents as z
4180
+ checkIfAttributeIsDisplayable as v,
4181
+ useGetAllDocumentsQuery as w,
4182
+ convertListLayoutToFieldLayouts as x,
4183
+ capitalise as y,
4184
+ useUpdateContentTypeConfigurationMutation as z
3919
4185
  };
3920
- //# sourceMappingURL=index-DrNe6ctw.mjs.map
4186
+ //# sourceMappingURL=index-BW-rXkjn.mjs.map