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

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 (189) 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--2aLCv-G.mjs → ComponentConfigurationPage-DJ5voqEK.mjs} +3 -3
  7. package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs.map → ComponentConfigurationPage-DJ5voqEK.mjs.map} +1 -1
  8. package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js → ComponentConfigurationPage-_6osrv39.js} +3 -3
  9. package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js.map → ComponentConfigurationPage-_6osrv39.js.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-CUcGHHvQ.mjs → EditConfigurationPage-CZofxSLy.mjs} +3 -3
  15. package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs.map → EditConfigurationPage-CZofxSLy.mjs.map} +1 -1
  16. package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js → EditConfigurationPage-ZN3s568V.js} +3 -3
  17. package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js.map → EditConfigurationPage-ZN3s568V.js.map} +1 -1
  18. package/dist/_chunks/{EditViewPage-CzOT5Kpj.js → EditViewPage-Co2IKQZH.js} +58 -49
  19. package/dist/_chunks/EditViewPage-Co2IKQZH.js.map +1 -0
  20. package/dist/_chunks/{EditViewPage-Bm8lgcm6.mjs → EditViewPage-HYljoEY7.mjs} +59 -48
  21. package/dist/_chunks/EditViewPage-HYljoEY7.mjs.map +1 -0
  22. package/dist/_chunks/{Field-Dlh0uGnL.mjs → Field-BOPUMZ1u.mjs} +995 -795
  23. package/dist/_chunks/Field-BOPUMZ1u.mjs.map +1 -0
  24. package/dist/_chunks/{Field-Caef4JjM.js → Field-G9CkFUtP.js} +1041 -842
  25. package/dist/_chunks/Field-G9CkFUtP.js.map +1 -0
  26. package/dist/_chunks/{Form-EnaQL_6L.mjs → Form-CDwNp7pU.mjs} +69 -48
  27. package/dist/_chunks/Form-CDwNp7pU.mjs.map +1 -0
  28. package/dist/_chunks/{Form-BzuAjtRq.js → Form-crsbkGxI.js} +68 -48
  29. package/dist/_chunks/Form-crsbkGxI.js.map +1 -0
  30. package/dist/_chunks/{History-D6sbCJvo.mjs → History-BDZrgfZ3.mjs} +151 -57
  31. package/dist/_chunks/History-BDZrgfZ3.mjs.map +1 -0
  32. package/dist/_chunks/{History-C17LiyRg.js → History-CWcM9HnW.js} +151 -58
  33. package/dist/_chunks/History-CWcM9HnW.js.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-Ce4qs7qE.mjs → ListConfigurationPage-BZ3ScUna.mjs} +67 -57
  35. package/dist/_chunks/ListConfigurationPage-BZ3ScUna.mjs.map +1 -0
  36. package/dist/_chunks/{ListConfigurationPage-Dks5SX6f.js → ListConfigurationPage-DGzoQD_I.js} +70 -61
  37. package/dist/_chunks/ListConfigurationPage-DGzoQD_I.js.map +1 -0
  38. package/dist/_chunks/{ListViewPage-BwrZrPsh.js → ListViewPage-BBAC9aPu.js} +132 -139
  39. package/dist/_chunks/ListViewPage-BBAC9aPu.js.map +1 -0
  40. package/dist/_chunks/{ListViewPage-Be7S5aKL.mjs → ListViewPage-CsX7tWx-.mjs} +129 -136
  41. package/dist/_chunks/ListViewPage-CsX7tWx-.mjs.map +1 -0
  42. package/dist/_chunks/{NoContentTypePage-Cu5r1-JT.js → NoContentTypePage-CwVDx_YC.js} +5 -5
  43. package/dist/_chunks/NoContentTypePage-CwVDx_YC.js.map +1 -0
  44. package/dist/_chunks/{NoContentTypePage-CIPmYQMm.mjs → NoContentTypePage-LClTUPWs.mjs} +7 -7
  45. package/dist/_chunks/NoContentTypePage-LClTUPWs.mjs.map +1 -0
  46. package/dist/_chunks/{NoPermissionsPage-C-j6TEUF.js → NoPermissionsPage-D2iWw-sn.js} +4 -5
  47. package/dist/_chunks/NoPermissionsPage-D2iWw-sn.js.map +1 -0
  48. package/dist/_chunks/{NoPermissionsPage-DhJ7LYrr.mjs → NoPermissionsPage-S4Re3FwO.mjs} +5 -6
  49. package/dist/_chunks/NoPermissionsPage-S4Re3FwO.mjs.map +1 -0
  50. package/dist/_chunks/{Relations-CY7AtkDA.mjs → Relations-Dmv0Tpe5.mjs} +67 -57
  51. package/dist/_chunks/Relations-Dmv0Tpe5.mjs.map +1 -0
  52. package/dist/_chunks/{Relations-Czs-uZ-s.js → Relations-jwuTFGOV.js} +71 -62
  53. package/dist/_chunks/Relations-jwuTFGOV.js.map +1 -0
  54. package/dist/_chunks/{en-C-V1_90f.js → en-BlhnxQfj.js} +17 -9
  55. package/dist/_chunks/{en-C-V1_90f.js.map → en-BlhnxQfj.js.map} +1 -1
  56. package/dist/_chunks/{en-MBPul9Su.mjs → en-C8YBvRrK.mjs} +17 -9
  57. package/dist/_chunks/{en-MBPul9Su.mjs.map → en-C8YBvRrK.mjs.map} +1 -1
  58. package/dist/_chunks/{index-DNVx8ssZ.mjs → index-BmUAydCA.mjs} +1715 -813
  59. package/dist/_chunks/index-BmUAydCA.mjs.map +1 -0
  60. package/dist/_chunks/{index-X_2tafck.js → index-CBX6KyXv.js} +1815 -914
  61. package/dist/_chunks/index-CBX6KyXv.js.map +1 -0
  62. package/dist/_chunks/{layout-Dnh0PNp9.mjs → layout-ClP-DC72.mjs} +47 -29
  63. package/dist/_chunks/layout-ClP-DC72.mjs.map +1 -0
  64. package/dist/_chunks/{layout-dBc7wN7L.js → layout-CxxkX9jY.js} +47 -31
  65. package/dist/_chunks/layout-CxxkX9jY.js.map +1 -0
  66. package/dist/_chunks/{relations-4pHtBrHJ.js → relations-DIjTADIu.js} +2 -2
  67. package/dist/_chunks/{relations-4pHtBrHJ.js.map → relations-DIjTADIu.js.map} +1 -1
  68. package/dist/_chunks/{relations-Dx7tMKJN.mjs → relations-op89RClB.mjs} +2 -2
  69. package/dist/_chunks/{relations-Dx7tMKJN.mjs.map → relations-op89RClB.mjs.map} +1 -1
  70. package/dist/_chunks/useDebounce-CtcjDB3L.js +28 -0
  71. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  72. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  73. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  74. package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
  75. package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
  76. package/dist/admin/index.js +3 -1
  77. package/dist/admin/index.js.map +1 -1
  78. package/dist/admin/index.mjs +9 -7
  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 +2 -1
  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 +35 -9
  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/WysiwygFooter.d.ts +2 -2
  102. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +16 -53
  103. package/dist/admin/src/pages/EditView/components/Header.d.ts +10 -11
  104. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
  105. package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
  106. package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
  107. package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
  108. package/dist/admin/src/services/api.d.ts +2 -3
  109. package/dist/admin/src/services/components.d.ts +2 -2
  110. package/dist/admin/src/services/contentTypes.d.ts +5 -5
  111. package/dist/admin/src/services/documents.d.ts +31 -17
  112. package/dist/admin/src/services/init.d.ts +2 -2
  113. package/dist/admin/src/services/relations.d.ts +3 -3
  114. package/dist/admin/src/services/uid.d.ts +3 -3
  115. package/dist/admin/src/utils/api.d.ts +4 -18
  116. package/dist/admin/src/utils/validation.d.ts +5 -7
  117. package/dist/server/index.js +648 -447
  118. package/dist/server/index.js.map +1 -1
  119. package/dist/server/index.mjs +656 -455
  120. package/dist/server/index.mjs.map +1 -1
  121. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  122. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  123. package/dist/server/src/controllers/single-types.d.ts.map +1 -1
  124. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  125. package/dist/server/src/controllers/utils/metadata.d.ts +8 -0
  126. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
  127. package/dist/server/src/controllers/validation/dimensions.d.ts +11 -0
  128. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
  129. package/dist/server/src/controllers/validation/index.d.ts +1 -1
  130. package/dist/server/src/history/services/history.d.ts +2 -4
  131. package/dist/server/src/history/services/history.d.ts.map +1 -1
  132. package/dist/server/src/history/services/index.d.ts +6 -2
  133. package/dist/server/src/history/services/index.d.ts.map +1 -1
  134. package/dist/server/src/history/services/lifecycles.d.ts +9 -0
  135. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -0
  136. package/dist/server/src/history/services/utils.d.ts +42 -9
  137. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  138. package/dist/server/src/history/utils.d.ts +6 -2
  139. package/dist/server/src/history/utils.d.ts.map +1 -1
  140. package/dist/server/src/index.d.ts +18 -39
  141. package/dist/server/src/index.d.ts.map +1 -1
  142. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  143. package/dist/server/src/services/document-manager.d.ts +13 -12
  144. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  145. package/dist/server/src/services/document-metadata.d.ts +8 -29
  146. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  147. package/dist/server/src/services/index.d.ts +18 -39
  148. package/dist/server/src/services/index.d.ts.map +1 -1
  149. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  150. package/dist/server/src/services/utils/populate.d.ts +8 -1
  151. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  152. package/dist/shared/contracts/collection-types.d.ts +17 -7
  153. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  154. package/dist/shared/contracts/relations.d.ts +2 -2
  155. package/dist/shared/contracts/relations.d.ts.map +1 -1
  156. package/package.json +16 -17
  157. package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
  158. package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
  159. package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
  160. package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
  161. package/dist/_chunks/EditViewPage-Bm8lgcm6.mjs.map +0 -1
  162. package/dist/_chunks/EditViewPage-CzOT5Kpj.js.map +0 -1
  163. package/dist/_chunks/Field-Caef4JjM.js.map +0 -1
  164. package/dist/_chunks/Field-Dlh0uGnL.mjs.map +0 -1
  165. package/dist/_chunks/Form-BzuAjtRq.js.map +0 -1
  166. package/dist/_chunks/Form-EnaQL_6L.mjs.map +0 -1
  167. package/dist/_chunks/History-C17LiyRg.js.map +0 -1
  168. package/dist/_chunks/History-D6sbCJvo.mjs.map +0 -1
  169. package/dist/_chunks/ListConfigurationPage-Ce4qs7qE.mjs.map +0 -1
  170. package/dist/_chunks/ListConfigurationPage-Dks5SX6f.js.map +0 -1
  171. package/dist/_chunks/ListViewPage-Be7S5aKL.mjs.map +0 -1
  172. package/dist/_chunks/ListViewPage-BwrZrPsh.js.map +0 -1
  173. package/dist/_chunks/NoContentTypePage-CIPmYQMm.mjs.map +0 -1
  174. package/dist/_chunks/NoContentTypePage-Cu5r1-JT.js.map +0 -1
  175. package/dist/_chunks/NoPermissionsPage-C-j6TEUF.js.map +0 -1
  176. package/dist/_chunks/NoPermissionsPage-DhJ7LYrr.mjs.map +0 -1
  177. package/dist/_chunks/Relations-CY7AtkDA.mjs.map +0 -1
  178. package/dist/_chunks/Relations-Czs-uZ-s.js.map +0 -1
  179. package/dist/_chunks/index-DNVx8ssZ.mjs.map +0 -1
  180. package/dist/_chunks/index-X_2tafck.js.map +0 -1
  181. package/dist/_chunks/layout-Dnh0PNp9.mjs.map +0 -1
  182. package/dist/_chunks/layout-dBc7wN7L.js.map +0 -1
  183. package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
  184. package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
  185. package/dist/_chunks/urls-DzZya_gm.js +0 -6
  186. package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
  187. package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
  188. package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
  189. package/strapi-server.js +0 -3
@@ -1,19 +1,17 @@
1
- import { ClockCounterClockwise, CrossCircle, More, WarningCircle, Cog, Pencil, Trash, ChevronRight, Duplicate, Feather } from "@strapi/icons";
1
+ import { More, Cross, WarningCircle, ListPlus, Pencil, Trash, Check, CrossCircle, 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, useQueryParams, getYupValidationErrors, useForm, useTracking, useGuidedTour, 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, Typography, Dialog, Modal, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
7
+ import { useIntl } from "react-intl";
8
+ import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
11
9
  import * as yup from "yup";
12
10
  import { ValidationError } from "yup";
13
- import { createApi } from "@reduxjs/toolkit/query/react";
14
- import { isAxiosError } from "axios";
15
11
  import pipe from "lodash/fp/pipe";
16
12
  import { intervalToDuration, isPast } from "date-fns";
13
+ import { styled } from "styled-components";
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,89 +150,20 @@ 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",
267
158
  "Document",
268
159
  "InitialData",
269
160
  "HistoryVersion",
270
- "Relations"
271
- ],
272
- endpoints: () => ({})
161
+ "Relations",
162
+ "UidAvailability"
163
+ ]
273
164
  });
