@strapi/content-manager 0.0.0-experimental.545ccead2ee1717bbc7ab950455dbb0ddb9924a3 → 0.0.0-experimental.56109c4ad2fb374b04c392a229599354fa6586e1

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 (134) hide show
  1. package/dist/_chunks/{ComponentConfigurationPage-Bqgx7Mes.js → ComponentConfigurationPage-CQDCxI8x.js} +3 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-Bqgx7Mes.js.map → ComponentConfigurationPage-CQDCxI8x.js.map} +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-B1bIXVuX.mjs → ComponentConfigurationPage-jmWwucg_.mjs} +3 -3
  4. package/dist/_chunks/{ComponentConfigurationPage-B1bIXVuX.mjs.map → ComponentConfigurationPage-jmWwucg_.mjs.map} +1 -1
  5. package/dist/_chunks/{EditConfigurationPage-BFEwvdMW.js → EditConfigurationPage-Ce4bIm4n.js} +3 -3
  6. package/dist/_chunks/{EditConfigurationPage-BFEwvdMW.js.map → EditConfigurationPage-Ce4bIm4n.js.map} +1 -1
  7. package/dist/_chunks/{EditConfigurationPage-ZO0vOO8q.mjs → EditConfigurationPage-W07CEdm2.mjs} +3 -3
  8. package/dist/_chunks/{EditConfigurationPage-ZO0vOO8q.mjs.map → EditConfigurationPage-W07CEdm2.mjs.map} +1 -1
  9. package/dist/_chunks/{EditViewPage-DA95Ha6J.js → EditViewPage-CqHMM0P0.js} +30 -9
  10. package/dist/_chunks/EditViewPage-CqHMM0P0.js.map +1 -0
  11. package/dist/_chunks/{EditViewPage-DlLEyUL6.mjs → EditViewPage-al5OO1NR.mjs} +30 -9
  12. package/dist/_chunks/EditViewPage-al5OO1NR.mjs.map +1 -0
  13. package/dist/_chunks/{Field-CnK8dO8N.js → Field-DSOUlTCm.js} +179 -107
  14. package/dist/_chunks/Field-DSOUlTCm.js.map +1 -0
  15. package/dist/_chunks/{Field-Dq7bDnuh.mjs → Field-EeG6NQ7x.mjs} +177 -105
  16. package/dist/_chunks/Field-EeG6NQ7x.mjs.map +1 -0
  17. package/dist/_chunks/{Form-B_JE0dbz.mjs → Form-BAo9ANb_.mjs} +36 -17
  18. package/dist/_chunks/Form-BAo9ANb_.mjs.map +1 -0
  19. package/dist/_chunks/{Form-BpiR4piS.js → Form-DAEfHKzm.js} +36 -17
  20. package/dist/_chunks/Form-DAEfHKzm.js.map +1 -0
  21. package/dist/_chunks/{History-CBNGU7a-.mjs → History-BpLIu67W.mjs} +41 -18
  22. package/dist/_chunks/History-BpLIu67W.mjs.map +1 -0
  23. package/dist/_chunks/{History-DdIstl8b.js → History-CTFvy6XH.js} +40 -17
  24. package/dist/_chunks/History-CTFvy6XH.js.map +1 -0
  25. package/dist/_chunks/{ListConfigurationPage-DkKRparB.js → ListConfigurationPage-CDzlMBz_.js} +14 -4
  26. package/dist/_chunks/ListConfigurationPage-CDzlMBz_.js.map +1 -0
  27. package/dist/_chunks/{ListConfigurationPage-5dr4qpue.mjs → ListConfigurationPage-DOqj5f8Y.mjs} +14 -4
  28. package/dist/_chunks/ListConfigurationPage-DOqj5f8Y.mjs.map +1 -0
  29. package/dist/_chunks/{ListViewPage-DecLrYV6.mjs → ListViewPage-BbXYNI0v.mjs} +47 -38
  30. package/dist/_chunks/ListViewPage-BbXYNI0v.mjs.map +1 -0
  31. package/dist/_chunks/{ListViewPage-wE0lXqoD.js → ListViewPage-D0fpPYKp.js} +49 -40
  32. package/dist/_chunks/ListViewPage-D0fpPYKp.js.map +1 -0
  33. package/dist/_chunks/{NoContentTypePage-DEKR6tf9.js → NoContentTypePage-DTzkSAV5.js} +2 -2
  34. package/dist/_chunks/{NoContentTypePage-DEKR6tf9.js.map → NoContentTypePage-DTzkSAV5.js.map} +1 -1
  35. package/dist/_chunks/{NoContentTypePage-CiIcfYsd.mjs → NoContentTypePage-w2Q0VVOT.mjs} +2 -2
  36. package/dist/_chunks/{NoContentTypePage-CiIcfYsd.mjs.map → NoContentTypePage-w2Q0VVOT.mjs.map} +1 -1
  37. package/dist/_chunks/{NoPermissionsPage-DmNfF2Bb.js → NoPermissionsPage-BoI2rU68.js} +2 -2
  38. package/dist/_chunks/{NoPermissionsPage-DmNfF2Bb.js.map → NoPermissionsPage-BoI2rU68.js.map} +1 -1
  39. package/dist/_chunks/{NoPermissionsPage-CM5UD8ee.mjs → NoPermissionsPage-Km0Vk5Wp.mjs} +2 -2
  40. package/dist/_chunks/{NoPermissionsPage-CM5UD8ee.mjs.map → NoPermissionsPage-Km0Vk5Wp.mjs.map} +1 -1
  41. package/dist/_chunks/{Relations-Dqz0C1fz.mjs → Relations-C_bpmSuQ.mjs} +51 -29
  42. package/dist/_chunks/Relations-C_bpmSuQ.mjs.map +1 -0
  43. package/dist/_chunks/{Relations-L0xYRoSQ.js → Relations-D6Nz5ksc.js} +51 -29
  44. package/dist/_chunks/Relations-D6Nz5ksc.js.map +1 -0
  45. package/dist/_chunks/{en-uOUIxfcQ.js → en-Bm0D0IWz.js} +13 -12
  46. package/dist/_chunks/{en-uOUIxfcQ.js.map → en-Bm0D0IWz.js.map} +1 -1
  47. package/dist/_chunks/{en-BrCTWlZv.mjs → en-DKV44jRb.mjs} +13 -12
  48. package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-DKV44jRb.mjs.map} +1 -1
  49. package/dist/_chunks/{index-DyvUPg1a.js → index-BsMu2oVP.js} +726 -530
  50. package/dist/_chunks/index-BsMu2oVP.js.map +1 -0
  51. package/dist/_chunks/{index-BSn97i8U.mjs → index-DcQ6xogO.mjs} +745 -550
  52. package/dist/_chunks/index-DcQ6xogO.mjs.map +1 -0
  53. package/dist/_chunks/{layout-TPqF2oJ5.js → layout-B4aCAdTt.js} +21 -8
  54. package/dist/_chunks/layout-B4aCAdTt.js.map +1 -0
  55. package/dist/_chunks/{layout-DPaHUusj.mjs → layout-BavJ6v4B.mjs} +22 -9
  56. package/dist/_chunks/layout-BavJ6v4B.mjs.map +1 -0
  57. package/dist/_chunks/{relations-Ck7-ecDT.mjs → relations-DMG453Od.mjs} +2 -2
  58. package/dist/_chunks/{relations-Ck7-ecDT.mjs.map → relations-DMG453Od.mjs.map} +1 -1
  59. package/dist/_chunks/{relations-BWYS9gkn.js → relations-Lrm9nz_m.js} +2 -2
  60. package/dist/_chunks/{relations-BWYS9gkn.js.map → relations-Lrm9nz_m.js.map} +1 -1
  61. package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
  62. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
  63. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
  64. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
  65. package/dist/admin/index.js +2 -1
  66. package/dist/admin/index.js.map +1 -1
  67. package/dist/admin/index.mjs +5 -4
  68. package/dist/admin/src/exports.d.ts +1 -1
  69. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  70. package/dist/admin/src/hooks/useDocument.d.ts +32 -1
  71. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  72. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  73. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
  74. package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
  75. package/dist/admin/src/services/api.d.ts +1 -1
  76. package/dist/admin/src/services/components.d.ts +2 -2
  77. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  78. package/dist/admin/src/services/documents.d.ts +19 -17
  79. package/dist/admin/src/services/init.d.ts +1 -1
  80. package/dist/admin/src/services/relations.d.ts +2 -2
  81. package/dist/admin/src/services/uid.d.ts +3 -3
  82. package/dist/admin/src/utils/validation.d.ts +4 -1
  83. package/dist/server/index.js +241 -132
  84. package/dist/server/index.js.map +1 -1
  85. package/dist/server/index.mjs +242 -133
  86. package/dist/server/index.mjs.map +1 -1
  87. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  88. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  89. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  90. package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
  91. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  92. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  93. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  94. package/dist/server/src/history/services/history.d.ts.map +1 -1
  95. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  96. package/dist/server/src/history/services/utils.d.ts +2 -1
  97. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  98. package/dist/server/src/index.d.ts +4 -4
  99. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  100. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  101. package/dist/server/src/services/document-metadata.d.ts +8 -8
  102. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  103. package/dist/server/src/services/index.d.ts +4 -4
  104. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  105. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  106. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  107. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  108. package/dist/server/src/utils/index.d.ts +2 -0
  109. package/dist/server/src/utils/index.d.ts.map +1 -1
  110. package/dist/shared/contracts/collection-types.d.ts +3 -1
  111. package/dist/shared/contracts/collection-types.d.ts.map +1 -1
  112. package/package.json +12 -12
  113. package/dist/_chunks/EditViewPage-DA95Ha6J.js.map +0 -1
  114. package/dist/_chunks/EditViewPage-DlLEyUL6.mjs.map +0 -1
  115. package/dist/_chunks/Field-CnK8dO8N.js.map +0 -1
  116. package/dist/_chunks/Field-Dq7bDnuh.mjs.map +0 -1
  117. package/dist/_chunks/Form-B_JE0dbz.mjs.map +0 -1
  118. package/dist/_chunks/Form-BpiR4piS.js.map +0 -1
  119. package/dist/_chunks/History-CBNGU7a-.mjs.map +0 -1
  120. package/dist/_chunks/History-DdIstl8b.js.map +0 -1
  121. package/dist/_chunks/ListConfigurationPage-5dr4qpue.mjs.map +0 -1
  122. package/dist/_chunks/ListConfigurationPage-DkKRparB.js.map +0 -1
  123. package/dist/_chunks/ListViewPage-DecLrYV6.mjs.map +0 -1
  124. package/dist/_chunks/ListViewPage-wE0lXqoD.js.map +0 -1
  125. package/dist/_chunks/Relations-Dqz0C1fz.mjs.map +0 -1
  126. package/dist/_chunks/Relations-L0xYRoSQ.js.map +0 -1
  127. package/dist/_chunks/index-BSn97i8U.mjs.map +0 -1
  128. package/dist/_chunks/index-DyvUPg1a.js.map +0 -1
  129. package/dist/_chunks/layout-DPaHUusj.mjs.map +0 -1
  130. package/dist/_chunks/layout-TPqF2oJ5.js.map +0 -1
  131. package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
  132. package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
  133. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
  134. package/strapi-server.js +0 -3
