@strapi/content-manager 0.0.0-experimental.9df68962083938acba06546a7901c68a63266aec → 0.0.0-experimental.9f812af47f0e9db3d5531382c836c2ac0776afdf

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 (220) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
  3. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-BSEZcJVB.js} +5 -6
  5. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-BSEZcJVB.js.map} +1 -1
  6. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs → ComponentConfigurationPage-BiASGi7x.mjs} +4 -4
  7. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-BiASGi7x.mjs.map} +1 -1
  8. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
  9. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
  10. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
  11. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-D2rtvneE.js} +5 -6
  12. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-D2rtvneE.js.map} +1 -1
  13. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs → EditConfigurationPage-vN4zupij.mjs} +4 -4
  14. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-vN4zupij.mjs.map} +1 -1
  15. package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-BwisF04Q.js} +63 -13
  16. package/dist/_chunks/EditViewPage-BwisF04Q.js.map +1 -0
  17. package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-_A31Cl4g.mjs} +63 -12
  18. package/dist/_chunks/EditViewPage-_A31Cl4g.mjs.map +1 -0
  19. package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-CvIunNOj.mjs} +405 -256
  20. package/dist/_chunks/Field-CvIunNOj.mjs.map +1 -0
  21. package/dist/_chunks/{Field-Boxf9Ajp.js → Field-Dsu6-FrM.js} +409 -260
  22. package/dist/_chunks/Field-Dsu6-FrM.js.map +1 -0
  23. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
  24. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
  25. package/dist/_chunks/{Form-DHrru2AV.mjs → Form-DK0fG0Gj.mjs} +37 -18
  26. package/dist/_chunks/Form-DK0fG0Gj.mjs.map +1 -0
  27. package/dist/_chunks/{Form-y5g1SRsh.js → Form-DUwWcCmA.js} +39 -21
  28. package/dist/_chunks/Form-DUwWcCmA.js.map +1 -0
  29. package/dist/_chunks/{History-CqN6K7SX.js → History-CeCDhoJG.js} +81 -114
  30. package/dist/_chunks/History-CeCDhoJG.js.map +1 -0
  31. package/dist/_chunks/{History-Bru_KoeP.mjs → History-DP8gmXpm.mjs} +82 -114
  32. package/dist/_chunks/History-DP8gmXpm.mjs.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-BCkO5iuN.mjs} +25 -12
  34. package/dist/_chunks/ListConfigurationPage-BCkO5iuN.mjs.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-C-bAd44a.js} +25 -13
  36. package/dist/_chunks/ListConfigurationPage-C-bAd44a.js.map +1 -0
  37. package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-BKTZFhsM.js} +121 -81
  38. package/dist/_chunks/ListViewPage-BKTZFhsM.js.map +1 -0
  39. package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-Cf_DgaFV.mjs} +118 -77
  40. package/dist/_chunks/ListViewPage-Cf_DgaFV.mjs.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-D3Cm3v3q.js} +2 -2
  42. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-D3Cm3v3q.js.map} +1 -1
  43. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-nHIyvJcB.mjs} +2 -2
  44. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-nHIyvJcB.mjs.map} +1 -1
  45. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-BALVSJ7x.mjs} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-BALVSJ7x.mjs.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-CChGWBj5.js} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-CChGWBj5.js.map} +1 -1
  49. package/dist/_chunks/Preview-C4NBzKUV.mjs +294 -0
  50. package/dist/_chunks/Preview-C4NBzKUV.mjs.map +1 -0
  51. package/dist/_chunks/Preview-CT28Ckpg.js +312 -0
  52. package/dist/_chunks/Preview-CT28Ckpg.js.map +1 -0
  53. package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-C8uC89cT.mjs} +76 -42
  54. package/dist/_chunks/Relations-C8uC89cT.mjs.map +1 -0
  55. package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-CvkPCng_.js} +76 -43
  56. package/dist/_chunks/Relations-CvkPCng_.js.map +1 -0
  57. package/dist/_chunks/{en-fbKQxLGn.js → en-BK8Xyl5I.js} +32 -18
  58. package/dist/_chunks/{en-fbKQxLGn.js.map → en-BK8Xyl5I.js.map} +1 -1
  59. package/dist/_chunks/{en-Ux26r5pl.mjs → en-Dtk_ot79.mjs} +32 -18
  60. package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-Dtk_ot79.mjs.map} +1 -1
  61. package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
  62. package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
  63. package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
  64. package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
  65. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
  66. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
  67. package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
  68. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
  69. package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
  70. package/dist/_chunks/{index-DVPWZkbS.js → index-CnX_j5h-.js} +1235 -746
  71. package/dist/_chunks/index-CnX_j5h-.js.map +1 -0
  72. package/dist/_chunks/{index-DJXJw9V5.mjs → index-Dh2aGTGJ.mjs} +1252 -763
  73. package/dist/_chunks/index-Dh2aGTGJ.mjs.map +1 -0
  74. package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
  75. package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
  76. package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
  77. package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
  78. package/dist/_chunks/{layout-Bau7ZfLV.mjs → layout-B5qsPihj.mjs} +26 -13
  79. package/dist/_chunks/layout-B5qsPihj.mjs.map +1 -0
  80. package/dist/_chunks/{layout-Dm6fbiQj.js → layout-B_qdWGny.js} +26 -14
  81. package/dist/_chunks/layout-B_qdWGny.js.map +1 -0
  82. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  83. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  84. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  85. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  86. package/dist/_chunks/{relations-CKnpRgrN.js → relations-ChcieiF5.js} +6 -7
  87. package/dist/_chunks/relations-ChcieiF5.js.map +1 -0
  88. package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-DMXpNY-e.mjs} +6 -7
  89. package/dist/_chunks/relations-DMXpNY-e.mjs.map +1 -0
  90. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  91. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  92. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  93. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  94. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
  95. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
  96. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
  97. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
  98. package/dist/admin/index.js +2 -1
  99. package/dist/admin/index.js.map +1 -1
  100. package/dist/admin/index.mjs +5 -4
  101. package/dist/admin/src/content-manager.d.ts +3 -2
  102. package/dist/admin/src/exports.d.ts +1 -1
  103. package/dist/admin/src/history/index.d.ts +3 -0
  104. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  105. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  106. package/dist/admin/src/index.d.ts +1 -0
  107. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  108. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +2 -1
  109. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
  110. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
  111. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
  112. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
  113. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  114. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  115. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  116. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  117. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  118. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  119. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  120. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  121. package/dist/admin/src/preview/index.d.ts +4 -0
  122. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  123. package/dist/admin/src/preview/routes.d.ts +3 -0
  124. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  125. package/dist/admin/src/router.d.ts +1 -1
  126. package/dist/admin/src/services/api.d.ts +1 -1
  127. package/dist/admin/src/services/components.d.ts +2 -2
  128. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  129. package/dist/admin/src/services/documents.d.ts +19 -20
  130. package/dist/admin/src/services/init.d.ts +1 -1
  131. package/dist/admin/src/services/relations.d.ts +2 -2
  132. package/dist/admin/src/services/uid.d.ts +3 -3
  133. package/dist/admin/src/utils/validation.d.ts +4 -1
  134. package/dist/server/index.js +686 -360
  135. package/dist/server/index.js.map +1 -1
  136. package/dist/server/index.mjs +687 -360
  137. package/dist/server/index.mjs.map +1 -1
  138. package/dist/server/src/bootstrap.d.ts.map +1 -1
  139. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  140. package/dist/server/src/controllers/index.d.ts.map +1 -1
  141. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  142. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  143. package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
  144. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  145. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  146. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  147. package/dist/server/src/history/services/history.d.ts.map +1 -1
  148. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  149. package/dist/server/src/history/services/utils.d.ts +4 -4
  150. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  151. package/dist/server/src/index.d.ts +7 -6
  152. package/dist/server/src/index.d.ts.map +1 -1
  153. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  154. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  155. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  156. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  157. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  158. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  159. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  160. package/dist/server/src/preview/index.d.ts +4 -0
  161. package/dist/server/src/preview/index.d.ts.map +1 -0
  162. package/dist/server/src/preview/routes/index.d.ts +8 -0
  163. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  164. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  165. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  166. package/dist/server/src/preview/services/index.d.ts +16 -0
  167. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  168. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  169. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  170. package/dist/server/src/preview/services/preview.d.ts +12 -0
  171. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  172. package/dist/server/src/preview/utils.d.ts +19 -0
  173. package/dist/server/src/preview/utils.d.ts.map +1 -0
  174. package/dist/server/src/register.d.ts.map +1 -1
  175. package/dist/server/src/routes/index.d.ts.map +1 -1
  176. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  177. package/dist/server/src/services/document-metadata.d.ts +12 -10
  178. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  179. package/dist/server/src/services/index.d.ts +7 -6
  180. package/dist/server/src/services/index.d.ts.map +1 -1
  181. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  182. package/dist/server/src/services/utils/populate.d.ts +2 -2
  183. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  184. package/dist/server/src/utils/index.d.ts +2 -0
  185. package/dist/server/src/utils/index.d.ts.map +1 -1
  186. package/dist/shared/contracts/collection-types.d.ts +3 -1
  187. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  188. package/dist/shared/contracts/index.d.ts +1 -0
  189. package/dist/shared/contracts/index.d.ts.map +1 -1
  190. package/dist/shared/contracts/preview.d.ts +27 -0
  191. package/dist/shared/contracts/preview.d.ts.map +1 -0
  192. package/dist/shared/index.js +4 -0
  193. package/dist/shared/index.js.map +1 -1
  194. package/dist/shared/index.mjs +4 -0
  195. package/dist/shared/index.mjs.map +1 -1
  196. package/package.json +17 -15
  197. package/dist/_chunks/EditViewPage-CPj61RMh.mjs.map +0 -1
  198. package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
  199. package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
  200. package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
  201. package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
  202. package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
  203. package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
  204. package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
  205. package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
  206. package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
  207. package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
  208. package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
  209. package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
  210. package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
  211. package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
  212. package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
  213. package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
  214. package/dist/_chunks/layout-Dm6fbiQj.js.map +0 -1
  215. package/dist/_chunks/relations-BH_kBSJ0.mjs.map +0 -1
  216. package/dist/_chunks/relations-CKnpRgrN.js.map +0 -1
  217. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  218. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  219. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  220. package/strapi-server.js +0 -3
@@ -2,20 +2,20 @@
2
2
  const Icons = require("@strapi/icons");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const strapiAdmin = require("@strapi/admin/strapi-admin");
5
- const qs = require("qs");
6
- const reactIntl = require("react-intl");
7
- const reactRouterDom = require("react-router-dom");
8
5
  const React = require("react");
9
6
  const designSystem = require("@strapi/design-system");
7
+ const mapValues = require("lodash/fp/mapValues");
8
+ const reactIntl = require("react-intl");
9
+ const reactRouterDom = require("react-router-dom");
10
10
  const styledComponents = require("styled-components");
11
11
  const yup = require("yup");
12
+ const qs = require("qs");
12
13
  const pipe = require("lodash/fp/pipe");
13
14
  const dateFns = require("date-fns");
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";
@@ -70,42 +78,6 @@ const useInjectionZone = (area) => {
70
78
  const [page, position] = area.split(".");
71
79
  return contentManagerPlugin.getInjectedComponents(page, position);
72
80
  };
73
- const HistoryAction = ({ model, document }) => {
74
- const { formatMessage } = reactIntl.useIntl();
75
- const [{ query }] = strapiAdmin.useQueryParams();
76
- const navigate = reactRouterDom.useNavigate();
77
- const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
78
- if (!window.strapi.features.isEnabled("cms-content-history")) {
79
- return null;
80
- }
81
- return {
82
- icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
83
- label: formatMessage({
84
- id: "content-manager.history.document-action",
85
- defaultMessage: "Content History"
86
- }),
87
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
88
- disabled: (
89
- /**
90
- * The user is creating a new document.
91
- * It hasn't been saved yet, so there's no history to go to
92
- */
93
- !document || /**
94
- * The document has been created but the current dimension has never been saved.
95
- * For example, the user is creating a new locale in an existing document,
96
- * so there's no history for the document in that locale
97
- */
98
- !document.id || /**
99
- * History is only available for content types created by the user.
100
- * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
101
- * which start with `admin::` or `plugin::`
102
- */
103
- !model.startsWith("api::")
104
- ),
105
- position: "header"
106
- };
107
- };
108
- HistoryAction.type = "history";
109
81
  const ID = "id";
110
82
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
111
83
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -157,6 +129,7 @@ const DocumentRBAC = ({ children, permissions }) => {
157
129
  if (!slug) {
158
130
  throw new Error("Cannot find the slug param in the URL");
159
131
  }
132
+ const [{ rawQuery }] = strapiAdmin.useQueryParams();
160
133
  const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
161
134
  const contentTypePermissions = React__namespace.useMemo(() => {
162
135
  const contentTypePermissions2 = userPermissions.filter(
@@ -167,7 +140,14 @@ const DocumentRBAC = ({ children, permissions }) => {
167
140
  return { ...acc, [action]: [permission] };
168
141
  }, {});
169
142
  }, [slug, userPermissions]);
170
- 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
+ );
171
151
  const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
