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

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 (170) 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-2iOVVhqV.js → ComponentConfigurationPage-BvHtG7uH.js} +3 -3
  6. package/dist/_chunks/{ComponentConfigurationPage-2iOVVhqV.js.map → ComponentConfigurationPage-BvHtG7uH.js.map} +1 -1
  7. package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs → ComponentConfigurationPage-DHNM3YBz.mjs} +3 -3
  8. package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs.map → ComponentConfigurationPage-DHNM3YBz.mjs.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-Cp6HAEzN.mjs} +3 -3
  14. package/dist/_chunks/{EditConfigurationPage-BoBb-DLH.mjs.map → EditConfigurationPage-Cp6HAEzN.mjs.map} +1 -1
  15. package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js → EditConfigurationPage-DOmfCEMo.js} +3 -3
  16. package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js.map → EditConfigurationPage-DOmfCEMo.js.map} +1 -1
  17. package/dist/_chunks/{EditViewPage-KRG56aCq.js → EditViewPage-BqNpC6hO.js} +46 -48
  18. package/dist/_chunks/EditViewPage-BqNpC6hO.js.map +1 -0
  19. package/dist/_chunks/{EditViewPage-aUnqL-63.mjs → EditViewPage-BtkEx339.mjs} +47 -47
  20. package/dist/_chunks/EditViewPage-BtkEx339.mjs.map +1 -0
  21. package/dist/_chunks/{Field-kVFO4ZKB.mjs → Field-R5NbffTB.mjs} +854 -707
  22. package/dist/_chunks/Field-R5NbffTB.mjs.map +1 -0
  23. package/dist/_chunks/{Field-kq1c2TF1.js → Field-lsPFnAmH.js} +906 -760
  24. package/dist/_chunks/Field-lsPFnAmH.js.map +1 -0
  25. package/dist/_chunks/{Form-Jgh5hGTu.mjs → Form-BHmXSfyy.mjs} +39 -37
  26. package/dist/_chunks/Form-BHmXSfyy.mjs.map +1 -0
  27. package/dist/_chunks/{Form-CQ67ZifP.js → Form-CcGboku8.js} +39 -38
  28. package/dist/_chunks/Form-CcGboku8.js.map +1 -0
  29. package/dist/_chunks/{History-BLEnudTX.js → History-Bsud8jwh.js} +138 -51
  30. package/dist/_chunks/History-Bsud8jwh.js.map +1 -0
  31. package/dist/_chunks/{History-DKhZAPcK.mjs → History-ByUPL3T3.mjs} +137 -49
  32. package/dist/_chunks/History-ByUPL3T3.mjs.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-nrXcxNYi.mjs → ListConfigurationPage-Bm5HACXf.mjs} +49 -51
  34. package/dist/_chunks/ListConfigurationPage-Bm5HACXf.mjs.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-Zso_LUjn.js → ListConfigurationPage-DiT463qx.js} +53 -56
  36. package/dist/_chunks/ListConfigurationPage-DiT463qx.js.map +1 -0
  37. package/dist/_chunks/{ListViewPage-DsaOakWQ.js → ListViewPage-CsrC9L_d.js} +92 -108
  38. package/dist/_chunks/ListViewPage-CsrC9L_d.js.map +1 -0
  39. package/dist/_chunks/{ListViewPage-ChhYmA-L.mjs → ListViewPage-JSyNAAYu.mjs} +87 -103
  40. package/dist/_chunks/ListViewPage-JSyNAAYu.mjs.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-DPCuS9Y1.js → NoContentTypePage-Bsvng4II.js} +3 -3
  42. package/dist/_chunks/NoContentTypePage-Bsvng4II.js.map +1 -0
  43. package/dist/_chunks/{NoContentTypePage-BrdFcN33.mjs → NoContentTypePage-CsrQUpBE.mjs} +3 -3
  44. package/dist/_chunks/NoContentTypePage-CsrQUpBE.mjs.map +1 -0
  45. package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js → NoPermissionsPage-CdHNJtEf.js} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js.map → NoPermissionsPage-CdHNJtEf.js.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs → NoPermissionsPage-DNmf_pj0.mjs} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs.map → NoPermissionsPage-DNmf_pj0.mjs.map} +1 -1
  49. package/dist/_chunks/{Relations-CY8Isqdu.js → Relations-CghaPv2D.js} +70 -61
  50. package/dist/_chunks/Relations-CghaPv2D.js.map +1 -0
  51. package/dist/_chunks/{Relations-DjFiYd7-.mjs → Relations-u8-37jK0.mjs} +66 -56
  52. package/dist/_chunks/Relations-u8-37jK0.mjs.map +1 -0
  53. package/dist/_chunks/{en-MBPul9Su.mjs → en-Ux26r5pl.mjs} +7 -1
  54. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-Ux26r5pl.mjs.map} +1 -1
  55. package/dist/_chunks/{en-C-V1_90f.js → en-fbKQxLGn.js} +7 -1
  56. package/dist/_chunks/{en-C-V1_90f.js.map → en-fbKQxLGn.js.map} +1 -1
  57. package/dist/_chunks/{index-DNa1J4HE.js → index-BOZx6IMg.js} +1481 -864
  58. package/dist/_chunks/index-BOZx6IMg.js.map +1 -0
  59. package/dist/_chunks/{index-CAc9yTnx.mjs → index-CaE6NG4a.mjs} +1450 -832
  60. package/dist/_chunks/index-CaE6NG4a.mjs.map +1 -0
  61. package/dist/_chunks/{layout-CXsHbc3E.mjs → layout-Bx7svTbY.mjs} +28 -23
  62. package/dist/_chunks/layout-Bx7svTbY.mjs.map +1 -0
  63. package/dist/_chunks/{layout-BqtLA6Lb.js → layout-Ciz224q5.js} +29 -26
  64. package/dist/_chunks/layout-Ciz224q5.js.map +1 -0
  65. package/dist/_chunks/{relations-BHY_KDJ_.js → relations-CP8sB2YZ.js} +2 -2
  66. package/dist/_chunks/{relations-BHY_KDJ_.js.map → relations-CP8sB2YZ.js.map} +1 -1
  67. package/dist/_chunks/{relations-mMFEcZRq.mjs → relations-Cxc1cEv3.mjs} +2 -2
  68. package/dist/_chunks/{relations-mMFEcZRq.mjs.map → relations-Cxc1cEv3.mjs.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/components/VersionInputRenderer.d.ts +1 -1
  82. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  83. package/dist/admin/src/hooks/useDocument.d.ts +5 -8
  84. package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
  85. package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
  86. package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
  87. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
  88. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +10 -4
  89. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
  90. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  91. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
  92. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  93. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  94. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +10 -18
  95. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  96. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  97. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  98. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +59 -52
  99. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  100. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  101. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  102. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  103. package/dist/admin/src/services/api.d.ts +2 -3
  104. package/dist/admin/src/services/components.d.ts +2 -2
  105. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  106. package/dist/admin/src/services/documents.d.ts +29 -17
  107. package/dist/admin/src/services/init.d.ts +2 -2
  108. package/dist/admin/src/services/relations.d.ts +3 -3
  109. package/dist/admin/src/services/uid.d.ts +3 -3
  110. package/dist/admin/src/utils/api.d.ts +4 -18
  111. package/dist/admin/src/utils/validation.d.ts +1 -6
  112. package/dist/server/index.js +293 -203
  113. package/dist/server/index.js.map +1 -1
  114. package/dist/server/index.mjs +295 -205
  115. package/dist/server/index.mjs.map +1 -1
  116. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  117. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  118. package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
  119. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  120. package/dist/server/src/controllers/validation/dimensions.d.ts +9 -0
  121. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  122. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  123. package/dist/server/src/history/services/history.d.ts.map +1 -1
  124. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  125. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  126. package/dist/server/src/index.d.ts +17 -33
  127. package/dist/server/src/index.d.ts.map +1 -1
  128. package/dist/server/src/services/document-manager.d.ts +11 -6
  129. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  130. package/dist/server/src/services/document-metadata.d.ts +8 -29
  131. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  132. package/dist/server/src/services/index.d.ts +17 -33
  133. package/dist/server/src/services/index.d.ts.map +1 -1
  134. package/dist/server/src/services/utils/populate.d.ts +8 -1
  135. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  136. package/dist/shared/contracts/collection-types.d.ts +14 -6
  137. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  138. package/dist/shared/contracts/relations.d.ts +2 -2
  139. package/dist/shared/contracts/relations.d.ts.map +1 -1
  140. package/package.json +13 -14
  141. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  142. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  143. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  144. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  145. package/dist/_chunks/EditViewPage-KRG56aCq.js.map +0 -1
  146. package/dist/_chunks/EditViewPage-aUnqL-63.mjs.map +0 -1
  147. package/dist/_chunks/Field-kVFO4ZKB.mjs.map +0 -1
  148. package/dist/_chunks/Field-kq1c2TF1.js.map +0 -1
  149. package/dist/_chunks/Form-CQ67ZifP.js.map +0 -1
  150. package/dist/_chunks/Form-Jgh5hGTu.mjs.map +0 -1
  151. package/dist/_chunks/History-BLEnudTX.js.map +0 -1
  152. package/dist/_chunks/History-DKhZAPcK.mjs.map +0 -1
  153. package/dist/_chunks/ListConfigurationPage-Zso_LUjn.js.map +0 -1
  154. package/dist/_chunks/ListConfigurationPage-nrXcxNYi.mjs.map +0 -1
  155. package/dist/_chunks/ListViewPage-ChhYmA-L.mjs.map +0 -1
  156. package/dist/_chunks/ListViewPage-DsaOakWQ.js.map +0 -1
  157. package/dist/_chunks/NoContentTypePage-BrdFcN33.mjs.map +0 -1
  158. package/dist/_chunks/NoContentTypePage-DPCuS9Y1.js.map +0 -1
  159. package/dist/_chunks/Relations-CY8Isqdu.js.map +0 -1
  160. package/dist/_chunks/Relations-DjFiYd7-.mjs.map +0 -1
  161. package/dist/_chunks/index-CAc9yTnx.mjs.map +0 -1
  162. package/dist/_chunks/index-DNa1J4HE.js.map +0 -1
  163. package/dist/_chunks/layout-BqtLA6Lb.js.map +0 -1
  164. package/dist/_chunks/layout-CXsHbc3E.mjs.map +0 -1
  165. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  166. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  167. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  168. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  169. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  170. package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
@@ -7,10 +7,8 @@ const reactIntl = require("react-intl");
7
7
  const reactRouterDom = require("react-router-dom");
8
8
  const React = require("react");
9
9
  const designSystem = require("@strapi/design-system");
10
- const styled = require("styled-components");
10
+ const styledComponents = require("styled-components");
11
11
  const yup = require("yup");
12
- const react = require("@reduxjs/toolkit/query/react");
13
- const axios = require("axios");
14
12
  const pipe = require("lodash/fp/pipe");
15
13
  const dateFns = require("date-fns");
16
14
  const toolkit = require("@reduxjs/toolkit");
@@ -34,7 +32,6 @@ function _interopNamespace(e) {
34
32
  return Object.freeze(n);
35
33
  }
36
34
  const React__namespace = /* @__PURE__ */ _interopNamespace(React);
37
- const styled__default = /* @__PURE__ */ _interopDefault(styled);
38
35
  const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
39
36
  const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
40
37
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
@@ -179,9 +176,8 @@ const DocumentRBAC = ({ children, permissions }) => {
179
176
  const name = removeNumericalStrings(fieldName.split("."));
180
177
  const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
181
178
  if (fieldType === "component") {
182
- const componentOrDynamicZoneFields = componentFieldNames.map((field) => field.split("."));
183
- return componentOrDynamicZoneFields.some((field) => {
184
- return field.includes(fieldName);
179
+ return componentFieldNames.some((field) => {
180
+ return field.includes(name.join("."));
185
181
  });
186
182
  }
187
183
  if (name.length > 1) {
@@ -211,78 +207,8 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
211
207
  (field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
212
208
  );
213
209
  const removeNumericalStrings = (arr) => arr.filter((item) => isNaN(Number(item)));
214
- const buildValidParams = (query) => {
215
- if (!query)
216
- return query;
217
- const { plugins: _, ...validQueryParams } = {
218
- ...query,
219
- ...Object.values(query?.plugins ?? {}).reduce(
220
- (acc, current) => Object.assign(acc, current),
221
- {}
222
- )
223
- };
224
- if ("_q" in validQueryParams) {
225
- validQueryParams._q = encodeURIComponent(validQueryParams._q);
226
- }
227
- return validQueryParams;
228
- };
229
- const axiosBaseQuery = () => async (query, { signal }) => {
230
- try {
231
- const { get, post, del, put } = strapiAdmin.getFetchClient();
232
- if (typeof query === "string") {
233
- const result = await get(query, { signal });
234
- return { data: result.data };
235
- } else {
236
- const { url, method = "GET", data, config } = query;
237
- if (method === "POST") {
238
- const result2 = await post(url, data, { ...config, signal });
239
- return { data: result2.data };
240
- }
241
- if (method === "DELETE") {
242
- const result2 = await del(url, { ...config, signal });
243
- return { data: result2.data };
244
- }
245
- if (method === "PUT") {
246
- const result2 = await put(url, data, { ...config, signal });
247
- return { data: result2.data };
248
- }
249
- const result = await get(url, { ...config, signal });
250
- return { data: result.data };
251
- }
252
- } catch (err) {
253
- if (axios.isAxiosError(err)) {
254
- if (typeof err.response?.data === "object" && err.response?.data !== null && "error" in err.response?.data) {
255
- return { data: void 0, error: err.response?.data.error };
256
- } else {
257
- return {
258
- data: void 0,
259
- error: {
260
- name: "UnknownError",
261
- message: "There was an unknown error response from the API",
262
- details: err.response?.data,
263
- status: err.response?.status
264
- }
265
- };
266
- }
267
- }
268
- const error = err;
269
- return {
270
- data: void 0,
271
- error: {
272
- name: error.name,
273
- message: error.message,
274
- stack: error.stack
275
- }
276
- };
277
- }
278
- };
279
- const isBaseQueryError = (error) => {
280
- return error.name !== void 0;
281
- };
282
- const contentManagerApi = react.createApi({
283
- reducerPath: "contentManagerApi",
284
- baseQuery: axiosBaseQuery(),
285
- tagTypes: [
210
+ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
211
+ addTagTypes: [
286
212
  "ComponentConfiguration",
287
213
  "ContentTypesConfiguration",
288
214
  "ContentTypeSettings",
@@ -290,10 +216,10 @@ const contentManagerApi = react.createApi({
290
216
  "InitialData",
291
217
  "HistoryVersion",
292
218
  "Relations"
293
- ],
294
- endpoints: () => ({})
219
+ ]
295
220
  });
296
221
  const documentApi = contentManagerApi.injectEndpoints({
222
+ overrideExisting: true,
297
223
  endpoints: (builder) => ({
298
224
  autoCloneDocument: builder.mutation({
299
225
  query: ({ model, sourceId, query }) => ({
@@ -347,12 +273,15 @@ const documentApi = contentManagerApi.injectEndpoints({
347
273
  ]
348
274
  }),
349
275
  deleteManyDocuments: builder.mutation({
350
- query: ({ model, ...body }) => ({
276
+ query: ({ model, params, ...body }) => ({
351
277
  url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
352
278
  method: "POST",
353
- data: body
279
+ data: body,
280
+ config: {
281
+ params
282
+ }
354
283
  }),
355
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
284
+ invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
356
285
  }),
357
286
  discardDocument: builder.mutation({
358
287
  query: ({ collectionType, model, documentId, params }) => ({
@@ -463,10 +392,13 @@ const documentApi = contentManagerApi.injectEndpoints({
463
392
  }
464
393
  }),
465
394
  publishManyDocuments: builder.mutation({
466
- query: ({ model, ...body }) => ({
395
+ query: ({ model, params, ...body }) => ({
467
396
  url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
468
397
  method: "POST",
469
- data: body
398
+ data: body,
399
+ config: {
400
+ params
401
+ }
470
402
  }),
471
403
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
472
404
  }),
@@ -508,10 +440,13 @@ const documentApi = contentManagerApi.injectEndpoints({
508
440
  }
509
441
  }),
510
442
  unpublishManyDocuments: builder.mutation({
511
- query: ({ model, ...body }) => ({
443
+ query: ({ model, params, ...body }) => ({
512
444
  url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
513
445
  method: "POST",
514
- data: body
446
+ data: body,
447
+ config: {
448
+ params
449
+ }
515
450
  }),
516
451
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
517
452
  })
@@ -535,6 +470,24 @@ const {
535
470
  useUnpublishDocumentMutation,
536
471
  useUnpublishManyDocumentsMutation
537
472
  } = documentApi;
473
+ const buildValidParams = (query) => {
474
+ if (!query)
475
+ return query;
476
+ const { plugins: _, ...validQueryParams } = {
477
+ ...query,
478
+ ...Object.values(query?.plugins ?? {}).reduce(
479
+ (acc, current) => Object.assign(acc, current),
480
+ {}
481
+ )
482
+ };
483
+ if ("_q" in validQueryParams) {
484
+ validQueryParams._q = encodeURIComponent(validQueryParams._q);
485
+ }
486
+ return validQueryParams;
487
+ };
488
+ const isBaseQueryError = (error) => {
489
+ return error.name !== void 0;
490
+ };
538
491
  const createYupSchema = (attributes = {}, components = {}) => {
539
492
  const createModelSchema = (attributes2) => yup__namespace.object().shape(
540
493
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
@@ -574,10 +527,14 @@ const createYupSchema = (attributes = {}, components = {}) => {
574
527
  yup__namespace.array().of(
575
528
  yup__namespace.lazy(
576
529
  (data) => {
577
- const { attributes: attributes3 } = components[data.__component];
578
- return yup__namespace.object().shape({
530
+ const attributes3 = components?.[data?.__component]?.attributes;
531
+ const validation = yup__namespace.object().shape({
579
532
  __component: yup__namespace.string().required().oneOf(Object.keys(components))
580
- }).nullable(false).concat(createModelSchema(attributes3));
533
+ }).nullable(false);
534
+ if (!attributes3) {
535
+ return validation;
536
+ }
537
+ return validation.concat(createModelSchema(attributes3));
581
538
  }
582
539
  )
583
540
  )
@@ -587,11 +544,25 @@ const createYupSchema = (attributes = {}, components = {}) => {
587
544
  return {
588
545
  ...acc,
589
546
  [name]: transformSchema(
590
- yup__namespace.array().of(
591
- yup__namespace.object().shape({
592
- id: yup__namespace.string().required()
593
- })
594
- )
547
+ yup__namespace.lazy((value) => {
548
+ if (!value) {
549
+ return yup__namespace.mixed().nullable(true);
550
+ } else if (Array.isArray(value)) {
551
+ return yup__namespace.array().of(
552
+ yup__namespace.object().shape({
553
+ id: yup__namespace.string().required()
554
+ })
555
+ );
556
+ } else if (typeof value === "object") {
557
+ return yup__namespace.object();
558
+ } else {
559
+ return yup__namespace.mixed().test(
560
+ "type-error",
561
+ "Relation values must be either null, an array of objects with {id} or an object.",
562
+ () => false
563
+ );
564
+ }
565
+ })
595
566
  )
596
567
  };
597
568
  default:
@@ -650,13 +621,18 @@ const createAttributeSchema = (attribute) => {
650
621
  }
651
622
  };
652
623
  const addRequiredValidation = (attribute) => (schema) => {
653
- if (attribute.required) {
624
+ if (attribute.required && attribute.type !== "relation") {
654
625
  return schema.required({
655
626
  id: strapiAdmin.translatedErrors.required.id,
656
627
  defaultMessage: "This field is required."
657
628
  });
658
629
  }
659
- return schema.nullable();
630
+ return schema?.nullable ? schema.nullable() : (
631
+ // In some cases '.nullable' will not be available on the schema.
632
+ // e.g. when the schema has been built using yup.lazy (e.g. for relations).
633
+ // In these cases we should just return the schema as it is.
634
+ schema
635
+ );
660
636
  };
661
637
  const addMinLengthValidation = (attribute) => (schema) => {
662
638
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
@@ -728,24 +704,6 @@ const addRegexValidation = (attribute) => (schema) => {
728
704
  }
729
705
  return schema;
730
706
  };
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
707
  const initApi = contentManagerApi.injectEndpoints({
750
708
  endpoints: (builder) => ({
751
709
  getInitialData: builder.query({
@@ -759,27 +717,20 @@ const { useGetInitialDataQuery } = initApi;
759
717
  const useContentTypeSchema = (model) => {
760
718
  const { toggleNotification } = strapiAdmin.useNotification();
761
719
  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
- });
720
+ const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
721
+ const { components, contentType, contentTypes } = React__namespace.useMemo(() => {
722
+ const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
723
+ const componentsByKey = data?.components.reduce((acc, component) => {
724
+ acc[component.uid] = component;
725
+ return acc;
726
+ }, {});
727
+ const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
728
+ return {
729
+ components: Object.keys(components2).length === 0 ? void 0 : components2,
730
+ contentType: contentType2,
731
+ contentTypes: data?.contentTypes ?? []
732
+ };
733
+ }, [model, data]);
783
734
  React__namespace.useEffect(() => {
784
735
  if (error) {
785
736
  toggleNotification({
@@ -834,7 +785,10 @@ const useDocument = (args, opts) => {
834
785
  isLoading: isLoadingDocument,
835
786
  isFetching: isFetchingDocument,
836
787
  error
837
- } = useGetDocumentQuery(args, opts);
788
+ } = useGetDocumentQuery(args, {
789
+ ...opts,
790
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
791
+ });
838
792
  const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
839
793
  React__namespace.useEffect(() => {
840
794
  if (error) {
@@ -862,7 +816,7 @@ const useDocument = (args, opts) => {
862
816
  return null;
863
817
  } catch (error2) {
864
818
  if (error2 instanceof yup.ValidationError) {
865
- return getInnerErrors(error2);
819
+ return strapiAdmin.getYupValidationErrors(error2);
866
820
  }
867
821
  throw error2;
868
822
  }
@@ -958,14 +912,53 @@ const useDocumentActions = () => {
958
912
  },
959
913
  [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
960
914
  );
915
+ const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
916
+ const deleteMany = React__namespace.useCallback(
917
+ async ({ model, documentIds, params }) => {
918
+ try {
919
+ trackUsage("willBulkDeleteEntries");
920
+ const res = await deleteManyDocuments({
921
+ model,
922
+ documentIds,
923
+ params
924
+ });
925
+ if ("error" in res) {
926
+ toggleNotification({
927
+ type: "danger",
928
+ message: formatAPIError(res.error)
929
+ });
930
+ return { error: res.error };
931
+ }
932
+ toggleNotification({
933
+ type: "success",
934
+ title: formatMessage({
935
+ id: getTranslation("success.records.delete"),
936
+ defaultMessage: "Successfully deleted."
937
+ }),
938
+ message: ""
939
+ });
940
+ trackUsage("didBulkDeleteEntries");
941
+ return res.data;
942
+ } catch (err) {
943
+ toggleNotification({
944
+ type: "danger",
945
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
946
+ });
947
+ trackUsage("didNotBulkDeleteEntries");
948
+ throw err;
949
+ }
950
+ },
951
+ [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
952
+ );
961
953
  const [discardDocument] = useDiscardDocumentMutation();
962
954
  const discard = React__namespace.useCallback(
963
- async ({ collectionType, model, documentId }) => {
955
+ async ({ collectionType, model, documentId, params }) => {
964
956
  try {
965
957
  const res = await discardDocument({
966
958
  collectionType,
967
959
  model,
968
- documentId
960
+ documentId,
961
+ params
969
962
  });
970
963
  if ("error" in res) {
971
964
  toggleNotification({
@@ -1027,6 +1020,43 @@ const useDocumentActions = () => {
1027
1020
  },
1028
1021
  [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1029
1022
  );
1023
+ const [publishManyDocuments] = usePublishManyDocumentsMutation();
1024
+ const publishMany = React__namespace.useCallback(
1025
+ async ({ model, documentIds, params }) => {
1026
+ try {
1027
+ const res = await publishManyDocuments({
1028
+ model,
1029
+ documentIds,
1030
+ params
1031
+ });
1032
+ if ("error" in res) {
1033
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1034
+ return { error: res.error };
1035
+ }
1036
+ toggleNotification({
1037
+ type: "success",
1038
+ message: formatMessage({
1039
+ id: getTranslation("success.record.publish"),
1040
+ defaultMessage: "Published document"
1041
+ })
1042
+ });
1043
+ return res.data;
1044
+ } catch (err) {
1045
+ toggleNotification({
1046
+ type: "danger",
1047
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1048
+ });
1049
+ throw err;
1050
+ }
1051
+ },
1052
+ [
1053
+ // trackUsage,
1054
+ publishManyDocuments,
1055
+ toggleNotification,
1056
+ formatMessage,
1057
+ formatAPIError
1058
+ ]
1059
+ );
1030
1060
  const [updateDocument] = useUpdateDocumentMutation();
1031
1061
  const update = React__namespace.useCallback(
1032
1062
  async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
@@ -1101,6 +1131,41 @@ const useDocumentActions = () => {
1101
1131
  },
1102
1132
  [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1103
1133
  );
1134
+ const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1135
+ const unpublishMany = React__namespace.useCallback(
1136
+ async ({ model, documentIds, params }) => {
1137
+ try {
1138
+ trackUsage("willBulkUnpublishEntries");
1139
+ const res = await unpublishManyDocuments({
1140
+ model,
1141
+ documentIds,
1142
+ params
1143
+ });
1144
+ if ("error" in res) {
1145
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1146
+ return { error: res.error };
1147
+ }
1148
+ trackUsage("didBulkUnpublishEntries");
1149
+ toggleNotification({
1150
+ type: "success",
1151
+ title: formatMessage({
1152
+ id: getTranslation("success.records.unpublish"),
1153
+ defaultMessage: "Successfully unpublished."
1154
+ }),
1155
+ message: ""
1156
+ });
1157
+ return res.data;
1158
+ } catch (err) {
1159
+ toggleNotification({
1160
+ type: "danger",
1161
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1162
+ });
1163
+ trackUsage("didNotBulkUnpublishEntries");
1164
+ throw err;
1165
+ }
1166
+ },
1167
+ [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1168
+ );
1104
1169
  const [createDocument] = useCreateDocumentMutation();
1105
1170
  const create = React__namespace.useCallback(
1106
1171
  async ({ model, params }, data, trackerProperty) => {
@@ -1214,15 +1279,18 @@ const useDocumentActions = () => {
1214
1279
  clone,
1215
1280
  create,
1216
1281
  delete: _delete,
1282
+ deleteMany,
1217
1283
  discard,
1218
1284
  getDocument,
1219
1285
  publish,
1286
+ publishMany,
1220
1287
  unpublish,
1288
+ unpublishMany,
1221
1289
  update
1222
1290
  };
1223
1291
  };
1224
1292
  const ProtectedHistoryPage = React.lazy(
1225
- () => Promise.resolve().then(() => require("./History-BLEnudTX.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1293
+ () => Promise.resolve().then(() => require("./History-Bsud8jwh.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1226
1294
  );
1227
1295
  const routes$1 = [
1228
1296
  {
@@ -1235,31 +1303,31 @@ const routes$1 = [
1235
1303
  }
1236
1304
  ];
1237
1305
  const ProtectedEditViewPage = React.lazy(
1238
- () => Promise.resolve().then(() => require("./EditViewPage-KRG56aCq.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1306
+ () => Promise.resolve().then(() => require("./EditViewPage-BqNpC6hO.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1239
1307
  );
1240
1308
  const ProtectedListViewPage = React.lazy(
1241
- () => Promise.resolve().then(() => require("./ListViewPage-DsaOakWQ.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1309
+ () => Promise.resolve().then(() => require("./ListViewPage-CsrC9L_d.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1242
1310
  );
1243
1311
  const ProtectedListConfiguration = React.lazy(
1244
- () => Promise.resolve().then(() => require("./ListConfigurationPage-Zso_LUjn.js")).then((mod) => ({
1312
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-DiT463qx.js")).then((mod) => ({
1245
1313
  default: mod.ProtectedListConfiguration
1246
1314
  }))
1247
1315
  );
1248
1316
  const ProtectedEditConfigurationPage = React.lazy(
1249
- () => Promise.resolve().then(() => require("./EditConfigurationPage-B7dw5_cS.js")).then((mod) => ({
1317
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-DOmfCEMo.js")).then((mod) => ({
1250
1318
  default: mod.ProtectedEditConfigurationPage
1251
1319
  }))
1252
1320
  );
1253
1321
  const ProtectedComponentConfigurationPage = React.lazy(
1254
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-2iOVVhqV.js")).then((mod) => ({
1322
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-BvHtG7uH.js")).then((mod) => ({
1255
1323
  default: mod.ProtectedComponentConfigurationPage
1256
1324
  }))
1257
1325
  );
1258
1326
  const NoPermissions = React.lazy(
1259
- () => Promise.resolve().then(() => require("./NoPermissionsPage-DdyOfdKb.js")).then((mod) => ({ default: mod.NoPermissions }))
1327
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-CdHNJtEf.js")).then((mod) => ({ default: mod.NoPermissions }))
1260
1328
  );
1261
1329
  const NoContentType = React.lazy(
1262
- () => Promise.resolve().then(() => require("./NoContentTypePage-DPCuS9Y1.js")).then((mod) => ({ default: mod.NoContentType }))
1330
+ () => Promise.resolve().then(() => require("./NoContentTypePage-Bsvng4II.js")).then((mod) => ({ default: mod.NoContentType }))
1263
1331
  );
1264
1332
  const CollectionTypePages = () => {
1265
1333
  const { collectionType } = reactRouterDom.useParams();
@@ -1449,7 +1517,7 @@ const DocumentActionsMenu = ({
1449
1517
  variant,
1450
1518
  children: [
1451
1519
  /* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
1452
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { as: "span", children: label || formatMessage({
1520
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
1453
1521
  id: "content-manager.containers.edit.panels.default.more-actions",
1454
1522
  defaultMessage: "More document actions"
1455
1523
  }) })
@@ -1465,8 +1533,8 @@ const DocumentActionsMenu = ({
1465
1533
  onSelect: handleClick(action),
1466
1534
  display: "block",
1467
1535
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
1468
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, as: "span", children: [
1469
- action.icon,
1536
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1537
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1470
1538
  action.label
1471
1539
  ] }),
1472
1540
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
@@ -1527,6 +1595,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1527
1595
  return "primary600";
1528
1596
  }
1529
1597
  };
1598
+ const convertActionVariantToIconColor = (variant = "secondary") => {
1599
+ switch (variant) {
1600
+ case "danger":
1601
+ return "danger600";
1602
+ case "secondary":
1603
+ return "neutral500";
1604
+ case "success":
1605
+ return "success600";
1606
+ default:
1607
+ return "primary600";
1608
+ }
1609
+ };
1530
1610
  const DocumentActionConfirmDialog = ({
1531
1611
  onClose,
1532
1612
  onCancel,
@@ -1549,61 +1629,42 @@ const DocumentActionConfirmDialog = ({
1549
1629
  }
1550
1630
  onClose();
1551
1631
  };
1552
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog, { isOpen, title, onClose: handleClose, children: [
1553
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.DialogBody, { children: content }),
1554
- /* @__PURE__ */ jsxRuntime.jsx(
1555
- designSystem.DialogFooter,
1556
- {
1557
- startAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", children: formatMessage({
1558
- id: "app.components.Button.cancel",
1559
- defaultMessage: "Cancel"
1560
- }) }),
1561
- endAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
1562
- id: "app.components.Button.confirm",
1563
- defaultMessage: "Confirm"
1564
- }) })
1565
- }
1566
- )
1567
- ] });
1632
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
1633
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
1634
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
1635
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
1636
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
1637
+ id: "app.components.Button.cancel",
1638
+ defaultMessage: "Cancel"
1639
+ }) }) }),
1640
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
1641
+ id: "app.components.Button.confirm",
1642
+ defaultMessage: "Confirm"
1643
+ }) })
1644
+ ] })
1645
+ ] }) });
1568
1646
  };
1569
1647
  const DocumentActionModal = ({
1570
1648
  isOpen,
1571
1649
  title,
1572
1650
  onClose,
1573
1651
  footer: Footer,
1574
- content,
1652
+ content: Content,
1575
1653
  onModalClose
1576
1654
  }) => {
1577
- const id = React__namespace.useId();
1578
- if (!isOpen) {
1579
- return null;
1580
- }
1581
1655
  const handleClose = () => {
1582
1656
  if (onClose) {
1583
1657
  onClose();
1584
1658
  }
1585
1659
  onModalClose();
1586
1660
  };
1587
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { borderRadius: "4px", overflow: "hidden", onClose: handleClose, labelledBy: id, children: [
1588
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: "neutral800", as: "h2", id, children: title }) }),
1589
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalBody, { children: content }),
1590
- /* @__PURE__ */ jsxRuntime.jsx(
1591
- designSystem.Box,
1592
- {
1593
- paddingTop: 4,
1594
- paddingBottom: 4,
1595
- paddingLeft: 5,
1596
- paddingRight: 5,
1597
- borderWidth: "1px 0 0 0",
1598
- borderStyle: "solid",
1599
- borderColor: "neutral150",
1600
- background: "neutral100",
1601
- children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
1602
- }
1603
- )
1604
- ] });
1661
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
1662
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
1663
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content }),
1664
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Footer, { children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer })
1665
+ ] }) });
1605
1666
  };
1606
- const PublishAction = ({
1667
+ const PublishAction$1 = ({
1607
1668
  activeTab,
1608
1669
  documentId,
1609
1670
  model,
@@ -1688,7 +1749,7 @@ const PublishAction = ({
1688
1749
  }
1689
1750
  };
1690
1751
  };
1691
- PublishAction.type = "publish";
1752
+ PublishAction$1.type = "publish";
1692
1753
  const UpdateAction = ({
1693
1754
  activeTab,
1694
1755
  documentId,
@@ -1784,10 +1845,13 @@ const UpdateAction = ({
1784
1845
  document
1785
1846
  );
1786
1847
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1787
- navigate({
1788
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1789
- search: rawQuery
1790
- });
1848
+ navigate(
1849
+ {
1850
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1851
+ search: rawQuery
1852
+ },
1853
+ { replace: true }
1854
+ );
1791
1855
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1792
1856
  setErrors(formatValidationErrors(res.error));
1793
1857
  }
@@ -1803,7 +1867,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
1803
1867
  KEEP: "keep",
1804
1868
  DISCARD: "discard"
1805
1869
  };
1806
- const UnpublishAction = ({
1870
+ const UnpublishAction$1 = ({
1807
1871
  activeTab,
1808
1872
  documentId,
1809
1873
  model,
@@ -1819,10 +1883,8 @@ const UnpublishAction = ({
1819
1883
  const { toggleNotification } = strapiAdmin.useNotification();
1820
1884
  const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
1821
1885
  const isDocumentModified = document?.status === "modified";
1822
- const handleChange = (e) => {
1823
- if ("value" in e.target) {
1824
- setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1825
- }
1886
+ const handleChange = (value) => {
1887
+ setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1826
1888
  };
1827
1889
  if (!schema?.options?.draftAndPublish) {
1828
1890
  return null;
@@ -1866,45 +1928,30 @@ const UnpublishAction = ({
1866
1928
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
1867
1929
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
1868
1930
  /* @__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({
1931
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1870
1932
  id: "content-manager.actions.unpublish.dialog.body",
1871
1933
  defaultMessage: "Are you sure?"
1872
1934
  }) })
1873
1935
  ] }),
1874
1936
  /* @__PURE__ */ jsxRuntime.jsxs(
1875
- designSystem.Flex,
1937
+ designSystem.Radio.Group,
1876
1938
  {
1877
- onChange: handleChange,
1878
- direction: "column",
1879
- alignItems: "flex-start",
1880
- as: "fieldset",
1881
- gap: 3,
1939
+ defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
1940
+ name: "discard-options",
1941
+ "aria-label": formatMessage({
1942
+ id: "content-manager.actions.unpublish.dialog.radio-label",
1943
+ defaultMessage: "Choose an option to unpublish the document."
1944
+ }),
1945
+ onValueChange: handleChange,
1882
1946
  children: [
1883
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { as: "legend" }),
1884
- /* @__PURE__ */ jsxRuntime.jsx(
1885
- designSystem.Radio,
1886
- {
1887
- checked: shouldKeepDraft,
1888
- value: UNPUBLISH_DRAFT_OPTIONS.KEEP,
1889
- name: "discard-options",
1890
- children: formatMessage({
1891
- id: "content-manager.actions.unpublish.dialog.option.keep-draft",
1892
- defaultMessage: "Keep draft"
1893
- })
1894
- }
1895
- ),
1896
- /* @__PURE__ */ jsxRuntime.jsx(
1897
- designSystem.Radio,
1898
- {
1899
- checked: !shouldKeepDraft,
1900
- value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
1901
- name: "discard-options",
1902
- children: formatMessage({
1903
- id: "content-manager.actions.unpublish.dialog.option.replace-draft",
1904
- defaultMessage: "Replace draft"
1905
- })
1906
- }
1907
- )
1947
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
1948
+ id: "content-manager.actions.unpublish.dialog.option.keep-draft",
1949
+ defaultMessage: "Keep draft"
1950
+ }) }),
1951
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
1952
+ id: "content-manager.actions.unpublish.dialog.option.replace-draft",
1953
+ defaultMessage: "Replace draft"
1954
+ }) })
1908
1955
  ]
1909
1956
  }
1910
1957
  )
@@ -1937,7 +1984,7 @@ const UnpublishAction = ({
1937
1984
  position: ["panel", "table-row"]
1938
1985
  };
1939
1986
  };
1940
- UnpublishAction.type = "unpublish";
1987
+ UnpublishAction$1.type = "unpublish";
1941
1988
  const DiscardAction = ({
1942
1989
  activeTab,
1943
1990
  documentId,
@@ -1971,7 +2018,7 @@ const DiscardAction = ({
1971
2018
  }),
1972
2019
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
1973
2020
  /* @__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({
2021
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1975
2022
  id: "content-manager.actions.discard.dialog.body",
1976
2023
  defaultMessage: "Are you sure?"
1977
2024
  }) })
@@ -1988,12 +2035,12 @@ const DiscardAction = ({
1988
2035
  };
1989
2036
  };
1990
2037
  DiscardAction.type = "discard";
1991
- const StyledCrossCircle = styled__default.default(Icons.CrossCircle)`
2038
+ const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
1992
2039
  path {
1993
2040
  fill: currentColor;
1994
2041
  }
1995
2042
  `;
1996
- const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
2043
+ const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
1997
2044
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
1998
2045
  const RelativeTime = React__namespace.forwardRef(
1999
2046
  ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
@@ -2041,7 +2088,7 @@ const getDisplayName = ({
2041
2088
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2042
2089
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2043
2090
  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) }) });
2091
+ 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
2092
  };
2046
2093
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2047
2094
  const { formatMessage } = reactIntl.useIntl();
@@ -2061,7 +2108,7 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2061
2108
  gap: "80px",
2062
2109
  alignItems: "flex-start",
2063
2110
  children: [
2064
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", children: title }),
2111
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
2065
2112
  /* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
2066
2113
  ]
2067
2114
  }
@@ -2218,7 +2265,7 @@ const Information = ({ activeTab }) => {
2218
2265
  borderColor: "neutral150",
2219
2266
  direction: "column",
2220
2267
  marginTop: 2,
2221
- as: "dl",
2268
+ tag: "dl",
2222
2269
  padding: 5,
2223
2270
  gap: 3,
2224
2271
  alignItems: "flex-start",
@@ -2226,8 +2273,8 @@ const Information = ({ activeTab }) => {
2226
2273
  marginRight: "-0.4rem",
2227
2274
  width: "calc(100% + 8px)",
2228
2275
  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 })
2276
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2277
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2231
2278
  ] }, info.label))
2232
2279
  }
2233
2280
  );
@@ -2260,7 +2307,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2260
2307
  id: "app.links.configure-view",
2261
2308
  defaultMessage: "Configure the view"
2262
2309
  }),
2263
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCog, {}),
2310
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
2264
2311
  onClick: () => {
2265
2312
  navigate(`../${collectionType}/${model}/configurations/edit`);
2266
2313
  },
@@ -2268,11 +2315,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2268
2315
  };
2269
2316
  };
2270
2317
  ConfigureTheViewAction.type = "configure-the-view";
2271
- const StyledCog = styled__default.default(Icons.Cog)`
2272
- path {
2273
- fill: currentColor;
2274
- }
2275
- `;
2276
2318
  const EditTheModelAction = ({ model }) => {
2277
2319
  const navigate = reactRouterDom.useNavigate();
2278
2320
  const { formatMessage } = reactIntl.useIntl();
@@ -2281,7 +2323,7 @@ const EditTheModelAction = ({ model }) => {
2281
2323
  id: "content-manager.link-to-ctb",
2282
2324
  defaultMessage: "Edit the model"
2283
2325
  }),
2284
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil$1, {}),
2326
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
2285
2327
  onClick: () => {
2286
2328
  navigate(`/plugins/content-type-builder/content-types/${model}`);
2287
2329
  },
@@ -2289,12 +2331,7 @@ const EditTheModelAction = ({ model }) => {
2289
2331
  };
2290
2332
  };
2291
2333
  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 }) => {
2334
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2298
2335
  const navigate = reactRouterDom.useNavigate();
2299
2336
  const { formatMessage } = reactIntl.useIntl();
2300
2337
  const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
@@ -2308,7 +2345,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2308
2345
  id: "content-manager.actions.delete.label",
2309
2346
  defaultMessage: "Delete document"
2310
2347
  }),
2311
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledTrash, {}),
2348
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2312
2349
  dialog: {
2313
2350
  type: "dialog",
2314
2351
  title: formatMessage({
@@ -2317,7 +2354,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2317
2354
  }),
2318
2355
  content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
2319
2356
  /* @__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({
2357
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2321
2358
  id: "content-manager.actions.delete.dialog.body",
2322
2359
  defaultMessage: "Are you sure?"
2323
2360
  }) })
@@ -2362,13 +2399,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2362
2399
  position: ["header", "table-row"]
2363
2400
  };
2364
2401
  };
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];
2402
+ DeleteAction$1.type = "delete";
2403
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2372
2404
  const Panels = () => {
2373
2405
  const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2374
2406
  const [
@@ -2442,7 +2474,7 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2442
2474
  designSystem.Flex,
2443
2475
  {
2444
2476
  ref,
2445
- as: "aside",
2477
+ tag: "aside",
2446
2478
  "aria-labelledby": "additional-information",
2447
2479
  background: "neutral0",
2448
2480
  borderColor: "neutral150",
@@ -2457,669 +2489,1244 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2457
2489
  justifyContent: "stretch",
2458
2490
  alignItems: "flex-start",
2459
2491
  children: [
2460
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { as: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2492
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2461
2493
  children
2462
2494
  ]
2463
2495
  }
2464
2496
  );
2465
2497
  });
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
- ] });
2498
+ const HOOKS = {
2499
+ /**
2500
+ * Hook that allows to mutate the displayed headers of the list view table
2501
+ * @constant
2502
+ * @type {string}
2503
+ */
2504
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2505
+ /**
2506
+ * Hook that allows to mutate the CM's collection types links pre-set filters
2507
+ * @constant
2508
+ * @type {string}
2509
+ */
2510
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2511
+ /**
2512
+ * Hook that allows to mutate the CM's edit view layout
2513
+ * @constant
2514
+ * @type {string}
2515
+ */
2516
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2517
+ /**
2518
+ * Hook that allows to mutate the CM's single types links pre-set filters
2519
+ * @constant
2520
+ * @type {string}
2521
+ */
2522
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2519
2523
  };
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
2524
+ const contentTypesApi = contentManagerApi.injectEndpoints({
2525
+ endpoints: (builder) => ({
2526
+ getContentTypeConfiguration: builder.query({
2527
+ query: (uid) => ({
2528
+ url: `/content-manager/content-types/${uid}/configuration`,
2529
+ method: "GET"
2530
+ }),
2531
+ transformResponse: (response) => response.data,
2532
+ providesTags: (_result, _error, uid) => [
2533
+ { type: "ContentTypesConfiguration", id: uid },
2534
+ { type: "ContentTypeSettings", id: "LIST" }
2535
+ ]
2536
+ }),
2537
+ getAllContentTypeSettings: builder.query({
2538
+ query: () => "/content-manager/content-types-settings",
2539
+ transformResponse: (response) => response.data,
2540
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2541
+ }),
2542
+ updateContentTypeConfiguration: builder.mutation({
2543
+ query: ({ uid, ...body }) => ({
2544
+ url: `/content-manager/content-types/${uid}/configuration`,
2545
+ method: "PUT",
2546
+ data: body
2547
+ }),
2548
+ transformResponse: (response) => response.data,
2549
+ invalidatesTags: (_result, _error, { uid }) => [
2550
+ { type: "ContentTypesConfiguration", id: uid },
2551
+ { type: "ContentTypeSettings", id: "LIST" },
2552
+ // Is this necessary?
2553
+ { type: "InitialData" }
2554
+ ]
2555
+ })
2556
+ })
2557
+ });
2558
+ const {
2559
+ useGetContentTypeConfigurationQuery,
2560
+ useGetAllContentTypeSettingsQuery,
2561
+ useUpdateContentTypeConfigurationMutation
2562
+ } = contentTypesApi;
2563
+ const checkIfAttributeIsDisplayable = (attribute) => {
2564
+ const { type } = attribute;
2565
+ if (type === "relation") {
2566
+ return !attribute.relation.toLowerCase().includes("morph");
2567
+ }
2568
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2569
+ };
2570
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2571
+ if (!mainFieldName) {
2572
+ return void 0;
2573
+ }
2574
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2575
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2576
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2577
+ );
2578
+ return {
2579
+ name: mainFieldName,
2580
+ type: mainFieldType ?? "string"
2530
2581
  };
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
- }
2582
+ };
2583
+ const DEFAULT_SETTINGS = {
2584
+ bulkable: false,
2585
+ filterable: false,
2586
+ searchable: false,
2587
+ pagination: false,
2588
+ defaultSortBy: "",
2589
+ defaultSortOrder: "asc",
2590
+ mainField: "id",
2591
+ pageSize: 10
2592
+ };
2593
+ const useDocumentLayout = (model) => {
2594
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2595
+ const [{ query }] = strapiAdmin.useQueryParams();
2596
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2597
+ const { toggleNotification } = strapiAdmin.useNotification();
2598
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2599
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2600
+ const {
2601
+ data,
2602
+ isLoading: isLoadingConfigs,
2603
+ error,
2604
+ isFetching: isFetchingConfigs
2605
+ } = useGetContentTypeConfigurationQuery(model);
2606
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2607
+ React__namespace.useEffect(() => {
2608
+ if (error) {
2609
+ toggleNotification({
2610
+ type: "danger",
2611
+ message: formatAPIError(error)
2612
+ });
2553
2613
  }
2614
+ }, [error, formatAPIError, toggleNotification]);
2615
+ const editLayout = React__namespace.useMemo(
2616
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2617
+ layout: [],
2618
+ components: {},
2619
+ metadatas: {},
2620
+ options: {},
2621
+ settings: DEFAULT_SETTINGS
2622
+ },
2623
+ [data, isLoading, schemas, schema, components]
2624
+ );
2625
+ const listLayout = React__namespace.useMemo(() => {
2626
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2627
+ layout: [],
2628
+ metadatas: {},
2629
+ options: {},
2630
+ settings: DEFAULT_SETTINGS
2631
+ };
2632
+ }, [data, isLoading, schemas, schema, components]);
2633
+ const { layout: edit } = React__namespace.useMemo(
2634
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2635
+ layout: editLayout,
2636
+ query
2637
+ }),
2638
+ [editLayout, query, runHookWaterfall]
2554
2639
  );
2640
+ return {
2641
+ error,
2642
+ isLoading,
2643
+ edit,
2644
+ list: listLayout
2645
+ };
2555
2646
  };
2556
- const EditAction = ({ documentId }) => {
2557
- const navigate = reactRouterDom.useNavigate();
2558
- const { formatMessage } = reactIntl.useIntl();
2559
- const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
2560
- const { toggleNotification } = strapiAdmin.useNotification();
2561
- const [{ query }] = strapiAdmin.useQueryParams();
2647
+ const useDocLayout = () => {
2648
+ const { model } = useDoc();
2649
+ return useDocumentLayout(model);
2650
+ };
2651
+ const formatEditLayout = (data, {
2652
+ schemas,
2653
+ schema,
2654
+ components
2655
+ }) => {
2656
+ let currentPanelIndex = 0;
2657
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2658
+ data.contentType.layouts.edit,
2659
+ schema?.attributes,
2660
+ data.contentType.metadatas,
2661
+ { configurations: data.components, schemas: components },
2662
+ schemas
2663
+ ).reduce((panels, row) => {
2664
+ if (row.some((field) => field.type === "dynamiczone")) {
2665
+ panels.push([row]);
2666
+ currentPanelIndex += 2;
2667
+ } else {
2668
+ if (!panels[currentPanelIndex]) {
2669
+ panels.push([]);
2670
+ }
2671
+ panels[currentPanelIndex].push(row);
2672
+ }
2673
+ return panels;
2674
+ }, []);
2675
+ const componentEditAttributes = Object.entries(data.components).reduce(
2676
+ (acc, [uid, configuration]) => {
2677
+ acc[uid] = {
2678
+ layout: convertEditLayoutToFieldLayouts(
2679
+ configuration.layouts.edit,
2680
+ components[uid].attributes,
2681
+ configuration.metadatas
2682
+ ),
2683
+ settings: {
2684
+ ...configuration.settings,
2685
+ icon: components[uid].info.icon,
2686
+ displayName: components[uid].info.displayName
2687
+ }
2688
+ };
2689
+ return acc;
2690
+ },
2691
+ {}
2692
+ );
2693
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2694
+ (acc, [attribute, metadata]) => {
2695
+ return {
2696
+ ...acc,
2697
+ [attribute]: metadata.edit
2698
+ };
2699
+ },
2700
+ {}
2701
+ );
2562
2702
  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;
2703
+ layout: panelledEditAttributes,
2704
+ components: componentEditAttributes,
2705
+ metadatas: editMetadatas,
2706
+ settings: {
2707
+ ...data.contentType.settings,
2708
+ displayName: schema?.info.displayName
2709
+ },
2710
+ options: {
2711
+ ...schema?.options,
2712
+ ...schema?.pluginOptions,
2713
+ ...data.contentType.options
2714
+ }
2715
+ };
2716
+ };
2717
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2718
+ return rows.map(
2719
+ (row) => row.map((field) => {
2720
+ const attribute = attributes[field.name];
2721
+ if (!attribute) {
2722
+ return null;
2583
2723
  }
2584
- navigate({
2585
- pathname: documentId,
2586
- search: qs.stringify({
2587
- plugins: query.plugins
2588
- })
2589
- });
2724
+ const { edit: metadata } = metadatas[field.name];
2725
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2726
+ return {
2727
+ attribute,
2728
+ disabled: !metadata.editable,
2729
+ hint: metadata.description,
2730
+ label: metadata.label ?? "",
2731
+ name: field.name,
2732
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
2733
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2734
+ schemas,
2735
+ components: components?.schemas ?? {}
2736
+ }),
2737
+ placeholder: metadata.placeholder ?? "",
2738
+ required: attribute.required ?? false,
2739
+ size: field.size,
2740
+ unique: "unique" in attribute ? attribute.unique : false,
2741
+ visible: metadata.visible ?? true,
2742
+ type: attribute.type
2743
+ };
2744
+ }).filter((field) => field !== null)
2745
+ );
2746
+ };
2747
+ const formatListLayout = (data, {
2748
+ schemas,
2749
+ schema,
2750
+ components
2751
+ }) => {
2752
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2753
+ (acc, [attribute, metadata]) => {
2754
+ return {
2755
+ ...acc,
2756
+ [attribute]: metadata.list
2757
+ };
2758
+ },
2759
+ {}
2760
+ );
2761
+ const listAttributes = convertListLayoutToFieldLayouts(
2762
+ data.contentType.layouts.list,
2763
+ schema?.attributes,
2764
+ listMetadatas,
2765
+ { configurations: data.components, schemas: components },
2766
+ schemas
2767
+ );
2768
+ return {
2769
+ layout: listAttributes,
2770
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2771
+ metadatas: listMetadatas,
2772
+ options: {
2773
+ ...schema?.options,
2774
+ ...schema?.pluginOptions,
2775
+ ...data.contentType.options
2590
2776
  }
2591
2777
  };
2592
2778
  };
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();
2779
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2780
+ return columns.map((name) => {
2781
+ const attribute = attributes[name];
2782
+ if (!attribute) {
2783
+ return null;
2784
+ }
2785
+ const metadata = metadatas[name];
2786
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2787
+ return {
2788
+ attribute,
2789
+ label: metadata.label ?? "",
2790
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2791
+ schemas,
2792
+ components: components?.schemas ?? {}
2793
+ }),
2794
+ name,
2795
+ searchable: metadata.searchable ?? true,
2796
+ sortable: metadata.sortable ?? true
2797
+ };
2798
+ }).filter((field) => field !== null);
2799
+ };
2800
+ const ConfirmBulkActionDialog = ({
2801
+ onToggleDialog,
2802
+ isOpen = false,
2803
+ dialogBody,
2804
+ endAction
2805
+ }) => {
2601
2806
  const { formatMessage } = reactIntl.useIntl();
2602
- const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
2807
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
2808
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
2809
+ id: "app.components.ConfirmDialog.title",
2810
+ defaultMessage: "Confirmation"
2811
+ }) }),
2812
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
2813
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
2814
+ dialogBody
2815
+ ] }) }),
2816
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
2817
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
2818
+ id: "app.components.Button.cancel",
2819
+ defaultMessage: "Cancel"
2820
+ }) }) }),
2821
+ endAction
2822
+ ] })
2823
+ ] }) });
2824
+ };
2825
+ const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
2826
+ const ConfirmDialogPublishAll = ({
2827
+ isOpen,
2828
+ onToggleDialog,
2829
+ isConfirmButtonLoading = false,
2830
+ onConfirm
2831
+ }) => {
2832
+ const { formatMessage } = reactIntl.useIntl();
2833
+ const selectedEntries = strapiAdmin.useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
2603
2834
  const { toggleNotification } = strapiAdmin.useNotification();
2604
- const { autoClone } = useDocumentActions();
2605
- const [prohibitedFields, setProhibitedFields] = React__namespace.useState([]);
2606
- return {
2607
- disabled: !canCreate,
2608
- icon: /* @__PURE__ */ jsxRuntime.jsx(StyledDuplicate, {}),
2609
- label: formatMessage({
2610
- id: "content-manager.actions.clone.label",
2611
- defaultMessage: "Duplicate"
2612
- }),
2613
- position: "table-row",
2614
- onClick: async () => {
2615
- if (!documentId) {
2616
- console.error(
2617
- "You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
2618
- );
2619
- toggleNotification({
2620
- message: formatMessage({
2621
- id: "content-manager.actions.clone.error",
2622
- defaultMessage: "An error occurred while trying to clone the document."
2623
- }),
2624
- type: "danger"
2625
- });
2626
- return;
2627
- }
2628
- const res = await autoClone({ model, sourceId: documentId });
2629
- if ("data" in res) {
2630
- navigate(res.data.documentId);
2631
- return true;
2632
- }
2633
- if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
2634
- const prohibitedFields2 = res.error.details.prohibitedFields;
2635
- setProhibitedFields(prohibitedFields2);
2636
- }
2835
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
2836
+ const { model, schema } = useDoc();
2837
+ const [{ query }] = strapiAdmin.useQueryParams();
2838
+ const {
2839
+ data: countDraftRelations = 0,
2840
+ isLoading,
2841
+ error
2842
+ } = useGetManyDraftRelationCountQuery(
2843
+ {
2844
+ model,
2845
+ documentIds: selectedEntries.map((entry) => entry.documentId),
2846
+ locale: query?.plugins?.i18n?.locale
2637
2847
  },
2638
- dialog: {
2639
- type: "modal",
2640
- title: formatMessage({
2641
- id: "content-manager.containers.list.autoCloneModal.header",
2642
- defaultMessage: "Duplicate"
2643
- }),
2644
- content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
2645
- footer: ({ onClose }) => {
2646
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
2647
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
2648
- id: "cancel",
2649
- defaultMessage: "Cancel"
2650
- }) }),
2651
- /* @__PURE__ */ jsxRuntime.jsx(
2652
- designSystem.LinkButton,
2848
+ {
2849
+ skip: selectedEntries.length === 0
2850
+ }
2851
+ );
2852
+ React__namespace.useEffect(() => {
2853
+ if (error) {
2854
+ toggleNotification({ type: "danger", message: formatAPIError(error) });
2855
+ }
2856
+ }, [error, formatAPIError, toggleNotification]);
2857
+ if (error) {
2858
+ return null;
2859
+ }
2860
+ return /* @__PURE__ */ jsxRuntime.jsx(
2861
+ ConfirmBulkActionDialog,
2862
+ {
2863
+ isOpen: isOpen && !isLoading,
2864
+ onToggleDialog,
2865
+ dialogBody: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2866
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: [
2867
+ countDraftRelations > 0 && formatMessage(
2653
2868
  {
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
- })
2869
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2870
+ 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. "
2871
+ },
2872
+ {
2873
+ b: BoldChunk$1,
2874
+ count: countDraftRelations,
2875
+ entities: selectedEntries.length
2662
2876
  }
2663
- )
2664
- ] });
2665
- }
2877
+ ),
2878
+ formatMessage({
2879
+ id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
2880
+ defaultMessage: "Are you sure you want to publish these entries?"
2881
+ })
2882
+ ] }),
2883
+ schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
2884
+ {
2885
+ id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
2886
+ defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
2887
+ },
2888
+ {
2889
+ em: Emphasis
2890
+ }
2891
+ ) })
2892
+ ] }),
2893
+ endAction: /* @__PURE__ */ jsxRuntime.jsx(
2894
+ designSystem.Button,
2895
+ {
2896
+ onClick: onConfirm,
2897
+ variant: "secondary",
2898
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
2899
+ loading: isConfirmButtonLoading,
2900
+ children: formatMessage({
2901
+ id: "app.utils.publish",
2902
+ defaultMessage: "Publish"
2903
+ })
2904
+ }
2905
+ )
2666
2906
  }
