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

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 (180) 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-43KmCNQE.js → ComponentConfigurationPage-BWQv6yRj.js} +3 -3
  7. package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js.map → ComponentConfigurationPage-BWQv6yRj.js.map} +1 -1
  8. package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs → ComponentConfigurationPage-C7ImeKGM.mjs} +3 -3
  9. package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs.map → ComponentConfigurationPage-C7ImeKGM.mjs.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-CEGwxV-L.js} +3 -3
  15. package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js.map → EditConfigurationPage-CEGwxV-L.js.map} +1 -1
  16. package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs → EditConfigurationPage-MItFGzT9.mjs} +3 -3
  17. package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs.map → EditConfigurationPage-MItFGzT9.mjs.map} +1 -1
  18. package/dist/_chunks/{EditViewPage-CzOT5Kpj.js → EditViewPage-CmMi2Xsn.js} +46 -48
  19. package/dist/_chunks/EditViewPage-CmMi2Xsn.js.map +1 -0
  20. package/dist/_chunks/{EditViewPage-Bm8lgcm6.mjs → EditViewPage-DhmAg0NK.mjs} +47 -47
  21. package/dist/_chunks/EditViewPage-DhmAg0NK.mjs.map +1 -0
  22. package/dist/_chunks/{Field-Caef4JjM.js → Field-1DLtcLAI.js} +948 -777
  23. package/dist/_chunks/Field-1DLtcLAI.js.map +1 -0
  24. package/dist/_chunks/{Field-Dlh0uGnL.mjs → Field-Cs62u5pl.mjs} +896 -724
  25. package/dist/_chunks/Field-Cs62u5pl.mjs.map +1 -0
  26. package/dist/_chunks/{Form-BzuAjtRq.js → Form-CqFA7F_V.js} +42 -41
  27. package/dist/_chunks/Form-CqFA7F_V.js.map +1 -0
  28. package/dist/_chunks/{Form-EnaQL_6L.mjs → Form-zYHtzGUX.mjs} +43 -41
  29. package/dist/_chunks/Form-zYHtzGUX.mjs.map +1 -0
  30. package/dist/_chunks/{History-C17LiyRg.js → History-BblwXv7-.js} +149 -66
  31. package/dist/_chunks/History-BblwXv7-.js.map +1 -0
  32. package/dist/_chunks/{History-D6sbCJvo.mjs → History-DalgFQ3D.mjs} +149 -65
  33. package/dist/_chunks/History-DalgFQ3D.mjs.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-Dks5SX6f.js → ListConfigurationPage-Cpy4QqNd.js} +61 -62
  35. package/dist/_chunks/ListConfigurationPage-Cpy4QqNd.js.map +1 -0
  36. package/dist/_chunks/{ListConfigurationPage-Ce4qs7qE.mjs → ListConfigurationPage-DWy-vRzs.mjs} +58 -58
  37. package/dist/_chunks/ListConfigurationPage-DWy-vRzs.mjs.map +1 -0
  38. package/dist/_chunks/{ListViewPage-Be7S5aKL.mjs → ListViewPage-BkAwIW9s.mjs} +90 -106
  39. package/dist/_chunks/ListViewPage-BkAwIW9s.mjs.map +1 -0
  40. package/dist/_chunks/{ListViewPage-BwrZrPsh.js → ListViewPage-DFjn1DNW.js} +95 -111
  41. package/dist/_chunks/ListViewPage-DFjn1DNW.js.map +1 -0
  42. package/dist/_chunks/{NoContentTypePage-CIPmYQMm.mjs → NoContentTypePage-B9BCNNdL.mjs} +7 -7
  43. package/dist/_chunks/NoContentTypePage-B9BCNNdL.mjs.map +1 -0
  44. package/dist/_chunks/{NoContentTypePage-Cu5r1-JT.js → NoContentTypePage-C-3ykoxs.js} +5 -5
  45. package/dist/_chunks/NoContentTypePage-C-3ykoxs.js.map +1 -0
  46. package/dist/_chunks/{NoPermissionsPage-DhJ7LYrr.mjs → NoPermissionsPage-Bt_HWGat.mjs} +5 -6
  47. package/dist/_chunks/NoPermissionsPage-Bt_HWGat.mjs.map +1 -0
  48. package/dist/_chunks/{NoPermissionsPage-C-j6TEUF.js → NoPermissionsPage-DKLmDZnZ.js} +4 -5
  49. package/dist/_chunks/NoPermissionsPage-DKLmDZnZ.js.map +1 -0
  50. package/dist/_chunks/{Relations-CY7AtkDA.mjs → Relations-CJmTbZ8T.mjs} +66 -56
  51. package/dist/_chunks/Relations-CJmTbZ8T.mjs.map +1 -0
  52. package/dist/_chunks/{Relations-Czs-uZ-s.js → Relations-CrxfoH2n.js} +70 -61
  53. package/dist/_chunks/Relations-CrxfoH2n.js.map +1 -0
  54. package/dist/_chunks/{en-MBPul9Su.mjs → en-Ux26r5pl.mjs} +7 -1
  55. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-Ux26r5pl.mjs.map} +1 -1
  56. package/dist/_chunks/{en-C-V1_90f.js → en-fbKQxLGn.js} +7 -1
  57. package/dist/_chunks/{en-C-V1_90f.js.map → en-fbKQxLGn.js.map} +1 -1
  58. package/dist/_chunks/{index-X_2tafck.js → index-Buwn78Rt.js} +1507 -868
  59. package/dist/_chunks/index-Buwn78Rt.js.map +1 -0
  60. package/dist/_chunks/{index-DNVx8ssZ.mjs → index-D1344xdw.mjs} +1476 -836
  61. package/dist/_chunks/index-D1344xdw.mjs.map +1 -0
  62. package/dist/_chunks/{layout-Dnh0PNp9.mjs → layout-ChVuUpa1.mjs} +32 -27
  63. package/dist/_chunks/layout-ChVuUpa1.mjs.map +1 -0
  64. package/dist/_chunks/{layout-dBc7wN7L.js → layout-DRuJUpas.js} +32 -29
  65. package/dist/_chunks/layout-DRuJUpas.js.map +1 -0
  66. package/dist/_chunks/{relations-Dx7tMKJN.mjs → relations-B-deMCy4.mjs} +2 -2
  67. package/dist/_chunks/{relations-Dx7tMKJN.mjs.map → relations-B-deMCy4.mjs.map} +1 -1
  68. package/dist/_chunks/{relations-4pHtBrHJ.js → relations-DuoUwyJr.js} +2 -2
  69. package/dist/_chunks/{relations-4pHtBrHJ.js.map → relations-DuoUwyJr.js.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/services/historyVersion.d.ts +1 -1
  84. package/dist/admin/src/hooks/useDocument.d.ts +5 -8
  85. package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
  86. package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
  87. package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
  88. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
  89. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +10 -4
  90. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
  91. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  92. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
  93. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  94. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  95. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +10 -18
  96. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  97. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  98. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  99. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +59 -52
  100. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  101. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  102. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  103. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  104. package/dist/admin/src/services/api.d.ts +2 -3
  105. package/dist/admin/src/services/components.d.ts +2 -2
  106. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  107. package/dist/admin/src/services/documents.d.ts +29 -17
  108. package/dist/admin/src/services/init.d.ts +2 -2
  109. package/dist/admin/src/services/relations.d.ts +3 -3
  110. package/dist/admin/src/services/uid.d.ts +3 -3
  111. package/dist/admin/src/utils/api.d.ts +4 -18
  112. package/dist/admin/src/utils/validation.d.ts +1 -6
  113. package/dist/server/index.js +547 -416
  114. package/dist/server/index.js.map +1 -1
  115. package/dist/server/index.mjs +555 -424
  116. package/dist/server/index.mjs.map +1 -1
  117. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  118. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  119. package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
  120. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  121. package/dist/server/src/controllers/validation/dimensions.d.ts +9 -0
  122. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  123. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  124. package/dist/server/src/history/services/history.d.ts +2 -4
  125. package/dist/server/src/history/services/history.d.ts.map +1 -1
  126. package/dist/server/src/history/services/index.d.ts +6 -2
  127. package/dist/server/src/history/services/index.d.ts.map +1 -1
  128. package/dist/server/src/history/services/lifecycles.d.ts +9 -0
  129. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -0
  130. package/dist/server/src/history/services/utils.d.ts +41 -9
  131. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  132. package/dist/server/src/history/utils.d.ts +6 -2
  133. package/dist/server/src/history/utils.d.ts.map +1 -1
  134. package/dist/server/src/index.d.ts +18 -39
  135. package/dist/server/src/index.d.ts.map +1 -1
  136. package/dist/server/src/services/document-manager.d.ts +13 -12
  137. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  138. package/dist/server/src/services/document-metadata.d.ts +8 -29
  139. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  140. package/dist/server/src/services/index.d.ts +18 -39
  141. package/dist/server/src/services/index.d.ts.map +1 -1
  142. package/dist/server/src/services/utils/populate.d.ts +8 -1
  143. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  144. package/dist/shared/contracts/collection-types.d.ts +14 -6
  145. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  146. package/dist/shared/contracts/relations.d.ts +2 -2
  147. package/dist/shared/contracts/relations.d.ts.map +1 -1
  148. package/package.json +13 -14
  149. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  150. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  151. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  152. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  153. package/dist/_chunks/EditViewPage-Bm8lgcm6.mjs.map +0 -1
  154. package/dist/_chunks/EditViewPage-CzOT5Kpj.js.map +0 -1
  155. package/dist/_chunks/Field-Caef4JjM.js.map +0 -1
  156. package/dist/_chunks/Field-Dlh0uGnL.mjs.map +0 -1
  157. package/dist/_chunks/Form-BzuAjtRq.js.map +0 -1
  158. package/dist/_chunks/Form-EnaQL_6L.mjs.map +0 -1
  159. package/dist/_chunks/History-C17LiyRg.js.map +0 -1
  160. package/dist/_chunks/History-D6sbCJvo.mjs.map +0 -1
  161. package/dist/_chunks/ListConfigurationPage-Ce4qs7qE.mjs.map +0 -1
  162. package/dist/_chunks/ListConfigurationPage-Dks5SX6f.js.map +0 -1
  163. package/dist/_chunks/ListViewPage-Be7S5aKL.mjs.map +0 -1
  164. package/dist/_chunks/ListViewPage-BwrZrPsh.js.map +0 -1
  165. package/dist/_chunks/NoContentTypePage-CIPmYQMm.mjs.map +0 -1
  166. package/dist/_chunks/NoContentTypePage-Cu5r1-JT.js.map +0 -1
  167. package/dist/_chunks/NoPermissionsPage-C-j6TEUF.js.map +0 -1
  168. package/dist/_chunks/NoPermissionsPage-DhJ7LYrr.mjs.map +0 -1
  169. package/dist/_chunks/Relations-CY7AtkDA.mjs.map +0 -1
  170. package/dist/_chunks/Relations-Czs-uZ-s.js.map +0 -1
  171. package/dist/_chunks/index-DNVx8ssZ.mjs.map +0 -1
  172. package/dist/_chunks/index-X_2tafck.js.map +0 -1
  173. package/dist/_chunks/layout-Dnh0PNp9.mjs.map +0 -1
  174. package/dist/_chunks/layout-dBc7wN7L.js.map +0 -1
  175. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  176. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  177. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  178. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  179. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  180. package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
@@ -7,10 +7,8 @@ const reactIntl = require("react-intl");
7
7
  const reactRouterDom = require("react-router-dom");
8
8
  const React = require("react");
9
9
  const designSystem = require("@strapi/design-system");
10
- const styled = require("styled-components");
10
+ const styledComponents = require("styled-components");
11
11
  const yup = require("yup");
12
- const react = require("@reduxjs/toolkit/query/react");
13
- const axios = require("axios");
14
12
  const pipe = require("lodash/fp/pipe");
15
13
  const dateFns = require("date-fns");
16
14
  const toolkit = require("@reduxjs/toolkit");
@@ -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) => {
@@ -179,9 +176,8 @@ const DocumentRBAC = ({ children, permissions }) => {
179
176
  const name = removeNumericalStrings(fieldName.split("."));
180
177
  const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
181
178
  if (fieldType === "component") {
182
- const componentOrDynamicZoneFields = componentFieldNames.map((field) => field.split("."));
183
- return componentOrDynamicZoneFields.some((field) => {
184
- return field.includes(fieldName);
179
+ return componentFieldNames.some((field) => {
180
+ return field.includes(name.join("."));
185
181
  });
186
182
  }
187
183
  if (name.length > 1) {
@@ -211,78 +207,8 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
211
207
  (field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
212
208
  );
213
209
  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: [
210
+ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
211
+ addTagTypes: [
286
212
  "ComponentConfiguration",
287
213
  "ContentTypesConfiguration",
288
214
  "ContentTypeSettings",
@@ -290,10 +216,10 @@ const contentManagerApi = react.createApi({
290
216
  "InitialData",
291
217
  "HistoryVersion",
292
218
  "Relations"
293
- ],
294
- endpoints: () => ({})
219
+ ]
295
220
  });
296
221
  const documentApi = contentManagerApi.injectEndpoints({
222
+ overrideExisting: true,
297
223
  endpoints: (builder) => ({
298
224
  autoCloneDocument: builder.mutation({
299
225
  query: ({ model, sourceId, query }) => ({
@@ -347,12 +273,15 @@ const documentApi = contentManagerApi.injectEndpoints({
347
273
  ]
348
274
  }),
349
275
  deleteManyDocuments: builder.mutation({
350
- query: ({ model, ...body }) => ({
276
+ query: ({ model, params, ...body }) => ({
351
277
  url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
352
278
  method: "POST",
353
- data: body
279
+ data: body,
280
+ config: {
281
+ params
282
+ }
354
283
  }),
355
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
284
+ invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
356
285
  }),
357
286
  discardDocument: builder.mutation({
358
287
  query: ({ collectionType, model, documentId, params }) => ({
@@ -463,10 +392,13 @@ const documentApi = contentManagerApi.injectEndpoints({
463
392
  }
464
393
  }),
465
394
  publishManyDocuments: builder.mutation({
466
- query: ({ model, ...body }) => ({
395
+ query: ({ model, params, ...body }) => ({
467
396
  url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
468
397
  method: "POST",
469
- data: body
398
+ data: body,
399
+ config: {
400
+ params
401
+ }
470
402
  }),
471
403
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
472
404
  }),
@@ -508,10 +440,13 @@ const documentApi = contentManagerApi.injectEndpoints({
508
440
  }
509
441
  }),
510
442
  unpublishManyDocuments: builder.mutation({
511
- query: ({ model, ...body }) => ({
443
+ query: ({ model, params, ...body }) => ({
512
444
  url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
513
445
  method: "POST",
514
- data: body
446
+ data: body,
447
+ config: {
448
+ params
449
+ }
515
450
  }),
516
451
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
517
452
  })
@@ -535,6 +470,24 @@ const {
535
470
  useUnpublishDocumentMutation,
536
471
  useUnpublishManyDocumentsMutation
537
472
  } = documentApi;
473
+ const buildValidParams = (query) => {
474
+ if (!query)
475
+ return query;
476
+ const { plugins: _, ...validQueryParams } = {
477
+ ...query,
478
+ ...Object.values(query?.plugins ?? {}).reduce(
479
+ (acc, current) => Object.assign(acc, current),
480
+ {}
481
+ )
482
+ };
483
+ if ("_q" in validQueryParams) {
484
+ validQueryParams._q = encodeURIComponent(validQueryParams._q);
485
+ }
486
+ return validQueryParams;
487
+ };
488
+ const isBaseQueryError = (error) => {
489
+ return error.name !== void 0;
490
+ };
538
491
  const createYupSchema = (attributes = {}, components = {}) => {
539
492
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
540
493
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
@@ -574,10 +527,14 @@ const createYupSchema = (attributes = {}, components = {}) => {
574
527
  yup__namespace.array().of(
575
528
  yup__namespace.lazy(
576
529
  (data) => {
577
- const { attributes: attributes3 } = components[data.__component];
578
- return yup__namespace.object().shape({
530
+ const attributes3 = components?.[data?.__component]?.attributes;
531
+ const validation = yup__namespace.object().shape({
579
532
  __component: yup__namespace.string().required().oneOf(Object.keys(components))
580
- }).nullable(false).concat(createModelSchema(attributes3));
533
+ }).nullable(false);
534
+ if (!attributes3) {
535
+ return validation;
536
+ }
537
+ return validation.concat(createModelSchema(attributes3));
581
538
  }
582
539
  )
583
540
  )
@@ -587,11 +544,25 @@ const createYupSchema = (attributes = {}, components = {}) => {
587
544
  return {
588
545
  ...acc,
589
546
  [name]: transformSchema(
590
- yup__namespace.array().of(
591
- yup__namespace.object().shape({
592
- id: yup__namespace.string().required()
593
- })
594
- )
547
+ yup__namespace.lazy((value) => {
548
+ if (!value) {
549
+ return yup__namespace.mixed().nullable(true);
550
+ } else if (Array.isArray(value)) {
551
+ return yup__namespace.array().of(
552
+ yup__namespace.object().shape({
553
+ id: yup__namespace.string().required()
554
+ })
555
+ );
556
+ } else if (typeof value === "object") {
557
+ return yup__namespace.object();
558
+ } else {
559
+ return yup__namespace.mixed().test(
560
+ "type-error",
561
+ "Relation values must be either null, an array of objects with {id} or an object.",
562
+ () => false
563
+ );
564
+ }
565
+ })
595
566
  )
596
567
  };
597
568
  default:
@@ -650,13 +621,18 @@ const createAttributeSchema = (attribute) => {
650
621
  }
651
622
  };
652
623
  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
- });
624
+ if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
625
+ return schema.min(1, strapiAdmin.translatedErrors.required);
658
626
  }
659
- return schema.nullable();
627
+ if (attribute.required && attribute.type !== "relation") {
628
+ return schema.required(strapiAdmin.translatedErrors.required);
629
+ }
630
+ return schema?.nullable ? schema.nullable() : (
631
+ // In some cases '.nullable' will not be available on the schema.
632
+ // e.g. when the schema has been built using yup.lazy (e.g. for relations).
633
+ // In these cases we should just return the schema as it is.
634
+ schema
635
+ );
660
636
  };
661
637
  const addMinLengthValidation = (attribute) => (schema) => {
662
638
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
@@ -683,6 +659,28 @@ const addMaxLengthValidation = (attribute) => (schema) => {
683
659
  const addMinValidation = (attribute) => (schema) => {
684
660
  if ("min" in attribute) {
685
661
  const min = toInteger(attribute.min);
662
+ if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
663
+ if (!attribute.required && "test" in schema && min) {
664
+ return schema.test(
665
+ "custom-min",
666
+ {
667
+ ...strapiAdmin.translatedErrors.min,
668
+ values: {
669
+ min: attribute.min
670
+ }
671
+ },
672
+ (value) => {
673
+ if (!value) {
674
+ return true;
675
+ }
676
+ if (Array.isArray(value) && value.length === 0) {
677
+ return true;
678
+ }
679
+ return value.length >= min;
680
+ }
681
+ );
682
+ }
683
+ }
686
684
  if ("min" in schema && min) {
687
685
  return schema.min(min, {
688
686
  ...strapiAdmin.translatedErrors.min,
@@ -728,24 +726,6 @@ const addRegexValidation = (attribute) => (schema) => {
728
726
  }
729
727
  return schema;
730
728
  };
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
729
  const initApi = contentManagerApi.injectEndpoints({
750
730
  endpoints: (builder) => ({
751
731
  getInitialData: builder.query({
@@ -759,27 +739,20 @@ const { useGetInitialDataQuery } = initApi;
759
739
  const useContentTypeSchema = (model) => {
760
740
  const { toggleNotification } = strapiAdmin.useNotification();
761
741
  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
- });
742
+ const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
743
+ const { components, contentType, contentTypes } = React__namespace.useMemo(() => {
744
+ const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
745
+ const componentsByKey = data?.components.reduce((acc, component) => {
746
+ acc[component.uid] = component;
747
+ return acc;
748
+ }, {});
749
+ const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
750
+ return {
751
+ components: Object.keys(components2).length === 0 ? void 0 : components2,
752
+ contentType: contentType2,
753
+ contentTypes: data?.contentTypes ?? []
754
+ };
755
+ }, [model, data]);
783
756
  React__namespace.useEffect(() => {
784
757
  if (error) {
785
758
  toggleNotification({
@@ -834,7 +807,10 @@ const useDocument = (args, opts) => {
834
807
  isLoading: isLoadingDocument,
835
808
  isFetching: isFetchingDocument,
836
809
  error
837
- } = useGetDocumentQuery(args, opts);
810
+ } = useGetDocumentQuery(args, {
811
+ ...opts,
812
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
813
+ });
838
814
  const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
839
815
  React__namespace.useEffect(() => {
840
816
  if (error) {
@@ -862,7 +838,7 @@ const useDocument = (args, opts) => {
862
838
  return null;
863
839
  } catch (error2) {
864
840
  if (error2 instanceof yup.ValidationError) {
865
- return getInnerErrors(error2);
841
+ return strapiAdmin.getYupValidationErrors(error2);
866
842
  }
867
843
  throw error2;
868
844
  }
@@ -958,14 +934,53 @@ const useDocumentActions = () => {
958
934
  },
959
935
  [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
960
936
  );
937
+ const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
938
+ const deleteMany = React__namespace.useCallback(
939
+ async ({ model, documentIds, params }) => {
940
+ try {
941
+ trackUsage("willBulkDeleteEntries");
942
+ const res = await deleteManyDocuments({
943
+ model,
944
+ documentIds,
945
+ params
946
+ });
947
+ if ("error" in res) {
948
+ toggleNotification({
949
+ type: "danger",
950
+ message: formatAPIError(res.error)
951
+ });
952
+ return { error: res.error };
953
+ }
954
+ toggleNotification({
955
+ type: "success",
956
+ title: formatMessage({
957
+ id: getTranslation("success.records.delete"),
958
+ defaultMessage: "Successfully deleted."
959
+ }),
960
+ message: ""
961
+ });
962
+ trackUsage("didBulkDeleteEntries");
963
+ return res.data;
964
+ } catch (err) {
965
+ toggleNotification({
966
+ type: "danger",
967
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
968
+ });
969
+ trackUsage("didNotBulkDeleteEntries");
970
+ throw err;
971
+ }
972
+ },
973
+ [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
974
+ );
961
975
  const [discardDocument] = useDiscardDocumentMutation();
962
976
  const discard = React__namespace.useCallback(
963
- async ({ collectionType, model, documentId }) => {
977
+ async ({ collectionType, model, documentId, params }) => {
964
978
  try {
965
979
  const res = await discardDocument({
966
980
  collectionType,
967
981
  model,
968
- documentId
982
+ documentId,
983
+ params
969
984
  });
970
985
  if ("error" in res) {
971
986
  toggleNotification({
@@ -1027,6 +1042,43 @@ const useDocumentActions = () => {
1027
1042
  },
1028
1043
  [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1029
1044
  );
1045
+ const [publishManyDocuments] = usePublishManyDocumentsMutation();
1046
+ const publishMany = React__namespace.useCallback(
1047
+ async ({ model, documentIds, params }) => {
1048
+ try {
1049
+ const res = await publishManyDocuments({
1050
+ model,
1051
+ documentIds,
1052
+ params
1053
+ });
1054
+ if ("error" in res) {
1055
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1056
+ return { error: res.error };
1057
+ }
1058
+ toggleNotification({
1059
+ type: "success",
1060
+ message: formatMessage({
1061
+ id: getTranslation("success.record.publish"),
1062
+ defaultMessage: "Published document"
1063
+ })
1064
+ });
1065
+ return res.data;
1066
+ } catch (err) {
1067
+ toggleNotification({
1068
+ type: "danger",
1069
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1070
+ });
1071
+ throw err;
1072
+ }
1073
+ },
1074
+ [
1075
+ // trackUsage,
1076
+ publishManyDocuments,
1077
+ toggleNotification,
1078
+ formatMessage,
1079
+ formatAPIError
1080
+ ]
1081
+ );
1030
1082
  const [updateDocument] = useUpdateDocumentMutation();
1031
1083
  const update = React__namespace.useCallback(
1032
1084
  async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
@@ -1101,6 +1153,41 @@ const useDocumentActions = () => {
1101
1153
  },
1102
1154
  [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1103
1155
  );
1156
+ const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1157
+ const unpublishMany = React__namespace.useCallback(
1158
+ async ({ model, documentIds, params }) => {
1159
+ try {
1160
+ trackUsage("willBulkUnpublishEntries");
1161
+ const res = await unpublishManyDocuments({
1162
+ model,
1163
+ documentIds,
1164
+ params
1165
+ });
1166
+ if ("error" in res) {
1167
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1168
+ return { error: res.error };
1169
+ }
1170
+ trackUsage("didBulkUnpublishEntries");
1171
+ toggleNotification({
1172
+ type: "success",
1173
+ title: formatMessage({
1174
+ id: getTranslation("success.records.unpublish"),
1175
+ defaultMessage: "Successfully unpublished."
1176
+ }),
1177
+ message: ""
1178
+ });
1179
+ return res.data;
1180
+ } catch (err) {
1181
+ toggleNotification({
1182
+ type: "danger",
1183
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1184
+ });
1185
+ trackUsage("didNotBulkUnpublishEntries");
1186
+ throw err;
1187
+ }
1188
+ },
1189
+ [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1190
+ );
1104
1191
  const [createDocument] = useCreateDocumentMutation();
1105
1192
  const create = React__namespace.useCallback(
1106
1193
  async ({ model, params }, data, trackerProperty) => {
@@ -1214,15 +1301,18 @@ const useDocumentActions = () => {
1214
1301
  clone,
1215
1302
  create,
1216
1303
  delete: _delete,
1304
+ deleteMany,
1217
1305
  discard,
1218
1306
  getDocument,
1219
1307
  publish,
1308
+ publishMany,
1220
1309
  unpublish,
1310
+ unpublishMany,
1221
1311
  update
1222
1312
  };
1223
1313
  };
1224
1314
  const ProtectedHistoryPage = React.lazy(
1225
- () => Promise.resolve().then(() => require("./History-C17LiyRg.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1315
+ () => Promise.resolve().then(() => require("./History-BblwXv7-.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1226
1316
  );
1227
1317
  const routes$1 = [
1228
1318
  {
@@ -1235,31 +1325,31 @@ const routes$1 = [
1235
1325
  }
1236
1326
  ];
1237
1327
  const ProtectedEditViewPage = React.lazy(
1238
- () => Promise.resolve().then(() => require("./EditViewPage-CzOT5Kpj.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1328
+ () => Promise.resolve().then(() => require("./EditViewPage-CmMi2Xsn.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1239
1329
  );
1240
1330
  const ProtectedListViewPage = React.lazy(
1241
- () => Promise.resolve().then(() => require("./ListViewPage-BwrZrPsh.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1331
+ () => Promise.resolve().then(() => require("./ListViewPage-DFjn1DNW.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1242
1332
  );
1243
1333
  const ProtectedListConfiguration = React.lazy(
1244
- () => Promise.resolve().then(() => require("./ListConfigurationPage-Dks5SX6f.js")).then((mod) => ({
1334
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-Cpy4QqNd.js")).then((mod) => ({
1245
1335
  default: mod.ProtectedListConfiguration
1246
1336
  }))
1247
1337
  );
1248
1338
  const ProtectedEditConfigurationPage = React.lazy(
1249
- () => Promise.resolve().then(() => require("./EditConfigurationPage-BfFzJ4Br.js")).then((mod) => ({
1339
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-CEGwxV-L.js")).then((mod) => ({
1250
1340
  default: mod.ProtectedEditConfigurationPage
1251
1341
  }))
1252
1342
  );
1253
1343
  const ProtectedComponentConfigurationPage = React.lazy(
1254
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-43KmCNQE.js")).then((mod) => ({
1344
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-BWQv6yRj.js")).then((mod) => ({
1255
1345
  default: mod.ProtectedComponentConfigurationPage
1256
1346
  }))
1257
1347
  );
1258
1348
  const NoPermissions = React.lazy(
1259
- () => Promise.resolve().then(() => require("./NoPermissionsPage-C-j6TEUF.js")).then((mod) => ({ default: mod.NoPermissions }))
1349
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-DKLmDZnZ.js")).then((mod) => ({ default: mod.NoPermissions }))
1260
1350
  );
1261
1351
  const NoContentType = React.lazy(
1262
- () => Promise.resolve().then(() => require("./NoContentTypePage-Cu5r1-JT.js")).then((mod) => ({ default: mod.NoContentType }))
1352
+ () => Promise.resolve().then(() => require("./NoContentTypePage-C-3ykoxs.js")).then((mod) => ({ default: mod.NoContentType }))
1263
1353
  );
1264
1354
  const CollectionTypePages = () => {
1265
1355
  const { collectionType } = reactRouterDom.useParams();
@@ -1449,7 +1539,7 @@ const DocumentActionsMenu = ({
1449
1539
  variant,
1450
1540
  children: [
1451
1541
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
1452
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { as: "span", children: label || formatMessage({
1542
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
1453
1543
  id: "content-manager.containers.edit.panels.default.more-actions",
1454
1544
  defaultMessage: "More document actions"
1455
1545
  }) })
@@ -1465,8 +1555,8 @@ const DocumentActionsMenu = ({
1465
1555
  onSelect: handleClick(action),
1466
1556
  display: "block",
1467
1557
  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,
1558
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1559
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1470
1560
  action.label
1471
1561
  ] }),
1472
1562
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
@@ -1527,6 +1617,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1527
1617
  return "primary600";
1528
1618
  }
1529
1619
  };
1620
+ const convertActionVariantToIconColor = (variant = "secondary") => {
1621
+ switch (variant) {
1622
+ case "danger":
1623
+ return "danger600";
1624
+ case "secondary":
1625
+ return "neutral500";
1626
+ case "success":
1627
+ return "success600";
1628
+ default:
1629
+ return "primary600";
1630
+ }
1631
+ };
1530
1632
  const DocumentActionConfirmDialog = ({
1531
1633
  onClose,
1532
1634
  onCancel,
@@ -1549,61 +1651,42 @@ const DocumentActionConfirmDialog = ({
1549
1651
  }
1550
1652
  onClose();
1551
1653
  };
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
- ] });
1654
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
1655
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
1656
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
1657
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
1658
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
1659
+ id: "app.components.Button.cancel",
1660
+ defaultMessage: "Cancel"
1661
+ }) }) }),
1662
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
1663
+ id: "app.components.Button.confirm",
1664
+ defaultMessage: "Confirm"
1665
+ }) })
1666
+ ] })
1667
+ ] }) });
1568
1668
  };
1569
1669
  const DocumentActionModal = ({
1570
1670
  isOpen,
1571
1671
  title,
1572
1672
  onClose,
1573
1673
  footer: Footer,
1574
- content,
1674
+ content: Content,
1575
1675
  onModalClose
1576
1676
  }) => {
1577
- const id = React__namespace.useId();
1578
- if (!isOpen) {
1579
- return null;
1580
- }
1581
1677
  const handleClose = () => {
1582
1678
  if (onClose) {
1583
1679
  onClose();
1584
1680
  }
1585
1681
  onModalClose();
1586
1682
  };
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
- ] });
1683
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
1684
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
1685
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content }),
1686
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Footer, { children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer })
1687
+ ] }) });
1605
1688
  };
1606
- const PublishAction = ({
1689
+ const PublishAction$1 = ({
1607
1690
  activeTab,
1608
1691
  documentId,
1609
1692
  model,
@@ -1688,7 +1771,7 @@ const PublishAction = ({
1688
1771
  }
1689
1772
  };
1690
1773
  };
1691
- PublishAction.type = "publish";
1774
+ PublishAction$1.type = "publish";
1692
1775
  const UpdateAction = ({
1693
1776
  activeTab,
1694
1777
  documentId,
@@ -1784,10 +1867,13 @@ const UpdateAction = ({
1784
1867
  document
1785
1868
  );
1786
1869
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1787
- navigate({
1788
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1789
- search: rawQuery
1790
- });
1870
+ navigate(
1871
+ {
1872
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1873
+ search: rawQuery
1874
+ },
1875
+ { replace: true }
1876
+ );
1791
1877
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1792
1878
  setErrors(formatValidationErrors(res.error));
1793
1879
  }
@@ -1803,7 +1889,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
1803
1889
  KEEP: "keep",
1804
1890
  DISCARD: "discard"
1805
1891
  };
1806
- const UnpublishAction = ({
1892
+ const UnpublishAction$1 = ({
1807
1893
  activeTab,
1808
1894
  documentId,
1809
1895
  model,
@@ -1819,10 +1905,8 @@ const UnpublishAction = ({
1819
1905
  const { toggleNotification } = strapiAdmin.useNotification();
1820
1906
  const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
1821
1907
  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
- }
1908
+ const handleChange = (value) => {
1909
+ setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1826
1910
  };
1827
1911
  if (!schema?.options?.draftAndPublish) {
1828
1912
  return null;
@@ -1866,45 +1950,30 @@ const UnpublishAction = ({
1866
1950
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
1867
1951
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
1868
1952
  /* @__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({
1953
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1870
1954
  id: "content-manager.actions.unpublish.dialog.body",
1871
1955
  defaultMessage: "Are you sure?"
1872
1956
  }) })
1873
1957
  ] }),
1874
1958
  /* @__PURE__ */ jsxRuntime.jsxs(
1875
- designSystem.Flex,
1959
+ designSystem.Radio.Group,
1876
1960
  {
1877
- onChange: handleChange,
1878
- direction: "column",
1879
- alignItems: "flex-start",
1880
- as: "fieldset",
1881
- gap: 3,
1961
+ defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
1962
+ name: "discard-options",
1963
+ "aria-label": formatMessage({
1964
+ id: "content-manager.actions.unpublish.dialog.radio-label",
1965
+ defaultMessage: "Choose an option to unpublish the document."
1966
+ }),
1967
+ onValueChange: handleChange,
1882
1968
  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
- )
1969
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
1970
+ id: "content-manager.actions.unpublish.dialog.option.keep-draft",
1971
+ defaultMessage: "Keep draft"
1972
+ }) }),
1973
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
1974
+ id: "content-manager.actions.unpublish.dialog.option.replace-draft",
1975
+ defaultMessage: "Replace draft"
1976
+ }) })
1908
1977
  ]
1909
1978
  }
1910
1979
  )
@@ -1937,7 +2006,7 @@ const UnpublishAction = ({
1937
2006
  position: ["panel", "table-row"]
1938
2007
  };
1939
2008
  };
1940
- UnpublishAction.type = "unpublish";
2009
+ UnpublishAction$1.type = "unpublish";
1941
2010
  const DiscardAction = ({
1942
2011
  activeTab,
1943
2012
  documentId,
@@ -1971,7 +2040,7 @@ const DiscardAction = ({
1971
2040
  }),
1972
2041
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
1973
2042
  /* @__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({
2043
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1975
2044
  id: "content-manager.actions.discard.dialog.body",
1976
2045
  defaultMessage: "Are you sure?"
1977
2046
  }) })
@@ -1988,12 +2057,12 @@ const DiscardAction = ({
1988
2057
  };
1989
2058
  };
1990
2059
  DiscardAction.type = "discard";
1991
- const StyledCrossCircle = styled__default.default(Icons.CrossCircle)`
2060
+ const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
1992
2061
  path {
1993
2062
  fill: currentColor;
1994
2063
  }
1995
2064
  `;
1996
- const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
2065
+ const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
1997
2066
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
1998
2067
  const RelativeTime = React__namespace.forwardRef(
1999
2068
  ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
@@ -2041,7 +2110,7 @@ const getDisplayName = ({
2041
2110
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2042
2111
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2043
2112
  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) }) });
2113
+ 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
2114
  };
2046
2115
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2047
2116
  const { formatMessage } = reactIntl.useIntl();
@@ -2061,7 +2130,7 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2061
2130
  gap: "80px",
2062
2131
  alignItems: "flex-start",
2063
2132
  children: [
2064
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", children: title }),
2133
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2065
2134
  /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2066
2135
  ]
2067
2136
  }
@@ -2218,7 +2287,7 @@ const Information = ({ activeTab }) => {
2218
2287
  borderColor: "neutral150",
2219
2288
  direction: "column",
2220
2289
  marginTop: 2,
2221
- as: "dl",
2290
+ tag: "dl",
2222
2291
  padding: 5,
2223
2292
  gap: 3,
2224
2293
  alignItems: "flex-start",
@@ -2226,8 +2295,8 @@ const Information = ({ activeTab }) => {
2226
2295
  marginRight: "-0.4rem",
2227
2296
  width: "calc(100% + 8px)",
2228
2297
  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 })
2298
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2299
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2231
2300
  ] }, info.label))
2232
2301
  }
2233
2302
  );
@@ -2260,7 +2329,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2260
2329
  id: "app.links.configure-view",
2261
2330
  defaultMessage: "Configure the view"
2262
2331
  }),
2263
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCog, {}),
2332
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
2264
2333
  onClick: () => {
2265
2334
  navigate(`../${collectionType}/${model}/configurations/edit`);
2266
2335
  },
@@ -2268,11 +2337,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2268
2337
  };
2269
2338
  };
2270
2339
  ConfigureTheViewAction.type = "configure-the-view";
2271
- const StyledCog = styled__default.default(Icons.Cog)`
2272
- path {
2273
- fill: currentColor;
2274
- }
2275
- `;
2276
2340
  const EditTheModelAction = ({ model }) => {
2277
2341
  const navigate = reactRouterDom.useNavigate();
2278
2342
  const { formatMessage } = reactIntl.useIntl();
@@ -2281,7 +2345,7 @@ const EditTheModelAction = ({ model }) => {
2281
2345
  id: "content-manager.link-to-ctb",
2282
2346
  defaultMessage: "Edit the model"
2283
2347
  }),
2284
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil$1, {}),
2348
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
2285
2349
  onClick: () => {
2286
2350
  navigate(`/plugins/content-type-builder/content-types/${model}`);
2287
2351
  },
@@ -2289,12 +2353,7 @@ const EditTheModelAction = ({ model }) => {
2289
2353
  };
2290
2354
  };
2291
2355
  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 }) => {
2356
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2298
2357
  const navigate = reactRouterDom.useNavigate();
2299
2358
  const { formatMessage } = reactIntl.useIntl();
2300
2359
  const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
@@ -2308,7 +2367,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2308
2367
  id: "content-manager.actions.delete.label",
2309
2368
  defaultMessage: "Delete document"
2310
2369
  }),
2311
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledTrash, {}),
2370
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2312
2371
  dialog: {
2313
2372
  type: "dialog",
2314
2373
  title: formatMessage({
@@ -2317,7 +2376,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2317
2376
  }),
2318
2377
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
2319
2378
  /* @__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({
2379
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2321
2380
  id: "content-manager.actions.delete.dialog.body",
2322
2381
  defaultMessage: "Are you sure?"
2323
2382
  }) })
@@ -2362,13 +2421,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2362
2421
  position: ["header", "table-row"]
2363
2422
  };
2364
2423
  };
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];
2424
+ DeleteAction$1.type = "delete";
2425
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2372
2426
  const Panels = () => {
2373
2427
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2374
2428
  const [
@@ -2442,7 +2496,7 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2442
2496
  designSystem.Flex,
2443
2497
  {
2444
2498
  ref,
2445
- as: "aside",
2499
+ tag: "aside",
2446
2500
  "aria-labelledby": "additional-information",
2447
2501
  background: "neutral0",
2448
2502
  borderColor: "neutral150",
@@ -2457,669 +2511,1244 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2457
2511
  justifyContent: "stretch",
2458
2512
  alignItems: "flex-start",
2459
2513
  children: [
2460
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2514
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2461
2515
  children
2462
2516
  ]
2463
2517
  }
2464
2518
  );
2465
2519
  });
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
- ] });
2520
+ const HOOKS = {
2521
+ /**
2522
+ * Hook that allows to mutate the displayed headers of the list view table
2523
+ * @constant
2524
+ * @type {string}
2525
+ */
2526
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2527
+ /**
2528
+ * Hook that allows to mutate the CM's collection types links pre-set filters
2529
+ * @constant
2530
+ * @type {string}
2531
+ */
2532
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2533
+ /**
2534
+ * Hook that allows to mutate the CM's edit view layout
2535
+ * @constant
2536
+ * @type {string}
2537
+ */
2538
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2539
+ /**
2540
+ * Hook that allows to mutate the CM's single types links pre-set filters
2541
+ * @constant
2542
+ * @type {string}
2543
+ */
2544
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2519
2545
  };
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
2546
+ const contentTypesApi = contentManagerApi.injectEndpoints({
2547
+ endpoints: (builder) => ({
2548
+ getContentTypeConfiguration: builder.query({
2549
+ query: (uid) => ({
2550
+ url: `/content-manager/content-types/${uid}/configuration`,
2551
+ method: "GET"
2552
+ }),
2553
+ transformResponse: (response) => response.data,
2554
+ providesTags: (_result, _error, uid) => [
2555
+ { type: "ContentTypesConfiguration", id: uid },
2556
+ { type: "ContentTypeSettings", id: "LIST" }
2557
+ ]
2558
+ }),
2559
+ getAllContentTypeSettings: builder.query({
2560
+ query: () => "/content-manager/content-types-settings",
2561
+ transformResponse: (response) => response.data,
2562
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2563
+ }),
2564
+ updateContentTypeConfiguration: builder.mutation({
2565
+ query: ({ uid, ...body }) => ({
2566
+ url: `/content-manager/content-types/${uid}/configuration`,
2567
+ method: "PUT",
2568
+ data: body
2569
+ }),
2570
+ transformResponse: (response) => response.data,
2571
+ invalidatesTags: (_result, _error, { uid }) => [
2572
+ { type: "ContentTypesConfiguration", id: uid },
2573
+ { type: "ContentTypeSettings", id: "LIST" },
2574
+ // Is this necessary?
2575
+ { type: "InitialData" }
2576
+ ]
2577
+ })
2578
+ })
2579
+ });
2580
+ const {
2581
+ useGetContentTypeConfigurationQuery,
2582
+ useGetAllContentTypeSettingsQuery,
2583
+ useUpdateContentTypeConfigurationMutation
2584
+ } = contentTypesApi;
2585
+ const checkIfAttributeIsDisplayable = (attribute) => {
2586
+ const { type } = attribute;
2587
+ if (type === "relation") {
2588
+ return !attribute.relation.toLowerCase().includes("morph");
2589
+ }
2590
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2591
+ };
2592
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2593
+ if (!mainFieldName) {
2594
+ return void 0;
2595
+ }
2596
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2597
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2598
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2599
+ );
2600
+ return {
2601
+ name: mainFieldName,
2602
+ type: mainFieldType ?? "string"
2530
2603
  };
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
- }
2604
+ };
2605
+ const DEFAULT_SETTINGS = {
2606
+ bulkable: false,
2607
+ filterable: false,
2608
+ searchable: false,
2609
+ pagination: false,
2610
+ defaultSortBy: "",
2611
+ defaultSortOrder: "asc",
2612
+ mainField: "id",
2613
+ pageSize: 10
2614
+ };
2615
+ const useDocumentLayout = (model) => {
2616
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2617
+ const [{ query }] = strapiAdmin.useQueryParams();
2618
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2619
+ const { toggleNotification } = strapiAdmin.useNotification();
2620
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2621
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2622
+ const {
2623
+ data,
2624
+ isLoading: isLoadingConfigs,
2625
+ error,
2626
+ isFetching: isFetchingConfigs
2627
+ } = useGetContentTypeConfigurationQuery(model);
2628
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2629
+ React__namespace.useEffect(() => {
2630
+ if (error) {
2631
+ toggleNotification({
2632
+ type: "danger",
2633
+ message: formatAPIError(error)
2634
+ });
2553
2635
  }
2636
+ }, [error, formatAPIError, toggleNotification]);
2637
+ const editLayout = React__namespace.useMemo(
2638
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2639
+ layout: [],
2640
+ components: {},
2641
+ metadatas: {},
2642
+ options: {},
2643
+ settings: DEFAULT_SETTINGS
2644
+ },
2645
+ [data, isLoading, schemas, schema, components]
2646
+ );
2647
+ const listLayout = React__namespace.useMemo(() => {
2648
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2649
+ layout: [],
2650
+ metadatas: {},
2651
+ options: {},
2652
+ settings: DEFAULT_SETTINGS
2653
+ };
2654
+ }, [data, isLoading, schemas, schema, components]);
2655
+ const { layout: edit } = React__namespace.useMemo(
2656
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2657
+ layout: editLayout,
2658
+ query
2659
+ }),
2660
+ [editLayout, query, runHookWaterfall]
2554
2661
  );
2662
+ return {
2663
+ error,
2664
+ isLoading,
2665
+ edit,
2666
+ list: listLayout
2667
+ };
2555
2668
  };
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();
2669
+ const useDocLayout = () => {
2670
+ const { model } = useDoc();
2671
+ return useDocumentLayout(model);
2672
+ };
2673
+ const formatEditLayout = (data, {
2674
+ schemas,
2675
+ schema,
2676
+ components
2677
+ }) => {
2678
+ let currentPanelIndex = 0;
2679
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2680
+ data.contentType.layouts.edit,
2681
+ schema?.attributes,
2682
+ data.contentType.metadatas,
2683
+ { configurations: data.components, schemas: components },
2684
+ schemas
2685
+ ).reduce((panels, row) => {
2686
+ if (row.some((field) => field.type === "dynamiczone")) {
2687
+ panels.push([row]);
2688
+ currentPanelIndex += 2;
2689
+ } else {
2690
+ if (!panels[currentPanelIndex]) {
2691
+ panels.push([]);
2692
+ }
2693
+ panels[currentPanelIndex].push(row);
2694
+ }
2695
+ return panels;
2696
+ }, []);
2697
+ const componentEditAttributes = Object.entries(data.components).reduce(
2698
+ (acc, [uid, configuration]) => {
2699
+ acc[uid] = {
2700
+ layout: convertEditLayoutToFieldLayouts(
2701
+ configuration.layouts.edit,
2702
+ components[uid].attributes,
2703
+ configuration.metadatas
2704
+ ),
2705
+ settings: {
2706
+ ...configuration.settings,
2707
+ icon: components[uid].info.icon,
2708
+ displayName: components[uid].info.displayName
2709
+ }
2710
+ };
2711
+ return acc;
2712
+ },
2713
+ {}
2714
+ );
2715
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2716
+ (acc, [attribute, metadata]) => {
2717
+ return {
2718
+ ...acc,
2719
+ [attribute]: metadata.edit
2720
+ };
2721
+ },
2722
+ {}
2723
+ );
2562
2724
  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 () => {
2571
- if (!documentId) {
2572
- console.error(
2573
- "You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
2574
- );
2575
- toggleNotification({
2576
- message: formatMessage({
2577
- id: "content-manager.actions.edit.error",
2578
- defaultMessage: "An error occurred while trying to edit the document."
2579
- }),
2580
- type: "danger"
2581
- });
2582
- return;
2725
+ layout: panelledEditAttributes,
2726
+ components: componentEditAttributes,
2727
+ metadatas: editMetadatas,
2728
+ settings: {
2729
+ ...data.contentType.settings,
2730
+ displayName: schema?.info.displayName
2731
+ },
2732
+ options: {
2733
+ ...schema?.options,
2734
+ ...schema?.pluginOptions,
2735
+ ...data.contentType.options
2736
+ }
2737
+ };
2738
+ };
2739
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2740
+ return rows.map(
2741
+ (row) => row.map((field) => {
2742
+ const attribute = attributes[field.name];
2743
+ if (!attribute) {
2744
+ return null;
2583
2745
  }
2584
- navigate({
2585
- pathname: documentId,
2586
- search: qs.stringify({
2587
- plugins: query.plugins
2588
- })
2589
- });
2746
+ const { edit: metadata } = metadatas[field.name];
2747
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2748
+ return {
2749
+ attribute,
2750
+ disabled: !metadata.editable,
2751
+ hint: metadata.description,
2752
+ label: metadata.label ?? "",
2753
+ name: field.name,
2754
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
2755
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2756
+ schemas,
2757
+ components: components?.schemas ?? {}
2758
+ }),
2759
+ placeholder: metadata.placeholder ?? "",
2760
+ required: attribute.required ?? false,
2761
+ size: field.size,
2762
+ unique: "unique" in attribute ? attribute.unique : false,
2763
+ visible: metadata.visible ?? true,
2764
+ type: attribute.type
2765
+ };
2766
+ }).filter((field) => field !== null)
2767
+ );
2768
+ };
2769
+ const formatListLayout = (data, {
2770
+ schemas,
2771
+ schema,
2772
+ components
2773
+ }) => {
2774
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2775
+ (acc, [attribute, metadata]) => {
2776
+ return {
2777
+ ...acc,
2778
+ [attribute]: metadata.list
2779
+ };
2780
+ },
2781
+ {}
2782
+ );
2783
+ const listAttributes = convertListLayoutToFieldLayouts(
2784
+ data.contentType.layouts.list,
2785
+ schema?.attributes,
2786
+ listMetadatas,
2787
+ { configurations: data.components, schemas: components },
2788
+ schemas
2789
+ );
2790
+ return {
2791
+ layout: listAttributes,
2792
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2793
+ metadatas: listMetadatas,
2794
+ options: {
2795
+ ...schema?.options,
2796
+ ...schema?.pluginOptions,
2797
+ ...data.contentType.options
2590
2798
  }
2591
2799
  };
2592
2800
  };
2593
- EditAction.type = "edit";
2594
- const StyledPencil = styled__default.default(Icons.Pencil)`
2595
- path {
2596
- fill: currentColor;
2597
- }
2598
- `;
2599
- const CloneAction = ({ model, documentId }) => {
2600
- const navigate = reactRouterDom.useNavigate();
2801
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2802
+ return columns.map((name) => {
2803
+ const attribute = attributes[name];
2804
+ if (!attribute) {
2805
+ return null;
2806
+ }
2807
+ const metadata = metadatas[name];
2808
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2809
+ return {
2810
+ attribute,
2811
+ label: metadata.label ?? "",
2812
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2813
+ schemas,
2814
+ components: components?.schemas ?? {}
2815
+ }),
2816
+ name,
2817
+ searchable: metadata.searchable ?? true,
2818
+ sortable: metadata.sortable ?? true
2819
+ };
2820
+ }).filter((field) => field !== null);
2821
+ };
2822
+ const ConfirmBulkActionDialog = ({
2823
+ onToggleDialog,
2824
+ isOpen = false,
2825
+ dialogBody,
2826
+ endAction
2827
+ }) => {
2601
2828
  const { formatMessage } = reactIntl.useIntl();
2602
- const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
2829
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2830
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2831
+ id: "app.components.ConfirmDialog.title",
2832
+ defaultMessage: "Confirmation"
2833
+ }) }),
2834
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
2835
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
2836
+ dialogBody
2837
+ ] }) }),
2838
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
2839
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
2840
+ id: "app.components.Button.cancel",
2841
+ defaultMessage: "Cancel"
2842
+ }) }) }),
2843
+ endAction
2844
+ ] })
2845
+ ] }) });
2846
+ };
2847
+ const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
2848
+ const ConfirmDialogPublishAll = ({
2849
+ isOpen,
2850
+ onToggleDialog,
2851
+ isConfirmButtonLoading = false,
2852
+ onConfirm
2853
+ }) => {
2854
+ const { formatMessage } = reactIntl.useIntl();
2855
+ const selectedEntries = strapiAdmin.useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
2603
2856
  const { toggleNotification } = strapiAdmin.useNotification();
2604
- const { autoClone } = useDocumentActions();
2605
- const [prohibitedFields, setProhibitedFields] = React__namespace.useState([]);
2606
- return {
2607
- disabled: !canCreate,
2608
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledDuplicate, {}),
2609
- label: formatMessage({
2610
- id: "content-manager.actions.clone.label",
2611
- defaultMessage: "Duplicate"
2612
- }),
2613
- position: "table-row",
2614
- onClick: async () => {
2615
- if (!documentId) {
2616
- console.error(
2617
- "You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
2618
- );
2619
- toggleNotification({
2620
- message: formatMessage({
2621
- id: "content-manager.actions.clone.error",
2622
- defaultMessage: "An error occurred while trying to clone the document."
2623
- }),
2624
- type: "danger"
2625
- });
2626
- return;
2627
- }
2628
- const res = await autoClone({ model, sourceId: documentId });
2629
- if ("data" in res) {
2630
- navigate(res.data.documentId);
2631
- return true;
2632
- }
2633
- if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
2634
- const prohibitedFields2 = res.error.details.prohibitedFields;
2635
- setProhibitedFields(prohibitedFields2);
2636
- }
2857
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2858
+ const { model, schema } = useDoc();
2859
+ const [{ query }] = strapiAdmin.useQueryParams();
2860
+ const {
2861
+ data: countDraftRelations = 0,
2862
+ isLoading,
2863
+ error
2864
+ } = useGetManyDraftRelationCountQuery(
2865
+ {
2866
+ model,
2867
+ documentIds: selectedEntries.map((entry) => entry.documentId),
2868
+ locale: query?.plugins?.i18n?.locale
2637
2869
  },
2638
- dialog: {
2639
- type: "modal",
2640
- title: formatMessage({
2641
- id: "content-manager.containers.list.autoCloneModal.header",
2642
- defaultMessage: "Duplicate"
2643
- }),
2644
- content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
2645
- footer: ({ onClose }) => {
2646
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
2647
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
2648
- id: "cancel",
2649
- defaultMessage: "Cancel"
2650
- }) }),
2651
- /* @__PURE__ */ jsxRuntime.jsx(
2652
- designSystem.LinkButton,
2870
+ {
2871
+ skip: selectedEntries.length === 0
2872
+ }
2873
+ );
2874
+ React__namespace.useEffect(() => {
2875
+ if (error) {
2876
+ toggleNotification({ type: "danger", message: formatAPIError(error) });
2877
+ }
2878
+ }, [error, formatAPIError, toggleNotification]);
2879
+ if (error) {
2880
+ return null;
2881
+ }
2882
+ return /* @__PURE__ */ jsxRuntime.jsx(
2883
+ ConfirmBulkActionDialog,
2884
+ {
2885
+ isOpen: isOpen && !isLoading,
2886
+ onToggleDialog,
2887
+ dialogBody: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2888
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: [
2889
+ countDraftRelations > 0 && formatMessage(
2653
2890
  {
2654
- as: reactRouterDom.NavLink,
2655
- to: {
2656
- pathname: `clone/${documentId}`
2657
- },
2658
- children: formatMessage({
2659
- id: "content-manager.containers.list.autoCloneModal.create",
2660
- defaultMessage: "Create"
2661
- })
2891
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2892
+ 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. "
2893
+ },
2894
+ {
2895
+ b: BoldChunk$1,
2896
+ count: countDraftRelations,
2897
+ entities: selectedEntries.length
2662
2898
  }
2663
- )
2664
- ] });
2665
- }
2899
+ ),
2900
+ formatMessage({
2901
+ id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
2902
+ defaultMessage: "Are you sure you want to publish these entries?"
2903
+ })
2904
+ ] }),
2905
+ schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
2906
+ {
2907
+ id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
2908
+ defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
2909
+ },
2910
+ {
2911
+ em: Emphasis
2912
+ }
2913
+ ) })
2914
+ ] }),
2915
+ endAction: /* @__PURE__ */ jsxRuntime.jsx(
2916
+ designSystem.Button,
2917
+ {
2918
+ onClick: onConfirm,
2919
+ variant: "secondary",
2920
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
2921
+ loading: isConfirmButtonLoading,
2922
+ children: formatMessage({
2923
+ id: "app.utils.publish",
2924
+ defaultMessage: "Publish"
2925
+ })
2926
+ }
2927
+ )
2666
2928
  }
