@strapi/content-manager 0.0.0-experimental.a65a85fdea97faae8679d3ffc5f9d79af61abd26 → 0.0.0-experimental.a9a5a36dd73072c19eadeff5f387e8286b2a4d22

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 (182) 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--2aLCv-G.mjs → ComponentConfigurationPage-B1bIXVuX.mjs} +3 -3
  7. package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs.map → ComponentConfigurationPage-B1bIXVuX.mjs.map} +1 -1
  8. package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js → ComponentConfigurationPage-Bqgx7Mes.js} +3 -3
  9. package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js.map → ComponentConfigurationPage-Bqgx7Mes.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-BfFzJ4Br.js → EditConfigurationPage-BFEwvdMW.js} +3 -3
  15. package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js.map → EditConfigurationPage-BFEwvdMW.js.map} +1 -1
  16. package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs → EditConfigurationPage-ZO0vOO8q.mjs} +3 -3
  17. package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs.map → EditConfigurationPage-ZO0vOO8q.mjs.map} +1 -1
  18. package/dist/_chunks/{EditViewPage-CzOT5Kpj.js → EditViewPage-DA95Ha6J.js} +46 -48
  19. package/dist/_chunks/EditViewPage-DA95Ha6J.js.map +1 -0
  20. package/dist/_chunks/{EditViewPage-Bm8lgcm6.mjs → EditViewPage-DlLEyUL6.mjs} +47 -47
  21. package/dist/_chunks/EditViewPage-DlLEyUL6.mjs.map +1 -0
  22. package/dist/_chunks/{Field-Caef4JjM.js → Field-CnK8dO8N.js} +948 -777
  23. package/dist/_chunks/Field-CnK8dO8N.js.map +1 -0
  24. package/dist/_chunks/{Field-Dlh0uGnL.mjs → Field-Dq7bDnuh.mjs} +896 -724
  25. package/dist/_chunks/Field-Dq7bDnuh.mjs.map +1 -0
  26. package/dist/_chunks/{Form-EnaQL_6L.mjs → Form-B_JE0dbz.mjs} +43 -41
  27. package/dist/_chunks/Form-B_JE0dbz.mjs.map +1 -0
  28. package/dist/_chunks/{Form-BzuAjtRq.js → Form-BpiR4piS.js} +42 -41
  29. package/dist/_chunks/Form-BpiR4piS.js.map +1 -0
  30. package/dist/_chunks/{History-D6sbCJvo.mjs → History-CBNGU7a-.mjs} +149 -65
  31. package/dist/_chunks/History-CBNGU7a-.mjs.map +1 -0
  32. package/dist/_chunks/{History-C17LiyRg.js → History-DdIstl8b.js} +149 -66
  33. package/dist/_chunks/History-DdIstl8b.js.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-Ce4qs7qE.mjs → ListConfigurationPage-5dr4qpue.mjs} +58 -58
  35. package/dist/_chunks/ListConfigurationPage-5dr4qpue.mjs.map +1 -0
  36. package/dist/_chunks/{ListConfigurationPage-Dks5SX6f.js → ListConfigurationPage-DkKRparB.js} +61 -62
  37. package/dist/_chunks/ListConfigurationPage-DkKRparB.js.map +1 -0
  38. package/dist/_chunks/{ListViewPage-Be7S5aKL.mjs → ListViewPage-DecLrYV6.mjs} +90 -106
  39. package/dist/_chunks/ListViewPage-DecLrYV6.mjs.map +1 -0
  40. package/dist/_chunks/{ListViewPage-BwrZrPsh.js → ListViewPage-wE0lXqoD.js} +95 -111
  41. package/dist/_chunks/ListViewPage-wE0lXqoD.js.map +1 -0
  42. package/dist/_chunks/{NoContentTypePage-CIPmYQMm.mjs → NoContentTypePage-CiIcfYsd.mjs} +7 -7
  43. package/dist/_chunks/NoContentTypePage-CiIcfYsd.mjs.map +1 -0
  44. package/dist/_chunks/{NoContentTypePage-Cu5r1-JT.js → NoContentTypePage-DEKR6tf9.js} +5 -5
  45. package/dist/_chunks/NoContentTypePage-DEKR6tf9.js.map +1 -0
  46. package/dist/_chunks/{NoPermissionsPage-DhJ7LYrr.mjs → NoPermissionsPage-CM5UD8ee.mjs} +5 -6
  47. package/dist/_chunks/NoPermissionsPage-CM5UD8ee.mjs.map +1 -0
  48. package/dist/_chunks/{NoPermissionsPage-C-j6TEUF.js → NoPermissionsPage-DmNfF2Bb.js} +4 -5
  49. package/dist/_chunks/NoPermissionsPage-DmNfF2Bb.js.map +1 -0
  50. package/dist/_chunks/{Relations-CY7AtkDA.mjs → Relations-Dqz0C1fz.mjs} +66 -56
  51. package/dist/_chunks/Relations-Dqz0C1fz.mjs.map +1 -0
  52. package/dist/_chunks/{Relations-Czs-uZ-s.js → Relations-L0xYRoSQ.js} +70 -61
  53. package/dist/_chunks/Relations-L0xYRoSQ.js.map +1 -0
  54. package/dist/_chunks/{en-MBPul9Su.mjs → en-BrCTWlZv.mjs} +11 -4
  55. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-BrCTWlZv.mjs.map} +1 -1
  56. package/dist/_chunks/{en-C-V1_90f.js → en-uOUIxfcQ.js} +11 -4
  57. package/dist/_chunks/{en-C-V1_90f.js.map → en-uOUIxfcQ.js.map} +1 -1
  58. package/dist/_chunks/{index-DNVx8ssZ.mjs → index-BSn97i8U.mjs} +1644 -911
  59. package/dist/_chunks/index-BSn97i8U.mjs.map +1 -0
  60. package/dist/_chunks/{index-X_2tafck.js → index-DyvUPg1a.js} +1622 -890
  61. package/dist/_chunks/index-DyvUPg1a.js.map +1 -0
  62. package/dist/_chunks/{layout-Dnh0PNp9.mjs → layout-DPaHUusj.mjs} +32 -27
  63. package/dist/_chunks/layout-DPaHUusj.mjs.map +1 -0
  64. package/dist/_chunks/{layout-dBc7wN7L.js → layout-TPqF2oJ5.js} +32 -29
  65. package/dist/_chunks/layout-TPqF2oJ5.js.map +1 -0
  66. package/dist/_chunks/{relations-4pHtBrHJ.js → relations-BWYS9gkn.js} +2 -2
  67. package/dist/_chunks/{relations-4pHtBrHJ.js.map → relations-BWYS9gkn.js.map} +1 -1
  68. package/dist/_chunks/{relations-Dx7tMKJN.mjs → relations-Ck7-ecDT.mjs} +2 -2
  69. package/dist/_chunks/{relations-Dx7tMKJN.mjs.map → relations-Ck7-ecDT.mjs.map} +1 -1
  70. package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
  71. package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
  72. package/dist/_chunks/usePrev-B9w_-eYc.js +15 -0
  73. package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -0
  74. package/dist/_chunks/usePrev-DH6iah0A.mjs +16 -0
  75. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +1 -0
  76. package/dist/admin/index.js +2 -1
  77. package/dist/admin/index.js.map +1 -1
  78. package/dist/admin/index.mjs +5 -4
  79. package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
  80. package/dist/admin/src/content-manager.d.ts +3 -3
  81. package/dist/admin/src/exports.d.ts +1 -0
  82. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
  83. package/dist/admin/src/history/index.d.ts +3 -0
  84. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  85. package/dist/admin/src/hooks/useDocument.d.ts +5 -8
  86. package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
  87. package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
  88. package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
  89. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
  90. package/dist/admin/src/index.d.ts +1 -0
  91. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +11 -4
  92. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
  93. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  94. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
  95. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  96. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  97. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +30 -18
  98. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  99. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  100. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  101. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +59 -52
  102. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  103. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  104. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  105. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  106. package/dist/admin/src/services/api.d.ts +2 -3
  107. package/dist/admin/src/services/components.d.ts +2 -2
  108. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  109. package/dist/admin/src/services/documents.d.ts +29 -17
  110. package/dist/admin/src/services/init.d.ts +2 -2
  111. package/dist/admin/src/services/relations.d.ts +3 -3
  112. package/dist/admin/src/services/uid.d.ts +3 -3
  113. package/dist/admin/src/utils/api.d.ts +4 -18
  114. package/dist/admin/src/utils/validation.d.ts +1 -6
  115. package/dist/server/index.js +547 -416
  116. package/dist/server/index.js.map +1 -1
  117. package/dist/server/index.mjs +555 -424
  118. package/dist/server/index.mjs.map +1 -1
  119. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  120. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  121. package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
  122. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  123. package/dist/server/src/controllers/validation/dimensions.d.ts +9 -0
  124. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  125. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  126. package/dist/server/src/history/services/history.d.ts +2 -4
  127. package/dist/server/src/history/services/history.d.ts.map +1 -1
  128. package/dist/server/src/history/services/index.d.ts +6 -2
  129. package/dist/server/src/history/services/index.d.ts.map +1 -1
  130. package/dist/server/src/history/services/lifecycles.d.ts +9 -0
  131. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -0
  132. package/dist/server/src/history/services/utils.d.ts +41 -9
  133. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  134. package/dist/server/src/history/utils.d.ts +6 -2
  135. package/dist/server/src/history/utils.d.ts.map +1 -1
  136. package/dist/server/src/index.d.ts +18 -39
  137. package/dist/server/src/index.d.ts.map +1 -1
  138. package/dist/server/src/services/document-manager.d.ts +13 -12
  139. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  140. package/dist/server/src/services/document-metadata.d.ts +8 -29
  141. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  142. package/dist/server/src/services/index.d.ts +18 -39
  143. package/dist/server/src/services/index.d.ts.map +1 -1
  144. package/dist/server/src/services/utils/populate.d.ts +8 -1
  145. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  146. package/dist/shared/contracts/collection-types.d.ts +14 -6
  147. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  148. package/dist/shared/contracts/relations.d.ts +2 -2
  149. package/dist/shared/contracts/relations.d.ts.map +1 -1
  150. package/package.json +13 -14
  151. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  152. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  153. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  154. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  155. package/dist/_chunks/EditViewPage-Bm8lgcm6.mjs.map +0 -1
  156. package/dist/_chunks/EditViewPage-CzOT5Kpj.js.map +0 -1
  157. package/dist/_chunks/Field-Caef4JjM.js.map +0 -1
  158. package/dist/_chunks/Field-Dlh0uGnL.mjs.map +0 -1
  159. package/dist/_chunks/Form-BzuAjtRq.js.map +0 -1
  160. package/dist/_chunks/Form-EnaQL_6L.mjs.map +0 -1
  161. package/dist/_chunks/History-C17LiyRg.js.map +0 -1
  162. package/dist/_chunks/History-D6sbCJvo.mjs.map +0 -1
  163. package/dist/_chunks/ListConfigurationPage-Ce4qs7qE.mjs.map +0 -1
  164. package/dist/_chunks/ListConfigurationPage-Dks5SX6f.js.map +0 -1
  165. package/dist/_chunks/ListViewPage-Be7S5aKL.mjs.map +0 -1
  166. package/dist/_chunks/ListViewPage-BwrZrPsh.js.map +0 -1
  167. package/dist/_chunks/NoContentTypePage-CIPmYQMm.mjs.map +0 -1
  168. package/dist/_chunks/NoContentTypePage-Cu5r1-JT.js.map +0 -1
  169. package/dist/_chunks/NoPermissionsPage-C-j6TEUF.js.map +0 -1
  170. package/dist/_chunks/NoPermissionsPage-DhJ7LYrr.mjs.map +0 -1
  171. package/dist/_chunks/Relations-CY7AtkDA.mjs.map +0 -1
  172. package/dist/_chunks/Relations-Czs-uZ-s.js.map +0 -1
  173. package/dist/_chunks/index-DNVx8ssZ.mjs.map +0 -1
  174. package/dist/_chunks/index-X_2tafck.js.map +0 -1
  175. package/dist/_chunks/layout-Dnh0PNp9.mjs.map +0 -1
  176. package/dist/_chunks/layout-dBc7wN7L.js.map +0 -1
  177. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  178. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  179. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  180. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  181. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  182. package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
