@strapi/content-manager 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 0.0.0-experimental.edc24aaa3bb5a90fa5fd4fee208167dd4e2e38d4

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 (174) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
  3. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
  4. package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
  5. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
  6. package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js → ComponentConfigurationPage-5ukroXAh.js} +3 -3
  7. package/dist/_chunks/{ComponentConfigurationPage-DjWJdz6Y.js.map → ComponentConfigurationPage-5ukroXAh.js.map} +1 -1
  8. package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs → ComponentConfigurationPage-BAgyHiMm.mjs} +3 -3
  9. package/dist/_chunks/{ComponentConfigurationPage-BPvzFjM7.mjs.map → ComponentConfigurationPage-BAgyHiMm.mjs.map} +1 -1
  10. package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-BXdiCGQp.js} +8 -2
  11. package/dist/_chunks/ComponentIcon-BXdiCGQp.js.map +1 -0
  12. package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
  13. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
  14. package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs → EditConfigurationPage-DmoXawIh.mjs} +3 -3
  15. package/dist/_chunks/{EditConfigurationPage-DacbqQ_f.mjs.map → EditConfigurationPage-DmoXawIh.mjs.map} +1 -1
  16. package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js → EditConfigurationPage-Xp7lun0f.js} +3 -3
  17. package/dist/_chunks/{EditConfigurationPage-Dmv83RlS.js.map → EditConfigurationPage-Xp7lun0f.js.map} +1 -1
  18. package/dist/_chunks/{EditViewPage-DDS6H9HO.mjs → EditViewPage-BLsjc5F-.mjs} +47 -47
  19. package/dist/_chunks/EditViewPage-BLsjc5F-.mjs.map +1 -0
  20. package/dist/_chunks/{EditViewPage-DvNpQkam.js → EditViewPage-C-ukDOB7.js} +46 -48
  21. package/dist/_chunks/EditViewPage-C-ukDOB7.js.map +1 -0
  22. package/dist/_chunks/{Field-DmVKIAOo.js → Field-Bfph5SOd.js} +953 -782
  23. package/dist/_chunks/Field-Bfph5SOd.js.map +1 -0
  24. package/dist/_chunks/{Field-6gvGdPBV.mjs → Field-Cs7duwWd.mjs} +901 -729
  25. package/dist/_chunks/Field-Cs7duwWd.mjs.map +1 -0
  26. package/dist/_chunks/{Form-CPZC9vWa.js → Form-CPYqIWDG.js} +39 -38
  27. package/dist/_chunks/Form-CPYqIWDG.js.map +1 -0
  28. package/dist/_chunks/{Form-DW6K1IH-.mjs → Form-Dg_GS5TQ.mjs} +39 -37
  29. package/dist/_chunks/Form-Dg_GS5TQ.mjs.map +1 -0
  30. package/dist/_chunks/{History-DeAPlvtv.js → History-DNQkXANT.js} +149 -56
  31. package/dist/_chunks/History-DNQkXANT.js.map +1 -0
  32. package/dist/_chunks/{History-Dmr9fmUA.mjs → History-wrnHqf09.mjs} +148 -54
  33. package/dist/_chunks/History-wrnHqf09.mjs.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-DPCwW5Vr.js → ListConfigurationPage-CUQxfpjT.js} +58 -59
  35. package/dist/_chunks/ListConfigurationPage-CUQxfpjT.js.map +1 -0
  36. package/dist/_chunks/{ListConfigurationPage-DhwvYcNv.mjs → ListConfigurationPage-DScmJVkW.mjs} +54 -54
  37. package/dist/_chunks/ListConfigurationPage-DScmJVkW.mjs.map +1 -0
  38. package/dist/_chunks/{ListViewPage-5ySZ-VUs.js → ListViewPage-BsLiH2-2.js} +92 -108
  39. package/dist/_chunks/ListViewPage-BsLiH2-2.js.map +1 -0
  40. package/dist/_chunks/{ListViewPage-BtAwuYLE.mjs → ListViewPage-C4IvrMgY.mjs} +87 -103
  41. package/dist/_chunks/ListViewPage-C4IvrMgY.mjs.map +1 -0
  42. package/dist/_chunks/{NoContentTypePage-DOC_yWOf.js → NoContentTypePage-BZ-PnGAf.js} +3 -3
  43. package/dist/_chunks/NoContentTypePage-BZ-PnGAf.js.map +1 -0
  44. package/dist/_chunks/{NoContentTypePage-DSPxnxxp.mjs → NoContentTypePage-Djg8nPlj.mjs} +3 -3
  45. package/dist/_chunks/NoContentTypePage-Djg8nPlj.mjs.map +1 -0
  46. package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs → NoPermissionsPage-DSP7R-hv.mjs} +2 -2
  47. package/dist/_chunks/{NoPermissionsPage-UWDC-1Tw.mjs.map → NoPermissionsPage-DSP7R-hv.mjs.map} +1 -1
  48. package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js → NoPermissionsPage-_lUqjGW3.js} +2 -2
  49. package/dist/_chunks/{NoPermissionsPage-Dwu8rRJu.js.map → NoPermissionsPage-_lUqjGW3.js.map} +1 -1
  50. package/dist/_chunks/{Relations-J8cscLlR.mjs → Relations-BZr8tL0R.mjs} +66 -56
  51. package/dist/_chunks/Relations-BZr8tL0R.mjs.map +1 -0
  52. package/dist/_chunks/{Relations-CgWtgnPe.js → Relations-CtELXYIK.js} +70 -61
  53. package/dist/_chunks/Relations-CtELXYIK.js.map +1 -0
  54. package/dist/_chunks/{en-MBPul9Su.mjs → en-BrCTWlZv.mjs} +11 -4
  55. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-BrCTWlZv.mjs.map} +1 -1
  56. package/dist/_chunks/{en-C-V1_90f.js → en-uOUIxfcQ.js} +11 -4
  57. package/dist/_chunks/{en-C-V1_90f.js.map → en-uOUIxfcQ.js.map} +1 -1
  58. package/dist/_chunks/{index-C6AH2hEl.js → index-OerGjbAN.js} +1588 -837
  59. package/dist/_chunks/index-OerGjbAN.js.map +1 -0
  60. package/dist/_chunks/{index-CwRRo1V9.mjs → index-c_5DdJi-.mjs} +1610 -858
  61. package/dist/_chunks/index-c_5DdJi-.mjs.map +1 -0
  62. package/dist/_chunks/{layout-B_SXLhqf.js → layout-Ci7qHlFb.js} +30 -27
  63. package/dist/_chunks/layout-Ci7qHlFb.js.map +1 -0
  64. package/dist/_chunks/{layout-jIDzX0Fp.mjs → layout-oPBiO7RY.mjs} +29 -24
  65. package/dist/_chunks/layout-oPBiO7RY.mjs.map +1 -0
  66. package/dist/_chunks/{relations-CuvIgCqI.mjs → relations-BIdWFjdq.mjs} +2 -2
  67. package/dist/_chunks/{relations-CuvIgCqI.mjs.map → relations-BIdWFjdq.mjs.map} +1 -1
  68. package/dist/_chunks/{relations-iBMa_OFG.js → relations-COBpStiF.js} +2 -2
  69. package/dist/_chunks/{relations-iBMa_OFG.js.map → relations-COBpStiF.js.map} +1 -1
  70. package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
  71. package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
  72. package/dist/_chunks/usePrev-B9w_-eYc.js +15 -0
  73. package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -0
  74. package/dist/_chunks/usePrev-DH6iah0A.mjs +16 -0
  75. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +1 -0
  76. package/dist/admin/index.js +2 -1
  77. package/dist/admin/index.js.map +1 -1
  78. package/dist/admin/index.mjs +5 -4
  79. package/dist/admin/src/components/ComponentIcon.d.ts +6 -3
  80. package/dist/admin/src/content-manager.d.ts +3 -3
  81. package/dist/admin/src/exports.d.ts +1 -0
  82. package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
  83. package/dist/admin/src/history/index.d.ts +3 -0
  84. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  85. package/dist/admin/src/hooks/useDocument.d.ts +5 -8
  86. package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
  87. package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
  88. package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
  89. package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
  90. package/dist/admin/src/index.d.ts +1 -0
  91. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +11 -4
  92. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
  93. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
  94. package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
  95. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
  96. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  97. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +30 -18
  98. package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
  99. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
  100. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.d.ts +2 -2
  101. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +59 -52
  102. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  103. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  104. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  105. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  106. package/dist/admin/src/services/api.d.ts +2 -3
  107. package/dist/admin/src/services/components.d.ts +2 -2
  108. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  109. package/dist/admin/src/services/documents.d.ts +29 -17
  110. package/dist/admin/src/services/init.d.ts +2 -2
  111. package/dist/admin/src/services/relations.d.ts +3 -3
  112. package/dist/admin/src/services/uid.d.ts +3 -3
  113. package/dist/admin/src/utils/api.d.ts +4 -18
  114. package/dist/admin/src/utils/validation.d.ts +1 -6
  115. package/dist/server/index.js +309 -218
  116. package/dist/server/index.js.map +1 -1
  117. package/dist/server/index.mjs +317 -226
  118. package/dist/server/index.mjs.map +1 -1
  119. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  120. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  121. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  122. package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
  123. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  124. package/dist/server/src/controllers/validation/dimensions.d.ts +11 -0
  125. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  126. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  127. package/dist/server/src/history/services/history.d.ts.map +1 -1
  128. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  129. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  130. package/dist/server/src/index.d.ts +18 -39
  131. package/dist/server/src/index.d.ts.map +1 -1
  132. package/dist/server/src/services/document-manager.d.ts +13 -12
  133. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  134. package/dist/server/src/services/document-metadata.d.ts +8 -29
  135. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  136. package/dist/server/src/services/index.d.ts +18 -39
  137. package/dist/server/src/services/index.d.ts.map +1 -1
  138. package/dist/server/src/services/utils/populate.d.ts +8 -1
  139. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  140. package/dist/shared/contracts/collection-types.d.ts +14 -6
  141. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  142. package/dist/shared/contracts/relations.d.ts +2 -2
  143. package/dist/shared/contracts/relations.d.ts.map +1 -1
  144. package/package.json +13 -14
  145. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  146. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  147. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  148. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  149. package/dist/_chunks/EditViewPage-DDS6H9HO.mjs.map +0 -1
  150. package/dist/_chunks/EditViewPage-DvNpQkam.js.map +0 -1
  151. package/dist/_chunks/Field-6gvGdPBV.mjs.map +0 -1
  152. package/dist/_chunks/Field-DmVKIAOo.js.map +0 -1
  153. package/dist/_chunks/Form-CPZC9vWa.js.map +0 -1
  154. package/dist/_chunks/Form-DW6K1IH-.mjs.map +0 -1
  155. package/dist/_chunks/History-DeAPlvtv.js.map +0 -1
  156. package/dist/_chunks/History-Dmr9fmUA.mjs.map +0 -1
  157. package/dist/_chunks/ListConfigurationPage-DPCwW5Vr.js.map +0 -1
  158. package/dist/_chunks/ListConfigurationPage-DhwvYcNv.mjs.map +0 -1
  159. package/dist/_chunks/ListViewPage-5ySZ-VUs.js.map +0 -1
  160. package/dist/_chunks/ListViewPage-BtAwuYLE.mjs.map +0 -1
  161. package/dist/_chunks/NoContentTypePage-DOC_yWOf.js.map +0 -1
  162. package/dist/_chunks/NoContentTypePage-DSPxnxxp.mjs.map +0 -1
  163. package/dist/_chunks/Relations-CgWtgnPe.js.map +0 -1
  164. package/dist/_chunks/Relations-J8cscLlR.mjs.map +0 -1
  165. package/dist/_chunks/index-C6AH2hEl.js.map +0 -1
  166. package/dist/_chunks/index-CwRRo1V9.mjs.map +0 -1
  167. package/dist/_chunks/layout-B_SXLhqf.js.map +0 -1
  168. package/dist/_chunks/layout-jIDzX0Fp.mjs.map +0 -1
  169. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  170. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  171. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  172. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  173. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  174. package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