2667
- };
2907
+ );
2668
2908
  };
2669
- CloneAction.type = "clone";
2670
- const StyledDuplicate = styled__default.default(Icons.Duplicate)`
2671
- path {
2672
- fill: currentColor;
2673
- }
2909
+ const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
2910
+ max-width: 300px;
2674
2911
  `;
2675
- const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
2676
- class ContentManagerPlugin {
2677
- /**
2678
- * The following properties are the stored ones provided by any plugins registering with
2679
- * the content-manager. The function calls however, need to be called at runtime in the
2680
- * application, so instead we collate them and run them later with the complete list incl.
2681
- * ones already registered & the context of the view.
2682
- */
2683
- bulkActions = [...DEFAULT_BULK_ACTIONS];
2684
- documentActions = [
2685
- ...DEFAULT_ACTIONS,
2686
- ...DEFAULT_TABLE_ROW_ACTIONS,
2687
- ...DEFAULT_HEADER_ACTIONS,
2688
- HistoryAction
2689
- ];
2690
- editViewSidePanels = [ActionsPanel];
2691
- headerActions = [];
2692
- constructor() {
2693
- }
2694
- addEditViewSidePanel(panels) {
2695
- if (Array.isArray(panels)) {
2696
- this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
2697
- } else if (typeof panels === "function") {
2698
- this.editViewSidePanels = panels(this.editViewSidePanels);
2912
+ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2913
+ const messages = [];
2914
+ Object.entries(errors).forEach(([key, value]) => {
2915
+ const currentKey = parentKey ? `${parentKey}.${key}` : key;
2916
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
2917
+ if ("id" in value && "defaultMessage" in value) {
2918
+ messages.push(
2919
+ formatMessage(
2920
+ {
2921
+ id: `${value.id}.withField`,
2922
+ defaultMessage: value.defaultMessage
2923
+ },
2924
+ { field: currentKey }
2925
+ )
2926
+ );
2927
+ } else {
2928
+ messages.push(
2929
+ ...formatErrorMessages(
2930
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
2931
+ value,
2932
+ currentKey,
2933
+ formatMessage
2934
+ )
2935
+ );
2936
+ }
2699
2937
  } 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
- )}`
2938
+ messages.push(
2939
+ formatMessage(
2940
+ {
2941
+ id: `${value}.withField`,
2942
+ defaultMessage: value
2943
+ },
2944
+ { field: currentKey }
2945
+ )
2704
2946
  );
2705
2947
  }
2948
+ });
2949
+ return messages;
2950
+ };
2951
+ const EntryValidationText = ({ validationErrors, status }) => {
2952
+ const { formatMessage } = reactIntl.useIntl();
2953
+ if (validationErrors) {
2954
+ const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
2955
+ " "
2956
+ );
2957
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2958
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
2959
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
2960
+ ] });
2706
2961
  }
2707
- addDocumentAction(actions2) {
2708
- if (Array.isArray(actions2)) {
2709
- this.documentActions = [...this.documentActions, ...actions2];
2710
- } else if (typeof actions2 === "function") {
2711
- this.documentActions = actions2(this.documentActions);
2712
- } else {
2713
- throw new Error(
2714
- `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
2715
- actions2
2716
- )}`
2717
- );
2718
- }
2962
+ if (status === "published") {
2963
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2964
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
2965
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
2966
+ id: "content-manager.bulk-publish.already-published",
2967
+ defaultMessage: "Already Published"
2968
+ }) })
2969
+ ] });
2719
2970
  }
2720
- addDocumentHeaderAction(actions2) {
2721
- if (Array.isArray(actions2)) {
2722
- this.headerActions = [...this.headerActions, ...actions2];
2723
- } else if (typeof actions2 === "function") {
2724
- this.headerActions = actions2(this.headerActions);
2725
- } else {
2726
- throw new Error(
2727
- `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
2728
- actions2
2729
- )}`
2730
- );
2731
- }
2971
+ if (status === "modified") {
2972
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2973
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
2974
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
2975
+ id: "content-manager.bulk-publish.modified",
2976
+ defaultMessage: "Ready to publish changes"
2977
+ }) })
2978
+ ] });
2732
2979
  }
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
- );
2980
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
2981
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
2982
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
2983
+ id: "app.utils.ready-to-publish",
2984
+ defaultMessage: "Ready to publish"
2985
+ }) })
2986
+ ] });
2987
+ };
2988
+ const TABLE_HEADERS = [
2989
+ { name: "id", label: "id" },
2990
+ { name: "name", label: "name" },
2991
+ { name: "status", label: "status" },
2992
+ { name: "publicationStatus", label: "Publication status" }
2993
+ ];
2994
+ const SelectedEntriesTableContent = ({
2995
+ isPublishing,
2996
+ rowsToDisplay = [],
2997
+ entriesToPublish = [],
2998
+ validationErrors = {}
2999
+ }) => {
3000
+ const { pathname } = reactRouterDom.useLocation();
3001
+ const { formatMessage } = reactIntl.useIntl();
3002
+ const {
3003
+ list: {
3004
+ settings: { mainField }
3005
+ }
3006
+ } = useDocLayout();
3007
+ const shouldDisplayMainField = mainField != null && mainField !== "id";
3008
+ return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
3009
+ /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
3010
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
3011
+ TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
3012
+ (head) => /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, { ...head }, head.name)
3013
+ )
3014
+ ] }),
3015
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
3016
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
3017
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
3018
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
3019
+ shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
3020
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
3021
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3022
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
3023
+ id: "content-manager.success.record.publishing",
3024
+ defaultMessage: "Publishing..."
3025
+ }) }),
3026
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true })
3027
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
3028
+ EntryValidationText,
3029
+ {
3030
+ validationErrors: validationErrors[row.documentId],
3031
+ status: row.status
3032
+ }
3033
+ ) }),
3034
+ /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
3035
+ designSystem.IconButton,
3036
+ {
3037
+ tag: reactRouterDom.Link,
3038
+ to: {
3039
+ pathname: `${pathname}/${row.documentId}`,
3040
+ search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3041
+ },
3042
+ state: { from: pathname },
3043
+ label: formatMessage(
3044
+ { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3045
+ {
3046
+ target: formatMessage(
3047
+ {
3048
+ id: "content-manager.components.ListViewHelperPluginTable.row-line",
3049
+ defaultMessage: "item line {number}"
3050
+ },
3051
+ { number: index2 + 1 }
3052
+ )
3053
+ }
3054
+ ),
3055
+ target: "_blank",
3056
+ marginLeft: "auto",
3057
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
3058
+ }
3059
+ ) })
3060
+ ] }, row.id)) })
3061
+ ] });
3062
+ };
3063
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
3064
+ const SelectedEntriesModalContent = ({
3065
+ listViewSelectedEntries,
3066
+ toggleModal,
3067
+ setListViewSelectedDocuments,
3068
+ model
3069
+ }) => {
3070
+ const { formatMessage } = reactIntl.useIntl();
3071
+ const { schema, components } = useContentTypeSchema(model);
3072
+ const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
3073
+ const [{ query }] = strapiAdmin.useQueryParams();
3074
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3075
+ const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
3076
+ {
3077
+ model,
3078
+ params: {
3079
+ page: "1",
3080
+ pageSize: documentIds.length.toString(),
3081
+ sort: query.sort,
3082
+ filters: {
3083
+ documentId: {
3084
+ $in: documentIds
3085
+ }
3086
+ },
3087
+ locale: query.plugins?.i18n?.locale
3088
+ }
3089
+ },
3090
+ {
3091
+ selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
3092
+ }
3093
+ );
3094
+ const { rows, validationErrors } = React__namespace.useMemo(() => {
3095
+ if (data.length > 0 && schema) {
3096
+ const validate = createYupSchema(schema.attributes, components);
3097
+ const validationErrors2 = {};
3098
+ const rows2 = data.map((entry) => {
3099
+ try {
3100
+ validate.validateSync(entry, { abortEarly: false });
3101
+ return entry;
3102
+ } catch (e) {
3103
+ if (e instanceof yup.ValidationError) {
3104
+ validationErrors2[entry.documentId] = strapiAdmin.getYupValidationErrors(e);
3105
+ }
3106
+ return entry;
3107
+ }
3108
+ });
3109
+ return { rows: rows2, validationErrors: validationErrors2 };
2744
3110
  }
2745
- }
2746
- get config() {
2747
3111
  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
- }
3112
+ rows: [],
3113
+ validationErrors: {}
2761
3114
  };
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;
3115
+ }, [components, data, schema]);
3116
+ const [publishedCount, setPublishedCount] = React__namespace.useState(0);
3117
+ const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
3118
+ const { publishMany: bulkPublishAction } = useDocumentActions();
3119
+ const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
3120
+ const selectedRows = strapiAdmin.useTable("publishAction", (state) => state.selectedRows);
3121
+ const selectedEntries = rows.filter(
3122
+ (entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
3123
+ );
3124
+ const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
3125
+ const selectedEntriesWithErrorsCount = selectedEntries.filter(
3126
+ ({ documentId }) => validationErrors[documentId]
3127
+ ).length;
3128
+ const selectedEntriesPublished = selectedEntries.filter(
3129
+ ({ status }) => status === "published"
3130
+ ).length;
3131
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3132
+ const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3133
+ const handleConfirmBulkPublish = async () => {
3134
+ toggleDialog();
3135
+ const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3136
+ if (!("error" in res)) {
3137
+ setPublishedCount(res.count);
3138
+ const unpublishedEntries = rows.filter((row) => {
3139
+ return !entriesToPublish.includes(row.documentId);
3140
+ });
3141
+ setListViewSelectedDocuments(unpublishedEntries);
2773
3142
  }
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
3143
+ };
3144
+ const getFormattedCountMessage = () => {
3145
+ if (publishedCount) {
3146
+ return formatMessage(
3147
+ {
3148
+ id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3149
+ 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."
3150
+ },
3151
+ {
3152
+ publishedCount,
3153
+ withErrorsCount: selectedEntriesWithErrorsCount,
3154
+ b: BoldChunk
3155
+ }
2799
3156
  );
2800
- state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
2801
- state.components = components;
2802
- state.models = contentTypeSchemas;
2803
- state.fieldSizes = fieldSizes;
2804
- state.isLoading = false;
2805
3157
  }
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"
3158
+ return formatMessage(
3159
+ {
3160
+ id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3161
+ 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."
3162
+ },
3163
+ {
3164
+ readyToPublishCount: selectedEntriesWithNoErrorsCount,
3165
+ withErrorsCount: selectedEntriesWithErrorsCount,
3166
+ alreadyPublishedCount: selectedEntriesPublished,
3167
+ b: BoldChunk
3168
+ }
3169
+ );
3170
+ };
3171
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3172
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
3173
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
3174
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
3175
+ SelectedEntriesTableContent,
3176
+ {
3177
+ isPublishing: isSubmittingForm,
3178
+ rowsToDisplay: rows,
3179
+ entriesToPublish,
3180
+ validationErrors
3181
+ }
3182
+ ) })
3183
+ ] }),
3184
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
3185
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3186
+ id: "app.components.Button.cancel",
3187
+ defaultMessage: "Cancel"
3188
+ }) }),
3189
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
3190
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3191
+ /* @__PURE__ */ jsxRuntime.jsx(
3192
+ designSystem.Button,
3193
+ {
3194
+ onClick: toggleDialog,
3195
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3196
+ loading: isSubmittingForm,
3197
+ children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3198
+ }
3199
+ )
3200
+ ] })
3201
+ ] }),
3202
+ /* @__PURE__ */ jsxRuntime.jsx(
3203
+ ConfirmDialogPublishAll,
3204
+ {
3205
+ isOpen: isDialogOpen,
3206
+ onToggleDialog: toggleDialog,
3207
+ isConfirmButtonLoading: isSubmittingForm,
3208
+ onConfirm: handleConfirmBulkPublish
3209
+ }
3210
+ )
3211
+ ] });
2838
3212
  };
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
3213
+ const PublishAction = ({ documents, model }) => {
3214
+ const { formatMessage } = reactIntl.useIntl();
3215
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3216
+ const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
3217
+ const setListViewSelectedDocuments = strapiAdmin.useTable("publishAction", (state) => state.selectRow);
3218
+ const refetchList = () => {
3219
+ contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3220
+ };
3221
+ if (!showPublishButton)
3222
+ return null;
3223
+ return {
3224
+ actionType: "publish",
3225
+ variant: "tertiary",
3226
+ label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
3227
+ dialog: {
3228
+ type: "modal",
3229
+ title: formatMessage({
3230
+ id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
3231
+ defaultMessage: "Publish entries"
2862
3232
  }),
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;
3233
+ content: ({ onClose }) => {
3234
+ return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsxRuntime.jsx(
3235
+ SelectedEntriesModalContent,
3236
+ {
3237
+ listViewSelectedEntries: documents,
3238
+ toggleModal: () => {
3239
+ onClose();
3240
+ refetchList();
3241
+ },
3242
+ setListViewSelectedDocuments,
3243
+ model
3244
+ }
3245
+ ) });
3246
+ },
3247
+ onClose: () => {
3248
+ refetchList();
3249
+ }
3250
+ }
3251
+ };
2884
3252
  };
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
- );
3253
+ const BulkActionsRenderer = () => {
3254
+ const plugins = strapiAdmin.useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
3255
+ const { model, collectionType } = useDoc();
3256
+ const { selectedRows } = strapiAdmin.useTable("BulkActionsRenderer", (state) => state);
3257
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
3258
+ strapiAdmin.DescriptionComponentRenderer,
3259
+ {
3260
+ props: {
3261
+ model,
3262
+ collectionType,
3263
+ documents: selectedRows
3264
+ },
3265
+ descriptions: plugins["content-manager"].apis.getBulkActions(),
3266
+ children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...action }, action.id))
3267
+ }
3268
+ ) });
3269
+ };
3270
+ const DeleteAction = ({ documents, model }) => {
3271
+ const { formatMessage } = reactIntl.useIntl();
3272
+ const { schema: contentType } = useDoc();
3273
+ const selectRow = strapiAdmin.useTable("DeleteAction", (state) => state.selectRow);
3274
+ const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
3275
+ const [{ query }] = strapiAdmin.useQueryParams();
3276
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3277
+ const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
3278
+ const { deleteMany: bulkDeleteAction } = useDocumentActions();
3279
+ const documentIds = documents.map(({ documentId }) => documentId);
3280
+ const handleConfirmBulkDelete = async () => {
3281
+ const res = await bulkDeleteAction({
3282
+ documentIds,
3283
+ model,
3284
+ params
3285
+ });
3286
+ if (!("error" in res)) {
3287
+ selectRow([]);
3288
+ }
3289
+ };
3290
+ if (!hasDeletePermission)
3291
+ return null;
2893
3292
  return {
2894
- name: mainFieldName,
2895
- type: mainFieldType ?? "string"
3293
+ variant: "danger-light",
3294
+ label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
3295
+ dialog: {
3296
+ type: "dialog",
3297
+ title: formatMessage({
3298
+ id: "app.components.ConfirmDialog.title",
3299
+ defaultMessage: "Confirmation"
3300
+ }),
3301
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3302
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3303
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3304
+ id: "popUpWarning.bodyMessage.contentType.delete.all",
3305
+ defaultMessage: "Are you sure you want to delete these entries?"
3306
+ }) }),
3307
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3308
+ {
3309
+ id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
3310
+ defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
3311
+ },
3312
+ {
3313
+ em: Emphasis
3314
+ }
3315
+ ) }) })
3316
+ ] }),
3317
+ onConfirm: handleConfirmBulkDelete
3318
+ }
2896
3319
  };
2897
3320
  };
2898
- const DEFAULT_SETTINGS = {
2899
- bulkable: false,
2900
- filterable: false,
2901
- searchable: false,
2902
- pagination: false,
2903
- defaultSortBy: "",
2904
- defaultSortOrder: "asc",
2905
- mainField: "id",
2906
- pageSize: 10
2907
- };
2908
- const useDocumentLayout = (model) => {
2909
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
3321
+ DeleteAction.type = "delete";
3322
+ const UnpublishAction = ({ documents, model }) => {
3323
+ const { formatMessage } = reactIntl.useIntl();
3324
+ const { schema } = useDoc();
3325
+ const selectRow = strapiAdmin.useTable("UnpublishAction", (state) => state.selectRow);
3326
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3327
+ const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
3328
+ const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
3329
+ const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
3330
+ const documentIds = documents.map(({ documentId }) => documentId);
2910
3331
  const [{ query }] = strapiAdmin.useQueryParams();
2911
- const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2912
- const { toggleNotification } = strapiAdmin.useNotification();
2913
- const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2914
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2915
- const {
2916
- data,
2917
- isLoading: isLoadingConfigs,
2918
- error,
2919
- isFetching: isFetchingConfigs
2920
- } = useGetContentTypeConfigurationQuery(model);
2921
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2922
- React__namespace.useEffect(() => {
2923
- if (error) {
2924
- toggleNotification({
2925
- type: "danger",
2926
- message: formatAPIError(error)
2927
- });
3332
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
3333
+ const handleConfirmBulkUnpublish = async () => {
3334
+ const data = await bulkUnpublishAction({ documentIds, model, params });
3335
+ if (!("error" in data)) {
3336
+ selectRow([]);
2928
3337
  }
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
- );
3338
+ };
3339
+ const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3340
+ if (!showUnpublishButton)
3341
+ return null;
2955
3342
  return {
2956
- error,
2957
- isLoading,
2958
- edit,
2959
- list: listLayout
3343
+ variant: "tertiary",
3344
+ label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
3345
+ dialog: {
3346
+ type: "dialog",
3347
+ title: formatMessage({
3348
+ id: "app.components.ConfirmDialog.title",
3349
+ defaultMessage: "Confirmation"
3350
+ }),
3351
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3352
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3353
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3354
+ id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3355
+ defaultMessage: "Are you sure you want to unpublish these entries?"
3356
+ }) }),
3357
+ hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
3358
+ {
3359
+ id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
3360
+ defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
3361
+ },
3362
+ {
3363
+ em: Emphasis
3364
+ }
3365
+ ) }) })
3366
+ ] }),
3367
+ confirmButton: formatMessage({
3368
+ id: "app.utils.unpublish",
3369
+ defaultMessage: "Unpublish"
3370
+ }),
3371
+ onConfirm: handleConfirmBulkUnpublish
3372
+ }
2960
3373
  };
2961
3374
  };
2962
- const useDocLayout = () => {
2963
- const { model } = useDoc();
2964
- return useDocumentLayout(model);
3375
+ UnpublishAction.type = "unpublish";
3376
+ const Emphasis = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
3377
+ const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
3378
+ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3379
+ const { formatMessage } = reactIntl.useIntl();
3380
+ const getDefaultErrorMessage = (reason) => {
3381
+ switch (reason) {
3382
+ case "relation":
3383
+ return "Duplicating the relation could remove it from the original entry.";
3384
+ case "unique":
3385
+ return "Identical values in a unique field are not allowed";
3386
+ default:
3387
+ return reason;
3388
+ }
3389
+ };
3390
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3391
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: formatMessage({
3392
+ id: getTranslation("containers.list.autoCloneModal.title"),
3393
+ defaultMessage: "This entry can't be duplicated directly."
3394
+ }) }),
3395
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatMessage({
3396
+ id: getTranslation("containers.list.autoCloneModal.description"),
3397
+ defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
3398
+ }) }) }),
3399
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxRuntime.jsxs(
3400
+ designSystem.Flex,
3401
+ {
3402
+ direction: "column",
3403
+ gap: 2,
3404
+ alignItems: "flex-start",
3405
+ borderColor: "neutral200",
3406
+ hasRadius: true,
3407
+ padding: 6,
3408
+ children: [
3409
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", tag: "li", children: [
3410
+ pathSegment,
3411
+ index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
3412
+ Icons.ChevronRight,
3413
+ {
3414
+ fill: "neutral500",
3415
+ height: "0.8rem",
3416
+ width: "0.8rem",
3417
+ style: { margin: "0 0.8rem" }
3418
+ }
3419
+ )
3420
+ ] }, index2)) }),
3421
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
3422
+ id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
3423
+ defaultMessage: getDefaultErrorMessage(reason)
3424
+ }) })
3425
+ ]
3426
+ },
3427
+ fieldPath.join()
3428
+ )) })
3429
+ ] });
2965
3430
  };
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([]);
3431
+ const TableActions = ({ document }) => {
3432
+ const { formatMessage } = reactIntl.useIntl();
3433
+ const { model, collectionType } = useDoc();
3434
+ const plugins = strapiAdmin.useStrapiApp("TableActions", (state) => state.plugins);
3435
+ const props = {
3436
+ activeTab: null,
3437
+ model,
3438
+ documentId: document.documentId,
3439
+ collectionType,
3440
+ document
3441
+ };
3442
+ return /* @__PURE__ */ jsxRuntime.jsx(
3443
+ strapiAdmin.DescriptionComponentRenderer,
3444
+ {
3445
+ props,
3446
+ descriptions: plugins["content-manager"].apis.getDocumentActions(),
3447
+ children: (actions2) => {
3448
+ const tableRowActions = actions2.filter((action) => {
3449
+ const positions = Array.isArray(action.position) ? action.position : [action.position];
3450
+ return positions.includes("table-row");
3451
+ });
3452
+ return /* @__PURE__ */ jsxRuntime.jsx(
3453
+ DocumentActionsMenu,
3454
+ {
3455
+ actions: tableRowActions,
3456
+ label: formatMessage({
3457
+ id: "content-manager.containers.list.table.row-actions",
3458
+ defaultMessage: "Row action"
3459
+ }),
3460
+ variant: "ghost"
3461
+ }
3462
+ );
2985
3463
  }
2986
- panels[currentPanelIndex].push(row);
2987
3464
  }
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
3465
  );
3466
+ };
3467
+ const EditAction = ({ documentId }) => {
3468
+ const navigate = reactRouterDom.useNavigate();
3469
+ const { formatMessage } = reactIntl.useIntl();
3470
+ const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
3471
+ const { toggleNotification } = strapiAdmin.useNotification();
3472
+ const [{ query }] = strapiAdmin.useQueryParams();
3017
3473
  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
3474
+ disabled: !canRead,
3475
+ icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil, {}),
3476
+ label: formatMessage({
3477
+ id: "content-manager.actions.edit.label",
3478
+ defaultMessage: "Edit"
3479
+ }),
3480
+ position: "table-row",
3481
+ onClick: async () => {
3482
+ if (!documentId) {
3483
+ console.error(
3484
+ "You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
3485
+ );
3486
+ toggleNotification({
3487
+ message: formatMessage({
3488
+ id: "content-manager.actions.edit.error",
3489
+ defaultMessage: "An error occurred while trying to edit the document."
3490
+ }),
3491
+ type: "danger"
3492
+ });
3493
+ return;
3494
+ }
3495
+ navigate({
3496
+ pathname: documentId,
3497
+ search: qs.stringify({
3498
+ plugins: query.plugins
3499
+ })
3500
+ });
3029
3501
  }
3030
3502
  };
3031
3503
  };
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;
3504
+ EditAction.type = "edit";
3505
+ const StyledPencil = styledComponents.styled(Icons.Pencil)`
3506
+ path {
3507
+ fill: currentColor;
3508
+ }
3509
+ `;
3510
+ const CloneAction = ({ model, documentId }) => {
3511
+ const navigate = reactRouterDom.useNavigate();
3512
+ const { formatMessage } = reactIntl.useIntl();
3513
+ const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
3514
+ const { toggleNotification } = strapiAdmin.useNotification();
3515
+ const { autoClone } = useDocumentActions();
3516
+ const [prohibitedFields, setProhibitedFields] = React__namespace.useState([]);
3517
+ return {
3518
+ disabled: !canCreate,
3519
+ icon: /* @__PURE__ */ jsxRuntime.jsx(StyledDuplicate, {}),
3520
+ label: formatMessage({
3521
+ id: "content-manager.actions.clone.label",
3522
+ defaultMessage: "Duplicate"
3523
+ }),
3524
+ position: "table-row",
3525
+ onClick: async () => {
3526
+ if (!documentId) {
3527
+ console.error(
3528
+ "You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
3529
+ );
3530
+ toggleNotification({
3531
+ message: formatMessage({
3532
+ id: "content-manager.actions.clone.error",
3533
+ defaultMessage: "An error occurred while trying to clone the document."
3534
+ }),
3535
+ type: "danger"
3536
+ });
3537
+ return;
3538
+ }
3539
+ const res = await autoClone({ model, sourceId: documentId });
3540
+ if ("data" in res) {
3541
+ navigate(res.data.documentId);
3542
+ return true;
3543
+ }
3544
+ if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
3545
+ const prohibitedFields2 = res.error.details.prohibitedFields;
3546
+ setProhibitedFields(prohibitedFields2);
3038
3547
  }
3039
- const { edit: metadata } = metadatas[field.name];
3040
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3041
- return {
3042
- attribute,
3043
- disabled: !metadata.editable,
3044
- hint: metadata.description,
3045
- label: metadata.label ?? "",
3046
- name: field.name,
3047
- // @ts-expect-error – mainField does exist on the metadata for a relation.
3048
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
3049
- schemas,
3050
- components: components?.schemas ?? {}
3051
- }),
3052
- placeholder: metadata.placeholder ?? "",
3053
- required: attribute.required ?? false,
3054
- size: field.size,
3055
- unique: "unique" in attribute ? attribute.unique : false,
3056
- visible: metadata.visible ?? true,
3057
- type: attribute.type
3058
- };
3059
- }).filter((field) => field !== null)
3060
- );
3061
- };
3062
- const formatListLayout = (data, {
3063
- schemas,
3064
- schema,
3065
- components
3066
- }) => {
3067
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
3068
- (acc, [attribute, metadata]) => {
3069
- return {
3070
- ...acc,
3071
- [attribute]: metadata.list
3072
- };
3073
3548
  },
3074
- {}
3075
- );
3076
- const listAttributes = convertListLayoutToFieldLayouts(
3077
- data.contentType.layouts.list,
3078
- schema?.attributes,
3079
- listMetadatas,
3080
- { configurations: data.components, schemas: components },
3081
- schemas
3082
- );
3083
- return {
3084
- layout: listAttributes,
3085
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
3086
- metadatas: listMetadatas,
3087
- options: {
3088
- ...schema?.options,
3089
- ...schema?.pluginOptions,
3090
- ...data.contentType.options
3549
+ dialog: {
3550
+ type: "modal",
3551
+ title: formatMessage({
3552
+ id: "content-manager.containers.list.autoCloneModal.header",
3553
+ defaultMessage: "Duplicate"
3554
+ }),
3555
+ content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3556
+ footer: ({ onClose }) => {
3557
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
3558
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3559
+ id: "cancel",
3560
+ defaultMessage: "Cancel"
3561
+ }) }),
3562
+ /* @__PURE__ */ jsxRuntime.jsx(
3563
+ designSystem.LinkButton,
3564
+ {
3565
+ tag: reactRouterDom.NavLink,
3566
+ to: {
3567
+ pathname: `clone/${documentId}`
3568
+ },
3569
+ children: formatMessage({
3570
+ id: "content-manager.containers.list.autoCloneModal.create",
3571
+ defaultMessage: "Create"
3572
+ })
3573
+ }
3574
+ )
3575
+ ] });
3576
+ }
3091
3577
  }
3092
3578
  };
3093
3579
  };
3094
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
3095
- return columns.map((name) => {
3096
- const attribute = attributes[name];
3097
- if (!attribute) {
3098
- return null;
3580
+ CloneAction.type = "clone";
3581
+ const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
3582
+ path {
3583
+ fill: currentColor;
3584
+ }
3585
+ `;
3586
+ const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
3587
+ class ContentManagerPlugin {
3588
+ /**
3589
+ * The following properties are the stored ones provided by any plugins registering with
3590
+ * the content-manager. The function calls however, need to be called at runtime in the
3591
+ * application, so instead we collate them and run them later with the complete list incl.
3592
+ * ones already registered & the context of the view.
3593
+ */
3594
+ bulkActions = [...DEFAULT_BULK_ACTIONS];
3595
+ documentActions = [
3596
+ ...DEFAULT_ACTIONS,
3597
+ ...DEFAULT_TABLE_ROW_ACTIONS,
3598
+ ...DEFAULT_HEADER_ACTIONS,
3599
+ HistoryAction
3600
+ ];
3601
+ editViewSidePanels = [ActionsPanel];
3602
+ headerActions = [];
3603
+ constructor() {
3604
+ }
3605
+ addEditViewSidePanel(panels) {
3606
+ if (Array.isArray(panels)) {
3607
+ this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
3608
+ } else if (typeof panels === "function") {
3609
+ this.editViewSidePanels = panels(this.editViewSidePanels);
3610
+ } else {
3611
+ throw new Error(
3612
+ `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
3613
+ panels
3614
+ )}`
3615
+ );
3099
3616
  }
3100
- const metadata = metadatas[name];
3101
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3617
+ }
3618
+ addDocumentAction(actions2) {
3619
+ if (Array.isArray(actions2)) {
3620
+ this.documentActions = [...this.documentActions, ...actions2];
3621
+ } else if (typeof actions2 === "function") {
3622
+ this.documentActions = actions2(this.documentActions);
3623
+ } else {
3624
+ throw new Error(
3625
+ `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
3626
+ actions2
3627
+ )}`
3628
+ );
3629
+ }
3630
+ }
3631
+ addDocumentHeaderAction(actions2) {
3632
+ if (Array.isArray(actions2)) {
3633
+ this.headerActions = [...this.headerActions, ...actions2];
3634
+ } else if (typeof actions2 === "function") {
3635
+ this.headerActions = actions2(this.headerActions);
3636
+ } else {
3637
+ throw new Error(
3638
+ `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
3639
+ actions2
3640
+ )}`
3641
+ );
3642
+ }
3643
+ }
3644
+ addBulkAction(actions2) {
3645
+ if (Array.isArray(actions2)) {
3646
+ this.bulkActions = [...this.bulkActions, ...actions2];
3647
+ } else if (typeof actions2 === "function") {
3648
+ this.bulkActions = actions2(this.bulkActions);
3649
+ } else {
3650
+ throw new Error(
3651
+ `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3652
+ actions2
3653
+ )}`
3654
+ );
3655
+ }
3656
+ }
3657
+ get config() {
3102
3658
  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
3659
+ id: PLUGIN_ID,
3660
+ name: "Content Manager",
3661
+ injectionZones: INJECTION_ZONES,
3662
+ apis: {
3663
+ addBulkAction: this.addBulkAction.bind(this),
3664
+ addDocumentAction: this.addDocumentAction.bind(this),
3665
+ addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3666
+ addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3667
+ getBulkActions: () => this.bulkActions,
3668
+ getDocumentActions: () => this.documentActions,
3669
+ getEditViewSidePanels: () => this.editViewSidePanels,
3670
+ getHeaderActions: () => this.headerActions
3671
+ }
3112
3672
  };
3113
- }).filter((field) => field !== null);
3673
+ }
3674
+ }
3675
+ const getPrintableType = (value) => {
3676
+ const nativeType = typeof value;
3677
+ if (nativeType === "object") {
3678
+ if (value === null)
3679
+ return "null";
3680
+ if (Array.isArray(value))
3681
+ return "array";
3682
+ if (value instanceof Object && value.constructor.name !== "Object") {
3683
+ return value.constructor.name;
3684
+ }
3685
+ }
3686
+ return nativeType;
3687
+ };
3688
+ const initialState = {
3689
+ collectionTypeLinks: [],
3690
+ components: [],
3691
+ fieldSizes: {},
3692
+ models: [],
3693
+ singleTypeLinks: [],
3694
+ isLoading: true
3114
3695
  };