@@ -2,17 +2,15 @@
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 reactIntl = require("react-intl");
8
+ const reactRouterDom = require("react-router-dom");
9
+ const styledComponents = require("styled-components");
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 qs = require("qs");
16
14
  const toolkit = require("@reduxjs/toolkit");
17
15
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
18
16
  function _interopNamespace(e) {
@@ -34,7 +32,6 @@ function _interopNamespace(e) {
34
32
  return Object.freeze(n);
35
33
  }
36
34
  const React__namespace = /* @__PURE__ */ _interopNamespace(React);
37
- const styled__default = /* @__PURE__ */ _interopDefault(styled);
38
35
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
39
36
  const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
40
37
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
@@ -73,42 +70,6 @@ const useInjectionZone = (area) => {
73
70
  const [page, position] = area.split(".");
74
71
  return contentManagerPlugin.getInjectedComponents(page, position);
75
72
  };
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
73
  const ID = "id";
113
74
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
114
75
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -179,9 +140,8 @@ const DocumentRBAC = ({ children, permissions }) => {
179
140
  const name = removeNumericalStrings(fieldName.split("."));
180
141
  const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
181
142
  if (fieldType === "component") {
182
- const componentOrDynamicZoneFields = componentFieldNames.map((field) => field.split("."));
183
- return componentOrDynamicZoneFields.some((field) => {
184
- return field.includes(fieldName);
143
+ return componentFieldNames.some((field) => {
144
+ return field.includes(name.join("."));
185
145
  });
186
146
  }
187
147
  if (name.length > 1) {
@@ -211,78 +171,8 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
211
171
  (field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
212
172
  );
213
173
  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: [
174
+ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
175
+ addTagTypes: [
286
176
  "ComponentConfiguration",
287
177
  "ContentTypesConfiguration",
288
178
  "ContentTypeSettings",
@@ -290,10 +180,10 @@ const contentManagerApi = react.createApi({
290
180
  "InitialData",
291
181
  "HistoryVersion",
292
182
  "Relations"
293
- ],
294
- endpoints: () => ({})
183
+ ]
295
184
  });
296
185
  const documentApi = contentManagerApi.injectEndpoints({
186
+ overrideExisting: true,
297
187
  endpoints: (builder) => ({
298
188
  autoCloneDocument: builder.mutation({
299
189
  query: ({ model, sourceId, query }) => ({
@@ -347,12 +237,15 @@ const documentApi = contentManagerApi.injectEndpoints({
347
237
  ]
348
238
  }),
349
239
  deleteManyDocuments: builder.mutation({
350
- query: ({ model, ...body }) => ({
240
+ query: ({ model, params, ...body }) => ({
351
241
  url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
352
242
  method: "POST",
353
- data: body
243
+ data: body,
244
+ config: {
245
+ params
246
+ }
354
247
  }),
355
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
248
+ invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
356
249
  }),
357
250
  discardDocument: builder.mutation({
358
251
  query: ({ collectionType, model, documentId, params }) => ({
@@ -463,10 +356,13 @@ const documentApi = contentManagerApi.injectEndpoints({
463
356
  }
464
357
  }),
465
358
  publishManyDocuments: builder.mutation({
466
- query: ({ model, ...body }) => ({
359
+ query: ({ model, params, ...body }) => ({
467
360
  url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
468
361
  method: "POST",
469
- data: body
362
+ data: body,
363
+ config: {
364
+ params
365
+ }
470
366
  }),
471
367
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
472
368
  }),
@@ -508,10 +404,13 @@ const documentApi = contentManagerApi.injectEndpoints({
508
404
  }
509
405
  }),
510
406
  unpublishManyDocuments: builder.mutation({
511
- query: ({ model, ...body }) => ({
407
+ query: ({ model, params, ...body }) => ({
512
408
  url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
513
409
  method: "POST",
514
- data: body
410
+ data: body,
411
+ config: {
412
+ params
413
+ }
515
414
  }),
516
415
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
517
416
  })
@@ -535,6 +434,24 @@ const {
535
434
  useUnpublishDocumentMutation,
536
435
  useUnpublishManyDocumentsMutation
537
436
  } = documentApi;
437
+ const buildValidParams = (query) => {
438
+ if (!query)
439
+ return query;
440
+ const { plugins: _, ...validQueryParams } = {
441
+ ...query,
442
+ ...Object.values(query?.plugins ?? {}).reduce(
443
+ (acc, current) => Object.assign(acc, current),
444
+ {}
445
+ )
446
+ };
447
+ if ("_q" in validQueryParams) {
448
+ validQueryParams._q = encodeURIComponent(validQueryParams._q);
449
+ }
450
+ return validQueryParams;
451
+ };
452
+ const isBaseQueryError = (error) => {
453
+ return error.name !== void 0;
454
+ };
538
455
  const createYupSchema = (attributes = {}, components = {}) => {
539
456
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
540
457
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
@@ -574,10 +491,14 @@ const createYupSchema = (attributes = {}, components = {}) => {
574
491
  yup__namespace.array().of(
575
492
  yup__namespace.lazy(
576
493
  (data) => {
577
- const { attributes: attributes3 } = components[data.__component];
578
- return yup__namespace.object().shape({
494
+ const attributes3 = components?.[data?.__component]?.attributes;
495
+ const validation = yup__namespace.object().shape({
579
496
  __component: yup__namespace.string().required().oneOf(Object.keys(components))
580
- }).nullable(false).concat(createModelSchema(attributes3));
497
+ }).nullable(false);
498
+ if (!attributes3) {
499
+ return validation;
500
+ }
501
+ return validation.concat(createModelSchema(attributes3));
581
502
  }
582
503
  )
583
504
  )
@@ -587,11 +508,25 @@ const createYupSchema = (attributes = {}, components = {}) => {
587
508
  return {
588
509
  ...acc,
589
510
  [name]: transformSchema(
590
- yup__namespace.array().of(
591
- yup__namespace.object().shape({
592
- id: yup__namespace.string().required()
593
- })
594
- )
511
+ yup__namespace.lazy((value) => {
512
+ if (!value) {
513
+ return yup__namespace.mixed().nullable(true);
514
+ } else if (Array.isArray(value)) {
515
+ return yup__namespace.array().of(
516
+ yup__namespace.object().shape({
517
+ id: yup__namespace.string().required()
518
+ })
519
+ );
520
+ } else if (typeof value === "object") {
521
+ return yup__namespace.object();
522
+ } else {
523
+ return yup__namespace.mixed().test(
524
+ "type-error",
525
+ "Relation values must be either null, an array of objects with {id} or an object.",
526
+ () => false
527
+ );
528
+ }
529
+ })
595
530
  )
596
531
  };
597
532
  default:
@@ -650,13 +585,18 @@ const createAttributeSchema = (attribute) => {
650
585
  }
651
586
  };
652
587
  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
- });
588
+ if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
589
+ return schema.min(1, strapiAdmin.translatedErrors.required);
658
590
  }
659
- return schema.nullable();
591
+ if (attribute.required && attribute.type !== "relation") {
592
+ return schema.required(strapiAdmin.translatedErrors.required);
593
+ }
594
+ return schema?.nullable ? schema.nullable() : (
595
+ // In some cases '.nullable' will not be available on the schema.
596
+ // e.g. when the schema has been built using yup.lazy (e.g. for relations).
597
+ // In these cases we should just return the schema as it is.
598
+ schema
599
+ );
660
600
  };
661
601
  const addMinLengthValidation = (attribute) => (schema) => {
662
602
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
@@ -683,6 +623,28 @@ const addMaxLengthValidation = (attribute) => (schema) => {
683
623
  const addMinValidation = (attribute) => (schema) => {
684
624
  if ("min" in attribute) {
685
625
  const min = toInteger(attribute.min);
626
+ if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
627
+ if (!attribute.required && "test" in schema && min) {
628
+ return schema.test(
629
+ "custom-min",
630
+ {
631
+ ...strapiAdmin.translatedErrors.min,
632
+ values: {
633
+ min: attribute.min
634
+ }
635
+ },
636
+ (value) => {
637
+ if (!value) {
638
+ return true;
639
+ }
640
+ if (Array.isArray(value) && value.length === 0) {
641
+ return true;
642
+ }
643
+ return value.length >= min;
644
+ }
645
+ );
646
+ }
647
+ }
686
648
  if ("min" in schema && min) {
687
649
  return schema.min(min, {
688
650
  ...strapiAdmin.translatedErrors.min,
@@ -728,24 +690,6 @@ const addRegexValidation = (attribute) => (schema) => {
728
690
  }
729
691
  return schema;
730
692
  };
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
693
  const initApi = contentManagerApi.injectEndpoints({
750
694
  endpoints: (builder) => ({
751
695
  getInitialData: builder.query({
@@ -759,27 +703,20 @@ const { useGetInitialDataQuery } = initApi;
759
703
  const useContentTypeSchema = (model) => {
760
704
  const { toggleNotification } = strapiAdmin.useNotification();
761
705
  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
- });
706
+ const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
707
+ const { components, contentType, contentTypes } = React__namespace.useMemo(() => {
708
+ const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
709
+ const componentsByKey = data?.components.reduce((acc, component) => {
710
+ acc[component.uid] = component;
711
+ return acc;
712
+ }, {});
713
+ const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
714
+ return {
715
+ components: Object.keys(components2).length === 0 ? void 0 : components2,
716
+ contentType: contentType2,
717
+ contentTypes: data?.contentTypes ?? []
718
+ };
719
+ }, [model, data]);
783
720
  React__namespace.useEffect(() => {
784
721
  if (error) {
785
722
  toggleNotification({
@@ -834,7 +771,10 @@ const useDocument = (args, opts) => {
834
771
  isLoading: isLoadingDocument,
835
772
  isFetching: isFetchingDocument,
836
773
  error
837
- } = useGetDocumentQuery(args, opts);
774
+ } = useGetDocumentQuery(args, {
775
+ ...opts,
776
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
777
+ });
838
778
  const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
839
779
  React__namespace.useEffect(() => {
840
780
  if (error) {
@@ -862,7 +802,7 @@ const useDocument = (args, opts) => {
862
802
  return null;
863
803
  } catch (error2) {
864
804
  if (error2 instanceof yup.ValidationError) {
865
- return getInnerErrors(error2);
805
+ return strapiAdmin.getYupValidationErrors(error2);
866
806
  }
867
807
  throw error2;
868
808
  }
@@ -958,14 +898,53 @@ const useDocumentActions = () => {
958
898
  },
959
899
  [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
960
900
  );
901
+ const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
902
+ const deleteMany = React__namespace.useCallback(
903
+ async ({ model, documentIds, params }) => {
904
+ try {
905
+ trackUsage("willBulkDeleteEntries");
906
+ const res = await deleteManyDocuments({
907
+ model,
908
+ documentIds,
909
+ params
910
+ });
911
+ if ("error" in res) {
912
+ toggleNotification({
913
+ type: "danger",
914
+ message: formatAPIError(res.error)
915
+ });
916
+ return { error: res.error };
917
+ }
918
+ toggleNotification({
919
+ type: "success",
920
+ title: formatMessage({
921
+ id: getTranslation("success.records.delete"),
922
+ defaultMessage: "Successfully deleted."
923
+ }),
924
+ message: ""
925
+ });
926
+ trackUsage("didBulkDeleteEntries");
927
+ return res.data;
928
+ } catch (err) {
929
+ toggleNotification({
930
+ type: "danger",
931
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
932
+ });
933
+ trackUsage("didNotBulkDeleteEntries");
934
+ throw err;
935
+ }
936
+ },
937
+ [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
938
+ );
961
939
  const [discardDocument] = useDiscardDocumentMutation();
962
940
  const discard = React__namespace.useCallback(
963
- async ({ collectionType, model, documentId }) => {
941
+ async ({ collectionType, model, documentId, params }) => {
964
942
  try {
965
943
  const res = await discardDocument({
966
944
  collectionType,
967
945
  model,
968
- documentId
946
+ documentId,
947
+ params
969
948
  });
970
949
  if ("error" in res) {
971
950
  toggleNotification({
@@ -1027,6 +1006,43 @@ const useDocumentActions = () => {
1027
1006
  },
1028
1007
  [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1029
1008
  );
1009
+ const [publishManyDocuments] = usePublishManyDocumentsMutation();
1010
+ const publishMany = React__namespace.useCallback(
1011
+ async ({ model, documentIds, params }) => {
1012
+ try {
1013
+ const res = await publishManyDocuments({
1014
+ model,
1015
+ documentIds,
1016
+ params
1017
+ });
1018
+ if ("error" in res) {
1019
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1020
+ return { error: res.error };
1021
+ }
1022
+ toggleNotification({
1023
+ type: "success",
1024
+ message: formatMessage({
1025
+ id: getTranslation("success.record.publish"),
1026
+ defaultMessage: "Published document"
1027
+ })
1028
+ });
1029
+ return res.data;
1030
+ } catch (err) {
1031
+ toggleNotification({
1032
+ type: "danger",
1033
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1034
+ });
1035
+ throw err;
1036
+ }
1037
+ },
1038
+ [
1039
+ // trackUsage,
1040
+ publishManyDocuments,
1041
+ toggleNotification,
1042
+ formatMessage,
1043
+ formatAPIError
1044
+ ]
1045
+ );
1030
1046
  const [updateDocument] = useUpdateDocumentMutation();
1031
1047
  const update = React__namespace.useCallback(
1032
1048
  async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
@@ -1101,6 +1117,41 @@ const useDocumentActions = () => {
1101
1117
  },
1102
1118
  [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1103
1119
  );
1120
+ const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1121
+ const unpublishMany = React__namespace.useCallback(
1122
+ async ({ model, documentIds, params }) => {
1123
+ try {
1124
+ trackUsage("willBulkUnpublishEntries");
1125
+ const res = await unpublishManyDocuments({
1126
+ model,
1127
+ documentIds,
1128
+ params
1129
+ });
1130
+ if ("error" in res) {
1131
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1132
+ return { error: res.error };
1133
+ }
1134
+ trackUsage("didBulkUnpublishEntries");
1135
+ toggleNotification({
1136
+ type: "success",
1137
+ title: formatMessage({
1138
+ id: getTranslation("success.records.unpublish"),
1139
+ defaultMessage: "Successfully unpublished."
1140
+ }),
1141
+ message: ""
1142
+ });
1143
+ return res.data;
1144
+ } catch (err) {
1145
+ toggleNotification({
1146
+ type: "danger",
1147
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1148
+ });
1149
+ trackUsage("didNotBulkUnpublishEntries");
1150
+ throw err;
1151
+ }
1152
+ },
1153
+ [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1154
+ );
1104
1155
  const [createDocument] = useCreateDocumentMutation();
1105
1156
  const create = React__namespace.useCallback(
1106
1157
  async ({ model, params }, data, trackerProperty) => {
@@ -1214,15 +1265,18 @@ const useDocumentActions = () => {
1214
1265
  clone,
1215
1266
  create,
1216
1267
  delete: _delete,
1268
+ deleteMany,
1217
1269
  discard,
1218
1270
  getDocument,
1219
1271
  publish,
1272
+ publishMany,
1220
1273
  unpublish,
1274
+ unpublishMany,
1221
1275
  update
1222
1276
  };
1223
1277
  };
1224
1278
  const ProtectedHistoryPage = React.lazy(
1225
- () => Promise.resolve().then(() => require("./History-C17LiyRg.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1279
+ () => Promise.resolve().then(() => require("./History-DdIstl8b.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1226
1280
  );
1227
1281
  const routes$1 = [
1228
1282
  {
@@ -1235,31 +1289,31 @@ const routes$1 = [
1235
1289
  }
1236
1290
  ];
1237
1291
  const ProtectedEditViewPage = React.lazy(
1238
- () => Promise.resolve().then(() => require("./EditViewPage-CzOT5Kpj.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1292
+ () => Promise.resolve().then(() => require("./EditViewPage-DA95Ha6J.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1239
1293
  );
1240
1294
  const ProtectedListViewPage = React.lazy(
1241
- () => Promise.resolve().then(() => require("./ListViewPage-BwrZrPsh.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1295
+ () => Promise.resolve().then(() => require("./ListViewPage-wE0lXqoD.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1242
1296
  );
1243
1297
  const ProtectedListConfiguration = React.lazy(
1244
- () => Promise.resolve().then(() => require("./ListConfigurationPage-Dks5SX6f.js")).then((mod) => ({
1298
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-DkKRparB.js")).then((mod) => ({
1245
1299
  default: mod.ProtectedListConfiguration
1246
1300
  }))
1247
1301
  );
1248
1302
  const ProtectedEditConfigurationPage = React.lazy(
1249
- () => Promise.resolve().then(() => require("./EditConfigurationPage-BfFzJ4Br.js")).then((mod) => ({
1303
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-BFEwvdMW.js")).then((mod) => ({
1250
1304
  default: mod.ProtectedEditConfigurationPage
1251
1305
  }))
1252
1306
  );
1253
1307
  const ProtectedComponentConfigurationPage = React.lazy(
1254
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-43KmCNQE.js")).then((mod) => ({
1308
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-Bqgx7Mes.js")).then((mod) => ({
1255
1309
  default: mod.ProtectedComponentConfigurationPage
1256
1310
  }))
1257
1311
  );
1258
1312
  const NoPermissions = React.lazy(
1259
- () => Promise.resolve().then(() => require("./NoPermissionsPage-C-j6TEUF.js")).then((mod) => ({ default: mod.NoPermissions }))
1313
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-DmNfF2Bb.js")).then((mod) => ({ default: mod.NoPermissions }))
1260
1314
  );
1261
1315
  const NoContentType = React.lazy(
1262
- () => Promise.resolve().then(() => require("./NoContentTypePage-Cu5r1-JT.js")).then((mod) => ({ default: mod.NoContentType }))
1316
+ () => Promise.resolve().then(() => require("./NoContentTypePage-DEKR6tf9.js")).then((mod) => ({ default: mod.NoContentType }))
1263
1317
  );
1264
1318
  const CollectionTypePages = () => {
1265
1319
  const { collectionType } = reactRouterDom.useParams();
@@ -1386,7 +1440,7 @@ const DocumentActionButton = (action) => {
1386
1440
  DocumentActionConfirmDialog,
1387
1441
  {
1388
1442
  ...action.dialog,
1389
- variant: action.variant,
1443
+ variant: action.dialog?.variant ?? action.variant,
1390
1444
  isOpen: dialogId === action.id,
1391
1445
  onClose: handleClose
1392
1446
  }
@@ -1449,7 +1503,7 @@ const DocumentActionsMenu = ({
1449
1503
  variant,
1450
1504
  children: [
1451
1505
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
1452
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { as: "span", children: label || formatMessage({
1506
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
1453
1507
  id: "content-manager.containers.edit.panels.default.more-actions",
1454
1508
  defaultMessage: "More document actions"
1455
1509
  }) })
@@ -1465,8 +1519,8 @@ const DocumentActionsMenu = ({
1465
1519
  onSelect: handleClick(action),
1466
1520
  display: "block",
1467
1521
  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,
1522
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1523
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1470
1524
  action.label
1471
1525
  ] }),
1472
1526
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
@@ -1527,6 +1581,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1527
1581
  return "primary600";
1528
1582
  }
1529
1583
  };
1584
+ const convertActionVariantToIconColor = (variant = "secondary") => {
1585
+ switch (variant) {
1586
+ case "danger":
1587
+ return "danger600";
1588
+ case "secondary":
1589
+ return "neutral500";
1590
+ case "success":
1591
+ return "success600";
1592
+ default:
1593
+ return "primary600";
1594
+ }
1595
+ };
1530
1596
  const DocumentActionConfirmDialog = ({
1531
1597
  onClose,
1532
1598
  onCancel,
@@ -1549,61 +1615,42 @@ const DocumentActionConfirmDialog = ({
1549
1615
  }
1550
1616
  onClose();
1551
1617
  };
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
- ] });
1618
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
1619
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
1620
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
1621
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
1622
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
1623
+ id: "app.components.Button.cancel",
1624
+ defaultMessage: "Cancel"
1625
+ }) }) }),
1626
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
1627
+ id: "app.components.Button.confirm",
1628
+ defaultMessage: "Confirm"
1629
+ }) })
1630
+ ] })
1631
+ ] }) });
1568
1632
  };
1569
1633
  const DocumentActionModal = ({
1570
1634
  isOpen,
1571
1635
  title,
1572
1636
  onClose,
1573
1637
  footer: Footer,
1574
- content,
1638
+ content: Content,
1575
1639
  onModalClose
1576
1640
  }) => {
1577
- const id = React__namespace.useId();
1578
- if (!isOpen) {
1579
- return null;
1580
- }
1581
1641
  const handleClose = () => {
1582
1642
  if (onClose) {
1583
1643
  onClose();
1584
1644
  }
1585
1645
  onModalClose();
1586
1646
  };
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
- ] });
1647
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
1648
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
1649
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content }),
1650
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Footer, { children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer })
1651
+ ] }) });
1605
1652
  };
1606
- const PublishAction = ({
1653
+ const PublishAction$1 = ({
1607
1654
  activeTab,
1608
1655
  documentId,
1609
1656
  model,
@@ -1622,6 +1669,12 @@ const PublishAction = ({
1622
1669
  ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1623
1670
  );
1624
1671
  const { publish } = useDocumentActions();
1672
+ const [
1673
+ countDraftRelations,
1674
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
1675
+ ] = useLazyGetDraftRelationCountQuery();
1676
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
1677
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
1625
1678
  const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
1626
1679
  const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1627
1680
  const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1630,65 +1683,148 @@ const PublishAction = ({
1630
1683
  const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
1631
1684
  const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
1632
1685
  const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
1633
- const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1634
- if (!schema?.options?.draftAndPublish) {
1635
- return null;
1636
- }
1637
- return {
1638
- /**
1639
- * Disabled when:
1640
- * - currently if you're cloning a document we don't support publish & clone at the same time.
1641
- * - the form is submitting
1642
- * - the active tab is the published tab
1643
- * - the document is already published & not modified
1644
- * - the document is being created & not modified
1645
- * - 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
- */
1649
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1686
+ React__namespace.useEffect(() => {
1687
+ if (isErrorDraftRelations) {
1688
+ toggleNotification({
1689
+ type: "danger",
1690
+ message: formatMessage({
1691
+ id: getTranslation("error.records.fetch-draft-relatons"),
1692
+ defaultMessage: "An error occurred while fetching draft relations on this document."
1693
+ })
1694
+ });
1695
+ }
1696
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
1697
+ React__namespace.useEffect(() => {
1698
+ const localDraftRelations = /* @__PURE__ */ new Set();
1699
+ const extractDraftRelations = (data) => {
1700
+ const relations = data.connect || [];
1701
+ relations.forEach((relation) => {
1702
+ if (relation.status === "draft") {
1703
+ localDraftRelations.add(relation.id);
1704
+ }
1705
+ });
1706
+ };
1707
+ const traverseAndExtract = (data) => {
1708
+ Object.entries(data).forEach(([key, value]) => {
1709
+ if (key === "connect" && Array.isArray(value)) {
1710
+ extractDraftRelations({ connect: value });
1711
+ } else if (typeof value === "object" && value !== null) {
1712
+ traverseAndExtract(value);
1713
+ }
1714
+ });
1715
+ };
1716
+ if (!documentId || modified) {
1717
+ traverseAndExtract(formValues);
1718
+ setLocalCountOfDraftRelations(localDraftRelations.size);
1719
+ }
1720
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
1721
+ React__namespace.useEffect(() => {
1722
+ if (documentId) {
1723
+ const fetchDraftRelationsCount = async () => {
1724
+ const { data, error } = await countDraftRelations({
1725
+ collectionType,
1726
+ model,
1727
+ documentId,
1728
+ params
1729
+ });
1730
+ if (error) {
1731
+ throw error;
1732
+ }
1733
+ if (data) {
1734
+ setServerCountOfDraftRelations(data.data);
1735
+ }
1736
+ };
1737
+ fetchDraftRelationsCount();
1738
+ }
1739
+ }, [documentId, countDraftRelations, collectionType, model, params]);
1740
+ const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1741
+ if (!schema?.options?.draftAndPublish) {
1742
+ return null;
1743
+ }
1744
+ const performPublish = async () => {
1745
+ setSubmitting(true);
1746
+ try {
1747
+ const { errors } = await validate();
1748
+ if (errors) {
1749
+ toggleNotification({
1750
+ type: "danger",
1751
+ message: formatMessage({
1752
+ id: "content-manager.validation.error",
1753
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1754
+ })
1755
+ });
1756
+ return;
1757
+ }
1758
+ const res = await publish(
1759
+ {
1760
+ collectionType,
1761
+ model,
1762
+ documentId,
1763
+ params
1764
+ },
1765
+ formValues
1766
+ );
1767
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
1768
+ navigate({
1769
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1770
+ search: rawQuery
1771
+ });
1772
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1773
+ setErrors(formatValidationErrors(res.error));
1774
+ }
1775
+ } finally {
1776
+ setSubmitting(false);
1777
+ }
1778
+ };
1779
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1780
+ const hasDraftRelations = totalDraftRelations > 0;
1781
+ return {
1782
+ /**
1783
+ * Disabled when:
1784
+ * - currently if you're cloning a document we don't support publish & clone at the same time.
1785
+ * - the form is submitting
1786
+ * - the active tab is the published tab
1787
+ * - the document is already published & not modified
1788
+ * - the document is being created & not modified
1789
+ * - the user doesn't have the permission to publish
1790
+ * - the user doesn't have the permission to create a new document
1791
+ * - the user doesn't have the permission to update the document
1792
+ */
1793
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1650
1794
  label: formatMessage({
1651
1795
  id: "app.utils.publish",
1652
1796
  defaultMessage: "Publish"
1653
1797
  }),
1654
1798
  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));
1799
+ if (hasDraftRelations) {
1800
+ return;
1801
+ }
1802
+ await performPublish();
1803
+ },
1804
+ dialog: hasDraftRelations ? {
1805
+ type: "dialog",
1806
+ variant: "danger",
1807
+ footer: null,
1808
+ title: formatMessage({
1809
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
1810
+ defaultMessage: "Confirmation"
1811
+ }),
1812
+ content: formatMessage(
1813
+ {
1814
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
1815
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
1816
+ },
1817
+ {
1818
+ count: totalDraftRelations
1684
1819
  }
1685
- } finally {
1686
- setSubmitting(false);
1820
+ ),
1821
+ onConfirm: async () => {
1822
+ await performPublish();
1687
1823
  }
1688
- }
1824
+ } : void 0
1689
1825
  };
1690
1826
  };
1691
- PublishAction.type = "publish";
1827
+ PublishAction$1.type = "publish";
1692
1828
  const UpdateAction = ({
1693
1829
  activeTab,
1694
1830
  documentId,
@@ -1784,10 +1920,13 @@ const UpdateAction = ({
1784
1920
  document
1785
1921
  );
1786
1922
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1787
- navigate({
1788
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1789
- search: rawQuery
1790
- });
1923
+ navigate(
1924
+ {
1925
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1926
+ search: rawQuery
1927
+ },
1928
+ { replace: true }
1929
+ );
1791
1930
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1792
1931
  setErrors(formatValidationErrors(res.error));
1793
1932
  }
@@ -1803,7 +1942,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
1803
1942
  KEEP: "keep",
1804
1943
  DISCARD: "discard"
1805
1944
  };
1806
- const UnpublishAction = ({
1945
+ const UnpublishAction$1 = ({
1807
1946
  activeTab,
1808
1947
  documentId,
1809
1948
  model,
@@ -1819,10 +1958,8 @@ const UnpublishAction = ({
1819
1958
  const { toggleNotification } = strapiAdmin.useNotification();
1820
1959
  const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
1821
1960
  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
- }
1961
+ const handleChange = (value) => {
1962
+ setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1826
1963
  };
1827
1964
  if (!schema?.options?.draftAndPublish) {
1828
1965
  return null;
@@ -1866,45 +2003,30 @@ const UnpublishAction = ({
1866
2003
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
1867
2004
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
1868
2005
  /* @__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({
2006
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1870
2007
  id: "content-manager.actions.unpublish.dialog.body",
1871
2008
  defaultMessage: "Are you sure?"
1872
2009
  }) })
1873
2010
  ] }),
1874
2011
  /* @__PURE__ */ jsxRuntime.jsxs(
1875
- designSystem.Flex,
2012
+ designSystem.Radio.Group,
1876
2013
  {
1877
- onChange: handleChange,
1878
- direction: "column",
1879
- alignItems: "flex-start",
1880
- as: "fieldset",
1881
- gap: 3,
2014
+ defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
2015
+ name: "discard-options",
2016
+ "aria-label": formatMessage({
2017
+ id: "content-manager.actions.unpublish.dialog.radio-label",
2018
+ defaultMessage: "Choose an option to unpublish the document."
2019
+ }),
2020
+ onValueChange: handleChange,
1882
2021
  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
- )
2022
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
2023
+ id: "content-manager.actions.unpublish.dialog.option.keep-draft",
2024
+ defaultMessage: "Keep draft"
2025
+ }) }),
2026
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
2027
+ id: "content-manager.actions.unpublish.dialog.option.replace-draft",
2028
+ defaultMessage: "Replace draft"
2029
+ }) })
1908
2030
  ]
1909
2031
  }
1910
2032
  )
@@ -1937,7 +2059,7 @@ const UnpublishAction = ({
1937
2059
  position: ["panel", "table-row"]
1938
2060
  };
1939
2061
  };
1940
- UnpublishAction.type = "unpublish";
2062
+ UnpublishAction$1.type = "unpublish";
1941
2063
  const DiscardAction = ({
1942
2064
  activeTab,
1943
2065
  documentId,
@@ -1971,7 +2093,7 @@ const DiscardAction = ({
1971
2093
  }),
1972
2094
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
1973
2095
  /* @__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({
2096
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1975
2097
  id: "content-manager.actions.discard.dialog.body",
1976
2098
  defaultMessage: "Are you sure?"
1977
2099
  }) })
@@ -1988,12 +2110,12 @@ const DiscardAction = ({
1988
2110
  };
1989
2111
  };
1990
2112
  DiscardAction.type = "discard";
1991
- const StyledCrossCircle = styled__default.default(Icons.CrossCircle)`
2113
+ const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
1992
2114
  path {
1993
2115
  fill: currentColor;
1994
2116
  }
1995
2117
  `;
1996
- const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
2118
+ const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
1997
2119
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
1998
2120
  const RelativeTime = React__namespace.forwardRef(
1999
2121
  ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
@@ -2041,7 +2163,7 @@ const getDisplayName = ({
2041
2163
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2042
2164
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2043
2165
  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) }) });
2166
+ 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
2167
  };
2046
2168
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2047
2169
  const { formatMessage } = reactIntl.useIntl();
@@ -2050,23 +2172,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2050
2172
  id: "content-manager.containers.edit.title.new",
2051
2173
  defaultMessage: "Create an entry"
2052
2174
  }) : documentTitle;
2053
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2175
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2054
2176
  /* @__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
2177
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2178
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2179
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2180
+ ] }),
2181
+ status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2070
2182
  ] });
2071
2183
  };
2072
2184
  const HeaderToolbar = () => {
@@ -2218,7 +2330,7 @@ const Information = ({ activeTab }) => {
2218
2330
  borderColor: "neutral150",
2219
2331
  direction: "column",
2220
2332
  marginTop: 2,
2221
- as: "dl",
2333
+ tag: "dl",
2222
2334
  padding: 5,
2223
2335
  gap: 3,
2224
2336
  alignItems: "flex-start",
@@ -2226,8 +2338,8 @@ const Information = ({ activeTab }) => {
2226
2338
  marginRight: "-0.4rem",
2227
2339
  width: "calc(100% + 8px)",
2228
2340
  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 })
2341
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2342
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2231
2343
  ] }, info.label))
2232
2344
  }
2233
2345
  );
@@ -2260,7 +2372,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2260
2372
  id: "app.links.configure-view",
2261
2373
  defaultMessage: "Configure the view"
2262
2374
  }),
2263
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCog, {}),
2375
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
2264
2376
  onClick: () => {
2265
2377
  navigate(`../${collectionType}/${model}/configurations/edit`);
2266
2378
  },
@@ -2268,11 +2380,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2268
2380
  };
2269
2381
  };
2270
2382
  ConfigureTheViewAction.type = "configure-the-view";
2271
- const StyledCog = styled__default.default(Icons.Cog)`
2272
- path {
2273
- fill: currentColor;
2274
- }
2275
- `;
2276
2383
  const EditTheModelAction = ({ model }) => {
2277
2384
  const navigate = reactRouterDom.useNavigate();
2278
2385
  const { formatMessage } = reactIntl.useIntl();
@@ -2281,7 +2388,7 @@ const EditTheModelAction = ({ model }) => {
2281
2388
  id: "content-manager.link-to-ctb",
2282
2389
  defaultMessage: "Edit the model"
2283
2390
  }),
2284
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil$1, {}),
2391
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
2285
2392
  onClick: () => {
2286
2393
  navigate(`/plugins/content-type-builder/content-types/${model}`);
2287
2394
  },
@@ -2289,12 +2396,7 @@ const EditTheModelAction = ({ model }) => {
2289
2396
  };
2290
2397
  };
2291
2398
  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 }) => {
2399
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2298
2400
  const navigate = reactRouterDom.useNavigate();
2299
2401
  const { formatMessage } = reactIntl.useIntl();
2300
2402
  const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
@@ -2308,7 +2410,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2308
2410
  id: "content-manager.actions.delete.label",
2309
2411
  defaultMessage: "Delete document"
2310
2412
  }),
2311
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledTrash, {}),
2413
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2312
2414
  dialog: {
2313
2415
  type: "dialog",
2314
2416
  title: formatMessage({
@@ -2317,7 +2419,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2317
2419
  }),
2318
2420
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
2319
2421
  /* @__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({
2422
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2321
2423
  id: "content-manager.actions.delete.dialog.body",
2322
2424
  defaultMessage: "Are you sure?"
2323
2425
  }) })
@@ -2362,13 +2464,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2362
2464
  position: ["header", "table-row"]
2363
2465
  };
2364
2466
  };
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];
2467
+ DeleteAction$1.type = "delete";
2468
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2372
2469
  const Panels = () => {
2373
2470
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2374
2471
  const [
@@ -2442,7 +2539,7 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2442
2539
  designSystem.Flex,
2443
2540
  {
2444
2541
  ref,
2445
- as: "aside",
2542
+ tag: "aside",
2446
2543
  "aria-labelledby": "additional-information",
2447
2544
  background: "neutral0",
2448
2545
  borderColor: "neutral150",
@@ -2457,117 +2554,996 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2457
2554
  justifyContent: "stretch",
2458
2555
  alignItems: "flex-start",
2459
2556
  children: [
2460
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2557
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2461
2558
  children
2462
2559
  ]
2463
2560
  }
2464
2561
  );
2465
2562
  });
2466
- const DEFAULT_BULK_ACTIONS = [];
2467
- const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
2468
- const { formatMessage } = reactIntl.useIntl();
2469
- const getDefaultErrorMessage = (reason) => {
2470
- switch (reason) {
2471
- case "relation":
2472
- return "Duplicating the relation could remove it from the original entry.";
2473
- case "unique":
2474
- return "Identical values in a unique field are not allowed";
2475
- default:
2476
- return reason;
2477
- }
2478
- };
2479
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2480
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: formatMessage({
2481
- id: getTranslation("containers.list.autoCloneModal.title"),
2482
- defaultMessage: "This entry can't be duplicated directly."
2483
- }) }),
2484
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatMessage({
2485
- id: getTranslation("containers.list.autoCloneModal.description"),
2486
- defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
2487
- }) }) }),
2488
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxRuntime.jsxs(
2489
- designSystem.Flex,
2490
- {
2491
- direction: "column",
2492
- gap: 2,
2493
- alignItems: "flex-start",
2494
- borderColor: "neutral200",
2495
- hasRadius: true,
2496
- padding: 6,
2497
- 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: [
2499
- pathSegment,
2500
- index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
2501
- Icons.ChevronRight,
2502
- {
2503
- fill: "neutral500",
2504
- height: "0.8rem",
2505
- width: "0.8rem",
2506
- style: { margin: "0 0.8rem" }
2507
- }
2508
- )
2509
- ] }, index2)) }),
2510
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "p", textColor: "neutral600", children: formatMessage({
2511
- id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
2512
- defaultMessage: getDefaultErrorMessage(reason)
2513
- }) })
2514
- ]
2515
- },
2516
- fieldPath.join()
2517
- )) })
2518
- ] });
2519
- };
2520
- const TableActions = ({ document }) => {
2521
- const { formatMessage } = reactIntl.useIntl();
2522
- const { model, collectionType } = useDoc();
2523
- const plugins = strapiAdmin.useStrapiApp("TableActions", (state) => state.plugins);
2524
- const props = {
2525
- activeTab: null,
2526
- model,
2527
- documentId: document.documentId,
2528
- collectionType,
2529
- document
2530
- };
2531
- return /* @__PURE__ */ jsxRuntime.jsx(
2532
- strapiAdmin.DescriptionComponentRenderer,
2533
- {
2534
- props,
2535
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2536
- children: (actions2) => {
2537
- const tableRowActions = actions2.filter((action) => {
2538
- const positions = Array.isArray(action.position) ? action.position : [action.position];
2539
- return positions.includes("table-row");
2540
- });
2541
- return /* @__PURE__ */ jsxRuntime.jsx(
2542
- DocumentActionsMenu,
2543
- {
2544
- actions: tableRowActions,
2545
- label: formatMessage({
2546
- id: "content-manager.containers.list.table.row-actions",
2547
- defaultMessage: "Row action"
2548
- }),
2549
- variant: "ghost"
2550
- }
2551
- );
2552
- }
2553
- }
2554
- );
2563
+ const HOOKS = {
2564
+ /**
2565
+ * Hook that allows to mutate the displayed headers of the list view table
2566
+ * @constant
2567
+ * @type {string}
2568
+ */
2569
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2570
+ /**
2571
+ * Hook that allows to mutate the CM's collection types links pre-set filters
2572
+ * @constant
2573
+ * @type {string}
2574
+ */
2575
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2576
+ /**
2577
+ * Hook that allows to mutate the CM's edit view layout
2578
+ * @constant
2579
+ * @type {string}
2580
+ */
2581
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2582
+ /**
2583
+ * Hook that allows to mutate the CM's single types links pre-set filters
2584
+ * @constant
2585
+ * @type {string}
2586
+ */
2587
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2555
2588
  };
2556
- const EditAction = ({ documentId }) => {
2557
- const navigate = reactRouterDom.useNavigate();
2558
- const { formatMessage } = reactIntl.useIntl();
2559
- const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
2560
- const { toggleNotification } = strapiAdmin.useNotification();
2561
- const [{ query }] = strapiAdmin.useQueryParams();
2562
- return {
2563
- disabled: !canRead,
2564
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil, {}),
2565
- label: formatMessage({
2566
- id: "content-manager.actions.edit.label",
2567
- defaultMessage: "Edit"
2568
- }),
2569
- position: "table-row",
2570
- onClick: async () => {
2589
+ const contentTypesApi = contentManagerApi.injectEndpoints({
2590
+ endpoints: (builder) => ({
2591
+ getContentTypeConfiguration: builder.query({
2592
+ query: (uid) => ({
2593
+ url: `/content-manager/content-types/${uid}/configuration`,
2594
+ method: "GET"
2595
+ }),
2596
+ transformResponse: (response) => response.data,
2597
+ providesTags: (_result, _error, uid) => [
2598
+ { type: "ContentTypesConfiguration", id: uid },
2599
+ { type: "ContentTypeSettings", id: "LIST" }
2600
+ ]
2601
+ }),
2602
+ getAllContentTypeSettings: builder.query({
2603
+ query: () => "/content-manager/content-types-settings",
2604
+ transformResponse: (response) => response.data,
2605
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2606
+ }),
2607
+ updateContentTypeConfiguration: builder.mutation({
2608
+ query: ({ uid, ...body }) => ({
2609
+ url: `/content-manager/content-types/${uid}/configuration`,
2610
+ method: "PUT",
2611
+ data: body
2612
+ }),
2613
+ transformResponse: (response) => response.data,
2614
+ invalidatesTags: (_result, _error, { uid }) => [
2615
+ { type: "ContentTypesConfiguration", id: uid },
2616
+ { type: "ContentTypeSettings", id: "LIST" },
2617
+ // Is this necessary?
2618
+ { type: "InitialData" }
2619
+ ]
2620
+ })
2621
+ })
2622
+ });
2623
+ const {
2624
+ useGetContentTypeConfigurationQuery,
2625
+ useGetAllContentTypeSettingsQuery,
2626
+ useUpdateContentTypeConfigurationMutation
2627
+ } = contentTypesApi;
2628
+ const checkIfAttributeIsDisplayable = (attribute) => {
2629
+ const { type } = attribute;
2630
+ if (type === "relation") {
2631
+ return !attribute.relation.toLowerCase().includes("morph");
2632
+ }
2633
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2634
+ };
2635
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2636
+ if (!mainFieldName) {
2637
+ return void 0;
2638
+ }
2639
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2640
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2641
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2642
+ );
2643
+ return {
2644
+ name: mainFieldName,
2645
+ type: mainFieldType ?? "string"
2646
+ };
2647
+ };
2648
+ const DEFAULT_SETTINGS = {
2649
+ bulkable: false,
2650
+ filterable: false,
2651
+ searchable: false,
2652
+ pagination: false,
2653
+ defaultSortBy: "",
2654
+ defaultSortOrder: "asc",
2655
+ mainField: "id",
2656
+ pageSize: 10
2657
+ };
2658
+ const useDocumentLayout = (model) => {
2659
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2660
+ const [{ query }] = strapiAdmin.useQueryParams();
2661
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2662
+ const { toggleNotification } = strapiAdmin.useNotification();
2663
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2664
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2665
+ const {
2666
+ data,
2667
+ isLoading: isLoadingConfigs,
2668
+ error,
2669
+ isFetching: isFetchingConfigs
2670
+ } = useGetContentTypeConfigurationQuery(model);
2671
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2672
+ React__namespace.useEffect(() => {
2673
+ if (error) {
2674
+ toggleNotification({
2675
+ type: "danger",
2676
+ message: formatAPIError(error)
2677
+ });
2678
+ }
2679
+ }, [error, formatAPIError, toggleNotification]);
2680
+ const editLayout = React__namespace.useMemo(
2681
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2682
+ layout: [],
2683
+ components: {},
2684
+ metadatas: {},
2685
+ options: {},
2686
+ settings: DEFAULT_SETTINGS
2687
+ },
2688
+ [data, isLoading, schemas, schema, components]
2689
+ );
2690
+ const listLayout = React__namespace.useMemo(() => {
2691
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2692
+ layout: [],
2693
+ metadatas: {},
2694
+ options: {},
2695
+ settings: DEFAULT_SETTINGS
2696
+ };
2697
+ }, [data, isLoading, schemas, schema, components]);
2698
+ const { layout: edit } = React__namespace.useMemo(
2699
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2700
+ layout: editLayout,
2701
+ query
2702
+ }),
2703
+ [editLayout, query, runHookWaterfall]
2704
+ );
2705
+ return {
2706
+ error,
2707
+ isLoading,
2708
+ edit,
2709
+ list: listLayout
2710
+ };
2711
+ };
2712
+ const useDocLayout = () => {
2713
+ const { model } = useDoc();
2714
+ return useDocumentLayout(model);
2715
+ };
2716
+ const formatEditLayout = (data, {
2717
+ schemas,
2718
+ schema,
2719
+ components
2720
+ }) => {
2721
+ let currentPanelIndex = 0;
2722
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2723
+ data.contentType.layouts.edit,
2724
+ schema?.attributes,
2725
+ data.contentType.metadatas,
2726
+ { configurations: data.components, schemas: components },
2727
+ schemas
2728
+ ).reduce((panels, row) => {
2729
+ if (row.some((field) => field.type === "dynamiczone")) {
2730
+ panels.push([row]);
2731
+ currentPanelIndex += 2;
2732
+ } else {
2733
+ if (!panels[currentPanelIndex]) {
2734
+ panels.push([]);
2735
+ }
2736
+ panels[currentPanelIndex].push(row);
2737
+ }
2738
+ return panels;
2739
+ }, []);
2740
+ const componentEditAttributes = Object.entries(data.components).reduce(
2741
+ (acc, [uid, configuration]) => {
2742
+ acc[uid] = {
2743
+ layout: convertEditLayoutToFieldLayouts(
2744
+ configuration.layouts.edit,
2745
+ components[uid].attributes,
2746
+ configuration.metadatas
2747
+ ),
2748
+ settings: {
2749
+ ...configuration.settings,
2750
+ icon: components[uid].info.icon,
2751
+ displayName: components[uid].info.displayName
2752
+ }
2753
+ };
2754
+ return acc;
2755
+ },
2756
+ {}
2757
+ );
2758
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2759
+ (acc, [attribute, metadata]) => {
2760
+ return {
2761
+ ...acc,
2762
+ [attribute]: metadata.edit
2763
+ };
2764
+ },
2765
+ {}
2766
+ );
2767
+ return {
2768
+ layout: panelledEditAttributes,
2769
+ components: componentEditAttributes,
2770
+ metadatas: editMetadatas,
2771
+ settings: {
2772
+ ...data.contentType.settings,
2773
+ displayName: schema?.info.displayName
2774
+ },
2775
+ options: {
2776
+ ...schema?.options,
2777
+ ...schema?.pluginOptions,
2778
+ ...data.contentType.options
2779
+ }
2780
+ };
2781
+ };
2782
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2783
+ return rows.map(
2784
+ (row) => row.map((field) => {
2785
+ const attribute = attributes[field.name];
2786
+ if (!attribute) {
2787
+ return null;
2788
+ }
2789
+ const { edit: metadata } = metadatas[field.name];
2790
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2791
+ return {
2792
+ attribute,
2793
+ disabled: !metadata.editable,
2794
+ hint: metadata.description,
2795
+ label: metadata.label ?? "",
2796
+ name: field.name,
2797
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
2798
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2799
+ schemas,
2800
+ components: components?.schemas ?? {}
2801
+ }),
2802
+ placeholder: metadata.placeholder ?? "",
2803
+ required: attribute.required ?? false,
2804
+ size: field.size,
2805
+ unique: "unique" in attribute ? attribute.unique : false,
2806
+ visible: metadata.visible ?? true,
2807
+ type: attribute.type
2808
+ };
2809
+ }).filter((field) => field !== null)
2810
+ );
2811
+ };
2812
+ const formatListLayout = (data, {
2813
+ schemas,
2814
+ schema,
2815
+ components
2816
+ }) => {
2817
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2818
+ (acc, [attribute, metadata]) => {
2819
+ return {
2820
+ ...acc,
2821
+ [attribute]: metadata.list
2822
+ };
2823
+ },
2824
+ {}
2825
+ );
2826
+ const listAttributes = convertListLayoutToFieldLayouts(
2827
+ data.contentType.layouts.list,
2828
+ schema?.attributes,
2829
+ listMetadatas,
2830
+ { configurations: data.components, schemas: components },
2831
+ schemas
2832
+ );
2833
+ return {
2834
+ layout: listAttributes,
2835
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2836
+ metadatas: listMetadatas,
2837
+ options: {
2838
+ ...schema?.options,
2839
+ ...schema?.pluginOptions,
2840
+ ...data.contentType.options
2841
+ }
2842
+ };
2843
+ };
2844
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2845
+ return columns.map((name) => {
2846
+ const attribute = attributes[name];
2847
+ if (!attribute) {
2848
+ return null;
2849
+ }
2850
+ const metadata = metadatas[name];
2851
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2852
+ return {
2853
+ attribute,
2854
+ label: metadata.label ?? "",
2855
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2856
+ schemas,
2857
+ components: components?.schemas ?? {}
2858
+ }),
2859
+ name,
2860
+ searchable: metadata.searchable ?? true,
2861
+ sortable: metadata.sortable ?? true
2862
+ };
2863
+ }).filter((field) => field !== null);
2864
+ };
2865
+ const ConfirmBulkActionDialog = ({
2866
+ onToggleDialog,
2867
+ isOpen = false,
2868
+ dialogBody,
2869
+ endAction
2870
+ }) => {
2871
+ const { formatMessage } = reactIntl.useIntl();
2872
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2873
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2874
+ id: "app.components.ConfirmDialog.title",
2875
+ defaultMessage: "Confirmation"
2876
+ }) }),
2877
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
2878
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
2879
+ dialogBody
2880
+ ] }) }),
2881
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
2882
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
2883
+ id: "app.components.Button.cancel",
2884
+ defaultMessage: "Cancel"
2885
+ }) }) }),
2886
+ endAction
2887
+ ] })
2888
+ ] }) });
2889
+ };
2890
+ const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
2891
+ const ConfirmDialogPublishAll = ({
2892
+ isOpen,
2893
+ onToggleDialog,
2894
+ isConfirmButtonLoading = false,
2895
+ onConfirm
2896
+ }) => {
2897
+ const { formatMessage } = reactIntl.useIntl();
2898
+ const selectedEntries = strapiAdmin.useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
2899
+ const { toggleNotification } = strapiAdmin.useNotification();
2900
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2901
+ const { model, schema } = useDoc();
2902
+ const [{ query }] = strapiAdmin.useQueryParams();
2903
+ const {
2904
+ data: countDraftRelations = 0,
2905
+ isLoading,
2906
+ error
2907
+ } = useGetManyDraftRelationCountQuery(
2908
+ {
2909
+ model,
2910
+ documentIds: selectedEntries.map((entry) => entry.documentId),
2911
+ locale: query?.plugins?.i18n?.locale
2912
+ },
2913
+ {
2914
+ skip: selectedEntries.length === 0
2915
+ }
2916
+ );
2917
+ React__namespace.useEffect(() => {
2918
+ if (error) {
2919
+ toggleNotification({ type: "danger", message: formatAPIError(error) });
2920
+ }
2921
+ }, [error, formatAPIError, toggleNotification]);
2922
+ if (error) {
2923
+ return null;
2924
+ }
2925
+ return /* @__PURE__ */ jsxRuntime.jsx(
2926
+ ConfirmBulkActionDialog,
2927
+ {
2928
+ isOpen: isOpen && !isLoading,
2929
+ onToggleDialog,
2930
+ dialogBody: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2931
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: [
2932
+ countDraftRelations > 0 && formatMessage(
2933
+ {
2934
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2935
+ 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. "
2936
+ },
2937
+ {
2938
+ b: BoldChunk$1,
2939
+ count: countDraftRelations,
2940
+ entities: selectedEntries.length
2941
+ }
2942
+ ),
2943
+ formatMessage({
2944
+ id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
2945
+ defaultMessage: "Are you sure you want to publish these entries?"
2946
+ })
2947
+ ] }),
2948
+ schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
2949
+ {
2950
+ id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
2951
+ defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
2952
+ },
2953
+ {
2954
+ em: Emphasis
2955
+ }
2956
+ ) })
2957
+ ] }),
2958
+ endAction: /* @__PURE__ */ jsxRuntime.jsx(
2959
+ designSystem.Button,
2960
+ {
2961
+ onClick: onConfirm,
2962
+ variant: "secondary",
2963
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
2964
+ loading: isConfirmButtonLoading,
2965
+ children: formatMessage({
2966
+ id: "app.utils.publish",
2967
+ defaultMessage: "Publish"
2968
+ })
2969
+ }
2970
+ )
2971
+ }
2972
+ );
2973
+ };
2974
+ const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
2975
+ max-width: 300px;
2976
+ `;
2977
+ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2978
+ const messages = [];
2979
+ Object.entries(errors).forEach(([key, value]) => {
2980
+ const currentKey = parentKey ? `${parentKey}.${key}` : key;
2981
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
2982
+ if ("id" in value && "defaultMessage" in value) {
2983
+ messages.push(
2984
+ formatMessage(
2985
+ {
2986
+ id: `${value.id}.withField`,
2987
+ defaultMessage: value.defaultMessage
2988
+ },
2989
+ { field: currentKey }
2990
+ )
2991
+ );
2992
+ } else {
2993
+ messages.push(
2994
+ ...formatErrorMessages(
2995
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
2996
+ value,
2997
+ currentKey,
2998
+ formatMessage
2999
+ )
3000
+ );
3001
+ }
3002
+ } else {
3003
+ messages.push(
3004
+ formatMessage(
3005
+ {
3006
+ id: `${value}.withField`,
3007
+ defaultMessage: value
3008
+ },
3009
+ { field: currentKey }
3010
+ )
3011
+ );
3012
+ }
3013
+ });
3014
+ return messages;
3015
+ };
3016
+ const EntryValidationText = ({ validationErrors, status }) => {
3017
+ const { formatMessage } = reactIntl.useIntl();
3018
+ if (validationErrors) {
3019
+ const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
3020
+ " "
3021
+ );
3022
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3023
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
3024
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
3025
+ ] });
3026
+ }
3027
+ if (status === "published") {
3028
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3029
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
3030
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
3031
+ id: "content-manager.bulk-publish.already-published",
3032
+ defaultMessage: "Already Published"
3033
+ }) })
3034
+ ] });
3035
+ }
3036
+ if (status === "modified") {
3037
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3038
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
3039
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3040
+ id: "content-manager.bulk-publish.modified",
3041
+ defaultMessage: "Ready to publish changes"
3042
+ }) })
3043
+ ] });
3044
+ }
3045
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3046
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
3047
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3048
+ id: "app.utils.ready-to-publish",
3049
+ defaultMessage: "Ready to publish"
3050
+ }) })
3051
+ ] });
3052
+ };
3053
+ const TABLE_HEADERS = [
3054
+ { name: "id", label: "id" },
3055
+ { name: "name", label: "name" },
3056
+ { name: "status", label: "status" },
3057
+ { name: "publicationStatus", label: "Publication status" }
3058
+ ];
3059
+ const SelectedEntriesTableContent = ({
3060
+ isPublishing,
3061
+ rowsToDisplay = [],
3062
+ entriesToPublish = [],
3063
+ validationErrors = {}
3064
+ }) => {
3065
+ const { pathname } = reactRouterDom.useLocation();
3066
+ const { formatMessage } = reactIntl.useIntl();
3067
+ const {
3068
+ list: {
3069
+ settings: { mainField }
3070
+ }
3071
+ } = useDocLayout();
3072
+ const shouldDisplayMainField = mainField != null && mainField !== "id";
3073
+ return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
3074
+ /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
3075
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
3076
+ TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
3077
+ (head) => /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, { ...head }, head.name)
3078
+ )
3079
+ ] }),
3080
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
3081
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
3082
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
3083
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
3084
+ shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
3085
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
3086
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3087
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3088
+ id: "content-manager.success.record.publishing",
3089
+ defaultMessage: "Publishing..."
3090
+ }) }),
3091
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true })
3092
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
3093
+ EntryValidationText,
3094
+ {
3095
+ validationErrors: validationErrors[row.documentId],
3096
+ status: row.status
3097
+ }
3098
+ ) }),
3099
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3100
+ designSystem.IconButton,
3101
+ {
3102
+ tag: reactRouterDom.Link,
3103
+ to: {
3104
+ pathname: `${pathname}/${row.documentId}`,
3105
+ search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3106
+ },
3107
+ state: { from: pathname },
3108
+ label: formatMessage(
3109
+ { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3110
+ {
3111
+ target: formatMessage(
3112
+ {
3113
+ id: "content-manager.components.ListViewHelperPluginTable.row-line",
3114
+ defaultMessage: "item line {number}"
3115
+ },
3116
+ { number: index2 + 1 }
3117
+ )
3118
+ }
3119
+ ),
3120
+ target: "_blank",
3121
+ marginLeft: "auto",
3122
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3123
+ }
3124
+ ) })
3125
+ ] }, row.id)) })
3126
+ ] });
3127
+ };
3128
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
3129
+ const SelectedEntriesModalContent = ({
3130
+ listViewSelectedEntries,
3131
+ toggleModal,
3132
+ setListViewSelectedDocuments,
3133
+ model
3134
+ }) => {
3135
+ const { formatMessage } = reactIntl.useIntl();
3136
+ const { schema, components } = useContentTypeSchema(model);
3137
+ const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
3138
+ const [{ query }] = strapiAdmin.useQueryParams();
3139
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3140
+ const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
3141
+ {
3142
+ model,
3143
+ params: {
3144
+ page: "1",
3145
+ pageSize: documentIds.length.toString(),
3146
+ sort: query.sort,
3147
+ filters: {
3148
+ documentId: {
3149
+ $in: documentIds
3150
+ }
3151
+ },
3152
+ locale: query.plugins?.i18n?.locale
3153
+ }
3154
+ },
3155
+ {
3156
+ selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
3157
+ }
3158
+ );
3159
+ const { rows, validationErrors } = React__namespace.useMemo(() => {
3160
+ if (data.length > 0 && schema) {
3161
+ const validate = createYupSchema(schema.attributes, components);
3162
+ const validationErrors2 = {};
3163
+ const rows2 = data.map((entry) => {
3164
+ try {
3165
+ validate.validateSync(entry, { abortEarly: false });
3166
+ return entry;
3167
+ } catch (e) {
3168
+ if (e instanceof yup.ValidationError) {
3169
+ validationErrors2[entry.documentId] = strapiAdmin.getYupValidationErrors(e);
3170
+ }
3171
+ return entry;
3172
+ }
3173
+ });
3174
+ return { rows: rows2, validationErrors: validationErrors2 };
3175
+ }
3176
+ return {
3177
+ rows: [],
3178
+ validationErrors: {}
3179
+ };
3180
+ }, [components, data, schema]);
3181
+ const [publishedCount, setPublishedCount] = React__namespace.useState(0);
3182
+ const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
3183
+ const { publishMany: bulkPublishAction } = useDocumentActions();
3184
+ const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
3185
+ const selectedRows = strapiAdmin.useTable("publishAction", (state) => state.selectedRows);
3186
+ const selectedEntries = rows.filter(
3187
+ (entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
3188
+ );
3189
+ const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
3190
+ const selectedEntriesWithErrorsCount = selectedEntries.filter(
3191
+ ({ documentId }) => validationErrors[documentId]
3192
+ ).length;
3193
+ const selectedEntriesPublished = selectedEntries.filter(
3194
+ ({ status }) => status === "published"
3195
+ ).length;
3196
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3197
+ const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3198
+ const handleConfirmBulkPublish = async () => {
3199
+ toggleDialog();
3200
+ const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3201
+ if (!("error" in res)) {
3202
+ setPublishedCount(res.count);
3203
+ const unpublishedEntries = rows.filter((row) => {
3204
+ return !entriesToPublish.includes(row.documentId);
3205
+ });
3206
+ setListViewSelectedDocuments(unpublishedEntries);
3207
+ }
3208
+ };
3209
+ const getFormattedCountMessage = () => {
3210
+ if (publishedCount) {
3211
+ return formatMessage(
3212
+ {
3213
+ id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3214
+ 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."
3215
+ },
3216
+ {
3217
+ publishedCount,
3218
+ withErrorsCount: selectedEntriesWithErrorsCount,
3219
+ b: BoldChunk
3220
+ }
3221
+ );
3222
+ }
3223
+ return formatMessage(
3224
+ {
3225
+ id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3226
+ 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."
3227
+ },
3228
+ {
3229
+ readyToPublishCount: selectedEntriesWithNoErrorsCount,
3230
+ withErrorsCount: selectedEntriesWithErrorsCount,
3231
+ alreadyPublishedCount: selectedEntriesPublished,
3232
+ b: BoldChunk
3233
+ }
3234
+ );
3235
+ };
3236
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3237
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
3238
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
3239
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
3240
+ SelectedEntriesTableContent,
3241
+ {
3242
+ isPublishing: isSubmittingForm,
3243
+ rowsToDisplay: rows,
3244
+ entriesToPublish,
3245
+ validationErrors
3246
+ }
3247
+ ) })
3248
+ ] }),
3249
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3250
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3251
+ id: "app.components.Button.cancel",
3252
+ defaultMessage: "Cancel"
3253
+ }) }),
3254
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3255
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3256
+ /* @__PURE__ */ jsxRuntime.jsx(
3257
+ designSystem.Button,
3258
+ {
3259
+ onClick: toggleDialog,
3260
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3261
+ loading: isSubmittingForm,
3262
+ children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3263
+ }
3264
+ )
3265
+ ] })
3266
+ ] }),
3267
+ /* @__PURE__ */ jsxRuntime.jsx(
3268
+ ConfirmDialogPublishAll,
3269
+ {
3270
+ isOpen: isDialogOpen,
3271
+ onToggleDialog: toggleDialog,
3272
+ isConfirmButtonLoading: isSubmittingForm,
3273
+ onConfirm: handleConfirmBulkPublish
3274
+ }
3275
+ )
3276
+ ] });
3277
+ };
3278
+ const PublishAction = ({ documents, model }) => {
3279
+ const { formatMessage } = reactIntl.useIntl();
3280
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3281
+ const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
3282
+ const setListViewSelectedDocuments = strapiAdmin.useTable("publishAction", (state) => state.selectRow);
3283
+ const refetchList = () => {
3284
+ contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3285
+ };
3286
+ if (!showPublishButton)
3287
+ return null;
3288
+ return {
3289
+ actionType: "publish",
3290
+ variant: "tertiary",
3291
+ label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
3292
+ dialog: {
3293
+ type: "modal",
3294
+ title: formatMessage({
3295
+ id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
3296
+ defaultMessage: "Publish entries"
3297
+ }),
3298
+ content: ({ onClose }) => {
3299
+ return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsxRuntime.jsx(
3300
+ SelectedEntriesModalContent,
3301
+ {
3302
+ listViewSelectedEntries: documents,
3303
+ toggleModal: () => {
3304
+ onClose();
3305
+ refetchList();
3306
+ },
3307
+ setListViewSelectedDocuments,
3308
+ model
3309
+ }
3310
+ ) });
3311
+ },
3312
+ onClose: () => {
3313
+ refetchList();
3314
+ }
3315
+ }
3316
+ };
3317
+ };
3318
+ const BulkActionsRenderer = () => {
3319
+ const plugins = strapiAdmin.useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
3320
+ const { model, collectionType } = useDoc();
3321
+ const { selectedRows } = strapiAdmin.useTable("BulkActionsRenderer", (state) => state);
3322
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
3323
+ strapiAdmin.DescriptionComponentRenderer,
3324
+ {
3325
+ props: {
3326
+ model,
3327
+ collectionType,
3328
+ documents: selectedRows
3329
+ },
3330
+ descriptions: plugins["content-manager"].apis.getBulkActions(),
3331
+ children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...action }, action.id))
3332
+ }
3333
+ ) });
3334
+ };
3335
+ const DeleteAction = ({ documents, model }) => {
3336
+ const { formatMessage } = reactIntl.useIntl();
3337
+ const { schema: contentType } = useDoc();
3338
+ const selectRow = strapiAdmin.useTable("DeleteAction", (state) => state.selectRow);
3339
+ const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
3340
+ const [{ query }] = strapiAdmin.useQueryParams();
3341
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3342
+ const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
3343
+ const { deleteMany: bulkDeleteAction } = useDocumentActions();
3344
+ const documentIds = documents.map(({ documentId }) => documentId);
3345
+ const handleConfirmBulkDelete = async () => {
3346
+ const res = await bulkDeleteAction({
3347
+ documentIds,
3348
+ model,
3349
+ params
3350
+ });
3351
+ if (!("error" in res)) {
3352
+ selectRow([]);
3353
+ }
3354
+ };
3355
+ if (!hasDeletePermission)
3356
+ return null;
3357
+ return {
3358
+ variant: "danger-light",
3359
+ label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
3360
+ dialog: {
3361
+ type: "dialog",
3362
+ title: formatMessage({
3363
+ id: "app.components.ConfirmDialog.title",
3364
+ defaultMessage: "Confirmation"
3365
+ }),
3366
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3367
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3368
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3369
+ id: "popUpWarning.bodyMessage.contentType.delete.all",
3370
+ defaultMessage: "Are you sure you want to delete these entries?"
3371
+ }) }),
3372
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3373
+ {
3374
+ id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
3375
+ defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
3376
+ },
3377
+ {
3378
+ em: Emphasis
3379
+ }
3380
+ ) }) })
3381
+ ] }),
3382
+ onConfirm: handleConfirmBulkDelete
3383
+ }
3384
+ };
3385
+ };
3386
+ DeleteAction.type = "delete";
3387
+ const UnpublishAction = ({ documents, model }) => {
3388
+ const { formatMessage } = reactIntl.useIntl();
3389
+ const { schema } = useDoc();
3390
+ const selectRow = strapiAdmin.useTable("UnpublishAction", (state) => state.selectRow);
3391
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3392
+ const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
3393
+ const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
3394
+ const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
3395
+ const documentIds = documents.map(({ documentId }) => documentId);
3396
+ const [{ query }] = strapiAdmin.useQueryParams();
3397
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3398
+ const handleConfirmBulkUnpublish = async () => {
3399
+ const data = await bulkUnpublishAction({ documentIds, model, params });
3400
+ if (!("error" in data)) {
3401
+ selectRow([]);
3402
+ }
3403
+ };
3404
+ const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3405
+ if (!showUnpublishButton)
3406
+ return null;
3407
+ return {
3408
+ variant: "tertiary",
3409
+ label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
3410
+ dialog: {
3411
+ type: "dialog",
3412
+ title: formatMessage({
3413
+ id: "app.components.ConfirmDialog.title",
3414
+ defaultMessage: "Confirmation"
3415
+ }),
3416
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3417
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3418
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3419
+ id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3420
+ defaultMessage: "Are you sure you want to unpublish these entries?"
3421
+ }) }),
3422
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3423
+ {
3424
+ id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
3425
+ defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
3426
+ },
3427
+ {
3428
+ em: Emphasis
3429
+ }
3430
+ ) }) })
3431
+ ] }),
3432
+ confirmButton: formatMessage({
3433
+ id: "app.utils.unpublish",
3434
+ defaultMessage: "Unpublish"
3435
+ }),
3436
+ onConfirm: handleConfirmBulkUnpublish
3437
+ }
3438
+ };
3439
+ };
3440
+ UnpublishAction.type = "unpublish";
3441
+ const Emphasis = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
3442
+ const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
3443
+ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3444
+ const { formatMessage } = reactIntl.useIntl();
3445
+ const getDefaultErrorMessage = (reason) => {
3446
+ switch (reason) {
3447
+ case "relation":
3448
+ return "Duplicating the relation could remove it from the original entry.";
3449
+ case "unique":
3450
+ return "Identical values in a unique field are not allowed";
3451
+ default:
3452
+ return reason;
3453
+ }
3454
+ };
3455
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3456
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: formatMessage({
3457
+ id: getTranslation("containers.list.autoCloneModal.title"),
3458
+ defaultMessage: "This entry can't be duplicated directly."
3459
+ }) }),
3460
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatMessage({
3461
+ id: getTranslation("containers.list.autoCloneModal.description"),
3462
+ defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
3463
+ }) }) }),
3464
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxRuntime.jsxs(
3465
+ designSystem.Flex,
3466
+ {
3467
+ direction: "column",
3468
+ gap: 2,
3469
+ alignItems: "flex-start",
3470
+ borderColor: "neutral200",
3471
+ hasRadius: true,
3472
+ padding: 6,
3473
+ children: [
3474
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", tag: "li", children: [
3475
+ pathSegment,
3476
+ index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
3477
+ Icons.ChevronRight,
3478
+ {
3479
+ fill: "neutral500",
3480
+ height: "0.8rem",
3481
+ width: "0.8rem",
3482
+ style: { margin: "0 0.8rem" }
3483
+ }
3484
+ )
3485
+ ] }, index2)) }),
3486
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
3487
+ id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
3488
+ defaultMessage: getDefaultErrorMessage(reason)
3489
+ }) })
3490
+ ]
3491
+ },
3492
+ fieldPath.join()
3493
+ )) })
3494
+ ] });
3495
+ };
3496
+ const TableActions = ({ document }) => {
3497
+ const { formatMessage } = reactIntl.useIntl();
3498
+ const { model, collectionType } = useDoc();
3499
+ const plugins = strapiAdmin.useStrapiApp("TableActions", (state) => state.plugins);
3500
+ const props = {
3501
+ activeTab: null,
3502
+ model,
3503
+ documentId: document.documentId,
3504
+ collectionType,
3505
+ document
3506
+ };
3507
+ return /* @__PURE__ */ jsxRuntime.jsx(
3508
+ strapiAdmin.DescriptionComponentRenderer,
3509
+ {
3510
+ props,
3511
+ descriptions: plugins["content-manager"].apis.getDocumentActions(),
3512
+ children: (actions2) => {
3513
+ const tableRowActions = actions2.filter((action) => {
3514
+ const positions = Array.isArray(action.position) ? action.position : [action.position];
3515
+ return positions.includes("table-row");
3516
+ });
3517
+ return /* @__PURE__ */ jsxRuntime.jsx(
3518
+ DocumentActionsMenu,
3519
+ {
3520
+ actions: tableRowActions,
3521
+ label: formatMessage({
3522
+ id: "content-manager.containers.list.table.row-actions",
3523
+ defaultMessage: "Row action"
3524
+ }),
3525
+ variant: "ghost"
3526
+ }
3527
+ );
3528
+ }
3529
+ }
3530
+ );
3531
+ };
3532
+ const EditAction = ({ documentId }) => {
3533
+ const navigate = reactRouterDom.useNavigate();
3534
+ const { formatMessage } = reactIntl.useIntl();
3535
+ const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
3536
+ const { toggleNotification } = strapiAdmin.useNotification();
3537
+ const [{ query }] = strapiAdmin.useQueryParams();
3538
+ return {
3539
+ disabled: !canRead,
3540
+ icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil, {}),
3541
+ label: formatMessage({
3542
+ id: "content-manager.actions.edit.label",
3543
+ defaultMessage: "Edit"
3544
+ }),
3545
+ position: "table-row",
3546
+ onClick: async () => {
2571
3547
  if (!documentId) {
2572
3548
  console.error(
2573
3549
  "You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
@@ -2591,7 +3567,7 @@ const EditAction = ({ documentId }) => {
2591
3567
  };
2592
3568
  };
2593
3569
  EditAction.type = "edit";
2594
- const StyledPencil = styled__default.default(Icons.Pencil)`
3570
+ const StyledPencil = styledComponents.styled(Icons.Pencil)`
2595
3571
  path {
2596
3572
  fill: currentColor;
2597
3573
  }
@@ -2651,7 +3627,7 @@ const CloneAction = ({ model, documentId }) => {
2651
3627
  /* @__PURE__ */ jsxRuntime.jsx(
2652
3628
  designSystem.LinkButton,
2653
3629
  {
2654
- as: reactRouterDom.NavLink,
3630
+ tag: reactRouterDom.NavLink,
2655
3631
  to: {
2656
3632
  pathname: `clone/${documentId}`
2657
3633
  },
@@ -2667,7 +3643,7 @@ const CloneAction = ({ model, documentId }) => {
2667
3643
  };
2668
3644
  };
2669
3645
  CloneAction.type = "clone";
2670
- const StyledDuplicate = styled__default.default(Icons.Duplicate)`
3646
+ const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
2671
3647
  path {
2672
3648
  fill: currentColor;
2673
3649
  }
