@strapi/content-manager 0.0.0-experimental.17b4116f461a49b8ce5386f7c8d79c511d40fb3b → 0.0.0-experimental.1fc4b627b49f713b07ed9f7f2b37741dcf8cf736

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 (214) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
  3. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
  4. package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
  5. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
  6. package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs → ComponentConfigurationPage-CIjXcRAB.mjs} +4 -4
  7. package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs.map → ComponentConfigurationPage-CIjXcRAB.mjs.map} +1 -1
  8. package/dist/_chunks/{ComponentConfigurationPage-2iOVVhqV.js → ComponentConfigurationPage-gsCd80MU.js} +4 -4
  9. package/dist/_chunks/{ComponentConfigurationPage-2iOVVhqV.js.map → ComponentConfigurationPage-gsCd80MU.js.map} +1 -1
  10. package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-BXdiCGQp.js} +8 -2
  11. package/dist/_chunks/ComponentIcon-BXdiCGQp.js.map +1 -0
  12. package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
  13. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
  14. package/dist/_chunks/{EditConfigurationPage-BoBb-DLH.mjs → EditConfigurationPage-BglmD_BF.mjs} +4 -4
  15. package/dist/_chunks/{EditConfigurationPage-BoBb-DLH.mjs.map → EditConfigurationPage-BglmD_BF.mjs.map} +1 -1
  16. package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js → EditConfigurationPage-DHDQKBzw.js} +4 -4
  17. package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js.map → EditConfigurationPage-DHDQKBzw.js.map} +1 -1
  18. package/dist/_chunks/{EditViewPage-KRG56aCq.js → EditViewPage-C4iTxUPU.js} +69 -50
  19. package/dist/_chunks/EditViewPage-C4iTxUPU.js.map +1 -0
  20. package/dist/_chunks/{EditViewPage-aUnqL-63.mjs → EditViewPage-CiwVPMaK.mjs} +70 -49
  21. package/dist/_chunks/EditViewPage-CiwVPMaK.mjs.map +1 -0
  22. package/dist/_chunks/{Field-kVFO4ZKB.mjs → Field-DIjL1b5d.mjs} +1046 -802
  23. package/dist/_chunks/Field-DIjL1b5d.mjs.map +1 -0
  24. package/dist/_chunks/{Field-kq1c2TF1.js → Field-DhXEK8y1.js} +1092 -849
  25. package/dist/_chunks/Field-DhXEK8y1.js.map +1 -0
  26. package/dist/_chunks/{Form-Jgh5hGTu.mjs → Form-CmNesrvR.mjs} +66 -45
  27. package/dist/_chunks/Form-CmNesrvR.mjs.map +1 -0
  28. package/dist/_chunks/{Form-CQ67ZifP.js → Form-CwmJ4sWe.js} +66 -46
  29. package/dist/_chunks/Form-CwmJ4sWe.js.map +1 -0
  30. package/dist/_chunks/{History-BLEnudTX.js → History-BLCCNgCt.js} +164 -54
  31. package/dist/_chunks/History-BLCCNgCt.js.map +1 -0
  32. package/dist/_chunks/{History-DKhZAPcK.mjs → History-D-99Wh30.mjs} +163 -52
  33. package/dist/_chunks/History-D-99Wh30.mjs.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-Zso_LUjn.js → ListConfigurationPage-DxWpeZrO.js} +68 -59
  35. package/dist/_chunks/ListConfigurationPage-DxWpeZrO.js.map +1 -0
  36. package/dist/_chunks/{ListConfigurationPage-nrXcxNYi.mjs → ListConfigurationPage-JPWZz7Kg.mjs} +64 -54
  37. package/dist/_chunks/ListConfigurationPage-JPWZz7Kg.mjs.map +1 -0
  38. package/dist/_chunks/{ListViewPage-DsaOakWQ.js → ListViewPage-CIQekSFz.js} +143 -139
  39. package/dist/_chunks/ListViewPage-CIQekSFz.js.map +1 -0
  40. package/dist/_chunks/{ListViewPage-ChhYmA-L.mjs → ListViewPage-DSK3f0ST.mjs} +140 -136
  41. package/dist/_chunks/ListViewPage-DSK3f0ST.mjs.map +1 -0
  42. package/dist/_chunks/{NoContentTypePage-DPCuS9Y1.js → NoContentTypePage-C5cxKvC2.js} +3 -3
  43. package/dist/_chunks/NoContentTypePage-C5cxKvC2.js.map +1 -0
  44. package/dist/_chunks/{NoContentTypePage-BrdFcN33.mjs → NoContentTypePage-D99LU1YP.mjs} +3 -3
  45. package/dist/_chunks/NoContentTypePage-D99LU1YP.mjs.map +1 -0
  46. package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs → NoPermissionsPage-DBrBw-0y.mjs} +2 -2
  47. package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs.map → NoPermissionsPage-DBrBw-0y.mjs.map} +1 -1
  48. package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js → NoPermissionsPage-Oy4tmUrW.js} +2 -2
  49. package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js.map → NoPermissionsPage-Oy4tmUrW.js.map} +1 -1
  50. package/dist/_chunks/{Relations-DjFiYd7-.mjs → Relations-BBmhcWFV.mjs} +132 -89
  51. package/dist/_chunks/Relations-BBmhcWFV.mjs.map +1 -0
  52. package/dist/_chunks/{Relations-CY8Isqdu.js → Relations-eG-9p_qS.js} +135 -93
  53. package/dist/_chunks/Relations-eG-9p_qS.js.map +1 -0
  54. package/dist/_chunks/{en-C-V1_90f.js → en-Bm0D0IWz.js} +23 -15
  55. package/dist/_chunks/{en-C-V1_90f.js.map → en-Bm0D0IWz.js.map} +1 -1
  56. package/dist/_chunks/{en-MBPul9Su.mjs → en-DKV44jRb.mjs} +23 -15
  57. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-DKV44jRb.mjs.map} +1 -1
  58. package/dist/_chunks/{index-DNa1J4HE.js → index-BIWDoFLK.js} +1877 -939
  59. package/dist/_chunks/index-BIWDoFLK.js.map +1 -0
  60. package/dist/_chunks/{index-CAc9yTnx.mjs → index-BrUzbQ30.mjs} +1902 -964
  61. package/dist/_chunks/index-BrUzbQ30.mjs.map +1 -0
  62. package/dist/_chunks/{layout-CXsHbc3E.mjs → layout-_5-cXs34.mjs} +45 -27
  63. package/dist/_chunks/layout-_5-cXs34.mjs.map +1 -0
  64. package/dist/_chunks/{layout-BqtLA6Lb.js → layout-lMc9i1-Z.js} +45 -29
  65. package/dist/_chunks/layout-lMc9i1-Z.js.map +1 -0
  66. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  67. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  68. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  69. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  70. package/dist/_chunks/{relations-BHY_KDJ_.js → relations-BRHithi8.js} +3 -7
  71. package/dist/_chunks/relations-BRHithi8.js.map +1 -0
  72. package/dist/_chunks/{relations-mMFEcZRq.mjs → relations-B_VLk-DD.mjs} +3 -7
  73. package/dist/_chunks/relations-B_VLk-DD.mjs.map +1 -0
  74. package/dist/_chunks/useDebounce-CtcjDB3L.js +28 -0
  75. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  76. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  77. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  78. package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
  79. package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
  80. package/dist/admin/index.js +3 -1
  81. package/dist/admin/index.js.map +1 -1
  82. package/dist/admin/index.mjs +9 -7
  83. package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
  84. package/dist/admin/src/content-manager.d.ts +3 -3
  85. package/dist/admin/src/exports.d.ts +2 -1
  86. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
  87. package/dist/admin/src/history/index.d.ts +3 -0
  88. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  89. package/dist/admin/src/hooks/useDocument.d.ts +37 -9
  90. package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
  91. package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
  92. package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
  93. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
  94. package/dist/admin/src/index.d.ts +1 -0
  95. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +11 -4
  96. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
  97. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  98. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
  99. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  100. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  101. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +30 -18
  102. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  103. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  104. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  105. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  106. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +16 -53
  107. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  108. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  109. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  110. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  111. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  112. package/dist/admin/src/preview/constants.d.ts +1 -0
  113. package/dist/admin/src/preview/index.d.ts +4 -0
  114. package/dist/admin/src/services/api.d.ts +2 -3
  115. package/dist/admin/src/services/components.d.ts +2 -2
  116. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  117. package/dist/admin/src/services/documents.d.ts +31 -17
  118. package/dist/admin/src/services/init.d.ts +2 -2
  119. package/dist/admin/src/services/relations.d.ts +3 -3
  120. package/dist/admin/src/services/uid.d.ts +3 -3
  121. package/dist/admin/src/utils/api.d.ts +4 -18
  122. package/dist/admin/src/utils/validation.d.ts +5 -7
  123. package/dist/server/index.js +571 -312
  124. package/dist/server/index.js.map +1 -1
  125. package/dist/server/index.mjs +573 -314
  126. package/dist/server/index.mjs.map +1 -1
  127. package/dist/server/src/bootstrap.d.ts.map +1 -1
  128. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  129. package/dist/server/src/controllers/index.d.ts.map +1 -1
  130. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  131. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  132. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  133. package/dist/server/src/controllers/utils/metadata.d.ts +22 -0
  134. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  135. package/dist/server/src/controllers/validation/dimensions.d.ts +11 -0
  136. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  137. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  138. package/dist/server/src/history/services/history.d.ts.map +1 -1
  139. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  140. package/dist/server/src/history/services/utils.d.ts +2 -1
  141. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  142. package/dist/server/src/index.d.ts +20 -36
  143. package/dist/server/src/index.d.ts.map +1 -1
  144. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  145. package/dist/server/src/preview/constants.d.ts +2 -0
  146. package/dist/server/src/preview/constants.d.ts.map +1 -0
  147. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  148. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  149. package/dist/server/src/preview/controllers/preview.d.ts +9 -0
  150. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  151. package/dist/server/src/preview/index.d.ts +4 -0
  152. package/dist/server/src/preview/index.d.ts.map +1 -0
  153. package/dist/server/src/preview/routes/index.d.ts +8 -0
  154. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  155. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  156. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  157. package/dist/server/src/preview/services/index.d.ts +4 -0
  158. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  159. package/dist/server/src/preview/services/preview.d.ts +6 -0
  160. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  161. package/dist/server/src/preview/utils.d.ts +7 -0
  162. package/dist/server/src/preview/utils.d.ts.map +1 -0
  163. package/dist/server/src/routes/index.d.ts.map +1 -1
  164. package/dist/server/src/services/document-manager.d.ts +11 -6
  165. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  166. package/dist/server/src/services/document-metadata.d.ts +14 -35
  167. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  168. package/dist/server/src/services/index.d.ts +20 -36
  169. package/dist/server/src/services/index.d.ts.map +1 -1
  170. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  171. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  172. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  173. package/dist/server/src/services/utils/populate.d.ts +8 -1
  174. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  175. package/dist/server/src/utils/index.d.ts +2 -0
  176. package/dist/server/src/utils/index.d.ts.map +1 -1
  177. package/dist/shared/contracts/collection-types.d.ts +17 -7
  178. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  179. package/dist/shared/contracts/relations.d.ts +2 -2
  180. package/dist/shared/contracts/relations.d.ts.map +1 -1
  181. package/package.json +17 -18
  182. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  183. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  184. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  185. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  186. package/dist/_chunks/EditViewPage-KRG56aCq.js.map +0 -1
  187. package/dist/_chunks/EditViewPage-aUnqL-63.mjs.map +0 -1
  188. package/dist/_chunks/Field-kVFO4ZKB.mjs.map +0 -1
  189. package/dist/_chunks/Field-kq1c2TF1.js.map +0 -1
  190. package/dist/_chunks/Form-CQ67ZifP.js.map +0 -1
  191. package/dist/_chunks/Form-Jgh5hGTu.mjs.map +0 -1
  192. package/dist/_chunks/History-BLEnudTX.js.map +0 -1
  193. package/dist/_chunks/History-DKhZAPcK.mjs.map +0 -1
  194. package/dist/_chunks/ListConfigurationPage-Zso_LUjn.js.map +0 -1
  195. package/dist/_chunks/ListConfigurationPage-nrXcxNYi.mjs.map +0 -1
  196. package/dist/_chunks/ListViewPage-ChhYmA-L.mjs.map +0 -1
  197. package/dist/_chunks/ListViewPage-DsaOakWQ.js.map +0 -1
  198. package/dist/_chunks/NoContentTypePage-BrdFcN33.mjs.map +0 -1
  199. package/dist/_chunks/NoContentTypePage-DPCuS9Y1.js.map +0 -1
  200. package/dist/_chunks/Relations-CY8Isqdu.js.map +0 -1
  201. package/dist/_chunks/Relations-DjFiYd7-.mjs.map +0 -1
  202. package/dist/_chunks/index-CAc9yTnx.mjs.map +0 -1
  203. package/dist/_chunks/index-DNa1J4HE.js.map +0 -1
  204. package/dist/_chunks/layout-BqtLA6Lb.js.map +0 -1
  205. package/dist/_chunks/layout-CXsHbc3E.mjs.map +0 -1
  206. package/dist/_chunks/relations-BHY_KDJ_.js.map +0 -1
  207. package/dist/_chunks/relations-mMFEcZRq.mjs.map +0 -1
  208. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  209. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  210. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  211. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  212. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  213. package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
  214. package/strapi-server.js +0 -3
@@ -2,17 +2,16 @@
2
2
  const Icons = require("@strapi/icons");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const strapiAdmin = require("@strapi/admin/strapi-admin");
5
- const qs = require("qs");
6
- const reactIntl = require("react-intl");
7
- const reactRouterDom = require("react-router-dom");
8
5
  const React = require("react");
9
6
  const designSystem = require("@strapi/design-system");
10
- const styled = require("styled-components");
7
+ const mapValues = require("lodash/fp/mapValues");
8
+ const reactIntl = require("react-intl");
9
+ const reactRouterDom = require("react-router-dom");
11
10
  const yup = require("yup");
12
- const react = require("@reduxjs/toolkit/query/react");
13
- const axios = require("axios");
14
11
  const pipe = require("lodash/fp/pipe");
15
12
  const dateFns = require("date-fns");
13
+ const styledComponents = require("styled-components");
14
+ const qs = require("qs");
16
15
  const toolkit = require("@reduxjs/toolkit");