274
165
  const documentApi = contentManagerApi.injectEndpoints({
166
+ overrideExisting: true,
275
167
  endpoints: (builder) => ({
276
168
  autoCloneDocument: builder.mutation({
277
169
  query: ({ model, sourceId, query }) => ({
@@ -281,7 +173,12 @@ const documentApi = contentManagerApi.injectEndpoints({
281
173
  params: query
282
174
  }
283
175
  }),
284
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
176
+ invalidatesTags: (_result, error, { model }) => {
177
+ if (error) {
178
+ return [];
179
+ }
180
+ return [{ type: "Document", id: `${model}_LIST` }];
181
+ }
285
182
  }),
286
183
  cloneDocument: builder.mutation({
287
184
  query: ({ model, sourceId, data, params }) => ({
@@ -292,7 +189,10 @@ const documentApi = contentManagerApi.injectEndpoints({
292
189
  params
293
190
  }
294
191
  }),
295
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
192
+ invalidatesTags: (_result, _error, { model }) => [
193
+ { type: "Document", id: `${model}_LIST` },
194
+ { type: "UidAvailability", id: model }
195
+ ]
296
196
  }),
297
197
  /**
298
198
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -309,7 +209,8 @@ const documentApi = contentManagerApi.injectEndpoints({
309
209
  }),
310
210
  invalidatesTags: (result, _error, { model }) => [
311
211
  { type: "Document", id: `${model}_LIST` },
312
- "Relations"
212
+ "Relations",
213
+ { type: "UidAvailability", id: model }
313
214
  ]
314
215
  }),
315
216
  deleteDocument: builder.mutation({
@@ -325,12 +226,15 @@ const documentApi = contentManagerApi.injectEndpoints({
325
226
  ]
326
227
  }),
327
228
  deleteManyDocuments: builder.mutation({
328
- query: ({ model, ...body }) => ({
229
+ query: ({ model, params, ...body }) => ({
329
230
  url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
330
231
  method: "POST",
331
- data: body
232
+ data: body,
233
+ config: {
234
+ params
235
+ }
332
236
  }),
333
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
237
+ invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
334
238
  }),
335
239
  discardDocument: builder.mutation({
336
240
  query: ({ collectionType, model, documentId, params }) => ({
@@ -347,7 +251,8 @@ const documentApi = contentManagerApi.injectEndpoints({
347
251
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
348
252
  },
349
253
  { type: "Document", id: `${model}_LIST` },
350
- "Relations"
254
+ "Relations",
255
+ { type: "UidAvailability", id: model }
351
256
  ];
352
257
  }
353
258
  }),
@@ -365,6 +270,7 @@ const documentApi = contentManagerApi.injectEndpoints({
365
270
  }),
366
271
  providesTags: (result, _error, arg) => {
367
272
  return [
273
+ { type: "Document", id: `ALL_LIST` },
368
274
  { type: "Document", id: `${arg.model}_LIST` },
369
275
  ...result?.results.map(({ documentId }) => ({
370
276
  type: "Document",
@@ -403,6 +309,11 @@ const documentApi = contentManagerApi.injectEndpoints({
403
309
  {
404
310
  type: "Document",
405
311
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
312
+ },
313
+ // Make it easy to invalidate all individual documents queries for a model
314
+ {
315
+ type: "Document",
316
+ id: `${model}_ALL_ITEMS`
406
317
  }
407
318
  ];
408
319
  }
@@ -441,10 +352,13 @@ const documentApi = contentManagerApi.injectEndpoints({
441
352
  }
442
353
  }),
443
354
  publishManyDocuments: builder.mutation({
444
- query: ({ model, ...body }) => ({
355
+ query: ({ model, params, ...body }) => ({
445
356
  url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
446
357
  method: "POST",
447
- data: body
358
+ data: body,
359
+ config: {
360
+ params
361
+ }
448
362
  }),
449
363
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
450
364
  }),
@@ -463,8 +377,21 @@ const documentApi = contentManagerApi.injectEndpoints({
463
377
  type: "Document",
464
378
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
465
379
  },
466
- "Relations"
380
+ "Relations",
381
+ { type: "UidAvailability", id: model }
467
382
  ];
383
+ },
384
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
385
+ const patchResult = dispatch(
386
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
387
+ Object.assign(draft.data, data);
388
+ })
389
+ );
390
+ try {
391
+ await queryFulfilled;
392
+ } catch {
393
+ patchResult.undo();
394
+ }
468
395
  }
469
396
  }),
470
397
  unpublishDocument: builder.mutation({
@@ -486,10 +413,13 @@ const documentApi = contentManagerApi.injectEndpoints({
486
413
  }
487
414
  }),
488
415
  unpublishManyDocuments: builder.mutation({
489
- query: ({ model, ...body }) => ({
416
+ query: ({ model, params, ...body }) => ({
490
417
  url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
491
418
  method: "POST",
492
- data: body
419
+ data: body,
420
+ config: {
421
+ params
422
+ }
493
423
  }),
494
424
  invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
495
425
  })
@@ -513,7 +443,25 @@ const {
513
443
  useUnpublishDocumentMutation,
514
444
  useUnpublishManyDocumentsMutation
515
445
  } = documentApi;
516
- const createYupSchema = (attributes = {}, components = {}) => {
446
+ const buildValidParams = (query) => {
447
+ if (!query)
448
+ return query;
449
+ const { plugins: _, ...validQueryParams } = {
450
+ ...query,
451
+ ...Object.values(query?.plugins ?? {}).reduce(
452
+ (acc, current) => Object.assign(acc, current),
453
+ {}
454
+ )
455
+ };
456
+ if ("_q" in validQueryParams) {
457
+ validQueryParams._q = encodeURIComponent(validQueryParams._q);
458
+ }
459
+ return validQueryParams;
460
+ };
461
+ const isBaseQueryError = (error) => {
462
+ return error.name !== void 0;
463
+ };
464
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
517
465
  const createModelSchema = (attributes2) => yup.object().shape(
518
466
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
519
467
  if (DOCUMENT_META_FIELDS.includes(name)) {
@@ -526,7 +474,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
526
474
  addMinValidation,
527
475
  addMaxValidation,
528
476
  addRegexValidation
529
- ].map((fn) => fn(attribute));
477
+ ].map((fn) => fn(attribute, options));
530
478
  const transformSchema = pipe(...validations);
531
479
  switch (attribute.type) {
532
480
  case "component": {
@@ -552,10 +500,14 @@ const createYupSchema = (attributes = {}, components = {}) => {
552
500
  yup.array().of(
553
501
  yup.lazy(
554
502
  (data) => {
555
- const { attributes: attributes3 } = components[data.__component];
556
- return yup.object().shape({
503
+ const attributes3 = components?.[data?.__component]?.attributes;
504
+ const validation = yup.object().shape({
557
505
  __component: yup.string().required().oneOf(Object.keys(components))
558
- }).nullable(false).concat(createModelSchema(attributes3));
506
+ }).nullable(false);
507
+ if (!attributes3) {
508
+ return validation;
509
+ }
510
+ return validation.concat(createModelSchema(attributes3));
559
511
  }
560
512
  )
561
513
  )
@@ -565,11 +517,25 @@ const createYupSchema = (attributes = {}, components = {}) => {
565
517
  return {
566
518
  ...acc,
567
519
  [name]: transformSchema(
568
- yup.array().of(
569
- yup.object().shape({
570
- id: yup.string().required()
571
- })
572
- )
520
+ yup.lazy((value) => {
521
+ if (!value) {
522
+ return yup.mixed().nullable(true);
523
+ } else if (Array.isArray(value)) {
524
+ return yup.array().of(
525
+ yup.object().shape({
526
+ id: yup.string().required()
527
+ })
528
+ );
529
+ } else if (typeof value === "object") {
530
+ return yup.object();
531
+ } else {
532
+ return yup.mixed().test(
533
+ "type-error",
534
+ "Relation values must be either null, an array of objects with {id} or an object.",
535
+ () => false
536
+ );
537
+ }
538
+ })
573
539
  )
574
540
  };
575
541
  default:
@@ -609,6 +575,14 @@ const createAttributeSchema = (attribute) => {
609
575
  if (!value || typeof value === "string" && value.length === 0) {
610
576
  return true;
611
577
  }
578
+ if (typeof value === "object") {
579
+ try {
580
+ JSON.stringify(value);
581
+ return true;
582
+ } catch (err) {
583
+ return false;
584
+ }
585
+ }
612
586
  try {
613
587
  JSON.parse(value);
614
588
  return true;
@@ -627,16 +601,30 @@ const createAttributeSchema = (attribute) => {
627
601
  return yup.mixed();
628
602
  }
629
603
  };
630
- const addRequiredValidation = (attribute) => (schema) => {
631
- if (attribute.required) {
632
- return schema.required({
633
- id: translatedErrors.required.id,
634
- defaultMessage: "This field is required."
635
- });
604
+ const nullableSchema = (schema) => {
605
+ return schema?.nullable ? schema.nullable() : (
606
+ // In some cases '.nullable' will not be available on the schema.
607
+ // e.g. when the schema has been built using yup.lazy (e.g. for relations).
608
+ // In these cases we should just return the schema as it is.
609
+ schema
610
+ );
611
+ };
612
+ const addRequiredValidation = (attribute, options) => (schema) => {
613
+ if (options.status === "draft") {
614
+ return nullableSchema(schema);
636
615
  }
637
- return schema.nullable();
616
+ if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
617
+ return schema.min(1, translatedErrors.required);
618
+ }
619
+ if (attribute.required && attribute.type !== "relation") {
620
+ return schema.required(translatedErrors.required);
621
+ }
622
+ return nullableSchema(schema);
638
623
  };
639
- const addMinLengthValidation = (attribute) => (schema) => {
624
+ const addMinLengthValidation = (attribute, options) => (schema) => {
625
+ if (options.status === "draft") {
626
+ return schema;
627
+ }
640
628
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
641
629
  return schema.min(attribute.minLength, {
642
630
  ...translatedErrors.minLength,
@@ -658,9 +646,31 @@ const addMaxLengthValidation = (attribute) => (schema) => {
658
646
  }
659
647
  return schema;
660
648
  };
661
- const addMinValidation = (attribute) => (schema) => {
649
+ const addMinValidation = (attribute, options) => (schema) => {
662
650
  if ("min" in attribute) {
663
651
  const min = toInteger(attribute.min);
652
+ if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
653
+ if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
654
+ return schema.test(
655
+ "custom-min",
656
+ {
657
+ ...translatedErrors.min,
658
+ values: {
659
+ min: attribute.min
660
+ }
661
+ },
662
+ (value) => {
663
+ if (!value) {
664
+ return true;
665
+ }
666
+ if (Array.isArray(value) && value.length === 0) {
667
+ return true;
668
+ }
669
+ return value.length >= min;
670
+ }
671
+ );
672
+ }
673
+ }
664
674
  if ("min" in schema && min) {
665
675
  return schema.min(min, {
666
676
  ...translatedErrors.min,
@@ -706,24 +716,6 @@ const addRegexValidation = (attribute) => (schema) => {
706
716
  }
707
717
  return schema;
708
718
  };
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
719
  const initApi = contentManagerApi.injectEndpoints({
728
720
  endpoints: (builder) => ({
729
721
  getInitialData: builder.query({
@@ -737,27 +729,20 @@ const { useGetInitialDataQuery } = initApi;
737
729
  const useContentTypeSchema = (model) => {
738
730
  const { toggleNotification } = useNotification();
739
731
  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
- });
732
+ const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
733
+ const { components, contentType, contentTypes } = React.useMemo(() => {
734
+ const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
735
+ const componentsByKey = data?.components.reduce((acc, component) => {
736
+ acc[component.uid] = component;
737
+ return acc;
738
+ }, {});
739
+ const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
740
+ return {
741
+ components: Object.keys(components2).length === 0 ? void 0 : components2,
742
+ contentType: contentType2,
743
+ contentTypes: data?.contentTypes ?? []
744
+ };
745
+ }, [model, data]);
761
746
  React.useEffect(() => {
762
747
  if (error) {
763
748
  toggleNotification({
@@ -804,7 +789,310 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
804
789
  }, {});
805
790
  return componentsByKey;
806
791
  };
807
- const useDocument = (args, opts) => {
792
+ const HOOKS = {
793
+ /**
794
+ * Hook that allows to mutate the displayed headers of the list view table
795
+ * @constant
796
+ * @type {string}
797
+ */
798
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
799
+ /**
800
+ * Hook that allows to mutate the CM's collection types links pre-set filters
801
+ * @constant
802
+ * @type {string}
803
+ */
804
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
805
+ /**
806
+ * Hook that allows to mutate the CM's edit view layout
807
+ * @constant
808
+ * @type {string}
809
+ */
810
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
811
+ /**
812
+ * Hook that allows to mutate the CM's single types links pre-set filters
813
+ * @constant
814
+ * @type {string}
815
+ */
816
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
817
+ };
818
+ const contentTypesApi = contentManagerApi.injectEndpoints({
819
+ endpoints: (builder) => ({
820
+ getContentTypeConfiguration: builder.query({
821
+ query: (uid) => ({
822
+ url: `/content-manager/content-types/${uid}/configuration`,
823
+ method: "GET"
824
+ }),
825
+ transformResponse: (response) => response.data,
826
+ providesTags: (_result, _error, uid) => [
827
+ { type: "ContentTypesConfiguration", id: uid },
828
+ { type: "ContentTypeSettings", id: "LIST" }
829
+ ]
830
+ }),
831
+ getAllContentTypeSettings: builder.query({
832
+ query: () => "/content-manager/content-types-settings",
833
+ transformResponse: (response) => response.data,
834
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
835
+ }),
836
+ updateContentTypeConfiguration: builder.mutation({
837
+ query: ({ uid, ...body }) => ({
838
+ url: `/content-manager/content-types/${uid}/configuration`,
839
+ method: "PUT",
840
+ data: body
841
+ }),
842
+ transformResponse: (response) => response.data,
843
+ invalidatesTags: (_result, _error, { uid }) => [
844
+ { type: "ContentTypesConfiguration", id: uid },
845
+ { type: "ContentTypeSettings", id: "LIST" },
846
+ // Is this necessary?
847
+ { type: "InitialData" }
848
+ ]
849
+ })
850
+ })
851
+ });
852
+ const {
853
+ useGetContentTypeConfigurationQuery,
854
+ useGetAllContentTypeSettingsQuery,
855
+ useUpdateContentTypeConfigurationMutation
856
+ } = contentTypesApi;
857
+ const checkIfAttributeIsDisplayable = (attribute) => {
858
+ const { type } = attribute;
859
+ if (type === "relation") {
860
+ return !attribute.relation.toLowerCase().includes("morph");
861
+ }
862
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
863
+ };
864
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
865
+ if (!mainFieldName) {
866
+ return void 0;
867
+ }
868
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
869
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
870
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
871
+ );
872
+ return {
873
+ name: mainFieldName,
874
+ type: mainFieldType ?? "string"
875
+ };
876
+ };
877
+ const DEFAULT_SETTINGS = {
878
+ bulkable: false,
879
+ filterable: false,
880
+ searchable: false,
881
+ pagination: false,
882
+ defaultSortBy: "",
883
+ defaultSortOrder: "asc",
884
+ mainField: "id",
885
+ pageSize: 10
886
+ };
887
+ const useDocumentLayout = (model) => {
888
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
889
+ const [{ query }] = useQueryParams();
890
+ const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
891
+ const { toggleNotification } = useNotification();
892
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
893
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
894
+ const {
895
+ data,
896
+ isLoading: isLoadingConfigs,
897
+ error,
898
+ isFetching: isFetchingConfigs
899
+ } = useGetContentTypeConfigurationQuery(model);
900
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
901
+ React.useEffect(() => {
902
+ if (error) {
903
+ toggleNotification({
904
+ type: "danger",
905
+ message: formatAPIError(error)
906
+ });
907
+ }
908
+ }, [error, formatAPIError, toggleNotification]);
909
+ const editLayout = React.useMemo(
910
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
911
+ layout: [],
912
+ components: {},
913
+ metadatas: {},
914
+ options: {},
915
+ settings: DEFAULT_SETTINGS
916
+ },
917
+ [data, isLoading, schemas, schema, components]
918
+ );
919
+ const listLayout = React.useMemo(() => {
920
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
921
+ layout: [],
922
+ metadatas: {},
923
+ options: {},
924
+ settings: DEFAULT_SETTINGS
925
+ };
926
+ }, [data, isLoading, schemas, schema, components]);
927
+ const { layout: edit } = React.useMemo(
928
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
929
+ layout: editLayout,
930
+ query
931
+ }),
932
+ [editLayout, query, runHookWaterfall]
933
+ );
934
+ return {
935
+ error,
936
+ isLoading,
937
+ edit,
938
+ list: listLayout
939
+ };
940
+ };
941
+ const useDocLayout = () => {
942
+ const { model } = useDoc();
943
+ return useDocumentLayout(model);
944
+ };
945
+ const formatEditLayout = (data, {
946
+ schemas,
947
+ schema,
948
+ components
949
+ }) => {
950
+ let currentPanelIndex = 0;
951
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
952
+ data.contentType.layouts.edit,
953
+ schema?.attributes,
954
+ data.contentType.metadatas,
955
+ { configurations: data.components, schemas: components },
956
+ schemas
957
+ ).reduce((panels, row) => {
958
+ if (row.some((field) => field.type === "dynamiczone")) {
959
+ panels.push([row]);
960
+ currentPanelIndex += 2;
961
+ } else {
962
+ if (!panels[currentPanelIndex]) {
963
+ panels.push([]);
964
+ }
965
+ panels[currentPanelIndex].push(row);
966
+ }
967
+ return panels;
968
+ }, []);
969
+ const componentEditAttributes = Object.entries(data.components).reduce(
970
+ (acc, [uid, configuration]) => {
971
+ acc[uid] = {
972
+ layout: convertEditLayoutToFieldLayouts(
973
+ configuration.layouts.edit,
974
+ components[uid].attributes,
975
+ configuration.metadatas,
976
+ { configurations: data.components, schemas: components }
977
+ ),
978
+ settings: {
979
+ ...configuration.settings,
980
+ icon: components[uid].info.icon,
981
+ displayName: components[uid].info.displayName
982
+ }
983
+ };
984
+ return acc;
985
+ },
986
+ {}
987
+ );
988
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
989
+ (acc, [attribute, metadata]) => {
990
+ return {
991
+ ...acc,
992
+ [attribute]: metadata.edit
993
+ };
994
+ },
995
+ {}
996
+ );
997
+ return {
998
+ layout: panelledEditAttributes,
999
+ components: componentEditAttributes,
1000
+ metadatas: editMetadatas,
1001
+ settings: {
1002
+ ...data.contentType.settings,
1003
+ displayName: schema?.info.displayName
1004
+ },
1005
+ options: {
1006
+ ...schema?.options,
1007
+ ...schema?.pluginOptions,
1008
+ ...data.contentType.options
1009
+ }
1010
+ };
1011
+ };
1012
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1013
+ return rows.map(
1014
+ (row) => row.map((field) => {
1015
+ const attribute = attributes[field.name];
1016
+ if (!attribute) {
1017
+ return null;
1018
+ }
1019
+ const { edit: metadata } = metadatas[field.name];
1020
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1021
+ return {
1022
+ attribute,
1023
+ disabled: !metadata.editable,
1024
+ hint: metadata.description,
1025
+ label: metadata.label ?? "",
1026
+ name: field.name,
1027
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1028
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1029
+ schemas,
1030
+ components: components?.schemas ?? {}
1031
+ }),
1032
+ placeholder: metadata.placeholder ?? "",
1033
+ required: attribute.required ?? false,
1034
+ size: field.size,
1035
+ unique: "unique" in attribute ? attribute.unique : false,
1036
+ visible: metadata.visible ?? true,
1037
+ type: attribute.type
1038
+ };
1039
+ }).filter((field) => field !== null)
1040
+ );
1041
+ };
1042
+ const formatListLayout = (data, {
1043
+ schemas,
1044
+ schema,
1045
+ components
1046
+ }) => {
1047
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1048
+ (acc, [attribute, metadata]) => {
1049
+ return {
1050
+ ...acc,
1051
+ [attribute]: metadata.list
1052
+ };
1053
+ },
1054
+ {}
1055
+ );
1056
+ const listAttributes = convertListLayoutToFieldLayouts(
1057
+ data.contentType.layouts.list,
1058
+ schema?.attributes,
1059
+ listMetadatas,
1060
+ { configurations: data.components, schemas: components },
1061
+ schemas
1062
+ );
1063
+ return {
1064
+ layout: listAttributes,
1065
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1066
+ metadatas: listMetadatas,
1067
+ options: {
1068
+ ...schema?.options,
1069
+ ...schema?.pluginOptions,
1070
+ ...data.contentType.options
1071
+ }
1072
+ };
1073
+ };
1074
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1075
+ return columns.map((name) => {
1076
+ const attribute = attributes[name];
1077
+ if (!attribute) {
1078
+ return null;
1079
+ }
1080
+ const metadata = metadatas[name];
1081
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1082
+ return {
1083
+ attribute,
1084
+ label: metadata.label ?? "",
1085
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1086
+ schemas,
1087
+ components: components?.schemas ?? {}
1088
+ }),
1089
+ name,
1090
+ searchable: metadata.searchable ?? true,
1091
+ sortable: metadata.sortable ?? true
1092
+ };
1093
+ }).filter((field) => field !== null);
1094
+ };
1095
+ const useDocument = (args, opts) => {
808
1096
  const { toggleNotification } = useNotification();
809
1097
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
810
1098
  const {
@@ -812,8 +1100,16 @@ const useDocument = (args, opts) => {
812
1100
  isLoading: isLoadingDocument,
813
1101
  isFetching: isFetchingDocument,
814
1102
  error
815
- } = useGetDocumentQuery(args, opts);
816
- const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
1103
+ } = useGetDocumentQuery(args, {
1104
+ ...opts,
1105
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1106
+ });
1107
+ const {
1108
+ components,
1109
+ schema,
1110
+ schemas,
1111
+ isLoading: isLoadingSchema
1112
+ } = useContentTypeSchema(args.model);
817
1113
  React.useEffect(() => {
818
1114
  if (error) {
819
1115
  toggleNotification({
@@ -840,7 +1136,7 @@ const useDocument = (args, opts) => {
840
1136
  return null;
841
1137
  } catch (error2) {
842
1138
  if (error2 instanceof ValidationError) {
843
- return getInnerErrors(error2);
1139
+ return getYupValidationErrors(error2);
844
1140
  }
845
1141
  throw error2;
846
1142
  }
@@ -854,6 +1150,7 @@ const useDocument = (args, opts) => {
854
1150
  meta: data?.meta,
855
1151
  isLoading,
856
1152
  schema,
1153
+ schemas,
857
1154
  validate
858
1155
  };
859
1156
  };
@@ -879,6 +1176,45 @@ const useDoc = () => {
879
1176
  )
880
1177
  };
881
1178
  };
1179
+ const useContentManagerContext = () => {
1180
+ const {
1181
+ collectionType,
1182
+ model,
1183
+ id,
1184
+ components,
1185
+ isLoading: isLoadingDoc,
1186
+ schema,
1187
+ schemas
1188
+ } = useDoc();
1189
+ const layout = useDocumentLayout(model);
1190
+ const form = useForm("useContentManagerContext", (state) => state);
1191
+ const isSingleType = collectionType === SINGLE_TYPES;
1192
+ const slug = model;
1193
+ const isCreatingEntry = id === "create";
1194
+ useContentTypeSchema();
1195
+ const isLoading = isLoadingDoc || layout.isLoading;
1196
+ const error = layout.error;
1197
+ return {
1198
+ error,
1199
+ isLoading,
1200
+ // Base metadata
1201
+ model,
1202
+ collectionType,
1203
+ id,
1204
+ slug,
1205
+ isCreatingEntry,
1206
+ isSingleType,
1207
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1208
+ // All schema infos
1209
+ components,
1210
+ contentType: schema,
1211
+ contentTypes: schemas,
1212
+ // Form state
1213
+ form,
1214
+ // layout infos
1215
+ layout
1216
+ };
1217
+ };
882
1218
  const prefixPluginTranslations = (trad, pluginId) => {
883
1219
  if (!pluginId) {
884
1220
  throw new TypeError("pluginId can't be empty");
@@ -898,6 +1234,8 @@ const useDocumentActions = () => {
898
1234
  const { formatMessage } = useIntl();
899
1235
  const { trackUsage } = useTracking();
900
1236
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
1237
+ const navigate = useNavigate();
1238
+ const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
901
1239
  const [deleteDocument] = useDeleteDocumentMutation();
902
1240
  const _delete = React.useCallback(
903
1241
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -936,14 +1274,53 @@ const useDocumentActions = () => {
936
1274
  },
937
1275
  [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
938
1276
  );
1277
+ const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
1278
+ const deleteMany = React.useCallback(
1279
+ async ({ model, documentIds, params }) => {
1280
+ try {
1281
+ trackUsage("willBulkDeleteEntries");
1282
+ const res = await deleteManyDocuments({
1283
+ model,
1284
+ documentIds,
1285
+ params
1286
+ });
1287
+ if ("error" in res) {
1288
+ toggleNotification({
1289
+ type: "danger",
1290
+ message: formatAPIError(res.error)
1291
+ });
1292
+ return { error: res.error };
1293
+ }
1294
+ toggleNotification({
1295
+ type: "success",
1296
+ title: formatMessage({
1297
+ id: getTranslation("success.records.delete"),
1298
+ defaultMessage: "Successfully deleted."
1299
+ }),
1300
+ message: ""
1301
+ });
1302
+ trackUsage("didBulkDeleteEntries");
1303
+ return res.data;
1304
+ } catch (err) {
1305
+ toggleNotification({
1306
+ type: "danger",
1307
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1308
+ });
1309
+ trackUsage("didNotBulkDeleteEntries");
1310
+ throw err;
1311
+ }
1312
+ },
1313
+ [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
1314
+ );
939
1315
  const [discardDocument] = useDiscardDocumentMutation();
940
1316
  const discard = React.useCallback(
941
- async ({ collectionType, model, documentId }) => {
1317
+ async ({ collectionType, model, documentId, params }) => {
942
1318
  try {
943
1319
  const res = await discardDocument({
944
1320
  collectionType,
945
1321
  model,
946
- documentId
1322
+ documentId,
1323
+ params
947
1324
  });
948
1325
  if ("error" in res) {
949
1326
  toggleNotification({
@@ -1005,15 +1382,52 @@ const useDocumentActions = () => {
1005
1382
  },
1006
1383
  [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1007
1384
  );
1008
- const [updateDocument] = useUpdateDocumentMutation();
1009
- const update = React.useCallback(
1010
- async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
1385
+ const [publishManyDocuments] = usePublishManyDocumentsMutation();
1386
+ const publishMany = React.useCallback(
1387
+ async ({ model, documentIds, params }) => {
1011
1388
  try {
1012
- trackUsage("willEditEntry", trackerProperty);
1013
- const res = await updateDocument({
1014
- collectionType,
1389
+ const res = await publishManyDocuments({
1015
1390
  model,
1016
- documentId,
1391
+ documentIds,
1392
+ params
1393
+ });
1394
+ if ("error" in res) {
1395
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1396
+ return { error: res.error };
1397
+ }
1398
+ toggleNotification({
1399
+ type: "success",
1400
+ message: formatMessage({
1401
+ id: getTranslation("success.record.publish"),
1402
+ defaultMessage: "Published document"
1403
+ })
1404
+ });
1405
+ return res.data;
1406
+ } catch (err) {
1407
+ toggleNotification({
1408
+ type: "danger",
1409
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1410
+ });
1411
+ throw err;
1412
+ }
1413
+ },
1414
+ [
1415
+ // trackUsage,
1416
+ publishManyDocuments,
1417
+ toggleNotification,
1418
+ formatMessage,
1419
+ formatAPIError
1420
+ ]
1421
+ );
1422
+ const [updateDocument] = useUpdateDocumentMutation();
1423
+ const update = React.useCallback(
1424
+ async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
1425
+ try {
1426
+ trackUsage("willEditEntry", trackerProperty);
1427
+ const res = await updateDocument({
1428
+ collectionType,
1429
+ model,
1430
+ documentId,
1017
1431
  data,
1018
1432
  params
1019
1433
  });
@@ -1079,6 +1493,41 @@ const useDocumentActions = () => {
1079
1493
  },
1080
1494
  [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1081
1495
  );
1496
+ const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1497
+ const unpublishMany = React.useCallback(
1498
+ async ({ model, documentIds, params }) => {
1499
+ try {
1500
+ trackUsage("willBulkUnpublishEntries");
1501
+ const res = await unpublishManyDocuments({
1502
+ model,
1503
+ documentIds,
1504
+ params
1505
+ });
1506
+ if ("error" in res) {
1507
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1508
+ return { error: res.error };
1509
+ }
1510
+ trackUsage("didBulkUnpublishEntries");
1511
+ toggleNotification({
1512
+ type: "success",
1513
+ title: formatMessage({
1514
+ id: getTranslation("success.records.unpublish"),
1515
+ defaultMessage: "Successfully unpublished."
1516
+ }),
1517
+ message: ""
1518
+ });
1519
+ return res.data;
1520
+ } catch (err) {
1521
+ toggleNotification({
1522
+ type: "danger",
1523
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1524
+ });
1525
+ trackUsage("didNotBulkUnpublishEntries");
1526
+ throw err;
1527
+ }
1528
+ },
1529
+ [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1530
+ );
1082
1531
  const [createDocument] = useCreateDocumentMutation();
1083
1532
  const create = React.useCallback(
1084
1533
  async ({ model, params }, data, trackerProperty) => {
@@ -1101,6 +1550,7 @@ const useDocumentActions = () => {
1101
1550
  defaultMessage: "Saved document"
1102
1551
  })
1103
1552
  });
1553
+ setCurrentStep("contentManager.success");
1104
1554
  return res.data;
1105
1555
  } catch (err) {
1106
1556
  toggleNotification({
@@ -1122,7 +1572,6 @@ const useDocumentActions = () => {
1122
1572
  sourceId
1123
1573
  });
1124
1574
  if ("error" in res) {
1125
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1126
1575
  return { error: res.error };
1127
1576
  }
1128
1577
  toggleNotification({
@@ -1141,7 +1590,7 @@ const useDocumentActions = () => {
1141
1590
  throw err;
1142
1591
  }
1143
1592
  },
1144
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1593
+ [autoCloneDocument, formatMessage, toggleNotification]
1145
1594
  );
1146
1595
  const [cloneDocument] = useCloneDocumentMutation();
1147
1596
  const clone = React.useCallback(
@@ -1167,6 +1616,7 @@ const useDocumentActions = () => {
1167
1616
  defaultMessage: "Cloned document"
1168
1617
  })
1169
1618
  });
1619
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1170
1620
  return res.data;
1171
1621
  } catch (err) {
1172
1622
  toggleNotification({
@@ -1177,7 +1627,7 @@ const useDocumentActions = () => {
1177
1627
  throw err;
1178
1628
  }
1179
1629
  },
1180
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1630
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1181
1631
  );
1182
1632
  const [getDoc] = useLazyGetDocumentQuery();
1183
1633
  const getDocument = React.useCallback(
@@ -1192,15 +1642,18 @@ const useDocumentActions = () => {
1192
1642
  clone,
1193
1643
  create,
1194
1644
  delete: _delete,
1645
+ deleteMany,
1195
1646
  discard,
1196
1647
  getDocument,
1197
1648
  publish,
1649
+ publishMany,
1198
1650
  unpublish,
1651
+ unpublishMany,
1199
1652
  update
1200
1653
  };
1201
1654
  };
1202
1655
  const ProtectedHistoryPage = lazy(
1203
- () => import("./History-D6sbCJvo.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1656
+ () => import("./History-BDZrgfZ3.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1204
1657
  );
1205
1658
  const routes$1 = [
1206
1659
  {
@@ -1213,31 +1666,31 @@ const routes$1 = [
1213
1666
  }
1214
1667
  ];
1215
1668
  const ProtectedEditViewPage = lazy(
1216
- () => import("./EditViewPage-Bm8lgcm6.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1669
+ () => import("./EditViewPage-HYljoEY7.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1217
1670
  );
1218
1671
  const ProtectedListViewPage = lazy(
1219
- () => import("./ListViewPage-Be7S5aKL.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1672
+ () => import("./ListViewPage-CsX7tWx-.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1220
1673
  );
1221
1674
  const ProtectedListConfiguration = lazy(
1222
- () => import("./ListConfigurationPage-Ce4qs7qE.mjs").then((mod) => ({
1675
+ () => import("./ListConfigurationPage-BZ3ScUna.mjs").then((mod) => ({
1223
1676
  default: mod.ProtectedListConfiguration
1224
1677
  }))
1225
1678
  );
1226
1679
  const ProtectedEditConfigurationPage = lazy(
1227
- () => import("./EditConfigurationPage-CUcGHHvQ.mjs").then((mod) => ({
1680
+ () => import("./EditConfigurationPage-CZofxSLy.mjs").then((mod) => ({
1228
1681
  default: mod.ProtectedEditConfigurationPage
1229
1682
  }))
1230
1683
  );
1231
1684
  const ProtectedComponentConfigurationPage = lazy(
1232
- () => import("./ComponentConfigurationPage--2aLCv-G.mjs").then((mod) => ({
1685
+ () => import("./ComponentConfigurationPage-DJ5voqEK.mjs").then((mod) => ({
1233
1686
  default: mod.ProtectedComponentConfigurationPage
1234
1687
  }))
1235
1688
  );
1236
1689
  const NoPermissions = lazy(
1237
- () => import("./NoPermissionsPage-DhJ7LYrr.mjs").then((mod) => ({ default: mod.NoPermissions }))
1690
+ () => import("./NoPermissionsPage-S4Re3FwO.mjs").then((mod) => ({ default: mod.NoPermissions }))
1238
1691
  );
1239
1692
  const NoContentType = lazy(
1240
- () => import("./NoContentTypePage-CIPmYQMm.mjs").then((mod) => ({ default: mod.NoContentType }))
1693
+ () => import("./NoContentTypePage-LClTUPWs.mjs").then((mod) => ({ default: mod.NoContentType }))
1241
1694
  );
1242
1695
  const CollectionTypePages = () => {
1243
1696
  const { collectionType } = useParams();
@@ -1351,12 +1804,14 @@ const DocumentActionButton = (action) => {
1351
1804
  /* @__PURE__ */ jsx(
1352
1805
  Button,
1353
1806
  {
1354
- flex: 1,
1807
+ flex: "auto",
1355
1808
  startIcon: action.icon,
1356
1809
  disabled: action.disabled,
1357
1810
  onClick: handleClick(action),
1358
1811
  justifyContent: "center",
1359
1812
  variant: action.variant || "default",
1813
+ paddingTop: "7px",
1814
+ paddingBottom: "7px",
1360
1815
  children: action.label
1361
1816
  }
1362
1817
  ),
@@ -1364,7 +1819,7 @@ const DocumentActionButton = (action) => {
1364
1819
  DocumentActionConfirmDialog,
1365
1820
  {
1366
1821
  ...action.dialog,
1367
- variant: action.variant,
1822
+ variant: action.dialog?.variant ?? action.variant,
1368
1823
  isOpen: dialogId === action.id,
1369
1824
  onClose: handleClose
1370
1825
  }
@@ -1421,20 +1876,20 @@ const DocumentActionsMenu = ({
1421
1876
  disabled: isDisabled,
1422
1877
  size: "S",
1423
1878
  endIcon: null,
1424
- paddingTop: "7px",
1425
- paddingLeft: "9px",
1426
- paddingRight: "9px",
1879
+ paddingTop: "4px",
1880
+ paddingLeft: "7px",
1881
+ paddingRight: "7px",
1427
1882
  variant,
1428
1883
  children: [
1429
1884
  /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
1430
- /* @__PURE__ */ jsx(VisuallyHidden, { as: "span", children: label || formatMessage({
1885
+ /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: label || formatMessage({
1431
1886
  id: "content-manager.containers.edit.panels.default.more-actions",
1432
1887
  defaultMessage: "More document actions"
1433
1888
  }) })
1434
1889
  ]
1435
1890
  }
1436
1891
  ),
1437
- /* @__PURE__ */ jsxs(Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1892
+ /* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1438
1893
  actions2.map((action) => {
1439
1894
  return /* @__PURE__ */ jsx(
1440
1895
  Menu.Item,
@@ -1443,10 +1898,25 @@ const DocumentActionsMenu = ({
1443
1898
  onSelect: handleClick(action),
1444
1899
  display: "block",
1445
1900
  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,
1448
- action.label
1449
- ] }),
1901
+ /* @__PURE__ */ jsxs(
1902
+ Flex,
1903
+ {
1904
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1905
+ gap: 2,
1906
+ tag: "span",
1907
+ children: [
1908
+ /* @__PURE__ */ jsx(
1909
+ Flex,
1910
+ {
1911
+ tag: "span",
1912
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1913
+ children: action.icon
1914
+ }
1915
+ ),
1916
+ action.label
1917
+ ]
1918
+ }
1919
+ ),
1450
1920
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
1451
1921
  Flex,
1452
1922
  {
@@ -1505,6 +1975,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
1505
1975
  return "primary600";
1506
1976
  }
1507
1977
  };
1978
+ const convertActionVariantToIconColor = (variant = "secondary") => {
1979
+ switch (variant) {
1980
+ case "danger":
1981
+ return "danger600";
1982
+ case "secondary":
1983
+ return "neutral500";
1984
+ case "success":
1985
+ return "success600";
1986
+ default:
1987
+ return "primary600";
1988
+ }
1989
+ };
1508
1990
  const DocumentActionConfirmDialog = ({
1509
1991
  onClose,
1510
1992
  onCancel,
@@ -1527,61 +2009,42 @@ const DocumentActionConfirmDialog = ({
1527
2009
  }
1528
2010
  onClose();
1529
2011
  };
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
- ] });
2012
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2013
+ /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
2014
+ /* @__PURE__ */ jsx(Dialog.Body, { children: content }),
2015
+ /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
2016
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
2017
+ id: "app.components.Button.cancel",
2018
+ defaultMessage: "Cancel"
2019
+ }) }) }),
2020
+ /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
2021
+ id: "app.components.Button.confirm",
2022
+ defaultMessage: "Confirm"
2023
+ }) })
2024
+ ] })
2025
+ ] }) });
1546
2026
  };
1547
2027
  const DocumentActionModal = ({
1548
2028
  isOpen,
1549
2029
  title,
1550
2030
  onClose,
1551
2031
  footer: Footer,
1552
- content,
2032
+ content: Content,
1553
2033
  onModalClose
1554
2034
  }) => {
1555
- const id = React.useId();
1556
- if (!isOpen) {
1557
- return null;
1558
- }
1559
2035
  const handleClose = () => {
1560
2036
  if (onClose) {
1561
2037
  onClose();
1562
2038
  }
1563
2039
  onModalClose();
1564
2040
  };
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
- ] });
2041
+ return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
2042
+ /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
2043
+ typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
2044
+ typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
2045
+ ] }) });
1583
2046
  };
1584
- const PublishAction = ({
2047
+ const PublishAction$1 = ({
1585
2048
  activeTab,
1586
2049
  documentId,
1587
2050
  model,
@@ -1593,13 +2056,17 @@ const PublishAction = ({
1593
2056
  const navigate = useNavigate();
1594
2057
  const { toggleNotification } = useNotification();
1595
2058
  const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
2059
+ const isListView = useMatch(LIST_PATH) !== null;
1596
2060
  const isCloning = useMatch(CLONE_PATH) !== null;
1597
2061
  const { formatMessage } = useIntl();
1598
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1599
- "PublishAction",
1600
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1601
- );
2062
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1602
2063
  const { publish } = useDocumentActions();
2064
+ const [
2065
+ countDraftRelations,
2066
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
2067
+ ] = useLazyGetDraftRelationCountQuery();
2068
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
2069
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
1603
2070
  const [{ query, rawQuery }] = useQueryParams();
1604
2071
  const params = React.useMemo(() => buildValidParams(query), [query]);
1605
2072
  const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1608,10 +2075,103 @@ const PublishAction = ({
1608
2075
  const validate = useForm("PublishAction", (state) => state.validate);
1609
2076
  const setErrors = useForm("PublishAction", (state) => state.setErrors);
1610
2077
  const formValues = useForm("PublishAction", ({ values }) => values);
2078
+ React.useEffect(() => {
2079
+ if (isErrorDraftRelations) {
2080
+ toggleNotification({
2081
+ type: "danger",
2082
+ message: formatMessage({
2083
+ id: getTranslation("error.records.fetch-draft-relatons"),
2084
+ defaultMessage: "An error occurred while fetching draft relations on this document."
2085
+ })
2086
+ });
2087
+ }
2088
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
2089
+ React.useEffect(() => {
2090
+ const localDraftRelations = /* @__PURE__ */ new Set();
2091
+ const extractDraftRelations = (data) => {
2092
+ const relations = data.connect || [];
2093
+ relations.forEach((relation) => {
2094
+ if (relation.status === "draft") {
2095
+ localDraftRelations.add(relation.id);
2096
+ }
2097
+ });
2098
+ };
2099
+ const traverseAndExtract = (data) => {
2100
+ Object.entries(data).forEach(([key, value]) => {
2101
+ if (key === "connect" && Array.isArray(value)) {
2102
+ extractDraftRelations({ connect: value });
2103
+ } else if (typeof value === "object" && value !== null) {
2104
+ traverseAndExtract(value);
2105
+ }
2106
+ });
2107
+ };
2108
+ if (!documentId || modified) {
2109
+ traverseAndExtract(formValues);
2110
+ setLocalCountOfDraftRelations(localDraftRelations.size);
2111
+ }
2112
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
2113
+ React.useEffect(() => {
2114
+ if (!document || !document.documentId || isListView) {
2115
+ return;
2116
+ }
2117
+ const fetchDraftRelationsCount = async () => {
2118
+ const { data, error } = await countDraftRelations({
2119
+ collectionType,
2120
+ model,
2121
+ documentId,
2122
+ params
2123
+ });
2124
+ if (error) {
2125
+ throw error;
2126
+ }
2127
+ if (data) {
2128
+ setServerCountOfDraftRelations(data.data);
2129
+ }
2130
+ };
2131
+ fetchDraftRelationsCount();
2132
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
1611
2133
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1612
2134
  if (!schema?.options?.draftAndPublish) {
1613
2135
  return null;
1614
2136
  }
2137
+ const performPublish = async () => {
2138
+ setSubmitting(true);
2139
+ try {
2140
+ const { errors } = await validate();
2141
+ if (errors) {
2142
+ toggleNotification({
2143
+ type: "danger",
2144
+ message: formatMessage({
2145
+ id: "content-manager.validation.error",
2146
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2147
+ })
2148
+ });
2149
+ return;
2150
+ }
2151
+ const res = await publish(
2152
+ {
2153
+ collectionType,
2154
+ model,
2155
+ documentId,
2156
+ params
2157
+ },
2158
+ formValues
2159
+ );
2160
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2161
+ navigate({
2162
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2163
+ search: rawQuery
2164
+ });
2165
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2166
+ setErrors(formatValidationErrors(res.error));
2167
+ }
2168
+ } finally {
2169
+ setSubmitting(false);
2170
+ }
2171
+ };
2172
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
2173
+ const enableDraftRelationsCount = false;
2174
+ const hasDraftRelations = enableDraftRelationsCount;
1615
2175
  return {
1616
2176
  /**
1617
2177
  * Disabled when:
@@ -1621,52 +2181,39 @@ const PublishAction = ({
1621
2181
  * - the document is already published & not modified
1622
2182
  * - the document is being created & not modified
1623
2183
  * - the user doesn't have the permission to publish
1624
- * - the user doesn't have the permission to create a new document
1625
- * - the user doesn't have the permission to update the document
1626
2184
  */
1627
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2185
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1628
2186
  label: formatMessage({
1629
2187
  id: "app.utils.publish",
1630
2188
  defaultMessage: "Publish"
1631
2189
  }),
1632
2190
  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));
2191
+ await performPublish();
2192
+ },
2193
+ dialog: hasDraftRelations ? {
2194
+ type: "dialog",
2195
+ variant: "danger",
2196
+ footer: null,
2197
+ title: formatMessage({
2198
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
2199
+ defaultMessage: "Confirmation"
2200
+ }),
2201
+ content: formatMessage(
2202
+ {
2203
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
2204
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
2205
+ },
2206
+ {
2207
+ count: totalDraftRelations
1662
2208
  }
1663
- } finally {
1664
- setSubmitting(false);
2209
+ ),
2210
+ onConfirm: async () => {
2211
+ await performPublish();
1665
2212
  }
1666
- }
2213
+ } : void 0
1667
2214
  };
1668
2215
  };
1669
- PublishAction.type = "publish";
2216
+ PublishAction$1.type = "publish";
1670
2217
  const UpdateAction = ({
1671
2218
  activeTab,
1672
2219
  documentId,
@@ -1679,10 +2226,6 @@ const UpdateAction = ({
1679
2226
  const cloneMatch = useMatch(CLONE_PATH);
1680
2227
  const isCloning = cloneMatch !== null;
1681
2228
  const { formatMessage } = useIntl();
1682
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1683
- canCreate: canCreate2,
1684
- canUpdate: canUpdate2
1685
- }));
1686
2229
  const { create, update, clone } = useDocumentActions();
1687
2230
  const [{ query, rawQuery }] = useQueryParams();
1688
2231
  const params = React.useMemo(() => buildValidParams(query), [query]);
@@ -1699,10 +2242,8 @@ const UpdateAction = ({
1699
2242
  * - the form is submitting
1700
2243
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1701
2244
  * - the active tab is the published tab
1702
- * - the user doesn't have the permission to create a new document
1703
- * - the user doesn't have the permission to update the document
1704
2245
  */
1705
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
2246
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1706
2247
  label: formatMessage({
1707
2248
  id: "content-manager.containers.Edit.save",
1708
2249
  defaultMessage: "Save"
@@ -1710,16 +2251,18 @@ const UpdateAction = ({
1710
2251
  onClick: async () => {
1711
2252
  setSubmitting(true);
1712
2253
  try {
1713
- const { errors } = await validate();
1714
- if (errors) {
1715
- toggleNotification({
1716
- type: "danger",
1717
- message: formatMessage({
1718
- id: "content-manager.validation.error",
1719
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1720
- })
1721
- });
1722
- return;
2254
+ if (activeTab !== "draft") {
2255
+ const { errors } = await validate();
2256
+ if (errors) {
2257
+ toggleNotification({
2258
+ type: "danger",
2259
+ message: formatMessage({
2260
+ id: "content-manager.validation.error",
2261
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2262
+ })
2263
+ });
2264
+ return;
2265
+ }
1723
2266
  }
1724
2267
  if (isCloning) {
1725
2268
  const res = await clone(
@@ -1731,10 +2274,13 @@ const UpdateAction = ({
1731
2274
  document
1732
2275
  );
1733
2276
  if ("data" in res) {
1734
- navigate({
1735
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1736
- search: rawQuery
1737
- });
2277
+ navigate(
2278
+ {
2279
+ pathname: `../${res.data.documentId}`,
2280
+ search: rawQuery
2281
+ },
2282
+ { relative: "path" }
2283
+ );
1738
2284
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1739
2285
  setErrors(formatValidationErrors(res.error));
1740
2286
  }
@@ -1762,10 +2308,13 @@ const UpdateAction = ({
1762
2308
  document
1763
2309
  );
1764
2310
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1765
- navigate({
1766
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1767
- search: rawQuery
1768
- });
2311
+ navigate(
2312
+ {
2313
+ pathname: `../${res.data.documentId}`,
2314
+ search: rawQuery
2315
+ },
2316
+ { replace: true, relative: "path" }
2317
+ );
1769
2318
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1770
2319
  setErrors(formatValidationErrors(res.error));
1771
2320
  }
@@ -1781,7 +2330,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
1781
2330
  KEEP: "keep",
1782
2331
  DISCARD: "discard"
1783
2332
  };
1784
- const UnpublishAction = ({
2333
+ const UnpublishAction$1 = ({
1785
2334
  activeTab,
1786
2335
  documentId,
1787
2336
  model,
@@ -1797,10 +2346,8 @@ const UnpublishAction = ({
1797
2346
  const { toggleNotification } = useNotification();
1798
2347
  const [shouldKeepDraft, setShouldKeepDraft] = React.useState(true);
1799
2348
  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
- }
2349
+ const handleChange = (value) => {
2350
+ setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
1804
2351
  };
1805
2352
  if (!schema?.options?.draftAndPublish) {
1806
2353
  return null;
@@ -1811,7 +2358,7 @@ const UnpublishAction = ({
1811
2358
  id: "app.utils.unpublish",
1812
2359
  defaultMessage: "Unpublish"
1813
2360
  }),
1814
- icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
2361
+ icon: /* @__PURE__ */ jsx(Cross, {}),
1815
2362
  onClick: async () => {
1816
2363
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1817
2364
  if (!documentId) {
@@ -1844,45 +2391,30 @@ const UnpublishAction = ({
1844
2391
  content: /* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
1845
2392
  /* @__PURE__ */ jsxs(Flex, { width: "100%", direction: "column", gap: 2, children: [
1846
2393
  /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
1847
- /* @__PURE__ */ jsx(Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2394
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1848
2395
  id: "content-manager.actions.unpublish.dialog.body",
1849
2396
  defaultMessage: "Are you sure?"
1850
2397
  }) })
1851
2398
  ] }),
1852
2399
  /* @__PURE__ */ jsxs(
1853
- Flex,
2400
+ Radio.Group,
1854
2401
  {
1855
- onChange: handleChange,
1856
- direction: "column",
1857
- alignItems: "flex-start",
1858
- as: "fieldset",
1859
- gap: 3,
2402
+ defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
2403
+ name: "discard-options",
2404
+ "aria-label": formatMessage({
2405
+ id: "content-manager.actions.unpublish.dialog.radio-label",
2406
+ defaultMessage: "Choose an option to unpublish the document."
2407
+ }),
2408
+ onValueChange: handleChange,
1860
2409
  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
- )
2410
+ /* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
2411
+ id: "content-manager.actions.unpublish.dialog.option.keep-draft",
2412
+ defaultMessage: "Keep draft"
2413
+ }) }),
2414
+ /* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
2415
+ id: "content-manager.actions.unpublish.dialog.option.replace-draft",
2416
+ defaultMessage: "Replace draft"
2417
+ }) })
1886
2418
  ]
1887
2419
  }
1888
2420
  )
@@ -1915,7 +2447,7 @@ const UnpublishAction = ({
1915
2447
  position: ["panel", "table-row"]
1916
2448
  };
1917
2449
  };
1918
- UnpublishAction.type = "unpublish";
2450
+ UnpublishAction$1.type = "unpublish";
1919
2451
  const DiscardAction = ({
1920
2452
  activeTab,
1921
2453
  documentId,
@@ -1938,7 +2470,7 @@ const DiscardAction = ({
1938
2470
  id: "content-manager.actions.discard.label",
1939
2471
  defaultMessage: "Discard changes"
1940
2472
  }),
1941
- icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
2473
+ icon: /* @__PURE__ */ jsx(Cross, {}),
1942
2474
  position: ["panel", "table-row"],
1943
2475
  variant: "danger",
1944
2476
  dialog: {
@@ -1949,7 +2481,7 @@ const DiscardAction = ({
1949
2481
  }),
1950
2482
  content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
1951
2483
  /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
1952
- /* @__PURE__ */ jsx(Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2484
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
1953
2485
  id: "content-manager.actions.discard.dialog.body",
1954
2486
  defaultMessage: "Are you sure?"
1955
2487
  }) })
@@ -1966,12 +2498,7 @@ const DiscardAction = ({
1966
2498
  };
1967
2499
  };
1968
2500
  DiscardAction.type = "discard";
1969
- const StyledCrossCircle = styled(CrossCircle)`
1970
- path {
1971
- fill: currentColor;
1972
- }
1973
- `;
1974
- const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
2501
+ const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
1975
2502
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
1976
2503
  const RelativeTime = React.forwardRef(
1977
2504
  ({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
@@ -2018,8 +2545,8 @@ const getDisplayName = ({
2018
2545
  };
2019
2546
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2020
2547
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2021
- 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) }) });
2548
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2549
+ 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
2550
  };
2024
2551
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2025
2552
  const { formatMessage } = useIntl();
@@ -2028,23 +2555,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2028
2555
  id: "content-manager.containers.edit.title.new",
2029
2556
  defaultMessage: "Create an entry"
2030
2557
  }) : documentTitle;
2031
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2558
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2032
2559
  /* @__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
2560
+ /* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2561
+ /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
2562
+ /* @__PURE__ */ jsx(HeaderToolbar, {})
2563
+ ] }),
2564
+ status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2048
2565
  ] });
2049
2566
  };
2050
2567
  const HeaderToolbar = () => {
@@ -2196,7 +2713,7 @@ const Information = ({ activeTab }) => {
2196
2713
  borderColor: "neutral150",
2197
2714
  direction: "column",
2198
2715
  marginTop: 2,
2199
- as: "dl",
2716
+ tag: "dl",
2200
2717
  padding: 5,
2201
2718
  gap: 3,
2202
2719
  alignItems: "flex-start",
@@ -2204,15 +2721,29 @@ const Information = ({ activeTab }) => {
2204
2721
  marginRight: "-0.4rem",
2205
2722
  width: "calc(100% + 8px)",
2206
2723
  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 })
2724
+ /* @__PURE__ */ jsx(Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
2725
+ /* @__PURE__ */ jsx(Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
2209
2726
  ] }, info.label))
2210
2727
  }
2211
2728
  );
2212
2729
  };
2213
2730
  const HeaderActions = ({ actions: actions2 }) => {
2214
- return /* @__PURE__ */ jsx(Flex, { children: actions2.map((action) => {
2215
- if ("options" in action) {
2731
+ const [dialogId, setDialogId] = React.useState(null);
2732
+ const handleClick = (action) => async (e) => {
2733
+ if (!("options" in action)) {
2734
+ const { onClick = () => false, dialog, id } = action;
2735
+ const muteDialog = await onClick(e);
2736
+ if (dialog && !muteDialog) {
2737
+ e.preventDefault();
2738
+ setDialogId(id);
2739
+ }
2740
+ }
2741
+ };
2742
+ const handleClose = () => {
2743
+ setDialogId(null);
2744
+ };
2745
+ return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
2746
+ if (action.options) {
2216
2747
  return /* @__PURE__ */ jsx(
2217
2748
  SingleSelect,
2218
2749
  {
@@ -2226,10 +2757,49 @@ const HeaderActions = ({ actions: actions2 }) => {
2226
2757
  action.id
2227
2758
  );
2228
2759
  } else {
2229
- return null;
2760
+ if (action.type === "icon") {
2761
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
2762
+ /* @__PURE__ */ jsx(
2763
+ IconButton,
2764
+ {
2765
+ disabled: action.disabled,
2766
+ label: action.label,
2767
+ size: "S",
2768
+ onClick: handleClick(action),
2769
+ children: action.icon
2770
+ }
2771
+ ),
2772
+ action.dialog ? /* @__PURE__ */ jsx(
2773
+ HeaderActionDialog,
2774
+ {
2775
+ ...action.dialog,
2776
+ isOpen: dialogId === action.id,
2777
+ onClose: handleClose
2778
+ }
2779
+ ) : null
2780
+ ] }, action.id);
2781
+ }
2230
2782
  }
2231
2783
  }) });
2232
2784
  };
2785
+ const HeaderActionDialog = ({
2786
+ onClose,
2787
+ onCancel,
2788
+ title,
2789
+ content: Content,
2790
+ isOpen
2791
+ }) => {
2792
+ const handleClose = async () => {
2793
+ if (onCancel) {
2794
+ await onCancel();
2795
+ }
2796
+ onClose();
2797
+ };
2798
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2799
+ /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
2800
+ typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
2801
+ ] }) });
2802
+ };
2233
2803
  const ConfigureTheViewAction = ({ collectionType, model }) => {
2234
2804
  const navigate = useNavigate();
2235
2805
  const { formatMessage } = useIntl();
@@ -2238,7 +2808,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2238
2808
  id: "app.links.configure-view",
2239
2809
  defaultMessage: "Configure the view"
2240
2810
  }),
2241
- icon: /* @__PURE__ */ jsx(StyledCog, {}),
2811
+ icon: /* @__PURE__ */ jsx(ListPlus, {}),
2242
2812
  onClick: () => {
2243
2813
  navigate(`../${collectionType}/${model}/configurations/edit`);
2244
2814
  },
@@ -2246,11 +2816,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2246
2816
  };
2247
2817
  };
2248
2818
  ConfigureTheViewAction.type = "configure-the-view";
2249
- const StyledCog = styled(Cog)`
2250
- path {
2251
- fill: currentColor;
2252
- }
2253
- `;
2254
2819
  const EditTheModelAction = ({ model }) => {
2255
2820
  const navigate = useNavigate();
2256
2821
  const { formatMessage } = useIntl();
@@ -2259,7 +2824,7 @@ const EditTheModelAction = ({ model }) => {
2259
2824
  id: "content-manager.link-to-ctb",
2260
2825
  defaultMessage: "Edit the model"
2261
2826
  }),
2262
- icon: /* @__PURE__ */ jsx(StyledPencil$1, {}),
2827
+ icon: /* @__PURE__ */ jsx(Pencil, {}),
2263
2828
  onClick: () => {
2264
2829
  navigate(`/plugins/content-type-builder/content-types/${model}`);
2265
2830
  },
@@ -2267,12 +2832,7 @@ const EditTheModelAction = ({ model }) => {
2267
2832
  };
2268
2833
  };
2269
2834
  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 }) => {
2835
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2276
2836
  const navigate = useNavigate();
2277
2837
  const { formatMessage } = useIntl();
2278
2838
  const listViewPathMatch = useMatch(LIST_PATH);
@@ -2280,13 +2840,17 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2280
2840
  const { delete: deleteAction } = useDocumentActions();
2281
2841
  const { toggleNotification } = useNotification();
2282
2842
  const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
2843
+ const isLocalized = document?.locale != null;
2283
2844
  return {
2284
2845
  disabled: !canDelete || !document,
2285
- label: formatMessage({
2286
- id: "content-manager.actions.delete.label",
2287
- defaultMessage: "Delete document"
2288
- }),
2289
- icon: /* @__PURE__ */ jsx(StyledTrash, {}),
2846
+ label: formatMessage(
2847
+ {
2848
+ id: "content-manager.actions.delete.label",
2849
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2850
+ },
2851
+ { isLocalized }
2852
+ ),
2853
+ icon: /* @__PURE__ */ jsx(Trash, {}),
2290
2854
  dialog: {
2291
2855
  type: "dialog",
2292
2856
  title: formatMessage({
@@ -2295,7 +2859,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2295
2859
  }),
2296
2860
  content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2297
2861
  /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2298
- /* @__PURE__ */ jsx(Typography, { as: "p", variant: "omega", textAlign: "center", children: formatMessage({
2862
+ /* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2299
2863
  id: "content-manager.actions.delete.dialog.body",
2300
2864
  defaultMessage: "Are you sure?"
2301
2865
  }) })
@@ -2340,13 +2904,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
2340
2904
  position: ["header", "table-row"]
2341
2905
  };
2342
2906
  };
2343
- DeleteAction.type = "delete";
2344
- const StyledTrash = styled(Trash)`
2345
- path {
2346
- fill: currentColor;
2347
- }
2348
- `;
2349
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction];
2907
+ DeleteAction$1.type = "delete";
2908
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2350
2909
  const Panels = () => {
2351
2910
  const isCloning = useMatch(CLONE_PATH) !== null;
2352
2911
  const [
@@ -2380,7 +2939,7 @@ const ActionsPanel = () => {
2380
2939
  return {
2381
2940
  title: formatMessage({
2382
2941
  id: "content-manager.containers.edit.panels.default.title",
2383
- defaultMessage: "Document"
2942
+ defaultMessage: "Entry"
2384
2943
  }),
2385
2944
  content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
2386
2945
  };
@@ -2420,7 +2979,7 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
2420
2979
  Flex,
2421
2980
  {
2422
2981
  ref,
2423
- as: "aside",
2982
+ tag: "aside",
2424
2983
  "aria-labelledby": "additional-information",
2425
2984
  background: "neutral0",
2426
2985
  borderColor: "neutral150",
@@ -2435,27 +2994,612 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
2435
2994
  justifyContent: "stretch",
2436
2995
  alignItems: "flex-start",
2437
2996
  children: [
2438
- /* @__PURE__ */ jsx(Typography, { as: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2997
+ /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2439
2998
  children
2440
2999
  ]
2441
3000
  }
2442
3001
  );
2443
3002
  });
2444
- const DEFAULT_BULK_ACTIONS = [];
2445
- const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3003
+ const ConfirmBulkActionDialog = ({
3004
+ onToggleDialog,
3005
+ isOpen = false,
3006
+ dialogBody,
3007
+ endAction
3008
+ }) => {
2446
3009
  const { formatMessage } = useIntl();
2447
- const getDefaultErrorMessage = (reason) => {
2448
- switch (reason) {
2449
- case "relation":
2450
- return "Duplicating the relation could remove it from the original entry.";
2451
- case "unique":
2452
- return "Identical values in a unique field are not allowed";
2453
- default:
2454
- return reason;
2455
- }
2456
- };
2457
- return /* @__PURE__ */ jsxs(Fragment, { children: [
2458
- /* @__PURE__ */ jsx(Typography, { variant: "beta", children: formatMessage({
3010
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
3011
+ /* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
3012
+ id: "app.components.ConfirmDialog.title",
3013
+ defaultMessage: "Confirmation"
3014
+ }) }),
3015
+ /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3016
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3017
+ dialogBody
3018
+ ] }) }),
3019
+ /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
3020
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
3021
+ id: "app.components.Button.cancel",
3022
+ defaultMessage: "Cancel"
3023
+ }) }) }),
3024
+ endAction
3025
+ ] })
3026
+ ] }) });
3027
+ };
3028
+ const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
3029
+ const ConfirmDialogPublishAll = ({
3030
+ isOpen,
3031
+ onToggleDialog,
3032
+ isConfirmButtonLoading = false,
3033
+ onConfirm
3034
+ }) => {
3035
+ const { formatMessage } = useIntl();
3036
+ const selectedEntries = useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
3037
+ const { toggleNotification } = useNotification();
3038
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
3039
+ const { model, schema } = useDoc();
3040
+ const [{ query }] = useQueryParams();
3041
+ const enableDraftRelationsCount = false;
3042
+ const {
3043
+ data: countDraftRelations = 0,
3044
+ isLoading,
3045
+ error
3046
+ } = useGetManyDraftRelationCountQuery(
3047
+ {
3048
+ model,
3049
+ documentIds: selectedEntries.map((entry) => entry.documentId),
3050
+ locale: query?.plugins?.i18n?.locale
3051
+ },
3052
+ {
3053
+ skip: !enableDraftRelationsCount
3054
+ }
3055
+ );
3056
+ React.useEffect(() => {
3057
+ if (error) {
3058
+ toggleNotification({ type: "danger", message: formatAPIError(error) });
3059
+ }
3060
+ }, [error, formatAPIError, toggleNotification]);
3061
+ if (error) {
3062
+ return null;
3063
+ }
3064
+ return /* @__PURE__ */ jsx(
3065
+ ConfirmBulkActionDialog,
3066
+ {
3067
+ isOpen: isOpen && !isLoading,
3068
+ onToggleDialog,
3069
+ dialogBody: /* @__PURE__ */ jsxs(Fragment, { children: [
3070
+ /* @__PURE__ */ jsxs(Typography, { id: "confirm-description", textAlign: "center", children: [
3071
+ countDraftRelations > 0 && formatMessage(
3072
+ {
3073
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
3074
+ 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. "
3075
+ },
3076
+ {
3077
+ b: BoldChunk$1,
3078
+ count: countDraftRelations,
3079
+ entities: selectedEntries.length
3080
+ }
3081
+ ),
3082
+ formatMessage({
3083
+ id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
3084
+ defaultMessage: "Are you sure you want to publish these entries?"
3085
+ })
3086
+ ] }),
3087
+ schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsx(Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
3088
+ {
3089
+ id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
3090
+ defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
3091
+ },
3092
+ {
3093
+ em: Emphasis
3094
+ }
3095
+ ) })
3096
+ ] }),
3097
+ endAction: /* @__PURE__ */ jsx(
3098
+ Button,
3099
+ {
3100
+ onClick: onConfirm,
3101
+ variant: "secondary",
3102
+ startIcon: /* @__PURE__ */ jsx(Check, {}),
3103
+ loading: isConfirmButtonLoading,
3104
+ children: formatMessage({
3105
+ id: "app.utils.publish",
3106
+ defaultMessage: "Publish"
3107
+ })
3108
+ }
3109
+ )
3110
+ }
3111
+ );
3112
+ };
3113
+ const TypographyMaxWidth = styled(Typography)`
3114
+ max-width: 300px;
3115
+ `;
3116
+ const formatErrorMessages = (errors, parentKey, formatMessage) => {
3117
+ const messages = [];
3118
+ Object.entries(errors).forEach(([key, value]) => {
3119
+ const currentKey = parentKey ? `${parentKey}.${key}` : key;
3120
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
3121
+ if ("id" in value && "defaultMessage" in value) {
3122
+ messages.push(
3123
+ formatMessage(
3124
+ {
3125
+ id: `${value.id}.withField`,
3126
+ defaultMessage: value.defaultMessage
3127
+ },
3128
+ { field: currentKey }
3129
+ )
3130
+ );
3131
+ } else {
3132
+ messages.push(
3133
+ ...formatErrorMessages(
3134
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3135
+ value,
3136
+ currentKey,
3137
+ formatMessage
3138
+ )
3139
+ );
3140
+ }
3141
+ } else {
3142
+ messages.push(
3143
+ formatMessage(
3144
+ {
3145
+ id: `${value}.withField`,
3146
+ defaultMessage: value
3147
+ },
3148
+ { field: currentKey }
3149
+ )
3150
+ );
3151
+ }
3152
+ });
3153
+ return messages;
3154
+ };
3155
+ const EntryValidationText = ({ validationErrors, status }) => {
3156
+ const { formatMessage } = useIntl();
3157
+ if (validationErrors) {
3158
+ const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
3159
+ " "
3160
+ );
3161
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3162
+ /* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
3163
+ /* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
3164
+ ] });
3165
+ }
3166
+ if (status === "published") {
3167
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3168
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
3169
+ /* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
3170
+ id: "content-manager.bulk-publish.already-published",
3171
+ defaultMessage: "Already Published"
3172
+ }) })
3173
+ ] });
3174
+ }
3175
+ if (status === "modified") {
3176
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3177
+ /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
3178
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
3179
+ id: "content-manager.bulk-publish.modified",
3180
+ defaultMessage: "Ready to publish changes"
3181
+ }) })
3182
+ ] });
3183
+ }
3184
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3185
+ /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
3186
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
3187
+ id: "app.utils.ready-to-publish",
3188
+ defaultMessage: "Ready to publish"
3189
+ }) })
3190
+ ] });
3191
+ };
3192
+ const TABLE_HEADERS = [
3193
+ { name: "id", label: "id" },
3194
+ { name: "name", label: "name" },
3195
+ { name: "status", label: "status" },
3196
+ { name: "publicationStatus", label: "Publication status" }
3197
+ ];
3198
+ const SelectedEntriesTableContent = ({
3199
+ isPublishing,
3200
+ rowsToDisplay = [],
3201
+ entriesToPublish = [],
3202
+ validationErrors = {}
3203
+ }) => {
3204
+ const { pathname } = useLocation();
3205
+ const { formatMessage } = useIntl();
3206
+ const {
3207
+ list: {
3208
+ settings: { mainField }
3209
+ }
3210
+ } = useDocLayout();
3211
+ const shouldDisplayMainField = mainField != null && mainField !== "id";
3212
+ return /* @__PURE__ */ jsxs(Table.Content, { children: [
3213
+ /* @__PURE__ */ jsxs(Table.Head, { children: [
3214
+ /* @__PURE__ */ jsx(Table.HeaderCheckboxCell, {}),
3215
+ TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
3216
+ (head) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...head }, head.name)
3217
+ )
3218
+ ] }),
3219
+ /* @__PURE__ */ jsx(Table.Loading, {}),
3220
+ /* @__PURE__ */ jsx(Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxs(Table.Row, { children: [
3221
+ /* @__PURE__ */ jsx(Table.CheckboxCell, { id: row.id }),
3222
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row.id }) }),
3223
+ shouldDisplayMainField && /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row[mainField] }) }),
3224
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
3225
+ /* @__PURE__ */ jsx(Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3226
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
3227
+ id: "content-manager.success.record.publishing",
3228
+ defaultMessage: "Publishing..."
3229
+ }) }),
3230
+ /* @__PURE__ */ jsx(Loader, { small: true })
3231
+ ] }) : /* @__PURE__ */ jsx(
3232
+ EntryValidationText,
3233
+ {
3234
+ validationErrors: validationErrors[row.documentId],
3235
+ status: row.status
3236
+ }
3237
+ ) }),
3238
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
3239
+ IconButton,
3240
+ {
3241
+ tag: Link,
3242
+ to: {
3243
+ pathname: `${pathname}/${row.documentId}`,
3244
+ search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3245
+ },
3246
+ state: { from: pathname },
3247
+ label: formatMessage(
3248
+ { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3249
+ {
3250
+ target: formatMessage(
3251
+ {
3252
+ id: "content-manager.components.ListViewHelperPluginTable.row-line",
3253
+ defaultMessage: "item line {number}"
3254
+ },
3255
+ { number: index2 + 1 }
3256
+ )
3257
+ }
3258
+ ),
3259
+ target: "_blank",
3260
+ marginLeft: "auto",
3261
+ variant: "ghost",
3262
+ children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
3263
+ }
3264
+ ) }) })
3265
+ ] }, row.id)) })
3266
+ ] });
3267
+ };
3268
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
3269
+ const SelectedEntriesModalContent = ({
3270
+ listViewSelectedEntries,
3271
+ toggleModal,
3272
+ setListViewSelectedDocuments,
3273
+ model
3274
+ }) => {
3275
+ const { formatMessage } = useIntl();
3276
+ const { schema, components } = useContentTypeSchema(model);
3277
+ const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
3278
+ const [{ query }] = useQueryParams();
3279
+ const params = React.useMemo(() => buildValidParams(query), [query]);
3280
+ const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
3281
+ {
3282
+ model,
3283
+ params: {
3284
+ page: "1",
3285
+ pageSize: documentIds.length.toString(),
3286
+ sort: query.sort,
3287
+ filters: {
3288
+ documentId: {
3289
+ $in: documentIds
3290
+ }
3291
+ },
3292
+ locale: query.plugins?.i18n?.locale
3293
+ }
3294
+ },
3295
+ {
3296
+ selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
3297
+ }
3298
+ );
3299
+ const { rows, validationErrors } = React.useMemo(() => {
3300
+ if (data.length > 0 && schema) {
3301
+ const validate = createYupSchema(
3302
+ schema.attributes,
3303
+ components,
3304
+ // Since this is the "Publish" action, the validation
3305
+ // schema must enforce the rules for published entities
3306
+ { status: "published" }
3307
+ );
3308
+ const validationErrors2 = {};
3309
+ const rows2 = data.map((entry) => {
3310
+ try {
3311
+ validate.validateSync(entry, { abortEarly: false });
3312
+ return entry;
3313
+ } catch (e) {
3314
+ if (e instanceof ValidationError) {
3315
+ validationErrors2[entry.documentId] = getYupValidationErrors(e);
3316
+ }
3317
+ return entry;
3318
+ }
3319
+ });
3320
+ return { rows: rows2, validationErrors: validationErrors2 };
3321
+ }
3322
+ return {
3323
+ rows: [],
3324
+ validationErrors: {}
3325
+ };
3326
+ }, [components, data, schema]);
3327
+ const [publishedCount, setPublishedCount] = React.useState(0);
3328
+ const [isDialogOpen, setIsDialogOpen] = React.useState(false);
3329
+ const { publishMany: bulkPublishAction } = useDocumentActions();
3330
+ const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
3331
+ const selectedRows = useTable("publishAction", (state) => state.selectedRows);
3332
+ const selectedEntries = rows.filter(
3333
+ (entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
3334
+ );
3335
+ const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
3336
+ const selectedEntriesWithErrorsCount = selectedEntries.filter(
3337
+ ({ documentId }) => validationErrors[documentId]
3338
+ ).length;
3339
+ const selectedEntriesPublished = selectedEntries.filter(
3340
+ ({ status }) => status === "published"
3341
+ ).length;
3342
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3343
+ const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3344
+ const handleConfirmBulkPublish = async () => {
3345
+ toggleDialog();
3346
+ const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3347
+ if (!("error" in res)) {
3348
+ setPublishedCount(res.count);
3349
+ const unpublishedEntries = rows.filter((row) => {
3350
+ return !entriesToPublish.includes(row.documentId);
3351
+ });
3352
+ setListViewSelectedDocuments(unpublishedEntries);
3353
+ }
3354
+ };
3355
+ const getFormattedCountMessage = () => {
3356
+ if (publishedCount) {
3357
+ return formatMessage(
3358
+ {
3359
+ id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3360
+ 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."
3361
+ },
3362
+ {
3363
+ publishedCount,
3364
+ withErrorsCount: selectedEntriesWithErrorsCount,
3365
+ b: BoldChunk
3366
+ }
3367
+ );
3368
+ }
3369
+ return formatMessage(
3370
+ {
3371
+ id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3372
+ 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."
3373
+ },
3374
+ {
3375
+ readyToPublishCount: selectedEntriesWithNoErrorsCount,
3376
+ withErrorsCount: selectedEntriesWithErrorsCount,
3377
+ alreadyPublishedCount: selectedEntriesPublished,
3378
+ b: BoldChunk
3379
+ }
3380
+ );
3381
+ };
3382
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3383
+ /* @__PURE__ */ jsxs(Modal.Body, { children: [
3384
+ /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
3385
+ /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsx(
3386
+ SelectedEntriesTableContent,
3387
+ {
3388
+ isPublishing: isSubmittingForm,
3389
+ rowsToDisplay: rows,
3390
+ entriesToPublish,
3391
+ validationErrors
3392
+ }
3393
+ ) })
3394
+ ] }),
3395
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
3396
+ /* @__PURE__ */ jsx(Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
3397
+ id: "app.components.Button.cancel",
3398
+ defaultMessage: "Cancel"
3399
+ }) }),
3400
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3401
+ /* @__PURE__ */ jsx(Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
3402
+ /* @__PURE__ */ jsx(
3403
+ Button,
3404
+ {
3405
+ onClick: toggleDialog,
3406
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3407
+ loading: isSubmittingForm,
3408
+ children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3409
+ }
3410
+ )
3411
+ ] })
3412
+ ] }),
3413
+ /* @__PURE__ */ jsx(
3414
+ ConfirmDialogPublishAll,
3415
+ {
3416
+ isOpen: isDialogOpen,
3417
+ onToggleDialog: toggleDialog,
3418
+ isConfirmButtonLoading: isSubmittingForm,
3419
+ onConfirm: handleConfirmBulkPublish
3420
+ }
3421
+ )
3422
+ ] });
3423
+ };
3424
+ const PublishAction = ({ documents, model }) => {
3425
+ const { formatMessage } = useIntl();
3426
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3427
+ const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
3428
+ const setListViewSelectedDocuments = useTable("publishAction", (state) => state.selectRow);
3429
+ const refetchList = () => {
3430
+ contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3431
+ };
3432
+ if (!showPublishButton)
3433
+ return null;
3434
+ return {
3435
+ actionType: "publish",
3436
+ variant: "tertiary",
3437
+ label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
3438
+ dialog: {
3439
+ type: "modal",
3440
+ title: formatMessage({
3441
+ id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
3442
+ defaultMessage: "Publish entries"
3443
+ }),
3444
+ content: ({ onClose }) => {
3445
+ return /* @__PURE__ */ jsx(Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsx(
3446
+ SelectedEntriesModalContent,
3447
+ {
3448
+ listViewSelectedEntries: documents,
3449
+ toggleModal: () => {
3450
+ onClose();
3451
+ refetchList();
3452
+ },
3453
+ setListViewSelectedDocuments,
3454
+ model
3455
+ }
3456
+ ) });
3457
+ },
3458
+ onClose: () => {
3459
+ refetchList();
3460
+ }
3461
+ }
3462
+ };
3463
+ };
3464
+ const BulkActionsRenderer = () => {
3465
+ const plugins = useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
3466
+ const { model, collectionType } = useDoc();
3467
+ const { selectedRows } = useTable("BulkActionsRenderer", (state) => state);
3468
+ return /* @__PURE__ */ jsx(Flex, { gap: 2, children: /* @__PURE__ */ jsx(
3469
+ DescriptionComponentRenderer,
3470
+ {
3471
+ props: {
3472
+ model,
3473
+ collectionType,
3474
+ documents: selectedRows
3475
+ },
3476
+ descriptions: plugins["content-manager"].apis.getBulkActions(),
3477
+ children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsx(DocumentActionButton, { ...action }, action.id))
3478
+ }
3479
+ ) });
3480
+ };
3481
+ const DeleteAction = ({ documents, model }) => {
3482
+ const { formatMessage } = useIntl();
3483
+ const { schema: contentType } = useDoc();
3484
+ const selectRow = useTable("DeleteAction", (state) => state.selectRow);
3485
+ const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
3486
+ const [{ query }] = useQueryParams();
3487
+ const params = React.useMemo(() => buildValidParams(query), [query]);
3488
+ const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
3489
+ const { deleteMany: bulkDeleteAction } = useDocumentActions();
3490
+ const documentIds = documents.map(({ documentId }) => documentId);
3491
+ const handleConfirmBulkDelete = async () => {
3492
+ const res = await bulkDeleteAction({
3493
+ documentIds,
3494
+ model,
3495
+ params
3496
+ });
3497
+ if (!("error" in res)) {
3498
+ selectRow([]);
3499
+ }
3500
+ };
3501
+ if (!hasDeletePermission)
3502
+ return null;
3503
+ return {
3504
+ variant: "danger-light",
3505
+ label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
3506
+ dialog: {
3507
+ type: "dialog",
3508
+ title: formatMessage({
3509
+ id: "app.components.ConfirmDialog.title",
3510
+ defaultMessage: "Confirmation"
3511
+ }),
3512
+ content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3513
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3514
+ /* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3515
+ id: "popUpWarning.bodyMessage.contentType.delete.all",
3516
+ defaultMessage: "Are you sure you want to delete these entries?"
3517
+ }) }),
3518
+ hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
3519
+ {
3520
+ id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
3521
+ defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
3522
+ },
3523
+ {
3524
+ em: Emphasis
3525
+ }
3526
+ ) }) })
3527
+ ] }),
3528
+ onConfirm: handleConfirmBulkDelete
3529
+ }
3530
+ };
3531
+ };
3532
+ DeleteAction.type = "delete";
3533
+ const UnpublishAction = ({ documents, model }) => {
3534
+ const { formatMessage } = useIntl();
3535
+ const { schema } = useDoc();
3536
+ const selectRow = useTable("UnpublishAction", (state) => state.selectRow);
3537
+ const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
3538
+ const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
3539
+ const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
3540
+ const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
3541
+ const documentIds = documents.map(({ documentId }) => documentId);
3542
+ const [{ query }] = useQueryParams();
3543
+ const params = React.useMemo(() => buildValidParams(query), [query]);
3544
+ const handleConfirmBulkUnpublish = async () => {
3545
+ const data = await bulkUnpublishAction({ documentIds, model, params });
3546
+ if (!("error" in data)) {
3547
+ selectRow([]);
3548
+ }
3549
+ };
3550
+ const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3551
+ if (!showUnpublishButton)
3552
+ return null;
3553
+ return {
3554
+ variant: "tertiary",
3555
+ label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
3556
+ dialog: {
3557
+ type: "dialog",
3558
+ title: formatMessage({
3559
+ id: "app.components.ConfirmDialog.title",
3560
+ defaultMessage: "Confirmation"
3561
+ }),
3562
+ content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
3563
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
3564
+ /* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
3565
+ id: "popUpWarning.bodyMessage.contentType.unpublish.all",
3566
+ defaultMessage: "Are you sure you want to unpublish these entries?"
3567
+ }) }),
3568
+ hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
3569
+ {
3570
+ id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
3571
+ defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
3572
+ },
3573
+ {
3574
+ em: Emphasis
3575
+ }
3576
+ ) }) })
3577
+ ] }),
3578
+ confirmButton: formatMessage({
3579
+ id: "app.utils.unpublish",
3580
+ defaultMessage: "Unpublish"
3581
+ }),
3582
+ onConfirm: handleConfirmBulkUnpublish
3583
+ }
3584
+ };
3585
+ };
3586
+ UnpublishAction.type = "unpublish";
3587
+ const Emphasis = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
3588
+ const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
3589
+ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
3590
+ const { formatMessage } = useIntl();
3591
+ const getDefaultErrorMessage = (reason) => {
3592
+ switch (reason) {
3593
+ case "relation":
3594
+ return "Duplicating the relation could remove it from the original entry.";
3595
+ case "unique":
3596
+ return "Identical values in a unique field are not allowed";
3597
+ default:
3598
+ return reason;
3599
+ }
3600
+ };
3601
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3602
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", children: formatMessage({
2459
3603
  id: getTranslation("containers.list.autoCloneModal.title"),
2460
3604
  defaultMessage: "This entry can't be duplicated directly."
2461
3605
  }) }),
@@ -2473,7 +3617,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
2473
3617
  hasRadius: true,
2474
3618
  padding: 6,
2475
3619
  children: [
2476
- /* @__PURE__ */ jsx(Flex, { direction: "row", as: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxs(Typography, { fontWeight: "semiBold", as: "li", children: [
3620
+ /* @__PURE__ */ jsx(Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxs(Typography, { fontWeight: "semiBold", tag: "li", children: [
2477
3621
  pathSegment,
2478
3622
  index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsx(
2479
3623
  ChevronRight,
@@ -2485,7 +3629,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
2485
3629
  }
2486
3630
  )
2487
3631
  ] }, index2)) }),
2488
- /* @__PURE__ */ jsx(Typography, { as: "p", textColor: "neutral600", children: formatMessage({
3632
+ /* @__PURE__ */ jsx(Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
2489
3633
  id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
2490
3634
  defaultMessage: getDefaultErrorMessage(reason)
2491
3635
  }) })
@@ -2510,7 +3654,7 @@ const TableActions = ({ document }) => {
2510
3654
  DescriptionComponentRenderer,
2511
3655
  {
2512
3656
  props,
2513
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3657
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
2514
3658
  children: (actions2) => {
2515
3659
  const tableRowActions = actions2.filter((action) => {
2516
3660
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -2621,7 +3765,7 @@ const CloneAction = ({ model, documentId }) => {
2621
3765
  }),
2622
3766
  content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
2623
3767
  footer: ({ onClose }) => {
2624
- return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
3768
+ return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
2625
3769
  /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
2626
3770
  id: "cancel",
2627
3771
  defaultMessage: "Cancel"
@@ -2629,7 +3773,7 @@ const CloneAction = ({ model, documentId }) => {
2629
3773
  /* @__PURE__ */ jsx(
2630
3774
  LinkButton,
2631
3775
  {
2632
- as: NavLink,
3776
+ tag: NavLink,
2633
3777
  to: {
2634
3778
  pathname: `clone/${documentId}`
2635
3779
  },
@@ -2662,8 +3806,7 @@ class ContentManagerPlugin {
2662
3806
  documentActions = [
2663
3807
  ...DEFAULT_ACTIONS,
2664
3808
  ...DEFAULT_TABLE_ROW_ACTIONS,
2665
- ...DEFAULT_HEADER_ACTIONS,
2666
- HistoryAction
3809
+ ...DEFAULT_HEADER_ACTIONS
2667
3810
  ];
2668
3811
  editViewSidePanels = [ActionsPanel];
2669
3812
  headerActions = [];
@@ -2752,352 +3895,94 @@ const getPrintableType = (value) => {
2752
3895
  }
2753
3896
  return nativeType;
2754
3897
  };
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;
3898
+ const HistoryAction = ({ model, document }) => {
3899
+ const { formatMessage } = useIntl();
3900
+ const [{ query }] = useQueryParams();
3901
+ const navigate = useNavigate();
3902
+ const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
3903
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3904
+ return null;
2866
3905
  }
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
3906
  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
3907
+ icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
3908
+ label: formatMessage({
3909
+ id: "content-manager.history.document-action",
3910
+ defaultMessage: "Content History"
2930
3911
  }),
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;
2960
- } else {
2961
- if (!panels[currentPanelIndex]) {
2962
- panels.push([]);
2963
- }
2964
- panels[currentPanelIndex].push(row);
2965
- }
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
3007
- }
3912
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3913
+ disabled: (
3914
+ /**
3915
+ * The user is creating a new document.
3916
+ * It hasn't been saved yet, so there's no history to go to
3917
+ */
3918
+ !document || /**
3919
+ * The document has been created but the current dimension has never been saved.
3920
+ * For example, the user is creating a new locale in an existing document,
3921
+ * so there's no history for the document in that locale
3922
+ */
3923
+ !document.id || /**
3924
+ * History is only available for content types created by the user.
3925
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3926
+ * which start with `admin::` or `plugin::`
3927
+ */
3928
+ !model.startsWith("api::")
3929
+ ),
3930
+ position: "header"
3008
3931
  };
3009
3932
  };
3010
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
3011
- return rows.map(
3012
- (row) => row.map((field) => {
3013
- const attribute = attributes[field.name];
3014
- if (!attribute) {
3015
- return null;
3016
- }
3017
- const { edit: metadata } = metadatas[field.name];
3018
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
3019
- return {
3020
- attribute,
3021
- disabled: !metadata.editable,
3022
- hint: metadata.description,
3023
- label: metadata.label ?? "",
3024
- name: field.name,
3025
- // @ts-expect-error – mainField does exist on the metadata for a relation.
3026
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
3027
- schemas,
3028
- components: components?.schemas ?? {}
3029
- }),
3030
- placeholder: metadata.placeholder ?? "",
3031
- required: attribute.required ?? false,
3032
- size: field.size,
3033
- unique: "unique" in attribute ? attribute.unique : false,
3034
- visible: metadata.visible ?? true,
3035
- type: attribute.type
3036
- };
3037
- }).filter((field) => field !== null)
3038
- );
3933
+ HistoryAction.type = "history";
3934
+ const historyAdmin = {
3935
+ bootstrap(app) {
3936
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3937
+ addDocumentAction((actions2) => {
3938
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3939
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3940
+ return actions2;
3941
+ });
3942
+ }
3039
3943
  };
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
- );
3061
- 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
- }
3070
- };
3944
+ const initialState = {
3945
+ collectionTypeLinks: [],
3946
+ components: [],
3947
+ fieldSizes: {},
3948
+ models: [],
3949
+ singleTypeLinks: [],
3950
+ isLoading: true
3071
3951
  };
3072
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
3073
- return columns.map((name) => {
3074
- const attribute = attributes[name];
3075
- if (!attribute) {
3076
- return null;
3952
+ const appSlice = createSlice({
3953
+ name: "app",
3954
+ initialState,
3955
+ reducers: {
3956
+ setInitialData(state, action) {
3957
+ const {
3958
+ authorizedCollectionTypeLinks,
3959
+ authorizedSingleTypeLinks,
3960
+ components,
3961
+ contentTypeSchemas,
3962
+ fieldSizes
3963
+ } = action.payload;
3964
+ state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
3965
+ ({ isDisplayed }) => isDisplayed
3966
+ );
3967
+ state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
3968
+ state.components = components;
3969
+ state.models = contentTypeSchemas;
3970
+ state.fieldSizes = fieldSizes;
3971
+ state.isLoading = false;
3077
3972
  }
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);
3092
- };
3973
+ }
3974
+ });
3975
+ const { actions, reducer: reducer$1 } = appSlice;
3976
+ const { setInitialData } = actions;
3977
+ const reducer = combineReducers({
3978
+ app: reducer$1
3979
+ });
3093
3980
  const index = {
3094
3981
  register(app) {
3095
3982
  const cm = new ContentManagerPlugin();
3096
3983
  app.addReducers({
3097
- [contentManagerApi.reducerPath]: contentManagerApi.reducer,
3098
3984
  [PLUGIN_ID]: reducer
3099
3985
  });
3100
- app.addMiddlewares([() => contentManagerApi.middleware]);
3101
3986
  app.addMenuLink({
3102
3987
  to: PLUGIN_ID,
3103
3988
  icon: Feather,
@@ -3106,14 +3991,29 @@ const index = {
3106
3991
  defaultMessage: "Content Manager"
3107
3992
  },
3108
3993
  permissions: [],
3109
- Component: () => import("./layout-Dnh0PNp9.mjs").then((mod) => ({ default: mod.Layout }))
3994
+ position: 1
3995
+ });
3996
+ app.router.addRoute({
3997
+ path: "content-manager/*",
3998
+ lazy: async () => {
3999
+ const { Layout } = await import("./layout-ClP-DC72.mjs");
4000
+ return {
4001
+ Component: Layout
4002
+ };
4003
+ },
4004
+ children: routes
3110
4005
  });
3111
4006
  app.registerPlugin(cm.config);
3112
4007
  },
4008
+ bootstrap(app) {
4009
+ if (typeof historyAdmin.bootstrap === "function") {
4010
+ historyAdmin.bootstrap(app);
4011
+ }
4012
+ },
3113
4013
  async registerTrads({ locales }) {
3114
4014
  const importedTrads = await Promise.all(
3115
4015
  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 }) => {
4016
+ 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-C8YBvRrK.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
4017
  return {
3118
4018
  data: prefixPluginTranslations(data, PLUGIN_ID),
3119
4019
  locale
@@ -3131,45 +4031,47 @@ const index = {
3131
4031
  };
3132
4032
  export {
3133
4033
  ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD as A,
3134
- extractContentTypeComponents as B,
4034
+ BulkActionsRenderer as B,
3135
4035
  COLLECTION_TYPES as C,
3136
4036
  DocumentStatus as D,
3137
- DEFAULT_SETTINGS as E,
3138
- convertEditLayoutToFieldLayouts as F,
3139
- useDocument as G,
4037
+ extractContentTypeComponents as E,
4038
+ DEFAULT_SETTINGS as F,
4039
+ convertEditLayoutToFieldLayouts as G,
3140
4040
  HOOKS as H,
3141
4041
  InjectionZone as I,
3142
- index as J,
3143
- useDocumentActions as K,
4042
+ useDocument as J,
4043
+ index as K,
4044
+ useContentManagerContext as L,
4045
+ useDocumentActions as M,
3144
4046
  Panels as P,
3145
4047
  RelativeTime as R,
3146
4048
  SINGLE_TYPES as S,
3147
4049
  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,
4050
+ useGetInitialDataQuery as a,
4051
+ useGetAllContentTypeSettingsQuery as b,
4052
+ useDoc as c,
4053
+ buildValidParams as d,
4054
+ contentManagerApi as e,
4055
+ useDocumentRBAC as f,
3154
4056
  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,
3162
- useGetContentTypeConfigurationQuery as o,
3163
- CREATOR_FIELDS as p,
3164
- getMainField as q,
3165
- routes as r,
4057
+ useDocumentLayout as h,
4058
+ createYupSchema as i,
4059
+ Header as j,
4060
+ PERMISSIONS as k,
4061
+ DocumentRBAC as l,
4062
+ DOCUMENT_META_FIELDS as m,
4063
+ CLONE_PATH as n,
4064
+ useDocLayout as o,
4065
+ useGetContentTypeConfigurationQuery as p,
4066
+ CREATOR_FIELDS as q,
4067
+ getMainField as r,
3166
4068
  setInitialData as s,
3167
4069
  getDisplayName as t,
3168
- useGetInitialDataQuery as u,
4070
+ useContentTypeSchema as u,
3169
4071
  checkIfAttributeIsDisplayable as v,
3170
4072
  useGetAllDocumentsQuery as w,
3171
4073
  convertListLayoutToFieldLayouts as x,
3172
4074
  capitalise as y,
3173
4075
  useUpdateContentTypeConfigurationMutation as z
3174
4076
  };
3175
- //# sourceMappingURL=index-DNVx8ssZ.mjs.map
4077
+ //# sourceMappingURL=index-BmUAydCA.mjs.map