@@ -2684,442 +3660,183 @@ class ContentManagerPlugin {
2684
3660
  documentActions = [
2685
3661
  ...DEFAULT_ACTIONS,
2686
3662
  ...DEFAULT_TABLE_ROW_ACTIONS,
2687
- ...DEFAULT_HEADER_ACTIONS,
2688
- HistoryAction
3663
+ ...DEFAULT_HEADER_ACTIONS
2689
3664
  ];
2690
3665
  editViewSidePanels = [ActionsPanel];
2691
3666
  headerActions = [];
2692
3667
  constructor() {
2693
3668
  }
2694
- 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);
3669
+ addEditViewSidePanel(panels) {
3670
+ if (Array.isArray(panels)) {
3671
+ this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
3672
+ } else if (typeof panels === "function") {
3673
+ this.editViewSidePanels = panels(this.editViewSidePanels);
2725
3674
  } else {
2726
3675
  throw new Error(
2727
- `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
2728
- actions2
3676
+ `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
3677
+ panels
2729
3678
  )}`
2730
3679
  );
2731
3680
  }
2732
3681
  }
2733
- addBulkAction(actions2) {
3682
+ addDocumentAction(actions2) {
2734
3683
  if (Array.isArray(actions2)) {
2735
- this.bulkActions = [...this.bulkActions, ...actions2];
3684
+ this.documentActions = [...this.documentActions, ...actions2];
2736
3685
  } else if (typeof actions2 === "function") {
2737
- this.bulkActions = actions2(this.bulkActions);
3686
+ this.documentActions = actions2(this.documentActions);
2738
3687
  } else {
2739
3688
  throw new Error(
2740
- `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3689
+ `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
2741
3690
  actions2
2742
3691
  )}`
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;
3692
+ );
3693
+ }
3694
+ }
3695
+ addDocumentHeaderAction(actions2) {
3696
+ if (Array.isArray(actions2)) {
3697
+ this.headerActions = [...this.headerActions, ...actions2];
3698
+ } else if (typeof actions2 === "function") {
3699
+ this.headerActions = actions2(this.headerActions);
2982
3700
  } else {
2983
- if (!panels[currentPanelIndex]) {
2984
- panels.push([]);
2985
- }
2986
- panels[currentPanelIndex].push(row);
3701
+ throw new Error(
3702
+ `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
3703
+ actions2
3704
+ )}`
3705
+ );
2987
3706
  }
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
3707
+ }
3708
+ addBulkAction(actions2) {
3709
+ if (Array.isArray(actions2)) {
3710
+ this.bulkActions = [...this.bulkActions, ...actions2];
3711
+ } else if (typeof actions2 === "function") {
3712
+ this.bulkActions = actions2(this.bulkActions);
3713
+ } else {
3714
+ throw new Error(
3715
+ `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3716
+ actions2
3717
+ )}`
3718
+ );
3029
3719
  }
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;
3720
+ }
3721
+ get config() {
3722
+ return {
3723
+ id: PLUGIN_ID,
3724
+ name: "Content Manager",
3725
+ injectionZones: INJECTION_ZONES,
3726
+ apis: {
3727
+ addBulkAction: this.addBulkAction.bind(this),
3728
+ addDocumentAction: this.addDocumentAction.bind(this),
3729
+ addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3730
+ addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3731
+ getBulkActions: () => this.bulkActions,
3732
+ getDocumentActions: () => this.documentActions,
3733
+ getEditViewSidePanels: () => this.editViewSidePanels,
3734
+ getHeaderActions: () => this.headerActions
3038
3735
  }
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
- );
3736
+ };
3737
+ }
3738
+ }
3739
+ const getPrintableType = (value) => {
3740
+ const nativeType = typeof value;
3741
+ if (nativeType === "object") {
3742
+ if (value === null)
3743
+ return "null";
3744
+ if (Array.isArray(value))
3745
+ return "array";
3746
+ if (value instanceof Object && value.constructor.name !== "Object") {
3747
+ return value.constructor.name;
3748
+ }
3749
+ }
3750
+ return nativeType;
3061
3751
  };
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
- );
3752
+ const HistoryAction = ({ model, document }) => {
3753
+ const { formatMessage } = reactIntl.useIntl();
3754
+ const [{ query }] = strapiAdmin.useQueryParams();
3755
+ const navigate = reactRouterDom.useNavigate();
3756
+ const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
3757
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3758
+ return null;
3759
+ }
3083
3760
  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
