@strapi/content-manager 0.0.0-experimental.745741d19e90275ca6f7c928ca19f9bb0fd9d933 → 0.0.0-experimental.76d3543c13df7ef0095963ae2c20b792f179eef0

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 (219) hide show
  1. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
  2. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js → ComponentConfigurationPage-CJPoOvy3.js} +5 -6
  4. package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js.map → ComponentConfigurationPage-CJPoOvy3.js.map} +1 -1
  5. package/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs → ComponentConfigurationPage-CcRDqD0e.mjs} +4 -4
  6. package/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs.map → ComponentConfigurationPage-CcRDqD0e.mjs.map} +1 -1
  7. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
  8. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
  9. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
  10. package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs → EditConfigurationPage-C1ddZ_zf.mjs} +4 -4
  11. package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs.map → EditConfigurationPage-C1ddZ_zf.mjs.map} +1 -1
  12. package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js → EditConfigurationPage-CF3lxOy2.js} +5 -6
  13. package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js.map → EditConfigurationPage-CF3lxOy2.js.map} +1 -1
  14. package/dist/_chunks/{EditViewPage-BtkEx339.mjs → EditViewPage-BPFcUbqi.mjs} +63 -12
  15. package/dist/_chunks/EditViewPage-BPFcUbqi.mjs.map +1 -0
  16. package/dist/_chunks/{EditViewPage-BqNpC6hO.js → EditViewPage-CDyTC6aU.js} +63 -13
  17. package/dist/_chunks/EditViewPage-CDyTC6aU.js.map +1 -0
  18. package/dist/_chunks/{Field-lsPFnAmH.js → Field-DuxAW9q2.js} +409 -260
  19. package/dist/_chunks/Field-DuxAW9q2.js.map +1 -0
  20. package/dist/_chunks/{Field-R5NbffTB.mjs → Field-fBnTwgU4.mjs} +405 -256
  21. package/dist/_chunks/Field-fBnTwgU4.mjs.map +1 -0
  22. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
  23. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
  24. package/dist/_chunks/{Form-BHmXSfyy.mjs → Form-BGl7PhlZ.mjs} +37 -18
  25. package/dist/_chunks/Form-BGl7PhlZ.mjs.map +1 -0
  26. package/dist/_chunks/{Form-CcGboku8.js → Form-DSGh_zkz.js} +39 -21
  27. package/dist/_chunks/Form-DSGh_zkz.js.map +1 -0
  28. package/dist/_chunks/{History-ByUPL3T3.mjs → History-DTYB9CSB.mjs} +66 -113
  29. package/dist/_chunks/History-DTYB9CSB.mjs.map +1 -0
  30. package/dist/_chunks/{History-Bsud8jwh.js → History-DrDJv698.js} +65 -113
  31. package/dist/_chunks/History-DrDJv698.js.map +1 -0
  32. package/dist/_chunks/{ListConfigurationPage-Bm5HACXf.mjs → ListConfigurationPage-qWx8r4D_.mjs} +25 -12
  33. package/dist/_chunks/ListConfigurationPage-qWx8r4D_.mjs.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-DiT463qx.js → ListConfigurationPage-zurIlUZ7.js} +25 -13
  35. package/dist/_chunks/ListConfigurationPage-zurIlUZ7.js.map +1 -0
  36. package/dist/_chunks/{ListViewPage-CsrC9L_d.js → ListViewPage-DTM2uO_S.js} +109 -78
  37. package/dist/_chunks/ListViewPage-DTM2uO_S.js.map +1 -0
  38. package/dist/_chunks/{ListViewPage-JSyNAAYu.mjs → ListViewPage-GKpL5p8A.mjs} +106 -74
  39. package/dist/_chunks/ListViewPage-GKpL5p8A.mjs.map +1 -0
  40. package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs → NoContentTypePage-B5Vc5Cal.mjs} +2 -2
  41. package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs.map → NoContentTypePage-B5Vc5Cal.mjs.map} +1 -1
  42. package/dist/_chunks/{NoContentTypePage-Bsvng4II.js → NoContentTypePage-BuZlNroO.js} +2 -2
  43. package/dist/_chunks/{NoContentTypePage-Bsvng4II.js.map → NoContentTypePage-BuZlNroO.js.map} +1 -1
  44. package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs → NoPermissionsPage-BAZlWgJ4.mjs} +2 -2
  45. package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs.map → NoPermissionsPage-BAZlWgJ4.mjs.map} +1 -1
  46. package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js → NoPermissionsPage-DLzkS4Hy.js} +2 -2
  47. package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js.map → NoPermissionsPage-DLzkS4Hy.js.map} +1 -1
  48. package/dist/_chunks/Preview-VOJ8RuQp.js +312 -0
  49. package/dist/_chunks/Preview-VOJ8RuQp.js.map +1 -0
  50. package/dist/_chunks/Preview-Zzjg2_K_.mjs +294 -0
  51. package/dist/_chunks/Preview-Zzjg2_K_.mjs.map +1 -0
  52. package/dist/_chunks/{Relations-u8-37jK0.mjs → Relations-BVdRfDkW.mjs} +76 -42
  53. package/dist/_chunks/Relations-BVdRfDkW.mjs.map +1 -0
  54. package/dist/_chunks/{Relations-CghaPv2D.js → Relations-Dsj0boFJ.js} +76 -43
  55. package/dist/_chunks/Relations-Dsj0boFJ.js.map +1 -0
  56. package/dist/_chunks/{en-fbKQxLGn.js → en-BzQmavmK.js} +37 -18
  57. package/dist/_chunks/{en-fbKQxLGn.js.map → en-BzQmavmK.js.map} +1 -1
  58. package/dist/_chunks/{en-Ux26r5pl.mjs → en-CSxLmrh1.mjs} +37 -18
  59. package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-CSxLmrh1.mjs.map} +1 -1
  60. package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
  61. package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
  62. package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
  63. package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
  64. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
  65. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
  66. package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
  67. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
  68. package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
  69. package/dist/_chunks/{index-CaE6NG4a.mjs → index-Bu_-B7ZA.mjs} +1263 -772
  70. package/dist/_chunks/index-Bu_-B7ZA.mjs.map +1 -0
  71. package/dist/_chunks/{index-BOZx6IMg.js → index-Ct-GZ0iV.js} +1246 -755
  72. package/dist/_chunks/index-Ct-GZ0iV.js.map +1 -0
  73. package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
  74. package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
  75. package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
  76. package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
  77. package/dist/_chunks/{layout-Ciz224q5.js → layout-CDBEgRsM.js} +24 -12
  78. package/dist/_chunks/layout-CDBEgRsM.js.map +1 -0
  79. package/dist/_chunks/{layout-Bx7svTbY.mjs → layout-COzAvgJh.mjs} +24 -11
  80. package/dist/_chunks/layout-COzAvgJh.mjs.map +1 -0
  81. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  82. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  83. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  84. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  85. package/dist/_chunks/{relations-CP8sB2YZ.js → relations-BjiF1Aad.js} +6 -7
  86. package/dist/_chunks/relations-BjiF1Aad.js.map +1 -0
  87. package/dist/_chunks/{relations-Cxc1cEv3.mjs → relations-BtmMFBpM.mjs} +6 -7
  88. package/dist/_chunks/relations-BtmMFBpM.mjs.map +1 -0
  89. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  90. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  91. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  92. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  93. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
  94. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
  95. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
  96. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
  97. package/dist/admin/index.js +3 -1
  98. package/dist/admin/index.js.map +1 -1
  99. package/dist/admin/index.mjs +6 -4
  100. package/dist/admin/src/content-manager.d.ts +3 -2
  101. package/dist/admin/src/exports.d.ts +2 -1
  102. package/dist/admin/src/history/index.d.ts +3 -0
  103. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  104. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  105. package/dist/admin/src/index.d.ts +1 -0
  106. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  107. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +2 -1
  108. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +3 -3
  109. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
  110. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
  111. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
  112. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  113. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  114. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  115. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  116. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  117. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  118. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  119. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  120. package/dist/admin/src/preview/index.d.ts +4 -0
  121. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  122. package/dist/admin/src/preview/routes.d.ts +3 -0
  123. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  124. package/dist/admin/src/router.d.ts +1 -1
  125. package/dist/admin/src/services/api.d.ts +1 -1
  126. package/dist/admin/src/services/components.d.ts +2 -2
  127. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  128. package/dist/admin/src/services/documents.d.ts +19 -20
  129. package/dist/admin/src/services/init.d.ts +1 -1
  130. package/dist/admin/src/services/relations.d.ts +2 -2
  131. package/dist/admin/src/services/uid.d.ts +3 -3
  132. package/dist/admin/src/utils/validation.d.ts +4 -1
  133. package/dist/server/index.js +682 -360
  134. package/dist/server/index.js.map +1 -1
  135. package/dist/server/index.mjs +683 -360
  136. package/dist/server/index.mjs.map +1 -1
  137. package/dist/server/src/bootstrap.d.ts.map +1 -1
  138. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  139. package/dist/server/src/controllers/index.d.ts.map +1 -1
  140. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  141. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  142. package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
  143. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  144. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  145. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  146. package/dist/server/src/history/services/history.d.ts.map +1 -1
  147. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  148. package/dist/server/src/history/services/utils.d.ts +4 -4
  149. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  150. package/dist/server/src/index.d.ts +7 -6
  151. package/dist/server/src/index.d.ts.map +1 -1
  152. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  153. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  154. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  155. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  156. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  157. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  158. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  159. package/dist/server/src/preview/index.d.ts +4 -0
  160. package/dist/server/src/preview/index.d.ts.map +1 -0
  161. package/dist/server/src/preview/routes/index.d.ts +8 -0
  162. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  163. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  164. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  165. package/dist/server/src/preview/services/index.d.ts +16 -0
  166. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  167. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  168. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  169. package/dist/server/src/preview/services/preview.d.ts +12 -0
  170. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  171. package/dist/server/src/preview/utils.d.ts +19 -0
  172. package/dist/server/src/preview/utils.d.ts.map +1 -0
  173. package/dist/server/src/register.d.ts.map +1 -1
  174. package/dist/server/src/routes/index.d.ts.map +1 -1
  175. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  176. package/dist/server/src/services/document-metadata.d.ts +12 -10
  177. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  178. package/dist/server/src/services/index.d.ts +7 -6
  179. package/dist/server/src/services/index.d.ts.map +1 -1
  180. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  181. package/dist/server/src/services/utils/populate.d.ts +2 -2
  182. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  183. package/dist/server/src/utils/index.d.ts +2 -0
  184. package/dist/server/src/utils/index.d.ts.map +1 -1
  185. package/dist/shared/contracts/collection-types.d.ts +3 -1
  186. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  187. package/dist/shared/contracts/index.d.ts +1 -0
  188. package/dist/shared/contracts/index.d.ts.map +1 -1
  189. package/dist/shared/contracts/preview.d.ts +27 -0
  190. package/dist/shared/contracts/preview.d.ts.map +1 -0
  191. package/dist/shared/index.js +4 -0
  192. package/dist/shared/index.js.map +1 -1
  193. package/dist/shared/index.mjs +4 -0
  194. package/dist/shared/index.mjs.map +1 -1
  195. package/package.json +17 -15
  196. package/dist/_chunks/EditViewPage-BqNpC6hO.js.map +0 -1
  197. package/dist/_chunks/EditViewPage-BtkEx339.mjs.map +0 -1
  198. package/dist/_chunks/Field-R5NbffTB.mjs.map +0 -1
  199. package/dist/_chunks/Field-lsPFnAmH.js.map +0 -1
  200. package/dist/_chunks/Form-BHmXSfyy.mjs.map +0 -1
  201. package/dist/_chunks/Form-CcGboku8.js.map +0 -1
  202. package/dist/_chunks/History-Bsud8jwh.js.map +0 -1
  203. package/dist/_chunks/History-ByUPL3T3.mjs.map +0 -1
  204. package/dist/_chunks/ListConfigurationPage-Bm5HACXf.mjs.map +0 -1
  205. package/dist/_chunks/ListConfigurationPage-DiT463qx.js.map +0 -1
  206. package/dist/_chunks/ListViewPage-CsrC9L_d.js.map +0 -1
  207. package/dist/_chunks/ListViewPage-JSyNAAYu.mjs.map +0 -1
  208. package/dist/_chunks/Relations-CghaPv2D.js.map +0 -1
  209. package/dist/_chunks/Relations-u8-37jK0.mjs.map +0 -1
  210. package/dist/_chunks/index-BOZx6IMg.js.map +0 -1
  211. package/dist/_chunks/index-CaE6NG4a.mjs.map +0 -1
  212. package/dist/_chunks/layout-Bx7svTbY.mjs.map +0 -1
  213. package/dist/_chunks/layout-Ciz224q5.js.map +0 -1
  214. package/dist/_chunks/relations-CP8sB2YZ.js.map +0 -1
  215. package/dist/_chunks/relations-Cxc1cEv3.mjs.map +0 -1
  216. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  217. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  218. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  219. package/strapi-server.js +0 -3