172
152
  const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
173
153
  const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
@@ -215,7 +195,8 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
215
195
  "Document",
216
196
  "InitialData",
217
197
  "HistoryVersion",
218
- "Relations"
198
+ "Relations",
199
+ "UidAvailability"
219
200
  ]
220
201
  });
221
202
  const documentApi = contentManagerApi.injectEndpoints({
@@ -229,7 +210,12 @@ const documentApi = contentManagerApi.injectEndpoints({
229
210
  params: query
230
211
  }
231
212
  }),
232
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
213
+ invalidatesTags: (_result, error, { model }) => {
214
+ if (error) {
215
+ return [];
216
+ }
217
+ return [{ type: "Document", id: `${model}_LIST` }];
218
+ }
233
219
  }),
234
220
  cloneDocument: builder.mutation({
235
221
  query: ({ model, sourceId, data, params }) => ({
@@ -240,7 +226,10 @@ const documentApi = contentManagerApi.injectEndpoints({
240
226
  params
241
227
  }
242
228
  }),
243
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
229
+ invalidatesTags: (_result, _error, { model }) => [
230
+ { type: "Document", id: `${model}_LIST` },
231
+ { type: "UidAvailability", id: model }
232
+ ]
244
233
  }),
245
234
  /**
246
235
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -257,8 +246,21 @@ const documentApi = contentManagerApi.injectEndpoints({
257
246
  }),
258
247
  invalidatesTags: (result, _error, { model }) => [
259
248
  { type: "Document", id: `${model}_LIST` },
260
- "Relations"
261
- ]
249
+ "Relations",
250
+ { type: "UidAvailability", id: model }
251
+ ],
252
+ transformResponse: (response, meta, arg) => {
253
+ if (!("data" in response) && arg.model === "plugin::users-permissions.user") {
254
+ return {
255
+ data: response,
256
+ meta: {
257
+ availableStatus: [],
258
+ availableLocales: []
259
+ }
260
+ };
261
+ }
262
+ return response;
263
+ }
262
264
  }),
263
265
  deleteDocument: builder.mutation({
264
266
  query: ({ collectionType, model, documentId, params }) => ({
@@ -298,7 +300,8 @@ const documentApi = contentManagerApi.injectEndpoints({
298
300
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
299
301
  },
300
302
  { type: "Document", id: `${model}_LIST` },
301
- "Relations"
303
+ "Relations",
304
+ { type: "UidAvailability", id: model }
302
305
  ];
303
306
  }
304
307
  }),
@@ -311,11 +314,12 @@ const documentApi = contentManagerApi.injectEndpoints({
311
314
  url: `/content-manager/collection-types/${model}`,
312
315
  method: "GET",
313
316
  config: {
314
- params
317
+ params: qs.stringify(params, { encode: true })
315
318
  }
316
319
  }),
317
320
  providesTags: (result, _error, arg) => {
318
321
  return [
322
+ { type: "Document", id: `ALL_LIST` },
319
323
  { type: "Document", id: `${arg.model}_LIST` },
320
324
  ...result?.results.map(({ documentId }) => ({
321
325
  type: "Document",
@@ -354,6 +358,11 @@ const documentApi = contentManagerApi.injectEndpoints({
354
358
  {
355
359
  type: "Document",
356
360
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
361
+ },
362
+ // Make it easy to invalidate all individual documents queries for a model
363
+ {
364
+ type: "Document",
365
+ id: `${model}_ALL_ITEMS`
357
366
  }
358
367
  ];
359
368
  }
@@ -417,8 +426,21 @@ const documentApi = contentManagerApi.injectEndpoints({
417
426
  type: "Document",
418
427
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
419
428
  },
420
- "Relations"
429
+ "Relations",
430
+ { type: "UidAvailability", id: model }
421
431
  ];
432
+ },
433
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
434
+ const patchResult = dispatch(
435
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
436
+ Object.assign(draft.data, data);
437
+ })
438
+ );
439
+ try {
440
+ await queryFulfilled;
441
+ } catch {
442
+ patchResult.undo();
443
+ }
422
444
  }
423
445
  }),
424
446
  unpublishDocument: builder.mutation({
@@ -471,8 +493,7 @@ const {
471
493
  useUnpublishManyDocumentsMutation
472
494
  } = documentApi;
473
495
  const buildValidParams = (query) => {
474
- if (!query)
475
- return query;
496
+ if (!query) return query;
476
497
  const { plugins: _, ...validQueryParams } = {
477
498
  ...query,
478
499
  ...Object.values(query?.plugins ?? {}).reduce(
@@ -480,28 +501,44 @@ const buildValidParams = (query) => {
480
501
  {}
481
502
  )
482
503
  };
483
- if ("_q" in validQueryParams) {
484
- validQueryParams._q = encodeURIComponent(validQueryParams._q);
485
- }
486
504
  return validQueryParams;
487
505
  };
488
506
  const isBaseQueryError = (error) => {
489
507
  return error.name !== void 0;
490
508
  };
491
- const createYupSchema = (attributes = {}, components = {}) => {
509
+ const arrayValidator = (attribute, options) => ({
510
+ message: strapiAdmin.translatedErrors.required,
511
+ test(value) {
512
+ if (options.status === "draft") {
513
+ return true;
514
+ }
515
+ if (!attribute.required) {
516
+ return true;
517
+ }
518
+ if (!value) {
519
+ return false;
520
+ }
521
+ if (Array.isArray(value) && value.length === 0) {
522
+ return false;
523
+ }
524
+ return true;
525
+ }
526
+ });
527
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
492
528
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
493
529
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
494
530
  if (DOCUMENT_META_FIELDS.includes(name)) {
495
531
  return acc;
496
532
  }
497
533
  const validations = [
534
+ addNullableValidation,
498
535
  addRequiredValidation,
499
536
  addMinLengthValidation,
500
537
  addMaxLengthValidation,
501
538
  addMinValidation,
502
539
  addMaxValidation,
503
540
  addRegexValidation
504
- ].map((fn) => fn(attribute));
541
+ ].map((fn) => fn(attribute, options));
505
542
  const transformSchema = pipe__default.default(...validations);
506
543
  switch (attribute.type) {
507
544
  case "component": {
@@ -511,12 +548,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
511
548
  ...acc,
512
549
  [name]: transformSchema(
513
550
  yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
514
- )
551
+ ).test(arrayValidator(attribute, options))
515
552
  };
516
553
  } else {
517
554
  return {
518
555
  ...acc,
519
- [name]: transformSchema(createModelSchema(attributes3))
556
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
520
557
  };
521
558
  }
522
559
  }
@@ -538,7 +575,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
538
575
  }
539
576
  )
540
577
  )
541
- )
578
+ ).test(arrayValidator(attribute, options))
542
579
  };
543
580
  case "relation":
544
581
  return {
@@ -550,7 +587,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
550
587
  } else if (Array.isArray(value)) {
551
588
  return yup__namespace.array().of(
552
589
  yup__namespace.object().shape({
553
- id: yup__namespace.string().required()
590
+ id: yup__namespace.number().required()
554
591
  })
555
592
  );
556
593
  } else if (typeof value === "object") {
@@ -602,6 +639,14 @@ const createAttributeSchema = (attribute) => {
602
639
  if (!value || typeof value === "string" && value.length === 0) {
603
640
  return true;
604
641
  }
642
+ if (typeof value === "object") {
643
+ try {
644
+ JSON.stringify(value);
645
+ return true;
646
+ } catch (err) {
647
+ return false;
648
+ }
649
+ }
605
650
  try {
606
651
  JSON.parse(value);
607
652
  return true;
@@ -620,13 +665,7 @@ const createAttributeSchema = (attribute) => {
620
665
  return yup__namespace.mixed();
621
666
  }
622
667
  };
623
- const addRequiredValidation = (attribute) => (schema) => {
624
- if (attribute.required) {
625
- return schema.required({
626
- id: strapiAdmin.translatedErrors.required.id,
627
- defaultMessage: "This field is required."
628
- });
629
- }
668
+ const nullableSchema = (schema) => {
630
669
  return schema?.nullable ? schema.nullable() : (
631
670
  // In some cases '.nullable' will not be available on the schema.
632
671
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -634,7 +673,22 @@ const addRequiredValidation = (attribute) => (schema) => {
634
673
  schema
635
674
  );
636
675
  };
637
- const addMinLengthValidation = (attribute) => (schema) => {
676
+ const addNullableValidation = () => (schema) => {
677
+ return nullableSchema(schema);
678
+ };
679
+ const addRequiredValidation = (attribute, options) => (schema) => {
680
+ if (options.status === "draft" || !attribute.required) {
681
+ return schema;
682
+ }
683
+ if (attribute.required && "required" in schema) {
684
+ return schema.required(strapiAdmin.translatedErrors.required);
685
+ }
686
+ return schema;
687
+ };
688
+ const addMinLengthValidation = (attribute, options) => (schema) => {
689
+ if (options.status === "draft") {
690
+ return schema;
691
+ }
638
692
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
639
693
  return schema.min(attribute.minLength, {
640
694
  ...strapiAdmin.translatedErrors.minLength,
@@ -656,10 +710,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
656
710
  }
657
711
  return schema;
658
712
  };
659
- const addMinValidation = (attribute) => (schema) => {
660
- if ("min" in attribute) {
713
+ const addMinValidation = (attribute, options) => (schema) => {
714
+ if (options.status === "draft") {
715
+ return schema;
716
+ }
717
+ if ("min" in attribute && "min" in schema) {
661
718
  const min = toInteger(attribute.min);
662
- if ("min" in schema && min) {
719
+ if (min) {
663
720
  return schema.min(min, {
664
721
  ...strapiAdmin.translatedErrors.min,
665
722
  values: {
@@ -777,16 +834,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
777
834
  }, {});
778
835
  return componentsByKey;
779
836
  };
780
- const useDocument = (args, opts) => {
837
+ const HOOKS = {
838
+ /**
839
+ * Hook that allows to mutate the displayed headers of the list view table
840
+ * @constant
841
+ * @type {string}
842
+ */
843
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
844
+ /**
845
+ * Hook that allows to mutate the CM's collection types links pre-set filters
846
+ * @constant
847
+ * @type {string}
848
+ */
849
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
850
+ /**
851
+ * Hook that allows to mutate the CM's edit view layout
852
+ * @constant
853
+ * @type {string}
854
+ */
855
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
856
+ /**
857
+ * Hook that allows to mutate the CM's single types links pre-set filters
858
+ * @constant
859
+ * @type {string}
860
+ */
861
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
862
+ };
863
+ const contentTypesApi = contentManagerApi.injectEndpoints({
864
+ endpoints: (builder) => ({
865
+ getContentTypeConfiguration: builder.query({
866
+ query: (uid) => ({
867
+ url: `/content-manager/content-types/${uid}/configuration`,
868
+ method: "GET"
869
+ }),
870
+ transformResponse: (response) => response.data,
871
+ providesTags: (_result, _error, uid) => [
872
+ { type: "ContentTypesConfiguration", id: uid },
873
+ { type: "ContentTypeSettings", id: "LIST" }
874
+ ]
875
+ }),
876
+ getAllContentTypeSettings: builder.query({
877
+ query: () => "/content-manager/content-types-settings",
878
+ transformResponse: (response) => response.data,
879
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
880
+ }),
881
+ updateContentTypeConfiguration: builder.mutation({
882
+ query: ({ uid, ...body }) => ({
883
+ url: `/content-manager/content-types/${uid}/configuration`,
884
+ method: "PUT",
885
+ data: body
886
+ }),
887
+ transformResponse: (response) => response.data,
888
+ invalidatesTags: (_result, _error, { uid }) => [
889
+ { type: "ContentTypesConfiguration", id: uid },
890
+ { type: "ContentTypeSettings", id: "LIST" },
891
+ // Is this necessary?
892
+ { type: "InitialData" }
893
+ ]
894
+ })
895
+ })
896
+ });
897
+ const {
898
+ useGetContentTypeConfigurationQuery,
899
+ useGetAllContentTypeSettingsQuery,
900
+ useUpdateContentTypeConfigurationMutation
901
+ } = contentTypesApi;
902
+ const checkIfAttributeIsDisplayable = (attribute) => {
903
+ const { type } = attribute;
904
+ if (type === "relation") {
905
+ return !attribute.relation.toLowerCase().includes("morph");
906
+ }
907
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
908
+ };
909
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
910
+ if (!mainFieldName) {
911
+ return void 0;
912
+ }
913
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
914
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
915
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
916
+ );
917
+ return {
918
+ name: mainFieldName,
919
+ type: mainFieldType ?? "string"
920
+ };
921
+ };
922
+ const DEFAULT_SETTINGS = {
923
+ bulkable: false,
924
+ filterable: false,
925
+ searchable: false,
926
+ pagination: false,
927
+ defaultSortBy: "",
928
+ defaultSortOrder: "asc",
929
+ mainField: "id",
930
+ pageSize: 10
931
+ };
932
+ const useDocumentLayout = (model) => {
933
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
934
+ const [{ query }] = strapiAdmin.useQueryParams();
935
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
781
936
  const { toggleNotification } = strapiAdmin.useNotification();
782
937
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
938
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
783
939
  const {
784
- currentData: data,
785
- isLoading: isLoadingDocument,
786
- isFetching: isFetchingDocument,
787
- error
788
- } = useGetDocumentQuery(args, opts);
789
- const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
940
+ data,
941
+ isLoading: isLoadingConfigs,
942
+ error,
943
+ isFetching: isFetchingConfigs
944
+ } = useGetContentTypeConfigurationQuery(model);
945
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
790
946
  React__namespace.useEffect(() => {
791
947
  if (error) {
792
948
  toggleNotification({
@@ -794,40 +950,256 @@ const useDocument = (args, opts) => {
794
950
  message: formatAPIError(error)
795
951
  });
796
952
  }
797
- }, [toggleNotification, error, formatAPIError, args.collectionType]);
798
- const validationSchema = React__namespace.useMemo(() => {
799
- if (!schema) {
800
- return null;
801
- }
802
- return createYupSchema(schema.attributes, components);
803
- }, [schema, components]);
804
- const validate = React__namespace.useCallback(
805
- (document) => {
806
- if (!validationSchema) {
807
- throw new Error(
808
- "There is no validation schema generated, this is likely due to the schema not being loaded yet."
809
- );
810
- }
811
- try {
812
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
813
- return null;
814
- } catch (error2) {
815
- if (error2 instanceof yup.ValidationError) {
816
- return strapiAdmin.getYupValidationErrors(error2);
817
- }
818
- throw error2;
819
- }
953
+ }, [error, formatAPIError, toggleNotification]);
954
+ const editLayout = React__namespace.useMemo(
955
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
956
+ layout: [],
957
+ components: {},
958
+ metadatas: {},
959
+ options: {},
960
+ settings: DEFAULT_SETTINGS
820
961
  },
821
- [validationSchema]
962
+ [data, isLoading, schemas, schema, components]
963
+ );
964
+ const listLayout = React__namespace.useMemo(() => {
965
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
966
+ layout: [],
967
+ metadatas: {},
968
+ options: {},
969
+ settings: DEFAULT_SETTINGS
970
+ };
971
+ }, [data, isLoading, schemas, schema, components]);
972
+ const { layout: edit } = React__namespace.useMemo(
973
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
974
+ layout: editLayout,
975
+ query
976
+ }),
977
+ [editLayout, query, runHookWaterfall]
822
978
  );