@@ -1,19 +1,17 @@
1
- import { ClockCounterClockwise, CrossCircle, More, WarningCircle, Cog, Pencil, Trash, ChevronRight, Duplicate, Feather } from "@strapi/icons";
1
+ import { CrossCircle, More, WarningCircle, ListPlus, Pencil, Trash, Check, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, 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";
4
- import { stringify } from "qs";
5
- import { useIntl } from "react-intl";
6
- import { useNavigate, useParams, Navigate, useMatch, NavLink } from "react-router-dom";
3
+ import { useStrapiApp, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useQueryParams, useTracking, useForm, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
7
4
  import * as React from "react";
8
5
  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";
6
+ import { Button, Menu, VisuallyHidden, Flex, Box, Typography, Dialog, Modal, Radio, Status, SingleSelect, SingleSelectOption, Loader, IconButton, Tooltip, LinkButton } from "@strapi/design-system";
7
+ import { useIntl } from "react-intl";
8
+ import { useParams, Navigate, useNavigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
9
+ import { styled } from "styled-components";
11
10
  import * as yup from "yup";
12
11
  import { ValidationError } from "yup";
13
- import { createApi } from "@reduxjs/toolkit/query/react";
14
- import { isAxiosError } from "axios";
15
12
  import pipe from "lodash/fp/pipe";
16
13
  import { intervalToDuration, isPast } from "date-fns";
14
+ import { stringify } from "qs";
17
15
  import { createSlice, combineReducers } from "@reduxjs/toolkit";
18
16
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
19
17
  const v = glob[path];
@@ -51,42 +49,6 @@ const useInjectionZone = (area) => {
51
49
  const [page, position] = area.split(".");
52
50
  return contentManagerPlugin.getInjectedComponents(page, position);
53
51
  };
54
- const HistoryAction = ({ model, document }) => {
55
- const { formatMessage } = useIntl();
56
- const [{ query }] = useQueryParams();
57
- const navigate = useNavigate();
58
- const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
59
- if (!window.strapi.features.isEnabled("cms-content-history")) {
60
- return null;
61
- }
62
- return {
63
- icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
64
- label: formatMessage({
65
- id: "content-manager.history.document-action",
66
- defaultMessage: "Content History"
67
- }),
68
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
69
- disabled: (
70
- /**
71
- * The user is creating a new document.
72
- * It hasn't been saved yet, so there's no history to go to
73
- */
74
- !document || /**
75
- * The document has been created but the current dimension has never been saved.
76
- * For example, the user is creating a new locale in an existing document,
77
- * so there's no history for the document in that locale
78
- */
79
- !document.id || /**
80
- * History is only available for content types created by the user.
81
- * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
82
- * which start with `admin::` or `plugin::`
83
- */
84
- !model.startsWith("api::")
85
- ),
86
- position: "header"
87
- };
88
- };
89
- HistoryAction.type = "history";
90
52
  const ID = "id";
91
53
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
92
54
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -157,9 +119,8 @@ const DocumentRBAC = ({ children, permissions }) => {
157
119
  const name = removeNumericalStrings(fieldName.split("."));
158
120
  const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
159
121
  if (fieldType === "component") {
160
- const componentOrDynamicZoneFields = componentFieldNames.map((field) => field.split("."));
161
- return componentOrDynamicZoneFields.some((field) => {
162
- return field.includes(fieldName);
122
+ return componentFieldNames.some((field) => {
123
+ return field.includes(name.join("."));
163
124
  });
164
125
  }
165
126
  if (name.length > 1) {
@@ -189,78 +150,8 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
189
150
  (field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
190
151
  );
191
152
  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: [
153
+ const contentManagerApi = adminApi.enhanceEndpoints({
154
+ addTagTypes: [
264
155
  "ComponentConfiguration",
265
156
  "ContentTypesConfiguration",
266
157
  "ContentTypeSettings",
@@ -268,10 +159,10 @@ const contentManagerApi = createApi({
268
159
  "InitialData",
269
160
  "HistoryVersion",
270
161
  "Relations"
271
- ],
272
- endpoints: () => ({})
162
+ ]
273
163
  });
274
164
  const documentApi = contentManagerApi.injectEndpoints({
165
+ overrideExisting: true,
275
166
  endpoints: (builder) => ({
276
167
  autoCloneDocument: builder.mutation({
277
168
  query: ({ model, sourceId, query }) => ({
@@ -281,7 +172,12 @@ const documentApi = contentManagerApi.injectEndpoints({
281
172
  params: query
282
173
  }
283
174
  }),
284
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
175
+ invalidatesTags: (_result, error, { model }) => {
176
+ if (error) {
177
+ return [];
178
+ }
179
+ return [{ type: "Document", id: `${model}_LIST` }];
180
+ }
285
181
  }),
286
182
  cloneDocument: builder.mutation({
287
183
  query: ({ model, sourceId, data, params }) => ({
@@ -325,12 +221,15 @@ const documentApi = contentManagerApi.injectEndpoints({
325
221
  ]
326
222
  }),
327
223
  deleteManyDocuments: builder.mutation({
328
- query: ({ model, ...body }) => ({
224
+ query: ({ model, params, ...body }) => ({
329
225
  url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
330
226
  method: "POST",
331
- data: body
227
+ data: body,
228
+ config: {
229
+ params
230
+ }
332
231
  }),
333
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
232
+ invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
334
233
  }),
335
234
  discardDocument: builder.mutation({
336
235
  query: ({ collectionType, model, documentId, params }) => ({
@@ -441,10 +340,13 @@ const documentApi = contentManagerApi.injectEndpoints({
441
340
  }
442
341
  }),
443
342
  publishManyDocuments: builder.mutation({
444
- query: ({ model, ...body }) => ({
343
+ query: ({ model, params, ...body }) => ({
445
344
  url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
446
345
  method: "POST",
447
- data: body
346
+ data: body,
347
+ config: {
348
+ params
349
+ }
448
350
  }),
449
351
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
450
352
  }),
@@ -465,6 +367,18 @@ const documentApi = contentManagerApi.injectEndpoints({
465
367
  },
466
368
  "Relations"
467
369
  ];
370
+ },
371
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
372
+ const patchResult = dispatch(
373
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
374
+ Object.assign(draft.data, data);
375
+ })
376
+ );
377
+ try {
378
+ await queryFulfilled;
379
+ } catch {
380
+ patchResult.undo();
381
+ }
468
382
  }
469
383
  }),
470
384
  unpublishDocument: builder.mutation({
@@ -486,10 +400,13 @@ const documentApi = contentManagerApi.injectEndpoints({
486
400
  }
487
401
  }),
488
402
  unpublishManyDocuments: builder.mutation({
489
- query: ({ model, ...body }) => ({
403
+ query: ({ model, params, ...body }) => ({
490
404
  url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
491
405
  method: "POST",
492
- data: body
406
+ data: body,
407
+ config: {
408
+ params
409
+ }
493
410
  }),
494
411
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
495
412
  })
@@ -513,6 +430,24 @@ const {
513
430
  useUnpublishDocumentMutation,
514
431
  useUnpublishManyDocumentsMutation
515
432
  } = documentApi;
433
+ const buildValidParams = (query) => {
434
+ if (!query)
435
+ return query;
436
+ const { plugins: _, ...validQueryParams } = {
437
+ ...query,
438
+ ...Object.values(query?.plugins ?? {}).reduce(
439
+ (acc, current) => Object.assign(acc, current),
440
+ {}
441
+ )
442
+ };
443
+ if ("_q" in validQueryParams) {
444
+ validQueryParams._q = encodeURIComponent(validQueryParams._q);
445
+ }
446
+ return validQueryParams;
447
+ };
448
+ const isBaseQueryError = (error) => {
449
+ return error.name !== void 0;
450
+ };
516
451
  const createYupSchema = (attributes = {}, components = {}) => {
517
452
  const createModelSchema = (attributes2) => yup.object().shape(
518
453
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
@@ -552,10 +487,14 @@ const createYupSchema = (attributes = {}, components = {}) => {
552
487
  yup.array().of(
553
488
  yup.lazy(
554
489
  (data) => {
555
- const { attributes: attributes3 } = components[data.__component];
556
- return yup.object().shape({
490
+ const attributes3 = components?.[data?.__component]?.attributes;
491
+ const validation = yup.object().shape({
557
492
  __component: yup.string().required().oneOf(Object.keys(components))
558
- }).nullable(false).concat(createModelSchema(attributes3));
493
+ }).nullable(false);
494
+ if (!attributes3) {
495
+ return validation;
496
+ }
497
+ return validation.concat(createModelSchema(attributes3));
559
498
  }
560
499
  )
561
500
  )
@@ -565,11 +504,25 @@ const createYupSchema = (attributes = {}, components = {}) => {
565
504
  return {
566
505
  ...acc,
567
506
  [name]: transformSchema(
568
- yup.array().of(
569
- yup.object().shape({
570
- id: yup.string().required()
571
- })
572
- )
507
+ yup.lazy((value) => {
508
+ if (!value) {
509
+ return yup.mixed().nullable(true);
510
+ } else if (Array.isArray(value)) {
511
+ return yup.array().of(
512
+ yup.object().shape({
513
+ id: yup.string().required()
514
+ })
515
+ );
516
+ } else if (typeof value === "object") {
517
+ return yup.object();
518
+ } else {
519
+ return yup.mixed().test(
520
+ "type-error",
521
+ "Relation values must be either null, an array of objects with {id} or an object.",
522
+ () => false
523
+ );
524
+ }
525
+ })
573
526
  )
574
527
  };
575
528
  default:
@@ -628,13 +581,18 @@ const createAttributeSchema = (attribute) => {
628
581
  }
629
582
  };
630
583
  const addRequiredValidation = (attribute) => (schema) => {
631
- if (attribute.required) {
632
- return schema.required({
633
- id: translatedErrors.required.id,
634
- defaultMessage: "This field is required."
635
- });
584
+ if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
585
+ return schema.min(1, translatedErrors.required);
636
586
  }
637
- return schema.nullable();
587
+ if (attribute.required && attribute.type !== "relation") {
588
+ return schema.required(translatedErrors.required);
589
+ }
590
+ return schema?.nullable ? schema.nullable() : (
591
+ // In some cases '.nullable' will not be available on the schema.
592
+ // e.g. when the schema has been built using yup.lazy (e.g. for relations).
593
+ // In these cases we should just return the schema as it is.
594
+ schema
595
+ );
638
596
  };
639
597
  const addMinLengthValidation = (attribute) => (schema) => {
640
598
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
@@ -661,6 +619,28 @@ const addMaxLengthValidation = (attribute) => (schema) => {
661
619
  const addMinValidation = (attribute) => (schema) => {
662
620
  if ("min" in attribute) {
663
621
  const min = toInteger(attribute.min);
622
+ if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
623
+ if (!attribute.required && "test" in schema && min) {
624
+ return schema.test(
625
+ "custom-min",
626
+ {
627
+ ...translatedErrors.min,
628
+ values: {
629
+ min: attribute.min
630
+ }
631
+ },
632
+ (value) => {
633
+ if (!value) {
634
+ return true;
635
+ }
636
+ if (Array.isArray(value) && value.length === 0) {
637
+ return true;
638
+ }
639
+ return value.length >= min;
640
+ }
641
+ );
642
+ }
643
+ }
664
644
  if ("min" in schema && min) {
665
645
  return schema.min(min, {
666
646
  ...translatedErrors.min,
@@ -706,24 +686,6 @@ const addRegexValidation = (attribute) => (schema) => {
706
686
  }
707
687
  return schema;
708
688
  };
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
689
  const initApi = contentManagerApi.injectEndpoints({
728
690
  endpoints: (builder) => ({
729
691
  getInitialData: builder.query({
@@ -737,27 +699,20 @@ const { useGetInitialDataQuery } = initApi;
737
699
  const useContentTypeSchema = (model) => {
738
700
  const { toggleNotification } = useNotification();
739
701
  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
- });
702
+ const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
703
+ const { components, contentType, contentTypes } = React.useMemo(() => {
704
+ const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
705
+ const componentsByKey = data?.components.reduce((acc, component) => {
706
+ acc[component.uid] = component;
707
+ return acc;
708
+ }, {});
709
+ const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
710
+ return {
711
+ components: Object.keys(components2).length === 0 ? void 0 : components2,
712
+ contentType: contentType2,
713
+ contentTypes: data?.contentTypes ?? []
714
+ };
715
+ }, [model, data]);
761
716
  React.useEffect(() => {
762
717
  if (error) {
763
718
  toggleNotification({
@@ -812,7 +767,10 @@ const useDocument = (args, opts) => {
812
767
  isLoading: isLoadingDocument,
813
768
  isFetching: isFetchingDocument,
814
769
  error
815
- } = useGetDocumentQuery(args, opts);
770
+ } = useGetDocumentQuery(args, {
771
+ ...opts,
772
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
773
+ });
816
774
  const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
817
775
  React.useEffect(() => {
818
776
  if (error) {
@@ -840,7 +798,7 @@ const useDocument = (args, opts) => {
840
798
  return null;
841
799
  } catch (error2) {
842
800
  if (error2 instanceof ValidationError) {
843
- return getInnerErrors(error2);
801
+ return getYupValidationErrors(error2);
844
802
  }
845
803
  throw error2;
846
804
  }
@@ -936,14 +894,53 @@ const useDocumentActions = () => {
936
894
  },
937
895
  [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
938
896
  );
897
+ const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
898
+ const deleteMany = React.useCallback(
899
+ async ({ model, documentIds, params }) => {
900
+ try {
901
+ trackUsage("willBulkDeleteEntries");
902
+ const res = await deleteManyDocuments({
903
+ model,
904
+ documentIds,
905
+ params
906
+ });
907
+ if ("error" in res) {
908
+ toggleNotification({
909
+ type: "danger",
910
+ message: formatAPIError(res.error)
911
+ });
912
+ return { error: res.error };
913
+ }
914
+ toggleNotification({
915
+ type: "success",
916
+ title: formatMessage({
917
+ id: getTranslation("success.records.delete"),
918
+ defaultMessage: "Successfully deleted."
919
+ }),
920
+ message: ""
921
+ });
922
+ trackUsage("didBulkDeleteEntries");
923
+ return res.data;
924
+ } catch (err) {
925
+ toggleNotification({
926
+ type: "danger",
927
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
928
+ });
929
+ trackUsage("didNotBulkDeleteEntries");
930
+ throw err;
931
+ }
932
+ },
933
+ [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
934
+ );
939
935
  const [discardDocument] = useDiscardDocumentMutation();
940
936
  const discard = React.useCallback(
941
- async ({ collectionType, model, documentId }) => {
937
+ async ({ collectionType, model, documentId, params }) => {
942
938
  try {
943
939
  const res = await discardDocument({
944
940
  collectionType,
945
941
  model,
946
- documentId
942
+ documentId,
943
+ params
947
944
  });
948
945
  if ("error" in res) {
949
946
  toggleNotification({
@@ -1005,6 +1002,43 @@ const useDocumentActions = () => {
1005
1002
  },
1006
1003
  [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1007
1004
  );
1005
+ const [publishManyDocuments] = usePublishManyDocumentsMutation();
1006
+ const publishMany = React.useCallback(
1007
+ async ({ model, documentIds, params }) => {
1008
+ try {
1009
+ const res = await publishManyDocuments({
1010
+ model,
1011
+ documentIds,
1012
+ params
1013
+ });
1014
+ if ("error" in res) {
1015
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1016
+ return { error: res.error };
1017
+ }
1018
+ toggleNotification({
1019
+ type: "success",
1020
+ message: formatMessage({
1021
+ id: getTranslation("success.record.publish"),
1022
+ defaultMessage: "Published document"
1023
+ })
1024
+ });
1025
+ return res.data;
1026
+ } catch (err) {
1027
+ toggleNotification({
1028
+ type: "danger",
1029
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1030
+ });
1031
+ throw err;
1032
+ }
1033
+ },
1034
+ [
1035
+ // trackUsage,
1036
+ publishManyDocuments,
1037
+ toggleNotification,
1038
+ formatMessage,
1039
+ formatAPIError
1040
+ ]
1041
+ );
1008
1042
  const [updateDocument] = useUpdateDocumentMutation();
1009
1043
  const update = React.useCallback(
1010
1044
  async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
@@ -1079,6 +1113,41 @@ const useDocumentActions = () => {
1079
1113
  },
1080
1114
  [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1081
1115
  );
1116
+ const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1117
+ const unpublishMany = React.useCallback(
1118
+ async ({ model, documentIds, params }) => {
1119
+ try {
1120
+ trackUsage("willBulkUnpublishEntries");
1121
+ const res = await unpublishManyDocuments({
1122
+ model,
1123
+ documentIds,
1124
+ params
1125
+ });
1126
+ if ("error" in res) {
1127
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1128
+ return { error: res.error };
1129
+ }
1130
+ trackUsage("didBulkUnpublishEntries");
1131
+ toggleNotification({
1132
+ type: "success",
1133
+ title: formatMessage({
1134
+ id: getTranslation("success.records.unpublish"),
1135
+ defaultMessage: "Successfully unpublished."
1136
+ }),
1137
+ message: ""
1138
+ });
1139
+ return res.data;
1140
+ } catch (err) {
1141
+ toggleNotification({
1142
+ type: "danger",
1143
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1144
+ });
1145
+ trackUsage("didNotBulkUnpublishEntries");
1146
+ throw err;
1147
+ }
1148
+ },
1149
+ [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1150
+ );
1082
1151
  const [createDocument] = useCreateDocumentMutation();
1083
1152
  const create = React.useCallback(
1084
1153
  async ({ model, params }, data, trackerProperty) => {
@@ -1122,7 +1191,6 @@ const useDocumentActions = () => {
1122
1191
  sourceId
1123
1192
  });
1124
1193
  if ("error" in res) {
1125
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1126
1194
  return { error: res.error };
1127
1195
  }
1128
1196
  toggleNotification({
@@ -1192,15 +1260,18 @@ const useDocumentActions = () => {
1192
1260
  clone,
1193
1261
  create,
1194
1262
  delete: _delete,
1263
+ deleteMany,
1195
1264
  discard,
1196
1265
  getDocument,
1197
1266
  publish,
1267
+ publishMany,
1198
1268
  unpublish,
1269
+ unpublishMany,
1199
1270
  update
1200
1271
  };
1201
1272
  };
1202
1273
  const ProtectedHistoryPage = lazy(
1203
- () => import("./History-Dmr9fmUA.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1274
+ () => import("./History-wrnHqf09.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1204
1275
  );
1205
1276
  const routes$1 = [
1206
1277
  {
@@ -1213,31 +1284,31 @@ const routes$1 = [
1213
1284
  }
1214
1285
  ];
1215
1286
  const ProtectedEditViewPage = lazy(
1216
- () => import("./EditViewPage-DDS6H9HO.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1287
+ () => import("./EditViewPage-BLsjc5F-.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1217
1288
  );
1218
1289
  const ProtectedListViewPage = lazy(
1219
- () => import("./ListViewPage-BtAwuYLE.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1290
+ () => import("./ListViewPage-C4IvrMgY.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1220
1291
  );
1221
1292
  const ProtectedListConfiguration = lazy(
1222
- () => import("./ListConfigurationPage-DhwvYcNv.mjs").then((mod) => ({
1293
+ () => import("./ListConfigurationPage-DScmJVkW.mjs").then((mod) => ({
1223
1294
  default: mod.ProtectedListConfiguration
1224
1295
  }))
1225
1296
  );
1226
1297
  const ProtectedEditConfigurationPage = lazy(
1227
- () => import("./EditConfigurationPage-DacbqQ_f.mjs").then((mod) => ({
1298
+ () => import("./EditConfigurationPage-DmoXawIh.mjs").then((mod) => ({
1228
1299
  default: mod.ProtectedEditConfigurationPage
1229
1300
  }))
1230
1301
  );
1231
1302
  const ProtectedComponentConfigurationPage = lazy(
1232
- () => import("./ComponentConfigurationPage-BPvzFjM7.mjs").then((mod) => ({
1303
+ () => import("./ComponentConfigurationPage-BAgyHiMm.mjs").then((mod) => ({
1233
1304
  default: mod.ProtectedComponentConfigurationPage
1234
1305
  }))
1235
1306
  );
1236
1307
  const NoPermissions = lazy(
1237
- () => import("./NoPermissionsPage-UWDC-1Tw.mjs").then((mod) => ({ default: mod.NoPermissions }))
1308
+ () => import("./NoPermissionsPage-DSP7R-hv.mjs").then((mod) => ({ default: mod.NoPermissions }))
1238
1309
  );
1239
1310
  const NoContentType = lazy(
1240
- () => import("./NoContentTypePage-DSPxnxxp.mjs").then((mod) => ({ default: mod.NoContentType }))
1311
+ () => import("./NoContentTypePage-Djg8nPlj.mjs").then((mod) => ({ default: mod.NoContentType }))
1241
1312
  );
1242
1313
  const CollectionTypePages = () => {
1243
1314
  const { collectionType } = useParams();
@@ -1364,7 +1435,7 @@ const DocumentActionButton = (action) => {
1364
1435
  DocumentActionConfirmDialog,
1365
1436
  {
1366
1437
  ...action.dialog,
1367
- variant: action.variant,
1438
+ variant: action.dialog?.variant ?? action.variant,
1368
1439
  isOpen: dialogId === action.id,
1369
1440
  onClose: handleClose
1370
1441
  }
@@ -1427,7 +1498,7 @@ const DocumentActionsMenu = ({
1427
1498
  variant,
1428
1499
  children: [
1429
1500
  /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
1430
- /* @__PURE__ */ jsx(VisuallyHidden, { as: "span", children: label || formatMessage({
1501
+ /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: label || formatMessage({
1431
1502
  id: "content-manager.containers.edit.panels.default.more-actions",
1432
1503
  defaultMessage: "More document actions"
1433
1504
  }) })
@@ -1443,8 +1514,8 @@ const DocumentActionsMenu = ({
1443
1514
  onSelect: handleClick(action),
1444
1515
  display: "block",
1445
1516
  children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
1446
- /* @__PURE__ */ jsxs(Flex, { color: convertActionVariantToColor(action.variant), gap: 2, as: "span", children: [
1447
- action.icon,
1517
+ /* @__PURE__ */ jsxs(Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1518
+ /* @__PURE__ */ jsx(Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1448
1519
  action.label
1449
1520
  ] }),
1450
1521
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
@@ -1505,6 +1576,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1505
1576
  return "primary600";
1506
1577
  }
1507
1578
  };
1579
+ const convertActionVariantToIconColor = (variant = "secondary") => {
1580
+ switch (variant) {
1581
+ case "danger":
1582
+ return "danger600";
1583
+ case "secondary":
1584
+ return "neutral500";
1585
+ case "success":
1586
+ return "success600";
1587
+ default:
1588
+ return "primary600";
1589
+ }
1590
+ };
1508
1591
  const DocumentActionConfirmDialog = ({
1509
1592
  onClose,
1510
1593
  onCancel,
@@ -1527,61 +1610,42 @@ const DocumentActionConfirmDialog = ({
1527
1610
  }
1528
1611
  onClose();
1529
1612
  };
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
- ] });
1613
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
1614
+ /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
1615
+ /* @__PURE__ */ jsx(Dialog.Body, { children: content }),
1616
+ /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
1617
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
1618
+ id: "app.components.Button.cancel",
1619
+ defaultMessage: "Cancel"
1620
+ }) }) }),
1621
+ /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
1622
+ id: "app.components.Button.confirm",
1623
+ defaultMessage: "Confirm"
1624
+ }) })
1625
+ ] })
1626
+ ] }) });
1546
1627
  };
1547
1628
  const DocumentActionModal = ({
1548
1629
  isOpen,
1549
1630
  title,
1550
1631
  onClose,
1551
1632
  footer: Footer,
1552
- content,
1633
+ content: Content,
1553
1634
  onModalClose
1554
1635
  }) => {
1555
- const id = React.useId();
1556
- if (!isOpen) {
1557
- return null;
1558
- }
1559
1636
  const handleClose = () => {
1560
1637
  if (onClose) {
1561
1638
  onClose();
1562
1639
  }
1563
1640
  onModalClose();
1564
1641
  };
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
- ] });
1642
+ return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
1643
+ /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
1644
+ typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
1645
+ typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
1646
+ ] }) });
1583
1647
  };
1584
- const PublishAction = ({
1648
+ const PublishAction$1 = ({
1585
1649
  activeTab,
1586
1650
  documentId,
1587
1651
  model,
@@ -1600,6 +1664,12 @@ const PublishAction = ({
1600
1664
  ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1601
1665
  );
1602
1666
  const { publish } = useDocumentActions();
1667
+ const [
1668
+ countDraftRelations,
1669
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
1670
+ ] = useLazyGetDraftRelationCountQuery();
1671
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
1672
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
1603
1673
  const [{ query, rawQuery }] = useQueryParams();
1604
1674
  const params = React.useMemo(() => buildValidParams(query), [query]);
1605
1675
  const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1608,15 +1678,106 @@ const PublishAction = ({
1608
1678
  const validate = useForm("PublishAction", (state) => state.validate);
1609
1679
  const setErrors = useForm("PublishAction", (state) => state.setErrors);
1610
1680
  const formValues = useForm("PublishAction", ({ values }) => values);
1611
- const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1612
- if (!schema?.options?.draftAndPublish) {
1613
- return null;
1614
- }
1615
- return {
1616
- /**
1617
- * Disabled when:
1618
- * - currently if you're cloning a document we don't support publish & clone at the same time.
1619
- * - the form is submitting
1681
+ React.useEffect(() => {
1682
+ if (isErrorDraftRelations) {
1683
+ toggleNotification({
1684
+ type: "danger",
1685
+ message: formatMessage({
1686
+ id: getTranslation("error.records.fetch-draft-relatons"),
1687
+ defaultMessage: "An error occurred while fetching draft relations on this document."
1688
+ })
1689
+ });
1690
+ }
1691
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
1692
+ React.useEffect(() => {
1693
+ const localDraftRelations = /* @__PURE__ */ new Set();
1694
+ const extractDraftRelations = (data) => {
1695
+ const relations = data.connect || [];
1696
+ relations.forEach((relation) => {
1697
+ if (relation.status === "draft") {
1698
+ localDraftRelations.add(relation.id);
1699
+ }
1700
+ });
1701
+ };
1702
+ const traverseAndExtract = (data) => {
1703
+ Object.entries(data).forEach(([key, value]) => {
1704
+ if (key === "connect" && Array.isArray(value)) {
1705
+ extractDraftRelations({ connect: value });
1706
+ } else if (typeof value === "object" && value !== null) {
1707
+ traverseAndExtract(value);
1708
+ }
1709
+ });
1710
+ };
1711
+ if (!documentId || modified) {
1712
+ traverseAndExtract(formValues);
1713
+ setLocalCountOfDraftRelations(localDraftRelations.size);
1714
+ }
1715
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
1716
+ React.useEffect(() => {
1717
+ if (documentId) {
1718
+ const fetchDraftRelationsCount = async () => {
1719
+ const { data, error } = await countDraftRelations({
1720
+ collectionType,
1721
+ model,
1722
+ documentId,
1723
+ params
1724
+ });
1725
+ if (error) {
1726
+ throw error;
1727
+ }
1728
+ if (data) {
1729
+ setServerCountOfDraftRelations(data.data);
1730
+ }
1731
+ };
1732
+ fetchDraftRelationsCount();
1733
+ }
1734
+ }, [documentId, countDraftRelations, collectionType, model, params]);
1735
+ const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1736
+ if (!schema?.options?.draftAndPublish) {
1737
+ return null;
1738
+ }
1739
+ const performPublish = async () => {
1740
+ setSubmitting(true);
1741
+ try {
1742
+ const { errors } = await validate();
1743
+ if (errors) {
1744
+ toggleNotification({
1745
+ type: "danger",
1746
+ message: formatMessage({
1747
+ id: "content-manager.validation.error",
1748
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1749
+ })
1750
+ });
1751
+ return;
1752
+ }
1753
+ const res = await publish(
1754
+ {
1755
+ collectionType,
1756
+ model,
1757
+ documentId,
1758
+ params
1759
+ },
1760
+ formValues
1761
+ );
1762
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
1763
+ navigate({
1764
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1765
+ search: rawQuery
1766
+ });
1767
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1768
+ setErrors(formatValidationErrors(res.error));
1769
+ }
1770
+ } finally {
1771
+ setSubmitting(false);
1772
+ }
1773
+ };
1774
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1775
+ const hasDraftRelations = totalDraftRelations > 0;
1776
+ return {
1777
+ /**
1778
+ * Disabled when:
1779
+ * - currently if you're cloning a document we don't support publish & clone at the same time.
1780
+ * - the form is submitting
1620
1781
  * - the active tab is the published tab
1621
1782
  * - the document is already published & not modified
1622
1783
  * - the document is being created & not modified
@@ -1624,49 +1785,41 @@ const PublishAction = ({
1624
1785
  * - the user doesn't have the permission to create a new document
1625
1786
  * - the user doesn't have the permission to update the document
1626
1787
  */
1627
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1788
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1628
1789
  label: formatMessage({
1629
1790
  id: "app.utils.publish",
1630
1791
  defaultMessage: "Publish"
1631
1792
  }),
1632
1793
  onClick: async () => {
1633
- setSubmitting(true);
1634
- try {
1635
- const { errors } = await validate();
1636
- if (errors) {
1637
- toggleNotification({
1638
- type: "danger",
1639
- message: formatMessage({
1640
- id: "content-manager.validation.error",
1641
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1642
- })
1643
- });
1644
- return;
1645
- }
1646
- const res = await publish(
1647
- {
1648
- collectionType,
1649
- model,
1650
- documentId,
1651
- params
1652
- },
1653
- formValues
1654
- );
1655
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1656
- navigate({
1657
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1658
- search: rawQuery
1659
- });
1660
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1661
- setErrors(formatValidationErrors(res.error));
1794
+ if (hasDraftRelations) {
1795
+ return;
1796
+ }
1797
+ await performPublish();
1798
+ },
1799
+ dialog: hasDraftRelations ? {
1800
+ type: "dialog",
1801
+ variant: "danger",
1802
+ footer: null,
1803
+ title: formatMessage({
1804
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
1805
+ defaultMessage: "Confirmation"
1806
+ }),
1807
+ content: formatMessage(
1808
+ {
1809
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
1810
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
1811
+ },
1812
+ {
1813
+ count: totalDraftRelations
1662
1814
  }
1663
- } finally {
1664
- setSubmitting(false);
1815
+ ),
1816
+ onConfirm: async () => {
1817
+ await performPublish();
1665
1818
  }
1666
- }
1819
+ } : void 0
1667
1820
  };
1668
1821
  };
1669
- PublishAction.type = "publish";
1822
+ PublishAction$1.type = "publish";
1670
1823
  const UpdateAction = ({
1671
1824
  activeTab,
1672
1825
  documentId,
@@ -1731,10 +1884,13 @@ const UpdateAction = ({
1731
1884
  document
1732
1885
  );
1733
1886
  if ("data" in res) {
1734
- navigate({
1735
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1736
- search: rawQuery
1737
- });
1887
+ navigate(
1888
+ {
1889
+ pathname: `../${res.data.documentId}`,
1890
+ search: rawQuery
1891
+ },
1892
+ { relative: "path" }
1893
+ );
1738
1894
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1739
1895
  setErrors(formatValidationErrors(res.error));
1740
1896
  }
@@ -1762,10 +1918,13 @@ const UpdateAction = ({
1762
1918
  document
1763
1919
  );
1764
1920
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1765
- navigate({
1766
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1767
- search: rawQuery
1768
- });
1921
+ navigate(
1922
+ {
1923
+ pathname: `../${res.data.documentId}`,
1924
+ search: rawQuery
1925
+ },
1926
+ { replace: true, relative: "path" }
1927
+ );
1769
1928
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1770
1929
  setErrors(formatValidationErrors(res.error));
1771
1930
  }
@@ -1781,7 +1940,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
1781
1940
  KEEP: "keep",
1782
1941
  DISCARD: "discard"
1783
1942
  };
1784
- const UnpublishAction = ({
1943
+ const UnpublishAction$1 = ({
1785
1944
  activeTab,
1786
1945
  documentId,
1787
1946
  model,
@@ -1797,10 +1956,8 @@ const UnpublishAction = ({
1797
1956
  const { toggleNotification } = useNotification();
1798
1957
  const [shouldKeepDraft, setShouldKeepDraft] = React.useState(true);
1799
1958
  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
- }
1959
+ const handleChange = (value) => {
1960
+ setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1804
1961
  };
1805
1962
  if (!schema?.options?.draftAndPublish) {
1806
1963
  return null;
@@ -1844,45 +2001,30 @@ const UnpublishAction = ({
1844
2001
  content: /* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
1845
2002
  /* @__PURE__ */ jsxs(Flex, { width: "100%", direction: "column", gap: 2, children: [
1846
2003
  /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
1847
- /* @__PURE__ */ jsx(Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2004
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1848
2005
  id: "content-manager.actions.unpublish.dialog.body",
1849
2006
  defaultMessage: "Are you sure?"
1850
2007
  }) })
1851
2008
  ] }),
1852
2009
  /* @__PURE__ */ jsxs(
1853
- Flex,
2010
+ Radio.Group,
1854
2011
  {
1855
- onChange: handleChange,
1856
- direction: "column",
1857
- alignItems: "flex-start",
1858
- as: "fieldset",
1859
- gap: 3,
2012
+ defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
2013
+ name: "discard-options",
2014
+ "aria-label": formatMessage({
2015
+ id: "content-manager.actions.unpublish.dialog.radio-label",
2016
+ defaultMessage: "Choose an option to unpublish the document."
2017
+ }),
2018
+ onValueChange: handleChange,
1860
2019
  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
- )
2020
+ /* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
2021
+ id: "content-manager.actions.unpublish.dialog.option.keep-draft",
2022
+ defaultMessage: "Keep draft"
2023
+ }) }),
2024
+ /* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
2025
+ id: "content-manager.actions.unpublish.dialog.option.replace-draft",
2026
+ defaultMessage: "Replace draft"
2027
+ }) })
1886
2028
  ]
1887
2029
  }
1888
2030
  )
@@ -1915,7 +2057,7 @@ const UnpublishAction = ({
1915
2057
  position: ["panel", "table-row"]
1916
2058
  };
1917
2059
  };
1918
- UnpublishAction.type = "unpublish";
2060
+ UnpublishAction$1.type = "unpublish";
1919
2061
  const DiscardAction = ({
1920
2062
  activeTab,
1921
2063
  documentId,
@@ -1949,7 +2091,7 @@ const DiscardAction = ({
1949
2091
  }),
1950
2092
  content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
1951
2093
  /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
1952
- /* @__PURE__ */ jsx(Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2094
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1953
2095
  id: "content-manager.actions.discard.dialog.body",
1954
2096
  defaultMessage: "Are you sure?"
1955
2097
  }) })
@@ -1971,7 +2113,7 @@ const StyledCrossCircle = styled(CrossCircle)`
1971
2113
  fill: currentColor;
1972
2114
  }
1973
2115
  `;
1974
- const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
2116
+ const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
1975
2117
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
1976
2118
  const RelativeTime = React.forwardRef(
1977
2119
  ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
@@ -2019,7 +2161,7 @@ const getDisplayName = ({
2019
2161
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2020
2162
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2021
2163
  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) }) });
2164
+ 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
2165
  };
2024
2166
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2025
2167
  const { formatMessage } = useIntl();
@@ -2028,23 +2170,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2028
2170
  id: "content-manager.containers.edit.title.new",
2029
2171
  defaultMessage: "Create an entry"
2030
2172
  }) : documentTitle;
2031
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2173
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2032
2174
  /* @__PURE__ */ jsx(BackButton, {}),
2033
- /* @__PURE__ */ jsxs(
2034
- Flex,
2035
- {
2036
- width: "100%",
2037
- justifyContent: "space-between",
2038
- paddingTop: 1,
2039
- gap: "80px",
2040
- alignItems: "flex-start",
2041
- children: [
2042
- /* @__PURE__ */ jsx(Typography, { variant: "alpha", as: "h1", children: title }),
2043
- /* @__PURE__ */ jsx(HeaderToolbar, {})
2044
- ]
2045
- }
2046
- ),
2047
- status ? /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2175
+ /* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2176
+ /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
2177
+ /* @__PURE__ */ jsx(HeaderToolbar, {})
2178
+ ] }),
2179
+ status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2048
2180
  ] });
2049
2181
  };
2050
2182
  const HeaderToolbar = () => {
@@ -2196,7 +2328,7 @@ const Information = ({ activeTab }) => {
2196
2328
  borderColor: "neutral150",
2197
2329
  direction: "column",
2198
2330
  marginTop: 2,
2199
- as: "dl",
2331
+ tag: "dl",
2200
2332
  padding: 5,
2201
2333
  gap: 3,
2202
2334
  alignItems: "flex-start",
@@ -2204,8 +2336,8 @@ const Information = ({ activeTab }) => {
2204
2336
  marginRight: "-0.4rem",
2205
2337
  width: "calc(100% + 8px)",
2206
2338
  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 })
2339
+ /* @__PURE__ */ jsx(Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2340
+ /* @__PURE__ */ jsx(Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2209
2341
  ] }, info.label))
2210
2342
  }
2211
2343
  );
@@ -2238,7 +2370,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2238
2370
  id: "app.links.configure-view",
2239
2371
  defaultMessage: "Configure the view"
2240
2372
  }),
2241
- icon: /* @__PURE__ */ jsx(StyledCog, {}),
2373
+ icon: /* @__PURE__ */ jsx(ListPlus, {}),
2242
2374
  onClick: () => {
2243
2375
  navigate(`../${collectionType}/${model}/configurations/edit`);
2244
2376
  },
@@ -2246,11 +2378,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2246
2378
  };
2247
2379
  };
2248
2380
  ConfigureTheViewAction.type = "configure-the-view";
2249
- const StyledCog = styled(Cog)`
2250
- path {
2251
- fill: currentColor;
2252
- }
2253
- `;
2254
2381
  const EditTheModelAction = ({ model }) => {
2255
2382
  const navigate = useNavigate();
2256
2383
  const { formatMessage } = useIntl();
@@ -2259,7 +2386,7 @@ const EditTheModelAction = ({ model }) => {
2259
2386
  id: "content-manager.link-to-ctb",
2260
2387
  defaultMessage: "Edit the model"
2261
2388
  }),
2262
- icon: /* @__PURE__ */ jsx(StyledPencil$1, {}),
2389
+ icon: /* @__PURE__ */ jsx(Pencil, {}),
2263
2390
  onClick: () => {
2264
2391
  navigate(`/plugins/content-type-builder/content-types/${model}`);
2265
2392
  },
@@ -2267,12 +2394,7 @@ const EditTheModelAction = ({ model }) => {
2267
2394
  };
2268
2395
  };
2269
2396
  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 }) => {
2397
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2276
2398
  const navigate = useNavigate();
2277
2399
  const { formatMessage } = useIntl();
2278
2400
  const listViewPathMatch = useMatch(LIST_PATH);
@@ -2286,7 +2408,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2286
2408
  id: "content-manager.actions.delete.label",
2287
2409
  defaultMessage: "Delete document"
2288
2410
  }),
2289
- icon: /* @__PURE__ */ jsx(StyledTrash, {}),
2411
+ icon: /* @__PURE__ */ jsx(Trash, {}),
2290
2412
  dialog: {
2291
2413
  type: "dialog",
2292
2414
  title: formatMessage({
@@ -2295,7 +2417,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2295
2417
  }),
2296
2418
  content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2297
2419
  /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2298
- /* @__PURE__ */ jsx(Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2420
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2299
2421
  id: "content-manager.actions.delete.dialog.body",
2300
2422
  defaultMessage: "Are you sure?"
2301
2423
  }) })
@@ -2340,13 +2462,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2340
2462
  position: ["header", "table-row"]
2341
2463
  };
2342
2464
  };
2343
- DeleteAction.type = "delete";
2344
- const StyledTrash = styled(Trash)`
2345
- path {
2346
- fill: currentColor;
2347
- }
2348
- `;
2349
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction];
2465
+ DeleteAction$1.type = "delete";
2466
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2350
2467
  const Panels = () => {
2351
2468
  const isCloning = useMatch(CLONE_PATH) !== null;
2352
2469
  const [
@@ -2420,7 +2537,7 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
2420
2537
  Flex,
2421
2538
  {
2422
2539
  ref,
2423
- as: "aside",
2540
+ tag: "aside",
2424
2541
  "aria-labelledby": "additional-information",
2425
2542
  background: "neutral0",
2426
2543
  borderColor: "neutral150",
@@ -2435,65 +2552,944 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
2435
2552
  justifyContent: "stretch",
2436
2553
  alignItems: "flex-start",
2437
2554
  children: [
2438
- /* @__PURE__ */ jsx(Typography, { as: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2555
+ /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2439
2556
  children
2440
2557
  ]
2441
2558
  }
2442
2559
  );
2443
2560
  });
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
- }
2561
+ const HOOKS = {
2562
+ /**
2563
+ * Hook that allows to mutate the displayed headers of the list view table
2564
+ * @constant
2565
+ * @type {string}
2566
+ */
2567
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2568
+ /**
2569
+ * Hook that allows to mutate the CM's collection types links pre-set filters
2570
+ * @constant
2571
+ * @type {string}
2572
+ */
2573
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2574
+ /**
2575
+ * Hook that allows to mutate the CM's edit view layout
2576
+ * @constant
2577
+ * @type {string}
2578
+ */
2579
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2580
+ /**
2581
+ * Hook that allows to mutate the CM's single types links pre-set filters
2582
+ * @constant
2583
+ * @type {string}
2584
+ */
2585
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2586
+ };
2587
+ const contentTypesApi = contentManagerApi.injectEndpoints({
2588
+ endpoints: (builder) => ({
2589
+ getContentTypeConfiguration: builder.query({
2590
+ query: (uid) => ({
2591
+ url: `/content-manager/content-types/${uid}/configuration`,
2592
+ method: "GET"
2593
+ }),
2594
+ transformResponse: (response) => response.data,
2595
+ providesTags: (_result, _error, uid) => [
2596
+ { type: "ContentTypesConfiguration", id: uid },
2597
+ { type: "ContentTypeSettings", id: "LIST" }
2598
+ ]
2599
+ }),
2600
+ getAllContentTypeSettings: builder.query({
2601
+ query: () => "/content-manager/content-types-settings",
2602
+ transformResponse: (response) => response.data,
2603
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2604
+ }),
2605
+ updateContentTypeConfiguration: builder.mutation({
2606
+ query: ({ uid, ...body }) => ({
2607
+ url: `/content-manager/content-types/${uid}/configuration`,
2608
+ method: "PUT",
2609
+ data: body
2610
+ }),
2611
+ transformResponse: (response) => response.data,
2612
+ invalidatesTags: (_result, _error, { uid }) => [
2613
+ { type: "ContentTypesConfiguration", id: uid },
2614
+ { type: "ContentTypeSettings", id: "LIST" },
2615
+ // Is this necessary?
2616
+ { type: "InitialData" }
2617
+ ]
2618
+ })
2619
+ })
2620
+ });
2621
+ const {
2622
+ useGetContentTypeConfigurationQuery,
2623
+ useGetAllContentTypeSettingsQuery,
2624
+ useUpdateContentTypeConfigurationMutation
2625
+ } = contentTypesApi;
2626
+ const checkIfAttributeIsDisplayable = (attribute) => {
2627
+ const { type } = attribute;
2628
+ if (type === "relation") {
2629
+ return !attribute.relation.toLowerCase().includes("morph");
2630
+ }
2631
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2632
+ };
2633
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2634
+ if (!mainFieldName) {
2635
+ return void 0;
2636
+ }
2637
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2638
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2639
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2640
+ );
2641
+ return {
2642
+ name: mainFieldName,
2643
+ type: mainFieldType ?? "string"
2456
2644
  };
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
- ] });
2645
+ };
2646
+ const DEFAULT_SETTINGS = {
2647
+ bulkable: false,
2648
+ filterable: false,
2649
+ searchable: false,
2650
+ pagination: false,
2651
+ defaultSortBy: "",
2652
+ defaultSortOrder: "asc",
2653
+ mainField: "id",
2654
+ pageSize: 10
2655
+ };
2656
+ const useDocumentLayout = (model) => {
2657
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2658
+ const [{ query }] = useQueryParams();
2659
+ const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2660
+ const { toggleNotification } = useNotification();
2661
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
2662
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2663
+ const {
2664
+ data,
2665
+ isLoading: isLoadingConfigs,
2666
+ error,
2667
+ isFetching: isFetchingConfigs
2668
+ } = useGetContentTypeConfigurationQuery(model);
2669
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2670
+ React.useEffect(() => {
2671
+ if (error) {
2672
+ toggleNotification({
2673
+ type: "danger",
2674
+ message: formatAPIError(error)
2675
+ });
2676
+ }
2677
+ }, [error, formatAPIError, toggleNotification]);
2678
+ const editLayout = React.useMemo(
2679
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2680
+ layout: [],
2681
+ components: {},
2682
+ metadatas: {},
2683
+ options: {},
2684
+ settings: DEFAULT_SETTINGS
2685
+ },
2686
+ [data, isLoading, schemas, schema, components]
2687
+ );
2688
+ const listLayout = React.useMemo(() => {
2689
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2690
+ layout: [],
2691
+ metadatas: {},
2692
+ options: {},
2693
+ settings: DEFAULT_SETTINGS
2694
+ };
2695
+ }, [data, isLoading, schemas, schema, components]);
2696
+ const { layout: edit } = React.useMemo(
2697
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2698
+ layout: editLayout,
2699
+ query
2700
+ }),
2701
+ [editLayout, query, runHookWaterfall]
2702
+ );
2703
+ return {
2704
+ error,
2705
+ isLoading,
2706
+ edit,
2707
+ list: listLayout
2708
+ };
2709
+ };
2710
+ const useDocLayout = () => {
2711
+ const { model } = useDoc();
2712
+ return useDocumentLayout(model);
2713
+ };
2714
+ const formatEditLayout = (data, {
2715
+ schemas,
2716
+ schema,
2717
+ components
2718
+ }) => {
2719
+ let currentPanelIndex = 0;
2720
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2721
+ data.contentType.layouts.edit,
2722
+ schema?.attributes,
2723
+ data.contentType.metadatas,
2724
+ { configurations: data.components, schemas: components },
2725
+ schemas
2726
+ ).reduce((panels, row) => {
2727
+ if (row.some((field) => field.type === "dynamiczone")) {
2728
+ panels.push([row]);
2729
+ currentPanelIndex += 2;
2730
+ } else {
2731
+ if (!panels[currentPanelIndex]) {
2732
+ panels.push([]);
2733
+ }
2734
+ panels[currentPanelIndex].push(row);
2735
+ }
2736
+ return panels;
2737
+ }, []);
2738
+ const componentEditAttributes = Object.entries(data.components).reduce(
2739
+ (acc, [uid, configuration]) => {
2740
+ acc[uid] = {
2741
+ layout: convertEditLayoutToFieldLayouts(
2742
+ configuration.layouts.edit,
2743
+ components[uid].attributes,
2744
+ configuration.metadatas
2745
+ ),
2746
+ settings: {
2747
+ ...configuration.settings,
2748
+ icon: components[uid].info.icon,
2749
+ displayName: components[uid].info.displayName
2750
+ }
2751
+ };
2752
+ return acc;
2753
+ },
2754
+ {}
2755
+ );
2756
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2757
+ (acc, [attribute, metadata]) => {
2758
+ return {
2759
+ ...acc,
2760
+ [attribute]: metadata.edit
2761
+ };
2762
+ },
2763
+ {}
2764
+ );
2765
+ return {
2766
+ layout: panelledEditAttributes,
2767
+ components: componentEditAttributes,
2768
+ metadatas: editMetadatas,
2769
+ settings: {
2770
+ ...data.contentType.settings,
2771
+ displayName: schema?.info.displayName
2772
+ },
2773
+ options: {
2774
+ ...schema?.options,
2775
+ ...schema?.pluginOptions,
2776
+ ...data.contentType.options
2777
+ }
2778
+ };
2779
+ };
2780
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2781
+ return rows.map(
2782
+ (row) => row.map((field) => {
2783
+ const attribute = attributes[field.name];
2784
+ if (!attribute) {
2785
+ return null;
2786
+ }
2787
+ const { edit: metadata } = metadatas[field.name];
2788
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2789
+ return {
2790
+ attribute,
2791
+ disabled: !metadata.editable,
2792
+ hint: metadata.description,
2793
+ label: metadata.label ?? "",
2794
+ name: field.name,
2795
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
2796
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2797
+ schemas,
2798
+ components: components?.schemas ?? {}
2799
+ }),
2800
+ placeholder: metadata.placeholder ?? "",
2801
+ required: attribute.required ?? false,
2802
+ size: field.size,
2803
+ unique: "unique" in attribute ? attribute.unique : false,
2804
+ visible: metadata.visible ?? true,
2805
+ type: attribute.type
2806
+ };
2807
+ }).filter((field) => field !== null)
2808
+ );
2809
+ };
2810
+ const formatListLayout = (data, {
2811
+ schemas,
2812
+ schema,
2813
+ components
2814
+ }) => {
2815
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2816
+ (acc, [attribute, metadata]) => {
2817
+ return {
2818
+ ...acc,
2819
+ [attribute]: metadata.list
2820
+ };
2821
+ },
2822
+ {}
2823
+ );
2824
+ const listAttributes = convertListLayoutToFieldLayouts(
2825
+ data.contentType.layouts.list,
2826
+ schema?.attributes,
2827
+ listMetadatas,
2828
+ { configurations: data.components, schemas: components },
2829
+ schemas
2830
+ );
2831
+ return {
2832
+ layout: listAttributes,
2833
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2834
+ metadatas: listMetadatas,
2835
+ options: {
2836
+ ...schema?.options,
2837
+ ...schema?.pluginOptions,
2838
+ ...data.contentType.options
2839
+ }
2840
+ };
2841
+ };
2842
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2843
+ return columns.map((name) => {
2844
+ const attribute = attributes[name];
2845
+ if (!attribute) {
2846
+ return null;
2847
+ }
2848
+ const metadata = metadatas[name];
2849
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2850
+ return {
2851
+ attribute,
2852
+ label: metadata.label ?? "",
2853
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2854
+ schemas,
2855
+ components: components?.schemas ?? {}
2856
+ }),
2857
+ name,
2858
+ searchable: metadata.searchable ?? true,
2859
+ sortable: metadata.sortable ?? true
2860
+ };
2861
+ }).filter((field) => field !== null);
2862
+ };
2863
+ const ConfirmBulkActionDialog = ({
2864
+ onToggleDialog,
2865
+ isOpen = false,
2866
+ dialogBody,
2867
+ endAction
2868
+ }) => {
2869
+ const { formatMessage } = useIntl();
2870
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2871
+ /* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
2872
+ id: "app.components.ConfirmDialog.title",
2873
+ defaultMessage: "Confirmation"
2874
+ }) }),
2875
+ /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
2876
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
2877
+ dialogBody
2878
+ ] }) }),
2879
+ /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
2880
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
2881
+ id: "app.components.Button.cancel",
2882
+ defaultMessage: "Cancel"
2883
+ }) }) }),
2884
+ endAction
2885
+ ] })
2886
+ ] }) });
2887
+ };
2888
+ const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
2889
+ const ConfirmDialogPublishAll = ({
2890
+ isOpen,
2891
+ onToggleDialog,
2892
+ isConfirmButtonLoading = false,
2893
+ onConfirm
2894
+ }) => {
2895
+ const { formatMessage } = useIntl();
2896
+ const selectedEntries = useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
2897
+ const { toggleNotification } = useNotification();
2898
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
2899
+ const { model, schema } = useDoc();
2900
+ const [{ query }] = useQueryParams();
2901
+ const {
2902
+ data: countDraftRelations = 0,
2903
+ isLoading,
2904
+ error
2905
+ } = useGetManyDraftRelationCountQuery(
2906
+ {
2907
+ model,
2908
+ documentIds: selectedEntries.map((entry) => entry.documentId),
2909
+ locale: query?.plugins?.i18n?.locale
2910
+ },
2911
+ {
2912
+ skip: selectedEntries.length === 0
2913
+ }
2914
+ );
2915
+ React.useEffect(() => {
2916
+ if (error) {
2917
+ toggleNotification({ type: "danger", message: formatAPIError(error) });
2918
+ }
2919
+ }, [error, formatAPIError, toggleNotification]);
2920
+ if (error) {
2921
+ return null;
2922
+ }
2923
+ return /* @__PURE__ */ jsx(
2924
+ ConfirmBulkActionDialog,
2925
+ {
2926
+ isOpen: isOpen && !isLoading,
2927
+ onToggleDialog,
2928
+ dialogBody: /* @__PURE__ */ jsxs(Fragment, { children: [
2929
+ /* @__PURE__ */ jsxs(Typography, { id: "confirm-description", textAlign: "center", children: [
2930
+ countDraftRelations > 0 && formatMessage(
2931
+ {
2932
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2933
+ 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. "
2934
+ },
2935
+ {
2936
+ b: BoldChunk$1,
2937
+ count: countDraftRelations,
2938
+ entities: selectedEntries.length
2939
+ }
2940
+ ),
2941
+ formatMessage({
2942
+ id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
2943
+ defaultMessage: "Are you sure you want to publish these entries?"
2944
+ })
2945
+ ] }),
2946
+ schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsx(Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
2947
+ {
2948
+ id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
2949
+ defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
2950
+ },
2951
+ {
2952
+ em: Emphasis
2953
+ }
2954
+ ) })
2955
+ ] }),
2956
+ endAction: /* @__PURE__ */ jsx(
2957
+ Button,
2958
+ {
2959
+ onClick: onConfirm,
2960
+ variant: "secondary",
2961
+ startIcon: /* @__PURE__ */ jsx(Check, {}),
2962
+ loading: isConfirmButtonLoading,
2963
+ children: formatMessage({
2964
+ id: "app.utils.publish",
2965
+ defaultMessage: "Publish"
2966
+ })
2967
+ }
2968
+ )
2969
+ }
2970
+ );
2971
+ };
2972
+ const TypographyMaxWidth = styled(Typography)`
2973
+ max-width: 300px;
2974
+ `;
2975
+ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2976
+ const messages = [];
2977
+ Object.entries(errors).forEach(([key, value]) => {
2978
+ const currentKey = parentKey ? `${parentKey}.${key}` : key;
2979
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
2980
+ if ("id" in value && "defaultMessage" in value) {
2981
+ messages.push(
2982
+ formatMessage(
2983
+ {
2984
+ id: `${value.id}.withField`,
2985
+ defaultMessage: value.defaultMessage
2986
+ },
2987
+ { field: currentKey }
2988
+ )
2989
+ );
2990
+ } else {
2991
+ messages.push(
2992
+ ...formatErrorMessages(
2993
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
2994
+ value,
2995
+ currentKey,
2996
+ formatMessage
2997
+ )
2998
+ );
2999
+ }
3000
+ } else {
3001
+ messages.push(
3002
+ formatMessage(
3003
+ {
3004
+ id: `${value}.withField`,
3005
+ defaultMessage: value
3006
+ },
3007
+ { field: currentKey }
3008
+ )
3009
+ );
3010
+ }
3011
+ });
3012
+ return messages;
3013
+ };
3014
+ const EntryValidationText = ({ validationErrors, status }) => {
3015
+ const { formatMessage } = useIntl();
3016
+ if (validationErrors) {
3017
+ const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
3018
+ " "
3019
+ );
3020
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3021
+ /* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
3022
+ /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
3023
+ ] });
3024
+ }
3025
+ if (status === "published") {
3026
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3027
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
3028
+ /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
3029
+ id: "content-manager.bulk-publish.already-published",
3030
+ defaultMessage: "Already Published"
3031
+ }) })
3032
+ ] });
3033
+ }
3034
+ if (status === "modified") {
3035
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3036
+ /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
3037
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
3038
+ id: "content-manager.bulk-publish.modified",
3039
+ defaultMessage: "Ready to publish changes"
3040
+ }) })
3041
+ ] });
3042
+ }
3043
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3044
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
3045
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
3046
+ id: "app.utils.ready-to-publish",
3047
+ defaultMessage: "Ready to publish"
3048
+ }) })
3049
+ ] });
3050
+ };
3051
+ const TABLE_HEADERS = [
3052
+ { name: "id", label: "id" },
3053
+ { name: "name", label: "name" },
3054
+ { name: "status", label: "status" },
3055
+ { name: "publicationStatus", label: "Publication status" }
3056
+ ];
3057
+ const SelectedEntriesTableContent = ({
3058
+ isPublishing,
3059
+ rowsToDisplay = [],
3060
+ entriesToPublish = [],
3061
+ validationErrors = {}
3062
+ }) => {
3063
+ const { pathname } = useLocation();
3064
+ const { formatMessage } = useIntl();
3065
+ const {
3066
+ list: {
3067
+ settings: { mainField }
3068
+ }
3069
+ } = useDocLayout();
3070
+ const shouldDisplayMainField = mainField != null && mainField !== "id";
3071
+ return /* @__PURE__ */ jsxs(Table.Content, { children: [
3072
+ /* @__PURE__ */ jsxs(Table.Head, { children: [
3073
+ /* @__PURE__ */ jsx(Table.HeaderCheckboxCell, {}),
3074
+ TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
3075
+ (head) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...head }, head.name)
3076
+ )
3077
+ ] }),
3078
+ /* @__PURE__ */ jsx(Table.Loading, {}),
3079
+ /* @__PURE__ */ jsx(Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxs(Table.Row, { children: [
3080
+ /* @__PURE__ */ jsx(Table.CheckboxCell, { id: row.id }),
3081
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row.id }) }),
3082
+ shouldDisplayMainField && /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row[mainField] }) }),
3083
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
3084
+ /* @__PURE__ */ jsx(Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3085
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
3086
+ id: "content-manager.success.record.publishing",
3087
+ defaultMessage: "Publishing..."
3088
+ }) }),
3089
+ /* @__PURE__ */ jsx(Loader, { small: true })
3090
+ ] }) : /* @__PURE__ */ jsx(
3091
+ EntryValidationText,
3092
+ {
3093
+ validationErrors: validationErrors[row.documentId],
3094
+ status: row.status
3095
+ }
3096
+ ) }),
3097
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
3098
+ IconButton,
3099
+ {
3100
+ tag: Link,
3101
+ to: {
3102
+ pathname: `${pathname}/${row.documentId}`,
3103
+ search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3104
+ },
3105
+ state: { from: pathname },
3106
+ label: formatMessage(
3107
+ { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3108
+ {
3109
+ target: formatMessage(
3110
+ {
3111
+ id: "content-manager.components.ListViewHelperPluginTable.row-line",
3112
+ defaultMessage: "item line {number}"
3113
+ },
3114
+ { number: index2 + 1 }
3115
+ )
3116
+ }
3117
+ ),
3118
+ target: "_blank",
3119
+ marginLeft: "auto",
3120
+ children: /* @__PURE__ */ jsx(Pencil, {})
3121
+ }
3122
+ ) })
3123
+ ] }, row.id)) })
3124
+ ] });
3125
+ };
3126
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
3127
+ const SelectedEntriesModalContent = ({
3128
+ listViewSelectedEntries,
3129
+ toggleModal,
3130
+ setListViewSelectedDocuments,
3131
+ model
3132
+ }) => {
3133
+ const { formatMessage } = useIntl();
3134
+ const { schema, components } = useContentTypeSchema(model);
3135
+ const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
3136
+ const [{ query }] = useQueryParams();
3137
+ const params = React.useMemo(() => buildValidParams(query), [query]);
3138
+ const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
3139
+ {
3140
+ model,
3141
+ params: {
3142
+ page: "1",
3143
+ pageSize: documentIds.length.toString(),
3144
+ sort: query.sort,
3145
+ filters: {
3146
+ documentId: {
3147
+ $in: documentIds
3148
+ }
3149
+ },
3150
+ locale: query.plugins?.i18n?.locale
3151
+ }
3152
+ },
3153
+ {
3154
+ selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
3155
+ }
3156
+ );
3157
+ const { rows, validationErrors } = React.useMemo(() => {
3158
+ if (data.length > 0 && schema) {
3159
+ const validate = createYupSchema(schema.attributes, components);
3160
+ const validationErrors2 = {};
3161
+ const rows2 = data.map((entry) => {
3162
+ try {
3163
+ validate.validateSync(entry, { abortEarly: false });
3164
+ return entry;
3165
+ } catch (e) {
3166
+ if (e instanceof ValidationError) {
3167
+ validationErrors2[entry.documentId] = getYupValidationErrors(e);
3168
+ }
3169
+ return entry;
3170
+ }
3171
+ });
3172
+ return { rows: rows2, validationErrors: validationErrors2 };
3173
+ }
3174
+ return {
3175
+ rows: [],
3176
+ validationErrors: {}
3177
+ };
3178
+ }, [components, data, schema]);
3179
+ const [publishedCount, setPublishedCount] = React.useState(0);
3180
+ const [isDialogOpen, setIsDialogOpen] = React.useState(false);
3181
+ const { publishMany: bulkPublishAction } = useDocumentActions();
3182
+ const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
3183
+ const selectedRows = useTable("publishAction", (state) => state.selectedRows);
3184
+ const selectedEntries = rows.filter(
3185
+ (entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
3186
+ );
3187
+ const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
3188
+ const selectedEntriesWithErrorsCount = selectedEntries.filter(
3189
+ ({ documentId }) => validationErrors[documentId]
3190
+ ).length;
3191
+ const selectedEntriesPublished = selectedEntries.filter(
3192
+ ({ status }) => status === "published"
3193
+ ).length;
3194
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3195
+ const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3196
+ const handleConfirmBulkPublish = async () => {
3197
+ toggleDialog();
3198
+ const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3199
+ if (!("error" in res)) {
3200
+ setPublishedCount(res.count);
3201
+ const unpublishedEntries = rows.filter((row) => {
3202
+ return !entriesToPublish.includes(row.documentId);
3203
+ });
3204
+ setListViewSelectedDocuments(unpublishedEntries);
3205
+ }
3206
+ };
3207
+ const getFormattedCountMessage = () => {
3208
+ if (publishedCount) {
3209
+ return formatMessage(
3210
+ {
3211
+ id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3212
+ 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."
3213
+ },
3214
+ {
3215
+ publishedCount,
3216
+ withErrorsCount: selectedEntriesWithErrorsCount,
3217
+ b: BoldChunk
3218
+ }
3219
+ );
3220
+ }
3221
+ return formatMessage(
3222
+ {
3223
+ id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3224
+ 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."
3225
+ },
3226
+ {
3227
+ readyToPublishCount: selectedEntriesWithNoErrorsCount,
3228
+ withErrorsCount: selectedEntriesWithErrorsCount,
3229
+ alreadyPublishedCount: selectedEntriesPublished,
3230
+ b: BoldChunk
3231
+ }
3232
+ );
3233
+ };
3234
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3235
+ /* @__PURE__ */ jsxs(Modal.Body, { children: [
3236
+ /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
3237
+ /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsx(
3238
+ SelectedEntriesTableContent,
3239
+ {
3240
+ isPublishing: isSubmittingForm,
3241
+ rowsToDisplay: rows,
3242
+ entriesToPublish,
3243
+ validationErrors
3244
+ }
3245
+ ) })
3246
+ ] }),
3247
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
3248
+ /* @__PURE__ */ jsx(Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3249
+ id: "app.components.Button.cancel",
3250
+ defaultMessage: "Cancel"
3251
+ }) }),
3252
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3253
+ /* @__PURE__ */ jsx(Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3254
+ /* @__PURE__ */ jsx(
3255
+ Button,
3256
+ {
3257
+ onClick: toggleDialog,
3258
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3259
+ loading: isSubmittingForm,
3260
+ children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3261
+ }
3262
+ )
3263
+ ] })
3264
+ ] }),
3265
+ /* @__PURE__ */ jsx(
3266
+ ConfirmDialogPublishAll,
3267
+ {
3268
+ isOpen: isDialogOpen,
3269
+ onToggleDialog: toggleDialog,
3270
+ isConfirmButtonLoading: isSubmittingForm,
3271
+ onConfirm: handleConfirmBulkPublish
3272
+ }
3273
+ )
3274
+ ] });
3275
+ };
3276
+ const PublishAction = ({ documents, model }) => {
3277
+ const { formatMessage } = useIntl();
3278
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3279
+ const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
3280
+ const setListViewSelectedDocuments = useTable("publishAction", (state) => state.selectRow);
3281
+ const refetchList = () => {
3282
+ contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3283
+ };
3284
+ if (!showPublishButton)
3285
+ return null;
3286
+ return {
3287
+ actionType: "publish",
3288
+ variant: "tertiary",
3289
+ label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
3290
+ dialog: {
3291
+ type: "modal",
3292
+ title: formatMessage({
3293
+ id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
3294
+ defaultMessage: "Publish entries"
3295
+ }),
3296
+ content: ({ onClose }) => {
3297
+ return /* @__PURE__ */ jsx(Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsx(
3298
+ SelectedEntriesModalContent,
3299
+ {
3300
+ listViewSelectedEntries: documents,
3301
+ toggleModal: () => {
3302
+ onClose();
3303
+ refetchList();
3304
+ },
3305
+ setListViewSelectedDocuments,
3306
+ model
3307
+ }
3308
+ ) });
3309
+ },
3310
+ onClose: () => {
3311
+ refetchList();
3312
+ }
3313
+ }
3314
+ };
3315
+ };
3316
+ const BulkActionsRenderer = () => {
3317
+ const plugins = useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
3318
+ const { model, collectionType } = useDoc();
3319
+ const { selectedRows } = useTable("BulkActionsRenderer", (state) => state);
3320
+ return /* @__PURE__ */ jsx(Flex, { gap: 2, children: /* @__PURE__ */ jsx(
3321
+ DescriptionComponentRenderer,
3322
+ {
3323
+ props: {
3324
+ model,
3325
+ collectionType,
3326
+ documents: selectedRows
3327
+ },
3328
+ descriptions: plugins["content-manager"].apis.getBulkActions(),
3329
+ children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsx(DocumentActionButton, { ...action }, action.id))
3330
+ }
3331
+ ) });
3332
+ };
3333
+ const DeleteAction = ({ documents, model }) => {
3334
+ const { formatMessage } = useIntl();
3335
+ const { schema: contentType } = useDoc();
3336
+ const selectRow = useTable("DeleteAction", (state) => state.selectRow);
3337
+ const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
3338
+ const [{ query }] = useQueryParams();
3339
+ const params = React.useMemo(() => buildValidParams(query), [query]);
3340
+ const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
3341
+ const { deleteMany: bulkDeleteAction } = useDocumentActions();
3342
+ const documentIds = documents.map(({ documentId }) => documentId);
3343
+ const handleConfirmBulkDelete = async () => {
3344
+ const res = await bulkDeleteAction({
3345
+ documentIds,
3346
+ model,
3347
+ params
3348
+ });
3349
+ if (!("error" in res)) {
3350
+ selectRow([]);
3351
+ }
3352
+ };
3353
+ if (!hasDeletePermission)
3354
+ return null;
3355
+ return {
3356
+ variant: "danger-light",
3357
+ label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
3358
+ dialog: {
3359
+ type: "dialog",
3360
+ title: formatMessage({
3361
+ id: "app.components.ConfirmDialog.title",
3362
+ defaultMessage: "Confirmation"
3363
+ }),
3364
+ content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3365
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3366
+ /* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3367
+ id: "popUpWarning.bodyMessage.contentType.delete.all",
3368
+ defaultMessage: "Are you sure you want to delete these entries?"
3369
+ }) }),
3370
+ hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
3371
+ {
3372
+ id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
3373
+ defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
3374
+ },
3375
+ {
3376
+ em: Emphasis
3377
+ }
3378
+ ) }) })
3379
+ ] }),
3380
+ onConfirm: handleConfirmBulkDelete
3381
+ }
3382
+ };
3383
+ };
3384
+ DeleteAction.type = "delete";
3385
+ const UnpublishAction = ({ documents, model }) => {
3386
+ const { formatMessage } = useIntl();
3387
+ const { schema } = useDoc();
3388
+ const selectRow = useTable("UnpublishAction", (state) => state.selectRow);
3389
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3390
+ const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
3391
+ const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
3392
+ const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
3393
+ const documentIds = documents.map(({ documentId }) => documentId);
3394
+ const [{ query }] = useQueryParams();
3395
+ const params = React.useMemo(() => buildValidParams(query), [query]);
3396
+ const handleConfirmBulkUnpublish = async () => {
3397
+ const data = await bulkUnpublishAction({ documentIds, model, params });
3398
+ if (!("error" in data)) {
3399
+ selectRow([]);
3400
+ }
3401
+ };
3402
+ const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3403
+ if (!showUnpublishButton)
3404
+ return null;
3405
+ return {
3406
+ variant: "tertiary",
3407
+ label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
3408
+ dialog: {
3409
+ type: "dialog",
3410
+ title: formatMessage({
3411
+ id: "app.components.ConfirmDialog.title",
3412
+ defaultMessage: "Confirmation"
3413
+ }),
3414
+ content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3415
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3416
+ /* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3417
+ id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3418
+ defaultMessage: "Are you sure you want to unpublish these entries?"
3419
+ }) }),
3420
+ hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
3421
+ {
3422
+ id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
3423
+ defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
3424
+ },
3425
+ {
3426
+ em: Emphasis
3427
+ }
3428
+ ) }) })
3429
+ ] }),
3430
+ confirmButton: formatMessage({
3431
+ id: "app.utils.unpublish",
3432
+ defaultMessage: "Unpublish"
3433
+ }),
3434
+ onConfirm: handleConfirmBulkUnpublish
3435
+ }
3436
+ };
3437
+ };
3438
+ UnpublishAction.type = "unpublish";
3439
+ const Emphasis = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
3440
+ const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
3441
+ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3442
+ const { formatMessage } = useIntl();
3443
+ const getDefaultErrorMessage = (reason) => {
3444
+ switch (reason) {
3445
+ case "relation":
3446
+ return "Duplicating the relation could remove it from the original entry.";
3447
+ case "unique":
3448
+ return "Identical values in a unique field are not allowed";
3449
+ default:
3450
+ return reason;
3451
+ }
3452
+ };
3453
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3454
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", children: formatMessage({
3455
+ id: getTranslation("containers.list.autoCloneModal.title"),
3456
+ defaultMessage: "This entry can't be duplicated directly."
3457
+ }) }),
3458
+ /* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage({
3459
+ id: getTranslation("containers.list.autoCloneModal.description"),
3460
+ defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
3461
+ }) }) }),
3462
+ /* @__PURE__ */ jsx(Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxs(
3463
+ Flex,
3464
+ {
3465
+ direction: "column",
3466
+ gap: 2,
3467
+ alignItems: "flex-start",
3468
+ borderColor: "neutral200",
3469
+ hasRadius: true,
3470
+ padding: 6,
3471
+ children: [
3472
+ /* @__PURE__ */ jsx(Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxs(Typography, { fontWeight: "semiBold", tag: "li", children: [
3473
+ pathSegment,
3474
+ index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsx(
3475
+ ChevronRight,
3476
+ {
3477
+ fill: "neutral500",
3478
+ height: "0.8rem",
3479
+ width: "0.8rem",
3480
+ style: { margin: "0 0.8rem" }
3481
+ }
3482
+ )
3483
+ ] }, index2)) }),
3484
+ /* @__PURE__ */ jsx(Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
3485
+ id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
3486
+ defaultMessage: getDefaultErrorMessage(reason)
3487
+ }) })
3488
+ ]
3489
+ },
3490
+ fieldPath.join()
3491
+ )) })
3492
+ ] });
2497
3493
  };