@@ -1,16 +1,17 @@
1
- import { CrossCircle, More, WarningCircle, ListPlus, Pencil, Trash, Check, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, 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, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useQueryParams, useTracking, useForm, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
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, Box, Typography, Dialog, Modal, Radio, Status, SingleSelect, SingleSelectOption, Loader, IconButton, Tooltip, LinkButton } from "@strapi/design-system";
6
+ import { Button, Menu, VisuallyHidden, Flex, Typography, Dialog, Modal, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
7
+ import mapValues from "lodash/fp/mapValues";
7
8
  import { useIntl } from "react-intl";
8
- import { useParams, Navigate, useNavigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
9
- import { styled } from "styled-components";
9
+ import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
10
10
  import * as yup from "yup";
11
11
  import { ValidationError } from "yup";
12
12
  import pipe from "lodash/fp/pipe";
13
13
  import { intervalToDuration, isPast } from "date-fns";
14
+ import { styled } from "styled-components";
14
15
  import { stringify } from "qs";
15
16
  import { createSlice, combineReducers } from "@reduxjs/toolkit";
16
17
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
@@ -100,6 +101,7 @@ const DocumentRBAC = ({ children, permissions }) => {
100
101
  if (!slug) {
101
102
  throw new Error("Cannot find the slug param in the URL");
102
103
  }
104
+ const [{ rawQuery }] = useQueryParams();
103
105
  const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
104
106
  const contentTypePermissions = React.useMemo(() => {
105
107
  const contentTypePermissions2 = userPermissions.filter(
@@ -110,7 +112,14 @@ const DocumentRBAC = ({ children, permissions }) => {
110
112
  return { ...acc, [action]: [permission] };
111
113
  }, {});
112
114
  }, [slug, userPermissions]);
113
- const { isLoading, allowedActions } = useRBAC(contentTypePermissions, permissions ?? void 0);
115
+ const { isLoading, allowedActions } = useRBAC(
116
+ contentTypePermissions,
117
+ permissions ?? void 0,
118
+ // TODO: useRBAC context should be typed and built differently
119
+ // We are passing raw query as context to the hook so that it can
120
+ // rely on the locale provided from DocumentRBAC for its permission calculations.
121
+ rawQuery
122
+ );
114
123
  const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
115
124
  const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
116
125
  const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
@@ -158,7 +167,8 @@ const contentManagerApi = adminApi.enhanceEndpoints({
158
167
  "Document",
159
168
  "InitialData",
160
169
  "HistoryVersion",
161
- "Relations"
170
+ "Relations",
171
+ "UidAvailability"
162
172
  ]
163
173
  });
164
174
  const documentApi = contentManagerApi.injectEndpoints({
@@ -172,7 +182,12 @@ const documentApi = contentManagerApi.injectEndpoints({
172
182
  params: query
173
183
  }
174
184
  }),
175
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
185
+ invalidatesTags: (_result, error, { model }) => {
186
+ if (error) {
187
+ return [];
188
+ }
189
+ return [{ type: "Document", id: `${model}_LIST` }];
190
+ }
176
191
  }),
177
192
  cloneDocument: builder.mutation({
178
193
  query: ({ model, sourceId, data, params }) => ({
@@ -183,7 +198,10 @@ const documentApi = contentManagerApi.injectEndpoints({
183
198
  params
184
199
  }
185
200
  }),
186
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
201
+ invalidatesTags: (_result, _error, { model }) => [
202
+ { type: "Document", id: `${model}_LIST` },
203
+ { type: "UidAvailability", id: model }
204
+ ]
187
205
  }),
188
206
  /**
189
207
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -200,7 +218,8 @@ const documentApi = contentManagerApi.injectEndpoints({
200
218
  }),
201
219
  invalidatesTags: (result, _error, { model }) => [
202
220
  { type: "Document", id: `${model}_LIST` },
203
- "Relations"
221
+ "Relations",
222
+ { type: "UidAvailability", id: model }
204
223
  ]
205
224
  }),
206
225
  deleteDocument: builder.mutation({
@@ -241,7 +260,8 @@ const documentApi = contentManagerApi.injectEndpoints({
241
260
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
242
261
  },
243
262
  { type: "Document", id: `${model}_LIST` },
244
- "Relations"
263
+ "Relations",
264
+ { type: "UidAvailability", id: model }
245
265
  ];
246
266
  }
247
267
  }),
@@ -259,6 +279,7 @@ const documentApi = contentManagerApi.injectEndpoints({
259
279
  }),
260
280
  providesTags: (result, _error, arg) => {
261
281
  return [
282
+ { type: "Document", id: `ALL_LIST` },
262
283
  { type: "Document", id: `${arg.model}_LIST` },
263
284
  ...result?.results.map(({ documentId }) => ({
264
285
  type: "Document",
@@ -297,6 +318,11 @@ const documentApi = contentManagerApi.injectEndpoints({
297
318
  {
298
319
  type: "Document",
299
320
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
321
+ },
322
+ // Make it easy to invalidate all individual documents queries for a model
323
+ {
324
+ type: "Document",
325
+ id: `${model}_ALL_ITEMS`
300
326
  }
301
327
  ];
302
328
  }
@@ -360,8 +386,21 @@ const documentApi = contentManagerApi.injectEndpoints({
360
386
  type: "Document",
361
387
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
362
388
  },
363
- "Relations"
389
+ "Relations",
390
+ { type: "UidAvailability", id: model }
364
391
  ];
392
+ },
393
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
394
+ const patchResult = dispatch(
395
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
396
+ Object.assign(draft.data, data);
397
+ })
398
+ );
399
+ try {
400
+ await queryFulfilled;
401
+ } catch {
402
+ patchResult.undo();
403
+ }
365
404
  }
366
405
  }),
367
406
  unpublishDocument: builder.mutation({
@@ -431,20 +470,39 @@ const buildValidParams = (query) => {
431
470
  const isBaseQueryError = (error) => {
432
471
  return error.name !== void 0;
433
472
  };
434
- const createYupSchema = (attributes = {}, components = {}) => {
473
+ const arrayValidator = (attribute, options) => ({
474
+ message: translatedErrors.required,
475
+ test(value) {
476
+ if (options.status === "draft") {
477
+ return true;
478
+ }
479
+ if (!attribute.required) {
480
+ return true;
481
+ }
482
+ if (!value) {
483
+ return false;
484
+ }
485
+ if (Array.isArray(value) && value.length === 0) {
486
+ return false;
487
+ }
488
+ return true;
489
+ }
490
+ });
491
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
435
492
  const createModelSchema = (attributes2) => yup.object().shape(
436
493
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
437
494
  if (DOCUMENT_META_FIELDS.includes(name)) {
438
495
  return acc;
439
496
  }
440
497
  const validations = [
498
+ addNullableValidation,
441
499
  addRequiredValidation,
442
500
  addMinLengthValidation,
443
501
  addMaxLengthValidation,
444
502
  addMinValidation,
445
503
  addMaxValidation,
446
504
  addRegexValidation
447
- ].map((fn) => fn(attribute));
505
+ ].map((fn) => fn(attribute, options));
448
506
  const transformSchema = pipe(...validations);
449
507
  switch (attribute.type) {
450
508
  case "component": {
@@ -454,12 +512,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
454
512
  ...acc,
455
513
  [name]: transformSchema(
456
514
  yup.array().of(createModelSchema(attributes3).nullable(false))
457
- )
515
+ ).test(arrayValidator(attribute, options))
458
516
  };
459
517
  } else {
460
518
  return {
461
519
  ...acc,
462
- [name]: transformSchema(createModelSchema(attributes3))
520
+ [name]: transformSchema(createModelSchema(attributes3).nullable())
463
521
  };
464
522
  }
465
523
  }
@@ -481,7 +539,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
481
539
  }
482
540
  )
483
541
  )
484
- )
542
+ ).test(arrayValidator(attribute, options))
485
543
  };
486
544
  case "relation":
487
545
  return {
@@ -493,7 +551,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
493
551
  } else if (Array.isArray(value)) {
494
552
  return yup.array().of(
495
553
  yup.object().shape({
496
- id: yup.string().required()
554
+ id: yup.number().required()
497
555
  })
498
556
  );
499
557
  } else if (typeof value === "object") {
@@ -545,6 +603,14 @@ const createAttributeSchema = (attribute) => {
545
603
  if (!value || typeof value === "string" && value.length === 0) {
546
604
  return true;
547
605
  }
606
+ if (typeof value === "object") {
607
+ try {
608
+ JSON.stringify(value);
609
+ return true;
610
+ } catch (err) {
611
+ return false;
612
+ }
613
+ }
548
614
  try {
549
615
  JSON.parse(value);
550
616
  return true;
@@ -563,13 +629,7 @@ const createAttributeSchema = (attribute) => {
563
629
  return yup.mixed();
564
630
  }
565
631
  };
566
- const addRequiredValidation = (attribute) => (schema) => {
567
- if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
568
- return schema.min(1, translatedErrors.required);
569
- }
570
- if (attribute.required && attribute.type !== "relation") {
571
- return schema.required(translatedErrors.required);
572
- }
632
+ const nullableSchema = (schema) => {
573
633
  return schema?.nullable ? schema.nullable() : (
574
634
  // In some cases '.nullable' will not be available on the schema.
575
635
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -577,7 +637,22 @@ const addRequiredValidation = (attribute) => (schema) => {
577
637
  schema
578
638
  );
579
639
  };
580
- const addMinLengthValidation = (attribute) => (schema) => {
640
+ const addNullableValidation = () => (schema) => {
641
+ return nullableSchema(schema);
642
+ };
643
+ const addRequiredValidation = (attribute, options) => (schema) => {
644
+ if (options.status === "draft" || !attribute.required) {
645
+ return schema;
646
+ }
647
+ if (attribute.required && "required" in schema) {
648
+ return schema.required(translatedErrors.required);
649
+ }
650
+ return schema;
651
+ };
652
+ const addMinLengthValidation = (attribute, options) => (schema) => {
653
+ if (options.status === "draft") {
654
+ return schema;
655
+ }
581
656
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
582
657
  return schema.min(attribute.minLength, {
583
658
  ...translatedErrors.minLength,
@@ -599,32 +674,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
599
674
  }
600
675
  return schema;
601
676
  };
602
- const addMinValidation = (attribute) => (schema) => {
603
- if ("min" in attribute) {
677
+ const addMinValidation = (attribute, options) => (schema) => {
678
+ if (options.status === "draft") {
679
+ return schema;
680
+ }
681
+ if ("min" in attribute && "min" in schema) {
604
682
  const min = toInteger(attribute.min);
605
- if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
606
- if (!attribute.required && "test" in schema && min) {
607
- return schema.test(
608
- "custom-min",
609
- {
610
- ...translatedErrors.min,
611
- values: {
612
- min: attribute.min
613
- }
614
- },
615
- (value) => {
616
- if (!value) {
617
- return true;
618
- }
619
- if (Array.isArray(value) && value.length === 0) {
620
- return true;
621
- }
622
- return value.length >= min;
623
- }
624
- );
625
- }
626
- }
627
- if ("min" in schema && min) {
683
+ if (min) {
628
684
  return schema.min(min, {
629
685
  ...translatedErrors.min,
630
686
  values: {
@@ -742,19 +798,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
742
798
  }, {});
743
799
  return componentsByKey;
744
800
  };
745
- const useDocument = (args, opts) => {
801
+ const HOOKS = {
802
+ /**
803
+ * Hook that allows to mutate the displayed headers of the list view table
804
+ * @constant
805
+ * @type {string}
806
+ */
807
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
808
+ /**
809
+ * Hook that allows to mutate the CM's collection types links pre-set filters
810
+ * @constant
811
+ * @type {string}
812
+ */
813
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
814
+ /**
815
+ * Hook that allows to mutate the CM's edit view layout
816
+ * @constant
817
+ * @type {string}
818
+ */
819
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
820
+ /**
821
+ * Hook that allows to mutate the CM's single types links pre-set filters
822
+ * @constant
823
+ * @type {string}
824
+ */
825
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
826
+ };
827
+ const contentTypesApi = contentManagerApi.injectEndpoints({
828
+ endpoints: (builder) => ({
829
+ getContentTypeConfiguration: builder.query({
830
+ query: (uid) => ({
831
+ url: `/content-manager/content-types/${uid}/configuration`,
832
+ method: "GET"
833
+ }),
834
+ transformResponse: (response) => response.data,
835
+ providesTags: (_result, _error, uid) => [
836
+ { type: "ContentTypesConfiguration", id: uid },
837
+ { type: "ContentTypeSettings", id: "LIST" }
838
+ ]
839
+ }),
840
+ getAllContentTypeSettings: builder.query({
841
+ query: () => "/content-manager/content-types-settings",
842
+ transformResponse: (response) => response.data,
843
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
844
+ }),
845
+ updateContentTypeConfiguration: builder.mutation({
846
+ query: ({ uid, ...body }) => ({
847
+ url: `/content-manager/content-types/${uid}/configuration`,
848
+ method: "PUT",
849
+ data: body
850
+ }),
851
+ transformResponse: (response) => response.data,
852
+ invalidatesTags: (_result, _error, { uid }) => [
853
+ { type: "ContentTypesConfiguration", id: uid },
854
+ { type: "ContentTypeSettings", id: "LIST" },
855
+ // Is this necessary?
856
+ { type: "InitialData" }
857
+ ]
858
+ })
859
+ })
860
+ });
861
+ const {
862
+ useGetContentTypeConfigurationQuery,
863
+ useGetAllContentTypeSettingsQuery,
864
+ useUpdateContentTypeConfigurationMutation
865
+ } = contentTypesApi;
866
+ const checkIfAttributeIsDisplayable = (attribute) => {
867
+ const { type } = attribute;
868
+ if (type === "relation") {
869
+ return !attribute.relation.toLowerCase().includes("morph");
870
+ }
871
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
872
+ };
873
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
874
+ if (!mainFieldName) {
875
+ return void 0;
876
+ }
877
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
878
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
879
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
880
+ );
881
+ return {
882
+ name: mainFieldName,
883
+ type: mainFieldType ?? "string"
884
+ };
885
+ };
886
+ const DEFAULT_SETTINGS = {
887
+ bulkable: false,
888
+ filterable: false,
889
+ searchable: false,
890
+ pagination: false,
891
+ defaultSortBy: "",
892
+ defaultSortOrder: "asc",
893
+ mainField: "id",
894
+ pageSize: 10
895
+ };
896
+ const useDocumentLayout = (model) => {
897
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
898
+ const [{ query }] = useQueryParams();
899
+ const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
746
900
  const { toggleNotification } = useNotification();
747
901
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
902
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
748
903
  const {
749
- currentData: data,
750
- isLoading: isLoadingDocument,
751
- isFetching: isFetchingDocument,
752
- error
753
- } = useGetDocumentQuery(args, {
754
- ...opts,
755
- skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
756
- });
757
- const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
904
+ data,
905
+ isLoading: isLoadingConfigs,
906
+ error,
907
+ isFetching: isFetchingConfigs
908
+ } = useGetContentTypeConfigurationQuery(model);
909
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
758
910
  React.useEffect(() => {
759
911
  if (error) {
760
912
  toggleNotification({
@@ -762,83 +914,341 @@ const useDocument = (args, opts) => {
762
914
  message: formatAPIError(error)
763
915
  });
764
916
  }
765
- }, [toggleNotification, error, formatAPIError, args.collectionType]);
766
- const validationSchema = React.useMemo(() => {
767
- if (!schema) {
768
- return null;
769
- }
770
- return createYupSchema(schema.attributes, components);
771
- }, [schema, components]);
772
- const validate = React.useCallback(
773
- (document) => {
774
- if (!validationSchema) {
775
- throw new Error(
776
- "There is no validation schema generated, this is likely due to the schema not being loaded yet."
777
- );
778
- }
779
- try {
780
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
781
- return null;
782
- } catch (error2) {
783
- if (error2 instanceof ValidationError) {
784
- return getYupValidationErrors(error2);
785
- }
786
- throw error2;
787
- }
917
+ }, [error, formatAPIError, toggleNotification]);
918
+ const editLayout = React.useMemo(
919
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
920
+ layout: [],
921
+ components: {},
922
+ metadatas: {},
923
+ options: {},
924
+ settings: DEFAULT_SETTINGS
788
925
  },
789
- [validationSchema]
926
+ [data, isLoading, schemas, schema, components]
927
+ );
928
+ const listLayout = React.useMemo(() => {
929
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
930
+ layout: [],
931
+ metadatas: {},
932
+ options: {},
933
+ settings: DEFAULT_SETTINGS
934
+ };
935
+ }, [data, isLoading, schemas, schema, components]);
936
+ const { layout: edit } = React.useMemo(
937
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
938
+ layout: editLayout,
939
+ query
940
+ }),
941
+ [editLayout, query, runHookWaterfall]
790
942
  );