17
16
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
18
17
  function _interopNamespace(e) {
@@ -34,7 +33,7 @@ function _interopNamespace(e) {
34
33
  return Object.freeze(n);
35
34
  }
36
35
  const React__namespace = /* @__PURE__ */ _interopNamespace(React);
37
- const styled__default = /* @__PURE__ */ _interopDefault(styled);
36
+ const mapValues__default = /* @__PURE__ */ _interopDefault(mapValues);
38
37
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
39
38
  const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
40
39
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
@@ -73,42 +72,6 @@ const useInjectionZone = (area) => {
73
72
  const [page, position] = area.split(".");
74
73
  return contentManagerPlugin.getInjectedComponents(page, position);
75
74
  };
76
- const HistoryAction = ({ model, document }) => {
77
- const { formatMessage } = reactIntl.useIntl();
78
- const [{ query }] = strapiAdmin.useQueryParams();
79
- const navigate = reactRouterDom.useNavigate();
80
- const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
81
- if (!window.strapi.features.isEnabled("cms-content-history")) {
82
- return null;
83
- }
84
- return {
85
- icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
86
- label: formatMessage({
87
- id: "content-manager.history.document-action",
88
- defaultMessage: "Content History"
89
- }),
90
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
91
- disabled: (
92
- /**
93
- * The user is creating a new document.
94
- * It hasn't been saved yet, so there's no history to go to
95
- */
96
- !document || /**
97
- * The document has been created but the current dimension has never been saved.
98
- * For example, the user is creating a new locale in an existing document,
99
- * so there's no history for the document in that locale
100
- */
101
- !document.id || /**
102
- * History is only available for content types created by the user.
103
- * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
104
- * which start with `admin::` or `plugin::`
105
- */
106
- !model.startsWith("api::")
107
- ),
108
- position: "header"
109
- };
110
- };
111
- HistoryAction.type = "history";
112
75
  const ID = "id";
113
76
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
114
77
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -160,6 +123,7 @@ const DocumentRBAC = ({ children, permissions }) => {
160
123
  if (!slug) {
161
124
  throw new Error("Cannot find the slug param in the URL");
162
125
  }
126
+ const [{ rawQuery }] = strapiAdmin.useQueryParams();
163
127
  const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
164
128
  const contentTypePermissions = React__namespace.useMemo(() => {
165
129
  const contentTypePermissions2 = userPermissions.filter(
@@ -170,7 +134,14 @@ const DocumentRBAC = ({ children, permissions }) => {
170
134
  return { ...acc, [action]: [permission] };
171
135
  }, {});
172
136
  }, [slug, userPermissions]);
173
- const { isLoading, allowedActions } = strapiAdmin.useRBAC(contentTypePermissions, permissions ?? void 0);
137
+ const { isLoading, allowedActions } = strapiAdmin.useRBAC(
138
+ contentTypePermissions,
139
+ permissions ?? void 0,
140
+ // TODO: useRBAC context should be typed and built differently
141
+ // We are passing raw query as context to the hook so that it can
142
+ // rely on the locale provided from DocumentRBAC for its permission calculations.
143
+ rawQuery
144
+ );
174
145
  const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
175
146
  const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
176
147
  const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
@@ -179,9 +150,8 @@ const DocumentRBAC = ({ children, permissions }) => {
179
150
  const name = removeNumericalStrings(fieldName.split("."));
180
151
  const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
181
152
  if (fieldType === "component") {
182
- const componentOrDynamicZoneFields = componentFieldNames.map((field) => field.split("."));
183
- return componentOrDynamicZoneFields.some((field) => {
184
- return field.includes(fieldName);
153
+ return componentFieldNames.some((field) => {
154
+ return field.includes(name.join("."));
185
155
  });
186
156
  }
187
157
  if (name.length > 1) {
@@ -211,89 +181,20 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
211
181
  (field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
212
182
  );
213
183
  const removeNumericalStrings = (arr) => arr.filter((item) => isNaN(Number(item)));
214
- const buildValidParams = (query) => {
215
- if (!query)
216
- return query;
217
- const { plugins: _, ...validQueryParams } = {
218
- ...query,
219
- ...Object.values(query?.plugins ?? {}).reduce(
220
- (acc, current) => Object.assign(acc, current),
221
- {}
222
- )
223
- };
224
- if ("_q" in validQueryParams) {
225
- validQueryParams._q = encodeURIComponent(validQueryParams._q);
226
- }
227
- return validQueryParams;
228
- };
229
- const axiosBaseQuery = () => async (query, { signal }) => {
230
- try {
231
- const { get, post, del, put } = strapiAdmin.getFetchClient();
232
- if (typeof query === "string") {
233
- const result = await get(query, { signal });
234
- return { data: result.data };
235
- } else {
236
- const { url, method = "GET", data, config } = query;
237
- if (method === "POST") {
238
- const result2 = await post(url, data, { ...config, signal });
239
- return { data: result2.data };
240
- }
241
- if (method === "DELETE") {
242
- const result2 = await del(url, { ...config, signal });
243
- return { data: result2.data };
244
- }
245
- if (method === "PUT") {
246
- const result2 = await put(url, data, { ...config, signal });
247
- return { data: result2.data };
248
- }
249
- const result = await get(url, { ...config, signal });
250
- return { data: result.data };
251
- }
252
- } catch (err) {
253
- if (axios.isAxiosError(err)) {
254
- if (typeof err.response?.data === "object" && err.response?.data !== null && "error" in err.response?.data) {
255
- return { data: void 0, error: err.response?.data.error };
256
- } else {
257
- return {
258
- data: void 0,
259
- error: {
260
- name: "UnknownError",
261
- message: "There was an unknown error response from the API",
262
- details: err.response?.data,
263
- status: err.response?.status
264
- }
265
- };
266
- }
267
- }
268
- const error = err;
269
- return {
270
- data: void 0,
271
- error: {
272
- name: error.name,
273
- message: error.message,
274
- stack: error.stack
275
- }
276
- };
277
- }
278
- };
279
- const isBaseQueryError = (error) => {
280
- return error.name !== void 0;
281
- };
282
- const contentManagerApi = react.createApi({
283
- reducerPath: "contentManagerApi",
284
- baseQuery: axiosBaseQuery(),
285
- tagTypes: [
184
+ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
185
+ addTagTypes: [
286
186
  "ComponentConfiguration",
287
187
  "ContentTypesConfiguration",
288
188
  "ContentTypeSettings",
289
189
  "Document",
290
190
  "InitialData",
291
191
  "HistoryVersion",
292
- "Relations"
293
- ],
294
- endpoints: () => ({})
192
+ "Relations",
193
+ "UidAvailability"
194
+ ]
295
195
  });
296
196
  const documentApi = contentManagerApi.injectEndpoints({
197
+ overrideExisting: true,
297
198
  endpoints: (builder) => ({
298
199
  autoCloneDocument: builder.mutation({
299
200
  query: ({ model, sourceId, query }) => ({
@@ -303,7 +204,12 @@ const documentApi = contentManagerApi.injectEndpoints({
303
204
  params: query
304
205
  }
305
206
  }),
306
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
207
+ invalidatesTags: (_result, error, { model }) => {
208
+ if (error) {
209
+ return [];
210
+ }
211
+ return [{ type: "Document", id: `${model}_LIST` }];
212
+ }
307
213
  }),
308
214
  cloneDocument: builder.mutation({
309
215
  query: ({ model, sourceId, data, params }) => ({
@@ -314,7 +220,10 @@ const documentApi = contentManagerApi.injectEndpoints({
314
220
  params
315
221
  }
316
222
  }),
317
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
223
+ invalidatesTags: (_result, _error, { model }) => [
224
+ { type: "Document", id: `${model}_LIST` },
225
+ { type: "UidAvailability", id: model }
226
+ ]
318
227
  }),
319
228
  /**
320
229
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -331,7 +240,8 @@ const documentApi = contentManagerApi.injectEndpoints({
331
240
  }),
332
241
  invalidatesTags: (result, _error, { model }) => [
333
242
  { type: "Document", id: `${model}_LIST` },
334
- "Relations"
243
+ "Relations",
244
+ { type: "UidAvailability", id: model }
335
245
  ]
336
246
  }),
337
247
  deleteDocument: builder.mutation({
@@ -347,12 +257,15 @@ const documentApi = contentManagerApi.injectEndpoints({
347
257
  ]
348
258
  }),
349
259
  deleteManyDocuments: builder.mutation({
350
- query: ({ model, ...body }) => ({
260
+ query: ({ model, params, ...body }) => ({
351
261
  url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
352
262
  method: "POST",
353
- data: body
263
+ data: body,
264
+ config: {
265
+ params
266
+ }
354
267
  }),
355
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
268
+ invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
356
269
  }),
357
270
  discardDocument: builder.mutation({
358
271
  query: ({ collectionType, model, documentId, params }) => ({
@@ -369,7 +282,8 @@ const documentApi = contentManagerApi.injectEndpoints({
369
282
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
370
283
  },
371
284
  { type: "Document", id: `${model}_LIST` },
372
- "Relations"
285
+ "Relations",
286
+ { type: "UidAvailability", id: model }
373
287
  ];
374
288
  }
375
289
  }),
@@ -379,7 +293,7 @@ const documentApi = contentManagerApi.injectEndpoints({
379
293
  */
380
294
  getAllDocuments: builder.query({
381
295
  query: ({ model, params }) => ({
382
- url: `/content-manager/collection-types/${model}`,
296
+ url: `/content-manager/collection-types/${model}${params ? `?${params}` : ""}`,
383
297
  method: "GET",
384
298
  config: {
385
299
  params
@@ -387,6 +301,7 @@ const documentApi = contentManagerApi.injectEndpoints({
387
301
  }),
388
302
  providesTags: (result, _error, arg) => {
389
303
  return [
304
+ { type: "Document", id: `ALL_LIST` },
390
305
  { type: "Document", id: `${arg.model}_LIST` },
391
306
  ...result?.results.map(({ documentId }) => ({
392
307
  type: "Document",
@@ -425,6 +340,11 @@ const documentApi = contentManagerApi.injectEndpoints({
425
340
  {
426
341
  type: "Document",
427
342
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
343
+ },
344
+ // Make it easy to invalidate all individual documents queries for a model
345
+ {
346
+ type: "Document",
347
+ id: `${model}_ALL_ITEMS`
428
348
  }
429
349
  ];
430
350
  }
@@ -463,10 +383,13 @@ const documentApi = contentManagerApi.injectEndpoints({
463
383
  }
464
384
  }),
465
385
  publishManyDocuments: builder.mutation({
466
- query: ({ model, ...body }) => ({
386
+ query: ({ model, params, ...body }) => ({
467
387
  url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
468
388
  method: "POST",
469
- data: body
389
+ data: body,
390
+ config: {
391
+ params
392
+ }
470
393
  }),
471
394
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
472
395
  }),
@@ -485,8 +408,21 @@ const documentApi = contentManagerApi.injectEndpoints({
485
408
  type: "Document",
486
409
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
487
410
  },
488
- "Relations"
411
+ "Relations",
412
+ { type: "UidAvailability", id: model }
489
413
  ];
414
+ },
415
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
416
+ const patchResult = dispatch(
417
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
418
+ Object.assign(draft.data, data);
419
+ })
420
+ );
421
+ try {
422
+ await queryFulfilled;
423
+ } catch {
424
+ patchResult.undo();
425
+ }
490
426
  }
491
427
  }),
492
428
  unpublishDocument: builder.mutation({
@@ -508,10 +444,13 @@ const documentApi = contentManagerApi.injectEndpoints({
508
444
  }
509
445
  }),
510
446
  unpublishManyDocuments: builder.mutation({
511
- query: ({ model, ...body }) => ({
447
+ query: ({ model, params, ...body }) => ({
512
448
  url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
513
449
  method: "POST",
514
- data: body
450
+ data: body,
451
+ config: {
452
+ params
453
+ }
515
454
  }),
516
455
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
517
456
  })
@@ -535,20 +474,57 @@ const {
535
474
  useUnpublishDocumentMutation,
536
475
  useUnpublishManyDocumentsMutation
537
476
  } = documentApi;
538
- const createYupSchema = (attributes = {}, components = {}) => {
477
+ const buildValidParams = (query) => {
478
+ if (!query)
479
+ return query;
480
+ const { plugins: _, ...validQueryParams } = {
481
+ ...query,
482
+ ...Object.values(query?.plugins ?? {}).reduce(
483
+ (acc, current) => Object.assign(acc, current),
484
+ {}
485
+ )
486
+ };
487
+ if ("_q" in validQueryParams) {
488
+ validQueryParams._q = encodeURIComponent(validQueryParams._q);
489
+ }
490
+ return validQueryParams;
491
+ };
492
+ const isBaseQueryError = (error) => {
493
+ return error.name !== void 0;
494
+ };
495
+ const arrayValidator = (attribute, options) => ({
496
+ message: strapiAdmin.translatedErrors.required,
497
+ test(value) {
498
+ if (options.status === "draft") {
499
+ return true;
500
+ }
501
+ if (!attribute.required) {
502
+ return true;
503
+ }
504
+ if (!value) {
505
+ return false;
506
+ }
507
+ if (Array.isArray(value) && value.length === 0) {
508
+ return false;
509
+ }
510
+ return true;
511
+ }
512
+ });
513
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
539
514
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
540
515
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
541
516
  if (DOCUMENT_META_FIELDS.includes(name)) {
542
517
  return acc;
543
518
  }
544
519
  const validations = [
520
+ addNullableValidation,
545
521
  addRequiredValidation,
546
522
  addMinLengthValidation,
547
523
  addMaxLengthValidation,
548
524
  addMinValidation,
549
525
  addMaxValidation,
550
526
  addRegexValidation
551
- ].map((fn) => fn(attribute));
527
+ ].map((fn) => fn(attribute, options));
552
528
  const transformSchema = pipe__default.default(...validations);
553
529
  switch (attribute.type) {
554
530
  case "component": {
@@ -558,12 +534,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
558
534
  ...acc,
559
535
  [name]: transformSchema(
560
536
  yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
561
- )
537
+ ).test(arrayValidator(attribute, options))
562
538
  };
563
539
  } else {
564
540
  return {
565
541
  ...acc,
566
- [name]: transformSchema(createModelSchema(attributes3))
542
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
567
543
  };
568
544
  }
569
545
  }
@@ -574,24 +550,42 @@ const createYupSchema = (attributes = {}, components = {}) => {
574
550
  yup__namespace.array().of(
575
551
  yup__namespace.lazy(
576
552
  (data) => {
577
- const { attributes: attributes3 } = components[data.__component];
578
- return yup__namespace.object().shape({
553
+ const attributes3 = components?.[data?.__component]?.attributes;
554
+ const validation = yup__namespace.object().shape({
579
555
  __component: yup__namespace.string().required().oneOf(Object.keys(components))
580
- }).nullable(false).concat(createModelSchema(attributes3));
556
+ }).nullable(false);
557
+ if (!attributes3) {
558
+ return validation;
559
+ }
560
+ return validation.concat(createModelSchema(attributes3));
581
561
  }
582
562
  )
583
563
  )
584
- )
564
+ ).test(arrayValidator(attribute, options))
585
565
  };
586
566
  case "relation":
587
567
  return {
588
568
  ...acc,
589
569
  [name]: transformSchema(
590
- yup__namespace.array().of(
591
- yup__namespace.object().shape({
592
- id: yup__namespace.string().required()
593
- })
594
- )
570
+ yup__namespace.lazy((value) => {
571
+ if (!value) {
572
+ return yup__namespace.mixed().nullable(true);
573
+ } else if (Array.isArray(value)) {
574
+ return yup__namespace.array().of(
575
+ yup__namespace.object().shape({
576
+ id: yup__namespace.number().required()
577
+ })
578
+ );
579
+ } else if (typeof value === "object") {
580
+ return yup__namespace.object();
581
+ } else {
582
+ return yup__namespace.mixed().test(
583
+ "type-error",
584
+ "Relation values must be either null, an array of objects with {id} or an object.",
585
+ () => false
586
+ );
587
+ }
588
+ })
595
589
  )
596
590
  };
597
591
  default:
@@ -631,6 +625,14 @@ const createAttributeSchema = (attribute) => {
631
625
  if (!value || typeof value === "string" && value.length === 0) {
632
626
  return true;
633
627
  }
628
+ if (typeof value === "object") {
629
+ try {
630
+ JSON.stringify(value);
631
+ return true;
632
+ } catch (err) {
633
+ return false;
634
+ }
635
+ }
634
636
  try {
635
637
  JSON.parse(value);
636
638
  return true;
@@ -649,16 +651,30 @@ const createAttributeSchema = (attribute) => {
649
651
  return yup__namespace.mixed();
650
652
  }
651
653
  };
652
- const addRequiredValidation = (attribute) => (schema) => {
653
- if (attribute.required) {
654
- return schema.required({
655
- id: strapiAdmin.translatedErrors.required.id,
656
- defaultMessage: "This field is required."
657
- });
654
+ const nullableSchema = (schema) => {
655
+ return schema?.nullable ? schema.nullable() : (
656
+ // In some cases '.nullable' will not be available on the schema.
657
+ // e.g. when the schema has been built using yup.lazy (e.g. for relations).
658
+ // In these cases we should just return the schema as it is.
659
+ schema
660
+ );
661
+ };
662
+ const addNullableValidation = () => (schema) => {
663
+ return nullableSchema(schema);
664
+ };
665
+ const addRequiredValidation = (attribute, options) => (schema) => {
666
+ if (options.status === "draft" || !attribute.required) {
667
+ return schema;
668
+ }
669
+ if (attribute.required && "required" in schema) {
670
+ return schema.required(strapiAdmin.translatedErrors.required);
658
671
  }
659
- return schema.nullable();
672
+ return schema;
660
673
  };
661
- const addMinLengthValidation = (attribute) => (schema) => {
674
+ const addMinLengthValidation = (attribute, options) => (schema) => {
675
+ if (options.status === "draft") {
676
+ return schema;
677
+ }
662
678
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
663
679
  return schema.min(attribute.minLength, {
664
680
  ...strapiAdmin.translatedErrors.minLength,
@@ -680,10 +696,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
680
696
  }
681
697
  return schema;
682
698
  };
683
- const addMinValidation = (attribute) => (schema) => {
684
- if ("min" in attribute) {
699
+ const addMinValidation = (attribute, options) => (schema) => {
700
+ if (options.status === "draft") {
701
+ return schema;
702
+ }
703
+ if ("min" in attribute && "min" in schema) {
685
704
  const min = toInteger(attribute.min);
686
- if ("min" in schema && min) {
705
+ if (min) {
687
706
  return schema.min(min, {
688
707
  ...strapiAdmin.translatedErrors.min,
689
708
  values: {
@@ -728,24 +747,6 @@ const addRegexValidation = (attribute) => (schema) => {
728
747
  }
729
748
  return schema;
730
749
  };
731
- const extractValuesFromYupError = (errorType, errorParams) => {
732
- if (!errorType || !errorParams) {
733
- return {};
734
- }
735
- return {
736
- [errorType]: errorParams[errorType]
737
- };
738
- };
739
- const getInnerErrors = (error) => (error?.inner || []).reduce((acc, currentError) => {
740
- if (currentError.path) {
741
- acc[currentError.path.split("[").join(".").split("]").join("")] = {
742
- id: currentError.message,
743
- defaultMessage: currentError.message,
744
- values: extractValuesFromYupError(currentError?.type, currentError?.params)
745
- };
746
- }
747
- return acc;
748
- }, {});
749
750
  const initApi = contentManagerApi.injectEndpoints({
750
751
  endpoints: (builder) => ({
751
752
  getInitialData: builder.query({
@@ -759,27 +760,20 @@ const { useGetInitialDataQuery } = initApi;
759
760
  const useContentTypeSchema = (model) => {
760
761
  const { toggleNotification } = strapiAdmin.useNotification();
761
762
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
762
- const { components, contentType, contentTypes, error, isLoading, isFetching } = useGetInitialDataQuery(void 0, {
763
- selectFromResult: (res) => {
764
- const contentType2 = res.data?.contentTypes.find((ct) => ct.uid === model);
765
- const componentsByKey = res.data?.components.reduce(
766
- (acc, component) => {
767
- acc[component.uid] = component;
768
- return acc;
769
- },
770
- {}
771
- );
772
- const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
773
- return {
774
- isLoading: res.isLoading,
775
- isFetching: res.isFetching,
776
- error: res.error,
777
- components: Object.keys(components2).length === 0 ? void 0 : components2,
778
- contentType: contentType2,
779
- contentTypes: res.data?.contentTypes ?? []
780
- };
781
- }
782
- });
763
+ const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
764
+ const { components, contentType, contentTypes } = React__namespace.useMemo(() => {
765
+ const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
766
+ const componentsByKey = data?.components.reduce((acc, component) => {
767
+ acc[component.uid] = component;
768
+ return acc;
769
+ }, {});
770
+ const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
771
+ return {
772
+ components: Object.keys(components2).length === 0 ? void 0 : components2,
773
+ contentType: contentType2,
774
+ contentTypes: data?.contentTypes ?? []
775
+ };
776
+ }, [model, data]);
783
777
  React__namespace.useEffect(() => {
784
778
  if (error) {
785
779
  toggleNotification({
@@ -826,88 +820,441 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
826
820
  }, {});
827
821
  return componentsByKey;
828
822
  };
829
- const useDocument = (args, opts) => {
830
- const { toggleNotification } = strapiAdmin.useNotification();
831
- const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
832
- const {
833
- currentData: data,
834
- isLoading: isLoadingDocument,
835
- isFetching: isFetchingDocument,
836
- error
837
- } = useGetDocumentQuery(args, opts);
838
- const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
839
- React__namespace.useEffect(() => {
840
- if (error) {
841
- toggleNotification({
842
- type: "danger",
843
- message: formatAPIError(error)
844
- });
845
- }
846
- }, [toggleNotification, error, formatAPIError, args.collectionType]);
847
- const validationSchema = React__namespace.useMemo(() => {
848
- if (!schema) {
849
- return null;
850
- }
851
- return createYupSchema(schema.attributes, components);
852
- }, [schema, components]);
853
- const validate = React__namespace.useCallback(
854
- (document) => {
855
- if (!validationSchema) {
856
- throw new Error(
857
- "There is no validation schema generated, this is likely due to the schema not being loaded yet."
858
- );
859
- }
860
- try {
861
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
862
- return null;
863
- } catch (error2) {
864
- if (error2 instanceof yup.ValidationError) {
865
- return getInnerErrors(error2);
866
- }
867
- throw error2;
868
- }
869
- },
870
- [validationSchema]
871
- );
872
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
873
- return {
874
- components,
875
- document: data?.data,
876
- meta: data?.meta,
877
- isLoading,
878
- schema,
879
- validate
880
- };
881
- };
882
- const useDoc = () => {
883
- const { id, slug, collectionType, origin } = reactRouterDom.useParams();
884
- const [{ query }] = strapiAdmin.useQueryParams();
885
- const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
886
- if (!collectionType) {
887
- throw new Error("Could not find collectionType in url params");
888
- }
889
- if (!slug) {
890
- throw new Error("Could not find model in url params");
891
- }
892
- return {
893
- collectionType,
894
- model: slug,
895
- id: origin || id === "create" ? void 0 : id,
896
- ...useDocument(
897
- { documentId: origin || id, model: slug, collectionType, params },
898
- {
899
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
900
- }
901
- )
902
- };
823
+ const HOOKS = {
824
+ /**
825
+ * Hook that allows to mutate the displayed headers of the list view table
826
+ * @constant
827
+ * @type {string}
828
+ */
829
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
830
+ /**
831
+ * Hook that allows to mutate the CM's collection types links pre-set filters
832
+ * @constant
833
+ * @type {string}
834
+ */
835
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
836
+ /**
837
+ * Hook that allows to mutate the CM's edit view layout
838
+ * @constant
839
+ * @type {string}
840
+ */
841
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
842
+ /**
843
+ * Hook that allows to mutate the CM's single types links pre-set filters
844
+ * @constant
845
+ * @type {string}
846
+ */
847
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
903
848
  };
904
- const prefixPluginTranslations = (trad, pluginId) => {
905
- if (!pluginId) {
906
- throw new TypeError("pluginId can't be empty");
907
- }
908
- return Object.keys(trad).reduce((acc, current) => {
909
- acc[`${pluginId}.${current}`] = trad[current];
910
- return acc;
849
+ const contentTypesApi = contentManagerApi.injectEndpoints({
850
+ endpoints: (builder) => ({
851
+ getContentTypeConfiguration: builder.query({
852
+ query: (uid) => ({
853
+ url: `/content-manager/content-types/${uid}/configuration`,
854
+ method: "GET"
855
+ }),
856
+ transformResponse: (response) => response.data,
857
+ providesTags: (_result, _error, uid) => [
858
+ { type: "ContentTypesConfiguration", id: uid },
859
+ { type: "ContentTypeSettings", id: "LIST" }
860
+ ]
861
+ }),
862
+ getAllContentTypeSettings: builder.query({
863
+ query: () => "/content-manager/content-types-settings",
864
+ transformResponse: (response) => response.data,
865
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
866
+ }),
867
+ updateContentTypeConfiguration: builder.mutation({
868
+ query: ({ uid, ...body }) => ({
869
+ url: `/content-manager/content-types/${uid}/configuration`,
870
+ method: "PUT",
871
+ data: body
872
+ }),
873
+ transformResponse: (response) => response.data,
874
+ invalidatesTags: (_result, _error, { uid }) => [
875
+ { type: "ContentTypesConfiguration", id: uid },
876
+ { type: "ContentTypeSettings", id: "LIST" },
877
+ // Is this necessary?
878
+ { type: "InitialData" }
879
+ ]
880
+ })
881
+ })
882
+ });
883
+ const {
884
+ useGetContentTypeConfigurationQuery,
885
+ useGetAllContentTypeSettingsQuery,
886
+ useUpdateContentTypeConfigurationMutation
887
+ } = contentTypesApi;
888
+ const checkIfAttributeIsDisplayable = (attribute) => {
889
+ const { type } = attribute;
890
+ if (type === "relation") {
891
+ return !attribute.relation.toLowerCase().includes("morph");
892
+ }
893
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
894
+ };
895
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
896
+ if (!mainFieldName) {
897
+ return void 0;
898
+ }
899
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
900
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
901
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
902
+ );
903
+ return {
904
+ name: mainFieldName,
905
+ type: mainFieldType ?? "string"
906
+ };
907
+ };
908
+ const DEFAULT_SETTINGS = {
909
+ bulkable: false,
910
+ filterable: false,
911
+ searchable: false,
912
+ pagination: false,
913
+ defaultSortBy: "",
914
+ defaultSortOrder: "asc",
915
+ mainField: "id",
916
+ pageSize: 10
917
+ };
918
+ const useDocumentLayout = (model) => {
919
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
920
+ const [{ query }] = strapiAdmin.useQueryParams();
921
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
922
+ const { toggleNotification } = strapiAdmin.useNotification();
923
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
924
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
925
+ const {
926
+ data,
927
+ isLoading: isLoadingConfigs,
928
+ error,
929
+ isFetching: isFetchingConfigs
930
+ } = useGetContentTypeConfigurationQuery(model);
931
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
932
+ React__namespace.useEffect(() => {
933
+ if (error) {
934
+ toggleNotification({
935
+ type: "danger",
936
+ message: formatAPIError(error)
937
+ });
938
+ }
939
+ }, [error, formatAPIError, toggleNotification]);
940
+ const editLayout = React__namespace.useMemo(
941
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
942
+ layout: [],
943
+ components: {},
944
+ metadatas: {},
945
+ options: {},
946
+ settings: DEFAULT_SETTINGS
947
+ },
948
+ [data, isLoading, schemas, schema, components]
949
+ );
950
+ const listLayout = React__namespace.useMemo(() => {
951
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
952
+ layout: [],
953
+ metadatas: {},
954
+ options: {},
955
+ settings: DEFAULT_SETTINGS
956
+ };
957
+ }, [data, isLoading, schemas, schema, components]);
958
+ const { layout: edit } = React__namespace.useMemo(
959
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
960
+ layout: editLayout,
961
+ query
962
+ }),
963
+ [editLayout, query, runHookWaterfall]
964
+ );
965
+ return {
966
+ error,
967
+ isLoading,
968
+ edit,
969
+ list: listLayout
970
+ };
971
+ };
972
+ const useDocLayout = () => {
973
+ const { model } = useDoc();
974
+ return useDocumentLayout(model);
975
+ };
976
+ const formatEditLayout = (data, {
977
+ schemas,
978
+ schema,
979
+ components
980
+ }) => {
981
+ let currentPanelIndex = 0;
982
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
983
+ data.contentType.layouts.edit,
984
+ schema?.attributes,
985
+ data.contentType.metadatas,
986
+ { configurations: data.components, schemas: components },
987
+ schemas
988
+ ).reduce((panels, row) => {
989
+ if (row.some((field) => field.type === "dynamiczone")) {
990
+ panels.push([row]);
991
+ currentPanelIndex += 2;
992
+ } else {
993
+ if (!panels[currentPanelIndex]) {
994
+ panels.push([row]);
995
+ } else {
996
+ panels[currentPanelIndex].push(row);
997
+ }
998
+ }
999
+ return panels;
1000
+ }, []);
1001
+ const componentEditAttributes = Object.entries(data.components).reduce(
1002
+ (acc, [uid, configuration]) => {
1003
+ acc[uid] = {
1004
+ layout: convertEditLayoutToFieldLayouts(
1005
+ configuration.layouts.edit,
1006
+ components[uid].attributes,
1007
+ configuration.metadatas,
1008
+ { configurations: data.components, schemas: components }
1009
+ ),
1010
+ settings: {
1011
+ ...configuration.settings,
1012
+ icon: components[uid].info.icon,
1013
+ displayName: components[uid].info.displayName
1014
+ }
1015
+ };
1016
+ return acc;
1017
+ },
1018
+ {}
1019
+ );
1020
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
1021
+ (acc, [attribute, metadata]) => {
1022
+ return {
1023
+ ...acc,
1024
+ [attribute]: metadata.edit
1025
+ };
1026
+ },
1027
+ {}
1028
+ );
1029
+ return {
1030
+ layout: panelledEditAttributes,
1031
+ components: componentEditAttributes,
1032
+ metadatas: editMetadatas,
1033
+ settings: {
1034
+ ...data.contentType.settings,
1035
+ displayName: schema?.info.displayName
1036
+ },
1037
+ options: {
1038
+ ...schema?.options,
1039
+ ...schema?.pluginOptions,
1040
+ ...data.contentType.options
1041
+ }
1042
+ };
1043
+ };
1044
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1045
+ return rows.map(
1046
+ (row) => row.map((field) => {
1047
+ const attribute = attributes[field.name];
1048
+ if (!attribute) {
1049
+ return null;
1050
+ }
1051
+ const { edit: metadata } = metadatas[field.name];
1052
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1053
+ return {
1054
+ attribute,
1055
+ disabled: !metadata.editable,
1056
+ hint: metadata.description,
1057
+ label: metadata.label ?? "",
1058
+ name: field.name,
1059
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1060
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1061
+ schemas,
1062
+ components: components?.schemas ?? {}
1063
+ }),
1064
+ placeholder: metadata.placeholder ?? "",
1065
+ required: attribute.required ?? false,
1066
+ size: field.size,
1067
+ unique: "unique" in attribute ? attribute.unique : false,
1068
+ visible: metadata.visible ?? true,
1069
+ type: attribute.type
1070
+ };
1071
+ }).filter((field) => field !== null)
1072
+ );
1073
+ };
1074
+ const formatListLayout = (data, {
1075
+ schemas,
1076
+ schema,
1077
+ components
1078
+ }) => {
1079
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1080
+ (acc, [attribute, metadata]) => {
1081
+ return {
1082
+ ...acc,
1083
+ [attribute]: metadata.list
1084
+ };
1085
+ },
1086
+ {}
1087
+ );
1088
+ const listAttributes = convertListLayoutToFieldLayouts(
1089
+ data.contentType.layouts.list,
1090
+ schema?.attributes,
1091
+ listMetadatas,
1092
+ { configurations: data.components, schemas: components },
1093
+ schemas
1094
+ );
1095
+ return {
1096
+ layout: listAttributes,
1097
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1098
+ metadatas: listMetadatas,
1099
+ options: {
1100
+ ...schema?.options,
1101
+ ...schema?.pluginOptions,
1102
+ ...data.contentType.options
1103
+ }
1104
+ };
1105
+ };
1106
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1107
+ return columns.map((name) => {
1108
+ const attribute = attributes[name];
1109
+ if (!attribute) {
1110
+ return null;
1111
+ }
1112
+ const metadata = metadatas[name];
1113
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1114
+ return {
1115
+ attribute,
1116
+ label: metadata.label ?? "",
1117
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1118
+ schemas,
1119
+ components: components?.schemas ?? {}
1120
+ }),
1121
+ name,
1122
+ searchable: metadata.searchable ?? true,
1123
+ sortable: metadata.sortable ?? true
1124
+ };
1125
+ }).filter((field) => field !== null);
1126
+ };
1127
+ const useDocument = (args, opts) => {
1128
+ const { toggleNotification } = strapiAdmin.useNotification();
1129
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1130
+ const {
1131
+ currentData: data,
1132
+ isLoading: isLoadingDocument,
1133
+ isFetching: isFetchingDocument,
1134
+ error
1135
+ } = useGetDocumentQuery(args, {
1136
+ ...opts,
1137
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1138
+ });
1139
+ const {
1140
+ components,
1141
+ schema,
1142
+ schemas,
1143
+ isLoading: isLoadingSchema
1144
+ } = useContentTypeSchema(args.model);
1145
+ React__namespace.useEffect(() => {
1146
+ if (error) {
1147
+ toggleNotification({
1148
+ type: "danger",
1149
+ message: formatAPIError(error)
1150
+ });
1151
+ }
1152
+ }, [toggleNotification, error, formatAPIError, args.collectionType]);
1153
+ const validationSchema = React__namespace.useMemo(() => {
1154
+ if (!schema) {
1155
+ return null;
1156
+ }
1157
+ return createYupSchema(schema.attributes, components);
1158
+ }, [schema, components]);
1159
+ const validate = React__namespace.useCallback(
1160
+ (document) => {
1161
+ if (!validationSchema) {
1162
+ throw new Error(
1163
+ "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1164
+ );
1165
+ }
1166
+ try {
1167
+ validationSchema.validateSync(document, { abortEarly: false, strict: true });
1168
+ return null;
1169
+ } catch (error2) {
1170
+ if (error2 instanceof yup.ValidationError) {
1171
+ return strapiAdmin.getYupValidationErrors(error2);
1172
+ }
1173
+ throw error2;
1174
+ }
1175
+ },
1176
+ [validationSchema]
1177
+ );
1178
+ const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1179
+ const hasError = !!error;
1180
+ return {
1181
+ components,
1182
+ document: data?.data,
1183
+ meta: data?.meta,
1184
+ isLoading,
1185
+ hasError,
1186
+ schema,
1187
+ schemas,
1188
+ validate
1189
+ };
1190
+ };
1191
+ const useDoc = () => {
1192
+ const { id, slug, collectionType, origin } = reactRouterDom.useParams();
1193
+ const [{ query }] = strapiAdmin.useQueryParams();
1194
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1195
+ if (!collectionType) {
1196
+ throw new Error("Could not find collectionType in url params");
1197
+ }
1198
+ if (!slug) {
1199
+ throw new Error("Could not find model in url params");
1200
+ }
1201
+ const document = useDocument(
1202
+ { documentId: origin || id, model: slug, collectionType, params },
1203
+ {
1204
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1205
+ }
1206
+ );
1207
+ const returnId = origin || id === "create" ? void 0 : id;
1208
+ return {
1209
+ collectionType,
1210
+ model: slug,
1211
+ id: returnId,
1212
+ ...document
1213
+ };
1214
+ };
1215
+ const useContentManagerContext = () => {
1216
+ const {
1217
+ collectionType,
1218
+ model,
1219
+ id,
1220
+ components,
1221
+ isLoading: isLoadingDoc,
1222
+ schema,
1223
+ schemas
1224
+ } = useDoc();
1225
+ const layout = useDocumentLayout(model);
1226
+ const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
1227
+ const isSingleType = collectionType === SINGLE_TYPES;
1228
+ const slug = model;
1229
+ const isCreatingEntry = id === "create";
1230
+ useContentTypeSchema();
1231
+ const isLoading = isLoadingDoc || layout.isLoading;
1232
+ const error = layout.error;
1233
+ return {
1234
+ error,
1235
+ isLoading,
1236
+ // Base metadata
1237
+ model,
1238
+ collectionType,
1239
+ id,
1240
+ slug,
1241
+ isCreatingEntry,
1242
+ isSingleType,
1243
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1244
+ // All schema infos
1245
+ components,
1246
+ contentType: schema,
1247
+ contentTypes: schemas,
1248
+ // Form state
1249
+ form,
1250
+ // layout infos
1251
+ layout
1252
+ };
1253
+ };
1254
+ const prefixPluginTranslations = (trad, pluginId) => {
1255
+ return Object.keys(trad).reduce((acc, current) => {
1256
+ acc[`${pluginId}.${current}`] = trad[current];
1257
+ return acc;
911
1258
  }, {});
912
1259
  };
913
1260
  const getTranslation = (id) => `content-manager.${id}`;
@@ -920,15 +1267,54 @@ const useDocumentActions = () => {
920
1267
  const { formatMessage } = reactIntl.useIntl();
921
1268
  const { trackUsage } = strapiAdmin.useTracking();
922
1269
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1270
+ const navigate = reactRouterDom.useNavigate();
1271
+ const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
923
1272
  const [deleteDocument] = useDeleteDocumentMutation();
924
1273
  const _delete = React__namespace.useCallback(
925
1274
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
926
1275
  try {
927
- trackUsage("willDeleteEntry", trackerProperty);
928
- const res = await deleteDocument({
929
- collectionType,
1276
+ trackUsage("willDeleteEntry", trackerProperty);
1277
+ const res = await deleteDocument({
1278
+ collectionType,
1279
+ model,
1280
+ documentId,
1281
+ params
1282
+ });
1283
+ if ("error" in res) {
1284
+ toggleNotification({
1285
+ type: "danger",
1286
+ message: formatAPIError(res.error)
1287
+ });
1288
+ return { error: res.error };
1289
+ }
1290
+ toggleNotification({
1291
+ type: "success",
1292
+ message: formatMessage({
1293
+ id: getTranslation("success.record.delete"),
1294
+ defaultMessage: "Deleted document"
1295
+ })
1296
+ });
1297
+ trackUsage("didDeleteEntry", trackerProperty);
1298
+ return res.data;
1299
+ } catch (err) {
1300
+ toggleNotification({
1301
+ type: "danger",
1302
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1303
+ });
1304
+ trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
1305
+ throw err;
1306
+ }
1307
+ },
1308
+ [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
1309
+ );
1310
+ const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
1311
+ const deleteMany = React__namespace.useCallback(
1312
+ async ({ model, documentIds, params }) => {
1313
+ try {
1314
+ trackUsage("willBulkDeleteEntries");
1315
+ const res = await deleteManyDocuments({
930
1316
  model,
931
- documentId,
1317
+ documentIds,
932
1318
  params
933
1319
  });
934
1320
  if ("error" in res) {
@@ -940,32 +1326,34 @@ const useDocumentActions = () => {
940
1326
  }
941
1327
  toggleNotification({
942
1328
  type: "success",
943
- message: formatMessage({
944
- id: getTranslation("success.record.delete"),
945
- defaultMessage: "Deleted document"
946
- })
1329
+ title: formatMessage({
1330
+ id: getTranslation("success.records.delete"),
1331
+ defaultMessage: "Successfully deleted."
1332
+ }),
1333
+ message: ""
947
1334
  });
948
- trackUsage("didDeleteEntry", trackerProperty);
1335
+ trackUsage("didBulkDeleteEntries");
949
1336
  return res.data;
950
1337
  } catch (err) {
951
1338
  toggleNotification({
952
1339
  type: "danger",
953
1340
  message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
954
1341
  });
955
- trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
1342
+ trackUsage("didNotBulkDeleteEntries");
956
1343
  throw err;
957
1344
  }
958
1345
  },
959
- [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
1346
+ [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
960
1347
  );
961
1348
  const [discardDocument] = useDiscardDocumentMutation();
962
1349
  const discard = React__namespace.useCallback(
963
- async ({ collectionType, model, documentId }) => {
1350
+ async ({ collectionType, model, documentId, params }) => {
964
1351
  try {
965
1352
  const res = await discardDocument({
966
1353
  collectionType,
967
1354
  model,
968
- documentId
1355
+ documentId,
1356
+ params
969
1357
  });
970
1358
  if ("error" in res) {
971
1359
  toggleNotification({
@@ -1027,6 +1415,43 @@ const useDocumentActions = () => {
1027
1415
  },
1028
1416
  [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1029
1417
  );
1418
+ const [publishManyDocuments] = usePublishManyDocumentsMutation();
1419
+ const publishMany = React__namespace.useCallback(
1420
+ async ({ model, documentIds, params }) => {
1421
+ try {
1422
+ const res = await publishManyDocuments({
1423
+ model,
1424
+ documentIds,
1425
+ params
1426
+ });
1427
+ if ("error" in res) {
1428
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1429
+ return { error: res.error };
1430
+ }
1431
+ toggleNotification({
1432
+ type: "success",
1433
+ message: formatMessage({
1434
+ id: getTranslation("success.record.publish"),
1435
+ defaultMessage: "Published document"
1436
+ })
1437
+ });
1438
+ return res.data;
1439
+ } catch (err) {
1440
+ toggleNotification({
1441
+ type: "danger",
1442
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1443
+ });
1444
+ throw err;
1445
+ }
1446
+ },
1447
+ [
1448
+ // trackUsage,
1449
+ publishManyDocuments,
1450
+ toggleNotification,
1451
+ formatMessage,
1452
+ formatAPIError
1453
+ ]
1454
+ );
1030
1455
  const [updateDocument] = useUpdateDocumentMutation();
1031
1456
  const update = React__namespace.useCallback(
1032
1457
  async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
@@ -1101,6 +1526,41 @@ const useDocumentActions = () => {
1101
1526
  },
1102
1527
  [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1103
1528
  );
1529
+ const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1530
+ const unpublishMany = React__namespace.useCallback(
1531
+ async ({ model, documentIds, params }) => {
1532
+ try {
1533
+ trackUsage("willBulkUnpublishEntries");
1534
+ const res = await unpublishManyDocuments({
1535
+ model,
1536
+ documentIds,
1537
+ params
1538
+ });
1539
+ if ("error" in res) {
1540
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1541
+ return { error: res.error };
1542
+ }
1543
+ trackUsage("didBulkUnpublishEntries");
1544
+ toggleNotification({
1545
+ type: "success",
1546
+ title: formatMessage({
1547
+ id: getTranslation("success.records.unpublish"),
1548
+ defaultMessage: "Successfully unpublished."
1549
+ }),
1550
+ message: ""
1551
+ });
1552
+ return res.data;
1553
+ } catch (err) {
1554
+ toggleNotification({
1555
+ type: "danger",
1556
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1557
+ });
1558
+ trackUsage("didNotBulkUnpublishEntries");
1559
+ throw err;
1560
+ }
1561
+ },
1562
+ [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1563
+ );
1104
1564
  const [createDocument] = useCreateDocumentMutation();
1105
1565
  const create = React__namespace.useCallback(
1106
1566
  async ({ model, params }, data, trackerProperty) => {
@@ -1123,6 +1583,7 @@ const useDocumentActions = () => {
1123
1583
  defaultMessage: "Saved document"
1124
1584
  })
1125
1585
  });
1586
+ setCurrentStep("contentManager.success");
1126
1587
  return res.data;
1127
1588
  } catch (err) {
1128
1589
  toggleNotification({
@@ -1144,7 +1605,6 @@ const useDocumentActions = () => {
1144
1605
  sourceId
1145
1606
  });
1146
1607
  if ("error" in res) {
1147
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1148
1608
  return { error: res.error };
1149
1609
  }
1150
1610
  toggleNotification({
@@ -1163,7 +1623,7 @@ const useDocumentActions = () => {
1163
1623
  throw err;
1164
1624
  }
1165
1625
  },
1166
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1626
+ [autoCloneDocument, formatMessage, toggleNotification]
1167
1627
  );
1168
1628
  const [cloneDocument] = useCloneDocumentMutation();
1169
1629
  const clone = React__namespace.useCallback(
@@ -1189,6 +1649,7 @@ const useDocumentActions = () => {
1189
1649
  defaultMessage: "Cloned document"
1190
1650
  })
1191
1651
  });
1652
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1192
1653
  return res.data;
1193
1654
  } catch (err) {
1194
1655
  toggleNotification({
@@ -1199,7 +1660,7 @@ const useDocumentActions = () => {
1199
1660
  throw err;
1200
1661
  }
1201
1662
  },
1202
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1663
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1203
1664
  );
1204
1665
  const [getDoc] = useLazyGetDocumentQuery();
1205
1666
  const getDocument = React__namespace.useCallback(
@@ -1214,15 +1675,18 @@ const useDocumentActions = () => {
1214
1675
  clone,
1215
1676
  create,
1216
1677
  delete: _delete,
1678
+ deleteMany,
1217
1679
  discard,
1218
1680
  getDocument,
1219
1681
  publish,
1682
+ publishMany,
1220
1683
  unpublish,
1684
+ unpublishMany,
1221
1685
  update
1222
1686
  };
1223
1687
  };
1224
1688
  const ProtectedHistoryPage = React.lazy(
1225
- () => Promise.resolve().then(() => require("./History-BLEnudTX.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1689
+ () => Promise.resolve().then(() => require("./History-BLCCNgCt.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1226
1690
  );
1227
1691
  const routes$1 = [
1228
1692
  {
@@ -1235,31 +1699,31 @@ const routes$1 = [
1235
1699
  }
1236
1700
  ];
1237
1701
  const ProtectedEditViewPage = React.lazy(
1238
- () => Promise.resolve().then(() => require("./EditViewPage-KRG56aCq.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1702
+ () => Promise.resolve().then(() => require("./EditViewPage-C4iTxUPU.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1239
1703
  );
1240
1704
  const ProtectedListViewPage = React.lazy(
1241
- () => Promise.resolve().then(() => require("./ListViewPage-DsaOakWQ.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1705
+ () => Promise.resolve().then(() => require("./ListViewPage-CIQekSFz.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1242
1706
  );
1243
1707
  const ProtectedListConfiguration = React.lazy(
1244
- () => Promise.resolve().then(() => require("./ListConfigurationPage-Zso_LUjn.js")).then((mod) => ({
1708
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-DxWpeZrO.js")).then((mod) => ({
1245
1709
  default: mod.ProtectedListConfiguration
1246
1710
  }))
1247
1711
  );
1248
1712
  const ProtectedEditConfigurationPage = React.lazy(
1249
- () => Promise.resolve().then(() => require("./EditConfigurationPage-B7dw5_cS.js")).then((mod) => ({
1713
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-DHDQKBzw.js")).then((mod) => ({
1250
1714
  default: mod.ProtectedEditConfigurationPage
1251
1715
  }))
1252
1716
  );
1253
1717
  const ProtectedComponentConfigurationPage = React.lazy(
1254
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-2iOVVhqV.js")).then((mod) => ({
1718
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-gsCd80MU.js")).then((mod) => ({
1255
1719
  default: mod.ProtectedComponentConfigurationPage
1256
1720
  }))
1257
1721
  );
1258
1722
  const NoPermissions = React.lazy(
1259
- () => Promise.resolve().then(() => require("./NoPermissionsPage-DdyOfdKb.js")).then((mod) => ({ default: mod.NoPermissions }))
1723
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-Oy4tmUrW.js")).then((mod) => ({ default: mod.NoPermissions }))
1260
1724
  );
1261
1725
  const NoContentType = React.lazy(
1262
- () => Promise.resolve().then(() => require("./NoContentTypePage-DPCuS9Y1.js")).then((mod) => ({ default: mod.NoContentType }))
1726
+ () => Promise.resolve().then(() => require("./NoContentTypePage-C5cxKvC2.js")).then((mod) => ({ default: mod.NoContentType }))
1263
1727
  );
1264
1728
  const CollectionTypePages = () => {
1265
1729
  const { collectionType } = reactRouterDom.useParams();
@@ -1373,12 +1837,14 @@ const DocumentActionButton = (action) => {
1373
1837
  /* @__PURE__ */ jsxRuntime.jsx(
1374
1838
  designSystem.Button,
1375
1839
  {
1376
- flex: 1,
1840
+ flex: "auto",
1377
1841
  startIcon: action.icon,
1378
1842
  disabled: action.disabled,
1379
1843
  onClick: handleClick(action),
1380
1844
  justifyContent: "center",
1381
1845
  variant: action.variant || "default",
1846
+ paddingTop: "7px",
1847
+ paddingBottom: "7px",
1382
1848
  children: action.label
1383
1849
  }
1384
1850
  ),
@@ -1386,7 +1852,7 @@ const DocumentActionButton = (action) => {
1386
1852
  DocumentActionConfirmDialog,
1387
1853
  {
1388
1854
  ...action.dialog,
1389
- variant: action.variant,
1855
+ variant: action.dialog?.variant ?? action.variant,
1390
1856
  isOpen: dialogId === action.id,
1391
1857
  onClose: handleClose
1392
1858
  }
@@ -1443,20 +1909,20 @@ const DocumentActionsMenu = ({
1443
1909
  disabled: isDisabled,
1444
1910
  size: "S",
1445
1911
  endIcon: null,
1446
- paddingTop: "7px",
1447
- paddingLeft: "9px",
1448
- paddingRight: "9px",
1912
+ paddingTop: "4px",
1913
+ paddingLeft: "7px",
1914
+ paddingRight: "7px",
1449
1915
  variant,
1450
1916
  children: [
1451
1917
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
1452
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { as: "span", children: label || formatMessage({
1918
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
1453
1919
  id: "content-manager.containers.edit.panels.default.more-actions",
1454
1920
  defaultMessage: "More document actions"
1455
1921
  }) })
1456
1922
  ]
1457
1923
  }
1458
1924
  ),
1459
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1925
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1460
1926
  actions2.map((action) => {
1461
1927
  return /* @__PURE__ */ jsxRuntime.jsx(
1462
1928
  designSystem.Menu.Item,
@@ -1465,10 +1931,25 @@ const DocumentActionsMenu = ({
1465
1931
  onSelect: handleClick(action),
1466
1932
  display: "block",
1467
1933
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1468
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, as: "span", children: [
1469
- action.icon,
1470
- action.label
1471
- ] }),
1934
+ /* @__PURE__ */ jsxRuntime.jsxs(
1935
+ designSystem.Flex,
1936
+ {
1937
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1938
+ gap: 2,
1939
+ tag: "span",
1940
+ children: [
1941
+ /* @__PURE__ */ jsxRuntime.jsx(
1942
+ designSystem.Flex,
1943
+ {
1944
+ tag: "span",
1945
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1946
+ children: action.icon
1947
+ }
1948
+ ),
1949
+ action.label
1950
+ ]
1951
+ }
1952
+ ),
1472
1953
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
1473
1954
  designSystem.Flex,
1474
1955
  {
@@ -1527,6 +2008,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1527
2008
  return "primary600";
1528
2009
  }
1529
2010
  };
2011
+ const convertActionVariantToIconColor = (variant = "secondary") => {
2012
+ switch (variant) {
2013
+ case "danger":
2014
+ return "danger600";
2015
+ case "secondary":
2016
+ return "neutral500";
2017
+ case "success":
2018
+ return "success600";
2019
+ default:
2020
+ return "primary600";
2021
+ }
2022
+ };
1530
2023
  const DocumentActionConfirmDialog = ({
1531
2024
  onClose,
1532
2025
  onCancel,
@@ -1549,61 +2042,54 @@ const DocumentActionConfirmDialog = ({
1549
2042
  }
1550
2043
  onClose();
1551
2044
  };
1552
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog, { isOpen, title, onClose: handleClose, children: [
1553
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.DialogBody, { children: content }),
1554
- /* @__PURE__ */ jsxRuntime.jsx(
1555
- designSystem.DialogFooter,
1556
- {
1557
- startAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", children: formatMessage({
1558
- id: "app.components.Button.cancel",
1559
- defaultMessage: "Cancel"
1560
- }) }),
1561
- endAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
1562
- id: "app.components.Button.confirm",
1563
- defaultMessage: "Confirm"
1564
- }) })
1565
- }
1566
- )
1567
- ] });
2045
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2046
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
2047
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
2048
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
2049
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
2050
+ id: "app.components.Button.cancel",
2051
+ defaultMessage: "Cancel"
2052
+ }) }) }),
2053
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
2054
+ id: "app.components.Button.confirm",
2055
+ defaultMessage: "Confirm"
2056
+ }) })
2057
+ ] })
2058
+ ] }) });
1568
2059
  };
1569
2060
  const DocumentActionModal = ({
1570
2061
  isOpen,
1571
2062
  title,
1572
2063
  onClose,
1573
2064
  footer: Footer,
1574
- content,
2065
+ content: Content,
1575
2066
  onModalClose
1576
2067
  }) => {
1577
- const id = React__namespace.useId();
1578
- if (!isOpen) {
1579
- return null;
1580
- }
1581
2068
  const handleClose = () => {
1582
2069
  if (onClose) {
1583
2070
  onClose();
1584
2071
  }
1585
2072
  onModalClose();
1586
2073
  };
1587
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { borderRadius: "4px", overflow: "hidden", onClose: handleClose, labelledBy: id, children: [
1588
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: "neutral800", as: "h2", id, children: title }) }),
1589
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: content }),
1590
- /* @__PURE__ */ jsxRuntime.jsx(
1591
- designSystem.Box,
1592
- {
1593
- paddingTop: 4,
1594
- paddingBottom: 4,
1595
- paddingLeft: 5,
1596
- paddingRight: 5,
1597
- borderWidth: "1px 0 0 0",
1598
- borderStyle: "solid",
1599
- borderColor: "neutral150",
1600
- background: "neutral100",
1601
- children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1602
- }
1603
- )
1604
- ] });
2074
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
2075
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
2076
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
2077
+ typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
2078
+ ] }) });
2079
+ };
2080
+ const transformData = (data) => {
2081
+ if (Array.isArray(data)) {
2082
+ return data.map(transformData);
2083
+ }
2084
+ if (typeof data === "object" && data !== null) {
2085
+ if ("apiData" in data) {
2086
+ return data.apiData;
2087
+ }
2088
+ return mapValues__default.default(transformData)(data);
2089
+ }
2090
+ return data;
1605
2091
  };
1606
- const PublishAction = ({
2092
+ const PublishAction$1 = ({
1607
2093
  activeTab,
1608
2094
  documentId,
1609
2095
  model,
@@ -1615,13 +2101,17 @@ const PublishAction = ({
1615
2101
  const navigate = reactRouterDom.useNavigate();
1616
2102
  const { toggleNotification } = strapiAdmin.useNotification();
1617
2103
  const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
2104
+ const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
1618
2105
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
1619
2106
  const { formatMessage } = reactIntl.useIntl();
1620
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1621
- "PublishAction",
1622
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1623
- );
2107
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1624
2108
  const { publish } = useDocumentActions();
2109
+ const [
2110
+ countDraftRelations,
2111
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
2112
+ ] = useLazyGetDraftRelationCountQuery();
2113
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
2114
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
1625
2115
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1626
2116
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1627
2117
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1630,10 +2120,105 @@ const PublishAction = ({
1630
2120
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1631
2121
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1632
2122
  const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
2123
+ React__namespace.useEffect(() => {
2124
+ if (isErrorDraftRelations) {
2125
+ toggleNotification({
2126
+ type: "danger",
2127
+ message: formatMessage({
2128
+ id: getTranslation("error.records.fetch-draft-relatons"),
2129
+ defaultMessage: "An error occurred while fetching draft relations on this document."
2130
+ })
2131
+ });
2132
+ }
2133
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
2134
+ React__namespace.useEffect(() => {
2135
+ const localDraftRelations = /* @__PURE__ */ new Set();
2136
+ const extractDraftRelations = (data) => {
2137
+ const relations = data.connect || [];
2138
+ relations.forEach((relation) => {
2139
+ if (relation.status === "draft") {
2140
+ localDraftRelations.add(relation.id);
2141
+ }
2142
+ });
2143
+ };
2144
+ const traverseAndExtract = (data) => {
2145
+ Object.entries(data).forEach(([key, value]) => {
2146
+ if (key === "connect" && Array.isArray(value)) {
2147
+ extractDraftRelations({ connect: value });
2148
+ } else if (typeof value === "object" && value !== null) {
2149
+ traverseAndExtract(value);
2150
+ }
2151
+ });
2152
+ };
2153
+ if (!documentId || modified) {
2154
+ traverseAndExtract(formValues);
2155
+ setLocalCountOfDraftRelations(localDraftRelations.size);
2156
+ }
2157
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
2158
+ React__namespace.useEffect(() => {
2159
+ if (!document || !document.documentId || isListView) {
2160
+ return;
2161
+ }
2162
+ const fetchDraftRelationsCount = async () => {
2163
+ const { data, error } = await countDraftRelations({
2164
+ collectionType,
2165
+ model,
2166
+ documentId,
2167
+ params
2168
+ });
2169
+ if (error) {
2170
+ throw error;
2171
+ }
2172
+ if (data) {
2173
+ setServerCountOfDraftRelations(data.data);
2174
+ }
2175
+ };
2176
+ fetchDraftRelationsCount();
2177
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
1633
2178
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1634
2179
  if (!schema?.options?.draftAndPublish) {
1635
2180
  return null;
1636
2181
  }
2182
+ const performPublish = async () => {
2183
+ setSubmitting(true);
2184
+ try {
2185
+ const { errors } = await validate(true, {
2186
+ status: "published"
2187
+ });
2188
+ if (errors) {
2189
+ toggleNotification({
2190
+ type: "danger",
2191
+ message: formatMessage({
2192
+ id: "content-manager.validation.error",
2193
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2194
+ })
2195
+ });
2196
+ return;
2197
+ }
2198
+ const res = await publish(
2199
+ {
2200
+ collectionType,
2201
+ model,
2202
+ documentId,
2203
+ params
2204
+ },
2205
+ transformData(formValues)
2206
+ );
2207
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2208
+ navigate({
2209
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2210
+ search: rawQuery
2211
+ });
2212
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2213
+ setErrors(formatValidationErrors(res.error));
2214
+ }
2215
+ } finally {
2216
+ setSubmitting(false);
2217
+ }
2218
+ };
2219
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
2220
+ const enableDraftRelationsCount = false;
2221
+ const hasDraftRelations = enableDraftRelationsCount;
1637
2222
  return {
1638
2223
  /**
1639
2224
  * Disabled when:
@@ -1643,52 +2228,39 @@ const PublishAction = ({
1643
2228
  * - the document is already published & not modified
1644
2229
  * - the document is being created & not modified
1645
2230
  * - the user doesn't have the permission to publish
1646
- * - the user doesn't have the permission to create a new document
1647
- * - the user doesn't have the permission to update the document
1648
2231
  */
1649
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2232
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1650
2233
  label: formatMessage({
1651
2234
  id: "app.utils.publish",
1652
2235
  defaultMessage: "Publish"
1653
2236
  }),
1654
2237
  onClick: async () => {
1655
- setSubmitting(true);
1656
- try {
1657
- const { errors } = await validate();
1658
- if (errors) {
1659
- toggleNotification({
1660
- type: "danger",
1661
- message: formatMessage({
1662
- id: "content-manager.validation.error",
1663
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1664
- })
1665
- });
1666
- return;
1667
- }
1668
- const res = await publish(
1669
- {
1670
- collectionType,
1671
- model,
1672
- documentId,
1673
- params
1674
- },
1675
- formValues
1676
- );
1677
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1678
- navigate({
1679
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1680
- search: rawQuery
1681
- });
1682
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1683
- setErrors(formatValidationErrors(res.error));
2238
+ await performPublish();
2239
+ },
2240
+ dialog: hasDraftRelations ? {
2241
+ type: "dialog",
2242
+ variant: "danger",
2243
+ footer: null,
2244
+ title: formatMessage({
2245
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
2246
+ defaultMessage: "Confirmation"
2247
+ }),
2248
+ content: formatMessage(
2249
+ {
2250
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2251
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
2252
+ },
2253
+ {
2254
+ count: totalDraftRelations
1684
2255
  }
1685
- } finally {
1686
- setSubmitting(false);
2256
+ ),
2257
+ onConfirm: async () => {
2258
+ await performPublish();
1687
2259
  }
1688
- }
2260
+ } : void 0
1689
2261
  };
1690
2262
  };
1691
- PublishAction.type = "publish";
2263
+ PublishAction$1.type = "publish";
1692
2264
  const UpdateAction = ({
1693
2265
  activeTab,
1694
2266
  documentId,
@@ -1701,10 +2273,6 @@ const UpdateAction = ({
1701
2273
  const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
1702
2274
  const isCloning = cloneMatch !== null;
1703
2275
  const { formatMessage } = reactIntl.useIntl();
1704
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1705
- canCreate: canCreate2,
1706
- canUpdate: canUpdate2
1707
- }));
1708
2276
  const { create, update, clone } = useDocumentActions();
1709
2277
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1710
2278
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
@@ -1721,10 +2289,8 @@ const UpdateAction = ({
1721
2289
  * - the form is submitting
1722
2290
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1723
2291
  * - the active tab is the published tab
1724
- * - the user doesn't have the permission to create a new document
1725
- * - the user doesn't have the permission to update the document
1726
2292
  */
1727
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
2293
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1728
2294
  label: formatMessage({
1729
2295
  id: "content-manager.containers.Edit.save",
1730
2296
  defaultMessage: "Save"
@@ -1732,7 +2298,9 @@ const UpdateAction = ({
1732
2298
  onClick: async () => {
1733
2299
  setSubmitting(true);
1734
2300
  try {
1735
- const { errors } = await validate();
2301
+ const { errors } = await validate(true, {
2302
+ status: "draft"
2303
+ });
1736
2304
  if (errors) {
1737
2305
  toggleNotification({
1738
2306
  type: "danger",
@@ -1750,13 +2318,16 @@ const UpdateAction = ({
1750
2318
  documentId: cloneMatch.params.origin,
1751
2319
  params
1752
2320
  },
1753
- document
2321
+ transformData(document)
1754
2322
  );
1755
2323
  if ("data" in res) {
1756
- navigate({
1757
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1758
- search: rawQuery
1759
- });
2324
+ navigate(
2325
+ {
2326
+ pathname: `../${res.data.documentId}`,
2327
+ search: rawQuery
2328
+ },
2329
+ { relative: "path" }
2330
+ );
1760
2331
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1761
2332
  setErrors(formatValidationErrors(res.error));
1762
2333
  }
@@ -1768,7 +2339,7 @@ const UpdateAction = ({
1768
2339
  documentId,
1769
2340
  params
1770
2341
  },
1771
- document
2342
+ transformData(document)
1772
2343
  );
1773
2344
  if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1774
2345
  setErrors(formatValidationErrors(res.error));
@@ -1781,13 +2352,16 @@ const UpdateAction = ({
1781
2352
  model,
1782
2353
  params
1783
2354
  },
1784
- document
2355
+ transformData(document)
1785
2356
  );
1786
2357
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1787
- navigate({
1788
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1789
- search: rawQuery
1790
- });
2358
+ navigate(
2359
+ {
2360
+ pathname: `../${res.data.documentId}`,
2361
+ search: rawQuery
2362
+ },
2363
+ { replace: true, relative: "path" }
2364
+ );
1791
2365
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1792
2366
  setErrors(formatValidationErrors(res.error));
1793
2367
  }
@@ -1803,7 +2377,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
1803
2377
  KEEP: "keep",
1804
2378
  DISCARD: "discard"
1805
2379
  };
1806
- const UnpublishAction = ({
2380
+ const UnpublishAction$1 = ({
1807
2381
  activeTab,
1808
2382
  documentId,
1809
2383
  model,
@@ -1819,10 +2393,8 @@ const UnpublishAction = ({
1819
2393
  const { toggleNotification } = strapiAdmin.useNotification();
1820
2394
  const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
1821
2395
  const isDocumentModified = document?.status === "modified";
1822
- const handleChange = (e) => {
1823
- if ("value" in e.target) {
1824
- setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1825
- }
2396
+ const handleChange = (value) => {
2397
+ setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1826
2398
  };
1827
2399
  if (!schema?.options?.draftAndPublish) {
1828
2400
  return null;
@@ -1833,7 +2405,7 @@ const UnpublishAction = ({
1833
2405
  id: "app.utils.unpublish",
1834
2406
  defaultMessage: "Unpublish"
1835
2407
  }),
1836
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2408
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
1837
2409
  onClick: async () => {
1838
2410
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1839
2411
  if (!documentId) {
@@ -1866,45 +2438,30 @@ const UnpublishAction = ({
1866
2438
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
1867
2439
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
1868
2440
  /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
1869
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2441
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1870
2442
  id: "content-manager.actions.unpublish.dialog.body",
1871
2443
  defaultMessage: "Are you sure?"
1872
2444
  }) })
1873
2445
  ] }),
1874
2446
  /* @__PURE__ */ jsxRuntime.jsxs(
1875
- designSystem.Flex,
2447
+ designSystem.Radio.Group,
1876
2448
  {
1877
- onChange: handleChange,
1878
- direction: "column",
1879
- alignItems: "flex-start",
1880
- as: "fieldset",
1881
- gap: 3,
2449
+ defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
2450
+ name: "discard-options",
2451
+ "aria-label": formatMessage({
2452
+ id: "content-manager.actions.unpublish.dialog.radio-label",
2453
+ defaultMessage: "Choose an option to unpublish the document."
2454
+ }),
2455
+ onValueChange: handleChange,
1882
2456
  children: [
1883
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { as: "legend" }),
1884
- /* @__PURE__ */ jsxRuntime.jsx(
1885
- designSystem.Radio,
1886
- {
1887
- checked: shouldKeepDraft,
1888
- value: UNPUBLISH_DRAFT_OPTIONS.KEEP,
1889
- name: "discard-options",
1890
- children: formatMessage({
1891
- id: "content-manager.actions.unpublish.dialog.option.keep-draft",
1892
- defaultMessage: "Keep draft"
1893
- })
1894
- }
1895
- ),
1896
- /* @__PURE__ */ jsxRuntime.jsx(
1897
- designSystem.Radio,
1898
- {
1899
- checked: !shouldKeepDraft,
1900
- value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
1901
- name: "discard-options",
1902
- children: formatMessage({
1903
- id: "content-manager.actions.unpublish.dialog.option.replace-draft",
1904
- defaultMessage: "Replace draft"
1905
- })
1906
- }
1907
- )
2457
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
2458
+ id: "content-manager.actions.unpublish.dialog.option.keep-draft",
2459
+ defaultMessage: "Keep draft"
2460
+ }) }),
2461
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
2462
+ id: "content-manager.actions.unpublish.dialog.option.replace-draft",
2463
+ defaultMessage: "Replace draft"
2464
+ }) })
1908
2465
  ]
1909
2466
  }
1910
2467
  )
@@ -1937,7 +2494,7 @@ const UnpublishAction = ({
1937
2494
  position: ["panel", "table-row"]
1938
2495
  };
1939
2496
  };
1940
- UnpublishAction.type = "unpublish";
2497
+ UnpublishAction$1.type = "unpublish";
1941
2498
  const DiscardAction = ({
1942
2499
  activeTab,
1943
2500
  documentId,
@@ -1960,7 +2517,7 @@ const DiscardAction = ({
1960
2517
  id: "content-manager.actions.discard.label",
1961
2518
  defaultMessage: "Discard changes"
1962
2519
  }),
1963
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
2520
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
1964
2521
  position: ["panel", "table-row"],
1965
2522
  variant: "danger",
1966
2523
  dialog: {
@@ -1971,7 +2528,7 @@ const DiscardAction = ({
1971
2528
  }),
1972
2529
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
1973
2530
  /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
1974
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2531
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1975
2532
  id: "content-manager.actions.discard.dialog.body",
1976
2533
  defaultMessage: "Are you sure?"
1977
2534
  }) })
@@ -1988,12 +2545,7 @@ const DiscardAction = ({
1988
2545
  };
1989
2546
  };
1990
2547
  DiscardAction.type = "discard";
1991
- const StyledCrossCircle = styled__default.default(Icons.CrossCircle)`
1992
- path {
1993
- fill: currentColor;
1994
- }
1995
- `;
1996
- const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
2548
+ const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
1997
2549
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
1998
2550
  const RelativeTime = React__namespace.forwardRef(
1999
2551
  ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
@@ -2040,8 +2592,8 @@ const getDisplayName = ({
2040
2592
  };
2041
2593
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2042
2594
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2043
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
2044
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2595
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2596
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2045
2597
  };
2046
2598
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2047
2599
  const { formatMessage } = reactIntl.useIntl();
@@ -2050,23 +2602,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2050
2602
  id: "content-manager.containers.edit.title.new",
2051
2603
  defaultMessage: "Create an entry"
2052
2604
  }) : documentTitle;
2053
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2605
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2054
2606
  /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
2055
- /* @__PURE__ */ jsxRuntime.jsxs(
2056
- designSystem.Flex,
2057
- {
2058
- width: "100%",
2059
- justifyContent: "space-between",
2060
- paddingTop: 1,
2061
- gap: "80px",
2062
- alignItems: "flex-start",
2063
- children: [
2064
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", children: title }),
2065
- /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2066
- ]
2067
- }
2068
- ),
2069
- status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2607
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2608
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2609
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2610
+ ] }),
2611
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2070
2612
  ] });
2071
2613
  };
2072
2614
  const HeaderToolbar = () => {
@@ -2149,12 +2691,12 @@ const Information = ({ activeTab }) => {
2149
2691
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2150
2692
  label: formatMessage({
2151
2693
  id: "content-manager.containers.edit.information.last-published.label",
2152
- defaultMessage: "Last published"
2694
+ defaultMessage: "Published"
2153
2695
  }),
2154
2696
  value: formatMessage(
2155
2697
  {
2156
2698
  id: "content-manager.containers.edit.information.last-published.value",
2157
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2699
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2158
2700
  },
2159
2701
  {
2160
2702
  time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2167,12 +2709,12 @@ const Information = ({ activeTab }) => {
2167
2709
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2168
2710
  label: formatMessage({
2169
2711
  id: "content-manager.containers.edit.information.last-draft.label",
2170
- defaultMessage: "Last draft"
2712
+ defaultMessage: "Updated"
2171
2713
  }),
2172
2714
  value: formatMessage(
2173
2715
  {
2174
2716
  id: "content-manager.containers.edit.information.last-draft.value",
2175
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2717
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2176
2718
  },
2177
2719
  {
2178
2720
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2190,12 +2732,12 @@ const Information = ({ activeTab }) => {
2190
2732
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2191
2733
  label: formatMessage({
2192
2734
  id: "content-manager.containers.edit.information.document.label",
2193
- defaultMessage: "Document"
2735
+ defaultMessage: "Created"
2194
2736
  }),
2195
2737
  value: formatMessage(
2196
2738
  {
2197
2739
  id: "content-manager.containers.edit.information.document.value",
2198
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2740
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2199
2741
  },
2200
2742
  {
2201
2743
  time: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2218,7 +2760,7 @@ const Information = ({ activeTab }) => {
2218
2760
  borderColor: "neutral150",
2219
2761
  direction: "column",
2220
2762
  marginTop: 2,
2221
- as: "dl",
2763
+ tag: "dl",
2222
2764
  padding: 5,
2223
2765
  gap: 3,
2224
2766
  alignItems: "flex-start",
@@ -2226,32 +2768,84 @@ const Information = ({ activeTab }) => {
2226
2768
  marginRight: "-0.4rem",
2227
2769
  width: "calc(100% + 8px)",
2228
2770
  children: information.map((info) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
2229
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2230
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2771
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2772
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2231
2773
  ] }, info.label))
2232
2774
  }
2233
2775
  );
2234
2776
  };
2235
2777
  const HeaderActions = ({ actions: actions2 }) => {
2236
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: actions2.map((action) => {
2237
- if ("options" in action) {
2778
+ const [dialogId, setDialogId] = React__namespace.useState(null);
2779
+ const handleClick = (action) => async (e) => {
2780
+ if (!("options" in action)) {
2781
+ const { onClick = () => false, dialog, id } = action;
2782
+ const muteDialog = await onClick(e);
2783
+ if (dialog && !muteDialog) {
2784
+ e.preventDefault();
2785
+ setDialogId(id);
2786
+ }
2787
+ }
2788
+ };
2789
+ const handleClose = () => {
2790
+ setDialogId(null);
2791
+ };
2792
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
2793
+ if (action.options) {
2238
2794
  return /* @__PURE__ */ jsxRuntime.jsx(
2239
2795
  designSystem.SingleSelect,
2240
2796
  {
2241
2797
  size: "S",
2242
- disabled: action.disabled,
2243
- "aria-label": action.label,
2244
2798
  onChange: action.onSelect,
2245
- value: action.value,
2799
+ "aria-label": action.label,
2800
+ ...action,
2246
2801
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
2247
2802
  },
2248
2803
  action.id
2249
2804
  );
2250
2805
  } else {
2251
- return null;
2806
+ if (action.type === "icon") {
2807
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
2808
+ /* @__PURE__ */ jsxRuntime.jsx(
2809
+ designSystem.IconButton,
2810
+ {
2811
+ disabled: action.disabled,
2812
+ label: action.label,
2813
+ size: "S",
2814
+ onClick: handleClick(action),
2815
+ children: action.icon
2816
+ }
2817
+ ),
2818
+ action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
2819
+ HeaderActionDialog,
2820
+ {
2821
+ ...action.dialog,
2822
+ isOpen: dialogId === action.id,
2823
+ onClose: handleClose
2824
+ }
2825
+ ) : null
2826
+ ] }, action.id);
2827
+ }
2252
2828
  }
2253
2829
  }) });
2254
2830
  };
2831
+ const HeaderActionDialog = ({
2832
+ onClose,
2833
+ onCancel,
2834
+ title,
2835
+ content: Content,
2836
+ isOpen
2837
+ }) => {
2838
+ const handleClose = async () => {
2839
+ if (onCancel) {
2840
+ await onCancel();
2841
+ }
2842
+ onClose();
2843
+ };
2844
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2845
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
2846
+ typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
2847
+ ] }) });
2848
+ };
2255
2849
  const ConfigureTheViewAction = ({ collectionType, model }) => {
2256
2850
  const navigate = reactRouterDom.useNavigate();
2257
2851
  const { formatMessage } = reactIntl.useIntl();
@@ -2260,7 +2854,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2260
2854
  id: "app.links.configure-view",
2261
2855
  defaultMessage: "Configure the view"
2262
2856
  }),
2263
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCog, {}),
2857
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
2264
2858
  onClick: () => {
2265
2859
  navigate(`../${collectionType}/${model}/configurations/edit`);
2266
2860
  },
@@ -2268,11 +2862,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2268
2862
  };
2269
2863
  };
2270
2864
  ConfigureTheViewAction.type = "configure-the-view";
2271
- const StyledCog = styled__default.default(Icons.Cog)`
2272
- path {
2273
- fill: currentColor;
2274
- }
2275
- `;
2276
2865
  const EditTheModelAction = ({ model }) => {
2277
2866
  const navigate = reactRouterDom.useNavigate();
2278
2867
  const { formatMessage } = reactIntl.useIntl();
@@ -2281,20 +2870,15 @@ const EditTheModelAction = ({ model }) => {
2281
2870
  id: "content-manager.link-to-ctb",
2282
2871
  defaultMessage: "Edit the model"
2283
2872
  }),
2284
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil$1, {}),
2873
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
2285
2874
  onClick: () => {
2286
2875
  navigate(`/plugins/content-type-builder/content-types/${model}`);
2287
2876
  },
2288
2877
  position: "header"
2289
2878
  };
2290
- };
2291
- EditTheModelAction.type = "edit-the-model";
2292
- const StyledPencil$1 = styled__default.default(Icons.Pencil)`
2293
- path {
2294
- fill: currentColor;
2295
- }
2296
- `;
2297
- const DeleteAction = ({ documentId, model, collectionType, document }) => {
2879
+ };
2880
+ EditTheModelAction.type = "edit-the-model";
2881
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2298
2882
  const navigate = reactRouterDom.useNavigate();
2299
2883
  const { formatMessage } = reactIntl.useIntl();
2300
2884
  const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
@@ -2302,13 +2886,17 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2302
2886
  const { delete: deleteAction } = useDocumentActions();
2303
2887
  const { toggleNotification } = strapiAdmin.useNotification();
2304
2888
  const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
2889
+ const isLocalized = document?.locale != null;
2305
2890
  return {
2306
2891
  disabled: !canDelete || !document,
2307
- label: formatMessage({
2308
- id: "content-manager.actions.delete.label",
2309
- defaultMessage: "Delete document"
2310
- }),
2311
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledTrash, {}),
2892
+ label: formatMessage(
2893
+ {
2894
+ id: "content-manager.actions.delete.label",
2895
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2896
+ },
2897
+ { isLocalized }
2898
+ ),
2899
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2312
2900
  dialog: {
2313
2901
  type: "dialog",
2314
2902
  title: formatMessage({
@@ -2317,7 +2905,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2317
2905
  }),
2318
2906
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
2319
2907
  /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2320
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2908
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2321
2909
  id: "content-manager.actions.delete.dialog.body",
2322
2910
  defaultMessage: "Are you sure?"
2323
2911
  }) })
@@ -2362,13 +2950,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2362
2950
  position: ["header", "table-row"]
2363
2951
  };
2364
2952
  };
2365
- DeleteAction.type = "delete";
2366
- const StyledTrash = styled__default.default(Icons.Trash)`
2367
- path {
2368
- fill: currentColor;
2369
- }
2370
- `;
2371
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction];
2953
+ DeleteAction$1.type = "delete";
2954
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2372
2955
  const Panels = () => {
2373
2956
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2374
2957
  const [
@@ -2402,7 +2985,7 @@ const ActionsPanel = () => {
2402
2985
  return {
2403
2986
  title: formatMessage({
2404
2987
  id: "content-manager.containers.edit.panels.default.title",
2405
- defaultMessage: "Document"
2988
+ defaultMessage: "Entry"
2406
2989
  }),
2407
2990
  content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2408
2991
  };
@@ -2442,7 +3025,7 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2442
3025
  designSystem.Flex,
2443
3026
  {
2444
3027
  ref,
2445
- as: "aside",
3028
+ tag: "aside",
2446
3029
  "aria-labelledby": "additional-information",
2447
3030
  background: "neutral0",
2448
3031
  borderColor: "neutral150",
@@ -2457,13 +3040,598 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2457
3040
  justifyContent: "stretch",
2458
3041
  alignItems: "flex-start",
2459
3042
  children: [
2460
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
3043
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
2461
3044
  children
2462
3045
  ]
2463
3046
  }
2464
3047
  );
2465
3048
  });
2466
- const DEFAULT_BULK_ACTIONS = [];
3049
+ const ConfirmBulkActionDialog = ({
3050
+ onToggleDialog,
3051
+ isOpen = false,
3052
+ dialogBody,
3053
+ endAction
3054
+ }) => {
3055
+ const { formatMessage } = reactIntl.useIntl();
3056
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
3057
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
3058
+ id: "app.components.ConfirmDialog.title",
3059
+ defaultMessage: "Confirmation"
3060
+ }) }),
3061
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3062
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3063
+ dialogBody
3064
+ ] }) }),
3065
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
3066
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
3067
+ id: "app.components.Button.cancel",
3068
+ defaultMessage: "Cancel"
3069
+ }) }) }),
3070
+ endAction
3071
+ ] })
3072
+ ] }) });
3073
+ };
3074
+ const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
3075
+ const ConfirmDialogPublishAll = ({
3076
+ isOpen,
3077
+ onToggleDialog,
3078
+ isConfirmButtonLoading = false,
3079
+ onConfirm
3080
+ }) => {
3081
+ const { formatMessage } = reactIntl.useIntl();
3082
+ const selectedEntries = strapiAdmin.useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
3083
+ const { toggleNotification } = strapiAdmin.useNotification();
3084
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
3085
+ const { model, schema } = useDoc();
3086
+ const [{ query }] = strapiAdmin.useQueryParams();
3087
+ const enableDraftRelationsCount = false;
3088
+ const {
3089
+ data: countDraftRelations = 0,
3090
+ isLoading,
3091
+ error
3092
+ } = useGetManyDraftRelationCountQuery(
3093
+ {
3094
+ model,
3095
+ documentIds: selectedEntries.map((entry) => entry.documentId),
3096
+ locale: query?.plugins?.i18n?.locale
3097
+ },
3098
+ {
3099
+ skip: !enableDraftRelationsCount
3100
+ }
3101
+ );
3102
+ React__namespace.useEffect(() => {
3103
+ if (error) {
3104
+ toggleNotification({ type: "danger", message: formatAPIError(error) });
3105
+ }
3106
+ }, [error, formatAPIError, toggleNotification]);
3107
+ if (error) {
3108
+ return null;
3109
+ }
3110
+ return /* @__PURE__ */ jsxRuntime.jsx(
3111
+ ConfirmBulkActionDialog,
3112
+ {
3113
+ isOpen: isOpen && !isLoading,
3114
+ onToggleDialog,
3115
+ dialogBody: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3116
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: [
3117
+ countDraftRelations > 0 && formatMessage(
3118
+ {
3119
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
3120
+ defaultMessage: "<b>{count} {count, plural, one { relation } other { relations } } out of {entities} { entities, plural, one { entry } other { entries } } {count, plural, one { is } other { are } }</b> not published yet and might lead to unexpected behavior. "
3121
+ },
3122
+ {
3123
+ b: BoldChunk$1,
3124
+ count: countDraftRelations,
3125
+ entities: selectedEntries.length
3126
+ }
3127
+ ),
3128
+ formatMessage({
3129
+ id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
3130
+ defaultMessage: "Are you sure you want to publish these entries?"
3131
+ })
3132
+ ] }),
3133
+ schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
3134
+ {
3135
+ id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
3136
+ defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
3137
+ },
3138
+ {
3139
+ em: Emphasis
3140
+ }
3141
+ ) })
3142
+ ] }),
3143
+ endAction: /* @__PURE__ */ jsxRuntime.jsx(
3144
+ designSystem.Button,
3145
+ {
3146
+ onClick: onConfirm,
3147
+ variant: "secondary",
3148
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
3149
+ loading: isConfirmButtonLoading,
3150
+ children: formatMessage({
3151
+ id: "app.utils.publish",
3152
+ defaultMessage: "Publish"
3153
+ })
3154
+ }
3155
+ )
3156
+ }
3157
+ );
3158
+ };
3159
+ const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
3160
+ max-width: 300px;
3161
+ `;
3162
+ const formatErrorMessages = (errors, parentKey, formatMessage) => {
3163
+ const messages = [];
3164
+ Object.entries(errors).forEach(([key, value]) => {
3165
+ const currentKey = parentKey ? `${parentKey}.${key}` : key;
3166
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
3167
+ if ("id" in value && "defaultMessage" in value) {
3168
+ messages.push(
3169
+ formatMessage(
3170
+ {
3171
+ id: `${value.id}.withField`,
3172
+ defaultMessage: value.defaultMessage
3173
+ },
3174
+ { field: currentKey }
3175
+ )
3176
+ );
3177
+ } else {
3178
+ messages.push(
3179
+ ...formatErrorMessages(
3180
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3181
+ value,
3182
+ currentKey,
3183
+ formatMessage
3184
+ )
3185
+ );
3186
+ }
3187
+ } else {
3188
+ messages.push(
3189
+ formatMessage(
3190
+ {
3191
+ id: `${value}.withField`,
3192
+ defaultMessage: value
3193
+ },
3194
+ { field: currentKey }
3195
+ )
3196
+ );
3197
+ }
3198
+ });
3199
+ return messages;
3200
+ };
3201
+ const EntryValidationText = ({ validationErrors, status }) => {
3202
+ const { formatMessage } = reactIntl.useIntl();
3203
+ if (validationErrors) {
3204
+ const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
3205
+ " "
3206
+ );
3207
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3208
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
3209
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
3210
+ ] });
3211
+ }
3212
+ if (status === "published") {
3213
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3214
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
3215
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
3216
+ id: "content-manager.bulk-publish.already-published",
3217
+ defaultMessage: "Already Published"
3218
+ }) })
3219
+ ] });
3220
+ }
3221
+ if (status === "modified") {
3222
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3223
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
3224
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3225
+ id: "content-manager.bulk-publish.modified",
3226
+ defaultMessage: "Ready to publish changes"
3227
+ }) })
3228
+ ] });
3229
+ }
3230
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3231
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
3232
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3233
+ id: "app.utils.ready-to-publish",
3234
+ defaultMessage: "Ready to publish"
3235
+ }) })
3236
+ ] });
3237
+ };
3238
+ const TABLE_HEADERS = [
3239
+ { name: "id", label: "id" },
3240
+ { name: "name", label: "name" },
3241
+ { name: "status", label: "status" },
3242
+ { name: "publicationStatus", label: "Publication status" }
3243
+ ];
3244
+ const SelectedEntriesTableContent = ({
3245
+ isPublishing,
3246
+ rowsToDisplay = [],
3247
+ entriesToPublish = [],
3248
+ validationErrors = {}
3249
+ }) => {
3250
+ const { pathname } = reactRouterDom.useLocation();
3251
+ const { formatMessage } = reactIntl.useIntl();
3252
+ const {
3253
+ list: {
3254
+ settings: { mainField }
3255
+ }
3256
+ } = useDocLayout();
3257
+ const shouldDisplayMainField = mainField != null && mainField !== "id";
3258
+ return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
3259
+ /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
3260
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
3261
+ TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
3262
+ (head) => /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, { ...head }, head.name)
3263
+ )
3264
+ ] }),
3265
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
3266
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
3267
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
3268
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
3269
+ shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
3270
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
3271
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3272
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3273
+ id: "content-manager.success.record.publishing",
3274
+ defaultMessage: "Publishing..."
3275
+ }) }),
3276
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true })
3277
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
3278
+ EntryValidationText,
3279
+ {
3280
+ validationErrors: validationErrors[row.documentId],
3281
+ status: row.status
3282
+ }
3283
+ ) }),
3284
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
3285
+ designSystem.IconButton,
3286
+ {
3287
+ tag: reactRouterDom.Link,
3288
+ to: {
3289
+ pathname: `${pathname}/${row.documentId}`,
3290
+ search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3291
+ },
3292
+ state: { from: pathname },
3293
+ label: formatMessage(
3294
+ { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3295
+ {
3296
+ target: formatMessage(
3297
+ {
3298
+ id: "content-manager.components.ListViewHelperPluginTable.row-line",
3299
+ defaultMessage: "item line {number}"
3300
+ },
3301
+ { number: index2 + 1 }
3302
+ )
3303
+ }
3304
+ ),
3305
+ target: "_blank",
3306
+ marginLeft: "auto",
3307
+ variant: "ghost",
3308
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
3309
+ }
3310
+ ) }) })
3311
+ ] }, row.id)) })
3312
+ ] });
3313
+ };
3314
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
3315
+ const SelectedEntriesModalContent = ({
3316
+ listViewSelectedEntries,
3317
+ toggleModal,
3318
+ setListViewSelectedDocuments,
3319
+ model
3320
+ }) => {
3321
+ const { formatMessage } = reactIntl.useIntl();
3322
+ const { schema, components } = useContentTypeSchema(model);
3323
+ const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
3324
+ const [{ query }] = strapiAdmin.useQueryParams();
3325
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3326
+ const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
3327
+ {
3328
+ model,
3329
+ params: {
3330
+ page: "1",
3331
+ pageSize: documentIds.length.toString(),
3332
+ sort: query.sort,
3333
+ filters: {
3334
+ documentId: {
3335
+ $in: documentIds
3336
+ }
3337
+ },
3338
+ locale: query.plugins?.i18n?.locale
3339
+ }
3340
+ },
3341
+ {
3342
+ selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
3343
+ }
3344
+ );
3345
+ const { rows, validationErrors } = React__namespace.useMemo(() => {
3346
+ if (data.length > 0 && schema) {
3347
+ const validate = createYupSchema(
3348
+ schema.attributes,
3349
+ components,
3350
+ // Since this is the "Publish" action, the validation
3351
+ // schema must enforce the rules for published entities
3352
+ { status: "published" }
3353
+ );
3354
+ const validationErrors2 = {};
3355
+ const rows2 = data.map((entry) => {
3356
+ try {
3357
+ validate.validateSync(entry, { abortEarly: false });
3358
+ return entry;
3359
+ } catch (e) {
3360
+ if (e instanceof yup.ValidationError) {
3361
+ validationErrors2[entry.documentId] = strapiAdmin.getYupValidationErrors(e);
3362
+ }
3363
+ return entry;
3364
+ }
3365
+ });
3366
+ return { rows: rows2, validationErrors: validationErrors2 };
3367
+ }
3368
+ return {
3369
+ rows: [],
3370
+ validationErrors: {}
3371
+ };
3372
+ }, [components, data, schema]);
3373
+ const [publishedCount, setPublishedCount] = React__namespace.useState(0);
3374
+ const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
3375
+ const { publishMany: bulkPublishAction } = useDocumentActions();
3376
+ const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
3377
+ const selectedRows = strapiAdmin.useTable("publishAction", (state) => state.selectedRows);
3378
+ const selectedEntries = rows.filter(
3379
+ (entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
3380
+ );
3381
+ const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
3382
+ const selectedEntriesWithErrorsCount = selectedEntries.filter(
3383
+ ({ documentId }) => validationErrors[documentId]
3384
+ ).length;
3385
+ const selectedEntriesPublished = selectedEntries.filter(
3386
+ ({ status }) => status === "published"
3387
+ ).length;
3388
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3389
+ const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3390
+ const handleConfirmBulkPublish = async () => {
3391
+ toggleDialog();
3392
+ const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3393
+ if (!("error" in res)) {
3394
+ setPublishedCount(res.count);
3395
+ const unpublishedEntries = rows.filter((row) => {
3396
+ return !entriesToPublish.includes(row.documentId);
3397
+ });
3398
+ setListViewSelectedDocuments(unpublishedEntries);
3399
+ }
3400
+ };
3401
+ const getFormattedCountMessage = () => {
3402
+ if (publishedCount) {
3403
+ return formatMessage(
3404
+ {
3405
+ id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3406
+ defaultMessage: "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} published. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
3407
+ },
3408
+ {
3409
+ publishedCount,
3410
+ withErrorsCount: selectedEntriesWithErrorsCount,
3411
+ b: BoldChunk
3412
+ }
3413
+ );
3414
+ }
3415
+ return formatMessage(
3416
+ {
3417
+ id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3418
+ defaultMessage: "<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
3419
+ },
3420
+ {
3421
+ readyToPublishCount: selectedEntriesWithNoErrorsCount,
3422
+ withErrorsCount: selectedEntriesWithErrorsCount,
3423
+ alreadyPublishedCount: selectedEntriesPublished,
3424
+ b: BoldChunk
3425
+ }
3426
+ );
3427
+ };
3428
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3429
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
3430
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
3431
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
3432
+ SelectedEntriesTableContent,
3433
+ {
3434
+ isPublishing: isSubmittingForm,
3435
+ rowsToDisplay: rows,
3436
+ entriesToPublish,
3437
+ validationErrors
3438
+ }
3439
+ ) })
3440
+ ] }),
3441
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3442
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3443
+ id: "app.components.Button.cancel",
3444
+ defaultMessage: "Cancel"
3445
+ }) }),
3446
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3447
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3448
+ /* @__PURE__ */ jsxRuntime.jsx(
3449
+ designSystem.Button,
3450
+ {
3451
+ onClick: toggleDialog,
3452
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3453
+ loading: isSubmittingForm,
3454
+ children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3455
+ }
3456
+ )
3457
+ ] })
3458
+ ] }),
3459
+ /* @__PURE__ */ jsxRuntime.jsx(
3460
+ ConfirmDialogPublishAll,
3461
+ {
3462
+ isOpen: isDialogOpen,
3463
+ onToggleDialog: toggleDialog,
3464
+ isConfirmButtonLoading: isSubmittingForm,
3465
+ onConfirm: handleConfirmBulkPublish
3466
+ }
3467
+ )
3468
+ ] });
3469
+ };
3470
+ const PublishAction = ({ documents, model }) => {
3471
+ const { formatMessage } = reactIntl.useIntl();
3472
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3473
+ const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
3474
+ const setListViewSelectedDocuments = strapiAdmin.useTable("publishAction", (state) => state.selectRow);
3475
+ const refetchList = () => {
3476
+ contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3477
+ };
3478
+ if (!showPublishButton)
3479
+ return null;
3480
+ return {
3481
+ actionType: "publish",
3482
+ variant: "tertiary",
3483
+ label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
3484
+ dialog: {
3485
+ type: "modal",
3486
+ title: formatMessage({
3487
+ id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
3488
+ defaultMessage: "Publish entries"
3489
+ }),
3490
+ content: ({ onClose }) => {
3491
+ return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsxRuntime.jsx(
3492
+ SelectedEntriesModalContent,
3493
+ {
3494
+ listViewSelectedEntries: documents,
3495
+ toggleModal: () => {
3496
+ onClose();
3497
+ refetchList();
3498
+ },
3499
+ setListViewSelectedDocuments,
3500
+ model
3501
+ }
3502
+ ) });
3503
+ },
3504
+ onClose: () => {
3505
+ refetchList();
3506
+ }
3507
+ }
3508
+ };
3509
+ };
3510
+ const BulkActionsRenderer = () => {
3511
+ const plugins = strapiAdmin.useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
3512
+ const { model, collectionType } = useDoc();
3513
+ const { selectedRows } = strapiAdmin.useTable("BulkActionsRenderer", (state) => state);
3514
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
3515
+ strapiAdmin.DescriptionComponentRenderer,
3516
+ {
3517
+ props: {
3518
+ model,
3519
+ collectionType,
3520
+ documents: selectedRows
3521
+ },
3522
+ descriptions: plugins["content-manager"].apis.getBulkActions(),
3523
+ children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...action }, action.id))
3524
+ }
3525
+ ) });
3526
+ };
3527
+ const DeleteAction = ({ documents, model }) => {
3528
+ const { formatMessage } = reactIntl.useIntl();
3529
+ const { schema: contentType } = useDoc();
3530
+ const selectRow = strapiAdmin.useTable("DeleteAction", (state) => state.selectRow);
3531
+ const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
3532
+ const [{ query }] = strapiAdmin.useQueryParams();
3533
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3534
+ const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
3535
+ const { deleteMany: bulkDeleteAction } = useDocumentActions();
3536
+ const documentIds = documents.map(({ documentId }) => documentId);
3537
+ const handleConfirmBulkDelete = async () => {
3538
+ const res = await bulkDeleteAction({
3539
+ documentIds,
3540
+ model,
3541
+ params
3542
+ });
3543
+ if (!("error" in res)) {
3544
+ selectRow([]);
3545
+ }
3546
+ };
3547
+ if (!hasDeletePermission)
3548
+ return null;
3549
+ return {
3550
+ variant: "danger-light",
3551
+ label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
3552
+ dialog: {
3553
+ type: "dialog",
3554
+ title: formatMessage({
3555
+ id: "app.components.ConfirmDialog.title",
3556
+ defaultMessage: "Confirmation"
3557
+ }),
3558
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3559
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3560
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3561
+ id: "popUpWarning.bodyMessage.contentType.delete.all",
3562
+ defaultMessage: "Are you sure you want to delete these entries?"
3563
+ }) }),
3564
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3565
+ {
3566
+ id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
3567
+ defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
3568
+ },
3569
+ {
3570
+ em: Emphasis
3571
+ }
3572
+ ) }) })
3573
+ ] }),
3574
+ onConfirm: handleConfirmBulkDelete
3575
+ }
3576
+ };
3577
+ };
3578
+ DeleteAction.type = "delete";
3579
+ const UnpublishAction = ({ documents, model }) => {
3580
+ const { formatMessage } = reactIntl.useIntl();
3581
+ const { schema } = useDoc();
3582
+ const selectRow = strapiAdmin.useTable("UnpublishAction", (state) => state.selectRow);
3583
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3584
+ const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
3585
+ const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
3586
+ const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
3587
+ const documentIds = documents.map(({ documentId }) => documentId);
3588
+ const [{ query }] = strapiAdmin.useQueryParams();
3589
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3590
+ const handleConfirmBulkUnpublish = async () => {
3591
+ const data = await bulkUnpublishAction({ documentIds, model, params });
3592
+ if (!("error" in data)) {
3593
+ selectRow([]);
3594
+ }
3595
+ };
3596
+ const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3597
+ if (!showUnpublishButton)
3598
+ return null;
3599
+ return {
3600
+ variant: "tertiary",
3601
+ label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
3602
+ dialog: {
3603
+ type: "dialog",
3604
+ title: formatMessage({
3605
+ id: "app.components.ConfirmDialog.title",
3606
+ defaultMessage: "Confirmation"
3607
+ }),
3608
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3609
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3610
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3611
+ id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3612
+ defaultMessage: "Are you sure you want to unpublish these entries?"
3613
+ }) }),
3614
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3615
+ {
3616
+ id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
3617
+ defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
3618
+ },
3619
+ {
3620
+ em: Emphasis
3621
+ }
3622
+ ) }) })
3623
+ ] }),
3624
+ confirmButton: formatMessage({
3625
+ id: "app.utils.unpublish",
3626
+ defaultMessage: "Unpublish"
3627
+ }),
3628
+ onConfirm: handleConfirmBulkUnpublish
3629
+ }
3630
+ };
3631
+ };
3632
+ UnpublishAction.type = "unpublish";
3633
+ const Emphasis = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
3634
+ const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
2467
3635
  const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
2468
3636
  const { formatMessage } = reactIntl.useIntl();
2469
3637
  const getDefaultErrorMessage = (reason) => {
@@ -2495,7 +3663,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
2495
3663
  hasRadius: true,
2496
3664
  padding: 6,
2497
3665
  children: [
2498
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", as: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", as: "li", children: [
3666
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", tag: "li", children: [
2499
3667
  pathSegment,
2500
3668
  index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
2501
3669
  Icons.ChevronRight,
@@ -2507,7 +3675,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
2507
3675
  }
2508
3676
  )
2509
3677
  ] }, index2)) }),
2510
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "p", textColor: "neutral600", children: formatMessage({
3678
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
2511
3679
  id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
2512
3680
  defaultMessage: getDefaultErrorMessage(reason)
2513
3681
  }) })
@@ -2532,7 +3700,7 @@ const TableActions = ({ document }) => {
2532
3700
  strapiAdmin.DescriptionComponentRenderer,
2533
3701
  {
2534
3702
  props,
2535
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3703
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
2536
3704
  children: (actions2) => {
2537
3705
  const tableRowActions = actions2.filter((action) => {
2538
3706
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -2591,7 +3759,7 @@ const EditAction = ({ documentId }) => {
2591
3759
  };
2592
3760
  };
2593
3761
  EditAction.type = "edit";
2594
- const StyledPencil = styled__default.default(Icons.Pencil)`
3762
+ const StyledPencil = styledComponents.styled(Icons.Pencil)`
2595
3763
  path {
2596
3764
  fill: currentColor;
2597
3765
  }
@@ -2643,7 +3811,7 @@ const CloneAction = ({ model, documentId }) => {
2643
3811
  }),
2644
3812
  content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
2645
3813
  footer: ({ onClose }) => {
2646
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3814
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
2647
3815
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
2648
3816
  id: "cancel",
2649
3817
  defaultMessage: "Cancel"
@@ -2651,7 +3819,7 @@ const CloneAction = ({ model, documentId }) => {
2651
3819
  /* @__PURE__ */ jsxRuntime.jsx(
2652
3820
  designSystem.LinkButton,
2653
3821
  {
2654
- as: reactRouterDom.NavLink,
3822
+ tag: reactRouterDom.NavLink,
2655
3823
  to: {
2656
3824
  pathname: `clone/${documentId}`
2657
3825
  },
@@ -2667,7 +3835,7 @@ const CloneAction = ({ model, documentId }) => {
2667
3835
  };
2668
3836
  };
2669
3837
  CloneAction.type = "clone";
2670
- const StyledDuplicate = styled__default.default(Icons.Duplicate)`
3838
+ const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
2671
3839
  path {
2672
3840
  fill: currentColor;
2673
3841
  }