@@ -1,25 +1,33 @@
1
- import { ClockCounterClockwise, CrossCircle, More, WarningCircle, ListPlus, Pencil, Trash, Check, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, Feather } from "@strapi/icons";
1
+ import { More, Cross, WarningCircle, ListPlus, Pencil, Trash, Check, CrossCircle, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, Feather } from "@strapi/icons";
2
2
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
3
- import { useStrapiApp, useQueryParams, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useTracking, useForm, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
4
- import { stringify } from "qs";
5
- import { useIntl } from "react-intl";
6
- import { useNavigate, useParams, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
3
+ import { useStrapiApp, createContext, useQueryParams, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useForm, useTracking, useGuidedTour, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
7
4
  import * as React from "react";
8
5
  import { lazy } from "react";
9
- import { Button, Menu, VisuallyHidden, Flex, Box, Typography, Dialog, Modal, Radio, Status, SingleSelect, SingleSelectOption, Loader, IconButton, Tooltip, LinkButton } from "@strapi/design-system";
6
+ import { Menu, Button, VisuallyHidden, Flex, Dialog, Modal, Typography, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
7
+ import mapValues from "lodash/fp/mapValues";
8
+ import { useIntl } from "react-intl";
9
+ import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
10
10
  import { styled } from "styled-components";
11
11
  import * as yup from "yup";
12
12
  import { ValidationError } from "yup";
13
+ import { stringify } from "qs";
13
14
  import pipe from "lodash/fp/pipe";
14
15
  import { intervalToDuration, isPast } from "date-fns";
15
16
  import { createSlice, combineReducers } from "@reduxjs/toolkit";
16
- const __variableDynamicImportRuntimeHelper = (glob, path) => {
17
+ const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
17
18
  const v = glob[path];
18
19
  if (v) {
19
20
  return typeof v === "function" ? v() : Promise.resolve(v);
20
21
  }
21
22
  return new Promise((_, reject) => {
22
- (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(reject.bind(null, new Error("Unknown variable dynamic import: " + path)));
23
+ (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
24
+ reject.bind(
25
+ null,
26
+ new Error(
27
+ "Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
28
+ )
29
+ )
30
+ );
23
31
  });
24
32
  };
25
33
  const PLUGIN_ID = "content-manager";
@@ -49,42 +57,6 @@ const useInjectionZone = (area) => {
49
57
  const [page, position] = area.split(".");
50
58
  return contentManagerPlugin.getInjectedComponents(page, position);
51
59
  };
52
- const HistoryAction = ({ model, document }) => {
53
- const { formatMessage } = useIntl();
54
- const [{ query }] = useQueryParams();
55
- const navigate = useNavigate();
56
- const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
57
- if (!window.strapi.features.isEnabled("cms-content-history")) {
58
- return null;
59
- }
60
- return {
61
- icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
62
- label: formatMessage({
63
- id: "content-manager.history.document-action",
64
- defaultMessage: "Content History"
65
- }),
66
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
67
- disabled: (
68
- /**
69
- * The user is creating a new document.
70
- * It hasn't been saved yet, so there's no history to go to
71
- */
72
- !document || /**
73
- * The document has been created but the current dimension has never been saved.
74
- * For example, the user is creating a new locale in an existing document,
75
- * so there's no history for the document in that locale
76
- */
77
- !document.id || /**
78
- * History is only available for content types created by the user.
79
- * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
80
- * which start with `admin::` or `plugin::`
81
- */
82
- !model.startsWith("api::")
83
- ),
84
- position: "header"
85
- };
86
- };
87
- HistoryAction.type = "history";
88
60
  const ID = "id";
89
61
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
90
62
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -136,6 +108,7 @@ const DocumentRBAC = ({ children, permissions }) => {
136
108
  if (!slug) {
137
109
  throw new Error("Cannot find the slug param in the URL");
138
110
  }
111
+ const [{ rawQuery }] = useQueryParams();
139
112
  const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
140
113
  const contentTypePermissions = React.useMemo(() => {
141
114
  const contentTypePermissions2 = userPermissions.filter(
@@ -146,7 +119,14 @@ const DocumentRBAC = ({ children, permissions }) => {
146
119
  return { ...acc, [action]: [permission] };
147
120
  }, {});
148
121
  }, [slug, userPermissions]);
149
- const { isLoading, allowedActions } = useRBAC(contentTypePermissions, permissions ?? void 0);
122
+ const { isLoading, allowedActions } = useRBAC(
123
+ contentTypePermissions,
124
+ permissions ?? void 0,
125
+ // TODO: useRBAC context should be typed and built differently
126
+ // We are passing raw query as context to the hook so that it can
127
+ // rely on the locale provided from DocumentRBAC for its permission calculations.
128
+ rawQuery
129
+ );
150
130
  const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
151
131
  const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
152
132
  const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
@@ -194,7 +174,9 @@ const contentManagerApi = adminApi.enhanceEndpoints({
194
174
  "Document",
195
175
  "InitialData",
196
176
  "HistoryVersion",
197
- "Relations"
177
+ "Relations",
178
+ "UidAvailability",
179
+ "RecentDocumentList"
198
180
  ]
199
181
  });
200
182
  const documentApi = contentManagerApi.injectEndpoints({
@@ -208,7 +190,12 @@ const documentApi = contentManagerApi.injectEndpoints({
208
190
  params: query
209
191
  }
210
192
  }),
211
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
193
+ invalidatesTags: (_result, error, { model }) => {
194
+ if (error) {
195
+ return [];
196
+ }
197
+ return [{ type: "Document", id: `${model}_LIST` }, "RecentDocumentList"];
198
+ }
212
199
  }),
213
200
  cloneDocument: builder.mutation({
214
201
  query: ({ model, sourceId, data, params }) => ({
@@ -219,7 +206,11 @@ const documentApi = contentManagerApi.injectEndpoints({
219
206
  params
220
207
  }
221
208
  }),
222
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
209
+ invalidatesTags: (_result, _error, { model }) => [
210
+ { type: "Document", id: `${model}_LIST` },
211
+ { type: "UidAvailability", id: model },
212
+ "RecentDocumentList"
213
+ ]
223
214
  }),
224
215
  /**
225
216
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -236,8 +227,22 @@ const documentApi = contentManagerApi.injectEndpoints({
236
227
  }),
237
228
  invalidatesTags: (result, _error, { model }) => [
238
229
  { type: "Document", id: `${model}_LIST` },
239
- "Relations"
240
- ]
230
+ "Relations",
231
+ { type: "UidAvailability", id: model },
232
+ "RecentDocumentList"
233
+ ],
234
+ transformResponse: (response, meta, arg) => {
235
+ if (!("data" in response) && arg.model === "plugin::users-permissions.user") {
236
+ return {
237
+ data: response,
238
+ meta: {
239
+ availableStatus: [],
240
+ availableLocales: []
241
+ }
242
+ };
243
+ }
244
+ return response;
245
+ }
241
246
  }),
242
247
  deleteDocument: builder.mutation({
243
248
  query: ({ collectionType, model, documentId, params }) => ({
@@ -248,7 +253,8 @@ const documentApi = contentManagerApi.injectEndpoints({
248
253
  }
249
254
  }),
250
255
  invalidatesTags: (_result, _error, { collectionType, model }) => [
251
- { type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model }
256
+ { type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model },
257
+ "RecentDocumentList"
252
258
  ]
253
259
  }),
254
260
  deleteManyDocuments: builder.mutation({
@@ -260,7 +266,10 @@ const documentApi = contentManagerApi.injectEndpoints({
260
266
  params
261
267
  }
262
268
  }),
263
- invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
269
+ invalidatesTags: (_res, _error, { model }) => [
270
+ { type: "Document", id: `${model}_LIST` },
271
+ "RecentDocumentList"
272
+ ]
264
273
  }),
265
274
  discardDocument: builder.mutation({
266
275
  query: ({ collectionType, model, documentId, params }) => ({
@@ -277,7 +286,9 @@ const documentApi = contentManagerApi.injectEndpoints({
277
286
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
278
287
  },
279
288
  { type: "Document", id: `${model}_LIST` },
280
- "Relations"
289
+ "Relations",
290
+ { type: "UidAvailability", id: model },
291
+ "RecentDocumentList"
281
292
  ];
282
293
  }
283
294
  }),
@@ -290,11 +301,12 @@ const documentApi = contentManagerApi.injectEndpoints({
290
301
  url: `/content-manager/collection-types/${model}`,
291
302
  method: "GET",
292
303
  config: {
293
- params
304
+ params: stringify(params, { encode: true })
294
305
  }
295
306
  }),
296
307
  providesTags: (result, _error, arg) => {
297
308
  return [
309
+ { type: "Document", id: `ALL_LIST` },
298
310
  { type: "Document", id: `${arg.model}_LIST` },
299
311
  ...result?.results.map(({ documentId }) => ({
300
312
  type: "Document",
@@ -333,6 +345,11 @@ const documentApi = contentManagerApi.injectEndpoints({
333
345
  {
334
346
  type: "Document",
335
347
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
348
+ },
349
+ // Make it easy to invalidate all individual documents queries for a model
350
+ {
351
+ type: "Document",
352
+ id: `${model}_ALL_ITEMS`
336
353
  }
337
354
  ];
338
355
  }
@@ -366,7 +383,8 @@ const documentApi = contentManagerApi.injectEndpoints({
366
383
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
367
384
  },
368
385
  { type: "Document", id: `${model}_LIST` },
369
- "Relations"
386
+ "Relations",
387
+ "RecentDocumentList"
370
388
  ];
371
389
  }
372
390
  }),
@@ -396,8 +414,23 @@ const documentApi = contentManagerApi.injectEndpoints({
396
414
  type: "Document",
397
415
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
398
416
  },
399
- "Relations"
417
+ "Relations",
418
+ { type: "UidAvailability", id: model },
419
+ "RecentDocumentList",
420
+ "RecentDocumentList"
400
421
  ];
422
+ },
423
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
424
+ const patchResult = dispatch(
425
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
426
+ Object.assign(draft.data, data);
427
+ })
428
+ );
429
+ try {
430
+ await queryFulfilled;
431
+ } catch {
432
+ patchResult.undo();
433
+ }
401
434
  }
402
435
  }),
403
436
  unpublishDocument: builder.mutation({
@@ -414,7 +447,8 @@ const documentApi = contentManagerApi.injectEndpoints({
414
447
  {
415
448
  type: "Document",
416
449
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
417
- }
450
+ },
451
+ "RecentDocumentList"
418
452
  ];
419
453
  }
420
454
  }),
@@ -427,7 +461,10 @@ const documentApi = contentManagerApi.injectEndpoints({
427
461
  params
428
462
  }
429
463
  }),
430
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
464
+ invalidatesTags: (_res, _error, { model, documentIds }) => [
465
+ ...documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` })),
466
+ "RecentDocumentList"
467
+ ]
431
468
  })
432
469
  })
433
470
  });
@@ -450,8 +487,7 @@ const {
450
487
  useUnpublishManyDocumentsMutation
451
488
  } = documentApi;
452
489
  const buildValidParams = (query) => {
453
- if (!query)
454
- return query;
490
+ if (!query) return query;
455
491
  const { plugins: _, ...validQueryParams } = {
456
492
  ...query,
457
493
  ...Object.values(query?.plugins ?? {}).reduce(
@@ -459,28 +495,44 @@ const buildValidParams = (query) => {
459
495
  {}
460
496
  )
461
497
  };
462
- if ("_q" in validQueryParams) {
463
- validQueryParams._q = encodeURIComponent(validQueryParams._q);
464
- }
465
498
  return validQueryParams;
466
499
  };
467
500
  const isBaseQueryError = (error) => {
468
501
  return error.name !== void 0;
469
502
  };
470
- const createYupSchema = (attributes = {}, components = {}) => {
503
+ const arrayValidator = (attribute, options) => ({
504
+ message: translatedErrors.required,
505
+ test(value) {
506
+ if (options.status === "draft") {
507
+ return true;
508
+ }
509
+ if (!attribute.required) {
510
+ return true;
511
+ }
512
+ if (!value) {
513
+ return false;
514
+ }
515
+ if (Array.isArray(value) && value.length === 0) {
516
+ return false;
517
+ }
518
+ return true;
519
+ }
520
+ });
521
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
471
522
  const createModelSchema = (attributes2) => yup.object().shape(
472
523
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
473
524
  if (DOCUMENT_META_FIELDS.includes(name)) {
474
525
  return acc;
475
526
  }
476
527
  const validations = [
528
+ addNullableValidation,
477
529
  addRequiredValidation,
478
530
  addMinLengthValidation,
479
531
  addMaxLengthValidation,
480
532
  addMinValidation,
481
533
  addMaxValidation,
482
534
  addRegexValidation
483
- ].map((fn) => fn(attribute));
535
+ ].map((fn) => fn(attribute, options));
484
536
  const transformSchema = pipe(...validations);
485
537
  switch (attribute.type) {
486
538
  case "component": {
@@ -490,12 +542,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
490
542
  ...acc,
491
543
  [name]: transformSchema(
492
544
  yup.array().of(createModelSchema(attributes3).nullable(false))
493
- )
545
+ ).test(arrayValidator(attribute, options))
494
546
  };
495
547
  } else {
496
548
  return {
497
549
  ...acc,
498
- [name]: transformSchema(createModelSchema(attributes3))
550
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
499
551
  };
500
552
  }
501
553
  }
@@ -517,7 +569,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
517
569
  }
518
570
  )
519
571
  )
520
- )
572
+ ).test(arrayValidator(attribute, options))
521
573
  };
522
574
  case "relation":
523
575
  return {
@@ -529,7 +581,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
529
581
  } else if (Array.isArray(value)) {
530
582
  return yup.array().of(
531
583
  yup.object().shape({
532
- id: yup.string().required()
584
+ id: yup.number().required()
533
585
  })
534
586
  );
535
587
  } else if (typeof value === "object") {
@@ -581,6 +633,14 @@ const createAttributeSchema = (attribute) => {
581
633
  if (!value || typeof value === "string" && value.length === 0) {
582
634
  return true;
583
635
  }
636
+ if (typeof value === "object") {
637
+ try {
638
+ JSON.stringify(value);
639
+ return true;
640
+ } catch (err) {
641
+ return false;
642
+ }
643
+ }
584
644
  try {
585
645
  JSON.parse(value);
586
646
  return true;
@@ -599,13 +659,7 @@ const createAttributeSchema = (attribute) => {
599
659
  return yup.mixed();
600
660
  }
601
661
  };
602
- const addRequiredValidation = (attribute) => (schema) => {
603
- if (attribute.required && attribute.type !== "relation") {
604
- return schema.required({
605
- id: translatedErrors.required.id,
606
- defaultMessage: "This field is required."
607
- });
608
- }
662
+ const nullableSchema = (schema) => {
609
663
  return schema?.nullable ? schema.nullable() : (
610
664
  // In some cases '.nullable' will not be available on the schema.
611
665
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -613,7 +667,22 @@ const addRequiredValidation = (attribute) => (schema) => {
613
667
  schema
614
668
  );
615
669
  };
616
- const addMinLengthValidation = (attribute) => (schema) => {
670
+ const addNullableValidation = () => (schema) => {
671
+ return nullableSchema(schema);
672
+ };
673
+ const addRequiredValidation = (attribute, options) => (schema) => {
674
+ if (options.status === "draft" || !attribute.required) {
675
+ return schema;
676
+ }
677
+ if (attribute.required && "required" in schema) {
678
+ return schema.required(translatedErrors.required);
679
+ }
680
+ return schema;
681
+ };
682
+ const addMinLengthValidation = (attribute, options) => (schema) => {
683
+ if (options.status === "draft") {
684
+ return schema;
685
+ }
617
686
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
618
687
  return schema.min(attribute.minLength, {
619
688
  ...translatedErrors.minLength,
@@ -635,10 +704,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
635
704
  }
636
705
  return schema;
637
706
  };
638
- const addMinValidation = (attribute) => (schema) => {
639
- if ("min" in attribute) {
707
+ const addMinValidation = (attribute, options) => (schema) => {
708
+ if (options.status === "draft") {
709
+ return schema;
710
+ }
711
+ if ("min" in attribute && "min" in schema) {
640
712
  const min = toInteger(attribute.min);
641
- if ("min" in schema && min) {
713
+ if (min) {
642
714
  return schema.min(min, {
643
715
  ...translatedErrors.min,
644
716
  values: {
@@ -756,19 +828,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
756
828
  }, {});
757
829
  return componentsByKey;
758
830
  };
759
- const useDocument = (args, opts) => {
831
+ const HOOKS = {
832
+ /**
833
+ * Hook that allows to mutate the displayed headers of the list view table
834
+ * @constant
835
+ * @type {string}
836
+ */
837
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
838
+ /**
839
+ * Hook that allows to mutate the CM's collection types links pre-set filters
840
+ * @constant
841
+ * @type {string}
842
+ */
843
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
844
+ /**
845
+ * Hook that allows to mutate the CM's edit view layout
846
+ * @constant
847
+ * @type {string}
848
+ */
849
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
850
+ /**
851
+ * Hook that allows to mutate the CM's single types links pre-set filters
852
+ * @constant
853
+ * @type {string}
854
+ */
855
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
856
+ };
857
+ const contentTypesApi = contentManagerApi.injectEndpoints({
858
+ endpoints: (builder) => ({
859
+ getContentTypeConfiguration: builder.query({
860
+ query: (uid) => ({
861
+ url: `/content-manager/content-types/${uid}/configuration`,
862
+ method: "GET"
863
+ }),
864
+ transformResponse: (response) => response.data,
865
+ providesTags: (_result, _error, uid) => [
866
+ { type: "ContentTypesConfiguration", id: uid },
867
+ { type: "ContentTypeSettings", id: "LIST" }
868
+ ]
869
+ }),
870
+ getAllContentTypeSettings: builder.query({
871
+ query: () => "/content-manager/content-types-settings",
872
+ transformResponse: (response) => response.data,
873
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
874
+ }),
875
+ updateContentTypeConfiguration: builder.mutation({
876
+ query: ({ uid, ...body }) => ({
877
+ url: `/content-manager/content-types/${uid}/configuration`,
878
+ method: "PUT",
879
+ data: body
880
+ }),
881
+ transformResponse: (response) => response.data,
882
+ invalidatesTags: (_result, _error, { uid }) => [
883
+ { type: "ContentTypesConfiguration", id: uid },
884
+ { type: "ContentTypeSettings", id: "LIST" },
885
+ // Is this necessary?
886
+ { type: "InitialData" }
887
+ ]
888
+ })
889
+ })
890
+ });
891
+ const {
892
+ useGetContentTypeConfigurationQuery,
893
+ useGetAllContentTypeSettingsQuery,
894
+ useUpdateContentTypeConfigurationMutation
895
+ } = contentTypesApi;
896
+ const checkIfAttributeIsDisplayable = (attribute) => {
897
+ const { type } = attribute;
898
+ if (type === "relation") {
899
+ return !attribute.relation.toLowerCase().includes("morph");
900
+ }
901
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
902
+ };
903
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
904
+ if (!mainFieldName) {
905
+ return void 0;
906
+ }
907
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
908
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
909
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
910
+ );
911
+ return {
912
+ name: mainFieldName,
913
+ type: mainFieldType ?? "string"
914
+ };
915
+ };
916
+ const DEFAULT_SETTINGS = {
917
+ bulkable: false,
918
+ filterable: false,
919
+ searchable: false,
920
+ pagination: false,
921
+ defaultSortBy: "",
922
+ defaultSortOrder: "asc",
923
+ mainField: "id",
924
+ pageSize: 10
925
+ };
926
+ const useDocumentLayout = (model) => {
927
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
928
+ const [{ query }] = useQueryParams();
929
+ const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
760
930
  const { toggleNotification } = useNotification();
761
931
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
932
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
762
933
  const {
763
- currentData: data,
764
- isLoading: isLoadingDocument,
765
- isFetching: isFetchingDocument,
766
- error
767
- } = useGetDocumentQuery(args, {
768
- ...opts,
769
- skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
770
- });
771
- const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
934
+ data,
935
+ isLoading: isLoadingConfigs,
936
+ error,
937
+ isFetching: isFetchingConfigs
938
+ } = useGetContentTypeConfigurationQuery(model);
939
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
772
940
  React.useEffect(() => {
773
941
  if (error) {
774
942
  toggleNotification({
@@ -776,39 +944,255 @@ const useDocument = (args, opts) => {
776
944
  message: formatAPIError(error)
777
945
  });
778
946
  }
779
- }, [toggleNotification, error, formatAPIError, args.collectionType]);
780
- const validationSchema = React.useMemo(() => {
781
- if (!schema) {
782
- return null;
783
- }
784
- return createYupSchema(schema.attributes, components);
785
- }, [schema, components]);
786
- const validate = React.useCallback(
787
- (document) => {
788
- if (!validationSchema) {
789
- throw new Error(
790
- "There is no validation schema generated, this is likely due to the schema not being loaded yet."
791
- );
792
- }
793
- try {
794
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
795
- return null;
796
- } catch (error2) {
797
- if (error2 instanceof ValidationError) {
798
- return getYupValidationErrors(error2);
799
- }
800
- throw error2;
801
- }
947
+ }, [error, formatAPIError, toggleNotification]);
948
+ const editLayout = React.useMemo(
949
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
950
+ layout: [],
951
+ components: {},
952
+ metadatas: {},
953
+ options: {},
954
+ settings: DEFAULT_SETTINGS
802
955
  },
803
- [validationSchema]
956
+ [data, isLoading, schemas, schema, components]
957
+ );
958
+ const listLayout = React.useMemo(() => {
959
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
960
+ layout: [],
961
+ metadatas: {},
962
+ options: {},
963
+ settings: DEFAULT_SETTINGS
964
+ };
965
+ }, [data, isLoading, schemas, schema, components]);
966
+ const { layout: edit } = React.useMemo(
967
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
968
+ layout: editLayout,
969
+ query
970
+ }),
971
+ [editLayout, query, runHookWaterfall]
804
972
  );
