@strapi/content-manager 0.0.0-experimental.d53e940834bf72ddc725f1d2fd36dac9abec30cb → 0.0.0-experimental.d834c9e658d1fb037e6da1105150593521c667cc

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 (115) hide show
  1. package/LICENSE +18 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-D_M8iBw5.js} +3 -3
  3. package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-D_M8iBw5.js.map} +1 -1
  4. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs → ComponentConfigurationPage-qemkOlnj.mjs} +3 -3
  5. package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-qemkOlnj.mjs.map} +1 -1
  6. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-BePwPuHy.js} +3 -3
  7. package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-BePwPuHy.js.map} +1 -1
  8. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs → EditConfigurationPage-CjUrEewK.mjs} +3 -3
  9. package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-CjUrEewK.mjs.map} +1 -1
  10. package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-B-RJeiJD.js} +19 -8
  11. package/dist/_chunks/EditViewPage-B-RJeiJD.js.map +1 -0
  12. package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-De8GyU8P.mjs} +19 -8
  13. package/dist/_chunks/EditViewPage-De8GyU8P.mjs.map +1 -0
  14. package/dist/_chunks/{Field-Boxf9Ajp.js → Field-dq8Tg1M_.js} +175 -84
  15. package/dist/_chunks/Field-dq8Tg1M_.js.map +1 -0
  16. package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-pb2o8uBe.mjs} +177 -86
  17. package/dist/_chunks/Field-pb2o8uBe.mjs.map +1 -0
  18. package/dist/_chunks/{Form-y5g1SRsh.js → Form-DGIf4jQU.js} +22 -11
  19. package/dist/_chunks/Form-DGIf4jQU.js.map +1 -0
  20. package/dist/_chunks/{Form-DHrru2AV.mjs → Form-DJn0Dxha.mjs} +22 -11
  21. package/dist/_chunks/Form-DJn0Dxha.mjs.map +1 -0
  22. package/dist/_chunks/{History-Bru_KoeP.mjs → History-BowL3JKP.mjs} +44 -19
  23. package/dist/_chunks/History-BowL3JKP.mjs.map +1 -0
  24. package/dist/_chunks/{History-CqN6K7SX.js → History-Dh2NEHnR.js} +44 -19
  25. package/dist/_chunks/History-Dh2NEHnR.js.map +1 -0
  26. package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-BpVOB-hn.mjs} +20 -8
  27. package/dist/_chunks/ListConfigurationPage-BpVOB-hn.mjs.map +1 -0
  28. package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-BxYCWz9e.js} +20 -8
  29. package/dist/_chunks/ListConfigurationPage-BxYCWz9e.js.map +1 -0
  30. package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-4XsciqHZ.js} +21 -7
  31. package/dist/_chunks/ListViewPage-4XsciqHZ.js.map +1 -0
  32. package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-CXFUjZQC.mjs} +22 -8
  33. package/dist/_chunks/ListViewPage-CXFUjZQC.mjs.map +1 -0
  34. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-C8OpoHeU.js} +2 -2
  35. package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-C8OpoHeU.js.map} +1 -1
  36. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-DuhOTp3x.mjs} +2 -2
  37. package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-DuhOTp3x.mjs.map} +1 -1
  38. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-DVz3mzDz.mjs} +2 -2
  39. package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-DVz3mzDz.mjs.map} +1 -1
  40. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-y_r7DVA2.js} +2 -2
  41. package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-y_r7DVA2.js.map} +1 -1
  42. package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-CVNLrn1Y.mjs} +4 -4
  43. package/dist/_chunks/Relations-CVNLrn1Y.mjs.map +1 -0
  44. package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-DPFCAa7b.js} +4 -4
  45. package/dist/_chunks/Relations-DPFCAa7b.js.map +1 -0
  46. package/dist/_chunks/{en-Ux26r5pl.mjs → en-BrCTWlZv.mjs} +5 -4
  47. package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-BrCTWlZv.mjs.map} +1 -1
  48. package/dist/_chunks/{en-fbKQxLGn.js → en-uOUIxfcQ.js} +5 -4
  49. package/dist/_chunks/{en-fbKQxLGn.js.map → en-uOUIxfcQ.js.map} +1 -1
  50. package/dist/_chunks/{index-DVPWZkbS.js → index-C3fJE-1-.js} +368 -168
  51. package/dist/_chunks/index-C3fJE-1-.js.map +1 -0
  52. package/dist/_chunks/{index-DJXJw9V5.mjs → index-DiMrfcfy.mjs} +387 -187
  53. package/dist/_chunks/index-DiMrfcfy.mjs.map +1 -0
  54. package/dist/_chunks/{layout-Dm6fbiQj.js → layout-C788OmNr.js} +22 -10
  55. package/dist/_chunks/layout-C788OmNr.js.map +1 -0
  56. package/dist/_chunks/{layout-Bau7ZfLV.mjs → layout-ls3gxfpH.mjs} +23 -11
  57. package/dist/_chunks/layout-ls3gxfpH.mjs.map +1 -0
  58. package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-CLcOmGO0.mjs} +2 -2
  59. package/dist/_chunks/{relations-BH_kBSJ0.mjs.map → relations-CLcOmGO0.mjs.map} +1 -1
  60. package/dist/_chunks/{relations-CKnpRgrN.js → relations-DYeotliT.js} +2 -2
  61. package/dist/_chunks/{relations-CKnpRgrN.js.map → relations-DYeotliT.js.map} +1 -1
  62. package/dist/admin/index.js +1 -1
  63. package/dist/admin/index.mjs +4 -4
  64. package/dist/admin/src/history/index.d.ts +3 -0
  65. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  66. package/dist/admin/src/index.d.ts +1 -0
  67. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -0
  68. package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
  69. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
  70. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
  71. package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +10 -22
  72. package/dist/admin/src/services/api.d.ts +1 -1
  73. package/dist/admin/src/services/components.d.ts +2 -2
  74. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  75. package/dist/admin/src/services/documents.d.ts +16 -16
  76. package/dist/admin/src/services/init.d.ts +1 -1
  77. package/dist/admin/src/services/relations.d.ts +2 -2
  78. package/dist/admin/src/services/uid.d.ts +3 -3
  79. package/dist/admin/src/utils/validation.d.ts +4 -1
  80. package/dist/server/index.js +165 -105
  81. package/dist/server/index.js.map +1 -1
  82. package/dist/server/index.mjs +166 -106
  83. package/dist/server/index.mjs.map +1 -1
  84. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  85. package/dist/server/src/controllers/relations.d.ts.map +1 -1
  86. package/dist/server/src/controllers/uid.d.ts.map +1 -1
  87. package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
  88. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  89. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  90. package/dist/server/src/history/services/utils.d.ts +1 -1
  91. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  92. package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
  93. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  94. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  95. package/dist/server/src/services/permission-checker.d.ts.map +1 -1
  96. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  97. package/package.json +8 -8
  98. package/dist/_chunks/EditViewPage-CPj61RMh.mjs.map +0 -1
  99. package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
  100. package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
  101. package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
  102. package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
  103. package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
  104. package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
  105. package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
  106. package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
  107. package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
  108. package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
  109. package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
  110. package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
  111. package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
  112. package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
  113. package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
  114. package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
  115. package/dist/_chunks/layout-Dm6fbiQj.js.map +0 -1