2498
3494
  const TableActions = ({ document }) => {
2499
3495
  const { formatMessage } = useIntl();
@@ -2629,7 +3625,7 @@ const CloneAction = ({ model, documentId }) => {
2629
3625
  /* @__PURE__ */ jsx(
2630
3626
  LinkButton,
2631
3627
  {
2632
- as: NavLink,
3628
+ tag: NavLink,
2633
3629
  to: {
2634
3630
  pathname: `clone/${documentId}`
2635
3631
  },
@@ -2662,442 +3658,183 @@ class ContentManagerPlugin {
2662
3658
  documentActions = [
2663
3659
  ...DEFAULT_ACTIONS,
2664
3660
  ...DEFAULT_TABLE_ROW_ACTIONS,
2665
- ...DEFAULT_HEADER_ACTIONS,
2666
- HistoryAction
3661
+ ...DEFAULT_HEADER_ACTIONS
2667
3662
  ];
2668
3663
  editViewSidePanels = [ActionsPanel];
2669
3664
  headerActions = [];
2670
3665
  constructor() {
2671
3666
  }
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);
2677
- } 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
- )}`
2682
- );
2683
- }
2684
- }
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
- }
2697
- }
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);
3667
+ addEditViewSidePanel(panels) {
3668
+ if (Array.isArray(panels)) {
3669
+ this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
3670
+ } else if (typeof panels === "function") {
3671
+ this.editViewSidePanels = panels(this.editViewSidePanels);
2703
3672
  } else {
2704
3673
  throw new Error(
2705
- `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
2706
- actions2
3674
+ `Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
3675
+ panels
2707
3676
  )}`
2708
3677
  );