791
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
792
943
  return {
793
- components,
794
- document: data?.data,
795
- meta: data?.meta,
944
+ error,
796
945
  isLoading,
797
- schema,
798
- validate
799
- };
800
- };
801
- const useDoc = () => {
802
- const { id, slug, collectionType, origin } = useParams();
803
- const [{ query }] = useQueryParams();
804
- const params = React.useMemo(() => buildValidParams(query), [query]);
805
- if (!collectionType) {
806
- throw new Error("Could not find collectionType in url params");
807
- }
808
- if (!slug) {
809
- throw new Error("Could not find model in url params");
810
- }
811
- return {
812
- collectionType,
813
- model: slug,
814
- id: origin || id === "create" ? void 0 : id,
815
- ...useDocument(
816
- { documentId: origin || id, model: slug, collectionType, params },
817
- {
818
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
819
- }
820
- )
946
+ edit,
947
+ list: listLayout
821
948
  };
822
949
  };
823
- const prefixPluginTranslations = (trad, pluginId) => {
824
- if (!pluginId) {
825
- throw new TypeError("pluginId can't be empty");
826
- }
827
- return Object.keys(trad).reduce((acc, current) => {
828
- acc[`${pluginId}.${current}`] = trad[current];
829
- return acc;
830
- }, {});
831
- };
832
- const getTranslation = (id) => `content-manager.${id}`;
833
- const DEFAULT_UNEXPECTED_ERROR_MSG = {
834
- id: "notification.error",
835
- defaultMessage: "An error occurred, please try again"
950
+ const useDocLayout = () => {
951
+ const { model } = useDoc();
952
+ return useDocumentLayout(model);
953
+ };
954
+ const formatEditLayout = (data, {
955
+ schemas,
956
+ schema,
957
+ components
958
+ }) => {
959
+ let currentPanelIndex = 0;
960
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
961
+ data.contentType.layouts.edit,
962
+ schema?.attributes,
963
+ data.contentType.metadatas,
964
+ { configurations: data.components, schemas: components },
965
+ schemas
966
+ ).reduce((panels, row) => {
967
+ if (row.some((field) => field.type === "dynamiczone")) {
968
+ panels.push([row]);
969
+ currentPanelIndex += 2;
970
+ } else {
971
+ if (!panels[currentPanelIndex]) {
972
+ panels.push([]);
973
+ }
974
+ panels[currentPanelIndex].push(row);
975
+ }
976
+ return panels;
977
+ }, []);
978
+ const componentEditAttributes = Object.entries(data.components).reduce(
979
+ (acc, [uid, configuration]) => {
980
+ acc[uid] = {
981
+ layout: convertEditLayoutToFieldLayouts(
982
+ configuration.layouts.edit,
983
+ components[uid].attributes,
984
+ configuration.metadatas,
985
+ { configurations: data.components, schemas: components }
986
+ ),
987
+ settings: {
988
+ ...configuration.settings,
989
+ icon: components[uid].info.icon,
990
+ displayName: components[uid].info.displayName
991
+ }
992
+ };
993
+ return acc;
994
+ },
995
+ {}
996
+ );
997
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
998
+ (acc, [attribute, metadata]) => {
999
+ return {
1000
+ ...acc,
1001
+ [attribute]: metadata.edit
1002
+ };
1003
+ },
1004
+ {}
1005
+ );
1006
+ return {
1007
+ layout: panelledEditAttributes,
1008
+ components: componentEditAttributes,
1009
+ metadatas: editMetadatas,
1010
+ settings: {
1011
+ ...data.contentType.settings,
1012
+ displayName: schema?.info.displayName
1013
+ },
1014
+ options: {
1015
+ ...schema?.options,
1016
+ ...schema?.pluginOptions,
1017
+ ...data.contentType.options
1018
+ }
1019
+ };
1020
+ };
1021
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1022
+ return rows.map(
1023
+ (row) => row.map((field) => {
1024
+ const attribute = attributes[field.name];
1025
+ if (!attribute) {
1026
+ return null;
1027
+ }
1028
+ const { edit: metadata } = metadatas[field.name];
1029
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1030
+ return {
1031
+ attribute,
1032
+ disabled: !metadata.editable,
1033
+ hint: metadata.description,
1034
+ label: metadata.label ?? "",
1035
+ name: field.name,
1036
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1037
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1038
+ schemas,
1039
+ components: components?.schemas ?? {}
1040
+ }),
1041
+ placeholder: metadata.placeholder ?? "",
1042
+ required: attribute.required ?? false,
1043
+ size: field.size,
1044
+ unique: "unique" in attribute ? attribute.unique : false,
1045
+ visible: metadata.visible ?? true,
1046
+ type: attribute.type
1047
+ };
1048
+ }).filter((field) => field !== null)
1049
+ );
1050
+ };
1051
+ const formatListLayout = (data, {
1052
+ schemas,
1053
+ schema,
1054
+ components
1055
+ }) => {
1056
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1057
+ (acc, [attribute, metadata]) => {
1058
+ return {
1059
+ ...acc,
1060
+ [attribute]: metadata.list
1061
+ };
1062
+ },
1063
+ {}
1064
+ );
1065
+ const listAttributes = convertListLayoutToFieldLayouts(
1066
+ data.contentType.layouts.list,
1067
+ schema?.attributes,
1068
+ listMetadatas,
1069
+ { configurations: data.components, schemas: components },
1070
+ schemas
1071
+ );
1072
+ return {
1073
+ layout: listAttributes,
1074
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1075
+ metadatas: listMetadatas,
1076
+ options: {
1077
+ ...schema?.options,
1078
+ ...schema?.pluginOptions,
1079
+ ...data.contentType.options
1080
+ }
1081
+ };
1082
+ };
1083
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1084
+ return columns.map((name) => {
1085
+ const attribute = attributes[name];
1086
+ if (!attribute) {
1087
+ return null;
1088
+ }
1089
+ const metadata = metadatas[name];
1090
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1091
+ return {
1092
+ attribute,
1093
+ label: metadata.label ?? "",
1094
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1095
+ schemas,
1096
+ components: components?.schemas ?? {}
1097
+ }),
1098
+ name,
1099
+ searchable: metadata.searchable ?? true,
1100
+ sortable: metadata.sortable ?? true
1101
+ };
1102
+ }).filter((field) => field !== null);
1103
+ };
1104
+ const useDocument = (args, opts) => {
1105
+ const { toggleNotification } = useNotification();
1106
+ const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
1107
+ const {
1108
+ currentData: data,
1109
+ isLoading: isLoadingDocument,
1110
+ isFetching: isFetchingDocument,
1111
+ error
1112
+ } = useGetDocumentQuery(args, {
1113
+ ...opts,
1114
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1115
+ });
1116
+ const {
1117
+ components,
1118
+ schema,
1119
+ schemas,
1120
+ isLoading: isLoadingSchema
1121
+ } = useContentTypeSchema(args.model);
1122
+ React.useEffect(() => {
1123
+ if (error) {
1124
+ toggleNotification({
1125
+ type: "danger",
1126
+ message: formatAPIError(error)
1127
+ });
1128
+ }
1129
+ }, [toggleNotification, error, formatAPIError, args.collectionType]);
1130
+ const validationSchema = React.useMemo(() => {
1131
+ if (!schema) {
1132
+ return null;
1133
+ }
1134
+ return createYupSchema(schema.attributes, components);
1135
+ }, [schema, components]);
1136
+ const validate = React.useCallback(
1137
+ (document) => {
1138
+ if (!validationSchema) {
1139
+ throw new Error(
1140
+ "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1141
+ );
1142
+ }
1143
+ try {
1144
+ validationSchema.validateSync(document, { abortEarly: false, strict: true });
1145
+ return null;
1146
+ } catch (error2) {
1147
+ if (error2 instanceof ValidationError) {
1148
+ return getYupValidationErrors(error2);
1149
+ }
1150
+ throw error2;
1151
+ }
1152
+ },
1153
+ [validationSchema]
1154
+ );
1155
+ const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1156
+ const hasError = !!error;
1157
+ return {
1158
+ components,
1159
+ document: data?.data,
1160
+ meta: data?.meta,
1161
+ isLoading,
1162
+ hasError,
1163
+ schema,
1164
+ schemas,
1165
+ validate
1166
+ };
1167
+ };
1168
+ const useDoc = () => {
1169
+ const { id, slug, collectionType, origin } = useParams();
1170
+ const [{ query }] = useQueryParams();
1171
+ const params = React.useMemo(() => buildValidParams(query), [query]);
1172
+ if (!collectionType) {
1173
+ throw new Error("Could not find collectionType in url params");
1174
+ }
1175
+ if (!slug) {
1176
+ throw new Error("Could not find model in url params");
1177
+ }
1178
+ const document = useDocument(
1179
+ { documentId: origin || id, model: slug, collectionType, params },
1180
+ {
1181
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1182
+ }
1183
+ );
1184
+ const returnId = origin || id === "create" ? void 0 : id;
1185
+ return {
1186
+ collectionType,
1187
+ model: slug,
1188
+ id: returnId,
1189
+ ...document
1190
+ };
1191
+ };
1192
+ const useContentManagerContext = () => {
1193
+ const {
1194
+ collectionType,
1195
+ model,
1196
+ id,
1197
+ components,
1198
+ isLoading: isLoadingDoc,
1199
+ schema,
1200
+ schemas
1201
+ } = useDoc();
1202
+ const layout = useDocumentLayout(model);
1203
+ const form = useForm("useContentManagerContext", (state) => state);
1204
+ const isSingleType = collectionType === SINGLE_TYPES;
1205
+ const slug = model;
1206
+ const isCreatingEntry = id === "create";
1207
+ useContentTypeSchema();
1208
+ const isLoading = isLoadingDoc || layout.isLoading;
1209
+ const error = layout.error;
1210
+ return {
1211
+ error,
1212
+ isLoading,
1213
+ // Base metadata
1214
+ model,
1215
+ collectionType,
1216
+ id,
1217
+ slug,
1218
+ isCreatingEntry,
1219
+ isSingleType,
1220
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1221
+ // All schema infos
1222
+ components,
1223
+ contentType: schema,
1224
+ contentTypes: schemas,
1225
+ // Form state
1226
+ form,
1227
+ // layout infos
1228
+ layout
1229
+ };
1230
+ };
1231
+ const prefixPluginTranslations = (trad, pluginId) => {
1232
+ if (!pluginId) {
1233
+ throw new TypeError("pluginId can't be empty");
1234
+ }
1235
+ return Object.keys(trad).reduce((acc, current) => {
1236
+ acc[`${pluginId}.${current}`] = trad[current];
1237
+ return acc;
1238
+ }, {});
1239
+ };
1240
+ const getTranslation = (id) => `content-manager.${id}`;
1241
+ const DEFAULT_UNEXPECTED_ERROR_MSG = {
1242
+ id: "notification.error",
1243
+ defaultMessage: "An error occurred, please try again"
836
1244
  };
