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

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-DmwmiFQy.mjs → ComponentConfigurationPage-D4J64ny7.mjs} +4 -4
  5. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-D4J64ny7.mjs.map} +1 -1
  6. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-DHV8IFbd.js} +5 -6
  7. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-DHV8IFbd.js.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-JT3E7NZy.mjs → EditConfigurationPage-DMnf8orh.mjs} +4 -4
  12. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-DMnf8orh.mjs.map} +1 -1
  13. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-q76oeVU1.js} +5 -6
  14. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-q76oeVU1.js.map} +1 -1
  15. package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-BXoY-ITh.js} +63 -13
  16. package/dist/_chunks/EditViewPage-BXoY-ITh.js.map +1 -0
  17. package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-COVXj9bh.mjs} +63 -12
  18. package/dist/_chunks/EditViewPage-COVXj9bh.mjs.map +1 -0
  19. package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-CcppsFQR.mjs} +300 -203
  20. package/dist/_chunks/Field-CcppsFQR.mjs.map +1 -0
  21. package/dist/_chunks/{Field-Boxf9Ajp.js → Field-Dj1nOvt8.js} +303 -207
  22. package/dist/_chunks/Field-Dj1nOvt8.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-DbWwH0-A.mjs} +37 -18
  26. package/dist/_chunks/Form-DbWwH0-A.mjs.map +1 -0
  27. package/dist/_chunks/{Form-y5g1SRsh.js → Form-aTchNxab.js} +39 -21
  28. package/dist/_chunks/Form-aTchNxab.js.map +1 -0
  29. package/dist/_chunks/{History-CqN6K7SX.js → History-Cs6XM6EU.js} +81 -114
  30. package/dist/_chunks/History-Cs6XM6EU.js.map +1 -0
  31. package/dist/_chunks/{History-Bru_KoeP.mjs → History-tU567_hc.mjs} +82 -114
  32. package/dist/_chunks/History-tU567_hc.mjs.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-7LeytuFD.js} +25 -13
  34. package/dist/_chunks/ListConfigurationPage-7LeytuFD.js.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-DQryo_4i.mjs} +25 -12
  36. package/dist/_chunks/ListConfigurationPage-DQryo_4i.mjs.map +1 -0
  37. package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-B50esy_x.mjs} +118 -77
  38. package/dist/_chunks/ListViewPage-B50esy_x.mjs.map +1 -0
  39. package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-CaGBu5H5.js} +121 -81
  40. package/dist/_chunks/ListViewPage-CaGBu5H5.js.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-BaBE00IO.js} +2 -2
  42. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-BaBE00IO.js.map} +1 -1
  43. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-CiPP8cLx.mjs} +2 -2
  44. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-CiPP8cLx.mjs.map} +1 -1
  45. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-0-CW106p.mjs} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-0-CW106p.mjs.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-DQn5cqZz.js} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-DQn5cqZz.js.map} +1 -1
  49. package/dist/_chunks/Preview-C1dBkhXf.mjs +272 -0
  50. package/dist/_chunks/Preview-C1dBkhXf.mjs.map +1 -0
  51. package/dist/_chunks/Preview-DH1h7kJ6.js +290 -0
  52. package/dist/_chunks/Preview-DH1h7kJ6.js.map +1 -0
  53. package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-Bvne4TvU.mjs} +76 -42
  54. package/dist/_chunks/Relations-Bvne4TvU.mjs.map +1 -0
  55. package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-CkECnBOd.js} +76 -43
  56. package/dist/_chunks/Relations-CkECnBOd.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-BN1pPa5v.js} +1135 -693
  71. package/dist/_chunks/index-BN1pPa5v.js.map +1 -0
  72. package/dist/_chunks/{index-DJXJw9V5.mjs → index-ByPZ754U.mjs} +1156 -714
  73. package/dist/_chunks/index-ByPZ754U.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-CUTOYU8I.mjs} +26 -13
  79. package/dist/_chunks/layout-CUTOYU8I.mjs.map +1 -0
  80. package/dist/_chunks/{layout-Dm6fbiQj.js → layout-nBPDlXjr.js} +26 -14
  81. package/dist/_chunks/layout-nBPDlXjr.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-B6B-b7lI.js} +6 -7
  87. package/dist/_chunks/relations-B6B-b7lI.js.map +1 -0
  88. package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-CBc5HYHC.mjs} +6 -7
  89. package/dist/_chunks/relations-CBc5HYHC.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/Relations.d.ts +20 -0
  111. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  112. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  113. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  114. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  115. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  116. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  117. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  118. package/dist/admin/src/preview/constants.d.ts +1 -0
  119. package/dist/admin/src/preview/index.d.ts +4 -0
  120. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  121. package/dist/admin/src/preview/routes.d.ts +3 -0
  122. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  123. package/dist/admin/src/router.d.ts +1 -1
  124. package/dist/admin/src/services/api.d.ts +1 -1
  125. package/dist/admin/src/services/components.d.ts +2 -2
  126. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  127. package/dist/admin/src/services/documents.d.ts +19 -20
  128. package/dist/admin/src/services/init.d.ts +1 -1
  129. package/dist/admin/src/services/relations.d.ts +2 -2
  130. package/dist/admin/src/services/uid.d.ts +3 -3
  131. package/dist/admin/src/utils/validation.d.ts +4 -1
  132. package/dist/server/index.js +615 -299
  133. package/dist/server/index.js.map +1 -1
  134. package/dist/server/index.mjs +615 -298
  135. package/dist/server/index.mjs.map +1 -1
  136. package/dist/server/src/bootstrap.d.ts.map +1 -1
  137. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  138. package/dist/server/src/controllers/index.d.ts.map +1 -1
  139. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  140. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  141. package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
  142. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  143. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  144. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  145. package/dist/server/src/history/services/history.d.ts.map +1 -1
  146. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  147. package/dist/server/src/history/services/utils.d.ts +4 -4
  148. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  149. package/dist/server/src/index.d.ts +4 -4
  150. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  151. package/dist/server/src/preview/constants.d.ts +2 -0
  152. package/dist/server/src/preview/constants.d.ts.map +1 -0
  153. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  154. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  155. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  156. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  157. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  158. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  159. package/dist/server/src/preview/index.d.ts +4 -0
  160. package/dist/server/src/preview/index.d.ts.map +1 -0
  161. package/dist/server/src/preview/routes/index.d.ts +8 -0
  162. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  163. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  164. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  165. package/dist/server/src/preview/services/index.d.ts +16 -0
  166. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  167. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  168. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  169. package/dist/server/src/preview/services/preview.d.ts +12 -0
  170. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  171. package/dist/server/src/preview/utils.d.ts +19 -0
  172. package/dist/server/src/preview/utils.d.ts.map +1 -0
  173. package/dist/server/src/register.d.ts.map +1 -1
  174. package/dist/server/src/routes/index.d.ts.map +1 -1
  175. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  176. package/dist/server/src/services/document-metadata.d.ts +8 -8
  177. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  178. package/dist/server/src/services/index.d.ts +4 -4
  179. package/dist/server/src/services/index.d.ts.map +1 -1
  180. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  181. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  182. package/dist/server/src/services/utils/configuration/layouts.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 +15 -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,7 +246,8 @@ const documentApi = contentManagerApi.injectEndpoints({
257
246
  }),
258
247
  invalidatesTags: (result, _error, { model }) => [
259
248
  { type: "Document", id: `${model}_LIST` },
260
- "Relations"
249
+ "Relations",
250
+ { type: "UidAvailability", id: model }
261
251
  ]
262
252
  }),
263
253
  deleteDocument: builder.mutation({
@@ -298,7 +288,8 @@ const documentApi = contentManagerApi.injectEndpoints({
298
288
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
299
289
  },
300
290
  { type: "Document", id: `${model}_LIST` },
301
- "Relations"
291
+ "Relations",
292
+ { type: "UidAvailability", id: model }
302
293
  ];
303
294
  }
304
295
  }),
@@ -311,11 +302,12 @@ const documentApi = contentManagerApi.injectEndpoints({
311
302
  url: `/content-manager/collection-types/${model}`,
312
303
  method: "GET",
313
304
  config: {
314
- params
305
+ params: qs.stringify(params, { encode: true })
315
306
  }
316
307
  }),
317
308
  providesTags: (result, _error, arg) => {
318
309
  return [
310
+ { type: "Document", id: `ALL_LIST` },
319
311
  { type: "Document", id: `${arg.model}_LIST` },
320
312
  ...result?.results.map(({ documentId }) => ({
321
313
  type: "Document",
@@ -354,6 +346,11 @@ const documentApi = contentManagerApi.injectEndpoints({
354
346
  {
355
347
  type: "Document",
356
348
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
349
+ },
350
+ // Make it easy to invalidate all individual documents queries for a model
351
+ {
352
+ type: "Document",
353
+ id: `${model}_ALL_ITEMS`
357
354
  }
358
355
  ];
359
356
  }
@@ -417,8 +414,21 @@ const documentApi = contentManagerApi.injectEndpoints({
417
414
  type: "Document",
418
415
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
419
416
  },
420
- "Relations"
417
+ "Relations",
418
+ { type: "UidAvailability", id: model }
421
419
  ];
420
+ },
421
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
422
+ const patchResult = dispatch(
423
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
424
+ Object.assign(draft.data, data);
425
+ })
426
+ );
427
+ try {
428
+ await queryFulfilled;
429
+ } catch {
430
+ patchResult.undo();
431
+ }
422
432
  }
423
433
  }),
