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

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 (168) 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-WRPUXGd6.js} +3 -3
  6. package/dist/_chunks/{ComponentConfigurationPage-2iOVVhqV.js.map → ComponentConfigurationPage-WRPUXGd6.js.map} +1 -1
  7. package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs → ComponentConfigurationPage-gdUj_t-O.mjs} +3 -3
  8. package/dist/_chunks/{ComponentConfigurationPage-DjQBdcKF.mjs.map → ComponentConfigurationPage-gdUj_t-O.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-BwuIPOJG.mjs} +3 -3
  14. package/dist/_chunks/{EditConfigurationPage-BoBb-DLH.mjs.map → EditConfigurationPage-BwuIPOJG.mjs.map} +1 -1
  15. package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js → EditConfigurationPage-C1vjMBgy.js} +3 -3
  16. package/dist/_chunks/{EditConfigurationPage-B7dw5_cS.js.map → EditConfigurationPage-C1vjMBgy.js.map} +1 -1
  17. package/dist/_chunks/{EditViewPage-aUnqL-63.mjs → EditViewPage-0MiFkXa8.mjs} +47 -47
  18. package/dist/_chunks/EditViewPage-0MiFkXa8.mjs.map +1 -0
  19. package/dist/_chunks/{EditViewPage-KRG56aCq.js → EditViewPage-DbcGfyqK.js} +46 -48
  20. package/dist/_chunks/EditViewPage-DbcGfyqK.js.map +1 -0
  21. package/dist/_chunks/{Field-kVFO4ZKB.mjs → Field-BDMSCcy5.mjs} +585 -705
  22. package/dist/_chunks/Field-BDMSCcy5.mjs.map +1 -0
  23. package/dist/_chunks/{Field-kq1c2TF1.js → Field-BG1xu38N.js} +637 -758
  24. package/dist/_chunks/Field-BG1xu38N.js.map +1 -0
  25. package/dist/_chunks/{Form-CQ67ZifP.js → Form-9BnFyUjy.js} +35 -37
  26. package/dist/_chunks/Form-9BnFyUjy.js.map +1 -0
  27. package/dist/_chunks/{Form-Jgh5hGTu.mjs → Form-CPVWavB8.mjs} +35 -36
  28. package/dist/_chunks/Form-CPVWavB8.mjs.map +1 -0
  29. package/dist/_chunks/{History-DKhZAPcK.mjs → History-BVpd8LP3.mjs} +121 -48
  30. package/dist/_chunks/History-BVpd8LP3.mjs.map +1 -0
  31. package/dist/_chunks/{History-BLEnudTX.js → History-BWWxLt2Z.js} +122 -50
  32. package/dist/_chunks/History-BWWxLt2Z.js.map +1 -0
  33. package/dist/_chunks/{ListConfigurationPage-Zso_LUjn.js → ListConfigurationPage-6swzjdAZ.js} +53 -56
  34. package/dist/_chunks/ListConfigurationPage-6swzjdAZ.js.map +1 -0
  35. package/dist/_chunks/{ListConfigurationPage-nrXcxNYi.mjs → ListConfigurationPage-DozVMKcR.mjs} +49 -51
  36. package/dist/_chunks/ListConfigurationPage-DozVMKcR.mjs.map +1 -0
  37. package/dist/_chunks/{ListViewPage-DsaOakWQ.js → ListViewPage-BlzfjS2Q.js} +80 -105
  38. package/dist/_chunks/ListViewPage-BlzfjS2Q.js.map +1 -0
  39. package/dist/_chunks/{ListViewPage-ChhYmA-L.mjs → ListViewPage-Ds0ulgfG.mjs} +75 -100
  40. package/dist/_chunks/ListViewPage-Ds0ulgfG.mjs.map +1 -0
  41. package/dist/_chunks/{NoContentTypePage-BrdFcN33.mjs → NoContentTypePage-BH11kaKt.mjs} +3 -3
  42. package/dist/_chunks/NoContentTypePage-BH11kaKt.mjs.map +1 -0
  43. package/dist/_chunks/{NoContentTypePage-DPCuS9Y1.js → NoContentTypePage-D2nCCWEl.js} +3 -3
  44. package/dist/_chunks/NoContentTypePage-D2nCCWEl.js.map +1 -0
  45. package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs → NoPermissionsPage-BT2Tn0D_.mjs} +2 -2
  46. package/dist/_chunks/{NoPermissionsPage-B9dqrtTy.mjs.map → NoPermissionsPage-BT2Tn0D_.mjs.map} +1 -1
  47. package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js → NoPermissionsPage-DN_JlsU2.js} +2 -2
  48. package/dist/_chunks/{NoPermissionsPage-DdyOfdKb.js.map → NoPermissionsPage-DN_JlsU2.js.map} +1 -1
  49. package/dist/_chunks/{Relations-CY8Isqdu.js → Relations-CcgFTcWo.js} +70 -61
  50. package/dist/_chunks/Relations-CcgFTcWo.js.map +1 -0
  51. package/dist/_chunks/{Relations-DjFiYd7-.mjs → Relations-Dnag3fhV.mjs} +66 -56
  52. package/dist/_chunks/Relations-Dnag3fhV.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-CWpLBSt0.js} +1391 -808
  58. package/dist/_chunks/index-CWpLBSt0.js.map +1 -0
  59. package/dist/_chunks/{index-CAc9yTnx.mjs → index-JNNNKUHs.mjs} +1465 -881
  60. package/dist/_chunks/index-JNNNKUHs.mjs.map +1 -0
  61. package/dist/_chunks/{layout-BqtLA6Lb.js → layout--iHdZzRk.js} +26 -23
  62. package/dist/_chunks/layout--iHdZzRk.js.map +1 -0
  63. package/dist/_chunks/{layout-CXsHbc3E.mjs → layout-DC503LnF.mjs} +24 -19
  64. package/dist/_chunks/layout-DC503LnF.mjs.map +1 -0
  65. package/dist/_chunks/{relations-BHY_KDJ_.js → relations-BbHizA5K.js} +2 -2
  66. package/dist/_chunks/{relations-BHY_KDJ_.js.map → relations-BbHizA5K.js.map} +1 -1
  67. package/dist/_chunks/{relations-mMFEcZRq.mjs → relations-CTje5t-a.mjs} +2 -2
  68. package/dist/_chunks/{relations-mMFEcZRq.mjs.map → relations-CTje5t-a.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 +8 -7
  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/Component/Input.d.ts +2 -2
  91. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  92. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  93. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +10 -18
  94. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  95. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  96. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  97. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +59 -52
  98. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  99. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  100. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  101. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  102. package/dist/admin/src/services/api.d.ts +2 -3
  103. package/dist/admin/src/services/components.d.ts +2 -2
  104. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  105. package/dist/admin/src/services/documents.d.ts +29 -17
  106. package/dist/admin/src/services/init.d.ts +2 -2
  107. package/dist/admin/src/services/relations.d.ts +3 -3
  108. package/dist/admin/src/services/uid.d.ts +3 -3
  109. package/dist/admin/src/utils/api.d.ts +4 -18
  110. package/dist/admin/src/utils/validation.d.ts +1 -6
  111. package/dist/server/index.js +285 -197
  112. package/dist/server/index.js.map +1 -1
  113. package/dist/server/index.mjs +287 -199
  114. package/dist/server/index.mjs.map +1 -1
  115. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  116. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  117. package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
  118. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  119. package/dist/server/src/controllers/validation/dimensions.d.ts +9 -0
  120. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  121. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  122. package/dist/server/src/history/services/history.d.ts.map +1 -1
  123. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  124. package/dist/server/src/index.d.ts +17 -33
  125. package/dist/server/src/index.d.ts.map +1 -1
  126. package/dist/server/src/services/document-manager.d.ts +11 -6
  127. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  128. package/dist/server/src/services/document-metadata.d.ts +8 -29
  129. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  130. package/dist/server/src/services/index.d.ts +17 -33
  131. package/dist/server/src/services/index.d.ts.map +1 -1
  132. package/dist/server/src/services/utils/populate.d.ts +8 -1
  133. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  134. package/dist/shared/contracts/collection-types.d.ts +14 -6
  135. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  136. package/dist/shared/contracts/relations.d.ts +2 -2
  137. package/dist/shared/contracts/relations.d.ts.map +1 -1
  138. package/package.json +13 -14
  139. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  140. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  141. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  142. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  143. package/dist/_chunks/EditViewPage-KRG56aCq.js.map +0 -1
  144. package/dist/_chunks/EditViewPage-aUnqL-63.mjs.map +0 -1
  145. package/dist/_chunks/Field-kVFO4ZKB.mjs.map +0 -1
  146. package/dist/_chunks/Field-kq1c2TF1.js.map +0 -1
  147. package/dist/_chunks/Form-CQ67ZifP.js.map +0 -1
  148. package/dist/_chunks/Form-Jgh5hGTu.mjs.map +0 -1
  149. package/dist/_chunks/History-BLEnudTX.js.map +0 -1
  150. package/dist/_chunks/History-DKhZAPcK.mjs.map +0 -1
  151. package/dist/_chunks/ListConfigurationPage-Zso_LUjn.js.map +0 -1
  152. package/dist/_chunks/ListConfigurationPage-nrXcxNYi.mjs.map +0 -1
  153. package/dist/_chunks/ListViewPage-ChhYmA-L.mjs.map +0 -1
  154. package/dist/_chunks/ListViewPage-DsaOakWQ.js.map +0 -1
  155. package/dist/_chunks/NoContentTypePage-BrdFcN33.mjs.map +0 -1
  156. package/dist/_chunks/NoContentTypePage-DPCuS9Y1.js.map +0 -1
  157. package/dist/_chunks/Relations-CY8Isqdu.js.map +0 -1
  158. package/dist/_chunks/Relations-DjFiYd7-.mjs.map +0 -1
  159. package/dist/_chunks/index-CAc9yTnx.mjs.map +0 -1
  160. package/dist/_chunks/index-DNa1J4HE.js.map +0 -1
  161. package/dist/_chunks/layout-BqtLA6Lb.js.map +0 -1
  162. package/dist/_chunks/layout-CXsHbc3E.mjs.map +0 -1
  163. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  164. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  165. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  166. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  167. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  168. package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
@@ -1,17 +1,15 @@
1
- import { ClockCounterClockwise, CrossCircle, More, WarningCircle, Cog, Pencil, Trash, ChevronRight, Duplicate, Feather } from "@strapi/icons";
1
+ import { ClockCounterClockwise, CrossCircle, More, WarningCircle, ListPlus, Pencil, Trash, Check, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, Feather } from "@strapi/icons";
2
2
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
3
- import { useStrapiApp, useQueryParams, createContext, useAuth, useRBAC, Page, getFetchClient, translatedErrors, useNotification, useAPIErrorHandler, useTracking, useForm, BackButton, DescriptionComponentRenderer } from "@strapi/admin/strapi-admin";
3
+ import { useStrapiApp, useQueryParams, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useTracking, useForm, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
4
4
  import { stringify } from "qs";
5
5
  import { useIntl } from "react-intl";
6
- import { useNavigate, useParams, Navigate, useMatch, NavLink } from "react-router-dom";
6
+ import { useNavigate, useParams, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
7
7
  import * as React from "react";
8
8
  import { lazy } from "react";
9
- import { Menu, VisuallyHidden, Flex, Typography, Dialog, DialogBody, DialogFooter, Button, ModalLayout, ModalHeader, ModalBody, Box, Radio, Status, SingleSelect, SingleSelectOption, LinkButton } from "@strapi/design-system";
10
- import styled from "styled-components";
9
+ import { Button, Menu, VisuallyHidden, Flex, Typography, Dialog, Modal, Radio, Status, SingleSelect, SingleSelectOption, Box, Loader, IconButton, Tooltip, LinkButton } from "@strapi/design-system";
10
+ import { styled } from "styled-components";
11
11
  import * as yup from "yup";
12
12
  import { ValidationError } from "yup";
13
- import { createApi } from "@reduxjs/toolkit/query/react";
14
- import { isAxiosError } from "axios";
15
13
  import pipe from "lodash/fp/pipe";
16
14
  import { intervalToDuration, isPast } from "date-fns";
17
15
  import { createSlice, combineReducers } from "@reduxjs/toolkit";
@@ -157,9 +155,8 @@ const DocumentRBAC = ({ children, permissions }) => {
157
155
  const name = removeNumericalStrings(fieldName.split("."));
158
156
  const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
159
157
  if (fieldType === "component") {
160
- const componentOrDynamicZoneFields = componentFieldNames.map((field) => field.split("."));
161
- return componentOrDynamicZoneFields.some((field) => {
162
- return field.includes(fieldName);
158
+ return componentFieldNames.some((field) => {
159
+ return field.includes(name.join("."));
163
160
  });
164
161
  }
165
162
  if (name.length > 1) {
@@ -189,78 +186,8 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
189
186
  (field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
190
187
  );
191
188
  const removeNumericalStrings = (arr) => arr.filter((item) => isNaN(Number(item)));
192
- const buildValidParams = (query) => {
193
- if (!query)
194
- return query;
195
- const { plugins: _, ...validQueryParams } = {
196
- ...query,
197
- ...Object.values(query?.plugins ?? {}).reduce(
198
- (acc, current) => Object.assign(acc, current),
199
- {}
200
- )
201
- };
202
- if ("_q" in validQueryParams) {
203
- validQueryParams._q = encodeURIComponent(validQueryParams._q);
204
- }
205
- return validQueryParams;
206
- };
207
- const axiosBaseQuery = () => async (query, { signal }) => {
208
- try {
209
- const { get, post, del, put } = getFetchClient();
210
- if (typeof query === "string") {
211
- const result = await get(query, { signal });
212
- return { data: result.data };
213
- } else {
214
- const { url, method = "GET", data, config } = query;
215
- if (method === "POST") {
216
- const result2 = await post(url, data, { ...config, signal });
217
- return { data: result2.data };
218
- }
219
- if (method === "DELETE") {
220
- const result2 = await del(url, { ...config, signal });
221
- return { data: result2.data };
222
- }
223
- if (method === "PUT") {
224
- const result2 = await put(url, data, { ...config, signal });
225
- return { data: result2.data };
226
- }
227
- const result = await get(url, { ...config, signal });
228
- return { data: result.data };
229
- }
230
- } catch (err) {
231
- if (isAxiosError(err)) {
232
- if (typeof err.response?.data === "object" && err.response?.data !== null && "error" in err.response?.data) {
233
- return { data: void 0, error: err.response?.data.error };
234
- } else {
235
- return {
236
- data: void 0,
237
- error: {
238
- name: "UnknownError",
239
- message: "There was an unknown error response from the API",
240
- details: err.response?.data,
241
- status: err.response?.status
242
- }
243
- };
244
- }
245
- }
246
- const error = err;
247
- return {
248
- data: void 0,
249
- error: {
250
- name: error.name,
251
- message: error.message,
252
- stack: error.stack
253
- }
254
- };
255
- }
256
- };
257
- const isBaseQueryError = (error) => {
258
- return error.name !== void 0;
259
- };
260
- const contentManagerApi = createApi({
261
- reducerPath: "contentManagerApi",
262
- baseQuery: axiosBaseQuery(),
263
- tagTypes: [
189
+ const contentManagerApi = adminApi.enhanceEndpoints({
190
+ addTagTypes: [
264
191
  "ComponentConfiguration",
265
192
  "ContentTypesConfiguration",
266
193
  "ContentTypeSettings",
@@ -268,8 +195,7 @@ const contentManagerApi = createApi({
268
195
  "InitialData",
269
196
  "HistoryVersion",
270
197
  "Relations"
271
- ],
272
- endpoints: () => ({})
198
+ ]
273
199
  });
274
200
  const documentApi = contentManagerApi.injectEndpoints({
275
201
  endpoints: (builder) => ({
@@ -325,12 +251,15 @@ const documentApi = contentManagerApi.injectEndpoints({
325
251
  ]
326
252
  }),
327
253
  deleteManyDocuments: builder.mutation({
328
- query: ({ model, ...body }) => ({
254
+ query: ({ model, params, ...body }) => ({
329
255
  url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
330
256
  method: "POST",
331
- data: body
257
+ data: body,
258
+ config: {
259
+ params
260
+ }
332
261
  }),
333
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
262
+ invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
334
263
  }),
335
264
  discardDocument: builder.mutation({
336
265
  query: ({ collectionType, model, documentId, params }) => ({
@@ -441,10 +370,13 @@ const documentApi = contentManagerApi.injectEndpoints({
441
370
  }
442
371
  }),
443
372
  publishManyDocuments: builder.mutation({
444
- query: ({ model, ...body }) => ({
373
+ query: ({ model, params, ...body }) => ({
445
374
  url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
446
375
  method: "POST",
447
- data: body
376
+ data: body,
377
+ config: {
378
+ params
379
+ }
448
380
  }),
449
381
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
450
382
  }),
@@ -486,10 +418,13 @@ const documentApi = contentManagerApi.injectEndpoints({
486
418
  }
487
419
  }),
488
420
  unpublishManyDocuments: builder.mutation({
489
- query: ({ model, ...body }) => ({
421
+ query: ({ model, params, ...body }) => ({
490
422
  url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
491
423
  method: "POST",
492
- data: body
424
+ data: body,
425
+ config: {
426
+ params
427
+ }
493
428
  }),
494
429
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
495
430
  })
@@ -513,6 +448,24 @@ const {
513
448
  useUnpublishDocumentMutation,
514
449
  useUnpublishManyDocumentsMutation
515
450
  } = documentApi;
451
+ const buildValidParams = (query) => {
452
+ if (!query)
453
+ return query;
454
+ const { plugins: _, ...validQueryParams } = {
455
+ ...query,
456
+ ...Object.values(query?.plugins ?? {}).reduce(
457
+ (acc, current) => Object.assign(acc, current),
458
+ {}
459
+ )
460
+ };
461
+ if ("_q" in validQueryParams) {
462
+ validQueryParams._q = encodeURIComponent(validQueryParams._q);
463
+ }
464
+ return validQueryParams;
465
+ };
466
+ const isBaseQueryError = (error) => {
467
+ return error.name !== void 0;
468
+ };
516
469
  const createYupSchema = (attributes = {}, components = {}) => {
517
470
  const createModelSchema = (attributes2) => yup.object().shape(
518
471
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
@@ -552,10 +505,14 @@ const createYupSchema = (attributes = {}, components = {}) => {
552
505
  yup.array().of(
553
506
  yup.lazy(
554
507
  (data) => {
555
- const { attributes: attributes3 } = components[data.__component];
556
- return yup.object().shape({
508
+ const attributes3 = components?.[data?.__component]?.attributes;
509
+ const validation = yup.object().shape({
557
510
  __component: yup.string().required().oneOf(Object.keys(components))
558
- }).nullable(false).concat(createModelSchema(attributes3));
511
+ }).nullable(false);
512
+ if (!attributes3) {
513
+ return validation;
514
+ }
515
+ return validation.concat(createModelSchema(attributes3));
559
516
  }
560
517
  )
561
518
  )
@@ -565,11 +522,25 @@ const createYupSchema = (attributes = {}, components = {}) => {
565
522
  return {
566
523
  ...acc,
567
524
  [name]: transformSchema(
568
- yup.array().of(
569
- yup.object().shape({
570
- id: yup.string().required()
571
- })
572
- )
525
+ yup.lazy((value) => {
526
+ if (!value) {
527
+ return yup.mixed().nullable(true);
528
+ } else if (Array.isArray(value)) {
529
+ return yup.array().of(
530
+ yup.object().shape({
531
+ id: yup.string().required()
532
+ })
533
+ );
534
+ } else if (typeof value === "object") {
535
+ return yup.object();
536
+ } else {
537
+ return yup.mixed().test(
538
+ "type-error",
539
+ "Relation values must be either null, an array of objects with {id} or an object.",
540
+ () => false
541
+ );
542
+ }
543
+ })
573
544
  )
574
545
  };
575
546
  default:
@@ -634,7 +605,12 @@ const addRequiredValidation = (attribute) => (schema) => {
634
605
  defaultMessage: "This field is required."
635
606
  });
636
607
  }
637
- return schema.nullable();
608
+ return schema?.nullable ? schema.nullable() : (
609
+ // In some cases '.nullable' will not be available on the schema.
610
+ // e.g. when the schema has been built using yup.lazy (e.g. for relations).
611
+ // In these cases we should just return the schema as it is.
612
+ schema
613
+ );
638
614
  };
639
615
  const addMinLengthValidation = (attribute) => (schema) => {
640
616
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
@@ -706,24 +682,6 @@ const addRegexValidation = (attribute) => (schema) => {
706
682
  }
707
683
  return schema;
708
684
  };
709
- const extractValuesFromYupError = (errorType, errorParams) => {
710
- if (!errorType || !errorParams) {
711
- return {};
712
- }
713
- return {
714
- [errorType]: errorParams[errorType]
715
- };
716
- };
717
- const getInnerErrors = (error) => (error?.inner || []).reduce((acc, currentError) => {
718
- if (currentError.path) {
719
- acc[currentError.path.split("[").join(".").split("]").join("")] = {
720
- id: currentError.message,
721
- defaultMessage: currentError.message,
722
- values: extractValuesFromYupError(currentError?.type, currentError?.params)
723
- };
724
- }
725
- return acc;
726
- }, {});
727
685
  const initApi = contentManagerApi.injectEndpoints({
728
686
  endpoints: (builder) => ({
729
687
  getInitialData: builder.query({
@@ -737,27 +695,20 @@ const { useGetInitialDataQuery } = initApi;
737
695
  const useContentTypeSchema = (model) => {
738
696
  const { toggleNotification } = useNotification();
739
697
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
740
- const { components, contentType, contentTypes, error, isLoading, isFetching } = useGetInitialDataQuery(void 0, {
741
- selectFromResult: (res) => {
742
- const contentType2 = res.data?.contentTypes.find((ct) => ct.uid === model);
743
- const componentsByKey = res.data?.components.reduce(
744
- (acc, component) => {
745
- acc[component.uid] = component;
746
- return acc;
747
- },
748
- {}
749
- );
750
- const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
751
- return {
752
- isLoading: res.isLoading,
753
- isFetching: res.isFetching,
754
- error: res.error,
755
- components: Object.keys(components2).length === 0 ? void 0 : components2,
756
- contentType: contentType2,
757
- contentTypes: res.data?.contentTypes ?? []
758
- };
759
- }
760
- });
698
+ const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
699
+ const { components, contentType, contentTypes } = React.useMemo(() => {
700
+ const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
701
+ const componentsByKey = data?.components.reduce((acc, component) => {
702
+ acc[component.uid] = component;
703
+ return acc;
704
+ }, {});
705
+ const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
706
+ return {
707
+ components: Object.keys(components2).length === 0 ? void 0 : components2,
708
+ contentType: contentType2,
709
+ contentTypes: data?.contentTypes ?? []
710
+ };
711
+ }, [model, data]);
761
712
  React.useEffect(() => {
762
713
  if (error) {
763
714
  toggleNotification({
@@ -840,7 +791,7 @@ const useDocument = (args, opts) => {
840
791
  return null;
841
792
  } catch (error2) {
842
793
  if (error2 instanceof ValidationError) {
843
- return getInnerErrors(error2);
794
+ return getYupValidationErrors(error2);
844
795
  }
845
796
  throw error2;
846
797
  }
@@ -936,14 +887,53 @@ const useDocumentActions = () => {
936
887
  },
937
888
  [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
938
889
  );
890
+ const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
891
+ const deleteMany = React.useCallback(
892
+ async ({ model, documentIds, params }) => {
893
+ try {
894
+ trackUsage("willBulkDeleteEntries");
895
+ const res = await deleteManyDocuments({
896
+ model,
897
+ documentIds,
898
+ params
899
+ });
900
+ if ("error" in res) {
901
+ toggleNotification({
902
+ type: "danger",
903
+ message: formatAPIError(res.error)
904
+ });
905
+ return { error: res.error };
906
+ }
907
+ toggleNotification({
908
+ type: "success",
909
+ title: formatMessage({
910
+ id: getTranslation("success.records.delete"),
911
+ defaultMessage: "Successfully deleted."
912
+ }),
913
+ message: ""
914
+ });
915
+ trackUsage("didBulkDeleteEntries");
916
+ return res.data;
917
+ } catch (err) {
918
+ toggleNotification({
919
+ type: "danger",
920
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
921
+ });
922
+ trackUsage("didNotBulkDeleteEntries");
923
+ throw err;
924
+ }
925
+ },
926
+ [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
927
+ );
939
928
  const [discardDocument] = useDiscardDocumentMutation();
940
929
  const discard = React.useCallback(
941
- async ({ collectionType, model, documentId }) => {
930
+ async ({ collectionType, model, documentId, params }) => {
942
931
  try {
943
932
  const res = await discardDocument({
944
933
  collectionType,
945
934
  model,
946
- documentId
935
+ documentId,
936
+ params
947
937
  });
948
938
  if ("error" in res) {
949
939
  toggleNotification({
@@ -1005,6 +995,43 @@ const useDocumentActions = () => {
1005
995
  },
1006
996
  [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1007
997
  );
998
+ const [publishManyDocuments] = usePublishManyDocumentsMutation();
999
+ const publishMany = React.useCallback(
1000
+ async ({ model, documentIds, params }) => {
1001
+ try {
1002
+ const res = await publishManyDocuments({
1003
+ model,
1004
+ documentIds,
1005
+ params
1006
+ });
1007
+ if ("error" in res) {
1008
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1009
+ return { error: res.error };
1010
+ }
1011
+ toggleNotification({
1012
+ type: "success",
1013
+ message: formatMessage({
1014
+ id: getTranslation("success.record.publish"),
1015
+ defaultMessage: "Published document"
1016
+ })
1017
+ });
1018
+ return res.data;
1019
+ } catch (err) {
1020
+ toggleNotification({
1021
+ type: "danger",
1022
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1023
+ });
1024
+ throw err;
1025
+ }
1026
+ },
1027
+ [
1028
+ // trackUsage,
1029
+ publishManyDocuments,
1030
+ toggleNotification,
1031
+ formatMessage,
1032
+ formatAPIError
1033
+ ]
1034
+ );
1008
1035
  const [updateDocument] = useUpdateDocumentMutation();
1009
1036
  const update = React.useCallback(
1010
1037
  async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
@@ -1079,6 +1106,41 @@ const useDocumentActions = () => {
1079
1106
  },
1080
1107
  [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1081
1108
  );
1109
+ const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1110
+ const unpublishMany = React.useCallback(
1111
+ async ({ model, documentIds, params }) => {
1112
+ try {
1113
+ trackUsage("willBulkUnpublishEntries");
1114
+ const res = await unpublishManyDocuments({
1115
+ model,
1116
+ documentIds,
1117
+ params
1118
+ });
1119
+ if ("error" in res) {
1120
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1121
+ return { error: res.error };
1122
+ }
1123
+ trackUsage("didBulkUnpublishEntries");
1124
+ toggleNotification({
1125
+ type: "success",
1126
+ title: formatMessage({
1127
+ id: getTranslation("success.records.unpublish"),
1128
+ defaultMessage: "Successfully unpublished."
1129
+ }),
1130
+ message: ""
1131
+ });
1132
+ return res.data;
1133
+ } catch (err) {
1134
+ toggleNotification({
1135
+ type: "danger",
1136
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1137
+ });
1138
+ trackUsage("didNotBulkUnpublishEntries");
1139
+ throw err;
1140
+ }
1141
+ },
1142
+ [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1143
+ );
1082
1144
  const [createDocument] = useCreateDocumentMutation();
1083
1145
  const create = React.useCallback(
1084
1146
  async ({ model, params }, data, trackerProperty) => {
@@ -1192,15 +1254,18 @@ const useDocumentActions = () => {
1192
1254
  clone,
1193
1255
  create,
1194
1256
  delete: _delete,
1257
+ deleteMany,
1195
1258
  discard,
1196
1259
  getDocument,
1197
1260
  publish,
1261
+ publishMany,
1198
1262
  unpublish,
1263
+ unpublishMany,
1199
1264
  update
1200
1265
  };
1201
1266
  };
1202
1267
  const ProtectedHistoryPage = lazy(
1203
- () => import("./History-DKhZAPcK.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1268
+ () => import("./History-BVpd8LP3.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1204
1269
  );
1205
1270
  const routes$1 = [
1206
1271
  {
@@ -1213,31 +1278,31 @@ const routes$1 = [
1213
1278
  }
1214
1279
  ];
1215
1280
  const ProtectedEditViewPage = lazy(
1216
- () => import("./EditViewPage-aUnqL-63.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1281
+ () => import("./EditViewPage-0MiFkXa8.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1217
1282
  );
1218
1283
  const ProtectedListViewPage = lazy(
1219
- () => import("./ListViewPage-ChhYmA-L.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1284
+ () => import("./ListViewPage-Ds0ulgfG.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1220
1285
  );
1221
1286
  const ProtectedListConfiguration = lazy(
1222
- () => import("./ListConfigurationPage-nrXcxNYi.mjs").then((mod) => ({
1287
+ () => import("./ListConfigurationPage-DozVMKcR.mjs").then((mod) => ({
1223
1288
  default: mod.ProtectedListConfiguration
1224
1289
  }))
1225
1290
  );
1226
1291
  const ProtectedEditConfigurationPage = lazy(
1227
- () => import("./EditConfigurationPage-BoBb-DLH.mjs").then((mod) => ({
1292
+ () => import("./EditConfigurationPage-BwuIPOJG.mjs").then((mod) => ({
1228
1293
  default: mod.ProtectedEditConfigurationPage
1229
1294
  }))
1230
1295
  );
1231
1296
  const ProtectedComponentConfigurationPage = lazy(
1232
- () => import("./ComponentConfigurationPage-DjQBdcKF.mjs").then((mod) => ({
1297
+ () => import("./ComponentConfigurationPage-gdUj_t-O.mjs").then((mod) => ({
1233
1298
  default: mod.ProtectedComponentConfigurationPage
1234
1299
  }))
1235
1300
  );
1236
1301
  const NoPermissions = lazy(
1237
- () => import("./NoPermissionsPage-B9dqrtTy.mjs").then((mod) => ({ default: mod.NoPermissions }))
1302
+ () => import("./NoPermissionsPage-BT2Tn0D_.mjs").then((mod) => ({ default: mod.NoPermissions }))
1238
1303
  );
1239
1304
  const NoContentType = lazy(
1240
- () => import("./NoContentTypePage-BrdFcN33.mjs").then((mod) => ({ default: mod.NoContentType }))
1305
+ () => import("./NoContentTypePage-BH11kaKt.mjs").then((mod) => ({ default: mod.NoContentType }))
1241
1306
  );
1242
1307
  const CollectionTypePages = () => {
1243
1308
  const { collectionType } = useParams();
@@ -1427,7 +1492,7 @@ const DocumentActionsMenu = ({
1427
1492
  variant,
1428
1493
  children: [
1429
1494
  /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
1430
- /* @__PURE__ */ jsx(VisuallyHidden, { as: "span", children: label || formatMessage({
1495
+ /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: label || formatMessage({
1431
1496
  id: "content-manager.containers.edit.panels.default.more-actions",
1432
1497
  defaultMessage: "More document actions"
1433
1498
  }) })
@@ -1443,7 +1508,7 @@ const DocumentActionsMenu = ({
1443
1508
  onSelect: handleClick(action),
1444
1509
  display: "block",
1445
1510
  children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
1446
- /* @__PURE__ */ jsxs(Flex, { color: convertActionVariantToColor(action.variant), gap: 2, as: "span", children: [
1511
+ /* @__PURE__ */ jsxs(Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1447
1512
  action.icon,
1448
1513
  action.label
1449
1514
  ] }),
@@ -1527,61 +1592,42 @@ const DocumentActionConfirmDialog = ({
1527
1592
  }
1528
1593
  onClose();
1529
1594
  };
1530
- return /* @__PURE__ */ jsxs(Dialog, { isOpen, title, onClose: handleClose, children: [
1531
- /* @__PURE__ */ jsx(DialogBody, { children: content }),
1532
- /* @__PURE__ */ jsx(
1533
- DialogFooter,
1534
- {
1535
- startAction: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", children: formatMessage({
1536
- id: "app.components.Button.cancel",
1537
- defaultMessage: "Cancel"
1538
- }) }),
1539
- endAction: /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
1540
- id: "app.components.Button.confirm",
1541
- defaultMessage: "Confirm"
1542
- }) })
1543
- }
1544
- )
1545
- ] });
1595
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
1596
+ /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
1597
+ /* @__PURE__ */ jsx(Dialog.Body, { children: content }),
1598
+ /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
1599
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
1600
+ id: "app.components.Button.cancel",
1601
+ defaultMessage: "Cancel"
1602
+ }) }) }),
1603
+ /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
1604
+ id: "app.components.Button.confirm",
1605
+ defaultMessage: "Confirm"
1606
+ }) })
1607
+ ] })
1608
+ ] }) });
1546
1609
  };
1547
1610
  const DocumentActionModal = ({
1548
1611
  isOpen,
1549
1612
  title,
1550
1613
  onClose,
1551
1614
  footer: Footer,
1552
- content,
1615
+ content: Content,
1553
1616
  onModalClose
1554
1617
  }) => {
1555
- const id = React.useId();
1556
- if (!isOpen) {
1557
- return null;
1558
- }
1559
1618
  const handleClose = () => {
1560
1619
  if (onClose) {
1561
1620
  onClose();
1562
1621
  }
1563
1622
  onModalClose();
1564
1623
  };
1565
- return /* @__PURE__ */ jsxs(ModalLayout, { borderRadius: "4px", overflow: "hidden", onClose: handleClose, labelledBy: id, children: [
1566
- /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", textColor: "neutral800", as: "h2", id, children: title }) }),
1567
- /* @__PURE__ */ jsx(ModalBody, { children: content }),
1568
- /* @__PURE__ */ jsx(
1569
- Box,
1570
- {
1571
- paddingTop: 4,
1572
- paddingBottom: 4,
1573
- paddingLeft: 5,
1574
- paddingRight: 5,
1575
- borderWidth: "1px 0 0 0",
1576
- borderStyle: "solid",
1577
- borderColor: "neutral150",
1578
- background: "neutral100",
1579
- children: typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
1580
- }
1581
- )
1582
- ] });
1624
+ return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
1625
+ /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
1626
+ typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
1627
+ typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
1628
+ ] }) });
1583
1629
  };
1584
- const PublishAction = ({
1630
+ const PublishAction$1 = ({
1585
1631
  activeTab,
1586
1632
  documentId,
1587
1633
  model,
@@ -1666,7 +1712,7 @@ const PublishAction = ({
1666
1712
  }
1667
1713
  };
1668
1714
  };
1669
- PublishAction.type = "publish";
1715
+ PublishAction$1.type = "publish";
1670
1716
  const UpdateAction = ({
1671
1717
  activeTab,
1672
1718
  documentId,
@@ -1781,7 +1827,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
1781
1827
  KEEP: "keep",
1782
1828
  DISCARD: "discard"
1783
1829
  };
1784
- const UnpublishAction = ({
1830
+ const UnpublishAction$1 = ({
1785
1831
  activeTab,
1786
1832
  documentId,
1787
1833
  model,
@@ -1797,10 +1843,8 @@ const UnpublishAction = ({
1797
1843
  const { toggleNotification } = useNotification();
1798
1844
  const [shouldKeepDraft, setShouldKeepDraft] = React.useState(true);
1799
1845
  const isDocumentModified = document?.status === "modified";
1800
- const handleChange = (e) => {
1801
- if ("value" in e.target) {
1802
- setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1803
- }
1846
+ const handleChange = (value) => {
1847
+ setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1804
1848
  };
1805
1849
  if (!schema?.options?.draftAndPublish) {
1806
1850
  return null;
@@ -1844,45 +1888,30 @@ const UnpublishAction = ({
1844
1888
  content: /* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
1845
1889
  /* @__PURE__ */ jsxs(Flex, { width: "100%", direction: "column", gap: 2, children: [
1846
1890
  /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
1847
- /* @__PURE__ */ jsx(Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
1891
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1848
1892
  id: "content-manager.actions.unpublish.dialog.body",
1849
1893
  defaultMessage: "Are you sure?"
1850
1894
  }) })
1851
1895
  ] }),
1852
1896
  /* @__PURE__ */ jsxs(
1853
- Flex,
1897
+ Radio.Group,
1854
1898
  {
1855
- onChange: handleChange,
1856
- direction: "column",
1857
- alignItems: "flex-start",
1858
- as: "fieldset",
1859
- gap: 3,
1899
+ defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
1900
+ name: "discard-options",
1901
+ "aria-label": formatMessage({
1902
+ id: "content-manager.actions.unpublish.dialog.radio-label",
1903
+ defaultMessage: "Choose an option to unpublish the document."
1904
+ }),
1905
+ onValueChange: handleChange,
1860
1906
  children: [
1861
- /* @__PURE__ */ jsx(VisuallyHidden, { as: "legend" }),
1862
- /* @__PURE__ */ jsx(
1863
- Radio,
1864
- {
1865
- checked: shouldKeepDraft,
1866
- value: UNPUBLISH_DRAFT_OPTIONS.KEEP,
1867
- name: "discard-options",
1868
- children: formatMessage({
1869
- id: "content-manager.actions.unpublish.dialog.option.keep-draft",
1870
- defaultMessage: "Keep draft"
1871
- })
1872
- }
1873
- ),
1874
- /* @__PURE__ */ jsx(
1875
- Radio,
1876
- {
1877
- checked: !shouldKeepDraft,
1878
- value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
1879
- name: "discard-options",
1880
- children: formatMessage({
1881
- id: "content-manager.actions.unpublish.dialog.option.replace-draft",
1882
- defaultMessage: "Replace draft"
1883
- })
1884
- }
1885
- )
1907
+ /* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
1908
+ id: "content-manager.actions.unpublish.dialog.option.keep-draft",
1909
+ defaultMessage: "Keep draft"
1910
+ }) }),
1911
+ /* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
1912
+ id: "content-manager.actions.unpublish.dialog.option.replace-draft",
1913
+ defaultMessage: "Replace draft"
1914
+ }) })
1886
1915
  ]
1887
1916
  }
1888
1917
  )
@@ -1915,7 +1944,7 @@ const UnpublishAction = ({
1915
1944
  position: ["panel", "table-row"]
1916
1945
  };
1917
1946
  };
1918
- UnpublishAction.type = "unpublish";
1947
+ UnpublishAction$1.type = "unpublish";
1919
1948
  const DiscardAction = ({
1920
1949
  activeTab,
1921
1950
  documentId,
@@ -1949,7 +1978,7 @@ const DiscardAction = ({
1949
1978
  }),
1950
1979
  content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
1951
1980
  /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
1952
- /* @__PURE__ */ jsx(Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
1981
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1953
1982
  id: "content-manager.actions.discard.dialog.body",
1954
1983
  defaultMessage: "Are you sure?"
1955
1984
  }) })
@@ -1971,7 +2000,7 @@ const StyledCrossCircle = styled(CrossCircle)`
1971
2000
  fill: currentColor;
1972
2001
  }
1973
2002
  `;
1974
- const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
2003
+ const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
1975
2004
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
1976
2005
  const RelativeTime = React.forwardRef(
1977
2006
  ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
@@ -2019,7 +2048,7 @@ const getDisplayName = ({
2019
2048
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2020
2049
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2021
2050
  const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
2022
- return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { as: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2051
+ return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2023
2052
  };
2024
2053
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2025
2054
  const { formatMessage } = useIntl();
@@ -2039,7 +2068,7 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2039
2068
  gap: "80px",
2040
2069
  alignItems: "flex-start",
2041
2070
  children: [
2042
- /* @__PURE__ */ jsx(Typography, { variant: "alpha", as: "h1", children: title }),
2071
+ /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
2043
2072
  /* @__PURE__ */ jsx(HeaderToolbar, {})
2044
2073
  ]
2045
2074
  }
@@ -2196,7 +2225,7 @@ const Information = ({ activeTab }) => {
2196
2225
  borderColor: "neutral150",
2197
2226
  direction: "column",
2198
2227
  marginTop: 2,
2199
- as: "dl",
2228
+ tag: "dl",
2200
2229
  padding: 5,
2201
2230
  gap: 3,
2202
2231
  alignItems: "flex-start",
@@ -2204,8 +2233,8 @@ const Information = ({ activeTab }) => {
2204
2233
  marginRight: "-0.4rem",
2205
2234
  width: "calc(100% + 8px)",
2206
2235
  children: information.map((info) => /* @__PURE__ */ jsxs(Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
2207
- /* @__PURE__ */ jsx(Typography, { as: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2208
- /* @__PURE__ */ jsx(Typography, { as: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2236
+ /* @__PURE__ */ jsx(Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2237
+ /* @__PURE__ */ jsx(Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2209
2238
  ] }, info.label))
2210
2239
  }
2211
2240
  );
@@ -2238,7 +2267,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2238
2267
  id: "app.links.configure-view",
2239
2268
  defaultMessage: "Configure the view"
2240
2269
  }),
2241
- icon: /* @__PURE__ */ jsx(StyledCog, {}),
2270
+ icon: /* @__PURE__ */ jsx(ListPlus, {}),
2242
2271
  onClick: () => {
2243
2272
  navigate(`../${collectionType}/${model}/configurations/edit`);
2244
2273
  },
@@ -2246,11 +2275,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2246
2275
  };
2247
2276
  };
2248
2277
  ConfigureTheViewAction.type = "configure-the-view";
2249
- const StyledCog = styled(Cog)`
2250
- path {
2251
- fill: currentColor;
2252
- }
2253
- `;
2254
2278
  const EditTheModelAction = ({ model }) => {
2255
2279
  const navigate = useNavigate();
2256
2280
  const { formatMessage } = useIntl();
@@ -2259,7 +2283,7 @@ const EditTheModelAction = ({ model }) => {
2259
2283
  id: "content-manager.link-to-ctb",
2260
2284
  defaultMessage: "Edit the model"
2261
2285
  }),
2262
- icon: /* @__PURE__ */ jsx(StyledPencil$1, {}),
2286
+ icon: /* @__PURE__ */ jsx(Pencil, {}),
2263
2287
  onClick: () => {
2264
2288
  navigate(`/plugins/content-type-builder/content-types/${model}`);
2265
2289
  },
@@ -2267,12 +2291,7 @@ const EditTheModelAction = ({ model }) => {
2267
2291
  };
2268
2292
  };
2269
2293
  EditTheModelAction.type = "edit-the-model";
2270
- const StyledPencil$1 = styled(Pencil)`
2271
- path {
2272
- fill: currentColor;
2273
- }
2274
- `;
2275
- const DeleteAction = ({ documentId, model, collectionType, document }) => {
2294
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2276
2295
  const navigate = useNavigate();
2277
2296
  const { formatMessage } = useIntl();
2278
2297
  const listViewPathMatch = useMatch(LIST_PATH);
@@ -2286,7 +2305,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2286
2305
  id: "content-manager.actions.delete.label",
2287
2306
  defaultMessage: "Delete document"
2288
2307
  }),
2289
- icon: /* @__PURE__ */ jsx(StyledTrash, {}),
2308
+ icon: /* @__PURE__ */ jsx(Trash, {}),
2290
2309
  dialog: {
2291
2310
  type: "dialog",
2292
2311
  title: formatMessage({
@@ -2295,7 +2314,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2295
2314
  }),
2296
2315
  content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2297
2316
  /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2298
- /* @__PURE__ */ jsx(Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2317
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2299
2318
  id: "content-manager.actions.delete.dialog.body",
2300
2319
  defaultMessage: "Are you sure?"
2301
2320
  }) })
@@ -2340,13 +2359,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2340
2359
  position: ["header", "table-row"]
2341
2360
  };
2342
2361
  };
2343
- DeleteAction.type = "delete";
2344
- const StyledTrash = styled(Trash)`
2345
- path {
2346
- fill: currentColor;
2347
- }
2348
- `;
2349
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction];
2362
+ DeleteAction$1.type = "delete";
2363
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2350
2364
  const Panels = () => {
2351
2365
  const isCloning = useMatch(CLONE_PATH) !== null;
2352
2366
  const [
@@ -2420,7 +2434,7 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
2420
2434
  Flex,
2421
2435
  {
2422
2436
  ref,
2423
- as: "aside",
2437
+ tag: "aside",
2424
2438
  "aria-labelledby": "additional-information",
2425
2439
  background: "neutral0",
2426
2440
  borderColor: "neutral150",
@@ -2435,669 +2449,1237 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
2435
2449
  justifyContent: "stretch",
2436
2450
  alignItems: "flex-start",
2437
2451
  children: [
2438
- /* @__PURE__ */ jsx(Typography, { as: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2452
+ /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2439
2453
  children
2440
2454
  ]
2441
2455
  }
2442
2456
  );
2443
2457
  });
2444
- const DEFAULT_BULK_ACTIONS = [];
2445
- const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
2446
- const { formatMessage } = useIntl();
2447
- const getDefaultErrorMessage = (reason) => {
2448
- switch (reason) {
2449
- case "relation":
2450
- return "Duplicating the relation could remove it from the original entry.";
2451
- case "unique":
2452
- return "Identical values in a unique field are not allowed";
2453
- default:
2454
- return reason;
2455
- }
2456
- };
2457
- return /* @__PURE__ */ jsxs(Fragment, { children: [
2458
- /* @__PURE__ */ jsx(Typography, { variant: "beta", children: formatMessage({
2459
- id: getTranslation("containers.list.autoCloneModal.title"),
2460
- defaultMessage: "This entry can't be duplicated directly."
2461
- }) }),
2462
- /* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage({
2463
- id: getTranslation("containers.list.autoCloneModal.description"),
2464
- defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
2465
- }) }) }),
2466
- /* @__PURE__ */ jsx(Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxs(
2467
- Flex,
2468
- {
2469
- direction: "column",
2470
- gap: 2,
2471
- alignItems: "flex-start",
2472
- borderColor: "neutral200",
2473
- hasRadius: true,
2474
- padding: 6,
2475
- children: [
2476
- /* @__PURE__ */ jsx(Flex, { direction: "row", as: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxs(Typography, { fontWeight: "semiBold", as: "li", children: [
2477
- pathSegment,
2478
- index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsx(
2479
- ChevronRight,
2480
- {
2481
- fill: "neutral500",
2482
- height: "0.8rem",
2483
- width: "0.8rem",
2484
- style: { margin: "0 0.8rem" }
2485
- }
2486
- )
2487
- ] }, index2)) }),
2488
- /* @__PURE__ */ jsx(Typography, { as: "p", textColor: "neutral600", children: formatMessage({
2489
- id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
2490
- defaultMessage: getDefaultErrorMessage(reason)
2491
- }) })
2492
- ]
2493
- },
2494
- fieldPath.join()
2495
- )) })
2496
- ] });
2497
- };
2498
- const TableActions = ({ document }) => {
2499
- const { formatMessage } = useIntl();
2500
- const { model, collectionType } = useDoc();
2501
- const plugins = useStrapiApp("TableActions", (state) => state.plugins);
2502
- const props = {
2503
- activeTab: null,
2504
- model,
2505
- documentId: document.documentId,
2506
- collectionType,
2507
- document
2508
- };
2509
- return /* @__PURE__ */ jsx(
2510
- DescriptionComponentRenderer,
2511
- {
2512
- props,
2513
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2514
- children: (actions2) => {
2515
- const tableRowActions = actions2.filter((action) => {
2516
- const positions = Array.isArray(action.position) ? action.position : [action.position];
2517
- return positions.includes("table-row");
2518
- });
2519
- return /* @__PURE__ */ jsx(
2520
- DocumentActionsMenu,
2521
- {
2522
- actions: tableRowActions,
2523
- label: formatMessage({
2524
- id: "content-manager.containers.list.table.row-actions",
2525
- defaultMessage: "Row action"
2526
- }),
2527
- variant: "ghost"
2528
- }
2529
- );
2530
- }
2531
- }
2458
+ const HOOKS = {
2459
+ /**
2460
+ * Hook that allows to mutate the displayed headers of the list view table
2461
+ * @constant
2462
+ * @type {string}
2463
+ */
2464
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2465
+ /**
2466
+ * Hook that allows to mutate the CM's collection types links pre-set filters
2467
+ * @constant
2468
+ * @type {string}
2469
+ */
2470
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2471
+ /**
2472
+ * Hook that allows to mutate the CM's edit view layout
2473
+ * @constant
2474
+ * @type {string}
2475
+ */
2476
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2477
+ /**
2478
+ * Hook that allows to mutate the CM's single types links pre-set filters
2479
+ * @constant
2480
+ * @type {string}
2481
+ */
2482
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2483
+ };
2484
+ const contentTypesApi = contentManagerApi.injectEndpoints({
2485
+ endpoints: (builder) => ({
2486
+ getContentTypeConfiguration: builder.query({
2487
+ query: (uid) => ({
2488
+ url: `/content-manager/content-types/${uid}/configuration`,
2489
+ method: "GET"
2490
+ }),
2491
+ transformResponse: (response) => response.data,
2492
+ providesTags: (_result, _error, uid) => [
2493
+ { type: "ContentTypesConfiguration", id: uid },
2494
+ { type: "ContentTypeSettings", id: "LIST" }
2495
+ ]
2496
+ }),
2497
+ getAllContentTypeSettings: builder.query({
2498
+ query: () => "/content-manager/content-types-settings",
2499
+ transformResponse: (response) => response.data,
2500
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2501
+ }),
2502
+ updateContentTypeConfiguration: builder.mutation({
2503
+ query: ({ uid, ...body }) => ({
2504
+ url: `/content-manager/content-types/${uid}/configuration`,
2505
+ method: "PUT",
2506
+ data: body
2507
+ }),
2508
+ transformResponse: (response) => response.data,
2509
+ invalidatesTags: (_result, _error, { uid }) => [
2510
+ { type: "ContentTypesConfiguration", id: uid },
2511
+ { type: "ContentTypeSettings", id: "LIST" },
2512
+ // Is this necessary?
2513
+ { type: "InitialData" }
2514
+ ]
2515
+ })
2516
+ })
2517
+ });
2518
+ const {
2519
+ useGetContentTypeConfigurationQuery,
2520
+ useGetAllContentTypeSettingsQuery,
2521
+ useUpdateContentTypeConfigurationMutation
2522
+ } = contentTypesApi;
2523
+ const checkIfAttributeIsDisplayable = (attribute) => {
2524
+ const { type } = attribute;
2525
+ if (type === "relation") {
2526
+ return !attribute.relation.toLowerCase().includes("morph");
2527
+ }
2528
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2529
+ };
2530
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2531
+ if (!mainFieldName) {
2532
+ return void 0;
2533
+ }
2534
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2535
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2536
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2532
2537
  );
2538
+ return {
2539
+ name: mainFieldName,
2540
+ type: mainFieldType ?? "string"
2541
+ };
2533
2542
  };
2534
- const EditAction = ({ documentId }) => {
2535
- const navigate = useNavigate();
2536
- const { formatMessage } = useIntl();
2537
- const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
2538
- const { toggleNotification } = useNotification();
2543
+ const DEFAULT_SETTINGS = {
2544
+ bulkable: false,
2545
+ filterable: false,
2546
+ searchable: false,
2547
+ pagination: false,
2548
+ defaultSortBy: "",
2549
+ defaultSortOrder: "asc",
2550
+ mainField: "id",
2551
+ pageSize: 10
2552
+ };
2553
+ const useDocumentLayout = (model) => {
2554
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2539
2555
  const [{ query }] = useQueryParams();
2540
- return {
2541
- disabled: !canRead,
2542
- icon: /* @__PURE__ */ jsx(StyledPencil, {}),
2543
- label: formatMessage({
2544
- id: "content-manager.actions.edit.label",
2545
- defaultMessage: "Edit"
2556
+ const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2557
+ const { toggleNotification } = useNotification();
2558
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
2559
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2560
+ const {
2561
+ data,
2562
+ isLoading: isLoadingConfigs,
2563
+ error,
2564
+ isFetching: isFetchingConfigs
2565
+ } = useGetContentTypeConfigurationQuery(model);
2566
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2567
+ React.useEffect(() => {
2568
+ if (error) {
2569
+ toggleNotification({
2570
+ type: "danger",
2571
+ message: formatAPIError(error)
2572
+ });
2573
+ }
2574
+ }, [error, formatAPIError, toggleNotification]);
2575
+ const editLayout = React.useMemo(
2576
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2577
+ layout: [],
2578
+ components: {},
2579
+ metadatas: {},
2580
+ options: {},
2581
+ settings: DEFAULT_SETTINGS
2582
+ },
2583
+ [data, isLoading, schemas, schema, components]
2584
+ );
2585
+ const listLayout = React.useMemo(() => {
2586
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2587
+ layout: [],
2588
+ metadatas: {},
2589
+ options: {},
2590
+ settings: DEFAULT_SETTINGS
2591
+ };
2592
+ }, [data, isLoading, schemas, schema, components]);
2593
+ const { layout: edit } = React.useMemo(
2594
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2595
+ layout: editLayout,
2596
+ query
2546
2597
  }),
2547
- position: "table-row",
2548
- onClick: async () => {
2549
- if (!documentId) {
2550
- console.error(
2551
- "You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
2552
- );
2553
- toggleNotification({
2554
- message: formatMessage({
2555
- id: "content-manager.actions.edit.error",
2556
- defaultMessage: "An error occurred while trying to edit the document."
2557
- }),
2558
- type: "danger"
2559
- });
2560
- return;
2598
+ [editLayout, query, runHookWaterfall]
2599
+ );
2600
+ return {
2601
+ error,
2602
+ isLoading,
2603
+ edit,
2604
+ list: listLayout
2605
+ };
2606
+ };
2607
+ const useDocLayout = () => {
2608
+ const { model } = useDoc();
2609
+ return useDocumentLayout(model);
2610
+ };
2611
+ const formatEditLayout = (data, {
2612
+ schemas,
2613
+ schema,
2614
+ components
2615
+ }) => {
2616
+ let currentPanelIndex = 0;
2617
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2618
+ data.contentType.layouts.edit,
2619
+ schema?.attributes,
2620
+ data.contentType.metadatas,
2621
+ { configurations: data.components, schemas: components },
2622
+ schemas
2623
+ ).reduce((panels, row) => {
2624
+ if (row.some((field) => field.type === "dynamiczone")) {
2625
+ panels.push([row]);
2626
+ currentPanelIndex += 2;
2627
+ } else {
2628
+ if (!panels[currentPanelIndex]) {
2629
+ panels.push([]);
2561
2630
  }
2562
- navigate({
2563
- pathname: documentId,
2564
- search: stringify({
2565
- plugins: query.plugins
2566
- })
2567
- });
2631
+ panels[currentPanelIndex].push(row);
2632
+ }
2633
+ return panels;
2634
+ }, []);
2635
+ const componentEditAttributes = Object.entries(data.components).reduce(
2636
+ (acc, [uid, configuration]) => {
2637
+ acc[uid] = {
2638
+ layout: convertEditLayoutToFieldLayouts(
2639
+ configuration.layouts.edit,
2640
+ components[uid].attributes,
2641
+ configuration.metadatas
2642
+ ),
2643
+ settings: {
2644
+ ...configuration.settings,
2645
+ icon: components[uid].info.icon,
2646
+ displayName: components[uid].info.displayName
2647
+ }
2648
+ };
2649
+ return acc;
2650
+ },
2651
+ {}
2652
+ );
2653
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2654
+ (acc, [attribute, metadata]) => {
2655
+ return {
2656
+ ...acc,
2657
+ [attribute]: metadata.edit
2658
+ };
2659
+ },
2660
+ {}
2661
+ );
2662
+ return {
2663
+ layout: panelledEditAttributes,
2664
+ components: componentEditAttributes,
2665
+ metadatas: editMetadatas,
2666
+ settings: {
2667
+ ...data.contentType.settings,
2668
+ displayName: schema?.info.displayName
2669
+ },
2670
+ options: {
2671
+ ...schema?.options,
2672
+ ...schema?.pluginOptions,
2673
+ ...data.contentType.options
2674
+ }
2675
+ };
2676
+ };
2677
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2678
+ return rows.map(
2679
+ (row) => row.map((field) => {
2680
+ const attribute = attributes[field.name];
2681
+ if (!attribute) {
2682
+ return null;
2683
+ }
2684
+ const { edit: metadata } = metadatas[field.name];
2685
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2686
+ return {
2687
+ attribute,
2688
+ disabled: !metadata.editable,
2689
+ hint: metadata.description,
2690
+ label: metadata.label ?? "",
2691
+ name: field.name,
2692
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
2693
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2694
+ schemas,
2695
+ components: components?.schemas ?? {}
2696
+ }),
2697
+ placeholder: metadata.placeholder ?? "",
2698
+ required: attribute.required ?? false,
2699
+ size: field.size,
2700
+ unique: "unique" in attribute ? attribute.unique : false,
2701
+ visible: metadata.visible ?? true,
2702
+ type: attribute.type
2703
+ };
2704
+ }).filter((field) => field !== null)
2705
+ );
2706
+ };
2707
+ const formatListLayout = (data, {
2708
+ schemas,
2709
+ schema,
2710
+ components
2711
+ }) => {
2712
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2713
+ (acc, [attribute, metadata]) => {
2714
+ return {
2715
+ ...acc,
2716
+ [attribute]: metadata.list
2717
+ };
2718
+ },
2719
+ {}
2720
+ );
2721
+ const listAttributes = convertListLayoutToFieldLayouts(
2722
+ data.contentType.layouts.list,
2723
+ schema?.attributes,
2724
+ listMetadatas,
2725
+ { configurations: data.components, schemas: components },
2726
+ schemas
2727
+ );
2728
+ return {
2729
+ layout: listAttributes,
2730
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2731
+ metadatas: listMetadatas,
2732
+ options: {
2733
+ ...schema?.options,
2734
+ ...schema?.pluginOptions,
2735
+ ...data.contentType.options
2568
2736
  }
2569
2737
  };
2570
2738
  };
2571
- EditAction.type = "edit";
2572
- const StyledPencil = styled(Pencil)`
2573
- path {
2574
- fill: currentColor;
2575
- }
2576
- `;
2577
- const CloneAction = ({ model, documentId }) => {
2578
- const navigate = useNavigate();
2739
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2740
+ return columns.map((name) => {
2741
+ const attribute = attributes[name];
2742
+ if (!attribute) {
2743
+ return null;
2744
+ }
2745
+ const metadata = metadatas[name];
2746
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2747
+ return {
2748
+ attribute,
2749
+ label: metadata.label ?? "",
2750
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2751
+ schemas,
2752
+ components: components?.schemas ?? {}
2753
+ }),
2754
+ name,
2755
+ searchable: metadata.searchable ?? true,
2756
+ sortable: metadata.sortable ?? true
2757
+ };
2758
+ }).filter((field) => field !== null);
2759
+ };
2760
+ const ConfirmBulkActionDialog = ({
2761
+ onToggleDialog,
2762
+ isOpen = false,
2763
+ dialogBody,
2764
+ endAction
2765
+ }) => {
2579
2766
  const { formatMessage } = useIntl();
2580
- const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
2767
+ return /* @__PURE__ */ jsx(Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2768
+ /* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
2769
+ id: "app.components.ConfirmDialog.title",
2770
+ defaultMessage: "Confirmation"
2771
+ }) }),
2772
+ /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
2773
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
2774
+ dialogBody
2775
+ ] }) }),
2776
+ /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
2777
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
2778
+ id: "app.components.Button.cancel",
2779
+ defaultMessage: "Cancel"
2780
+ }) }) }),
2781
+ endAction
2782
+ ] })
2783
+ ] }) });
2784
+ };
2785
+ const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
2786
+ const ConfirmDialogPublishAll = ({
2787
+ isOpen,
2788
+ onToggleDialog,
2789
+ isConfirmButtonLoading = false,
2790
+ onConfirm
2791
+ }) => {
2792
+ const { formatMessage } = useIntl();
2793
+ const selectedEntries = useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
2581
2794
  const { toggleNotification } = useNotification();
2582
- const { autoClone } = useDocumentActions();
2583
- const [prohibitedFields, setProhibitedFields] = React.useState([]);
2584
- return {
2585
- disabled: !canCreate,
2586
- icon: /* @__PURE__ */ jsx(StyledDuplicate, {}),
2587
- label: formatMessage({
2588
- id: "content-manager.actions.clone.label",
2589
- defaultMessage: "Duplicate"
2590
- }),
2591
- position: "table-row",
2592
- onClick: async () => {
2593
- if (!documentId) {
2594
- console.error(
2595
- "You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
2596
- );
2597
- toggleNotification({
2598
- message: formatMessage({
2599
- id: "content-manager.actions.clone.error",
2600
- defaultMessage: "An error occurred while trying to clone the document."
2601
- }),
2602
- type: "danger"
2603
- });
2604
- return;
2605
- }
2606
- const res = await autoClone({ model, sourceId: documentId });
2607
- if ("data" in res) {
2608
- navigate(res.data.documentId);
2609
- return true;
2610
- }
2611
- if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
2612
- const prohibitedFields2 = res.error.details.prohibitedFields;
2613
- setProhibitedFields(prohibitedFields2);
2614
- }
2795
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
2796
+ const { model, schema } = useDoc();
2797
+ const [{ query }] = useQueryParams();
2798
+ const {
2799
+ data: countDraftRelations = 0,
2800
+ isLoading,
2801
+ error
2802
+ } = useGetManyDraftRelationCountQuery(
2803
+ {
2804
+ model,
2805
+ documentIds: selectedEntries.map((entry) => entry.documentId),
2806
+ locale: query?.plugins?.i18n?.locale
2615
2807
  },
2616
- dialog: {
2617
- type: "modal",
2618
- title: formatMessage({
2619
- id: "content-manager.containers.list.autoCloneModal.header",
2620
- defaultMessage: "Duplicate"
2621
- }),
2622
- content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
2623
- footer: ({ onClose }) => {
2624
- return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
2625
- /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
2626
- id: "cancel",
2627
- defaultMessage: "Cancel"
2628
- }) }),
2629
- /* @__PURE__ */ jsx(
2630
- LinkButton,
2808
+ {
2809
+ skip: selectedEntries.length === 0
2810
+ }
2811
+ );
2812
+ React.useEffect(() => {
2813
+ if (error) {
2814
+ toggleNotification({ type: "danger", message: formatAPIError(error) });
2815
+ }
2816
+ }, [error, formatAPIError, toggleNotification]);
2817
+ if (error) {
2818
+ return null;
2819
+ }
2820
+ return /* @__PURE__ */ jsx(
2821
+ ConfirmBulkActionDialog,
2822
+ {
2823
+ isOpen: isOpen && !isLoading,
2824
+ onToggleDialog,
2825
+ dialogBody: /* @__PURE__ */ jsxs(Fragment, { children: [
2826
+ /* @__PURE__ */ jsxs(Typography, { id: "confirm-description", textAlign: "center", children: [
2827
+ countDraftRelations > 0 && formatMessage(
2631
2828
  {
2632
- as: NavLink,
2633
- to: {
2634
- pathname: `clone/${documentId}`
2635
- },
2636
- children: formatMessage({
2637
- id: "content-manager.containers.list.autoCloneModal.create",
2638
- defaultMessage: "Create"
2639
- })
2829
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2830
+ 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. "
2831
+ },
2832
+ {
2833
+ b: BoldChunk$1,
2834
+ count: countDraftRelations,
2835
+ entities: selectedEntries.length
2640
2836
  }
2641
- )
2642
- ] });
2643
- }
2837
+ ),
2838
+ formatMessage({
2839
+ id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
2840
+ defaultMessage: "Are you sure you want to publish these entries?"
2841
+ })
2842
+ ] }),
2843
+ schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsx(Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
2844
+ {
2845
+ id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
2846
+ defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
2847
+ },
2848
+ {
2849
+ em: Emphasis
2850
+ }
2851
+ ) })
2852
+ ] }),
2853
+ endAction: /* @__PURE__ */ jsx(
2854
+ Button,
2855
+ {
2856
+ onClick: onConfirm,
2857
+ variant: "secondary",
2858
+ startIcon: /* @__PURE__ */ jsx(Check, {}),
2859
+ loading: isConfirmButtonLoading,
2860
+ children: formatMessage({
2861
+ id: "app.utils.publish",
2862
+ defaultMessage: "Publish"
2863
+ })
2864
+ }
2865
+ )
2644
2866
  }
2645
- };
2867
+ );
2646
2868
  };
2647
- CloneAction.type = "clone";
2648
- const StyledDuplicate = styled(Duplicate)`
2649
- path {
2650
- fill: currentColor;
2651
- }
2869
+ const TypographyMaxWidth = styled(Typography)`
2870
+ max-width: 300px;
2652
2871
  `;
2653
- const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
2654
- class ContentManagerPlugin {
2655
- /**
2656
- * The following properties are the stored ones provided by any plugins registering with
2657
- * the content-manager. The function calls however, need to be called at runtime in the
2658
- * application, so instead we collate them and run them later with the complete list incl.
2659
- * ones already registered & the context of the view.
2660
- */
2661
- bulkActions = [...DEFAULT_BULK_ACTIONS];
2662
- documentActions = [
2663
- ...DEFAULT_ACTIONS,
2664
- ...DEFAULT_TABLE_ROW_ACTIONS,
2665
- ...DEFAULT_HEADER_ACTIONS,
2666
- HistoryAction
2667
- ];
2668
- editViewSidePanels = [ActionsPanel];
2669
- headerActions = [];
2670
- constructor() {
2671
- }
2672
- addEditViewSidePanel(panels) {
2673
- if (Array.isArray(panels)) {
2674
- this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
2675
- } else if (typeof panels === "function") {
2676
- this.editViewSidePanels = panels(this.editViewSidePanels);
2872
+ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2873
+ const messages = [];
2874
+ Object.entries(errors).forEach(([key, value]) => {
2875
+ const currentKey = parentKey ? `${parentKey}.${key}` : key;
2876
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
2877
+ if ("id" in value && "defaultMessage" in value) {
2878
+ messages.push(
2879
+ formatMessage(
2880
+ {
2881
+ id: `${value.id}.withField`,
2882
+ defaultMessage: value.defaultMessage
2883
+ },
2884
+ { field: currentKey }
2885
+ )
2886
+ );
2887
+ } else {
2888
+ messages.push(...formatErrorMessages(value, currentKey, formatMessage));
2889
+ }
2677
2890
  } else {
2678
- throw new Error(
2679
- `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
2680
- panels
2681
- )}`
2891
+ messages.push(
2892
+ formatMessage(
2893
+ {
2894
+ id: `${value}.withField`,
2895
+ defaultMessage: value
2896
+ },
2897
+ { field: currentKey }
2898
+ )
2682
2899
  );
2683
2900
  }
2901
+ });
2902
+ return messages;
2903
+ };
2904
+ const EntryValidationText = ({ validationErrors, status }) => {
2905
+ const { formatMessage } = useIntl();
2906
+ if (validationErrors) {
2907
+ const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
2908
+ " "
2909
+ );
2910
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
2911
+ /* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
2912
+ /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
2913
+ ] });
2684
2914
  }
2685
- addDocumentAction(actions2) {
2686
- if (Array.isArray(actions2)) {
2687
- this.documentActions = [...this.documentActions, ...actions2];
2688
- } else if (typeof actions2 === "function") {
2689
- this.documentActions = actions2(this.documentActions);
2690
- } else {
2691
- throw new Error(
2692
- `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
2693
- actions2
2694
- )}`
2695
- );
2696
- }
2915
+ if (status === "published") {
2916
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
2917
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
2918
+ /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
2919
+ id: "content-manager.bulk-publish.already-published",
2920
+ defaultMessage: "Already Published"
2921
+ }) })
2922
+ ] });
2697
2923
  }
2698
- addDocumentHeaderAction(actions2) {
2699
- if (Array.isArray(actions2)) {
2700
- this.headerActions = [...this.headerActions, ...actions2];
2701
- } else if (typeof actions2 === "function") {
2702
- this.headerActions = actions2(this.headerActions);
2703
- } else {
2704
- throw new Error(
2705
- `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
2706
- actions2
2707
- )}`
2708
- );
2709
- }
2924
+ if (status === "modified") {
2925
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
2926
+ /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
2927
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
2928
+ id: "content-manager.bulk-publish.modified",
2929
+ defaultMessage: "Ready to publish changes"
2930
+ }) })
2931
+ ] });
2710
2932
  }
2711
- addBulkAction(actions2) {
2712
- if (Array.isArray(actions2)) {
2713
- this.bulkActions = [...this.bulkActions, ...actions2];
2714
- } else if (typeof actions2 === "function") {
2715
- this.bulkActions = actions2(this.bulkActions);
2716
- } else {
2717
- throw new Error(
2718
- `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
2719
- actions2
2720
- )}`
2721
- );
2933
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
2934
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
2935
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
2936
+ id: "app.utils.ready-to-publish",
2937
+ defaultMessage: "Ready to publish"
2938
+ }) })
2939
+ ] });
2940
+ };
2941
+ const TABLE_HEADERS = [
2942
+ { name: "id", label: "id" },
2943
+ { name: "name", label: "name" },
2944
+ { name: "status", label: "status" },
2945
+ { name: "publicationStatus", label: "Publication status" }
2946
+ ];
2947
+ const SelectedEntriesTableContent = ({
2948
+ isPublishing,
2949
+ rowsToDisplay = [],
2950
+ entriesToPublish = [],
2951
+ validationErrors = {}
2952
+ }) => {
2953
+ const { pathname } = useLocation();
2954
+ const { formatMessage } = useIntl();
2955
+ const {
2956
+ list: {
2957
+ settings: { mainField }
2958
+ }
2959
+ } = useDocLayout();
2960
+ const shouldDisplayMainField = mainField != null && mainField !== "id";
2961
+ return /* @__PURE__ */ jsxs(Table.Content, { children: [
2962
+ /* @__PURE__ */ jsxs(Table.Head, { children: [
2963
+ /* @__PURE__ */ jsx(Table.HeaderCheckboxCell, {}),
2964
+ TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
2965
+ (head) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...head }, head.name)
2966
+ )
2967
+ ] }),
2968
+ /* @__PURE__ */ jsx(Table.Loading, {}),
2969
+ /* @__PURE__ */ jsx(Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxs(Table.Row, { children: [
2970
+ /* @__PURE__ */ jsx(Table.CheckboxCell, { id: row.id }),
2971
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row.id }) }),
2972
+ shouldDisplayMainField && /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row[mainField] }) }),
2973
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
2974
+ /* @__PURE__ */ jsx(Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
2975
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
2976
+ id: "content-manager.success.record.publishing",
2977
+ defaultMessage: "Publishing..."
2978
+ }) }),
2979
+ /* @__PURE__ */ jsx(Loader, { small: true })
2980
+ ] }) : /* @__PURE__ */ jsx(
2981
+ EntryValidationText,
2982
+ {
2983
+ validationErrors: validationErrors[row.documentId],
2984
+ status: row.status
2985
+ }
2986
+ ) }),
2987
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
2988
+ IconButton,
2989
+ {
2990
+ tag: Link,
2991
+ to: {
2992
+ pathname: `${pathname}/${row.documentId}`,
2993
+ search: row.locale && `?plugins[i18n][locale]=${row.locale}`
2994
+ },
2995
+ state: { from: pathname },
2996
+ label: formatMessage(
2997
+ { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
2998
+ {
2999
+ target: formatMessage(
3000
+ {
3001
+ id: "content-manager.components.ListViewHelperPluginTable.row-line",
3002
+ defaultMessage: "item line {number}"
3003
+ },
3004
+ { number: index2 + 1 }
3005
+ )
3006
+ }
3007
+ ),
3008
+ target: "_blank",
3009
+ marginLeft: "auto",
3010
+ children: /* @__PURE__ */ jsx(Pencil, {})
3011
+ }
3012
+ ) })
3013
+ ] }, row.id)) })
3014
+ ] });
3015
+ };
3016
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
3017
+ const SelectedEntriesModalContent = ({
3018
+ listViewSelectedEntries,
3019
+ toggleModal,
3020
+ setListViewSelectedDocuments,
3021
+ model
3022
+ }) => {
3023
+ const { formatMessage } = useIntl();
3024
+ const { schema, components } = useContentTypeSchema(model);
3025
+ const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
3026
+ const [{ query }] = useQueryParams();
3027
+ const params = React.useMemo(() => buildValidParams(query), [query]);
3028
+ const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
3029
+ {
3030
+ model,
3031
+ params: {
3032
+ page: "1",
3033
+ pageSize: documentIds.length.toString(),
3034
+ sort: query.sort,
3035
+ filters: {
3036
+ documentId: {
3037
+ $in: documentIds
3038
+ }
3039
+ },
3040
+ locale: query.plugins?.i18n?.locale
3041
+ }
3042
+ },
3043
+ {
3044
+ selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
3045
+ }
3046
+ );
3047
+ const { rows, validationErrors } = React.useMemo(() => {
3048
+ if (data.length > 0 && schema) {
3049
+ const validate = createYupSchema(schema.attributes, components);
3050
+ const validationErrors2 = {};
3051
+ const rows2 = data.map((entry) => {
3052
+ try {
3053
+ validate.validateSync(entry, { abortEarly: false });
3054
+ return entry;
3055
+ } catch (e) {
3056
+ if (e instanceof ValidationError) {
3057
+ validationErrors2[entry.documentId] = getYupValidationErrors(e);
3058
+ }
3059
+ return entry;
3060
+ }
3061
+ });
3062
+ return { rows: rows2, validationErrors: validationErrors2 };
2722
3063
  }
2723
- }
2724
- get config() {
2725
3064
  return {
2726
- id: PLUGIN_ID,
2727
- name: "Content Manager",
2728
- injectionZones: INJECTION_ZONES,
2729
- apis: {
2730
- addBulkAction: this.addBulkAction.bind(this),
2731
- addDocumentAction: this.addDocumentAction.bind(this),
2732
- addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
2733
- addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
2734
- getBulkActions: () => this.bulkActions,
2735
- getDocumentActions: () => this.documentActions,
2736
- getEditViewSidePanels: () => this.editViewSidePanels,
2737
- getHeaderActions: () => this.headerActions
2738
- }
3065
+ rows: [],
3066
+ validationErrors: {}
2739
3067
  };
2740
- }
2741
- }
2742
- const getPrintableType = (value) => {
2743
- const nativeType = typeof value;
2744
- if (nativeType === "object") {
2745
- if (value === null)
2746
- return "null";
2747
- if (Array.isArray(value))
2748
- return "array";
2749
- if (value instanceof Object && value.constructor.name !== "Object") {
2750
- return value.constructor.name;
3068
+ }, [components, data, schema]);
3069
+ const [publishedCount, setPublishedCount] = React.useState(0);
3070
+ const [isDialogOpen, setIsDialogOpen] = React.useState(false);
3071
+ const { publishMany: bulkPublishAction } = useDocumentActions();
3072
+ const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
3073
+ const selectedRows = useTable("publishAction", (state) => state.selectedRows);
3074
+ const selectedEntries = rows.filter(
3075
+ (entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
3076
+ );
3077
+ const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
3078
+ const selectedEntriesWithErrorsCount = selectedEntries.filter(
3079
+ ({ documentId }) => validationErrors[documentId]
3080
+ ).length;
3081
+ const selectedEntriesPublished = selectedEntries.filter(
3082
+ ({ status }) => status === "published"
3083
+ ).length;
3084
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3085
+ const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3086
+ const handleConfirmBulkPublish = async () => {
3087
+ toggleDialog();
3088
+ const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3089
+ if (!("error" in res)) {
3090
+ setPublishedCount(res.count);
3091
+ const unpublishedEntries = rows.filter((row) => {
3092
+ return !entriesToPublish.includes(row.documentId);
3093
+ });
3094
+ setListViewSelectedDocuments(unpublishedEntries);
2751
3095
  }
2752
- }
2753
- return nativeType;
2754
- };
2755
- const initialState = {
2756
- collectionTypeLinks: [],
2757
- components: [],
2758
- fieldSizes: {},
2759
- models: [],
2760
- singleTypeLinks: [],
2761
- isLoading: true
2762
- };
2763
- const appSlice = createSlice({
2764
- name: "app",
2765
- initialState,
2766
- reducers: {
2767
- setInitialData(state, action) {
2768
- const {
2769
- authorizedCollectionTypeLinks,
2770
- authorizedSingleTypeLinks,
2771
- components,
2772
- contentTypeSchemas,
2773
- fieldSizes
2774
- } = action.payload;
2775
- state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
2776
- ({ isDisplayed }) => isDisplayed
3096
+ };
3097
+ const getFormattedCountMessage = () => {
3098
+ if (publishedCount) {
3099
+ return formatMessage(
3100
+ {
3101
+ id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3102
+ 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."
3103
+ },
3104
+ {
3105
+ publishedCount,
3106
+ withErrorsCount: selectedEntriesWithErrorsCount,
3107
+ b: BoldChunk
3108
+ }
2777
3109
  );
2778
- state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
2779
- state.components = components;
2780
- state.models = contentTypeSchemas;
2781
- state.fieldSizes = fieldSizes;
2782
- state.isLoading = false;
2783
3110
  }
2784
- }
2785
- });
2786
- const { actions, reducer: reducer$1 } = appSlice;
2787
- const { setInitialData } = actions;
2788
- const reducer = combineReducers({
2789
- app: reducer$1
2790
- });
2791
- const HOOKS = {
2792
- /**
2793
- * Hook that allows to mutate the displayed headers of the list view table
2794
- * @constant
2795
- * @type {string}
2796
- */
2797
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2798
- /**
2799
- * Hook that allows to mutate the CM's collection types links pre-set filters
2800
- * @constant
2801
- * @type {string}
2802
- */
2803
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2804
- /**
2805
- * Hook that allows to mutate the CM's edit view layout
2806
- * @constant
2807
- * @type {string}
2808
- */
2809
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2810
- /**
2811
- * Hook that allows to mutate the CM's single types links pre-set filters
2812
- * @constant
2813
- * @type {string}
2814
- */
2815
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
3111
+ return formatMessage(
3112
+ {
3113
+ id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3114
+ 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."
3115
+ },
3116
+ {
3117
+ readyToPublishCount: selectedEntriesWithNoErrorsCount,
3118
+ withErrorsCount: selectedEntriesWithErrorsCount,
3119
+ alreadyPublishedCount: selectedEntriesPublished,
3120
+ b: BoldChunk
3121
+ }
3122
+ );
3123
+ };
3124
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3125
+ /* @__PURE__ */ jsxs(Modal.Body, { children: [
3126
+ /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
3127
+ /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsx(
3128
+ SelectedEntriesTableContent,
3129
+ {
3130
+ isPublishing: isSubmittingForm,
3131
+ rowsToDisplay: rows,
3132
+ entriesToPublish,
3133
+ validationErrors
3134
+ }
3135
+ ) })
3136
+ ] }),
3137
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
3138
+ /* @__PURE__ */ jsx(Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3139
+ id: "app.components.Button.cancel",
3140
+ defaultMessage: "Cancel"
3141
+ }) }),
3142
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3143
+ /* @__PURE__ */ jsx(Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3144
+ /* @__PURE__ */ jsx(
3145
+ Button,
3146
+ {
3147
+ onClick: toggleDialog,
3148
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3149
+ loading: isSubmittingForm,
3150
+ children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3151
+ }
3152
+ )
3153
+ ] })
3154
+ ] }),
3155
+ /* @__PURE__ */ jsx(
3156
+ ConfirmDialogPublishAll,
3157
+ {
3158
+ isOpen: isDialogOpen,
3159
+ onToggleDialog: toggleDialog,
3160
+ isConfirmButtonLoading: isSubmittingForm,
3161
+ onConfirm: handleConfirmBulkPublish
3162
+ }
3163
+ )
3164
+ ] });
2816
3165
  };
2817
- const contentTypesApi = contentManagerApi.injectEndpoints({
2818
- endpoints: (builder) => ({
2819
- getContentTypeConfiguration: builder.query({
2820
- query: (uid) => ({
2821
- url: `/content-manager/content-types/${uid}/configuration`,
2822
- method: "GET"
2823
- }),
2824
- transformResponse: (response) => response.data,
2825
- providesTags: (_result, _error, uid) => [
2826
- { type: "ContentTypesConfiguration", id: uid },
2827
- { type: "ContentTypeSettings", id: "LIST" }
2828
- ]
2829
- }),
2830
- getAllContentTypeSettings: builder.query({
2831
- query: () => "/content-manager/content-types-settings",
2832
- transformResponse: (response) => response.data,
2833
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2834
- }),
2835
- updateContentTypeConfiguration: builder.mutation({
2836
- query: ({ uid, ...body }) => ({
2837
- url: `/content-manager/content-types/${uid}/configuration`,
2838
- method: "PUT",
2839
- data: body
3166
+ const PublishAction = ({ documents, model }) => {
3167
+ const { formatMessage } = useIntl();
3168
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3169
+ const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
3170
+ const setListViewSelectedDocuments = useTable("publishAction", (state) => state.selectRow);
3171
+ const refetchList = () => {
3172
+ contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3173
+ };
3174
+ if (!showPublishButton)
3175
+ return null;
3176
+ return {
3177
+ actionType: "publish",
3178
+ variant: "tertiary",
3179
+ label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
3180
+ dialog: {
3181
+ type: "modal",
3182
+ title: formatMessage({
3183
+ id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
3184
+ defaultMessage: "Publish entries"
2840
3185
  }),
2841
- transformResponse: (response) => response.data,
2842
- invalidatesTags: (_result, _error, { uid }) => [
2843
- { type: "ContentTypesConfiguration", id: uid },
2844
- { type: "ContentTypeSettings", id: "LIST" },
2845
- // Is this necessary?
2846
- { type: "InitialData" }
2847
- ]
2848
- })
2849
- })
2850
- });
2851
- const {
2852
- useGetContentTypeConfigurationQuery,
2853
- useGetAllContentTypeSettingsQuery,
2854
- useUpdateContentTypeConfigurationMutation
2855
- } = contentTypesApi;
2856
- const checkIfAttributeIsDisplayable = (attribute) => {
2857
- const { type } = attribute;
2858
- if (type === "relation") {
2859
- return !attribute.relation.toLowerCase().includes("morph");
2860
- }
2861
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
3186
+ content: ({ onClose }) => {
3187
+ return /* @__PURE__ */ jsx(Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsx(
3188
+ SelectedEntriesModalContent,
3189
+ {
3190
+ listViewSelectedEntries: documents,
3191
+ toggleModal: () => {
3192
+ onClose();
3193
+ refetchList();
3194
+ },
3195
+ setListViewSelectedDocuments,
3196
+ model
3197
+ }
3198
+ ) });
3199
+ },
3200
+ onClose: () => {
3201
+ refetchList();
3202
+ }
3203
+ }
3204
+ };
2862
3205
  };
2863
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2864
- if (!mainFieldName) {
2865
- return void 0;
2866
- }
2867
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2868
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2869
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2870
- );
3206
+ const BulkActionsRenderer = () => {
3207
+ const plugins = useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
3208
+ const { model, collectionType } = useDoc();
3209
+ const { selectedRows } = useTable("BulkActionsRenderer", (state) => state);
3210
+ return /* @__PURE__ */ jsx(Flex, { gap: 2, children: /* @__PURE__ */ jsx(
3211
+ DescriptionComponentRenderer,
3212
+ {
3213
+ props: {
3214
+ model,
3215
+ collectionType,
3216
+ documents: selectedRows
3217
+ },
3218
+ descriptions: plugins["content-manager"].apis.getBulkActions(),
3219
+ children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsx(DocumentActionButton, { ...action }, action.id))
3220
+ }
3221
+ ) });
3222
+ };
3223
+ const DeleteAction = ({ documents, model }) => {
3224
+ const { formatMessage } = useIntl();
3225
+ const { schema: contentType } = useDoc();
3226
+ const selectRow = useTable("DeleteAction", (state) => state.selectRow);
3227
+ const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
3228
+ const [{ query }] = useQueryParams();
3229
+ const params = React.useMemo(() => buildValidParams(query), [query]);
3230
+ const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
3231
+ const { deleteMany: bulkDeleteAction } = useDocumentActions();
3232
+ const documentIds = documents.map(({ documentId }) => documentId);
3233
+ const handleConfirmBulkDelete = async () => {
3234
+ const res = await bulkDeleteAction({
3235
+ documentIds,
3236
+ model,
3237
+ params
3238
+ });
3239
+ if (!("error" in res)) {
3240
+ selectRow([]);
3241
+ }
3242
+ };
3243
+ if (!hasDeletePermission)
3244
+ return null;
2871
3245
  return {
2872
- name: mainFieldName,
2873
- type: mainFieldType ?? "string"
3246
+ variant: "danger-light",
3247
+ label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
3248
+ dialog: {
3249
+ type: "dialog",
3250
+ title: formatMessage({
3251
+ id: "app.components.ConfirmDialog.title",
3252
+ defaultMessage: "Confirmation"
3253
+ }),
3254
+ content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3255
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3256
+ /* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3257
+ id: "popUpWarning.bodyMessage.contentType.delete.all",
3258
+ defaultMessage: "Are you sure you want to delete these entries?"
3259
+ }) }),
3260
+ hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
3261
+ {
3262
+ id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
3263
+ defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
3264
+ },
3265
+ {
3266
+ em: Emphasis
3267
+ }
3268
+ ) }) })
3269
+ ] }),
3270
+ onConfirm: handleConfirmBulkDelete
3271
+ }
2874
3272
  };
2875
3273
  };
2876
- const DEFAULT_SETTINGS = {
2877
- bulkable: false,
2878
- filterable: false,
2879
- searchable: false,
2880
- pagination: false,
2881
- defaultSortBy: "",
2882
- defaultSortOrder: "asc",
2883
- mainField: "id",
2884
- pageSize: 10
2885
- };
2886
- const useDocumentLayout = (model) => {
2887
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
3274
+ DeleteAction.type = "delete";
3275
+ const UnpublishAction = ({ documents, model }) => {
3276
+ const { formatMessage } = useIntl();
3277
+ const { schema } = useDoc();
3278
+ const selectRow = useTable("UnpublishAction", (state) => state.selectRow);
3279
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3280
+ const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
3281
+ const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
3282
+ const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
3283
+ const documentIds = documents.map(({ documentId }) => documentId);
2888
3284
  const [{ query }] = useQueryParams();
2889
- const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2890
- const { toggleNotification } = useNotification();
2891
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
2892
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2893
- const {
2894
- data,
2895
- isLoading: isLoadingConfigs,
2896
- error,
2897
- isFetching: isFetchingConfigs
2898
- } = useGetContentTypeConfigurationQuery(model);
2899
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2900
- React.useEffect(() => {
2901
- if (error) {
2902
- toggleNotification({
2903
- type: "danger",
2904
- message: formatAPIError(error)
2905
- });
3285
+ const params = React.useMemo(() => buildValidParams(query), [query]);
3286
+ const handleConfirmBulkUnpublish = async () => {
3287
+ const data = await bulkUnpublishAction({ documentIds, model, params });
3288
+ if (!("error" in data)) {
3289
+ selectRow([]);
2906
3290
  }
2907
- }, [error, formatAPIError, toggleNotification]);
2908
- const editLayout = React.useMemo(
2909
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2910
- layout: [],
2911
- components: {},
2912
- metadatas: {},
2913
- options: {},
2914
- settings: DEFAULT_SETTINGS
2915
- },
2916
- [data, isLoading, schemas, schema, components]
2917
- );
2918
- const listLayout = React.useMemo(() => {
2919
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2920
- layout: [],
2921
- metadatas: {},
2922
- options: {},
2923
- settings: DEFAULT_SETTINGS
2924
- };
2925
- }, [data, isLoading, schemas, schema, components]);
2926
- const { layout: edit } = React.useMemo(
2927
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2928
- layout: editLayout,
2929
- query
2930
- }),
2931
- [editLayout, query, runHookWaterfall]
2932
- );
3291
+ };
3292
+ const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3293
+ if (!showUnpublishButton)
3294
+ return null;
2933
3295
  return {
2934
- error,
2935
- isLoading,
2936
- edit,
2937
- list: listLayout
3296
+ variant: "tertiary",
3297
+ label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
3298
+ dialog: {
3299
+ type: "dialog",
3300
+ title: formatMessage({
3301
+ id: "app.components.ConfirmDialog.title",
3302
+ defaultMessage: "Confirmation"
3303
+ }),
3304
+ content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3305
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3306
+ /* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3307
+ id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3308
+ defaultMessage: "Are you sure you want to unpublish these entries?"
3309
+ }) }),
3310
+ hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
3311
+ {
3312
+ id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
3313
+ defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
3314
+ },
3315
+ {
3316
+ em: Emphasis
3317
+ }
3318
+ ) }) })
3319
+ ] }),
3320
+ confirmButton: formatMessage({
3321
+ id: "app.utils.unpublish",
3322
+ defaultMessage: "Unpublish"
3323
+ }),
3324
+ onConfirm: handleConfirmBulkUnpublish
3325
+ }
2938
3326
  };
2939
3327
  };
2940
- const useDocLayout = () => {
2941
- const { model } = useDoc();
2942
- return useDocumentLayout(model);
3328
+ UnpublishAction.type = "unpublish";
3329
+ const Emphasis = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
3330
+ const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
3331
+ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3332
+ const { formatMessage } = useIntl();
3333
+ const getDefaultErrorMessage = (reason) => {
3334
+ switch (reason) {
3335
+ case "relation":
3336
+ return "Duplicating the relation could remove it from the original entry.";
3337
+ case "unique":
3338
+ return "Identical values in a unique field are not allowed";
3339
+ default:
3340
+ return reason;
3341
+ }
3342
+ };
3343
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3344
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", children: formatMessage({
3345
+ id: getTranslation("containers.list.autoCloneModal.title"),
3346
+ defaultMessage: "This entry can't be duplicated directly."
3347
+ }) }),
3348
+ /* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage({
3349
+ id: getTranslation("containers.list.autoCloneModal.description"),
3350
+ defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
3351
+ }) }) }),
3352
+ /* @__PURE__ */ jsx(Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxs(
3353
+ Flex,
3354
+ {
3355
+ direction: "column",
3356
+ gap: 2,
3357
+ alignItems: "flex-start",
3358
+ borderColor: "neutral200",
3359
+ hasRadius: true,
3360
+ padding: 6,
3361
+ children: [
3362
+ /* @__PURE__ */ jsx(Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxs(Typography, { fontWeight: "semiBold", tag: "li", children: [
3363
+ pathSegment,
3364
+ index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsx(
3365
+ ChevronRight,
3366
+ {
3367
+ fill: "neutral500",
3368
+ height: "0.8rem",
3369
+ width: "0.8rem",
3370
+ style: { margin: "0 0.8rem" }
3371
+ }
3372
+ )
3373
+ ] }, index2)) }),
3374
+ /* @__PURE__ */ jsx(Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
3375
+ id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
3376
+ defaultMessage: getDefaultErrorMessage(reason)
3377
+ }) })
3378
+ ]
3379
+ },
3380
+ fieldPath.join()
3381
+ )) })
3382
+ ] });
2943
3383
  };
2944
- const formatEditLayout = (data, {
2945
- schemas,
2946
- schema,
2947
- components
2948
- }) => {
2949
- let currentPanelIndex = 0;
2950
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2951
- data.contentType.layouts.edit,
2952
- schema?.attributes,
2953
- data.contentType.metadatas,
2954
- { configurations: data.components, schemas: components },
2955
- schemas
2956
- ).reduce((panels, row) => {
2957
- if (row.some((field) => field.type === "dynamiczone")) {
2958
- panels.push([row]);
2959
- currentPanelIndex += 2;
2960
- } else {
2961
- if (!panels[currentPanelIndex]) {
2962
- panels.push([]);
3384
+ const TableActions = ({ document }) => {
3385
+ const { formatMessage } = useIntl();
3386
+ const { model, collectionType } = useDoc();
3387
+ const plugins = useStrapiApp("TableActions", (state) => state.plugins);
3388
+ const props = {
3389
+ activeTab: null,
3390
+ model,
3391
+ documentId: document.documentId,
3392
+ collectionType,
3393
+ document
3394
+ };
3395
+ return /* @__PURE__ */ jsx(
3396
+ DescriptionComponentRenderer,
3397
+ {
3398
+ props,
3399
+ descriptions: plugins["content-manager"].apis.getDocumentActions(),
3400
+ children: (actions2) => {
3401
+ const tableRowActions = actions2.filter((action) => {
3402
+ const positions = Array.isArray(action.position) ? action.position : [action.position];
3403
+ return positions.includes("table-row");
3404
+ });
3405
+ return /* @__PURE__ */ jsx(
3406
+ DocumentActionsMenu,
3407
+ {
3408
+ actions: tableRowActions,
3409
+ label: formatMessage({
3410
+ id: "content-manager.containers.list.table.row-actions",
3411
+ defaultMessage: "Row action"
3412
+ }),
3413
+ variant: "ghost"
3414
+ }
3415
+ );
2963
3416
  }
2964
- panels[currentPanelIndex].push(row);
2965
3417
  }
2966
- return panels;
2967
- }, []);
2968
- const componentEditAttributes = Object.entries(data.components).reduce(
2969
- (acc, [uid, configuration]) => {
2970
- acc[uid] = {
2971
- layout: convertEditLayoutToFieldLayouts(
2972
- configuration.layouts.edit,
2973
- components[uid].attributes,
2974
- configuration.metadatas
2975
- ),
2976
- settings: {
2977
- ...configuration.settings,
2978
- icon: components[uid].info.icon,
2979
- displayName: components[uid].info.displayName
2980
- }
2981
- };
2982
- return acc;
2983
- },
2984
- {}
2985
- );
2986
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2987
- (acc, [attribute, metadata]) => {
2988
- return {
2989
- ...acc,
2990
- [attribute]: metadata.edit
2991
- };
2992
- },
2993
- {}
2994
3418
  );
3419
+ };
3420
+ const EditAction = ({ documentId }) => {
3421
+ const navigate = useNavigate();
3422
+ const { formatMessage } = useIntl();
3423
+ const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
3424
+ const { toggleNotification } = useNotification();
3425
+ const [{ query }] = useQueryParams();
2995
3426
  return {
2996
- layout: panelledEditAttributes,
2997
- components: componentEditAttributes,
2998
- metadatas: editMetadatas,
2999
- settings: {
3000
- ...data.contentType.settings,
3001
- displayName: schema?.info.displayName
3002
- },
3003
- options: {
3004
- ...schema?.options,
3005
- ...schema?.pluginOptions,
3006
- ...data.contentType.options
3427
+ disabled: !canRead,
3428
+ icon: /* @__PURE__ */ jsx(StyledPencil, {}),
3429
+ label: formatMessage({
3430
+ id: "content-manager.actions.edit.label",
3431
+ defaultMessage: "Edit"
3432
+ }),
3433
+ position: "table-row",
3434
+ onClick: async () => {
3435
+ if (!documentId) {
3436
+ console.error(
3437
+ "You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
3438
+ );
3439
+ toggleNotification({
3440
+ message: formatMessage({
3441
+ id: "content-manager.actions.edit.error",
3442
+ defaultMessage: "An error occurred while trying to edit the document."
3443
+ }),
3444
+ type: "danger"
3445
+ });
3446
+ return;
3447
+ }
3448
+ navigate({
3449
+ pathname: documentId,
3450
+ search: stringify({
3451
+ plugins: query.plugins
3452
+ })
3453
+ });
3007
3454
  }
3008
3455
  };
3009
3456
  };
3010
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
3011
- return rows.map(
3012
- (row) => row.map((field) => {
3013
- const attribute = attributes[field.name];
3014
- if (!attribute) {
3015
- return null;
3016
- }
3017
- const { edit: metadata } = metadatas[field.name];
3018
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3019
- return {
3020
- attribute,
3021
- disabled: !metadata.editable,
3022
- hint: metadata.description,
3023
- label: metadata.label ?? "",
3024
- name: field.name,
3025
- // @ts-expect-error – mainField does exist on the metadata for a relation.
3026
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
3027
- schemas,
3028
- components: components?.schemas ?? {}
3029
- }),
3030
- placeholder: metadata.placeholder ?? "",
3031
- required: attribute.required ?? false,
3032
- size: field.size,
3033
- unique: "unique" in attribute ? attribute.unique : false,
3034
- visible: metadata.visible ?? true,
3035
- type: attribute.type
3036
- };
3037
- }).filter((field) => field !== null)
3038
- );
3039
- };
3040
- const formatListLayout = (data, {
3041
- schemas,
3042
- schema,
3043
- components
3044
- }) => {
3045
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
3046
- (acc, [attribute, metadata]) => {
3047
- return {
3048
- ...acc,
3049
- [attribute]: metadata.list
3050
- };
3051
- },
3052
- {}
3053
- );
3054
- const listAttributes = convertListLayoutToFieldLayouts(
3055
- data.contentType.layouts.list,
3056
- schema?.attributes,
3057
- listMetadatas,
3058
- { configurations: data.components, schemas: components },
3059
- schemas
3060
- );
3457
+ EditAction.type = "edit";
3458
+ const StyledPencil = styled(Pencil)`
3459
+ path {
3460
+ fill: currentColor;
3461
+ }
3462
+ `;
3463
+ const CloneAction = ({ model, documentId }) => {
3464
+ const navigate = useNavigate();
3465
+ const { formatMessage } = useIntl();
3466
+ const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
3467
+ const { toggleNotification } = useNotification();
3468
+ const { autoClone } = useDocumentActions();
3469
+ const [prohibitedFields, setProhibitedFields] = React.useState([]);
3061
3470
  return {
3062
- layout: listAttributes,
3063
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
3064
- metadatas: listMetadatas,
3065
- options: {
3066
- ...schema?.options,
3067
- ...schema?.pluginOptions,
3068
- ...data.contentType.options
3471
+ disabled: !canCreate,
3472
+ icon: /* @__PURE__ */ jsx(StyledDuplicate, {}),
3473
+ label: formatMessage({
3474
+ id: "content-manager.actions.clone.label",
3475
+ defaultMessage: "Duplicate"
3476
+ }),
3477
+ position: "table-row",
3478
+ onClick: async () => {
3479
+ if (!documentId) {
3480
+ console.error(
3481
+ "You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
3482
+ );
3483
+ toggleNotification({
3484
+ message: formatMessage({
3485
+ id: "content-manager.actions.clone.error",
3486
+ defaultMessage: "An error occurred while trying to clone the document."
3487
+ }),
3488
+ type: "danger"
3489
+ });
3490
+ return;
3491
+ }
3492
+ const res = await autoClone({ model, sourceId: documentId });
3493
+ if ("data" in res) {
3494
+ navigate(res.data.documentId);
3495
+ return true;
3496
+ }
3497
+ if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
3498
+ const prohibitedFields2 = res.error.details.prohibitedFields;
3499
+ setProhibitedFields(prohibitedFields2);
3500
+ }
3501
+ },
3502
+ dialog: {
3503
+ type: "modal",
3504
+ title: formatMessage({
3505
+ id: "content-manager.containers.list.autoCloneModal.header",
3506
+ defaultMessage: "Duplicate"
3507
+ }),
3508
+ content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3509
+ footer: ({ onClose }) => {
3510
+ return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
3511
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3512
+ id: "cancel",
3513
+ defaultMessage: "Cancel"
3514
+ }) }),
3515
+ /* @__PURE__ */ jsx(
3516
+ LinkButton,
3517
+ {
3518
+ tag: NavLink,
3519
+ to: {
3520
+ pathname: `clone/${documentId}`
3521
+ },
3522
+ children: formatMessage({
3523
+ id: "content-manager.containers.list.autoCloneModal.create",
3524
+ defaultMessage: "Create"
3525
+ })
3526
+ }
3527
+ )
3528
+ ] });
3529
+ }
3069
3530
  }
3070
3531
  };
3071
3532
  };
3072
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
3073
- return columns.map((name) => {
3074
- const attribute = attributes[name];
3075
- if (!attribute) {
3076
- return null;
3533
+ CloneAction.type = "clone";
3534
+ const StyledDuplicate = styled(Duplicate)`
3535
+ path {
3536
+ fill: currentColor;
3537
+ }
3538
+ `;
3539
+ const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
3540
+ class ContentManagerPlugin {
3541
+ /**
3542
+ * The following properties are the stored ones provided by any plugins registering with
3543
+ * the content-manager. The function calls however, need to be called at runtime in the
3544
+ * application, so instead we collate them and run them later with the complete list incl.
3545
+ * ones already registered & the context of the view.
3546
+ */
3547
+ bulkActions = [...DEFAULT_BULK_ACTIONS];
3548
+ documentActions = [
3549
+ ...DEFAULT_ACTIONS,
3550
+ ...DEFAULT_TABLE_ROW_ACTIONS,
3551
+ ...DEFAULT_HEADER_ACTIONS,
3552
+ HistoryAction
3553
+ ];
3554
+ editViewSidePanels = [ActionsPanel];
3555
+ headerActions = [];
3556
+ constructor() {
3557
+ }
3558
+ addEditViewSidePanel(panels) {
3559
+ if (Array.isArray(panels)) {
3560
+ this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
3561
+ } else if (typeof panels === "function") {
3562
+ this.editViewSidePanels = panels(this.editViewSidePanels);
3563
+ } else {
3564
+ throw new Error(
3565
+ `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
3566
+ panels
3567
+ )}`
3568
+ );
3077
3569
  }
3078
- const metadata = metadatas[name];
3079
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3570
+ }
3571
+ addDocumentAction(actions2) {
3572
+ if (Array.isArray(actions2)) {
3573
+ this.documentActions = [...this.documentActions, ...actions2];
3574
+ } else if (typeof actions2 === "function") {
3575
+ this.documentActions = actions2(this.documentActions);
3576
+ } else {
3577
+ throw new Error(
3578
+ `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
3579
+ actions2
3580
+ )}`
3581
+ );
3582
+ }
3583
+ }
3584
+ addDocumentHeaderAction(actions2) {
3585
+ if (Array.isArray(actions2)) {
3586
+ this.headerActions = [...this.headerActions, ...actions2];
3587
+ } else if (typeof actions2 === "function") {
3588
+ this.headerActions = actions2(this.headerActions);
3589
+ } else {
3590
+ throw new Error(
3591
+ `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
3592
+ actions2
3593
+ )}`
3594
+ );
3595
+ }
3596
+ }
3597
+ addBulkAction(actions2) {
3598
+ if (Array.isArray(actions2)) {
3599
+ this.bulkActions = [...this.bulkActions, ...actions2];
3600
+ } else if (typeof actions2 === "function") {
3601
+ this.bulkActions = actions2(this.bulkActions);
3602
+ } else {
3603
+ throw new Error(
3604
+ `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3605
+ actions2
3606
+ )}`
3607
+ );
3608
+ }
3609
+ }
3610
+ get config() {
3080
3611
  return {
3081
- attribute,
3082
- label: metadata.label ?? "",
3083
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
3084
- schemas,
3085
- components: components?.schemas ?? {}
3086
- }),
3087
- name,
3088
- searchable: metadata.searchable ?? true,
3089
- sortable: metadata.sortable ?? true
3612
+ id: PLUGIN_ID,
3613
+ name: "Content Manager",
3614
+ injectionZones: INJECTION_ZONES,
3615
+ apis: {
3616
+ addBulkAction: this.addBulkAction.bind(this),
3617
+ addDocumentAction: this.addDocumentAction.bind(this),
3618
+ addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3619
+ addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3620
+ getBulkActions: () => this.bulkActions,
3621
+ getDocumentActions: () => this.documentActions,
3622
+ getEditViewSidePanels: () => this.editViewSidePanels,
3623
+ getHeaderActions: () => this.headerActions
3624
+ }
3090
3625
  };
3091
- }).filter((field) => field !== null);
3626
+ }
3627
+ }
3628
+ const getPrintableType = (value) => {
3629
+ const nativeType = typeof value;
3630
+ if (nativeType === "object") {
3631
+ if (value === null)
3632
+ return "null";
3633
+ if (Array.isArray(value))
3634
+ return "array";
3635
+ if (value instanceof Object && value.constructor.name !== "Object") {
3636
+ return value.constructor.name;
3637
+ }
3638
+ }
3639
+ return nativeType;
3640
+ };
3641
+ const initialState = {
3642
+ collectionTypeLinks: [],
3643
+ components: [],
3644
+ fieldSizes: {},
3645
+ models: [],
3646
+ singleTypeLinks: [],
3647
+ isLoading: true
3092
3648
  };
3649
+ const appSlice = createSlice({
3650
+ name: "app",
3651
+ initialState,
3652
+ reducers: {
3653
+ setInitialData(state, action) {
3654
+ const {
3655
+ authorizedCollectionTypeLinks,
3656
+ authorizedSingleTypeLinks,
3657
+ components,
3658
+ contentTypeSchemas,
3659
+ fieldSizes
3660
+ } = action.payload;
3661
+ state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
3662
+ ({ isDisplayed }) => isDisplayed
3663
+ );
3664
+ state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
3665
+ state.components = components;
3666
+ state.models = contentTypeSchemas;
3667
+ state.fieldSizes = fieldSizes;
3668
+ state.isLoading = false;
3669
+ }
3670
+ }
3671
+ });
3672
+ const { actions, reducer: reducer$1 } = appSlice;
3673
+ const { setInitialData } = actions;
3674
+ const reducer = combineReducers({
3675
+ app: reducer$1
3676
+ });
3093
3677
  const index = {
3094
3678
  register(app) {
3095
3679
  const cm = new ContentManagerPlugin();
3096
3680
  app.addReducers({
3097
- [contentManagerApi.reducerPath]: contentManagerApi.reducer,
3098
3681
  [PLUGIN_ID]: reducer
3099
3682
  });
3100
- app.addMiddlewares([() => contentManagerApi.middleware]);
3101
3683
  app.addMenuLink({
3102
3684
  to: PLUGIN_ID,
3103
3685
  icon: Feather,
@@ -3106,14 +3688,15 @@ const index = {
3106
3688
  defaultMessage: "Content Manager"
3107
3689
  },
3108
3690
  permissions: [],
3109
- Component: () => import("./layout-CXsHbc3E.mjs").then((mod) => ({ default: mod.Layout }))
3691
+ Component: () => import("./layout-DC503LnF.mjs").then((mod) => ({ default: mod.Layout })),
3692
+ position: 1
3110
3693
  });
3111
3694
  app.registerPlugin(cm.config);
3112
3695
  },
3113
3696
  async registerTrads({ locales }) {
3114
3697
  const importedTrads = await Promise.all(
3115
3698
  locales.map((locale) => {
3116
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-MBPul9Su.mjs"), "./translations/es.json": () => import("./es-CeXiYflN.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr-CD9VFbPM.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-CtsUxOvk.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
3699
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-Ux26r5pl.mjs"), "./translations/es.json": () => import("./es-CeXiYflN.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr-CD9VFbPM.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-CtsUxOvk.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
3117
3700
  return {
3118
3701
  data: prefixPluginTranslations(data, PLUGIN_ID),
3119
3702
  locale
@@ -3131,45 +3714,46 @@ const index = {
3131
3714
  };
3132
3715
  export {
3133
3716
  ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD as A,
3134
- extractContentTypeComponents as B,
3717
+ BulkActionsRenderer as B,
3135
3718
  COLLECTION_TYPES as C,
3136
3719
  DocumentStatus as D,
3137
- DEFAULT_SETTINGS as E,
3138
- convertEditLayoutToFieldLayouts as F,
3139
- useDocument as G,
3720
+ extractContentTypeComponents as E,
3721
+ DEFAULT_SETTINGS as F,
3722
+ convertEditLayoutToFieldLayouts as G,
3140
3723
  HOOKS as H,
3141
3724
  InjectionZone as I,
3142
- index as J,
3143
- useDocumentActions as K,
3725
+ useDocument as J,
3726
+ index as K,
3727
+ useDocumentActions as L,
3144
3728
  Panels as P,
3145
3729
  RelativeTime as R,
3146
3730
  SINGLE_TYPES as S,
3147
3731
  TableActions as T,
3148
- useGetAllContentTypeSettingsQuery as a,
3149
- useDoc as b,
3150
- buildValidParams as c,
3151
- contentManagerApi as d,
3152
- useDocumentRBAC as e,
3153
- useDocumentLayout as f,
3732
+ useGetInitialDataQuery as a,
3733
+ useGetAllContentTypeSettingsQuery as b,
3734
+ useDoc as c,
3735
+ buildValidParams as d,
3736
+ contentManagerApi as e,
3737
+ useDocumentRBAC as f,
3154
3738
  getTranslation as g,
3155
- createYupSchema as h,
3156
- Header as i,
3157
- PERMISSIONS as j,
3158
- DocumentRBAC as k,
3159
- DOCUMENT_META_FIELDS as l,
3160
- useDocLayout as m,
3161
- useContentTypeSchema as n,
3739
+ useDocumentLayout as h,
3740
+ createYupSchema as i,
3741
+ Header as j,
3742
+ PERMISSIONS as k,
3743
+ DocumentRBAC as l,
3744
+ DOCUMENT_META_FIELDS as m,
3745
+ useDocLayout as n,
3162
3746
  useGetContentTypeConfigurationQuery as o,
3163
3747
  CREATOR_FIELDS as p,
3164
3748
  getMainField as q,
3165
3749
  routes as r,
3166
3750
  setInitialData as s,
3167
3751
  getDisplayName as t,
3168
- useGetInitialDataQuery as u,
3752
+ useContentTypeSchema as u,
3169
3753
  checkIfAttributeIsDisplayable as v,
3170
3754
  useGetAllDocumentsQuery as w,
3171
3755
  convertListLayoutToFieldLayouts as x,
3172
3756
  capitalise as y,
3173
3757
  useUpdateContentTypeConfigurationMutation as z
3174
3758
  };
3175
- //# sourceMappingURL=index-CAc9yTnx.mjs.map
3759
+ //# sourceMappingURL=index-JNNNKUHs.mjs.map