823
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
824
979
  return {
825
- components,
826
- document: data?.data,
827
- meta: data?.meta,
980
+ error,
828
981
  isLoading,
829
- schema,
830
- validate
982
+ edit,
983
+ list: listLayout
984
+ };
985
+ };
986
+ const useDocLayout = () => {
987
+ const { model } = useDoc();
988
+ return useDocumentLayout(model);
989
+ };
990
+ const formatEditLayout = (data, {
991
+ schemas,
992
+ schema,
993
+ components
994
+ }) => {
995
+ let currentPanelIndex = 0;
996
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
997
+ data.contentType.layouts.edit,
998
+ schema?.attributes,
999
+ data.contentType.metadatas,
1000
+ { configurations: data.components, schemas: components },
1001
+ schemas
1002
+ ).reduce((panels, row) => {
1003
+ if (row.some((field) => field.type === "dynamiczone")) {
1004
+ panels.push([row]);
1005
+ currentPanelIndex += 2;
1006
+ } else {
1007
+ if (!panels[currentPanelIndex]) {
1008
+ panels.push([row]);
1009
+ } else {
1010
+ panels[currentPanelIndex].push(row);
1011
+ }
1012
+ }
1013
+ return panels;
1014
+ }, []);
1015
+ const componentEditAttributes = Object.entries(data.components).reduce(
1016
+ (acc, [uid, configuration]) => {
1017
+ acc[uid] = {
1018
+ layout: convertEditLayoutToFieldLayouts(
1019
+ configuration.layouts.edit,
1020
+ components[uid].attributes,
1021
+ configuration.metadatas,
1022
+ { configurations: data.components, schemas: components }
1023
+ ),
1024
+ settings: {
1025
+ ...configuration.settings,
1026
+ icon: components[uid].info.icon,
1027
+ displayName: components[uid].info.displayName
1028
+ }
1029
+ };
1030
+ return acc;
1031
+ },
1032
+ {}
1033
+ );
1034
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
1035
+ (acc, [attribute, metadata]) => {
1036
+ return {
1037
+ ...acc,
1038
+ [attribute]: metadata.edit
1039
+ };
1040
+ },
1041
+ {}
1042
+ );
1043
+ return {
1044
+ layout: panelledEditAttributes,
1045
+ components: componentEditAttributes,
1046
+ metadatas: editMetadatas,
1047
+ settings: {
1048
+ ...data.contentType.settings,
1049
+ displayName: schema?.info.displayName
1050
+ },
1051
+ options: {
1052
+ ...schema?.options,
1053
+ ...schema?.pluginOptions,
1054
+ ...data.contentType.options
1055
+ }
1056
+ };
1057
+ };
1058
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1059
+ return rows.map(
1060
+ (row) => row.map((field) => {
1061
+ const attribute = attributes[field.name];
1062
+ if (!attribute) {
1063
+ return null;
1064
+ }
1065
+ const { edit: metadata } = metadatas[field.name];
1066
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1067
+ return {
1068
+ attribute,
1069
+ disabled: !metadata.editable,
1070
+ hint: metadata.description,
1071
+ label: metadata.label ?? "",
1072
+ name: field.name,
1073
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1074
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1075
+ schemas,
1076
+ components: components?.schemas ?? {}
1077
+ }),
1078
+ placeholder: metadata.placeholder ?? "",
1079
+ required: attribute.required ?? false,
1080
+ size: field.size,
1081
+ unique: "unique" in attribute ? attribute.unique : false,
1082
+ visible: metadata.visible ?? true,
1083
+ type: attribute.type
1084
+ };
1085
+ }).filter((field) => field !== null)
1086
+ );
1087
+ };
1088
+ const formatListLayout = (data, {
1089
+ schemas,
1090
+ schema,
1091
+ components
1092
+ }) => {
1093
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1094
+ (acc, [attribute, metadata]) => {
1095
+ return {
1096
+ ...acc,
1097
+ [attribute]: metadata.list
1098
+ };
1099
+ },
1100
+ {}
1101
+ );
1102
+ const listAttributes = convertListLayoutToFieldLayouts(
1103
+ data.contentType.layouts.list,
1104
+ schema?.attributes,
1105
+ listMetadatas,
1106
+ { configurations: data.components, schemas: components },
1107
+ schemas
1108
+ );
1109
+ return {
1110
+ layout: listAttributes,
1111
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1112
+ metadatas: listMetadatas,
1113
+ options: {
1114
+ ...schema?.options,
1115
+ ...schema?.pluginOptions,
1116
+ ...data.contentType.options
1117
+ }
1118
+ };
1119
+ };
1120
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1121
+ return columns.map((name) => {
1122
+ const attribute = attributes[name];
1123
+ if (!attribute) {
1124
+ return null;
1125
+ }
1126
+ const metadata = metadatas[name];
1127
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1128
+ return {
1129
+ attribute,
1130
+ label: metadata.label ?? "",
1131
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1132
+ schemas,
1133
+ components: components?.schemas ?? {}
1134
+ }),
1135
+ name,
1136
+ searchable: metadata.searchable ?? true,
1137
+ sortable: metadata.sortable ?? true
1138
+ };
1139
+ }).filter((field) => field !== null);
1140
+ };
1141
+ const useDocument = (args, opts) => {
1142
+ const { toggleNotification } = strapiAdmin.useNotification();
1143
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1144
+ const {
1145
+ currentData: data,
1146
+ isLoading: isLoadingDocument,
1147
+ isFetching: isFetchingDocument,
1148
+ error
1149
+ } = useGetDocumentQuery(args, {
1150
+ ...opts,
1151
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1152
+ });
1153
+ const {
1154
+ components,
1155
+ schema,
1156
+ schemas,
1157
+ isLoading: isLoadingSchema
1158
+ } = useContentTypeSchema(args.model);
1159
+ React__namespace.useEffect(() => {
1160
+ if (error) {
1161
+ toggleNotification({
1162
+ type: "danger",
1163
+ message: formatAPIError(error)
1164
+ });
1165
+ }
1166
+ }, [toggleNotification, error, formatAPIError, args.collectionType]);
1167
+ const validationSchema = React__namespace.useMemo(() => {
1168
+ if (!schema) {
1169
+ return null;
1170
+ }
1171
+ return createYupSchema(schema.attributes, components);
1172
+ }, [schema, components]);
1173
+ const validate = React__namespace.useCallback(
1174
+ (document) => {
1175
+ if (!validationSchema) {
1176
+ throw new Error(
1177
+ "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1178
+ );
1179
+ }
1180
+ try {
1181
+ validationSchema.validateSync(document, { abortEarly: false, strict: true });
1182
+ return null;
1183
+ } catch (error2) {
1184
+ if (error2 instanceof yup.ValidationError) {
1185
+ return strapiAdmin.getYupValidationErrors(error2);
1186
+ }
1187
+ throw error2;
1188
+ }
1189
+ },
1190
+ [validationSchema]
1191
+ );
1192
+ const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1193
+ const hasError = !!error;
1194
+ return {
1195
+ components,
1196
+ document: data?.data,
1197
+ meta: data?.meta,
1198
+ isLoading,
1199
+ hasError,
1200
+ schema,
1201
+ schemas,
1202
+ validate
831
1203
  };
832
1204
  };
