@strapi/content-manager 0.0.0-experimental.16eaafeff6bd4cd49d56f3c31d002cad71a1134a → 0.0.0-experimental.19d775295eb622de3e659110caf22fcd2cd5d10d

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 (227) 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-B5mDY7I0.mjs → ComponentConfigurationPage-B_99pmC0.mjs} +4 -4
  5. package/dist/_chunks/{ComponentConfigurationPage-B5mDY7I0.mjs.map → ComponentConfigurationPage-B_99pmC0.mjs.map} +1 -1
  6. package/dist/_chunks/{ComponentConfigurationPage-Tqd-Ji_E.js → ComponentConfigurationPage-NeMPjY5M.js} +5 -6
  7. package/dist/_chunks/{ComponentConfigurationPage-Tqd-Ji_E.js.map → ComponentConfigurationPage-NeMPjY5M.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-B8UqkdtD.mjs → EditConfigurationPage-B0kNlNoj.mjs} +4 -4
  12. package/dist/_chunks/{EditConfigurationPage-B8UqkdtD.mjs.map → EditConfigurationPage-B0kNlNoj.mjs.map} +1 -1
  13. package/dist/_chunks/{EditConfigurationPage-C28IfcPs.js → EditConfigurationPage-n7_xHayb.js} +5 -6
  14. package/dist/_chunks/{EditConfigurationPage-C28IfcPs.js.map → EditConfigurationPage-n7_xHayb.js.map} +1 -1
  15. package/dist/_chunks/{EditViewPage-BDL9cM0Q.js → EditViewPage-BT7Achc-.js} +36 -49
  16. package/dist/_chunks/EditViewPage-BT7Achc-.js.map +1 -0
  17. package/dist/_chunks/{EditViewPage-DQUCbpW-.mjs → EditViewPage-DYXZs4_2.mjs} +34 -46
  18. package/dist/_chunks/EditViewPage-DYXZs4_2.mjs.map +1 -0
  19. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
  20. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
  21. package/dist/_chunks/{Form-DVvv6Hst.js → Form-BRmk2Dp3.js} +39 -21
  22. package/dist/_chunks/Form-BRmk2Dp3.js.map +1 -0
  23. package/dist/_chunks/{Form-DZGlZ79l.mjs → Form-D3paRF1F.mjs} +37 -18
  24. package/dist/_chunks/Form-D3paRF1F.mjs.map +1 -0
  25. package/dist/_chunks/{History-CQl54kNG.js → History-BQpDoOu8.js} +118 -127
  26. package/dist/_chunks/History-BQpDoOu8.js.map +1 -0
  27. package/dist/_chunks/{History-DOWk7MB4.mjs → History-CzQbTOwa.mjs} +108 -116
  28. package/dist/_chunks/History-CzQbTOwa.mjs.map +1 -0
  29. package/dist/_chunks/{Field-DSGnyyoh.mjs → Input-ww3KFYZr.mjs} +1439 -1320
  30. package/dist/_chunks/Input-ww3KFYZr.mjs.map +1 -0
  31. package/dist/_chunks/{Field-D8I8rXr9.js → Input-yM6HnyQa.js} +1431 -1312
  32. package/dist/_chunks/Input-yM6HnyQa.js.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-G_22rTAp.js → ListConfigurationPage-B6NsS-0m.js} +25 -13
  34. package/dist/_chunks/ListConfigurationPage-B6NsS-0m.js.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-lN3NMkhK.mjs → ListConfigurationPage-Bbw8w5cS.mjs} +25 -12
  36. package/dist/_chunks/ListConfigurationPage-Bbw8w5cS.mjs.map +1 -0
  37. package/dist/_chunks/{ListViewPage-D_MY3zjg.mjs → ListViewPage-DnOP55pM.mjs} +122 -78
  38. package/dist/_chunks/ListViewPage-DnOP55pM.mjs.map +1 -0
  39. package/dist/_chunks/{ListViewPage-BIEXJtcz.js → ListViewPage-Dt8OUTwO.js} +121 -78
  40. package/dist/_chunks/ListViewPage-Dt8OUTwO.js.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-CUrrV_mP.mjs → NoContentTypePage-CXKXHNMa.mjs} +2 -2
  42. package/dist/_chunks/{NoContentTypePage-CUrrV_mP.mjs.map → NoContentTypePage-CXKXHNMa.mjs.map} +1 -1
  43. package/dist/_chunks/{NoContentTypePage-P-gvTfgg.js → NoContentTypePage-Dgm-uj-6.js} +2 -2
  44. package/dist/_chunks/{NoContentTypePage-P-gvTfgg.js.map → NoContentTypePage-Dgm-uj-6.js.map} +1 -1
  45. package/dist/_chunks/{NoPermissionsPage-CIFc7iTR.js → NoPermissionsPage-CLbU5SOt.js} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-CIFc7iTR.js.map → NoPermissionsPage-CLbU5SOt.js.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-B-DP9Ht4.mjs → NoPermissionsPage-kaj1rPiW.mjs} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-B-DP9Ht4.mjs.map → NoPermissionsPage-kaj1rPiW.mjs.map} +1 -1
  49. package/dist/_chunks/Preview-Bieh13Ro.mjs +287 -0
  50. package/dist/_chunks/Preview-Bieh13Ro.mjs.map +1 -0
  51. package/dist/_chunks/Preview-CbXHXqBg.js +305 -0
  52. package/dist/_chunks/Preview-CbXHXqBg.js.map +1 -0
  53. package/dist/_chunks/{Relations-CSzJbIBP.mjs → Relations-7rWJcZ3_.mjs} +76 -42
  54. package/dist/_chunks/Relations-7rWJcZ3_.mjs.map +1 -0
  55. package/dist/_chunks/{Relations-BqSXkgPb.js → Relations-CvifV6Y6.js} +76 -43
  56. package/dist/_chunks/Relations-CvifV6Y6.js.map +1 -0
  57. package/dist/_chunks/{en-fbKQxLGn.js → en-BR48D_RH.js} +39 -18
  58. package/dist/_chunks/{en-fbKQxLGn.js.map → en-BR48D_RH.js.map} +1 -1
  59. package/dist/_chunks/{en-Ux26r5pl.mjs → en-D65uIF6Y.mjs} +39 -18
  60. package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-D65uIF6Y.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-B7kGGg3E.js → fr-C43IbhA_.js} +16 -3
  66. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-C43IbhA_.js.map} +1 -1
  67. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr-DBseuRuB.mjs} +16 -3
  68. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr-DBseuRuB.mjs.map} +1 -1
  69. package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
  70. package/dist/_chunks/{index-BYpa_5O9.mjs → index-BH2JnYpF.mjs} +1477 -782
  71. package/dist/_chunks/index-BH2JnYpF.mjs.map +1 -0
  72. package/dist/_chunks/{index-iXGIUU_l.js → index-DkJQjlak.js} +1459 -764
  73. package/dist/_chunks/index-DkJQjlak.js.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-BLa_DTtQ.js → layout-4BqLFW_b.js} +26 -14
  79. package/dist/_chunks/layout-4BqLFW_b.js.map +1 -0
  80. package/dist/_chunks/{layout-DT9g7_U1.mjs → layout-bbOlPwLA.mjs} +26 -13
  81. package/dist/_chunks/layout-bbOlPwLA.mjs.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-CHM_mYAI.mjs → relations-HsflnFpO.mjs} +6 -7
  87. package/dist/_chunks/relations-HsflnFpO.mjs.map +1 -0
  88. package/dist/_chunks/{relations--l5ixWIN.js → relations-Yc0Z6A20.js} +6 -7
  89. package/dist/_chunks/relations-Yc0Z6A20.js.map +1 -0
  90. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
  91. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
  92. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
  93. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
  94. package/dist/_chunks/usePrev-CZGy2Vjf.mjs +29 -0
  95. package/dist/_chunks/usePrev-CZGy2Vjf.mjs.map +1 -0
  96. package/dist/_chunks/{usePrev-B9w_-eYc.js → usePrev-D5J_2fEu.js} +14 -1
  97. package/dist/_chunks/usePrev-D5J_2fEu.js.map +1 -0
  98. package/dist/admin/index.js +3 -1
  99. package/dist/admin/index.js.map +1 -1
  100. package/dist/admin/index.mjs +6 -4
  101. package/dist/admin/src/content-manager.d.ts +4 -2
  102. package/dist/admin/src/exports.d.ts +2 -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 +49 -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 +3 -3
  110. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
  111. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
  112. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
  113. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +4 -1
  114. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +4 -1
  115. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  116. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  117. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  118. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  119. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +27 -0
  120. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  121. package/dist/admin/src/pages/EditView/utils/data.d.ts +1 -0
  122. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  123. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  124. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  125. package/dist/admin/src/preview/index.d.ts +4 -0
  126. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  127. package/dist/admin/src/preview/routes.d.ts +3 -0
  128. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  129. package/dist/admin/src/router.d.ts +1 -1
  130. package/dist/admin/src/services/api.d.ts +1 -1
  131. package/dist/admin/src/services/components.d.ts +2 -2
  132. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  133. package/dist/admin/src/services/documents.d.ts +19 -20
  134. package/dist/admin/src/services/init.d.ts +1 -1
  135. package/dist/admin/src/services/relations.d.ts +2 -2
  136. package/dist/admin/src/services/uid.d.ts +3 -3
  137. package/dist/admin/src/utils/validation.d.ts +4 -1
  138. package/dist/server/index.js +762 -432
  139. package/dist/server/index.js.map +1 -1
  140. package/dist/server/index.mjs +763 -432
  141. package/dist/server/index.mjs.map +1 -1
  142. package/dist/server/src/bootstrap.d.ts.map +1 -1
  143. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  144. package/dist/server/src/controllers/index.d.ts.map +1 -1
  145. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  146. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  147. package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
  148. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  149. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  150. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  151. package/dist/server/src/history/controllers/history-version.d.ts +1 -1
  152. package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
  153. package/dist/server/src/history/services/history.d.ts +3 -3
  154. package/dist/server/src/history/services/history.d.ts.map +1 -1
  155. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  156. package/dist/server/src/history/services/utils.d.ts +8 -12
  157. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  158. package/dist/server/src/index.d.ts +7 -6
  159. package/dist/server/src/index.d.ts.map +1 -1
  160. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  161. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  162. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  163. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  164. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  165. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  166. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  167. package/dist/server/src/preview/index.d.ts +4 -0
  168. package/dist/server/src/preview/index.d.ts.map +1 -0
  169. package/dist/server/src/preview/routes/index.d.ts +8 -0
  170. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  171. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  172. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  173. package/dist/server/src/preview/services/index.d.ts +16 -0
  174. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  175. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  176. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  177. package/dist/server/src/preview/services/preview.d.ts +12 -0
  178. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  179. package/dist/server/src/preview/utils.d.ts +19 -0
  180. package/dist/server/src/preview/utils.d.ts.map +1 -0
  181. package/dist/server/src/register.d.ts.map +1 -1
  182. package/dist/server/src/routes/index.d.ts.map +1 -1
  183. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  184. package/dist/server/src/services/document-metadata.d.ts +12 -10
  185. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  186. package/dist/server/src/services/index.d.ts +7 -6
  187. package/dist/server/src/services/index.d.ts.map +1 -1
  188. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  189. package/dist/server/src/services/utils/populate.d.ts +2 -2
  190. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  191. package/dist/server/src/utils/index.d.ts +2 -0
  192. package/dist/server/src/utils/index.d.ts.map +1 -1
  193. package/dist/shared/contracts/collection-types.d.ts +3 -1
  194. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  195. package/dist/shared/contracts/index.d.ts +1 -0
  196. package/dist/shared/contracts/index.d.ts.map +1 -1
  197. package/dist/shared/contracts/preview.d.ts +27 -0
  198. package/dist/shared/contracts/preview.d.ts.map +1 -0
  199. package/dist/shared/index.js +4 -0
  200. package/dist/shared/index.js.map +1 -1
  201. package/dist/shared/index.mjs +4 -0
  202. package/dist/shared/index.mjs.map +1 -1
  203. package/package.json +17 -16
  204. package/dist/_chunks/EditViewPage-BDL9cM0Q.js.map +0 -1
  205. package/dist/_chunks/EditViewPage-DQUCbpW-.mjs.map +0 -1
  206. package/dist/_chunks/Field-D8I8rXr9.js.map +0 -1
  207. package/dist/_chunks/Field-DSGnyyoh.mjs.map +0 -1
  208. package/dist/_chunks/Form-DVvv6Hst.js.map +0 -1
  209. package/dist/_chunks/Form-DZGlZ79l.mjs.map +0 -1
  210. package/dist/_chunks/History-CQl54kNG.js.map +0 -1
  211. package/dist/_chunks/History-DOWk7MB4.mjs.map +0 -1
  212. package/dist/_chunks/ListConfigurationPage-G_22rTAp.js.map +0 -1
  213. package/dist/_chunks/ListConfigurationPage-lN3NMkhK.mjs.map +0 -1
  214. package/dist/_chunks/ListViewPage-BIEXJtcz.js.map +0 -1
  215. package/dist/_chunks/ListViewPage-D_MY3zjg.mjs.map +0 -1
  216. package/dist/_chunks/Relations-BqSXkgPb.js.map +0 -1
  217. package/dist/_chunks/Relations-CSzJbIBP.mjs.map +0 -1
  218. package/dist/_chunks/index-BYpa_5O9.mjs.map +0 -1
  219. package/dist/_chunks/index-iXGIUU_l.js.map +0 -1
  220. package/dist/_chunks/layout-BLa_DTtQ.js.map +0 -1
  221. package/dist/_chunks/layout-DT9g7_U1.mjs.map +0 -1
  222. package/dist/_chunks/relations--l5ixWIN.js.map +0 -1
  223. package/dist/_chunks/relations-CHM_mYAI.mjs.map +0 -1
  224. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  225. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  226. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  227. package/strapi-server.js +0 -3
