@strapi/content-manager 0.0.0-experimental.545ccead2ee1717bbc7ab950455dbb0ddb9924a3 → 0.0.0-experimental.550e739e36d7678bd8317b48acab2f24b1f4dcd6

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 (216) hide show
  1. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
  2. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-Bqgx7Mes.js → ComponentConfigurationPage-CJPoOvy3.js} +5 -6
  4. package/dist/_chunks/{ComponentConfigurationPage-Bqgx7Mes.js.map → ComponentConfigurationPage-CJPoOvy3.js.map} +1 -1
  5. package/dist/_chunks/{ComponentConfigurationPage-B1bIXVuX.mjs → ComponentConfigurationPage-CcRDqD0e.mjs} +4 -4
  6. package/dist/_chunks/{ComponentConfigurationPage-B1bIXVuX.mjs.map → ComponentConfigurationPage-CcRDqD0e.mjs.map} +1 -1
  7. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
  8. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
  9. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
  10. package/dist/_chunks/{EditConfigurationPage-ZO0vOO8q.mjs → EditConfigurationPage-C1ddZ_zf.mjs} +4 -4
  11. package/dist/_chunks/{EditConfigurationPage-ZO0vOO8q.mjs.map → EditConfigurationPage-C1ddZ_zf.mjs.map} +1 -1
  12. package/dist/_chunks/{EditConfigurationPage-BFEwvdMW.js → EditConfigurationPage-CF3lxOy2.js} +5 -6
  13. package/dist/_chunks/{EditConfigurationPage-BFEwvdMW.js.map → EditConfigurationPage-CF3lxOy2.js.map} +1 -1
  14. package/dist/_chunks/{EditViewPage-DlLEyUL6.mjs → EditViewPage-BPFcUbqi.mjs} +63 -12
  15. package/dist/_chunks/EditViewPage-BPFcUbqi.mjs.map +1 -0
  16. package/dist/_chunks/{EditViewPage-DA95Ha6J.js → EditViewPage-CDyTC6aU.js} +63 -13
  17. package/dist/_chunks/EditViewPage-CDyTC6aU.js.map +1 -0
  18. package/dist/_chunks/{Field-CnK8dO8N.js → Field-DuxAW9q2.js} +344 -220
  19. package/dist/_chunks/Field-DuxAW9q2.js.map +1 -0
  20. package/dist/_chunks/{Field-Dq7bDnuh.mjs → Field-fBnTwgU4.mjs} +340 -216
  21. package/dist/_chunks/Field-fBnTwgU4.mjs.map +1 -0
  22. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
  23. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
  24. package/dist/_chunks/{Form-B_JE0dbz.mjs → Form-BGl7PhlZ.mjs} +37 -18
  25. package/dist/_chunks/Form-BGl7PhlZ.mjs.map +1 -0
  26. package/dist/_chunks/{Form-BpiR4piS.js → Form-DSGh_zkz.js} +39 -21
  27. package/dist/_chunks/Form-DSGh_zkz.js.map +1 -0
  28. package/dist/_chunks/{History-CBNGU7a-.mjs → History-DTYB9CSB.mjs} +59 -106
  29. package/dist/_chunks/History-DTYB9CSB.mjs.map +1 -0
  30. package/dist/_chunks/{History-DdIstl8b.js → History-DrDJv698.js} +58 -106
  31. package/dist/_chunks/History-DrDJv698.js.map +1 -0
  32. package/dist/_chunks/{ListConfigurationPage-5dr4qpue.mjs → ListConfigurationPage-qWx8r4D_.mjs} +19 -8
  33. package/dist/_chunks/ListConfigurationPage-qWx8r4D_.mjs.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-DkKRparB.js → ListConfigurationPage-zurIlUZ7.js} +19 -9
  35. package/dist/_chunks/ListConfigurationPage-zurIlUZ7.js.map +1 -0
  36. package/dist/_chunks/{ListViewPage-wE0lXqoD.js → ListViewPage-DTM2uO_S.js} +109 -78
  37. package/dist/_chunks/ListViewPage-DTM2uO_S.js.map +1 -0
  38. package/dist/_chunks/{ListViewPage-DecLrYV6.mjs → ListViewPage-GKpL5p8A.mjs} +106 -74
  39. package/dist/_chunks/ListViewPage-GKpL5p8A.mjs.map +1 -0
  40. package/dist/_chunks/{NoContentTypePage-CiIcfYsd.mjs → NoContentTypePage-B5Vc5Cal.mjs} +2 -2
  41. package/dist/_chunks/{NoContentTypePage-CiIcfYsd.mjs.map → NoContentTypePage-B5Vc5Cal.mjs.map} +1 -1
  42. package/dist/_chunks/{NoContentTypePage-DEKR6tf9.js → NoContentTypePage-BuZlNroO.js} +2 -2
  43. package/dist/_chunks/{NoContentTypePage-DEKR6tf9.js.map → NoContentTypePage-BuZlNroO.js.map} +1 -1
  44. package/dist/_chunks/{NoPermissionsPage-CM5UD8ee.mjs → NoPermissionsPage-BAZlWgJ4.mjs} +2 -2
  45. package/dist/_chunks/{NoPermissionsPage-CM5UD8ee.mjs.map → NoPermissionsPage-BAZlWgJ4.mjs.map} +1 -1
  46. package/dist/_chunks/{NoPermissionsPage-DmNfF2Bb.js → NoPermissionsPage-DLzkS4Hy.js} +2 -2
  47. package/dist/_chunks/{NoPermissionsPage-DmNfF2Bb.js.map → NoPermissionsPage-DLzkS4Hy.js.map} +1 -1
  48. package/dist/_chunks/Preview-VOJ8RuQp.js +312 -0
  49. package/dist/_chunks/Preview-VOJ8RuQp.js.map +1 -0
  50. package/dist/_chunks/Preview-Zzjg2_K_.mjs +294 -0
  51. package/dist/_chunks/Preview-Zzjg2_K_.mjs.map +1 -0
  52. package/dist/_chunks/{Relations-Dqz0C1fz.mjs → Relations-BVdRfDkW.mjs} +76 -42
  53. package/dist/_chunks/Relations-BVdRfDkW.mjs.map +1 -0
  54. package/dist/_chunks/{Relations-L0xYRoSQ.js → Relations-Dsj0boFJ.js} +76 -43
  55. package/dist/_chunks/Relations-Dsj0boFJ.js.map +1 -0
  56. package/dist/_chunks/{en-uOUIxfcQ.js → en-BzQmavmK.js} +33 -15
  57. package/dist/_chunks/{en-uOUIxfcQ.js.map → en-BzQmavmK.js.map} +1 -1
  58. package/dist/_chunks/{en-BrCTWlZv.mjs → en-CSxLmrh1.mjs} +33 -15
  59. package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-CSxLmrh1.mjs.map} +1 -1
  60. package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
  61. package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
  62. package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
  63. package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
  64. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
  65. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
  66. package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
  67. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
  68. package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
  69. package/dist/_chunks/{index-BSn97i8U.mjs → index-Bu_-B7ZA.mjs} +1143 -767
  70. package/dist/_chunks/index-Bu_-B7ZA.mjs.map +1 -0
  71. package/dist/_chunks/{index-DyvUPg1a.js → index-Ct-GZ0iV.js} +1125 -749
  72. package/dist/_chunks/index-Ct-GZ0iV.js.map +1 -0
  73. package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
  74. package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
  75. package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
  76. package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
  77. package/dist/_chunks/{layout-TPqF2oJ5.js → layout-CDBEgRsM.js} +23 -11
  78. package/dist/_chunks/layout-CDBEgRsM.js.map +1 -0
  79. package/dist/_chunks/{layout-DPaHUusj.mjs → layout-COzAvgJh.mjs} +23 -10
  80. package/dist/_chunks/layout-COzAvgJh.mjs.map +1 -0
  81. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  82. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  83. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  84. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  85. package/dist/_chunks/{relations-BWYS9gkn.js → relations-BjiF1Aad.js} +6 -7
  86. package/dist/_chunks/relations-BjiF1Aad.js.map +1 -0
  87. package/dist/_chunks/{relations-Ck7-ecDT.mjs → relations-BtmMFBpM.mjs} +6 -7
  88. package/dist/_chunks/relations-BtmMFBpM.mjs.map +1 -0
  89. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  90. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  91. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  92. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  93. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
  94. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
  95. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
  96. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
  97. package/dist/admin/index.js +3 -1
  98. package/dist/admin/index.js.map +1 -1
  99. package/dist/admin/index.mjs +6 -4
  100. package/dist/admin/src/content-manager.d.ts +3 -2
  101. package/dist/admin/src/exports.d.ts +2 -1
  102. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  103. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  104. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  105. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -1
  106. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +3 -3
  107. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
  108. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
  109. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
  110. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  111. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  112. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  113. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  114. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  115. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  116. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  117. package/dist/admin/src/preview/index.d.ts +4 -0
  118. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  119. package/dist/admin/src/preview/routes.d.ts +3 -0
  120. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  121. package/dist/admin/src/router.d.ts +1 -1
  122. package/dist/admin/src/services/api.d.ts +1 -1
  123. package/dist/admin/src/services/components.d.ts +2 -2
  124. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  125. package/dist/admin/src/services/documents.d.ts +19 -20
  126. package/dist/admin/src/services/init.d.ts +1 -1
  127. package/dist/admin/src/services/relations.d.ts +2 -2
  128. package/dist/admin/src/services/uid.d.ts +3 -3
  129. package/dist/admin/src/utils/validation.d.ts +4 -1
  130. package/dist/server/index.js +682 -360
  131. package/dist/server/index.js.map +1 -1
  132. package/dist/server/index.mjs +683 -360
  133. package/dist/server/index.mjs.map +1 -1
  134. package/dist/server/src/bootstrap.d.ts.map +1 -1
  135. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  136. package/dist/server/src/controllers/index.d.ts.map +1 -1
  137. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  138. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  139. package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
  140. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  141. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  142. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  143. package/dist/server/src/history/services/history.d.ts.map +1 -1
  144. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  145. package/dist/server/src/history/services/utils.d.ts +4 -4
  146. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  147. package/dist/server/src/index.d.ts +7 -6
  148. package/dist/server/src/index.d.ts.map +1 -1
  149. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  150. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  151. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  152. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  153. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  154. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  155. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  156. package/dist/server/src/preview/index.d.ts +4 -0
  157. package/dist/server/src/preview/index.d.ts.map +1 -0
  158. package/dist/server/src/preview/routes/index.d.ts +8 -0
  159. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  160. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  161. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  162. package/dist/server/src/preview/services/index.d.ts +16 -0
  163. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  164. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  165. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  166. package/dist/server/src/preview/services/preview.d.ts +12 -0
  167. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  168. package/dist/server/src/preview/utils.d.ts +19 -0
  169. package/dist/server/src/preview/utils.d.ts.map +1 -0
  170. package/dist/server/src/register.d.ts.map +1 -1
  171. package/dist/server/src/routes/index.d.ts.map +1 -1
  172. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  173. package/dist/server/src/services/document-metadata.d.ts +12 -10
  174. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  175. package/dist/server/src/services/index.d.ts +7 -6
  176. package/dist/server/src/services/index.d.ts.map +1 -1
  177. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  178. package/dist/server/src/services/utils/populate.d.ts +2 -2
  179. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  180. package/dist/server/src/utils/index.d.ts +2 -0
  181. package/dist/server/src/utils/index.d.ts.map +1 -1
  182. package/dist/shared/contracts/collection-types.d.ts +3 -1
  183. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  184. package/dist/shared/contracts/index.d.ts +1 -0
  185. package/dist/shared/contracts/index.d.ts.map +1 -1
  186. package/dist/shared/contracts/preview.d.ts +27 -0
  187. package/dist/shared/contracts/preview.d.ts.map +1 -0
  188. package/dist/shared/index.js +4 -0
  189. package/dist/shared/index.js.map +1 -1
  190. package/dist/shared/index.mjs +4 -0
  191. package/dist/shared/index.mjs.map +1 -1
  192. package/package.json +17 -15
  193. package/dist/_chunks/EditViewPage-DA95Ha6J.js.map +0 -1
  194. package/dist/_chunks/EditViewPage-DlLEyUL6.mjs.map +0 -1
  195. package/dist/_chunks/Field-CnK8dO8N.js.map +0 -1
  196. package/dist/_chunks/Field-Dq7bDnuh.mjs.map +0 -1
  197. package/dist/_chunks/Form-B_JE0dbz.mjs.map +0 -1
  198. package/dist/_chunks/Form-BpiR4piS.js.map +0 -1
  199. package/dist/_chunks/History-CBNGU7a-.mjs.map +0 -1
  200. package/dist/_chunks/History-DdIstl8b.js.map +0 -1
  201. package/dist/_chunks/ListConfigurationPage-5dr4qpue.mjs.map +0 -1
  202. package/dist/_chunks/ListConfigurationPage-DkKRparB.js.map +0 -1
  203. package/dist/_chunks/ListViewPage-DecLrYV6.mjs.map +0 -1
  204. package/dist/_chunks/ListViewPage-wE0lXqoD.js.map +0 -1
  205. package/dist/_chunks/Relations-Dqz0C1fz.mjs.map +0 -1
  206. package/dist/_chunks/Relations-L0xYRoSQ.js.map +0 -1
  207. package/dist/_chunks/index-BSn97i8U.mjs.map +0 -1
  208. package/dist/_chunks/index-DyvUPg1a.js.map +0 -1
  209. package/dist/_chunks/layout-DPaHUusj.mjs.map +0 -1
  210. package/dist/_chunks/layout-TPqF2oJ5.js.map +0 -1
  211. package/dist/_chunks/relations-BWYS9gkn.js.map +0 -1
  212. package/dist/_chunks/relations-Ck7-ecDT.mjs.map +0 -1
  213. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  214. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  215. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  216. package/strapi-server.js +0 -3