3696
+ const appSlice = toolkit.createSlice({
3697
+ name: "app",
3698
+ initialState,
3699
+ reducers: {
3700
+ setInitialData(state, action) {
3701
+ const {
3702
+ authorizedCollectionTypeLinks,
3703
+ authorizedSingleTypeLinks,
3704
+ components,
3705
+ contentTypeSchemas,
3706
+ fieldSizes
3707
+ } = action.payload;
3708
+ state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
3709
+ ({ isDisplayed }) => isDisplayed
3710
+ );
3711
+ state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
3712
+ state.components = components;
3713
+ state.models = contentTypeSchemas;
3714
+ state.fieldSizes = fieldSizes;
3715
+ state.isLoading = false;
3716
+ }
3717
+ }
3718
+ });
3719
+ const { actions, reducer: reducer$1 } = appSlice;
3720
+ const { setInitialData } = actions;
3721
+ const reducer = toolkit.combineReducers({
3722
+ app: reducer$1
3723
+ });
3115
3724
  const index = {
3116
3725
  register(app) {
3117
3726
  const cm = new ContentManagerPlugin();
3118
3727
  app.addReducers({
3119
- [contentManagerApi.reducerPath]: contentManagerApi.reducer,
3120
3728
  [PLUGIN_ID]: reducer
3121
3729
  });
3122
- app.addMiddlewares([() => contentManagerApi.middleware]);
3123
3730
  app.addMenuLink({
3124
3731
  to: PLUGIN_ID,
3125
3732
  icon: Icons.Feather,
@@ -3128,14 +3735,24 @@ const index = {
3128
3735
  defaultMessage: "Content Manager"
3129
3736
  },
3130
3737
  permissions: [],
3131
- Component: () => Promise.resolve().then(() => require("./layout-BqtLA6Lb.js")).then((mod) => ({ default: mod.Layout }))
3738
+ position: 1
3739
+ });
3740
+ app.router.addRoute({
3741
+ path: "content-manager/*",
3742
+ lazy: async () => {
3743
+ const { Layout } = await Promise.resolve().then(() => require("./layout-Ciz224q5.js"));
3744
+ return {
3745
+ Component: Layout
3746
+ };
3747
+ },
3748
+ children: routes
3132
3749
  });
3133
3750
  app.registerPlugin(cm.config);
3134
3751
  },
3135
3752
  async registerTrads({ locales }) {
3136
3753
  const importedTrads = await Promise.all(
3137
3754
  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 }) => {
3755
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-fbKQxLGn.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
3139
3756
  return {
3140
3757
  data: prefixPluginTranslations(data, PLUGIN_ID),
3141
3758
  locale
@@ -3152,6 +3769,7 @@ const index = {
3152
3769
  }
3153
3770
  };
3154
3771
  exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
3772
+ exports.BulkActionsRenderer = BulkActionsRenderer;
3155
3773
  exports.COLLECTION_TYPES = COLLECTION_TYPES;
3156
3774
  exports.CREATOR_FIELDS = CREATOR_FIELDS;
3157
3775
  exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
@@ -3178,7 +3796,6 @@ exports.getDisplayName = getDisplayName;
3178
3796
  exports.getMainField = getMainField;
3179
3797
  exports.getTranslation = getTranslation;
3180
3798
  exports.index = index;
3181
- exports.routes = routes;
3182
3799
  exports.setInitialData = setInitialData;
3183
3800
  exports.useContentTypeSchema = useContentTypeSchema;
3184
3801
  exports.useDoc = useDoc;
@@ -3192,4 +3809,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
3192
3809
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
3193
3810
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
3194
3811
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
3195
- //# sourceMappingURL=index-DNa1J4HE.js.map
3812
+ //# sourceMappingURL=index-BOZx6IMg.js.map