424
434
  unpublishDocument: builder.mutation({
@@ -471,8 +481,7 @@ const {
471
481
  useUnpublishManyDocumentsMutation
472
482
  } = documentApi;
473
483
  const buildValidParams = (query) => {
474
- if (!query)
475
- return query;
484
+ if (!query) return query;
476
485
  const { plugins: _, ...validQueryParams } = {
477
486
  ...query,
478
487
  ...Object.values(query?.plugins ?? {}).reduce(
@@ -480,28 +489,44 @@ const buildValidParams = (query) => {
480
489
  {}
481
490
  )
482
491
  };
483
- if ("_q" in validQueryParams) {
484
- validQueryParams._q = encodeURIComponent(validQueryParams._q);
485
- }
486
492
  return validQueryParams;
487
493
  };
488
494
  const isBaseQueryError = (error) => {
489
495
  return error.name !== void 0;
490
496
  };
491
- const createYupSchema = (attributes = {}, components = {}) => {
497
+ const arrayValidator = (attribute, options) => ({
498
+ message: strapiAdmin.translatedErrors.required,
499
+ test(value) {
500
+ if (options.status === "draft") {
501
+ return true;
502
+ }
503
+ if (!attribute.required) {
504
+ return true;
505
+ }
506
+ if (!value) {
507
+ return false;
508
+ }
509
+ if (Array.isArray(value) && value.length === 0) {
510
+ return false;
511
+ }
512
+ return true;
513
+ }
514
+ });
515
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
492
516
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
493
517
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
494
518
  if (DOCUMENT_META_FIELDS.includes(name)) {
495
519
  return acc;
496
520
  }
497
521
  const validations = [
522
+ addNullableValidation,
498
523
  addRequiredValidation,
499
524
  addMinLengthValidation,
500
525
  addMaxLengthValidation,
501
526
  addMinValidation,
502
527
  addMaxValidation,
503
528
  addRegexValidation
504
- ].map((fn) => fn(attribute));
529
+ ].map((fn) => fn(attribute, options));
505
530
  const transformSchema = pipe__default.default(...validations);
506
531
  switch (attribute.type) {
507
532
  case "component": {
@@ -511,12 +536,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
511
536
  ...acc,
512
537
  [name]: transformSchema(
513
538
  yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
514
- )
539
+ ).test(arrayValidator(attribute, options))
515
540
  };
516
541
  } else {
517
542
  return {
518
543
  ...acc,
519
- [name]: transformSchema(createModelSchema(attributes3))
544
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
520
545
  };
521
546
  }
522
547
  }
@@ -538,7 +563,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
538
563
  }
539
564
  )
540
565
  )
541
- )
566
+ ).test(arrayValidator(attribute, options))
542
567
  };
543
568
  case "relation":
