@strapi/content-manager 0.0.0-experimental.62ce06180fe9a772eaeb3d43d238b26644f39f7c → 0.0.0-experimental.6d27139261823fc4b18da9f3c10b271d5010dbf0
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.
- package/LICENSE +18 -3
- package/dist/_chunks/{ComponentConfigurationPage-DErJQEVW.mjs → ComponentConfigurationPage-9lRmRdIr.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-DErJQEVW.mjs.map → ComponentConfigurationPage-9lRmRdIr.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-Cl7eB3s4.js → ComponentConfigurationPage-DyDkPajU.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-Cl7eB3s4.js.map → ComponentConfigurationPage-DyDkPajU.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CBosWqQ7.mjs → EditConfigurationPage-Bk893vVY.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CBosWqQ7.mjs.map → EditConfigurationPage-Bk893vVY.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CyfFvH6-.js → EditConfigurationPage-DValmA0m.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CyfFvH6-.js.map → EditConfigurationPage-DValmA0m.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-ClIueJnM.mjs → EditViewPage-DiNFdFqP.mjs} +19 -8
- package/dist/_chunks/EditViewPage-DiNFdFqP.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-DxyAOItK.js → EditViewPage-Dk7Eaft4.js} +19 -8
- package/dist/_chunks/EditViewPage-Dk7Eaft4.js.map +1 -0
- package/dist/_chunks/{Field-C0Y_SR9e.js → Field-DH2OaqUP.js} +458 -128
- package/dist/_chunks/Field-DH2OaqUP.js.map +1 -0
- package/dist/_chunks/{Field-BZBYmvaf.mjs → Field-Dv_HTFTa.mjs} +460 -130
- package/dist/_chunks/Field-Dv_HTFTa.mjs.map +1 -0
- package/dist/_chunks/{Form-DwvGnISS.js → Form-B_dUDizM.js} +22 -11
- package/dist/_chunks/Form-B_dUDizM.js.map +1 -0
- package/dist/_chunks/{Form-jwRSC2kV.mjs → Form-Dy6P4HgH.mjs} +22 -11
- package/dist/_chunks/Form-Dy6P4HgH.mjs.map +1 -0
- package/dist/_chunks/{History-Cda0Yjzz.js → History-BT4w83Oa.js} +44 -19
- package/dist/_chunks/History-BT4w83Oa.js.map +1 -0
- package/dist/_chunks/{History-BgzAIj0G.mjs → History-DrwsD1Vc.mjs} +44 -19
- package/dist/_chunks/History-DrwsD1Vc.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-GH55qfoT.mjs → ListConfigurationPage-BxIP0jRy.mjs} +20 -8
- package/dist/_chunks/ListConfigurationPage-BxIP0jRy.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-C29EF97r.js → ListConfigurationPage-CuYrMcW3.js} +20 -8
- package/dist/_chunks/ListConfigurationPage-CuYrMcW3.js.map +1 -0
- package/dist/_chunks/{ListViewPage-QU03PFj1.mjs → ListViewPage-5a1vw-OK.mjs} +40 -34
- package/dist/_chunks/ListViewPage-5a1vw-OK.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-CnRt0UT7.js → ListViewPage-BvpwNur7.js} +38 -32
- package/dist/_chunks/ListViewPage-BvpwNur7.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CPs2CnzH.mjs → NoContentTypePage-Bm6tRcd3.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CPs2CnzH.mjs.map → NoContentTypePage-Bm6tRcd3.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-DFDjxByI.js → NoContentTypePage-UqEiWKkM.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-DFDjxByI.js.map → NoContentTypePage-UqEiWKkM.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-ct58lcY0.mjs → NoPermissionsPage-BHPqn_tQ.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-ct58lcY0.mjs.map → NoPermissionsPage-BHPqn_tQ.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BVHI-jv5.js → NoPermissionsPage-C_vGRo8Q.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BVHI-jv5.js.map → NoPermissionsPage-C_vGRo8Q.js.map} +1 -1
- package/dist/_chunks/{Relations-KMf5qEN0.mjs → Relations-C7fPyh5P.mjs} +4 -4
- package/dist/_chunks/Relations-C7fPyh5P.mjs.map +1 -0
- package/dist/_chunks/{Relations-BjpPPCKp.js → Relations-CznVF6LS.js} +4 -4
- package/dist/_chunks/Relations-CznVF6LS.js.map +1 -0
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-CbaIuYoB.mjs} +6 -5
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-CbaIuYoB.mjs.map} +1 -1
- package/dist/_chunks/{en-fbKQxLGn.js → en-otD_UBJi.js} +6 -5
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-otD_UBJi.js.map} +1 -1
- package/dist/_chunks/{index-6kKXK7y8.mjs → index-BJ6uTqLL.mjs} +381 -190
- package/dist/_chunks/index-BJ6uTqLL.mjs.map +1 -0
- package/dist/_chunks/{index-D9ZwczCV.js → index-D9UmmBcM.js} +374 -183
- package/dist/_chunks/index-D9UmmBcM.js.map +1 -0
- package/dist/_chunks/{layout-BJfBoBiF.js → layout-kfu5Wtix.js} +23 -11
- package/dist/_chunks/layout-kfu5Wtix.js.map +1 -0
- package/dist/_chunks/{layout-B1Z-9koY.mjs → layout-uomiIGbG.mjs} +25 -13
- package/dist/_chunks/layout-uomiIGbG.mjs.map +1 -0
- package/dist/_chunks/{relations-CMvjzyU3.js → relations-DKENrxko.js} +2 -2
- package/dist/_chunks/{relations-CMvjzyU3.js.map → relations-DKENrxko.js.map} +1 -1
- package/dist/_chunks/{relations-CgZg7Pyx.mjs → relations-DiDufGSA.mjs} +2 -2
- package/dist/_chunks/{relations-CgZg7Pyx.mjs.map → relations-DiDufGSA.mjs.map} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +16 -16
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +175 -104
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +176 -105
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +2 -1
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/_chunks/EditViewPage-ClIueJnM.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-DxyAOItK.js.map +0 -1
- package/dist/_chunks/Field-BZBYmvaf.mjs.map +0 -1
- package/dist/_chunks/Field-C0Y_SR9e.js.map +0 -1
- package/dist/_chunks/Form-DwvGnISS.js.map +0 -1
- package/dist/_chunks/Form-jwRSC2kV.mjs.map +0 -1
- package/dist/_chunks/History-BgzAIj0G.mjs.map +0 -1
- package/dist/_chunks/History-Cda0Yjzz.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-C29EF97r.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-GH55qfoT.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-CnRt0UT7.js.map +0 -1
- package/dist/_chunks/ListViewPage-QU03PFj1.mjs.map +0 -1
- package/dist/_chunks/Relations-BjpPPCKp.js.map +0 -1
- package/dist/_chunks/Relations-KMf5qEN0.mjs.map +0 -1
- package/dist/_chunks/index-6kKXK7y8.mjs.map +0 -1
- package/dist/_chunks/index-D9ZwczCV.js.map +0 -1
- package/dist/_chunks/layout-B1Z-9koY.mjs.map +0 -1
- package/dist/_chunks/layout-BJfBoBiF.js.map +0 -1
@@ -1,17 +1,17 @@
|
|
1
|
-
import {
|
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,
|
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,
|
6
|
+
import { Button, Menu, 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";
|
@@ -195,8 +159,7 @@ const contentManagerApi = adminApi.enhanceEndpoints({
|
|
195
159
|
"InitialData",
|
196
160
|
"HistoryVersion",
|
197
161
|
"Relations",
|
198
|
-
"
|
199
|
-
"ReleaseAction"
|
162
|
+
"UidAvailability"
|
200
163
|
]
|
201
164
|
});
|
202
165
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -210,7 +173,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
210
173
|
params: query
|
211
174
|
}
|
212
175
|
}),
|
213
|
-
invalidatesTags: (_result,
|
176
|
+
invalidatesTags: (_result, error, { model }) => {
|
177
|
+
if (error) {
|
178
|
+
return [];
|
179
|
+
}
|
180
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
181
|
+
}
|
214
182
|
}),
|
215
183
|
cloneDocument: builder.mutation({
|
216
184
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -221,7 +189,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
221
189
|
params
|
222
190
|
}
|
223
191
|
}),
|
224
|
-
invalidatesTags: (_result, _error, { model }) => [
|
192
|
+
invalidatesTags: (_result, _error, { model }) => [
|
193
|
+
{ type: "Document", id: `${model}_LIST` },
|
194
|
+
{ type: "UidAvailability", id: model }
|
195
|
+
]
|
225
196
|
}),
|
226
197
|
/**
|
227
198
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -238,7 +209,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
238
209
|
}),
|
239
210
|
invalidatesTags: (result, _error, { model }) => [
|
240
211
|
{ type: "Document", id: `${model}_LIST` },
|
241
|
-
"Relations"
|
212
|
+
"Relations",
|
213
|
+
{ type: "UidAvailability", id: model }
|
242
214
|
]
|
243
215
|
}),
|
244
216
|
deleteDocument: builder.mutation({
|
@@ -250,9 +222,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
250
222
|
}
|
251
223
|
}),
|
252
224
|
invalidatesTags: (_result, _error, { collectionType, model }) => [
|
253
|
-
{ type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model }
|
254
|
-
{ type: "Release", id: "LIST" },
|
255
|
-
{ type: "ReleaseAction", id: "LIST" }
|
225
|
+
{ type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model }
|
256
226
|
]
|
257
227
|
}),
|
258
228
|
deleteManyDocuments: builder.mutation({
|
@@ -264,11 +234,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
264
234
|
params
|
265
235
|
}
|
266
236
|
}),
|
267
|
-
invalidatesTags: (_res, _error, { model }) => [
|
268
|
-
{ type: "Document", id: `${model}_LIST` },
|
269
|
-
{ type: "Release", id: "LIST" },
|
270
|
-
{ type: "ReleaseAction", id: "LIST" }
|
271
|
-
]
|
237
|
+
invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
|
272
238
|
}),
|
273
239
|
discardDocument: builder.mutation({
|
274
240
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -286,8 +252,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
286
252
|
},
|
287
253
|
{ type: "Document", id: `${model}_LIST` },
|
288
254
|
"Relations",
|
289
|
-
{ type: "
|
290
|
-
{ type: "ReleaseAction", id: "LIST" }
|
255
|
+
{ type: "UidAvailability", id: model }
|
291
256
|
];
|
292
257
|
}
|
293
258
|
}),
|
@@ -305,6 +270,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
305
270
|
}),
|
306
271
|
providesTags: (result, _error, arg) => {
|
307
272
|
return [
|
273
|
+
{ type: "Document", id: `ALL_LIST` },
|
308
274
|
{ type: "Document", id: `${arg.model}_LIST` },
|
309
275
|
...result?.results.map(({ documentId }) => ({
|
310
276
|
type: "Document",
|
@@ -343,6 +309,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
343
309
|
{
|
344
310
|
type: "Document",
|
345
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`
|
346
317
|
}
|
347
318
|
];
|
348
319
|
}
|
@@ -407,9 +378,20 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
407
378
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
408
379
|
},
|
409
380
|
"Relations",
|
410
|
-
{ type: "
|
411
|
-
{ type: "ReleaseAction", id: "LIST" }
|
381
|
+
{ type: "UidAvailability", id: model }
|
412
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
|
+
}
|
413
395
|
}
|
414
396
|
}),
|
415
397
|
unpublishDocument: builder.mutation({
|
@@ -479,7 +461,7 @@ const buildValidParams = (query) => {
|
|
479
461
|
const isBaseQueryError = (error) => {
|
480
462
|
return error.name !== void 0;
|
481
463
|
};
|
482
|
-
const createYupSchema = (attributes = {}, components = {}) => {
|
464
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
483
465
|
const createModelSchema = (attributes2) => yup.object().shape(
|
484
466
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
485
467
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
@@ -492,7 +474,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
492
474
|
addMinValidation,
|
493
475
|
addMaxValidation,
|
494
476
|
addRegexValidation
|
495
|
-
].map((fn) => fn(attribute));
|
477
|
+
].map((fn) => fn(attribute, options));
|
496
478
|
const transformSchema = pipe(...validations);
|
497
479
|
switch (attribute.type) {
|
498
480
|
case "component": {
|
@@ -593,6 +575,14 @@ const createAttributeSchema = (attribute) => {
|
|
593
575
|
if (!value || typeof value === "string" && value.length === 0) {
|
594
576
|
return true;
|
595
577
|
}
|
578
|
+
if (typeof value === "object") {
|
579
|
+
try {
|
580
|
+
JSON.stringify(value);
|
581
|
+
return true;
|
582
|
+
} catch (err) {
|
583
|
+
return false;
|
584
|
+
}
|
585
|
+
}
|
596
586
|
try {
|
597
587
|
JSON.parse(value);
|
598
588
|
return true;
|
@@ -611,13 +601,7 @@ const createAttributeSchema = (attribute) => {
|
|
611
601
|
return yup.mixed();
|
612
602
|
}
|
613
603
|
};
|
614
|
-
const
|
615
|
-
if (attribute.required) {
|
616
|
-
return schema.required({
|
617
|
-
id: translatedErrors.required.id,
|
618
|
-
defaultMessage: "This field is required."
|
619
|
-
});
|
620
|
-
}
|
604
|
+
const nullableSchema = (schema) => {
|
621
605
|
return schema?.nullable ? schema.nullable() : (
|
622
606
|
// In some cases '.nullable' will not be available on the schema.
|
623
607
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -625,7 +609,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
625
609
|
schema
|
626
610
|
);
|
627
611
|
};
|
628
|
-
const
|
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
|
+
}
|
629
628
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
630
629
|
return schema.min(attribute.minLength, {
|
631
630
|
...translatedErrors.minLength,
|
@@ -647,9 +646,31 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
647
646
|
}
|
648
647
|
return schema;
|
649
648
|
};
|
650
|
-
const addMinValidation = (attribute) => (schema) => {
|
649
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
651
650
|
if ("min" in attribute) {
|
652
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
|
+
}
|
653
674
|
if ("min" in schema && min) {
|
654
675
|
return schema.min(min, {
|
655
676
|
...translatedErrors.min,
|
@@ -776,7 +797,10 @@ const useDocument = (args, opts) => {
|
|
776
797
|
isLoading: isLoadingDocument,
|
777
798
|
isFetching: isFetchingDocument,
|
778
799
|
error
|
779
|
-
} = useGetDocumentQuery(args,
|
800
|
+
} = useGetDocumentQuery(args, {
|
801
|
+
...opts,
|
802
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
803
|
+
});
|
780
804
|
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
781
805
|
React.useEffect(() => {
|
782
806
|
if (error) {
|
@@ -862,6 +886,7 @@ const useDocumentActions = () => {
|
|
862
886
|
const { formatMessage } = useIntl();
|
863
887
|
const { trackUsage } = useTracking();
|
864
888
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
889
|
+
const navigate = useNavigate();
|
865
890
|
const [deleteDocument] = useDeleteDocumentMutation();
|
866
891
|
const _delete = React.useCallback(
|
867
892
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1197,7 +1222,6 @@ const useDocumentActions = () => {
|
|
1197
1222
|
sourceId
|
1198
1223
|
});
|
1199
1224
|
if ("error" in res) {
|
1200
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1201
1225
|
return { error: res.error };
|
1202
1226
|
}
|
1203
1227
|
toggleNotification({
|
@@ -1216,7 +1240,7 @@ const useDocumentActions = () => {
|
|
1216
1240
|
throw err;
|
1217
1241
|
}
|
1218
1242
|
},
|
1219
|
-
[autoCloneDocument,
|
1243
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1220
1244
|
);
|
1221
1245
|
const [cloneDocument] = useCloneDocumentMutation();
|
1222
1246
|
const clone = React.useCallback(
|
@@ -1242,6 +1266,7 @@ const useDocumentActions = () => {
|
|
1242
1266
|
defaultMessage: "Cloned document"
|
1243
1267
|
})
|
1244
1268
|
});
|
1269
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1245
1270
|
return res.data;
|
1246
1271
|
} catch (err) {
|
1247
1272
|
toggleNotification({
|
@@ -1252,7 +1277,7 @@ const useDocumentActions = () => {
|
|
1252
1277
|
throw err;
|
1253
1278
|
}
|
1254
1279
|
},
|
1255
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1280
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1256
1281
|
);
|
1257
1282
|
const [getDoc] = useLazyGetDocumentQuery();
|
1258
1283
|
const getDocument = React.useCallback(
|
@@ -1278,7 +1303,7 @@ const useDocumentActions = () => {
|
|
1278
1303
|
};
|
1279
1304
|
};
|
1280
1305
|
const ProtectedHistoryPage = lazy(
|
1281
|
-
() => import("./History-
|
1306
|
+
() => import("./History-DrwsD1Vc.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1282
1307
|
);
|
1283
1308
|
const routes$1 = [
|
1284
1309
|
{
|
@@ -1291,31 +1316,31 @@ const routes$1 = [
|
|
1291
1316
|
}
|
1292
1317
|
];
|
1293
1318
|
const ProtectedEditViewPage = lazy(
|
1294
|
-
() => import("./EditViewPage-
|
1319
|
+
() => import("./EditViewPage-DiNFdFqP.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1295
1320
|
);
|
1296
1321
|
const ProtectedListViewPage = lazy(
|
1297
|
-
() => import("./ListViewPage-
|
1322
|
+
() => import("./ListViewPage-5a1vw-OK.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1298
1323
|
);
|
1299
1324
|
const ProtectedListConfiguration = lazy(
|
1300
|
-
() => import("./ListConfigurationPage-
|
1325
|
+
() => import("./ListConfigurationPage-BxIP0jRy.mjs").then((mod) => ({
|
1301
1326
|
default: mod.ProtectedListConfiguration
|
1302
1327
|
}))
|
1303
1328
|
);
|
1304
1329
|
const ProtectedEditConfigurationPage = lazy(
|
1305
|
-
() => import("./EditConfigurationPage-
|
1330
|
+
() => import("./EditConfigurationPage-Bk893vVY.mjs").then((mod) => ({
|
1306
1331
|
default: mod.ProtectedEditConfigurationPage
|
1307
1332
|
}))
|
1308
1333
|
);
|
1309
1334
|
const ProtectedComponentConfigurationPage = lazy(
|
1310
|
-
() => import("./ComponentConfigurationPage-
|
1335
|
+
() => import("./ComponentConfigurationPage-9lRmRdIr.mjs").then((mod) => ({
|
1311
1336
|
default: mod.ProtectedComponentConfigurationPage
|
1312
1337
|
}))
|
1313
1338
|
);
|
1314
1339
|
const NoPermissions = lazy(
|
1315
|
-
() => import("./NoPermissionsPage-
|
1340
|
+
() => import("./NoPermissionsPage-BHPqn_tQ.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1316
1341
|
);
|
1317
1342
|
const NoContentType = lazy(
|
1318
|
-
() => import("./NoContentTypePage-
|
1343
|
+
() => import("./NoContentTypePage-Bm6tRcd3.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1319
1344
|
);
|
1320
1345
|
const CollectionTypePages = () => {
|
1321
1346
|
const { collectionType } = useParams();
|
@@ -1429,12 +1454,14 @@ const DocumentActionButton = (action) => {
|
|
1429
1454
|
/* @__PURE__ */ jsx(
|
1430
1455
|
Button,
|
1431
1456
|
{
|
1432
|
-
flex:
|
1457
|
+
flex: "auto",
|
1433
1458
|
startIcon: action.icon,
|
1434
1459
|
disabled: action.disabled,
|
1435
1460
|
onClick: handleClick(action),
|
1436
1461
|
justifyContent: "center",
|
1437
1462
|
variant: action.variant || "default",
|
1463
|
+
paddingTop: "7px",
|
1464
|
+
paddingBottom: "7px",
|
1438
1465
|
children: action.label
|
1439
1466
|
}
|
1440
1467
|
),
|
@@ -1442,7 +1469,7 @@ const DocumentActionButton = (action) => {
|
|
1442
1469
|
DocumentActionConfirmDialog,
|
1443
1470
|
{
|
1444
1471
|
...action.dialog,
|
1445
|
-
variant: action.variant,
|
1472
|
+
variant: action.dialog?.variant ?? action.variant,
|
1446
1473
|
isOpen: dialogId === action.id,
|
1447
1474
|
onClose: handleClose
|
1448
1475
|
}
|
@@ -1499,9 +1526,9 @@ const DocumentActionsMenu = ({
|
|
1499
1526
|
disabled: isDisabled,
|
1500
1527
|
size: "S",
|
1501
1528
|
endIcon: null,
|
1502
|
-
paddingTop: "
|
1503
|
-
paddingLeft: "
|
1504
|
-
paddingRight: "
|
1529
|
+
paddingTop: "4px",
|
1530
|
+
paddingLeft: "7px",
|
1531
|
+
paddingRight: "7px",
|
1505
1532
|
variant,
|
1506
1533
|
children: [
|
1507
1534
|
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
@@ -1521,10 +1548,25 @@ const DocumentActionsMenu = ({
|
|
1521
1548
|
onSelect: handleClick(action),
|
1522
1549
|
display: "block",
|
1523
1550
|
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
1524
|
-
/* @__PURE__ */ jsxs(
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
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
|
+
),
|
1528
1570
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
1529
1571
|
Flex,
|
1530
1572
|
{
|
@@ -1664,13 +1706,17 @@ const PublishAction$1 = ({
|
|
1664
1706
|
const navigate = useNavigate();
|
1665
1707
|
const { toggleNotification } = useNotification();
|
1666
1708
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
1709
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
1667
1710
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
1668
1711
|
const { formatMessage } = useIntl();
|
1669
|
-
const { canPublish
|
1670
|
-
"PublishAction",
|
1671
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1672
|
-
);
|
1712
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1673
1713
|
const { publish } = useDocumentActions();
|
1714
|
+
const [
|
1715
|
+
countDraftRelations,
|
1716
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
1717
|
+
] = useLazyGetDraftRelationCountQuery();
|
1718
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
1719
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1674
1720
|
const [{ query, rawQuery }] = useQueryParams();
|
1675
1721
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1676
1722
|
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1679,10 +1725,102 @@ const PublishAction$1 = ({
|
|
1679
1725
|
const validate = useForm("PublishAction", (state) => state.validate);
|
1680
1726
|
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1681
1727
|
const formValues = useForm("PublishAction", ({ values }) => values);
|
1728
|
+
React.useEffect(() => {
|
1729
|
+
if (isErrorDraftRelations) {
|
1730
|
+
toggleNotification({
|
1731
|
+
type: "danger",
|
1732
|
+
message: formatMessage({
|
1733
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
1734
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
1735
|
+
})
|
1736
|
+
});
|
1737
|
+
}
|
1738
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
1739
|
+
React.useEffect(() => {
|
1740
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
1741
|
+
const extractDraftRelations = (data) => {
|
1742
|
+
const relations = data.connect || [];
|
1743
|
+
relations.forEach((relation) => {
|
1744
|
+
if (relation.status === "draft") {
|
1745
|
+
localDraftRelations.add(relation.id);
|
1746
|
+
}
|
1747
|
+
});
|
1748
|
+
};
|
1749
|
+
const traverseAndExtract = (data) => {
|
1750
|
+
Object.entries(data).forEach(([key, value]) => {
|
1751
|
+
if (key === "connect" && Array.isArray(value)) {
|
1752
|
+
extractDraftRelations({ connect: value });
|
1753
|
+
} else if (typeof value === "object" && value !== null) {
|
1754
|
+
traverseAndExtract(value);
|
1755
|
+
}
|
1756
|
+
});
|
1757
|
+
};
|
1758
|
+
if (!documentId || modified) {
|
1759
|
+
traverseAndExtract(formValues);
|
1760
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
1761
|
+
}
|
1762
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1763
|
+
React.useEffect(() => {
|
1764
|
+
if (documentId && !isListView) {
|
1765
|
+
const fetchDraftRelationsCount = async () => {
|
1766
|
+
const { data, error } = await countDraftRelations({
|
1767
|
+
collectionType,
|
1768
|
+
model,
|
1769
|
+
documentId,
|
1770
|
+
params
|
1771
|
+
});
|
1772
|
+
if (error) {
|
1773
|
+
throw error;
|
1774
|
+
}
|
1775
|
+
if (data) {
|
1776
|
+
setServerCountOfDraftRelations(data.data);
|
1777
|
+
}
|
1778
|
+
};
|
1779
|
+
fetchDraftRelationsCount();
|
1780
|
+
}
|
1781
|
+
}, [isListView, documentId, countDraftRelations, collectionType, model, params]);
|
1682
1782
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1683
1783
|
if (!schema?.options?.draftAndPublish) {
|
1684
1784
|
return null;
|
1685
1785
|
}
|
1786
|
+
const performPublish = async () => {
|
1787
|
+
setSubmitting(true);
|
1788
|
+
try {
|
1789
|
+
const { errors } = await validate();
|
1790
|
+
if (errors) {
|
1791
|
+
toggleNotification({
|
1792
|
+
type: "danger",
|
1793
|
+
message: formatMessage({
|
1794
|
+
id: "content-manager.validation.error",
|
1795
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1796
|
+
})
|
1797
|
+
});
|
1798
|
+
return;
|
1799
|
+
}
|
1800
|
+
const res = await publish(
|
1801
|
+
{
|
1802
|
+
collectionType,
|
1803
|
+
model,
|
1804
|
+
documentId,
|
1805
|
+
params
|
1806
|
+
},
|
1807
|
+
formValues
|
1808
|
+
);
|
1809
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1810
|
+
navigate({
|
1811
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1812
|
+
search: rawQuery
|
1813
|
+
});
|
1814
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1815
|
+
setErrors(formatValidationErrors(res.error));
|
1816
|
+
}
|
1817
|
+
} finally {
|
1818
|
+
setSubmitting(false);
|
1819
|
+
}
|
1820
|
+
};
|
1821
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1822
|
+
const enableDraftRelationsCount = false;
|
1823
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1686
1824
|
return {
|
1687
1825
|
/**
|
1688
1826
|
* Disabled when:
|
@@ -1692,49 +1830,36 @@ const PublishAction$1 = ({
|
|
1692
1830
|
* - the document is already published & not modified
|
1693
1831
|
* - the document is being created & not modified
|
1694
1832
|
* - the user doesn't have the permission to publish
|
1695
|
-
* - the user doesn't have the permission to create a new document
|
1696
|
-
* - the user doesn't have the permission to update the document
|
1697
1833
|
*/
|
1698
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
1834
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1699
1835
|
label: formatMessage({
|
1700
1836
|
id: "app.utils.publish",
|
1701
1837
|
defaultMessage: "Publish"
|
1702
1838
|
}),
|
1703
1839
|
onClick: async () => {
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
documentId,
|
1722
|
-
params
|
1723
|
-
},
|
1724
|
-
formValues
|
1725
|
-
);
|
1726
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1727
|
-
navigate({
|
1728
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1729
|
-
search: rawQuery
|
1730
|
-
});
|
1731
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1732
|
-
setErrors(formatValidationErrors(res.error));
|
1840
|
+
await performPublish();
|
1841
|
+
},
|
1842
|
+
dialog: hasDraftRelations ? {
|
1843
|
+
type: "dialog",
|
1844
|
+
variant: "danger",
|
1845
|
+
footer: null,
|
1846
|
+
title: formatMessage({
|
1847
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
1848
|
+
defaultMessage: "Confirmation"
|
1849
|
+
}),
|
1850
|
+
content: formatMessage(
|
1851
|
+
{
|
1852
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
1853
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
1854
|
+
},
|
1855
|
+
{
|
1856
|
+
count: totalDraftRelations
|
1733
1857
|
}
|
1734
|
-
|
1735
|
-
|
1858
|
+
),
|
1859
|
+
onConfirm: async () => {
|
1860
|
+
await performPublish();
|
1736
1861
|
}
|
1737
|
-
}
|
1862
|
+
} : void 0
|
1738
1863
|
};
|
1739
1864
|
};
|
1740
1865
|
PublishAction$1.type = "publish";
|
@@ -1750,10 +1875,6 @@ const UpdateAction = ({
|
|
1750
1875
|
const cloneMatch = useMatch(CLONE_PATH);
|
1751
1876
|
const isCloning = cloneMatch !== null;
|
1752
1877
|
const { formatMessage } = useIntl();
|
1753
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1754
|
-
canCreate: canCreate2,
|
1755
|
-
canUpdate: canUpdate2
|
1756
|
-
}));
|
1757
1878
|
const { create, update, clone } = useDocumentActions();
|
1758
1879
|
const [{ query, rawQuery }] = useQueryParams();
|
1759
1880
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
@@ -1770,10 +1891,8 @@ const UpdateAction = ({
|
|
1770
1891
|
* - the form is submitting
|
1771
1892
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1772
1893
|
* - the active tab is the published tab
|
1773
|
-
* - the user doesn't have the permission to create a new document
|
1774
|
-
* - the user doesn't have the permission to update the document
|
1775
1894
|
*/
|
1776
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
1895
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1777
1896
|
label: formatMessage({
|
1778
1897
|
id: "content-manager.containers.Edit.save",
|
1779
1898
|
defaultMessage: "Save"
|
@@ -1781,16 +1900,18 @@ const UpdateAction = ({
|
|
1781
1900
|
onClick: async () => {
|
1782
1901
|
setSubmitting(true);
|
1783
1902
|
try {
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1903
|
+
if (activeTab !== "draft") {
|
1904
|
+
const { errors } = await validate();
|
1905
|
+
if (errors) {
|
1906
|
+
toggleNotification({
|
1907
|
+
type: "danger",
|
1908
|
+
message: formatMessage({
|
1909
|
+
id: "content-manager.validation.error",
|
1910
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1911
|
+
})
|
1912
|
+
});
|
1913
|
+
return;
|
1914
|
+
}
|
1794
1915
|
}
|
1795
1916
|
if (isCloning) {
|
1796
1917
|
const res = await clone(
|
@@ -1802,10 +1923,13 @@ const UpdateAction = ({
|
|
1802
1923
|
document
|
1803
1924
|
);
|
1804
1925
|
if ("data" in res) {
|
1805
|
-
navigate(
|
1806
|
-
|
1807
|
-
|
1808
|
-
|
1926
|
+
navigate(
|
1927
|
+
{
|
1928
|
+
pathname: `../${res.data.documentId}`,
|
1929
|
+
search: rawQuery
|
1930
|
+
},
|
1931
|
+
{ relative: "path" }
|
1932
|
+
);
|
1809
1933
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1810
1934
|
setErrors(formatValidationErrors(res.error));
|
1811
1935
|
}
|
@@ -1833,10 +1957,13 @@ const UpdateAction = ({
|
|
1833
1957
|
document
|
1834
1958
|
);
|
1835
1959
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1836
|
-
navigate(
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1960
|
+
navigate(
|
1961
|
+
{
|
1962
|
+
pathname: `../${res.data.documentId}`,
|
1963
|
+
search: rawQuery
|
1964
|
+
},
|
1965
|
+
{ replace: true, relative: "path" }
|
1966
|
+
);
|
1840
1967
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1841
1968
|
setErrors(formatValidationErrors(res.error));
|
1842
1969
|
}
|
@@ -2082,23 +2209,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2082
2209
|
id: "content-manager.containers.edit.title.new",
|
2083
2210
|
defaultMessage: "Create an entry"
|
2084
2211
|
}) : documentTitle;
|
2085
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2212
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2086
2213
|
/* @__PURE__ */ jsx(BackButton, {}),
|
2087
|
-
/* @__PURE__ */ jsxs(
|
2088
|
-
|
2089
|
-
{
|
2090
|
-
|
2091
|
-
|
2092
|
-
paddingTop: 1,
|
2093
|
-
gap: "80px",
|
2094
|
-
alignItems: "flex-start",
|
2095
|
-
children: [
|
2096
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2097
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2098
|
-
]
|
2099
|
-
}
|
2100
|
-
),
|
2101
|
-
status ? /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2214
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2215
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2216
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2217
|
+
] }),
|
2218
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2102
2219
|
] });
|
2103
2220
|
};
|
2104
2221
|
const HeaderToolbar = () => {
|
@@ -2789,7 +2906,7 @@ const ConfirmBulkActionDialog = ({
|
|
2789
2906
|
endAction
|
2790
2907
|
}) => {
|
2791
2908
|
const { formatMessage } = useIntl();
|
2792
|
-
return /* @__PURE__ */ jsx(Dialog.Root, {
|
2909
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2793
2910
|
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
2794
2911
|
id: "app.components.ConfirmDialog.title",
|
2795
2912
|
defaultMessage: "Confirmation"
|
@@ -2820,6 +2937,7 @@ const ConfirmDialogPublishAll = ({
|
|
2820
2937
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2821
2938
|
const { model, schema } = useDoc();
|
2822
2939
|
const [{ query }] = useQueryParams();
|
2940
|
+
const enableDraftRelationsCount = false;
|
2823
2941
|
const {
|
2824
2942
|
data: countDraftRelations = 0,
|
2825
2943
|
isLoading,
|
@@ -2831,7 +2949,7 @@ const ConfirmDialogPublishAll = ({
|
|
2831
2949
|
locale: query?.plugins?.i18n?.locale
|
2832
2950
|
},
|
2833
2951
|
{
|
2834
|
-
skip:
|
2952
|
+
skip: !enableDraftRelationsCount
|
2835
2953
|
}
|
2836
2954
|
);
|
2837
2955
|
React.useEffect(() => {
|
@@ -2910,7 +3028,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
|
2910
3028
|
)
|
2911
3029
|
);
|
2912
3030
|
} else {
|
2913
|
-
messages.push(
|
3031
|
+
messages.push(
|
3032
|
+
...formatErrorMessages(
|
3033
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3034
|
+
value,
|
3035
|
+
currentKey,
|
3036
|
+
formatMessage
|
3037
|
+
)
|
3038
|
+
);
|
2914
3039
|
}
|
2915
3040
|
} else {
|
2916
3041
|
messages.push(
|
@@ -3009,7 +3134,7 @@ const SelectedEntriesTableContent = ({
|
|
3009
3134
|
status: row.status
|
3010
3135
|
}
|
3011
3136
|
) }),
|
3012
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3137
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3013
3138
|
IconButton,
|
3014
3139
|
{
|
3015
3140
|
tag: Link,
|
@@ -3032,9 +3157,10 @@ const SelectedEntriesTableContent = ({
|
|
3032
3157
|
),
|
3033
3158
|
target: "_blank",
|
3034
3159
|
marginLeft: "auto",
|
3035
|
-
|
3160
|
+
variant: "ghost",
|
3161
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3036
3162
|
}
|
3037
|
-
) })
|
3163
|
+
) }) })
|
3038
3164
|
] }, row.id)) })
|
3039
3165
|
] });
|
3040
3166
|
};
|
@@ -3071,7 +3197,13 @@ const SelectedEntriesModalContent = ({
|
|
3071
3197
|
);
|
3072
3198
|
const { rows, validationErrors } = React.useMemo(() => {
|
3073
3199
|
if (data.length > 0 && schema) {
|
3074
|
-
const validate = createYupSchema(
|
3200
|
+
const validate = createYupSchema(
|
3201
|
+
schema.attributes,
|
3202
|
+
components,
|
3203
|
+
// Since this is the "Publish" action, the validation
|
3204
|
+
// schema must enforce the rules for published entities
|
3205
|
+
{ status: "published" }
|
3206
|
+
);
|
3075
3207
|
const validationErrors2 = {};
|
3076
3208
|
const rows2 = data.map((entry) => {
|
3077
3209
|
try {
|
@@ -3421,7 +3553,7 @@ const TableActions = ({ document }) => {
|
|
3421
3553
|
DescriptionComponentRenderer,
|
3422
3554
|
{
|
3423
3555
|
props,
|
3424
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3556
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3425
3557
|
children: (actions2) => {
|
3426
3558
|
const tableRowActions = actions2.filter((action) => {
|
3427
3559
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3532,7 +3664,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3532
3664
|
}),
|
3533
3665
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3534
3666
|
footer: ({ onClose }) => {
|
3535
|
-
return /* @__PURE__ */ jsxs(
|
3667
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3536
3668
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3537
3669
|
id: "cancel",
|
3538
3670
|
defaultMessage: "Cancel"
|
@@ -3573,8 +3705,7 @@ class ContentManagerPlugin {
|
|
3573
3705
|
documentActions = [
|
3574
3706
|
...DEFAULT_ACTIONS,
|
3575
3707
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3576
|
-
...DEFAULT_HEADER_ACTIONS
|
3577
|
-
HistoryAction
|
3708
|
+
...DEFAULT_HEADER_ACTIONS
|
3578
3709
|
];
|
3579
3710
|
editViewSidePanels = [ActionsPanel];
|
3580
3711
|
headerActions = [];
|
@@ -3663,6 +3794,52 @@ const getPrintableType = (value) => {
|
|
3663
3794
|
}
|
3664
3795
|
return nativeType;
|
3665
3796
|
};
|
3797
|
+
const HistoryAction = ({ model, document }) => {
|
3798
|
+
const { formatMessage } = useIntl();
|
3799
|
+
const [{ query }] = useQueryParams();
|
3800
|
+
const navigate = useNavigate();
|
3801
|
+
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3802
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3803
|
+
return null;
|
3804
|
+
}
|
3805
|
+
return {
|
3806
|
+
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3807
|
+
label: formatMessage({
|
3808
|
+
id: "content-manager.history.document-action",
|
3809
|
+
defaultMessage: "Content History"
|
3810
|
+
}),
|
3811
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3812
|
+
disabled: (
|
3813
|
+
/**
|
3814
|
+
* The user is creating a new document.
|
3815
|
+
* It hasn't been saved yet, so there's no history to go to
|
3816
|
+
*/
|
3817
|
+
!document || /**
|
3818
|
+
* The document has been created but the current dimension has never been saved.
|
3819
|
+
* For example, the user is creating a new locale in an existing document,
|
3820
|
+
* so there's no history for the document in that locale
|
3821
|
+
*/
|
3822
|
+
!document.id || /**
|
3823
|
+
* History is only available for content types created by the user.
|
3824
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3825
|
+
* which start with `admin::` or `plugin::`
|
3826
|
+
*/
|
3827
|
+
!model.startsWith("api::")
|
3828
|
+
),
|
3829
|
+
position: "header"
|
3830
|
+
};
|
3831
|
+
};
|
3832
|
+
HistoryAction.type = "history";
|
3833
|
+
const historyAdmin = {
|
3834
|
+
bootstrap(app) {
|
3835
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3836
|
+
addDocumentAction((actions2) => {
|
3837
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3838
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3839
|
+
return actions2;
|
3840
|
+
});
|
3841
|
+
}
|
3842
|
+
};
|
3666
3843
|
const initialState = {
|
3667
3844
|
collectionTypeLinks: [],
|
3668
3845
|
components: [],
|
@@ -3713,15 +3890,29 @@ const index = {
|
|
3713
3890
|
defaultMessage: "Content Manager"
|
3714
3891
|
},
|
3715
3892
|
permissions: [],
|
3716
|
-
Component: () => import("./layout-B1Z-9koY.mjs").then((mod) => ({ default: mod.Layout })),
|
3717
3893
|
position: 1
|
3718
3894
|
});
|
3895
|
+
app.router.addRoute({
|
3896
|
+
path: "content-manager/*",
|
3897
|
+
lazy: async () => {
|
3898
|
+
const { Layout } = await import("./layout-uomiIGbG.mjs");
|
3899
|
+
return {
|
3900
|
+
Component: Layout
|
3901
|
+
};
|
3902
|
+
},
|
3903
|
+
children: routes
|
3904
|
+
});
|
3719
3905
|
app.registerPlugin(cm.config);
|
3720
3906
|
},
|
3907
|
+
bootstrap(app) {
|
3908
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
3909
|
+
historyAdmin.bootstrap(app);
|
3910
|
+
}
|
3911
|
+
},
|
3721
3912
|
async registerTrads({ locales }) {
|
3722
3913
|
const importedTrads = await Promise.all(
|
3723
3914
|
locales.map((locale) => {
|
3724
|
-
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-
|
3915
|
+
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-CbaIuYoB.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 }) => {
|
3725
3916
|
return {
|
3726
3917
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3727
3918
|
locale
|
@@ -3767,11 +3958,11 @@ export {
|
|
3767
3958
|
PERMISSIONS as k,
|
3768
3959
|
DocumentRBAC as l,
|
3769
3960
|
DOCUMENT_META_FIELDS as m,
|
3770
|
-
|
3771
|
-
|
3772
|
-
|
3773
|
-
|
3774
|
-
|
3961
|
+
CLONE_PATH as n,
|
3962
|
+
useDocLayout as o,
|
3963
|
+
useGetContentTypeConfigurationQuery as p,
|
3964
|
+
CREATOR_FIELDS as q,
|
3965
|
+
getMainField as r,
|
3775
3966
|
setInitialData as s,
|
3776
3967
|
getDisplayName as t,
|
3777
3968
|
useContentTypeSchema as u,
|
@@ -3781,4 +3972,4 @@ export {
|
|
3781
3972
|
capitalise as y,
|
3782
3973
|
useUpdateContentTypeConfigurationMutation as z
|
3783
3974
|
};
|
3784
|
-
//# sourceMappingURL=index-
|
3975
|
+
//# sourceMappingURL=index-BJ6uTqLL.mjs.map
|