@strapi/content-manager 0.0.0-experimental.86fea32ae4240d73f76516d7238e302b6b927e88 → 0.0.0-experimental.8e4302929d7fe147203ed0266450d0a565c69660

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 (205) hide show
  1. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
  2. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-B2g3icXu.mjs → ComponentConfigurationPage-D4H-v0et.mjs} +4 -4
  4. package/dist/_chunks/{ComponentConfigurationPage-B2g3icXu.mjs.map → ComponentConfigurationPage-D4H-v0et.mjs.map} +1 -1
  5. package/dist/_chunks/{ComponentConfigurationPage-CzDn8Uxh.js → ComponentConfigurationPage-DdkVGfXC.js} +5 -6
  6. package/dist/_chunks/{ComponentConfigurationPage-CzDn8Uxh.js.map → ComponentConfigurationPage-DdkVGfXC.js.map} +1 -1
  7. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
  8. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
  9. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
  10. package/dist/_chunks/{EditConfigurationPage-DSA1zONV.mjs → EditConfigurationPage-D1nvB7Br.mjs} +4 -4
  11. package/dist/_chunks/{EditConfigurationPage-DSA1zONV.mjs.map → EditConfigurationPage-D1nvB7Br.mjs.map} +1 -1
  12. package/dist/_chunks/{EditConfigurationPage-Bcbi6r5y.js → EditConfigurationPage-LYEvR4fW.js} +5 -6
  13. package/dist/_chunks/{EditConfigurationPage-Bcbi6r5y.js.map → EditConfigurationPage-LYEvR4fW.js.map} +1 -1
  14. package/dist/_chunks/{EditViewPage-Ca2EmJpb.mjs → EditViewPage-Bcnff6Vd.mjs} +21 -54
  15. package/dist/_chunks/EditViewPage-Bcnff6Vd.mjs.map +1 -0
  16. package/dist/_chunks/{EditViewPage-BvcMXaP2.js → EditViewPage-DqelJ9UK.js} +23 -57
  17. package/dist/_chunks/EditViewPage-DqelJ9UK.js.map +1 -0
  18. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
  19. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
  20. package/dist/_chunks/{Form-DAUpPBVM.js → Form-CnHfBeiB.js} +5 -6
  21. package/dist/_chunks/{Form-DAUpPBVM.js.map → Form-CnHfBeiB.js.map} +1 -1
  22. package/dist/_chunks/{Form-BJVbU6w4.mjs → Form-CzPCJi3B.mjs} +3 -3
  23. package/dist/_chunks/{Form-BJVbU6w4.mjs.map → Form-CzPCJi3B.mjs.map} +1 -1
  24. package/dist/_chunks/{History-M6Pk9CoY.mjs → History-CcmSn3Mj.mjs} +51 -97
  25. package/dist/_chunks/History-CcmSn3Mj.mjs.map +1 -0
  26. package/dist/_chunks/{History-Bw9vfT1k.js → History-zArjENzj.js} +62 -109
  27. package/dist/_chunks/History-zArjENzj.js.map +1 -0
  28. package/dist/_chunks/{Field-CmaWxdpf.js → Input-CDHKQd7o.js} +1259 -1236
  29. package/dist/_chunks/Input-CDHKQd7o.js.map +1 -0
  30. package/dist/_chunks/{Field-BEYkgCZ0.mjs → Input-aV8SSoTa.mjs} +1334 -1311
  31. package/dist/_chunks/Input-aV8SSoTa.mjs.map +1 -0
  32. package/dist/_chunks/{ListConfigurationPage-D7ior2zq.mjs → ListConfigurationPage-BPvzENJJ.mjs} +7 -6
  33. package/dist/_chunks/ListConfigurationPage-BPvzENJJ.mjs.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-DBVqF5fc.js → ListConfigurationPage-ByZAO_9H.js} +7 -7
  35. package/dist/_chunks/ListConfigurationPage-ByZAO_9H.js.map +1 -0
  36. package/dist/_chunks/{ListViewPage-MZu-8OKX.js → ListViewPage-BVKBeQAA.js} +73 -48
  37. package/dist/_chunks/ListViewPage-BVKBeQAA.js.map +1 -0
  38. package/dist/_chunks/{ListViewPage-BH37wONY.mjs → ListViewPage-HljQVnFH.mjs} +67 -41
  39. package/dist/_chunks/ListViewPage-HljQVnFH.mjs.map +1 -0
  40. package/dist/_chunks/{NoContentTypePage-C9lRMTCa.js → NoContentTypePage-BV5zfDxr.js} +2 -2
  41. package/dist/_chunks/{NoContentTypePage-C9lRMTCa.js.map → NoContentTypePage-BV5zfDxr.js.map} +1 -1
  42. package/dist/_chunks/{NoContentTypePage-DRp7Aem_.mjs → NoContentTypePage-BfHaSM-K.mjs} +2 -2
  43. package/dist/_chunks/{NoContentTypePage-DRp7Aem_.mjs.map → NoContentTypePage-BfHaSM-K.mjs.map} +1 -1
  44. package/dist/_chunks/{NoPermissionsPage-CzhRt5CA.mjs → NoPermissionsPage-D6ze2nQL.mjs} +2 -2
  45. package/dist/_chunks/{NoPermissionsPage-CzhRt5CA.mjs.map → NoPermissionsPage-D6ze2nQL.mjs.map} +1 -1
  46. package/dist/_chunks/{NoPermissionsPage-COs61PpB.js → NoPermissionsPage-vdNpc6jb.js} +2 -2
  47. package/dist/_chunks/{NoPermissionsPage-COs61PpB.js.map → NoPermissionsPage-vdNpc6jb.js.map} +1 -1
  48. package/dist/_chunks/Preview-DEHdENT1.js +305 -0
  49. package/dist/_chunks/Preview-DEHdENT1.js.map +1 -0
  50. package/dist/_chunks/Preview-vfWOtPG5.mjs +287 -0
  51. package/dist/_chunks/Preview-vfWOtPG5.mjs.map +1 -0
  52. package/dist/_chunks/{Relations-68XxIzPI.mjs → Relations-B7_hbF0w.mjs} +33 -19
  53. package/dist/_chunks/Relations-B7_hbF0w.mjs.map +1 -0
  54. package/dist/_chunks/{Relations-CsGlulU_.js → Relations-DcoOBejP.js} +33 -20
  55. package/dist/_chunks/Relations-DcoOBejP.js.map +1 -0
  56. package/dist/_chunks/{en-Bm0D0IWz.js → en-BR48D_RH.js} +23 -4
  57. package/dist/_chunks/{en-Bm0D0IWz.js.map → en-BR48D_RH.js.map} +1 -1
  58. package/dist/_chunks/{en-DKV44jRb.mjs → en-D65uIF6Y.mjs} +23 -4
  59. package/dist/_chunks/{en-DKV44jRb.mjs.map → en-D65uIF6Y.mjs.map} +1 -1
  60. package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
  61. package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
  62. package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
  63. package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
  64. package/dist/_chunks/{fr-B7kGGg3E.js → fr-C43IbhA_.js} +16 -3
  65. package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-C43IbhA_.js.map} +1 -1
  66. package/dist/_chunks/{fr-CD9VFbPM.mjs → fr-DBseuRuB.mjs} +16 -3
  67. package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr-DBseuRuB.mjs.map} +1 -1
  68. package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
  69. package/dist/_chunks/{index-oDq3VO9j.js → index-CxLSGwnk.js} +614 -237
  70. package/dist/_chunks/index-CxLSGwnk.js.map +1 -0
  71. package/dist/_chunks/{index-CsfwpRfc.mjs → index-EH8ZtHd5.mjs} +631 -253
  72. package/dist/_chunks/index-EH8ZtHd5.mjs.map +1 -0
  73. package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
  74. package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
  75. package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
  76. package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
  77. package/dist/_chunks/{layout-C5uSVTqi.mjs → layout-CxDMdJ13.mjs} +4 -4
  78. package/dist/_chunks/{layout-C5uSVTqi.mjs.map → layout-CxDMdJ13.mjs.map} +1 -1
  79. package/dist/_chunks/{layout-Euka-kfv.js → layout-DSeUTfMv.js} +5 -6
  80. package/dist/_chunks/{layout-Euka-kfv.js.map → layout-DSeUTfMv.js.map} +1 -1
  81. package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
  82. package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
  83. package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
  84. package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
  85. package/dist/_chunks/{relations-BpHVgFuV.mjs → relations-B8_Uu38Q.mjs} +21 -8
  86. package/dist/_chunks/relations-B8_Uu38Q.mjs.map +1 -0
  87. package/dist/_chunks/{relations-DG7kmxa0.js → relations-S5nNKdN3.js} +20 -7
  88. package/dist/_chunks/relations-S5nNKdN3.js.map +1 -0
  89. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
  90. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
  91. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
  92. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
  93. package/dist/_chunks/{useDebounce-CtcjDB3L.js → usePrev-B9w_-eYc.js} +1 -14
  94. package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -0
  95. package/dist/_chunks/usePrev-DH6iah0A.mjs +16 -0
  96. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +1 -0
  97. package/dist/admin/index.js +2 -1
  98. package/dist/admin/index.js.map +1 -1
  99. package/dist/admin/index.mjs +6 -5
  100. package/dist/admin/src/content-manager.d.ts +3 -2
  101. package/dist/admin/src/exports.d.ts +1 -0
  102. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  103. package/dist/admin/src/hooks/useDocument.d.ts +19 -2
  104. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  105. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -1
  106. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +3 -3
  107. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
  108. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
  109. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
  110. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +4 -1
  111. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +4 -1
  112. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +27 -0
  113. package/dist/admin/src/pages/EditView/utils/data.d.ts +1 -0
  114. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  115. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  116. package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
  117. package/dist/admin/src/preview/index.d.ts +4 -0
  118. package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
  119. package/dist/admin/src/preview/routes.d.ts +3 -0
  120. package/dist/admin/src/preview/services/preview.d.ts +3 -0
  121. package/dist/admin/src/router.d.ts +1 -1
  122. package/dist/admin/src/services/api.d.ts +1 -1
  123. package/dist/admin/src/services/components.d.ts +2 -2
  124. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  125. package/dist/admin/src/services/documents.d.ts +16 -19
  126. package/dist/admin/src/services/init.d.ts +1 -1
  127. package/dist/admin/src/services/relations.d.ts +2 -2
  128. package/dist/admin/src/services/uid.d.ts +3 -3
  129. package/dist/server/index.js +561 -323
  130. package/dist/server/index.js.map +1 -1
  131. package/dist/server/index.mjs +562 -323
  132. package/dist/server/index.mjs.map +1 -1
  133. package/dist/server/src/bootstrap.d.ts.map +1 -1
  134. package/dist/server/src/controllers/index.d.ts.map +1 -1
  135. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  136. package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
  137. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  138. package/dist/server/src/history/controllers/history-version.d.ts +1 -1
  139. package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
  140. package/dist/server/src/history/services/history.d.ts +3 -3
  141. package/dist/server/src/history/services/history.d.ts.map +1 -1
  142. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  143. package/dist/server/src/history/services/utils.d.ts +6 -11
  144. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  145. package/dist/server/src/index.d.ts +7 -6
  146. package/dist/server/src/index.d.ts.map +1 -1
  147. package/dist/server/src/preview/controllers/index.d.ts +2 -0
  148. package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
  149. package/dist/server/src/preview/controllers/preview.d.ts +13 -0
  150. package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
  151. package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
  152. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
  153. package/dist/server/src/preview/index.d.ts +4 -0
  154. package/dist/server/src/preview/index.d.ts.map +1 -0
  155. package/dist/server/src/preview/routes/index.d.ts +8 -0
  156. package/dist/server/src/preview/routes/index.d.ts.map +1 -0
  157. package/dist/server/src/preview/routes/preview.d.ts +4 -0
  158. package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
  159. package/dist/server/src/preview/services/index.d.ts +16 -0
  160. package/dist/server/src/preview/services/index.d.ts.map +1 -0
  161. package/dist/server/src/preview/services/preview-config.d.ts +32 -0
  162. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
  163. package/dist/server/src/preview/services/preview.d.ts +12 -0
  164. package/dist/server/src/preview/services/preview.d.ts.map +1 -0
  165. package/dist/server/src/preview/utils.d.ts +19 -0
  166. package/dist/server/src/preview/utils.d.ts.map +1 -0
  167. package/dist/server/src/register.d.ts.map +1 -1
  168. package/dist/server/src/routes/index.d.ts.map +1 -1
  169. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  170. package/dist/server/src/services/document-metadata.d.ts +12 -10
  171. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  172. package/dist/server/src/services/index.d.ts +7 -6
  173. package/dist/server/src/services/index.d.ts.map +1 -1
  174. package/dist/server/src/services/utils/populate.d.ts +2 -2
  175. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  176. package/dist/server/src/utils/index.d.ts +2 -0
  177. package/dist/server/src/utils/index.d.ts.map +1 -1
  178. package/dist/shared/contracts/index.d.ts +1 -0
  179. package/dist/shared/contracts/index.d.ts.map +1 -1
  180. package/dist/shared/contracts/preview.d.ts +27 -0
  181. package/dist/shared/contracts/preview.d.ts.map +1 -0
  182. package/dist/shared/index.js +4 -0
  183. package/dist/shared/index.js.map +1 -1
  184. package/dist/shared/index.mjs +4 -0
  185. package/dist/shared/index.mjs.map +1 -1
  186. package/package.json +13 -12
  187. package/dist/_chunks/EditViewPage-BvcMXaP2.js.map +0 -1
  188. package/dist/_chunks/EditViewPage-Ca2EmJpb.mjs.map +0 -1
  189. package/dist/_chunks/Field-BEYkgCZ0.mjs.map +0 -1
  190. package/dist/_chunks/Field-CmaWxdpf.js.map +0 -1
  191. package/dist/_chunks/History-Bw9vfT1k.js.map +0 -1
  192. package/dist/_chunks/History-M6Pk9CoY.mjs.map +0 -1
  193. package/dist/_chunks/ListConfigurationPage-D7ior2zq.mjs.map +0 -1
  194. package/dist/_chunks/ListConfigurationPage-DBVqF5fc.js.map +0 -1
  195. package/dist/_chunks/ListViewPage-BH37wONY.mjs.map +0 -1
  196. package/dist/_chunks/ListViewPage-MZu-8OKX.js.map +0 -1
  197. package/dist/_chunks/Relations-68XxIzPI.mjs.map +0 -1
  198. package/dist/_chunks/Relations-CsGlulU_.js.map +0 -1
  199. package/dist/_chunks/index-CsfwpRfc.mjs.map +0 -1
  200. package/dist/_chunks/index-oDq3VO9j.js.map +0 -1
  201. package/dist/_chunks/relations-BpHVgFuV.mjs.map +0 -1
  202. package/dist/_chunks/relations-DG7kmxa0.js.map +0 -1
  203. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +0 -1
  204. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +0 -29
  205. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +0 -1