544
569
  return {
@@ -550,7 +575,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
550
575
  } else if (Array.isArray(value)) {
551
576
  return yup__namespace.array().of(
552
577
  yup__namespace.object().shape({
553
- id: yup__namespace.string().required()
578
+ id: yup__namespace.number().required()
554
579
  })
555
580
  );
556
581
  } else if (typeof value === "object") {
@@ -602,6 +627,14 @@ const createAttributeSchema = (attribute) => {
602
627
  if (!value || typeof value === "string" && value.length === 0) {
603
628
  return true;
604
629
  }
630
+ if (typeof value === "object") {
631
+ try {
632
+ JSON.stringify(value);
633
+ return true;
634
+ } catch (err) {
635
+ return false;
636
+ }
637
+ }
605
638
  try {
606
639
  JSON.parse(value);
607
640
  return true;
@@ -620,13 +653,7 @@ const createAttributeSchema = (attribute) => {
620
653
  return yup__namespace.mixed();
621
654
  }
622
655
  };
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
- }
656
+ const nullableSchema = (schema) => {
630
657
  return schema?.nullable ? schema.nullable() : (
631
658
  // In some cases '.nullable' will not be available on the schema.
632
659
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -634,7 +661,22 @@ const addRequiredValidation = (attribute) => (schema) => {
634
661
  schema
635
662
  );
636
663
  };
637
- const addMinLengthValidation = (attribute) => (schema) => {
664
+ const addNullableValidation = () => (schema) => {
665
+ return nullableSchema(schema);
666
+ };
667
+ const addRequiredValidation = (attribute, options) => (schema) => {
668
+ if (options.status === "draft" || !attribute.required) {
669
+ return schema;
670
+ }
671
+ if (attribute.required && "required" in schema) {
672
+ return schema.required(strapiAdmin.translatedErrors.required);
673
+ }
674
+ return schema;
675
+ };
676
+ const addMinLengthValidation = (attribute, options) => (schema) => {
677
+ if (options.status === "draft") {
678
+ return schema;
679
+ }
638
680
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
639
681
  return schema.min(attribute.minLength, {
640
682
  ...strapiAdmin.translatedErrors.minLength,
@@ -656,10 +698,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
656
698
  }
657
699
  return schema;
658
700
  };
659
- const addMinValidation = (attribute) => (schema) => {
660
- if ("min" in attribute) {
701
+ const addMinValidation = (attribute, options) => (schema) => {
702
+ if (options.status === "draft") {
703
+ return schema;
704
+ }
705
+ if ("min" in attribute && "min" in schema) {
661
706
  const min = toInteger(attribute.min);
662
- if ("min" in schema && min) {
707
+ if (min) {
663
708
  return schema.min(min, {
664
709
  ...strapiAdmin.translatedErrors.min,
665
710
  values: {
@@ -777,16 +822,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
777
822
  }, {});
778
823
  return componentsByKey;
779
824
  };
780
- const useDocument = (args, opts) => {
825
+ const HOOKS = {
826
+ /**
827
+ * Hook that allows to mutate the displayed headers of the list view table
828
+ * @constant
829
+ * @type {string}
830
+ */
831
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
832
+ /**
833
+ * Hook that allows to mutate the CM's collection types links pre-set filters
834
+ * @constant
835
+ * @type {string}
836
+ */
837
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
838
+ /**
839
+ * Hook that allows to mutate the CM's edit view layout
840
+ * @constant
841
+ * @type {string}
842
+ */
843
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
844
+ /**
845
+ * Hook that allows to mutate the CM's single types links pre-set filters
846
+ * @constant
847
+ * @type {string}
848
+ */
849
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
850
+ };
851
+ const contentTypesApi = contentManagerApi.injectEndpoints({
852
+ endpoints: (builder) => ({
853
+ getContentTypeConfiguration: builder.query({
854
+ query: (uid) => ({
855
+ url: `/content-manager/content-types/${uid}/configuration`,
856
+ method: "GET"
857
+ }),
858
+ transformResponse: (response) => response.data,
859
+ providesTags: (_result, _error, uid) => [
860
+ { type: "ContentTypesConfiguration", id: uid },
861
+ { type: "ContentTypeSettings", id: "LIST" }
862
+ ]
863
+ }),
864
+ getAllContentTypeSettings: builder.query({
865
+ query: () => "/content-manager/content-types-settings",
866
+ transformResponse: (response) => response.data,
867
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
868
+ }),
869
+ updateContentTypeConfiguration: builder.mutation({
870
+ query: ({ uid, ...body }) => ({
871
+ url: `/content-manager/content-types/${uid}/configuration`,
872
+ method: "PUT",
873
+ data: body
874
+ }),
875
+ transformResponse: (response) => response.data,
876
+ invalidatesTags: (_result, _error, { uid }) => [
877
+ { type: "ContentTypesConfiguration", id: uid },
878
+ { type: "ContentTypeSettings", id: "LIST" },
879
+ // Is this necessary?
880
+ { type: "InitialData" }
881
+ ]
882
+ })
883
+ })
884
+ });
885
+ const {
886
+ useGetContentTypeConfigurationQuery,
887
+ useGetAllContentTypeSettingsQuery,
888
+ useUpdateContentTypeConfigurationMutation
889
+ } = contentTypesApi;
890
+ const checkIfAttributeIsDisplayable = (attribute) => {
891
+ const { type } = attribute;
892
+ if (type === "relation") {
893
+ return !attribute.relation.toLowerCase().includes("morph");
894
+ }
895
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
896
+ };
897
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
898
+ if (!mainFieldName) {
899
+ return void 0;
900
+ }
901
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
902
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
903
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
904
+ );
905
+ return {
906
+ name: mainFieldName,
907
+ type: mainFieldType ?? "string"
908
+ };
909
+ };
910
+ const DEFAULT_SETTINGS = {
911
+ bulkable: false,
912
+ filterable: false,
913
+ searchable: false,
914
+ pagination: false,
915
+ defaultSortBy: "",
916
+ defaultSortOrder: "asc",
917
+ mainField: "id",
918
+ pageSize: 10
919
+ };
920
+ const useDocumentLayout = (model) => {
921
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
922
+ const [{ query }] = strapiAdmin.useQueryParams();
923
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
781
924
  const { toggleNotification } = strapiAdmin.useNotification();
782
925
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
926
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
783
927
  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);
928
+ data,
929
+ isLoading: isLoadingConfigs,
930
+ error,
931
+ isFetching: isFetchingConfigs
932
+ } = useGetContentTypeConfigurationQuery(model);
933
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
790
934
  React__namespace.useEffect(() => {
791
935
  if (error) {
792
936
  toggleNotification({
@@ -794,68 +938,322 @@ const useDocument = (args, opts) => {
794
938
  message: formatAPIError(error)
795
939
  });
796
940
  }
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
- }
941
+ }, [error, formatAPIError, toggleNotification]);
942
+ const editLayout = React__namespace.useMemo(
943
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
944
+ layout: [],
945
+ components: {},
946
+ metadatas: {},
947
+ options: {},
948
+ settings: DEFAULT_SETTINGS
820
949
  },
821
- [validationSchema]
950
+ [data, isLoading, schemas, schema, components]
951
+ );
952
+ const listLayout = React__namespace.useMemo(() => {
953
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
954
+ layout: [],
955
+ metadatas: {},
956
+ options: {},
957
+ settings: DEFAULT_SETTINGS
958
+ };
959
+ }, [data, isLoading, schemas, schema, components]);
960
+ const { layout: edit } = React__namespace.useMemo(
961
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
962
+ layout: editLayout,
963
+ query
964
+ }),
965
+ [editLayout, query, runHookWaterfall]
822
966
  );
823
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
824
967
  return {
825
- components,
826
- document: data?.data,
827
- meta: data?.meta,
968
+ error,
828
969
  isLoading,
829
- schema,
830
- validate
970
+ edit,
971
+ list: listLayout
831
972
  };
832
973
  };
833
- const useDoc = () => {
834
- const { id, slug, collectionType, origin } = reactRouterDom.useParams();
835
- const [{ query }] = strapiAdmin.useQueryParams();
836
- const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
837
- if (!collectionType) {
838
- throw new Error("Could not find collectionType in url params");
974
+ const useDocLayout = () => {
975
+ const { model } = useDoc();
976
+ return useDocumentLayout(model);
977
+ };
978
+ const formatEditLayout = (data, {
979
+ schemas,
980
+ schema,
981
+ components
982
+ }) => {
983
+ let currentPanelIndex = 0;
984
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
985
+ data.contentType.layouts.edit,
986
+ schema?.attributes,
987
+ data.contentType.metadatas,
988
+ { configurations: data.components, schemas: components },
989
+ schemas
990
+ ).reduce((panels, row) => {
991
+ if (row.some((field) => field.type === "dynamiczone")) {
992
+ panels.push([row]);
993
+ currentPanelIndex += 2;
994
+ } else {
995
+ if (!panels[currentPanelIndex]) {
996
+ panels.push([row]);
997
+ } else {
998
+ panels[currentPanelIndex].push(row);
999
+ }
1000
+ }
1001
+ return panels;
1002
+ }, []);
1003
+ const componentEditAttributes = Object.entries(data.components).reduce(
1004
+ (acc, [uid, configuration]) => {
1005
+ acc[uid] = {
1006
+ layout: convertEditLayoutToFieldLayouts(
1007
+ configuration.layouts.edit,
1008
+ components[uid].attributes,
1009
+ configuration.metadatas,
1010
+ { configurations: data.components, schemas: components }
1011
+ ),
1012
+ settings: {
1013
+ ...configuration.settings,
1014
+ icon: components[uid].info.icon,
1015
+ displayName: components[uid].info.displayName
1016
+ }
1017
+ };
1018
+ return acc;
1019
+ },
1020
+ {}
1021
+ );
1022
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
1023
+ (acc, [attribute, metadata]) => {
1024
+ return {
1025
+ ...acc,
1026
+ [attribute]: metadata.edit
1027
+ };
1028
+ },
1029
+ {}
1030
+ );
1031
+ return {
1032
+ layout: panelledEditAttributes,
1033
+ components: componentEditAttributes,
1034
+ metadatas: editMetadatas,
1035
+ settings: {
1036
+ ...data.contentType.settings,
1037
+ displayName: schema?.info.displayName
1038
+ },
1039
+ options: {
1040
+ ...schema?.options,
1041
+ ...schema?.pluginOptions,
1042
+ ...data.contentType.options
1043
+ }
1044
+ };
1045
+ };
1046
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1047
+ return rows.map(
1048
+ (row) => row.map((field) => {
1049
+ const attribute = attributes[field.name];
1050
+ if (!attribute) {
1051
+ return null;
1052
+ }
1053
+ const { edit: metadata } = metadatas[field.name];
1054
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1055
+ return {
1056
+ attribute,
1057
+ disabled: !metadata.editable,
1058
+ hint: metadata.description,
1059
+ label: metadata.label ?? "",
1060
+ name: field.name,
1061
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1062
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1063
+ schemas,
1064
+ components: components?.schemas ?? {}
1065
+ }),
1066
+ placeholder: metadata.placeholder ?? "",
1067
+ required: attribute.required ?? false,
1068
+ size: field.size,
1069
+ unique: "unique" in attribute ? attribute.unique : false,
1070
+ visible: metadata.visible ?? true,
1071
+ type: attribute.type
1072
+ };
1073
+ }).filter((field) => field !== null)
1074
+ );
1075
+ };
1076
+ const formatListLayout = (data, {
1077
+ schemas,
1078
+ schema,
1079
+ components
1080
+ }) => {
1081
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1082
+ (acc, [attribute, metadata]) => {
1083
+ return {
1084
+ ...acc,
1085
+ [attribute]: metadata.list
1086
+ };
1087
+ },
1088
+ {}
1089
+ );
1090
+ const listAttributes = convertListLayoutToFieldLayouts(
1091
+ data.contentType.layouts.list,
1092
+ schema?.attributes,
1093
+ listMetadatas,
1094
+ { configurations: data.components, schemas: components },
1095
+ schemas
1096
+ );
1097
+ return {
1098
+ layout: listAttributes,
1099
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1100
+ metadatas: listMetadatas,
1101
+ options: {
1102
+ ...schema?.options,
1103
+ ...schema?.pluginOptions,
1104
+ ...data.contentType.options
1105
+ }
1106
+ };
1107
+ };
1108
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1109
+ return columns.map((name) => {
1110
+ const attribute = attributes[name];
1111
+ if (!attribute) {
1112
+ return null;
1113
+ }
1114
+ const metadata = metadatas[name];
1115
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1116
+ return {
1117
+ attribute,
1118
+ label: metadata.label ?? "",
1119
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1120
+ schemas,
1121
+ components: components?.schemas ?? {}
1122
+ }),
1123
+ name,
1124
+ searchable: metadata.searchable ?? true,
1125
+ sortable: metadata.sortable ?? true
1126
+ };
1127
+ }).filter((field) => field !== null);
1128
+ };
1129
+ const useDocument = (args, opts) => {
1130
+ const { toggleNotification } = strapiAdmin.useNotification();
1131
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1132
+ const {
1133
+ currentData: data,
1134
+ isLoading: isLoadingDocument,
1135
+ isFetching: isFetchingDocument,
1136
+ error
1137
+ } = useGetDocumentQuery(args, {
1138
+ ...opts,
1139
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1140
+ });
1141
+ const {
1142
+ components,
1143
+ schema,
1144
+ schemas,
1145
+ isLoading: isLoadingSchema
1146
+ } = useContentTypeSchema(args.model);
1147
+ React__namespace.useEffect(() => {
1148
+ if (error) {
1149
+ toggleNotification({
1150
+ type: "danger",
1151
+ message: formatAPIError(error)
1152
+ });
1153
+ }
1154
+ }, [toggleNotification, error, formatAPIError, args.collectionType]);
1155
+ const validationSchema = React__namespace.useMemo(() => {
1156
+ if (!schema) {
1157
+ return null;
1158
+ }
1159
+ return createYupSchema(schema.attributes, components);
1160
+ }, [schema, components]);
1161
+ const validate = React__namespace.useCallback(
1162
+ (document) => {
1163
+ if (!validationSchema) {
1164
+ throw new Error(
1165
+ "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1166
+ );
1167
+ }
1168
+ try {
1169
+ validationSchema.validateSync(document, { abortEarly: false, strict: true });
1170
+ return null;
1171
+ } catch (error2) {
1172
+ if (error2 instanceof yup.ValidationError) {
1173
+ return strapiAdmin.getYupValidationErrors(error2);
1174
+ }
1175
+ throw error2;
1176
+ }
1177
+ },
1178
+ [validationSchema]
1179
+ );
1180
+ const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1181
+ const hasError = !!error;
1182
+ return {
1183
+ components,
1184
+ document: data?.data,
1185
+ meta: data?.meta,
1186
+ isLoading,
1187
+ hasError,
1188
+ schema,
1189
+ schemas,
1190
+ validate
1191
+ };
1192
+ };
1193
+ const useDoc = () => {
1194
+ const { id, slug, collectionType, origin } = reactRouterDom.useParams();
1195
+ const [{ query }] = strapiAdmin.useQueryParams();
1196
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1197
+ if (!collectionType) {
1198
+ throw new Error("Could not find collectionType in url params");
839
1199
  }
840
1200
  if (!slug) {
841
1201
  throw new Error("Could not find model in url params");
842
1202
  }
1203
+ const document = useDocument(
1204
+ { documentId: origin || id, model: slug, collectionType, params },
1205
+ {
1206
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1207
+ }
1208
+ );
1209
+ const returnId = origin || id === "create" ? void 0 : id;
843
1210
  return {
844
1211
  collectionType,
845
1212
  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
- )
1213
+ id: returnId,
1214
+ ...document
1215
+ };
1216
+ };
1217
+ const useContentManagerContext = () => {
1218
+ const {
1219
+ collectionType,
1220
+ model,
1221
+ id,
1222
+ components,
1223
+ isLoading: isLoadingDoc,
1224
+ schema,
1225
+ schemas
1226
+ } = useDoc();
1227
+ const layout = useDocumentLayout(model);
1228
+ const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
1229
+ const isSingleType = collectionType === SINGLE_TYPES;
1230
+ const slug = model;
1231
+ const isCreatingEntry = id === "create";
1232
+ useContentTypeSchema();
1233
+ const isLoading = isLoadingDoc || layout.isLoading;
1234
+ const error = layout.error;
1235
+ return {
1236
+ error,
1237
+ isLoading,
1238
+ // Base metadata
1239
+ model,
1240
+ collectionType,
1241
+ id,
1242
+ slug,
1243
+ isCreatingEntry,
1244
+ isSingleType,
1245
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1246
+ // All schema infos
1247
+ components,
1248
+ contentType: schema,
1249
+ contentTypes: schemas,
1250
+ // Form state
1251
+ form,
1252
+ // layout infos
1253
+ layout
853
1254
  };
854
1255
  };