833
1205
  const useDoc = () => {
@@ -840,22 +1212,60 @@ const useDoc = () => {
840
1212
  if (!slug) {
841
1213
  throw new Error("Could not find model in url params");
842
1214
  }
1215
+ const document = useDocument(
1216
+ { documentId: origin || id, model: slug, collectionType, params },
1217
+ {
1218
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1219
+ }
1220
+ );
1221
+ const returnId = origin || id === "create" ? void 0 : id;
843
1222
  return {
844
1223
  collectionType,
845
1224
  model: slug,
846
- id: origin || id === "create" ? void 0 : id,
847
- ...useDocument(
848
- { documentId: origin || id, model: slug, collectionType, params },
849
- {
850
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
851
- }
852
- )
1225
+ id: returnId,
1226
+ ...document
1227
+ };
1228
+ };
1229
+ const useContentManagerContext = () => {
1230
+ const {
1231
+ collectionType,
1232
+ model,
1233
+ id,
1234
+ components,
1235
+ isLoading: isLoadingDoc,
1236
+ schema,
1237
+ schemas
1238
+ } = useDoc();
1239
+ const layout = useDocumentLayout(model);
1240
+ const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
1241
+ const isSingleType = collectionType === SINGLE_TYPES;
1242
+ const slug = model;
1243
+ const isCreatingEntry = id === "create";
1244
+ useContentTypeSchema();
1245
+ const isLoading = isLoadingDoc || layout.isLoading;
1246
+ const error = layout.error;
1247
+ return {
1248
+ error,
1249
+ isLoading,
1250
+ // Base metadata
1251
+ model,
1252
+ collectionType,
1253
+ id,
1254
+ slug,
1255
+ isCreatingEntry,
1256
+ isSingleType,
1257
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1258
+ // All schema infos
1259
+ components,
1260
+ contentType: schema,
1261
+ contentTypes: schemas,
1262
+ // Form state
1263
+ form,
1264
+ // layout infos
1265
+ layout
853
1266
  };
854
1267
  };
855
1268
  const prefixPluginTranslations = (trad, pluginId) => {
856
- if (!pluginId) {
857
- throw new TypeError("pluginId can't be empty");
858
- }
859
1269
  return Object.keys(trad).reduce((acc, current) => {
860
1270
  acc[`${pluginId}.${current}`] = trad[current];
861
1271
  return acc;
@@ -871,6 +1281,8 @@ const useDocumentActions = () => {
871
1281
  const { formatMessage } = reactIntl.useIntl();
872
1282
  const { trackUsage } = strapiAdmin.useTracking();
873
1283
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1284
+ const navigate = reactRouterDom.useNavigate();
1285
+ const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
874
1286
  const [deleteDocument] = useDeleteDocumentMutation();
875
1287
  const _delete = React__namespace.useCallback(
876
1288
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -1185,6 +1597,7 @@ const useDocumentActions = () => {
1185
1597
  defaultMessage: "Saved document"
1186
1598
  })
1187
1599
  });
1600
+ setCurrentStep("contentManager.success");
1188
1601
  return res.data;
1189
1602
  } catch (err) {
1190
1603
  toggleNotification({
@@ -1206,7 +1619,6 @@ const useDocumentActions = () => {
1206
1619
  sourceId
1207
1620
  });
1208
1621
  if ("error" in res) {
1209
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1210
1622
  return { error: res.error };
1211
1623
  }
1212
1624
  toggleNotification({
@@ -1225,7 +1637,7 @@ const useDocumentActions = () => {
1225
1637
  throw err;
1226
1638
  }
1227
1639
  },
1228
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1640
+ [autoCloneDocument, formatMessage, toggleNotification]
1229
1641
  );
1230
1642
  const [cloneDocument] = useCloneDocumentMutation();
1231
1643
  const clone = React__namespace.useCallback(
@@ -1251,6 +1663,7 @@ const useDocumentActions = () => {
1251
1663
  defaultMessage: "Cloned document"
1252
1664
  })
1253
1665
  });
1666
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1254
1667
  return res.data;
1255
1668
  } catch (err) {
1256
1669
  toggleNotification({
@@ -1261,7 +1674,7 @@ const useDocumentActions = () => {
1261
1674
  throw err;
1262
1675
  }
1263
1676
  },
1264
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1677
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1265
1678
  );
1266
1679
  const [getDoc] = useLazyGetDocumentQuery();
1267
1680
  const getDocument = React__namespace.useCallback(
@@ -1286,10 +1699,10 @@ const useDocumentActions = () => {
1286
1699
  update
1287
1700
  };
1288
1701
  };
1289
- const ProtectedHistoryPage = React.lazy(
1290
- () => Promise.resolve().then(() => require("./History-CqN6K7SX.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1702
+ const ProtectedHistoryPage = React__namespace.lazy(
1703
+ () => Promise.resolve().then(() => require("./History-CeCDhoJG.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1291
1704
  );
1292
- const routes$1 = [
1705
+ const routes$2 = [
1293
1706
  {
1294
1707
  path: ":collectionType/:slug/:id/history",
1295
1708
  Component: ProtectedHistoryPage
@@ -1299,32 +1712,45 @@ const routes$1 = [
1299
1712
  Component: ProtectedHistoryPage
1300
1713
  }
1301
1714
  ];
1715
+ const ProtectedPreviewPage = React__namespace.lazy(
1716
+ () => Promise.resolve().then(() => require("./Preview-CT28Ckpg.js")).then((mod) => ({ default: mod.ProtectedPreviewPage }))
1717
+ );
1718
+ const routes$1 = [
1719
+ {
1720
+ path: ":collectionType/:slug/:id/preview",
1721
+ Component: ProtectedPreviewPage
1722
+ },
1723
+ {
1724
+ path: ":collectionType/:slug/preview",
1725
+ Component: ProtectedPreviewPage
1726
+ }
1727
+ ];
1302
1728
  const ProtectedEditViewPage = React.lazy(
1303
- () => Promise.resolve().then(() => require("./EditViewPage-zT3fBr4Y.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1729
+ () => Promise.resolve().then(() => require("./EditViewPage-BwisF04Q.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1304
1730
  );
1305
1731
  const ProtectedListViewPage = React.lazy(
1306
- () => Promise.resolve().then(() => require("./ListViewPage-pEw_zug9.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1732
+ () => Promise.resolve().then(() => require("./ListViewPage-BKTZFhsM.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1307
1733
  );
1308
1734
  const ProtectedListConfiguration = React.lazy(
1309
- () => Promise.resolve().then(() => require("./ListConfigurationPage-R_p-SbHZ.js")).then((mod) => ({
1735
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-C-bAd44a.js")).then((mod) => ({
1310
1736
  default: mod.ProtectedListConfiguration
1311
1737
  }))
1312
1738
  );
1313
1739
  const ProtectedEditConfigurationPage = React.lazy(
1314
- () => Promise.resolve().then(() => require("./EditConfigurationPage-DjFJw56M.js")).then((mod) => ({
1740
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-D2rtvneE.js")).then((mod) => ({
1315
1741
  default: mod.ProtectedEditConfigurationPage
1316
1742
  }))
1317
1743
  );
1318
1744
  const ProtectedComponentConfigurationPage = React.lazy(
1319
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-C-49MccQ.js")).then((mod) => ({
1745
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-BSEZcJVB.js")).then((mod) => ({
1320
1746
  default: mod.ProtectedComponentConfigurationPage
1321
1747
  }))
1322
1748
  );
1323
1749
  const NoPermissions = React.lazy(
1324
- () => Promise.resolve().then(() => require("./NoPermissionsPage-BtPrImPP.js")).then((mod) => ({ default: mod.NoPermissions }))
1750
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-CChGWBj5.js")).then((mod) => ({ default: mod.NoPermissions }))
1325
1751
  );
1326
1752
  const NoContentType = React.lazy(
1327
- () => Promise.resolve().then(() => require("./NoContentTypePage-C5dcQojD.js")).then((mod) => ({ default: mod.NoContentType }))
1753
+ () => Promise.resolve().then(() => require("./NoContentTypePage-D3Cm3v3q.js")).then((mod) => ({ default: mod.NoContentType }))
1328
1754
  );
1329
1755
  const CollectionTypePages = () => {
1330
1756
  const { collectionType } = reactRouterDom.useParams();
@@ -1336,7 +1762,7 @@ const CollectionTypePages = () => {
1336
1762
  const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
1337
1763
  const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
1338
1764
  const LIST_RELATIVE_PATH = ":collectionType/:slug";
1339
- const LIST_PATH = `/content-manager/${LIST_RELATIVE_PATH}`;
1765
+ const LIST_PATH = `/content-manager/collection-types/:slug`;
1340
1766
  const routes = [
1341
1767
  {
1342
1768
  path: LIST_RELATIVE_PATH,
@@ -1370,6 +1796,7 @@ const routes = [
1370
1796
  path: "no-content-types",
1371
1797
  Component: NoContentType
1372
1798
  },
1799
+ ...routes$2,
1373
1800
  ...routes$1
1374
1801
  ];
1375
1802
  const DocumentActions = ({ actions: actions2 }) => {
@@ -1438,12 +1865,14 @@ const DocumentActionButton = (action) => {
1438
1865
  /* @__PURE__ */ jsxRuntime.jsx(
1439
1866
  designSystem.Button,
1440
1867
  {
1441
- flex: 1,
1868
+ flex: "auto",
1442
1869
  startIcon: action.icon,
1443
1870
  disabled: action.disabled,
1444
1871
  onClick: handleClick(action),
1445
1872
  justifyContent: "center",
1446
1873
  variant: action.variant || "default",
1874
+ paddingTop: "7px",
1875
+ paddingBottom: "7px",
1447
1876
  children: action.label
1448
1877
  }
1449
1878
  ),
@@ -1451,7 +1880,7 @@ const DocumentActionButton = (action) => {
1451
1880
  DocumentActionConfirmDialog,
1452
1881
  {
1453
1882
  ...action.dialog,
1454
- variant: action.variant,
1883
+ variant: action.dialog?.variant ?? action.variant,
1455
1884
  isOpen: dialogId === action.id,
1456
1885
  onClose: handleClose
1457
1886
  }
@@ -1466,6 +1895,11 @@ const DocumentActionButton = (action) => {
1466
1895
  ) : null
1467
1896
  ] });
1468
1897
  };
1898
+ const MenuItem = styledComponents.styled(designSystem.Menu.Item)`
1899
+ &:hover {
1900
+ background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
1901
+ }
1902
+ `;
1469
1903
  const DocumentActionsMenu = ({
1470
1904
  actions: actions2,
1471
1905
  children,
@@ -1508,9 +1942,9 @@ const DocumentActionsMenu = ({
1508
1942
  disabled: isDisabled,
1509
1943
  size: "S",
1510
1944
  endIcon: null,
1511
- paddingTop: "7px",
1512
- paddingLeft: "9px",
1513
- paddingRight: "9px",
1945
+ paddingTop: "4px",
1946
+ paddingLeft: "7px",
1947
+ paddingRight: "7px",
1514
1948
  variant,
1515
1949
  children: [
1516
1950
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
@@ -1521,36 +1955,35 @@ const DocumentActionsMenu = ({
1521
1955
  ]
1522
1956
  }
1523
1957
  ),
1524
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1958
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1525
1959
  actions2.map((action) => {
1526
1960
  return /* @__PURE__ */ jsxRuntime.jsx(
1527
- designSystem.Menu.Item,
1961
+ MenuItem,
1528
1962
  {
1529
1963
  disabled: action.disabled,
1530
1964
  onSelect: handleClick(action),
1531
1965
  display: "block",
1532
- children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1533
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1534
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1535
- action.label
1536
- ] }),
1537
- action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
1538
- designSystem.Flex,
1539
- {
1540
- alignItems: "center",
1541
- background: "alternative100",
1542
- borderStyle: "solid",
1543
- borderColor: "alternative200",
1544
- borderWidth: "1px",
1545
- height: 5,
1546
- paddingLeft: 2,
1547
- paddingRight: 2,
1548
- hasRadius: true,
1549
- color: "alternative600",
1550
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
1551
- }
1552
- )
1553
- ] })
1966
+ isVariantDanger: action.variant === "danger",
1967
+ isDisabled: action.disabled,
1968
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
1969
+ designSystem.Flex,
1970
+ {
1971
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1972
+ gap: 2,
1973
+ tag: "span",
1974
+ children: [
1975
+ /* @__PURE__ */ jsxRuntime.jsx(
1976
+ designSystem.Flex,
1977
+ {
1978
+ tag: "span",
1979
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1980
+ children: action.icon
1981
+ }
1982
+ ),
1983
+ action.label
1984
+ ]
1985
+ }
1986
+ ) })
1554
1987
  },
1555
1988
  action.id
1556
1989
  );
@@ -1630,11 +2063,11 @@ const DocumentActionConfirmDialog = ({
1630
2063
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
1631
2064
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
1632
2065
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
1633
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
2066
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
1634
2067
  id: "app.components.Button.cancel",
1635
2068
  defaultMessage: "Cancel"
1636
2069
  }) }) }),
1637
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
2070
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
1638
2071
  id: "app.components.Button.confirm",
1639
2072
  defaultMessage: "Confirm"
1640
2073
  }) })
@@ -1661,6 +2094,18 @@ const DocumentActionModal = ({
1661
2094
  typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1662
2095
  ] }) });
1663
2096
  };