@@ -1,17 +1,17 @@
1
- import { ClockCounterClockwise, CrossCircle, More, WarningCircle, ListPlus, Pencil, Trash, Check, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, Feather } from "@strapi/icons";
1
+ import { CrossCircle, More, WarningCircle, ListPlus, Pencil, Trash, Check, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, Feather } from "@strapi/icons";
2
2
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
3
- import { useStrapiApp, useQueryParams, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useTracking, useForm, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
4
- import { stringify } from "qs";
5
- import { useIntl } from "react-intl";
6
- import { useNavigate, useParams, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
3
+ import { useStrapiApp, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useQueryParams, useTracking, useForm, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
7
4
  import * as React from "react";
8
5
  import { lazy } from "react";
9
- import { Button, Menu, VisuallyHidden, Flex, Box, Typography, Dialog, Modal, Radio, Status, SingleSelect, SingleSelectOption, Loader, IconButton, Tooltip, LinkButton } from "@strapi/design-system";
6
+ import { Menu, Button, VisuallyHidden, Flex, Typography, Dialog, Modal, Radio, Status, Box, SingleSelect, SingleSelectOption, Loader, IconButton, Tooltip, LinkButton } from "@strapi/design-system";
7
+ import { useIntl } from "react-intl";
8
+ import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
10
9
  import { styled } from "styled-components";
11
10
  import * as yup from "yup";
12
11
  import { ValidationError } from "yup";
13
12
  import pipe from "lodash/fp/pipe";
14
13
  import { intervalToDuration, isPast } from "date-fns";
14
+ import { stringify } from "qs";
15
15
  import { createSlice, combineReducers } from "@reduxjs/toolkit";
16
16
  const __variableDynamicImportRuntimeHelper = (glob, path) => {
17
17
  const v = glob[path];
@@ -49,42 +49,6 @@ const useInjectionZone = (area) => {
49
49
  const [page, position] = area.split(".");
50
50
  return contentManagerPlugin.getInjectedComponents(page, position);
51
51
  };
52
- const HistoryAction = ({ model, document }) => {
53
- const { formatMessage } = useIntl();
54
- const [{ query }] = useQueryParams();
55
- const navigate = useNavigate();
56
- const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
57
- if (!window.strapi.features.isEnabled("cms-content-history")) {
58
- return null;
59
- }
60
- return {
61
- icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
62
- label: formatMessage({
63
- id: "content-manager.history.document-action",
64
- defaultMessage: "Content History"
65
- }),
66
- onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
67
- disabled: (
68
- /**
69
- * The user is creating a new document.
70
- * It hasn't been saved yet, so there's no history to go to
71
- */
72
- !document || /**
73
- * The document has been created but the current dimension has never been saved.
74
- * For example, the user is creating a new locale in an existing document,
75
- * so there's no history for the document in that locale
76
- */
77
- !document.id || /**
78
- * History is only available for content types created by the user.
79
- * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
80
- * which start with `admin::` or `plugin::`
81
- */
82
- !model.startsWith("api::")
83
- ),
84
- position: "header"
85
- };
86
- };
87
- HistoryAction.type = "history";
88
52
  const ID = "id";
89
53
  const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
90
54
  const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
@@ -194,7 +158,8 @@ const contentManagerApi = adminApi.enhanceEndpoints({
194
158
  "Document",
195
159
  "InitialData",
196
160
  "HistoryVersion",
197
- "Relations"
161
+ "Relations",
162
+ "UidAvailability"
198
163
  ]
199
164
  });
200
165
  const documentApi = contentManagerApi.injectEndpoints({
@@ -208,7 +173,12 @@ const documentApi = contentManagerApi.injectEndpoints({
208
173
  params: query
209
174
  }
210
175
  }),
211
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
176
+ invalidatesTags: (_result, error, { model }) => {
177
+ if (error) {
178
+ return [];
179
+ }
180
+ return [{ type: "Document", id: `${model}_LIST` }];
181
+ }
212
182
  }),
213
183
  cloneDocument: builder.mutation({
214
184
  query: ({ model, sourceId, data, params }) => ({
@@ -219,7 +189,10 @@ const documentApi = contentManagerApi.injectEndpoints({
219
189
  params
220
190
  }
221
191
  }),
222
- invalidatesTags: (_result, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
192
+ invalidatesTags: (_result, _error, { model }) => [
193
+ { type: "Document", id: `${model}_LIST` },
194
+ { type: "UidAvailability", id: model }
195
+ ]
223
196
  }),
224
197
  /**
225
198
  * Creates a new collection-type document. This should ONLY be used for collection-types.
@@ -236,7 +209,8 @@ const documentApi = contentManagerApi.injectEndpoints({
236
209
  }),
237
210
  invalidatesTags: (result, _error, { model }) => [
238
211
  { type: "Document", id: `${model}_LIST` },
239
- "Relations"
212
+ "Relations",
213
+ { type: "UidAvailability", id: model }
240
214
  ]
241
215
  }),
242
216
  deleteDocument: builder.mutation({
@@ -277,7 +251,8 @@ const documentApi = contentManagerApi.injectEndpoints({
277
251
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
278
252
  },
279
253
  { type: "Document", id: `${model}_LIST` },
280
- "Relations"
254
+ "Relations",
255
+ { type: "UidAvailability", id: model }
281
256
  ];
282
257
  }
283
258
  }),
@@ -295,6 +270,7 @@ const documentApi = contentManagerApi.injectEndpoints({
295
270
  }),
296
271
  providesTags: (result, _error, arg) => {
297
272
  return [
273
+ { type: "Document", id: `ALL_LIST` },
298
274
  { type: "Document", id: `${arg.model}_LIST` },
299
275
  ...result?.results.map(({ documentId }) => ({
300
276
  type: "Document",
@@ -333,6 +309,11 @@ const documentApi = contentManagerApi.injectEndpoints({
333
309
  {
334
310
  type: "Document",
335
311
  id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
312
+ },
313
+ // Make it easy to invalidate all individual documents queries for a model
314
+ {
315
+ type: "Document",
316
+ id: `${model}_ALL_ITEMS`
336
317
  }
337
318
  ];
338
319
  }
@@ -396,8 +377,21 @@ const documentApi = contentManagerApi.injectEndpoints({
396
377
  type: "Document",
397
378
  id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
398
379
  },
399
- "Relations"
380
+ "Relations",
381
+ { type: "UidAvailability", id: model }
400
382
  ];
383
+ },
384
+ async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
385
+ const patchResult = dispatch(
386
+ documentApi.util.updateQueryData("getDocument", patch, (draft) => {
387
+ Object.assign(draft.data, data);
388
+ })
389
+ );
390
+ try {
391
+ await queryFulfilled;
392
+ } catch {
393
+ patchResult.undo();
394
+ }
401
395
  }
402
396
  }),
403
397
  unpublishDocument: builder.mutation({
@@ -467,7 +461,7 @@ const buildValidParams = (query) => {
467
461
  const isBaseQueryError = (error) => {
468
462
  return error.name !== void 0;
469
463
  };
470
- const createYupSchema = (attributes = {}, components = {}) => {
464
+ const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
471
465
  const createModelSchema = (attributes2) => yup.object().shape(
472
466
  Object.entries(attributes2).reduce((acc, [name, attribute]) => {
473
467
  if (DOCUMENT_META_FIELDS.includes(name)) {
@@ -480,7 +474,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
480
474
  addMinValidation,
481
475
  addMaxValidation,
482
476
  addRegexValidation
483
- ].map((fn) => fn(attribute));
477
+ ].map((fn) => fn(attribute, options));
484
478
  const transformSchema = pipe(...validations);
485
479
  switch (attribute.type) {
486
480
  case "component": {
@@ -581,6 +575,14 @@ const createAttributeSchema = (attribute) => {
581
575
  if (!value || typeof value === "string" && value.length === 0) {
582
576
  return true;
583
577
  }
578
+ if (typeof value === "object") {
579
+ try {
580
+ JSON.stringify(value);
581
+ return true;
582
+ } catch (err) {
583
+ return false;
584
+ }
585
+ }
584
586
  try {
585
587
  JSON.parse(value);
586
588
  return true;
@@ -599,13 +601,7 @@ const createAttributeSchema = (attribute) => {
599
601
  return yup.mixed();
600
602
  }
601
603
  };
602
- const addRequiredValidation = (attribute) => (schema) => {
603
- if (attribute.required) {
604
- return schema.required({
605
- id: translatedErrors.required.id,
606
- defaultMessage: "This field is required."
607
- });
608
- }
604
+ const nullableSchema = (schema) => {
609
605
  return schema?.nullable ? schema.nullable() : (
610
606
  // In some cases '.nullable' will not be available on the schema.
611
607
  // e.g. when the schema has been built using yup.lazy (e.g. for relations).
@@ -613,7 +609,22 @@ const addRequiredValidation = (attribute) => (schema) => {
613
609
  schema
614
610
  );
615
611
  };
616
- const addMinLengthValidation = (attribute) => (schema) => {
612
+ const addRequiredValidation = (attribute, options) => (schema) => {
613
+ if (options.status === "draft") {
614
+ return nullableSchema(schema);
615
+ }
616
+ if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
617
+ return schema.min(1, translatedErrors.required);
618
+ }
619
+ if (attribute.required && attribute.type !== "relation") {
620
+ return schema.required(translatedErrors.required);
621
+ }
622
+ return nullableSchema(schema);
623
+ };
624
+ const addMinLengthValidation = (attribute, options) => (schema) => {
625
+ if (options.status === "draft") {
626
+ return schema;
627
+ }
617
628
  if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
618
629
  return schema.min(attribute.minLength, {
619
630
  ...translatedErrors.minLength,
@@ -635,9 +646,31 @@ const addMaxLengthValidation = (attribute) => (schema) => {
635
646
  }
636
647
  return schema;
637
648
  };
638
- const addMinValidation = (attribute) => (schema) => {
649
+ const addMinValidation = (attribute, options) => (schema) => {
639
650
  if ("min" in attribute) {
640
651
  const min = toInteger(attribute.min);
652
+ if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
653
+ if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
654
+ return schema.test(
655
+ "custom-min",
656
+ {
657
+ ...translatedErrors.min,
658
+ values: {
659
+ min: attribute.min
660
+ }
661
+ },
662
+ (value) => {
663
+ if (!value) {
664
+ return true;
665
+ }
666
+ if (Array.isArray(value) && value.length === 0) {
667
+ return true;
668
+ }
669
+ return value.length >= min;
670
+ }
671
+ );
672
+ }
673
+ }
641
674
  if ("min" in schema && min) {
642
675
  return schema.min(min, {
643
676
  ...translatedErrors.min,
@@ -764,7 +797,10 @@ const useDocument = (args, opts) => {
764
797
  isLoading: isLoadingDocument,
765
798
  isFetching: isFetchingDocument,
766
799
  error
767
- } = useGetDocumentQuery(args, opts);
800
+ } = useGetDocumentQuery(args, {
801
+ ...opts,
802
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
803
+ });
768
804
  const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
769
805
  React.useEffect(() => {
770
806
  if (error) {
@@ -850,6 +886,7 @@ const useDocumentActions = () => {
850
886
  const { formatMessage } = useIntl();
851
887
  const { trackUsage } = useTracking();
852
888
  const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
889
+ const navigate = useNavigate();
853
890
  const [deleteDocument] = useDeleteDocumentMutation();
854
891
  const _delete = React.useCallback(
855
892
  async ({ collectionType, model, documentId, params }, trackerProperty) => {
@@ -1185,7 +1222,6 @@ const useDocumentActions = () => {
1185
1222
  sourceId
1186
1223
  });
1187
1224
  if ("error" in res) {
1188
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1189
1225
  return { error: res.error };
1190
1226
  }
1191
1227
  toggleNotification({
@@ -1204,7 +1240,7 @@ const useDocumentActions = () => {
1204
1240
  throw err;
1205
1241
  }
1206
1242
  },
1207
- [autoCloneDocument, formatAPIError, formatMessage, toggleNotification]
1243
+ [autoCloneDocument, formatMessage, toggleNotification]
1208
1244
  );
1209
1245
  const [cloneDocument] = useCloneDocumentMutation();
1210
1246
  const clone = React.useCallback(
@@ -1230,6 +1266,7 @@ const useDocumentActions = () => {
1230
1266
  defaultMessage: "Cloned document"
1231
1267
  })
1232
1268
  });
1269
+ navigate(`../../${res.data.data.documentId}`, { relative: "path" });
1233
1270
  return res.data;
1234
1271
  } catch (err) {
1235
1272
  toggleNotification({
@@ -1240,7 +1277,7 @@ const useDocumentActions = () => {
1240
1277
  throw err;
1241
1278
  }
1242
1279
  },
1243
- [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
1280
+ [cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
1244
1281
  );
1245
1282
  const [getDoc] = useLazyGetDocumentQuery();
1246
1283
  const getDocument = React.useCallback(
@@ -1266,7 +1303,7 @@ const useDocumentActions = () => {
1266
1303
  };
1267
1304
  };
1268
1305
  const ProtectedHistoryPage = lazy(
1269
- () => import("./History-Bru_KoeP.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1306
+ () => import("./History-BowL3JKP.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
1270
1307
  );
1271
1308
  const routes$1 = [
1272
1309
  {
@@ -1279,31 +1316,31 @@ const routes$1 = [
1279
1316
  }
1280
1317
  ];
1281
1318
  const ProtectedEditViewPage = lazy(
1282
- () => import("./EditViewPage-CPj61RMh.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1319
+ () => import("./EditViewPage-De8GyU8P.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
1283
1320
  );
1284
1321
  const ProtectedListViewPage = lazy(
1285
- () => import("./ListViewPage-SID6TRb9.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1322
+ () => import("./ListViewPage-CXFUjZQC.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
1286
1323
  );
1287
1324
  const ProtectedListConfiguration = lazy(
1288
- () => import("./ListConfigurationPage-D8wGABj0.mjs").then((mod) => ({
1325
+ () => import("./ListConfigurationPage-BpVOB-hn.mjs").then((mod) => ({
1289
1326
  default: mod.ProtectedListConfiguration
1290
1327
  }))
1291
1328
  );
1292
1329
  const ProtectedEditConfigurationPage = lazy(
1293
- () => import("./EditConfigurationPage-JT3E7NZy.mjs").then((mod) => ({
1330
+ () => import("./EditConfigurationPage-CjUrEewK.mjs").then((mod) => ({
1294
1331
  default: mod.ProtectedEditConfigurationPage
1295
1332
  }))
1296
1333
  );
1297
1334
  const ProtectedComponentConfigurationPage = lazy(
1298
- () => import("./ComponentConfigurationPage-DmwmiFQy.mjs").then((mod) => ({
1335
+ () => import("./ComponentConfigurationPage-qemkOlnj.mjs").then((mod) => ({
1299
1336
  default: mod.ProtectedComponentConfigurationPage
1300
1337
  }))
1301
1338
  );
1302
1339
  const NoPermissions = lazy(
1303
- () => import("./NoPermissionsPage-B7syEq5E.mjs").then((mod) => ({ default: mod.NoPermissions }))
1340
+ () => import("./NoPermissionsPage-DVz3mzDz.mjs").then((mod) => ({ default: mod.NoPermissions }))
1304
1341
  );
1305
1342
  const NoContentType = lazy(
1306
- () => import("./NoContentTypePage-CJ7UXwrQ.mjs").then((mod) => ({ default: mod.NoContentType }))
1343
+ () => import("./NoContentTypePage-DuhOTp3x.mjs").then((mod) => ({ default: mod.NoContentType }))
1307
1344
  );
1308
1345
  const CollectionTypePages = () => {
1309
1346
  const { collectionType } = useParams();
@@ -1417,12 +1454,14 @@ const DocumentActionButton = (action) => {
1417
1454
  /* @__PURE__ */ jsx(
1418
1455
  Button,
1419
1456
  {
1420
- flex: 1,
1457
+ flex: "auto",
1421
1458
  startIcon: action.icon,
1422
1459
  disabled: action.disabled,
1423
1460
  onClick: handleClick(action),
1424
1461
  justifyContent: "center",
1425
1462
  variant: action.variant || "default",
1463
+ paddingTop: "7px",
1464
+ paddingBottom: "7px",
1426
1465
  children: action.label
1427
1466
  }
1428
1467
  ),
@@ -1430,7 +1469,7 @@ const DocumentActionButton = (action) => {
1430
1469
  DocumentActionConfirmDialog,
1431
1470
  {
1432
1471
  ...action.dialog,
1433
- variant: action.variant,
1472
+ variant: action.dialog?.variant ?? action.variant,
1434
1473
  isOpen: dialogId === action.id,
1435
1474
  onClose: handleClose
1436
1475
  }
@@ -1482,14 +1521,14 @@ const DocumentActionsMenu = ({
1482
1521
  };
1483
1522
  return /* @__PURE__ */ jsxs(Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
1484
1523
  /* @__PURE__ */ jsxs(
1485
- Menu.Trigger,
1524
+ StyledMoreButton,
1486
1525
  {
1487
1526
  disabled: isDisabled,
1488
1527
  size: "S",
1489
1528
  endIcon: null,
1490
- paddingTop: "7px",
1491
- paddingLeft: "9px",
1492
- paddingRight: "9px",
1529
+ paddingTop: "4px",
1530
+ paddingLeft: "7px",
1531
+ paddingRight: "7px",
1493
1532
  variant,
1494
1533
  children: [
1495
1534
  /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
@@ -1509,10 +1548,25 @@ const DocumentActionsMenu = ({
1509
1548
  onSelect: handleClick(action),
1510
1549
  display: "block",
1511
1550
  children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
1512
- /* @__PURE__ */ jsxs(Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
1513
- /* @__PURE__ */ jsx(Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
1514
- action.label
1515
- ] }),
1551
+ /* @__PURE__ */ jsxs(
1552
+ Flex,
1553
+ {
1554
+ color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
1555
+ gap: 2,
1556
+ tag: "span",
1557
+ children: [
1558
+ /* @__PURE__ */ jsx(
1559
+ Flex,
1560
+ {
1561
+ tag: "span",
1562
+ color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
1563
+ children: action.icon
1564
+ }
1565
+ ),
1566
+ action.label
1567
+ ]
1568
+ }
1569
+ ),
1516
1570
  action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
1517
1571
  Flex,
1518
1572
  {
@@ -1583,6 +1637,11 @@ const convertActionVariantToIconColor = (variant = "secondary") => {
1583
1637
  return "primary600";
1584
1638
  }
1585
1639
  };
1640
+ const StyledMoreButton = styled(Menu.Trigger)`
1641
+ & > span {
1642
+ display: flex;
1643
+ }
1644
+ `;
1586
1645
  const DocumentActionConfirmDialog = ({
1587
1646
  onClose,
1588
1647
  onCancel,
@@ -1652,13 +1711,17 @@ const PublishAction$1 = ({
1652
1711
  const navigate = useNavigate();
1653
1712
  const { toggleNotification } = useNotification();
1654
1713
  const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
1714
+ const isListView = useMatch(LIST_PATH) !== null;
1655
1715
  const isCloning = useMatch(CLONE_PATH) !== null;
1656
1716
  const { formatMessage } = useIntl();
1657
- const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
1658
- "PublishAction",
1659
- ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
1660
- );
1717
+ const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
1661
1718
  const { publish } = useDocumentActions();
1719
+ const [
1720
+ countDraftRelations,
1721
+ { isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
1722
+ ] = useLazyGetDraftRelationCountQuery();
1723
+ const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
1724
+ const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
1662
1725
  const [{ query, rawQuery }] = useQueryParams();
1663
1726
  const params = React.useMemo(() => buildValidParams(query), [query]);
1664
1727
  const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
@@ -1667,10 +1730,101 @@ const PublishAction$1 = ({
1667
1730
  const validate = useForm("PublishAction", (state) => state.validate);
1668
1731
  const setErrors = useForm("PublishAction", (state) => state.setErrors);
1669
1732
  const formValues = useForm("PublishAction", ({ values }) => values);
1733
+ React.useEffect(() => {
1734
+ if (isErrorDraftRelations) {
1735
+ toggleNotification({
1736
+ type: "danger",
1737
+ message: formatMessage({
1738
+ id: getTranslation("error.records.fetch-draft-relatons"),
1739
+ defaultMessage: "An error occurred while fetching draft relations on this document."
1740
+ })
1741
+ });
1742
+ }
1743
+ }, [isErrorDraftRelations, toggleNotification, formatMessage]);
1744
+ React.useEffect(() => {
1745
+ const localDraftRelations = /* @__PURE__ */ new Set();
1746
+ const extractDraftRelations = (data) => {
1747
+ const relations = data.connect || [];
1748
+ relations.forEach((relation) => {
1749
+ if (relation.status === "draft") {
1750
+ localDraftRelations.add(relation.id);
1751
+ }
1752
+ });
1753
+ };
1754
+ const traverseAndExtract = (data) => {
1755
+ Object.entries(data).forEach(([key, value]) => {
1756
+ if (key === "connect" && Array.isArray(value)) {
1757
+ extractDraftRelations({ connect: value });
1758
+ } else if (typeof value === "object" && value !== null) {
1759
+ traverseAndExtract(value);
1760
+ }
1761
+ });
1762
+ };
1763
+ if (!documentId || modified) {
1764
+ traverseAndExtract(formValues);
1765
+ setLocalCountOfDraftRelations(localDraftRelations.size);
1766
+ }
1767
+ }, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
1768
+ React.useEffect(() => {
1769
+ if (documentId && !isListView) {
1770
+ const fetchDraftRelationsCount = async () => {
1771
+ const { data, error } = await countDraftRelations({
1772
+ collectionType,
1773
+ model,
1774
+ documentId,
1775
+ params
1776
+ });
1777
+ if (error) {
1778
+ throw error;
1779
+ }
1780
+ if (data) {
1781
+ setServerCountOfDraftRelations(data.data);
1782
+ }
1783
+ };
1784
+ fetchDraftRelationsCount();
1785
+ }
1786
+ }, [isListView, documentId, countDraftRelations, collectionType, model, params]);
1670
1787
  const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
1671
1788
  if (!schema?.options?.draftAndPublish) {
1672
1789
  return null;
1673
1790
  }
1791
+ const performPublish = async () => {
1792
+ setSubmitting(true);
1793
+ try {
1794
+ const { errors } = await validate();
1795
+ if (errors) {
1796
+ toggleNotification({
1797
+ type: "danger",
1798
+ message: formatMessage({
1799
+ id: "content-manager.validation.error",
1800
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1801
+ })
1802
+ });
1803
+ return;
1804
+ }
1805
+ const res = await publish(
1806
+ {
1807
+ collectionType,
1808
+ model,
1809
+ documentId,
1810
+ params
1811
+ },
1812
+ formValues
1813
+ );
1814
+ if ("data" in res && collectionType !== SINGLE_TYPES) {
1815
+ navigate({
1816
+ pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1817
+ search: rawQuery
1818
+ });
1819
+ } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1820
+ setErrors(formatValidationErrors(res.error));
1821
+ }
1822
+ } finally {
1823
+ setSubmitting(false);
1824
+ }
1825
+ };
1826
+ const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
1827
+ const hasDraftRelations = totalDraftRelations > 0;
1674
1828
  return {
1675
1829
  /**
1676
1830
  * Disabled when:
@@ -1680,49 +1834,39 @@ const PublishAction$1 = ({
1680
1834
  * - the document is already published & not modified
1681
1835
  * - the document is being created & not modified
1682
1836
  * - the user doesn't have the permission to publish
1683
- * - the user doesn't have the permission to create a new document
1684
- * - the user doesn't have the permission to update the document
1685
1837
  */
1686
- disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
1838
+ disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
1687
1839
  label: formatMessage({
1688
1840
  id: "app.utils.publish",
1689
1841
  defaultMessage: "Publish"
1690
1842
  }),
1691
1843
  onClick: async () => {
1692
- setSubmitting(true);
1693
- try {
1694
- const { errors } = await validate();
1695
- if (errors) {
1696
- toggleNotification({
1697
- type: "danger",
1698
- message: formatMessage({
1699
- id: "content-manager.validation.error",
1700
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1701
- })
1702
- });
1703
- return;
1704
- }
1705
- const res = await publish(
1706
- {
1707
- collectionType,
1708
- model,
1709
- documentId,
1710
- params
1711
- },
1712
- formValues
1713
- );
1714
- if ("data" in res && collectionType !== SINGLE_TYPES) {
1715
- navigate({
1716
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1717
- search: rawQuery
1718
- });
1719
- } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1720
- setErrors(formatValidationErrors(res.error));
1844
+ if (hasDraftRelations) {
1845
+ return;
1846
+ }
1847
+ await performPublish();
1848
+ },
1849
+ dialog: hasDraftRelations ? {
1850
+ type: "dialog",
1851
+ variant: "danger",
1852
+ footer: null,
1853
+ title: formatMessage({
1854
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
1855
+ defaultMessage: "Confirmation"
1856
+ }),
1857
+ content: formatMessage(
1858
+ {
1859
+ id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
1860
+ defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
1861
+ },
1862
+ {
1863
+ count: totalDraftRelations
1721
1864
  }
1722
- } finally {
1723
- setSubmitting(false);
1865
+ ),
1866
+ onConfirm: async () => {
1867
+ await performPublish();
1724
1868
  }
1725
- }
1869
+ } : void 0
1726
1870
  };
1727
1871
  };
1728
1872
  PublishAction$1.type = "publish";
@@ -1738,10 +1882,6 @@ const UpdateAction = ({
1738
1882
  const cloneMatch = useMatch(CLONE_PATH);
1739
1883
  const isCloning = cloneMatch !== null;
1740
1884
  const { formatMessage } = useIntl();
1741
- const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
1742
- canCreate: canCreate2,
1743
- canUpdate: canUpdate2
1744
- }));
1745
1885
  const { create, update, clone } = useDocumentActions();
1746
1886
  const [{ query, rawQuery }] = useQueryParams();
1747
1887
  const params = React.useMemo(() => buildValidParams(query), [query]);
@@ -1758,10 +1898,8 @@ const UpdateAction = ({
1758
1898
  * - the form is submitting
1759
1899
  * - the document is not modified & we're not cloning (you can save a clone entity straight away)
1760
1900
  * - the active tab is the published tab
1761
- * - the user doesn't have the permission to create a new document
1762
- * - the user doesn't have the permission to update the document
1763
1901
  */
1764
- disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
1902
+ disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
1765
1903
  label: formatMessage({
1766
1904
  id: "content-manager.containers.Edit.save",
1767
1905
  defaultMessage: "Save"
@@ -1769,16 +1907,18 @@ const UpdateAction = ({
1769
1907
  onClick: async () => {
1770
1908
  setSubmitting(true);
1771
1909
  try {
1772
- const { errors } = await validate();
1773
- if (errors) {
1774
- toggleNotification({
1775
- type: "danger",
1776
- message: formatMessage({
1777
- id: "content-manager.validation.error",
1778
- defaultMessage: "There are validation errors in your document. Please fix them before saving."
1779
- })
1780
- });
1781
- return;
1910
+ if (activeTab !== "draft") {
1911
+ const { errors } = await validate();
1912
+ if (errors) {
1913
+ toggleNotification({
1914
+ type: "danger",
1915
+ message: formatMessage({
1916
+ id: "content-manager.validation.error",
1917
+ defaultMessage: "There are validation errors in your document. Please fix them before saving."
1918
+ })
1919
+ });
1920
+ return;
1921
+ }
1782
1922
  }
1783
1923
  if (isCloning) {
1784
1924
  const res = await clone(
@@ -1790,10 +1930,13 @@ const UpdateAction = ({
1790
1930
  document
1791
1931
  );
1792
1932
  if ("data" in res) {
1793
- navigate({
1794
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1795
- search: rawQuery
1796
- });
1933
+ navigate(
1934
+ {
1935
+ pathname: `../${res.data.documentId}`,
1936
+ search: rawQuery
1937
+ },
1938
+ { relative: "path" }
1939
+ );
1797
1940
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1798
1941
  setErrors(formatValidationErrors(res.error));
1799
1942
  }
@@ -1821,10 +1964,13 @@ const UpdateAction = ({
1821
1964
  document
1822
1965
  );
1823
1966
  if ("data" in res && collectionType !== SINGLE_TYPES) {
1824
- navigate({
1825
- pathname: `../${collectionType}/${model}/${res.data.documentId}`,
1826
- search: rawQuery
1827
- });
1967
+ navigate(
1968
+ {
1969
+ pathname: `../${res.data.documentId}`,
1970
+ search: rawQuery
1971
+ },
1972
+ { replace: true, relative: "path" }
1973
+ );
1828
1974
  } else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
1829
1975
  setErrors(formatValidationErrors(res.error));
1830
1976
  }
@@ -2070,23 +2216,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
2070
2216
  id: "content-manager.containers.edit.title.new",
2071
2217
  defaultMessage: "Create an entry"
2072
2218
  }) : documentTitle;
2073
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 8, paddingBottom: 4, gap: 3, children: [
2219
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
2074
2220
  /* @__PURE__ */ jsx(BackButton, {}),
2075
- /* @__PURE__ */ jsxs(
2076
- Flex,
2077
- {
2078
- width: "100%",
2079
- justifyContent: "space-between",
2080
- paddingTop: 1,
2081
- gap: "80px",
2082
- alignItems: "flex-start",
2083
- children: [
2084
- /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
2085
- /* @__PURE__ */ jsx(HeaderToolbar, {})
2086
- ]
2087
- }
2088
- ),
2089
- status ? /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
2221
+ /* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
2222
+ /* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
2223
+ /* @__PURE__ */ jsx(HeaderToolbar, {})
2224
+ ] }),
2225
+ status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
2090
2226
  ] });
2091
2227
  };
2092
2228
  const HeaderToolbar = () => {
@@ -2777,7 +2913,7 @@ const ConfirmBulkActionDialog = ({
2777
2913
  endAction
2778
2914
  }) => {
2779
2915
  const { formatMessage } = useIntl();
2780
- return /* @__PURE__ */ jsx(Dialog.Root, { onOpenChange: onToggleDialog, open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2916
+ return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
2781
2917
  /* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
2782
2918
  id: "app.components.ConfirmDialog.title",
2783
2919
  defaultMessage: "Confirmation"
@@ -2898,7 +3034,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
2898
3034
  )
2899
3035
  );
2900
3036
  } else {
2901
- messages.push(...formatErrorMessages(value, currentKey, formatMessage));
3037
+ messages.push(
3038
+ ...formatErrorMessages(
3039
+ // @ts-expect-error TODO: check why value is not compatible with FormErrors
3040
+ value,
3041
+ currentKey,
3042
+ formatMessage
3043
+ )
3044
+ );
2902
3045
  }
2903
3046
  } else {
2904
3047
  messages.push(
@@ -3059,7 +3202,13 @@ const SelectedEntriesModalContent = ({
3059
3202
  );
3060
3203
  const { rows, validationErrors } = React.useMemo(() => {
3061
3204
  if (data.length > 0 && schema) {
3062
- const validate = createYupSchema(schema.attributes, components);
3205
+ const validate = createYupSchema(
3206
+ schema.attributes,
3207
+ components,
3208
+ // Since this is the "Publish" action, the validation
3209
+ // schema must enforce the rules for published entities
3210
+ { status: "published" }
3211
+ );
3063
3212
  const validationErrors2 = {};
3064
3213
  const rows2 = data.map((entry) => {
3065
3214
  try {
@@ -3409,7 +3558,7 @@ const TableActions = ({ document }) => {
3409
3558
  DescriptionComponentRenderer,
3410
3559
  {
3411
3560
  props,
3412
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
3561
+ descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
3413
3562
  children: (actions2) => {
3414
3563
  const tableRowActions = actions2.filter((action) => {
3415
3564
  const positions = Array.isArray(action.position) ? action.position : [action.position];
@@ -3520,7 +3669,7 @@ const CloneAction = ({ model, documentId }) => {
3520
3669
  }),
3521
3670
  content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
3522
3671
  footer: ({ onClose }) => {
3523
- return /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
3672
+ return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
3524
3673
  /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
3525
3674
  id: "cancel",
3526
3675
  defaultMessage: "Cancel"
@@ -3561,8 +3710,7 @@ class ContentManagerPlugin {
3561
3710
  documentActions = [
3562
3711
  ...DEFAULT_ACTIONS,
3563
3712
  ...DEFAULT_TABLE_ROW_ACTIONS,
3564
- ...DEFAULT_HEADER_ACTIONS,
3565
- HistoryAction
3713
+ ...DEFAULT_HEADER_ACTIONS
3566
3714
  ];
3567
3715
  editViewSidePanels = [ActionsPanel];
3568
3716
  headerActions = [];
@@ -3651,6 +3799,52 @@ const getPrintableType = (value) => {
3651
3799
  }
3652
3800
  return nativeType;
3653
3801
  };
3802
+ const HistoryAction = ({ model, document }) => {
3803
+ const { formatMessage } = useIntl();
3804
+ const [{ query }] = useQueryParams();
3805
+ const navigate = useNavigate();
3806
+ const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
3807
+ if (!window.strapi.features.isEnabled("cms-content-history")) {
3808
+ return null;
3809
+ }
3810
+ return {
3811
+ icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
3812
+ label: formatMessage({
3813
+ id: "content-manager.history.document-action",
3814
+ defaultMessage: "Content History"
3815
+ }),
3816
+ onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
3817
+ disabled: (
3818
+ /**
3819
+ * The user is creating a new document.
3820
+ * It hasn't been saved yet, so there's no history to go to
3821
+ */
3822
+ !document || /**
3823
+ * The document has been created but the current dimension has never been saved.
3824
+ * For example, the user is creating a new locale in an existing document,
3825
+ * so there's no history for the document in that locale
3826
+ */
3827
+ !document.id || /**
3828
+ * History is only available for content types created by the user.
3829
+ * These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
3830
+ * which start with `admin::` or `plugin::`
3831
+ */
3832
+ !model.startsWith("api::")
3833
+ ),
3834
+ position: "header"
3835
+ };
3836
+ };
3837
+ HistoryAction.type = "history";
3838
+ const historyAdmin = {
3839
+ bootstrap(app) {
3840
+ const { addDocumentAction } = app.getPlugin("content-manager").apis;
3841
+ addDocumentAction((actions2) => {
3842
+ const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
3843
+ actions2.splice(indexOfDeleteAction, 0, HistoryAction);
3844
+ return actions2;
3845
+ });
3846
+ }
3847
+ };
3654
3848
  const initialState = {
3655
3849
  collectionTypeLinks: [],
3656
3850
  components: [],
@@ -3706,7 +3900,7 @@ const index = {
3706
3900
  app.router.addRoute({
3707
3901
  path: "content-manager/*",
3708
3902
  lazy: async () => {
3709
- const { Layout } = await import("./layout-Bau7ZfLV.mjs");
3903
+ const { Layout } = await import("./layout-ls3gxfpH.mjs");
3710
3904
  return {
3711
3905
  Component: Layout
3712
3906
  };
@@ -3715,10 +3909,15 @@ const index = {
3715
3909
  });
3716
3910
  app.registerPlugin(cm.config);
3717
3911
  },
3912
+ bootstrap(app) {
3913
+ if (typeof historyAdmin.bootstrap === "function") {
3914
+ historyAdmin.bootstrap(app);
3915
+ }
3916
+ },
3718
3917
  async registerTrads({ locales }) {
3719
3918
  const importedTrads = await Promise.all(
3720
3919
  locales.map((locale) => {
3721
- return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-Ux26r5pl.mjs"), "./translations/es.json": () => import("./es-CeXiYflN.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr-CD9VFbPM.mjs"), "./translations/gu.json": () => import("./gu-CNpaMDpH.mjs"), "./translations/hi.json": () => import("./hi-Dwvd04m3.mjs"), "./translations/hu.json": () => import("./hu-CeYvaaO0.mjs"), "./translations/id.json": () => import("./id-BtwA9WJT.mjs"), "./translations/it.json": () => import("./it-BrVPqaf1.mjs"), "./translations/ja.json": () => import("./ja-CtsUxOvk.mjs"), "./translations/ko.json": () => import("./ko-HVQRlfUI.mjs"), "./translations/ml.json": () => import("./ml-BihZwQit.mjs"), "./translations/ms.json": () => import("./ms-m_WjyWx7.mjs"), "./translations/nl.json": () => import("./nl-D4R9gHx5.mjs"), "./translations/pl.json": () => import("./pl-sbx9mSt_.mjs"), "./translations/pt-BR.json": () => import("./pt-BR-C71iDxnh.mjs"), "./translations/pt.json": () => import("./pt-BsaFvS8-.mjs"), "./translations/ru.json": () => import("./ru-BE6A4Exp.mjs"), "./translations/sa.json": () => import("./sa-Dag0k-Z8.mjs"), "./translations/sk.json": () => import("./sk-BFg-R8qJ.mjs"), "./translations/sv.json": () => import("./sv-CUnfWGsh.mjs"), "./translations/th.json": () => import("./th-BqbI8lIT.mjs"), "./translations/tr.json": () => import("./tr-CgeK3wJM.mjs"), "./translations/uk.json": () => import("./uk-CR-zDhAY.mjs"), "./translations/vi.json": () => import("./vi-DUXIk_fw.mjs"), "./translations/zh-Hans.json": () => import("./zh-Hans-BPQcRIyH.mjs"), "./translations/zh.json": () => import("./zh-BWZspA60.mjs") }), `./translations/${locale}.json`).then(({ default: data }) => {
3920
+ 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 }) => {
3722
3921
  return {
3723
3922
  data: prefixPluginTranslations(data, PLUGIN_ID),
3724
3923
  locale
@@ -3739,13 +3938,14 @@ export {
3739
3938
  BulkActionsRenderer as B,
3740
3939
  COLLECTION_TYPES as C,
3741
3940
  DocumentStatus as D,
3742
- DEFAULT_SETTINGS as E,
3743
- convertEditLayoutToFieldLayouts as F,
3744
- useDocument as G,
3941
+ extractContentTypeComponents as E,
3942
+ DEFAULT_SETTINGS as F,
3943
+ convertEditLayoutToFieldLayouts as G,
3745
3944
  HOOKS as H,
3746
3945
  InjectionZone as I,
3747
- index as J,
3748
- useDocumentActions as K,
3946
+ useDocument as J,
3947
+ index as K,
3948
+ useDocumentActions as L,
3749
3949
  Panels as P,
3750
3950
  RelativeTime as R,
3751
3951
  SINGLE_TYPES as S,
@@ -3763,18 +3963,18 @@ export {
3763
3963
  PERMISSIONS as k,
3764
3964
  DocumentRBAC as l,
3765
3965
  DOCUMENT_META_FIELDS as m,
3766
- useDocLayout as n,
3767
- useGetContentTypeConfigurationQuery as o,
3768
- CREATOR_FIELDS as p,
3769
- getMainField as q,
3770
- getDisplayName as r,
3966
+ CLONE_PATH as n,
3967
+ useDocLayout as o,
3968
+ useGetContentTypeConfigurationQuery as p,
3969
+ CREATOR_FIELDS as q,
3970
+ getMainField as r,
3771
3971
  setInitialData as s,
3772
- checkIfAttributeIsDisplayable as t,
3972
+ getDisplayName as t,
3773
3973
  useContentTypeSchema as u,
3774
- useGetAllDocumentsQuery as v,
3775
- convertListLayoutToFieldLayouts as w,
3776
- capitalise as x,
3777
- useUpdateContentTypeConfigurationMutation as y,
3778
- extractContentTypeComponents as z
3974
+ checkIfAttributeIsDisplayable as v,
3975
+ useGetAllDocumentsQuery as w,
3976
+ convertListLayoutToFieldLayouts as x,
3977
+ capitalise as y,
3978
+ useUpdateContentTypeConfigurationMutation as z
3779
3979
  };
3780
- //# sourceMappingURL=index-DJXJw9V5.mjs.map
3980
+ //# sourceMappingURL=index-DiMrfcfy.mjs.map