2709
3678
  }
2710
3679
  }
2711
- addBulkAction(actions2) {
3680
+ addDocumentAction(actions2) {
2712
3681
  if (Array.isArray(actions2)) {
2713
- this.bulkActions = [...this.bulkActions, ...actions2];
3682
+ this.documentActions = [...this.documentActions, ...actions2];
2714
3683
  } else if (typeof actions2 === "function") {
2715
- this.bulkActions = actions2(this.bulkActions);
3684
+ this.documentActions = actions2(this.documentActions);
2716
3685
  } else {
2717
3686
  throw new Error(
2718
- `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3687
+ `Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
2719
3688
  actions2
2720
3689
  )}`
2721
- );
2722
- }
2723
- }
2724
- get config() {
2725
- 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
- }
2739
- };
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;
2751
- }
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
2777
- );
2778
- state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
2779
- state.components = components;
2780
- state.models = contentTypeSchemas;
2781
- state.fieldSizes = fieldSizes;
2782
- state.isLoading = false;
2783
- }
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"
2816
- };
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
2840
- }),
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;
2862
- };
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
- );
2871
- return {
2872
- name: mainFieldName,
2873
- type: mainFieldType ?? "string"
2874
- };
2875
- };
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 });
2888
- 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
- });
2906
- }
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
- );
2933
- return {
2934
- error,
2935
- isLoading,
2936
- edit,
2937
- list: listLayout
2938
- };
2939
- };
2940
- const useDocLayout = () => {
2941
- const { model } = useDoc();
2942
- return useDocumentLayout(model);
2943
- };
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;
3690
+ );
3691
+ }
3692
+ }
3693
+ addDocumentHeaderAction(actions2) {
3694
+ if (Array.isArray(actions2)) {
3695
+ this.headerActions = [...this.headerActions, ...actions2];
3696
+ } else if (typeof actions2 === "function") {
3697
+ this.headerActions = actions2(this.headerActions);
2960
3698
  } else {
2961
- if (!panels[currentPanelIndex]) {
2962
- panels.push([]);
2963
- }
2964
- panels[currentPanelIndex].push(row);
3699
+ throw new Error(
3700
+ `Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
3701
+ actions2
3702
+ )}`
3703
+ );
2965
3704
  }
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
- );
2995
- 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
3705
+ }
3706
+ addBulkAction(actions2) {
3707
+ if (Array.isArray(actions2)) {
3708
+ this.bulkActions = [...this.bulkActions, ...actions2];
3709
+ } else if (typeof actions2 === "function") {
3710
+ this.bulkActions = actions2(this.bulkActions);
3711
+ } else {
3712
+ throw new Error(
3713
+ `Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
3714
+ actions2
3715
+ )}`
3716
+ );
3007
3717
  }
3008
- };
3009
- };
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;
3718
+ }
3719
+ get config() {
3720
+ return {
3721
+ id: PLUGIN_ID,
3722
+ name: "Content Manager",
3723
+ injectionZones: INJECTION_ZONES,
3724
+ apis: {
3725
+ addBulkAction: this.addBulkAction.bind(this),
3726
+ addDocumentAction: this.addDocumentAction.bind(this),
3727
+ addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3728
+ addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3729
+ getBulkActions: () => this.bulkActions,
3730
+ getDocumentActions: () => this.documentActions,
3731
+ getEditViewSidePanels: () => this.editViewSidePanels,
3732
+ getHeaderActions: () => this.headerActions
3016
3733
  }
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
- );
3734
+ };
3735
+ }
3736
+ }
3737
+ const getPrintableType = (value) => {
3738
+ const nativeType = typeof value;
3739
+ if (nativeType === "object") {
3740
+ if (value === null)
3741
+ return "null";
3742
+ if (Array.isArray(value))
3743
+ return "array";
3744
+ if (value instanceof Object && value.constructor.name !== "Object") {
3745
+ return value.constructor.name;
3746
+ }
3747
+ }
3748
+ return nativeType;
3039
3749
  };
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
- );
3750
+ const HistoryAction = ({ model, document }) => {
3751
+ const { formatMessage } = useIntl();
3752
+ const [{ query }] = useQueryParams();
3753
+ const navigate = useNavigate();
3754
+ const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
3755
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3756
+ return null;
3757
+ }
3061
3758
  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
3069
- }
3759
+ icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
3760
+ label: formatMessage({
3761
+ id: "content-manager.history.document-action",
3762
+ defaultMessage: "Content History"
3763
+ }),
3764
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3765
+ disabled: (
3766
+ /**
3767
+ * The user is creating a new document.
3768
+ * It hasn't been saved yet, so there's no history to go to
3769
+ */
3770
+ !document || /**
3771
+ * The document has been created but the current dimension has never been saved.
3772
+ * For example, the user is creating a new locale in an existing document,
3773
+ * so there's no history for the document in that locale
3774
+ */
3775
+ !document.id || /**
3776
+ * History is only available for content types created by the user.
3777
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3778
+ * which start with `admin::` or `plugin::`
3779
+ */
3780
+ !model.startsWith("api::")
3781
+ ),
3782
+ position: "header"
3070
3783
  };
3071
3784
  };
3072
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
3073
- return columns.map((name) => {
3074
- const attribute = attributes[name];
3075
- if (!attribute) {
3076
- return null;
3077
- }
3078
- const metadata = metadatas[name];
3079
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3080
- 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
3090
- };
3091
- }).filter((field) => field !== null);
3785
+ HistoryAction.type = "history";
3786
+ const historyAdmin = {
3787
+ bootstrap(app) {
3788
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3789
+ addDocumentAction((actions2) => {
3790
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3791
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3792
+ return actions2;
3793
+ });
3794
+ }
3795
+ };
3796
+ const initialState = {
3797
+ collectionTypeLinks: [],
3798
+ components: [],
3799
+ fieldSizes: {},
3800
+ models: [],
3801
+ singleTypeLinks: [],
3802
+ isLoading: true
3092
3803
  };
3804
+ const appSlice = createSlice({
3805
+ name: "app",
3806
+ initialState,
3807
+ reducers: {
3808
+ setInitialData(state, action) {
3809
+ const {
3810
+ authorizedCollectionTypeLinks,
3811
+ authorizedSingleTypeLinks,
3812
+ components,
3813
+ contentTypeSchemas,
3814
+ fieldSizes
3815
+ } = action.payload;
3816
+ state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
3817
+ ({ isDisplayed }) => isDisplayed
3818
+ );
3819
+ state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
3820
+ state.components = components;
3821
+ state.models = contentTypeSchemas;
3822
+ state.fieldSizes = fieldSizes;
3823
+ state.isLoading = false;
3824
+ }
3825
+ }
3826
+ });
3827
+ const { actions, reducer: reducer$1 } = appSlice;
3828
+ const { setInitialData } = actions;
3829
+ const reducer = combineReducers({
3830
+ app: reducer$1
3831
+ });
3093
3832
  const index = {
3094
3833
  register(app) {
3095
3834
  const cm = new ContentManagerPlugin();
3096
3835
  app.addReducers({
3097
- [contentManagerApi.reducerPath]: contentManagerApi.reducer,
3098
3836
  [PLUGIN_ID]: reducer
3099
3837
  });
3100
- app.addMiddlewares([() => contentManagerApi.middleware]);
3101
3838
  app.addMenuLink({
3102
3839
  to: PLUGIN_ID,
3103
3840
  icon: Feather,
@@ -3106,14 +3843,29 @@ const index = {
3106
3843
  defaultMessage: "Content Manager"
3107
3844
  },
3108
3845
  permissions: [],
3109
- Component: () => import("./layout-jIDzX0Fp.mjs").then((mod) => ({ default: mod.Layout }))
3846
+ position: 1
3847
+ });
3848
+ app.router.addRoute({
3849
+ path: "content-manager/*",
3850
+ lazy: async () => {
3851
+ const { Layout } = await import("./layout-oPBiO7RY.mjs");
3852
+ return {
3853
+ Component: Layout
3854
+ };
3855
+ },
3856
+ children: routes
3110
3857
  });
3111
3858
  app.registerPlugin(cm.config);
3112
3859
  },
3860
+ bootstrap(app) {
3861
+ if (typeof historyAdmin.bootstrap === "function") {
3862
+ historyAdmin.bootstrap(app);
3863
+ }
3864
+ },
3113
3865
  async registerTrads({ locales }) {
3114
3866
  const importedTrads = await Promise.all(
3115
3867
  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 }) => {
3868
+ 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-BrCTWlZv.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
3869
  return {
3118
3870
  data: prefixPluginTranslations(data, PLUGIN_ID),
3119
3871
  locale
@@ -3131,7 +3883,7 @@ const index = {
3131
3883
  };
3132
3884
  export {
3133
3885
  ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD as A,
3134
- extractContentTypeComponents as B,
3886
+ BulkActionsRenderer as B,
3135
3887
  COLLECTION_TYPES as C,
3136
3888
  DocumentStatus as D,
3137
3889
  DEFAULT_SETTINGS as E,
@@ -3145,31 +3897,31 @@ export {
3145
3897
  RelativeTime as R,
3146
3898
  SINGLE_TYPES as S,
3147
3899
  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,
3900
+ useGetInitialDataQuery as a,
3901
+ useGetAllContentTypeSettingsQuery as b,
3902
+ useDoc as c,
3903
+ buildValidParams as d,
3904
+ contentManagerApi as e,
3905
+ useDocumentRBAC as f,
3154
3906
  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,
3907
+ useDocumentLayout as h,
3908
+ createYupSchema as i,
3909
+ Header as j,
3910
+ PERMISSIONS as k,
3911
+ DocumentRBAC as l,
3912
+ DOCUMENT_META_FIELDS as m,
3913
+ useDocLayout as n,
3162
3914
  useGetContentTypeConfigurationQuery as o,
3163
3915
  CREATOR_FIELDS as p,
3164
3916
  getMainField as q,
3165
- routes as r,
3917
+ getDisplayName as r,
3166
3918
  setInitialData as s,
3167
- getDisplayName as t,
3168
- useGetInitialDataQuery as u,
3169
- checkIfAttributeIsDisplayable as v,
3170
- useGetAllDocumentsQuery as w,
3171
- convertListLayoutToFieldLayouts as x,
3172
- capitalise as y,
3173
- useUpdateContentTypeConfigurationMutation as z
3174
- };
3175
- //# sourceMappingURL=index-CwRRo1V9.mjs.map
3919
+ checkIfAttributeIsDisplayable as t,
3920
+ useContentTypeSchema as u,
3921
+ useGetAllDocumentsQuery as v,
3922
+ convertListLayoutToFieldLayouts as w,
3923
+ capitalise as x,
3924
+ useUpdateContentTypeConfigurationMutation as y,
3925
+ extractContentTypeComponents as z
3926
+ };
3927
+ //# sourceMappingURL=index-c_5DdJi-.mjs.map