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

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 (165) hide show
  1. package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
  2. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
  3. package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
  4. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
  5. package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs → ComponentConfigurationPage-CYqQv0ne.mjs} +3 -3
  6. package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs.map → ComponentConfigurationPage-CYqQv0ne.mjs.map} +1 -1
  7. package/dist/_chunks/{ComponentConfigurationPage-2iOVVhqV.js → ComponentConfigurationPage-DiigqkCf.js} +3 -3
  8. package/dist/_chunks/{ComponentConfigurationPage-2iOVVhqV.js.map → ComponentConfigurationPage-DiigqkCf.js.map} +1 -1
  9. package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-BXdiCGQp.js} +8 -2
  10. package/dist/_chunks/ComponentIcon-BXdiCGQp.js.map +1 -0
  11. package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
  12. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
  13. package/dist/_chunks/{EditConfigurationPage-BoBb-DLH.mjs → EditConfigurationPage-BArY-b8_.mjs} +3 -3
  14. package/dist/_chunks/{EditConfigurationPage-BoBb-DLH.mjs.map → EditConfigurationPage-BArY-b8_.mjs.map} +1 -1
  15. package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js → EditConfigurationPage-BeeGw2RI.js} +3 -3
  16. package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js.map → EditConfigurationPage-BeeGw2RI.js.map} +1 -1
  17. package/dist/_chunks/{EditViewPage-aUnqL-63.mjs → EditViewPage-B8ETGsFo.mjs} +6 -6
  18. package/dist/_chunks/EditViewPage-B8ETGsFo.mjs.map +1 -0
  19. package/dist/_chunks/{EditViewPage-KRG56aCq.js → EditViewPage-DZPDqo_G.js} +7 -9
  20. package/dist/_chunks/EditViewPage-DZPDqo_G.js.map +1 -0
  21. package/dist/_chunks/{Field-kVFO4ZKB.mjs → Field-Dn4ThnFB.mjs} +500 -608
  22. package/dist/_chunks/Field-Dn4ThnFB.mjs.map +1 -0
  23. package/dist/_chunks/{Field-kq1c2TF1.js → Field-DnJMS8cB.js} +552 -661
  24. package/dist/_chunks/Field-DnJMS8cB.js.map +1 -0
  25. package/dist/_chunks/{Form-Jgh5hGTu.mjs → Form-DY721B6y.mjs} +16 -13
  26. package/dist/_chunks/Form-DY721B6y.mjs.map +1 -0
  27. package/dist/_chunks/{Form-CQ67ZifP.js → Form-DiTmWq2k.js} +18 -16
  28. package/dist/_chunks/Form-DiTmWq2k.js.map +1 -0
  29. package/dist/_chunks/{History-DKhZAPcK.mjs → History-CwWN_uNp.mjs} +28 -34
  30. package/dist/_chunks/History-CwWN_uNp.mjs.map +1 -0
  31. package/dist/_chunks/{History-BLEnudTX.js → History-DShoVAh0.js} +29 -36
  32. package/dist/_chunks/History-DShoVAh0.js.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-Zso_LUjn.js → ListConfigurationPage-COIRGF5b.js} +14 -16
  34. package/dist/_chunks/ListConfigurationPage-COIRGF5b.js.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-nrXcxNYi.mjs → ListConfigurationPage-D062TiTL.mjs} +9 -9
  36. package/dist/_chunks/ListConfigurationPage-D062TiTL.mjs.map +1 -0
  37. package/dist/_chunks/{ListViewPage-ChhYmA-L.mjs → ListViewPage-BeHTsIr5.mjs} +21 -41
  38. package/dist/_chunks/ListViewPage-BeHTsIr5.mjs.map +1 -0
  39. package/dist/_chunks/{ListViewPage-DsaOakWQ.js → ListViewPage-CFuXPZ_r.js} +28 -48
  40. package/dist/_chunks/ListViewPage-CFuXPZ_r.js.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-BrdFcN33.mjs → NoContentTypePage-B_KLijrG.mjs} +3 -3
  42. package/dist/_chunks/NoContentTypePage-B_KLijrG.mjs.map +1 -0
  43. package/dist/_chunks/{NoContentTypePage-DPCuS9Y1.js → NoContentTypePage-rdH0Zp0A.js} +3 -3
  44. package/dist/_chunks/NoContentTypePage-rdH0Zp0A.js.map +1 -0
  45. package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs → NoPermissionsPage-BPU-v48V.mjs} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs.map → NoPermissionsPage-BPU-v48V.mjs.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js → NoPermissionsPage-D8gbX1Y_.js} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js.map → NoPermissionsPage-D8gbX1Y_.js.map} +1 -1
  49. package/dist/_chunks/{Relations-DjFiYd7-.mjs → Relations-Bbz90ZWv.mjs} +66 -56
  50. package/dist/_chunks/Relations-Bbz90ZWv.mjs.map +1 -0
  51. package/dist/_chunks/{Relations-CY8Isqdu.js → Relations-wHyjWWT5.js} +70 -61
  52. package/dist/_chunks/Relations-wHyjWWT5.js.map +1 -0
  53. package/dist/_chunks/{en-C-V1_90f.js → en-BN1bvFK7.js} +4 -1
  54. package/dist/_chunks/{en-C-V1_90f.js.map → en-BN1bvFK7.js.map} +1 -1
  55. package/dist/_chunks/{en-MBPul9Su.mjs → en-Dzv55oQw.mjs} +4 -1
  56. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-Dzv55oQw.mjs.map} +1 -1
  57. package/dist/_chunks/{index-DNa1J4HE.js → index-BRHpg0az.js} +1535 -789
  58. package/dist/_chunks/index-BRHpg0az.js.map +1 -0
  59. package/dist/_chunks/{index-CAc9yTnx.mjs → index-Dv4oDn11.mjs} +1538 -791
  60. package/dist/_chunks/index-Dv4oDn11.mjs.map +1 -0
  61. package/dist/_chunks/{layout-CXsHbc3E.mjs → layout-hInnLBbA.mjs} +10 -10
  62. package/dist/_chunks/layout-hInnLBbA.mjs.map +1 -0
  63. package/dist/_chunks/{layout-BqtLA6Lb.js → layout-pZc2Q3bK.js} +12 -14
  64. package/dist/_chunks/layout-pZc2Q3bK.js.map +1 -0
  65. package/dist/_chunks/{relations-mMFEcZRq.mjs → relations-BcPI8XhI.mjs} +2 -2
  66. package/dist/_chunks/{relations-mMFEcZRq.mjs.map → relations-BcPI8XhI.mjs.map} +1 -1
  67. package/dist/_chunks/{relations-BHY_KDJ_.js → relations-CVE30dYt.js} +2 -2
  68. package/dist/_chunks/{relations-BHY_KDJ_.js.map → relations-CVE30dYt.js.map} +1 -1
  69. package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
  70. package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
  71. package/dist/_chunks/usePrev-B9w_-eYc.js +15 -0
  72. package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -0
  73. package/dist/_chunks/usePrev-DH6iah0A.mjs +16 -0
  74. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +1 -0
  75. package/dist/admin/index.js +2 -1
  76. package/dist/admin/index.js.map +1 -1
  77. package/dist/admin/index.mjs +5 -4
  78. package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
  79. package/dist/admin/src/content-manager.d.ts +3 -3
  80. package/dist/admin/src/exports.d.ts +1 -0
  81. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  82. package/dist/admin/src/hooks/useDocument.d.ts +5 -8
  83. package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
  84. package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
  85. package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
  86. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
  87. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +3 -1
  88. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
  89. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
  90. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  91. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  92. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +10 -18
  93. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  94. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  95. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  96. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +67 -52
  97. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  98. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  99. package/dist/admin/src/services/api.d.ts +2 -3
  100. package/dist/admin/src/services/components.d.ts +2 -2
  101. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  102. package/dist/admin/src/services/documents.d.ts +29 -17
  103. package/dist/admin/src/services/init.d.ts +2 -2
  104. package/dist/admin/src/services/relations.d.ts +3 -3
  105. package/dist/admin/src/services/uid.d.ts +3 -3
  106. package/dist/admin/src/utils/api.d.ts +4 -18
  107. package/dist/admin/src/utils/validation.d.ts +1 -6
  108. package/dist/server/index.js +267 -186
  109. package/dist/server/index.js.map +1 -1
  110. package/dist/server/index.mjs +269 -188
  111. package/dist/server/index.mjs.map +1 -1
  112. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  113. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  114. package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
  115. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  116. package/dist/server/src/controllers/validation/dimensions.d.ts +9 -0
  117. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  118. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  119. package/dist/server/src/history/services/history.d.ts.map +1 -1
  120. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  121. package/dist/server/src/index.d.ts +17 -33
  122. package/dist/server/src/index.d.ts.map +1 -1
  123. package/dist/server/src/services/document-manager.d.ts +11 -6
  124. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  125. package/dist/server/src/services/document-metadata.d.ts +8 -29
  126. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  127. package/dist/server/src/services/index.d.ts +17 -33
  128. package/dist/server/src/services/index.d.ts.map +1 -1
  129. package/dist/server/src/services/utils/populate.d.ts +8 -1
  130. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  131. package/dist/shared/contracts/collection-types.d.ts +14 -6
  132. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  133. package/dist/shared/contracts/relations.d.ts +2 -2
  134. package/dist/shared/contracts/relations.d.ts.map +1 -1
  135. package/package.json +13 -14
  136. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  137. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  138. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  139. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  140. package/dist/_chunks/EditViewPage-KRG56aCq.js.map +0 -1
  141. package/dist/_chunks/EditViewPage-aUnqL-63.mjs.map +0 -1
  142. package/dist/_chunks/Field-kVFO4ZKB.mjs.map +0 -1
  143. package/dist/_chunks/Field-kq1c2TF1.js.map +0 -1
  144. package/dist/_chunks/Form-CQ67ZifP.js.map +0 -1
  145. package/dist/_chunks/Form-Jgh5hGTu.mjs.map +0 -1
  146. package/dist/_chunks/History-BLEnudTX.js.map +0 -1
  147. package/dist/_chunks/History-DKhZAPcK.mjs.map +0 -1
  148. package/dist/_chunks/ListConfigurationPage-Zso_LUjn.js.map +0 -1
  149. package/dist/_chunks/ListConfigurationPage-nrXcxNYi.mjs.map +0 -1
  150. package/dist/_chunks/ListViewPage-ChhYmA-L.mjs.map +0 -1
  151. package/dist/_chunks/ListViewPage-DsaOakWQ.js.map +0 -1
  152. package/dist/_chunks/NoContentTypePage-BrdFcN33.mjs.map +0 -1
  153. package/dist/_chunks/NoContentTypePage-DPCuS9Y1.js.map +0 -1
  154. package/dist/_chunks/Relations-CY8Isqdu.js.map +0 -1
  155. package/dist/_chunks/Relations-DjFiYd7-.mjs.map +0 -1
  156. package/dist/_chunks/index-CAc9yTnx.mjs.map +0 -1
  157. package/dist/_chunks/index-DNa1J4HE.js.map +0 -1
  158. package/dist/_chunks/layout-BqtLA6Lb.js.map +0 -1
  159. package/dist/_chunks/layout-CXsHbc3E.mjs.map +0 -1
  160. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  161. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  162. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  163. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  164. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  165. 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,8 +216,7 @@ 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({
297
222
  endpoints: (builder) => ({
@@ -347,12 +272,15 @@ const documentApi = contentManagerApi.injectEndpoints({
347
272
  ]
348
273
  }),
349
274
  deleteManyDocuments: builder.mutation({
350
- query: ({ model, ...body }) => ({
275
+ query: ({ model, params, ...body }) => ({
351
276
  url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
352
277
  method: "POST",
353
- data: body
278
+ data: body,
279
+ config: {
280
+ params
281
+ }
354
282
  }),
355
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
283
+ invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
356
284
  }),
357
285
  discardDocument: builder.mutation({
358
286
  query: ({ collectionType, model, documentId, params }) => ({
@@ -463,10 +391,13 @@ const documentApi = contentManagerApi.injectEndpoints({
463
391
  }
464
392
  }),
465
393
  publishManyDocuments: builder.mutation({
466
- query: ({ model, ...body }) => ({
394
+ query: ({ model, params, ...body }) => ({
467
395
  url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
468
396
  method: "POST",
469
- data: body
397
+ data: body,
398
+ config: {
399
+ params
400
+ }
470
401
  }),
471
402
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
472
403
  }),
@@ -508,10 +439,13 @@ const documentApi = contentManagerApi.injectEndpoints({
508
439
  }
509
440
  }),
510
441
  unpublishManyDocuments: builder.mutation({
511
- query: ({ model, ...body }) => ({
442
+ query: ({ model, params, ...body }) => ({
512
443
  url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
513
444
  method: "POST",
514
- data: body
445
+ data: body,
446
+ config: {
447
+ params
448
+ }
515
449
  }),
516
450
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
517
451
  })
@@ -535,6 +469,24 @@ const {
535
469
  useUnpublishDocumentMutation,
536
470
  useUnpublishManyDocumentsMutation
537
471
  } = documentApi;
472
+ const buildValidParams = (query) => {
473
+ if (!query)
474
+ return query;
475
+ const { plugins: _, ...validQueryParams } = {
476
+ ...query,
477
+ ...Object.values(query?.plugins ?? {}).reduce(
478
+ (acc, current) => Object.assign(acc, current),
479
+ {}
480
+ )
481
+ };
482
+ if ("_q" in validQueryParams) {
483
+ validQueryParams._q = encodeURIComponent(validQueryParams._q);
484
+ }
485
+ return validQueryParams;
486
+ };
487
+ const isBaseQueryError = (error) => {
488
+ return error.name !== void 0;
489
+ };
538
490
  const createYupSchema = (attributes = {}, components = {}) => {
539
491
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
540
492
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
@@ -574,10 +526,14 @@ const createYupSchema = (attributes = {}, components = {}) => {
574
526
  yup__namespace.array().of(
575
527
  yup__namespace.lazy(
576
528
  (data) => {
577
- const { attributes: attributes3 } = components[data.__component];
578
- return yup__namespace.object().shape({
529
+ const attributes3 = components?.[data?.__component]?.attributes;
530
+ const validation = yup__namespace.object().shape({
579
531
  __component: yup__namespace.string().required().oneOf(Object.keys(components))
580
- }).nullable(false).concat(createModelSchema(attributes3));
532
+ }).nullable(false);
533
+ if (!attributes3) {
534
+ return validation;
535
+ }
536
+ return validation.concat(createModelSchema(attributes3));
581
537
  }
582
538
  )
583
539
  )
@@ -587,11 +543,25 @@ const createYupSchema = (attributes = {}, components = {}) => {
587
543
  return {
588
544
  ...acc,
589
545
  [name]: transformSchema(
590
- yup__namespace.array().of(
591
- yup__namespace.object().shape({
592
- id: yup__namespace.string().required()
593
- })
594
- )
546
+ yup__namespace.lazy((value) => {
547
+ if (!value) {
548
+ return yup__namespace.mixed().nullable(true);
549
+ } else if (Array.isArray(value)) {
550
+ return yup__namespace.array().of(
551
+ yup__namespace.object().shape({
552
+ id: yup__namespace.string().required()
553
+ })
554
+ );
555
+ } else if (typeof value === "object") {
556
+ return yup__namespace.object();
557
+ } else {
558
+ return yup__namespace.mixed().test(
559
+ "type-error",
560
+ "Relation values must be either null, an array of objects with {id} or an object.",
561
+ () => false
562
+ );
563
+ }
564
+ })
595
565
  )
596
566
  };
597
567
  default:
@@ -656,7 +626,12 @@ const addRequiredValidation = (attribute) => (schema) => {
656
626
  defaultMessage: "This field is required."
657
627
  });
658
628
  }
659
- return schema.nullable();
629
+ return schema?.nullable ? schema.nullable() : (
630
+ // In some cases '.nullable' will not be available on the schema.
631
+ // e.g. when the schema has been built using yup.lazy (e.g. for relations).
632
+ // In these cases we should just return the schema as it is.
633
+ schema
634
+ );
660
635
  };
661
636
  const addMinLengthValidation = (attribute) => (schema) => {
662
637
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
@@ -728,24 +703,6 @@ const addRegexValidation = (attribute) => (schema) => {
728
703
  }
729
704
  return schema;
730
705
  };
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
706
  const initApi = contentManagerApi.injectEndpoints({
750
707
  endpoints: (builder) => ({
751
708
  getInitialData: builder.query({
@@ -759,27 +716,20 @@ const { useGetInitialDataQuery } = initApi;
759
716
  const useContentTypeSchema = (model) => {
760
717
  const { toggleNotification } = strapiAdmin.useNotification();
761
718
  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
- });
719
+ const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
720
+ const { components, contentType, contentTypes } = React__namespace.useMemo(() => {
721
+ const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
722
+ const componentsByKey = data?.components.reduce((acc, component) => {
723
+ acc[component.uid] = component;
724
+ return acc;
725
+ }, {});
726
+ const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
727
+ return {
728
+ components: Object.keys(components2).length === 0 ? void 0 : components2,
729
+ contentType: contentType2,
730
+ contentTypes: data?.contentTypes ?? []
731
+ };
732
+ }, [model, data]);
783
733
  React__namespace.useEffect(() => {
784
734
  if (error) {
785
735
  toggleNotification({
@@ -862,7 +812,7 @@ const useDocument = (args, opts) => {
862
812
  return null;
863
813
  } catch (error2) {
864
814
  if (error2 instanceof yup.ValidationError) {
865
- return getInnerErrors(error2);
815
+ return strapiAdmin.getYupValidationErrors(error2);
866
816
  }
867
817
  throw error2;
868
818
  }
@@ -958,6 +908,44 @@ const useDocumentActions = () => {
958
908
  },
959
909
  [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
960
910
  );
911
+ const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
912
+ const deleteMany = React__namespace.useCallback(
913
+ async ({ model, documentIds, params }) => {
914
+ try {
915
+ trackUsage("willBulkDeleteEntries");
916
+ const res = await deleteManyDocuments({
917
+ model,
918
+ documentIds,
919
+ params
920
+ });
921
+ if ("error" in res) {
922
+ toggleNotification({
923
+ type: "danger",
924
+ message: formatAPIError(res.error)
925
+ });
926
+ return { error: res.error };
927
+ }
928
+ toggleNotification({
929
+ type: "success",
930
+ title: formatMessage({
931
+ id: getTranslation("success.records.delete"),
932
+ defaultMessage: "Successfully deleted."
933
+ }),
934
+ message: ""
935
+ });
936
+ trackUsage("didBulkDeleteEntries");
937
+ return res.data;
938
+ } catch (err) {
939
+ toggleNotification({
940
+ type: "danger",
941
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
942
+ });
943
+ trackUsage("didNotBulkDeleteEntries");
944
+ throw err;
945
+ }
946
+ },
947
+ [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
948
+ );
961
949
  const [discardDocument] = useDiscardDocumentMutation();
962
950
  const discard = React__namespace.useCallback(
963
951
  async ({ collectionType, model, documentId }) => {
@@ -1027,6 +1015,43 @@ const useDocumentActions = () => {
1027
1015
  },
1028
1016
  [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1029
1017
  );
1018
+ const [publishManyDocuments] = usePublishManyDocumentsMutation();
1019
+ const publishMany = React__namespace.useCallback(
1020
+ async ({ model, documentIds, params }) => {
1021
+ try {
1022
+ const res = await publishManyDocuments({
1023
+ model,
1024
+ documentIds,
1025
+ params
1026
+ });
1027
+ if ("error" in res) {
1028
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1029
+ return { error: res.error };
1030
+ }
1031
+ toggleNotification({
1032
+ type: "success",
1033
+ message: formatMessage({
1034
+ id: getTranslation("success.record.publish"),
1035
+ defaultMessage: "Published document"
1036
+ })
1037
+ });
1038
+ return res.data;
1039
+ } catch (err) {
1040
+ toggleNotification({
1041
+ type: "danger",
1042
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1043
+ });
1044
+ throw err;
1045
+ }
1046
+ },
1047
+ [
1048
+ // trackUsage,
1049
+ publishManyDocuments,
1050
+ toggleNotification,
1051
+ formatMessage,
1052
+ formatAPIError
1053
+ ]
1054
+ );
1030
1055
  const [updateDocument] = useUpdateDocumentMutation();
1031
1056
  const update = React__namespace.useCallback(
1032
1057
  async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
@@ -1101,6 +1126,41 @@ const useDocumentActions = () => {
1101
1126
  },
1102
1127
  [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1103
1128
  );
1129
+ const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1130
+ const unpublishMany = React__namespace.useCallback(
1131
+ async ({ model, documentIds, params }) => {
1132
+ try {
1133
+ trackUsage("willBulkUnpublishEntries");
1134
+ const res = await unpublishManyDocuments({
1135
+ model,
1136
+ documentIds,
1137
+ params
1138
+ });
1139
+ if ("error" in res) {
1140
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1141
+ return { error: res.error };
1142
+ }
1143
+ trackUsage("didBulkUnpublishEntries");
1144
+ toggleNotification({
1145
+ type: "success",
1146
+ title: formatMessage({
1147
+ id: getTranslation("success.records.unpublish"),
1148
+ defaultMessage: "Successfully unpublished."
1149
+ }),
1150
+ message: ""
1151
+ });
1152
+ return res.data;
1153
+ } catch (err) {
1154
+ toggleNotification({
1155
+ type: "danger",
1156
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1157
+ });
1158
+ trackUsage("didNotBulkUnpublishEntries");
1159
+ throw err;
1160
+ }
1161
+ },
1162
+ [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1163
+ );
1104
1164
  const [createDocument] = useCreateDocumentMutation();
1105
1165
  const create = React__namespace.useCallback(
1106
1166
  async ({ model, params }, data, trackerProperty) => {
@@ -1214,15 +1274,18 @@ const useDocumentActions = () => {
1214
1274
  clone,
1215
1275
  create,
1216
1276
  delete: _delete,
1277
+ deleteMany,
1217
1278
  discard,
1218
1279
  getDocument,
1219
1280
  publish,
1281
+ publishMany,
1220
1282
  unpublish,
1283
+ unpublishMany,
1221
1284
  update
1222
1285
  };
1223
1286
  };
1224
1287
  const ProtectedHistoryPage = React.lazy(
1225
- () => Promise.resolve().then(() => require("./History-BLEnudTX.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1288
+ () => Promise.resolve().then(() => require("./History-DShoVAh0.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1226
1289
  );
1227
1290
  const routes$1 = [
1228
1291
  {
@@ -1235,31 +1298,31 @@ const routes$1 = [
1235
1298
  }
1236
1299
  ];
1237
1300
  const ProtectedEditViewPage = React.lazy(
1238
- () => Promise.resolve().then(() => require("./EditViewPage-KRG56aCq.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1301
+ () => Promise.resolve().then(() => require("./EditViewPage-DZPDqo_G.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1239
1302
  );
1240
1303
  const ProtectedListViewPage = React.lazy(
1241
- () => Promise.resolve().then(() => require("./ListViewPage-DsaOakWQ.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1304
+ () => Promise.resolve().then(() => require("./ListViewPage-CFuXPZ_r.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1242
1305
  );
1243
1306
  const ProtectedListConfiguration = React.lazy(
1244
- () => Promise.resolve().then(() => require("./ListConfigurationPage-Zso_LUjn.js")).then((mod) => ({
1307
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-COIRGF5b.js")).then((mod) => ({
1245
1308
  default: mod.ProtectedListConfiguration
1246
1309
  }))
1247
1310
  );
1248
1311
  const ProtectedEditConfigurationPage = React.lazy(
1249
- () => Promise.resolve().then(() => require("./EditConfigurationPage-B7dw5_cS.js")).then((mod) => ({
1312
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-BeeGw2RI.js")).then((mod) => ({
1250
1313
  default: mod.ProtectedEditConfigurationPage
1251
1314
  }))
1252
1315
  );
1253
1316
  const ProtectedComponentConfigurationPage = React.lazy(
1254
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-2iOVVhqV.js")).then((mod) => ({
1317
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-DiigqkCf.js")).then((mod) => ({
1255
1318
  default: mod.ProtectedComponentConfigurationPage
1256
1319
  }))
1257
1320
  );
1258
1321
  const NoPermissions = React.lazy(
1259
- () => Promise.resolve().then(() => require("./NoPermissionsPage-DdyOfdKb.js")).then((mod) => ({ default: mod.NoPermissions }))
1322
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-D8gbX1Y_.js")).then((mod) => ({ default: mod.NoPermissions }))
1260
1323
  );
1261
1324
  const NoContentType = React.lazy(
1262
- () => Promise.resolve().then(() => require("./NoContentTypePage-DPCuS9Y1.js")).then((mod) => ({ default: mod.NoContentType }))
1325
+ () => Promise.resolve().then(() => require("./NoContentTypePage-rdH0Zp0A.js")).then((mod) => ({ default: mod.NoContentType }))
1263
1326
  );
1264
1327
  const CollectionTypePages = () => {
1265
1328
  const { collectionType } = reactRouterDom.useParams();
@@ -1449,7 +1512,7 @@ const DocumentActionsMenu = ({
1449
1512
  variant,
1450
1513
  children: [
1451
1514
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
1452
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { as: "span", children: label || formatMessage({
1515
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
1453
1516
  id: "content-manager.containers.edit.panels.default.more-actions",
1454
1517
  defaultMessage: "More document actions"
1455
1518
  }) })
@@ -1465,7 +1528,7 @@ const DocumentActionsMenu = ({
1465
1528
  onSelect: handleClick(action),
1466
1529
  display: "block",
1467
1530
  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: [
1531
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1469
1532
  action.icon,
1470
1533
  action.label
1471
1534
  ] }),
@@ -1571,7 +1634,7 @@ const DocumentActionModal = ({
1571
1634
  title,
1572
1635
  onClose,
1573
1636
  footer: Footer,
1574
- content,
1637
+ content: Content,
1575
1638
  onModalClose
1576
1639
  }) => {
1577
1640
  const id = React__namespace.useId();
@@ -1585,8 +1648,8 @@ const DocumentActionModal = ({
1585
1648
  onModalClose();
1586
1649
  };
1587
1650
  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 }),
1651
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: "neutral800", tag: "h2", id, children: title }) }),
1652
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content }),
1590
1653
  /* @__PURE__ */ jsxRuntime.jsx(
1591
1654
  designSystem.Box,
1592
1655
  {
@@ -1603,7 +1666,7 @@ const DocumentActionModal = ({
1603
1666
  )
1604
1667
  ] });
1605
1668
  };
1606
- const PublishAction = ({
1669
+ const PublishAction$1 = ({
1607
1670
  activeTab,
1608
1671
  documentId,
1609
1672
  model,
@@ -1688,7 +1751,7 @@ const PublishAction = ({
1688
1751
  }
1689
1752
  };
1690
1753
  };
1691
- PublishAction.type = "publish";
1754
+ PublishAction$1.type = "publish";
1692
1755
  const UpdateAction = ({
1693
1756
  activeTab,
1694
1757
  documentId,
@@ -1803,7 +1866,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
1803
1866
  KEEP: "keep",
1804
1867
  DISCARD: "discard"
1805
1868
  };
1806
- const UnpublishAction = ({
1869
+ const UnpublishAction$1 = ({
1807
1870
  activeTab,
1808
1871
  documentId,
1809
1872
  model,
@@ -1866,7 +1929,7 @@ const UnpublishAction = ({
1866
1929
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
1867
1930
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
1868
1931
  /* @__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({
1932
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1870
1933
  id: "content-manager.actions.unpublish.dialog.body",
1871
1934
  defaultMessage: "Are you sure?"
1872
1935
  }) })
@@ -1877,10 +1940,11 @@ const UnpublishAction = ({
1877
1940
  onChange: handleChange,
1878
1941
  direction: "column",
1879
1942
  alignItems: "flex-start",
1880
- as: "fieldset",
1943
+ tag: "fieldset",
1944
+ borderWidth: 0,
1881
1945
  gap: 3,
1882
1946
  children: [
1883
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { as: "legend" }),
1947
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "legend" }),
1884
1948
  /* @__PURE__ */ jsxRuntime.jsx(
1885
1949
  designSystem.Radio,
1886
1950
  {
@@ -1937,7 +2001,7 @@ const UnpublishAction = ({
1937
2001
  position: ["panel", "table-row"]
1938
2002
  };
1939
2003
  };
1940
- UnpublishAction.type = "unpublish";
2004
+ UnpublishAction$1.type = "unpublish";
1941
2005
  const DiscardAction = ({
1942
2006
  activeTab,
1943
2007
  documentId,
@@ -1971,7 +2035,7 @@ const DiscardAction = ({
1971
2035
  }),
1972
2036
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
1973
2037
  /* @__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({
2038
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1975
2039
  id: "content-manager.actions.discard.dialog.body",
1976
2040
  defaultMessage: "Are you sure?"
1977
2041
  }) })
@@ -1988,12 +2052,12 @@ const DiscardAction = ({
1988
2052
  };
1989
2053
  };
1990
2054
  DiscardAction.type = "discard";
1991
- const StyledCrossCircle = styled__default.default(Icons.CrossCircle)`
2055
+ const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
1992
2056
  path {
1993
2057
  fill: currentColor;
1994
2058
  }
1995
2059
  `;
1996
- const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
2060
+ const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
1997
2061
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
1998
2062
  const RelativeTime = React__namespace.forwardRef(
1999
2063
  ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
@@ -2041,7 +2105,7 @@ const getDisplayName = ({
2041
2105
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2042
2106
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2043
2107
  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) }) });
2108
+ 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
2109
  };
2046
2110
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2047
2111
  const { formatMessage } = reactIntl.useIntl();
@@ -2061,7 +2125,7 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2061
2125
  gap: "80px",
2062
2126
  alignItems: "flex-start",
2063
2127
  children: [
2064
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", children: title }),
2128
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2065
2129
  /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2066
2130
  ]
2067
2131
  }
@@ -2218,7 +2282,7 @@ const Information = ({ activeTab }) => {
2218
2282
  borderColor: "neutral150",
2219
2283
  direction: "column",
2220
2284
  marginTop: 2,
2221
- as: "dl",
2285
+ tag: "dl",
2222
2286
  padding: 5,
2223
2287
  gap: 3,
2224
2288
  alignItems: "flex-start",
@@ -2226,8 +2290,8 @@ const Information = ({ activeTab }) => {
2226
2290
  marginRight: "-0.4rem",
2227
2291
  width: "calc(100% + 8px)",
2228
2292
  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 })
2293
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2294
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2231
2295
  ] }, info.label))
2232
2296
  }
2233
2297
  );
@@ -2260,7 +2324,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2260
2324
  id: "app.links.configure-view",
2261
2325
  defaultMessage: "Configure the view"
2262
2326
  }),
2263
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCog, {}),
2327
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
2264
2328
  onClick: () => {
2265
2329
  navigate(`../${collectionType}/${model}/configurations/edit`);
2266
2330
  },
@@ -2268,11 +2332,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2268
2332
  };
2269
2333
  };
2270
2334
  ConfigureTheViewAction.type = "configure-the-view";
2271
- const StyledCog = styled__default.default(Icons.Cog)`
2272
- path {
2273
- fill: currentColor;
2274
- }
2275
- `;
2276
2335
  const EditTheModelAction = ({ model }) => {
2277
2336
  const navigate = reactRouterDom.useNavigate();
2278
2337
  const { formatMessage } = reactIntl.useIntl();
@@ -2281,7 +2340,7 @@ const EditTheModelAction = ({ model }) => {
2281
2340
  id: "content-manager.link-to-ctb",
2282
2341
  defaultMessage: "Edit the model"
2283
2342
  }),
2284
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil$1, {}),
2343
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
2285
2344
  onClick: () => {
2286
2345
  navigate(`/plugins/content-type-builder/content-types/${model}`);
2287
2346
  },
@@ -2289,12 +2348,7 @@ const EditTheModelAction = ({ model }) => {
2289
2348
  };
2290
2349
  };
2291
2350
  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 }) => {
2351
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2298
2352
  const navigate = reactRouterDom.useNavigate();
2299
2353
  const { formatMessage } = reactIntl.useIntl();
2300
2354
  const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
@@ -2308,7 +2362,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2308
2362
  id: "content-manager.actions.delete.label",
2309
2363
  defaultMessage: "Delete document"
2310
2364
  }),
2311
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledTrash, {}),
2365
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2312
2366
  dialog: {
2313
2367
  type: "dialog",
2314
2368
  title: formatMessage({
@@ -2317,7 +2371,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2317
2371
  }),
2318
2372
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
2319
2373
  /* @__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({
2374
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2321
2375
  id: "content-manager.actions.delete.dialog.body",
2322
2376
  defaultMessage: "Are you sure?"
2323
2377
  }) })
@@ -2362,13 +2416,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2362
2416
  position: ["header", "table-row"]
2363
2417
  };
2364
2418
  };
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];
2419
+ DeleteAction$1.type = "delete";
2420
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2372
2421
  const Panels = () => {
2373
2422
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2374
2423
  const [
@@ -2442,7 +2491,7 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2442
2491
  designSystem.Flex,
2443
2492
  {
2444
2493
  ref,
2445
- as: "aside",
2494
+ tag: "aside",
2446
2495
  "aria-labelledby": "additional-information",
2447
2496
  background: "neutral0",
2448
2497
  borderColor: "neutral150",
@@ -2457,669 +2506,1364 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2457
2506
  justifyContent: "stretch",
2458
2507
  alignItems: "flex-start",
2459
2508
  children: [
2460
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2509
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2461
2510
  children
2462
2511
  ]
2463
2512
  }
2464
2513
  );
2465
2514
  });
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
- ] });
2515
+ const HOOKS = {
2516
+ /**
2517
+ * Hook that allows to mutate the displayed headers of the list view table
2518
+ * @constant
2519
+ * @type {string}
2520
+ */
2521
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2522
+ /**
2523
+ * Hook that allows to mutate the CM's collection types links pre-set filters
2524
+ * @constant
2525
+ * @type {string}
2526
+ */
2527
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2528
+ /**
2529
+ * Hook that allows to mutate the CM's edit view layout
2530
+ * @constant
2531
+ * @type {string}
2532
+ */
2533
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2534
+ /**
2535
+ * Hook that allows to mutate the CM's single types links pre-set filters
2536
+ * @constant
2537
+ * @type {string}
2538
+ */
2539
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2519
2540
  };
2520
- const TableActions = ({ document }) => {
2521
- const { formatMessage } = reactIntl.useIntl();
2522
- const { model, collectionType } = useDoc();
2523
- const plugins = strapiAdmin.useStrapiApp("TableActions", (state) => state.plugins);
2524
- const props = {
2525
- activeTab: null,
2526
- model,
2527
- documentId: document.documentId,
2528
- collectionType,
2529
- document
2530
- };
2531
- return /* @__PURE__ */ jsxRuntime.jsx(
2532
- strapiAdmin.DescriptionComponentRenderer,
2533
- {
2534
- props,
2535
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2536
- children: (actions2) => {
2537
- const tableRowActions = actions2.filter((action) => {
2538
- const positions = Array.isArray(action.position) ? action.position : [action.position];
2539
- return positions.includes("table-row");
2540
- });
2541
- return /* @__PURE__ */ jsxRuntime.jsx(
2542
- DocumentActionsMenu,
2543
- {
2544
- actions: tableRowActions,
2545
- label: formatMessage({
2546
- id: "content-manager.containers.list.table.row-actions",
2547
- defaultMessage: "Row action"
2548
- }),
2549
- variant: "ghost"
2550
- }
2551
- );
2552
- }
2553
- }
2541
+ const contentTypesApi = contentManagerApi.injectEndpoints({
2542
+ endpoints: (builder) => ({
2543
+ getContentTypeConfiguration: builder.query({
2544
+ query: (uid) => ({
2545
+ url: `/content-manager/content-types/${uid}/configuration`,
2546
+ method: "GET"
2547
+ }),
2548
+ transformResponse: (response) => response.data,
2549
+ providesTags: (_result, _error, uid) => [
2550
+ { type: "ContentTypesConfiguration", id: uid },
2551
+ { type: "ContentTypeSettings", id: "LIST" }
2552
+ ]
2553
+ }),
2554
+ getAllContentTypeSettings: builder.query({
2555
+ query: () => "/content-manager/content-types-settings",
2556
+ transformResponse: (response) => response.data,
2557
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2558
+ }),
2559
+ updateContentTypeConfiguration: builder.mutation({
2560
+ query: ({ uid, ...body }) => ({
2561
+ url: `/content-manager/content-types/${uid}/configuration`,
2562
+ method: "PUT",
2563
+ data: body
2564
+ }),
2565
+ transformResponse: (response) => response.data,
2566
+ invalidatesTags: (_result, _error, { uid }) => [
2567
+ { type: "ContentTypesConfiguration", id: uid },
2568
+ { type: "ContentTypeSettings", id: "LIST" },
2569
+ // Is this necessary?
2570
+ { type: "InitialData" }
2571
+ ]
2572
+ })
2573
+ })
2574
+ });
2575
+ const {
2576
+ useGetContentTypeConfigurationQuery,
2577
+ useGetAllContentTypeSettingsQuery,
2578
+ useUpdateContentTypeConfigurationMutation
2579
+ } = contentTypesApi;
2580
+ const checkIfAttributeIsDisplayable = (attribute) => {
2581
+ const { type } = attribute;
2582
+ if (type === "relation") {
2583
+ return !attribute.relation.toLowerCase().includes("morph");
2584
+ }
2585
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2586
+ };
2587
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2588
+ if (!mainFieldName) {
2589
+ return void 0;
2590
+ }
2591
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2592
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2593
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2554
2594
  );
2595
+ return {
2596
+ name: mainFieldName,
2597
+ type: mainFieldType ?? "string"
2598
+ };
2555
2599
  };
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();
2600
+ const DEFAULT_SETTINGS = {
2601
+ bulkable: false,
2602
+ filterable: false,
2603
+ searchable: false,
2604
+ pagination: false,
2605
+ defaultSortBy: "",
2606
+ defaultSortOrder: "asc",
2607
+ mainField: "id",
2608
+ pageSize: 10
2609
+ };
2610
+ const useDocumentLayout = (model) => {
2611
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2561
2612
  const [{ query }] = strapiAdmin.useQueryParams();
2562
- return {
2563
- disabled: !canRead,
2564
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil, {}),
2565
- label: formatMessage({
2566
- id: "content-manager.actions.edit.label",
2567
- defaultMessage: "Edit"
2568
- }),
2569
- position: "table-row",
2570
- onClick: async () => {
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;
2583
- }
2584
- navigate({
2585
- pathname: documentId,
2586
- search: qs.stringify({
2587
- plugins: query.plugins
2588
- })
2613
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2614
+ const { toggleNotification } = strapiAdmin.useNotification();
2615
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2616
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2617
+ const {
2618
+ data,
2619
+ isLoading: isLoadingConfigs,
2620
+ error,
2621
+ isFetching: isFetchingConfigs
2622
+ } = useGetContentTypeConfigurationQuery(model);
2623
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2624
+ React__namespace.useEffect(() => {
2625
+ if (error) {
2626
+ toggleNotification({
2627
+ type: "danger",
2628
+ message: formatAPIError(error)
2589
2629
  });
2590
2630
  }
2631
+ }, [error, formatAPIError, toggleNotification]);
2632
+ const editLayout = React__namespace.useMemo(
2633
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2634
+ layout: [],
2635
+ components: {},
2636
+ metadatas: {},
2637
+ options: {},
2638
+ settings: DEFAULT_SETTINGS
2639
+ },
2640
+ [data, isLoading, schemas, schema, components]
2641
+ );
2642
+ const listLayout = React__namespace.useMemo(() => {
2643
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2644
+ layout: [],
2645
+ metadatas: {},
2646
+ options: {},
2647
+ settings: DEFAULT_SETTINGS
2648
+ };
2649
+ }, [data, isLoading, schemas, schema, components]);
2650
+ const { layout: edit } = React__namespace.useMemo(
2651
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2652
+ layout: editLayout,
2653
+ query
2654
+ }),
2655
+ [editLayout, query, runHookWaterfall]
2656
+ );
2657
+ return {
2658
+ error,
2659
+ isLoading,
2660
+ edit,
2661
+ list: listLayout
2591
2662
  };
2592
2663
  };
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();
2601
- const { formatMessage } = reactIntl.useIntl();
2602
- const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
2603
- 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);
2664
+ const useDocLayout = () => {
2665
+ const { model } = useDoc();
2666
+ return useDocumentLayout(model);
2667
+ };
2668
+ const formatEditLayout = (data, {
2669
+ schemas,
2670
+ schema,
2671
+ components
2672
+ }) => {
2673
+ let currentPanelIndex = 0;
2674
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2675
+ data.contentType.layouts.edit,
2676
+ schema?.attributes,
2677
+ data.contentType.metadatas,
2678
+ { configurations: data.components, schemas: components },
2679
+ schemas
2680
+ ).reduce((panels, row) => {
2681
+ if (row.some((field) => field.type === "dynamiczone")) {
2682
+ panels.push([row]);
2683
+ currentPanelIndex += 2;
2684
+ } else {
2685
+ if (!panels[currentPanelIndex]) {
2686
+ panels.push([]);
2636
2687
  }
2688
+ panels[currentPanelIndex].push(row);
2689
+ }
2690
+ return panels;
2691
+ }, []);
2692
+ const componentEditAttributes = Object.entries(data.components).reduce(
2693
+ (acc, [uid, configuration]) => {
2694
+ acc[uid] = {
2695
+ layout: convertEditLayoutToFieldLayouts(
2696
+ configuration.layouts.edit,
2697
+ components[uid].attributes,
2698
+ configuration.metadatas
2699
+ ),
2700
+ settings: {
2701
+ ...configuration.settings,
2702
+ icon: components[uid].info.icon,
2703
+ displayName: components[uid].info.displayName
2704
+ }
2705
+ };
2706
+ return acc;
2637
2707
  },
2638
- dialog: {
2639
- type: "modal",
2708
+ {}
2709
+ );
2710
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2711
+ (acc, [attribute, metadata]) => {
2712
+ return {
2713
+ ...acc,
2714
+ [attribute]: metadata.edit
2715
+ };
2716
+ },
2717
+ {}
2718
+ );
2719
+ return {
2720
+ layout: panelledEditAttributes,
2721
+ components: componentEditAttributes,
2722
+ metadatas: editMetadatas,
2723
+ settings: {
2724
+ ...data.contentType.settings,
2725
+ displayName: schema?.info.displayName
2726
+ },
2727
+ options: {
2728
+ ...schema?.options,
2729
+ ...schema?.pluginOptions,
2730
+ ...data.contentType.options
2731
+ }
2732
+ };
2733
+ };
2734
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2735
+ return rows.map(
2736
+ (row) => row.map((field) => {
2737
+ const attribute = attributes[field.name];
2738
+ if (!attribute) {
2739
+ return null;
2740
+ }
2741
+ const { edit: metadata } = metadatas[field.name];
2742
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2743
+ return {
2744
+ attribute,
2745
+ disabled: !metadata.editable,
2746
+ hint: metadata.description,
2747
+ label: metadata.label ?? "",
2748
+ name: field.name,
2749
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
2750
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2751
+ schemas,
2752
+ components: components?.schemas ?? {}
2753
+ }),
2754
+ placeholder: metadata.placeholder ?? "",
2755
+ required: attribute.required ?? false,
2756
+ size: field.size,
2757
+ unique: "unique" in attribute ? attribute.unique : false,
2758
+ visible: metadata.visible ?? true,
2759
+ type: attribute.type
2760
+ };
2761
+ }).filter((field) => field !== null)
2762
+ );
2763
+ };
2764
+ const formatListLayout = (data, {
2765
+ schemas,
2766
+ schema,
2767
+ components
2768
+ }) => {
2769
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2770
+ (acc, [attribute, metadata]) => {
2771
+ return {
2772
+ ...acc,
2773
+ [attribute]: metadata.list
2774
+ };
2775
+ },
2776
+ {}
2777
+ );
2778
+ const listAttributes = convertListLayoutToFieldLayouts(
2779
+ data.contentType.layouts.list,
2780
+ schema?.attributes,
2781
+ listMetadatas,
2782
+ { configurations: data.components, schemas: components },
2783
+ schemas
2784
+ );
2785
+ return {
2786
+ layout: listAttributes,
2787
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2788
+ metadatas: listMetadatas,
2789
+ options: {
2790
+ ...schema?.options,
2791
+ ...schema?.pluginOptions,
2792
+ ...data.contentType.options
2793
+ }
2794
+ };
2795
+ };
2796
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2797
+ return columns.map((name) => {
2798
+ const attribute = attributes[name];
2799
+ if (!attribute) {
2800
+ return null;
2801
+ }
2802
+ const metadata = metadatas[name];
2803
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2804
+ return {
2805
+ attribute,
2806
+ label: metadata.label ?? "",
2807
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2808
+ schemas,
2809
+ components: components?.schemas ?? {}
2810
+ }),
2811
+ name,
2812
+ searchable: metadata.searchable ?? true,
2813
+ sortable: metadata.sortable ?? true
2814
+ };
2815
+ }).filter((field) => field !== null);
2816
+ };
2817
+ const ConfirmBulkActionDialog = ({
2818
+ onToggleDialog,
2819
+ isOpen = false,
2820
+ dialogBody,
2821
+ endAction
2822
+ }) => {
2823
+ const { formatMessage } = reactIntl.useIntl();
2824
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2825
+ designSystem.Dialog,
2826
+ {
2827
+ onClose: onToggleDialog,
2640
2828
  title: formatMessage({
2641
- id: "content-manager.containers.list.autoCloneModal.header",
2642
- defaultMessage: "Duplicate"
2829
+ id: "app.components.ConfirmDialog.title",
2830
+ defaultMessage: "Confirmation"
2643
2831
  }),
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,
2832
+ isOpen,
2833
+ children: [
2834
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.DialogBody, { icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, {}), children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: dialogBody }) }),
2835
+ /* @__PURE__ */ jsxRuntime.jsx(
2836
+ designSystem.DialogFooter,
2837
+ {
2838
+ startAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
2839
+ id: "app.components.Button.cancel",
2840
+ defaultMessage: "Cancel"
2841
+ }) }),
2842
+ endAction
2843
+ }
2844
+ )
2845
+ ]
2846
+ }
2847
+ );
2848
+ };
2849
+ const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
2850
+ const ConfirmDialogPublishAll = ({
2851
+ isOpen,
2852
+ onToggleDialog,
2853
+ isConfirmButtonLoading = false,
2854
+ onConfirm
2855
+ }) => {
2856
+ const { formatMessage } = reactIntl.useIntl();
2857
+ const selectedEntries = strapiAdmin.useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
2858
+ const { toggleNotification } = strapiAdmin.useNotification();
2859
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2860
+ const { model, schema } = useDoc();
2861
+ const [{ query }] = strapiAdmin.useQueryParams();
2862
+ const {
2863
+ data: countDraftRelations = 0,
2864
+ isLoading,
2865
+ error
2866
+ } = useGetManyDraftRelationCountQuery(
2867
+ {
2868
+ model,
2869
+ documentIds: selectedEntries.map((entry) => entry.documentId),
2870
+ locale: query?.plugins?.i18n?.locale
2871
+ },
2872
+ {
2873
+ skip: selectedEntries.length === 0
2874
+ }
2875
+ );
2876
+ React__namespace.useEffect(() => {
2877
+ if (error) {
2878
+ toggleNotification({ type: "danger", message: formatAPIError(error) });
2879
+ }
2880
+ }, [error, formatAPIError, toggleNotification]);
2881
+ if (error) {
2882
+ return null;
2883
+ }
2884
+ return /* @__PURE__ */ jsxRuntime.jsx(
2885
+ ConfirmBulkActionDialog,
2886
+ {
2887
+ isOpen: isOpen && !isLoading,
2888
+ onToggleDialog,
2889
+ dialogBody: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2890
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: [
2891
+ countDraftRelations > 0 && formatMessage(
2653
2892
  {
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
- })
2893
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2894
+ 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. "
2895
+ },
2896
+ {
2897
+ b: BoldChunk$1,
2898
+ count: countDraftRelations,
2899
+ entities: selectedEntries.length
2662
2900
  }
2901
+ ),
2902
+ formatMessage({
2903
+ id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
2904
+ defaultMessage: "Are you sure you want to publish these entries?"
2905
+ })
2906
+ ] }),
2907
+ schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
2908
+ {
2909
+ id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
2910
+ defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
2911
+ },
2912
+ {
2913
+ em: Emphasis
2914
+ }
2915
+ ) })
2916
+ ] }),
2917
+ endAction: /* @__PURE__ */ jsxRuntime.jsx(
2918
+ designSystem.Button,
2919
+ {
2920
+ onClick: onConfirm,
2921
+ variant: "secondary",
2922
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
2923
+ loading: isConfirmButtonLoading,
2924
+ children: formatMessage({
2925
+ id: "app.utils.publish",
2926
+ defaultMessage: "Publish"
2927
+ })
2928
+ }
2929
+ )
2930
+ }
2931
+ );
2932
+ };
2933
+ const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
2934
+ max-width: 300px;
2935
+ `;
2936
+ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2937
+ const messages = [];
2938
+ Object.entries(errors).forEach(([key, value]) => {
2939
+ const currentKey = parentKey ? `${parentKey}.${key}` : key;
2940
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
2941
+ if ("id" in value && "defaultMessage" in value) {
2942
+ messages.push(
2943
+ formatMessage(
2944
+ {
2945
+ id: `${value.id}.withField`,
2946
+ defaultMessage: value.defaultMessage
2947
+ },
2948
+ { field: currentKey }
2663
2949
  )
2664
- ] });
2950
+ );
2951
+ } else {
2952
+ messages.push(...formatErrorMessages(value, currentKey, formatMessage));
2665
2953
  }
2666
2954
  }
2667
- };
2955
+ });
2956
+ return messages;
2668
2957
  };
2669
- CloneAction.type = "clone";
2670
- const StyledDuplicate = styled__default.default(Icons.Duplicate)`
2671
- path {
2672
- fill: currentColor;
2673
- }
2674
- `;
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() {
2958
+ const EntryValidationText = ({
2959
+ validationErrors,
2960
+ isPublished = false
2961
+ }) => {
2962
+ const { formatMessage } = reactIntl.useIntl();
2963
+ if (validationErrors) {
2964
+ const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
2965
+ " "
2966
+ );
2967
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2968
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
2969
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
2970
+ ] });
2693
2971
  }
2694
- addEditViewSidePanel(panels) {
2695
- if (Array.isArray(panels)) {
2696
- this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
2697
- } else if (typeof panels === "function") {
2698
- this.editViewSidePanels = panels(this.editViewSidePanels);
2699
- } else {
2700
- throw new Error(
2701
- `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
2702
- panels
2703
- )}`
2704
- );
2705
- }
2972
+ if (isPublished) {
2973
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2974
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
2975
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
2976
+ id: "content-manager.bulk-publish.already-published",
2977
+ defaultMessage: "Already Published"
2978
+ }) })
2979
+ ] });
2706
2980
  }
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
- );
2981
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2982
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
2983
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
2984
+ id: "app.utils.ready-to-publish",
2985
+ defaultMessage: "Ready to publish"
2986
+ }) })
2987
+ ] });
2988
+ };
2989
+ const TABLE_HEADERS = [
2990
+ { name: "id", label: "id" },
2991
+ { name: "name", label: "name" },
2992
+ { name: "status", label: "status" },
2993
+ { name: "publicationStatus", label: "Publication status" }
2994
+ ];
2995
+ const SelectedEntriesTableContent = ({
2996
+ isPublishing,
2997
+ rowsToDisplay = [],
2998
+ entriesToPublish = [],
2999
+ validationErrors = {}
3000
+ }) => {
3001
+ const { pathname } = reactRouterDom.useLocation();
3002
+ const { formatMessage } = reactIntl.useIntl();
3003
+ const {
3004
+ list: {
3005
+ settings: { mainField }
2718
3006
  }
2719
- }
2720
- addDocumentHeaderAction(actions2) {
2721
- if (Array.isArray(actions2)) {
2722
- this.headerActions = [...this.headerActions, ...actions2];
2723
- } else if (typeof actions2 === "function") {
2724
- this.headerActions = actions2(this.headerActions);
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
- );
3007
+ } = useDocLayout();
3008
+ const shouldDisplayMainField = mainField != null && mainField !== "id";
3009
+ return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
3010
+ /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
3011
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
3012
+ TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
3013
+ (head) => /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, { ...head }, head.name)
3014
+ )
3015
+ ] }),
3016
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
3017
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
3018
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
3019
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
3020
+ shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
3021
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
3022
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3023
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3024
+ id: "content-manager.success.record.publishing",
3025
+ defaultMessage: "Publishing..."
3026
+ }) }),
3027
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true })
3028
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
3029
+ EntryValidationText,
3030
+ {
3031
+ validationErrors: validationErrors[row.documentId],
3032
+ isPublished: row.publishedAt !== null
3033
+ }
3034
+ ) }),
3035
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3036
+ designSystem.IconButton,
3037
+ {
3038
+ tag: reactRouterDom.Link,
3039
+ to: {
3040
+ pathname: `${pathname}/${row.documentId}`,
3041
+ search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3042
+ },
3043
+ state: { from: pathname },
3044
+ label: formatMessage(
3045
+ { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3046
+ {
3047
+ target: formatMessage(
3048
+ {
3049
+ id: "content-manager.components.ListViewHelperPluginTable.row-line",
3050
+ defaultMessage: "item line {number}"
3051
+ },
3052
+ { number: index2 + 1 }
3053
+ )
3054
+ }
3055
+ ),
3056
+ target: "_blank",
3057
+ marginLeft: "auto",
3058
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3059
+ }
3060
+ ) })
3061
+ ] }, row.id)) })
3062
+ ] });
3063
+ };
3064
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
3065
+ const SelectedEntriesModalContent = ({
3066
+ listViewSelectedEntries,
3067
+ toggleModal,
3068
+ setListViewSelectedDocuments,
3069
+ model
3070
+ }) => {
3071
+ const { formatMessage } = reactIntl.useIntl();
3072
+ const { schema, components } = useContentTypeSchema(model);
3073
+ const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
3074
+ const [{ query }] = strapiAdmin.useQueryParams();
3075
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3076
+ const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
3077
+ {
3078
+ model,
3079
+ params: {
3080
+ page: "1",
3081
+ pageSize: documentIds.length.toString(),
3082
+ sort: query.sort,
3083
+ filters: {
3084
+ documentId: {
3085
+ $in: documentIds
3086
+ }
3087
+ },
3088
+ locale: query.plugins?.i18n?.locale
3089
+ }
3090
+ },
3091
+ {
3092
+ selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
2731
3093
  }
2732
- }
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
- );
3094
+ );
3095
+ const { rows, validationErrors } = React__namespace.useMemo(() => {
3096
+ if (data.length > 0 && schema) {
3097
+ const validate = createYupSchema(schema.attributes, components);
3098
+ const validationErrors2 = {};
3099
+ const rows2 = data.map((entry) => {
3100
+ try {
3101
+ validate.validateSync(entry, { abortEarly: false });
3102
+ return entry;
3103
+ } catch (e) {
3104
+ if (e instanceof yup.ValidationError) {
3105
+ validationErrors2[entry.documentId] = strapiAdmin.getYupValidationErrors(e);
3106
+ }
3107
+ return entry;
3108
+ }
3109
+ });
3110
+ return { rows: rows2, validationErrors: validationErrors2 };
2744
3111
  }
2745
- }
2746
- get config() {
2747
3112
  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
- }
3113
+ rows: [],
3114
+ validationErrors: {}
2761
3115
  };
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;
3116
+ }, [components, data, schema]);
3117
+ const [publishedCount, setPublishedCount] = React__namespace.useState(0);
3118
+ const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
3119
+ const { publishMany: bulkPublishAction } = useDocumentActions();
3120
+ const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
3121
+ const selectedEntries = strapiAdmin.useTable("publishAction", (state) => state.selectedRows);
3122
+ const entriesToPublish = selectedEntries.reduce((acc, entry) => {
3123
+ if (!validationErrors[entry.documentId]) {
3124
+ acc.push(entry.documentId);
2773
3125
  }
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
3126
+ return acc;
3127
+ }, []);
3128
+ const selectedEntriesWithErrorsCount = selectedEntries.filter(
3129
+ ({ documentId }) => validationErrors[documentId]
3130
+ ).length;
3131
+ const selectedEntriesPublished = selectedEntries.filter(
3132
+ ({ publishedAt }) => !!publishedAt
3133
+ ).length;
3134
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3135
+ const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3136
+ const handleConfirmBulkPublish = async () => {
3137
+ toggleDialog();
3138
+ const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3139
+ if (!("error" in res)) {
3140
+ setPublishedCount(res.count);
3141
+ const unpublishedEntries = rows.filter((row) => {
3142
+ return !entriesToPublish.includes(row.documentId);
3143
+ });
3144
+ setListViewSelectedDocuments(unpublishedEntries);
3145
+ }
3146
+ };
3147
+ const getFormattedCountMessage = () => {
3148
+ if (publishedCount) {
3149
+ return formatMessage(
3150
+ {
3151
+ id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3152
+ 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."
3153
+ },
3154
+ {
3155
+ publishedCount,
3156
+ withErrorsCount: selectedEntriesWithErrorsCount,
3157
+ b: BoldChunk
3158
+ }
2799
3159
  );
2800
- state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
2801
- state.components = components;
2802
- state.models = contentTypeSchemas;
2803
- state.fieldSizes = fieldSizes;
2804
- state.isLoading = false;
2805
3160
  }
2806
- }
2807
- });
2808
- const { actions, reducer: reducer$1 } = appSlice;
2809
- const { setInitialData } = actions;
2810
- const reducer = toolkit.combineReducers({
2811
- app: reducer$1
2812
- });
2813
- const HOOKS = {
2814
- /**
2815
- * Hook that allows to mutate the displayed headers of the list view table
2816
- * @constant
2817
- * @type {string}
2818
- */
2819
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2820
- /**
2821
- * Hook that allows to mutate the CM's collection types links pre-set filters
2822
- * @constant
2823
- * @type {string}
2824
- */
2825
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2826
- /**
2827
- * Hook that allows to mutate the CM's edit view layout
2828
- * @constant
2829
- * @type {string}
2830
- */
2831
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2832
- /**
2833
- * Hook that allows to mutate the CM's single types links pre-set filters
2834
- * @constant
2835
- * @type {string}
2836
- */
2837
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2838
- };
2839
- const contentTypesApi = contentManagerApi.injectEndpoints({
2840
- endpoints: (builder) => ({
2841
- getContentTypeConfiguration: builder.query({
2842
- query: (uid) => ({
2843
- url: `/content-manager/content-types/${uid}/configuration`,
2844
- method: "GET"
2845
- }),
2846
- transformResponse: (response) => response.data,
2847
- providesTags: (_result, _error, uid) => [
2848
- { type: "ContentTypesConfiguration", id: uid },
2849
- { type: "ContentTypeSettings", id: "LIST" }
2850
- ]
2851
- }),
2852
- getAllContentTypeSettings: builder.query({
2853
- query: () => "/content-manager/content-types-settings",
2854
- transformResponse: (response) => response.data,
2855
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2856
- }),
2857
- updateContentTypeConfiguration: builder.mutation({
2858
- query: ({ uid, ...body }) => ({
2859
- url: `/content-manager/content-types/${uid}/configuration`,
2860
- method: "PUT",
2861
- data: body
2862
- }),
2863
- transformResponse: (response) => response.data,
2864
- invalidatesTags: (_result, _error, { uid }) => [
2865
- { type: "ContentTypesConfiguration", id: uid },
2866
- { type: "ContentTypeSettings", id: "LIST" },
2867
- // Is this necessary?
2868
- { type: "InitialData" }
2869
- ]
2870
- })
2871
- })
2872
- });
2873
- const {
2874
- useGetContentTypeConfigurationQuery,
2875
- useGetAllContentTypeSettingsQuery,
2876
- useUpdateContentTypeConfigurationMutation
2877
- } = contentTypesApi;
2878
- const checkIfAttributeIsDisplayable = (attribute) => {
2879
- const { type } = attribute;
2880
- if (type === "relation") {
2881
- return !attribute.relation.toLowerCase().includes("morph");
2882
- }
2883
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
3161
+ return formatMessage(
3162
+ {
3163
+ id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3164
+ 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."
3165
+ },
3166
+ {
3167
+ readyToPublishCount: selectedEntriesWithNoErrorsCount,
3168
+ withErrorsCount: selectedEntriesWithErrorsCount,
3169
+ alreadyPublishedCount: selectedEntriesPublished,
3170
+ b: BoldChunk
3171
+ }
3172
+ );
3173
+ };
3174
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3175
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalBody, { children: [
3176
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
3177
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
3178
+ SelectedEntriesTableContent,
3179
+ {
3180
+ isPublishing: isSubmittingForm,
3181
+ rowsToDisplay: rows,
3182
+ entriesToPublish,
3183
+ validationErrors
3184
+ }
3185
+ ) })
3186
+ ] }),
3187
+ /* @__PURE__ */ jsxRuntime.jsx(
3188
+ designSystem.ModalFooter,
3189
+ {
3190
+ startActions: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3191
+ id: "app.components.Button.cancel",
3192
+ defaultMessage: "Cancel"
3193
+ }) }),
3194
+ endActions: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3195
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3196
+ /* @__PURE__ */ jsxRuntime.jsx(
3197
+ designSystem.Button,
3198
+ {
3199
+ onClick: toggleDialog,
3200
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || isLoading,
3201
+ loading: isSubmittingForm,
3202
+ children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3203
+ }
3204
+ )
3205
+ ] })
3206
+ }
3207
+ ),
3208
+ /* @__PURE__ */ jsxRuntime.jsx(
3209
+ ConfirmDialogPublishAll,
3210
+ {
3211
+ isOpen: isDialogOpen,
3212
+ onToggleDialog: toggleDialog,
3213
+ isConfirmButtonLoading: isSubmittingForm,
3214
+ onConfirm: handleConfirmBulkPublish
3215
+ }
3216
+ )
3217
+ ] });
2884
3218
  };
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
- );
3219
+ const PublishAction = ({ documents, model }) => {
3220
+ const { formatMessage } = reactIntl.useIntl();
3221
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3222
+ const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
3223
+ const setListViewSelectedDocuments = strapiAdmin.useTable("publishAction", (state) => state.selectRow);
3224
+ const refetchList = () => {
3225
+ contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3226
+ };
3227
+ if (!showPublishButton)
3228
+ return null;
2893
3229
  return {
2894
- name: mainFieldName,
2895
- type: mainFieldType ?? "string"
3230
+ actionType: "publish",
3231
+ variant: "tertiary",
3232
+ label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
3233
+ dialog: {
3234
+ type: "modal",
3235
+ title: formatMessage({
3236
+ id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
3237
+ defaultMessage: "Publish entries"
3238
+ }),
3239
+ content: ({ onClose }) => {
3240
+ return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsxRuntime.jsx(
3241
+ SelectedEntriesModalContent,
3242
+ {
3243
+ listViewSelectedEntries: documents,
3244
+ toggleModal: () => {
3245
+ onClose();
3246
+ refetchList();
3247
+ },
3248
+ setListViewSelectedDocuments,
3249
+ model
3250
+ }
3251
+ ) });
3252
+ },
3253
+ onClose: () => {
3254
+ refetchList();
3255
+ }
3256
+ }
2896
3257
  };
2897
3258
  };
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
3259
+ const BulkActionsRenderer = () => {
3260
+ const plugins = strapiAdmin.useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
3261
+ const { model, collectionType } = useDoc();
3262
+ const { selectedRows } = strapiAdmin.useTable("BulkActionsRenderer", (state) => state);
3263
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
3264
+ strapiAdmin.DescriptionComponentRenderer,
3265
+ {
3266
+ props: {
3267
+ model,
3268
+ collectionType,
3269
+ documents: selectedRows
3270
+ },
3271
+ descriptions: plugins["content-manager"].apis.getBulkActions(),
3272
+ children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(BulkActionAction, { ...action }, action.id))
3273
+ }
3274
+ ) });
2907
3275
  };
2908
- const useDocumentLayout = (model) => {
2909
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2910
- const [{ query }] = strapiAdmin.useQueryParams();
2911
- const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
3276
+ const BulkActionAction = (action) => {
3277
+ const [dialogId, setDialogId] = React__namespace.useState(null);
2912
3278
  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
- });
3279
+ const handleClick = (action2) => (e) => {
3280
+ const { onClick, dialog, id } = action2;
3281
+ if (onClick) {
3282
+ onClick(e);
2928
3283
  }
2929
- }, [error, formatAPIError, toggleNotification]);
2930
- const editLayout = React__namespace.useMemo(
2931
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2932
- layout: [],
2933
- components: {},
2934
- metadatas: {},
2935
- options: {},
2936
- settings: DEFAULT_SETTINGS
2937
- },
2938
- [data, isLoading, schemas, schema, components]
2939
- );
2940
- const listLayout = React__namespace.useMemo(() => {
2941
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2942
- layout: [],
2943
- metadatas: {},
2944
- options: {},
2945
- settings: DEFAULT_SETTINGS
2946
- };
2947
- }, [data, isLoading, schemas, schema, components]);
2948
- const { layout: edit } = React__namespace.useMemo(
2949
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2950
- layout: editLayout,
2951
- query
2952
- }),
2953
- [editLayout, query, runHookWaterfall]
2954
- );
2955
- return {
2956
- error,
2957
- isLoading,
2958
- edit,
2959
- list: listLayout
3284
+ if (dialog) {
3285
+ switch (dialog.type) {
3286
+ case "notification":
3287
+ toggleNotification({
3288
+ title: dialog.title,
3289
+ message: dialog.content,
3290
+ type: dialog.status,
3291
+ timeout: dialog.timeout,
3292
+ onClose: dialog.onClose
3293
+ });
3294
+ break;
3295
+ case "dialog":
3296
+ case "modal": {
3297
+ e.preventDefault();
3298
+ setDialogId(id);
3299
+ }
3300
+ }
3301
+ }
3302
+ };
3303
+ const handleClose = () => {
3304
+ setDialogId(null);
3305
+ if (action.dialog?.type === "modal" && action.dialog?.onClose) {
3306
+ action.dialog.onClose();
3307
+ }
3308
+ };
3309
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3310
+ /* @__PURE__ */ jsxRuntime.jsx(
3311
+ designSystem.Button,
3312
+ {
3313
+ disabled: action.disabled,
3314
+ startIcon: action.icon,
3315
+ variant: action.variant,
3316
+ onClick: handleClick(action),
3317
+ children: action.label
3318
+ }
3319
+ ),
3320
+ action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
3321
+ BulkActionConfirmDialog,
3322
+ {
3323
+ ...action.dialog,
3324
+ variant: action.variant,
3325
+ isOpen: dialogId === action.id,
3326
+ onClose: handleClose
3327
+ }
3328
+ ) : null,
3329
+ action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
3330
+ BulkActionModal,
3331
+ {
3332
+ ...action.dialog,
3333
+ onModalClose: handleClose,
3334
+ isOpen: dialogId === action.id
3335
+ }
3336
+ ) : null
3337
+ ] });
3338
+ };
3339
+ const BulkActionConfirmDialog = ({
3340
+ onClose,
3341
+ onCancel,
3342
+ onConfirm,
3343
+ title,
3344
+ content,
3345
+ confirmButton,
3346
+ isOpen,
3347
+ variant = "secondary"
3348
+ }) => {
3349
+ const { formatMessage } = reactIntl.useIntl();
3350
+ const handleClose = async () => {
3351
+ if (onCancel) {
3352
+ await onCancel();
3353
+ }
3354
+ onClose();
3355
+ };
3356
+ const handleConfirm = async () => {
3357
+ if (onConfirm) {
3358
+ await onConfirm();
3359
+ }
3360
+ onClose();
3361
+ };
3362
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog, { isOpen, title, onClose: handleClose, children: [
3363
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.DialogBody, { icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, {}), children: content }),
3364
+ /* @__PURE__ */ jsxRuntime.jsx(
3365
+ designSystem.DialogFooter,
3366
+ {
3367
+ startAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", children: formatMessage({
3368
+ id: "app.components.Button.cancel",
3369
+ defaultMessage: "Cancel"
3370
+ }) }),
3371
+ endAction: /* @__PURE__ */ jsxRuntime.jsx(
3372
+ designSystem.Button,
3373
+ {
3374
+ onClick: handleConfirm,
3375
+ variant: variant === "danger-light" ? variant : "secondary",
3376
+ startIcon: variant === "danger-light" ? /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}) : /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
3377
+ children: confirmButton ? confirmButton : formatMessage({
3378
+ id: "app.components.Button.confirm",
3379
+ defaultMessage: "Confirm"
3380
+ })
3381
+ }
3382
+ )
3383
+ }
3384
+ )
3385
+ ] });
3386
+ };
3387
+ const BulkActionModal = ({
3388
+ isOpen,
3389
+ title,
3390
+ onClose,
3391
+ content: Content,
3392
+ onModalClose
3393
+ }) => {
3394
+ const id = React__namespace.useId();
3395
+ if (!isOpen) {
3396
+ return null;
3397
+ }
3398
+ const handleClose = () => {
3399
+ if (onClose) {
3400
+ onClose();
3401
+ }
3402
+ onModalClose();
2960
3403
  };
3404
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { borderRadius: "4px", overflow: "hidden", onClose: handleClose, labelledBy: id, children: [
3405
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: "neutral800", tag: "h2", id, children: title }) }),
3406
+ /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose })
3407
+ ] });
2961
3408
  };
2962
- const useDocLayout = () => {
2963
- const { model } = useDoc();
2964
- return useDocumentLayout(model);
3409
+ const DeleteAction = ({ documents, model }) => {
3410
+ const { formatMessage } = reactIntl.useIntl();
3411
+ const { schema: contentType } = useDoc();
3412
+ const selectRow = strapiAdmin.useTable("DeleteAction", (state) => state.selectRow);
3413
+ const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
3414
+ const [{ query }] = strapiAdmin.useQueryParams();
3415
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3416
+ const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
3417
+ const { deleteMany: bulkDeleteAction } = useDocumentActions();
3418
+ const documentIds = documents.map(({ documentId }) => documentId);
3419
+ const handleConfirmBulkDelete = async () => {
3420
+ const res = await bulkDeleteAction({
3421
+ documentIds,
3422
+ model,
3423
+ params
3424
+ });
3425
+ if (!("error" in res)) {
3426
+ selectRow([]);
3427
+ }
3428
+ };
3429
+ if (!hasDeletePermission)
3430
+ return null;
3431
+ return {
3432
+ variant: "danger-light",
3433
+ label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
3434
+ dialog: {
3435
+ type: "dialog",
3436
+ title: formatMessage({
3437
+ id: "app.components.ConfirmDialog.title",
3438
+ defaultMessage: "Confirmation"
3439
+ }),
3440
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3441
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3442
+ id: "popUpWarning.bodyMessage.contentType.delete.all",
3443
+ defaultMessage: "Are you sure you want to delete these entries?"
3444
+ }) }),
3445
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3446
+ {
3447
+ id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
3448
+ defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
3449
+ },
3450
+ {
3451
+ em: Emphasis
3452
+ }
3453
+ ) }) })
3454
+ ] }),
3455
+ onConfirm: handleConfirmBulkDelete
3456
+ }
3457
+ };
2965
3458
  };
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([]);
2985
- }
2986
- panels[currentPanelIndex].push(row);
3459
+ DeleteAction.type = "delete";
3460
+ const UnpublishAction = ({ documents, model }) => {
3461
+ const { formatMessage } = reactIntl.useIntl();
3462
+ const { schema } = useDoc();
3463
+ const selectRow = strapiAdmin.useTable("UnpublishAction", (state) => state.selectRow);
3464
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3465
+ const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
3466
+ const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
3467
+ const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
3468
+ const documentIds = documents.map(({ documentId }) => documentId);
3469
+ const [{ query }] = strapiAdmin.useQueryParams();
3470
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3471
+ const handleConfirmBulkUnpublish = async () => {
3472
+ const data = await bulkUnpublishAction({ documentIds, model, params });
3473
+ if (!("error" in data)) {
3474
+ selectRow([]);
2987
3475
  }
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
- );
3476
+ };
3477
+ const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published");
3478
+ if (!showUnpublishButton)
3479
+ return null;
3017
3480
  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
3481
+ variant: "tertiary",
3482
+ label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
3483
+ dialog: {
3484
+ type: "dialog",
3485
+ title: formatMessage({
3486
+ id: "app.components.ConfirmDialog.title",
3487
+ defaultMessage: "Confirmation"
3488
+ }),
3489
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3490
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3491
+ id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3492
+ defaultMessage: "Are you sure you want to unpublish these entries?"
3493
+ }) }),
3494
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3495
+ {
3496
+ id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
3497
+ defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
3498
+ },
3499
+ {
3500
+ em: Emphasis
3501
+ }
3502
+ ) }) })
3503
+ ] }),
3504
+ confirmButton: formatMessage({
3505
+ id: "app.utils.unpublish",
3506
+ defaultMessage: "Unpublish"
3507
+ }),
3508
+ onConfirm: handleConfirmBulkUnpublish
3029
3509
  }
3030
3510
  };
3031
3511
  };
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;
3512
+ UnpublishAction.type = "unpublish";
3513
+ const Emphasis = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
3514
+ const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
3515
+ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3516
+ const { formatMessage } = reactIntl.useIntl();
3517
+ const getDefaultErrorMessage = (reason) => {
3518
+ switch (reason) {
3519
+ case "relation":
3520
+ return "Duplicating the relation could remove it from the original entry.";
3521
+ case "unique":
3522
+ return "Identical values in a unique field are not allowed";
3523
+ default:
3524
+ return reason;
3525
+ }
3526
+ };
3527
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3528
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: formatMessage({
3529
+ id: getTranslation("containers.list.autoCloneModal.title"),
3530
+ defaultMessage: "This entry can't be duplicated directly."
3531
+ }) }),
3532
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatMessage({
3533
+ id: getTranslation("containers.list.autoCloneModal.description"),
3534
+ defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
3535
+ }) }) }),
3536
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxRuntime.jsxs(
3537
+ designSystem.Flex,
3538
+ {
3539
+ direction: "column",
3540
+ gap: 2,
3541
+ alignItems: "flex-start",
3542
+ borderColor: "neutral200",
3543
+ hasRadius: true,
3544
+ padding: 6,
3545
+ children: [
3546
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", tag: "li", children: [
3547
+ pathSegment,
3548
+ index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
3549
+ Icons.ChevronRight,
3550
+ {
3551
+ fill: "neutral500",
3552
+ height: "0.8rem",
3553
+ width: "0.8rem",
3554
+ style: { margin: "0 0.8rem" }
3555
+ }
3556
+ )
3557
+ ] }, index2)) }),
3558
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
3559
+ id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
3560
+ defaultMessage: getDefaultErrorMessage(reason)
3561
+ }) })
3562
+ ]
3563
+ },
3564
+ fieldPath.join()
3565
+ )) })
3566
+ ] });
3567
+ };
3568
+ const TableActions = ({ document }) => {
3569
+ const { formatMessage } = reactIntl.useIntl();
3570
+ const { model, collectionType } = useDoc();
3571
+ const plugins = strapiAdmin.useStrapiApp("TableActions", (state) => state.plugins);
3572
+ const props = {
3573
+ activeTab: null,
3574
+ model,
3575
+ documentId: document.documentId,
3576
+ collectionType,
3577
+ document
3578
+ };
3579
+ return /* @__PURE__ */ jsxRuntime.jsx(
3580
+ strapiAdmin.DescriptionComponentRenderer,
3581
+ {
3582
+ props,
3583
+ descriptions: plugins["content-manager"].apis.getDocumentActions(),
3584
+ children: (actions2) => {
3585
+ const tableRowActions = actions2.filter((action) => {
3586
+ const positions = Array.isArray(action.position) ? action.position : [action.position];
3587
+ return positions.includes("table-row");
3588
+ });
3589
+ return /* @__PURE__ */ jsxRuntime.jsx(
3590
+ DocumentActionsMenu,
3591
+ {
3592
+ actions: tableRowActions,
3593
+ label: formatMessage({
3594
+ id: "content-manager.containers.list.table.row-actions",
3595
+ defaultMessage: "Row action"
3596
+ }),
3597
+ variant: "ghost"
3598
+ }
3599
+ );
3038
3600
  }
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)
3601
+ }
3060
3602
  );
3061
3603
  };
3062
- const formatListLayout = (data, {
3063
- schemas,
3064
- schema,
3065
- components
3066
- }) => {
3067
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
3068
- (acc, [attribute, metadata]) => {
3069
- return {
3070
- ...acc,
3071
- [attribute]: metadata.list
3072
- };
3073
- },
3074
- {}
3075
- );
3076
- const listAttributes = convertListLayoutToFieldLayouts(
3077
- data.contentType.layouts.list,
3078
- schema?.attributes,
3079
- listMetadatas,
3080
- { configurations: data.components, schemas: components },
3081
- schemas
3082
- );
3604
+ const EditAction = ({ documentId }) => {
3605
+ const navigate = reactRouterDom.useNavigate();
3606
+ const { formatMessage } = reactIntl.useIntl();
3607
+ const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
3608
+ const { toggleNotification } = strapiAdmin.useNotification();
3609
+ const [{ query }] = strapiAdmin.useQueryParams();
3610
+ return {
3611
+ disabled: !canRead,
3612
+ icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil, {}),
3613
+ label: formatMessage({
3614
+ id: "content-manager.actions.edit.label",
3615
+ defaultMessage: "Edit"
3616
+ }),
3617
+ position: "table-row",
3618
+ onClick: async () => {
3619
+ if (!documentId) {
3620
+ console.error(
3621
+ "You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
3622
+ );
3623
+ toggleNotification({
3624
+ message: formatMessage({
3625
+ id: "content-manager.actions.edit.error",
3626
+ defaultMessage: "An error occurred while trying to edit the document."
3627
+ }),
3628
+ type: "danger"
3629
+ });
3630
+ return;
3631
+ }
3632
+ navigate({
3633
+ pathname: documentId,
3634
+ search: qs.stringify({
3635
+ plugins: query.plugins
3636
+ })
3637
+ });
3638
+ }
3639
+ };
3640
+ };
3641
+ EditAction.type = "edit";
3642
+ const StyledPencil = styledComponents.styled(Icons.Pencil)`
3643
+ path {
3644
+ fill: currentColor;
3645
+ }
3646
+ `;
3647
+ const CloneAction = ({ model, documentId }) => {
3648
+ const navigate = reactRouterDom.useNavigate();
3649
+ const { formatMessage } = reactIntl.useIntl();
3650
+ const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
3651
+ const { toggleNotification } = strapiAdmin.useNotification();
3652
+ const { autoClone } = useDocumentActions();
3653
+ const [prohibitedFields, setProhibitedFields] = React__namespace.useState([]);
3083
3654
  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
3655
+ disabled: !canCreate,
3656
+ icon: /* @__PURE__ */ jsxRuntime.jsx(StyledDuplicate, {}),
3657
+ label: formatMessage({
3658
+ id: "content-manager.actions.clone.label",
3659
+ defaultMessage: "Duplicate"
3660
+ }),
3661
+ position: "table-row",
3662
+ onClick: async () => {
3663
+ if (!documentId) {
3664
+ console.error(
3665
+ "You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
3666
+ );
3667
+ toggleNotification({
3668
+ message: formatMessage({
3669
+ id: "content-manager.actions.clone.error",
3670
+ defaultMessage: "An error occurred while trying to clone the document."
3671
+ }),
3672
+ type: "danger"
3673
+ });
3674
+ return;
3675
+ }
3676
+ const res = await autoClone({ model, sourceId: documentId });
3677
+ if ("data" in res) {
3678
+ navigate(res.data.documentId);
3679
+ return true;
3680
+ }
3681
+ if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
3682
+ const prohibitedFields2 = res.error.details.prohibitedFields;
3683
+ setProhibitedFields(prohibitedFields2);
3684
+ }
3685
+ },
3686
+ dialog: {
3687
+ type: "modal",
3688
+ title: formatMessage({
3689
+ id: "content-manager.containers.list.autoCloneModal.header",
3690
+ defaultMessage: "Duplicate"
3691
+ }),
3692
+ content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3693
+ footer: ({ onClose }) => {
3694
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3695
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3696
+ id: "cancel",
3697
+ defaultMessage: "Cancel"
3698
+ }) }),
3699
+ /* @__PURE__ */ jsxRuntime.jsx(
3700
+ designSystem.LinkButton,
3701
+ {
3702
+ tag: reactRouterDom.NavLink,
3703
+ to: {
3704
+ pathname: `clone/${documentId}`
3705
+ },
3706
+ children: formatMessage({
3707
+ id: "content-manager.containers.list.autoCloneModal.create",
3708
+ defaultMessage: "Create"
3709
+ })
3710
+ }
3711
+ )
3712
+ ] });
3713
+ }
3091
3714
  }
3092
3715
  };
3093
3716
  };
3094
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
3095
- return columns.map((name) => {
3096
- const attribute = attributes[name];
3097
- if (!attribute) {
3098
- return null;
3717
+ CloneAction.type = "clone";
3718
+ const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
3719
+ path {
3720
+ fill: currentColor;
3721
+ }
3722
+ `;
3723
+ const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
3724
+ class ContentManagerPlugin {
3725
+ /**
3726
+ * The following properties are the stored ones provided by any plugins registering with
3727
+ * the content-manager. The function calls however, need to be called at runtime in the
3728
+ * application, so instead we collate them and run them later with the complete list incl.
3729
+ * ones already registered & the context of the view.
3730
+ */
3731
+ bulkActions = [...DEFAULT_BULK_ACTIONS];
3732
+ documentActions = [
3733
+ ...DEFAULT_ACTIONS,
3734
+ ...DEFAULT_TABLE_ROW_ACTIONS,
3735
+ ...DEFAULT_HEADER_ACTIONS,
3736
+ HistoryAction
3737
+ ];
3738
+ editViewSidePanels = [ActionsPanel];
3739
+ headerActions = [];
3740
+ constructor() {
3741
+ }
3742
+ addEditViewSidePanel(panels) {
3743
+ if (Array.isArray(panels)) {
3744
+ this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
3745
+ } else if (typeof panels === "function") {
3746
+ this.editViewSidePanels = panels(this.editViewSidePanels);
3747
+ } else {
3748
+ throw new Error(
3749
+ `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
3750
+ panels
3751
+ )}`
3752
+ );
3099
3753
  }
3100
- const metadata = metadatas[name];
3101
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3754
+ }
3755
+ addDocumentAction(actions2) {
3756
+ if (Array.isArray(actions2)) {
3757
+ this.documentActions = [...this.documentActions, ...actions2];
3758
+ } else if (typeof actions2 === "function") {
3759
+ this.documentActions = actions2(this.documentActions);
3760
+ } else {
3761
+ throw new Error(
3762
+ `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
3763
+ actions2
3764
+ )}`
3765
+ );
3766
+ }
3767
+ }
3768
+ addDocumentHeaderAction(actions2) {
3769
+ if (Array.isArray(actions2)) {
3770
+ this.headerActions = [...this.headerActions, ...actions2];
3771
+ } else if (typeof actions2 === "function") {
3772
+ this.headerActions = actions2(this.headerActions);
3773
+ } else {
3774
+ throw new Error(
3775
+ `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
3776
+ actions2
3777
+ )}`
3778
+ );
3779
+ }
3780
+ }
3781
+ addBulkAction(actions2) {
3782
+ if (Array.isArray(actions2)) {
3783
+ this.bulkActions = [...this.bulkActions, ...actions2];
3784
+ } else if (typeof actions2 === "function") {
3785
+ this.bulkActions = actions2(this.bulkActions);
3786
+ } else {
3787
+ throw new Error(
3788
+ `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3789
+ actions2
3790
+ )}`
3791
+ );
3792
+ }
3793
+ }
3794
+ get config() {
3102
3795
  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
3796
+ id: PLUGIN_ID,
3797
+ name: "Content Manager",
3798
+ injectionZones: INJECTION_ZONES,
3799
+ apis: {
3800
+ addBulkAction: this.addBulkAction.bind(this),
3801
+ addDocumentAction: this.addDocumentAction.bind(this),
3802
+ addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3803
+ addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3804
+ getBulkActions: () => this.bulkActions,
3805
+ getDocumentActions: () => this.documentActions,
3806
+ getEditViewSidePanels: () => this.editViewSidePanels,
3807
+ getHeaderActions: () => this.headerActions
3808
+ }
3112
3809
  };
3113
- }).filter((field) => field !== null);
3810
+ }
3811
+ }
3812
+ const getPrintableType = (value) => {
3813
+ const nativeType = typeof value;
3814
+ if (nativeType === "object") {
3815
+ if (value === null)
3816
+ return "null";
3817
+ if (Array.isArray(value))
3818
+ return "array";
3819
+ if (value instanceof Object && value.constructor.name !== "Object") {
3820
+ return value.constructor.name;
3821
+ }
3822
+ }
3823
+ return nativeType;
3824
+ };
3825
+ const initialState = {
3826
+ collectionTypeLinks: [],
3827
+ components: [],
3828
+ fieldSizes: {},
3829
+ models: [],
3830
+ singleTypeLinks: [],
3831
+ isLoading: true
3114
3832
  };
3833
+ const appSlice = toolkit.createSlice({
3834
+ name: "app",
3835
+ initialState,
3836
+ reducers: {
3837
+ setInitialData(state, action) {
3838
+ const {
3839
+ authorizedCollectionTypeLinks,
3840
+ authorizedSingleTypeLinks,
3841
+ components,
3842
+ contentTypeSchemas,
3843
+ fieldSizes
3844
+ } = action.payload;
3845
+ state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
3846
+ ({ isDisplayed }) => isDisplayed
3847
+ );
3848
+ state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
3849
+ state.components = components;
3850
+ state.models = contentTypeSchemas;
3851
+ state.fieldSizes = fieldSizes;
3852
+ state.isLoading = false;
3853
+ }
3854
+ }
3855
+ });
3856
+ const { actions, reducer: reducer$1 } = appSlice;
3857
+ const { setInitialData } = actions;
3858
+ const reducer = toolkit.combineReducers({
3859
+ app: reducer$1
3860
+ });
3115
3861
  const index = {
3116
3862
  register(app) {
3117
3863
  const cm = new ContentManagerPlugin();
3118
3864
  app.addReducers({
3119
- [contentManagerApi.reducerPath]: contentManagerApi.reducer,
3120
3865
  [PLUGIN_ID]: reducer
3121
3866
  });
3122
- app.addMiddlewares([() => contentManagerApi.middleware]);
3123
3867
  app.addMenuLink({
3124
3868
  to: PLUGIN_ID,
3125
3869
  icon: Icons.Feather,
@@ -3128,14 +3872,15 @@ const index = {
3128
3872
  defaultMessage: "Content Manager"
3129
3873
  },
3130
3874
  permissions: [],
3131
- Component: () => Promise.resolve().then(() => require("./layout-BqtLA6Lb.js")).then((mod) => ({ default: mod.Layout }))
3875
+ Component: () => Promise.resolve().then(() => require("./layout-pZc2Q3bK.js")).then((mod) => ({ default: mod.Layout })),
3876
+ position: 1
3132
3877
  });
3133
3878
  app.registerPlugin(cm.config);
3134
3879
  },
3135
3880
  async registerTrads({ locales }) {
3136
3881
  const importedTrads = await Promise.all(
3137
3882
  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 }) => {
3883
+ 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-BN1bvFK7.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
3884
  return {
3140
3885
  data: prefixPluginTranslations(data, PLUGIN_ID),
3141
3886
  locale
@@ -3152,6 +3897,7 @@ const index = {
3152
3897
  }
3153
3898
  };
3154
3899
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3900
+ exports.BulkActionsRenderer = BulkActionsRenderer;
3155
3901
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3156
3902
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3157
3903
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3192,4 +3938,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3192
3938
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3193
3939
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3194
3940
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3195
- //# sourceMappingURL=index-DNa1J4HE.js.map
3941
+ //# sourceMappingURL=index-BRHpg0az.js.map