2667
- };
2929
+ );
2668
2930
  };
2669
- CloneAction.type = "clone";
2670
- const StyledDuplicate = styled__default.default(Icons.Duplicate)`
2671
- path {
2672
- fill: currentColor;
2673
- }
2931
+ const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
2932
+ max-width: 300px;
2674
2933
  `;
2675
- const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
2676
- class ContentManagerPlugin {
2677
- /**
2678
- * The following properties are the stored ones provided by any plugins registering with
2679
- * the content-manager. The function calls however, need to be called at runtime in the
2680
- * application, so instead we collate them and run them later with the complete list incl.
2681
- * ones already registered & the context of the view.
2682
- */
2683
- bulkActions = [...DEFAULT_BULK_ACTIONS];
2684
- documentActions = [
2685
- ...DEFAULT_ACTIONS,
2686
- ...DEFAULT_TABLE_ROW_ACTIONS,
2687
- ...DEFAULT_HEADER_ACTIONS,
2688
- HistoryAction
2689
- ];
2690
- editViewSidePanels = [ActionsPanel];
2691
- headerActions = [];
2692
- constructor() {
2693
- }
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);
2934
+ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2935
+ const messages = [];
2936
+ Object.entries(errors).forEach(([key, value]) => {
2937
+ const currentKey = parentKey ? `${parentKey}.${key}` : key;
2938
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
2939
+ if ("id" in value && "defaultMessage" in value) {
2940
+ messages.push(
2941
+ formatMessage(
2942
+ {
2943
+ id: `${value.id}.withField`,
2944
+ defaultMessage: value.defaultMessage
2945
+ },
2946
+ { field: currentKey }
2947
+ )
2948
+ );
2949
+ } else {
2950
+ messages.push(
2951
+ ...formatErrorMessages(
2952
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
2953
+ value,
2954
+ currentKey,
2955
+ formatMessage
2956
+ )
2957
+ );
2958
+ }
2699
2959
  } 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
- )}`
2960
+ messages.push(
2961
+ formatMessage(
2962
+ {
2963
+ id: `${value}.withField`,
2964
+ defaultMessage: value
2965
+ },
2966
+ { field: currentKey }
2967
+ )
2704
2968
  );
2705
2969
  }
2970
+ });
2971
+ return messages;
2972
+ };
2973
+ const EntryValidationText = ({ validationErrors, status }) => {
2974
+ const { formatMessage } = reactIntl.useIntl();
2975
+ if (validationErrors) {
2976
+ const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
2977
+ " "
2978
+ );
2979
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2980
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
2981
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
2982
+ ] });
2706
2983
  }
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
- }
2984
+ if (status === "published") {
2985
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2986
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
2987
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
2988
+ id: "content-manager.bulk-publish.already-published",
2989
+ defaultMessage: "Already Published"
2990
+ }) })
2991
+ ] });
2719
2992
  }
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);
2725
- } else {
2726
- throw new Error(
2727
- `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
2728
- actions2
2729
- )}`
2730
- );
2731
- }
2993
+ if (status === "modified") {
2994
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2995
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
2996
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
2997
+ id: "content-manager.bulk-publish.modified",
2998
+ defaultMessage: "Ready to publish changes"
2999
+ }) })
3000
+ ] });
2732
3001
  }
2733
- addBulkAction(actions2) {
2734
- if (Array.isArray(actions2)) {
2735
- this.bulkActions = [...this.bulkActions, ...actions2];
2736
- } else if (typeof actions2 === "function") {
2737
- this.bulkActions = actions2(this.bulkActions);
2738
- } else {
2739
- throw new Error(
2740
- `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
2741
- actions2
2742
- )}`
2743
- );
3002
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3003
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
3004
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3005
+ id: "app.utils.ready-to-publish",
3006
+ defaultMessage: "Ready to publish"
3007
+ }) })
3008
+ ] });
3009
+ };
3010
+ const TABLE_HEADERS = [
3011
+ { name: "id", label: "id" },
3012
+ { name: "name", label: "name" },
3013
+ { name: "status", label: "status" },
3014
+ { name: "publicationStatus", label: "Publication status" }
3015
+ ];
3016
+ const SelectedEntriesTableContent = ({
3017
+ isPublishing,
3018
+ rowsToDisplay = [],
3019
+ entriesToPublish = [],
3020
+ validationErrors = {}
3021
+ }) => {
3022
+ const { pathname } = reactRouterDom.useLocation();
3023
+ const { formatMessage } = reactIntl.useIntl();
3024
+ const {
3025
+ list: {
3026
+ settings: { mainField }
3027
+ }
3028
+ } = useDocLayout();
3029
+ const shouldDisplayMainField = mainField != null && mainField !== "id";
3030
+ return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
3031
+ /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
3032
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
3033
+ TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
3034
+ (head) => /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, { ...head }, head.name)
3035
+ )
3036
+ ] }),
3037
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
3038
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
3039
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
3040
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
3041
+ shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
3042
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
3043
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3044
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3045
+ id: "content-manager.success.record.publishing",
3046
+ defaultMessage: "Publishing..."
3047
+ }) }),
3048
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true })
3049
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
3050
+ EntryValidationText,
3051
+ {
3052
+ validationErrors: validationErrors[row.documentId],
3053
+ status: row.status
3054
+ }
3055
+ ) }),
3056
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3057
+ designSystem.IconButton,
3058
+ {
3059
+ tag: reactRouterDom.Link,
3060
+ to: {
3061
+ pathname: `${pathname}/${row.documentId}`,
3062
+ search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3063
+ },
3064
+ state: { from: pathname },
3065
+ label: formatMessage(
3066
+ { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3067
+ {
3068
+ target: formatMessage(
3069
+ {
3070
+ id: "content-manager.components.ListViewHelperPluginTable.row-line",
3071
+ defaultMessage: "item line {number}"
3072
+ },
3073
+ { number: index2 + 1 }
3074
+ )
3075
+ }
3076
+ ),
3077
+ target: "_blank",
3078
+ marginLeft: "auto",
3079
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3080
+ }
3081
+ ) })
3082
+ ] }, row.id)) })
3083
+ ] });
3084
+ };
3085
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
3086
+ const SelectedEntriesModalContent = ({
3087
+ listViewSelectedEntries,
3088
+ toggleModal,
3089
+ setListViewSelectedDocuments,
3090
+ model
3091
+ }) => {
3092
+ const { formatMessage } = reactIntl.useIntl();
3093
+ const { schema, components } = useContentTypeSchema(model);
3094
+ const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
3095
+ const [{ query }] = strapiAdmin.useQueryParams();
3096
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3097
+ const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
3098
+ {
3099
+ model,
3100
+ params: {
3101
+ page: "1",
3102
+ pageSize: documentIds.length.toString(),
3103
+ sort: query.sort,
3104
+ filters: {
3105
+ documentId: {
3106
+ $in: documentIds
3107
+ }
3108
+ },
3109
+ locale: query.plugins?.i18n?.locale
3110
+ }
3111
+ },
3112
+ {
3113
+ selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
3114
+ }
3115
+ );
3116
+ const { rows, validationErrors } = React__namespace.useMemo(() => {
3117
+ if (data.length > 0 && schema) {
3118
+ const validate = createYupSchema(schema.attributes, components);
3119
+ const validationErrors2 = {};
3120
+ const rows2 = data.map((entry) => {
3121
+ try {
3122
+ validate.validateSync(entry, { abortEarly: false });
3123
+ return entry;
3124
+ } catch (e) {
3125
+ if (e instanceof yup.ValidationError) {
3126
+ validationErrors2[entry.documentId] = strapiAdmin.getYupValidationErrors(e);
3127
+ }
3128
+ return entry;
3129
+ }
3130
+ });
3131
+ return { rows: rows2, validationErrors: validationErrors2 };
2744
3132
  }
2745
- }
2746
- get config() {
2747
3133
  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
- }
3134
+ rows: [],
3135
+ validationErrors: {}
2761
3136
  };
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;
3137
+ }, [components, data, schema]);
3138
+ const [publishedCount, setPublishedCount] = React__namespace.useState(0);
3139
+ const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
3140
+ const { publishMany: bulkPublishAction } = useDocumentActions();
3141
+ const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
3142
+ const selectedRows = strapiAdmin.useTable("publishAction", (state) => state.selectedRows);
3143
+ const selectedEntries = rows.filter(
3144
+ (entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
3145
+ );
3146
+ const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
3147
+ const selectedEntriesWithErrorsCount = selectedEntries.filter(
3148
+ ({ documentId }) => validationErrors[documentId]
3149
+ ).length;
3150
+ const selectedEntriesPublished = selectedEntries.filter(
3151
+ ({ status }) => status === "published"
3152
+ ).length;
3153
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3154
+ const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3155
+ const handleConfirmBulkPublish = async () => {
3156
+ toggleDialog();
3157
+ const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3158
+ if (!("error" in res)) {
3159
+ setPublishedCount(res.count);
3160
+ const unpublishedEntries = rows.filter((row) => {
3161
+ return !entriesToPublish.includes(row.documentId);
3162
+ });
3163
+ setListViewSelectedDocuments(unpublishedEntries);
2773
3164
  }
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
3165
+ };
3166
+ const getFormattedCountMessage = () => {
3167
+ if (publishedCount) {
3168
+ return formatMessage(
3169
+ {
3170
+ id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3171
+ 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."
3172
+ },
3173
+ {
3174
+ publishedCount,
3175
+ withErrorsCount: selectedEntriesWithErrorsCount,
3176
+ b: BoldChunk
3177
+ }
2799
3178
  );
2800
- state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
2801
- state.components = components;
2802
- state.models = contentTypeSchemas;
2803
- state.fieldSizes = fieldSizes;
2804
- state.isLoading = false;
2805
3179
  }
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"
3180
+ return formatMessage(
3181
+ {
3182
+ id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3183
+ 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."
3184
+ },
3185
+ {
3186
+ readyToPublishCount: selectedEntriesWithNoErrorsCount,
3187
+ withErrorsCount: selectedEntriesWithErrorsCount,
3188
+ alreadyPublishedCount: selectedEntriesPublished,
3189
+ b: BoldChunk
3190
+ }
3191
+ );
3192
+ };
3193
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3194
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
3195
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
3196
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
3197
+ SelectedEntriesTableContent,
3198
+ {
3199
+ isPublishing: isSubmittingForm,
3200
+ rowsToDisplay: rows,
3201
+ entriesToPublish,
3202
+ validationErrors
3203
+ }
3204
+ ) })
3205
+ ] }),
3206
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3207
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3208
+ id: "app.components.Button.cancel",
3209
+ defaultMessage: "Cancel"
3210
+ }) }),
3211
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3212
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3213
+ /* @__PURE__ */ jsxRuntime.jsx(
3214
+ designSystem.Button,
3215
+ {
3216
+ onClick: toggleDialog,
3217
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3218
+ loading: isSubmittingForm,
3219
+ children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3220
+ }
3221
+ )
3222
+ ] })
3223
+ ] }),
3224
+ /* @__PURE__ */ jsxRuntime.jsx(
3225
+ ConfirmDialogPublishAll,
3226
+ {
3227
+ isOpen: isDialogOpen,
3228
+ onToggleDialog: toggleDialog,
3229
+ isConfirmButtonLoading: isSubmittingForm,
3230
+ onConfirm: handleConfirmBulkPublish
3231
+ }
3232
+ )
3233
+ ] });
2838
3234
  };
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
3235
+ const PublishAction = ({ documents, model }) => {
3236
+ const { formatMessage } = reactIntl.useIntl();
3237
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3238
+ const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
3239
+ const setListViewSelectedDocuments = strapiAdmin.useTable("publishAction", (state) => state.selectRow);
3240
+ const refetchList = () => {
3241
+ contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3242
+ };
3243
+ if (!showPublishButton)
3244
+ return null;
3245
+ return {
3246
+ actionType: "publish",
3247
+ variant: "tertiary",
3248
+ label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
3249
+ dialog: {
3250
+ type: "modal",
3251
+ title: formatMessage({
3252
+ id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
3253
+ defaultMessage: "Publish entries"
2862
3254
  }),
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;
3255
+ content: ({ onClose }) => {
3256
+ return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsxRuntime.jsx(
3257
+ SelectedEntriesModalContent,
3258
+ {
3259
+ listViewSelectedEntries: documents,
3260
+ toggleModal: () => {
3261
+ onClose();
3262
+ refetchList();
3263
+ },
3264
+ setListViewSelectedDocuments,
3265
+ model
3266
+ }
3267
+ ) });
3268
+ },
3269
+ onClose: () => {
3270
+ refetchList();
3271
+ }
3272
+ }
3273
+ };
2884
3274
  };
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
- );
3275
+ const BulkActionsRenderer = () => {
3276
+ const plugins = strapiAdmin.useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
3277
+ const { model, collectionType } = useDoc();
3278
+ const { selectedRows } = strapiAdmin.useTable("BulkActionsRenderer", (state) => state);
3279
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
3280
+ strapiAdmin.DescriptionComponentRenderer,
3281
+ {
3282
+ props: {
3283
+ model,
3284
+ collectionType,
3285
+ documents: selectedRows
3286
+ },
3287
+ descriptions: plugins["content-manager"].apis.getBulkActions(),
3288
+ children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...action }, action.id))
3289
+ }
3290
+ ) });
3291
+ };
3292
+ const DeleteAction = ({ documents, model }) => {
3293
+ const { formatMessage } = reactIntl.useIntl();
3294
+ const { schema: contentType } = useDoc();
3295
+ const selectRow = strapiAdmin.useTable("DeleteAction", (state) => state.selectRow);
3296
+ const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
3297
+ const [{ query }] = strapiAdmin.useQueryParams();
3298
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3299
+ const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
3300
+ const { deleteMany: bulkDeleteAction } = useDocumentActions();
3301
+ const documentIds = documents.map(({ documentId }) => documentId);
3302
+ const handleConfirmBulkDelete = async () => {
3303
+ const res = await bulkDeleteAction({
3304
+ documentIds,
3305
+ model,
3306
+ params
3307
+ });
3308
+ if (!("error" in res)) {
3309
+ selectRow([]);
3310
+ }
3311
+ };
3312
+ if (!hasDeletePermission)
3313
+ return null;
2893
3314
  return {
2894
- name: mainFieldName,
2895
- type: mainFieldType ?? "string"
3315
+ variant: "danger-light",
3316
+ label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
3317
+ dialog: {
3318
+ type: "dialog",
3319
+ title: formatMessage({
3320
+ id: "app.components.ConfirmDialog.title",
3321
+ defaultMessage: "Confirmation"
3322
+ }),
3323
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3324
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3325
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3326
+ id: "popUpWarning.bodyMessage.contentType.delete.all",
3327
+ defaultMessage: "Are you sure you want to delete these entries?"
3328
+ }) }),
3329
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3330
+ {
3331
+ id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
3332
+ defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
3333
+ },
3334
+ {
3335
+ em: Emphasis
3336
+ }
3337
+ ) }) })
3338
+ ] }),
3339
+ onConfirm: handleConfirmBulkDelete
3340
+ }
2896
3341
  };
2897
3342
  };
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 });
3343
+ DeleteAction.type = "delete";
3344
+ const UnpublishAction = ({ documents, model }) => {
3345
+ const { formatMessage } = reactIntl.useIntl();
3346
+ const { schema } = useDoc();
3347
+ const selectRow = strapiAdmin.useTable("UnpublishAction", (state) => state.selectRow);
3348
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3349
+ const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
3350
+ const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
3351
+ const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
3352
+ const documentIds = documents.map(({ documentId }) => documentId);
2910
3353
  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
- });
3354
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3355
+ const handleConfirmBulkUnpublish = async () => {
3356
+ const data = await bulkUnpublishAction({ documentIds, model, params });
3357
+ if (!("error" in data)) {
3358
+ selectRow([]);
2928
3359
  }
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
- );
3360
+ };
3361
+ const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3362
+ if (!showUnpublishButton)
3363
+ return null;
2955
3364
  return {
2956
- error,
2957
- isLoading,
2958
- edit,
2959
- list: listLayout
3365
+ variant: "tertiary",
3366
+ label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
3367
+ dialog: {
3368
+ type: "dialog",
3369
+ title: formatMessage({
3370
+ id: "app.components.ConfirmDialog.title",
3371
+ defaultMessage: "Confirmation"
3372
+ }),
3373
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3374
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3375
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3376
+ id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3377
+ defaultMessage: "Are you sure you want to unpublish these entries?"
3378
+ }) }),
3379
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3380
+ {
3381
+ id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
3382
+ defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
3383
+ },
3384
+ {
3385
+ em: Emphasis
3386
+ }
3387
+ ) }) })
3388
+ ] }),
3389
+ confirmButton: formatMessage({
3390
+ id: "app.utils.unpublish",
3391
+ defaultMessage: "Unpublish"
3392
+ }),
3393
+ onConfirm: handleConfirmBulkUnpublish
3394
+ }
2960
3395
  };
2961
3396
  };
2962
- const useDocLayout = () => {
2963
- const { model } = useDoc();
2964
- return useDocumentLayout(model);
3397
+ UnpublishAction.type = "unpublish";
3398
+ const Emphasis = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
3399
+ const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
3400
+ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3401
+ const { formatMessage } = reactIntl.useIntl();
3402
+ const getDefaultErrorMessage = (reason) => {
3403
+ switch (reason) {
3404
+ case "relation":
3405
+ return "Duplicating the relation could remove it from the original entry.";
3406
+ case "unique":
3407
+ return "Identical values in a unique field are not allowed";
3408
+ default:
3409
+ return reason;
3410
+ }
3411
+ };
3412
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3413
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: formatMessage({
3414
+ id: getTranslation("containers.list.autoCloneModal.title"),
3415
+ defaultMessage: "This entry can't be duplicated directly."
3416
+ }) }),
3417
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatMessage({
3418
+ id: getTranslation("containers.list.autoCloneModal.description"),
3419
+ defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
3420
+ }) }) }),
3421
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxRuntime.jsxs(
3422
+ designSystem.Flex,
3423
+ {
3424
+ direction: "column",
3425
+ gap: 2,
3426
+ alignItems: "flex-start",
3427
+ borderColor: "neutral200",
3428
+ hasRadius: true,
3429
+ padding: 6,
3430
+ children: [
3431
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", tag: "li", children: [
3432
+ pathSegment,
3433
+ index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
3434
+ Icons.ChevronRight,
3435
+ {
3436
+ fill: "neutral500",
3437
+ height: "0.8rem",
3438
+ width: "0.8rem",
3439
+ style: { margin: "0 0.8rem" }
3440
+ }
3441
+ )
3442
+ ] }, index2)) }),
3443
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
3444
+ id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
3445
+ defaultMessage: getDefaultErrorMessage(reason)
3446
+ }) })
3447
+ ]
3448
+ },
3449
+ fieldPath.join()
3450
+ )) })
3451
+ ] });
2965
3452
  };
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;
2982
- } else {
2983
- if (!panels[currentPanelIndex]) {
2984
- panels.push([]);
3453
+ const TableActions = ({ document }) => {
3454
+ const { formatMessage } = reactIntl.useIntl();
3455
+ const { model, collectionType } = useDoc();
3456
+ const plugins = strapiAdmin.useStrapiApp("TableActions", (state) => state.plugins);
3457
+ const props = {
3458
+ activeTab: null,
3459
+ model,
3460
+ documentId: document.documentId,
3461
+ collectionType,
3462
+ document
3463
+ };
3464
+ return /* @__PURE__ */ jsxRuntime.jsx(
3465
+ strapiAdmin.DescriptionComponentRenderer,
3466
+ {
3467
+ props,
3468
+ descriptions: plugins["content-manager"].apis.getDocumentActions(),
3469
+ children: (actions2) => {
3470
+ const tableRowActions = actions2.filter((action) => {
3471
+ const positions = Array.isArray(action.position) ? action.position : [action.position];
3472
+ return positions.includes("table-row");
3473
+ });
3474
+ return /* @__PURE__ */ jsxRuntime.jsx(
3475
+ DocumentActionsMenu,
3476
+ {
3477
+ actions: tableRowActions,
3478
+ label: formatMessage({
3479
+ id: "content-manager.containers.list.table.row-actions",
3480
+ defaultMessage: "Row action"
3481
+ }),
3482
+ variant: "ghost"
3483
+ }
3484
+ );
2985
3485
  }
2986
- panels[currentPanelIndex].push(row);
2987
3486
  }
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
3487
  );
3488
+ };
3489
+ const EditAction = ({ documentId }) => {
3490
+ const navigate = reactRouterDom.useNavigate();
3491
+ const { formatMessage } = reactIntl.useIntl();
3492
+ const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
3493
+ const { toggleNotification } = strapiAdmin.useNotification();
3494
+ const [{ query }] = strapiAdmin.useQueryParams();
3017
3495
  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
3496
+ disabled: !canRead,
3497
+ icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil, {}),
3498
+ label: formatMessage({
3499
+ id: "content-manager.actions.edit.label",
3500
+ defaultMessage: "Edit"
3501
+ }),
3502
+ position: "table-row",
3503
+ onClick: async () => {
3504
+ if (!documentId) {
3505
+ console.error(
3506
+ "You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
3507
+ );
3508
+ toggleNotification({
3509
+ message: formatMessage({
3510
+ id: "content-manager.actions.edit.error",
3511
+ defaultMessage: "An error occurred while trying to edit the document."
3512
+ }),
3513
+ type: "danger"
3514
+ });
3515
+ return;
3516
+ }
3517
+ navigate({
3518
+ pathname: documentId,
3519
+ search: qs.stringify({
3520
+ plugins: query.plugins
3521
+ })
3522
+ });
3029
3523
  }
3030
3524
  };
3031
3525
  };
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;
3526
+ EditAction.type = "edit";
3527
+ const StyledPencil = styledComponents.styled(Icons.Pencil)`
3528
+ path {
3529
+ fill: currentColor;
3530
+ }
3531
+ `;
3532
+ const CloneAction = ({ model, documentId }) => {
3533
+ const navigate = reactRouterDom.useNavigate();
3534
+ const { formatMessage } = reactIntl.useIntl();
3535
+ const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
3536
+ const { toggleNotification } = strapiAdmin.useNotification();
3537
+ const { autoClone } = useDocumentActions();
3538
+ const [prohibitedFields, setProhibitedFields] = React__namespace.useState([]);
3539
+ return {
3540
+ disabled: !canCreate,
3541
+ icon: /* @__PURE__ */ jsxRuntime.jsx(StyledDuplicate, {}),
3542
+ label: formatMessage({
3543
+ id: "content-manager.actions.clone.label",
3544
+ defaultMessage: "Duplicate"
3545
+ }),
3546
+ position: "table-row",
3547
+ onClick: async () => {
3548
+ if (!documentId) {
3549
+ console.error(
3550
+ "You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
3551
+ );
3552
+ toggleNotification({
3553
+ message: formatMessage({
3554
+ id: "content-manager.actions.clone.error",
3555
+ defaultMessage: "An error occurred while trying to clone the document."
3556
+ }),
3557
+ type: "danger"
3558
+ });
3559
+ return;
3560
+ }
3561
+ const res = await autoClone({ model, sourceId: documentId });
3562
+ if ("data" in res) {
3563
+ navigate(res.data.documentId);
3564
+ return true;
3565
+ }
3566
+ if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
3567
+ const prohibitedFields2 = res.error.details.prohibitedFields;
3568
+ setProhibitedFields(prohibitedFields2);
3038
3569
  }
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
- );
3061
- };
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
3570
  },
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
- );
3083
- 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
3571
+ dialog: {
3572
+ type: "modal",
3573
+ title: formatMessage({
3574
+ id: "content-manager.containers.list.autoCloneModal.header",
3575
+ defaultMessage: "Duplicate"
3576
+ }),
3577
+ content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3578
+ footer: ({ onClose }) => {
3579
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3580
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3581
+ id: "cancel",
3582
+ defaultMessage: "Cancel"
3583
+ }) }),
3584
+ /* @__PURE__ */ jsxRuntime.jsx(
3585
+ designSystem.LinkButton,
3586
+ {
3587
+ tag: reactRouterDom.NavLink,
3588
+ to: {
3589
+ pathname: `clone/${documentId}`
3590
+ },
3591
+ children: formatMessage({
3592
+ id: "content-manager.containers.list.autoCloneModal.create",
3593
+ defaultMessage: "Create"
3594
+ })
3595
+ }
3596
+ )
3597
+ ] });
3598
+ }
3091
3599
  }
3092
3600
  };
3093
3601
  };
3094
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
3095
- return columns.map((name) => {
3096
- const attribute = attributes[name];
3097
- if (!attribute) {
3098
- return null;
3602
+ CloneAction.type = "clone";
3603
+ const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
3604
+ path {
3605
+ fill: currentColor;
3606
+ }
3607
+ `;
3608
+ const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
3609
+ class ContentManagerPlugin {
3610
+ /**
3611
+ * The following properties are the stored ones provided by any plugins registering with
3612
+ * the content-manager. The function calls however, need to be called at runtime in the
3613
+ * application, so instead we collate them and run them later with the complete list incl.
3614
+ * ones already registered & the context of the view.
3615
+ */
3616
+ bulkActions = [...DEFAULT_BULK_ACTIONS];
3617
+ documentActions = [
3618
+ ...DEFAULT_ACTIONS,
3619
+ ...DEFAULT_TABLE_ROW_ACTIONS,
3620
+ ...DEFAULT_HEADER_ACTIONS,
3621
+ HistoryAction
3622
+ ];
3623
+ editViewSidePanels = [ActionsPanel];
3624
+ headerActions = [];
3625
+ constructor() {
3626
+ }
3627
+ addEditViewSidePanel(panels) {
3628
+ if (Array.isArray(panels)) {
3629
+ this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
3630
+ } else if (typeof panels === "function") {
3631
+ this.editViewSidePanels = panels(this.editViewSidePanels);
3632
+ } else {
3633
+ throw new Error(
3634
+ `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
3635
+ panels
3636
+ )}`
3637
+ );
3099
3638
  }
3100
- const metadata = metadatas[name];
3101
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3639
+ }
3640
+ addDocumentAction(actions2) {
3641
+ if (Array.isArray(actions2)) {
3642
+ this.documentActions = [...this.documentActions, ...actions2];
3643
+ } else if (typeof actions2 === "function") {
3644
+ this.documentActions = actions2(this.documentActions);
3645
+ } else {
3646
+ throw new Error(
3647
+ `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
3648
+ actions2
3649
+ )}`
3650
+ );
3651
+ }
3652
+ }
3653
+ addDocumentHeaderAction(actions2) {
3654
+ if (Array.isArray(actions2)) {
3655
+ this.headerActions = [...this.headerActions, ...actions2];
3656
+ } else if (typeof actions2 === "function") {
3657
+ this.headerActions = actions2(this.headerActions);
3658
+ } else {
3659
+ throw new Error(
3660
+ `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
3661
+ actions2
3662
+ )}`
3663
+ );
3664
+ }
3665
+ }
3666
+ addBulkAction(actions2) {
3667
+ if (Array.isArray(actions2)) {
3668
+ this.bulkActions = [...this.bulkActions, ...actions2];
3669
+ } else if (typeof actions2 === "function") {
3670
+ this.bulkActions = actions2(this.bulkActions);
3671
+ } else {
3672
+ throw new Error(
3673
+ `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3674
+ actions2
3675
+ )}`
3676
+ );
3677
+ }
3678
+ }
3679
+ get config() {
3102
3680
  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
3681
+ id: PLUGIN_ID,
3682
+ name: "Content Manager",
3683
+ injectionZones: INJECTION_ZONES,
3684
+ apis: {
3685
+ addBulkAction: this.addBulkAction.bind(this),
3686
+ addDocumentAction: this.addDocumentAction.bind(this),
3687
+ addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3688
+ addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3689
+ getBulkActions: () => this.bulkActions,
3690
+ getDocumentActions: () => this.documentActions,
3691
+ getEditViewSidePanels: () => this.editViewSidePanels,
3692
+ getHeaderActions: () => this.headerActions
3693
+ }
3112
3694
  };
3113
- }).filter((field) => field !== null);
3695
+ }
3696
+ }
3697
+ const getPrintableType = (value) => {
3698
+ const nativeType = typeof value;
3699
+ if (nativeType === "object") {
3700
+ if (value === null)
3701
+ return "null";
3702
+ if (Array.isArray(value))
3703
+ return "array";
3704
+ if (value instanceof Object && value.constructor.name !== "Object") {
3705
+ return value.constructor.name;
3706
+ }
3707
+ }
3708
+ return nativeType;
3709
+ };
3710
+ const initialState = {
3711
+ collectionTypeLinks: [],
3712
+ components: [],
3713
+ fieldSizes: {},
3714
+ models: [],
3715
+ singleTypeLinks: [],
3716
+ isLoading: true
3114
3717
  };