@@ -1,26 +1,34 @@
1
- import { More, Cross, WarningCircle, ListPlus, Pencil, Trash, Check, CrossCircle, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, Feather } from "@strapi/icons";
1
+ import { More, Cross, WarningCircle, ListPlus, Pencil, Trash, Check, CheckCircle, ArrowsCounterClockwise, CrossCircle, ChevronRight, Duplicate, ClockCounterClockwise, Feather } from "@strapi/icons";
2
2
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
3
3
  import { useStrapiApp, createContext, useQueryParams, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useForm, useTracking, useGuidedTour, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
4
4
  import * as React from "react";
5
5
  import { lazy } from "react";
6
- import { Button, Menu, VisuallyHidden, Flex, Typography, Dialog, Modal, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
6
+ import { Menu, Button, VisuallyHidden, Flex, Dialog, Modal, Typography, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, RawTable, Loader, Tbody, Tr, Td, Tooltip, LinkButton } from "@strapi/design-system";
7
7
  import mapValues from "lodash/fp/mapValues";
8
8
  import { useIntl } from "react-intl";
9
9
  import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
10
+ import { styled } from "styled-components";
10
11
  import * as yup from "yup";
11
12
  import { ValidationError } from "yup";
13
+ import { generateNKeysBetween } from "fractional-indexing";
12
14
  import pipe from "lodash/fp/pipe";
13
- import { intervalToDuration, isPast } from "date-fns";
14
- import { styled } from "styled-components";
15
15
  import { stringify } from "qs";
16
+ import { intervalToDuration, isPast } from "date-fns";
16
17
  import { createSlice, combineReducers } from "@reduxjs/toolkit";
17
- const __variableDynamicImportRuntimeHelper = (glob, path) => {
18
+ const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
18
19
  const v = glob[path];
19
20
  if (v) {
20
21
  return typeof v === "function" ? v() : Promise.resolve(v);
21
22
  }
22
23
  return new Promise((_, reject) => {
23
- (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(reject.bind(null, new Error("Unknown variable dynamic import: " + path)));
24
+ (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
25
+ reject.bind(
26
+ null,
27
+ new Error(
28
+ "Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
29
+ )
30
+ )
31
+ );
24
32
  });
25
33
  };
26
34
  const PLUGIN_ID = "content-manager";
@@ -159,6 +167,113 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
159
167
  (field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
160
168
  );
161
169
  const removeNumericalStrings = (arr) => arr.filter((item) => isNaN(Number(item)));
170
+ const BLOCK_LIST_ATTRIBUTE_KEYS = ["__component", "__temp_key__"];
171
+ const traverseData = (predicate, transform) => (schema, components = {}) => (data = {}) => {
172
+ const traverse = (datum, attributes) => {
173
+ return Object.entries(datum).reduce((acc, [key, value]) => {
174
+ const attribute = attributes[key];
175
+ if (BLOCK_LIST_ATTRIBUTE_KEYS.includes(key) || value === null || value === void 0) {
176
+ acc[key] = value;
177
+ return acc;
178
+ }
179
+ if (attribute.type === "component") {
180
+ if (attribute.repeatable) {
181
+ const componentValue = predicate(attribute, value) ? transform(value, attribute) : value;
182
+ acc[key] = componentValue.map(
183
+ (componentData) => traverse(componentData, components[attribute.component]?.attributes ?? {})
184
+ );
185
+ } else {
186
+ const componentValue = predicate(attribute, value) ? transform(value, attribute) : value;
187
+ acc[key] = traverse(componentValue, components[attribute.component]?.attributes ?? {});
188
+ }
189
+ } else if (attribute.type === "dynamiczone") {
190
+ const dynamicZoneValue = predicate(attribute, value) ? transform(value, attribute) : value;
191
+ acc[key] = dynamicZoneValue.map(
192
+ (componentData) => traverse(componentData, components[componentData.__component]?.attributes ?? {})
193
+ );
194
+ } else if (predicate(attribute, value)) {
195
+ acc[key] = transform(value, attribute);
196
+ } else {
197
+ acc[key] = value;
198
+ }
199
+ return acc;
200
+ }, {});
201
+ };
202
+ return traverse(data, schema.attributes);
203
+ };
204
+ const removeProhibitedFields = (prohibitedFields) => traverseData(
205
+ (attribute) => prohibitedFields.includes(attribute.type),
206
+ () => ""
207
+ );
208
+ const prepareRelations = traverseData(
209
+ (attribute) => attribute.type === "relation",
210
+ () => ({
211
+ connect: [],
212
+ disconnect: []
213
+ })
214
+ );
215
+ const prepareTempKeys = traverseData(
216
+ (attribute) => attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone",
217
+ (data) => {
218
+ if (Array.isArray(data) && data.length > 0) {
219
+ const keys = generateNKeysBetween(void 0, void 0, data.length);
220
+ return data.map((datum, index2) => ({
221
+ ...datum,
222
+ __temp_key__: keys[index2]
223
+ }));
224
+ }
225
+ return data;
226
+ }
227
+ );
228
+ const removeFieldsThatDontExistOnSchema = (schema) => (data) => {
229
+ const schemaKeys = Object.keys(schema.attributes);
230
+ const dataKeys = Object.keys(data);
231
+ const keysToRemove = dataKeys.filter((key) => !schemaKeys.includes(key));
232
+ const revisedData = [...keysToRemove, ...DOCUMENT_META_FIELDS].reduce((acc, key) => {
233
+ delete acc[key];
234
+ return acc;
235
+ }, structuredClone(data));
236
+ return revisedData;
237
+ };
238
+ const removeNullValues = (data) => {
239
+ return Object.entries(data).reduce((acc, [key, value]) => {
240
+ if (value === null) {
241
+ return acc;
242
+ }
243
+ acc[key] = value;
244
+ return acc;
245
+ }, {});
246
+ };
247
+ const transformDocument = (schema, components = {}) => (document) => {
248
+ const transformations = pipe(
249
+ removeFieldsThatDontExistOnSchema(schema),
250
+ removeProhibitedFields(["password"])(schema, components),
251
+ removeNullValues,
252
+ prepareRelations(schema, components),
253
+ prepareTempKeys(schema, components)
254
+ );
255
+ return transformations(document);
256
+ };
257
+ const createDefaultForm = (contentType, components = {}) => {
258
+ const traverseSchema = (attributes) => {
259
+ return Object.entries(attributes).reduce((acc, [key, attribute]) => {
260
+ if ("default" in attribute) {
261
+ acc[key] = attribute.default;
262
+ } else if (attribute.type === "component" && attribute.required) {
263
+ const defaultComponentForm = traverseSchema(components[attribute.component].attributes);
264
+ if (attribute.repeatable) {
265
+ acc[key] = attribute.min ? [...Array(attribute.min).fill(defaultComponentForm)] : [];
266
+ } else {
267
+ acc[key] = defaultComponentForm;
268
+ }
269
+ } else if (attribute.type === "dynamiczone" && attribute.required) {
270
+ acc[key] = [];
271
+ }
272
+ return acc;
273
+ }, {});
274
+ };
275
+ return traverseSchema(contentType.attributes);
276
+ };
162
277
  const contentManagerApi = adminApi.enhanceEndpoints({
163
278
  addTagTypes: [
164
279
  "ComponentConfiguration",
@@ -168,7 +283,8 @@ const contentManagerApi = adminApi.enhanceEndpoints({
168
283
  "InitialData",
169
284
  "HistoryVersion",
170
285
  "Relations",
171
- "UidAvailability"
286
+ "UidAvailability",
287
+ "RecentDocumentList"
172
288
  ]
173
289
  });
174
290
  const documentApi = contentManagerApi.injectEndpoints({
@@ -186,7 +302,7 @@ const documentApi = contentManagerApi.injectEndpoints({
186
302
  if (error) {
187
303
  return [];
188
304
  }
189
- return [{ type: "Document", id: `${model}_LIST` }];
305
+ return [{ type: "Document", id: `${model}_LIST` }, "RecentDocumentList"];
190
306
  }
191
307
  }),
192
308
  cloneDocument: builder.mutation({
@@ -200,7 +316,8 @@ const documentApi = contentManagerApi.injectEndpoints({
200
316
  }),
201
317
  invalidatesTags: (_result, _error, { model }) => [
202
318
  { type: "Document", id: `${model}_LIST` },
203
- { type: "UidAvailability", id: model }
319
+ { type: "UidAvailability", id: model },
320
+ "RecentDocumentList"
204
321
  ]
205
322
  }),
206
323
  /**
@@ -219,8 +336,21 @@ const documentApi = contentManagerApi.injectEndpoints({
219
336
  invalidatesTags: (result, _error, { model }) => [
220
337
  { type: "Document", id: `${model}_LIST` },
221
338
  "Relations",
222
- { type: "UidAvailability", id: model }
223
- ]
339
+ { type: "UidAvailability", id: model },
340
+ "RecentDocumentList"
341
+ ],
342
+ transformResponse: (response, meta, arg) => {
343
+ if (!("data" in response) && arg.model === "plugin::users-permissions.user") {
344
+ return {
345
+ data: response,
346
+ meta: {
347
+ availableStatus: [],
348
+ availableLocales: []
349
+ }
350
+ };
351
+ }
352
+ return response;
353
+ }
224
354
  }),
225
355
  deleteDocument: builder.mutation({
226
356
  query: ({ collectionType, model, documentId, params }) => ({
@@ -231,7 +361,8 @@ const documentApi = contentManagerApi.injectEndpoints({
231
361
  }
232
362
  }),
233
363
  invalidatesTags: (_result, _error, { collectionType, model }) => [
234
- { type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model }
364
+ { type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model },
365
+ "RecentDocumentList"
235
366
  ]
236
367
  }),
237
368
  deleteManyDocuments: builder.mutation({
@@ -243,7 +374,10 @@ const documentApi = contentManagerApi.injectEndpoints({
243
374
  params
244
375
  }
245
376
  }),
246
- invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
377
+ invalidatesTags: (_res, _error, { model }) => [
378
+ { type: "Document", id: `${model}_LIST` },
379
+ "RecentDocumentList"
380
+ ]
247
381
  }),
248
382
  discardDocument: builder.mutation({
249
383
  query: ({ collectionType, model, documentId, params }) => ({
@@ -261,7 +395,8 @@ const documentApi = contentManagerApi.injectEndpoints({
261
395
  },
262
396
  { type: "Document", id: `${model}_LIST` },
263
397
  "Relations",
264
- { type: "UidAvailability", id: model }
398
+ { type: "UidAvailability", id: model },
399
+ "RecentDocumentList"
265
400
  ];
266
401
  }
267
402
  }),
@@ -274,7 +409,7 @@ const documentApi = contentManagerApi.injectEndpoints({
274
409
  url: `/content-manager/collection-types/${model}`,
275
410
  method: "GET",
276
411
  config: {
277
- params
412
+ params: stringify(params, { encode: true })
278
413
  }
279
414
  }),
280
415
  providesTags: (result, _error, arg) => {
@@ -356,7 +491,8 @@ const documentApi = contentManagerApi.injectEndpoints({
356
491
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
357
492
  },
358
493
  { type: "Document", id: `${model}_LIST` },
359
- "Relations"
494
+ "Relations",
495
+ "RecentDocumentList"
360
496
  ];
361
497
  }
362
498
  }),
@@ -387,7 +523,9 @@ const documentApi = contentManagerApi.injectEndpoints({
387
523
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
388
524
  },
389
525
  "Relations",
390
- { type: "UidAvailability", id: model }
526
+ { type: "UidAvailability", id: model },
527
+ "RecentDocumentList",
528
+ "RecentDocumentList"
391
529
  ];
392
530
  },
393
531
  async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
@@ -417,7 +555,8 @@ const documentApi = contentManagerApi.injectEndpoints({
417
555
  {
418
556
  type: "Document",
419
557
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
420
- }
558
+ },
559
+ "RecentDocumentList"
421
560
  ];
422
561
  }
423
562
  }),
@@ -430,7 +569,10 @@ const documentApi = contentManagerApi.injectEndpoints({
430
569
  params
431
570
  }
432
571
  }),
433
- invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
572
+ invalidatesTags: (_res, _error, { model, documentIds }) => [
573
+ ...documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` })),
574
+ "RecentDocumentList"
575
+ ]
434
576
  })
435
577
  })
436
578
  });
@@ -453,8 +595,7 @@ const {
453
595
  useUnpublishManyDocumentsMutation
454
596
  } = documentApi;
455
597
  const buildValidParams = (query) => {
456
- if (!query)
457
- return query;
598
+ if (!query) return query;
458
599
  const { plugins: _, ...validQueryParams } = {
459
600
  ...query,
460
601
  ...Object.values(query?.plugins ?? {}).reduce(
@@ -462,9 +603,6 @@ const buildValidParams = (query) => {
462
603
  {}
463
604
  )
464
605
  };
465
- if ("_q" in validQueryParams) {
466
- validQueryParams._q = encodeURIComponent(validQueryParams._q);
467
- }
468
606
  return validQueryParams;
469
607
  };
470
608
  const isBaseQueryError = (error) => {
@@ -969,9 +1107,10 @@ const formatEditLayout = (data, {
969
1107
  currentPanelIndex += 2;
970
1108
  } else {
971
1109
  if (!panels[currentPanelIndex]) {
972
- panels.push([]);
1110
+ panels.push([row]);
1111
+ } else {
1112
+ panels[currentPanelIndex].push(row);
973
1113
  }
974
- panels[currentPanelIndex].push(row);
975
1114
  }
976
1115
  return panels;
977
1116
  }, []);
@@ -1104,6 +1243,7 @@ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, co
1104
1243
  const useDocument = (args, opts) => {
1105
1244
  const { toggleNotification } = useNotification();
1106
1245
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
1246
+ const { formatMessage } = useIntl();
1107
1247
  const {
1108
1248
  currentData: data,
1109
1249
  isLoading: isLoadingDocument,
@@ -1113,12 +1253,27 @@ const useDocument = (args, opts) => {
1113
1253
  ...opts,
1114
1254
  skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1115
1255
  });
1256
+ const document = data?.data;
1257
+ const meta = data?.meta;
1116
1258
  const {
1117
1259
  components,
1118
1260
  schema,
1119
1261
  schemas,
1120
1262
  isLoading: isLoadingSchema
1121
1263
  } = useContentTypeSchema(args.model);
1264
+ const isSingleType = schema?.kind === "singleType";
1265
+ const getTitle = (mainField) => {
1266
+ if (mainField !== "id" && document?.[mainField]) {
1267
+ return document[mainField];
1268
+ }
1269
+ if (isSingleType && schema?.info.displayName) {
1270
+ return schema.info.displayName;
1271
+ }
1272
+ return formatMessage({
1273
+ id: "content-manager.containers.untitled",
1274
+ defaultMessage: "Untitled"
1275
+ });
1276
+ };
1122
1277
  React.useEffect(() => {
1123
1278
  if (error) {
1124
1279
  toggleNotification({
@@ -1134,14 +1289,14 @@ const useDocument = (args, opts) => {
1134
1289
  return createYupSchema(schema.attributes, components);
1135
1290
  }, [schema, components]);
1136
1291
  const validate = React.useCallback(
1137
- (document) => {
1292
+ (document2) => {
1138
1293
  if (!validationSchema) {
1139
1294
  throw new Error(
1140
1295
  "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1141
1296
  );
1142
1297
  }
1143
1298
  try {
1144
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
1299
+ validationSchema.validateSync(document2, { abortEarly: false, strict: true });
1145
1300
  return null;
1146
1301
  } catch (error2) {
1147
1302
  if (error2 instanceof ValidationError) {
@@ -1152,17 +1307,29 @@ const useDocument = (args, opts) => {
1152
1307
  },
1153
1308
  [validationSchema]
1154
1309
  );
1310
+ const getInitialFormValues = React.useCallback(
1311
+ (isCreatingDocument = false) => {
1312
+ if (!document && !isCreatingDocument && !isSingleType || !schema) {
1313
+ return void 0;
1314
+ }
1315
+ const form = document?.id ? document : createDefaultForm(schema, components);
1316
+ return transformDocument(schema, components)(form);
1317
+ },
1318
+ [document, isSingleType, schema, components]
1319
+ );
1155
1320
  const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1156
1321
  const hasError = !!error;
1157
1322
  return {
1158
1323
  components,
1159
- document: data?.data,
1160
- meta: data?.meta,
1324
+ document,
1325
+ meta,
1161
1326
  isLoading,
1162
1327
  hasError,
1163
1328
  schema,
1164
1329
  schemas,
1165
- validate
1330
+ validate,
1331
+ getTitle,
1332
+ getInitialFormValues
1166
1333
  };
1167
1334
  };
1168
1335
  const useDoc = () => {
@@ -1229,9 +1396,6 @@ const useContentManagerContext = () => {
1229
1396
  };
1230
1397
  };
1231
1398
  const prefixPluginTranslations = (trad, pluginId) => {
1232
- if (!pluginId) {
1233
- throw new TypeError("pluginId can't be empty");
1234
- }
1235
1399
  return Object.keys(trad).reduce((acc, current) => {
1236
1400
  acc[`${pluginId}.${current}`] = trad[current];
1237
1401
  return acc;
@@ -1665,10 +1829,10 @@ const useDocumentActions = () => {
1665
1829
  update
1666
1830
  };
1667
1831
  };
1668
- const ProtectedHistoryPage = lazy(
1669
- () => import("./History-M6Pk9CoY.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1832
+ const ProtectedHistoryPage = React.lazy(
1833
+ () => import("./History-CcmSn3Mj.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1670
1834
  );
1671
- const routes$1 = [
1835
+ const routes$2 = [
1672
1836
  {
1673
1837
  path: ":collectionType/:slug/:id/history",
1674
1838
  Component: ProtectedHistoryPage
@@ -1678,32 +1842,45 @@ const routes$1 = [
1678
1842
  Component: ProtectedHistoryPage
1679
1843
  }
1680
1844
  ];
1845
+ const ProtectedPreviewPage = React.lazy(
1846
+ () => import("./Preview-vfWOtPG5.mjs").then((mod) => ({ default: mod.ProtectedPreviewPage }))
1847
+ );
1848
+ const routes$1 = [
1849
+ {
1850
+ path: ":collectionType/:slug/:id/preview",
1851
+ Component: ProtectedPreviewPage
1852
+ },
1853
+ {
1854
+ path: ":collectionType/:slug/preview",
1855
+ Component: ProtectedPreviewPage
1856
+ }
1857
+ ];
1681
1858
  const ProtectedEditViewPage = lazy(
1682
- () => import("./EditViewPage-Ca2EmJpb.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1859
+ () => import("./EditViewPage-Bcnff6Vd.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1683
1860
  );
1684
1861
  const ProtectedListViewPage = lazy(
1685
- () => import("./ListViewPage-BH37wONY.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1862
+ () => import("./ListViewPage-HljQVnFH.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1686
1863
  );
1687
1864
  const ProtectedListConfiguration = lazy(
1688
- () => import("./ListConfigurationPage-D7ior2zq.mjs").then((mod) => ({
1865
+ () => import("./ListConfigurationPage-BPvzENJJ.mjs").then((mod) => ({
1689
1866
  default: mod.ProtectedListConfiguration
1690
1867
  }))
1691
1868
  );
1692
1869
  const ProtectedEditConfigurationPage = lazy(
1693
- () => import("./EditConfigurationPage-DSA1zONV.mjs").then((mod) => ({
1870
+ () => import("./EditConfigurationPage-D1nvB7Br.mjs").then((mod) => ({
1694
1871
  default: mod.ProtectedEditConfigurationPage
1695
1872
  }))
1696
1873
  );
1697
1874
  const ProtectedComponentConfigurationPage = lazy(
1698
- () => import("./ComponentConfigurationPage-B2g3icXu.mjs").then((mod) => ({
1875
+ () => import("./ComponentConfigurationPage-D4H-v0et.mjs").then((mod) => ({
1699
1876
  default: mod.ProtectedComponentConfigurationPage
1700
1877
  }))
1701
1878
  );
1702
1879
  const NoPermissions = lazy(
1703
- () => import("./NoPermissionsPage-CzhRt5CA.mjs").then((mod) => ({ default: mod.NoPermissions }))
1880
+ () => import("./NoPermissionsPage-D6ze2nQL.mjs").then((mod) => ({ default: mod.NoPermissions }))
1704
1881
  );
1705
1882
  const NoContentType = lazy(
1706
- () => import("./NoContentTypePage-DRp7Aem_.mjs").then((mod) => ({ default: mod.NoContentType }))
1883
+ () => import("./NoContentTypePage-BfHaSM-K.mjs").then((mod) => ({ default: mod.NoContentType }))
1707
1884
  );
1708
1885
  const CollectionTypePages = () => {
1709
1886
  const { collectionType } = useParams();
@@ -1715,7 +1892,7 @@ const CollectionTypePages = () => {
1715
1892
  const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
1716
1893
  const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
1717
1894
  const LIST_RELATIVE_PATH = ":collectionType/:slug";
1718
- const LIST_PATH = `/content-manager/${LIST_RELATIVE_PATH}`;
1895
+ const LIST_PATH = `/content-manager/collection-types/:slug`;
1719
1896
  const routes = [
1720
1897
  {
1721
1898
  path: LIST_RELATIVE_PATH,
@@ -1749,6 +1926,7 @@ const routes = [
1749
1926
  path: "no-content-types",
1750
1927
  Component: NoContentType
1751
1928
  },
1929
+ ...routes$2,
1752
1930
  ...routes$1
1753
1931
  ];
1754
1932
  const DocumentActions = ({ actions: actions2 }) => {
@@ -1847,6 +2025,11 @@ const DocumentActionButton = (action) => {
1847
2025
  ) : null
1848
2026
  ] });
1849
2027
  };
2028
+ const MenuItem = styled(Menu.Item)`
2029
+ &:hover {
2030
+ background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
2031
+ }
2032
+ `;
1850
2033
  const DocumentActionsMenu = ({
1851
2034
  actions: actions2,
1852
2035
  children,
@@ -1905,48 +2088,32 @@ const DocumentActionsMenu = ({
1905
2088
  /* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1906
2089
  actions2.map((action) => {
1907
2090
  return /* @__PURE__ */ jsx(
1908
- Menu.Item,
2091
+ MenuItem,
1909
2092
  {
1910
2093
  disabled: action.disabled,
1911
2094
  onSelect: handleClick(action),
1912
2095
  display: "block",
1913
- children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
1914
- /* @__PURE__ */ jsxs(
1915
- Flex,
1916
- {
1917
- color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1918
- gap: 2,
1919
- tag: "span",
1920
- children: [
1921
- /* @__PURE__ */ jsx(
1922
- Flex,
1923
- {
1924
- tag: "span",
1925
- color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1926
- children: action.icon
1927
- }
1928
- ),
1929
- action.label
1930
- ]
1931
- }
1932
- ),
1933
- action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
1934
- Flex,
1935
- {
1936
- alignItems: "center",
1937
- background: "alternative100",
1938
- borderStyle: "solid",
1939
- borderColor: "alternative200",
1940
- borderWidth: "1px",
1941
- height: 5,
1942
- paddingLeft: 2,
1943
- paddingRight: 2,
1944
- hasRadius: true,
1945
- color: "alternative600",
1946
- children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
1947
- }
1948
- )
1949
- ] })
2096
+ isVariantDanger: action.variant === "danger",
2097
+ isDisabled: action.disabled,
2098
+ children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxs(
2099
+ Flex,
2100
+ {
2101
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
2102
+ gap: 2,
2103
+ tag: "span",
2104
+ children: [
2105
+ /* @__PURE__ */ jsx(
2106
+ Flex,
2107
+ {
2108
+ tag: "span",
2109
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
2110
+ children: action.icon
2111
+ }
2112
+ ),
2113
+ action.label
2114
+ ]
2115
+ }
2116
+ ) })
1950
2117
  },
1951
2118
  action.id
1952
2119
  );