@@ -2,20 +2,21 @@
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 fractionalIndexing = require("fractional-indexing");
12
13
  const pipe = require("lodash/fp/pipe");
14
+ const qs = require("qs");
13
15
  const dateFns = require("date-fns");
14
16
  const toolkit = require("@reduxjs/toolkit");
15
17
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
16
18
  function _interopNamespace(e) {
17
- if (e && e.__esModule)
18
- return e;
19
+ if (e && e.__esModule) return e;
19
20
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
20
21
  if (e) {
21
22
  for (const k in e) {
@@ -32,15 +33,23 @@ function _interopNamespace(e) {
32
33
  return Object.freeze(n);
33
34
  }
34
35
  const React__namespace = /* @__PURE__ */ _interopNamespace(React);
36
+ const mapValues__default = /* @__PURE__ */ _interopDefault(mapValues);
35
37
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
36
38
  const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
37
- const __variableDynamicImportRuntimeHelper = (glob, path) => {
39
+ const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
38
40
  const v = glob[path];
39
41
  if (v) {
40
42
  return typeof v === "function" ? v() : Promise.resolve(v);
41
43
  }
42
44
  return new Promise((_, reject) => {
43
- (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(reject.bind(null, new Error("Unknown variable dynamic import: " + path)));
45
+ (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
46
+ reject.bind(
47
+ null,
48
+ new Error(
49
+ "Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
50
+ )
51
+ )
52
+ );
44
53
  });
45
54
  };
46
55
  const PLUGIN_ID = "content-manager";
@@ -70,42 +79,6 @@ const useInjectionZone = (area) => {
70
79
  const [page, position] = area.split(".");
71
80
  return contentManagerPlugin.getInjectedComponents(page, position);
72
81
  };
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
82
  const ID = "id";
110
83
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
111
84
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -157,6 +130,7 @@ const DocumentRBAC = ({ children, permissions }) => {
157
130
  if (!slug) {
158
131
  throw new Error("Cannot find the slug param in the URL");
159
132
  }
133
+ const [{ rawQuery }] = strapiAdmin.useQueryParams();
160
134
  const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
161
135
  const contentTypePermissions = React__namespace.useMemo(() => {
162
136
  const contentTypePermissions2 = userPermissions.filter(
@@ -167,7 +141,14 @@ const DocumentRBAC = ({ children, permissions }) => {
167
141
  return { ...acc, [action]: [permission] };
168
142
  }, {});
169
143
  }, [slug, userPermissions]);
170
- const { isLoading, allowedActions } = strapiAdmin.useRBAC(contentTypePermissions, permissions ?? void 0);
144
+ const { isLoading, allowedActions } = strapiAdmin.useRBAC(
145
+ contentTypePermissions,
146
+ permissions ?? void 0,
147
+ // TODO: useRBAC context should be typed and built differently
148
+ // We are passing raw query as context to the hook so that it can
149
+ // rely on the locale provided from DocumentRBAC for its permission calculations.
150
+ rawQuery
151
+ );
171
152
  const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
172
153
  const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
173
154
  const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
@@ -207,6 +188,113 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
207
188
  (field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
208
189
  );
209
190
  const removeNumericalStrings = (arr) => arr.filter((item) => isNaN(Number(item)));
191
+ const BLOCK_LIST_ATTRIBUTE_KEYS = ["__component", "__temp_key__"];
192
+ const traverseData = (predicate, transform) => (schema, components = {}) => (data = {}) => {
193
+ const traverse = (datum, attributes) => {
194
+ return Object.entries(datum).reduce((acc, [key, value]) => {
195
+ const attribute = attributes[key];
196
+ if (BLOCK_LIST_ATTRIBUTE_KEYS.includes(key) || value === null || value === void 0) {
197
+ acc[key] = value;
198
+ return acc;
199
+ }
200
+ if (attribute.type === "component") {
201
+ if (attribute.repeatable) {
202
+ const componentValue = predicate(attribute, value) ? transform(value, attribute) : value;
203
+ acc[key] = componentValue.map(
204
+ (componentData) => traverse(componentData, components[attribute.component]?.attributes ?? {})
205
+ );
206
+ } else {
207
+ const componentValue = predicate(attribute, value) ? transform(value, attribute) : value;
208
+ acc[key] = traverse(componentValue, components[attribute.component]?.attributes ?? {});
209
+ }
210
+ } else if (attribute.type === "dynamiczone") {
211
+ const dynamicZoneValue = predicate(attribute, value) ? transform(value, attribute) : value;
212
+ acc[key] = dynamicZoneValue.map(
213
+ (componentData) => traverse(componentData, components[componentData.__component]?.attributes ?? {})
214
+ );
215
+ } else if (predicate(attribute, value)) {
216
+ acc[key] = transform(value, attribute);
217
+ } else {
218
+ acc[key] = value;
219
+ }
220
+ return acc;
221
+ }, {});
222
+ };
223
+ return traverse(data, schema.attributes);
224
+ };
225
+ const removeProhibitedFields = (prohibitedFields) => traverseData(
226
+ (attribute) => prohibitedFields.includes(attribute.type),
227
+ () => ""
228
+ );
229
+ const prepareRelations = traverseData(
230
+ (attribute) => attribute.type === "relation",
231
+ () => ({
232
+ connect: [],
233
+ disconnect: []
234
+ })
235
+ );
236
+ const prepareTempKeys = traverseData(
237
+ (attribute) => attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone",
238
+ (data) => {
239
+ if (Array.isArray(data) && data.length > 0) {
240
+ const keys = fractionalIndexing.generateNKeysBetween(void 0, void 0, data.length);
241
+ return data.map((datum, index2) => ({
242
+ ...datum,
243
+ __temp_key__: keys[index2]
244
+ }));
245
+ }
246
+ return data;
247
+ }
248
+ );
249
+ const removeFieldsThatDontExistOnSchema = (schema) => (data) => {
250
+ const schemaKeys = Object.keys(schema.attributes);
251
+ const dataKeys = Object.keys(data);
252
+ const keysToRemove = dataKeys.filter((key) => !schemaKeys.includes(key));
253
+ const revisedData = [...keysToRemove, ...DOCUMENT_META_FIELDS].reduce((acc, key) => {
254
+ delete acc[key];
255
+ return acc;
256
+ }, structuredClone(data));
257
+ return revisedData;
258
+ };
259
+ const removeNullValues = (data) => {
260
+ return Object.entries(data).reduce((acc, [key, value]) => {
261
+ if (value === null) {
262
+ return acc;
263
+ }
264
+ acc[key] = value;
265
+ return acc;
266
+ }, {});
267
+ };
268
+ const transformDocument = (schema, components = {}) => (document) => {
269
+ const transformations = pipe__default.default(
270
+ removeFieldsThatDontExistOnSchema(schema),
271
+ removeProhibitedFields(["password"])(schema, components),
272
+ removeNullValues,
273
+ prepareRelations(schema, components),
274
+ prepareTempKeys(schema, components)
275
+ );
276
+ return transformations(document);
277
+ };
278
+ const createDefaultForm = (contentType, components = {}) => {
279
+ const traverseSchema = (attributes) => {
280
+ return Object.entries(attributes).reduce((acc, [key, attribute]) => {
281
+ if ("default" in attribute) {
282
+ acc[key] = attribute.default;
283
+ } else if (attribute.type === "component" && attribute.required) {
284
+ const defaultComponentForm = traverseSchema(components[attribute.component].attributes);
285
+ if (attribute.repeatable) {
286
+ acc[key] = attribute.min ? [...Array(attribute.min).fill(defaultComponentForm)] : [];
287
+ } else {
288
+ acc[key] = defaultComponentForm;
289
+ }
290
+ } else if (attribute.type === "dynamiczone" && attribute.required) {
291
+ acc[key] = [];
292
+ }
293
+ return acc;
294
+ }, {});
295
+ };
296
+ return traverseSchema(contentType.attributes);
297
+ };
210
298
  const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
211
299
  addTagTypes: [
212
300
  "ComponentConfiguration",
@@ -215,7 +303,9 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
215
303
  "Document",
216
304
  "InitialData",
217
305
  "HistoryVersion",
218
- "Relations"
306
+ "Relations",
307
+ "UidAvailability",
308
+ "RecentDocumentList"
219
309
  ]
220
310
  });
221
311
  const documentApi = contentManagerApi.injectEndpoints({
@@ -229,7 +319,12 @@ const documentApi = contentManagerApi.injectEndpoints({
229
319
  params: query
230
320
  }
231
321
  }),
232
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
322
+ invalidatesTags: (_result, error, { model }) => {
323
+ if (error) {
324
+ return [];
325
+ }
326
+ return [{ type: "Document", id: `${model}_LIST` }, "RecentDocumentList"];
327
+ }
233
328
  }),
234
329
  cloneDocument: builder.mutation({
235
330
  query: ({ model, sourceId, data, params }) => ({
@@ -240,7 +335,11 @@ const documentApi = contentManagerApi.injectEndpoints({
240
335
  params
241
336
  }
242
337
  }),
243
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
338
+ invalidatesTags: (_result, _error, { model }) => [
339
+ { type: "Document", id: `${model}_LIST` },
340
+ { type: "UidAvailability", id: model },
341
+ "RecentDocumentList"
342
+ ]
244
343
  }),
245
344
  /**
246
345
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -257,8 +356,22 @@ const documentApi = contentManagerApi.injectEndpoints({
257
356
  }),
258
357
  invalidatesTags: (result, _error, { model }) => [
259
358
  { type: "Document", id: `${model}_LIST` },
260
- "Relations"
261
- ]
359
+ "Relations",
360
+ { type: "UidAvailability", id: model },
361
+ "RecentDocumentList"
362
+ ],
363
+ transformResponse: (response, meta, arg) => {
364
+ if (!("data" in response) && arg.model === "plugin::users-permissions.user") {
365
+ return {
366
+ data: response,
367
+ meta: {
368
+ availableStatus: [],
369
+ availableLocales: []
370
+ }
371
+ };
372
+ }
373
+ return response;
374
+ }
262
375
  }),
263
376
  deleteDocument: builder.mutation({
264
377
  query: ({ collectionType, model, documentId, params }) => ({
@@ -269,7 +382,8 @@ const documentApi = contentManagerApi.injectEndpoints({
269
382
  }
270
383
  }),
271
384
  invalidatesTags: (_result, _error, { collectionType, model }) => [
272
- { type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model }
385
+ { type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model },
386
+ "RecentDocumentList"
273
387
  ]
274
388
  }),
275
389
  deleteManyDocuments: builder.mutation({
@@ -281,7 +395,10 @@ const documentApi = contentManagerApi.injectEndpoints({
281
395
  params
282
396
  }
283
397
  }),
284
- invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
398
+ invalidatesTags: (_res, _error, { model }) => [
399
+ { type: "Document", id: `${model}_LIST` },
400
+ "RecentDocumentList"
401
+ ]
285
402
  }),
286
403
  discardDocument: builder.mutation({
287
404
  query: ({ collectionType, model, documentId, params }) => ({
@@ -298,7 +415,9 @@ const documentApi = contentManagerApi.injectEndpoints({
298
415
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
299
416
  },
300
417
  { type: "Document", id: `${model}_LIST` },
301
- "Relations"
418
+ "Relations",
419
+ { type: "UidAvailability", id: model },
420
+ "RecentDocumentList"
302
421
  ];
303
422
  }
304
423
  }),
@@ -311,11 +430,12 @@ const documentApi = contentManagerApi.injectEndpoints({
311
430
  url: `/content-manager/collection-types/${model}`,
312
431
  method: "GET",
313
432
  config: {
314
- params
433
+ params: qs.stringify(params, { encode: true })
315
434
  }
316
435
  }),
317
436
  providesTags: (result, _error, arg) => {
318
437
  return [
438
+ { type: "Document", id: `ALL_LIST` },
319
439
  { type: "Document", id: `${arg.model}_LIST` },
320
440
  ...result?.results.map(({ documentId }) => ({
321
441
  type: "Document",
@@ -354,6 +474,11 @@ const documentApi = contentManagerApi.injectEndpoints({
354
474
  {
355
475
  type: "Document",
356
476
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
477
+ },
478
+ // Make it easy to invalidate all individual documents queries for a model
479
+ {
480
+ type: "Document",
481
+ id: `${model}_ALL_ITEMS`
357
482
  }
358
483
  ];
359
484
  }
@@ -387,7 +512,8 @@ const documentApi = contentManagerApi.injectEndpoints({
387
512
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
388
513
  },
389
514
  { type: "Document", id: `${model}_LIST` },
390
- "Relations"
515
+ "Relations",
516
+ "RecentDocumentList"
391
517
  ];
392
518
  }
393
519
  }),
@@ -417,8 +543,23 @@ const documentApi = contentManagerApi.injectEndpoints({
417
543
  type: "Document",
418
544
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
419
545
  },
420
- "Relations"
546
+ "Relations",
547
+ { type: "UidAvailability", id: model },
548
+ "RecentDocumentList",
549
+ "RecentDocumentList"
421
550
  ];
551
+ },
552
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
553
+ const patchResult = dispatch(
554
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
555
+ Object.assign(draft.data, data);
556
+ })
557
+ );
558
+ try {
559
+ await queryFulfilled;
560
+ } catch {
561
+ patchResult.undo();
562
+ }
422
563
  }
423
564
  }),
424
565
  unpublishDocument: builder.mutation({
@@ -435,7 +576,8 @@ const documentApi = contentManagerApi.injectEndpoints({
435
576
  {
436
577
  type: "Document",
437
578
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
438
- }
579
+ },
580
+ "RecentDocumentList"
439
581
  ];
440
582
  }
441
583
  }),
@@ -448,7 +590,10 @@ const documentApi = contentManagerApi.injectEndpoints({
448
590
  params
449
591
  }
450
592
  }),
451
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
593
+ invalidatesTags: (_res, _error, { model, documentIds }) => [
594
+ ...documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` })),
595
+ "RecentDocumentList"
596
+ ]
452
597
  })
453
598
  })
454
599
  });
@@ -471,8 +616,7 @@ const {
471
616
  useUnpublishManyDocumentsMutation
472
617
  } = documentApi;
473
618
  const buildValidParams = (query) => {
474
- if (!query)
475
- return query;
619
+ if (!query) return query;
476
620
  const { plugins: _, ...validQueryParams } = {
477
621
  ...query,
478
622
  ...Object.values(query?.plugins ?? {}).reduce(
@@ -480,28 +624,44 @@ const buildValidParams = (query) => {
480
624
  {}
481
625
  )
482
626
  };
483
- if ("_q" in validQueryParams) {
484
- validQueryParams._q = encodeURIComponent(validQueryParams._q);
485
- }
486
627
  return validQueryParams;
487
628
  };
488
629
  const isBaseQueryError = (error) => {
489
630
  return error.name !== void 0;
490
631
  };
491
- const createYupSchema = (attributes = {}, components = {}) => {
632
+ const arrayValidator = (attribute, options) => ({
633
+ message: strapiAdmin.translatedErrors.required,
634
+ test(value) {
635
+ if (options.status === "draft") {
636
+ return true;
637
+ }
638
+ if (!attribute.required) {
639
+ return true;
640
+ }
641
+ if (!value) {
642
+ return false;
643
+ }
644
+ if (Array.isArray(value) && value.length === 0) {
645
+ return false;
646
+ }
647
+ return true;
648
+ }
649
+ });
650
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
492
651
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
493
652
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
494
653
  if (DOCUMENT_META_FIELDS.includes(name)) {
495
654
  return acc;
496
655
  }
497
656
  const validations = [
657
+ addNullableValidation,
498
658
  addRequiredValidation,
499
659
  addMinLengthValidation,
500
660
  addMaxLengthValidation,
501
661
  addMinValidation,
502
662
  addMaxValidation,
503
663
  addRegexValidation
504
- ].map((fn) => fn(attribute));
664
+ ].map((fn) => fn(attribute, options));
505
665
  const transformSchema = pipe__default.default(...validations);
506
666
  switch (attribute.type) {
507
667
  case "component": {
@@ -511,12 +671,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
511
671
  ...acc,
512
672
  [name]: transformSchema(
513
673
  yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
514
- )
674
+ ).test(arrayValidator(attribute, options))
515
675
  };
516
676
  } else {
517
677
  return {
518
678
  ...acc,
519
- [name]: transformSchema(createModelSchema(attributes3))
679
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
520
680
  };
521
681
  }
522
682
  }
@@ -538,7 +698,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
538
698
  }
539
699
  )
540
700
  )
541
- )
701
+ ).test(arrayValidator(attribute, options))
542
702
  };
543
703
  case "relation":
544
704
  return {
@@ -550,7 +710,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
550
710
  } else if (Array.isArray(value)) {
551
711
  return yup__namespace.array().of(
552
712
  yup__namespace.object().shape({
553
- id: yup__namespace.string().required()
713
+ id: yup__namespace.number().required()
554
714
  })
555
715
  );
556
716
  } else if (typeof value === "object") {
@@ -602,6 +762,14 @@ const createAttributeSchema = (attribute) => {
602
762
  if (!value || typeof value === "string" && value.length === 0) {
603
763
  return true;
604
764
  }
765
+ if (typeof value === "object") {
766
+ try {
767
+ JSON.stringify(value);
768
+ return true;
769
+ } catch (err) {
770
+ return false;
771
+ }
772
+ }
605
773
  try {
606
774
  JSON.parse(value);
607
775
  return true;
@@ -620,13 +788,7 @@ const createAttributeSchema = (attribute) => {
620
788
  return yup__namespace.mixed();
621
789
  }
622
790
  };
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
- }
791
+ const nullableSchema = (schema) => {
630
792
  return schema?.nullable ? schema.nullable() : (
631
793
  // In some cases '.nullable' will not be available on the schema.
632
794
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -634,7 +796,22 @@ const addRequiredValidation = (attribute) => (schema) => {
634
796
  schema
635
797
  );
636
798
  };
637
- const addMinLengthValidation = (attribute) => (schema) => {
799
+ const addNullableValidation = () => (schema) => {
800
+ return nullableSchema(schema);
801
+ };
802
+ const addRequiredValidation = (attribute, options) => (schema) => {
803
+ if (options.status === "draft" || !attribute.required) {
804
+ return schema;
805
+ }
806
+ if (attribute.required && "required" in schema) {
807
+ return schema.required(strapiAdmin.translatedErrors.required);
808
+ }
809
+ return schema;
810
+ };
811
+ const addMinLengthValidation = (attribute, options) => (schema) => {
812
+ if (options.status === "draft") {
813
+ return schema;
814
+ }
638
815
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
639
816
  return schema.min(attribute.minLength, {
640
817
  ...strapiAdmin.translatedErrors.minLength,
@@ -656,10 +833,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
656
833
  }
657
834
  return schema;
658
835
  };
659
- const addMinValidation = (attribute) => (schema) => {
660
- if ("min" in attribute) {
836
+ const addMinValidation = (attribute, options) => (schema) => {
837
+ if (options.status === "draft") {
838
+ return schema;
839
+ }
840
+ if ("min" in attribute && "min" in schema) {
661
841
  const min = toInteger(attribute.min);
662
- if ("min" in schema && min) {
842
+ if (min) {
663
843
  return schema.min(min, {
664
844
  ...strapiAdmin.translatedErrors.min,
665
845
  values: {
@@ -777,16 +957,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
777
957
  }, {});
778
958
  return componentsByKey;
779
959
  };
780
- const useDocument = (args, opts) => {
960
+ const HOOKS = {
961
+ /**
962
+ * Hook that allows to mutate the displayed headers of the list view table
963
+ * @constant
964
+ * @type {string}
965
+ */
966
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
967
+ /**
968
+ * Hook that allows to mutate the CM's collection types links pre-set filters
969
+ * @constant
970
+ * @type {string}
971
+ */
972
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
973
+ /**
974
+ * Hook that allows to mutate the CM's edit view layout
975
+ * @constant
976
+ * @type {string}
977
+ */
978
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
979
+ /**
980
+ * Hook that allows to mutate the CM's single types links pre-set filters
981
+ * @constant
982
+ * @type {string}
983
+ */
984
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
985
+ };
986
+ const contentTypesApi = contentManagerApi.injectEndpoints({
987
+ endpoints: (builder) => ({
988
+ getContentTypeConfiguration: builder.query({
989
+ query: (uid) => ({
990
+ url: `/content-manager/content-types/${uid}/configuration`,
991
+ method: "GET"
992
+ }),
993
+ transformResponse: (response) => response.data,
994
+ providesTags: (_result, _error, uid) => [
995
+ { type: "ContentTypesConfiguration", id: uid },
996
+ { type: "ContentTypeSettings", id: "LIST" }
997
+ ]
998
+ }),
999
+ getAllContentTypeSettings: builder.query({
1000
+ query: () => "/content-manager/content-types-settings",
1001
+ transformResponse: (response) => response.data,
1002
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
1003
+ }),
1004
+ updateContentTypeConfiguration: builder.mutation({
1005
+ query: ({ uid, ...body }) => ({
1006
+ url: `/content-manager/content-types/${uid}/configuration`,
1007
+ method: "PUT",
1008
+ data: body
1009
+ }),
1010
+ transformResponse: (response) => response.data,
1011
+ invalidatesTags: (_result, _error, { uid }) => [
1012
+ { type: "ContentTypesConfiguration", id: uid },
1013
+ { type: "ContentTypeSettings", id: "LIST" },
1014
+ // Is this necessary?
1015
+ { type: "InitialData" }
1016
+ ]
1017
+ })
1018
+ })
1019
+ });
1020
+ const {
1021
+ useGetContentTypeConfigurationQuery,
1022
+ useGetAllContentTypeSettingsQuery,
1023
+ useUpdateContentTypeConfigurationMutation
1024
+ } = contentTypesApi;
1025
+ const checkIfAttributeIsDisplayable = (attribute) => {
1026
+ const { type } = attribute;
1027
+ if (type === "relation") {
1028
+ return !attribute.relation.toLowerCase().includes("morph");
1029
+ }
1030
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
1031
+ };
1032
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
1033
+ if (!mainFieldName) {
1034
+ return void 0;
1035
+ }
1036
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
1037
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
1038
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
1039
+ );
1040
+ return {
1041
+ name: mainFieldName,
1042
+ type: mainFieldType ?? "string"
1043
+ };
1044
+ };
1045
+ const DEFAULT_SETTINGS = {
1046
+ bulkable: false,
1047
+ filterable: false,
1048
+ searchable: false,
1049
+ pagination: false,
1050
+ defaultSortBy: "",
1051
+ defaultSortOrder: "asc",
1052
+ mainField: "id",
1053
+ pageSize: 10
1054
+ };
1055
+ const useDocumentLayout = (model) => {
1056
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
1057
+ const [{ query }] = strapiAdmin.useQueryParams();
1058
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
781
1059
  const { toggleNotification } = strapiAdmin.useNotification();
782
1060
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1061
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
783
1062
  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);