837
1245
  const useDocumentActions = () => {
838
1246
  const { toggleNotification } = useNotification();
839
1247
  const { formatMessage } = useIntl();
840
1248
  const { trackUsage } = useTracking();
841
1249
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
1250
+ const navigate = useNavigate();
1251
+ const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
842
1252
  const [deleteDocument] = useDeleteDocumentMutation();
843
1253
  const _delete = React.useCallback(
844
1254
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -1153,6 +1563,7 @@ const useDocumentActions = () => {
1153
1563
  defaultMessage: "Saved document"
1154
1564
  })
1155
1565
  });
1566
+ setCurrentStep("contentManager.success");
1156
1567
  return res.data;
1157
1568
  } catch (err) {
1158
1569
  toggleNotification({
@@ -1174,7 +1585,6 @@ const useDocumentActions = () => {
1174
1585
  sourceId
1175
1586
  });
1176
1587
  if ("error" in res) {
1177
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1178
1588
  return { error: res.error };
1179
1589
  }
1180
1590
  toggleNotification({
@@ -1193,7 +1603,7 @@ const useDocumentActions = () => {
1193
1603
  throw err;
1194
1604
  }
1195
1605
  },
1196
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1606
+ [autoCloneDocument, formatMessage, toggleNotification]
1197
1607
  );
1198
1608
  const [cloneDocument] = useCloneDocumentMutation();
1199
1609
  const clone = React.useCallback(
@@ -1219,6 +1629,7 @@ const useDocumentActions = () => {
1219
1629
  defaultMessage: "Cloned document"
1220
1630
  })
1221
1631
  });