3718
+ const appSlice = toolkit.createSlice({
3719
+ name: "app",
3720
+ initialState,
3721
+ reducers: {
3722
+ setInitialData(state, action) {
3723
+ const {
3724
+ authorizedCollectionTypeLinks,
3725
+ authorizedSingleTypeLinks,
3726
+ components,
3727
+ contentTypeSchemas,
3728
+ fieldSizes
3729
+ } = action.payload;
3730
+ state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
3731
+ ({ isDisplayed }) => isDisplayed
3732
+ );
3733
+ state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
3734
+ state.components = components;
3735
+ state.models = contentTypeSchemas;
3736
+ state.fieldSizes = fieldSizes;
3737
+ state.isLoading = false;
3738
+ }
3739
+ }
3740
+ });
3741
+ const { actions, reducer: reducer$1 } = appSlice;
3742
+ const { setInitialData } = actions;
3743
+ const reducer = toolkit.combineReducers({
3744
+ app: reducer$1
3745
+ });
3115
3746
  const index = {
3116
3747
  register(app) {
3117
3748
  const cm = new ContentManagerPlugin();
3118
3749
  app.addReducers({
3119
- [contentManagerApi.reducerPath]: contentManagerApi.reducer,
3120
3750
  [PLUGIN_ID]: reducer
3121
3751
  });
3122
- app.addMiddlewares([() => contentManagerApi.middleware]);
3123
3752
  app.addMenuLink({
3124
3753
  to: PLUGIN_ID,
3125
3754
  icon: Icons.Feather,
@@ -3128,14 +3757,24 @@ const index = {
3128
3757
  defaultMessage: "Content Manager"
3129
3758
  },
3130
3759
  permissions: [],
3131
- Component: () => Promise.resolve().then(() => require("./layout-dBc7wN7L.js")).then((mod) => ({ default: mod.Layout }))
3760
+ position: 1
3761
+ });
3762
+ app.router.addRoute({
3763
+ path: "content-manager/*",
3764
+ lazy: async () => {
3765
+ const { Layout } = await Promise.resolve().then(() => require("./layout-DRuJUpas.js"));
3766
+ return {
3767
+ Component: Layout
3768
+ };
3769
+ },
3770
+ children: routes
3132
3771
  });
3133
3772
  app.registerPlugin(cm.config);
3134
3773
  },
3135
3774
  async registerTrads({ locales }) {
3136
3775
  const importedTrads = await Promise.all(
3137
3776
  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 }) => {
3777
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-fbKQxLGn.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
3139
3778
  return {
3140
3779
  data: prefixPluginTranslations(data, PLUGIN_ID),
3141
3780
  locale
@@ -3152,6 +3791,7 @@ const index = {
3152
3791
  }
3153
3792
  };
3154
3793
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3794
+ exports.BulkActionsRenderer = BulkActionsRenderer;
3155
3795
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3156
3796
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3157
3797
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3178,7 +3818,6 @@ exports.getDisplayName = getDisplayName;
3178
3818
  exports.getMainField = getMainField;
3179
3819
  exports.getTranslation = getTranslation;
3180
3820
  exports.index = index;
3181
- exports.routes = routes;
3182
3821
  exports.setInitialData = setInitialData;
3183
3822
  exports.useContentTypeSchema = useContentTypeSchema;
3184
3823
  exports.useDoc = useDoc;
@@ -3192,4 +3831,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3192
3831
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3193
3832
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3194
3833
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3195
- //# sourceMappingURL=index-X_2tafck.js.map
3834
+ //# sourceMappingURL=index-Buwn78Rt.js.map