1063
+ data,
1064
+ isLoading: isLoadingConfigs,
1065
+ error,
1066
+ isFetching: isFetchingConfigs
1067
+ } = useGetContentTypeConfigurationQuery(model);
1068
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
790
1069
  React__namespace.useEffect(() => {
791
1070
  if (error) {
792
1071
  toggleNotification({
@@ -794,25 +1073,254 @@ const useDocument = (args, opts) => {
794
1073
  message: formatAPIError(error)
795
1074
  });
796
1075
  }
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) {
1076
+ }, [error, formatAPIError, toggleNotification]);
1077
+ const editLayout = React__namespace.useMemo(
1078
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
1079
+ layout: [],
1080
+ components: {},
1081
+ metadatas: {},
1082
+ options: {},
1083
+ settings: DEFAULT_SETTINGS
1084
+ },
1085
+ [data, isLoading, schemas, schema, components]
1086
+ );
1087
+ const listLayout = React__namespace.useMemo(() => {
1088
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
1089
+ layout: [],
1090
+ metadatas: {},
1091
+ options: {},
1092
+ settings: DEFAULT_SETTINGS
1093
+ };
1094
+ }, [data, isLoading, schemas, schema, components]);
1095
+ const { layout: edit } = React__namespace.useMemo(
1096
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
1097
+ layout: editLayout,
1098
+ query
1099
+ }),
1100
+ [editLayout, query, runHookWaterfall]
1101
+ );
1102
+ return {
1103
+ error,
1104
+ isLoading,
1105
+ edit,
1106
+ list: listLayout
1107
+ };
1108
+ };
1109
+ const useDocLayout = () => {
1110
+ const { model } = useDoc();
1111
+ return useDocumentLayout(model);
1112
+ };
1113
+ const formatEditLayout = (data, {
1114
+ schemas,
1115
+ schema,
1116
+ components
1117
+ }) => {
1118
+ let currentPanelIndex = 0;
1119
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
1120
+ data.contentType.layouts.edit,
1121
+ schema?.attributes,
1122
+ data.contentType.metadatas,
1123
+ { configurations: data.components, schemas: components },
1124
+ schemas
1125
+ ).reduce((panels, row) => {
1126
+ if (row.some((field) => field.type === "dynamiczone")) {
1127
+ panels.push([row]);
1128
+ currentPanelIndex += 2;
1129
+ } else {
1130
+ if (!panels[currentPanelIndex]) {
1131
+ panels.push([row]);
1132
+ } else {
1133
+ panels[currentPanelIndex].push(row);
1134
+ }
1135
+ }
1136
+ return panels;
1137
+ }, []);
1138
+ const componentEditAttributes = Object.entries(data.components).reduce(
1139
+ (acc, [uid, configuration]) => {
1140
+ acc[uid] = {
1141
+ layout: convertEditLayoutToFieldLayouts(
1142
+ configuration.layouts.edit,
1143
+ components[uid].attributes,
1144
+ configuration.metadatas,
1145
+ { configurations: data.components, schemas: components }
1146
+ ),
1147
+ settings: {
1148
+ ...configuration.settings,
1149
+ icon: components[uid].info.icon,
1150
+ displayName: components[uid].info.displayName
1151
+ }
1152
+ };
1153
+ return acc;
1154
+ },
1155
+ {}
1156
+ );
1157
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
1158
+ (acc, [attribute, metadata]) => {
1159
+ return {
1160
+ ...acc,
1161
+ [attribute]: metadata.edit
1162
+ };
1163
+ },
1164
+ {}
1165
+ );
1166
+ return {
1167
+ layout: panelledEditAttributes,
1168
+ components: componentEditAttributes,
1169
+ metadatas: editMetadatas,
1170
+ settings: {
1171
+ ...data.contentType.settings,
1172
+ displayName: schema?.info.displayName
1173
+ },
1174
+ options: {
1175
+ ...schema?.options,
1176
+ ...schema?.pluginOptions,
1177
+ ...data.contentType.options
1178
+ }
1179
+ };
1180
+ };
1181
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1182
+ return rows.map(
1183
+ (row) => row.map((field) => {
1184
+ const attribute = attributes[field.name];
1185
+ if (!attribute) {
1186
+ return null;
1187
+ }
1188
+ const { edit: metadata } = metadatas[field.name];
1189
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1190
+ return {
1191
+ attribute,
1192
+ disabled: !metadata.editable,
1193
+ hint: metadata.description,
1194
+ label: metadata.label ?? "",
1195
+ name: field.name,
1196
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1197
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1198
+ schemas,
1199
+ components: components?.schemas ?? {}
1200
+ }),
1201
+ placeholder: metadata.placeholder ?? "",
1202
+ required: attribute.required ?? false,
1203
+ size: field.size,
1204
+ unique: "unique" in attribute ? attribute.unique : false,
1205
+ visible: metadata.visible ?? true,
1206
+ type: attribute.type
1207
+ };
1208
+ }).filter((field) => field !== null)
1209
+ );
1210
+ };
1211
+ const formatListLayout = (data, {
1212
+ schemas,
1213
+ schema,
1214
+ components
1215
+ }) => {
1216
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1217
+ (acc, [attribute, metadata]) => {
1218
+ return {
1219
+ ...acc,
1220
+ [attribute]: metadata.list
1221
+ };
1222
+ },
1223
+ {}
1224
+ );
1225
+ const listAttributes = convertListLayoutToFieldLayouts(
1226
+ data.contentType.layouts.list,
1227
+ schema?.attributes,
1228
+ listMetadatas,
1229
+ { configurations: data.components, schemas: components },
1230
+ schemas
1231
+ );
1232
+ return {
1233
+ layout: listAttributes,
1234
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1235
+ metadatas: listMetadatas,
1236
+ options: {
1237
+ ...schema?.options,
1238
+ ...schema?.pluginOptions,
1239
+ ...data.contentType.options
1240
+ }
1241
+ };
1242
+ };
1243
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1244
+ return columns.map((name) => {
1245
+ const attribute = attributes[name];
1246
+ if (!attribute) {
1247
+ return null;
1248
+ }
1249
+ const metadata = metadatas[name];
1250
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1251
+ return {
1252
+ attribute,
1253
+ label: metadata.label ?? "",
1254
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1255
+ schemas,
1256
+ components: components?.schemas ?? {}
1257
+ }),
1258
+ name,
1259
+ searchable: metadata.searchable ?? true,
1260
+ sortable: metadata.sortable ?? true
1261
+ };
1262
+ }).filter((field) => field !== null);
1263
+ };
1264
+ const useDocument = (args, opts) => {
1265
+ const { toggleNotification } = strapiAdmin.useNotification();
1266
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1267
+ const { formatMessage } = reactIntl.useIntl();
1268
+ const {
1269
+ currentData: data,
1270
+ isLoading: isLoadingDocument,
1271
+ isFetching: isFetchingDocument,
1272
+ error
1273
+ } = useGetDocumentQuery(args, {
1274
+ ...opts,
1275
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1276
+ });
1277
+ const document = data?.data;
1278
+ const meta = data?.meta;
1279
+ const {
1280
+ components,
1281
+ schema,
1282
+ schemas,
1283
+ isLoading: isLoadingSchema
1284
+ } = useContentTypeSchema(args.model);
1285
+ const isSingleType = schema?.kind === "singleType";
1286
+ const getTitle = (mainField) => {
1287
+ if (mainField !== "id" && document?.[mainField]) {
1288
+ return document[mainField];
1289
+ }
1290
+ if (isSingleType && schema?.info.displayName) {
1291
+ return schema.info.displayName;
1292
+ }
1293
+ return formatMessage({
1294
+ id: "content-manager.containers.untitled",
1295
+ defaultMessage: "Untitled"
1296
+ });
1297
+ };
1298
+ React__namespace.useEffect(() => {
1299
+ if (error) {
1300
+ toggleNotification({
1301
+ type: "danger",
1302
+ message: formatAPIError(error)
1303
+ });
1304
+ }
1305
+ }, [toggleNotification, error, formatAPIError, args.collectionType]);
1306
+ const validationSchema = React__namespace.useMemo(() => {
1307
+ if (!schema) {
1308
+ return null;
1309
+ }
1310
+ return createYupSchema(schema.attributes, components);
1311
+ }, [schema, components]);
1312
+ const validate = React__namespace.useCallback(
1313
+ (document2) => {
1314
+ if (!validationSchema) {
1315
+ throw new Error(
1316
+ "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1317
+ );
1318
+ }
1319
+ try {
1320
+ validationSchema.validateSync(document2, { abortEarly: false, strict: true });
1321
+ return null;
1322
+ } catch (error2) {
1323
+ if (error2 instanceof yup.ValidationError) {
816
1324
  return strapiAdmin.getYupValidationErrors(error2);
817
1325
  }
818
1326
  throw error2;
@@ -820,14 +1328,29 @@ const useDocument = (args, opts) => {
820
1328
  },
821
1329
  [validationSchema]
822
1330
  );
1331
+ const getInitialFormValues = React__namespace.useCallback(
1332
+ (isCreatingDocument = false) => {
1333
+ if (!document && !isCreatingDocument && !isSingleType || !schema) {
1334
+ return void 0;
1335
+ }
1336
+ const form = document?.id ? document : createDefaultForm(schema, components);
1337
+ return transformDocument(schema, components)(form);
1338
+ },
1339
+ [document, isSingleType, schema, components]
1340
+ );
823
1341
  const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1342
+ const hasError = !!error;
824
1343
  return {
825
1344
  components,
826
- document: data?.data,
827
- meta: data?.meta,
1345
+ document,
1346
+ meta,
828
1347
  isLoading,
1348
+ hasError,
829
1349
  schema,
830
- validate
1350
+ schemas,
1351
+ validate,
1352
+ getTitle,
1353
+ getInitialFormValues
831
1354
  };
832
1355
  };
833
1356
  const useDoc = () => {
@@ -840,22 +1363,60 @@ const useDoc = () => {
840
1363
  if (!slug) {
841
1364
  throw new Error("Could not find model in url params");
842
1365
  }
1366
+ const document = useDocument(
1367
+ { documentId: origin || id, model: slug, collectionType, params },
1368
+ {
1369
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1370
+ }
1371
+ );
1372
+ const returnId = origin || id === "create" ? void 0 : id;
843
1373
  return {
844
1374
  collectionType,
845
1375
  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
- )
1376
+ id: returnId,
1377
+ ...document
1378
+ };
1379
+ };
1380
+ const useContentManagerContext = () => {
1381
+ const {
1382
+ collectionType,
1383
+ model,
1384
+ id,
1385
+ components,
1386
+ isLoading: isLoadingDoc,
1387
+ schema,
1388
+ schemas
1389
+ } = useDoc();
1390
+ const layout = useDocumentLayout(model);
1391
+ const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
1392
+ const isSingleType = collectionType === SINGLE_TYPES;
1393
+ const slug = model;
1394
+ const isCreatingEntry = id === "create";
1395
+ useContentTypeSchema();
1396
+ const isLoading = isLoadingDoc || layout.isLoading;
1397
+ const error = layout.error;
1398
+ return {
1399
+ error,
1400
+ isLoading,
1401
+ // Base metadata
1402
+ model,
1403
+ collectionType,
1404
+ id,
1405
+ slug,
1406
+ isCreatingEntry,
1407
+ isSingleType,
1408
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1409
+ // All schema infos
1410
+ components,
1411
+ contentType: schema,
1412
+ contentTypes: schemas,
1413
+ // Form state
1414
+ form,
1415
+ // layout infos
1416
+ layout
853
1417
  };
854
1418
  };
855
1419
  const prefixPluginTranslations = (trad, pluginId) => {
856
- if (!pluginId) {
857
- throw new TypeError("pluginId can't be empty");
858
- }
859
1420
  return Object.keys(trad).reduce((acc, current) => {
860
1421
  acc[`${pluginId}.${current}`] = trad[current];
861
1422
  return acc;
@@ -871,6 +1432,8 @@ const useDocumentActions = () => {
871
1432
  const { formatMessage } = reactIntl.useIntl();
872
1433
  const { trackUsage } = strapiAdmin.useTracking();
873
1434
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1435
+ const navigate = reactRouterDom.useNavigate();
1436
+ const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
874
1437
  const [deleteDocument] = useDeleteDocumentMutation();
875
1438
  const _delete = React__namespace.useCallback(
876
1439
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -1185,6 +1748,7 @@ const useDocumentActions = () => {
1185
1748
  defaultMessage: "Saved document"
1186
1749
  })
1187
1750
  });
1751
+ setCurrentStep("contentManager.success");
1188
1752
  return res.data;
1189
1753
  } catch (err) {
1190
1754
  toggleNotification({
@@ -1206,7 +1770,6 @@ const useDocumentActions = () => {
1206
1770
  sourceId
1207
1771
  });
1208
1772
  if ("error" in res) {
1209
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1210
1773
  return { error: res.error };
1211
1774
  }
1212
1775
  toggleNotification({
@@ -1225,7 +1788,7 @@ const useDocumentActions = () => {
1225
1788
  throw err;
1226
1789
  }
1227
1790
  },
1228
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1791
+ [autoCloneDocument, formatMessage, toggleNotification]
1229
1792
  );
1230
1793
  const [cloneDocument] = useCloneDocumentMutation();
1231
1794
  const clone = React__namespace.useCallback(
@@ -1251,6 +1814,7 @@ const useDocumentActions = () => {
1251
1814
  defaultMessage: "Cloned document"
1252
1815
  })
1253
1816
  });
1817
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1254
1818
  return res.data;
1255
1819
  } catch (err) {
1256
1820
  toggleNotification({
@@ -1261,7 +1825,7 @@ const useDocumentActions = () => {
1261
1825
  throw err;
1262
1826
  }
1263
1827
  },
1264
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1828
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1265
1829
  );
1266
1830
  const [getDoc] = useLazyGetDocumentQuery();
1267
1831
  const getDocument = React__namespace.useCallback(
@@ -1286,10 +1850,10 @@ const useDocumentActions = () => {
1286
1850
  update
1287
1851
  };
1288
1852
  };
1289
- const ProtectedHistoryPage = React.lazy(
1290
- () => Promise.resolve().then(() => require("./History-CQl54kNG.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1853
+ const ProtectedHistoryPage = React__namespace.lazy(
1854
+ () => Promise.resolve().then(() => require("./History-BQpDoOu8.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1291
1855
  );
1292
- const routes$1 = [
1856
+ const routes$2 = [
1293
1857
  {
1294
1858
  path: ":collectionType/:slug/:id/history",
1295
1859
  Component: ProtectedHistoryPage
@@ -1299,32 +1863,45 @@ const routes$1 = [
1299
1863
  Component: ProtectedHistoryPage
1300
1864
  }
1301
1865
  ];
1302
- const ProtectedEditViewPage = React.lazy(
1303
- () => Promise.resolve().then(() => require("./EditViewPage-BDL9cM0Q.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1304
- );
1305
- const ProtectedListViewPage = React.lazy(
1306
- () => Promise.resolve().then(() => require("./ListViewPage-BIEXJtcz.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1866
+ const ProtectedPreviewPage = React__namespace.lazy(
1867
+ () => Promise.resolve().then(() => require("./Preview-CbXHXqBg.js")).then((mod) => ({ default: mod.ProtectedPreviewPage }))
1868
+ );
1869
+ const routes$1 = [
1870
+ {
1871
+ path: ":collectionType/:slug/:id/preview",
1872
+ Component: ProtectedPreviewPage
1873
+ },
1874
+ {
1875
+ path: ":collectionType/:slug/preview",
1876
+ Component: ProtectedPreviewPage
1877
+ }
1878
+ ];
1879
+ const ProtectedEditViewPage = React.lazy(
1880
+ () => Promise.resolve().then(() => require("./EditViewPage-BT7Achc-.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1881
+ );
1882
+ const ProtectedListViewPage = React.lazy(
1883
+ () => Promise.resolve().then(() => require("./ListViewPage-Dt8OUTwO.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1307
1884
  );
1308
1885
  const ProtectedListConfiguration = React.lazy(
1309
- () => Promise.resolve().then(() => require("./ListConfigurationPage-G_22rTAp.js")).then((mod) => ({
1886
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-B6NsS-0m.js")).then((mod) => ({
1310
1887
  default: mod.ProtectedListConfiguration
1311
1888
  }))
1312
1889
  );
1313
1890
  const ProtectedEditConfigurationPage = React.lazy(
1314
- () => Promise.resolve().then(() => require("./EditConfigurationPage-C28IfcPs.js")).then((mod) => ({
1891
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-n7_xHayb.js")).then((mod) => ({
1315
1892
  default: mod.ProtectedEditConfigurationPage
1316
1893
  }))
1317
1894
  );
1318
1895
  const ProtectedComponentConfigurationPage = React.lazy(
1319
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-Tqd-Ji_E.js")).then((mod) => ({
1896
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-NeMPjY5M.js")).then((mod) => ({
1320
1897
  default: mod.ProtectedComponentConfigurationPage
1321
1898
  }))
1322
1899
  );
1323
1900
  const NoPermissions = React.lazy(
1324
- () => Promise.resolve().then(() => require("./NoPermissionsPage-CIFc7iTR.js")).then((mod) => ({ default: mod.NoPermissions }))
1901
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-CLbU5SOt.js")).then((mod) => ({ default: mod.NoPermissions }))
1325
1902
  );
1326
1903
  const NoContentType = React.lazy(
1327
- () => Promise.resolve().then(() => require("./NoContentTypePage-P-gvTfgg.js")).then((mod) => ({ default: mod.NoContentType }))
1904
+ () => Promise.resolve().then(() => require("./NoContentTypePage-Dgm-uj-6.js")).then((mod) => ({ default: mod.NoContentType }))
1328
1905
  );
1329
1906
  const CollectionTypePages = () => {
1330
1907
  const { collectionType } = reactRouterDom.useParams();
@@ -1336,7 +1913,7 @@ const CollectionTypePages = () => {
1336
1913
  const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
1337
1914
  const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
1338
1915
  const LIST_RELATIVE_PATH = ":collectionType/:slug";
1339
- const LIST_PATH = `/content-manager/${LIST_RELATIVE_PATH}`;
1916
+ const LIST_PATH = `/content-manager/collection-types/:slug`;
1340
1917
  const routes = [
1341
1918
  {
1342
1919
  path: LIST_RELATIVE_PATH,
@@ -1370,6 +1947,7 @@ const routes = [
1370
1947
  path: "no-content-types",
1371
1948
  Component: NoContentType
1372
1949
  },
1950
+ ...routes$2,
1373
1951
  ...routes$1
1374
1952
  ];
1375
1953
  const DocumentActions = ({ actions: actions2 }) => {
@@ -1438,12 +2016,14 @@ const DocumentActionButton = (action) => {
1438
2016
  /* @__PURE__ */ jsxRuntime.jsx(
1439
2017
  designSystem.Button,
1440
2018
  {
1441
- flex: 1,
2019
+ flex: "auto",
1442
2020
  startIcon: action.icon,
1443
2021
  disabled: action.disabled,
1444
2022
  onClick: handleClick(action),
1445
2023
  justifyContent: "center",
1446
2024
  variant: action.variant || "default",
2025
+ paddingTop: "7px",
2026
+ paddingBottom: "7px",
1447
2027
  children: action.label
1448
2028
  }
1449
2029
  ),
@@ -1451,7 +2031,7 @@ const DocumentActionButton = (action) => {
1451
2031
  DocumentActionConfirmDialog,
1452
2032
  {
1453
2033
  ...action.dialog,
1454
- variant: action.variant,
2034
+ variant: action.dialog?.variant ?? action.variant,
1455
2035
  isOpen: dialogId === action.id,
1456
2036
  onClose: handleClose
1457
2037
  }
@@ -1466,6 +2046,11 @@ const DocumentActionButton = (action) => {
1466
2046
  ) : null
1467
2047
  ] });
1468
2048
  };
2049
+ const MenuItem = styledComponents.styled(designSystem.Menu.Item)`
2050
+ &:hover {
2051
+ background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
2052
+ }
2053
+ `;
1469
2054
  const DocumentActionsMenu = ({
1470
2055
  actions: actions2,
1471
2056
  children,
@@ -1508,9 +2093,9 @@ const DocumentActionsMenu = ({
1508
2093
  disabled: isDisabled,
1509
2094
  size: "S",
1510
2095
  endIcon: null,
1511
- paddingTop: "7px",
1512
- paddingLeft: "9px",
1513
- paddingRight: "9px",
2096
+ paddingTop: "4px",
2097
+ paddingLeft: "7px",
2098
+ paddingRight: "7px",
1514
2099
  variant,
1515
2100
  children: [
1516
2101
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
@@ -1521,36 +2106,35 @@ const DocumentActionsMenu = ({
1521
2106
  ]
1522
2107
  }
1523
2108
  ),
1524
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
2109
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1525
2110
  actions2.map((action) => {
1526
2111
  return /* @__PURE__ */ jsxRuntime.jsx(
1527
- designSystem.Menu.Item,
2112
+ MenuItem,
1528
2113
  {
1529
2114
  disabled: action.disabled,
1530
2115
  onSelect: handleClick(action),
1531
2116
  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
- ] })
2117
+ isVariantDanger: action.variant === "danger",
2118
+ isDisabled: action.disabled,
2119
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
2120
+ designSystem.Flex,
2121
+ {
2122
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
2123
+ gap: 2,
2124
+ tag: "span",
2125
+ children: [
2126
+ /* @__PURE__ */ jsxRuntime.jsx(
2127
+ designSystem.Flex,
2128
+ {
2129
+ tag: "span",
2130
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
2131
+ children: action.icon
2132
+ }
2133
+ ),
2134
+ action.label
2135
+ ]
2136
+ }
2137
+ ) })
1554
2138
  },
1555
2139
  action.id
1556
2140
  );
@@ -1630,11 +2214,11 @@ const DocumentActionConfirmDialog = ({
1630
2214
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
1631
2215
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
1632
2216
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
1633
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
2217
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
1634
2218
  id: "app.components.Button.cancel",
1635
2219
  defaultMessage: "Cancel"
1636
2220
  }) }) }),
1637
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
2221
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
1638
2222
  id: "app.components.Button.confirm",
1639
2223
  defaultMessage: "Confirm"
1640
2224
  }) })
@@ -1661,6 +2245,18 @@ const DocumentActionModal = ({
1661
2245
  typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1662
2246
  ] }) });
1663
2247
  };
2248
+ const transformData = (data) => {
2249
+ if (Array.isArray(data)) {
2250
+ return data.map(transformData);
2251
+ }
2252
+ if (typeof data === "object" && data !== null) {
2253
+ if ("apiData" in data) {
2254
+ return data.apiData;
2255
+ }
2256
+ return mapValues__default.default(transformData)(data);
2257
+ }
2258
+ return data;
2259
+ };
1664
2260
  const PublishAction$1 = ({
1665
2261
  activeTab,
1666
2262
  documentId,
@@ -1673,13 +2269,18 @@ const PublishAction$1 = ({
1673
2269
  const navigate = reactRouterDom.useNavigate();
1674
2270
  const { toggleNotification } = strapiAdmin.useNotification();
1675
2271
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
2272
+ const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
1676
2273
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2274
+ const { id } = reactRouterDom.useParams();
1677
2275
  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
- );
2276
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1682
2277
  const { publish } = useDocumentActions();
2278
+ const [
2279
+ countDraftRelations,
2280
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
2281
+ ] = useLazyGetDraftRelationCountQuery();
2282
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
2283
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
1683
2284
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1684
2285
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1685
2286
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1688,10 +2289,107 @@ const PublishAction$1 = ({
1688
2289
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1689
2290
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1690
2291
  const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
2292
+ React__namespace.useEffect(() => {
2293
+ if (isErrorDraftRelations) {
2294
+ toggleNotification({
2295
+ type: "danger",
2296
+ message: formatMessage({
2297
+ id: getTranslation("error.records.fetch-draft-relatons"),
2298
+ defaultMessage: "An error occurred while fetching draft relations on this document."
2299
+ })
2300
+ });
2301
+ }
2302
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
2303
+ React__namespace.useEffect(() => {
2304
+ const localDraftRelations = /* @__PURE__ */ new Set();
2305
+ const extractDraftRelations = (data) => {
2306
+ const relations = data.connect || [];
2307
+ relations.forEach((relation) => {
2308
+ if (relation.status === "draft") {
2309
+ localDraftRelations.add(relation.id);
2310
+ }
2311
+ });
2312
+ };
2313
+ const traverseAndExtract = (data) => {
2314
+ Object.entries(data).forEach(([key, value]) => {
2315
+ if (key === "connect" && Array.isArray(value)) {
2316
+ extractDraftRelations({ connect: value });
2317
+ } else if (typeof value === "object" && value !== null) {
2318
+ traverseAndExtract(value);
2319
+ }
2320
+ });
2321
+ };
2322
+ if (!documentId || modified) {
2323
+ traverseAndExtract(formValues);
2324
+ setLocalCountOfDraftRelations(localDraftRelations.size);
2325
+ }
2326
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
2327
+ React__namespace.useEffect(() => {
2328
+ if (!document || !document.documentId || isListView) {
2329
+ return;
2330
+ }
2331
+ const fetchDraftRelationsCount = async () => {
2332
+ const { data, error } = await countDraftRelations({
2333
+ collectionType,
2334
+ model,
2335
+ documentId,
2336
+ params
2337
+ });
2338
+ if (error) {
2339
+ throw error;
2340
+ }
2341
+ if (data) {
2342
+ setServerCountOfDraftRelations(data.data);
2343
+ }
2344
+ };
2345
+ fetchDraftRelationsCount();
2346
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
1691
2347
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1692
2348
  if (!schema?.options?.draftAndPublish) {
1693
2349
  return null;
1694
2350
  }
2351
+ const performPublish = async () => {
2352
+ setSubmitting(true);
2353
+ try {
2354
+ const { errors } = await validate(true, {
2355
+ status: "published"
2356
+ });
2357
+ if (errors) {
2358
+ toggleNotification({
2359
+ type: "danger",
2360
+ message: formatMessage({
2361
+ id: "content-manager.validation.error",
2362
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2363
+ })
2364
+ });
2365
+ return;
2366
+ }
2367
+ const res = await publish(
2368
+ {
2369
+ collectionType,
2370
+ model,
2371
+ documentId,
2372
+ params
2373
+ },
2374
+ transformData(formValues)
2375
+ );
2376
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2377
+ if (id === "create") {
2378
+ navigate({
2379
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2380
+ search: rawQuery
2381
+ });
2382
+ }
2383
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2384
+ setErrors(formatValidationErrors(res.error));
2385
+ }
2386
+ } finally {
2387
+ setSubmitting(false);
2388
+ }
2389
+ };
2390
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
2391
+ const enableDraftRelationsCount = false;
2392
+ const hasDraftRelations = enableDraftRelationsCount;
1695
2393
  return {
1696
2394
  /**
1697
2395
  * Disabled when:
@@ -1701,52 +2399,40 @@ const PublishAction$1 = ({
1701
2399
  * - the document is already published & not modified
1702
2400
  * - the document is being created & not modified
1703
2401
  * - 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
2402
  */
1707
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2403
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1708
2404
  label: formatMessage({
1709
2405
  id: "app.utils.publish",
1710
2406
  defaultMessage: "Publish"
1711
2407
  }),
1712
2408
  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));
2409
+ await performPublish();
2410
+ },
2411
+ dialog: hasDraftRelations ? {
2412
+ type: "dialog",
2413
+ variant: "danger",
2414
+ footer: null,
2415
+ title: formatMessage({
2416
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
2417
+ defaultMessage: "Confirmation"
2418
+ }),
2419
+ content: formatMessage(
2420
+ {
2421
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2422
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
2423
+ },
2424
+ {
2425
+ count: totalDraftRelations
1742
2426
  }
1743
- } finally {
1744
- setSubmitting(false);
2427
+ ),
2428
+ onConfirm: async () => {
2429
+ await performPublish();
1745
2430
  }
1746
- }
2431
+ } : void 0
1747
2432
  };
1748
2433
  };
1749
2434
  PublishAction$1.type = "publish";
2435
+ PublishAction$1.position = "panel";
1750
2436
  const UpdateAction = ({
1751
2437
  activeTab,
1752
2438
  documentId,
@@ -1759,10 +2445,6 @@ const UpdateAction = ({
1759
2445
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1760
2446
  const isCloning = cloneMatch !== null;
1761
2447
  const { formatMessage } = reactIntl.useIntl();
1762
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1763
- canCreate: canCreate2,
1764
- canUpdate: canUpdate2
1765
- }));
1766
2448
  const { create, update, clone } = useDocumentActions();
1767
2449
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1768
2450
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1773,90 +2455,134 @@ const UpdateAction = ({
1773
2455
  const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
1774
2456
  const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
1775
2457
  const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
1776
- return {
1777
- /**
1778
- * Disabled when:
1779
- * - the form is submitting
1780
- * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1781
- * - the active tab is the published tab
1782
- * - the user doesn't have the permission to create a new document
1783
- * - the user doesn't have the permission to update the document
1784
- */
1785
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
1786
- label: formatMessage({
1787
- id: "content-manager.containers.Edit.save",
1788
- defaultMessage: "Save"
1789
- }),
1790
- onClick: async () => {
1791
- setSubmitting(true);
1792
- try {
1793
- const { errors } = await validate();
1794
- if (errors) {
1795
- toggleNotification({
1796
- type: "danger",
1797
- message: formatMessage({
1798
- id: "content-manager.validation.error",
1799
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1800
- })
1801
- });
1802
- return;
1803
- }
1804
- if (isCloning) {
1805
- const res = await clone(
2458
+ const handleUpdate = React__namespace.useCallback(async () => {
2459
+ setSubmitting(true);
2460
+ try {
2461
+ if (!modified) {
2462
+ return;
2463
+ }
2464
+ const { errors } = await validate(true, {
2465
+ status: "draft"
2466
+ });
2467
+ if (errors) {
2468
+ toggleNotification({
2469
+ type: "danger",
2470
+ message: formatMessage({
2471
+ id: "content-manager.validation.error",
2472
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2473
+ })
2474
+ });
2475
+ return;
2476
+ }
2477
+ if (isCloning) {
2478
+ const res = await clone(
2479
+ {
2480
+ model,
2481
+ documentId: cloneMatch.params.origin,
2482
+ params
2483
+ },
2484
+ transformData(document)
2485
+ );
2486
+ if ("data" in res) {
2487
+ navigate(
1806
2488
  {
1807
- model,
1808
- documentId: cloneMatch.params.origin,
1809
- params
1810
- },
1811
- document
1812
- );
1813
- if ("data" in res) {
1814
- navigate({
1815
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2489
+ pathname: `../${res.data.documentId}`,
1816
2490
  search: rawQuery
1817
- });
1818
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1819
- setErrors(formatValidationErrors(res.error));
1820
- }
1821
- } else if (documentId || collectionType === SINGLE_TYPES) {
1822
- const res = await update(
1823
- {
1824
- collectionType,
1825
- model,
1826
- documentId,
1827
- params
1828
2491
  },
1829
- document
2492
+ { relative: "path" }
1830
2493
  );
1831
- if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1832
- setErrors(formatValidationErrors(res.error));
1833
- } else {
1834
- resetForm();
1835
- }
2494
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2495
+ setErrors(formatValidationErrors(res.error));
2496
+ }
2497
+ } else if (documentId || collectionType === SINGLE_TYPES) {
2498
+ const res = await update(
2499
+ {
2500
+ collectionType,
2501
+ model,
2502
+ documentId,
2503
+ params
2504
+ },
2505
+ transformData(document)
2506
+ );
2507
+ if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2508
+ setErrors(formatValidationErrors(res.error));
1836
2509
  } else {
1837
- const res = await create(
2510
+ resetForm();
2511
+ }
2512
+ } else {
2513
+ const res = await create(
2514
+ {
2515
+ model,
2516
+ params
2517
+ },
2518
+ transformData(document)
2519
+ );
2520
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2521
+ navigate(
1838
2522
  {
1839
- model,
1840
- params
2523
+ pathname: `../${res.data.documentId}`,
2524
+ search: rawQuery
1841
2525
  },
1842
- document
2526
+ { replace: true, relative: "path" }
1843
2527
  );
1844
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1845
- navigate({
1846
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1847
- search: rawQuery
1848
- });
1849
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1850
- setErrors(formatValidationErrors(res.error));
1851
- }
2528
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2529
+ setErrors(formatValidationErrors(res.error));
1852
2530
  }
1853
- } finally {
1854
- setSubmitting(false);
1855
2531
  }
2532
+ } finally {
2533
+ setSubmitting(false);
1856
2534
  }
2535
+ }, [
2536
+ clone,
2537
+ cloneMatch?.params.origin,
2538
+ collectionType,
2539
+ create,
2540
+ document,
2541
+ documentId,
2542
+ formatMessage,
2543
+ formatValidationErrors,
2544
+ isCloning,
2545
+ model,
2546
+ modified,
2547
+ navigate,
2548
+ params,
2549
+ rawQuery,
2550
+ resetForm,
2551
+ setErrors,
2552
+ setSubmitting,
2553
+ toggleNotification,
2554
+ update,
2555
+ validate
2556
+ ]);
2557
+ React__namespace.useEffect(() => {
2558
+ const handleKeyDown = (e) => {
2559
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
2560
+ e.preventDefault();
2561
+ handleUpdate();
2562
+ }
2563
+ };
2564
+ window.addEventListener("keydown", handleKeyDown);
2565
+ return () => {
2566
+ window.removeEventListener("keydown", handleKeyDown);
2567
+ };
2568
+ }, [handleUpdate]);
2569
+ return {
2570
+ /**
2571
+ * Disabled when:
2572
+ * - the form is submitting
2573
+ * - the document is not modified & we're not cloning (you can save a clone entity straight away)
2574
+ * - the active tab is the published tab
2575
+ */
2576
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
2577
+ label: formatMessage({
2578
+ id: "global.save",
2579
+ defaultMessage: "Save"
2580
+ }),
2581
+ onClick: handleUpdate
1857
2582
  };
1858
2583
  };
1859
2584
  UpdateAction.type = "update";
2585
+ UpdateAction.position = "panel";
1860
2586
  const UNPUBLISH_DRAFT_OPTIONS = {
1861
2587
  KEEP: "keep",
1862
2588
  DISCARD: "discard"
@@ -1889,7 +2615,7 @@ const UnpublishAction$1 = ({
1889
2615
  id: "app.utils.unpublish",
1890
2616
  defaultMessage: "Unpublish"
1891
2617
  }),
1892
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2618
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
1893
2619
  onClick: async () => {
1894
2620
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1895
2621
  if (!documentId) {
@@ -1979,6 +2705,7 @@ const UnpublishAction$1 = ({
1979
2705
  };
1980
2706
  };
1981
2707
  UnpublishAction$1.type = "unpublish";
2708
+ UnpublishAction$1.position = "panel";
1982
2709
  const DiscardAction = ({
1983
2710
  activeTab,
1984
2711
  documentId,
@@ -2001,7 +2728,7 @@ const DiscardAction = ({
2001
2728
  id: "content-manager.actions.discard.label",
2002
2729
  defaultMessage: "Discard changes"
2003
2730
  }),
2004
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2731
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
2005
2732
  position: ["panel", "table-row"],
2006
2733
  variant: "danger",
2007
2734
  dialog: {
@@ -2029,11 +2756,7 @@ const DiscardAction = ({
2029
2756
  };
2030
2757
  };
2031
2758
  DiscardAction.type = "discard";
2032
- const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
2033
- path {
2034
- fill: currentColor;
2035
- }
2036
- `;
2759
+ DiscardAction.position = "panel";
2037
2760
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2038
2761
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2039
2762
  const RelativeTime = React__namespace.forwardRef(
@@ -2046,7 +2769,7 @@ const RelativeTime = React__namespace.forwardRef(
2046
2769
  });
2047
2770
  const unit = intervals.find((intervalUnit) => {
2048
2771
  return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
2049
- });
2772
+ }) ?? "seconds";
2050
2773
  const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
2051
2774
  const customInterval = customIntervals.find(
2052
2775
  (custom) => interval[custom.unit] < custom.threshold
@@ -2080,34 +2803,34 @@ const getDisplayName = ({
2080
2803
  return email ?? "";
2081
2804
  };
2082
2805
  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) }) });
2806
+ const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
2807
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2808
+ const { formatMessage } = reactIntl.useIntl();
2809
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
2810
+ id: `content-manager.containers.List.${status}`,
2811
+ defaultMessage: capitalise(status)
2812
+ }) }) });
2086
2813
  };
2087
2814
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2088
2815
  const { formatMessage } = reactIntl.useIntl();
2089
2816
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2817
+ const params = reactRouterDom.useParams();
2090
2818
  const title = isCreating ? formatMessage({
2091
2819
  id: "content-manager.containers.edit.title.new",
2092
2820
  defaultMessage: "Create an entry"
2093
2821
  }) : 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,
2822
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2823
+ /* @__PURE__ */ jsxRuntime.jsx(
2824
+ strapiAdmin.BackButton,
2098
2825
  {
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
- ]
2826
+ fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
2108
2827
  }
2109
2828
  ),
2110
- status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2829
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2830
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2831
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2832
+ ] }),
2833
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2111
2834
  ] });
2112
2835
  };
2113
2836
  const HeaderToolbar = () => {
@@ -2153,7 +2876,7 @@ const HeaderToolbar = () => {
2153
2876
  meta: isCloning ? void 0 : meta,
2154
2877
  collectionType
2155
2878
  },
2156
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2879
+ descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
2157
2880
  children: (actions2) => {
2158
2881
  const headerActions = actions2.filter((action) => {
2159
2882
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -2190,12 +2913,12 @@ const Information = ({ activeTab }) => {
2190
2913
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2191
2914
  label: formatMessage({
2192
2915
  id: "content-manager.containers.edit.information.last-published.label",
2193
- defaultMessage: "Last published"
2916
+ defaultMessage: "Published"
2194
2917
  }),
2195
2918
  value: formatMessage(
2196
2919
  {
2197
2920
  id: "content-manager.containers.edit.information.last-published.value",
2198
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2921
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2199
2922
  },
2200
2923
  {
2201
2924
  time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2208,12 +2931,12 @@ const Information = ({ activeTab }) => {
2208
2931
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2209
2932
  label: formatMessage({
2210
2933
  id: "content-manager.containers.edit.information.last-draft.label",
2211
- defaultMessage: "Last draft"
2934
+ defaultMessage: "Updated"
2212
2935
  }),
2213
2936
  value: formatMessage(
2214
2937
  {
2215
2938
  id: "content-manager.containers.edit.information.last-draft.value",
2216
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2939
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2217
2940
  },
2218
2941
  {
2219
2942
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2231,12 +2954,12 @@ const Information = ({ activeTab }) => {
2231
2954
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2232
2955
  label: formatMessage({
2233
2956
  id: "content-manager.containers.edit.information.document.label",
2234
- defaultMessage: "Document"
2957
+ defaultMessage: "Created"
2235
2958
  }),
2236
2959
  value: formatMessage(
2237
2960
  {
2238
2961
  id: "content-manager.containers.edit.information.document.value",
2239
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2962
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2240
2963
  },
2241
2964
  {
2242
2965
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2274,25 +2997,77 @@ const Information = ({ activeTab }) => {
2274
2997
  );
2275
2998
  };
2276
2999
  const HeaderActions = ({ actions: actions2 }) => {
2277
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: actions2.map((action) => {
2278
- if ("options" in action) {
3000
+ const [dialogId, setDialogId] = React__namespace.useState(null);
3001
+ const handleClick = (action) => async (e) => {
3002
+ if (!("options" in action)) {
3003
+ const { onClick = () => false, dialog, id } = action;
3004
+ const muteDialog = await onClick(e);
3005
+ if (dialog && !muteDialog) {
3006
+ e.preventDefault();
3007
+ setDialogId(id);
3008
+ }
3009
+ }
3010
+ };
3011
+ const handleClose = () => {
3012
+ setDialogId(null);
3013
+ };
3014
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
3015
+ if (action.options) {
2279
3016
  return /* @__PURE__ */ jsxRuntime.jsx(
2280
3017
  designSystem.SingleSelect,
2281
3018
  {
2282
3019
  size: "S",
2283
- disabled: action.disabled,
2284
- "aria-label": action.label,
2285
3020
  onChange: action.onSelect,
2286
- value: action.value,
3021
+ "aria-label": action.label,
3022
+ ...action,
2287
3023
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
2288
3024
  },
2289
3025
  action.id
2290
3026
  );
2291
3027
  } else {
2292
- return null;
3028
+ if (action.type === "icon") {
3029
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
3030
+ /* @__PURE__ */ jsxRuntime.jsx(
3031
+ designSystem.IconButton,
3032
+ {
3033
+ disabled: action.disabled,
3034
+ label: action.label,
3035
+ size: "S",
3036
+ onClick: handleClick(action),
3037
+ children: action.icon
3038
+ }
3039
+ ),
3040
+ action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
3041
+ HeaderActionDialog,
3042
+ {
3043
+ ...action.dialog,
3044
+ isOpen: dialogId === action.id,
3045
+ onClose: handleClose
3046
+ }
3047
+ ) : null
3048
+ ] }, action.id);
3049
+ }
2293
3050
  }
2294
3051
  }) });
2295
3052
  };
3053
+ const HeaderActionDialog = ({
3054
+ onClose,
3055
+ onCancel,
3056
+ title,
3057
+ content: Content,
3058
+ isOpen
3059
+ }) => {
3060
+ const handleClose = async () => {
3061
+ if (onCancel) {
3062
+ await onCancel();
3063
+ }
3064
+ onClose();
3065
+ };
3066
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
3067
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
3068
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
3069
+ ] }) });
3070
+ };
2296
3071
  const ConfigureTheViewAction = ({ collectionType, model }) => {
2297
3072
  const navigate = reactRouterDom.useNavigate();
2298
3073
  const { formatMessage } = reactIntl.useIntl();
@@ -2309,6 +3084,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2309
3084
  };
2310
3085
  };
2311
3086
  ConfigureTheViewAction.type = "configure-the-view";
3087
+ ConfigureTheViewAction.position = "header";
2312
3088
  const EditTheModelAction = ({ model }) => {
2313
3089
  const navigate = reactRouterDom.useNavigate();
2314
3090
  const { formatMessage } = reactIntl.useIntl();
@@ -2325,6 +3101,7 @@ const EditTheModelAction = ({ model }) => {
2325
3101
  };
2326
3102
  };
2327
3103
  EditTheModelAction.type = "edit-the-model";
3104
+ EditTheModelAction.position = "header";
2328
3105
  const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2329
3106
  const navigate = reactRouterDom.useNavigate();
2330
3107
  const { formatMessage } = reactIntl.useIntl();
@@ -2333,12 +3110,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2333
3110
  const { delete: deleteAction } = useDocumentActions();
2334
3111
  const { toggleNotification } = strapiAdmin.useNotification();
2335
3112
  const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
3113
+ const isLocalized = document?.locale != null;
2336
3114
  return {
2337
3115
  disabled: !canDelete || !document,
2338
- label: formatMessage({
2339
- id: "content-manager.actions.delete.label",
2340
- defaultMessage: "Delete document"
2341
- }),
3116
+ label: formatMessage(
3117
+ {
3118
+ id: "content-manager.actions.delete.label",
3119
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
3120
+ },
3121
+ { isLocalized }
3122
+ ),
2342
3123
  icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2343
3124
  dialog: {
2344
3125
  type: "dialog",
@@ -2394,6 +3175,7 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2394
3175
  };
2395
3176
  };
2396
3177
  DeleteAction$1.type = "delete";
3178
+ DeleteAction$1.position = ["header", "table-row"];
2397
3179
  const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2398
3180
  const Panels = () => {
2399
3181
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
@@ -2417,380 +3199,78 @@ const Panels = () => {
2417
3199
  return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
2418
3200
  strapiAdmin.DescriptionComponentRenderer,
2419
3201
  {
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
2708
- }
2709
- };
2710
- };
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
- );
3202
+ props,
3203
+ descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
3204
+ children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
3205
+ }
3206
+ ) });
2740
3207
  };
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
- );
3208
+ const ActionsPanel = () => {
3209
+ const { formatMessage } = reactIntl.useIntl();
2762
3210
  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
- }
3211
+ title: formatMessage({
3212
+ id: "content-manager.containers.edit.panels.default.title",
3213
+ defaultMessage: "Entry"
3214
+ }),
3215
+ content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2771
3216
  };
2772
3217
  };
2773
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2774
- return columns.map((name) => {
2775
- const attribute = attributes[name];
2776
- if (!attribute) {
2777
- return null;
3218
+ ActionsPanel.type = "actions";
3219
+ const ActionsPanelContent = () => {
3220
+ const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
3221
+ const [
3222
+ {
3223
+ query: { status = "draft" }
2778
3224
  }
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);
3225
+ ] = strapiAdmin.useQueryParams();
3226
+ const { model, id, document, meta, collectionType } = useDoc();
3227
+ const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
3228
+ const props = {
3229
+ activeTab: status,
3230
+ model,
3231
+ documentId: id,
3232
+ document: isCloning ? void 0 : document,
3233
+ meta: isCloning ? void 0 : meta,
3234
+ collectionType
3235
+ };
3236
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
3237
+ /* @__PURE__ */ jsxRuntime.jsx(
3238
+ strapiAdmin.DescriptionComponentRenderer,
3239
+ {
3240
+ props,
3241
+ descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
3242
+ children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
3243
+ }
3244
+ ),
3245
+ /* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
3246
+ ] });
2793
3247
  };
3248
+ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
3249
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3250
+ designSystem.Flex,
3251
+ {
3252
+ ref,
3253
+ tag: "aside",
3254
+ "aria-labelledby": "additional-information",
3255
+ background: "neutral0",
3256
+ borderColor: "neutral150",
3257
+ hasRadius: true,
3258
+ paddingBottom: 4,
3259
+ paddingLeft: 4,
3260
+ paddingRight: 4,
3261
+ paddingTop: 4,
3262
+ shadow: "tableShadow",
3263
+ gap: 3,
3264
+ direction: "column",
3265
+ justifyContent: "stretch",
3266
+ alignItems: "flex-start",
3267
+ children: [
3268
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
3269
+ children
3270
+ ]
3271
+ }
3272
+ );
3273
+ });
2794
3274
  const ConfirmBulkActionDialog = ({
2795
3275
  onToggleDialog,
2796
3276
  isOpen = false,
@@ -2798,7 +3278,7 @@ const ConfirmBulkActionDialog = ({
2798
3278
  endAction
2799
3279
  }) => {
2800
3280
  const { formatMessage } = reactIntl.useIntl();
2801
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
3281
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2802
3282
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2803
3283
  id: "app.components.ConfirmDialog.title",
2804
3284
  defaultMessage: "Confirmation"
@@ -2816,7 +3296,7 @@ const ConfirmBulkActionDialog = ({
2816
3296
  ] })
2817
3297
  ] }) });
2818
3298
  };
2819
- const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
3299
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
2820
3300
  const ConfirmDialogPublishAll = ({
2821
3301
  isOpen,
2822
3302
  onToggleDialog,
@@ -2829,6 +3309,7 @@ const ConfirmDialogPublishAll = ({
2829
3309
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2830
3310
  const { model, schema } = useDoc();
2831
3311
  const [{ query }] = strapiAdmin.useQueryParams();
3312
+ const enableDraftRelationsCount = false;
2832
3313
  const {
2833
3314
  data: countDraftRelations = 0,
2834
3315
  isLoading,
@@ -2840,7 +3321,7 @@ const ConfirmDialogPublishAll = ({
2840
3321
  locale: query?.plugins?.i18n?.locale
2841
3322
  },
2842
3323
  {
2843
- skip: selectedEntries.length === 0
3324
+ skip: !enableDraftRelationsCount
2844
3325
  }
2845
3326
  );
2846
3327
  React__namespace.useEffect(() => {
@@ -2864,7 +3345,7 @@ const ConfirmDialogPublishAll = ({
2864
3345
  defaultMessage: "<b>{count} {count, plural, one { relation } other { relations } } out of {entities} { entities, plural, one { entry } other { entries } } {count, plural, one { is } other { are } }</b> not published yet and might lead to unexpected behavior. "
2865
3346
  },
2866
3347
  {
2867
- b: BoldChunk$1,
3348
+ b: BoldChunk,
2868
3349
  count: countDraftRelations,
2869
3350
  entities: selectedEntries.length
2870
3351
  }
@@ -2903,6 +3384,16 @@ const ConfirmDialogPublishAll = ({
2903
3384
  const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
2904
3385
  max-width: 300px;
2905
3386
  `;
3387
+ const TableComponent = styledComponents.styled(designSystem.RawTable)`
3388
+ width: 100%;
3389
+ table-layout: fixed;
3390
+ td:first-child {
3391
+ border-right: 1px solid ${({ theme }) => theme.colors.neutral150};
3392
+ }
3393
+ td:first-of-type {
3394
+ padding: ${({ theme }) => theme.spaces[4]};
3395
+ }
3396
+ `;
2906
3397
  const formatErrorMessages = (errors, parentKey, formatMessage) => {
2907
3398
  const messages = [];
2908
3399
  Object.entries(errors).forEach(([key, value]) => {
@@ -3007,7 +3498,7 @@ const SelectedEntriesTableContent = ({
3007
3498
  )
3008
3499
  ] }),
3009
3500
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
3010
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
3501
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
3011
3502
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
3012
3503
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
3013
3504
  shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
@@ -3025,7 +3516,7 @@ const SelectedEntriesTableContent = ({
3025
3516
  status: row.status
3026
3517
  }
3027
3518
  ) }),
3028
- /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3519
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
3029
3520
  designSystem.IconButton,
3030
3521
  {
3031
3522
  tag: reactRouterDom.Link,
@@ -3034,27 +3525,86 @@ const SelectedEntriesTableContent = ({
3034
3525
  search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3035
3526
  },
3036
3527
  state: { from: pathname },
3037
- label: formatMessage(
3038
- { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3039
- {
3040
- target: formatMessage(
3041
- {
3042
- id: "content-manager.components.ListViewHelperPluginTable.row-line",
3043
- defaultMessage: "item line {number}"
3044
- },
3045
- { number: index2 + 1 }
3046
- )
3047
- }
3048
- ),
3528
+ label: formatMessage({
3529
+ id: "content-manager.bulk-publish.edit",
3530
+ defaultMessage: "Edit"
3531
+ }),
3049
3532
  target: "_blank",
3050
3533
  marginLeft: "auto",
3051
- children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3534
+ variant: "ghost",
3535
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
3052
3536
  }
3053
- ) })
3537
+ ) }) })
3054
3538
  ] }, row.id)) })
3055
3539
  ] });
3056
3540
  };
3057
- const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
3541
+ const PublicationStatusSummary = ({ count, icon, message }) => {
3542
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", flex: 1, gap: 3, children: [
3543
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3544
+ icon,
3545
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: message })
3546
+ ] }),
3547
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: count })
3548
+ ] });
3549
+ };
3550
+ const PublicationStatusGrid = ({
3551
+ entriesReadyToPublishCount,
3552
+ entriesPublishedCount,
3553
+ entriesModifiedCount,
3554
+ entriesWithErrorsCount
3555
+ }) => {
3556
+ const { formatMessage } = reactIntl.useIntl();
3557
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { hasRadius: true, borderColor: "neutral150", children: /* @__PURE__ */ jsxRuntime.jsx(TableComponent, { colCount: 2, rowCount: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tbody, { children: [
3558
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
3559
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(
3560
+ PublicationStatusSummary,
3561
+ {
3562
+ count: entriesReadyToPublishCount,
3563
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
3564
+ message: formatMessage({
3565
+ id: "app.utils.ready-to-publish",
3566
+ defaultMessage: "Ready to publish"
3567
+ })
3568
+ }
3569
+ ) }),
3570
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(
3571
+ PublicationStatusSummary,
3572
+ {
3573
+ count: entriesPublishedCount,
3574
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
3575
+ message: formatMessage({
3576
+ id: "app.utils.already-published",
3577
+ defaultMessage: "Already published"
3578
+ })
3579
+ }
3580
+ ) })
3581
+ ] }),
3582
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
3583
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(
3584
+ PublicationStatusSummary,
3585
+ {
3586
+ count: entriesModifiedCount,
3587
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
3588
+ message: formatMessage({
3589
+ id: "content-manager.bulk-publish.modified",
3590
+ defaultMessage: "Ready to publish changes"
3591
+ })
3592
+ }
3593
+ ) }),
3594
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(
3595
+ PublicationStatusSummary,
3596
+ {
3597
+ count: entriesWithErrorsCount,
3598
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
3599
+ message: formatMessage({
3600
+ id: "content-manager.bulk-publish.waiting-for-action",
3601
+ defaultMessage: "Waiting for action"
3602
+ })
3603
+ }
3604
+ ) })
3605
+ ] })
3606
+ ] }) }) });
3607
+ };
3058
3608
  const SelectedEntriesModalContent = ({
3059
3609
  listViewSelectedEntries,
3060
3610
  toggleModal,
@@ -3087,7 +3637,13 @@ const SelectedEntriesModalContent = ({
3087
3637
  );
3088
3638
  const { rows, validationErrors } = React__namespace.useMemo(() => {
3089
3639
  if (data.length > 0 && schema) {
3090
- const validate = createYupSchema(schema.attributes, components);
3640
+ const validate = createYupSchema(
3641
+ schema.attributes,
3642
+ components,
3643
+ // Since this is the "Publish" action, the validation
3644
+ // schema must enforce the rules for published entities
3645
+ { status: "published" }
3646
+ );
3091
3647
  const validationErrors2 = {};
3092
3648
  const rows2 = data.map((entry) => {
3093
3649
  try {
@@ -3107,7 +3663,6 @@ const SelectedEntriesModalContent = ({
3107
3663
  validationErrors: {}
3108
3664
  };
3109
3665
  }, [components, data, schema]);
3110
- const [publishedCount, setPublishedCount] = React__namespace.useState(0);
3111
3666
  const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
3112
3667
  const { publishMany: bulkPublishAction } = useDocumentActions();
3113
3668
  const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
@@ -3119,53 +3674,36 @@ const SelectedEntriesModalContent = ({
3119
3674
  const selectedEntriesWithErrorsCount = selectedEntries.filter(
3120
3675
  ({ documentId }) => validationErrors[documentId]
3121
3676
  ).length;
3122
- const selectedEntriesPublished = selectedEntries.filter(
3677
+ const selectedEntriesPublishedCount = selectedEntries.filter(
3123
3678
  ({ status }) => status === "published"
3124
3679
  ).length;
3125
- const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3680
+ const selectedEntriesModifiedCount = selectedEntries.filter(
3681
+ ({ status, documentId }) => status === "modified" && !validationErrors[documentId]
3682
+ ).length;
3683
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublishedCount;
3126
3684
  const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3127
3685
  const handleConfirmBulkPublish = async () => {
3128
3686
  toggleDialog();
3129
3687
  const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3130
3688
  if (!("error" in res)) {
3131
- setPublishedCount(res.count);
3132
3689
  const unpublishedEntries = rows.filter((row) => {
3133
3690
  return !entriesToPublish.includes(row.documentId);
3134
3691
  });
3135
3692
  setListViewSelectedDocuments(unpublishedEntries);
3136
3693
  }
3137
3694
  };
3138
- const getFormattedCountMessage = () => {
3139
- if (publishedCount) {
3140
- return formatMessage(
3141
- {
3142
- id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3143
- defaultMessage: "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} published. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
3144
- },
3145
- {
3146
- publishedCount,
3147
- withErrorsCount: selectedEntriesWithErrorsCount,
3148
- b: BoldChunk
3149
- }
3150
- );
3151
- }
3152
- return formatMessage(
3153
- {
3154
- id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3155
- defaultMessage: "<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
3156
- },
3157
- {
3158
- readyToPublishCount: selectedEntriesWithNoErrorsCount,
3159
- withErrorsCount: selectedEntriesWithErrorsCount,
3160
- alreadyPublishedCount: selectedEntriesPublished,
3161
- b: BoldChunk
3162
- }
3163
- );
3164
- };
3165
3695
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3166
3696
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
3167
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
3168
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
3697
+ /* @__PURE__ */ jsxRuntime.jsx(
3698
+ PublicationStatusGrid,
3699
+ {
3700
+ entriesReadyToPublishCount: selectedEntriesWithNoErrorsCount - selectedEntriesModifiedCount,
3701
+ entriesPublishedCount: selectedEntriesPublishedCount,
3702
+ entriesModifiedCount: selectedEntriesModifiedCount,
3703
+ entriesWithErrorsCount: selectedEntriesWithErrorsCount
3704
+ }
3705
+ ),
3706
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 7, children: /* @__PURE__ */ jsxRuntime.jsx(
3169
3707
  SelectedEntriesTableContent,
3170
3708
  {
3171
3709
  isPublishing: isSubmittingForm,
@@ -3186,7 +3724,7 @@ const SelectedEntriesModalContent = ({
3186
3724
  designSystem.Button,
3187
3725
  {
3188
3726
  onClick: toggleDialog,
3189
- disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3727
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublishedCount === selectedEntries.length || isLoading,
3190
3728
  loading: isSubmittingForm,
3191
3729
  children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3192
3730
  }
@@ -3212,8 +3750,7 @@ const PublishAction = ({ documents, model }) => {
3212
3750
  const refetchList = () => {
3213
3751
  contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3214
3752
  };
3215
- if (!showPublishButton)
3216
- return null;
3753
+ if (!showPublishButton) return null;
3217
3754
  return {
3218
3755
  actionType: "publish",
3219
3756
  variant: "tertiary",
@@ -3281,8 +3818,7 @@ const DeleteAction = ({ documents, model }) => {
3281
3818
  selectRow([]);
3282
3819
  }
3283
3820
  };
3284
- if (!hasDeletePermission)
3285
- return null;
3821
+ if (!hasDeletePermission) return null;
3286
3822
  return {
3287
3823
  variant: "danger-light",
3288
3824
  label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
@@ -3331,8 +3867,7 @@ const UnpublishAction = ({ documents, model }) => {
3331
3867
  }
3332
3868
  };
3333
3869
  const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3334
- if (!showUnpublishButton)
3335
- return null;
3870
+ if (!showUnpublishButton) return null;
3336
3871
  return {
3337
3872
  variant: "tertiary",
3338
3873
  label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
@@ -3437,7 +3972,7 @@ const TableActions = ({ document }) => {
3437
3972
  strapiAdmin.DescriptionComponentRenderer,
3438
3973
  {
3439
3974
  props,
3440
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3975
+ descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
3441
3976
  children: (actions2) => {
3442
3977
  const tableRowActions = actions2.filter((action) => {
3443
3978
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3496,6 +4031,7 @@ const EditAction = ({ documentId }) => {
3496
4031
  };
3497
4032
  };
3498
4033
  EditAction.type = "edit";
4034
+ EditAction.position = "table-row";
3499
4035
  const StyledPencil = styledComponents.styled(Icons.Pencil)`
3500
4036
  path {
3501
4037
  fill: currentColor;
@@ -3548,7 +4084,7 @@ const CloneAction = ({ model, documentId }) => {
3548
4084
  }),
3549
4085
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3550
4086
  footer: ({ onClose }) => {
3551
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
4087
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3552
4088
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3553
4089
  id: "cancel",
3554
4090
  defaultMessage: "Cancel"
@@ -3572,6 +4108,7 @@ const CloneAction = ({ model, documentId }) => {
3572
4108
  };
3573
4109
  };
3574
4110
  CloneAction.type = "clone";
4111
+ CloneAction.position = "table-row";
3575
4112
  const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
3576
4113
  path {
3577
4114
  fill: currentColor;
@@ -3589,8 +4126,7 @@ class ContentManagerPlugin {
3589
4126
  documentActions = [
3590
4127
  ...DEFAULT_ACTIONS,
3591
4128
  ...DEFAULT_TABLE_ROW_ACTIONS,
3592
- ...DEFAULT_HEADER_ACTIONS,
3593
- HistoryAction
4129
+ ...DEFAULT_HEADER_ACTIONS
3594
4130
  ];
3595
4131
  editViewSidePanels = [ActionsPanel];
3596
4132
  headerActions = [];
@@ -3653,13 +4189,21 @@ class ContentManagerPlugin {
3653
4189
  id: PLUGIN_ID,
3654
4190
  name: "Content Manager",
3655
4191
  injectionZones: INJECTION_ZONES,
4192
+ isReady: false,
3656
4193
  apis: {
3657
4194
  addBulkAction: this.addBulkAction.bind(this),
3658
4195
  addDocumentAction: this.addDocumentAction.bind(this),
3659
4196
  addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3660
4197
  addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3661
4198
  getBulkActions: () => this.bulkActions,
3662
- getDocumentActions: () => this.documentActions,
4199
+ getDocumentActions: (position) => {
4200
+ if (position) {
4201
+ return this.documentActions.filter(
4202
+ (action) => action.position == void 0 || [action.position].flat().includes(position)
4203
+ );
4204
+ }
4205
+ return this.documentActions;
4206
+ },
3663
4207
  getEditViewSidePanels: () => this.editViewSidePanels,
3664
4208
  getHeaderActions: () => this.headerActions
3665
4209
  }
@@ -3669,16 +4213,71 @@ class ContentManagerPlugin {
3669
4213
  const getPrintableType = (value) => {
3670
4214
  const nativeType = typeof value;
3671
4215
  if (nativeType === "object") {
3672
- if (value === null)
3673
- return "null";
3674
- if (Array.isArray(value))
3675
- return "array";
4216
+ if (value === null) return "null";
4217
+ if (Array.isArray(value)) return "array";
3676
4218
  if (value instanceof Object && value.constructor.name !== "Object") {
3677
4219
  return value.constructor.name;
3678
4220
  }
3679
4221
  }
3680
4222
  return nativeType;
3681
4223
  };
4224
+ const HistoryAction = ({ model, document }) => {
4225
+ const { formatMessage } = reactIntl.useIntl();
4226
+ const [{ query }] = strapiAdmin.useQueryParams();
4227
+ const navigate = reactRouterDom.useNavigate();
4228
+ const { trackUsage } = strapiAdmin.useTracking();
4229
+ const { pathname } = reactRouterDom.useLocation();
4230
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
4231
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
4232
+ return null;
4233
+ }
4234
+ const handleOnClick = () => {
4235
+ const destination = { pathname: "history", search: pluginsQueryParams };
4236
+ trackUsage("willNavigate", {
4237
+ from: pathname,
4238
+ to: `${pathname}/${destination.pathname}`
4239
+ });
4240
+ navigate(destination);
4241
+ };
4242
+ return {
4243
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
4244
+ label: formatMessage({
4245
+ id: "content-manager.history.document-action",
4246
+ defaultMessage: "Content History"
4247
+ }),
4248
+ onClick: handleOnClick,
4249
+ disabled: (
4250
+ /**
4251
+ * The user is creating a new document.
4252
+ * It hasn't been saved yet, so there's no history to go to
4253
+ */
4254
+ !document || /**
4255
+ * The document has been created but the current dimension has never been saved.
4256
+ * For example, the user is creating a new locale in an existing document,
4257
+ * so there's no history for the document in that locale
4258
+ */
4259
+ !document.id || /**
4260
+ * History is only available for content types created by the user.
4261
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
4262
+ * which start with `admin::` or `plugin::`
4263
+ */
4264
+ !model.startsWith("api::")
4265
+ ),
4266
+ position: "header"
4267
+ };
4268
+ };
4269
+ HistoryAction.type = "history";
4270
+ HistoryAction.position = "header";
4271
+ const historyAdmin = {
4272
+ bootstrap(app) {
4273
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
4274
+ addDocumentAction((actions2) => {
4275
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
4276
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
4277
+ return actions2;
4278
+ });
4279
+ }
4280
+ };
3682
4281
  const initialState = {
3683
4282
  collectionTypeLinks: [],
3684
4283
  components: [],
@@ -3715,6 +4314,88 @@ const { setInitialData } = actions;
3715
4314
  const reducer = toolkit.combineReducers({
3716
4315
  app: reducer$1
3717
4316
  });
4317
+ const previewApi = contentManagerApi.injectEndpoints({
4318
+ endpoints: (builder) => ({
4319
+ getPreviewUrl: builder.query({
4320
+ query({ query, params }) {
4321
+ return {
4322
+ url: `/content-manager/preview/url/${params.contentType}`,
4323
+ method: "GET",
4324
+ config: {
4325
+ params: query
4326
+ }
4327
+ };
4328
+ }
4329
+ })
4330
+ })
4331
+ });
4332
+ const { useGetPreviewUrlQuery } = previewApi;
4333
+ const ConditionalTooltip = ({ isShown, label, children }) => {
4334
+ if (isShown) {
4335
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { label, children });
4336
+ }
4337
+ return children;
4338
+ };
4339
+ const PreviewSidePanel = ({ model, documentId, document }) => {
4340
+ const { formatMessage } = reactIntl.useIntl();
4341
+ const { trackUsage } = strapiAdmin.useTracking();
4342
+ const { pathname } = reactRouterDom.useLocation();
4343
+ const [{ query }] = strapiAdmin.useQueryParams();
4344
+ const isModified = strapiAdmin.useForm("PreviewSidePanel", (state) => state.modified);
4345
+ const { data, error } = useGetPreviewUrlQuery({
4346
+ params: {
4347
+ contentType: model
4348
+ },
4349
+ query: {
4350
+ documentId,
4351
+ locale: document?.locale,
4352
+ status: document?.status
4353
+ }
4354
+ });
4355
+ if (!data?.data?.url || error) {
4356
+ return null;
4357
+ }
4358
+ const trackNavigation = () => {
4359
+ const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
4360
+ trackUsage("willNavigate", { from: pathname, to: destinationPathname });
4361
+ };
4362
+ return {
4363
+ title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
4364
+ content: /* @__PURE__ */ jsxRuntime.jsx(
4365
+ ConditionalTooltip,
4366
+ {
4367
+ label: formatMessage({
4368
+ id: "content-manager.preview.panel.button-disabled-tooltip",
4369
+ defaultMessage: "Please save to open the preview"
4370
+ }),
4371
+ isShown: isModified,
4372
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(
4373
+ designSystem.Button,
4374
+ {
4375
+ variant: "tertiary",
4376
+ tag: reactRouterDom.Link,
4377
+ to: { pathname: "preview", search: qs.stringify(query, { encode: false }) },
4378
+ onClick: trackNavigation,
4379
+ width: "100%",
4380
+ disabled: isModified,
4381
+ pointerEvents: isModified ? "none" : void 0,
4382
+ tabIndex: isModified ? -1 : void 0,
4383
+ children: formatMessage({
4384
+ id: "content-manager.preview.panel.button",
4385
+ defaultMessage: "Open preview"
4386
+ })
4387
+ }
4388
+ ) })
4389
+ }
4390
+ )
4391
+ };
4392
+ };
4393
+ const previewAdmin = {
4394
+ bootstrap(app) {
4395
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
4396
+ contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
4397
+ }
4398
+ };
3718
4399
  const index = {
3719
4400
  register(app) {
3720
4401
  const cm = new ContentManagerPlugin();
@@ -3734,7 +4415,7 @@ const index = {
3734
4415
  app.router.addRoute({
3735
4416
  path: "content-manager/*",
3736
4417
  lazy: async () => {
3737
- const { Layout } = await Promise.resolve().then(() => require("./layout-BLa_DTtQ.js"));
4418
+ const { Layout } = await Promise.resolve().then(() => require("./layout-4BqLFW_b.js"));
3738
4419
  return {
3739
4420
  Component: Layout
3740
4421
  };
@@ -3743,10 +4424,18 @@ const index = {
3743
4424
  });
3744
4425
  app.registerPlugin(cm.config);
3745
4426
  },
4427
+ bootstrap(app) {
4428
+ if (typeof historyAdmin.bootstrap === "function") {
4429
+ historyAdmin.bootstrap(app);
4430
+ }
4431
+ if (typeof previewAdmin.bootstrap === "function") {
4432
+ previewAdmin.bootstrap(app);
4433
+ }
4434
+ },
3746
4435
  async registerTrads({ locales }) {
3747
4436
  const importedTrads = await Promise.all(
3748
4437
  locales.map((locale) => {
3749
- 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 }) => {
4438
+ 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-BR48D_RH.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-C43IbhA_.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 }) => {
3750
4439
  return {
3751
4440
  data: prefixPluginTranslations(data, PLUGIN_ID),
3752
4441
  locale
@@ -3764,10 +4453,10 @@ const index = {
3764
4453
  };
3765
4454
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3766
4455
  exports.BulkActionsRenderer = BulkActionsRenderer;
4456
+ exports.CLONE_PATH = CLONE_PATH;
3767
4457
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3768
4458
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3769
4459
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
3770
- exports.DOCUMENT_META_FIELDS = DOCUMENT_META_FIELDS;
3771
4460
  exports.DocumentRBAC = DocumentRBAC;
3772
4461
  exports.DocumentStatus = DocumentStatus;
3773
4462
  exports.HOOKS = HOOKS;
@@ -3784,13 +4473,18 @@ exports.checkIfAttributeIsDisplayable = checkIfAttributeIsDisplayable;
3784
4473
  exports.contentManagerApi = contentManagerApi;
3785
4474
  exports.convertEditLayoutToFieldLayouts = convertEditLayoutToFieldLayouts;
3786
4475
  exports.convertListLayoutToFieldLayouts = convertListLayoutToFieldLayouts;
4476
+ exports.createDefaultForm = createDefaultForm;
3787
4477
  exports.createYupSchema = createYupSchema;
3788
4478
  exports.extractContentTypeComponents = extractContentTypeComponents;
3789
4479
  exports.getDisplayName = getDisplayName;
3790
4480
  exports.getMainField = getMainField;
3791
4481
  exports.getTranslation = getTranslation;
3792
4482
  exports.index = index;
4483
+ exports.prepareTempKeys = prepareTempKeys;
4484
+ exports.removeFieldsThatDontExistOnSchema = removeFieldsThatDontExistOnSchema;
3793
4485
  exports.setInitialData = setInitialData;
4486
+ exports.transformDocument = transformDocument;
4487
+ exports.useContentManagerContext = useContentManagerContext;
3794
4488
  exports.useContentTypeSchema = useContentTypeSchema;
3795
4489
  exports.useDoc = useDoc;
3796
4490
  exports.useDocLayout = useDocLayout;
@@ -3802,5 +4496,6 @@ exports.useGetAllContentTypeSettingsQuery = useGetAllContentTypeSettingsQuery;
3802
4496
  exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3803
4497
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3804
4498
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
4499
+ exports.useGetPreviewUrlQuery = useGetPreviewUrlQuery;
3805
4500
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3806
- //# sourceMappingURL=index-iXGIUU_l.js.map
4501
+ //# sourceMappingURL=index-DkJQjlak.js.map