855
1256
  const prefixPluginTranslations = (trad, pluginId) => {
856
- if (!pluginId) {
857
- throw new TypeError("pluginId can't be empty");
858
- }
859
1257
  return Object.keys(trad).reduce((acc, current) => {
860
1258
  acc[`${pluginId}.${current}`] = trad[current];
861
1259
  return acc;
@@ -871,6 +1269,8 @@ const useDocumentActions = () => {
871
1269
  const { formatMessage } = reactIntl.useIntl();
872
1270
  const { trackUsage } = strapiAdmin.useTracking();
873
1271
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1272
+ const navigate = reactRouterDom.useNavigate();
1273
+ const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
874
1274
  const [deleteDocument] = useDeleteDocumentMutation();
875
1275
  const _delete = React__namespace.useCallback(
876
1276
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -1185,6 +1585,7 @@ const useDocumentActions = () => {
1185
1585
  defaultMessage: "Saved document"
1186
1586
  })
1187
1587
  });
1588
+ setCurrentStep("contentManager.success");
1188
1589
  return res.data;
1189
1590
  } catch (err) {
1190
1591
  toggleNotification({
@@ -1206,7 +1607,6 @@ const useDocumentActions = () => {
1206
1607
  sourceId
1207
1608
  });
1208
1609
  if ("error" in res) {
1209
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1210
1610
  return { error: res.error };
1211
1611
  }
1212
1612
  toggleNotification({
@@ -1225,7 +1625,7 @@ const useDocumentActions = () => {
1225
1625
  throw err;
1226
1626
  }
1227
1627
  },
1228
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1628
+ [autoCloneDocument, formatMessage, toggleNotification]
1229
1629
  );
1230
1630
  const [cloneDocument] = useCloneDocumentMutation();
1231
1631
  const clone = React__namespace.useCallback(
@@ -1251,6 +1651,7 @@ const useDocumentActions = () => {
1251
1651
  defaultMessage: "Cloned document"
1252
1652
  })
1253
1653
  });
1654
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1254
1655
  return res.data;
1255
1656
  } catch (err) {
1256
1657
  toggleNotification({
@@ -1261,7 +1662,7 @@ const useDocumentActions = () => {
1261
1662
  throw err;
1262
1663
  }
1263
1664
  },
1264
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1665
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1265
1666
  );
1266
1667
  const [getDoc] = useLazyGetDocumentQuery();
1267
1668
  const getDocument = React__namespace.useCallback(
@@ -1286,10 +1687,10 @@ const useDocumentActions = () => {
1286
1687
  update
1287
1688
  };
1288
1689
  };
1289
- const ProtectedHistoryPage = React.lazy(
1290
- () => Promise.resolve().then(() => require("./History-CqN6K7SX.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1690
+ const ProtectedHistoryPage = React__namespace.lazy(
1691
+ () => Promise.resolve().then(() => require("./History-Cs6XM6EU.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1291
1692
  );
1292
- const routes$1 = [
1693
+ const routes$2 = [
1293
1694
  {
1294
1695
  path: ":collectionType/:slug/:id/history",
1295
1696
  Component: ProtectedHistoryPage
@@ -1299,32 +1700,45 @@ const routes$1 = [
1299
1700
  Component: ProtectedHistoryPage
1300
1701
  }
1301
1702
  ];
1703
+ const ProtectedPreviewPage = React__namespace.lazy(
1704
+ () => Promise.resolve().then(() => require("./Preview-DH1h7kJ6.js")).then((mod) => ({ default: mod.ProtectedPreviewPage }))
1705
+ );
1706
+ const routes$1 = [
1707
+ {
1708
+ path: ":collectionType/:slug/:id/preview",
1709
+ Component: ProtectedPreviewPage
1710
+ },
1711
+ {
1712
+ path: ":collectionType/:slug/preview",
1713
+ Component: ProtectedPreviewPage
1714
+ }
1715
+ ];
1302
1716
  const ProtectedEditViewPage = React.lazy(
1303
- () => Promise.resolve().then(() => require("./EditViewPage-zT3fBr4Y.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1717
+ () => Promise.resolve().then(() => require("./EditViewPage-BXoY-ITh.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1304
1718
  );
1305
1719
  const ProtectedListViewPage = React.lazy(
1306
- () => Promise.resolve().then(() => require("./ListViewPage-pEw_zug9.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1720
+ () => Promise.resolve().then(() => require("./ListViewPage-CaGBu5H5.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1307
1721
  );
1308
1722
  const ProtectedListConfiguration = React.lazy(
1309
- () => Promise.resolve().then(() => require("./ListConfigurationPage-R_p-SbHZ.js")).then((mod) => ({
1723
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-7LeytuFD.js")).then((mod) => ({
1310
1724
  default: mod.ProtectedListConfiguration
1311
1725
  }))
1312
1726
  );
1313
1727
  const ProtectedEditConfigurationPage = React.lazy(
1314
- () => Promise.resolve().then(() => require("./EditConfigurationPage-DjFJw56M.js")).then((mod) => ({
1728
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-q76oeVU1.js")).then((mod) => ({
1315
1729
  default: mod.ProtectedEditConfigurationPage
1316
1730
  }))
1317
1731
  );
1318
1732
  const ProtectedComponentConfigurationPage = React.lazy(
1319
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-C-49MccQ.js")).then((mod) => ({
1733
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-DHV8IFbd.js")).then((mod) => ({
1320
1734
  default: mod.ProtectedComponentConfigurationPage
1321
1735
  }))
1322
1736
  );
1323
1737
  const NoPermissions = React.lazy(
1324
- () => Promise.resolve().then(() => require("./NoPermissionsPage-BtPrImPP.js")).then((mod) => ({ default: mod.NoPermissions }))
1738
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-DQn5cqZz.js")).then((mod) => ({ default: mod.NoPermissions }))
1325
1739
  );
1326
1740
  const NoContentType = React.lazy(
1327
- () => Promise.resolve().then(() => require("./NoContentTypePage-C5dcQojD.js")).then((mod) => ({ default: mod.NoContentType }))
1741
+ () => Promise.resolve().then(() => require("./NoContentTypePage-BaBE00IO.js")).then((mod) => ({ default: mod.NoContentType }))
1328
1742
  );
1329
1743
  const CollectionTypePages = () => {
1330
1744
  const { collectionType } = reactRouterDom.useParams();
@@ -1336,7 +1750,7 @@ const CollectionTypePages = () => {
1336
1750
  const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
1337
1751
  const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
1338
1752
  const LIST_RELATIVE_PATH = ":collectionType/:slug";
1339
- const LIST_PATH = `/content-manager/${LIST_RELATIVE_PATH}`;
1753
+ const LIST_PATH = `/content-manager/collection-types/:slug`;
1340
1754
  const routes = [
1341
1755
  {
1342
1756
  path: LIST_RELATIVE_PATH,
@@ -1370,6 +1784,7 @@ const routes = [
1370
1784
  path: "no-content-types",
1371
1785
  Component: NoContentType
1372
1786
  },
1787
+ ...routes$2,
1373
1788
  ...routes$1
1374
1789
  ];
1375
1790
  const DocumentActions = ({ actions: actions2 }) => {
@@ -1438,12 +1853,14 @@ const DocumentActionButton = (action) => {
1438
1853
  /* @__PURE__ */ jsxRuntime.jsx(
1439
1854
  designSystem.Button,
1440
1855
  {
1441
- flex: 1,
1856
+ flex: "auto",
1442
1857
  startIcon: action.icon,
1443
1858
  disabled: action.disabled,
1444
1859
  onClick: handleClick(action),
1445
1860
  justifyContent: "center",
1446
1861
  variant: action.variant || "default",
1862
+ paddingTop: "7px",
1863
+ paddingBottom: "7px",
1447
1864
  children: action.label
1448
1865
  }
1449
1866
  ),
@@ -1451,7 +1868,7 @@ const DocumentActionButton = (action) => {
1451
1868
  DocumentActionConfirmDialog,
1452
1869
  {
1453
1870
  ...action.dialog,
1454
- variant: action.variant,
1871
+ variant: action.dialog?.variant ?? action.variant,
1455
1872
  isOpen: dialogId === action.id,
1456
1873
  onClose: handleClose
1457
1874
  }
@@ -1466,6 +1883,11 @@ const DocumentActionButton = (action) => {
1466
1883
  ) : null
1467
1884
  ] });
1468
1885
  };
1886
+ const MenuItem = styledComponents.styled(designSystem.Menu.Item)`
1887
+ &:hover {
1888
+ background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
1889
+ }
1890
+ `;
1469
1891
  const DocumentActionsMenu = ({
1470
1892
  actions: actions2,
1471
1893
  children,
@@ -1508,9 +1930,9 @@ const DocumentActionsMenu = ({
1508
1930
  disabled: isDisabled,
1509
1931
  size: "S",
1510
1932
  endIcon: null,
1511
- paddingTop: "7px",
1512
- paddingLeft: "9px",
1513
- paddingRight: "9px",
1933
+ paddingTop: "4px",
1934
+ paddingLeft: "7px",
1935
+ paddingRight: "7px",
1514
1936
  variant,
1515
1937
  children: [
1516
1938
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
@@ -1521,36 +1943,35 @@ const DocumentActionsMenu = ({
1521
1943
  ]
1522
1944
  }
1523
1945
  ),
1524
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1946
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1525
1947
  actions2.map((action) => {
1526
1948
  return /* @__PURE__ */ jsxRuntime.jsx(
1527
- designSystem.Menu.Item,
1949
+ MenuItem,
1528
1950
  {
1529
1951
  disabled: action.disabled,
1530
1952
  onSelect: handleClick(action),
1531
1953
  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
- ] })
1954
+ isVariantDanger: action.variant === "danger",
1955
+ isDisabled: action.disabled,
1956
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
1957
+ designSystem.Flex,
1958
+ {
1959
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1960
+ gap: 2,
1961
+ tag: "span",
1962
+ children: [
1963
+ /* @__PURE__ */ jsxRuntime.jsx(
1964
+ designSystem.Flex,
1965
+ {
1966
+ tag: "span",
1967
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1968
+ children: action.icon
1969
+ }
1970
+ ),
1971
+ action.label
1972
+ ]
1973
+ }
1974
+ ) })
1554
1975
  },
1555
1976
  action.id
1556
1977
  );
@@ -1630,11 +2051,11 @@ const DocumentActionConfirmDialog = ({
1630
2051
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
1631
2052
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
1632
2053
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
1633
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
2054
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
1634
2055
  id: "app.components.Button.cancel",
1635
2056
  defaultMessage: "Cancel"
1636
2057
  }) }) }),
1637
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
2058
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
1638
2059
  id: "app.components.Button.confirm",
1639
2060
  defaultMessage: "Confirm"
1640
2061
  }) })
@@ -1661,6 +2082,18 @@ const DocumentActionModal = ({
1661
2082
  typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1662
2083
  ] }) });
1663
2084
  };
2085
+ const transformData = (data) => {
2086
+ if (Array.isArray(data)) {
2087
+ return data.map(transformData);
2088
+ }
2089
+ if (typeof data === "object" && data !== null) {
2090
+ if ("apiData" in data) {
2091
+ return data.apiData;
2092
+ }
2093
+ return mapValues__default.default(transformData)(data);
2094
+ }
2095
+ return data;
2096
+ };
1664
2097
  const PublishAction$1 = ({
1665
2098
  activeTab,
1666
2099
  documentId,
@@ -1673,13 +2106,18 @@ const PublishAction$1 = ({
1673
2106
  const navigate = reactRouterDom.useNavigate();
1674
2107
  const { toggleNotification } = strapiAdmin.useNotification();
1675
2108
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
2109
+ const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
1676
2110
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2111
+ const { id } = reactRouterDom.useParams();
1677
2112
  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
- );
2113
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1682
2114
  const { publish } = useDocumentActions();
2115
+ const [
2116
+ countDraftRelations,
2117
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
2118
+ ] = useLazyGetDraftRelationCountQuery();
2119
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
2120
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
1683
2121
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1684
2122
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1685
2123
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1688,10 +2126,107 @@ const PublishAction$1 = ({
1688
2126
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1689
2127
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1690
2128
  const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
2129
+ React__namespace.useEffect(() => {
2130
+ if (isErrorDraftRelations) {
2131
+ toggleNotification({
2132
+ type: "danger",
2133
+ message: formatMessage({
2134
+ id: getTranslation("error.records.fetch-draft-relatons"),
2135
+ defaultMessage: "An error occurred while fetching draft relations on this document."
2136
+ })
2137
+ });
2138
+ }
2139
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
2140
+ React__namespace.useEffect(() => {
2141
+ const localDraftRelations = /* @__PURE__ */ new Set();
2142
+ const extractDraftRelations = (data) => {
2143
+ const relations = data.connect || [];
2144
+ relations.forEach((relation) => {
2145
+ if (relation.status === "draft") {
2146
+ localDraftRelations.add(relation.id);
2147
+ }
2148
+ });
2149
+ };
2150
+ const traverseAndExtract = (data) => {
2151
+ Object.entries(data).forEach(([key, value]) => {
2152
+ if (key === "connect" && Array.isArray(value)) {
2153
+ extractDraftRelations({ connect: value });
2154
+ } else if (typeof value === "object" && value !== null) {
2155
+ traverseAndExtract(value);
2156
+ }
2157
+ });
2158
+ };
2159
+ if (!documentId || modified) {
2160
+ traverseAndExtract(formValues);
2161
+ setLocalCountOfDraftRelations(localDraftRelations.size);
2162
+ }
2163
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
2164
+ React__namespace.useEffect(() => {
2165
+ if (!document || !document.documentId || isListView) {
2166
+ return;
2167
+ }
2168
+ const fetchDraftRelationsCount = async () => {
2169
+ const { data, error } = await countDraftRelations({
2170
+ collectionType,
2171
+ model,
2172
+ documentId,
2173
+ params
2174
+ });
2175
+ if (error) {
2176
+ throw error;
2177
+ }
2178
+ if (data) {
2179
+ setServerCountOfDraftRelations(data.data);
2180
+ }
2181
+ };
2182
+ fetchDraftRelationsCount();
2183
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
1691
2184
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1692
2185
  if (!schema?.options?.draftAndPublish) {
1693
2186
  return null;
1694
2187
  }
2188
+ const performPublish = async () => {
2189
+ setSubmitting(true);
2190
+ try {
2191
+ const { errors } = await validate(true, {
2192
+ status: "published"
2193
+ });
2194
+ if (errors) {
2195
+ toggleNotification({
2196
+ type: "danger",
2197
+ message: formatMessage({
2198
+ id: "content-manager.validation.error",
2199
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2200
+ })
2201
+ });
2202
+ return;
2203
+ }
2204
+ const res = await publish(
2205
+ {
2206
+ collectionType,
2207
+ model,
2208
+ documentId,
2209
+ params
2210
+ },
2211
+ transformData(formValues)
2212
+ );
2213
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2214
+ if (id === "create") {
2215
+ navigate({
2216
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2217
+ search: rawQuery
2218
+ });
2219
+ }
2220
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2221
+ setErrors(formatValidationErrors(res.error));
2222
+ }
2223
+ } finally {
2224
+ setSubmitting(false);
2225
+ }
2226
+ };
2227
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
2228
+ const enableDraftRelationsCount = false;
2229
+ const hasDraftRelations = enableDraftRelationsCount;
1695
2230
  return {
1696
2231
  /**
1697
2232
  * Disabled when:
@@ -1701,52 +2236,40 @@ const PublishAction$1 = ({
1701
2236
  * - the document is already published & not modified
1702
2237
  * - the document is being created & not modified
1703
2238
  * - 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
2239
  */
1707
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2240
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1708
2241
  label: formatMessage({
1709
2242
  id: "app.utils.publish",
1710
2243
  defaultMessage: "Publish"
1711
2244
  }),
1712
2245
  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));
2246
+ await performPublish();
2247
+ },
2248
+ dialog: hasDraftRelations ? {
2249
+ type: "dialog",
2250
+ variant: "danger",
2251
+ footer: null,
2252
+ title: formatMessage({
2253
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
2254
+ defaultMessage: "Confirmation"
2255
+ }),
2256
+ content: formatMessage(
2257
+ {
2258
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2259
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
2260
+ },
2261
+ {
2262
+ count: totalDraftRelations
1742
2263
  }
1743
- } finally {
1744
- setSubmitting(false);
2264
+ ),
2265
+ onConfirm: async () => {
2266
+ await performPublish();
1745
2267
  }
1746
- }
2268
+ } : void 0
1747
2269
  };
1748
2270
  };
1749
2271
  PublishAction$1.type = "publish";
2272
+ PublishAction$1.position = "panel";
1750
2273
  const UpdateAction = ({
1751
2274
  activeTab,
1752
2275
  documentId,
@@ -1759,10 +2282,6 @@ const UpdateAction = ({
1759
2282
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1760
2283
  const isCloning = cloneMatch !== null;
1761
2284
  const { formatMessage } = reactIntl.useIntl();
1762
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1763
- canCreate: canCreate2,
1764
- canUpdate: canUpdate2
1765
- }));
1766
2285
  const { create, update, clone } = useDocumentActions();
1767
2286
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1768
2287
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1779,18 +2298,18 @@ const UpdateAction = ({
1779
2298
  * - the form is submitting
1780
2299
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1781
2300
  * - 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
2301
  */
1785
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
2302
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1786
2303
  label: formatMessage({
1787
- id: "content-manager.containers.Edit.save",
2304
+ id: "global.save",
1788
2305
  defaultMessage: "Save"
1789
2306
  }),
1790
2307
  onClick: async () => {
1791
2308
  setSubmitting(true);
1792
2309
  try {
1793
- const { errors } = await validate();
2310
+ const { errors } = await validate(true, {
2311
+ status: "draft"
2312
+ });
1794
2313
  if (errors) {
1795
2314
  toggleNotification({
1796
2315
  type: "danger",
@@ -1808,13 +2327,16 @@ const UpdateAction = ({
1808
2327
  documentId: cloneMatch.params.origin,
1809
2328
  params
1810
2329
  },
1811
- document
2330
+ transformData(document)
1812
2331
  );
1813
2332
  if ("data" in res) {
1814
- navigate({
1815
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1816
- search: rawQuery
1817
- });
2333
+ navigate(
2334
+ {
2335
+ pathname: `../${res.data.documentId}`,
2336
+ search: rawQuery
2337
+ },
2338
+ { relative: "path" }
2339
+ );
1818
2340
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1819
2341
  setErrors(formatValidationErrors(res.error));
1820
2342
  }
@@ -1826,7 +2348,7 @@ const UpdateAction = ({
1826
2348
  documentId,
1827
2349
  params
1828
2350
  },
1829
- document
2351
+ transformData(document)
1830
2352
  );
1831
2353
  if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1832
2354
  setErrors(formatValidationErrors(res.error));
@@ -1839,13 +2361,16 @@ const UpdateAction = ({
1839
2361
  model,
1840
2362
  params
1841
2363
  },
1842
- document
2364
+ transformData(document)
1843
2365
  );
1844
2366
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1845
- navigate({
1846
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1847
- search: rawQuery
1848
- });
2367
+ navigate(
2368
+ {
2369
+ pathname: `../${res.data.documentId}`,
2370
+ search: rawQuery
2371
+ },
2372
+ { replace: true, relative: "path" }
2373
+ );
1849
2374
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1850
2375
  setErrors(formatValidationErrors(res.error));
1851
2376
  }
@@ -1857,6 +2382,7 @@ const UpdateAction = ({
1857
2382
  };
1858
2383
  };
1859
2384
  UpdateAction.type = "update";
2385
+ UpdateAction.position = "panel";
1860
2386
  const UNPUBLISH_DRAFT_OPTIONS = {
1861
2387
  KEEP: "keep",
1862
2388
  DISCARD: "discard"
@@ -1889,7 +2415,7 @@ const UnpublishAction$1 = ({
1889
2415
  id: "app.utils.unpublish",
1890
2416
  defaultMessage: "Unpublish"
1891
2417
  }),
1892
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2418
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
1893
2419
  onClick: async () => {
1894
2420
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1895
2421
  if (!documentId) {
@@ -1979,6 +2505,7 @@ const UnpublishAction$1 = ({
1979
2505
  };
1980
2506
  };
1981
2507
  UnpublishAction$1.type = "unpublish";
2508
+ UnpublishAction$1.position = "panel";
1982
2509
  const DiscardAction = ({
1983
2510
  activeTab,
1984
2511
  documentId,
@@ -2001,7 +2528,7 @@ const DiscardAction = ({
2001
2528
  id: "content-manager.actions.discard.label",
2002
2529
  defaultMessage: "Discard changes"
2003
2530
  }),
2004
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2531
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
2005
2532
  position: ["panel", "table-row"],
2006
2533
  variant: "danger",
2007
2534
  dialog: {
@@ -2029,11 +2556,7 @@ const DiscardAction = ({
2029
2556
  };
2030
2557
  };
2031
2558
  DiscardAction.type = "discard";
2032
- const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
2033
- path {
2034
- fill: currentColor;
2035
- }
2036
- `;
2559
+ DiscardAction.position = "panel";
2037
2560
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2038
2561
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2039
2562
  const RelativeTime = React__namespace.forwardRef(
@@ -2046,7 +2569,7 @@ const RelativeTime = React__namespace.forwardRef(
2046
2569
  });
2047
2570
  const unit = intervals.find((intervalUnit) => {
2048
2571
  return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
2049
- });
2572
+ }) ?? "seconds";
2050
2573
  const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
2051
2574
  const customInterval = customIntervals.find(
2052
2575
  (custom) => interval[custom.unit] < custom.threshold
@@ -2080,34 +2603,34 @@ const getDisplayName = ({
2080
2603
  return email ?? "";
2081
2604
  };
2082
2605
  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) }) });
2606
+ const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
2607
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2608
+ const { formatMessage } = reactIntl.useIntl();
2609
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
2610
+ id: `content-manager.containers.List.${status}`,
2611
+ defaultMessage: capitalise(status)
2612
+ }) }) });
2086
2613
  };
2087
2614
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2088
2615
  const { formatMessage } = reactIntl.useIntl();
2089
2616
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2617
+ const params = reactRouterDom.useParams();
2090
2618
  const title = isCreating ? formatMessage({
2091
2619
  id: "content-manager.containers.edit.title.new",
2092
2620
  defaultMessage: "Create an entry"
2093
2621
  }) : 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,
2622
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2623
+ /* @__PURE__ */ jsxRuntime.jsx(
2624
+ strapiAdmin.BackButton,
2098
2625
  {
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
- ]
2626
+ fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
2108
2627
  }
2109
2628
  ),
2110
- status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2629
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2630
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2631
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2632
+ ] }),
2633
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2111
2634
  ] });
2112
2635
  };
2113
2636
  const HeaderToolbar = () => {
@@ -2153,7 +2676,7 @@ const HeaderToolbar = () => {
2153
2676
  meta: isCloning ? void 0 : meta,
2154
2677
  collectionType
2155
2678
  },
2156
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2679
+ descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
2157
2680
  children: (actions2) => {
2158
2681
  const headerActions = actions2.filter((action) => {
2159
2682
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -2190,12 +2713,12 @@ const Information = ({ activeTab }) => {
2190
2713
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2191
2714
  label: formatMessage({
2192
2715
  id: "content-manager.containers.edit.information.last-published.label",
2193
- defaultMessage: "Last published"
2716
+ defaultMessage: "Published"
2194
2717
  }),
2195
2718
  value: formatMessage(
2196
2719
  {
2197
2720
  id: "content-manager.containers.edit.information.last-published.value",
2198
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2721
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2199
2722
  },
2200
2723
  {
2201
2724
  time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2208,12 +2731,12 @@ const Information = ({ activeTab }) => {
2208
2731
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2209
2732
  label: formatMessage({
2210
2733
  id: "content-manager.containers.edit.information.last-draft.label",
2211
- defaultMessage: "Last draft"
2734
+ defaultMessage: "Updated"
2212
2735
  }),
2213
2736
  value: formatMessage(
2214
2737
  {
2215
2738
  id: "content-manager.containers.edit.information.last-draft.value",
2216
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2739
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2217
2740
  },
2218
2741
  {
2219
2742
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2231,12 +2754,12 @@ const Information = ({ activeTab }) => {
2231
2754
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2232
2755
  label: formatMessage({
2233
2756
  id: "content-manager.containers.edit.information.document.label",
2234
- defaultMessage: "Document"
2757
+ defaultMessage: "Created"
2235
2758
  }),
2236
2759
  value: formatMessage(
2237
2760
  {
2238
2761
  id: "content-manager.containers.edit.information.document.value",
2239
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2762
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2240
2763
  },
2241
2764
  {
2242
2765
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2274,25 +2797,77 @@ const Information = ({ activeTab }) => {
2274
2797
  );
2275
2798
  };
2276
2799
  const HeaderActions = ({ actions: actions2 }) => {
2277
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: actions2.map((action) => {
2278
- if ("options" in action) {
2800
+ const [dialogId, setDialogId] = React__namespace.useState(null);
2801
+ const handleClick = (action) => async (e) => {
2802
+ if (!("options" in action)) {
2803
+ const { onClick = () => false, dialog, id } = action;
2804
+ const muteDialog = await onClick(e);
2805
+ if (dialog && !muteDialog) {
2806
+ e.preventDefault();
2807
+ setDialogId(id);
2808
+ }
2809
+ }
2810
+ };
2811
+ const handleClose = () => {
2812
+ setDialogId(null);
2813
+ };
2814
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
2815
+ if (action.options) {
2279
2816
  return /* @__PURE__ */ jsxRuntime.jsx(
2280
2817
  designSystem.SingleSelect,
2281
2818
  {
2282
2819
  size: "S",
2283
- disabled: action.disabled,
2284
- "aria-label": action.label,
2285
2820
  onChange: action.onSelect,
2286
- value: action.value,
2821
+ "aria-label": action.label,
2822
+ ...action,
2287
2823
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
2288
2824
  },
2289
2825
  action.id
2290
2826
  );
2291
2827
  } else {
2292
- return null;
2828
+ if (action.type === "icon") {
2829
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
2830
+ /* @__PURE__ */ jsxRuntime.jsx(
2831
+ designSystem.IconButton,
2832
+ {
2833
+ disabled: action.disabled,
2834
+ label: action.label,
2835
+ size: "S",
2836
+ onClick: handleClick(action),
2837
+ children: action.icon
2838
+ }
2839
+ ),
2840
+ action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
2841
+ HeaderActionDialog,
2842
+ {
2843
+ ...action.dialog,
2844
+ isOpen: dialogId === action.id,
2845
+ onClose: handleClose
2846
+ }
2847
+ ) : null
2848
+ ] }, action.id);
2849
+ }
2293
2850
  }
2294
2851
  }) });
2295
2852
  };
2853
+ const HeaderActionDialog = ({
2854
+ onClose,
2855
+ onCancel,
2856
+ title,
2857
+ content: Content,
2858
+ isOpen
2859
+ }) => {
2860
+ const handleClose = async () => {
2861
+ if (onCancel) {
2862
+ await onCancel();
2863
+ }
2864
+ onClose();
2865
+ };
2866
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2867
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
2868
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
2869
+ ] }) });
2870
+ };
2296
2871
  const ConfigureTheViewAction = ({ collectionType, model }) => {
2297
2872
  const navigate = reactRouterDom.useNavigate();
2298
2873
  const { formatMessage } = reactIntl.useIntl();
@@ -2309,6 +2884,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2309
2884
  };
2310
2885
  };
2311
2886
  ConfigureTheViewAction.type = "configure-the-view";
2887
+ ConfigureTheViewAction.position = "header";
2312
2888
  const EditTheModelAction = ({ model }) => {
2313
2889
  const navigate = reactRouterDom.useNavigate();
2314
2890
  const { formatMessage } = reactIntl.useIntl();
@@ -2325,6 +2901,7 @@ const EditTheModelAction = ({ model }) => {
2325
2901
  };
2326
2902
  };
2327
2903
  EditTheModelAction.type = "edit-the-model";
2904
+ EditTheModelAction.position = "header";
2328
2905
  const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2329
2906
  const navigate = reactRouterDom.useNavigate();
2330
2907
  const { formatMessage } = reactIntl.useIntl();
@@ -2333,12 +2910,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2333
2910
  const { delete: deleteAction } = useDocumentActions();
2334
2911
  const { toggleNotification } = strapiAdmin.useNotification();
2335
2912
  const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
2913
+ const isLocalized = document?.locale != null;
2336
2914
  return {
2337
2915
  disabled: !canDelete || !document,
2338
- label: formatMessage({
2339
- id: "content-manager.actions.delete.label",
2340
- defaultMessage: "Delete document"
2341
- }),
2916
+ label: formatMessage(
2917
+ {
2918
+ id: "content-manager.actions.delete.label",
2919
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2920
+ },
2921
+ { isLocalized }
2922
+ ),
2342
2923
  icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2343
2924
  dialog: {
2344
2925
  type: "dialog",
@@ -2394,403 +2975,102 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2394
2975
  };
2395
2976
  };
2396
2977
  DeleteAction$1.type = "delete";
2978
+ DeleteAction$1.position = ["header", "table-row"];
2397
2979
  const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2398
2980
  const Panels = () => {
2399
2981
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2400
2982
  const [
2401
2983
  {
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
2984
+ query: { status }
2708
2985
  }
2986
+ ] = strapiAdmin.useQueryParams({
2987
+ status: "draft"
2988
+ });
2989
+ const { model, id, document, meta, collectionType } = useDoc();
2990
+ const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
2991
+ const props = {
2992
+ activeTab: status,
2993
+ model,
2994
+ documentId: id,
2995
+ document: isCloning ? void 0 : document,
2996
+ meta: isCloning ? void 0 : meta,
2997
+ collectionType
2709
2998
  };
2999
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
3000
+ strapiAdmin.DescriptionComponentRenderer,
3001
+ {
3002
+ props,
3003
+ descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
3004
+ children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
3005
+ }
3006
+ ) });
2710
3007
  };
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
- );
3008
+ const ActionsPanel = () => {
3009
+ const { formatMessage } = reactIntl.useIntl();
2762
3010
  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
- }
3011
+ title: formatMessage({
3012
+ id: "content-manager.containers.edit.panels.default.title",
3013
+ defaultMessage: "Entry"
3014
+ }),
3015
+ content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2771
3016
  };
2772
3017
  };
2773
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2774
- return columns.map((name) => {
2775
- const attribute = attributes[name];
2776
- if (!attribute) {
2777
- return null;
3018
+ ActionsPanel.type = "actions";
3019
+ const ActionsPanelContent = () => {
3020
+ const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
3021
+ const [
3022
+ {
3023
+ query: { status = "draft" }
2778
3024
  }
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);
3025
+ ] = strapiAdmin.useQueryParams();
3026
+ const { model, id, document, meta, collectionType } = useDoc();
3027
+ const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
3028
+ const props = {
3029
+ activeTab: status,
3030
+ model,
3031
+ documentId: id,
3032
+ document: isCloning ? void 0 : document,
3033
+ meta: isCloning ? void 0 : meta,
3034
+ collectionType
3035
+ };
3036
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
3037
+ /* @__PURE__ */ jsxRuntime.jsx(
3038
+ strapiAdmin.DescriptionComponentRenderer,
3039
+ {
3040
+ props,
3041
+ descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
3042
+ children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
3043
+ }
3044
+ ),
3045
+ /* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
3046
+ ] });
2793
3047
  };
3048
+ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
3049
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3050
+ designSystem.Flex,
3051
+ {
3052
+ ref,
3053
+ tag: "aside",
3054
+ "aria-labelledby": "additional-information",
3055
+ background: "neutral0",
3056
+ borderColor: "neutral150",
3057
+ hasRadius: true,
3058
+ paddingBottom: 4,
3059
+ paddingLeft: 4,
3060
+ paddingRight: 4,
3061
+ paddingTop: 4,
3062
+ shadow: "tableShadow",
3063
+ gap: 3,
3064
+ direction: "column",
3065
+ justifyContent: "stretch",
3066
+ alignItems: "flex-start",
3067
+ children: [
3068
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
3069
+ children
3070
+ ]
3071
+ }
3072
+ );
3073
+ });
2794
3074
  const ConfirmBulkActionDialog = ({
2795
3075
  onToggleDialog,
2796
3076
  isOpen = false,
@@ -2798,7 +3078,7 @@ const ConfirmBulkActionDialog = ({
2798
3078
  endAction
2799
3079
  }) => {
2800
3080
  const { formatMessage } = reactIntl.useIntl();
2801
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
3081
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2802
3082
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2803
3083
  id: "app.components.ConfirmDialog.title",
2804
3084
  defaultMessage: "Confirmation"
@@ -2829,6 +3109,7 @@ const ConfirmDialogPublishAll = ({
2829
3109
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2830
3110
  const { model, schema } = useDoc();
2831
3111
  const [{ query }] = strapiAdmin.useQueryParams();
3112
+ const enableDraftRelationsCount = false;
2832
3113
  const {
2833
3114
  data: countDraftRelations = 0,
2834
3115
  isLoading,
@@ -2840,7 +3121,7 @@ const ConfirmDialogPublishAll = ({
2840
3121
  locale: query?.plugins?.i18n?.locale
2841
3122
  },
2842
3123
  {
2843
- skip: selectedEntries.length === 0
3124
+ skip: !enableDraftRelationsCount
2844
3125
  }
2845
3126
  );
2846
3127
  React__namespace.useEffect(() => {
@@ -2919,7 +3200,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2919
3200
  )
2920
3201
  );
2921
3202
  } else {
2922
- messages.push(...formatErrorMessages(value, currentKey, formatMessage));
3203
+ messages.push(
3204
+ ...formatErrorMessages(
3205
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3206
+ value,
3207
+ currentKey,
3208
+ formatMessage
3209
+ )
3210
+ );
2923
3211
  }
2924
3212
  } else {
2925
3213
  messages.push(
@@ -3018,7 +3306,7 @@ const SelectedEntriesTableContent = ({
3018
3306
  status: row.status
3019
3307
  }
3020
3308
  ) }),
3021
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3309
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
3022
3310
  designSystem.IconButton,
3023
3311
  {
3024
3312
  tag: reactRouterDom.Link,
@@ -3027,23 +3315,16 @@ const SelectedEntriesTableContent = ({
3027
3315
  search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3028
3316
  },
3029
3317
  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
- ),
3318
+ label: formatMessage({
3319
+ id: "content-manager.bulk-publish.edit",
3320
+ defaultMessage: "Edit"
3321
+ }),
3042
3322
  target: "_blank",
3043
3323
  marginLeft: "auto",
3044
- children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3324
+ variant: "ghost",
3325
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
3045
3326
  }
3046
- ) })
3327
+ ) }) })
3047
3328
  ] }, row.id)) })
3048
3329
  ] });
3049
3330
  };
@@ -3080,7 +3361,13 @@ const SelectedEntriesModalContent = ({
3080
3361
  );
3081
3362
  const { rows, validationErrors } = React__namespace.useMemo(() => {
3082
3363
  if (data.length > 0 && schema) {
3083
- const validate = createYupSchema(schema.attributes, components);
3364
+ const validate = createYupSchema(
3365
+ schema.attributes,
3366
+ components,
3367
+ // Since this is the "Publish" action, the validation
3368
+ // schema must enforce the rules for published entities
3369
+ { status: "published" }
3370
+ );
3084
3371
  const validationErrors2 = {};
3085
3372
  const rows2 = data.map((entry) => {
3086
3373
  try {
@@ -3205,8 +3492,7 @@ const PublishAction = ({ documents, model }) => {
3205
3492
  const refetchList = () => {
3206
3493
  contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3207
3494
  };
3208
- if (!showPublishButton)
3209
- return null;
3495
+ if (!showPublishButton) return null;
3210
3496
  return {
3211
3497
  actionType: "publish",
3212
3498
  variant: "tertiary",
@@ -3274,8 +3560,7 @@ const DeleteAction = ({ documents, model }) => {
3274
3560
  selectRow([]);
3275
3561
  }
3276
3562
  };
3277
- if (!hasDeletePermission)
3278
- return null;
3563
+ if (!hasDeletePermission) return null;
3279
3564
  return {
3280
3565
  variant: "danger-light",
3281
3566
  label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
@@ -3324,8 +3609,7 @@ const UnpublishAction = ({ documents, model }) => {
3324
3609
  }
3325
3610
  };
3326
3611
  const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3327
- if (!showUnpublishButton)
3328
- return null;
3612
+ if (!showUnpublishButton) return null;
3329
3613
  return {
3330
3614
  variant: "tertiary",
3331
3615
  label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
@@ -3430,7 +3714,7 @@ const TableActions = ({ document }) => {
3430
3714
  strapiAdmin.DescriptionComponentRenderer,
3431
3715
  {
3432
3716
  props,
3433
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3717
+ descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
3434
3718
  children: (actions2) => {
3435
3719
  const tableRowActions = actions2.filter((action) => {
3436
3720
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3489,6 +3773,7 @@ const EditAction = ({ documentId }) => {
3489
3773
  };
3490
3774
  };
3491
3775
  EditAction.type = "edit";
3776
+ EditAction.position = "table-row";
3492
3777
  const StyledPencil = styledComponents.styled(Icons.Pencil)`
3493
3778
  path {
3494
3779
  fill: currentColor;
@@ -3541,7 +3826,7 @@ const CloneAction = ({ model, documentId }) => {
3541
3826
  }),
3542
3827
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3543
3828
  footer: ({ onClose }) => {
3544
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3829
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3545
3830
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3546
3831
  id: "cancel",
3547
3832
  defaultMessage: "Cancel"
@@ -3565,6 +3850,7 @@ const CloneAction = ({ model, documentId }) => {
3565
3850
  };
3566
3851
  };
3567
3852
  CloneAction.type = "clone";
3853
+ CloneAction.position = "table-row";
3568
3854
  const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
3569
3855
  path {
3570
3856
  fill: currentColor;
@@ -3582,8 +3868,7 @@ class ContentManagerPlugin {
3582
3868
  documentActions = [
3583
3869
  ...DEFAULT_ACTIONS,
3584
3870
  ...DEFAULT_TABLE_ROW_ACTIONS,
3585
- ...DEFAULT_HEADER_ACTIONS,
3586
- HistoryAction
3871
+ ...DEFAULT_HEADER_ACTIONS
3587
3872
  ];
3588
3873
  editViewSidePanels = [ActionsPanel];
3589
3874
  headerActions = [];
@@ -3652,7 +3937,14 @@ class ContentManagerPlugin {
3652
3937
  addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3653
3938
  addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3654
3939
  getBulkActions: () => this.bulkActions,
3655
- getDocumentActions: () => this.documentActions,
3940
+ getDocumentActions: (position) => {
3941
+ if (position) {
3942
+ return this.documentActions.filter(
3943
+ (action) => action.position == void 0 || [action.position].flat().includes(position)
3944
+ );
3945
+ }
3946
+ return this.documentActions;
3947
+ },
3656
3948
  getEditViewSidePanels: () => this.editViewSidePanels,
3657
3949
  getHeaderActions: () => this.headerActions
3658
3950
  }
@@ -3662,16 +3954,71 @@ class ContentManagerPlugin {
3662
3954
  const getPrintableType = (value) => {
3663
3955
  const nativeType = typeof value;
3664
3956
  if (nativeType === "object") {
3665
- if (value === null)
3666
- return "null";
3667
- if (Array.isArray(value))
3668
- return "array";
3957
+ if (value === null) return "null";
3958
+ if (Array.isArray(value)) return "array";
3669
3959
  if (value instanceof Object && value.constructor.name !== "Object") {
3670
3960
  return value.constructor.name;
3671
3961
  }
3672
3962
  }
3673
3963
  return nativeType;
3674
3964
  };
3965
+ const HistoryAction = ({ model, document }) => {
3966
+ const { formatMessage } = reactIntl.useIntl();
3967
+ const [{ query }] = strapiAdmin.useQueryParams();
3968
+ const navigate = reactRouterDom.useNavigate();
3969
+ const { trackUsage } = strapiAdmin.useTracking();
3970
+ const { pathname } = reactRouterDom.useLocation();
3971
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3972
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3973
+ return null;
3974
+ }
3975
+ const handleOnClick = () => {
3976
+ const destination = { pathname: "history", search: pluginsQueryParams };
3977
+ trackUsage("willNavigate", {
3978
+ from: pathname,
3979
+ to: `${pathname}/${destination.pathname}`
3980
+ });
3981
+ navigate(destination);
3982
+ };
3983
+ return {
3984
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3985
+ label: formatMessage({
3986
+ id: "content-manager.history.document-action",
3987
+ defaultMessage: "Content History"
3988
+ }),
3989
+ onClick: handleOnClick,
3990
+ disabled: (
3991
+ /**
3992
+ * The user is creating a new document.
3993
+ * It hasn't been saved yet, so there's no history to go to
3994
+ */
3995
+ !document || /**
3996
+ * The document has been created but the current dimension has never been saved.
3997
+ * For example, the user is creating a new locale in an existing document,
3998
+ * so there's no history for the document in that locale
3999
+ */
4000
+ !document.id || /**
4001
+ * History is only available for content types created by the user.
4002
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
4003
+ * which start with `admin::` or `plugin::`
4004
+ */
4005
+ !model.startsWith("api::")
4006
+ ),
4007
+ position: "header"
4008
+ };
4009
+ };
4010
+ HistoryAction.type = "history";
4011
+ HistoryAction.position = "header";
4012
+ const historyAdmin = {
4013
+ bootstrap(app) {
4014
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
4015
+ addDocumentAction((actions2) => {
4016
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
4017
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
4018
+ return actions2;
4019
+ });
4020
+ }
4021
+ };
3675
4022
  const initialState = {
3676
4023
  collectionTypeLinks: [],
3677
4024
  components: [],
@@ -3708,6 +4055,90 @@ const { setInitialData } = actions;
3708
4055
  const reducer = toolkit.combineReducers({
3709
4056
  app: reducer$1
3710
4057
  });
4058
+ const previewApi = contentManagerApi.injectEndpoints({
4059
+ endpoints: (builder) => ({
4060
+ getPreviewUrl: builder.query({
4061
+ query({ query, params }) {
4062
+ return {
4063
+ url: `/content-manager/preview/url/${params.contentType}`,
4064
+ method: "GET",
4065
+ config: {
4066
+ params: query
4067
+ }
4068
+ };
4069
+ }
4070
+ })
4071
+ })
4072
+ });
4073
+ const { useGetPreviewUrlQuery } = previewApi;
4074
+ const ConditionalTooltip = ({ isShown, label, children }) => {
4075
+ if (isShown) {
4076
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { label, children });
4077
+ }
4078
+ return children;
4079
+ };
4080
+ const PreviewSidePanel = ({ model, documentId, document }) => {
4081
+ const { formatMessage } = reactIntl.useIntl();
4082
+ const { trackUsage } = strapiAdmin.useTracking();
4083
+ const { pathname } = reactRouterDom.useLocation();
4084
+ const [{ query }] = strapiAdmin.useQueryParams();
4085
+ const isModified = strapiAdmin.useForm("PreviewSidePanel", (state) => state.modified);
4086
+ const { data, error } = useGetPreviewUrlQuery({
4087
+ params: {
4088
+ contentType: model
4089
+ },
4090
+ query: {
4091
+ documentId,
4092
+ locale: document?.locale,
4093
+ status: document?.status
4094
+ }
4095
+ });
4096
+ if (!data?.data?.url || error) {
4097
+ return null;
4098
+ }
4099
+ const trackNavigation = () => {
4100
+ const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
4101
+ trackUsage("willNavigate", { from: pathname, to: destinationPathname });
4102
+ };
4103
+ return {
4104
+ title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
4105
+ content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
4106
+ ConditionalTooltip,
4107
+ {
4108
+ label: formatMessage({
4109
+ id: "content-manager.preview.panel.button-disabled-tooltip",
4110
+ defaultMessage: "Please save to open the preview"
4111
+ }),
4112
+ isShown: isModified,
4113
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4114
+ designSystem.Button,
4115
+ {
4116
+ variant: "tertiary",
4117
+ tag: reactRouterDom.Link,
4118
+ to: { pathname: "preview", search: qs.stringify(query, { encode: false }) },
4119
+ onClick: trackNavigation,
4120
+ flex: "auto",
4121
+ disabled: isModified,
4122
+ children: formatMessage({
4123
+ id: "content-manager.preview.panel.button",
4124
+ defaultMessage: "Open preview"
4125
+ })
4126
+ }
4127
+ )
4128
+ }
4129
+ ) })
4130
+ };
4131
+ };
4132
+ const FEATURE_ID = "preview";
4133
+ const previewAdmin = {
4134
+ bootstrap(app) {
4135
+ if (!window.strapi.future.isEnabled(FEATURE_ID)) {
4136
+ return;
4137
+ }
4138
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
4139
+ contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
4140
+ }
4141
+ };
3711
4142
  const index = {
3712
4143
  register(app) {
3713
4144
  const cm = new ContentManagerPlugin();
@@ -3727,7 +4158,7 @@ const index = {
3727
4158
  app.router.addRoute({
3728
4159
  path: "content-manager/*",
3729
4160
  lazy: async () => {
3730
- const { Layout } = await Promise.resolve().then(() => require("./layout-Dm6fbiQj.js"));
4161
+ const { Layout } = await Promise.resolve().then(() => require("./layout-nBPDlXjr.js"));
3731
4162
  return {
3732
4163
  Component: Layout
3733
4164
  };
@@ -3736,10 +4167,18 @@ const index = {
3736
4167
  });
3737
4168
  app.registerPlugin(cm.config);
3738
4169
  },
4170
+ bootstrap(app) {
4171
+ if (typeof historyAdmin.bootstrap === "function") {
4172
+ historyAdmin.bootstrap(app);
4173
+ }
4174
+ if (typeof previewAdmin.bootstrap === "function") {
4175
+ previewAdmin.bootstrap(app);
4176
+ }
4177
+ },
3739
4178
  async registerTrads({ locales }) {
3740
4179
  const importedTrads = await Promise.all(
3741
4180
  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 }) => {
4181
+ 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
4182
  return {
3744
4183
  data: prefixPluginTranslations(data, PLUGIN_ID),
3745
4184
  locale
@@ -3757,6 +4196,7 @@ const index = {
3757
4196
  };
3758
4197
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3759
4198
  exports.BulkActionsRenderer = BulkActionsRenderer;
4199
+ exports.CLONE_PATH = CLONE_PATH;
3760
4200
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3761
4201
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3762
4202
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3784,6 +4224,7 @@ exports.getMainField = getMainField;
3784
4224
  exports.getTranslation = getTranslation;
3785
4225
  exports.index = index;
3786
4226
  exports.setInitialData = setInitialData;
4227
+ exports.useContentManagerContext = useContentManagerContext;
3787
4228
  exports.useContentTypeSchema = useContentTypeSchema;
3788
4229
  exports.useDoc = useDoc;
3789
4230
  exports.useDocLayout = useDocLayout;
@@ -3795,5 +4236,6 @@ exports.useGetAllContentTypeSettingsQuery = useGetAllContentTypeSettingsQuery;
3795
4236
  exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3796
4237
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3797
4238
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
4239
+ exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
3798
4240
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3799
- //# sourceMappingURL=index-DVPWZkbS.js.map
4241
+ //# sourceMappingURL=index-BN1pPa5v.js.map