@@ -2083,6 +2250,7 @@ const PublishAction$1 = ({
2083
2250
  const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
2084
2251
  const isListView = useMatch(LIST_PATH) !== null;
2085
2252
  const isCloning = useMatch(CLONE_PATH) !== null;
2253
+ const { id } = useParams();
2086
2254
  const { formatMessage } = useIntl();
2087
2255
  const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
2088
2256
  const { publish } = useDocumentActions();
@@ -2185,10 +2353,12 @@ const PublishAction$1 = ({
2185
2353
  transformData(formValues)
2186
2354
  );
2187
2355
  if ("data" in res && collectionType !== SINGLE_TYPES) {
2188
- navigate({
2189
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2190
- search: rawQuery
2191
- });
2356
+ if (id === "create") {
2357
+ navigate({
2358
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2359
+ search: rawQuery
2360
+ });
2361
+ }
2192
2362
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2193
2363
  setErrors(formatValidationErrors(res.error));
2194
2364
  }
@@ -2241,6 +2411,7 @@ const PublishAction$1 = ({
2241
2411
  };
2242
2412
  };
2243
2413
  PublishAction$1.type = "publish";
2414
+ PublishAction$1.position = "panel";
2244
2415
  const UpdateAction = ({
2245
2416
  activeTab,
2246
2417
  documentId,
@@ -2263,96 +2434,134 @@ const UpdateAction = ({
2263
2434
  const validate = useForm("UpdateAction", (state) => state.validate);
2264
2435
  const setErrors = useForm("UpdateAction", (state) => state.setErrors);
2265
2436
  const resetForm = useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
2266
- return {
2267
- /**
2268
- * Disabled when:
2269
- * - the form is submitting
2270
- * - the document is not modified & we're not cloning (you can save a clone entity straight away)
2271
- * - the active tab is the published tab
2272
- */
2273
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
2274
- label: formatMessage({
2275
- id: "content-manager.containers.Edit.save",
2276
- defaultMessage: "Save"
2277
- }),
2278
- onClick: async () => {
2279
- setSubmitting(true);
2280
- try {
2281
- const { errors } = await validate(true, {
2282
- status: "draft"
2437
+ const handleUpdate = React.useCallback(async () => {
2438
+ setSubmitting(true);
2439
+ try {
2440
+ if (!modified) {
2441
+ return;
2442
+ }
2443
+ const { errors } = await validate(true, {
2444
+ status: "draft"
2445
+ });
2446
+ if (errors) {
2447
+ toggleNotification({
2448
+ type: "danger",
2449
+ message: formatMessage({
2450
+ id: "content-manager.validation.error",
2451
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
2452
+ })
2283
2453
  });
2284
- if (errors) {
2285
- toggleNotification({
2286
- type: "danger",
2287
- message: formatMessage({
2288
- id: "content-manager.validation.error",
2289
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
2290
- })
2291
- });
2292
- return;
2293
- }
2294
- if (isCloning) {
2295
- const res = await clone(
2296
- {
2297
- model,
2298
- documentId: cloneMatch.params.origin,
2299
- params
2300
- },
2301
- transformData(document)
2302
- );
2303
- if ("data" in res) {
2304
- navigate(
2305
- {
2306
- pathname: `../${res.data.documentId}`,
2307
- search: rawQuery
2308
- },
2309
- { relative: "path" }
2310
- );
2311
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2312
- setErrors(formatValidationErrors(res.error));
2313
- }
2314
- } else if (documentId || collectionType === SINGLE_TYPES) {
2315
- const res = await update(
2454
+ return;
2455
+ }
2456
+ if (isCloning) {
2457
+ const res = await clone(
2458
+ {
2459
+ model,
2460
+ documentId: cloneMatch.params.origin,
2461
+ params
2462
+ },
2463
+ transformData(document)
2464
+ );
2465
+ if ("data" in res) {
2466
+ navigate(
2316
2467
  {
2317
- collectionType,
2318
- model,
2319
- documentId,
2320
- params
2468
+ pathname: `../${res.data.documentId}`,
2469
+ search: rawQuery
2321
2470
  },
2322
- transformData(document)
2471
+ { relative: "path" }
2323
2472
  );
2324
- if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2325
- setErrors(formatValidationErrors(res.error));
2326
- } else {
2327
- resetForm();
2328
- }
2473
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2474
+ setErrors(formatValidationErrors(res.error));
2475
+ }
2476
+ } else if (documentId || collectionType === SINGLE_TYPES) {
2477
+ const res = await update(
2478
+ {
2479
+ collectionType,
2480
+ model,
2481
+ documentId,
2482
+ params
2483
+ },
2484
+ transformData(document)
2485
+ );
2486
+ if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2487
+ setErrors(formatValidationErrors(res.error));
2329
2488
  } else {
2330
- const res = await create(
2489
+ resetForm();
2490
+ }
2491
+ } else {
2492
+ const res = await create(
2493
+ {
2494
+ model,
2495
+ params
2496
+ },
2497
+ transformData(document)
2498
+ );
2499
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
2500
+ navigate(
2331
2501
  {
2332
- model,
2333
- params
2502
+ pathname: `../${res.data.documentId}`,
2503
+ search: rawQuery
2334
2504
  },
2335
- transformData(document)
2505
+ { replace: true, relative: "path" }
2336
2506
  );
2337
- if ("data" in res && collectionType !== SINGLE_TYPES) {
2338
- navigate(
2339
- {
2340
- pathname: `../${res.data.documentId}`,
2341
- search: rawQuery
2342
- },
2343
- { replace: true, relative: "path" }
2344
- );
2345
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2346
- setErrors(formatValidationErrors(res.error));
2347
- }
2507
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
2508
+ setErrors(formatValidationErrors(res.error));
2348
2509
  }
2349
- } finally {
2350
- setSubmitting(false);
2351
2510
  }
2511
+ } finally {
2512
+ setSubmitting(false);
2352
2513
  }
2514
+ }, [
2515
+ clone,
2516
+ cloneMatch?.params.origin,
2517
+ collectionType,
2518
+ create,
2519
+ document,
2520
+ documentId,
2521
+ formatMessage,
2522
+ formatValidationErrors,
2523
+ isCloning,
2524
+ model,
2525
+ modified,
2526
+ navigate,
2527
+ params,
2528
+ rawQuery,
2529
+ resetForm,
2530
+ setErrors,
2531
+ setSubmitting,
2532
+ toggleNotification,
2533
+ update,
2534
+ validate
2535
+ ]);
2536
+ React.useEffect(() => {
2537
+ const handleKeyDown = (e) => {
2538
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
2539
+ e.preventDefault();
2540
+ handleUpdate();
2541
+ }
2542
+ };
2543
+ window.addEventListener("keydown", handleKeyDown);
2544
+ return () => {
2545
+ window.removeEventListener("keydown", handleKeyDown);
2546
+ };
2547
+ }, [handleUpdate]);
2548
+ return {
2549
+ /**
2550
+ * Disabled when:
2551
+ * - the form is submitting
2552
+ * - the document is not modified & we're not cloning (you can save a clone entity straight away)
2553
+ * - the active tab is the published tab
2554
+ */
2555
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
2556
+ label: formatMessage({
2557
+ id: "global.save",
2558
+ defaultMessage: "Save"
2559
+ }),
2560
+ onClick: handleUpdate
2353
2561
  };
2354
2562
  };
2355
2563
  UpdateAction.type = "update";
2564
+ UpdateAction.position = "panel";
2356
2565
  const UNPUBLISH_DRAFT_OPTIONS = {
2357
2566
  KEEP: "keep",
2358
2567
  DISCARD: "discard"
@@ -2475,6 +2684,7 @@ const UnpublishAction$1 = ({
2475
2684
  };
2476
2685
  };
2477
2686
  UnpublishAction$1.type = "unpublish";
2687
+ UnpublishAction$1.position = "panel";
2478
2688
  const DiscardAction = ({
2479
2689
  activeTab,
2480
2690
  documentId,
@@ -2525,6 +2735,7 @@ const DiscardAction = ({
2525
2735
  };
2526
2736
  };
2527
2737
  DiscardAction.type = "discard";
2738
+ DiscardAction.position = "panel";
2528
2739
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2529
2740
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2530
2741
  const RelativeTime = React.forwardRef(
@@ -2537,7 +2748,7 @@ const RelativeTime = React.forwardRef(
2537
2748
  });
2538
2749
  const unit = intervals.find((intervalUnit) => {
2539
2750
  return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
2540
- });
2751
+ }) ?? "seconds";
2541
2752
  const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
2542
2753
  const customInterval = customIntervals.find(
2543
2754
  (custom) => interval[custom.unit] < custom.threshold
@@ -2571,19 +2782,29 @@ const getDisplayName = ({
2571
2782
  return email ?? "";
2572
2783
  };
2573
2784
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2574
- const DocumentStatus = ({ status = "draft", ...restProps }) => {
2785
+ const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
2575
2786
  const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2576
- return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
2787
+ const { formatMessage } = useIntl();
2788
+ return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
2789
+ id: `content-manager.containers.List.${status}`,
2790
+ defaultMessage: capitalise(status)
2791
+ }) }) });
2577
2792
  };
2578
2793
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2579
2794
  const { formatMessage } = useIntl();
2580
2795
  const isCloning = useMatch(CLONE_PATH) !== null;
2796
+ const params = useParams();
2581
2797
  const title = isCreating ? formatMessage({
2582
2798
  id: "content-manager.containers.edit.title.new",
2583
2799
  defaultMessage: "Create an entry"
2584
2800
  }) : documentTitle;
2585
2801
  return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2586
- /* @__PURE__ */ jsx(BackButton, {}),
2802
+ /* @__PURE__ */ jsx(
2803
+ BackButton,
2804
+ {
2805
+ fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
2806
+ }
2807
+ ),
2587
2808
  /* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2588
2809
  /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
2589
2810
  /* @__PURE__ */ jsx(HeaderToolbar, {})
@@ -2634,7 +2855,7 @@ const HeaderToolbar = () => {
2634
2855
  meta: isCloning ? void 0 : meta,
2635
2856
  collectionType
2636
2857
  },
2637
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2858
+ descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
2638
2859
  children: (actions2) => {
2639
2860
  const headerActions = actions2.filter((action) => {
2640
2861
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -2842,6 +3063,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2842
3063
  };
2843
3064
  };
2844
3065
  ConfigureTheViewAction.type = "configure-the-view";
3066
+ ConfigureTheViewAction.position = "header";
2845
3067
  const EditTheModelAction = ({ model }) => {
2846
3068
  const navigate = useNavigate();
2847
3069
  const { formatMessage } = useIntl();
@@ -2858,6 +3080,7 @@ const EditTheModelAction = ({ model }) => {
2858
3080
  };
2859
3081
  };
2860
3082
  EditTheModelAction.type = "edit-the-model";
3083
+ EditTheModelAction.position = "header";
2861
3084
  const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2862
3085
  const navigate = useNavigate();
2863
3086
  const { formatMessage } = useIntl();
@@ -2931,6 +3154,7 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2931
3154
  };
2932
3155
  };
2933
3156
  DeleteAction$1.type = "delete";
3157
+ DeleteAction$1.position = ["header", "table-row"];
2934
3158
  const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2935
3159
  const Panels = () => {
2936
3160
  const isCloning = useMatch(CLONE_PATH) !== null;
@@ -2993,7 +3217,7 @@ const ActionsPanelContent = () => {
2993
3217
  DescriptionComponentRenderer,
2994
3218
  {
2995
3219
  props,
2996
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3220
+ descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
2997
3221
  children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
2998
3222
  }
2999
3223
  ),
@@ -3020,7 +3244,7 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
3020
3244
  justifyContent: "stretch",
3021
3245
  alignItems: "flex-start",
3022
3246
  children: [
3023
- /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
3247
+ /* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
3024
3248
  children
3025
3249
  ]
3026
3250
  }
@@ -3051,7 +3275,7 @@ const ConfirmBulkActionDialog = ({
3051
3275
  ] })
3052
3276
  ] }) });
3053
3277
  };
3054
- const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
3278
+ const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
3055
3279
  const ConfirmDialogPublishAll = ({
3056
3280
  isOpen,
3057
3281
  onToggleDialog,
@@ -3100,7 +3324,7 @@ const ConfirmDialogPublishAll = ({
3100
3324
  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. "
3101
3325
  },
3102
3326
  {
3103
- b: BoldChunk$1,
3327
+ b: BoldChunk,
3104
3328
  count: countDraftRelations,
3105
3329
  entities: selectedEntries.length
3106
3330
  }
@@ -3139,6 +3363,16 @@ const ConfirmDialogPublishAll = ({
3139
3363
  const TypographyMaxWidth = styled(Typography)`
3140
3364
  max-width: 300px;
3141
3365
  `;
3366
+ const TableComponent = styled(RawTable)`
3367
+ width: 100%;
3368
+ table-layout: fixed;
3369
+ td:first-child {
3370
+ border-right: 1px solid ${({ theme }) => theme.colors.neutral150};
3371
+ }
3372
+ td:first-of-type {
3373
+ padding: ${({ theme }) => theme.spaces[4]};
3374
+ }
3375
+ `;
3142
3376
  const formatErrorMessages = (errors, parentKey, formatMessage) => {
3143
3377
  const messages = [];
3144
3378
  Object.entries(errors).forEach(([key, value]) => {
@@ -3243,7 +3477,7 @@ const SelectedEntriesTableContent = ({
3243
3477
  )
3244
3478
  ] }),
3245
3479
  /* @__PURE__ */ jsx(Table.Loading, {}),
3246
- /* @__PURE__ */ jsx(Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxs(Table.Row, { children: [
3480
+ /* @__PURE__ */ jsx(Table.Body, { children: rowsToDisplay.map((row) => /* @__PURE__ */ jsxs(Table.Row, { children: [
3247
3481
  /* @__PURE__ */ jsx(Table.CheckboxCell, { id: row.id }),
3248
3482
  /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row.id }) }),
3249
3483
  shouldDisplayMainField && /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row[mainField] }) }),
@@ -3270,18 +3504,10 @@ const SelectedEntriesTableContent = ({
3270
3504
  search: row.locale && `?plugins[i18n][locale]=${row.locale}`
3271
3505
  },
3272
3506
  state: { from: pathname },
3273
- label: formatMessage(
3274
- { id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
3275
- {
3276
- target: formatMessage(
3277
- {
3278
- id: "content-manager.components.ListViewHelperPluginTable.row-line",
3279
- defaultMessage: "item line {number}"
3280
- },
3281
- { number: index2 + 1 }
3282
- )
3283
- }
3284
- ),
3507
+ label: formatMessage({
3508
+ id: "content-manager.bulk-publish.edit",
3509
+ defaultMessage: "Edit"
3510
+ }),
3285
3511
  target: "_blank",
3286
3512
  marginLeft: "auto",
3287
3513
  variant: "ghost",
@@ -3291,7 +3517,73 @@ const SelectedEntriesTableContent = ({
3291
3517
  ] }, row.id)) })
3292
3518
  ] });
3293
3519
  };
3294
- const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
3520
+ const PublicationStatusSummary = ({ count, icon, message }) => {
3521
+ return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", flex: 1, gap: 3, children: [
3522
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
3523
+ icon,
3524
+ /* @__PURE__ */ jsx(Typography, { children: message })
3525
+ ] }),
3526
+ /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: count })
3527
+ ] });
3528
+ };
3529
+ const PublicationStatusGrid = ({
3530
+ entriesReadyToPublishCount,
3531
+ entriesPublishedCount,
3532
+ entriesModifiedCount,
3533
+ entriesWithErrorsCount
3534
+ }) => {
3535
+ const { formatMessage } = useIntl();
3536
+ return /* @__PURE__ */ jsx(Box, { hasRadius: true, borderColor: "neutral150", children: /* @__PURE__ */ jsx(TableComponent, { colCount: 2, rowCount: 2, children: /* @__PURE__ */ jsxs(Tbody, { children: [
3537
+ /* @__PURE__ */ jsxs(Tr, { children: [
3538
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(
3539
+ PublicationStatusSummary,
3540
+ {
3541
+ count: entriesReadyToPublishCount,
3542
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
3543
+ message: formatMessage({
3544
+ id: "app.utils.ready-to-publish",
3545
+ defaultMessage: "Ready to publish"
3546
+ })
3547
+ }
3548
+ ) }),
3549
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(
3550
+ PublicationStatusSummary,
3551
+ {
3552
+ count: entriesPublishedCount,
3553
+ icon: /* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
3554
+ message: formatMessage({
3555
+ id: "app.utils.already-published",
3556
+ defaultMessage: "Already published"
3557
+ })
3558
+ }
3559
+ ) })
3560
+ ] }),
3561
+ /* @__PURE__ */ jsxs(Tr, { children: [
3562
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(
3563
+ PublicationStatusSummary,
3564
+ {
3565
+ count: entriesModifiedCount,
3566
+ icon: /* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
3567
+ message: formatMessage({
3568
+ id: "content-manager.bulk-publish.modified",
3569
+ defaultMessage: "Ready to publish changes"
3570
+ })
3571
+ }
3572
+ ) }),
3573
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(
3574
+ PublicationStatusSummary,
3575
+ {
3576
+ count: entriesWithErrorsCount,
3577
+ icon: /* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
3578
+ message: formatMessage({
3579
+ id: "content-manager.bulk-publish.waiting-for-action",
3580
+ defaultMessage: "Waiting for action"
3581
+ })
3582
+ }
3583
+ ) })
3584
+ ] })
3585
+ ] }) }) });
3586
+ };
3295
3587
  const SelectedEntriesModalContent = ({
3296
3588
  listViewSelectedEntries,
3297
3589
  toggleModal,
@@ -3350,7 +3642,6 @@ const SelectedEntriesModalContent = ({
3350
3642
  validationErrors: {}
3351
3643
  };
3352
3644
  }, [components, data, schema]);
3353
- const [publishedCount, setPublishedCount] = React.useState(0);
3354
3645
  const [isDialogOpen, setIsDialogOpen] = React.useState(false);
3355
3646
  const { publishMany: bulkPublishAction } = useDocumentActions();
3356
3647
  const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
@@ -3362,53 +3653,36 @@ const SelectedEntriesModalContent = ({
3362
3653
  const selectedEntriesWithErrorsCount = selectedEntries.filter(
3363
3654
  ({ documentId }) => validationErrors[documentId]
3364
3655
  ).length;
3365
- const selectedEntriesPublished = selectedEntries.filter(
3656
+ const selectedEntriesPublishedCount = selectedEntries.filter(
3366
3657
  ({ status }) => status === "published"
3367
3658
  ).length;
3368
- const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
3659
+ const selectedEntriesModifiedCount = selectedEntries.filter(
3660
+ ({ status, documentId }) => status === "modified" && !validationErrors[documentId]
3661
+ ).length;
3662
+ const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublishedCount;
3369
3663
  const toggleDialog = () => setIsDialogOpen((prev) => !prev);
3370
3664
  const handleConfirmBulkPublish = async () => {
3371
3665
  toggleDialog();
3372
3666
  const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
3373
3667
  if (!("error" in res)) {
3374
- setPublishedCount(res.count);
3375
3668
  const unpublishedEntries = rows.filter((row) => {
3376
3669
  return !entriesToPublish.includes(row.documentId);
3377
3670
  });
3378
3671
  setListViewSelectedDocuments(unpublishedEntries);
3379
3672
  }
3380
3673
  };
3381
- const getFormattedCountMessage = () => {
3382
- if (publishedCount) {
3383
- return formatMessage(
3384
- {
3385
- id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
3386
- 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."
3387
- },
3388
- {
3389
- publishedCount,
3390
- withErrorsCount: selectedEntriesWithErrorsCount,
3391
- b: BoldChunk
3392
- }
3393
- );
3394
- }
3395
- return formatMessage(
3396
- {
3397
- id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
3398
- 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."
3399
- },
3400
- {
3401
- readyToPublishCount: selectedEntriesWithNoErrorsCount,
3402
- withErrorsCount: selectedEntriesWithErrorsCount,
3403
- alreadyPublishedCount: selectedEntriesPublished,
3404
- b: BoldChunk
3405
- }
3406
- );
3407
- };
3408
3674
  return /* @__PURE__ */ jsxs(Fragment, { children: [
3409
3675
  /* @__PURE__ */ jsxs(Modal.Body, { children: [
3410
- /* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
3411
- /* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsx(
3676
+ /* @__PURE__ */ jsx(
3677
+ PublicationStatusGrid,
3678
+ {
3679
+ entriesReadyToPublishCount: selectedEntriesWithNoErrorsCount - selectedEntriesModifiedCount,
3680
+ entriesPublishedCount: selectedEntriesPublishedCount,
3681
+ entriesModifiedCount: selectedEntriesModifiedCount,
3682
+ entriesWithErrorsCount: selectedEntriesWithErrorsCount
3683
+ }
3684
+ ),
3685
+ /* @__PURE__ */ jsx(Box, { marginTop: 7, children: /* @__PURE__ */ jsx(
3412
3686
  SelectedEntriesTableContent,
3413
3687
  {
3414
3688
  isPublishing: isSubmittingForm,
@@ -3429,7 +3703,7 @@ const SelectedEntriesModalContent = ({
3429
3703
  Button,
3430
3704
  {
3431
3705
  onClick: toggleDialog,
3432
- disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
3706
+ disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublishedCount === selectedEntries.length || isLoading,
3433
3707
  loading: isSubmittingForm,
3434
3708
  children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
3435
3709
  }
@@ -3455,8 +3729,7 @@ const PublishAction = ({ documents, model }) => {
3455
3729
  const refetchList = () => {
3456
3730
  contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
3457
3731
  };
3458
- if (!showPublishButton)
3459
- return null;
3732
+ if (!showPublishButton) return null;
3460
3733
  return {
3461
3734
  actionType: "publish",
3462
3735
  variant: "tertiary",
@@ -3524,8 +3797,7 @@ const DeleteAction = ({ documents, model }) => {
3524
3797
  selectRow([]);
3525
3798
  }
3526
3799
  };
3527
- if (!hasDeletePermission)
3528
- return null;
3800
+ if (!hasDeletePermission) return null;
3529
3801
  return {
3530
3802
  variant: "danger-light",
3531
3803
  label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
@@ -3574,8 +3846,7 @@ const UnpublishAction = ({ documents, model }) => {
3574
3846
  }
3575
3847
  };
3576
3848
  const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
3577
- if (!showUnpublishButton)
3578
- return null;
3849
+ if (!showUnpublishButton) return null;
3579
3850
  return {
3580
3851
  variant: "tertiary",
3581
3852
  label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
@@ -3680,7 +3951,7 @@ const TableActions = ({ document }) => {
3680
3951
  DescriptionComponentRenderer,
3681
3952
  {
3682
3953
  props,
3683
- descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
3954
+ descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
3684
3955
  children: (actions2) => {
3685
3956
  const tableRowActions = actions2.filter((action) => {
3686
3957
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3739,6 +4010,7 @@ const EditAction = ({ documentId }) => {
3739
4010
  };
3740
4011
  };
3741
4012
  EditAction.type = "edit";
4013
+ EditAction.position = "table-row";
3742
4014
  const StyledPencil = styled(Pencil)`
3743
4015
  path {
3744
4016
  fill: currentColor;
@@ -3815,6 +4087,7 @@ const CloneAction = ({ model, documentId }) => {
3815
4087
  };
3816
4088
  };
3817
4089
  CloneAction.type = "clone";
4090
+ CloneAction.position = "table-row";
3818
4091
  const StyledDuplicate = styled(Duplicate)`
3819
4092
  path {
3820
4093
  fill: currentColor;
@@ -3901,7 +4174,14 @@ class ContentManagerPlugin {
3901
4174
  addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
3902
4175
  addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
3903
4176
  getBulkActions: () => this.bulkActions,
3904
- getDocumentActions: () => this.documentActions,
4177
+ getDocumentActions: (position) => {
4178
+ if (position) {
4179
+ return this.documentActions.filter(
4180
+ (action) => action.position == void 0 || [action.position].flat().includes(position)
4181
+ );
4182
+ }
4183
+ return this.documentActions;
4184
+ },
3905
4185
  getEditViewSidePanels: () => this.editViewSidePanels,
3906
4186
  getHeaderActions: () => this.headerActions
3907
4187
  }
@@ -3911,10 +4191,8 @@ class ContentManagerPlugin {
3911
4191
  const getPrintableType = (value) => {
3912
4192
  const nativeType = typeof value;
3913
4193
  if (nativeType === "object") {
3914
- if (value === null)
3915
- return "null";
3916
- if (Array.isArray(value))
3917
- return "array";
4194
+ if (value === null) return "null";
4195
+ if (Array.isArray(value)) return "array";
3918
4196
  if (value instanceof Object && value.constructor.name !== "Object") {
3919
4197
  return value.constructor.name;
3920
4198
  }
@@ -3925,17 +4203,27 @@ const HistoryAction = ({ model, document }) => {
3925
4203
  const { formatMessage } = useIntl();
3926
4204
  const [{ query }] = useQueryParams();
3927
4205
  const navigate = useNavigate();
4206
+ const { trackUsage } = useTracking();
4207
+ const { pathname } = useLocation();
3928
4208
  const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
3929
4209
  if (!window.strapi.features.isEnabled("cms-content-history")) {
3930
4210
  return null;
3931
4211
  }
4212
+ const handleOnClick = () => {
4213
+ const destination = { pathname: "history", search: pluginsQueryParams };
4214
+ trackUsage("willNavigate", {
4215
+ from: pathname,
4216
+ to: `${pathname}/${destination.pathname}`
4217
+ });
4218
+ navigate(destination);
4219
+ };
3932
4220
  return {
3933
4221
  icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
3934
4222
  label: formatMessage({
3935
4223
  id: "content-manager.history.document-action",
3936
4224
  defaultMessage: "Content History"
3937
4225
  }),
3938
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
4226
+ onClick: handleOnClick,
3939
4227
  disabled: (
3940
4228
  /**
3941
4229
  * The user is creating a new document.
@@ -3957,6 +4245,7 @@ const HistoryAction = ({ model, document }) => {
3957
4245
  };
3958
4246
  };
3959
4247
  HistoryAction.type = "history";
4248
+ HistoryAction.position = "header";
3960
4249
  const historyAdmin = {
3961
4250
  bootstrap(app) {
3962
4251
  const { addDocumentAction } = app.getPlugin("content-manager").apis;
@@ -4003,6 +4292,88 @@ const { setInitialData } = actions;
4003
4292
  const reducer = combineReducers({
4004
4293
  app: reducer$1
4005
4294
  });
4295
+ const previewApi = contentManagerApi.injectEndpoints({
4296
+ endpoints: (builder) => ({
4297
+ getPreviewUrl: builder.query({
4298
+ query({ query, params }) {
4299
+ return {
4300
+ url: `/content-manager/preview/url/${params.contentType}`,
4301
+ method: "GET",
4302
+ config: {
4303
+ params: query
4304
+ }
4305
+ };
4306
+ }
4307
+ })
4308
+ })
4309
+ });
4310
+ const { useGetPreviewUrlQuery } = previewApi;
4311
+ const ConditionalTooltip = ({ isShown, label, children }) => {
4312
+ if (isShown) {
4313
+ return /* @__PURE__ */ jsx(Tooltip, { label, children });
4314
+ }
4315
+ return children;
4316
+ };
4317
+ const PreviewSidePanel = ({ model, documentId, document }) => {
4318
+ const { formatMessage } = useIntl();
4319
+ const { trackUsage } = useTracking();
4320
+ const { pathname } = useLocation();
4321
+ const [{ query }] = useQueryParams();
4322
+ const isModified = useForm("PreviewSidePanel", (state) => state.modified);
4323
+ const { data, error } = useGetPreviewUrlQuery({
4324
+ params: {
4325
+ contentType: model
4326
+ },
4327
+ query: {
4328
+ documentId,
4329
+ locale: document?.locale,
4330
+ status: document?.status
4331
+ }
4332
+ });
4333
+ if (!data?.data?.url || error) {
4334
+ return null;
4335
+ }
4336
+ const trackNavigation = () => {
4337
+ const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
4338
+ trackUsage("willNavigate", { from: pathname, to: destinationPathname });
4339
+ };
4340
+ return {
4341
+ title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
4342
+ content: /* @__PURE__ */ jsx(
4343
+ ConditionalTooltip,
4344
+ {
4345
+ label: formatMessage({
4346
+ id: "content-manager.preview.panel.button-disabled-tooltip",
4347
+ defaultMessage: "Please save to open the preview"
4348
+ }),
4349
+ isShown: isModified,
4350
+ children: /* @__PURE__ */ jsx(Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsx(
4351
+ Button,
4352
+ {
4353
+ variant: "tertiary",
4354
+ tag: Link,
4355
+ to: { pathname: "preview", search: stringify(query, { encode: false }) },
4356
+ onClick: trackNavigation,
4357
+ width: "100%",
4358
+ disabled: isModified,
4359
+ pointerEvents: isModified ? "none" : void 0,
4360
+ tabIndex: isModified ? -1 : void 0,
4361
+ children: formatMessage({
4362
+ id: "content-manager.preview.panel.button",
4363
+ defaultMessage: "Open preview"
4364
+ })
4365
+ }
4366
+ ) })
4367
+ }
4368
+ )
4369
+ };
4370
+ };
4371
+ const previewAdmin = {
4372
+ bootstrap(app) {
4373
+ const contentManagerPluginApis = app.getPlugin("content-manager").apis;
4374
+ contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
4375
+ }
4376
+ };
4006
4377
  const index = {
4007
4378
  register(app) {
4008
4379
  const cm = new ContentManagerPlugin();
@@ -4022,7 +4393,7 @@ const index = {
4022
4393
  app.router.addRoute({
4023
4394
  path: "content-manager/*",
4024
4395
  lazy: async () => {
4025
- const { Layout } = await import("./layout-C5uSVTqi.mjs");
4396
+ const { Layout } = await import("./layout-CxDMdJ13.mjs");
4026
4397
  return {
4027
4398
  Component: Layout
4028
4399
  };
@@ -4035,11 +4406,14 @@ const index = {
4035
4406
  if (typeof historyAdmin.bootstrap === "function") {
4036
4407
  historyAdmin.bootstrap(app);
4037
4408
  }
4409
+ if (typeof previewAdmin.bootstrap === "function") {
4410
+ previewAdmin.bootstrap(app);
4411
+ }
4038
4412
  },
4039
4413
  async registerTrads({ locales }) {
4040
4414
  const importedTrads = await Promise.all(
4041
4415
  locales.map((locale) => {
4042
- 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-DKV44jRb.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 }) => {
4416
+ 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-D65uIF6Y.mjs"), "./translations/es.json": () => import("./es-D34tqjMw.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr-DBseuRuB.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-BHqhDq4V.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`, 3).then(({ default: data }) => {
4043
4417
  return {
4044
4418
  data: prefixPluginTranslations(data, PLUGIN_ID),
4045
4419
  locale
@@ -4056,23 +4430,27 @@ const index = {
4056
4430
  }
4057
4431
  };
4058
4432
  export {
4059
- ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD as A,
4433
+ useUpdateContentTypeConfigurationMutation as A,
4060
4434
  BulkActionsRenderer as B,
4061
4435
  COLLECTION_TYPES as C,
4062
4436
  DocumentStatus as D,
4063
- extractContentTypeComponents as E,
4064
- DEFAULT_SETTINGS as F,
4065
- convertEditLayoutToFieldLayouts as G,
4437
+ ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD as E,
4438
+ extractContentTypeComponents as F,
4439
+ DEFAULT_SETTINGS as G,
4066
4440
  HOOKS as H,
4067
4441
  InjectionZone as I,
4068
- useDocument as J,
4069
- index as K,
4070
- useContentManagerContext as L,
4071
- useDocumentActions as M,
4442
+ convertEditLayoutToFieldLayouts as J,
4443
+ removeFieldsThatDontExistOnSchema as K,
4444
+ prepareTempKeys as L,
4445
+ useDocument as M,
4446
+ useGetPreviewUrlQuery as N,
4447
+ index as O,
4072
4448
  Panels as P,
4449
+ useContentManagerContext as Q,
4073
4450
  RelativeTime as R,
4074
4451
  SINGLE_TYPES as S,
4075
4452
  TableActions as T,
4453
+ useDocumentActions as U,
4076
4454
  useGetInitialDataQuery as a,
4077
4455
  useGetAllContentTypeSettingsQuery as b,
4078
4456
  useDoc as c,
@@ -4085,19 +4463,19 @@ export {
4085
4463
  Header as j,
4086
4464
  PERMISSIONS as k,
4087
4465
  DocumentRBAC as l,
4088
- DOCUMENT_META_FIELDS as m,
4089
- CLONE_PATH as n,
4090
- useDocLayout as o,
4466
+ useDocLayout as m,
4467
+ createDefaultForm as n,
4468
+ CLONE_PATH as o,
4091
4469
  useGetContentTypeConfigurationQuery as p,
4092
4470
  CREATOR_FIELDS as q,
4093
4471
  getMainField as r,
4094
4472
  setInitialData as s,
4095
- getDisplayName as t,
4473
+ transformDocument as t,
4096
4474
  useContentTypeSchema as u,
4097
- checkIfAttributeIsDisplayable as v,
4098
- useGetAllDocumentsQuery as w,
4099
- convertListLayoutToFieldLayouts as x,
4100
- capitalise as y,
4101
- useUpdateContentTypeConfigurationMutation as z
4475
+ getDisplayName as v,
4476
+ checkIfAttributeIsDisplayable as w,
4477
+ useGetAllDocumentsQuery as x,
4478
+ convertListLayoutToFieldLayouts as y,
4479
+ capitalise as z
4102
4480
  };
4103
- //# sourceMappingURL=index-CsfwpRfc.mjs.map
4481
+ //# sourceMappingURL=index-EH8ZtHd5.mjs.map