805
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
806
973
  return {
807
- components,
808
- document: data?.data,
974
+ error,
975
+ isLoading,
976
+ edit,
977
+ list: listLayout
978
+ };
979
+ };
980
+ const useDocLayout = () => {
981
+ const { model } = useDoc();
982
+ return useDocumentLayout(model);
983
+ };
984
+ const formatEditLayout = (data, {
985
+ schemas,
986
+ schema,
987
+ components
988
+ }) => {
989
+ let currentPanelIndex = 0;
990
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
991
+ data.contentType.layouts.edit,
992
+ schema?.attributes,
993
+ data.contentType.metadatas,
994
+ { configurations: data.components, schemas: components },
995
+ schemas
996
+ ).reduce((panels, row) => {
997
+ if (row.some((field) => field.type === "dynamiczone")) {
998
+ panels.push([row]);
999
+ currentPanelIndex += 2;
1000
+ } else {
1001
+ if (!panels[currentPanelIndex]) {
1002
+ panels.push([row]);
1003
+ } else {
1004
+ panels[currentPanelIndex].push(row);
1005
+ }
1006
+ }
1007
+ return panels;
1008
+ }, []);
1009
+ const componentEditAttributes = Object.entries(data.components).reduce(
1010
+ (acc, [uid, configuration]) => {
1011
+ acc[uid] = {
1012
+ layout: convertEditLayoutToFieldLayouts(
1013
+ configuration.layouts.edit,
1014
+ components[uid].attributes,
1015
+ configuration.metadatas,
1016
+ { configurations: data.components, schemas: components }
1017
+ ),
1018
+ settings: {
1019
+ ...configuration.settings,
1020
+ icon: components[uid].info.icon,
1021
+ displayName: components[uid].info.displayName
1022
+ }
1023
+ };
1024
+ return acc;
1025
+ },
1026
+ {}
1027
+ );
1028
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
1029
+ (acc, [attribute, metadata]) => {
1030
+ return {
1031
+ ...acc,
1032
+ [attribute]: metadata.edit
1033
+ };
1034
+ },
1035
+ {}
1036
+ );
1037
+ return {
1038
+ layout: panelledEditAttributes,
1039
+ components: componentEditAttributes,
1040
+ metadatas: editMetadatas,
1041
+ settings: {
1042
+ ...data.contentType.settings,
1043
+ displayName: schema?.info.displayName
1044
+ },
1045
+ options: {
1046
+ ...schema?.options,
1047
+ ...schema?.pluginOptions,
1048
+ ...data.contentType.options
1049
+ }
1050
+ };
1051
+ };
1052
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1053
+ return rows.map(
1054
+ (row) => row.map((field) => {
1055
+ const attribute = attributes[field.name];
1056
+ if (!attribute) {
1057
+ return null;
1058
+ }
1059
+ const { edit: metadata } = metadatas[field.name];
1060
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1061
+ return {
1062
+ attribute,
1063
+ disabled: !metadata.editable,
1064
+ hint: metadata.description,
1065
+ label: metadata.label ?? "",
1066
+ name: field.name,
1067
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1068
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1069
+ schemas,
1070
+ components: components?.schemas ?? {}
1071
+ }),
1072
+ placeholder: metadata.placeholder ?? "",
1073
+ required: attribute.required ?? false,
1074
+ size: field.size,
1075
+ unique: "unique" in attribute ? attribute.unique : false,
1076
+ visible: metadata.visible ?? true,
1077
+ type: attribute.type
1078
+ };
1079
+ }).filter((field) => field !== null)
1080
+ );
1081
+ };
1082
+ const formatListLayout = (data, {
1083
+ schemas,
1084
+ schema,
1085
+ components
1086
+ }) => {
1087
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1088
+ (acc, [attribute, metadata]) => {
1089
+ return {
1090
+ ...acc,
1091
+ [attribute]: metadata.list
1092
+ };
1093
+ },
1094
+ {}
1095
+ );
1096
+ const listAttributes = convertListLayoutToFieldLayouts(
1097
+ data.contentType.layouts.list,
1098
+ schema?.attributes,
1099
+ listMetadatas,
1100
+ { configurations: data.components, schemas: components },
1101
+ schemas
1102
+ );
1103
+ return {
1104
+ layout: listAttributes,
1105
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1106
+ metadatas: listMetadatas,
1107
+ options: {
1108
+ ...schema?.options,
1109
+ ...schema?.pluginOptions,
1110
+ ...data.contentType.options
1111
+ }
1112
+ };
1113
+ };
1114
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1115
+ return columns.map((name) => {
1116
+ const attribute = attributes[name];
1117
+ if (!attribute) {
1118
+ return null;
1119
+ }
1120
+ const metadata = metadatas[name];
1121
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1122
+ return {
1123
+ attribute,
1124
+ label: metadata.label ?? "",
1125
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1126
+ schemas,
1127
+ components: components?.schemas ?? {}
1128
+ }),
1129
+ name,
1130
+ searchable: metadata.searchable ?? true,
1131
+ sortable: metadata.sortable ?? true
1132
+ };
1133
+ }).filter((field) => field !== null);
1134
+ };
1135
+ const useDocument = (args, opts) => {
1136
+ const { toggleNotification } = useNotification();
1137
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
1138
+ const {
1139
+ currentData: data,
1140
+ isLoading: isLoadingDocument,
1141
+ isFetching: isFetchingDocument,
1142
+ error
1143
+ } = useGetDocumentQuery(args, {
1144
+ ...opts,
1145
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1146
+ });
1147
+ const {
1148
+ components,
1149
+ schema,
1150
+ schemas,
1151
+ isLoading: isLoadingSchema
1152
+ } = useContentTypeSchema(args.model);
1153
+ React.useEffect(() => {
1154
+ if (error) {
1155
+ toggleNotification({
1156
+ type: "danger",
1157
+ message: formatAPIError(error)
1158
+ });
1159
+ }
1160
+ }, [toggleNotification, error, formatAPIError, args.collectionType]);
1161
+ const validationSchema = React.useMemo(() => {
1162
+ if (!schema) {
1163
+ return null;
1164
+ }
1165
+ return createYupSchema(schema.attributes, components);
1166
+ }, [schema, components]);
1167
+ const validate = React.useCallback(
1168
+ (document) => {
1169
+ if (!validationSchema) {
1170
+ throw new Error(
1171
+ "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1172
+ );
1173
+ }
1174
+ try {
1175
+ validationSchema.validateSync(document, { abortEarly: false, strict: true });
1176
+ return null;
1177
+ } catch (error2) {
1178
+ if (error2 instanceof ValidationError) {
1179
+ return getYupValidationErrors(error2);
1180
+ }
1181
+ throw error2;
1182
+ }
1183
+ },
1184
+ [validationSchema]
1185
+ );
1186
+ const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1187
+ const hasError = !!error;
1188
+ return {
1189
+ components,
1190
+ document: data?.data,
809
1191
  meta: data?.meta,
810
1192
  isLoading,
1193
+ hasError,
811
1194
  schema,
1195
+ schemas,
812
1196
  validate
813
1197
  };
814
1198
  };