2097
+ const transformData = (data) => {
2098
+ if (Array.isArray(data)) {
2099
+ return data.map(transformData);
2100
+ }
2101
+ if (typeof data === "object" && data !== null) {
2102
+ if ("apiData" in data) {
2103
+ return data.apiData;
2104
+ }
2105
+ return mapValues__default.default(transformData)(data);
2106
+ }
2107
+ return data;
2108
+ };
1664
2109
  const PublishAction$1 = ({
1665
2110
  activeTab,
1666
2111
  documentId,
@@ -1673,13 +2118,18 @@ const PublishAction$1 = ({
1673
2118
  const navigate = reactRouterDom.useNavigate();
1674
2119
  const { toggleNotification } = strapiAdmin.useNotification();
1675
2120
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
2121
+ const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
1676
2122
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2123
+ const { id } = reactRouterDom.useParams();
1677
2124
  const { formatMessage } = reactIntl.useIntl();
1678
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1679
- "PublishAction",
1680
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1681
- );
2125
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1682
2126
  const { publish } = useDocumentActions();
2127
+ const [
2128
+ countDraftRelations,
2129
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
2130
+ ] = useLazyGetDraftRelationCountQuery();
2131
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
2132
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
1683
2133
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1684
2134
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1685
2135
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1688,10 +2138,107 @@ const PublishAction$1 = ({
1688
2138
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1689
2139
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1690
2140
  const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
1691
- const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1692
- if (!schema?.options?.draftAndPublish) {
1693
- return null;
1694
- }
2141
+ React__namespace.useEffect(() => {
2142
+ if (isErrorDraftRelations) {
2143
+ toggleNotification({
2144
+ type: "danger",
2145
+ message: formatMessage({
2146
+ id: getTranslation("error.records.fetch-draft-relatons"),
2147
+ defaultMessage: "An error occurred while fetching draft relations on this document."
2148
+ })
2149
+ });
2150
+ }
2151
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
2152
+ React__namespace.useEffect(() => {
2153
+ const localDraftRelations = /* @__PURE__ */ new Set();
2154
+ const extractDraftRelations = (data) => {
2155
+ const relations = data.connect || [];
2156
+ relations.forEach((relation) => {
2157
+ if (relation.status === "draft") {
2158
+ localDraftRelations.add(relation.id);
2159
+ }
2160
+ });
2161
+ };
2162
+ const traverseAndExtract = (data) => {
2163
+ Object.entries(data).forEach(([key, value]) => {
2164
+ if (key === "connect" && Array.isArray(value)) {
2165
+ extractDraftRelations({ connect: value });
2166
+ } else if (typeof value === "object" && value !== null) {
2167
+ traverseAndExtract(value);
2168
+ }
2169
+ });
2170
+ };
2171
+ if (!documentId || modified) {
2172
+ traverseAndExtract(formValues);
2173
+ setLocalCountOfDraftRelations(localDraftRelations.size);
2174
+ }
2175
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
2176
+ React__namespace.useEffect(() => {
2177
+ if (!document || !document.documentId || isListView) {
2178
+ return;
2179
+ }
2180
+ const fetchDraftRelationsCount = async () => {
2181
+ const { data, error } = await countDraftRelations({
2182
+ collectionType,
2183
+ model,
2184
+ documentId,
2185
+ params
2186
+ });
2187
+ if (error) {
2188
+ throw error;
2189
+ }
2190
+ if (data) {
2191
+ setServerCountOfDraftRelations(data.data);
2192
+ }
2193
+ };
2194
+ fetchDraftRelationsCount();
2195
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
2196
+ const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
2197
+ if (!schema?.options?.draftAndPublish) {
2198
+ return null;
2199
+ }
2200
+ const performPublish = async () => {
2201
+ setSubmitting(true);
2202
+ try {
2203
+ const { errors } = await validate(true, {
2204
+ status: "published"
2205
+ });
2206
+ if (errors) {
2207
+ toggleNotification({
2208
+ type: "danger",
2209
+ message: formatMessage({
2210
+ id: "content-manager.validation.error",
2211
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2212
+ })
2213
+ });
2214
+ return;
2215
+ }
2216
+ const res = await publish(
2217
+ {
2218
+ collectionType,
2219
+ model,
2220
+ documentId,
2221
+ params
2222
+ },
2223
+ transformData(formValues)
2224
+ );
2225
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2226
+ if (id === "create") {
2227
+ navigate({
2228
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2229
+ search: rawQuery
2230
+ });
2231
+ }
2232
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2233
+ setErrors(formatValidationErrors(res.error));
2234
+ }
2235
+ } finally {
2236
+ setSubmitting(false);
2237
+ }
2238
+ };
2239
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
2240
+ const enableDraftRelationsCount = false;
2241
+ const hasDraftRelations = enableDraftRelationsCount;
1695
2242
  return {
1696
2243
  /**
1697
2244
  * Disabled when:
@@ -1701,52 +2248,40 @@ const PublishAction$1 = ({
1701
2248
  * - the document is already published & not modified
1702
2249
  * - the document is being created & not modified
1703
2250
  * - the user doesn't have the permission to publish
1704
- * - the user doesn't have the permission to create a new document
1705
- * - the user doesn't have the permission to update the document
1706
2251
  */
1707
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2252
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1708
2253
  label: formatMessage({
1709
2254
  id: "app.utils.publish",
1710
2255
  defaultMessage: "Publish"
1711
2256
  }),
1712
2257
  onClick: async () => {
1713
- setSubmitting(true);
1714
- try {
1715
- const { errors } = await validate();
1716
- if (errors) {
1717
- toggleNotification({
1718
- type: "danger",
1719
- message: formatMessage({
1720
- id: "content-manager.validation.error",
1721
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1722
- })
1723
- });
1724
- return;
1725
- }
1726
- const res = await publish(
1727
- {
1728
- collectionType,
1729
- model,
1730
- documentId,
1731
- params
1732
- },
1733
- formValues
1734
- );
1735
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1736
- navigate({
1737
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1738
- search: rawQuery
1739
- });
1740
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1741
- setErrors(formatValidationErrors(res.error));
2258
+ await performPublish();
2259
+ },
2260
+ dialog: hasDraftRelations ? {
2261
+ type: "dialog",
2262
+ variant: "danger",
2263
+ footer: null,
2264
+ title: formatMessage({
2265
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
2266
+ defaultMessage: "Confirmation"
2267
+ }),
2268
+ content: formatMessage(
2269
+ {
2270
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2271
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
2272
+ },
2273
+ {
2274
+ count: totalDraftRelations
1742
2275
  }
1743
- } finally {
1744
- setSubmitting(false);
2276
+ ),
2277
+ onConfirm: async () => {
2278
+ await performPublish();
1745
2279
  }
1746
- }
2280
+ } : void 0
1747
2281
  };
1748
2282
  };
1749
2283
  PublishAction$1.type = "publish";
2284
+ PublishAction$1.position = "panel";
1750
2285
  const UpdateAction = ({
1751
2286
  activeTab,
1752
2287
  documentId,
@@ -1759,10 +2294,6 @@ const UpdateAction = ({
1759
2294
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1760
2295
  const isCloning = cloneMatch !== null;
1761
2296
  const { formatMessage } = reactIntl.useIntl();
1762
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1763
- canCreate: canCreate2,
1764
- canUpdate: canUpdate2
1765
- }));
1766
2297
  const { create, update, clone } = useDocumentActions();
1767
2298
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1768
2299
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1773,90 +2304,134 @@ const UpdateAction = ({
1773
2304
  const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
1774
2305
  const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
1775
2306
  const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
1776
- return {
1777
- /**
1778
- * Disabled when:
1779
- * - the form is submitting
1780
- * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1781
- * - the active tab is the published tab
1782
- * - the user doesn't have the permission to create a new document
1783
- * - the user doesn't have the permission to update the document
1784
- */
1785
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
1786
- label: formatMessage({
1787
- id: "content-manager.containers.Edit.save",
1788
- defaultMessage: "Save"
1789
- }),
1790
- onClick: async () => {
1791
- setSubmitting(true);
1792
- try {
1793
- const { errors } = await validate();
1794
- if (errors) {
1795
- toggleNotification({
1796
- type: "danger",
1797
- message: formatMessage({
1798
- id: "content-manager.validation.error",
1799
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1800
- })
1801
- });
1802
- return;
1803
- }
1804
- if (isCloning) {
1805
- const res = await clone(
2307
+ const handleUpdate = React__namespace.useCallback(async () => {
2308
+ setSubmitting(true);
2309
+ try {
2310
+ if (!modified) {
2311
+ return;
2312
+ }
2313
+ const { errors } = await validate(true, {
2314
+ status: "draft"
2315
+ });
2316
+ if (errors) {
2317
+ toggleNotification({
2318
+ type: "danger",
2319
+ message: formatMessage({
2320
+ id: "content-manager.validation.error",
2321
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2322
+ })
2323
+ });
2324
+ return;
2325
+ }
2326
+ if (isCloning) {
2327
+ const res = await clone(
2328
+ {
2329
+ model,
2330
+ documentId: cloneMatch.params.origin,
2331
+ params
2332
+ },
2333
+ transformData(document)
2334
+ );
2335
+ if ("data" in res) {
2336
+ navigate(
1806
2337
  {
1807
- model,
1808
- documentId: cloneMatch.params.origin,
1809
- params
1810
- },
1811
- document
1812
- );
1813
- if ("data" in res) {
1814
- navigate({
1815
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2338
+ pathname: `../${res.data.documentId}`,
1816
2339
  search: rawQuery
1817
- });
1818
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1819
- setErrors(formatValidationErrors(res.error));
1820
- }
1821
- } else if (documentId || collectionType === SINGLE_TYPES) {
1822
- const res = await update(
1823
- {
1824
- collectionType,
1825
- model,
1826
- documentId,
1827
- params
1828
2340
  },
1829
- document
2341
+ { relative: "path" }
1830
2342
  );
1831
- if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1832
- setErrors(formatValidationErrors(res.error));
1833
- } else {
1834
- resetForm();
1835
- }
2343
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2344
+ setErrors(formatValidationErrors(res.error));
2345
+ }
2346
+ } else if (documentId || collectionType === SINGLE_TYPES) {
2347
+ const res = await update(
2348
+ {
2349
+ collectionType,
2350
+ model,
2351
+ documentId,
2352
+ params
2353
+ },
2354
+ transformData(document)
2355
+ );
2356
+ if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2357
+ setErrors(formatValidationErrors(res.error));
1836
2358
  } else {
1837
- const res = await create(
2359
+ resetForm();
2360
+ }
2361
+ } else {
2362
+ const res = await create(
2363
+ {
2364
+ model,
2365
+ params
2366
+ },
2367
+ transformData(document)
2368
+ );
2369
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2370
+ navigate(
1838
2371
  {
1839
- model,
1840
- params
2372
+ pathname: `../${res.data.documentId}`,
2373
+ search: rawQuery
1841
2374
  },
1842
- document
2375
+ { replace: true, relative: "path" }
1843
2376
  );
1844
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1845
- navigate({
1846
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1847
- search: rawQuery
1848
- });
1849
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1850
- setErrors(formatValidationErrors(res.error));
1851
- }
2377
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2378
+ setErrors(formatValidationErrors(res.error));
1852
2379
  }
1853
- } finally {
1854
- setSubmitting(false);
1855
2380
  }
2381
+ } finally {
2382
+ setSubmitting(false);
1856
2383
  }
2384
+ }, [
2385
+ clone,
2386
+ cloneMatch?.params.origin,
2387
+ collectionType,
2388
+ create,
2389
+ document,
2390
+ documentId,
2391
+ formatMessage,
2392
+ formatValidationErrors,
2393
+ isCloning,
2394
+ model,
2395
+ modified,
2396
+ navigate,
2397
+ params,
2398
+ rawQuery,
2399
+ resetForm,
2400
+ setErrors,
2401
+ setSubmitting,
2402
+ toggleNotification,
2403
+ update,
2404
+ validate
2405
+ ]);
2406
+ React__namespace.useEffect(() => {
2407
+ const handleKeyDown = (e) => {
2408
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
2409
+ e.preventDefault();
2410
+ handleUpdate();
2411
+ }
2412
+ };
2413
+ window.addEventListener("keydown", handleKeyDown);
2414
+ return () => {
2415
+ window.removeEventListener("keydown", handleKeyDown);
2416
+ };
2417
+ }, [handleUpdate]);
2418
+ return {
2419
+ /**
2420
+ * Disabled when:
2421
+ * - the form is submitting
2422
+ * - the document is not modified & we're not cloning (you can save a clone entity straight away)
2423
+ * - the active tab is the published tab
2424
+ */
2425
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
2426
+ label: formatMessage({
2427
+ id: "global.save",
2428
+ defaultMessage: "Save"
2429
+ }),
2430
+ onClick: handleUpdate
1857
2431
  };
1858
2432
  };
1859
2433
  UpdateAction.type = "update";
2434
+ UpdateAction.position = "panel";
1860
2435
  const UNPUBLISH_DRAFT_OPTIONS = {
1861
2436
  KEEP: "keep",
1862
2437
  DISCARD: "discard"
@@ -1889,7 +2464,7 @@ const UnpublishAction$1 = ({
1889
2464
  id: "app.utils.unpublish",
1890
2465
  defaultMessage: "Unpublish"
1891
2466
  }),
1892
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2467
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
1893
2468
  onClick: async () => {
1894
2469
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1895
2470
  if (!documentId) {
@@ -1979,6 +2554,7 @@ const UnpublishAction$1 = ({
1979
2554
  };
1980
2555
  };
1981
2556
  UnpublishAction$1.type = "unpublish";
2557
+ UnpublishAction$1.position = "panel";
1982
2558
  const DiscardAction = ({
1983
2559
  activeTab,
1984
2560
  documentId,
@@ -2001,7 +2577,7 @@ const DiscardAction = ({
2001
2577
  id: "content-manager.actions.discard.label",
2002
2578
  defaultMessage: "Discard changes"
2003
2579
  }),
2004
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2580
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
2005
2581
  position: ["panel", "table-row"],
2006
2582
  variant: "danger",
2007
2583
  dialog: {
@@ -2029,11 +2605,7 @@ const DiscardAction = ({
2029
2605
  };
2030
2606
  };
2031
2607
  DiscardAction.type = "discard";
2032
- const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
2033
- path {
2034
- fill: currentColor;
2035
- }
2036
- `;
2608
+ DiscardAction.position = "panel";
2037
2609
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2038
2610
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2039
2611
  const RelativeTime = React__namespace.forwardRef(
@@ -2046,7 +2618,7 @@ const RelativeTime = React__namespace.forwardRef(
2046
2618
  });
2047
2619
  const unit = intervals.find((intervalUnit) => {
2048
2620
  return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
2049
- });
2621
+ }) ?? "seconds";
2050
2622
  const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
2051
2623
  const customInterval = customIntervals.find(
2052
2624
  (custom) => interval[custom.unit] < custom.threshold
@@ -2080,34 +2652,34 @@ const getDisplayName = ({
2080
2652
  return email ?? "";
2081
2653
  };
2082
2654
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2083
- const DocumentStatus = ({ status = "draft", ...restProps }) => {
2084
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
2085
- 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) }) });
2655
+ const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
2656
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2657
+ const { formatMessage } = reactIntl.useIntl();
2658
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
2659
+ id: `content-manager.containers.List.${status}`,
2660
+ defaultMessage: capitalise(status)
2661
+ }) }) });
2086
2662
  };
2087
2663
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2088
2664
  const { formatMessage } = reactIntl.useIntl();
2089
2665
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2666
+ const params = reactRouterDom.useParams();
2090
2667
  const title = isCreating ? formatMessage({
2091
2668
  id: "content-manager.containers.edit.title.new",
2092
2669
  defaultMessage: "Create an entry"
2093
2670
  }) : documentTitle;
2094
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2095
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
2096
- /* @__PURE__ */ jsxRuntime.jsxs(
2097
- designSystem.Flex,
2671
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2672
+ /* @__PURE__ */ jsxRuntime.jsx(
2673
+ strapiAdmin.BackButton,
2098
2674
  {
2099
- width: "100%",
2100
- justifyContent: "space-between",
2101
- paddingTop: 1,
2102
- gap: "80px",
2103
- alignItems: "flex-start",
2104
- children: [
2105
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2106
- /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2107
- ]
2675
+ fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
2108
2676
  }
2109
2677
  ),
2110
- status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2678
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2679
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2680
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2681
+ ] }),
2682
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2111
2683
  ] });
2112
2684
  };
2113
2685
  const HeaderToolbar = () => {
@@ -2153,7 +2725,7 @@ const HeaderToolbar = () => {
2153
2725
  meta: isCloning ? void 0 : meta,
2154
2726
  collectionType
2155
2727
  },
2156
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2728
+ descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
2157
2729
  children: (actions2) => {
2158
2730
  const headerActions = actions2.filter((action) => {
2159
2731
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -2190,12 +2762,12 @@ const Information = ({ activeTab }) => {
2190
2762
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2191
2763
  label: formatMessage({
2192
2764
  id: "content-manager.containers.edit.information.last-published.label",
2193
- defaultMessage: "Last published"
2765
+ defaultMessage: "Published"
2194
2766
  }),
2195
2767
  value: formatMessage(
2196
2768
  {
2197
2769
  id: "content-manager.containers.edit.information.last-published.value",
2198
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2770
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2199
2771
  },
2200
2772
  {
2201
2773
  time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2208,12 +2780,12 @@ const Information = ({ activeTab }) => {
2208
2780
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2209
2781
  label: formatMessage({
2210
2782
  id: "content-manager.containers.edit.information.last-draft.label",
2211
- defaultMessage: "Last draft"
2783
+ defaultMessage: "Updated"
2212
2784
  }),
2213
2785
  value: formatMessage(
2214
2786
  {
2215
2787
  id: "content-manager.containers.edit.information.last-draft.value",
2216
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2788
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2217
2789
  },
2218
2790
  {
2219
2791
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2231,12 +2803,12 @@ const Information = ({ activeTab }) => {
2231
2803
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2232
2804
  label: formatMessage({
2233
2805
  id: "content-manager.containers.edit.information.document.label",
2234
- defaultMessage: "Document"
2806
+ defaultMessage: "Created"
2235
2807
  }),
2236
2808
  value: formatMessage(
2237
2809
  {
2238
2810
  id: "content-manager.containers.edit.information.document.value",
2239
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2811
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2240
2812
  },
2241
2813
  {
2242
2814
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2274,25 +2846,77 @@ const Information = ({ activeTab }) => {
2274
2846
  );
2275
2847
  };
2276
2848
  const HeaderActions = ({ actions: actions2 }) => {
2277
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: actions2.map((action) => {
2278
- if ("options" in action) {
2849
+ const [dialogId, setDialogId] = React__namespace.useState(null);
2850
+ const handleClick = (action) => async (e) => {
2851
+ if (!("options" in action)) {
2852
+ const { onClick = () => false, dialog, id } = action;
2853
+ const muteDialog = await onClick(e);
2854
+ if (dialog && !muteDialog) {
2855
+ e.preventDefault();
2856
+ setDialogId(id);
2857
+ }
2858
+ }
2859
+ };
2860
+ const handleClose = () => {
2861
+ setDialogId(null);
2862
+ };
2863
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
2864
+ if (action.options) {
2279
2865
  return /* @__PURE__ */ jsxRuntime.jsx(
2280
2866
  designSystem.SingleSelect,
2281
2867
  {
2282
2868
  size: "S",
2283
- disabled: action.disabled,
2284
- "aria-label": action.label,
2285
2869
  onChange: action.onSelect,
2286
- value: action.value,
2870
+ "aria-label": action.label,
2871
+ ...action,
2287
2872
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
2288
2873
  },
2289
2874
  action.id
2290
2875
  );
2291
2876
  } else {
2292
- return null;
2877
+ if (action.type === "icon") {
2878
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
2879
+ /* @__PURE__ */ jsxRuntime.jsx(
2880
+ designSystem.IconButton,
2881
+ {
2882
+ disabled: action.disabled,
2883
+ label: action.label,
2884
+ size: "S",
2885
+ onClick: handleClick(action),
2886
+ children: action.icon
2887
+ }
2888
+ ),
2889
+ action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
2890
+ HeaderActionDialog,
2891
+ {
2892
+ ...action.dialog,
2893
+ isOpen: dialogId === action.id,
2894
+ onClose: handleClose
2895
+ }
2896
+ ) : null
2897
+ ] }, action.id);
2898
+ }
2293
2899
  }
2294
2900
  }) });
2295
2901
  };
2902
+ const HeaderActionDialog = ({
2903
+ onClose,
2904
+ onCancel,
2905
+ title,
2906
+ content: Content,
2907
+ isOpen
2908
+ }) => {
2909
+ const handleClose = async () => {
2910
+ if (onCancel) {
2911
+ await onCancel();
2912
+ }
2913
+ onClose();
2914
+ };
2915
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2916
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
2917
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
2918
+ ] }) });
2919
+ };
2296
2920
  const ConfigureTheViewAction = ({ collectionType, model }) => {
2297
2921
  const navigate = reactRouterDom.useNavigate();
2298
2922
  const { formatMessage } = reactIntl.useIntl();
@@ -2309,6 +2933,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2309
2933
  };
2310
2934
  };
2311
2935
  ConfigureTheViewAction.type = "configure-the-view";
2936
+ ConfigureTheViewAction.position = "header";
2312
2937
  const EditTheModelAction = ({ model }) => {
2313
2938
  const navigate = reactRouterDom.useNavigate();
2314
2939
  const { formatMessage } = reactIntl.useIntl();
@@ -2325,6 +2950,7 @@ const EditTheModelAction = ({ model }) => {
2325
2950
  };
2326
2951
  };
2327
2952
  EditTheModelAction.type = "edit-the-model";
2953
+ EditTheModelAction.position = "header";
2328
2954
  const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2329
2955
  const navigate = reactRouterDom.useNavigate();
2330
2956
  const { formatMessage } = reactIntl.useIntl();
@@ -2333,12 +2959,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2333
2959
  const { delete: deleteAction } = useDocumentActions();
2334
2960
  const { toggleNotification } = strapiAdmin.useNotification();
2335
2961
  const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
2962
+ const isLocalized = document?.locale != null;
2336
2963
  return {
2337
2964
  disabled: !canDelete || !document,
2338
- label: formatMessage({
2339
- id: "content-manager.actions.delete.label",
2340
- defaultMessage: "Delete document"
2341
- }),
2965
+ label: formatMessage(
2966
+ {
2967
+ id: "content-manager.actions.delete.label",
2968
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2969
+ },
2970
+ { isLocalized }
2971
+ ),
2342
2972
  icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2343
2973
  dialog: {
2344
2974
  type: "dialog",
@@ -2394,403 +3024,102 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2394
3024
  };
2395
3025
  };
2396
3026
  DeleteAction$1.type = "delete";
3027
+ DeleteAction$1.position = ["header", "table-row"];
2397
3028
  const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2398
3029
  const Panels = () => {
2399
3030
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2400
3031
  const [
2401
3032
  {
2402
- query: { status }
2403
- }
2404
- ] = strapiAdmin.useQueryParams({
2405
- status: "draft"
2406
- });
2407
- const { model, id, document, meta, collectionType } = useDoc();
2408
- const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
2409
- const props = {
2410
- activeTab: status,
2411
- model,
2412
- documentId: id,
2413
- document: isCloning ? void 0 : document,
2414
- meta: isCloning ? void 0 : meta,
2415
- collectionType
2416
- };
2417
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
2418
- strapiAdmin.DescriptionComponentRenderer,
2419
- {
2420
- props,
2421
- descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2422
- children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
2423
- }
2424
- ) });
2425
- };
2426
- const ActionsPanel = () => {
2427
- const { formatMessage } = reactIntl.useIntl();
2428
- return {
2429
- title: formatMessage({
2430
- id: "content-manager.containers.edit.panels.default.title",
2431
- defaultMessage: "Document"
2432
- }),
2433
- content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2434
- };
2435
- };
2436
- ActionsPanel.type = "actions";
2437
- const ActionsPanelContent = () => {
2438
- const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2439
- const [
2440
- {
2441
- query: { status = "draft" }
2442
- }
2443
- ] = strapiAdmin.useQueryParams();
2444
- const { model, id, document, meta, collectionType } = useDoc();
2445
- const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
2446
- const props = {
2447
- activeTab: status,
2448
- model,
2449
- documentId: id,
2450
- document: isCloning ? void 0 : document,
2451
- meta: isCloning ? void 0 : meta,
2452
- collectionType
2453
- };
2454
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
2455
- /* @__PURE__ */ jsxRuntime.jsx(
2456
- strapiAdmin.DescriptionComponentRenderer,
2457
- {
2458
- props,
2459
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2460
- children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
2461
- }
2462
- ),
2463
- /* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
2464
- ] });
2465
- };
2466
- const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2467
- return /* @__PURE__ */ jsxRuntime.jsxs(
2468
- designSystem.Flex,
2469
- {
2470
- ref,
2471
- tag: "aside",
2472
- "aria-labelledby": "additional-information",
2473
- background: "neutral0",
2474
- borderColor: "neutral150",
2475
- hasRadius: true,
2476
- paddingBottom: 4,
2477
- paddingLeft: 4,
2478
- paddingRight: 4,
2479
- paddingTop: 4,
2480
- shadow: "tableShadow",
2481
- gap: 3,
2482
- direction: "column",
2483
- justifyContent: "stretch",
2484
- alignItems: "flex-start",
2485
- children: [
2486
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2487
- children
2488
- ]
2489
- }
2490
- );
2491
- });
2492
- const HOOKS = {
2493
- /**
2494
- * Hook that allows to mutate the displayed headers of the list view table
2495
- * @constant
2496
- * @type {string}
2497
- */
2498
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2499
- /**
2500
- * Hook that allows to mutate the CM's collection types links pre-set filters
2501
- * @constant
2502
- * @type {string}
2503
- */
2504
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2505
- /**
2506
- * Hook that allows to mutate the CM's edit view layout
2507
- * @constant
2508
- * @type {string}
2509
- */
2510
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2511
- /**
2512
- * Hook that allows to mutate the CM's single types links pre-set filters
2513
- * @constant
2514
- * @type {string}
2515
- */
2516
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2517
- };
2518
- const contentTypesApi = contentManagerApi.injectEndpoints({
2519
- endpoints: (builder) => ({
2520
- getContentTypeConfiguration: builder.query({
2521
- query: (uid) => ({
2522
- url: `/content-manager/content-types/${uid}/configuration`,
2523
- method: "GET"
2524
- }),
2525
- transformResponse: (response) => response.data,
2526
- providesTags: (_result, _error, uid) => [
2527
- { type: "ContentTypesConfiguration", id: uid },
2528
- { type: "ContentTypeSettings", id: "LIST" }
2529
- ]
2530
- }),
2531
- getAllContentTypeSettings: builder.query({
2532
- query: () => "/content-manager/content-types-settings",
2533
- transformResponse: (response) => response.data,
2534
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2535
- }),
2536
- updateContentTypeConfiguration: builder.mutation({
2537
- query: ({ uid, ...body }) => ({
2538
- url: `/content-manager/content-types/${uid}/configuration`,
2539
- method: "PUT",
2540
- data: body
2541
- }),
2542
- transformResponse: (response) => response.data,
2543
- invalidatesTags: (_result, _error, { uid }) => [
2544
- { type: "ContentTypesConfiguration", id: uid },
2545
- { type: "ContentTypeSettings", id: "LIST" },
2546
- // Is this necessary?
2547
- { type: "InitialData" }
2548
- ]
2549
- })
2550
- })
2551
- });
2552
- const {
2553
- useGetContentTypeConfigurationQuery,
2554
- useGetAllContentTypeSettingsQuery,
2555
- useUpdateContentTypeConfigurationMutation
2556
- } = contentTypesApi;
2557
- const checkIfAttributeIsDisplayable = (attribute) => {
2558
- const { type } = attribute;
2559
- if (type === "relation") {
2560
- return !attribute.relation.toLowerCase().includes("morph");
2561
- }
2562
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2563
- };
2564
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2565
- if (!mainFieldName) {
2566
- return void 0;
2567
- }
2568
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2569
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2570
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2571
- );
2572
- return {
2573
- name: mainFieldName,
2574
- type: mainFieldType ?? "string"
2575
- };
2576
- };
2577
- const DEFAULT_SETTINGS = {
2578
- bulkable: false,
2579
- filterable: false,
2580
- searchable: false,
2581
- pagination: false,
2582
- defaultSortBy: "",
2583
- defaultSortOrder: "asc",
2584
- mainField: "id",
2585
- pageSize: 10
2586
- };
2587
- const useDocumentLayout = (model) => {
2588
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2589
- const [{ query }] = strapiAdmin.useQueryParams();
2590
- const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2591
- const { toggleNotification } = strapiAdmin.useNotification();
2592
- const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2593
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2594
- const {
2595
- data,
2596
- isLoading: isLoadingConfigs,
2597
- error,
2598
- isFetching: isFetchingConfigs
2599
- } = useGetContentTypeConfigurationQuery(model);
2600
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2601
- React__namespace.useEffect(() => {
2602
- if (error) {
2603
- toggleNotification({
2604
- type: "danger",
2605
- message: formatAPIError(error)
2606
- });
2607
- }
2608
- }, [error, formatAPIError, toggleNotification]);
2609
- const editLayout = React__namespace.useMemo(
2610
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2611
- layout: [],
2612
- components: {},
2613
- metadatas: {},
2614
- options: {},
2615
- settings: DEFAULT_SETTINGS
2616
- },
2617
- [data, isLoading, schemas, schema, components]
2618
- );
2619
- const listLayout = React__namespace.useMemo(() => {
2620
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2621
- layout: [],
2622
- metadatas: {},
2623
- options: {},
2624
- settings: DEFAULT_SETTINGS
2625
- };
2626
- }, [data, isLoading, schemas, schema, components]);
2627
- const { layout: edit } = React__namespace.useMemo(
2628
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2629
- layout: editLayout,
2630
- query
2631
- }),
2632
- [editLayout, query, runHookWaterfall]
2633
- );
2634
- return {
2635
- error,
2636
- isLoading,
2637
- edit,
2638
- list: listLayout
2639
- };
2640
- };
2641
- const useDocLayout = () => {
2642
- const { model } = useDoc();
2643
- return useDocumentLayout(model);
2644
- };
2645
- const formatEditLayout = (data, {
2646
- schemas,
2647
- schema,
2648
- components
2649
- }) => {
2650
- let currentPanelIndex = 0;
2651
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2652
- data.contentType.layouts.edit,
2653
- schema?.attributes,
2654
- data.contentType.metadatas,
2655
- { configurations: data.components, schemas: components },
2656
- schemas
2657
- ).reduce((panels, row) => {
2658
- if (row.some((field) => field.type === "dynamiczone")) {
2659
- panels.push([row]);
2660
- currentPanelIndex += 2;
2661
- } else {
2662
- if (!panels[currentPanelIndex]) {
2663
- panels.push([]);
2664
- }
2665
- panels[currentPanelIndex].push(row);
2666
- }
2667
- return panels;
2668
- }, []);
2669
- const componentEditAttributes = Object.entries(data.components).reduce(
2670
- (acc, [uid, configuration]) => {
2671
- acc[uid] = {
2672
- layout: convertEditLayoutToFieldLayouts(
2673
- configuration.layouts.edit,
2674
- components[uid].attributes,
2675
- configuration.metadatas
2676
- ),
2677
- settings: {
2678
- ...configuration.settings,
2679
- icon: components[uid].info.icon,
2680
- displayName: components[uid].info.displayName
2681
- }
2682
- };
2683
- return acc;
2684
- },
2685
- {}
2686
- );
2687
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2688
- (acc, [attribute, metadata]) => {
2689
- return {
2690
- ...acc,
2691
- [attribute]: metadata.edit
2692
- };
2693
- },
2694
- {}
2695
- );
2696
- return {
2697
- layout: panelledEditAttributes,
2698
- components: componentEditAttributes,
2699
- metadatas: editMetadatas,
2700
- settings: {
2701
- ...data.contentType.settings,
2702
- displayName: schema?.info.displayName
2703
- },
2704
- options: {
2705
- ...schema?.options,
2706
- ...schema?.pluginOptions,
2707
- ...data.contentType.options
3033
+ query: { status }
2708
3034
  }
3035
+ ] = strapiAdmin.useQueryParams({
3036
+ status: "draft"
3037
+ });
3038
+ const { model, id, document, meta, collectionType } = useDoc();
3039
+ const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
3040
+ const props = {
3041
+ activeTab: status,
3042
+ model,
3043
+ documentId: id,
3044
+ document: isCloning ? void 0 : document,
3045
+ meta: isCloning ? void 0 : meta,
3046
+ collectionType
2709
3047
  };
3048
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
3049
+ strapiAdmin.DescriptionComponentRenderer,
3050
+ {
3051
+ props,
3052
+ descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
3053
+ children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
3054
+ }
3055
+ ) });
2710
3056
  };
2711
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2712
- return rows.map(
2713
- (row) => row.map((field) => {
2714
- const attribute = attributes[field.name];
2715
- if (!attribute) {
2716
- return null;
2717
- }
2718
- const { edit: metadata } = metadatas[field.name];
2719
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2720
- return {
2721
- attribute,
2722
- disabled: !metadata.editable,
2723
- hint: metadata.description,
2724
- label: metadata.label ?? "",
2725
- name: field.name,
2726
- // @ts-expect-error – mainField does exist on the metadata for a relation.
2727
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2728
- schemas,
2729
- components: components?.schemas ?? {}
2730
- }),
2731
- placeholder: metadata.placeholder ?? "",
2732
- required: attribute.required ?? false,
2733
- size: field.size,
2734
- unique: "unique" in attribute ? attribute.unique : false,
2735
- visible: metadata.visible ?? true,
2736
- type: attribute.type
2737
- };
2738
- }).filter((field) => field !== null)
2739
- );
2740
- };
2741
- const formatListLayout = (data, {
2742
- schemas,
2743
- schema,
2744
- components
2745
- }) => {
2746
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2747
- (acc, [attribute, metadata]) => {
2748
- return {
2749
- ...acc,
2750
- [attribute]: metadata.list
2751
- };
2752
- },
2753
- {}
2754
- );
2755
- const listAttributes = convertListLayoutToFieldLayouts(
2756
- data.contentType.layouts.list,
2757
- schema?.attributes,
2758
- listMetadatas,
2759
- { configurations: data.components, schemas: components },
2760
- schemas
2761
- );
3057
+ const ActionsPanel = () => {
3058
+ const { formatMessage } = reactIntl.useIntl();
2762
3059
  return {
2763
- layout: listAttributes,
2764
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2765
- metadatas: listMetadatas,
2766
- options: {
2767
- ...schema?.options,
2768
- ...schema?.pluginOptions,
2769
- ...data.contentType.options
2770
- }
3060
+ title: formatMessage({
3061
+ id: "content-manager.containers.edit.panels.default.title",
3062
+ defaultMessage: "Entry"
3063
+ }),
3064
+ content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2771
3065
  };
2772
3066
  };
2773
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2774
- return columns.map((name) => {
2775
- const attribute = attributes[name];
2776
- if (!attribute) {
2777
- return null;
3067
+ ActionsPanel.type = "actions";
3068
+ const ActionsPanelContent = () => {
3069
+ const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
3070
+ const [
3071
+ {
3072
+ query: { status = "draft" }
2778
3073
  }
2779
- const metadata = metadatas[name];
2780
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2781
- return {
2782
- attribute,
2783
- label: metadata.label ?? "",
2784
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2785
- schemas,
2786
- components: components?.schemas ?? {}
2787
- }),
2788
- name,
2789
- searchable: metadata.searchable ?? true,
2790
- sortable: metadata.sortable ?? true
2791
- };
2792
- }).filter((field) => field !== null);
3074
+ ] = strapiAdmin.useQueryParams();
3075
+ const { model, id, document, meta, collectionType } = useDoc();
3076
+ const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
3077
+ const props = {
3078
+ activeTab: status,
3079
+ model,
3080
+ documentId: id,
3081
+ document: isCloning ? void 0 : document,
3082
+ meta: isCloning ? void 0 : meta,
3083
+ collectionType
3084
+ };
3085
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
3086
+ /* @__PURE__ */ jsxRuntime.jsx(
3087
+ strapiAdmin.DescriptionComponentRenderer,
3088
+ {
3089
+ props,
3090
+ descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
3091
+ children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
3092
+ }
3093
+ ),
3094
+ /* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
3095
+ ] });
2793
3096
  };
3097
+ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
3098
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3099
+ designSystem.Flex,
3100
+ {
3101
+ ref,
3102
+ tag: "aside",
3103
+ "aria-labelledby": "additional-information",
3104
+ background: "neutral0",
3105
+ borderColor: "neutral150",
3106
+ hasRadius: true,
3107
+ paddingBottom: 4,
3108
+ paddingLeft: 4,
3109
+ paddingRight: 4,
3110
+ paddingTop: 4,
3111
+ shadow: "tableShadow",
3112
+ gap: 3,
3113
+ direction: "column",
3114
+ justifyContent: "stretch",
3115
+ alignItems: "flex-start",
3116
+ children: [
3117
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
3118
+ children
3119
+ ]
3120
+ }
3121
+ );
3122
+ });
2794
3123
  const ConfirmBulkActionDialog = ({
2795
3124
  onToggleDialog,
2796
3125
  isOpen = false,
@@ -2798,7 +3127,7 @@ const ConfirmBulkActionDialog = ({
2798
3127
  endAction
2799
3128
  }) => {
2800
3129
  const { formatMessage } = reactIntl.useIntl();
2801
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
3130
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2802
3131
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2803
3132
  id: "app.components.ConfirmDialog.title",
2804
3133
  defaultMessage: "Confirmation"
@@ -2829,6 +3158,7 @@ const ConfirmDialogPublishAll = ({
2829
3158
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2830
3159
  const { model, schema } = useDoc();
2831
3160
  const [{ query }] = strapiAdmin.useQueryParams();
3161
+ const enableDraftRelationsCount = false;
2832
3162
  const {
2833
3163
  data: countDraftRelations = 0,
2834
3164
  isLoading,
@@ -2840,7 +3170,7 @@ const ConfirmDialogPublishAll = ({
2840
3170
  locale: query?.plugins?.i18n?.locale
2841
3171
  },
2842
3172
  {
2843
- skip: selectedEntries.length === 0
3173
+ skip: !enableDraftRelationsCount
2844
3174
  }
2845
3175
  );
2846
3176
  React__namespace.useEffect(() => {
@@ -2919,7 +3249,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2919
3249
  )
2920
3250
  );
2921
3251
  } else {
2922
- messages.push(...formatErrorMessages(value, currentKey, formatMessage));
3252
+ messages.push(
3253
+ ...formatErrorMessages(
3254
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3255
+ value,
3256
+ currentKey,
3257
+ formatMessage
3258
+ )
3259
+ );
2923
3260
  }
2924
3261
  } else {
2925
3262
  messages.push(
@@ -3018,7 +3355,7 @@ const SelectedEntriesTableContent = ({
3018
3355
  status: row.status
3019
3356
  }
3020
3357
  ) }),
3021
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3358
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
3022
3359
  designSystem.IconButton,
3023
3360
  {
3024
3361
  tag: reactRouterDom.Link,
@@ -3027,23 +3364,16 @@ const SelectedEntriesTableContent = ({
3027
3364
  search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3028
3365
  },
3029
3366
  state: { from: pathname },
3030
- label: formatMessage(
3031
- { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3032
- {
3033
- target: formatMessage(
3034
- {
3035
- id: "content-manager.components.ListViewHelperPluginTable.row-line",
3036
- defaultMessage: "item line {number}"
3037
- },
3038
- { number: index2 + 1 }
3039
- )
3040
- }
3041
- ),
3367
+ label: formatMessage({
3368
+ id: "content-manager.bulk-publish.edit",
3369
+ defaultMessage: "Edit"
3370
+ }),
3042
3371
  target: "_blank",
3043
3372
  marginLeft: "auto",
3044
- children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3373
+ variant: "ghost",
3374
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
3045
3375
  }
3046
- ) })
3376
+ ) }) })
3047
3377
  ] }, row.id)) })
3048
3378
  ] });
3049
3379
  };
@@ -3080,7 +3410,13 @@ const SelectedEntriesModalContent = ({
3080
3410
  );
3081
3411
  const { rows, validationErrors } = React__namespace.useMemo(() => {
3082
3412
  if (data.length > 0 && schema) {
3083
- const validate = createYupSchema(schema.attributes, components);
3413
+ const validate = createYupSchema(
3414
+ schema.attributes,
3415
+ components,
3416
+ // Since this is the "Publish" action, the validation
3417
+ // schema must enforce the rules for published entities
3418
+ { status: "published" }
3419
+ );
3084
3420
  const validationErrors2 = {};
3085
3421
  const rows2 = data.map((entry) => {
3086
3422
  try {
@@ -3205,8 +3541,7 @@ const PublishAction = ({ documents, model }) => {
3205
3541
  const refetchList = () => {
3206
3542
  contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3207
3543
  };
3208
- if (!showPublishButton)
3209
- return null;
3544
+ if (!showPublishButton) return null;
3210
3545
  return {
3211
3546
  actionType: "publish",
3212
3547
  variant: "tertiary",
@@ -3274,8 +3609,7 @@ const DeleteAction = ({ documents, model }) => {
3274
3609
  selectRow([]);
3275
3610
  }
3276
3611
  };
3277
- if (!hasDeletePermission)
3278
- return null;
3612
+ if (!hasDeletePermission) return null;
3279
3613
  return {
3280
3614
  variant: "danger-light",
3281
3615
  label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
@@ -3324,8 +3658,7 @@ const UnpublishAction = ({ documents, model }) => {
3324
3658
  }
3325
3659
  };
3326
3660
  const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3327
- if (!showUnpublishButton)
3328
- return null;
3661
+ if (!showUnpublishButton) return null;
3329
3662
  return {
3330
3663
  variant: "tertiary",
3331
3664
  label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
@@ -3430,7 +3763,7 @@ const TableActions = ({ document }) => {
3430
3763
  strapiAdmin.DescriptionComponentRenderer,
3431
3764
  {
3432
3765
  props,
3433
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3766
+ descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
3434
3767
  children: (actions2) => {
3435
3768
  const tableRowActions = actions2.filter((action) => {
3436
3769
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3489,6 +3822,7 @@ const EditAction = ({ documentId }) => {
3489
3822
  };
3490
3823
  };
3491
3824
  EditAction.type = "edit";
3825
+ EditAction.position = "table-row";
3492
3826
  const StyledPencil = styledComponents.styled(Icons.Pencil)`
3493
3827
  path {
3494
3828
  fill: currentColor;
@@ -3541,7 +3875,7 @@ const CloneAction = ({ model, documentId }) => {
3541
3875
  }),
3542
3876
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3543
3877
  footer: ({ onClose }) => {
3544
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3878
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3545
3879
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3546
3880
  id: "cancel",
3547
3881
  defaultMessage: "Cancel"
@@ -3565,6 +3899,7 @@ const CloneAction = ({ model, documentId }) => {
3565
3899
  };
3566
3900
  };
3567
3901
  CloneAction.type = "clone";
3902
+ CloneAction.position = "table-row";
3568
3903
  const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
3569
3904
  path {
3570
3905
  fill: currentColor;
@@ -3582,8 +3917,7 @@ class ContentManagerPlugin {
3582
3917
  documentActions = [
3583
3918
  ...DEFAULT_ACTIONS,
3584
3919
  ...DEFAULT_TABLE_ROW_ACTIONS,
3585
- ...DEFAULT_HEADER_ACTIONS,
3586
- HistoryAction
3920
+ ...DEFAULT_HEADER_ACTIONS
3587
3921
  ];
3588
3922
  editViewSidePanels = [ActionsPanel];
3589
3923
  headerActions = [];
@@ -3652,7 +3986,14 @@ class ContentManagerPlugin {
3652
3986
  addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3653
3987
  addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3654
3988
  getBulkActions: () => this.bulkActions,
3655
- getDocumentActions: () => this.documentActions,
3989
+ getDocumentActions: (position) => {
3990
+ if (position) {
3991
+ return this.documentActions.filter(
3992
+ (action) => action.position == void 0 || [action.position].flat().includes(position)
3993
+ );
3994
+ }
3995
+ return this.documentActions;
3996
+ },
3656
3997
  getEditViewSidePanels: () => this.editViewSidePanels,
3657
3998
  getHeaderActions: () => this.headerActions
3658
3999
  }
@@ -3662,16 +4003,71 @@ class ContentManagerPlugin {
3662
4003
  const getPrintableType = (value) => {
3663
4004
  const nativeType = typeof value;
3664
4005
  if (nativeType === "object") {
3665
- if (value === null)
3666
- return "null";
3667
- if (Array.isArray(value))
3668
- return "array";
4006
+ if (value === null) return "null";
4007
+ if (Array.isArray(value)) return "array";
3669
4008
  if (value instanceof Object && value.constructor.name !== "Object") {
3670
4009
  return value.constructor.name;
3671
4010
  }
3672
4011
  }
3673
4012
  return nativeType;
3674
4013
  };
4014
+ const HistoryAction = ({ model, document }) => {
4015
+ const { formatMessage } = reactIntl.useIntl();
4016
+ const [{ query }] = strapiAdmin.useQueryParams();
4017
+ const navigate = reactRouterDom.useNavigate();
4018
+ const { trackUsage } = strapiAdmin.useTracking();
4019
+ const { pathname } = reactRouterDom.useLocation();
4020
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
4021
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
4022
+ return null;
4023
+ }
4024
+ const handleOnClick = () => {
4025
+ const destination = { pathname: "history", search: pluginsQueryParams };
4026
+ trackUsage("willNavigate", {
4027
+ from: pathname,
4028
+ to: `${pathname}/${destination.pathname}`
4029
+ });
4030
+ navigate(destination);
4031
+ };
4032
+ return {
4033
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
4034
+ label: formatMessage({
4035
+ id: "content-manager.history.document-action",
4036
+ defaultMessage: "Content History"
4037
+ }),
4038
+ onClick: handleOnClick,
4039
+ disabled: (
4040
+ /**
4041
+ * The user is creating a new document.
4042
+ * It hasn't been saved yet, so there's no history to go to
4043
+ */
4044
+ !document || /**
4045
+ * The document has been created but the current dimension has never been saved.
4046
+ * For example, the user is creating a new locale in an existing document,
4047
+ * so there's no history for the document in that locale
4048
+ */
4049
+ !document.id || /**
4050
+ * History is only available for content types created by the user.
4051
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
4052
+ * which start with `admin::` or `plugin::`
4053
+ */
4054
+ !model.startsWith("api::")
4055
+ ),
4056
+ position: "header"
4057
+ };
4058
+ };
4059
+ HistoryAction.type = "history";
4060
+ HistoryAction.position = "header";
4061
+ const historyAdmin = {
4062
+ bootstrap(app) {
4063
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
4064
+ addDocumentAction((actions2) => {
4065
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
4066
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
4067
+ return actions2;
4068
+ });
4069
+ }
4070
+ };
3675
4071
  const initialState = {
3676
4072
  collectionTypeLinks: [],
3677
4073
  components: [],
@@ -3708,6 +4104,88 @@ const { setInitialData } = actions;
3708
4104
  const reducer = toolkit.combineReducers({
3709
4105
  app: reducer$1
3710
4106
  });
4107
+ const previewApi = contentManagerApi.injectEndpoints({
4108
+ endpoints: (builder) => ({
4109
+ getPreviewUrl: builder.query({
4110
+ query({ query, params }) {
4111
+ return {
4112
+ url: `/content-manager/preview/url/${params.contentType}`,
4113
+ method: "GET",
4114
+ config: {
4115
+ params: query
4116
+ }
4117
+ };
4118
+ }
4119
+ })
4120
+ })
4121
+ });
4122
+ const { useGetPreviewUrlQuery } = previewApi;
4123
+ const ConditionalTooltip = ({ isShown, label, children }) => {
4124
+ if (isShown) {
4125
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { label, children });
4126
+ }
4127
+ return children;
4128
+ };
4129
+ const PreviewSidePanel = ({ model, documentId, document }) => {
4130
+ const { formatMessage } = reactIntl.useIntl();
4131
+ const { trackUsage } = strapiAdmin.useTracking();
4132
+ const { pathname } = reactRouterDom.useLocation();
4133
+ const [{ query }] = strapiAdmin.useQueryParams();
4134
+ const isModified = strapiAdmin.useForm("PreviewSidePanel", (state) => state.modified);
4135
+ const { data, error } = useGetPreviewUrlQuery({
4136
+ params: {
4137
+ contentType: model
4138
+ },
4139
+ query: {
4140
+ documentId,
4141
+ locale: document?.locale,
4142
+ status: document?.status
4143
+ }
4144
+ });
4145
+ if (!data?.data?.url || error) {
4146
+ return null;
4147
+ }
4148
+ const trackNavigation = () => {
4149
+ const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
4150
+ trackUsage("willNavigate", { from: pathname, to: destinationPathname });
4151
+ };
4152
+ return {
4153
+ title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
4154
+ content: /* @__PURE__ */ jsxRuntime.jsx(
4155
+ ConditionalTooltip,
4156
+ {
4157
+ label: formatMessage({
4158
+ id: "content-manager.preview.panel.button-disabled-tooltip",
4159
+ defaultMessage: "Please save to open the preview"
4160
+ }),
4161
+ isShown: isModified,
4162
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
4163
+ designSystem.Button,
4164
+ {
4165
+ variant: "tertiary",
4166
+ tag: reactRouterDom.Link,
4167
+ to: { pathname: "preview", search: qs.stringify(query, { encode: false }) },
4168
+ onClick: trackNavigation,
4169
+ width: "100%",
4170
+ disabled: isModified,
4171
+ pointerEvents: isModified ? "none" : void 0,
4172
+ tabIndex: isModified ? -1 : void 0,
4173
+ children: formatMessage({
4174
+ id: "content-manager.preview.panel.button",
4175
+ defaultMessage: "Open preview"
4176
+ })
4177
+ }
4178
+ ) })
4179
+ }
4180
+ )
4181
+ };
4182
+ };
4183
+ const previewAdmin = {
4184
+ bootstrap(app) {
4185
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
4186
+ contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
4187
+ }
4188
+ };
3711
4189
  const index = {
3712
4190
  register(app) {
3713
4191
  const cm = new ContentManagerPlugin();
@@ -3727,7 +4205,7 @@ const index = {
3727
4205
  app.router.addRoute({
3728
4206
  path: "content-manager/*",
3729
4207
  lazy: async () => {
3730
- const { Layout } = await Promise.resolve().then(() => require("./layout-Dm6fbiQj.js"));
4208
+ const { Layout } = await Promise.resolve().then(() => require("./layout-B_qdWGny.js"));
3731
4209
  return {
3732
4210
  Component: Layout
3733
4211
  };
@@ -3736,10 +4214,18 @@ const index = {
3736
4214
  });
3737
4215
  app.registerPlugin(cm.config);
3738
4216
  },
4217
+ bootstrap(app) {
4218
+ if (typeof historyAdmin.bootstrap === "function") {
4219
+ historyAdmin.bootstrap(app);
4220
+ }
4221
+ if (typeof previewAdmin.bootstrap === "function") {
4222
+ previewAdmin.bootstrap(app);
4223
+ }
4224
+ },
3739
4225
  async registerTrads({ locales }) {
3740
4226
  const importedTrads = await Promise.all(
3741
4227
  locales.map((locale) => {
3742
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-fbKQxLGn.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
4228
+ 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-BK8Xyl5I.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 }) => {
3743
4229
  return {
3744
4230
  data: prefixPluginTranslations(data, PLUGIN_ID),
3745
4231
  locale
@@ -3757,6 +4243,7 @@ const index = {
3757
4243
  };
3758
4244
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3759
4245
  exports.BulkActionsRenderer = BulkActionsRenderer;
4246
+ exports.CLONE_PATH = CLONE_PATH;
3760
4247
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3761
4248
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3762
4249
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3784,6 +4271,7 @@ exports.getMainField = getMainField;
3784
4271
  exports.getTranslation = getTranslation;
3785
4272
  exports.index = index;
3786
4273
  exports.setInitialData = setInitialData;
4274
+ exports.useContentManagerContext = useContentManagerContext;
3787
4275
  exports.useContentTypeSchema = useContentTypeSchema;
3788
4276
  exports.useDoc = useDoc;
3789
4277
  exports.useDocLayout = useDocLayout;
@@ -3795,5 +4283,6 @@ exports.useGetAllContentTypeSettingsQuery = useGetAllContentTypeSettingsQuery;
3795
4283
  exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3796
4284
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3797
4285
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
4286
+ exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
3798
4287
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3799
- //# sourceMappingURL=index-DVPWZkbS.js.map
4288
+ //# sourceMappingURL=index-CnX_j5h-.js.map