@@ -4,18 +4,18 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const strapiAdmin = require("@strapi/admin/strapi-admin");
5
5
  const React = require("react");
6
6
  const designSystem = require("@strapi/design-system");
7
+ const mapValues = require("lodash/fp/mapValues");
7
8
  const reactIntl = require("react-intl");
8
9
  const reactRouterDom = require("react-router-dom");
9
10
  const styledComponents = require("styled-components");
10
11
  const yup = require("yup");
12
+ const qs = require("qs");
11
13
  const pipe = require("lodash/fp/pipe");
12
14
  const dateFns = require("date-fns");
13
- const qs = require("qs");
14
15
  const toolkit = require("@reduxjs/toolkit");
15
16
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
16
17
  function _interopNamespace(e) {
17
- if (e && e.__esModule)
18
- return e;
18
+ if (e && e.__esModule) return e;
19
19
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
20
20
  if (e) {
21
21
  for (const k in e) {
@@ -32,15 +32,23 @@ function _interopNamespace(e) {
32
32
  return Object.freeze(n);
33
33
  }
34
34
  const React__namespace = /* @__PURE__ */ _interopNamespace(React);
35
+ const mapValues__default = /* @__PURE__ */ _interopDefault(mapValues);
35
36
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
36
37
  const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
37
- const __variableDynamicImportRuntimeHelper = (glob, path) => {
38
+ const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
38
39
  const v = glob[path];
39
40
  if (v) {
40
41
  return typeof v === "function" ? v() : Promise.resolve(v);
41
42
  }
42
43
  return new Promise((_, reject) => {
43
- (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(reject.bind(null, new Error("Unknown variable dynamic import: " + path)));
44
+ (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
45
+ reject.bind(
46
+ null,
47
+ new Error(
48
+ "Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
49
+ )
50
+ )
51
+ );
44
52
  });
45
53
  };
46
54
  const PLUGIN_ID = "content-manager";
@@ -121,6 +129,7 @@ const DocumentRBAC = ({ children, permissions }) => {
121
129
  if (!slug) {
122
130
  throw new Error("Cannot find the slug param in the URL");
123
131
  }
132
+ const [{ rawQuery }] = strapiAdmin.useQueryParams();
124
133
  const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
125
134
  const contentTypePermissions = React__namespace.useMemo(() => {
126
135
  const contentTypePermissions2 = userPermissions.filter(
@@ -131,7 +140,14 @@ const DocumentRBAC = ({ children, permissions }) => {
131
140
  return { ...acc, [action]: [permission] };
132
141
  }, {});
133
142
  }, [slug, userPermissions]);
134
- const { isLoading, allowedActions } = strapiAdmin.useRBAC(contentTypePermissions, permissions ?? void 0);
143
+ const { isLoading, allowedActions } = strapiAdmin.useRBAC(
144
+ contentTypePermissions,
145
+ permissions ?? void 0,
146
+ // TODO: useRBAC context should be typed and built differently
147
+ // We are passing raw query as context to the hook so that it can
148
+ // rely on the locale provided from DocumentRBAC for its permission calculations.
149
+ rawQuery
150
+ );
135
151
  const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
136
152
  const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
137
153
  const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
@@ -179,7 +195,9 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
179
195
  "Document",
180
196
  "InitialData",
181
197
  "HistoryVersion",
182
- "Relations"
198
+ "Relations",
199
+ "UidAvailability",
200
+ "RecentDocumentList"
183
201
  ]
184
202
  });
185
203
  const documentApi = contentManagerApi.injectEndpoints({
@@ -193,7 +211,12 @@ const documentApi = contentManagerApi.injectEndpoints({
193
211
  params: query
194
212
  }
195
213
  }),
196
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
214
+ invalidatesTags: (_result, error, { model }) => {
215
+ if (error) {
216
+ return [];
217
+ }
218
+ return [{ type: "Document", id: `${model}_LIST` }, "RecentDocumentList"];
219
+ }
197
220
  }),
198
221
  cloneDocument: builder.mutation({
199
222
  query: ({ model, sourceId, data, params }) => ({
@@ -204,7 +227,11 @@ const documentApi = contentManagerApi.injectEndpoints({
204
227
  params
205
228
  }
206
229
  }),
207
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
230
+ invalidatesTags: (_result, _error, { model }) => [
231
+ { type: "Document", id: `${model}_LIST` },
232
+ { type: "UidAvailability", id: model },
233
+ "RecentDocumentList"
234
+ ]
208
235
  }),
209
236
  /**
210
237
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -221,8 +248,22 @@ const documentApi = contentManagerApi.injectEndpoints({
221
248
  }),
222
249
  invalidatesTags: (result, _error, { model }) => [
223
250
  { type: "Document", id: `${model}_LIST` },
224
- "Relations"
225
- ]
251
+ "Relations",
252
+ { type: "UidAvailability", id: model },
253
+ "RecentDocumentList"
254
+ ],
255
+ transformResponse: (response, meta, arg) => {
256
+ if (!("data" in response) && arg.model === "plugin::users-permissions.user") {
257
+ return {
258
+ data: response,
259
+ meta: {
260
+ availableStatus: [],
261
+ availableLocales: []
262
+ }
263
+ };
264
+ }
265
+ return response;
266
+ }
226
267
  }),
227
268
  deleteDocument: builder.mutation({
228
269
  query: ({ collectionType, model, documentId, params }) => ({
@@ -233,7 +274,8 @@ const documentApi = contentManagerApi.injectEndpoints({
233
274
  }
234
275
  }),
235
276
  invalidatesTags: (_result, _error, { collectionType, model }) => [
236
- { type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model }
277
+ { type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model },
278
+ "RecentDocumentList"
237
279
  ]
238
280
  }),
239
281
  deleteManyDocuments: builder.mutation({
@@ -245,7 +287,10 @@ const documentApi = contentManagerApi.injectEndpoints({
245
287
  params
246
288
  }
247
289
  }),
248
- invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
290
+ invalidatesTags: (_res, _error, { model }) => [
291
+ { type: "Document", id: `${model}_LIST` },
292
+ "RecentDocumentList"
293
+ ]
249
294
  }),
250
295
  discardDocument: builder.mutation({
251
296
  query: ({ collectionType, model, documentId, params }) => ({
@@ -262,7 +307,9 @@ const documentApi = contentManagerApi.injectEndpoints({
262
307
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
263
308
  },
264
309
  { type: "Document", id: `${model}_LIST` },
265
- "Relations"
310
+ "Relations",
311
+ { type: "UidAvailability", id: model },
312
+ "RecentDocumentList"
266
313
  ];
267
314
  }
268
315
  }),
@@ -275,11 +322,12 @@ const documentApi = contentManagerApi.injectEndpoints({
275
322
  url: `/content-manager/collection-types/${model}`,
276
323
  method: "GET",
277
324
  config: {
278
- params
325
+ params: qs.stringify(params, { encode: true })
279
326
  }
280
327
  }),
281
328
  providesTags: (result, _error, arg) => {
282
329
  return [
330
+ { type: "Document", id: `ALL_LIST` },
283
331
  { type: "Document", id: `${arg.model}_LIST` },
284
332
  ...result?.results.map(({ documentId }) => ({
285
333
  type: "Document",
@@ -318,6 +366,11 @@ const documentApi = contentManagerApi.injectEndpoints({
318
366
  {
319
367
  type: "Document",
320
368
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
369
+ },
370
+ // Make it easy to invalidate all individual documents queries for a model
371
+ {
372
+ type: "Document",
373
+ id: `${model}_ALL_ITEMS`
321
374
  }
322
375
  ];
323
376
  }
@@ -351,7 +404,8 @@ const documentApi = contentManagerApi.injectEndpoints({
351
404
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
352
405
  },
353
406
  { type: "Document", id: `${model}_LIST` },
354
- "Relations"
407
+ "Relations",
408
+ "RecentDocumentList"
355
409
  ];
356
410
  }
357
411
  }),
@@ -381,8 +435,23 @@ const documentApi = contentManagerApi.injectEndpoints({
381
435
  type: "Document",
382
436
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
383
437
  },
384
- "Relations"
438
+ "Relations",
439
+ { type: "UidAvailability", id: model },
440
+ "RecentDocumentList",
441
+ "RecentDocumentList"
385
442
  ];
443
+ },
444
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
445
+ const patchResult = dispatch(
446
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
447
+ Object.assign(draft.data, data);
448
+ })
449
+ );
450
+ try {
451
+ await queryFulfilled;
452
+ } catch {
453
+ patchResult.undo();
454
+ }
386
455
  }
387
456
  }),
388
457
  unpublishDocument: builder.mutation({
@@ -399,7 +468,8 @@ const documentApi = contentManagerApi.injectEndpoints({
399
468
  {
400
469
  type: "Document",
401
470
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
402
- }
471
+ },
472
+ "RecentDocumentList"
403
473
  ];
404
474
  }
405
475
  }),
@@ -412,7 +482,10 @@ const documentApi = contentManagerApi.injectEndpoints({
412
482
  params
413
483
  }
414
484
  }),
415
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
485
+ invalidatesTags: (_res, _error, { model, documentIds }) => [
486
+ ...documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` })),
487
+ "RecentDocumentList"
488
+ ]
416
489
  })
417
490
  })
418
491
  });
@@ -435,8 +508,7 @@ const {
435
508
  useUnpublishManyDocumentsMutation
436
509
  } = documentApi;
437
510
  const buildValidParams = (query) => {
438
- if (!query)
439
- return query;
511
+ if (!query) return query;
440
512
  const { plugins: _, ...validQueryParams } = {
441
513
  ...query,
442
514
  ...Object.values(query?.plugins ?? {}).reduce(
@@ -444,28 +516,44 @@ const buildValidParams = (query) => {
444
516
  {}
445
517
  )
446
518
  };
447
- if ("_q" in validQueryParams) {
448
- validQueryParams._q = encodeURIComponent(validQueryParams._q);
449
- }
450
519
  return validQueryParams;
451
520
  };
452
521
  const isBaseQueryError = (error) => {
453
522
  return error.name !== void 0;
454
523
  };
455
- const createYupSchema = (attributes = {}, components = {}) => {
524
+ const arrayValidator = (attribute, options) => ({
525
+ message: strapiAdmin.translatedErrors.required,
526
+ test(value) {
527
+ if (options.status === "draft") {
528
+ return true;
529
+ }
530
+ if (!attribute.required) {
531
+ return true;
532
+ }
533
+ if (!value) {
534
+ return false;
535
+ }
536
+ if (Array.isArray(value) && value.length === 0) {
537
+ return false;
538
+ }
539
+ return true;
540
+ }
541
+ });
542
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
456
543
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
457
544
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
458
545
  if (DOCUMENT_META_FIELDS.includes(name)) {
459
546
  return acc;
460
547
  }
461
548
  const validations = [
549
+ addNullableValidation,
462
550
  addRequiredValidation,
463
551
  addMinLengthValidation,
464
552
  addMaxLengthValidation,
465
553
  addMinValidation,
466
554
  addMaxValidation,
467
555
  addRegexValidation
468
- ].map((fn) => fn(attribute));
556
+ ].map((fn) => fn(attribute, options));
469
557
  const transformSchema = pipe__default.default(...validations);
470
558
  switch (attribute.type) {
471
559
  case "component": {
@@ -475,12 +563,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
475
563
  ...acc,
476
564
  [name]: transformSchema(
477
565
  yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
478
- )
566
+ ).test(arrayValidator(attribute, options))
479
567
  };
480
568
  } else {
481
569
  return {
482
570
  ...acc,
483
- [name]: transformSchema(createModelSchema(attributes3))
571
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
484
572
  };
485
573
  }
486
574
  }
@@ -502,7 +590,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
502
590
  }
503
591
  )
504
592
  )
505
- )
593
+ ).test(arrayValidator(attribute, options))
506
594
  };
507
595
  case "relation":
508
596
  return {
@@ -514,7 +602,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
514
602
  } else if (Array.isArray(value)) {
515
603
  return yup__namespace.array().of(
516
604
  yup__namespace.object().shape({
517
- id: yup__namespace.string().required()
605
+ id: yup__namespace.number().required()
518
606
  })
519
607
  );
520
608
  } else if (typeof value === "object") {
@@ -566,6 +654,14 @@ const createAttributeSchema = (attribute) => {
566
654
  if (!value || typeof value === "string" && value.length === 0) {
567
655
  return true;
568
656
  }
657
+ if (typeof value === "object") {
658
+ try {
659
+ JSON.stringify(value);
660
+ return true;
661
+ } catch (err) {
662
+ return false;
663
+ }
664
+ }
569
665
  try {
570
666
  JSON.parse(value);
571
667
  return true;
@@ -584,13 +680,7 @@ const createAttributeSchema = (attribute) => {
584
680
  return yup__namespace.mixed();
585
681
  }
586
682
  };
587
- const addRequiredValidation = (attribute) => (schema) => {
588
- if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
589
- return schema.min(1, strapiAdmin.translatedErrors.required);
590
- }
591
- if (attribute.required && attribute.type !== "relation") {
592
- return schema.required(strapiAdmin.translatedErrors.required);
593
- }
683
+ const nullableSchema = (schema) => {
594
684
  return schema?.nullable ? schema.nullable() : (
595
685
  // In some cases '.nullable' will not be available on the schema.
596
686
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -598,7 +688,22 @@ const addRequiredValidation = (attribute) => (schema) => {
598
688
  schema
599
689
  );
600
690
  };
601
- const addMinLengthValidation = (attribute) => (schema) => {
691
+ const addNullableValidation = () => (schema) => {
692
+ return nullableSchema(schema);
693
+ };
694
+ const addRequiredValidation = (attribute, options) => (schema) => {
695
+ if (options.status === "draft" || !attribute.required) {
696
+ return schema;
697
+ }
698
+ if (attribute.required && "required" in schema) {
699
+ return schema.required(strapiAdmin.translatedErrors.required);
700
+ }
701
+ return schema;
702
+ };
703
+ const addMinLengthValidation = (attribute, options) => (schema) => {
704
+ if (options.status === "draft") {
705
+ return schema;
706
+ }
602
707
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
603
708
  return schema.min(attribute.minLength, {
604
709
  ...strapiAdmin.translatedErrors.minLength,
@@ -620,32 +725,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
620
725
  }
621
726
  return schema;
622
727
  };
623
- const addMinValidation = (attribute) => (schema) => {
624
- if ("min" in attribute) {
728
+ const addMinValidation = (attribute, options) => (schema) => {
729
+ if (options.status === "draft") {
730
+ return schema;
731
+ }
732
+ if ("min" in attribute && "min" in schema) {
625
733
  const min = toInteger(attribute.min);
626
- if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
627
- if (!attribute.required && "test" in schema && min) {
628
- return schema.test(
629
- "custom-min",
630
- {
631
- ...strapiAdmin.translatedErrors.min,
632
- values: {
633
- min: attribute.min
634
- }
635
- },
636
- (value) => {
637
- if (!value) {
638
- return true;
639
- }
640
- if (Array.isArray(value) && value.length === 0) {
641
- return true;
642
- }
643
- return value.length >= min;
644
- }
645
- );
646
- }
647
- }
648
- if ("min" in schema && min) {
734
+ if (min) {
649
735
  return schema.min(min, {
650
736
  ...strapiAdmin.translatedErrors.min,
651
737
  values: {
@@ -763,19 +849,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
763
849
  }, {});
764
850
  return componentsByKey;
765
851
  };
766
- const useDocument = (args, opts) => {
852
+ const HOOKS = {
853
+ /**
854
+ * Hook that allows to mutate the displayed headers of the list view table
855
+ * @constant
856
+ * @type {string}
857
+ */
858
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
859
+ /**
860
+ * Hook that allows to mutate the CM's collection types links pre-set filters
861
+ * @constant
862
+ * @type {string}
863
+ */
864
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
865
+ /**
866
+ * Hook that allows to mutate the CM's edit view layout
867
+ * @constant
868
+ * @type {string}
869
+ */
870
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
871
+ /**
872
+ * Hook that allows to mutate the CM's single types links pre-set filters
873
+ * @constant
874
+ * @type {string}
875
+ */
876
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
877
+ };
878
+ const contentTypesApi = contentManagerApi.injectEndpoints({
879
+ endpoints: (builder) => ({
880
+ getContentTypeConfiguration: builder.query({
881
+ query: (uid) => ({
882
+ url: `/content-manager/content-types/${uid}/configuration`,
883
+ method: "GET"
884
+ }),
885
+ transformResponse: (response) => response.data,
886
+ providesTags: (_result, _error, uid) => [
887
+ { type: "ContentTypesConfiguration", id: uid },
888
+ { type: "ContentTypeSettings", id: "LIST" }
889
+ ]
890
+ }),
891
+ getAllContentTypeSettings: builder.query({
892
+ query: () => "/content-manager/content-types-settings",
893
+ transformResponse: (response) => response.data,
894
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
895
+ }),
896
+ updateContentTypeConfiguration: builder.mutation({
897
+ query: ({ uid, ...body }) => ({
898
+ url: `/content-manager/content-types/${uid}/configuration`,
899
+ method: "PUT",
900
+ data: body
901
+ }),
902
+ transformResponse: (response) => response.data,
903
+ invalidatesTags: (_result, _error, { uid }) => [
904
+ { type: "ContentTypesConfiguration", id: uid },
905
+ { type: "ContentTypeSettings", id: "LIST" },
906
+ // Is this necessary?
907
+ { type: "InitialData" }
908
+ ]
909
+ })
910
+ })
911
+ });
912
+ const {
913
+ useGetContentTypeConfigurationQuery,
914
+ useGetAllContentTypeSettingsQuery,
915
+ useUpdateContentTypeConfigurationMutation
916
+ } = contentTypesApi;
917
+ const checkIfAttributeIsDisplayable = (attribute) => {
918
+ const { type } = attribute;
919
+ if (type === "relation") {
920
+ return !attribute.relation.toLowerCase().includes("morph");
921
+ }
922
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
923
+ };
924
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
925
+ if (!mainFieldName) {
926
+ return void 0;
927
+ }
928
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
929
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
930
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
931
+ );
932
+ return {
933
+ name: mainFieldName,
934
+ type: mainFieldType ?? "string"
935
+ };
936
+ };
937
+ const DEFAULT_SETTINGS = {
938
+ bulkable: false,
939
+ filterable: false,
940
+ searchable: false,
941
+ pagination: false,
942
+ defaultSortBy: "",
943
+ defaultSortOrder: "asc",
944
+ mainField: "id",
945
+ pageSize: 10
946
+ };
947
+ const useDocumentLayout = (model) => {
948
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
949
+ const [{ query }] = strapiAdmin.useQueryParams();
950
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
767
951
  const { toggleNotification } = strapiAdmin.useNotification();
768
952
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
953
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
769
954
  const {
770
- currentData: data,
771
- isLoading: isLoadingDocument,
772
- isFetching: isFetchingDocument,
773
- error
774
- } = useGetDocumentQuery(args, {
775
- ...opts,
776
- skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
777
- });
778
- const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
955
+ data,
956
+ isLoading: isLoadingConfigs,
957
+ error,
958
+ isFetching: isFetchingConfigs
959
+ } = useGetContentTypeConfigurationQuery(model);
960
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
779
961
  React__namespace.useEffect(() => {
780
962
  if (error) {
781
963
  toggleNotification({
@@ -783,68 +965,322 @@ const useDocument = (args, opts) => {
783
965
  message: formatAPIError(error)
784
966
  });
785
967
  }
786
- }, [toggleNotification, error, formatAPIError, args.collectionType]);
787
- const validationSchema = React__namespace.useMemo(() => {
788
- if (!schema) {
789
- return null;
790
- }
791
- return createYupSchema(schema.attributes, components);
792
- }, [schema, components]);
793
- const validate = React__namespace.useCallback(
794
- (document) => {
795
- if (!validationSchema) {
796
- throw new Error(
797
- "There is no validation schema generated, this is likely due to the schema not being loaded yet."
798
- );
799
- }
800
- try {
801
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
802
- return null;
803
- } catch (error2) {
804
- if (error2 instanceof yup.ValidationError) {
805
- return strapiAdmin.getYupValidationErrors(error2);
806
- }
807
- throw error2;
808
- }
968
+ }, [error, formatAPIError, toggleNotification]);
969
+ const editLayout = React__namespace.useMemo(
970
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
971
+ layout: [],
972
+ components: {},
973
+ metadatas: {},
974
+ options: {},
975
+ settings: DEFAULT_SETTINGS
809
976
  },
810
- [validationSchema]
977
+ [data, isLoading, schemas, schema, components]
978
+ );
979
+ const listLayout = React__namespace.useMemo(() => {
980
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
981
+ layout: [],
982
+ metadatas: {},
983
+ options: {},
984
+ settings: DEFAULT_SETTINGS
985
+ };
986
+ }, [data, isLoading, schemas, schema, components]);
987
+ const { layout: edit } = React__namespace.useMemo(
988
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
989
+ layout: editLayout,
990
+ query
991
+ }),
992
+ [editLayout, query, runHookWaterfall]
811
993
  );