@@ -822,22 +1206,60 @@ const useDoc = () => {
822
1206
  if (!slug) {
823
1207
  throw new Error("Could not find model in url params");
824
1208
  }
1209
+ const document = useDocument(
1210
+ { documentId: origin || id, model: slug, collectionType, params },
1211
+ {
1212
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1213
+ }
1214
+ );
1215
+ const returnId = origin || id === "create" ? void 0 : id;
825
1216
  return {
826
1217
  collectionType,
827
1218
  model: slug,
828
- id: origin || id === "create" ? void 0 : id,
829
- ...useDocument(
830
- { documentId: origin || id, model: slug, collectionType, params },
831
- {
832
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
833
- }
834
- )
1219
+ id: returnId,
1220
+ ...document
1221
+ };
1222
+ };
1223
+ const useContentManagerContext = () => {
1224
+ const {
1225
+ collectionType,
1226
+ model,
1227
+ id,
1228
+ components,
1229
+ isLoading: isLoadingDoc,
1230
+ schema,
1231
+ schemas
1232
+ } = useDoc();
1233
+ const layout = useDocumentLayout(model);
1234
+ const form = useForm("useContentManagerContext", (state) => state);
1235
+ const isSingleType = collectionType === SINGLE_TYPES;
1236
+ const slug = model;
1237
+ const isCreatingEntry = id === "create";
1238
+ useContentTypeSchema();
1239
+ const isLoading = isLoadingDoc || layout.isLoading;
1240
+ const error = layout.error;
1241
+ return {
1242
+ error,
1243
+ isLoading,
1244
+ // Base metadata
1245
+ model,
1246
+ collectionType,
1247
+ id,
1248
+ slug,
1249
+ isCreatingEntry,
1250
+ isSingleType,
1251
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1252
+ // All schema infos
1253
+ components,
1254
+ contentType: schema,
1255
+ contentTypes: schemas,
1256
+ // Form state
1257
+ form,
1258
+ // layout infos
1259
+ layout
835
1260
  };
836
1261
  };
