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