812
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
813
994
  return {
814
- components,
815
- document: data?.data,
816
- meta: data?.meta,
995
+ error,
817
996
  isLoading,
818
- schema,
819
- validate
820
- };
821
- };
822
- const useDoc = () => {
823
- const { id, slug, collectionType, origin } = reactRouterDom.useParams();
824
- const [{ query }] = strapiAdmin.useQueryParams();
825
- const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
826
- if (!collectionType) {
827
- throw new Error("Could not find collectionType in url params");
828
- }
829
- if (!slug) {
830
- throw new Error("Could not find model in url params");
831
- }
832
- return {
833
- collectionType,
834
- model: slug,
835
- id: origin || id === "create" ? void 0 : id,
836
- ...useDocument(
837
- { documentId: origin || id, model: slug, collectionType, params },
838
- {
839
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
840
- }
841
- )
997
+ edit,
998
+ list: listLayout
842
999
  };
843
1000
  };
844
- const prefixPluginTranslations = (trad, pluginId) => {
845
- if (!pluginId) {
846
- throw new TypeError("pluginId can't be empty");
1001
+ const useDocLayout = () => {
1002
+ const { model } = useDoc();
1003
+ return useDocumentLayout(model);
1004
+ };
1005
+ const formatEditLayout = (data, {
1006
+ schemas,
1007
+ schema,
1008
+ components
1009
+ }) => {
1010
+ let currentPanelIndex = 0;
1011
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
1012
+ data.contentType.layouts.edit,
1013
+ schema?.attributes,
1014
+ data.contentType.metadatas,
1015
+ { configurations: data.components, schemas: components },
1016
+ schemas
1017
+ ).reduce((panels, row) => {
1018
+ if (row.some((field) => field.type === "dynamiczone")) {
1019
+ panels.push([row]);
1020
+ currentPanelIndex += 2;
1021
+ } else {
1022
+ if (!panels[currentPanelIndex]) {
1023
+ panels.push([row]);
1024
+ } else {
1025
+ panels[currentPanelIndex].push(row);
1026
+ }
1027
+ }
1028
+ return panels;
1029
+ }, []);
1030
+ const componentEditAttributes = Object.entries(data.components).reduce(
1031
+ (acc, [uid, configuration]) => {
1032
+ acc[uid] = {
1033
+ layout: convertEditLayoutToFieldLayouts(
1034
+ configuration.layouts.edit,
1035
+ components[uid].attributes,
1036
+ configuration.metadatas,
1037
+ { configurations: data.components, schemas: components }
1038
+ ),
1039
+ settings: {
1040
+ ...configuration.settings,
1041
+ icon: components[uid].info.icon,
1042
+ displayName: components[uid].info.displayName
1043
+ }
1044
+ };
1045
+ return acc;
1046
+ },
1047
+ {}
1048
+ );
1049
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
1050
+ (acc, [attribute, metadata]) => {
1051
+ return {
1052
+ ...acc,
1053
+ [attribute]: metadata.edit
1054
+ };
1055
+ },
1056
+ {}
1057
+ );
1058
+ return {
1059
+ layout: panelledEditAttributes,
1060
+ components: componentEditAttributes,
1061
+ metadatas: editMetadatas,
1062
+ settings: {
1063
+ ...data.contentType.settings,
1064
+ displayName: schema?.info.displayName
1065
+ },
1066
+ options: {
1067
+ ...schema?.options,
1068
+ ...schema?.pluginOptions,
1069
+ ...data.contentType.options
1070
+ }
1071
+ };
1072
+ };
1073
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1074
+ return rows.map(
1075
+ (row) => row.map((field) => {
1076
+ const attribute = attributes[field.name];
1077
+ if (!attribute) {
1078
+ return null;
1079
+ }
1080
+ const { edit: metadata } = metadatas[field.name];
1081
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1082
+ return {
1083
+ attribute,
1084
+ disabled: !metadata.editable,
1085
+ hint: metadata.description,
1086
+ label: metadata.label ?? "",
1087
+ name: field.name,
1088
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1089
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1090
+ schemas,
1091
+ components: components?.schemas ?? {}
1092
+ }),
1093
+ placeholder: metadata.placeholder ?? "",
1094
+ required: attribute.required ?? false,
1095
+ size: field.size,
1096
+ unique: "unique" in attribute ? attribute.unique : false,
1097
+ visible: metadata.visible ?? true,
1098
+ type: attribute.type
1099
+ };
1100
+ }).filter((field) => field !== null)
1101
+ );
1102
+ };
1103
+ const formatListLayout = (data, {
1104
+ schemas,
1105
+ schema,
1106
+ components
1107
+ }) => {
1108
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1109
+ (acc, [attribute, metadata]) => {
1110
+ return {
1111
+ ...acc,
1112
+ [attribute]: metadata.list
1113
+ };
1114
+ },
1115
+ {}
1116
+ );
1117
+ const listAttributes = convertListLayoutToFieldLayouts(
1118
+ data.contentType.layouts.list,
1119
+ schema?.attributes,
1120
+ listMetadatas,
1121
+ { configurations: data.components, schemas: components },
1122
+ schemas
1123
+ );
1124
+ return {
1125
+ layout: listAttributes,
1126
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1127
+ metadatas: listMetadatas,
1128
+ options: {
1129
+ ...schema?.options,
1130
+ ...schema?.pluginOptions,
1131
+ ...data.contentType.options
1132
+ }
1133
+ };
1134
+ };
1135
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1136
+ return columns.map((name) => {
1137
+ const attribute = attributes[name];
1138
+ if (!attribute) {
1139
+ return null;
1140
+ }
1141
+ const metadata = metadatas[name];
1142
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1143
+ return {
1144
+ attribute,
1145
+ label: metadata.label ?? "",
1146
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1147
+ schemas,
1148
+ components: components?.schemas ?? {}
1149
+ }),
1150
+ name,
1151
+ searchable: metadata.searchable ?? true,
1152
+ sortable: metadata.sortable ?? true
1153
+ };
1154
+ }).filter((field) => field !== null);
1155
+ };
1156
+ const useDocument = (args, opts) => {
1157
+ const { toggleNotification } = strapiAdmin.useNotification();
1158
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1159
+ const {
1160
+ currentData: data,
1161
+ isLoading: isLoadingDocument,
1162
+ isFetching: isFetchingDocument,
1163
+ error
1164
+ } = useGetDocumentQuery(args, {
1165
+ ...opts,
1166
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1167
+ });
1168
+ const {
1169
+ components,
1170
+ schema,
1171
+ schemas,
1172
+ isLoading: isLoadingSchema
1173
+ } = useContentTypeSchema(args.model);
1174
+ React__namespace.useEffect(() => {
1175
+ if (error) {
1176
+ toggleNotification({
1177
+ type: "danger",
1178
+ message: formatAPIError(error)
1179
+ });
1180
+ }
1181
+ }, [toggleNotification, error, formatAPIError, args.collectionType]);
1182
+ const validationSchema = React__namespace.useMemo(() => {
1183
+ if (!schema) {
1184
+ return null;
1185
+ }
1186
+ return createYupSchema(schema.attributes, components);
1187
+ }, [schema, components]);
1188
+ const validate = React__namespace.useCallback(
1189
+ (document) => {
1190
+ if (!validationSchema) {
1191
+ throw new Error(
1192
+ "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1193
+ );
1194
+ }
1195
+ try {
1196
+ validationSchema.validateSync(document, { abortEarly: false, strict: true });
1197
+ return null;
1198
+ } catch (error2) {
1199
+ if (error2 instanceof yup.ValidationError) {
1200
+ return strapiAdmin.getYupValidationErrors(error2);
1201
+ }
1202
+ throw error2;
1203
+ }
1204
+ },
1205
+ [validationSchema]
1206
+ );
1207
+ const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1208
+ const hasError = !!error;
1209
+ return {
1210
+ components,
1211
+ document: data?.data,
1212
+ meta: data?.meta,
1213
+ isLoading,
1214
+ hasError,
1215
+ schema,
1216
+ schemas,
1217
+ validate
1218
+ };
1219
+ };
1220
+ const useDoc = () => {
1221
+ const { id, slug, collectionType, origin } = reactRouterDom.useParams();
1222
+ const [{ query }] = strapiAdmin.useQueryParams();
1223
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1224
+ if (!collectionType) {
1225
+ throw new Error("Could not find collectionType in url params");
1226
+ }
1227
+ if (!slug) {
1228
+ throw new Error("Could not find model in url params");
847
1229
  }
1230
+ const document = useDocument(
1231
+ { documentId: origin || id, model: slug, collectionType, params },
1232
+ {
1233
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1234
+ }
1235
+ );
1236
+ const returnId = origin || id === "create" ? void 0 : id;
1237
+ return {
1238
+ collectionType,
1239
+ model: slug,
1240
+ id: returnId,
1241
+ ...document
1242
+ };
1243
+ };
1244
+ const useContentManagerContext = () => {
1245
+ const {
1246
+ collectionType,
1247
+ model,
1248
+ id,
1249
+ components,
1250
+ isLoading: isLoadingDoc,
1251
+ schema,
1252
+ schemas
1253
+ } = useDoc();
1254
+ const layout = useDocumentLayout(model);
1255
+ const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
1256
+ const isSingleType = collectionType === SINGLE_TYPES;
1257
+ const slug = model;
1258
+ const isCreatingEntry = id === "create";
1259
+ useContentTypeSchema();
1260
+ const isLoading = isLoadingDoc || layout.isLoading;
1261
+ const error = layout.error;
1262
+ return {
1263
+ error,
1264
+ isLoading,
1265
+ // Base metadata
1266
+ model,
1267
+ collectionType,
1268
+ id,
1269
+ slug,
1270
+ isCreatingEntry,
1271
+ isSingleType,
1272
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1273
+ // All schema infos
1274
+ components,
1275
+ contentType: schema,
1276
+ contentTypes: schemas,
1277
+ // Form state
1278
+ form,
1279
+ // layout infos
1280
+ layout
1281
+ };
1282
+ };
1283
+ const prefixPluginTranslations = (trad, pluginId) => {
848
1284
  return Object.keys(trad).reduce((acc, current) => {
849
1285
  acc[`${pluginId}.${current}`] = trad[current];
850
1286
  return acc;
@@ -860,6 +1296,8 @@ const useDocumentActions = () => {
860
1296
  const { formatMessage } = reactIntl.useIntl();
861
1297
  const { trackUsage } = strapiAdmin.useTracking();
862
1298
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1299
+ const navigate = reactRouterDom.useNavigate();
1300
+ const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
863
1301
  const [deleteDocument] = useDeleteDocumentMutation();
864
1302
  const _delete = React__namespace.useCallback(
865
1303
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -1174,6 +1612,7 @@ const useDocumentActions = () => {
1174
1612
  defaultMessage: "Saved document"
1175
1613
  })
1176
1614
  });
1615
+ setCurrentStep("contentManager.success");
1177
1616
  return res.data;
1178
1617
  } catch (err) {
1179
1618
  toggleNotification({
@@ -1195,7 +1634,6 @@ const useDocumentActions = () => {
1195
1634
  sourceId
1196
1635
  });
1197
1636
  if ("error" in res) {
1198
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1199
1637
  return { error: res.error };
1200
1638
  }
1201
1639
  toggleNotification({
@@ -1214,7 +1652,7 @@ const useDocumentActions = () => {
1214
1652
  throw err;
1215
1653
  }
1216
1654
  },
1217
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1655
+ [autoCloneDocument, formatMessage, toggleNotification]
1218
1656
  );
1219
1657
  const [cloneDocument] = useCloneDocumentMutation();
1220
1658
  const clone = React__namespace.useCallback(
@@ -1240,6 +1678,7 @@ const useDocumentActions = () => {
1240
1678
  defaultMessage: "Cloned document"
1241
1679
  })
1242
1680
  });
1681
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1243
1682
  return res.data;
1244
1683
  } catch (err) {
1245
1684
  toggleNotification({
@@ -1250,7 +1689,7 @@ const useDocumentActions = () => {
1250
1689
  throw err;
1251
1690
  }
1252
1691
  },
1253
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1692
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1254
1693
  );
1255
1694
  const [getDoc] = useLazyGetDocumentQuery();
1256
1695
  const getDocument = React__namespace.useCallback(
@@ -1275,10 +1714,10 @@ const useDocumentActions = () => {
1275
1714
  update
1276
1715
  };
1277
1716
  };
1278
- const ProtectedHistoryPage = React.lazy(
1279
- () => Promise.resolve().then(() => require("./History-DdIstl8b.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1717
+ const ProtectedHistoryPage = React__namespace.lazy(
1718
+ () => Promise.resolve().then(() => require("./History-DrDJv698.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1280
1719
  );
1281
- const routes$1 = [
1720
+ const routes$2 = [
1282
1721
  {
1283
1722
  path: ":collectionType/:slug/:id/history",
1284
1723
  Component: ProtectedHistoryPage
@@ -1288,32 +1727,45 @@ const routes$1 = [
1288
1727
  Component: ProtectedHistoryPage
1289
1728
  }
1290
1729
  ];
1730
+ const ProtectedPreviewPage = React__namespace.lazy(
1731
+ () => Promise.resolve().then(() => require("./Preview-VOJ8RuQp.js")).then((mod) => ({ default: mod.ProtectedPreviewPage }))
1732
+ );
1733
+ const routes$1 = [
1734
+ {
1735
+ path: ":collectionType/:slug/:id/preview",
1736
+ Component: ProtectedPreviewPage
1737
+ },
1738
+ {
1739
+ path: ":collectionType/:slug/preview",
1740
+ Component: ProtectedPreviewPage
1741
+ }
1742
+ ];
1291
1743
  const ProtectedEditViewPage = React.lazy(
1292
- () => Promise.resolve().then(() => require("./EditViewPage-DA95Ha6J.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1744
+ () => Promise.resolve().then(() => require("./EditViewPage-CDyTC6aU.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1293
1745
  );
1294
1746
  const ProtectedListViewPage = React.lazy(
1295
- () => Promise.resolve().then(() => require("./ListViewPage-wE0lXqoD.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1747
+ () => Promise.resolve().then(() => require("./ListViewPage-DTM2uO_S.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1296
1748
  );
1297
1749
  const ProtectedListConfiguration = React.lazy(
1298
- () => Promise.resolve().then(() => require("./ListConfigurationPage-DkKRparB.js")).then((mod) => ({
1750
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-zurIlUZ7.js")).then((mod) => ({
1299
1751
  default: mod.ProtectedListConfiguration
1300
1752
  }))
1301
1753
  );
1302
1754
  const ProtectedEditConfigurationPage = React.lazy(
1303
- () => Promise.resolve().then(() => require("./EditConfigurationPage-BFEwvdMW.js")).then((mod) => ({
1755
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-CF3lxOy2.js")).then((mod) => ({
1304
1756
  default: mod.ProtectedEditConfigurationPage
1305
1757
  }))
1306
1758
  );
1307
1759
  const ProtectedComponentConfigurationPage = React.lazy(
1308
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-Bqgx7Mes.js")).then((mod) => ({
1760
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-CJPoOvy3.js")).then((mod) => ({
1309
1761
  default: mod.ProtectedComponentConfigurationPage
1310
1762
  }))
1311
1763
  );
1312
1764
  const NoPermissions = React.lazy(
1313
- () => Promise.resolve().then(() => require("./NoPermissionsPage-DmNfF2Bb.js")).then((mod) => ({ default: mod.NoPermissions }))
1765
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-DLzkS4Hy.js")).then((mod) => ({ default: mod.NoPermissions }))
1314
1766
  );
1315
1767
  const NoContentType = React.lazy(
1316
- () => Promise.resolve().then(() => require("./NoContentTypePage-DEKR6tf9.js")).then((mod) => ({ default: mod.NoContentType }))
1768
+ () => Promise.resolve().then(() => require("./NoContentTypePage-BuZlNroO.js")).then((mod) => ({ default: mod.NoContentType }))
1317
1769
  );
1318
1770
  const CollectionTypePages = () => {
1319
1771
  const { collectionType } = reactRouterDom.useParams();
@@ -1325,7 +1777,7 @@ const CollectionTypePages = () => {
1325
1777
  const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
1326
1778
  const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
1327
1779
  const LIST_RELATIVE_PATH = ":collectionType/:slug";
1328
- const LIST_PATH = `/content-manager/${LIST_RELATIVE_PATH}`;
1780
+ const LIST_PATH = `/content-manager/collection-types/:slug`;
1329
1781
  const routes = [
1330
1782
  {
1331
1783
  path: LIST_RELATIVE_PATH,
@@ -1359,6 +1811,7 @@ const routes = [
1359
1811
  path: "no-content-types",
1360
1812
  Component: NoContentType
1361
1813
  },
1814
+ ...routes$2,
1362
1815
  ...routes$1
1363
1816
  ];
1364
1817
  const DocumentActions = ({ actions: actions2 }) => {
@@ -1427,12 +1880,14 @@ const DocumentActionButton = (action) => {
1427
1880
  /* @__PURE__ */ jsxRuntime.jsx(
1428
1881
  designSystem.Button,
1429
1882
  {
1430
- flex: 1,
1883
+ flex: "auto",
1431
1884
  startIcon: action.icon,
1432
1885
  disabled: action.disabled,
1433
1886
  onClick: handleClick(action),
1434
1887
  justifyContent: "center",
1435
1888
  variant: action.variant || "default",
1889
+ paddingTop: "7px",
1890
+ paddingBottom: "7px",
1436
1891
  children: action.label
1437
1892
  }
1438
1893
  ),
@@ -1455,6 +1910,11 @@ const DocumentActionButton = (action) => {
1455
1910
  ) : null
1456
1911
  ] });
1457
1912
  };
1913
+ const MenuItem = styledComponents.styled(designSystem.Menu.Item)`
1914
+ &:hover {
1915
+ background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
1916
+ }
1917
+ `;
1458
1918
  const DocumentActionsMenu = ({
1459
1919
  actions: actions2,
1460
1920
  children,
@@ -1497,9 +1957,9 @@ const DocumentActionsMenu = ({
1497
1957
  disabled: isDisabled,
1498
1958
  size: "S",
1499
1959
  endIcon: null,
1500
- paddingTop: "7px",
1501
- paddingLeft: "9px",
1502
- paddingRight: "9px",
1960
+ paddingTop: "4px",
1961
+ paddingLeft: "7px",
1962
+ paddingRight: "7px",
1503
1963
  variant,
1504
1964
  children: [
1505
1965
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
@@ -1510,36 +1970,35 @@ const DocumentActionsMenu = ({
1510
1970
  ]
1511
1971
  }
1512
1972
  ),
1513
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1973
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1514
1974
  actions2.map((action) => {
1515
1975
  return /* @__PURE__ */ jsxRuntime.jsx(
1516
- designSystem.Menu.Item,
1976
+ MenuItem,
1517
1977
  {
1518
1978
  disabled: action.disabled,
1519
1979
  onSelect: handleClick(action),
1520
1980
  display: "block",
1521
- children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1522
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1523
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1524
- action.label
1525
- ] }),
1526
- action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
1527
- designSystem.Flex,
1528
- {
1529
- alignItems: "center",
1530
- background: "alternative100",
1531
- borderStyle: "solid",
1532
- borderColor: "alternative200",
1533
- borderWidth: "1px",
1534
- height: 5,
1535
- paddingLeft: 2,
1536
- paddingRight: 2,
1537
- hasRadius: true,
1538
- color: "alternative600",
1539
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
1540
- }
1541
- )
1542
- ] })
1981
+ isVariantDanger: action.variant === "danger",
1982
+ isDisabled: action.disabled,
1983
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
1984
+ designSystem.Flex,
1985
+ {
1986
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1987
+ gap: 2,
1988
+ tag: "span",
1989
+ children: [
1990
+ /* @__PURE__ */ jsxRuntime.jsx(
1991
+ designSystem.Flex,
1992
+ {
1993
+ tag: "span",
1994
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1995
+ children: action.icon
1996
+ }
1997
+ ),
1998
+ action.label
1999
+ ]
2000
+ }
2001
+ ) })
1543
2002
  },
1544
2003
  action.id
1545
2004
  );
@@ -1619,11 +2078,11 @@ const DocumentActionConfirmDialog = ({
1619
2078
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
1620
2079
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
1621
2080
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
1622
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
2081
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
1623
2082
  id: "app.components.Button.cancel",
1624
2083
  defaultMessage: "Cancel"
1625
2084
  }) }) }),
1626
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
2085
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
1627
2086
  id: "app.components.Button.confirm",
1628
2087
  defaultMessage: "Confirm"
1629
2088
  }) })
@@ -1646,10 +2105,22 @@ const DocumentActionModal = ({
1646
2105
  };
1647
2106
  return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
1648
2107
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
1649
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content }),
1650
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Footer, { children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer })
2108
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
2109
+ typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1651
2110
  ] }) });