837
1262
  const prefixPluginTranslations = (trad, pluginId) => {
838
- if (!pluginId) {
839
- throw new TypeError("pluginId can't be empty");
840
- }
841
1263
  return Object.keys(trad).reduce((acc, current) => {
842
1264
  acc[`${pluginId}.${current}`] = trad[current];
843
1265
  return acc;
@@ -853,6 +1275,8 @@ const useDocumentActions = () => {
853
1275
  const { formatMessage } = useIntl();
854
1276
  const { trackUsage } = useTracking();
855
1277
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
1278
+ const navigate = useNavigate();
1279
+ const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
856
1280
  const [deleteDocument] = useDeleteDocumentMutation();
857
1281
  const _delete = React.useCallback(
858
1282
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -1167,6 +1591,7 @@ const useDocumentActions = () => {
1167
1591
  defaultMessage: "Saved document"
1168
1592
  })
1169
1593
  });
1594
+ setCurrentStep("contentManager.success");
1170
1595
  return res.data;
1171
1596
  } catch (err) {
1172
1597
  toggleNotification({
@@ -1188,7 +1613,6 @@ const useDocumentActions = () => {
1188
1613
  sourceId
1189
1614
  });
1190
1615
  if ("error" in res) {
1191
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1192
1616
  return { error: res.error };
1193
1617
  }
1194
1618
  toggleNotification({
@@ -1207,7 +1631,7 @@ const useDocumentActions = () => {
1207
1631
  throw err;
1208
1632
  }
1209
1633
  },
1210
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1634
+ [autoCloneDocument, formatMessage, toggleNotification]
1211
1635
  );
1212
1636
  const [cloneDocument] = useCloneDocumentMutation();
1213
1637
  const clone = React.useCallback(
@@ -1233,6 +1657,7 @@ const useDocumentActions = () => {
1233
1657
  defaultMessage: "Cloned document"
1234
1658
  })
1235
1659
  });
1660
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1236
1661
  return res.data;
1237
1662
  } catch (err) {
1238
1663
  toggleNotification({
@@ -1243,7 +1668,7 @@ const useDocumentActions = () => {
1243
1668
  throw err;
1244
1669
  }
1245
1670
  },
1246
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1671
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1247
1672
  );
1248
1673
  const [getDoc] = useLazyGetDocumentQuery();
1249
1674
  const getDocument = React.useCallback(
@@ -1268,10 +1693,10 @@ const useDocumentActions = () => {
1268
1693
  update
1269
1694
  };
1270
1695
  };
1271
- const ProtectedHistoryPage = lazy(
1272
- () => import("./History-ByUPL3T3.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1696
+ const ProtectedHistoryPage = React.lazy(
1697
+ () => import("./History-DTYB9CSB.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1273
1698
  );
1274
- const routes$1 = [
1699
+ const routes$2 = [
1275
1700
  {
1276
1701
  path: ":collectionType/:slug/:id/history",
1277
1702
  Component: ProtectedHistoryPage
@@ -1281,32 +1706,45 @@ const routes$1 = [
1281
1706
  Component: ProtectedHistoryPage
1282
1707
  }
1283
1708
  ];
1709
+ const ProtectedPreviewPage = React.lazy(
1710
+ () => import("./Preview-Zzjg2_K_.mjs").then((mod) => ({ default: mod.ProtectedPreviewPage }))
1711
+ );
1712
+ const routes$1 = [
1713
+ {
1714
+ path: ":collectionType/:slug/:id/preview",
1715
+ Component: ProtectedPreviewPage
1716
+ },
1717
+ {
1718
+ path: ":collectionType/:slug/preview",
1719
+ Component: ProtectedPreviewPage
1720
+ }
1721
+ ];
1284
1722
  const ProtectedEditViewPage = lazy(
1285
- () => import("./EditViewPage-BtkEx339.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1723
+ () => import("./EditViewPage-BPFcUbqi.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1286
1724
  );
1287
1725
  const ProtectedListViewPage = lazy(
1288
- () => import("./ListViewPage-JSyNAAYu.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1726
+ () => import("./ListViewPage-GKpL5p8A.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1289
1727
  );
1290
1728
  const ProtectedListConfiguration = lazy(
1291
- () => import("./ListConfigurationPage-Bm5HACXf.mjs").then((mod) => ({
1729
+ () => import("./ListConfigurationPage-qWx8r4D_.mjs").then((mod) => ({
1292
1730
  default: mod.ProtectedListConfiguration
1293
1731
  }))
1294
1732
  );
1295
1733
  const ProtectedEditConfigurationPage = lazy(
1296
- () => import("./EditConfigurationPage-Cp6HAEzN.mjs").then((mod) => ({
1734
+ () => import("./EditConfigurationPage-C1ddZ_zf.mjs").then((mod) => ({
1297
1735
  default: mod.ProtectedEditConfigurationPage
1298
1736
  }))
1299
1737
  );
1300
1738
  const ProtectedComponentConfigurationPage = lazy(
1301
- () => import("./ComponentConfigurationPage-DHNM3YBz.mjs").then((mod) => ({
1739
+ () => import("./ComponentConfigurationPage-CcRDqD0e.mjs").then((mod) => ({
1302
1740
  default: mod.ProtectedComponentConfigurationPage
1303
1741
  }))
1304
1742
  );
1305
1743
  const NoPermissions = lazy(
1306
- () => import("./NoPermissionsPage-DNmf_pj0.mjs").then((mod) => ({ default: mod.NoPermissions }))
1744
+ () => import("./NoPermissionsPage-BAZlWgJ4.mjs").then((mod) => ({ default: mod.NoPermissions }))
1307
1745
  );
1308
1746
  const NoContentType = lazy(
1309
- () => import("./NoContentTypePage-CsrQUpBE.mjs").then((mod) => ({ default: mod.NoContentType }))
1747
+ () => import("./NoContentTypePage-B5Vc5Cal.mjs").then((mod) => ({ default: mod.NoContentType }))
1310
1748
  );
1311
1749
  const CollectionTypePages = () => {
1312
1750
  const { collectionType } = useParams();
@@ -1318,7 +1756,7 @@ const CollectionTypePages = () => {
1318
1756
  const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
1319
1757
  const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
1320
1758
  const LIST_RELATIVE_PATH = ":collectionType/:slug";
1321
- const LIST_PATH = `/content-manager/${LIST_RELATIVE_PATH}`;
1759
+ const LIST_PATH = `/content-manager/collection-types/:slug`;
1322
1760
  const routes = [
1323
1761
  {
1324
1762
  path: LIST_RELATIVE_PATH,
@@ -1352,6 +1790,7 @@ const routes = [
1352
1790
  path: "no-content-types",
1353
1791
  Component: NoContentType
1354
1792
  },
1793
+ ...routes$2,
1355
1794
  ...routes$1
1356
1795
  ];
1357
1796
  const DocumentActions = ({ actions: actions2 }) => {
@@ -1420,12 +1859,14 @@ const DocumentActionButton = (action) => {
1420
1859
  /* @__PURE__ */ jsx(
1421
1860
  Button,
1422
1861
  {
1423
- flex: 1,
1862
+ flex: "auto",
1424
1863
  startIcon: action.icon,
1425
1864
  disabled: action.disabled,
1426
1865
  onClick: handleClick(action),
1427
1866
  justifyContent: "center",
1428
1867
  variant: action.variant || "default",
1868
+ paddingTop: "7px",
1869
+ paddingBottom: "7px",
1429
1870
  children: action.label
1430
1871
  }
1431
1872
  ),
@@ -1433,7 +1874,7 @@ const DocumentActionButton = (action) => {
1433
1874
  DocumentActionConfirmDialog,
1434
1875
  {
1435
1876
  ...action.dialog,
1436
- variant: action.variant,
1877
+ variant: action.dialog?.variant ?? action.variant,
1437
1878
  isOpen: dialogId === action.id,
1438
1879
  onClose: handleClose
1439
1880
  }
@@ -1448,6 +1889,11 @@ const DocumentActionButton = (action) => {
1448
1889
  ) : null
1449
1890
  ] });
1450
1891
  };
1892
+ const MenuItem = styled(Menu.Item)`
1893
+ &:hover {
1894
+ background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
1895
+ }
1896
+ `;
1451
1897
  const DocumentActionsMenu = ({
1452
1898
  actions: actions2,
1453
1899
  children,
@@ -1490,9 +1936,9 @@ const DocumentActionsMenu = ({
1490
1936
  disabled: isDisabled,
1491
1937
  size: "S",
1492
1938
  endIcon: null,
1493
- paddingTop: "7px",
1494
- paddingLeft: "9px",
1495
- paddingRight: "9px",
1939
+ paddingTop: "4px",
1940
+ paddingLeft: "7px",
1941
+ paddingRight: "7px",
1496
1942
  variant,
1497
1943
  children: [
1498
1944
  /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
@@ -1503,36 +1949,35 @@ const DocumentActionsMenu = ({
1503
1949
  ]
1504
1950
  }
1505
1951
  ),
1506
- /* @__PURE__ */ jsxs(Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1952
+ /* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1507
1953
  actions2.map((action) => {
1508
1954
  return /* @__PURE__ */ jsx(
1509
- Menu.Item,
1955
+ MenuItem,
1510
1956
  {
1511
1957
  disabled: action.disabled,
1512
1958
  onSelect: handleClick(action),
1513
1959
  display: "block",
1514
- children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
1515
- /* @__PURE__ */ jsxs(Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1516
- /* @__PURE__ */ jsx(Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1517
- action.label
1518
- ] }),
1519
- action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
1520
- Flex,
1521
- {
1522
- alignItems: "center",
1523
- background: "alternative100",
1524
- borderStyle: "solid",
1525
- borderColor: "alternative200",
1526
- borderWidth: "1px",
1527
- height: 5,
1528
- paddingLeft: 2,
1529
- paddingRight: 2,
1530
- hasRadius: true,
1531
- color: "alternative600",
1532
- children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
1533
- }
1534
- )
1535
- ] })
1960
+ isVariantDanger: action.variant === "danger",
1961
+ isDisabled: action.disabled,
1962
+ children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxs(
1963
+ Flex,
1964
+ {
1965
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1966
+ gap: 2,
1967
+ tag: "span",
1968
+ children: [
1969
+ /* @__PURE__ */ jsx(
1970
+ Flex,
1971
+ {
1972
+ tag: "span",
1973
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1974
+ children: action.icon
1975
+ }
1976
+ ),
1977
+ action.label
1978
+ ]
1979
+ }
1980
+ ) })
1536
1981
  },
1537
1982
  action.id
1538
1983
  );
@@ -1612,11 +2057,11 @@ const DocumentActionConfirmDialog = ({
1612
2057
  /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
1613
2058
  /* @__PURE__ */ jsx(Dialog.Body, { children: content }),
1614
2059
  /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
1615
- /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
2060
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
1616
2061
  id: "app.components.Button.cancel",
1617
2062
  defaultMessage: "Cancel"
1618
2063
  }) }) }),
1619
- /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
2064
+ /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
1620
2065
  id: "app.components.Button.confirm",
1621
2066
  defaultMessage: "Confirm"
1622
2067
  }) })
@@ -1639,10 +2084,22 @@ const DocumentActionModal = ({
1639
2084
  };
1640
2085
  return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
1641
2086
  /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
1642
- /* @__PURE__ */ jsx(Modal.Body, { children: typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content }),
1643
- /* @__PURE__ */ jsx(Modal.Footer, { children: typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer })
2087
+ typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
2088
+ typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
1644
2089
  ] }) });
1645
2090
  };
2091
+ const transformData = (data) => {
2092
+ if (Array.isArray(data)) {
2093
+ return data.map(transformData);
2094
+ }
2095
+ if (typeof data === "object" && data !== null) {
2096
+ if ("apiData" in data) {
2097
+ return data.apiData;
2098
+ }
2099
+ return mapValues(transformData)(data);
2100
+ }
2101
+ return data;
2102
+ };
1646
2103
  const PublishAction$1 = ({
1647
2104
  activeTab,
1648
2105
  documentId,
@@ -1655,13 +2112,18 @@ const PublishAction$1 = ({
1655
2112
  const navigate = useNavigate();
1656
2113
  const { toggleNotification } = useNotification();
1657
2114
  const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
2115
+ const isListView = useMatch(LIST_PATH) !== null;
1658
2116
  const isCloning = useMatch(CLONE_PATH) !== null;
2117
+ const { id } = useParams();
1659
2118
  const { formatMessage } = useIntl();
1660
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1661
- "PublishAction",
1662
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1663
- );
2119
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1664
2120
  const { publish } = useDocumentActions();
2121
+ const [
2122
+ countDraftRelations,
2123
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
2124
+ ] = useLazyGetDraftRelationCountQuery();
2125
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
2126
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
1665
2127
  const [{ query, rawQuery }] = useQueryParams();
1666
2128
  const params = React.useMemo(() => buildValidParams(query), [query]);
1667
2129
  const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1670,10 +2132,107 @@ const PublishAction$1 = ({
1670
2132
  const validate = useForm("PublishAction", (state) => state.validate);
1671
2133
  const setErrors = useForm("PublishAction", (state) => state.setErrors);
1672
2134
  const formValues = useForm("PublishAction", ({ values }) => values);
1673
- const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
2135
+ React.useEffect(() => {
2136
+ if (isErrorDraftRelations) {
2137
+ toggleNotification({
2138
+ type: "danger",
2139
+ message: formatMessage({
2140
+ id: getTranslation("error.records.fetch-draft-relatons"),
2141
+ defaultMessage: "An error occurred while fetching draft relations on this document."
2142
+ })
2143
+ });
2144
+ }
2145
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
2146
+ React.useEffect(() => {
2147
+ const localDraftRelations = /* @__PURE__ */ new Set();
2148
+ const extractDraftRelations = (data) => {
2149
+ const relations = data.connect || [];
2150
+ relations.forEach((relation) => {
2151
+ if (relation.status === "draft") {
2152
+ localDraftRelations.add(relation.id);
2153
+ }
2154
+ });
2155
+ };
2156
+ const traverseAndExtract = (data) => {
2157
+ Object.entries(data).forEach(([key, value]) => {
2158
+ if (key === "connect" && Array.isArray(value)) {
2159
+ extractDraftRelations({ connect: value });
2160
+ } else if (typeof value === "object" && value !== null) {
2161
+ traverseAndExtract(value);
2162
+ }
2163
+ });
2164
+ };
2165
+ if (!documentId || modified) {
2166
+ traverseAndExtract(formValues);
2167
+ setLocalCountOfDraftRelations(localDraftRelations.size);
2168
+ }
2169
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
2170
+ React.useEffect(() => {
2171
+ if (!document || !document.documentId || isListView) {
2172
+ return;
2173
+ }
2174
+ const fetchDraftRelationsCount = async () => {
2175
+ const { data, error } = await countDraftRelations({
2176
+ collectionType,
2177
+ model,
2178
+ documentId,
2179
+ params
2180
+ });
2181
+ if (error) {
2182
+ throw error;
2183
+ }
2184
+ if (data) {
2185
+ setServerCountOfDraftRelations(data.data);
2186
+ }
2187
+ };
2188
+ fetchDraftRelationsCount();
2189
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
2190
+ const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1674
2191
  if (!schema?.options?.draftAndPublish) {
1675
2192
  return null;
1676
2193
  }
2194
+ const performPublish = async () => {
2195
+ setSubmitting(true);
2196
+ try {
2197
+ const { errors } = await validate(true, {
2198
+ status: "published"
2199
+ });
2200
+ if (errors) {
2201
+ toggleNotification({
2202
+ type: "danger",
2203
+ message: formatMessage({
2204
+ id: "content-manager.validation.error",
2205
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2206
+ })
2207
+ });
2208
+ return;
2209
+ }
2210
+ const res = await publish(
2211
+ {
2212
+ collectionType,
2213
+ model,
2214
+ documentId,
2215
+ params
2216
+ },
2217
+ transformData(formValues)
2218
+ );
2219
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2220
+ if (id === "create") {
2221
+ navigate({
2222
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2223
+ search: rawQuery
2224
+ });
2225
+ }
2226
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2227
+ setErrors(formatValidationErrors(res.error));
2228
+ }
2229
+ } finally {
2230
+ setSubmitting(false);
2231
+ }
2232
+ };
2233
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
2234
+ const enableDraftRelationsCount = false;
2235
+ const hasDraftRelations = enableDraftRelationsCount;
1677
2236
  return {
1678
2237
  /**
1679
2238
  * Disabled when:
@@ -1683,52 +2242,40 @@ const PublishAction$1 = ({
1683
2242
  * - the document is already published & not modified
1684
2243
  * - the document is being created & not modified
1685
2244
  * - the user doesn't have the permission to publish
1686
- * - the user doesn't have the permission to create a new document
1687
- * - the user doesn't have the permission to update the document
1688
2245
  */
1689
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2246
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1690
2247
  label: formatMessage({
1691
2248
  id: "app.utils.publish",
1692
2249
  defaultMessage: "Publish"
1693
2250
  }),
1694
2251
  onClick: async () => {
1695
- setSubmitting(true);
1696
- try {
1697
- const { errors } = await validate();
1698
- if (errors) {
1699
- toggleNotification({
1700
- type: "danger",
1701
- message: formatMessage({
1702
- id: "content-manager.validation.error",
1703
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1704
- })
1705
- });
1706
- return;
1707
- }
1708
- const res = await publish(
1709
- {
1710
- collectionType,
1711
- model,
1712
- documentId,
1713
- params
1714
- },
1715
- formValues
1716
- );
1717
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1718
- navigate({
1719
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1720
- search: rawQuery
1721
- });
1722
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1723
- setErrors(formatValidationErrors(res.error));
2252
+ await performPublish();
2253
+ },
2254
+ dialog: hasDraftRelations ? {
2255
+ type: "dialog",
2256
+ variant: "danger",
2257
+ footer: null,
2258
+ title: formatMessage({
2259
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
2260
+ defaultMessage: "Confirmation"
2261
+ }),
2262
+ content: formatMessage(
2263
+ {
2264
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2265
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
2266
+ },
2267
+ {
2268
+ count: totalDraftRelations
1724
2269
  }
1725
- } finally {
1726
- setSubmitting(false);
2270
+ ),
2271
+ onConfirm: async () => {
2272
+ await performPublish();
1727
2273
  }
1728
- }
2274
+ } : void 0
1729
2275
  };
1730
2276
  };
1731
2277
  PublishAction$1.type = "publish";
2278
+ PublishAction$1.position = "panel";
1732
2279
  const UpdateAction = ({
1733
2280
  activeTab,
1734
2281
  documentId,
@@ -1741,10 +2288,6 @@ const UpdateAction = ({
1741
2288
  const cloneMatch = useMatch(CLONE_PATH);
1742
2289
  const isCloning = cloneMatch !== null;
1743
2290
  const { formatMessage } = useIntl();
1744
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1745
- canCreate: canCreate2,
1746
- canUpdate: canUpdate2
1747
- }));
1748
2291
  const { create, update, clone } = useDocumentActions();
1749
2292
  const [{ query, rawQuery }] = useQueryParams();
1750
2293
  const params = React.useMemo(() => buildValidParams(query), [query]);
@@ -1755,93 +2298,134 @@ const UpdateAction = ({
1755
2298
  const validate = useForm("UpdateAction", (state) => state.validate);
1756
2299
  const setErrors = useForm("UpdateAction", (state) => state.setErrors);
1757
2300
  const resetForm = useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
1758
- return {
1759
- /**
1760
- * Disabled when:
1761
- * - the form is submitting
1762
- * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1763
- * - the active tab is the published tab
1764
- * - the user doesn't have the permission to create a new document
1765
- * - the user doesn't have the permission to update the document
1766
- */
1767
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
1768
- label: formatMessage({
1769
- id: "content-manager.containers.Edit.save",
1770
- defaultMessage: "Save"
1771
- }),
1772
- onClick: async () => {
1773
- setSubmitting(true);
1774
- try {
1775
- const { errors } = await validate();
1776
- if (errors) {
1777
- toggleNotification({
1778
- type: "danger",
1779
- message: formatMessage({
1780
- id: "content-manager.validation.error",
1781
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1782
- })
1783
- });
1784
- return;
1785
- }
1786
- if (isCloning) {
1787
- const res = await clone(
2301
+ const handleUpdate = React.useCallback(async () => {
2302
+ setSubmitting(true);
2303
+ try {
2304
+ if (!modified) {
2305
+ return;
2306
+ }
2307
+ const { errors } = await validate(true, {
2308
+ status: "draft"
2309
+ });
2310
+ if (errors) {
2311
+ toggleNotification({
2312
+ type: "danger",
2313
+ message: formatMessage({
2314
+ id: "content-manager.validation.error",
2315
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2316
+ })
2317
+ });
2318
+ return;
2319
+ }
2320
+ if (isCloning) {
2321
+ const res = await clone(
2322
+ {
2323
+ model,
2324
+ documentId: cloneMatch.params.origin,
2325
+ params
2326
+ },
2327
+ transformData(document)
2328
+ );
2329
+ if ("data" in res) {
2330
+ navigate(
1788
2331
  {
1789
- model,
1790
- documentId: cloneMatch.params.origin,
1791
- params
1792
- },
1793
- document
1794
- );
1795
- if ("data" in res) {
1796
- navigate({
1797
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2332
+ pathname: `../${res.data.documentId}`,
1798
2333
  search: rawQuery
1799
- });
1800
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1801
- setErrors(formatValidationErrors(res.error));
1802
- }
1803
- } else if (documentId || collectionType === SINGLE_TYPES) {
1804
- const res = await update(
1805
- {
1806
- collectionType,
1807
- model,
1808
- documentId,
1809
- params
1810
2334
  },
1811
- document
2335
+ { relative: "path" }
1812
2336
  );
1813
- if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1814
- setErrors(formatValidationErrors(res.error));
1815
- } else {
1816
- resetForm();
1817
- }
2337
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2338
+ setErrors(formatValidationErrors(res.error));
2339
+ }
2340
+ } else if (documentId || collectionType === SINGLE_TYPES) {
2341
+ const res = await update(
2342
+ {
2343
+ collectionType,
2344
+ model,
2345
+ documentId,
2346
+ params
2347
+ },
2348
+ transformData(document)
2349
+ );
2350
+ if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2351
+ setErrors(formatValidationErrors(res.error));
1818
2352
  } else {
1819
- const res = await create(
2353
+ resetForm();
2354
+ }
2355
+ } else {
2356
+ const res = await create(
2357
+ {
2358
+ model,
2359
+ params
2360
+ },
2361
+ transformData(document)
2362
+ );
2363
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2364
+ navigate(
1820
2365
  {
1821
- model,
1822
- params
2366
+ pathname: `../${res.data.documentId}`,
2367
+ search: rawQuery
1823
2368
  },
1824
- document
2369
+ { replace: true, relative: "path" }
1825
2370
  );
1826
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1827
- navigate(
1828
- {
1829
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1830
- search: rawQuery
1831
- },
1832
- { replace: true }
1833
- );
1834
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1835
- setErrors(formatValidationErrors(res.error));
1836
- }
2371
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2372
+ setErrors(formatValidationErrors(res.error));
1837
2373
  }
1838
- } finally {
1839
- setSubmitting(false);
1840
2374
  }
2375
+ } finally {
2376
+ setSubmitting(false);
1841
2377
  }
2378
+ }, [
2379
+ clone,
2380
+ cloneMatch?.params.origin,
2381
+ collectionType,
2382
+ create,
2383
+ document,
2384
+ documentId,
2385
+ formatMessage,
2386
+ formatValidationErrors,
2387
+ isCloning,
2388
+ model,
2389
+ modified,
2390
+ navigate,
2391
+ params,
2392
+ rawQuery,
2393
+ resetForm,
2394
+ setErrors,
2395
+ setSubmitting,
2396
+ toggleNotification,
2397
+ update,
2398
+ validate
2399
+ ]);
2400
+ React.useEffect(() => {
2401
+ const handleKeyDown = (e) => {
2402
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
2403
+ e.preventDefault();
2404
+ handleUpdate();
2405
+ }
2406
+ };
2407
+ window.addEventListener("keydown", handleKeyDown);
2408
+ return () => {
2409
+ window.removeEventListener("keydown", handleKeyDown);
2410
+ };
2411
+ }, [handleUpdate]);
2412
+ return {
2413
+ /**
2414
+ * Disabled when:
2415
+ * - the form is submitting
2416
+ * - the document is not modified & we're not cloning (you can save a clone entity straight away)
2417
+ * - the active tab is the published tab
2418
+ */
2419
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
2420
+ label: formatMessage({
2421
+ id: "global.save",
2422
+ defaultMessage: "Save"
2423
+ }),
2424
+ onClick: handleUpdate
1842
2425
  };
1843
2426
  };
1844
2427
  UpdateAction.type = "update";
2428
+ UpdateAction.position = "panel";
1845
2429
  const UNPUBLISH_DRAFT_OPTIONS = {
1846
2430
  KEEP: "keep",
1847
2431
  DISCARD: "discard"
@@ -1874,7 +2458,7 @@ const UnpublishAction$1 = ({
1874
2458
  id: "app.utils.unpublish",
1875
2459
  defaultMessage: "Unpublish"
1876
2460
  }),
1877
- icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
2461
+ icon: /* @__PURE__ */ jsx(Cross, {}),
1878
2462
  onClick: async () => {
1879
2463
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1880
2464
  if (!documentId) {
@@ -1964,6 +2548,7 @@ const UnpublishAction$1 = ({
1964
2548
  };
1965
2549
  };
1966
2550
  UnpublishAction$1.type = "unpublish";
2551
+ UnpublishAction$1.position = "panel";
1967
2552
  const DiscardAction = ({
1968
2553
  activeTab,
1969
2554
  documentId,
@@ -1986,7 +2571,7 @@ const DiscardAction = ({
1986
2571
  id: "content-manager.actions.discard.label",
1987
2572
  defaultMessage: "Discard changes"
1988
2573
  }),
1989
- icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
2574
+ icon: /* @__PURE__ */ jsx(Cross, {}),
1990
2575
  position: ["panel", "table-row"],
1991
2576
  variant: "danger",
1992
2577
  dialog: {
@@ -2014,11 +2599,7 @@ const DiscardAction = ({
2014
2599
  };
2015
2600
  };
2016
2601
  DiscardAction.type = "discard";
2017
- const StyledCrossCircle = styled(CrossCircle)`
2018
- path {
2019
- fill: currentColor;
2020
- }
2021
- `;
2602
+ DiscardAction.position = "panel";
2022
2603
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2023
2604
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2024
2605
  const RelativeTime = React.forwardRef(
@@ -2031,7 +2612,7 @@ const RelativeTime = React.forwardRef(
2031
2612
  });
2032
2613
  const unit = intervals.find((intervalUnit) => {
2033
2614
  return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
2034
- });
2615
+ }) ?? "seconds";
2035
2616
  const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
2036
2617
  const customInterval = customIntervals.find(
2037
2618
  (custom) => interval[custom.unit] < custom.threshold
@@ -2065,34 +2646,34 @@ const getDisplayName = ({
2065
2646
  return email ?? "";
2066
2647
  };
2067
2648
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2068
- const DocumentStatus = ({ status = "draft", ...restProps }) => {
2069
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
2070
- return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2649
+ const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
2650
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2651
+ const { formatMessage } = useIntl();
2652
+ return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
2653
+ id: `content-manager.containers.List.${status}`,
2654
+ defaultMessage: capitalise(status)
2655
+ }) }) });
2071
2656
  };
2072
2657
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2073
2658
  const { formatMessage } = useIntl();
2074
2659
  const isCloning = useMatch(CLONE_PATH) !== null;
2660
+ const params = useParams();
2075
2661
  const title = isCreating ? formatMessage({
2076
2662
  id: "content-manager.containers.edit.title.new",
2077
2663
  defaultMessage: "Create an entry"
2078
2664
  }) : documentTitle;
2079
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2080
- /* @__PURE__ */ jsx(BackButton, {}),
2081
- /* @__PURE__ */ jsxs(
2082
- Flex,
2665
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2666
+ /* @__PURE__ */ jsx(
2667
+ BackButton,
2083
2668
  {
2084
- width: "100%",
2085
- justifyContent: "space-between",
2086
- paddingTop: 1,
2087
- gap: "80px",
2088
- alignItems: "flex-start",
2089
- children: [
2090
- /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
2091
- /* @__PURE__ */ jsx(HeaderToolbar, {})
2092
- ]
2669
+ fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
2093
2670
  }
2094
2671
  ),
2095
- status ? /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2672
+ /* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2673
+ /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
2674
+ /* @__PURE__ */ jsx(HeaderToolbar, {})
2675
+ ] }),
2676
+ status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2096
2677
  ] });
2097
2678
  };
2098
2679
  const HeaderToolbar = () => {
@@ -2138,7 +2719,7 @@ const HeaderToolbar = () => {
2138
2719
  meta: isCloning ? void 0 : meta,
2139
2720
  collectionType
2140
2721
  },
2141
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2722
+ descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
2142
2723
  children: (actions2) => {
2143
2724
  const headerActions = actions2.filter((action) => {
2144
2725
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -2175,12 +2756,12 @@ const Information = ({ activeTab }) => {
2175
2756
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2176
2757
  label: formatMessage({
2177
2758
  id: "content-manager.containers.edit.information.last-published.label",
2178
- defaultMessage: "Last published"
2759
+ defaultMessage: "Published"
2179
2760
  }),
2180
2761
  value: formatMessage(
2181
2762
  {
2182
2763
  id: "content-manager.containers.edit.information.last-published.value",
2183
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2764
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2184
2765
  },
2185
2766
  {
2186
2767
  time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2193,12 +2774,12 @@ const Information = ({ activeTab }) => {
2193
2774
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2194
2775
  label: formatMessage({
2195
2776
  id: "content-manager.containers.edit.information.last-draft.label",
2196
- defaultMessage: "Last draft"
2777
+ defaultMessage: "Updated"
2197
2778
  }),
2198
2779
  value: formatMessage(
2199
2780
  {
2200
2781
  id: "content-manager.containers.edit.information.last-draft.value",
2201
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2782
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2202
2783
  },
2203
2784
  {
2204
2785
  time: /* @__PURE__ */ jsx(
@@ -2216,12 +2797,12 @@ const Information = ({ activeTab }) => {
2216
2797
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2217
2798
  label: formatMessage({
2218
2799
  id: "content-manager.containers.edit.information.document.label",
2219
- defaultMessage: "Document"
2800
+ defaultMessage: "Created"
2220
2801
  }),
2221
2802
  value: formatMessage(
2222
2803
  {
2223
2804
  id: "content-manager.containers.edit.information.document.value",
2224
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2805
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2225
2806
  },
2226
2807
  {
2227
2808
  time: /* @__PURE__ */ jsx(
@@ -2259,25 +2840,77 @@ const Information = ({ activeTab }) => {
2259
2840
  );
2260
2841
  };
2261
2842
  const HeaderActions = ({ actions: actions2 }) => {
2262
- return /* @__PURE__ */ jsx(Flex, { children: actions2.map((action) => {
2263
- if ("options" in action) {
2843
+ const [dialogId, setDialogId] = React.useState(null);
2844
+ const handleClick = (action) => async (e) => {
2845
+ if (!("options" in action)) {
2846
+ const { onClick = () => false, dialog, id } = action;
2847
+ const muteDialog = await onClick(e);
2848
+ if (dialog && !muteDialog) {
2849
+ e.preventDefault();
2850
+ setDialogId(id);
2851
+ }
2852
+ }
2853
+ };
2854
+ const handleClose = () => {
2855
+ setDialogId(null);
2856
+ };
2857
+ return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
2858
+ if (action.options) {
2264
2859
  return /* @__PURE__ */ jsx(
2265
2860
  SingleSelect,
2266
2861
  {
2267
2862
  size: "S",
2268
- disabled: action.disabled,
2269
- "aria-label": action.label,
2270
2863
  onChange: action.onSelect,
2271
- value: action.value,
2864
+ "aria-label": action.label,
2865
+ ...action,
2272
2866
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
2273
2867
  },
2274
2868
  action.id
2275
2869
  );
2276
2870
  } else {
2277
- return null;
2871
+ if (action.type === "icon") {
2872
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
2873
+ /* @__PURE__ */ jsx(
2874
+ IconButton,
2875
+ {
2876
+ disabled: action.disabled,
2877
+ label: action.label,
2878
+ size: "S",
2879
+ onClick: handleClick(action),
2880
+ children: action.icon
2881
+ }
2882
+ ),
2883
+ action.dialog ? /* @__PURE__ */ jsx(
2884
+ HeaderActionDialog,
2885
+ {
2886
+ ...action.dialog,
2887
+ isOpen: dialogId === action.id,
2888
+ onClose: handleClose
2889
+ }
2890
+ ) : null
2891
+ ] }, action.id);
2892
+ }
2278
2893
  }
2279
2894
  }) });
2280
2895
  };
2896
+ const HeaderActionDialog = ({
2897
+ onClose,
2898
+ onCancel,
2899
+ title,
2900
+ content: Content,
2901
+ isOpen
2902
+ }) => {
2903
+ const handleClose = async () => {
2904
+ if (onCancel) {
2905
+ await onCancel();
2906
+ }
2907
+ onClose();
2908
+ };
2909
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2910
+ /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
2911
+ typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
2912
+ ] }) });
2913
+ };
2281
2914
  const ConfigureTheViewAction = ({ collectionType, model }) => {
2282
2915
  const navigate = useNavigate();
2283
2916
  const { formatMessage } = useIntl();
@@ -2294,6 +2927,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2294
2927
  };
2295
2928
  };
2296
2929
  ConfigureTheViewAction.type = "configure-the-view";
2930
+ ConfigureTheViewAction.position = "header";
2297
2931
  const EditTheModelAction = ({ model }) => {
2298
2932
  const navigate = useNavigate();
2299
2933
  const { formatMessage } = useIntl();
@@ -2310,6 +2944,7 @@ const EditTheModelAction = ({ model }) => {
2310
2944
  };
2311
2945
  };
2312
2946
  EditTheModelAction.type = "edit-the-model";
2947
+ EditTheModelAction.position = "header";
2313
2948
  const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2314
2949
  const navigate = useNavigate();
2315
2950
  const { formatMessage } = useIntl();
@@ -2318,12 +2953,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2318
2953
  const { delete: deleteAction } = useDocumentActions();
2319
2954
  const { toggleNotification } = useNotification();
2320
2955
  const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
2956
+ const isLocalized = document?.locale != null;
2321
2957
  return {
2322
2958
  disabled: !canDelete || !document,
2323
- label: formatMessage({
2324
- id: "content-manager.actions.delete.label",
2325
- defaultMessage: "Delete document"
2326
- }),
2959
+ label: formatMessage(
2960
+ {
2961
+ id: "content-manager.actions.delete.label",
2962
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2963
+ },
2964
+ { isLocalized }
2965
+ ),
2327
2966
  icon: /* @__PURE__ */ jsx(Trash, {}),
2328
2967
  dialog: {
2329
2968
  type: "dialog",
@@ -2379,403 +3018,102 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2379
3018
  };
2380
3019
  };
2381
3020
  DeleteAction$1.type = "delete";
3021
+ DeleteAction$1.position = ["header", "table-row"];
2382
3022
  const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2383
3023
  const Panels = () => {
2384
- const isCloning = useMatch(CLONE_PATH) !== null;
2385
- const [
2386
- {
2387
- query: { status }
2388
- }
2389
- ] = useQueryParams({
2390
- status: "draft"
2391
- });
2392
- const { model, id, document, meta, collectionType } = useDoc();
2393
- const plugins = useStrapiApp("Panels", (state) => state.plugins);
2394
- const props = {
2395
- activeTab: status,
2396
- model,
2397
- documentId: id,
2398
- document: isCloning ? void 0 : document,
2399
- meta: isCloning ? void 0 : meta,
2400
- collectionType
2401
- };
2402
- return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
2403
- DescriptionComponentRenderer,
2404
- {
2405
- props,
2406
- descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2407
- children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
2408
- }
2409
- ) });
2410
- };
2411
- const ActionsPanel = () => {
2412
- const { formatMessage } = useIntl();
2413
- return {
2414
- title: formatMessage({
2415
- id: "content-manager.containers.edit.panels.default.title",
2416
- defaultMessage: "Document"
2417
- }),
2418
- content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
2419
- };
2420
- };
2421
- ActionsPanel.type = "actions";
2422
- const ActionsPanelContent = () => {
2423
- const isCloning = useMatch(CLONE_PATH) !== null;
2424
- const [
2425
- {
2426
- query: { status = "draft" }
2427
- }
2428
- ] = useQueryParams();
2429
- const { model, id, document, meta, collectionType } = useDoc();
2430
- const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
2431
- const props = {
2432
- activeTab: status,
2433
- model,
2434
- documentId: id,
2435
- document: isCloning ? void 0 : document,
2436
- meta: isCloning ? void 0 : meta,
2437
- collectionType
2438
- };
2439
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
2440
- /* @__PURE__ */ jsx(
2441
- DescriptionComponentRenderer,
2442
- {
2443
- props,
2444
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2445
- children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
2446
- }
2447
- ),
2448
- /* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
2449
- ] });
2450
- };
2451
- const Panel = React.forwardRef(({ children, title }, ref) => {
2452
- return /* @__PURE__ */ jsxs(
2453
- Flex,
2454
- {
2455
- ref,
2456
- tag: "aside",
2457
- "aria-labelledby": "additional-information",
2458
- background: "neutral0",
2459
- borderColor: "neutral150",
2460
- hasRadius: true,
2461
- paddingBottom: 4,
2462
- paddingLeft: 4,
2463
- paddingRight: 4,
2464
- paddingTop: 4,
2465
- shadow: "tableShadow",
2466
- gap: 3,
2467
- direction: "column",
2468
- justifyContent: "stretch",
2469
- alignItems: "flex-start",
2470
- children: [
2471
- /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2472
- children
2473
- ]
2474
- }
2475
- );
2476
- });
2477
- const HOOKS = {
2478
- /**
2479
- * Hook that allows to mutate the displayed headers of the list view table
2480
- * @constant
2481
- * @type {string}
2482
- */
2483
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2484
- /**
2485
- * Hook that allows to mutate the CM's collection types links pre-set filters
2486
- * @constant
2487
- * @type {string}
2488
- */
2489
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2490
- /**
2491
- * Hook that allows to mutate the CM's edit view layout
2492
- * @constant
2493
- * @type {string}
2494
- */
2495
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2496
- /**
2497
- * Hook that allows to mutate the CM's single types links pre-set filters
2498
- * @constant
2499
- * @type {string}
2500
- */
2501
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2502
- };
2503
- const contentTypesApi = contentManagerApi.injectEndpoints({
2504
- endpoints: (builder) => ({
2505
- getContentTypeConfiguration: builder.query({
2506
- query: (uid) => ({
2507
- url: `/content-manager/content-types/${uid}/configuration`,
2508
- method: "GET"
2509
- }),
2510
- transformResponse: (response) => response.data,
2511
- providesTags: (_result, _error, uid) => [
2512
- { type: "ContentTypesConfiguration", id: uid },
2513
- { type: "ContentTypeSettings", id: "LIST" }
2514
- ]
2515
- }),
2516
- getAllContentTypeSettings: builder.query({
2517
- query: () => "/content-manager/content-types-settings",
2518
- transformResponse: (response) => response.data,
2519
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2520
- }),
2521
- updateContentTypeConfiguration: builder.mutation({
2522
- query: ({ uid, ...body }) => ({
2523
- url: `/content-manager/content-types/${uid}/configuration`,
2524
- method: "PUT",
2525
- data: body
2526
- }),
2527
- transformResponse: (response) => response.data,
2528
- invalidatesTags: (_result, _error, { uid }) => [
2529
- { type: "ContentTypesConfiguration", id: uid },
2530
- { type: "ContentTypeSettings", id: "LIST" },
2531
- // Is this necessary?
2532
- { type: "InitialData" }
2533
- ]
2534
- })
2535
- })
2536
- });
2537
- const {
2538
- useGetContentTypeConfigurationQuery,
2539
- useGetAllContentTypeSettingsQuery,
2540
- useUpdateContentTypeConfigurationMutation
2541
- } = contentTypesApi;
2542
- const checkIfAttributeIsDisplayable = (attribute) => {
2543
- const { type } = attribute;
2544
- if (type === "relation") {
2545
- return !attribute.relation.toLowerCase().includes("morph");
2546
- }
2547
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2548
- };
2549
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2550
- if (!mainFieldName) {
2551
- return void 0;
2552
- }
2553
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2554
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2555
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2556
- );
2557
- return {
2558
- name: mainFieldName,
2559
- type: mainFieldType ?? "string"
2560
- };
2561
- };
2562
- const DEFAULT_SETTINGS = {
2563
- bulkable: false,
2564
- filterable: false,
2565
- searchable: false,
2566
- pagination: false,
2567
- defaultSortBy: "",
2568
- defaultSortOrder: "asc",
2569
- mainField: "id",
2570
- pageSize: 10
2571
- };
2572
- const useDocumentLayout = (model) => {
2573
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2574
- const [{ query }] = useQueryParams();
2575
- const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2576
- const { toggleNotification } = useNotification();
2577
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
2578
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2579
- const {
2580
- data,
2581
- isLoading: isLoadingConfigs,
2582
- error,
2583
- isFetching: isFetchingConfigs
2584
- } = useGetContentTypeConfigurationQuery(model);
2585
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2586
- React.useEffect(() => {
2587
- if (error) {
2588
- toggleNotification({
2589
- type: "danger",
2590
- message: formatAPIError(error)
2591
- });
2592
- }
2593
- }, [error, formatAPIError, toggleNotification]);
2594
- const editLayout = React.useMemo(
2595
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2596
- layout: [],
2597
- components: {},
2598
- metadatas: {},
2599
- options: {},
2600
- settings: DEFAULT_SETTINGS
2601
- },
2602
- [data, isLoading, schemas, schema, components]
2603
- );
2604
- const listLayout = React.useMemo(() => {
2605
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2606
- layout: [],
2607
- metadatas: {},
2608
- options: {},
2609
- settings: DEFAULT_SETTINGS
2610
- };
2611
- }, [data, isLoading, schemas, schema, components]);
2612
- const { layout: edit } = React.useMemo(
2613
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2614
- layout: editLayout,
2615
- query
2616
- }),
2617
- [editLayout, query, runHookWaterfall]
2618
- );
2619
- return {
2620
- error,
2621
- isLoading,
2622
- edit,
2623
- list: listLayout
2624
- };
2625
- };
2626
- const useDocLayout = () => {
2627
- const { model } = useDoc();
2628
- return useDocumentLayout(model);
2629
- };
2630
- const formatEditLayout = (data, {
2631
- schemas,
2632
- schema,
2633
- components
2634
- }) => {
2635
- let currentPanelIndex = 0;
2636
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2637
- data.contentType.layouts.edit,
2638
- schema?.attributes,
2639
- data.contentType.metadatas,
2640
- { configurations: data.components, schemas: components },
2641
- schemas
2642
- ).reduce((panels, row) => {
2643
- if (row.some((field) => field.type === "dynamiczone")) {
2644
- panels.push([row]);
2645
- currentPanelIndex += 2;
2646
- } else {
2647
- if (!panels[currentPanelIndex]) {
2648
- panels.push([]);
2649
- }
2650
- panels[currentPanelIndex].push(row);
2651
- }
2652
- return panels;
2653
- }, []);
2654
- const componentEditAttributes = Object.entries(data.components).reduce(
2655
- (acc, [uid, configuration]) => {
2656
- acc[uid] = {
2657
- layout: convertEditLayoutToFieldLayouts(
2658
- configuration.layouts.edit,
2659
- components[uid].attributes,
2660
- configuration.metadatas
2661
- ),
2662
- settings: {
2663
- ...configuration.settings,
2664
- icon: components[uid].info.icon,
2665
- displayName: components[uid].info.displayName
2666
- }
2667
- };
2668
- return acc;
2669
- },
2670
- {}
2671
- );
2672
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2673
- (acc, [attribute, metadata]) => {
2674
- return {
2675
- ...acc,
2676
- [attribute]: metadata.edit
2677
- };
2678
- },
2679
- {}
2680
- );
2681
- return {
2682
- layout: panelledEditAttributes,
2683
- components: componentEditAttributes,
2684
- metadatas: editMetadatas,
2685
- settings: {
2686
- ...data.contentType.settings,
2687
- displayName: schema?.info.displayName
2688
- },
2689
- options: {
2690
- ...schema?.options,
2691
- ...schema?.pluginOptions,
2692
- ...data.contentType.options
3024
+ const isCloning = useMatch(CLONE_PATH) !== null;
3025
+ const [
3026
+ {
3027
+ query: { status }
2693
3028
  }
3029
+ ] = useQueryParams({
3030
+ status: "draft"
3031
+ });
3032
+ const { model, id, document, meta, collectionType } = useDoc();
3033
+ const plugins = useStrapiApp("Panels", (state) => state.plugins);
3034
+ const props = {
3035
+ activeTab: status,
3036
+ model,
3037
+ documentId: id,
3038
+ document: isCloning ? void 0 : document,
3039
+ meta: isCloning ? void 0 : meta,
3040
+ collectionType
2694
3041
  };
3042
+ return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
3043
+ DescriptionComponentRenderer,
3044
+ {
3045
+ props,
3046
+ descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
3047
+ children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
3048
+ }
3049
+ ) });
2695
3050
  };
2696
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2697
- return rows.map(
2698
- (row) => row.map((field) => {
2699
- const attribute = attributes[field.name];
2700
- if (!attribute) {
2701
- return null;
2702
- }
2703
- const { edit: metadata } = metadatas[field.name];
2704
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2705
- return {
2706
- attribute,
2707
- disabled: !metadata.editable,
2708
- hint: metadata.description,
2709
- label: metadata.label ?? "",
2710
- name: field.name,
2711
- // @ts-expect-error – mainField does exist on the metadata for a relation.
2712
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2713
- schemas,
2714
- components: components?.schemas ?? {}
2715
- }),
2716
- placeholder: metadata.placeholder ?? "",
2717
- required: attribute.required ?? false,
2718
- size: field.size,
2719
- unique: "unique" in attribute ? attribute.unique : false,
2720
- visible: metadata.visible ?? true,
2721
- type: attribute.type
2722
- };
2723
- }).filter((field) => field !== null)
2724
- );
2725
- };
2726
- const formatListLayout = (data, {
2727
- schemas,
2728
- schema,
2729
- components
2730
- }) => {
2731
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2732
- (acc, [attribute, metadata]) => {
2733
- return {
2734
- ...acc,
2735
- [attribute]: metadata.list
2736
- };
2737
- },
2738
- {}
2739
- );
2740
- const listAttributes = convertListLayoutToFieldLayouts(
2741
- data.contentType.layouts.list,
2742
- schema?.attributes,
2743
- listMetadatas,
2744
- { configurations: data.components, schemas: components },
2745
- schemas
2746
- );
3051
+ const ActionsPanel = () => {
3052
+ const { formatMessage } = useIntl();
2747
3053
  return {
2748
- layout: listAttributes,
2749
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2750
- metadatas: listMetadatas,
2751
- options: {
2752
- ...schema?.options,
2753
- ...schema?.pluginOptions,
2754
- ...data.contentType.options
2755
- }
3054
+ title: formatMessage({
3055
+ id: "content-manager.containers.edit.panels.default.title",
3056
+ defaultMessage: "Entry"
3057
+ }),
3058
+ content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
2756
3059
  };
2757
3060
  };
2758
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2759
- return columns.map((name) => {
2760
- const attribute = attributes[name];
2761
- if (!attribute) {
2762
- return null;
3061
+ ActionsPanel.type = "actions";
3062
+ const ActionsPanelContent = () => {
3063
+ const isCloning = useMatch(CLONE_PATH) !== null;
3064
+ const [
3065
+ {
3066
+ query: { status = "draft" }
2763
3067
  }
2764
- const metadata = metadatas[name];
2765
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2766
- return {
2767
- attribute,
2768
- label: metadata.label ?? "",
2769
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2770
- schemas,
2771
- components: components?.schemas ?? {}
2772
- }),
2773
- name,
2774
- searchable: metadata.searchable ?? true,
2775
- sortable: metadata.sortable ?? true
2776
- };
2777
- }).filter((field) => field !== null);
3068
+ ] = useQueryParams();
3069
+ const { model, id, document, meta, collectionType } = useDoc();
3070
+ const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
3071
+ const props = {
3072
+ activeTab: status,
3073
+ model,
3074
+ documentId: id,
3075
+ document: isCloning ? void 0 : document,
3076
+ meta: isCloning ? void 0 : meta,
3077
+ collectionType
3078
+ };
3079
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
3080
+ /* @__PURE__ */ jsx(
3081
+ DescriptionComponentRenderer,
3082
+ {
3083
+ props,
3084
+ descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
3085
+ children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
3086
+ }
3087
+ ),
3088
+ /* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
3089
+ ] });
2778
3090
  };
3091
+ const Panel = React.forwardRef(({ children, title }, ref) => {
3092
+ return /* @__PURE__ */ jsxs(
3093
+ Flex,
3094
+ {
3095
+ ref,
3096
+ tag: "aside",
3097
+ "aria-labelledby": "additional-information",
3098
+ background: "neutral0",
3099
+ borderColor: "neutral150",
3100
+ hasRadius: true,
3101
+ paddingBottom: 4,
3102
+ paddingLeft: 4,
3103
+ paddingRight: 4,
3104
+ paddingTop: 4,
3105
+ shadow: "tableShadow",
3106
+ gap: 3,
3107
+ direction: "column",
3108
+ justifyContent: "stretch",
3109
+ alignItems: "flex-start",
3110
+ children: [
3111
+ /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
3112
+ children
3113
+ ]
3114
+ }
3115
+ );
3116
+ });
2779
3117
  const ConfirmBulkActionDialog = ({
2780
3118
  onToggleDialog,
2781
3119
  isOpen = false,
@@ -2783,7 +3121,7 @@ const ConfirmBulkActionDialog = ({
2783
3121
  endAction
2784
3122
  }) => {
2785
3123
  const { formatMessage } = useIntl();
2786
- return /* @__PURE__ */ jsx(Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
3124
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2787
3125
  /* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
2788
3126
  id: "app.components.ConfirmDialog.title",
2789
3127
  defaultMessage: "Confirmation"
@@ -2814,6 +3152,7 @@ const ConfirmDialogPublishAll = ({
2814
3152
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
2815
3153
  const { model, schema } = useDoc();
2816
3154
  const [{ query }] = useQueryParams();
3155
+ const enableDraftRelationsCount = false;
2817
3156
  const {
2818
3157
  data: countDraftRelations = 0,
2819
3158
  isLoading,
@@ -2825,7 +3164,7 @@ const ConfirmDialogPublishAll = ({
2825
3164
  locale: query?.plugins?.i18n?.locale
2826
3165
  },
2827
3166
  {
2828
- skip: selectedEntries.length === 0
3167
+ skip: !enableDraftRelationsCount
2829
3168
  }
2830
3169
  );
2831
3170
  React.useEffect(() => {
@@ -3010,7 +3349,7 @@ const SelectedEntriesTableContent = ({
3010
3349
  status: row.status
3011
3350
  }
3012
3351
  ) }),
3013
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
3352
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
3014
3353
  IconButton,
3015
3354
  {
3016
3355
  tag: Link,
@@ -3019,23 +3358,16 @@ const SelectedEntriesTableContent = ({
3019
3358
  search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3020
3359
  },
3021
3360
  state: { from: pathname },
3022
- label: formatMessage(
3023
- { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3024
- {
3025
- target: formatMessage(
3026
- {
3027
- id: "content-manager.components.ListViewHelperPluginTable.row-line",
3028
- defaultMessage: "item line {number}"
3029
- },
3030
- { number: index2 + 1 }
3031
- )
3032
- }
3033
- ),
3361
+ label: formatMessage({
3362
+ id: "content-manager.bulk-publish.edit",
3363
+ defaultMessage: "Edit"
3364
+ }),
3034
3365
  target: "_blank",
3035
3366
  marginLeft: "auto",
3036
- children: /* @__PURE__ */ jsx(Pencil, {})
3367
+ variant: "ghost",
3368
+ children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
3037
3369
  }
3038
- ) })
3370
+ ) }) })
3039
3371
  ] }, row.id)) })