- }
3761
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
3762
+ label: formatMessage({
3763
+ id: "content-manager.history.document-action",
3764
+ defaultMessage: "Content History"
3765
+ }),
3766
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3767
+ disabled: (
3768
+ /**
3769
+ * The user is creating a new document.
3770
+ * It hasn't been saved yet, so there's no history to go to
3771
+ */
3772
+ !document || /**
3773
+ * The document has been created but the current dimension has never been saved.
3774
+ * For example, the user is creating a new locale in an existing document,
3775
+ * so there's no history for the document in that locale
3776
+ */
3777
+ !document.id || /**
3778
+ * History is only available for content types created by the user.
3779
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3780
+ * which start with `admin::` or `plugin::`
3781
+ */
3782
+ !model.startsWith("api::")
3783
+ ),
3784
+ position: "header"
3092
3785
  };
3093
3786
  };
3094
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
3095
- return columns.map((name) => {
3096
- const attribute = attributes[name];
3097
- if (!attribute) {
3098
- return null;
3099
- }
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);
3787
+ HistoryAction.type = "history";
3788
+ const historyAdmin = {
3789
+ bootstrap(app) {
3790
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3791
+ addDocumentAction((actions2) => {
3792
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3793
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3794
+ return actions2;
3795
+ });
3796
+ }
3797
+ };
3798
+ const initialState = {
3799
+ collectionTypeLinks: [],
3800
+ components: [],
3801
+ fieldSizes: {},
3802
+ models: [],
3803
+ singleTypeLinks: [],
3804
+ isLoading: true
3114
3805
  };
3806
+ const appSlice = toolkit.createSlice({
3807
+ name: "app",
3808
+ initialState,
3809
+ reducers: {
3810
+ setInitialData(state, action) {
3811
+ const {
3812
+ authorizedCollectionTypeLinks,
3813
+ authorizedSingleTypeLinks,
3814
+ components,
3815
+ contentTypeSchemas,
3816
+ fieldSizes
3817
+ } = action.payload;
3818
+ state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
3819
+ ({ isDisplayed }) => isDisplayed
3820
+ );
3821
+ state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
3822
+ state.components = components;
3823
+ state.models = contentTypeSchemas;
3824
+ state.fieldSizes = fieldSizes;
3825
+ state.isLoading = false;
3826
+ }
3827
+ }
3828
+ });
3829
+ const { actions, reducer: reducer$1 } = appSlice;
3830
+ const { setInitialData } = actions;
3831
+ const reducer = toolkit.combineReducers({
3832
+ app: reducer$1
3833
+ });
3115
3834
  const index = {
3116
3835
  register(app) {
3117
3836
  const cm = new ContentManagerPlugin();
3118
3837
  app.addReducers({
3119
- [contentManagerApi.reducerPath]: contentManagerApi.reducer,
3120
3838
  [PLUGIN_ID]: reducer
3121
3839
  });
3122
- app.addMiddlewares([() => contentManagerApi.middleware]);
3123
3840
  app.addMenuLink({
3124
3841
  to: PLUGIN_ID,
3125
3842
  icon: Icons.Feather,
@@ -3128,14 +3845,29 @@ const index = {
3128
3845
  defaultMessage: "Content Manager"
3129
3846
  },
3130
3847
  permissions: [],
3131
- Component: () => Promise.resolve().then(() => require("./layout-dBc7wN7L.js")).then((mod) => ({ default: mod.Layout }))
3848
+ position: 1
3849
+ });
3850
+ app.router.addRoute({
3851
+ path: "content-manager/*",
3852
+ lazy: async () => {
3853
+ const { Layout } = await Promise.resolve().then(() => require("./layout-TPqF2oJ5.js"));
3854
+ return {
3855
+ Component: Layout
3856
+ };
3857
+ },
3858
+ children: routes
3132
3859
  });
3133
3860
  app.registerPlugin(cm.config);
3134
3861
  },
3862
+ bootstrap(app) {
3863
+ if (typeof historyAdmin.bootstrap === "function") {
3864
+ historyAdmin.bootstrap(app);
3865
+ }
3866
+ },
3135
3867
  async registerTrads({ locales }) {
3136
3868
  const importedTrads = await Promise.all(
3137
3869
  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 }) => {
3870
+ 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-uOUIxfcQ.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
3871
  return {
3140
3872
  data: prefixPluginTranslations(data, PLUGIN_ID),
3141
3873
  locale
@@ -3152,6 +3884,7 @@ const index = {
3152
3884
  }
3153
3885
  };
3154
3886
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3887
+ exports.BulkActionsRenderer = BulkActionsRenderer;
3155
3888
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3156
3889
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3157
3890
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3178,7 +3911,6 @@ exports.getDisplayName = getDisplayName;
3178
3911
  exports.getMainField = getMainField;
3179
3912
  exports.getTranslation = getTranslation;
3180
3913
  exports.index = index;
3181
- exports.routes = routes;
3182
3914
  exports.setInitialData = setInitialData;
3183
3915
  exports.useContentTypeSchema = useContentTypeSchema;
3184
3916
  exports.useDoc = useDoc;
@@ -3192,4 +3924,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3192
3924
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3193
3925
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3194
3926
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3195
- //# sourceMappingURL=index-X_2tafck.js.map
3927
+ //# sourceMappingURL=index-DyvUPg1a.js.map