1652
2111
  };
2112
+ const transformData = (data) => {
2113
+ if (Array.isArray(data)) {
2114
+ return data.map(transformData);
2115
+ }
2116
+ if (typeof data === "object" && data !== null) {
2117
+ if ("apiData" in data) {
2118
+ return data.apiData;
2119
+ }
2120
+ return mapValues__default.default(transformData)(data);
2121
+ }
2122
+ return data;
2123
+ };
1653
2124
  const PublishAction$1 = ({
1654
2125
  activeTab,
1655
2126
  documentId,
@@ -1662,12 +2133,11 @@ const PublishAction$1 = ({
1662
2133
  const navigate = reactRouterDom.useNavigate();
1663
2134
  const { toggleNotification } = strapiAdmin.useNotification();
1664
2135
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
2136
+ const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
1665
2137
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2138
+ const { id } = reactRouterDom.useParams();
1666
2139
  const { formatMessage } = reactIntl.useIntl();
1667
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1668
- "PublishAction",
1669
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1670
- );
2140
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1671
2141
  const { publish } = useDocumentActions();
1672
2142
  const [
1673
2143
  countDraftRelations,
@@ -1719,24 +2189,25 @@ const PublishAction$1 = ({
1719
2189
  }
1720
2190
  }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
1721
2191
  React__namespace.useEffect(() => {
1722
- if (documentId) {
1723
- const fetchDraftRelationsCount = async () => {
1724
- const { data, error } = await countDraftRelations({
1725
- collectionType,
1726
- model,
1727
- documentId,
1728
- params
1729
- });
1730
- if (error) {
1731
- throw error;
1732
- }
1733
- if (data) {
1734
- setServerCountOfDraftRelations(data.data);
1735
- }
1736
- };
1737
- fetchDraftRelationsCount();
2192
+ if (!document || !document.documentId || isListView) {
2193
+ return;
1738
2194
  }
1739
- }, [documentId, countDraftRelations, collectionType, model, params]);
2195
+ const fetchDraftRelationsCount = async () => {
2196
+ const { data, error } = await countDraftRelations({
2197
+ collectionType,
2198
+ model,
2199
+ documentId,
2200
+ params
2201
+ });
2202
+ if (error) {
2203
+ throw error;
2204
+ }
2205
+ if (data) {
2206
+ setServerCountOfDraftRelations(data.data);
2207
+ }
2208
+ };
2209
+ fetchDraftRelationsCount();
2210
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
1740
2211
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1741
2212
  if (!schema?.options?.draftAndPublish) {
1742
2213
  return null;
@@ -1744,7 +2215,9 @@ const PublishAction$1 = ({
1744
2215
  const performPublish = async () => {
1745
2216
  setSubmitting(true);
1746
2217
  try {
1747
- const { errors } = await validate();
2218
+ const { errors } = await validate(true, {
2219
+ status: "published"
2220
+ });
1748
2221
  if (errors) {
1749
2222
  toggleNotification({
1750
2223
  type: "danger",
@@ -1762,13 +2235,15 @@ const PublishAction$1 = ({
1762
2235
  documentId,
1763
2236
  params
1764
2237
  },
1765
- formValues
2238
+ transformData(formValues)
1766
2239
  );
1767
2240
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1768
- navigate({
1769
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1770
- search: rawQuery
1771
- });
2241
+ if (id === "create") {
2242
+ navigate({
2243
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2244
+ search: rawQuery
2245
+ });
2246
+ }
1772
2247
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1773
2248
  setErrors(formatValidationErrors(res.error));
1774
2249
  }
@@ -1777,7 +2252,8 @@ const PublishAction$1 = ({
1777
2252
  }
1778
2253
  };
1779
2254
  const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1780
- const hasDraftRelations = totalDraftRelations > 0;
2255
+ const enableDraftRelationsCount = false;
2256
+ const hasDraftRelations = enableDraftRelationsCount;
1781
2257
  return {
1782
2258
  /**
1783
2259
  * Disabled when:
@@ -1787,18 +2263,13 @@ const PublishAction$1 = ({
1787
2263
  * - the document is already published & not modified
1788
2264
  * - the document is being created & not modified
1789
2265
  * - the user doesn't have the permission to publish
1790
- * - the user doesn't have the permission to create a new document
1791
- * - the user doesn't have the permission to update the document
1792
2266
  */
1793
- disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2267
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1794
2268
  label: formatMessage({
1795
2269
  id: "app.utils.publish",
1796
2270
  defaultMessage: "Publish"
1797
2271
  }),
1798
2272
  onClick: async () => {
1799
- if (hasDraftRelations) {
1800
- return;
1801
- }
1802
2273
  await performPublish();
1803
2274
  },
1804
2275
  dialog: hasDraftRelations ? {
@@ -1825,6 +2296,7 @@ const PublishAction$1 = ({
1825
2296
  };
1826
2297
  };
1827
2298
  PublishAction$1.type = "publish";
2299
+ PublishAction$1.position = "panel";
1828
2300
  const UpdateAction = ({
1829
2301
  activeTab,
1830
2302
  documentId,
@@ -1837,10 +2309,6 @@ const UpdateAction = ({
1837
2309
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1838
2310
  const isCloning = cloneMatch !== null;
1839
2311
  const { formatMessage } = reactIntl.useIntl();
1840
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1841
- canCreate: canCreate2,
1842
- canUpdate: canUpdate2
1843
- }));
1844
2312
  const { create, update, clone } = useDocumentActions();
1845
2313
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1846
2314
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1851,93 +2319,134 @@ const UpdateAction = ({
1851
2319
  const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
1852
2320
  const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
1853
2321
  const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
1854
- return {
1855
- /**
1856
- * Disabled when:
1857
- * - the form is submitting
1858
- * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1859
- * - the active tab is the published tab
1860
- * - the user doesn't have the permission to create a new document
1861
- * - the user doesn't have the permission to update the document
1862
- */
1863
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
1864
- label: formatMessage({
1865
- id: "content-manager.containers.Edit.save",
1866
- defaultMessage: "Save"
1867
- }),
1868
- onClick: async () => {
1869
- setSubmitting(true);
1870
- try {
1871
- const { errors } = await validate();
1872
- if (errors) {
1873
- toggleNotification({
1874
- type: "danger",
1875
- message: formatMessage({
1876
- id: "content-manager.validation.error",
1877
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1878
- })
1879
- });
1880
- return;
1881
- }
1882
- if (isCloning) {
1883
- const res = await clone(
2322
+ const handleUpdate = React__namespace.useCallback(async () => {
2323
+ setSubmitting(true);
2324
+ try {
2325
+ if (!modified) {
2326
+ return;
2327
+ }
2328
+ const { errors } = await validate(true, {
2329
+ status: "draft"
2330
+ });
2331
+ if (errors) {
2332
+ toggleNotification({
2333
+ type: "danger",
2334
+ message: formatMessage({
2335
+ id: "content-manager.validation.error",
2336
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2337
+ })
2338
+ });
2339
+ return;
2340
+ }
2341
+ if (isCloning) {
2342
+ const res = await clone(
2343
+ {
2344
+ model,
2345
+ documentId: cloneMatch.params.origin,
2346
+ params
2347
+ },
2348
+ transformData(document)
2349
+ );
2350
+ if ("data" in res) {
2351
+ navigate(
1884
2352
  {
1885
- model,
1886
- documentId: cloneMatch.params.origin,
1887
- params
1888
- },
1889
- document
1890
- );
1891
- if ("data" in res) {
1892
- navigate({
1893
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2353
+ pathname: `../${res.data.documentId}`,
1894
2354
  search: rawQuery
1895
- });
1896
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1897
- setErrors(formatValidationErrors(res.error));
1898
- }
1899
- } else if (documentId || collectionType === SINGLE_TYPES) {
1900
- const res = await update(
1901
- {
1902
- collectionType,
1903
- model,
1904
- documentId,
1905
- params
1906
2355
  },
1907
- document
2356
+ { relative: "path" }
1908
2357
  );
1909
- if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1910
- setErrors(formatValidationErrors(res.error));
1911
- } else {
1912
- resetForm();
1913
- }
2358
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2359
+ setErrors(formatValidationErrors(res.error));
2360
+ }
2361
+ } else if (documentId || collectionType === SINGLE_TYPES) {
2362
+ const res = await update(
2363
+ {
2364
+ collectionType,
2365
+ model,
2366
+ documentId,
2367
+ params
2368
+ },
2369
+ transformData(document)
2370
+ );
2371
+ if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2372
+ setErrors(formatValidationErrors(res.error));
1914
2373
  } else {
1915
- const res = await create(
2374
+ resetForm();
2375
+ }
2376
+ } else {
2377
+ const res = await create(
2378
+ {
2379
+ model,
2380
+ params
2381
+ },
2382
+ transformData(document)
2383
+ );
2384
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2385
+ navigate(
1916
2386
  {
1917
- model,
1918
- params
2387
+ pathname: `../${res.data.documentId}`,
2388
+ search: rawQuery
1919
2389
  },
1920
- document
2390
+ { replace: true, relative: "path" }
1921
2391
  );
1922
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1923
- navigate(
1924
- {
1925
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1926
- search: rawQuery
1927
- },
1928
- { replace: true }
1929
- );
1930
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1931
- setErrors(formatValidationErrors(res.error));
1932
- }
2392
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2393
+ setErrors(formatValidationErrors(res.error));
1933
2394
  }
1934
- } finally {
1935
- setSubmitting(false);
1936
2395
  }
2396
+ } finally {
2397
+ setSubmitting(false);
1937
2398
  }
2399
+ }, [
2400
+ clone,
2401
+ cloneMatch?.params.origin,
2402
+ collectionType,
2403
+ create,
2404
+ document,
2405
+ documentId,
2406
+ formatMessage,
2407
+ formatValidationErrors,
2408
+ isCloning,
2409
+ model,
2410
+ modified,
2411
+ navigate,
2412
+ params,
2413
+ rawQuery,
2414
+ resetForm,
2415
+ setErrors,
2416
+ setSubmitting,
2417
+ toggleNotification,
2418
+ update,
2419
+ validate
2420
+ ]);
2421
+ React__namespace.useEffect(() => {
2422
+ const handleKeyDown = (e) => {
2423
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
2424
+ e.preventDefault();
2425
+ handleUpdate();
2426
+ }
2427
+ };
2428
+ window.addEventListener("keydown", handleKeyDown);
2429
+ return () => {
2430
+ window.removeEventListener("keydown", handleKeyDown);
2431
+ };
2432
+ }, [handleUpdate]);
2433
+ return {
2434
+ /**
2435
+ * Disabled when:
2436
+ * - the form is submitting
2437
+ * - the document is not modified & we're not cloning (you can save a clone entity straight away)
2438
+ * - the active tab is the published tab
2439
+ */
2440
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
2441
+ label: formatMessage({
2442
+ id: "global.save",
2443
+ defaultMessage: "Save"
2444
+ }),
2445
+ onClick: handleUpdate
1938
2446
  };
1939
2447
  };
1940
2448
  UpdateAction.type = "update";
2449
+ UpdateAction.position = "panel";
1941
2450
  const UNPUBLISH_DRAFT_OPTIONS = {
1942
2451
  KEEP: "keep",
1943
2452
  DISCARD: "discard"
@@ -1970,7 +2479,7 @@ const UnpublishAction$1 = ({
1970
2479
  id: "app.utils.unpublish",
1971
2480
  defaultMessage: "Unpublish"
1972
2481
  }),
1973
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2482
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
1974
2483
  onClick: async () => {
1975
2484
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1976
2485
  if (!documentId) {
@@ -2060,6 +2569,7 @@ const UnpublishAction$1 = ({
2060
2569
  };
2061
2570
  };
2062
2571
  UnpublishAction$1.type = "unpublish";
2572
+ UnpublishAction$1.position = "panel";
2063
2573
  const DiscardAction = ({
2064
2574
  activeTab,
2065
2575
  documentId,
@@ -2082,7 +2592,7 @@ const DiscardAction = ({
2082
2592
  id: "content-manager.actions.discard.label",
2083
2593
  defaultMessage: "Discard changes"
2084
2594
  }),
2085
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2595
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
2086
2596
  position: ["panel", "table-row"],
2087
2597
  variant: "danger",
2088
2598
  dialog: {
@@ -2110,11 +2620,7 @@ const DiscardAction = ({
2110
2620
  };
2111
2621
  };
2112
2622
  DiscardAction.type = "discard";
2113
- const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
2114
- path {
2115
- fill: currentColor;
2116
- }
2117
- `;
2623
+ DiscardAction.position = "panel";
2118
2624
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2119
2625
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2120
2626
  const RelativeTime = React__namespace.forwardRef(
@@ -2127,7 +2633,7 @@ const RelativeTime = React__namespace.forwardRef(
2127
2633
  });
2128
2634
  const unit = intervals.find((intervalUnit) => {
2129
2635
  return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
2130
- });
2636
+ }) ?? "seconds";
2131
2637
  const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
2132
2638
  const customInterval = customIntervals.find(
2133
2639
  (custom) => interval[custom.unit] < custom.threshold
@@ -2161,19 +2667,29 @@ const getDisplayName = ({
2161
2667
  return email ?? "";
2162
2668
  };
2163
2669
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2164
- const DocumentStatus = ({ status = "draft", ...restProps }) => {
2165
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
2166
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2670
+ const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
2671
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2672
+ const { formatMessage } = reactIntl.useIntl();
2673
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
2674
+ id: `content-manager.containers.List.${status}`,
2675
+ defaultMessage: capitalise(status)
2676
+ }) }) });
2167
2677
  };
2168
2678
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2169
2679
  const { formatMessage } = reactIntl.useIntl();
2170
2680
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2681
+ const params = reactRouterDom.useParams();
2171
2682
  const title = isCreating ? formatMessage({
2172
2683
  id: "content-manager.containers.edit.title.new",
2173
2684
  defaultMessage: "Create an entry"
2174
2685
  }) : documentTitle;
2175
2686
  return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2176
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
2687
+ /* @__PURE__ */ jsxRuntime.jsx(
2688
+ strapiAdmin.BackButton,
2689
+ {
2690
+ fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
2691
+ }
2692
+ ),
2177
2693
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2178
2694
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2179
2695
  /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
@@ -2224,7 +2740,7 @@ const HeaderToolbar = () => {
2224
2740
  meta: isCloning ? void 0 : meta,
2225
2741
  collectionType
2226
2742
  },
2227
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2743
+ descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
2228
2744
  children: (actions2) => {
2229
2745
  const headerActions = actions2.filter((action) => {
2230
2746
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -2261,12 +2777,12 @@ const Information = ({ activeTab }) => {
2261
2777
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2262
2778
  label: formatMessage({
2263
2779
  id: "content-manager.containers.edit.information.last-published.label",
2264
- defaultMessage: "Last published"
2780
+ defaultMessage: "Published"
2265
2781
  }),
2266
2782
  value: formatMessage(
2267
2783
  {
2268
2784
  id: "content-manager.containers.edit.information.last-published.value",
2269
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2785
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2270
2786
  },
2271
2787
  {
2272
2788
  time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2279,12 +2795,12 @@ const Information = ({ activeTab }) => {
2279
2795
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2280
2796
  label: formatMessage({
2281
2797
  id: "content-manager.containers.edit.information.last-draft.label",
2282
- defaultMessage: "Last draft"
2798
+ defaultMessage: "Updated"
2283
2799
  }),
2284
2800
  value: formatMessage(
2285
2801
  {
2286
2802
  id: "content-manager.containers.edit.information.last-draft.value",
2287
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2803
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2288
2804
  },
2289
2805
  {
2290
2806
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2302,12 +2818,12 @@ const Information = ({ activeTab }) => {
2302
2818
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2303
2819
  label: formatMessage({
2304
2820
  id: "content-manager.containers.edit.information.document.label",
2305
- defaultMessage: "Document"
2821
+ defaultMessage: "Created"
2306
2822
  }),
2307
2823
  value: formatMessage(
2308
2824
  {
2309
2825
  id: "content-manager.containers.edit.information.document.value",
2310
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2826
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2311
2827
  },
2312
2828
  {
2313
2829
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2345,25 +2861,77 @@ const Information = ({ activeTab }) => {
2345
2861
  );
2346
2862
  };
2347
2863
  const HeaderActions = ({ actions: actions2 }) => {
2348
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: actions2.map((action) => {
2349
- if ("options" in action) {
2864
+ const [dialogId, setDialogId] = React__namespace.useState(null);
2865
+ const handleClick = (action) => async (e) => {
2866
+ if (!("options" in action)) {
2867
+ const { onClick = () => false, dialog, id } = action;
2868
+ const muteDialog = await onClick(e);
2869
+ if (dialog && !muteDialog) {
2870
+ e.preventDefault();
2871
+ setDialogId(id);
2872
+ }
2873
+ }
2874
+ };
2875
+ const handleClose = () => {
2876
+ setDialogId(null);
2877
+ };
2878
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
2879
+ if (action.options) {
2350
2880
  return /* @__PURE__ */ jsxRuntime.jsx(
2351
2881
  designSystem.SingleSelect,
2352
2882
  {
2353
2883
  size: "S",
2354
- disabled: action.disabled,
2355
- "aria-label": action.label,
2356
2884
  onChange: action.onSelect,
2357
- value: action.value,
2885
+ "aria-label": action.label,
2886
+ ...action,
2358
2887
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
2359
2888
  },
2360
2889
  action.id
2361
2890
  );
2362
2891
  } else {
2363
- return null;
2892
+ if (action.type === "icon") {
2893
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
2894
+ /* @__PURE__ */ jsxRuntime.jsx(
2895
+ designSystem.IconButton,
2896
+ {
2897
+ disabled: action.disabled,
2898
+ label: action.label,
2899
+ size: "S",
2900
+ onClick: handleClick(action),
2901
+ children: action.icon
2902
+ }
2903
+ ),
2904
+ action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
2905
+ HeaderActionDialog,
2906
+ {
2907
+ ...action.dialog,
2908
+ isOpen: dialogId === action.id,
2909
+ onClose: handleClose
2910
+ }
2911
+ ) : null
2912
+ ] }, action.id);
2913
+ }
2364
2914
  }
2365
2915
  }) });
2366
2916
  };
2917
+ const HeaderActionDialog = ({
2918
+ onClose,
2919
+ onCancel,
2920
+ title,
2921
+ content: Content,
2922
+ isOpen
2923
+ }) => {
2924
+ const handleClose = async () => {
2925
+ if (onCancel) {
2926
+ await onCancel();
2927
+ }
2928
+ onClose();
2929
+ };
2930
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2931
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
2932
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
2933
+ ] }) });
2934
+ };
2367
2935
  const ConfigureTheViewAction = ({ collectionType, model }) => {
2368
2936
  const navigate = reactRouterDom.useNavigate();
2369
2937
  const { formatMessage } = reactIntl.useIntl();
@@ -2380,6 +2948,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2380
2948
  };
2381
2949
  };
2382
2950
  ConfigureTheViewAction.type = "configure-the-view";
2951
+ ConfigureTheViewAction.position = "header";
2383
2952
  const EditTheModelAction = ({ model }) => {
2384
2953
  const navigate = reactRouterDom.useNavigate();
2385
2954
  const { formatMessage } = reactIntl.useIntl();
@@ -2396,6 +2965,7 @@ const EditTheModelAction = ({ model }) => {
2396
2965
  };
2397
2966
  };
2398
2967
  EditTheModelAction.type = "edit-the-model";
2968
+ EditTheModelAction.position = "header";
2399
2969
  const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2400
2970
  const navigate = reactRouterDom.useNavigate();
2401
2971
  const { formatMessage } = reactIntl.useIntl();
@@ -2404,12 +2974,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2404
2974
  const { delete: deleteAction } = useDocumentActions();
2405
2975
  const { toggleNotification } = strapiAdmin.useNotification();
2406
2976
  const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
2977
+ const isLocalized = document?.locale != null;
2407
2978
  return {
2408
2979
  disabled: !canDelete || !document,
2409
- label: formatMessage({
2410
- id: "content-manager.actions.delete.label",
2411
- defaultMessage: "Delete document"
2412
- }),
2980
+ label: formatMessage(
2981
+ {
2982
+ id: "content-manager.actions.delete.label",
2983
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2984
+ },
2985
+ { isLocalized }
2986
+ ),
2413
2987
  icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2414
2988
  dialog: {
2415
2989
  type: "dialog",
@@ -2451,417 +3025,116 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2451
3025
  }
2452
3026
  });
2453
3027
  if (!("error" in res)) {
2454
- navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
2455
- }
2456
- } finally {
2457
- if (!listViewPathMatch) {
2458
- setSubmitting(false);
2459
- }
2460
- }
2461
- }
2462
- },
2463
- variant: "danger",
2464
- position: ["header", "table-row"]
2465
- };
2466
- };
2467
- DeleteAction$1.type = "delete";
2468
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2469
- const Panels = () => {
2470
- const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2471
- const [
2472
- {
2473
- query: { status }
2474
- }
2475
- ] = strapiAdmin.useQueryParams({
2476
- status: "draft"
2477
- });
2478
- const { model, id, document, meta, collectionType } = useDoc();
2479
- const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
2480
- const props = {
2481
- activeTab: status,
2482
- model,
2483
- documentId: id,
2484
- document: isCloning ? void 0 : document,
2485
- meta: isCloning ? void 0 : meta,
2486
- collectionType
2487
- };
2488
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
2489
- strapiAdmin.DescriptionComponentRenderer,
2490
- {
2491
- props,
2492
- descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2493
- children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
2494
- }
2495
- ) });
2496
- };
2497
- const ActionsPanel = () => {
2498
- const { formatMessage } = reactIntl.useIntl();
2499
- return {
2500
- title: formatMessage({
2501
- id: "content-manager.containers.edit.panels.default.title",
2502
- defaultMessage: "Document"
2503
- }),
2504
- content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2505
- };
2506
- };
2507
- ActionsPanel.type = "actions";
2508
- const ActionsPanelContent = () => {
2509
- const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2510
- const [
2511
- {
2512
- query: { status = "draft" }
2513
- }
2514
- ] = strapiAdmin.useQueryParams();
2515
- const { model, id, document, meta, collectionType } = useDoc();
2516
- const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
2517
- const props = {
2518
- activeTab: status,
2519
- model,
2520
- documentId: id,
2521
- document: isCloning ? void 0 : document,
2522
- meta: isCloning ? void 0 : meta,
2523
- collectionType
2524
- };
2525
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
2526
- /* @__PURE__ */ jsxRuntime.jsx(
2527
- strapiAdmin.DescriptionComponentRenderer,
2528
- {
2529
- props,
2530
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2531
- children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
2532
- }
2533
- ),
2534
- /* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
2535
- ] });
2536
- };
2537
- const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2538
- return /* @__PURE__ */ jsxRuntime.jsxs(
2539
- designSystem.Flex,
2540
- {
2541
- ref,
2542
- tag: "aside",
2543
- "aria-labelledby": "additional-information",
2544
- background: "neutral0",
2545
- borderColor: "neutral150",
2546
- hasRadius: true,
2547
- paddingBottom: 4,
2548
- paddingLeft: 4,
2549
- paddingRight: 4,
2550
- paddingTop: 4,
2551
- shadow: "tableShadow",
2552
- gap: 3,
2553
- direction: "column",
2554
- justifyContent: "stretch",
2555
- alignItems: "flex-start",
2556
- children: [
2557
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2558
- children
2559
- ]
2560
- }
2561
- );
2562
- });
2563
- const HOOKS = {
2564
- /**
2565
- * Hook that allows to mutate the displayed headers of the list view table
2566
- * @constant
2567
- * @type {string}
2568
- */
2569
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2570
- /**
2571
- * Hook that allows to mutate the CM's collection types links pre-set filters
2572
- * @constant
2573
- * @type {string}
2574
- */
2575
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2576
- /**
2577
- * Hook that allows to mutate the CM's edit view layout
2578
- * @constant
2579
- * @type {string}
2580
- */
2581
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2582
- /**
2583
- * Hook that allows to mutate the CM's single types links pre-set filters
2584
- * @constant
2585
- * @type {string}
2586
- */
2587
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2588
- };
2589
- const contentTypesApi = contentManagerApi.injectEndpoints({
2590
- endpoints: (builder) => ({
2591
- getContentTypeConfiguration: builder.query({
2592
- query: (uid) => ({
2593
- url: `/content-manager/content-types/${uid}/configuration`,
2594
- method: "GET"
2595
- }),
2596
- transformResponse: (response) => response.data,
2597
- providesTags: (_result, _error, uid) => [
2598
- { type: "ContentTypesConfiguration", id: uid },
2599
- { type: "ContentTypeSettings", id: "LIST" }
2600
- ]
2601
- }),
2602
- getAllContentTypeSettings: builder.query({
2603
- query: () => "/content-manager/content-types-settings",
2604
- transformResponse: (response) => response.data,
2605
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2606
- }),
2607
- updateContentTypeConfiguration: builder.mutation({
2608
- query: ({ uid, ...body }) => ({
2609
- url: `/content-manager/content-types/${uid}/configuration`,
2610
- method: "PUT",
2611
- data: body
2612
- }),
2613
- transformResponse: (response) => response.data,
2614
- invalidatesTags: (_result, _error, { uid }) => [
2615
- { type: "ContentTypesConfiguration", id: uid },
2616
- { type: "ContentTypeSettings", id: "LIST" },
2617
- // Is this necessary?
2618
- { type: "InitialData" }
2619
- ]
2620
- })
2621
- })
2622
- });
2623
- const {
2624
- useGetContentTypeConfigurationQuery,
2625
- useGetAllContentTypeSettingsQuery,
2626
- useUpdateContentTypeConfigurationMutation
2627
- } = contentTypesApi;
2628
- const checkIfAttributeIsDisplayable = (attribute) => {
2629
- const { type } = attribute;
2630
- if (type === "relation") {
2631
- return !attribute.relation.toLowerCase().includes("morph");
2632
- }
2633
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2634
- };
2635
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2636
- if (!mainFieldName) {
2637
- return void 0;
2638
- }
2639
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2640
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2641
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2642
- );
2643
- return {
2644
- name: mainFieldName,
2645
- type: mainFieldType ?? "string"
2646
- };
2647
- };
2648
- const DEFAULT_SETTINGS = {
2649
- bulkable: false,
2650
- filterable: false,
2651
- searchable: false,
2652
- pagination: false,
2653
- defaultSortBy: "",
2654
- defaultSortOrder: "asc",
2655
- mainField: "id",
2656
- pageSize: 10
2657
- };
2658
- const useDocumentLayout = (model) => {
2659
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2660
- const [{ query }] = strapiAdmin.useQueryParams();
2661
- const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2662
- const { toggleNotification } = strapiAdmin.useNotification();
2663
- const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2664
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2665
- const {
2666
- data,
2667
- isLoading: isLoadingConfigs,
2668
- error,
2669
- isFetching: isFetchingConfigs
2670
- } = useGetContentTypeConfigurationQuery(model);
2671
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2672
- React__namespace.useEffect(() => {
2673
- if (error) {
2674
- toggleNotification({
2675
- type: "danger",
2676
- message: formatAPIError(error)
2677
- });
2678
- }
2679
- }, [error, formatAPIError, toggleNotification]);
2680
- const editLayout = React__namespace.useMemo(
2681
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2682
- layout: [],
2683
- components: {},
2684
- metadatas: {},
2685
- options: {},
2686
- settings: DEFAULT_SETTINGS
2687
- },
2688
- [data, isLoading, schemas, schema, components]
2689
- );
2690
- const listLayout = React__namespace.useMemo(() => {
2691
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2692
- layout: [],
2693
- metadatas: {},
2694
- options: {},
2695
- settings: DEFAULT_SETTINGS
2696
- };
2697
- }, [data, isLoading, schemas, schema, components]);
2698
- const { layout: edit } = React__namespace.useMemo(
2699
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2700
- layout: editLayout,
2701
- query
2702
- }),
2703
- [editLayout, query, runHookWaterfall]
2704
- );
2705
- return {
2706
- error,
2707
- isLoading,
2708
- edit,
2709
- list: listLayout
2710
- };
2711
- };
2712
- const useDocLayout = () => {
2713
- const { model } = useDoc();
2714
- return useDocumentLayout(model);
2715
- };
2716
- const formatEditLayout = (data, {
2717
- schemas,
2718
- schema,
2719
- components
2720
- }) => {
2721
- let currentPanelIndex = 0;
2722
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2723
- data.contentType.layouts.edit,
2724
- schema?.attributes,
2725
- data.contentType.metadatas,
2726
- { configurations: data.components, schemas: components },
2727
- schemas
2728
- ).reduce((panels, row) => {
2729
- if (row.some((field) => field.type === "dynamiczone")) {
2730
- panels.push([row]);
2731
- currentPanelIndex += 2;
2732
- } else {
2733
- if (!panels[currentPanelIndex]) {
2734
- panels.push([]);
2735
- }
2736
- panels[currentPanelIndex].push(row);
2737
- }
2738
- return panels;
2739
- }, []);
2740
- const componentEditAttributes = Object.entries(data.components).reduce(
2741
- (acc, [uid, configuration]) => {
2742
- acc[uid] = {
2743
- layout: convertEditLayoutToFieldLayouts(
2744
- configuration.layouts.edit,
2745
- components[uid].attributes,
2746
- configuration.metadatas
2747
- ),
2748
- settings: {
2749
- ...configuration.settings,
2750
- icon: components[uid].info.icon,
2751
- displayName: components[uid].info.displayName
3028
+ navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
3029
+ }
3030
+ } finally {
3031
+ if (!listViewPathMatch) {
3032
+ setSubmitting(false);
3033
+ }
2752
3034
  }
2753
- };
2754
- return acc;
2755
- },
2756
- {}
2757
- );
2758
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2759
- (acc, [attribute, metadata]) => {
2760
- return {
2761
- ...acc,
2762
- [attribute]: metadata.edit
2763
- };
2764
- },
2765
- {}
2766
- );
2767
- return {
2768
- layout: panelledEditAttributes,
2769
- components: componentEditAttributes,
2770
- metadatas: editMetadatas,
2771
- settings: {
2772
- ...data.contentType.settings,
2773
- displayName: schema?.info.displayName
3035
+ }
2774
3036
  },
2775
- options: {
2776
- ...schema?.options,
2777
- ...schema?.pluginOptions,
2778
- ...data.contentType.options
2779
- }
3037
+ variant: "danger",
3038
+ position: ["header", "table-row"]
2780
3039
  };
2781
3040
  };
2782
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2783
- return rows.map(
2784
- (row) => row.map((field) => {
2785
- const attribute = attributes[field.name];
2786
- if (!attribute) {
2787
- return null;
2788
- }
2789
- const { edit: metadata } = metadatas[field.name];
2790
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2791
- return {
2792
- attribute,
2793
- disabled: !metadata.editable,
2794
- hint: metadata.description,
2795
- label: metadata.label ?? "",
2796
- name: field.name,
2797
- // @ts-expect-error – mainField does exist on the metadata for a relation.
2798
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2799
- schemas,
2800
- components: components?.schemas ?? {}
2801
- }),
2802
- placeholder: metadata.placeholder ?? "",
2803
- required: attribute.required ?? false,
2804
- size: field.size,
2805
- unique: "unique" in attribute ? attribute.unique : false,
2806
- visible: metadata.visible ?? true,
2807
- type: attribute.type
2808
- };
2809
- }).filter((field) => field !== null)
2810
- );
3041
+ DeleteAction$1.type = "delete";
3042
+ DeleteAction$1.position = ["header", "table-row"];
3043
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
3044
+ const Panels = () => {
3045
+ const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
3046
+ const [
3047
+ {
3048
+ query: { status }
3049
+ }
3050
+ ] = strapiAdmin.useQueryParams({
3051
+ status: "draft"
3052
+ });
3053
+ const { model, id, document, meta, collectionType } = useDoc();
3054
+ const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
3055
+ const props = {
3056
+ activeTab: status,
3057
+ model,
3058
+ documentId: id,
3059
+ document: isCloning ? void 0 : document,
3060
+ meta: isCloning ? void 0 : meta,
3061
+ collectionType
3062
+ };
3063
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
3064
+ strapiAdmin.DescriptionComponentRenderer,
3065
+ {
3066
+ props,
3067
+ descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
3068
+ children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
3069
+ }
3070
+ ) });
2811
3071
  };
2812
- const formatListLayout = (data, {
2813
- schemas,
2814
- schema,
2815
- components
2816
- }) => {
2817
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2818
- (acc, [attribute, metadata]) => {
2819
- return {
2820
- ...acc,
2821
- [attribute]: metadata.list
2822
- };
2823
- },
2824
- {}
2825
- );
2826
- const listAttributes = convertListLayoutToFieldLayouts(
2827
- data.contentType.layouts.list,
2828
- schema?.attributes,
2829
- listMetadatas,
2830
- { configurations: data.components, schemas: components },
2831
- schemas
2832
- );
3072
+ const ActionsPanel = () => {
3073
+ const { formatMessage } = reactIntl.useIntl();
2833
3074
  return {
2834
- layout: listAttributes,
2835
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2836
- metadatas: listMetadatas,
2837
- options: {
2838
- ...schema?.options,
2839
- ...schema?.pluginOptions,
2840
- ...data.contentType.options
2841
- }
3075
+ title: formatMessage({
3076
+ id: "content-manager.containers.edit.panels.default.title",
3077
+ defaultMessage: "Entry"
3078
+ }),
3079
+ content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2842
3080
  };
2843
3081
  };
2844
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2845
- return columns.map((name) => {
2846
- const attribute = attributes[name];
2847
- if (!attribute) {
2848
- return null;
3082
+ ActionsPanel.type = "actions";
3083
+ const ActionsPanelContent = () => {
3084
+ const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
3085
+ const [
3086
+ {
3087
+ query: { status = "draft" }
2849
3088
  }
2850
- const metadata = metadatas[name];
2851
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2852
- return {
2853
- attribute,
2854
- label: metadata.label ?? "",
2855
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2856
- schemas,
2857
- components: components?.schemas ?? {}
2858
- }),
2859
- name,
2860
- searchable: metadata.searchable ?? true,
2861
- sortable: metadata.sortable ?? true
2862
- };
2863
- }).filter((field) => field !== null);
3089
+ ] = strapiAdmin.useQueryParams();
3090
+ const { model, id, document, meta, collectionType } = useDoc();
3091
+ const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
3092
+ const props = {
3093
+ activeTab: status,
3094
+ model,
3095
+ documentId: id,
3096
+ document: isCloning ? void 0 : document,
3097
+ meta: isCloning ? void 0 : meta,
3098
+ collectionType
3099
+ };
3100
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
3101
+ /* @__PURE__ */ jsxRuntime.jsx(
3102
+ strapiAdmin.DescriptionComponentRenderer,
3103
+ {
3104
+ props,
3105
+ descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
3106
+ children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
3107
+ }
3108
+ ),
3109
+ /* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
3110
+ ] });
2864
3111
  };
3112
+ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
3113
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3114
+ designSystem.Flex,
3115
+ {
3116
+ ref,
3117
+ tag: "aside",
3118
+ "aria-labelledby": "additional-information",
3119
+ background: "neutral0",
3120
+ borderColor: "neutral150",
3121
+ hasRadius: true,
3122
+ paddingBottom: 4,
3123
+ paddingLeft: 4,
3124
+ paddingRight: 4,
3125
+ paddingTop: 4,
3126
+ shadow: "tableShadow",
3127
+ gap: 3,
3128
+ direction: "column",
3129
+ justifyContent: "stretch",
3130
+ alignItems: "flex-start",
3131
+ children: [
3132
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
3133
+ children
3134
+ ]
3135
+ }
3136
+ );
3137
+ });
2865
3138
  const ConfirmBulkActionDialog = ({
2866
3139
  onToggleDialog,
2867
3140
  isOpen = false,
@@ -2900,6 +3173,7 @@ const ConfirmDialogPublishAll = ({
2900
3173
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2901
3174
  const { model, schema } = useDoc();
2902
3175
  const [{ query }] = strapiAdmin.useQueryParams();
3176
+ const enableDraftRelationsCount = false;
2903
3177
  const {
2904
3178
  data: countDraftRelations = 0,
2905
3179
  isLoading,
@@ -2911,7 +3185,7 @@ const ConfirmDialogPublishAll = ({
2911
3185
  locale: query?.plugins?.i18n?.locale
2912
3186
  },
2913
3187
  {
2914
- skip: selectedEntries.length === 0
3188
+ skip: !enableDraftRelationsCount
2915
3189
  }
2916
3190
  );
2917
3191
  React__namespace.useEffect(() => {
@@ -3096,7 +3370,7 @@ const SelectedEntriesTableContent = ({
3096
3370
  status: row.status
3097
3371
  }
3098
3372
  ) }),
3099
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3373
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
3100
3374
  designSystem.IconButton,
3101
3375
  {
3102
3376
  tag: reactRouterDom.Link,
@@ -3105,23 +3379,16 @@ const SelectedEntriesTableContent = ({
3105
3379
  search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3106
3380
  },
3107
3381
  state: { from: pathname },
3108
- label: formatMessage(
3109
- { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3110
- {
3111
- target: formatMessage(
3112
- {
3113
- id: "content-manager.components.ListViewHelperPluginTable.row-line",
3114
- defaultMessage: "item line {number}"
3115
- },
3116
- { number: index2 + 1 }
3117
- )
3118
- }
3119
- ),
3382
+ label: formatMessage({
3383
+ id: "content-manager.bulk-publish.edit",
3384
+ defaultMessage: "Edit"
3385
+ }),
3120
3386
  target: "_blank",
3121
3387
  marginLeft: "auto",
3122
- children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3388
+ variant: "ghost",
3389
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
3123
3390
  }
3124
- ) })
3391
+ ) }) })
3125
3392
  ] }, row.id)) })
3126
3393
  ] });
3127
3394
  };
@@ -3158,7 +3425,13 @@ const SelectedEntriesModalContent = ({
3158
3425
  );
3159
3426
  const { rows, validationErrors } = React__namespace.useMemo(() => {
3160
3427
  if (data.length > 0 && schema) {
3161
- const validate = createYupSchema(schema.attributes, components);
3428
+ const validate = createYupSchema(
3429
+ schema.attributes,
3430
+ components,
3431
+ // Since this is the "Publish" action, the validation
3432
+ // schema must enforce the rules for published entities
3433
+ { status: "published" }
3434
+ );
3162
3435
  const validationErrors2 = {};
3163
3436
  const rows2 = data.map((entry) => {
3164
3437
  try {
@@ -3283,8 +3556,7 @@ const PublishAction = ({ documents, model }) => {
3283
3556
  const refetchList = () => {
3284
3557
  contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3285
3558
  };
3286
- if (!showPublishButton)
3287
- return null;
3559
+ if (!showPublishButton) return null;
3288
3560
  return {
3289
3561
  actionType: "publish",
3290
3562
  variant: "tertiary",
@@ -3352,8 +3624,7 @@ const DeleteAction = ({ documents, model }) => {
3352
3624
  selectRow([]);
3353
3625
  }
3354
3626
  };
3355
- if (!hasDeletePermission)
3356
- return null;
3627
+ if (!hasDeletePermission) return null;
3357
3628
  return {
3358
3629
  variant: "danger-light",
3359
3630
  label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
@@ -3402,8 +3673,7 @@ const UnpublishAction = ({ documents, model }) => {
3402
3673
  }
3403
3674
  };
3404
3675
  const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3405
- if (!showUnpublishButton)
3406
- return null;
3676
+ if (!showUnpublishButton) return null;
3407
3677
  return {
3408
3678
  variant: "tertiary",
3409
3679
  label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
@@ -3508,7 +3778,7 @@ const TableActions = ({ document }) => {
3508
3778
  strapiAdmin.DescriptionComponentRenderer,
3509
3779
  {
3510
3780
  props,
3511
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3781
+ descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
3512
3782
  children: (actions2) => {
3513
3783
  const tableRowActions = actions2.filter((action) => {
3514
3784
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3567,6 +3837,7 @@ const EditAction = ({ documentId }) => {
3567
3837
  };
3568
3838
  };
3569
3839
  EditAction.type = "edit";
3840
+ EditAction.position = "table-row";
3570
3841
  const StyledPencil = styledComponents.styled(Icons.Pencil)`
3571
3842
  path {
3572
3843
  fill: currentColor;
@@ -3619,7 +3890,7 @@ const CloneAction = ({ model, documentId }) => {
3619
3890
  }),
3620
3891
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3621
3892
  footer: ({ onClose }) => {
3622
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3893
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3623
3894
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3624
3895
  id: "cancel",
3625
3896
  defaultMessage: "Cancel"
@@ -3643,6 +3914,7 @@ const CloneAction = ({ model, documentId }) => {
3643
3914
  };
3644
3915
  };
3645
3916
  CloneAction.type = "clone";
3917
+ CloneAction.position = "table-row";
3646
3918
  const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
3647
3919
  path {
3648
3920
  fill: currentColor;
@@ -3729,7 +4001,14 @@ class ContentManagerPlugin {
3729
4001
  addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3730
4002
  addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3731
4003
  getBulkActions: () => this.bulkActions,
3732
- getDocumentActions: () => this.documentActions,
4004
+ getDocumentActions: (position) => {
4005
+ if (position) {
4006
+ return this.documentActions.filter(
4007
+ (action) => action.position == void 0 || [action.position].flat().includes(position)
4008
+ );
4009
+ }
4010
+ return this.documentActions;
4011
+ },
3733
4012
  getEditViewSidePanels: () => this.editViewSidePanels,
3734
4013
  getHeaderActions: () => this.headerActions
3735
4014
  }
@@ -3739,10 +4018,8 @@ class ContentManagerPlugin {
3739
4018
  const getPrintableType = (value) => {
3740
4019
  const nativeType = typeof value;
3741
4020
  if (nativeType === "object") {
3742
- if (value === null)
3743
- return "null";
3744
- if (Array.isArray(value))
3745
- return "array";
4021
+ if (value === null) return "null";
4022
+ if (Array.isArray(value)) return "array";
3746
4023
  if (value instanceof Object && value.constructor.name !== "Object") {
3747
4024
  return value.constructor.name;
3748
4025
  }
@@ -3753,17 +4030,27 @@ const HistoryAction = ({ model, document }) => {
3753
4030
  const { formatMessage } = reactIntl.useIntl();
3754
4031
  const [{ query }] = strapiAdmin.useQueryParams();
3755
4032
  const navigate = reactRouterDom.useNavigate();
4033
+ const { trackUsage } = strapiAdmin.useTracking();
4034
+ const { pathname } = reactRouterDom.useLocation();
3756
4035
  const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3757
4036
  if (!window.strapi.features.isEnabled("cms-content-history")) {
3758
4037
  return null;
3759
4038
  }
4039
+ const handleOnClick = () => {
4040
+ const destination = { pathname: "history", search: pluginsQueryParams };
4041
+ trackUsage("willNavigate", {
4042
+ from: pathname,
4043
+ to: `${pathname}/${destination.pathname}`
4044
+ });
4045
+ navigate(destination);
4046
+ };
3760
4047
  return {
3761
4048
  icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3762
4049
  label: formatMessage({
3763
4050
  id: "content-manager.history.document-action",
3764
4051
  defaultMessage: "Content History"
3765
4052
  }),
3766
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
4053
+ onClick: handleOnClick,
3767
4054
  disabled: (
3768
4055
  /**
3769
4056
  * The user is creating a new document.
@@ -3785,6 +4072,7 @@ const HistoryAction = ({ model, document }) => {
3785
4072
  };
3786
4073
  };
3787
4074
  HistoryAction.type = "history";
4075
+ HistoryAction.position = "header";
3788
4076
  const historyAdmin = {
3789
4077
  bootstrap(app) {
3790
4078
  const { addDocumentAction } = app.getPlugin("content-manager").apis;
@@ -3831,6 +4119,88 @@ const { setInitialData } = actions;
3831
4119
  const reducer = toolkit.combineReducers({
3832
4120
  app: reducer$1
3833
4121
  });
4122
+ const previewApi = contentManagerApi.injectEndpoints({
4123
+ endpoints: (builder) => ({
4124
+ getPreviewUrl: builder.query({
4125
+ query({ query, params }) {
4126
+ return {
4127
+ url: `/content-manager/preview/url/${params.contentType}`,
4128
+ method: "GET",
4129
+ config: {
4130
+ params: query
4131
+ }
4132
+ };
4133
+ }
4134
+ })
4135
+ })
4136
+ });
4137
+ const { useGetPreviewUrlQuery } = previewApi;
4138
+ const ConditionalTooltip = ({ isShown, label, children }) => {
4139
+ if (isShown) {
4140
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { label, children });
4141
+ }
4142
+ return children;
4143
+ };
4144
+ const PreviewSidePanel = ({ model, documentId, document }) => {
4145
+ const { formatMessage } = reactIntl.useIntl();
4146
+ const { trackUsage } = strapiAdmin.useTracking();
4147
+ const { pathname } = reactRouterDom.useLocation();
4148
+ const [{ query }] = strapiAdmin.useQueryParams();
4149
+ const isModified = strapiAdmin.useForm("PreviewSidePanel", (state) => state.modified);
4150
+ const { data, error } = useGetPreviewUrlQuery({
4151
+ params: {
4152
+ contentType: model
4153
+ },
4154
+ query: {
4155
+ documentId,
4156
+ locale: document?.locale,
4157
+ status: document?.status
4158
+ }
4159
+ });
4160
+ if (!data?.data?.url || error) {
4161
+ return null;
4162
+ }
4163
+ const trackNavigation = () => {
4164
+ const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
4165
+ trackUsage("willNavigate", { from: pathname, to: destinationPathname });
4166
+ };
4167
+ return {
4168
+ title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
4169
+ content: /* @__PURE__ */ jsxRuntime.jsx(
4170
+ ConditionalTooltip,
4171
+ {
4172
+ label: formatMessage({
4173
+ id: "content-manager.preview.panel.button-disabled-tooltip",
4174
+ defaultMessage: "Please save to open the preview"
4175
+ }),
4176
+ isShown: isModified,
4177
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
4178
+ designSystem.Button,
4179
+ {
4180
+ variant: "tertiary",
4181
+ tag: reactRouterDom.Link,
4182
+ to: { pathname: "preview", search: qs.stringify(query, { encode: false }) },
4183
+ onClick: trackNavigation,
4184
+ width: "100%",
4185
+ disabled: isModified,
4186
+ pointerEvents: isModified ? "none" : void 0,
4187
+ tabIndex: isModified ? -1 : void 0,
4188
+ children: formatMessage({
4189
+ id: "content-manager.preview.panel.button",
4190
+ defaultMessage: "Open preview"
4191
+ })
4192
+ }
4193
+ ) })
4194
+ }
4195
+ )
4196
+ };
4197
+ };
4198
+ const previewAdmin = {
4199
+ bootstrap(app) {
4200
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
4201
+ contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
4202
+ }
4203
+ };
3834
4204
  const index = {
3835
4205
  register(app) {
3836
4206
  const cm = new ContentManagerPlugin();
@@ -3850,7 +4220,7 @@ const index = {
3850
4220
  app.router.addRoute({
3851
4221
  path: "content-manager/*",
3852
4222
  lazy: async () => {
3853
- const { Layout } = await Promise.resolve().then(() => require("./layout-TPqF2oJ5.js"));
4223
+ const { Layout } = await Promise.resolve().then(() => require("./layout-CDBEgRsM.js"));
3854
4224
  return {
3855
4225
  Component: Layout
3856
4226
  };
@@ -3863,11 +4233,14 @@ const index = {
3863
4233
  if (typeof historyAdmin.bootstrap === "function") {
3864
4234
  historyAdmin.bootstrap(app);
3865
4235
  }
4236
+ if (typeof previewAdmin.bootstrap === "function") {
4237
+ previewAdmin.bootstrap(app);
4238
+ }
3866
4239
  },
3867
4240
  async registerTrads({ locales }) {
3868
4241
  const importedTrads = await Promise.all(
3869
4242
  locales.map((locale) => {
3870
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-uOUIxfcQ.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
4243
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-BzQmavmK.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-9K52xZIr.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B2Kyv8Z9.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-7sfIbjxE.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
3871
4244
  return {
3872
4245
  data: prefixPluginTranslations(data, PLUGIN_ID),
3873
4246
  locale
@@ -3885,6 +4258,7 @@ const index = {
3885
4258
  };
3886
4259
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3887
4260
  exports.BulkActionsRenderer = BulkActionsRenderer;
4261
+ exports.CLONE_PATH = CLONE_PATH;
3888
4262
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3889
4263
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3890
4264
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3912,6 +4286,7 @@ exports.getMainField = getMainField;
3912
4286
  exports.getTranslation = getTranslation;
3913
4287
  exports.index = index;
3914
4288
  exports.setInitialData = setInitialData;
4289
+ exports.useContentManagerContext = useContentManagerContext;
3915
4290
  exports.useContentTypeSchema = useContentTypeSchema;
3916
4291
  exports.useDoc = useDoc;
3917
4292
  exports.useDocLayout = useDocLayout;
@@ -3923,5 +4298,6 @@ exports.useGetAllContentTypeSettingsQuery = useGetAllContentTypeSettingsQuery;
3923
4298
  exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3924
4299
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3925
4300
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
4301
+ exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
3926
4302
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3927
- //# sourceMappingURL=index-DyvUPg1a.js.map
4303
+ //# sourceMappingURL=index-Ct-GZ0iV.js.map