3040
3372
  ] });
3041
3373
  };
@@ -3072,7 +3404,13 @@ const SelectedEntriesModalContent = ({
3072
3404
  );
3073
3405
  const { rows, validationErrors } = React.useMemo(() => {
3074
3406
  if (data.length > 0 && schema) {
3075
- const validate = createYupSchema(schema.attributes, components);
3407
+ const validate = createYupSchema(
3408
+ schema.attributes,
3409
+ components,
3410
+ // Since this is the "Publish" action, the validation
3411
+ // schema must enforce the rules for published entities
3412
+ { status: "published" }
3413
+ );
3076
3414
  const validationErrors2 = {};
3077
3415
  const rows2 = data.map((entry) => {
3078
3416
  try {
@@ -3197,8 +3535,7 @@ const PublishAction = ({ documents, model }) => {
3197
3535
  const refetchList = () => {
3198
3536
  contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3199
3537
  };
3200
- if (!showPublishButton)
3201
- return null;
3538
+ if (!showPublishButton) return null;
3202
3539
  return {
3203
3540
  actionType: "publish",
3204
3541
  variant: "tertiary",
@@ -3266,8 +3603,7 @@ const DeleteAction = ({ documents, model }) => {
3266
3603
  selectRow([]);
3267
3604
  }
3268
3605
  };
3269
- if (!hasDeletePermission)
3270
- return null;
3606
+ if (!hasDeletePermission) return null;
3271
3607
  return {
3272
3608
  variant: "danger-light",
3273
3609
  label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
@@ -3316,8 +3652,7 @@ const UnpublishAction = ({ documents, model }) => {
3316
3652
  }
3317
3653
  };
3318
3654
  const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3319
- if (!showUnpublishButton)
3320
- return null;
3655
+ if (!showUnpublishButton) return null;
3321
3656
  return {
3322
3657
  variant: "tertiary",
3323
3658
  label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
@@ -3422,7 +3757,7 @@ const TableActions = ({ document }) => {
3422
3757
  DescriptionComponentRenderer,
3423
3758
  {
3424
3759
  props,
3425
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3760
+ descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
3426
3761
  children: (actions2) => {
3427
3762
  const tableRowActions = actions2.filter((action) => {
3428
3763
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3481,6 +3816,7 @@ const EditAction = ({ documentId }) => {
3481
3816
  };
3482
3817
  };
3483
3818
  EditAction.type = "edit";
3819
+ EditAction.position = "table-row";
3484
3820
  const StyledPencil = styled(Pencil)`
3485
3821
  path {
3486
3822
  fill: currentColor;
@@ -3533,7 +3869,7 @@ const CloneAction = ({ model, documentId }) => {
3533
3869
  }),
3534
3870
  content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3535
3871
  footer: ({ onClose }) => {
3536
- return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
3872
+ return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
3537
3873
  /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3538
3874
  id: "cancel",
3539
3875
  defaultMessage: "Cancel"
@@ -3557,6 +3893,7 @@ const CloneAction = ({ model, documentId }) => {
3557
3893
  };
3558
3894
  };
3559
3895
  CloneAction.type = "clone";
3896
+ CloneAction.position = "table-row";
3560
3897
  const StyledDuplicate = styled(Duplicate)`
3561
3898
  path {
3562
3899
  fill: currentColor;
@@ -3574,8 +3911,7 @@ class ContentManagerPlugin {
3574
3911
  documentActions = [
3575
3912
  ...DEFAULT_ACTIONS,
3576
3913
  ...DEFAULT_TABLE_ROW_ACTIONS,
3577
- ...DEFAULT_HEADER_ACTIONS,
3578
- HistoryAction
3914
+ ...DEFAULT_HEADER_ACTIONS
3579
3915
  ];
3580
3916
  editViewSidePanels = [ActionsPanel];
3581
3917
  headerActions = [];
@@ -3644,7 +3980,14 @@ class ContentManagerPlugin {
3644
3980
  addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3645
3981
  addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3646
3982
  getBulkActions: () => this.bulkActions,
3647
- getDocumentActions: () => this.documentActions,
3983
+ getDocumentActions: (position) => {
3984
+ if (position) {
3985
+ return this.documentActions.filter(
3986
+ (action) => action.position == void 0 || [action.position].flat().includes(position)
3987
+ );
3988
+ }
3989
+ return this.documentActions;
3990
+ },
3648
3991
  getEditViewSidePanels: () => this.editViewSidePanels,
3649
3992
  getHeaderActions: () => this.headerActions
3650
3993
  }
@@ -3654,16 +3997,71 @@ class ContentManagerPlugin {
3654
3997
  const getPrintableType = (value) => {
3655
3998
  const nativeType = typeof value;
3656
3999
  if (nativeType === "object") {
3657
- if (value === null)
3658
- return "null";
3659
- if (Array.isArray(value))
3660
- return "array";
4000
+ if (value === null) return "null";
4001
+ if (Array.isArray(value)) return "array";
3661
4002
  if (value instanceof Object && value.constructor.name !== "Object") {
3662
4003
  return value.constructor.name;
3663
4004
  }
3664
4005
  }
3665
4006
  return nativeType;
3666
4007
  };
4008
+ const HistoryAction = ({ model, document }) => {
4009
+ const { formatMessage } = useIntl();
4010
+ const [{ query }] = useQueryParams();
4011
+ const navigate = useNavigate();
4012
+ const { trackUsage } = useTracking();
4013
+ const { pathname } = useLocation();
4014
+ const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
4015
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
4016
+ return null;
4017
+ }
4018
+ const handleOnClick = () => {
4019
+ const destination = { pathname: "history", search: pluginsQueryParams };
4020
+ trackUsage("willNavigate", {
4021
+ from: pathname,
4022
+ to: `${pathname}/${destination.pathname}`
4023
+ });
4024
+ navigate(destination);
4025
+ };
4026
+ return {
4027
+ icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
4028
+ label: formatMessage({
4029
+ id: "content-manager.history.document-action",
4030
+ defaultMessage: "Content History"
4031
+ }),
4032
+ onClick: handleOnClick,
4033
+ disabled: (
4034
+ /**
4035
+ * The user is creating a new document.
4036
+ * It hasn't been saved yet, so there's no history to go to
4037
+ */
4038
+ !document || /**
4039
+ * The document has been created but the current dimension has never been saved.
4040
+ * For example, the user is creating a new locale in an existing document,
4041
+ * so there's no history for the document in that locale
4042
+ */
4043
+ !document.id || /**
4044
+ * History is only available for content types created by the user.
4045
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
4046
+ * which start with `admin::` or `plugin::`
4047
+ */
4048
+ !model.startsWith("api::")
4049
+ ),
4050
+ position: "header"
4051
+ };
4052
+ };
4053
+ HistoryAction.type = "history";
4054
+ HistoryAction.position = "header";
4055
+ const historyAdmin = {
4056
+ bootstrap(app) {
4057
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
4058
+ addDocumentAction((actions2) => {
4059
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
4060
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
4061
+ return actions2;
4062
+ });
4063
+ }
4064
+ };
3667
4065
  const initialState = {
3668
4066
  collectionTypeLinks: [],
3669
4067
  components: [],
@@ -3700,6 +4098,88 @@ const { setInitialData } = actions;
3700
4098
  const reducer = combineReducers({
3701
4099
  app: reducer$1
3702
4100
  });
4101
+ const previewApi = contentManagerApi.injectEndpoints({
4102
+ endpoints: (builder) => ({
4103
+ getPreviewUrl: builder.query({
4104
+ query({ query, params }) {
4105
+ return {
4106
+ url: `/content-manager/preview/url/${params.contentType}`,
4107
+ method: "GET",
4108
+ config: {
4109
+ params: query
4110
+ }
4111
+ };
4112
+ }
4113
+ })
4114
+ })
4115
+ });
4116
+ const { useGetPreviewUrlQuery } = previewApi;
4117
+ const ConditionalTooltip = ({ isShown, label, children }) => {
4118
+ if (isShown) {
4119
+ return /* @__PURE__ */ jsx(Tooltip, { label, children });
4120
+ }
4121
+ return children;
4122
+ };
4123
+ const PreviewSidePanel = ({ model, documentId, document }) => {
4124
+ const { formatMessage } = useIntl();
4125
+ const { trackUsage } = useTracking();
4126
+ const { pathname } = useLocation();
4127
+ const [{ query }] = useQueryParams();
4128
+ const isModified = useForm("PreviewSidePanel", (state) => state.modified);
4129
+ const { data, error } = useGetPreviewUrlQuery({
4130
+ params: {
4131
+ contentType: model
4132
+ },
4133
+ query: {
4134
+ documentId,
4135
+ locale: document?.locale,
4136
+ status: document?.status
4137
+ }
4138
+ });
4139
+ if (!data?.data?.url || error) {
4140
+ return null;
4141
+ }
4142
+ const trackNavigation = () => {
4143
+ const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
4144
+ trackUsage("willNavigate", { from: pathname, to: destinationPathname });
4145
+ };
4146
+ return {
4147
+ title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
4148
+ content: /* @__PURE__ */ jsx(
4149
+ ConditionalTooltip,
4150
+ {
4151
+ label: formatMessage({
4152
+ id: "content-manager.preview.panel.button-disabled-tooltip",
4153
+ defaultMessage: "Please save to open the preview"
4154
+ }),
4155
+ isShown: isModified,
4156
+ children: /* @__PURE__ */ jsx(Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsx(
4157
+ Button,
4158
+ {
4159
+ variant: "tertiary",
4160
+ tag: Link,
4161
+ to: { pathname: "preview", search: stringify(query, { encode: false }) },
4162
+ onClick: trackNavigation,
4163
+ width: "100%",
4164
+ disabled: isModified,
4165
+ pointerEvents: isModified ? "none" : void 0,
4166
+ tabIndex: isModified ? -1 : void 0,
4167
+ children: formatMessage({
4168
+ id: "content-manager.preview.panel.button",
4169
+ defaultMessage: "Open preview"
4170
+ })
4171
+ }
4172
+ ) })
4173
+ }
4174
+ )
4175
+ };
4176
+ };
4177
+ const previewAdmin = {
4178
+ bootstrap(app) {
4179
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
4180
+ contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
4181
+ }
4182
+ };
3703
4183
  const index = {
3704
4184
  register(app) {
3705
4185
  const cm = new ContentManagerPlugin();
@@ -3719,7 +4199,7 @@ const index = {
3719
4199
  app.router.addRoute({
3720
4200
  path: "content-manager/*",
3721
4201
  lazy: async () => {
3722
- const { Layout } = await import("./layout-Bx7svTbY.mjs");
4202
+ const { Layout } = await import("./layout-COzAvgJh.mjs");
3723
4203
  return {
3724
4204
  Component: Layout
3725
4205
  };
@@ -3728,10 +4208,18 @@ const index = {
3728
4208
  });
3729
4209
  app.registerPlugin(cm.config);
3730
4210
  },
4211
+ bootstrap(app) {
4212
+ if (typeof historyAdmin.bootstrap === "function") {
4213
+ historyAdmin.bootstrap(app);
4214
+ }
4215
+ if (typeof previewAdmin.bootstrap === "function") {
4216
+ previewAdmin.bootstrap(app);
4217
+ }
4218
+ },
3731
4219
  async registerTrads({ locales }) {
3732
4220
  const importedTrads = await Promise.all(
3733
4221
  locales.map((locale) => {
3734
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-Ux26r5pl.mjs"), "./translations/es.json": () => import("./es-CeXiYflN.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr-CD9VFbPM.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-CtsUxOvk.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
4222
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-CSxLmrh1.mjs"), "./translations/es.json": () => import("./es-D34tqjMw.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr--pg5jUbt.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-BHqhDq4V.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`, 3).then(({ default: data }) => {
3735
4223
  return {
3736
4224
  data: prefixPluginTranslations(data, PLUGIN_ID),
3737
4225
  locale
@@ -3752,13 +4240,16 @@ export {
3752
4240
  BulkActionsRenderer as B,
3753
4241
  COLLECTION_TYPES as C,
3754
4242
  DocumentStatus as D,
3755
- DEFAULT_SETTINGS as E,
3756
- convertEditLayoutToFieldLayouts as F,
3757
- useDocument as G,
4243
+ extractContentTypeComponents as E,
4244
+ DEFAULT_SETTINGS as F,
4245
+ convertEditLayoutToFieldLayouts as G,
3758
4246
  HOOKS as H,
3759
4247
  InjectionZone as I,
3760
- index as J,
3761
- useDocumentActions as K,
4248
+ useDocument as J,
4249
+ useGetPreviewUrlQuery as K,
4250
+ index as L,
4251
+ useContentManagerContext as M,
4252
+ useDocumentActions as N,
3762
4253
  Panels as P,
3763
4254
  RelativeTime as R,
3764
4255
  SINGLE_TYPES as S,
@@ -3776,18 +4267,18 @@ export {
3776
4267
  PERMISSIONS as k,
3777
4268
  DocumentRBAC as l,
3778
4269
  DOCUMENT_META_FIELDS as m,
3779
- useDocLayout as n,
3780
- useGetContentTypeConfigurationQuery as o,
3781
- CREATOR_FIELDS as p,
3782
- getMainField as q,
3783
- getDisplayName as r,
4270
+ CLONE_PATH as n,
4271
+ useDocLayout as o,
4272
+ useGetContentTypeConfigurationQuery as p,
4273
+ CREATOR_FIELDS as q,
4274
+ getMainField as r,
3784
4275
  setInitialData as s,
3785
- checkIfAttributeIsDisplayable as t,
4276
+ getDisplayName as t,
3786
4277
  useContentTypeSchema as u,
3787
- useGetAllDocumentsQuery as v,
3788
- convertListLayoutToFieldLayouts as w,
3789
- capitalise as x,
3790
- useUpdateContentTypeConfigurationMutation as y,
3791
- extractContentTypeComponents as z
4278
+ checkIfAttributeIsDisplayable as v,
4279
+ useGetAllDocumentsQuery as w,
4280
+ convertListLayoutToFieldLayouts as x,
4281
+ capitalise as y,
4282
+ useUpdateContentTypeConfigurationMutation as z
3792
4283
  };
3793
- //# sourceMappingURL=index-CaE6NG4a.mjs.map
4284
+ //# sourceMappingURL=index-Bu_-B7ZA.mjs.map