@@ -2684,442 +3852,192 @@ class ContentManagerPlugin {
2684
3852
  documentActions = [
2685
3853
  ...DEFAULT_ACTIONS,
2686
3854
  ...DEFAULT_TABLE_ROW_ACTIONS,
2687
- ...DEFAULT_HEADER_ACTIONS,
2688
- HistoryAction
3855
+ ...DEFAULT_HEADER_ACTIONS
2689
3856
  ];
2690
3857
  editViewSidePanels = [ActionsPanel];
2691
3858
  headerActions = [];
2692
3859
  constructor() {
2693
3860
  }
2694
3861
  addEditViewSidePanel(panels) {
2695
- if (Array.isArray(panels)) {
2696
- this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
2697
- } else if (typeof panels === "function") {
2698
- this.editViewSidePanels = panels(this.editViewSidePanels);
2699
- } else {
2700
- throw new Error(
2701
- `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
2702
- panels
2703
- )}`
2704
- );
2705
- }
2706
- }
2707
- addDocumentAction(actions2) {
2708
- if (Array.isArray(actions2)) {
2709
- this.documentActions = [...this.documentActions, ...actions2];
2710
- } else if (typeof actions2 === "function") {
2711
- this.documentActions = actions2(this.documentActions);
2712
- } else {
2713
- throw new Error(
2714
- `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
2715
- actions2
2716
- )}`
2717
- );
2718
- }
2719
- }
2720
- addDocumentHeaderAction(actions2) {
2721
- if (Array.isArray(actions2)) {
2722
- this.headerActions = [...this.headerActions, ...actions2];
2723
- } else if (typeof actions2 === "function") {
2724
- this.headerActions = actions2(this.headerActions);
3862
+ if (Array.isArray(panels)) {
3863
+ this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
3864
+ } else if (typeof panels === "function") {
3865
+ this.editViewSidePanels = panels(this.editViewSidePanels);
2725
3866
  } else {
2726
3867
  throw new Error(
2727
- `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
2728
- actions2
3868
+ `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
3869
+ panels
2729
3870
  )}`
2730
3871
  );
2731
3872
  }
2732
3873
  }
2733
- addBulkAction(actions2) {
3874
+ addDocumentAction(actions2) {
2734
3875
  if (Array.isArray(actions2)) {
2735
- this.bulkActions = [...this.bulkActions, ...actions2];
3876
+ this.documentActions = [...this.documentActions, ...actions2];
2736
3877
  } else if (typeof actions2 === "function") {
2737
- this.bulkActions = actions2(this.bulkActions);
3878
+ this.documentActions = actions2(this.documentActions);
2738
3879
  } else {
2739
3880
  throw new Error(
2740
- `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3881
+ `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
2741
3882
  actions2
2742
- )}`
2743
- );
2744
- }
2745
- }
2746
- get config() {
2747
- return {
2748
- id: PLUGIN_ID,
2749
- name: "Content Manager",
2750
- injectionZones: INJECTION_ZONES,
2751
- apis: {
2752
- addBulkAction: this.addBulkAction.bind(this),
2753
- addDocumentAction: this.addDocumentAction.bind(this),
2754
- addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
2755
- addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
2756
- getBulkActions: () => this.bulkActions,
2757
- getDocumentActions: () => this.documentActions,
2758
- getEditViewSidePanels: () => this.editViewSidePanels,
2759
- getHeaderActions: () => this.headerActions
2760
- }
2761
- };
2762
- }
2763
- }
2764
- const getPrintableType = (value) => {
2765
- const nativeType = typeof value;
2766
- if (nativeType === "object") {
2767
- if (value === null)
2768
- return "null";
2769
- if (Array.isArray(value))
2770
- return "array";
2771
- if (value instanceof Object && value.constructor.name !== "Object") {
2772
- return value.constructor.name;
2773
- }
2774
- }
2775
- return nativeType;
2776
- };
2777
- const initialState = {
2778
- collectionTypeLinks: [],
2779
- components: [],
2780
- fieldSizes: {},
2781
- models: [],
2782
- singleTypeLinks: [],
2783
- isLoading: true
2784
- };
2785
- const appSlice = toolkit.createSlice({
2786
- name: "app",
2787
- initialState,
2788
- reducers: {
2789
- setInitialData(state, action) {
2790
- const {
2791
- authorizedCollectionTypeLinks,
2792
- authorizedSingleTypeLinks,
2793
- components,
2794
- contentTypeSchemas,
2795
- fieldSizes
2796
- } = action.payload;
2797
- state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
2798
- ({ isDisplayed }) => isDisplayed
2799
- );
2800
- state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
2801
- state.components = components;
2802
- state.models = contentTypeSchemas;
2803
- state.fieldSizes = fieldSizes;
2804
- state.isLoading = false;
2805
- }
2806
- }
2807
- });
2808
- const { actions, reducer: reducer$1 } = appSlice;
2809
- const { setInitialData } = actions;
2810
- const reducer = toolkit.combineReducers({
2811
- app: reducer$1
2812
- });
2813
- const HOOKS = {
2814
- /**
2815
- * Hook that allows to mutate the displayed headers of the list view table
2816
- * @constant
2817
- * @type {string}
2818
- */
2819
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2820
- /**
2821
- * Hook that allows to mutate the CM's collection types links pre-set filters
2822
- * @constant
2823
- * @type {string}
2824
- */
2825
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2826
- /**
2827
- * Hook that allows to mutate the CM's edit view layout
2828
- * @constant
2829
- * @type {string}
2830
- */
2831
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2832
- /**
2833
- * Hook that allows to mutate the CM's single types links pre-set filters
2834
- * @constant
2835
- * @type {string}
2836
- */
2837
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2838
- };
2839
- const contentTypesApi = contentManagerApi.injectEndpoints({
2840
- endpoints: (builder) => ({
2841
- getContentTypeConfiguration: builder.query({
2842
- query: (uid) => ({
2843
- url: `/content-manager/content-types/${uid}/configuration`,
2844
- method: "GET"
2845
- }),
2846
- transformResponse: (response) => response.data,
2847
- providesTags: (_result, _error, uid) => [
2848
- { type: "ContentTypesConfiguration", id: uid },
2849
- { type: "ContentTypeSettings", id: "LIST" }
2850
- ]
2851
- }),
2852
- getAllContentTypeSettings: builder.query({
2853
- query: () => "/content-manager/content-types-settings",
2854
- transformResponse: (response) => response.data,
2855
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2856
- }),
2857
- updateContentTypeConfiguration: builder.mutation({
2858
- query: ({ uid, ...body }) => ({
2859
- url: `/content-manager/content-types/${uid}/configuration`,
2860
- method: "PUT",
2861
- data: body
2862
- }),
2863
- transformResponse: (response) => response.data,
2864
- invalidatesTags: (_result, _error, { uid }) => [
2865
- { type: "ContentTypesConfiguration", id: uid },
2866
- { type: "ContentTypeSettings", id: "LIST" },
2867
- // Is this necessary?
2868
- { type: "InitialData" }
2869
- ]
2870
- })
2871
- })
2872
- });
2873
- const {
2874
- useGetContentTypeConfigurationQuery,
2875
- useGetAllContentTypeSettingsQuery,
2876
- useUpdateContentTypeConfigurationMutation
2877
- } = contentTypesApi;
2878
- const checkIfAttributeIsDisplayable = (attribute) => {
2879
- const { type } = attribute;
2880
- if (type === "relation") {
2881
- return !attribute.relation.toLowerCase().includes("morph");
2882
- }
2883
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2884
- };
2885
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2886
- if (!mainFieldName) {
2887
- return void 0;
2888
- }
2889
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2890
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2891
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2892
- );
2893
- return {
2894
- name: mainFieldName,
2895
- type: mainFieldType ?? "string"
2896
- };
2897
- };
2898
- const DEFAULT_SETTINGS = {
2899
- bulkable: false,
2900
- filterable: false,
2901
- searchable: false,
2902
- pagination: false,
2903
- defaultSortBy: "",
2904
- defaultSortOrder: "asc",
2905
- mainField: "id",
2906
- pageSize: 10
2907
- };
2908
- const useDocumentLayout = (model) => {
2909
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2910
- const [{ query }] = strapiAdmin.useQueryParams();
2911
- const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2912
- const { toggleNotification } = strapiAdmin.useNotification();
2913
- const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2914
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2915
- const {
2916
- data,
2917
- isLoading: isLoadingConfigs,
2918
- error,
2919
- isFetching: isFetchingConfigs
2920
- } = useGetContentTypeConfigurationQuery(model);
2921
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2922
- React__namespace.useEffect(() => {
2923
- if (error) {
2924
- toggleNotification({
2925
- type: "danger",
2926
- message: formatAPIError(error)
2927
- });
2928
- }
2929
- }, [error, formatAPIError, toggleNotification]);
2930
- const editLayout = React__namespace.useMemo(
2931
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2932
- layout: [],
2933
- components: {},
2934
- metadatas: {},
2935
- options: {},
2936
- settings: DEFAULT_SETTINGS
2937
- },
2938
- [data, isLoading, schemas, schema, components]
2939
- );
2940
- const listLayout = React__namespace.useMemo(() => {
2941
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2942
- layout: [],
2943
- metadatas: {},
2944
- options: {},
2945
- settings: DEFAULT_SETTINGS
2946
- };
2947
- }, [data, isLoading, schemas, schema, components]);
2948
- const { layout: edit } = React__namespace.useMemo(
2949
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2950
- layout: editLayout,
2951
- query
2952
- }),
2953
- [editLayout, query, runHookWaterfall]
2954
- );
2955
- return {
2956
- error,
2957
- isLoading,
2958
- edit,
2959
- list: listLayout
2960
- };
2961
- };
2962
- const useDocLayout = () => {
2963
- const { model } = useDoc();
2964
- return useDocumentLayout(model);
2965
- };
2966
- const formatEditLayout = (data, {
2967
- schemas,
2968
- schema,
2969
- components
2970
- }) => {
2971
- let currentPanelIndex = 0;
2972
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2973
- data.contentType.layouts.edit,
2974
- schema?.attributes,
2975
- data.contentType.metadatas,
2976
- { configurations: data.components, schemas: components },
2977
- schemas
2978
- ).reduce((panels, row) => {
2979
- if (row.some((field) => field.type === "dynamiczone")) {
2980
- panels.push([row]);
2981
- currentPanelIndex += 2;
3883
+ )}`
3884
+ );
3885
+ }
3886
+ }
3887
+ addDocumentHeaderAction(actions2) {
3888
+ if (Array.isArray(actions2)) {
3889
+ this.headerActions = [...this.headerActions, ...actions2];
3890
+ } else if (typeof actions2 === "function") {
3891
+ this.headerActions = actions2(this.headerActions);
2982
3892
  } else {
2983
- if (!panels[currentPanelIndex]) {
2984
- panels.push([]);
2985
- }
2986
- panels[currentPanelIndex].push(row);
3893
+ throw new Error(
3894
+ `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
3895
+ actions2
3896
+ )}`
3897
+ );
2987
3898
  }
2988
- return panels;
2989
- }, []);
2990
- const componentEditAttributes = Object.entries(data.components).reduce(
2991
- (acc, [uid, configuration]) => {
2992
- acc[uid] = {
2993
- layout: convertEditLayoutToFieldLayouts(
2994
- configuration.layouts.edit,
2995
- components[uid].attributes,
2996
- configuration.metadatas
2997
- ),
2998
- settings: {
2999
- ...configuration.settings,
3000
- icon: components[uid].info.icon,
3001
- displayName: components[uid].info.displayName
3002
- }
3003
- };
3004
- return acc;
3005
- },
3006
- {}
3007
- );
3008
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
3009
- (acc, [attribute, metadata]) => {
3010
- return {
3011
- ...acc,
3012
- [attribute]: metadata.edit
3013
- };
3014
- },
3015
- {}
3016
- );
3017
- return {
3018
- layout: panelledEditAttributes,
3019
- components: componentEditAttributes,
3020
- metadatas: editMetadatas,
3021
- settings: {
3022
- ...data.contentType.settings,
3023
- displayName: schema?.info.displayName
3024
- },
3025
- options: {
3026
- ...schema?.options,
3027
- ...schema?.pluginOptions,
3028
- ...data.contentType.options
3899
+ }
3900
+ addBulkAction(actions2) {
3901
+ if (Array.isArray(actions2)) {
3902
+ this.bulkActions = [...this.bulkActions, ...actions2];
3903
+ } else if (typeof actions2 === "function") {
3904
+ this.bulkActions = actions2(this.bulkActions);
3905
+ } else {
3906
+ throw new Error(
3907
+ `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3908
+ actions2
3909
+ )}`
3910
+ );
3029
3911
  }
3030
- };
3031
- };
3032
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
3033
- return rows.map(
3034
- (row) => row.map((field) => {
3035
- const attribute = attributes[field.name];
3036
- if (!attribute) {
3037
- return null;
3912
+ }
3913
+ get config() {
3914
+ return {
3915
+ id: PLUGIN_ID,
3916
+ name: "Content Manager",
3917
+ injectionZones: INJECTION_ZONES,
3918
+ apis: {
3919
+ addBulkAction: this.addBulkAction.bind(this),
3920
+ addDocumentAction: this.addDocumentAction.bind(this),
3921
+ addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3922
+ addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3923
+ getBulkActions: () => this.bulkActions,
3924
+ getDocumentActions: () => this.documentActions,
3925
+ getEditViewSidePanels: () => this.editViewSidePanels,
3926
+ getHeaderActions: () => this.headerActions
3038
3927
  }
3039
- const { edit: metadata } = metadatas[field.name];
3040
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3041
- return {
3042
- attribute,
3043
- disabled: !metadata.editable,
3044
- hint: metadata.description,
3045
- label: metadata.label ?? "",
3046
- name: field.name,
3047
- // @ts-expect-error – mainField does exist on the metadata for a relation.
3048
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
3049
- schemas,
3050
- components: components?.schemas ?? {}
3051
- }),
3052
- placeholder: metadata.placeholder ?? "",
3053
- required: attribute.required ?? false,
3054
- size: field.size,
3055
- unique: "unique" in attribute ? attribute.unique : false,
3056
- visible: metadata.visible ?? true,
3057
- type: attribute.type
3058
- };
3059
- }).filter((field) => field !== null)
3060
- );
3928
+ };
3929
+ }
3930
+ }
3931
+ const getPrintableType = (value) => {
3932
+ const nativeType = typeof value;
3933
+ if (nativeType === "object") {
3934
+ if (value === null)
3935
+ return "null";
3936
+ if (Array.isArray(value))
3937
+ return "array";
3938
+ if (value instanceof Object && value.constructor.name !== "Object") {
3939
+ return value.constructor.name;
3940
+ }
3941
+ }
3942
+ return nativeType;
3061
3943
  };
3062
- const formatListLayout = (data, {
3063
- schemas,
3064
- schema,
3065
- components
3066
- }) => {
3067
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
3068
- (acc, [attribute, metadata]) => {
3069
- return {
3070
- ...acc,
3071
- [attribute]: metadata.list
3072
- };
3073
- },
3074
- {}
3075
- );
3076
- const listAttributes = convertListLayoutToFieldLayouts(
3077
- data.contentType.layouts.list,
3078
- schema?.attributes,
3079
- listMetadatas,
3080
- { configurations: data.components, schemas: components },
3081
- schemas
3082
- );
3944
+ const HistoryAction = ({ model, document }) => {
3945
+ const { formatMessage } = reactIntl.useIntl();
3946
+ const [{ query }] = strapiAdmin.useQueryParams();
3947
+ const navigate = reactRouterDom.useNavigate();
3948
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3949
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3950
+ return null;
3951
+ }
3083
3952
  return {
3084
- layout: listAttributes,
3085
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
3086
- metadatas: listMetadatas,
3087
- options: {
3088
- ...schema?.options,
3089
- ...schema?.pluginOptions,
3090
- ...data.contentType.options
3091
- }
3953
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3954
+ label: formatMessage({
3955
+ id: "content-manager.history.document-action",
3956
+ defaultMessage: "Content History"
3957
+ }),
3958
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3959
+ disabled: (
3960
+ /**
3961
+ * The user is creating a new document.
3962
+ * It hasn't been saved yet, so there's no history to go to
3963
+ */
3964
+ !document || /**
3965
+ * The document has been created but the current dimension has never been saved.
3966
+ * For example, the user is creating a new locale in an existing document,
3967
+ * so there's no history for the document in that locale
3968
+ */
3969
+ !document.id || /**
3970
+ * History is only available for content types created by the user.
3971
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3972
+ * which start with `admin::` or `plugin::`
3973
+ */
3974
+ !model.startsWith("api::")
3975
+ ),
3976
+ position: "header"
3092
3977
  };
3093
3978
  };
3094
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
3095
- return columns.map((name) => {
3096
- const attribute = attributes[name];
3097
- if (!attribute) {
3098
- return null;
3979
+ HistoryAction.type = "history";
3980
+ const historyAdmin = {
3981
+ bootstrap(app) {
3982
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3983
+ addDocumentAction((actions2) => {
3984
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3985
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3986
+ return actions2;
3987
+ });
3988
+ }
3989
+ };
3990
+ const initialState = {
3991
+ collectionTypeLinks: [],
3992
+ components: [],
3993
+ fieldSizes: {},
3994
+ models: [],
3995
+ singleTypeLinks: [],
3996
+ isLoading: true
3997
+ };
3998
+ const appSlice = toolkit.createSlice({
3999
+ name: "app",
4000
+ initialState,
4001
+ reducers: {
4002
+ setInitialData(state, action) {
4003
+ const {
4004
+ authorizedCollectionTypeLinks,
4005
+ authorizedSingleTypeLinks,
4006
+ components,
4007
+ contentTypeSchemas,
4008
+ fieldSizes
4009
+ } = action.payload;
4010
+ state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
4011
+ ({ isDisplayed }) => isDisplayed
4012
+ );
4013
+ state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
4014
+ state.components = components;
4015
+ state.models = contentTypeSchemas;
4016
+ state.fieldSizes = fieldSizes;
4017
+ state.isLoading = false;
3099
4018
  }
3100
- const metadata = metadatas[name];
3101
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3102
- return {
3103
- attribute,
3104
- label: metadata.label ?? "",
3105
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
3106
- schemas,
3107
- components: components?.schemas ?? {}
3108
- }),
3109
- name,
3110
- searchable: metadata.searchable ?? true,
3111
- sortable: metadata.sortable ?? true
3112
- };
3113
- }).filter((field) => field !== null);
4019
+ }
4020
+ });
4021
+ const { actions, reducer: reducer$1 } = appSlice;
4022
+ const { setInitialData } = actions;
4023
+ const reducer = toolkit.combineReducers({
4024
+ app: reducer$1
4025
+ });
4026
+ const FEATURE_ID = "preview";
4027
+ const previewAdmin = {
4028
+ bootstrap(app) {
4029
+ if (!window.strapi.future.isEnabled(FEATURE_ID)) {
4030
+ return {};
4031
+ }
4032
+ console.log("Bootstrapping preview admin");
4033
+ }
3114
4034
  };
3115
4035
  const index = {
3116
4036
  register(app) {
3117
4037
  const cm = new ContentManagerPlugin();
3118
4038
  app.addReducers({
3119
- [contentManagerApi.reducerPath]: contentManagerApi.reducer,
3120
4039
  [PLUGIN_ID]: reducer
3121
4040
  });
3122
- app.addMiddlewares([() => contentManagerApi.middleware]);
3123
4041
  app.addMenuLink({
3124
4042
  to: PLUGIN_ID,
3125
4043
  icon: Icons.Feather,
@@ -3128,14 +4046,32 @@ const index = {
3128
4046
  defaultMessage: "Content Manager"
3129
4047
  },
3130
4048
  permissions: [],
3131
- Component: () => Promise.resolve().then(() => require("./layout-BqtLA6Lb.js")).then((mod) => ({ default: mod.Layout }))
4049
+ position: 1
4050
+ });
4051
+ app.router.addRoute({
4052
+ path: "content-manager/*",
4053
+ lazy: async () => {
4054
+ const { Layout } = await Promise.resolve().then(() => require("./layout-lMc9i1-Z.js"));
4055
+ return {
4056
+ Component: Layout
4057
+ };
4058
+ },
4059
+ children: routes
3132
4060
  });
3133
4061
  app.registerPlugin(cm.config);
3134
4062
  },
4063
+ bootstrap(app) {
4064
+ if (typeof historyAdmin.bootstrap === "function") {
4065
+ historyAdmin.bootstrap(app);
4066
+ }
4067
+ if (typeof previewAdmin.bootstrap === "function") {
4068
+ previewAdmin.bootstrap(app);
4069
+ }
4070
+ },
3135
4071
  async registerTrads({ locales }) {
3136
4072
  const importedTrads = await Promise.all(
3137
4073
  locales.map((locale) => {
3138
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-C-V1_90f.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
4074
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-Bm0D0IWz.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
3139
4075
  return {
3140
4076
  data: prefixPluginTranslations(data, PLUGIN_ID),
3141
4077
  locale
@@ -3152,6 +4088,8 @@ const index = {
3152
4088
  }
3153
4089
  };
3154
4090
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
4091
+ exports.BulkActionsRenderer = BulkActionsRenderer;
4092
+ exports.CLONE_PATH = CLONE_PATH;
3155
4093
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3156
4094
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3157
4095
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3178,8 +4116,8 @@ exports.getDisplayName = getDisplayName;
3178
4116
  exports.getMainField = getMainField;
3179
4117
  exports.getTranslation = getTranslation;
3180
4118
  exports.index = index;
3181
- exports.routes = routes;
3182
4119
  exports.setInitialData = setInitialData;
4120
+ exports.useContentManagerContext = useContentManagerContext;
3183
4121
  exports.useContentTypeSchema = useContentTypeSchema;
3184
4122
  exports.useDoc = useDoc;
3185
4123
  exports.useDocLayout = useDocLayout;
@@ -3192,4 +4130,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3192
4130
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3193
4131
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3194
4132
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3195
- //# sourceMappingURL=index-DNa1J4HE.js.map
4133
+ //# sourceMappingURL=index-BIWDoFLK.js.map