1632
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1222
1633
  return res.data;
1223
1634
  } catch (err) {
1224
1635
  toggleNotification({
@@ -1229,7 +1640,7 @@ const useDocumentActions = () => {
1229
1640
  throw err;
1230
1641
  }
1231
1642
  },
1232
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1643
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1233
1644
  );
1234
1645
  const [getDoc] = useLazyGetDocumentQuery();
1235
1646
  const getDocument = React.useCallback(
@@ -1255,7 +1666,7 @@ const useDocumentActions = () => {
1255
1666
  };
1256
1667
  };
1257
1668
  const ProtectedHistoryPage = lazy(
1258
- () => import("./History-CBNGU7a-.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1669
+ () => import("./History-BpLIu67W.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1259
1670
  );
1260
1671
  const routes$1 = [
1261
1672
  {
@@ -1268,31 +1679,31 @@ const routes$1 = [
1268
1679
  }
1269
1680
  ];
1270
1681
  const ProtectedEditViewPage = lazy(
1271
- () => import("./EditViewPage-DlLEyUL6.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1682
+ () => import("./EditViewPage-al5OO1NR.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1272
1683
  );
1273
1684
  const ProtectedListViewPage = lazy(
1274
- () => import("./ListViewPage-DecLrYV6.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1685
+ () => import("./ListViewPage-BbXYNI0v.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1275
1686
  );
1276
1687
  const ProtectedListConfiguration = lazy(
1277
- () => import("./ListConfigurationPage-5dr4qpue.mjs").then((mod) => ({
1688
+ () => import("./ListConfigurationPage-DOqj5f8Y.mjs").then((mod) => ({
1278
1689
  default: mod.ProtectedListConfiguration
1279
1690
  }))
1280
1691
  );
1281
1692
  const ProtectedEditConfigurationPage = lazy(
1282
- () => import("./EditConfigurationPage-ZO0vOO8q.mjs").then((mod) => ({
1693
+ () => import("./EditConfigurationPage-W07CEdm2.mjs").then((mod) => ({
1283
1694
  default: mod.ProtectedEditConfigurationPage
1284
1695
  }))
1285
1696
  );
1286
1697
  const ProtectedComponentConfigurationPage = lazy(
1287
- () => import("./ComponentConfigurationPage-B1bIXVuX.mjs").then((mod) => ({
1698
+ () => import("./ComponentConfigurationPage-jmWwucg_.mjs").then((mod) => ({
1288
1699
  default: mod.ProtectedComponentConfigurationPage
1289
1700
  }))
1290
1701
  );
1291
1702
  const NoPermissions = lazy(
1292
- () => import("./NoPermissionsPage-CM5UD8ee.mjs").then((mod) => ({ default: mod.NoPermissions }))
1703
+ () => import("./NoPermissionsPage-Km0Vk5Wp.mjs").then((mod) => ({ default: mod.NoPermissions }))
1293
1704
  );
1294
1705
  const NoContentType = lazy(
1295
- () => import("./NoContentTypePage-CiIcfYsd.mjs").then((mod) => ({ default: mod.NoContentType }))
1706
+ () => import("./NoContentTypePage-w2Q0VVOT.mjs").then((mod) => ({ default: mod.NoContentType }))
1296
1707
  );
1297
1708
  const CollectionTypePages = () => {
1298
1709
  const { collectionType } = useParams();
@@ -1406,12 +1817,14 @@ const DocumentActionButton = (action) => {
1406
1817
  /* @__PURE__ */ jsx(
1407
1818
  Button,
1408
1819
  {
1409
- flex: 1,
1820
+ flex: "auto",
1410
1821
  startIcon: action.icon,
1411
1822
  disabled: action.disabled,
1412
1823
  onClick: handleClick(action),
1413
1824
  justifyContent: "center",
1414
1825
  variant: action.variant || "default",
1826
+ paddingTop: "7px",
1827
+ paddingBottom: "7px",
1415
1828
  children: action.label
1416
1829
  }
1417
1830
  ),
@@ -1476,9 +1889,9 @@ const DocumentActionsMenu = ({
1476
1889
  disabled: isDisabled,
1477
1890
  size: "S",
1478
1891
  endIcon: null,
1479
- paddingTop: "7px",
1480
- paddingLeft: "9px",
1481
- paddingRight: "9px",
1892
+ paddingTop: "4px",
1893
+ paddingLeft: "7px",
1894
+ paddingRight: "7px",
1482
1895
  variant,
1483
1896
  children: [
1484
1897
  /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
@@ -1489,7 +1902,7 @@ const DocumentActionsMenu = ({
1489
1902
  ]
1490
1903
  }
1491
1904
  ),
1492
- /* @__PURE__ */ jsxs(Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1905
+ /* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
1493
1906
  actions2.map((action) => {
1494
1907
  return /* @__PURE__ */ jsx(
1495
1908
  Menu.Item,
@@ -1498,10 +1911,25 @@ const DocumentActionsMenu = ({
1498
1911
  onSelect: handleClick(action),
1499
1912
  display: "block",
1500
1913
  children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
1501
- /* @__PURE__ */ jsxs(Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1502
- /* @__PURE__ */ jsx(Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1503
- action.label
1504
- ] }),
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
+ ),
1505
1933
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
1506
1934
  Flex,
1507
1935
  {
@@ -1598,11 +2026,11 @@ const DocumentActionConfirmDialog = ({
1598
2026
  /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
1599
2027
  /* @__PURE__ */ jsx(Dialog.Body, { children: content }),
1600
2028
  /* @__PURE__ */ jsxs(Dialog.Footer, { children: [
1601
- /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
2029
+ /* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
1602
2030
  id: "app.components.Button.cancel",
1603
2031
  defaultMessage: "Cancel"
1604
2032
  }) }) }),
1605
- /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
2033
+ /* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
1606
2034
  id: "app.components.Button.confirm",
1607
2035
  defaultMessage: "Confirm"
1608
2036
  }) })
@@ -1625,10 +2053,22 @@ const DocumentActionModal = ({
1625
2053
  };
1626
2054
  return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
1627
2055
  /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
1628
- /* @__PURE__ */ jsx(Modal.Body, { children: typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content }),
1629
- /* @__PURE__ */ jsx(Modal.Footer, { children: typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer })
2056
+ typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
2057
+ typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
1630
2058
  ] }) });
1631
2059
  };
2060
+ const transformData = (data) => {
2061
+ if (Array.isArray(data)) {
2062
+ return data.map(transformData);
2063
+ }
2064
+ if (typeof data === "object" && data !== null) {
2065
+ if ("apiData" in data) {
2066
+ return data.apiData;
2067
+ }
2068
+ return mapValues(transformData)(data);
2069
+ }
2070
+ return data;
2071
+ };
1632
2072
  const PublishAction$1 = ({
1633
2073
  activeTab,
1634
2074
  documentId,
@@ -1641,12 +2081,10 @@ const PublishAction$1 = ({
1641
2081
  const navigate = useNavigate();
1642
2082
  const { toggleNotification } = useNotification();
1643
2083
  const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
2084
+ const isListView = useMatch(LIST_PATH) !== null;
1644
2085
  const isCloning = useMatch(CLONE_PATH) !== null;
1645
2086
  const { formatMessage } = useIntl();
1646
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1647
- "PublishAction",
1648
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1649
- );
2087
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1650
2088
  const { publish } = useDocumentActions();
1651
2089
  const [
1652
2090
  countDraftRelations,
@@ -1698,24 +2136,25 @@ const PublishAction$1 = ({
1698
2136
  }
1699
2137
  }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
1700
2138
  React.useEffect(() => {
1701
- if (documentId) {
1702
- const fetchDraftRelationsCount = async () => {
1703
- const { data, error } = await countDraftRelations({
1704
- collectionType,
1705
- model,
1706
- documentId,
1707
- params
1708
- });
1709
- if (error) {
1710
- throw error;
1711
- }
1712
- if (data) {
1713
- setServerCountOfDraftRelations(data.data);
1714
- }
1715
- };
1716
- fetchDraftRelationsCount();
2139
+ if (!document || !document.documentId || isListView) {
2140
+ return;
1717
2141
  }
1718
- }, [documentId, countDraftRelations, collectionType, model, params]);
2142
+ const fetchDraftRelationsCount = async () => {
2143
+ const { data, error } = await countDraftRelations({
2144
+ collectionType,
2145
+ model,
2146
+ documentId,
2147
+ params
2148
+ });
2149
+ if (error) {
2150
+ throw error;
2151
+ }
2152
+ if (data) {
2153
+ setServerCountOfDraftRelations(data.data);
2154
+ }
2155
+ };
2156
+ fetchDraftRelationsCount();
2157
+ }, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
1719
2158
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1720
2159
  if (!schema?.options?.draftAndPublish) {
1721
2160
  return null;
@@ -1723,7 +2162,9 @@ const PublishAction$1 = ({
1723
2162
  const performPublish = async () => {
1724
2163
  setSubmitting(true);
1725
2164
  try {
1726
- const { errors } = await validate();
2165
+ const { errors } = await validate(true, {
2166
+ status: "published"
2167
+ });
1727
2168
  if (errors) {
1728
2169
  toggleNotification({
1729
2170
  type: "danger",
@@ -1741,7 +2182,7 @@ const PublishAction$1 = ({
1741
2182
  documentId,
1742
2183
  params
1743
2184
  },
1744
- formValues
2185
+ transformData(formValues)
1745
2186
  );
1746
2187
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1747
2188
  navigate({
@@ -1756,7 +2197,8 @@ const PublishAction$1 = ({
1756
2197
  }
1757
2198
  };
1758
2199
  const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1759
- const hasDraftRelations = totalDraftRelations > 0;
2200
+ const enableDraftRelationsCount = false;
2201
+ const hasDraftRelations = enableDraftRelationsCount;
1760
2202
  return {
1761
2203
  /**
1762
2204
  * Disabled when:
@@ -1766,18 +2208,13 @@ const PublishAction$1 = ({
1766
2208
  * - the document is already published & not modified
1767
2209
  * - the document is being created & not modified
1768
2210
  * - the user doesn't have the permission to publish
1769
- * - the user doesn't have the permission to create a new document
1770
- * - the user doesn't have the permission to update the document
1771
2211
  */
1772
- disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
2212
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1773
2213
  label: formatMessage({
1774
2214
  id: "app.utils.publish",
1775
2215
  defaultMessage: "Publish"
1776
2216
  }),
1777
2217
  onClick: async () => {
1778
- if (hasDraftRelations) {
1779
- return;
1780
- }
1781
2218
  await performPublish();
1782
2219
  },
1783
2220
  dialog: hasDraftRelations ? {
@@ -1816,10 +2253,6 @@ const UpdateAction = ({
1816
2253
  const cloneMatch = useMatch(CLONE_PATH);
1817
2254
  const isCloning = cloneMatch !== null;
1818
2255
  const { formatMessage } = useIntl();
1819
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1820
- canCreate: canCreate2,
1821
- canUpdate: canUpdate2
1822
- }));
1823
2256
  const { create, update, clone } = useDocumentActions();
1824
2257
  const [{ query, rawQuery }] = useQueryParams();
1825
2258
  const params = React.useMemo(() => buildValidParams(query), [query]);
@@ -1836,10 +2269,8 @@ const UpdateAction = ({
1836
2269
  * - the form is submitting
1837
2270
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1838
2271
  * - the active tab is the published tab
1839
- * - the user doesn't have the permission to create a new document
1840
- * - the user doesn't have the permission to update the document
1841
2272
  */
1842
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
2273
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1843
2274
  label: formatMessage({
1844
2275
  id: "content-manager.containers.Edit.save",
1845
2276
  defaultMessage: "Save"
@@ -1847,7 +2278,9 @@ const UpdateAction = ({
1847
2278
  onClick: async () => {
1848
2279
  setSubmitting(true);
1849
2280
  try {
1850
- const { errors } = await validate();
2281
+ const { errors } = await validate(true, {
2282
+ status: "draft"
2283
+ });
1851
2284
  if (errors) {
1852
2285
  toggleNotification({
1853
2286
  type: "danger",
@@ -1865,13 +2298,16 @@ const UpdateAction = ({
1865
2298
  documentId: cloneMatch.params.origin,
1866
2299
  params
1867
2300
  },
1868
- document
2301
+ transformData(document)
1869
2302
  );
1870
2303
  if ("data" in res) {
1871
- navigate({
1872
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1873
- search: rawQuery
1874
- });
2304
+ navigate(
2305
+ {
2306
+ pathname: `../${res.data.documentId}`,
2307
+ search: rawQuery
2308
+ },
2309
+ { relative: "path" }
2310
+ );
1875
2311
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1876
2312
  setErrors(formatValidationErrors(res.error));
1877
2313
  }
@@ -1883,7 +2319,7 @@ const UpdateAction = ({
1883
2319
  documentId,
1884
2320
  params
1885
2321
  },
1886
- document
2322
+ transformData(document)
1887
2323
  );
1888
2324
  if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1889
2325
  setErrors(formatValidationErrors(res.error));
@@ -1896,15 +2332,15 @@ const UpdateAction = ({
1896
2332
  model,
1897
2333
  params
1898
2334
  },
1899
- document
2335
+ transformData(document)
1900
2336
  );
1901
2337
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1902
2338
  navigate(
1903
2339
  {
1904
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
2340
+ pathname: `../${res.data.documentId}`,
1905
2341
  search: rawQuery
1906
2342
  },
1907
- { replace: true }
2343
+ { replace: true, relative: "path" }
1908
2344
  );
1909
2345
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1910
2346
  setErrors(formatValidationErrors(res.error));
@@ -1949,7 +2385,7 @@ const UnpublishAction$1 = ({
1949
2385
  id: "app.utils.unpublish",
1950
2386
  defaultMessage: "Unpublish"
1951
2387
  }),
1952
- icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
2388
+ icon: /* @__PURE__ */ jsx(Cross, {}),
1953
2389
  onClick: async () => {
1954
2390
  if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
1955
2391
  if (!documentId) {
@@ -2061,7 +2497,7 @@ const DiscardAction = ({
2061
2497
  id: "content-manager.actions.discard.label",
2062
2498
  defaultMessage: "Discard changes"
2063
2499
  }),
2064
- icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
2500
+ icon: /* @__PURE__ */ jsx(Cross, {}),
2065
2501
  position: ["panel", "table-row"],
2066
2502
  variant: "danger",
2067
2503
  dialog: {
@@ -2089,11 +2525,6 @@ const DiscardAction = ({
2089
2525
  };
2090
2526
  };
2091
2527
  DiscardAction.type = "discard";
2092
- const StyledCrossCircle = styled(CrossCircle)`
2093
- path {
2094
- fill: currentColor;
2095
- }
2096
- `;
2097
2528
  const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
2098
2529
  const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
2099
2530
  const RelativeTime = React.forwardRef(
@@ -2141,7 +2572,7 @@ const getDisplayName = ({
2141
2572
  };
2142
2573
  const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
2143
2574
  const DocumentStatus = ({ status = "draft", ...restProps }) => {
2144
- const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
2575
+ const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
2145
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) }) });
2146
2577
  };
2147
2578
  const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
@@ -2240,12 +2671,12 @@ const Information = ({ activeTab }) => {
2240
2671
  isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
2241
2672
  label: formatMessage({
2242
2673
  id: "content-manager.containers.edit.information.last-published.label",
2243
- defaultMessage: "Last published"
2674
+ defaultMessage: "Published"
2244
2675
  }),
2245
2676
  value: formatMessage(
2246
2677
  {
2247
2678
  id: "content-manager.containers.edit.information.last-published.value",
2248
- defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
2679
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2249
2680
  },
2250
2681
  {
2251
2682
  time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
@@ -2258,12 +2689,12 @@ const Information = ({ activeTab }) => {
2258
2689
  isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
2259
2690
  label: formatMessage({
2260
2691
  id: "content-manager.containers.edit.information.last-draft.label",
2261
- defaultMessage: "Last draft"
2692
+ defaultMessage: "Updated"
2262
2693
  }),
2263
2694
  value: formatMessage(
2264
2695
  {
2265
2696
  id: "content-manager.containers.edit.information.last-draft.value",
2266
- defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
2697
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2267
2698
  },
2268
2699
  {
2269
2700
  time: /* @__PURE__ */ jsx(
@@ -2281,12 +2712,12 @@ const Information = ({ activeTab }) => {
2281
2712
  isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
2282
2713
  label: formatMessage({
2283
2714
  id: "content-manager.containers.edit.information.document.label",
2284
- defaultMessage: "Document"
2715
+ defaultMessage: "Created"
2285
2716
  }),
2286
2717
  value: formatMessage(
2287
2718
  {
2288
2719
  id: "content-manager.containers.edit.information.document.value",
2289
- defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
2720
+ defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
2290
2721
  },
2291
2722
  {
2292
2723
  time: /* @__PURE__ */ jsx(
@@ -2324,25 +2755,77 @@ const Information = ({ activeTab }) => {
2324
2755
  );
2325
2756
  };
2326
2757
  const HeaderActions = ({ actions: actions2 }) => {
2327
- return /* @__PURE__ */ jsx(Flex, { children: actions2.map((action) => {
2328
- if ("options" in action) {
2758
+ const [dialogId, setDialogId] = React.useState(null);
2759
+ const handleClick = (action) => async (e) => {
2760
+ if (!("options" in action)) {
2761
+ const { onClick = () => false, dialog, id } = action;
2762
+ const muteDialog = await onClick(e);
2763
+ if (dialog && !muteDialog) {
2764
+ e.preventDefault();
2765
+ setDialogId(id);
2766
+ }
2767
+ }
2768
+ };
2769
+ const handleClose = () => {
2770
+ setDialogId(null);
2771
+ };
2772
+ return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
2773
+ if (action.options) {
2329
2774
  return /* @__PURE__ */ jsx(
2330
2775
  SingleSelect,
2331
2776
  {
2332
2777
  size: "S",
2333
- disabled: action.disabled,
2334
- "aria-label": action.label,
2335
2778
  onChange: action.onSelect,
2336
- value: action.value,
2779
+ "aria-label": action.label,
2780
+ ...action,
2337
2781
  children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
2338
2782
  },
2339
2783
  action.id
2340
2784
  );
2341
2785
  } else {
2342
- return null;
2786
+ if (action.type === "icon") {
2787
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
2788
+ /* @__PURE__ */ jsx(
2789
+ IconButton,
2790
+ {
2791
+ disabled: action.disabled,
2792
+ label: action.label,
2793
+ size: "S",
2794
+ onClick: handleClick(action),
2795
+ children: action.icon
2796
+ }
2797
+ ),
2798
+ action.dialog ? /* @__PURE__ */ jsx(
2799
+ HeaderActionDialog,
2800
+ {
2801
+ ...action.dialog,
2802
+ isOpen: dialogId === action.id,
2803
+ onClose: handleClose
2804
+ }
2805
+ ) : null
2806
+ ] }, action.id);
2807
+ }
2343
2808
  }
2344
2809
  }) });
2345
2810
  };
2811
+ const HeaderActionDialog = ({
2812
+ onClose,
2813
+ onCancel,
2814
+ title,
2815
+ content: Content,
2816
+ isOpen
2817
+ }) => {
2818
+ const handleClose = async () => {
2819
+ if (onCancel) {
2820
+ await onCancel();
2821
+ }
2822
+ onClose();
2823
+ };
2824
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2825
+ /* @__PURE__ */ jsx(Dialog.Header, { children: title }),
2826
+ typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
2827
+ ] }) });
2828
+ };
2346
2829
  const ConfigureTheViewAction = ({ collectionType, model }) => {
2347
2830
  const navigate = useNavigate();
2348
2831
  const { formatMessage } = useIntl();
@@ -2383,12 +2866,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2383
2866
  const { delete: deleteAction } = useDocumentActions();
2384
2867
  const { toggleNotification } = useNotification();
2385
2868
  const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
2869
+ const isLocalized = document?.locale != null;
2386
2870
  return {
2387
2871
  disabled: !canDelete || !document,
2388
- label: formatMessage({
2389
- id: "content-manager.actions.delete.label",
2390
- defaultMessage: "Delete document"
2391
- }),
2872
+ label: formatMessage(
2873
+ {
2874
+ id: "content-manager.actions.delete.label",
2875
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2876
+ },
2877
+ { isLocalized }
2878
+ ),
2392
2879
  icon: /* @__PURE__ */ jsx(Trash, {}),
2393
2880
  dialog: {
2394
2881
  type: "dialog",
@@ -2478,7 +2965,7 @@ const ActionsPanel = () => {
2478
2965
  return {
2479
2966
  title: formatMessage({
2480
2967
  id: "content-manager.containers.edit.panels.default.title",
2481
- defaultMessage: "Document"
2968
+ defaultMessage: "Entry"
2482
2969
  }),
2483
2970
  content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
2484
2971
  };
@@ -2539,308 +3026,6 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
2539
3026
  }
2540
3027
  );
2541
3028
  });
2542
- const HOOKS = {
2543
- /**
2544
- * Hook that allows to mutate the displayed headers of the list view table
2545
- * @constant
2546
- * @type {string}
2547
- */
2548
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2549
- /**
2550
- * Hook that allows to mutate the CM's collection types links pre-set filters
2551
- * @constant
2552
- * @type {string}
2553
- */
2554
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2555
- /**
2556
- * Hook that allows to mutate the CM's edit view layout
2557
- * @constant
2558
- * @type {string}
2559
- */
2560
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2561
- /**
2562
- * Hook that allows to mutate the CM's single types links pre-set filters
2563
- * @constant
2564
- * @type {string}
2565
- */
2566
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2567
- };
2568
- const contentTypesApi = contentManagerApi.injectEndpoints({
2569
- endpoints: (builder) => ({
2570
- getContentTypeConfiguration: builder.query({
2571
- query: (uid) => ({
2572
- url: `/content-manager/content-types/${uid}/configuration`,
2573
- method: "GET"
2574
- }),
2575
- transformResponse: (response) => response.data,
2576
- providesTags: (_result, _error, uid) => [
2577
- { type: "ContentTypesConfiguration", id: uid },
2578
- { type: "ContentTypeSettings", id: "LIST" }
2579
- ]
2580
- }),
2581
- getAllContentTypeSettings: builder.query({
2582
- query: () => "/content-manager/content-types-settings",
2583
- transformResponse: (response) => response.data,
2584
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2585
- }),
2586
- updateContentTypeConfiguration: builder.mutation({
2587
- query: ({ uid, ...body }) => ({
2588
- url: `/content-manager/content-types/${uid}/configuration`,
2589
- method: "PUT",
2590
- data: body
2591
- }),
2592
- transformResponse: (response) => response.data,
2593
- invalidatesTags: (_result, _error, { uid }) => [
2594
- { type: "ContentTypesConfiguration", id: uid },
2595
- { type: "ContentTypeSettings", id: "LIST" },
2596
- // Is this necessary?
2597
- { type: "InitialData" }
2598
- ]
2599
- })
2600
- })
2601
- });
2602
- const {
2603
- useGetContentTypeConfigurationQuery,
2604
- useGetAllContentTypeSettingsQuery,
2605
- useUpdateContentTypeConfigurationMutation
2606
- } = contentTypesApi;
2607
- const checkIfAttributeIsDisplayable = (attribute) => {
2608
- const { type } = attribute;
2609
- if (type === "relation") {
2610
- return !attribute.relation.toLowerCase().includes("morph");
2611
- }
2612
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2613
- };
2614
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2615
- if (!mainFieldName) {
2616
- return void 0;
2617
- }
2618
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2619
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2620
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2621
- );
2622
- return {
2623
- name: mainFieldName,
2624
- type: mainFieldType ?? "string"
2625
- };
2626
- };
2627
- const DEFAULT_SETTINGS = {
2628
- bulkable: false,
2629
- filterable: false,
2630
- searchable: false,
2631
- pagination: false,
2632
- defaultSortBy: "",
2633
- defaultSortOrder: "asc",
2634
- mainField: "id",
2635
- pageSize: 10
2636
- };
2637
- const useDocumentLayout = (model) => {
2638
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2639
- const [{ query }] = useQueryParams();
2640
- const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2641
- const { toggleNotification } = useNotification();
2642
- const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
2643
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2644
- const {
2645
- data,
2646
- isLoading: isLoadingConfigs,
2647
- error,
2648
- isFetching: isFetchingConfigs
2649
- } = useGetContentTypeConfigurationQuery(model);
2650
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2651
- React.useEffect(() => {
2652
- if (error) {
2653
- toggleNotification({
2654
- type: "danger",
2655
- message: formatAPIError(error)
2656
- });
2657
- }
2658
- }, [error, formatAPIError, toggleNotification]);
2659
- const editLayout = React.useMemo(
2660
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2661
- layout: [],
2662
- components: {},
2663
- metadatas: {},
2664
- options: {},
2665
- settings: DEFAULT_SETTINGS
2666
- },
2667
- [data, isLoading, schemas, schema, components]
2668
- );
2669
- const listLayout = React.useMemo(() => {
2670
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2671
- layout: [],
2672
- metadatas: {},
2673
- options: {},
2674
- settings: DEFAULT_SETTINGS
2675
- };
2676
- }, [data, isLoading, schemas, schema, components]);
2677
- const { layout: edit } = React.useMemo(
2678
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2679
- layout: editLayout,
2680
- query
2681
- }),
2682
- [editLayout, query, runHookWaterfall]
2683
- );
2684
- return {
2685
- error,
2686
- isLoading,
2687
- edit,
2688
- list: listLayout
2689
- };
2690
- };
2691
- const useDocLayout = () => {
2692
- const { model } = useDoc();
2693
- return useDocumentLayout(model);
2694
- };
2695
- const formatEditLayout = (data, {
2696
- schemas,
2697
- schema,
2698
- components
2699
- }) => {
2700
- let currentPanelIndex = 0;
2701
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2702
- data.contentType.layouts.edit,
2703
- schema?.attributes,
2704
- data.contentType.metadatas,
2705
- { configurations: data.components, schemas: components },
2706
- schemas
2707
- ).reduce((panels, row) => {
2708
- if (row.some((field) => field.type === "dynamiczone")) {
2709
- panels.push([row]);
2710
- currentPanelIndex += 2;
2711
- } else {
2712
- if (!panels[currentPanelIndex]) {
2713
- panels.push([]);
2714
- }
2715
- panels[currentPanelIndex].push(row);
2716
- }
2717
- return panels;
2718
- }, []);
2719
- const componentEditAttributes = Object.entries(data.components).reduce(
2720
- (acc, [uid, configuration]) => {
2721
- acc[uid] = {
2722
- layout: convertEditLayoutToFieldLayouts(
2723
- configuration.layouts.edit,
2724
- components[uid].attributes,
2725
- configuration.metadatas
2726
- ),
2727
- settings: {
2728
- ...configuration.settings,
2729
- icon: components[uid].info.icon,
2730
- displayName: components[uid].info.displayName
2731
- }
2732
- };
2733
- return acc;
2734
- },
2735
- {}
2736
- );
2737
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2738
- (acc, [attribute, metadata]) => {
2739
- return {
2740
- ...acc,
2741
- [attribute]: metadata.edit
2742
- };
2743
- },
2744
- {}
2745
- );
2746
- return {
2747
- layout: panelledEditAttributes,
2748
- components: componentEditAttributes,
2749
- metadatas: editMetadatas,
2750
- settings: {
2751
- ...data.contentType.settings,
2752
- displayName: schema?.info.displayName
2753
- },
2754
- options: {
2755
- ...schema?.options,
2756
- ...schema?.pluginOptions,
2757
- ...data.contentType.options
2758
- }
2759
- };
2760
- };
2761
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2762
- return rows.map(
2763
- (row) => row.map((field) => {
2764
- const attribute = attributes[field.name];
2765
- if (!attribute) {
2766
- return null;
2767
- }
2768
- const { edit: metadata } = metadatas[field.name];
2769
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2770
- return {
2771
- attribute,
2772
- disabled: !metadata.editable,
2773
- hint: metadata.description,
2774
- label: metadata.label ?? "",
2775
- name: field.name,
2776
- // @ts-expect-error – mainField does exist on the metadata for a relation.
2777
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2778
- schemas,
2779
- components: components?.schemas ?? {}
2780
- }),
2781
- placeholder: metadata.placeholder ?? "",
2782
- required: attribute.required ?? false,
2783
- size: field.size,
2784
- unique: "unique" in attribute ? attribute.unique : false,
2785
- visible: metadata.visible ?? true,
2786
- type: attribute.type
2787
- };
2788
- }).filter((field) => field !== null)
2789
- );
2790
- };
2791
- const formatListLayout = (data, {
2792
- schemas,
2793
- schema,
2794
- components
2795
- }) => {
2796
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2797
- (acc, [attribute, metadata]) => {
2798
- return {
2799
- ...acc,
2800
- [attribute]: metadata.list
2801
- };
2802
- },
2803
- {}
2804
- );
2805
- const listAttributes = convertListLayoutToFieldLayouts(
2806
- data.contentType.layouts.list,
2807
- schema?.attributes,
2808
- listMetadatas,
2809
- { configurations: data.components, schemas: components },
2810
- schemas
2811
- );
2812
- return {
2813
- layout: listAttributes,
2814
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2815
- metadatas: listMetadatas,
2816
- options: {
2817
- ...schema?.options,
2818
- ...schema?.pluginOptions,
2819
- ...data.contentType.options
2820
- }
2821
- };
2822
- };
2823
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2824
- return columns.map((name) => {
2825
- const attribute = attributes[name];
2826
- if (!attribute) {
2827
- return null;
2828
- }
2829
- const metadata = metadatas[name];
2830
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2831
- return {
2832
- attribute,
2833
- label: metadata.label ?? "",
2834
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2835
- schemas,
2836
- components: components?.schemas ?? {}
2837
- }),
2838
- name,
2839
- searchable: metadata.searchable ?? true,
2840
- sortable: metadata.sortable ?? true
2841
- };
2842
- }).filter((field) => field !== null);
2843
- };
2844
3029
  const ConfirmBulkActionDialog = ({
2845
3030
  onToggleDialog,
2846
3031
  isOpen = false,
@@ -2879,6 +3064,7 @@ const ConfirmDialogPublishAll = ({
2879
3064
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
2880
3065
  const { model, schema } = useDoc();
2881
3066
  const [{ query }] = useQueryParams();
3067
+ const enableDraftRelationsCount = false;
2882
3068
  const {
2883
3069
  data: countDraftRelations = 0,
2884
3070
  isLoading,
@@ -2890,7 +3076,7 @@ const ConfirmDialogPublishAll = ({
2890
3076
  locale: query?.plugins?.i18n?.locale
2891
3077
  },
2892
3078
  {
2893
- skip: selectedEntries.length === 0
3079
+ skip: !enableDraftRelationsCount
2894
3080
  }
2895
3081
  );
2896
3082
  React.useEffect(() => {
@@ -3075,7 +3261,7 @@ const SelectedEntriesTableContent = ({
3075
3261
  status: row.status
3076
3262
  }
3077
3263
  ) }),
3078
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
3264
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
3079
3265
  IconButton,
3080
3266
  {
3081
3267
  tag: Link,
@@ -3098,9 +3284,10 @@ const SelectedEntriesTableContent = ({
3098
3284
  ),
3099
3285
  target: "_blank",
3100
3286
  marginLeft: "auto",
3101
- children: /* @__PURE__ */ jsx(Pencil, {})
3287
+ variant: "ghost",
3288
+ children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
3102
3289
  }
3103
- ) })
3290
+ ) }) })
3104
3291
  ] }, row.id)) })
3105
3292
  ] });
3106
3293
  };
@@ -3137,7 +3324,13 @@ const SelectedEntriesModalContent = ({
3137
3324
  );
3138
3325
  const { rows, validationErrors } = React.useMemo(() => {
3139
3326
  if (data.length > 0 && schema) {
3140
- const validate = createYupSchema(schema.attributes, components);
3327
+ const validate = createYupSchema(
3328
+ schema.attributes,
3329
+ components,
3330
+ // Since this is the "Publish" action, the validation
3331
+ // schema must enforce the rules for published entities
3332
+ { status: "published" }
3333
+ );
3141
3334
  const validationErrors2 = {};
3142
3335
  const rows2 = data.map((entry) => {
3143
3336
  try {
@@ -3487,7 +3680,7 @@ const TableActions = ({ document }) => {
3487
3680
  DescriptionComponentRenderer,
3488
3681
  {
3489
3682
  props,
3490
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3683
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
3491
3684
  children: (actions2) => {
3492
3685
  const tableRowActions = actions2.filter((action) => {
3493
3686
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3598,7 +3791,7 @@ const CloneAction = ({ model, documentId }) => {
3598
3791
  }),
3599
3792
  content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3600
3793
  footer: ({ onClose }) => {
3601
- return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
3794
+ return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
3602
3795
  /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3603
3796
  id: "cancel",
3604
3797
  defaultMessage: "Cancel"
@@ -3829,7 +4022,7 @@ const index = {
3829
4022
  app.router.addRoute({
3830
4023
  path: "content-manager/*",
3831
4024
  lazy: async () => {
3832
- const { Layout } = await import("./layout-DPaHUusj.mjs");
4025
+ const { Layout } = await import("./layout-BavJ6v4B.mjs");
3833
4026
  return {
3834
4027
  Component: Layout
3835
4028
  };
@@ -3846,7 +4039,7 @@ const index = {
3846
4039
  async registerTrads({ locales }) {
3847
4040
  const importedTrads = await Promise.all(
3848
4041
  locales.map((locale) => {
3849
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-BrCTWlZv.mjs"), "./translations/es.json": () => import("./es-CeXiYflN.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr-CD9VFbPM.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-CtsUxOvk.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
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 }) => {
3850
4043
  return {
3851
4044
  data: prefixPluginTranslations(data, PLUGIN_ID),
3852
4045
  locale
@@ -3867,13 +4060,15 @@ export {
3867
4060
  BulkActionsRenderer as B,
3868
4061
  COLLECTION_TYPES as C,
3869
4062
  DocumentStatus as D,
3870
- DEFAULT_SETTINGS as E,
3871
- convertEditLayoutToFieldLayouts as F,
3872
- useDocument as G,
4063
+ extractContentTypeComponents as E,
4064
+ DEFAULT_SETTINGS as F,
4065
+ convertEditLayoutToFieldLayouts as G,
3873
4066
  HOOKS as H,
3874
4067
  InjectionZone as I,
3875
- index as J,
3876
- useDocumentActions as K,
4068
+ useDocument as J,
4069
+ index as K,
4070
+ useContentManagerContext as L,
4071
+ useDocumentActions as M,
3877
4072
  Panels as P,
3878
4073
  RelativeTime as R,
3879
4074
  SINGLE_TYPES as S,
@@ -3891,18 +4086,18 @@ export {
3891
4086
  PERMISSIONS as k,
3892
4087
  DocumentRBAC as l,
3893
4088
  DOCUMENT_META_FIELDS as m,
3894
- useDocLayout as n,
3895
- useGetContentTypeConfigurationQuery as o,
3896
- CREATOR_FIELDS as p,
3897
- getMainField as q,
3898
- getDisplayName as r,
4089
+ CLONE_PATH as n,
4090
+ useDocLayout as o,
4091
+ useGetContentTypeConfigurationQuery as p,
4092
+ CREATOR_FIELDS as q,
4093
+ getMainField as r,
3899
4094
  setInitialData as s,
3900
- checkIfAttributeIsDisplayable as t,
4095
+ getDisplayName as t,
3901
4096
  useContentTypeSchema as u,
3902
- useGetAllDocumentsQuery as v,
3903
- convertListLayoutToFieldLayouts as w,
3904
- capitalise as x,
3905
- useUpdateContentTypeConfigurationMutation as y,
3906
- extractContentTypeComponents as z
4097
+ checkIfAttributeIsDisplayable as v,
4098
+ useGetAllDocumentsQuery as w,
4099
+ convertListLayoutToFieldLayouts as x,
4100
+ capitalise as y,
4101
+ useUpdateContentTypeConfigurationMutation as z
3907
4102
  };
3908
- //# sourceMappingURL=index-BSn97i8U.mjs.map
4103
+ //# sourceMappingURL=index-DcQ6xogO.mjs.map