@strapi/content-manager 0.0.0-experimental.fb442e5e12dd3f611303691bf85a249520ba348b → 0.0.0-next.ce84fada19d58a7dfbdd553035e6558f8befcba4
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-B3yDbeU1.mjs → ComponentConfigurationPage-DfFSZQxe.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-B3yDbeU1.mjs.map → ComponentConfigurationPage-DfFSZQxe.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-KXSuLnQD.js → ComponentConfigurationPage-FqfsxQ1j.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-KXSuLnQD.js.map → ComponentConfigurationPage-FqfsxQ1j.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-BQ17--5R.js → EditConfigurationPage-Cn0e8t3I.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BQ17--5R.js.map → EditConfigurationPage-Cn0e8t3I.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-D7PrLO8j.mjs → EditConfigurationPage-DdPNAbl3.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-D7PrLO8j.mjs.map → EditConfigurationPage-DdPNAbl3.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-B7VgwJaG.mjs → EditViewPage-B82x_x1b.mjs} +15 -5
- package/dist/_chunks/EditViewPage-B82x_x1b.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-BgjdnGz2.js → EditViewPage-DlxEHhUt.js} +15 -5
- package/dist/_chunks/EditViewPage-DlxEHhUt.js.map +1 -0
- package/dist/_chunks/{Field-CdK7ZLmv.js → Field-COL25JiC.js} +100 -87
- package/dist/_chunks/Field-COL25JiC.js.map +1 -0
- package/dist/_chunks/{Field-tHCw4lGA.mjs → Field-DufHXW17.mjs} +97 -84
- package/dist/_chunks/Field-DufHXW17.mjs.map +1 -0
- package/dist/_chunks/{Form-C_0KTVvV.js → Form-BssUwrTO.js} +16 -8
- package/dist/_chunks/Form-BssUwrTO.js.map +1 -0
- package/dist/_chunks/{Form-BJxdTv3Q.mjs → Form-u_kAOhwB.mjs} +16 -8
- package/dist/_chunks/Form-u_kAOhwB.mjs.map +1 -0
- package/dist/_chunks/{History-nuEzM5qm.js → History-C9t9UqpO.js} +23 -10
- package/dist/_chunks/History-C9t9UqpO.js.map +1 -0
- package/dist/_chunks/{History-DR2txJLE.mjs → History-DRwA3oMM.mjs} +24 -11
- package/dist/_chunks/History-DRwA3oMM.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-CnB86Psm.js → ListConfigurationPage-BXYPohh-.js} +2 -2
- package/dist/_chunks/{ListConfigurationPage-CnB86Psm.js.map → ListConfigurationPage-BXYPohh-.js.map} +1 -1
- package/dist/_chunks/{ListConfigurationPage-voFVtXu6.mjs → ListConfigurationPage-BxfQJzPk.mjs} +2 -2
- package/dist/_chunks/{ListConfigurationPage-voFVtXu6.mjs.map → ListConfigurationPage-BxfQJzPk.mjs.map} +1 -1
- package/dist/_chunks/{ListViewPage-B_GaWgRH.mjs → ListViewPage-CELx2ysp.mjs} +40 -36
- package/dist/_chunks/ListViewPage-CELx2ysp.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-SXIXm-RM.js → ListViewPage-D2VD8Szg.js} +43 -39
- package/dist/_chunks/ListViewPage-D2VD8Szg.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-BzsQ3hLZ.js → NoContentTypePage-BV9IjJSM.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-BzsQ3hLZ.js.map → NoContentTypePage-BV9IjJSM.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-CYiGpsbj.mjs → NoContentTypePage-DtJ9jcfk.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CYiGpsbj.mjs.map → NoContentTypePage-DtJ9jcfk.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-B5baIHal.mjs → NoPermissionsPage-DWleVYK7.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-B5baIHal.mjs.map → NoPermissionsPage-DWleVYK7.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-IGkId4C5.js → NoPermissionsPage-Dp8NpF9I.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-IGkId4C5.js.map → NoPermissionsPage-Dp8NpF9I.js.map} +1 -1
- package/dist/_chunks/{Relations-CIYDdKU-.mjs → Relations-BTcf5xaw.mjs} +32 -23
- package/dist/_chunks/Relations-BTcf5xaw.mjs.map +1 -0
- package/dist/_chunks/{Relations-Dhuurpx2.js → Relations-DR7EUgyC.js} +32 -23
- 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-CdT0kHZ8.js → index-BdMf2lfT.js} +2017 -1886
- package/dist/_chunks/index-BdMf2lfT.js.map +1 -0
- package/dist/_chunks/{index-C9TJPyni.mjs → index-wnqzm4Q8.mjs} +2037 -1906
- package/dist/_chunks/index-wnqzm4Q8.mjs.map +1 -0
- package/dist/_chunks/{layout-BNqvLR_b.mjs → layout-2CfjL0T9.mjs} +5 -4
- package/dist/_chunks/{layout-BNqvLR_b.mjs.map → layout-2CfjL0T9.mjs.map} +1 -1
- package/dist/_chunks/{layout-C6dxWYT7.js → layout-B2MyZU-_.js} +5 -4
- package/dist/_chunks/{layout-C6dxWYT7.js.map → layout-B2MyZU-_.js.map} +1 -1
- package/dist/_chunks/{relations-DtFaDnP1.js → relations-BH7JJGGe.js} +2 -2
- package/dist/_chunks/{relations-DtFaDnP1.js.map → relations-BH7JJGGe.js.map} +1 -1
- package/dist/_chunks/{relations-CkKqKw65.mjs → relations-C0w0GcXi.mjs} +2 -2
- package/dist/_chunks/{relations-CkKqKw65.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/WysiwygStyles.d.ts +0 -32
- 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 +77 -39
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +77 -39
- 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/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 +1 -0
- 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/permission-checker.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-B7VgwJaG.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-BgjdnGz2.js.map +0 -1
- package/dist/_chunks/Field-CdK7ZLmv.js.map +0 -1
- package/dist/_chunks/Field-tHCw4lGA.mjs.map +0 -1
- package/dist/_chunks/Form-BJxdTv3Q.mjs.map +0 -1
- package/dist/_chunks/Form-C_0KTVvV.js.map +0 -1
- package/dist/_chunks/History-DR2txJLE.mjs.map +0 -1
- package/dist/_chunks/History-nuEzM5qm.js.map +0 -1
- package/dist/_chunks/ListViewPage-B_GaWgRH.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-SXIXm-RM.js.map +0 -1
- package/dist/_chunks/Relations-CIYDdKU-.mjs.map +0 -1
- package/dist/_chunks/Relations-Dhuurpx2.js.map +0 -1
- package/dist/_chunks/index-C9TJPyni.mjs.map +0 -1
- package/dist/_chunks/index-CdT0kHZ8.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 {
|
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({
|
@@ -188,7 +197,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
188
197
|
params
|
189
198
|
}
|
190
199
|
}),
|
191
|
-
invalidatesTags: (_result, _error, { model }) => [
|
200
|
+
invalidatesTags: (_result, _error, { model }) => [
|
201
|
+
{ type: "Document", id: `${model}_LIST` },
|
202
|
+
{ type: "UidAvailability", id: model }
|
203
|
+
]
|
192
204
|
}),
|
193
205
|
/**
|
194
206
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -205,7 +217,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
205
217
|
}),
|
206
218
|
invalidatesTags: (result, _error, { model }) => [
|
207
219
|
{ type: "Document", id: `${model}_LIST` },
|
208
|
-
"Relations"
|
220
|
+
"Relations",
|
221
|
+
{ type: "UidAvailability", id: model }
|
209
222
|
]
|
210
223
|
}),
|
211
224
|
deleteDocument: builder.mutation({
|
@@ -246,7 +259,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
246
259
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
247
260
|
},
|
248
261
|
{ type: "Document", id: `${model}_LIST` },
|
249
|
-
"Relations"
|
262
|
+
"Relations",
|
263
|
+
{ type: "UidAvailability", id: model }
|
250
264
|
];
|
251
265
|
}
|
252
266
|
}),
|
@@ -371,7 +385,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
371
385
|
type: "Document",
|
372
386
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
373
387
|
},
|
374
|
-
"Relations"
|
388
|
+
"Relations",
|
389
|
+
{ type: "UidAvailability", id: model }
|
375
390
|
];
|
376
391
|
},
|
377
392
|
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
@@ -454,20 +469,39 @@ const buildValidParams = (query) => {
|
|
454
469
|
const isBaseQueryError = (error) => {
|
455
470
|
return error.name !== void 0;
|
456
471
|
};
|
457
|
-
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 }) => {
|
458
491
|
const createModelSchema = (attributes2) => yup.object().shape(
|
459
492
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
460
493
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
461
494
|
return acc;
|
462
495
|
}
|
463
496
|
const validations = [
|
497
|
+
addNullableValidation,
|
464
498
|
addRequiredValidation,
|
465
499
|
addMinLengthValidation,
|
466
500
|
addMaxLengthValidation,
|
467
501
|
addMinValidation,
|
468
502
|
addMaxValidation,
|
469
503
|
addRegexValidation
|
470
|
-
].map((fn) => fn(attribute));
|
504
|
+
].map((fn) => fn(attribute, options));
|
471
505
|
const transformSchema = pipe(...validations);
|
472
506
|
switch (attribute.type) {
|
473
507
|
case "component": {
|
@@ -477,12 +511,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
477
511
|
...acc,
|
478
512
|
[name]: transformSchema(
|
479
513
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
480
|
-
)
|
514
|
+
).test(arrayValidator(attribute, options))
|
481
515
|
};
|
482
516
|
} else {
|
483
517
|
return {
|
484
518
|
...acc,
|
485
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
519
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
486
520
|
};
|
487
521
|
}
|
488
522
|
}
|
@@ -504,7 +538,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
504
538
|
}
|
505
539
|
)
|
506
540
|
)
|
507
|
-
)
|
541
|
+
).test(arrayValidator(attribute, options))
|
508
542
|
};
|
509
543
|
case "relation":
|
510
544
|
return {
|
@@ -516,7 +550,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
516
550
|
} else if (Array.isArray(value)) {
|
517
551
|
return yup.array().of(
|
518
552
|
yup.object().shape({
|
519
|
-
id: yup.
|
553
|
+
id: yup.number().required()
|
520
554
|
})
|
521
555
|
);
|
522
556
|
} else if (typeof value === "object") {
|
@@ -594,13 +628,7 @@ const createAttributeSchema = (attribute) => {
|
|
594
628
|
return yup.mixed();
|
595
629
|
}
|
596
630
|
};
|
597
|
-
const
|
598
|
-
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
599
|
-
return schema.min(1, translatedErrors.required);
|
600
|
-
}
|
601
|
-
if (attribute.required && attribute.type !== "relation") {
|
602
|
-
return schema.required(translatedErrors.required);
|
603
|
-
}
|
631
|
+
const nullableSchema = (schema) => {
|
604
632
|
return schema?.nullable ? schema.nullable() : (
|
605
633
|
// In some cases '.nullable' will not be available on the schema.
|
606
634
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -608,7 +636,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
608
636
|
schema
|
609
637
|
);
|
610
638
|
};
|
611
|
-
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
|
+
}
|
612
655
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
613
656
|
return schema.min(attribute.minLength, {
|
614
657
|
...translatedErrors.minLength,
|
@@ -630,32 +673,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
630
673
|
}
|
631
674
|
return schema;
|
632
675
|
};
|
633
|
-
const addMinValidation = (attribute) => (schema) => {
|
634
|
-
if ("
|
676
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
677
|
+
if (options.status === "draft") {
|
678
|
+
return schema;
|
679
|
+
}
|
680
|
+
if ("min" in attribute && "min" in schema) {
|
635
681
|
const min = toInteger(attribute.min);
|
636
|
-
if (
|
637
|
-
if (!attribute.required && "test" in schema && min) {
|
638
|
-
return schema.test(
|
639
|
-
"custom-min",
|
640
|
-
{
|
641
|
-
...translatedErrors.min,
|
642
|
-
values: {
|
643
|
-
min: attribute.min
|
644
|
-
}
|
645
|
-
},
|
646
|
-
(value) => {
|
647
|
-
if (!value) {
|
648
|
-
return true;
|
649
|
-
}
|
650
|
-
if (Array.isArray(value) && value.length === 0) {
|
651
|
-
return true;
|
652
|
-
}
|
653
|
-
return value.length >= min;
|
654
|
-
}
|
655
|
-
);
|
656
|
-
}
|
657
|
-
}
|
658
|
-
if ("min" in schema && min) {
|
682
|
+
if (min) {
|
659
683
|
return schema.min(min, {
|
660
684
|
...translatedErrors.min,
|
661
685
|
values: {
|
@@ -773,19 +797,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
773
797
|
}, {});
|
774
798
|
return componentsByKey;
|
775
799
|
};
|
776
|
-
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);
|
777
899
|
const { toggleNotification } = useNotification();
|
778
900
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
901
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
779
902
|
const {
|
780
|
-
|
781
|
-
isLoading:
|
782
|
-
|
783
|
-
|
784
|
-
} =
|
785
|
-
|
786
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
787
|
-
});
|
788
|
-
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;
|
789
909
|
React.useEffect(() => {
|
790
910
|
if (error) {
|
791
911
|
toggleNotification({
|
@@ -793,362 +913,440 @@ const useDocument = (args, opts) => {
|
|
793
913
|
message: formatAPIError(error)
|
794
914
|
});
|
795
915
|
}
|
796
|
-
}, [
|
797
|
-
const
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
(document) => {
|
805
|
-
if (!validationSchema) {
|
806
|
-
throw new Error(
|
807
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
808
|
-
);
|
809
|
-
}
|
810
|
-
try {
|
811
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
812
|
-
return null;
|
813
|
-
} catch (error2) {
|
814
|
-
if (error2 instanceof ValidationError) {
|
815
|
-
return getYupValidationErrors(error2);
|
816
|
-
}
|
817
|
-
throw error2;
|
818
|
-
}
|
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
|
819
924
|
},
|
820
|
-
[
|
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]
|
821
941
|
);
|
822
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
823
942
|
return {
|
824
|
-
|
825
|
-
document: data?.data,
|
826
|
-
meta: data?.meta,
|
943
|
+
error,
|
827
944
|
isLoading,
|
828
|
-
|
829
|
-
|
830
|
-
};
|
831
|
-
};
|
832
|
-
const useDoc = () => {
|
833
|
-
const { id, slug, collectionType, origin } = useParams();
|
834
|
-
const [{ query }] = useQueryParams();
|
835
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
836
|
-
if (!collectionType) {
|
837
|
-
throw new Error("Could not find collectionType in url params");
|
838
|
-
}
|
839
|
-
if (!slug) {
|
840
|
-
throw new Error("Could not find model in url params");
|
841
|
-
}
|
842
|
-
return {
|
843
|
-
collectionType,
|
844
|
-
model: slug,
|
845
|
-
id: origin || id === "create" ? void 0 : id,
|
846
|
-
...useDocument(
|
847
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
848
|
-
{
|
849
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
850
|
-
}
|
851
|
-
)
|
945
|
+
edit,
|
946
|
+
list: listLayout
|
852
947
|
};
|
853
948
|
};
|
854
|
-
const
|
855
|
-
|
856
|
-
|
857
|
-
}
|
858
|
-
return Object.keys(trad).reduce((acc, current) => {
|
859
|
-
acc[`${pluginId}.${current}`] = trad[current];
|
860
|
-
return acc;
|
861
|
-
}, {});
|
862
|
-
};
|
863
|
-
const getTranslation = (id) => `content-manager.${id}`;
|
864
|
-
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
865
|
-
id: "notification.error",
|
866
|
-
defaultMessage: "An error occurred, please try again"
|
949
|
+
const useDocLayout = () => {
|
950
|
+
const { model } = useDoc();
|
951
|
+
return useDocumentLayout(model);
|
867
952
|
};
|
868
|
-
const
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
const
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
message: formatAPIError(res.error)
|
888
|
-
});
|
889
|
-
return { error: res.error };
|
890
|
-
}
|
891
|
-
toggleNotification({
|
892
|
-
type: "success",
|
893
|
-
message: formatMessage({
|
894
|
-
id: getTranslation("success.record.delete"),
|
895
|
-
defaultMessage: "Deleted document"
|
896
|
-
})
|
897
|
-
});
|
898
|
-
trackUsage("didDeleteEntry", trackerProperty);
|
899
|
-
return res.data;
|
900
|
-
} catch (err) {
|
901
|
-
toggleNotification({
|
902
|
-
type: "danger",
|
903
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
904
|
-
});
|
905
|
-
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
906
|
-
throw err;
|
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([]);
|
907
972
|
}
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
const
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
});
|
926
|
-
return { error: res.error };
|
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
|
927
990
|
}
|
928
|
-
|
929
|
-
|
930
|
-
title: formatMessage({
|
931
|
-
id: getTranslation("success.records.delete"),
|
932
|
-
defaultMessage: "Successfully deleted."
|
933
|
-
}),
|
934
|
-
message: ""
|
935
|
-
});
|
936
|
-
trackUsage("didBulkDeleteEntries");
|
937
|
-
return res.data;
|
938
|
-
} catch (err) {
|
939
|
-
toggleNotification({
|
940
|
-
type: "danger",
|
941
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
942
|
-
});
|
943
|
-
trackUsage("didNotBulkDeleteEntries");
|
944
|
-
throw err;
|
945
|
-
}
|
991
|
+
};
|
992
|
+
return acc;
|
946
993
|
},
|
947
|
-
|
994
|
+
{}
|
948
995
|
);
|
949
|
-
const
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
model,
|
956
|
-
documentId,
|
957
|
-
params
|
958
|
-
});
|
959
|
-
if ("error" in res) {
|
960
|
-
toggleNotification({
|
961
|
-
type: "danger",
|
962
|
-
message: formatAPIError(res.error)
|
963
|
-
});
|
964
|
-
return { error: res.error };
|
965
|
-
}
|
966
|
-
toggleNotification({
|
967
|
-
type: "success",
|
968
|
-
message: formatMessage({
|
969
|
-
id: "content-manager.success.record.discard",
|
970
|
-
defaultMessage: "Changes discarded"
|
971
|
-
})
|
972
|
-
});
|
973
|
-
return res.data;
|
974
|
-
} catch (err) {
|
975
|
-
toggleNotification({
|
976
|
-
type: "danger",
|
977
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
978
|
-
});
|
979
|
-
throw err;
|
980
|
-
}
|
996
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
997
|
+
(acc, [attribute, metadata]) => {
|
998
|
+
return {
|
999
|
+
...acc,
|
1000
|
+
[attribute]: metadata.edit
|
1001
|
+
};
|
981
1002
|
},
|
982
|
-
|
1003
|
+
{}
|
983
1004
|
);
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
model,
|
992
|
-
documentId,
|
993
|
-
data,
|
994
|
-
params
|
995
|
-
});
|
996
|
-
if ("error" in res) {
|
997
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
998
|
-
return { error: res.error };
|
999
|
-
}
|
1000
|
-
trackUsage("didPublishEntry");
|
1001
|
-
toggleNotification({
|
1002
|
-
type: "success",
|
1003
|
-
message: formatMessage({
|
1004
|
-
id: getTranslation("success.record.publish"),
|
1005
|
-
defaultMessage: "Published document"
|
1006
|
-
})
|
1007
|
-
});
|
1008
|
-
return res.data;
|
1009
|
-
} catch (err) {
|
1010
|
-
toggleNotification({
|
1011
|
-
type: "danger",
|
1012
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1013
|
-
});
|
1014
|
-
throw err;
|
1015
|
-
}
|
1005
|
+
return {
|
1006
|
+
layout: panelledEditAttributes,
|
1007
|
+
components: componentEditAttributes,
|
1008
|
+
metadatas: editMetadatas,
|
1009
|
+
settings: {
|
1010
|
+
...data.contentType.settings,
|
1011
|
+
displayName: schema?.info.displayName
|
1016
1012
|
},
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
return { error: res.error };
|
1031
|
-
}
|
1032
|
-
toggleNotification({
|
1033
|
-
type: "success",
|
1034
|
-
message: formatMessage({
|
1035
|
-
id: getTranslation("success.record.publish"),
|
1036
|
-
defaultMessage: "Published document"
|
1037
|
-
})
|
1038
|
-
});
|
1039
|
-
return res.data;
|
1040
|
-
} catch (err) {
|
1041
|
-
toggleNotification({
|
1042
|
-
type: "danger",
|
1043
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1044
|
-
});
|
1045
|
-
throw err;
|
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;
|
1046
1026
|
}
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
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)
|
1055
1048
|
);
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
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"
|
1243
|
+
};
|
1244
|
+
const useDocumentActions = () => {
|
1245
|
+
const { toggleNotification } = useNotification();
|
1246
|
+
const { formatMessage } = useIntl();
|
1247
|
+
const { trackUsage } = useTracking();
|
1248
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1249
|
+
const navigate = useNavigate();
|
1250
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
1251
|
+
const [deleteDocument] = useDeleteDocumentMutation();
|
1252
|
+
const _delete = React.useCallback(
|
1253
|
+
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
1254
|
+
try {
|
1255
|
+
trackUsage("willDeleteEntry", trackerProperty);
|
1256
|
+
const res = await deleteDocument({
|
1062
1257
|
collectionType,
|
1063
1258
|
model,
|
1064
1259
|
documentId,
|
1065
|
-
data,
|
1066
1260
|
params
|
1067
1261
|
});
|
1068
1262
|
if ("error" in res) {
|
1069
|
-
toggleNotification({
|
1070
|
-
|
1263
|
+
toggleNotification({
|
1264
|
+
type: "danger",
|
1265
|
+
message: formatAPIError(res.error)
|
1266
|
+
});
|
1071
1267
|
return { error: res.error };
|
1072
1268
|
}
|
1073
|
-
trackUsage("didEditEntry", trackerProperty);
|
1074
1269
|
toggleNotification({
|
1075
1270
|
type: "success",
|
1076
1271
|
message: formatMessage({
|
1077
|
-
id: getTranslation("success.record.
|
1078
|
-
defaultMessage: "
|
1272
|
+
id: getTranslation("success.record.delete"),
|
1273
|
+
defaultMessage: "Deleted document"
|
1079
1274
|
})
|
1080
1275
|
});
|
1276
|
+
trackUsage("didDeleteEntry", trackerProperty);
|
1081
1277
|
return res.data;
|
1082
1278
|
} catch (err) {
|
1083
|
-
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1084
1279
|
toggleNotification({
|
1085
1280
|
type: "danger",
|
1086
1281
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1087
1282
|
});
|
1283
|
+
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
1088
1284
|
throw err;
|
1089
1285
|
}
|
1090
1286
|
},
|
1091
|
-
[trackUsage,
|
1287
|
+
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
1092
1288
|
);
|
1093
|
-
const [
|
1094
|
-
const
|
1095
|
-
async ({
|
1289
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1290
|
+
const deleteMany = React.useCallback(
|
1291
|
+
async ({ model, documentIds, params }) => {
|
1096
1292
|
try {
|
1097
|
-
trackUsage("
|
1098
|
-
const res = await
|
1099
|
-
collectionType,
|
1293
|
+
trackUsage("willBulkDeleteEntries");
|
1294
|
+
const res = await deleteManyDocuments({
|
1100
1295
|
model,
|
1101
|
-
|
1102
|
-
params
|
1103
|
-
data: {
|
1104
|
-
discardDraft
|
1105
|
-
}
|
1296
|
+
documentIds,
|
1297
|
+
params
|
1106
1298
|
});
|
1107
1299
|
if ("error" in res) {
|
1108
|
-
toggleNotification({
|
1300
|
+
toggleNotification({
|
1301
|
+
type: "danger",
|
1302
|
+
message: formatAPIError(res.error)
|
1303
|
+
});
|
1109
1304
|
return { error: res.error };
|
1110
1305
|
}
|
1111
|
-
trackUsage("didUnpublishEntry");
|
1112
1306
|
toggleNotification({
|
1113
1307
|
type: "success",
|
1114
|
-
|
1115
|
-
id: getTranslation("success.
|
1116
|
-
defaultMessage: "
|
1117
|
-
})
|
1308
|
+
title: formatMessage({
|
1309
|
+
id: getTranslation("success.records.delete"),
|
1310
|
+
defaultMessage: "Successfully deleted."
|
1311
|
+
}),
|
1312
|
+
message: ""
|
1118
1313
|
});
|
1314
|
+
trackUsage("didBulkDeleteEntries");
|
1119
1315
|
return res.data;
|
1120
1316
|
} catch (err) {
|
1121
1317
|
toggleNotification({
|
1122
1318
|
type: "danger",
|
1123
1319
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1124
1320
|
});
|
1321
|
+
trackUsage("didNotBulkDeleteEntries");
|
1125
1322
|
throw err;
|
1126
1323
|
}
|
1127
1324
|
},
|
1128
|
-
[trackUsage,
|
1325
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1129
1326
|
);
|
1130
|
-
const [
|
1131
|
-
const
|
1132
|
-
async ({ model,
|
1327
|
+
const [discardDocument] = useDiscardDocumentMutation();
|
1328
|
+
const discard = React.useCallback(
|
1329
|
+
async ({ collectionType, model, documentId, params }) => {
|
1133
1330
|
try {
|
1134
|
-
|
1135
|
-
|
1331
|
+
const res = await discardDocument({
|
1332
|
+
collectionType,
|
1136
1333
|
model,
|
1137
|
-
|
1334
|
+
documentId,
|
1138
1335
|
params
|
1139
1336
|
});
|
1140
1337
|
if ("error" in res) {
|
1141
|
-
toggleNotification({
|
1338
|
+
toggleNotification({
|
1339
|
+
type: "danger",
|
1340
|
+
message: formatAPIError(res.error)
|
1341
|
+
});
|
1142
1342
|
return { error: res.error };
|
1143
1343
|
}
|
1144
|
-
trackUsage("didBulkUnpublishEntries");
|
1145
1344
|
toggleNotification({
|
1146
1345
|
type: "success",
|
1147
|
-
|
1148
|
-
id:
|
1149
|
-
defaultMessage: "
|
1150
|
-
})
|
1151
|
-
message: ""
|
1346
|
+
message: formatMessage({
|
1347
|
+
id: "content-manager.success.record.discard",
|
1348
|
+
defaultMessage: "Changes discarded"
|
1349
|
+
})
|
1152
1350
|
});
|
1153
1351
|
return res.data;
|
1154
1352
|
} catch (err) {
|
@@ -1156,32 +1354,33 @@ const useDocumentActions = () => {
|
|
1156
1354
|
type: "danger",
|
1157
1355
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1158
1356
|
});
|
1159
|
-
trackUsage("didNotBulkUnpublishEntries");
|
1160
1357
|
throw err;
|
1161
1358
|
}
|
1162
1359
|
},
|
1163
|
-
[
|
1360
|
+
[discardDocument, formatAPIError, formatMessage, toggleNotification]
|
1164
1361
|
);
|
1165
|
-
const [
|
1166
|
-
const
|
1167
|
-
async ({ model, params }, data
|
1362
|
+
const [publishDocument] = usePublishDocumentMutation();
|
1363
|
+
const publish = React.useCallback(
|
1364
|
+
async ({ collectionType, model, documentId, params }, data) => {
|
1168
1365
|
try {
|
1169
|
-
|
1366
|
+
trackUsage("willPublishEntry");
|
1367
|
+
const res = await publishDocument({
|
1368
|
+
collectionType,
|
1170
1369
|
model,
|
1370
|
+
documentId,
|
1171
1371
|
data,
|
1172
1372
|
params
|
1173
1373
|
});
|
1174
1374
|
if ("error" in res) {
|
1175
1375
|
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1176
|
-
trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
|
1177
1376
|
return { error: res.error };
|
1178
1377
|
}
|
1179
|
-
trackUsage("
|
1378
|
+
trackUsage("didPublishEntry");
|
1180
1379
|
toggleNotification({
|
1181
1380
|
type: "success",
|
1182
1381
|
message: formatMessage({
|
1183
|
-
id: getTranslation("success.record.
|
1184
|
-
defaultMessage: "
|
1382
|
+
id: getTranslation("success.record.publish"),
|
1383
|
+
defaultMessage: "Published document"
|
1185
1384
|
})
|
1186
1385
|
});
|
1187
1386
|
return res.data;
|
@@ -1190,28 +1389,29 @@ const useDocumentActions = () => {
|
|
1190
1389
|
type: "danger",
|
1191
1390
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1192
1391
|
});
|
1193
|
-
trackUsage("didNotCreateEntry", { error: err, ...trackerProperty });
|
1194
1392
|
throw err;
|
1195
1393
|
}
|
1196
1394
|
},
|
1197
|
-
[
|
1395
|
+
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1198
1396
|
);
|
1199
|
-
const [
|
1200
|
-
const
|
1201
|
-
async ({ model,
|
1397
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1398
|
+
const publishMany = React.useCallback(
|
1399
|
+
async ({ model, documentIds, params }) => {
|
1202
1400
|
try {
|
1203
|
-
const res = await
|
1401
|
+
const res = await publishManyDocuments({
|
1204
1402
|
model,
|
1205
|
-
|
1403
|
+
documentIds,
|
1404
|
+
params
|
1206
1405
|
});
|
1207
1406
|
if ("error" in res) {
|
1407
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1208
1408
|
return { error: res.error };
|
1209
1409
|
}
|
1210
1410
|
toggleNotification({
|
1211
1411
|
type: "success",
|
1212
1412
|
message: formatMessage({
|
1213
|
-
id: getTranslation("success.record.
|
1214
|
-
defaultMessage: "
|
1413
|
+
id: getTranslation("success.record.publish"),
|
1414
|
+
defaultMessage: "Published document"
|
1215
1415
|
})
|
1216
1416
|
});
|
1217
1417
|
return res.data;
|
@@ -1223,1224 +1423,1070 @@ const useDocumentActions = () => {
|
|
1223
1423
|
throw err;
|
1224
1424
|
}
|
1225
1425
|
},
|
1226
|
-
[
|
1426
|
+
[
|
1427
|
+
// trackUsage,
|
1428
|
+
publishManyDocuments,
|
1429
|
+
toggleNotification,
|
1430
|
+
formatMessage,
|
1431
|
+
formatAPIError
|
1432
|
+
]
|
1227
1433
|
);
|
1228
|
-
const [
|
1229
|
-
const
|
1230
|
-
async ({ model, documentId, params },
|
1434
|
+
const [updateDocument] = useUpdateDocumentMutation();
|
1435
|
+
const update = React.useCallback(
|
1436
|
+
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
1231
1437
|
try {
|
1232
|
-
|
1233
|
-
const res = await
|
1438
|
+
trackUsage("willEditEntry", trackerProperty);
|
1439
|
+
const res = await updateDocument({
|
1440
|
+
collectionType,
|
1234
1441
|
model,
|
1235
|
-
|
1236
|
-
data
|
1442
|
+
documentId,
|
1443
|
+
data,
|
1237
1444
|
params
|
1238
1445
|
});
|
1239
1446
|
if ("error" in res) {
|
1240
1447
|
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1241
|
-
trackUsage("
|
1448
|
+
trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
|
1242
1449
|
return { error: res.error };
|
1243
1450
|
}
|
1244
|
-
trackUsage("
|
1451
|
+
trackUsage("didEditEntry", trackerProperty);
|
1245
1452
|
toggleNotification({
|
1246
1453
|
type: "success",
|
1247
1454
|
message: formatMessage({
|
1248
|
-
id: getTranslation("success.record.
|
1249
|
-
defaultMessage: "
|
1455
|
+
id: getTranslation("success.record.save"),
|
1456
|
+
defaultMessage: "Saved document"
|
1250
1457
|
})
|
1251
1458
|
});
|
1252
1459
|
return res.data;
|
1253
1460
|
} catch (err) {
|
1461
|
+
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1254
1462
|
toggleNotification({
|
1255
1463
|
type: "danger",
|
1256
1464
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1257
1465
|
});
|
1258
|
-
trackUsage("didNotCreateEntry", { error: err, ...trackerProperty });
|
1259
1466
|
throw err;
|
1260
1467
|
}
|
1261
1468
|
},
|
1262
|
-
[
|
1263
|
-
);
|
1264
|
-
const [getDoc] = useLazyGetDocumentQuery();
|
1265
|
-
const getDocument = React.useCallback(
|
1266
|
-
async (args) => {
|
1267
|
-
const { data } = await getDoc(args);
|
1268
|
-
return data;
|
1269
|
-
},
|
1270
|
-
[getDoc]
|
1469
|
+
[trackUsage, updateDocument, toggleNotification, formatMessage, formatAPIError]
|
1271
1470
|
);
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
discard,
|
1279
|
-
getDocument,
|
1280
|
-
publish,
|
1281
|
-
publishMany,
|
1282
|
-
unpublish,
|
1283
|
-
unpublishMany,
|
1284
|
-
update
|
1285
|
-
};
|
1286
|
-
};
|
1287
|
-
const ProtectedHistoryPage = lazy(
|
1288
|
-
() => import("./History-DR2txJLE.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1289
|
-
);
|
1290
|
-
const routes$1 = [
|
1291
|
-
{
|
1292
|
-
path: ":collectionType/:slug/:id/history",
|
1293
|
-
Component: ProtectedHistoryPage
|
1294
|
-
},
|
1295
|
-
{
|
1296
|
-
path: ":collectionType/:slug/history",
|
1297
|
-
Component: ProtectedHistoryPage
|
1298
|
-
}
|
1299
|
-
];
|
1300
|
-
const ProtectedEditViewPage = lazy(
|
1301
|
-
() => import("./EditViewPage-B7VgwJaG.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1302
|
-
);
|
1303
|
-
const ProtectedListViewPage = lazy(
|
1304
|
-
() => import("./ListViewPage-B_GaWgRH.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1305
|
-
);
|
1306
|
-
const ProtectedListConfiguration = lazy(
|
1307
|
-
() => import("./ListConfigurationPage-voFVtXu6.mjs").then((mod) => ({
|
1308
|
-
default: mod.ProtectedListConfiguration
|
1309
|
-
}))
|
1310
|
-
);
|
1311
|
-
const ProtectedEditConfigurationPage = lazy(
|
1312
|
-
() => import("./EditConfigurationPage-D7PrLO8j.mjs").then((mod) => ({
|
1313
|
-
default: mod.ProtectedEditConfigurationPage
|
1314
|
-
}))
|
1315
|
-
);
|
1316
|
-
const ProtectedComponentConfigurationPage = lazy(
|
1317
|
-
() => import("./ComponentConfigurationPage-B3yDbeU1.mjs").then((mod) => ({
|
1318
|
-
default: mod.ProtectedComponentConfigurationPage
|
1319
|
-
}))
|
1320
|
-
);
|
1321
|
-
const NoPermissions = lazy(
|
1322
|
-
() => import("./NoPermissionsPage-B5baIHal.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1323
|
-
);
|
1324
|
-
const NoContentType = lazy(
|
1325
|
-
() => import("./NoContentTypePage-CYiGpsbj.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1326
|
-
);
|
1327
|
-
const CollectionTypePages = () => {
|
1328
|
-
const { collectionType } = useParams();
|
1329
|
-
if (collectionType !== COLLECTION_TYPES && collectionType !== SINGLE_TYPES) {
|
1330
|
-
return /* @__PURE__ */ jsx(Navigate, { to: "/404" });
|
1331
|
-
}
|
1332
|
-
return collectionType === COLLECTION_TYPES ? /* @__PURE__ */ jsx(ProtectedListViewPage, {}) : /* @__PURE__ */ jsx(ProtectedEditViewPage, {});
|
1333
|
-
};
|
1334
|
-
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1335
|
-
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1336
|
-
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1337
|
-
const LIST_PATH = `/content-manager/${LIST_RELATIVE_PATH}`;
|
1338
|
-
const routes = [
|
1339
|
-
{
|
1340
|
-
path: LIST_RELATIVE_PATH,
|
1341
|
-
element: /* @__PURE__ */ jsx(CollectionTypePages, {})
|
1342
|
-
},
|
1343
|
-
{
|
1344
|
-
path: ":collectionType/:slug/:id",
|
1345
|
-
Component: ProtectedEditViewPage
|
1346
|
-
},
|
1347
|
-
{
|
1348
|
-
path: CLONE_RELATIVE_PATH,
|
1349
|
-
Component: ProtectedEditViewPage
|
1350
|
-
},
|
1351
|
-
{
|
1352
|
-
path: ":collectionType/:slug/configurations/list",
|
1353
|
-
Component: ProtectedListConfiguration
|
1354
|
-
},
|
1355
|
-
{
|
1356
|
-
path: "components/:slug/configurations/edit",
|
1357
|
-
Component: ProtectedComponentConfigurationPage
|
1358
|
-
},
|
1359
|
-
{
|
1360
|
-
path: ":collectionType/:slug/configurations/edit",
|
1361
|
-
Component: ProtectedEditConfigurationPage
|
1362
|
-
},
|
1363
|
-
{
|
1364
|
-
path: "403",
|
1365
|
-
Component: NoPermissions
|
1366
|
-
},
|
1367
|
-
{
|
1368
|
-
path: "no-content-types",
|
1369
|
-
Component: NoContentType
|
1370
|
-
},
|
1371
|
-
...routes$1
|
1372
|
-
];
|
1373
|
-
const DocumentActions = ({ actions: actions2 }) => {
|
1374
|
-
const { formatMessage } = useIntl();
|
1375
|
-
const [primaryAction, secondaryAction, ...restActions] = actions2.filter((action) => {
|
1376
|
-
if (action.position === void 0) {
|
1377
|
-
return true;
|
1378
|
-
}
|
1379
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
1380
|
-
return positions.includes("panel");
|
1381
|
-
});
|
1382
|
-
if (!primaryAction) {
|
1383
|
-
return null;
|
1384
|
-
}
|
1385
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
|
1386
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
1387
|
-
/* @__PURE__ */ jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
|
1388
|
-
restActions.length > 0 ? /* @__PURE__ */ jsx(
|
1389
|
-
DocumentActionsMenu,
|
1390
|
-
{
|
1391
|
-
actions: restActions,
|
1392
|
-
label: formatMessage({
|
1393
|
-
id: "content-manager.containers.edit.panels.default.more-actions",
|
1394
|
-
defaultMessage: "More document actions"
|
1395
|
-
})
|
1396
|
-
}
|
1397
|
-
) : null
|
1398
|
-
] }),
|
1399
|
-
secondaryAction ? /* @__PURE__ */ jsx(
|
1400
|
-
DocumentActionButton,
|
1401
|
-
{
|
1402
|
-
...secondaryAction,
|
1403
|
-
variant: secondaryAction.variant || "secondary"
|
1404
|
-
}
|
1405
|
-
) : null
|
1406
|
-
] });
|
1407
|
-
};
|
1408
|
-
const DocumentActionButton = (action) => {
|
1409
|
-
const [dialogId, setDialogId] = React.useState(null);
|
1410
|
-
const { toggleNotification } = useNotification();
|
1411
|
-
const handleClick = (action2) => async (e) => {
|
1412
|
-
const { onClick = () => false, dialog, id } = action2;
|
1413
|
-
const muteDialog = await onClick(e);
|
1414
|
-
if (dialog && !muteDialog) {
|
1415
|
-
switch (dialog.type) {
|
1416
|
-
case "notification":
|
1417
|
-
toggleNotification({
|
1418
|
-
title: dialog.title,
|
1419
|
-
message: dialog.content,
|
1420
|
-
type: dialog.status,
|
1421
|
-
timeout: dialog.timeout,
|
1422
|
-
onClose: dialog.onClose
|
1423
|
-
});
|
1424
|
-
break;
|
1425
|
-
case "dialog":
|
1426
|
-
case "modal":
|
1427
|
-
e.preventDefault();
|
1428
|
-
setDialogId(id);
|
1429
|
-
}
|
1430
|
-
}
|
1431
|
-
};
|
1432
|
-
const handleClose = () => {
|
1433
|
-
setDialogId(null);
|
1434
|
-
};
|
1435
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
1436
|
-
/* @__PURE__ */ jsx(
|
1437
|
-
Button,
|
1438
|
-
{
|
1439
|
-
flex: "auto",
|
1440
|
-
startIcon: action.icon,
|
1441
|
-
disabled: action.disabled,
|
1442
|
-
onClick: handleClick(action),
|
1443
|
-
justifyContent: "center",
|
1444
|
-
variant: action.variant || "default",
|
1445
|
-
paddingTop: "7px",
|
1446
|
-
paddingBottom: "7px",
|
1447
|
-
children: action.label
|
1448
|
-
}
|
1449
|
-
),
|
1450
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
|
1451
|
-
DocumentActionConfirmDialog,
|
1452
|
-
{
|
1453
|
-
...action.dialog,
|
1454
|
-
variant: action.dialog?.variant ?? action.variant,
|
1455
|
-
isOpen: dialogId === action.id,
|
1456
|
-
onClose: handleClose
|
1457
|
-
}
|
1458
|
-
) : null,
|
1459
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
|
1460
|
-
DocumentActionModal,
|
1461
|
-
{
|
1462
|
-
...action.dialog,
|
1463
|
-
onModalClose: handleClose,
|
1464
|
-
isOpen: dialogId === action.id
|
1465
|
-
}
|
1466
|
-
) : null
|
1467
|
-
] });
|
1468
|
-
};
|
1469
|
-
const DocumentActionsMenu = ({
|
1470
|
-
actions: actions2,
|
1471
|
-
children,
|
1472
|
-
label,
|
1473
|
-
variant = "tertiary"
|
1474
|
-
}) => {
|
1475
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
1476
|
-
const [dialogId, setDialogId] = React.useState(null);
|
1477
|
-
const { formatMessage } = useIntl();
|
1478
|
-
const { toggleNotification } = useNotification();
|
1479
|
-
const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
|
1480
|
-
const handleClick = (action) => async (e) => {
|
1481
|
-
const { onClick = () => false, dialog, id } = action;
|
1482
|
-
const muteDialog = await onClick(e);
|
1483
|
-
if (dialog && !muteDialog) {
|
1484
|
-
switch (dialog.type) {
|
1485
|
-
case "notification":
|
1486
|
-
toggleNotification({
|
1487
|
-
title: dialog.title,
|
1488
|
-
message: dialog.content,
|
1489
|
-
type: dialog.status,
|
1490
|
-
timeout: dialog.timeout,
|
1491
|
-
onClose: dialog.onClose
|
1492
|
-
});
|
1493
|
-
break;
|
1494
|
-
case "dialog":
|
1495
|
-
case "modal":
|
1496
|
-
setDialogId(id);
|
1497
|
-
}
|
1498
|
-
}
|
1499
|
-
};
|
1500
|
-
const handleClose = () => {
|
1501
|
-
setDialogId(null);
|
1502
|
-
setIsOpen(false);
|
1503
|
-
};
|
1504
|
-
return /* @__PURE__ */ jsxs(Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1505
|
-
/* @__PURE__ */ jsxs(
|
1506
|
-
StyledMoreButton,
|
1507
|
-
{
|
1508
|
-
disabled: isDisabled,
|
1509
|
-
size: "S",
|
1510
|
-
endIcon: null,
|
1511
|
-
paddingTop: "4px",
|
1512
|
-
paddingLeft: "7px",
|
1513
|
-
paddingRight: "7px",
|
1514
|
-
variant,
|
1515
|
-
children: [
|
1516
|
-
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
1517
|
-
/* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1518
|
-
id: "content-manager.containers.edit.panels.default.more-actions",
|
1519
|
-
defaultMessage: "More document actions"
|
1520
|
-
}) })
|
1521
|
-
]
|
1522
|
-
}
|
1523
|
-
),
|
1524
|
-
/* @__PURE__ */ jsxs(Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1525
|
-
actions2.map((action) => {
|
1526
|
-
return /* @__PURE__ */ jsx(
|
1527
|
-
Menu.Item,
|
1528
|
-
{
|
1529
|
-
disabled: action.disabled,
|
1530
|
-
onSelect: handleClick(action),
|
1531
|
-
display: "block",
|
1532
|
-
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
1533
|
-
/* @__PURE__ */ jsxs(
|
1534
|
-
Flex,
|
1535
|
-
{
|
1536
|
-
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1537
|
-
gap: 2,
|
1538
|
-
tag: "span",
|
1539
|
-
children: [
|
1540
|
-
/* @__PURE__ */ jsx(
|
1541
|
-
Flex,
|
1542
|
-
{
|
1543
|
-
tag: "span",
|
1544
|
-
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1545
|
-
children: action.icon
|
1546
|
-
}
|
1547
|
-
),
|
1548
|
-
action.label
|
1549
|
-
]
|
1550
|
-
}
|
1551
|
-
),
|
1552
|
-
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
1553
|
-
Flex,
|
1554
|
-
{
|
1555
|
-
alignItems: "center",
|
1556
|
-
background: "alternative100",
|
1557
|
-
borderStyle: "solid",
|
1558
|
-
borderColor: "alternative200",
|
1559
|
-
borderWidth: "1px",
|
1560
|
-
height: 5,
|
1561
|
-
paddingLeft: 2,
|
1562
|
-
paddingRight: 2,
|
1563
|
-
hasRadius: true,
|
1564
|
-
color: "alternative600",
|
1565
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1566
|
-
}
|
1567
|
-
)
|
1568
|
-
] })
|
1569
|
-
},
|
1570
|
-
action.id
|
1571
|
-
);
|
1572
|
-
}),
|
1573
|
-
children
|
1574
|
-
] }),
|
1575
|
-
actions2.map((action) => {
|
1576
|
-
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
1577
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
|
1578
|
-
DocumentActionConfirmDialog,
|
1579
|
-
{
|
1580
|
-
...action.dialog,
|
1581
|
-
variant: action.variant,
|
1582
|
-
isOpen: dialogId === action.id,
|
1583
|
-
onClose: handleClose
|
1584
|
-
}
|
1585
|
-
) : null,
|
1586
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
|
1587
|
-
DocumentActionModal,
|
1588
|
-
{
|
1589
|
-
...action.dialog,
|
1590
|
-
onModalClose: handleClose,
|
1591
|
-
isOpen: dialogId === action.id
|
1592
|
-
}
|
1593
|
-
) : null
|
1594
|
-
] }, action.id);
|
1595
|
-
})
|
1596
|
-
] });
|
1597
|
-
};
|
1598
|
-
const convertActionVariantToColor = (variant = "secondary") => {
|
1599
|
-
switch (variant) {
|
1600
|
-
case "danger":
|
1601
|
-
return "danger600";
|
1602
|
-
case "secondary":
|
1603
|
-
return void 0;
|
1604
|
-
case "success":
|
1605
|
-
return "success600";
|
1606
|
-
default:
|
1607
|
-
return "primary600";
|
1608
|
-
}
|
1609
|
-
};
|
1610
|
-
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1611
|
-
switch (variant) {
|
1612
|
-
case "danger":
|
1613
|
-
return "danger600";
|
1614
|
-
case "secondary":
|
1615
|
-
return "neutral500";
|
1616
|
-
case "success":
|
1617
|
-
return "success600";
|
1618
|
-
default:
|
1619
|
-
return "primary600";
|
1620
|
-
}
|
1621
|
-
};
|
1622
|
-
const StyledMoreButton = styled(Menu.Trigger)`
|
1623
|
-
& > span {
|
1624
|
-
display: flex;
|
1625
|
-
}
|
1626
|
-
`;
|
1627
|
-
const DocumentActionConfirmDialog = ({
|
1628
|
-
onClose,
|
1629
|
-
onCancel,
|
1630
|
-
onConfirm,
|
1631
|
-
title,
|
1632
|
-
content,
|
1633
|
-
isOpen,
|
1634
|
-
variant = "secondary"
|
1635
|
-
}) => {
|
1636
|
-
const { formatMessage } = useIntl();
|
1637
|
-
const handleClose = async () => {
|
1638
|
-
if (onCancel) {
|
1639
|
-
await onCancel();
|
1640
|
-
}
|
1641
|
-
onClose();
|
1642
|
-
};
|
1643
|
-
const handleConfirm = async () => {
|
1644
|
-
if (onConfirm) {
|
1645
|
-
await onConfirm();
|
1646
|
-
}
|
1647
|
-
onClose();
|
1648
|
-
};
|
1649
|
-
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
1650
|
-
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1651
|
-
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1652
|
-
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1653
|
-
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
1654
|
-
id: "app.components.Button.cancel",
|
1655
|
-
defaultMessage: "Cancel"
|
1656
|
-
}) }) }),
|
1657
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
1658
|
-
id: "app.components.Button.confirm",
|
1659
|
-
defaultMessage: "Confirm"
|
1660
|
-
}) })
|
1661
|
-
] })
|
1662
|
-
] }) });
|
1663
|
-
};
|
1664
|
-
const DocumentActionModal = ({
|
1665
|
-
isOpen,
|
1666
|
-
title,
|
1667
|
-
onClose,
|
1668
|
-
footer: Footer,
|
1669
|
-
content: Content,
|
1670
|
-
onModalClose
|
1671
|
-
}) => {
|
1672
|
-
const handleClose = () => {
|
1673
|
-
if (onClose) {
|
1674
|
-
onClose();
|
1675
|
-
}
|
1676
|
-
onModalClose();
|
1677
|
-
};
|
1678
|
-
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
1679
|
-
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
1680
|
-
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
|
1681
|
-
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1682
|
-
] }) });
|
1683
|
-
};
|
1684
|
-
const PublishAction$1 = ({
|
1685
|
-
activeTab,
|
1686
|
-
documentId,
|
1687
|
-
model,
|
1688
|
-
collectionType,
|
1689
|
-
meta,
|
1690
|
-
document
|
1691
|
-
}) => {
|
1692
|
-
const { schema } = useDoc();
|
1693
|
-
const navigate = useNavigate();
|
1694
|
-
const { toggleNotification } = useNotification();
|
1695
|
-
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
1696
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
1697
|
-
const { formatMessage } = useIntl();
|
1698
|
-
const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
|
1699
|
-
"PublishAction",
|
1700
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1701
|
-
);
|
1702
|
-
const { publish } = useDocumentActions();
|
1703
|
-
const [
|
1704
|
-
countDraftRelations,
|
1705
|
-
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
1706
|
-
] = useLazyGetDraftRelationCountQuery();
|
1707
|
-
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
1708
|
-
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1709
|
-
const [{ query, rawQuery }] = useQueryParams();
|
1710
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1711
|
-
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
1712
|
-
const setSubmitting = useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
1713
|
-
const isSubmitting = useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
1714
|
-
const validate = useForm("PublishAction", (state) => state.validate);
|
1715
|
-
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1716
|
-
const formValues = useForm("PublishAction", ({ values }) => values);
|
1717
|
-
React.useEffect(() => {
|
1718
|
-
if (isErrorDraftRelations) {
|
1719
|
-
toggleNotification({
|
1720
|
-
type: "danger",
|
1721
|
-
message: formatMessage({
|
1722
|
-
id: getTranslation("error.records.fetch-draft-relatons"),
|
1723
|
-
defaultMessage: "An error occurred while fetching draft relations on this document."
|
1724
|
-
})
|
1725
|
-
});
|
1726
|
-
}
|
1727
|
-
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
1728
|
-
React.useEffect(() => {
|
1729
|
-
const localDraftRelations = /* @__PURE__ */ new Set();
|
1730
|
-
const extractDraftRelations = (data) => {
|
1731
|
-
const relations = data.connect || [];
|
1732
|
-
relations.forEach((relation) => {
|
1733
|
-
if (relation.status === "draft") {
|
1734
|
-
localDraftRelations.add(relation.id);
|
1735
|
-
}
|
1736
|
-
});
|
1737
|
-
};
|
1738
|
-
const traverseAndExtract = (data) => {
|
1739
|
-
Object.entries(data).forEach(([key, value]) => {
|
1740
|
-
if (key === "connect" && Array.isArray(value)) {
|
1741
|
-
extractDraftRelations({ connect: value });
|
1742
|
-
} else if (typeof value === "object" && value !== null) {
|
1743
|
-
traverseAndExtract(value);
|
1744
|
-
}
|
1745
|
-
});
|
1746
|
-
};
|
1747
|
-
if (!documentId || modified) {
|
1748
|
-
traverseAndExtract(formValues);
|
1749
|
-
setLocalCountOfDraftRelations(localDraftRelations.size);
|
1750
|
-
}
|
1751
|
-
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1752
|
-
React.useEffect(() => {
|
1753
|
-
if (documentId) {
|
1754
|
-
const fetchDraftRelationsCount = async () => {
|
1755
|
-
const { data, error } = await countDraftRelations({
|
1471
|
+
const [unpublishDocument] = useUnpublishDocumentMutation();
|
1472
|
+
const unpublish = React.useCallback(
|
1473
|
+
async ({ collectionType, model, documentId, params }, discardDraft = false) => {
|
1474
|
+
try {
|
1475
|
+
trackUsage("willUnpublishEntry");
|
1476
|
+
const res = await unpublishDocument({
|
1756
1477
|
collectionType,
|
1757
1478
|
model,
|
1758
|
-
documentId,
|
1479
|
+
documentId,
|
1480
|
+
params,
|
1481
|
+
data: {
|
1482
|
+
discardDraft
|
1483
|
+
}
|
1484
|
+
});
|
1485
|
+
if ("error" in res) {
|
1486
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1487
|
+
return { error: res.error };
|
1488
|
+
}
|
1489
|
+
trackUsage("didUnpublishEntry");
|
1490
|
+
toggleNotification({
|
1491
|
+
type: "success",
|
1492
|
+
message: formatMessage({
|
1493
|
+
id: getTranslation("success.record.unpublish"),
|
1494
|
+
defaultMessage: "Unpublished document"
|
1495
|
+
})
|
1496
|
+
});
|
1497
|
+
return res.data;
|
1498
|
+
} catch (err) {
|
1499
|
+
toggleNotification({
|
1500
|
+
type: "danger",
|
1501
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1502
|
+
});
|
1503
|
+
throw err;
|
1504
|
+
}
|
1505
|
+
},
|
1506
|
+
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1507
|
+
);
|
1508
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1509
|
+
const unpublishMany = React.useCallback(
|
1510
|
+
async ({ model, documentIds, params }) => {
|
1511
|
+
try {
|
1512
|
+
trackUsage("willBulkUnpublishEntries");
|
1513
|
+
const res = await unpublishManyDocuments({
|
1514
|
+
model,
|
1515
|
+
documentIds,
|
1759
1516
|
params
|
1760
1517
|
});
|
1761
|
-
if (error) {
|
1762
|
-
|
1518
|
+
if ("error" in res) {
|
1519
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1520
|
+
return { error: res.error };
|
1763
1521
|
}
|
1764
|
-
|
1765
|
-
|
1522
|
+
trackUsage("didBulkUnpublishEntries");
|
1523
|
+
toggleNotification({
|
1524
|
+
type: "success",
|
1525
|
+
title: formatMessage({
|
1526
|
+
id: getTranslation("success.records.unpublish"),
|
1527
|
+
defaultMessage: "Successfully unpublished."
|
1528
|
+
}),
|
1529
|
+
message: ""
|
1530
|
+
});
|
1531
|
+
return res.data;
|
1532
|
+
} catch (err) {
|
1533
|
+
toggleNotification({
|
1534
|
+
type: "danger",
|
1535
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1536
|
+
});
|
1537
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1538
|
+
throw err;
|
1539
|
+
}
|
1540
|
+
},
|
1541
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1542
|
+
);
|
1543
|
+
const [createDocument] = useCreateDocumentMutation();
|
1544
|
+
const create = React.useCallback(
|
1545
|
+
async ({ model, params }, data, trackerProperty) => {
|
1546
|
+
try {
|
1547
|
+
const res = await createDocument({
|
1548
|
+
model,
|
1549
|
+
data,
|
1550
|
+
params
|
1551
|
+
});
|
1552
|
+
if ("error" in res) {
|
1553
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1554
|
+
trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
|
1555
|
+
return { error: res.error };
|
1766
1556
|
}
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
const { errors } = await validate();
|
1779
|
-
if (errors) {
|
1557
|
+
trackUsage("didCreateEntry", trackerProperty);
|
1558
|
+
toggleNotification({
|
1559
|
+
type: "success",
|
1560
|
+
message: formatMessage({
|
1561
|
+
id: getTranslation("success.record.save"),
|
1562
|
+
defaultMessage: "Saved document"
|
1563
|
+
})
|
1564
|
+
});
|
1565
|
+
setCurrentStep("contentManager.success");
|
1566
|
+
return res.data;
|
1567
|
+
} catch (err) {
|
1780
1568
|
toggleNotification({
|
1781
1569
|
type: "danger",
|
1570
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1571
|
+
});
|
1572
|
+
trackUsage("didNotCreateEntry", { error: err, ...trackerProperty });
|
1573
|
+
throw err;
|
1574
|
+
}
|
1575
|
+
},
|
1576
|
+
[createDocument, formatAPIError, formatMessage, toggleNotification, trackUsage]
|
1577
|
+
);
|
1578
|
+
const [autoCloneDocument] = useAutoCloneDocumentMutation();
|
1579
|
+
const autoClone = React.useCallback(
|
1580
|
+
async ({ model, sourceId }) => {
|
1581
|
+
try {
|
1582
|
+
const res = await autoCloneDocument({
|
1583
|
+
model,
|
1584
|
+
sourceId
|
1585
|
+
});
|
1586
|
+
if ("error" in res) {
|
1587
|
+
return { error: res.error };
|
1588
|
+
}
|
1589
|
+
toggleNotification({
|
1590
|
+
type: "success",
|
1782
1591
|
message: formatMessage({
|
1783
|
-
id: "
|
1784
|
-
defaultMessage: "
|
1592
|
+
id: getTranslation("success.record.clone"),
|
1593
|
+
defaultMessage: "Cloned document"
|
1785
1594
|
})
|
1786
1595
|
});
|
1787
|
-
return;
|
1596
|
+
return res.data;
|
1597
|
+
} catch (err) {
|
1598
|
+
toggleNotification({
|
1599
|
+
type: "danger",
|
1600
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1601
|
+
});
|
1602
|
+
throw err;
|
1788
1603
|
}
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1604
|
+
},
|
1605
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1606
|
+
);
|
1607
|
+
const [cloneDocument] = useCloneDocumentMutation();
|
1608
|
+
const clone = React.useCallback(
|
1609
|
+
async ({ model, documentId, params }, body, trackerProperty) => {
|
1610
|
+
try {
|
1611
|
+
const { id: _id, ...restBody } = body;
|
1612
|
+
const res = await cloneDocument({
|
1792
1613
|
model,
|
1793
|
-
documentId,
|
1614
|
+
sourceId: documentId,
|
1615
|
+
data: restBody,
|
1794
1616
|
params
|
1795
|
-
},
|
1796
|
-
formValues
|
1797
|
-
);
|
1798
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1799
|
-
navigate({
|
1800
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1801
|
-
search: rawQuery
|
1802
1617
|
});
|
1803
|
-
|
1804
|
-
|
1618
|
+
if ("error" in res) {
|
1619
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1620
|
+
trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
|
1621
|
+
return { error: res.error };
|
1622
|
+
}
|
1623
|
+
trackUsage("didCreateEntry", trackerProperty);
|
1624
|
+
toggleNotification({
|
1625
|
+
type: "success",
|
1626
|
+
message: formatMessage({
|
1627
|
+
id: getTranslation("success.record.clone"),
|
1628
|
+
defaultMessage: "Cloned document"
|
1629
|
+
})
|
1630
|
+
});
|
1631
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1632
|
+
return res.data;
|
1633
|
+
} catch (err) {
|
1634
|
+
toggleNotification({
|
1635
|
+
type: "danger",
|
1636
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1637
|
+
});
|
1638
|
+
trackUsage("didNotCreateEntry", { error: err, ...trackerProperty });
|
1639
|
+
throw err;
|
1805
1640
|
}
|
1806
|
-
}
|
1807
|
-
|
1641
|
+
},
|
1642
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1643
|
+
);
|
1644
|
+
const [getDoc] = useLazyGetDocumentQuery();
|
1645
|
+
const getDocument = React.useCallback(
|
1646
|
+
async (args) => {
|
1647
|
+
const { data } = await getDoc(args);
|
1648
|
+
return data;
|
1649
|
+
},
|
1650
|
+
[getDoc]
|
1651
|
+
);
|
1652
|
+
return {
|
1653
|
+
autoClone,
|
1654
|
+
clone,
|
1655
|
+
create,
|
1656
|
+
delete: _delete,
|
1657
|
+
deleteMany,
|
1658
|
+
discard,
|
1659
|
+
getDocument,
|
1660
|
+
publish,
|
1661
|
+
publishMany,
|
1662
|
+
unpublish,
|
1663
|
+
unpublishMany,
|
1664
|
+
update
|
1665
|
+
};
|
1666
|
+
};
|
1667
|
+
const ProtectedHistoryPage = lazy(
|
1668
|
+
() => import("./History-DRwA3oMM.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1669
|
+
);
|
1670
|
+
const routes$1 = [
|
1671
|
+
{
|
1672
|
+
path: ":collectionType/:slug/:id/history",
|
1673
|
+
Component: ProtectedHistoryPage
|
1674
|
+
},
|
1675
|
+
{
|
1676
|
+
path: ":collectionType/:slug/history",
|
1677
|
+
Component: ProtectedHistoryPage
|
1678
|
+
}
|
1679
|
+
];
|
1680
|
+
const ProtectedEditViewPage = lazy(
|
1681
|
+
() => import("./EditViewPage-B82x_x1b.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1682
|
+
);
|
1683
|
+
const ProtectedListViewPage = lazy(
|
1684
|
+
() => import("./ListViewPage-CELx2ysp.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1685
|
+
);
|
1686
|
+
const ProtectedListConfiguration = lazy(
|
1687
|
+
() => import("./ListConfigurationPage-BxfQJzPk.mjs").then((mod) => ({
|
1688
|
+
default: mod.ProtectedListConfiguration
|
1689
|
+
}))
|
1690
|
+
);
|
1691
|
+
const ProtectedEditConfigurationPage = lazy(
|
1692
|
+
() => import("./EditConfigurationPage-DdPNAbl3.mjs").then((mod) => ({
|
1693
|
+
default: mod.ProtectedEditConfigurationPage
|
1694
|
+
}))
|
1695
|
+
);
|
1696
|
+
const ProtectedComponentConfigurationPage = lazy(
|
1697
|
+
() => import("./ComponentConfigurationPage-DfFSZQxe.mjs").then((mod) => ({
|
1698
|
+
default: mod.ProtectedComponentConfigurationPage
|
1699
|
+
}))
|
1700
|
+
);
|
1701
|
+
const NoPermissions = lazy(
|
1702
|
+
() => import("./NoPermissionsPage-DWleVYK7.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1703
|
+
);
|
1704
|
+
const NoContentType = lazy(
|
1705
|
+
() => import("./NoContentTypePage-DtJ9jcfk.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1706
|
+
);
|
1707
|
+
const CollectionTypePages = () => {
|
1708
|
+
const { collectionType } = useParams();
|
1709
|
+
if (collectionType !== COLLECTION_TYPES && collectionType !== SINGLE_TYPES) {
|
1710
|
+
return /* @__PURE__ */ jsx(Navigate, { to: "/404" });
|
1711
|
+
}
|
1712
|
+
return collectionType === COLLECTION_TYPES ? /* @__PURE__ */ jsx(ProtectedListViewPage, {}) : /* @__PURE__ */ jsx(ProtectedEditViewPage, {});
|
1713
|
+
};
|
1714
|
+
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1715
|
+
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1716
|
+
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1717
|
+
const LIST_PATH = `/content-manager/${LIST_RELATIVE_PATH}`;
|
1718
|
+
const routes = [
|
1719
|
+
{
|
1720
|
+
path: LIST_RELATIVE_PATH,
|
1721
|
+
element: /* @__PURE__ */ jsx(CollectionTypePages, {})
|
1722
|
+
},
|
1723
|
+
{
|
1724
|
+
path: ":collectionType/:slug/:id",
|
1725
|
+
Component: ProtectedEditViewPage
|
1726
|
+
},
|
1727
|
+
{
|
1728
|
+
path: CLONE_RELATIVE_PATH,
|
1729
|
+
Component: ProtectedEditViewPage
|
1730
|
+
},
|
1731
|
+
{
|
1732
|
+
path: ":collectionType/:slug/configurations/list",
|
1733
|
+
Component: ProtectedListConfiguration
|
1734
|
+
},
|
1735
|
+
{
|
1736
|
+
path: "components/:slug/configurations/edit",
|
1737
|
+
Component: ProtectedComponentConfigurationPage
|
1738
|
+
},
|
1739
|
+
{
|
1740
|
+
path: ":collectionType/:slug/configurations/edit",
|
1741
|
+
Component: ProtectedEditConfigurationPage
|
1742
|
+
},
|
1743
|
+
{
|
1744
|
+
path: "403",
|
1745
|
+
Component: NoPermissions
|
1746
|
+
},
|
1747
|
+
{
|
1748
|
+
path: "no-content-types",
|
1749
|
+
Component: NoContentType
|
1750
|
+
},
|
1751
|
+
...routes$1
|
1752
|
+
];
|
1753
|
+
const DocumentActions = ({ actions: actions2 }) => {
|
1754
|
+
const { formatMessage } = useIntl();
|
1755
|
+
const [primaryAction, secondaryAction, ...restActions] = actions2.filter((action) => {
|
1756
|
+
if (action.position === void 0) {
|
1757
|
+
return true;
|
1808
1758
|
}
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
1813
|
-
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
1817
|
-
|
1818
|
-
|
1819
|
-
|
1820
|
-
* - the user doesn't have the permission to publish
|
1821
|
-
*/
|
1822
|
-
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1823
|
-
label: formatMessage({
|
1824
|
-
id: "app.utils.publish",
|
1825
|
-
defaultMessage: "Publish"
|
1826
|
-
}),
|
1827
|
-
onClick: async () => {
|
1828
|
-
if (hasDraftRelations) {
|
1829
|
-
return;
|
1830
|
-
}
|
1831
|
-
await performPublish();
|
1832
|
-
},
|
1833
|
-
dialog: hasDraftRelations ? {
|
1834
|
-
type: "dialog",
|
1835
|
-
variant: "danger",
|
1836
|
-
footer: null,
|
1837
|
-
title: formatMessage({
|
1838
|
-
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
1839
|
-
defaultMessage: "Confirmation"
|
1840
|
-
}),
|
1841
|
-
content: formatMessage(
|
1842
|
-
{
|
1843
|
-
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
1844
|
-
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
1845
|
-
},
|
1759
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
1760
|
+
return positions.includes("panel");
|
1761
|
+
});
|
1762
|
+
if (!primaryAction) {
|
1763
|
+
return null;
|
1764
|
+
}
|
1765
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
|
1766
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
1767
|
+
/* @__PURE__ */ jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
|
1768
|
+
restActions.length > 0 ? /* @__PURE__ */ jsx(
|
1769
|
+
DocumentActionsMenu,
|
1846
1770
|
{
|
1847
|
-
|
1771
|
+
actions: restActions,
|
1772
|
+
label: formatMessage({
|
1773
|
+
id: "content-manager.containers.edit.panels.default.more-actions",
|
1774
|
+
defaultMessage: "More document actions"
|
1775
|
+
})
|
1848
1776
|
}
|
1849
|
-
)
|
1850
|
-
|
1851
|
-
|
1777
|
+
) : null
|
1778
|
+
] }),
|
1779
|
+
secondaryAction ? /* @__PURE__ */ jsx(
|
1780
|
+
DocumentActionButton,
|
1781
|
+
{
|
1782
|
+
...secondaryAction,
|
1783
|
+
variant: secondaryAction.variant || "secondary"
|
1852
1784
|
}
|
1853
|
-
|
1854
|
-
};
|
1785
|
+
) : null
|
1786
|
+
] });
|
1855
1787
|
};
|
1856
|
-
|
1857
|
-
const
|
1858
|
-
activeTab,
|
1859
|
-
documentId,
|
1860
|
-
model,
|
1861
|
-
collectionType
|
1862
|
-
}) => {
|
1863
|
-
const navigate = useNavigate();
|
1788
|
+
const DocumentActionButton = (action) => {
|
1789
|
+
const [dialogId, setDialogId] = React.useState(null);
|
1864
1790
|
const { toggleNotification } = useNotification();
|
1865
|
-
const
|
1866
|
-
|
1867
|
-
|
1868
|
-
|
1869
|
-
|
1870
|
-
|
1871
|
-
canUpdate: canUpdate2
|
1872
|
-
}));
|
1873
|
-
const { create, update, clone } = useDocumentActions();
|
1874
|
-
const [{ query, rawQuery }] = useQueryParams();
|
1875
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1876
|
-
const isSubmitting = useForm("UpdateAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
1877
|
-
const modified = useForm("UpdateAction", ({ modified: modified2 }) => modified2);
|
1878
|
-
const setSubmitting = useForm("UpdateAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
1879
|
-
const document = useForm("UpdateAction", ({ values }) => values);
|
1880
|
-
const validate = useForm("UpdateAction", (state) => state.validate);
|
1881
|
-
const setErrors = useForm("UpdateAction", (state) => state.setErrors);
|
1882
|
-
const resetForm = useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
1883
|
-
return {
|
1884
|
-
/**
|
1885
|
-
* Disabled when:
|
1886
|
-
* - the form is submitting
|
1887
|
-
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1888
|
-
* - the active tab is the published tab
|
1889
|
-
*/
|
1890
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1891
|
-
label: formatMessage({
|
1892
|
-
id: "content-manager.containers.Edit.save",
|
1893
|
-
defaultMessage: "Save"
|
1894
|
-
}),
|
1895
|
-
onClick: async () => {
|
1896
|
-
setSubmitting(true);
|
1897
|
-
try {
|
1898
|
-
const { errors } = await validate();
|
1899
|
-
if (errors) {
|
1791
|
+
const handleClick = (action2) => async (e) => {
|
1792
|
+
const { onClick = () => false, dialog, id } = action2;
|
1793
|
+
const muteDialog = await onClick(e);
|
1794
|
+
if (dialog && !muteDialog) {
|
1795
|
+
switch (dialog.type) {
|
1796
|
+
case "notification":
|
1900
1797
|
toggleNotification({
|
1901
|
-
|
1902
|
-
message:
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1798
|
+
title: dialog.title,
|
1799
|
+
message: dialog.content,
|
1800
|
+
type: dialog.status,
|
1801
|
+
timeout: dialog.timeout,
|
1802
|
+
onClose: dialog.onClose
|
1906
1803
|
});
|
1907
|
-
|
1908
|
-
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
1912
|
-
model,
|
1913
|
-
documentId: cloneMatch.params.origin,
|
1914
|
-
params
|
1915
|
-
},
|
1916
|
-
document
|
1917
|
-
);
|
1918
|
-
if ("data" in res) {
|
1919
|
-
navigate(
|
1920
|
-
{
|
1921
|
-
pathname: `../${res.data.documentId}`,
|
1922
|
-
search: rawQuery
|
1923
|
-
},
|
1924
|
-
{ relative: "path" }
|
1925
|
-
);
|
1926
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1927
|
-
setErrors(formatValidationErrors(res.error));
|
1928
|
-
}
|
1929
|
-
} else if (documentId || collectionType === SINGLE_TYPES) {
|
1930
|
-
const res = await update(
|
1931
|
-
{
|
1932
|
-
collectionType,
|
1933
|
-
model,
|
1934
|
-
documentId,
|
1935
|
-
params
|
1936
|
-
},
|
1937
|
-
document
|
1938
|
-
);
|
1939
|
-
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1940
|
-
setErrors(formatValidationErrors(res.error));
|
1941
|
-
} else {
|
1942
|
-
resetForm();
|
1943
|
-
}
|
1944
|
-
} else {
|
1945
|
-
const res = await create(
|
1946
|
-
{
|
1947
|
-
model,
|
1948
|
-
params
|
1949
|
-
},
|
1950
|
-
document
|
1951
|
-
);
|
1952
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1953
|
-
navigate(
|
1954
|
-
{
|
1955
|
-
pathname: `../${res.data.documentId}`,
|
1956
|
-
search: rawQuery
|
1957
|
-
},
|
1958
|
-
{ replace: true, relative: "path" }
|
1959
|
-
);
|
1960
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1961
|
-
setErrors(formatValidationErrors(res.error));
|
1962
|
-
}
|
1963
|
-
}
|
1964
|
-
} finally {
|
1965
|
-
setSubmitting(false);
|
1804
|
+
break;
|
1805
|
+
case "dialog":
|
1806
|
+
case "modal":
|
1807
|
+
e.preventDefault();
|
1808
|
+
setDialogId(id);
|
1966
1809
|
}
|
1967
1810
|
}
|
1968
1811
|
};
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1812
|
+
const handleClose = () => {
|
1813
|
+
setDialogId(null);
|
1814
|
+
};
|
1815
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
1816
|
+
/* @__PURE__ */ jsx(
|
1817
|
+
Button,
|
1818
|
+
{
|
1819
|
+
flex: "auto",
|
1820
|
+
startIcon: action.icon,
|
1821
|
+
disabled: action.disabled,
|
1822
|
+
onClick: handleClick(action),
|
1823
|
+
justifyContent: "center",
|
1824
|
+
variant: action.variant || "default",
|
1825
|
+
paddingTop: "7px",
|
1826
|
+
paddingBottom: "7px",
|
1827
|
+
children: action.label
|
1828
|
+
}
|
1829
|
+
),
|
1830
|
+
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
|
1831
|
+
DocumentActionConfirmDialog,
|
1832
|
+
{
|
1833
|
+
...action.dialog,
|
1834
|
+
variant: action.dialog?.variant ?? action.variant,
|
1835
|
+
isOpen: dialogId === action.id,
|
1836
|
+
onClose: handleClose
|
1837
|
+
}
|
1838
|
+
) : null,
|
1839
|
+
action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
|
1840
|
+
DocumentActionModal,
|
1841
|
+
{
|
1842
|
+
...action.dialog,
|
1843
|
+
onModalClose: handleClose,
|
1844
|
+
isOpen: dialogId === action.id
|
1845
|
+
}
|
1846
|
+
) : null
|
1847
|
+
] });
|
1848
|
+
};
|
1849
|
+
const DocumentActionsMenu = ({
|
1850
|
+
actions: actions2,
|
1851
|
+
children,
|
1852
|
+
label,
|
1853
|
+
variant = "tertiary"
|
1981
1854
|
}) => {
|
1855
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
1856
|
+
const [dialogId, setDialogId] = React.useState(null);
|
1982
1857
|
const { formatMessage } = useIntl();
|
1983
|
-
const { schema } = useDoc();
|
1984
|
-
const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1985
|
-
const { unpublish } = useDocumentActions();
|
1986
|
-
const [{ query }] = useQueryParams();
|
1987
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1988
1858
|
const { toggleNotification } = useNotification();
|
1989
|
-
const
|
1990
|
-
const
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
1995
|
-
|
1996
|
-
}
|
1997
|
-
return {
|
1998
|
-
disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
|
1999
|
-
label: formatMessage({
|
2000
|
-
id: "app.utils.unpublish",
|
2001
|
-
defaultMessage: "Unpublish"
|
2002
|
-
}),
|
2003
|
-
icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
|
2004
|
-
onClick: async () => {
|
2005
|
-
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2006
|
-
if (!documentId) {
|
2007
|
-
console.error(
|
2008
|
-
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2009
|
-
);
|
1859
|
+
const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
|
1860
|
+
const handleClick = (action) => async (e) => {
|
1861
|
+
const { onClick = () => false, dialog, id } = action;
|
1862
|
+
const muteDialog = await onClick(e);
|
1863
|
+
if (dialog && !muteDialog) {
|
1864
|
+
switch (dialog.type) {
|
1865
|
+
case "notification":
|
2010
1866
|
toggleNotification({
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
1867
|
+
title: dialog.title,
|
1868
|
+
message: dialog.content,
|
1869
|
+
type: dialog.status,
|
1870
|
+
timeout: dialog.timeout,
|
1871
|
+
onClose: dialog.onClose
|
2016
1872
|
});
|
2017
|
-
|
2018
|
-
|
1873
|
+
break;
|
1874
|
+
case "dialog":
|
1875
|
+
case "modal":
|
1876
|
+
setDialogId(id);
|
2019
1877
|
}
|
2020
|
-
|
2021
|
-
|
2022
|
-
|
2023
|
-
|
2024
|
-
|
2025
|
-
|
2026
|
-
|
2027
|
-
|
2028
|
-
|
2029
|
-
|
2030
|
-
|
2031
|
-
|
2032
|
-
|
2033
|
-
|
2034
|
-
|
2035
|
-
|
2036
|
-
|
2037
|
-
|
2038
|
-
|
1878
|
+
}
|
1879
|
+
};
|
1880
|
+
const handleClose = () => {
|
1881
|
+
setDialogId(null);
|
1882
|
+
setIsOpen(false);
|
1883
|
+
};
|
1884
|
+
return /* @__PURE__ */ jsxs(Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1885
|
+
/* @__PURE__ */ jsxs(
|
1886
|
+
Menu.Trigger,
|
1887
|
+
{
|
1888
|
+
disabled: isDisabled,
|
1889
|
+
size: "S",
|
1890
|
+
endIcon: null,
|
1891
|
+
paddingTop: "4px",
|
1892
|
+
paddingLeft: "7px",
|
1893
|
+
paddingRight: "7px",
|
1894
|
+
variant,
|
1895
|
+
children: [
|
1896
|
+
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
1897
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1898
|
+
id: "content-manager.containers.edit.panels.default.more-actions",
|
1899
|
+
defaultMessage: "More document actions"
|
2039
1900
|
}) })
|
2040
|
-
]
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2047
|
-
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2048
|
-
defaultMessage: "Choose an option to unpublish the document."
|
2049
|
-
}),
|
2050
|
-
onValueChange: handleChange,
|
2051
|
-
children: [
|
2052
|
-
/* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2053
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2054
|
-
defaultMessage: "Keep draft"
|
2055
|
-
}) }),
|
2056
|
-
/* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2057
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2058
|
-
defaultMessage: "Replace draft"
|
2059
|
-
}) })
|
2060
|
-
]
|
2061
|
-
}
|
2062
|
-
)
|
2063
|
-
] }),
|
2064
|
-
onConfirm: async () => {
|
2065
|
-
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2066
|
-
console.error(
|
2067
|
-
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2068
|
-
);
|
2069
|
-
toggleNotification({
|
2070
|
-
message: formatMessage({
|
2071
|
-
id: "content-manager.actions.unpublish.error",
|
2072
|
-
defaultMessage: "An error occurred while trying to unpublish the document."
|
2073
|
-
}),
|
2074
|
-
type: "danger"
|
2075
|
-
});
|
2076
|
-
}
|
2077
|
-
await unpublish(
|
1901
|
+
]
|
1902
|
+
}
|
1903
|
+
),
|
1904
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1905
|
+
actions2.map((action) => {
|
1906
|
+
return /* @__PURE__ */ jsx(
|
1907
|
+
Menu.Item,
|
2078
1908
|
{
|
2079
|
-
|
2080
|
-
|
2081
|
-
|
2082
|
-
|
1909
|
+
disabled: action.disabled,
|
1910
|
+
onSelect: handleClick(action),
|
1911
|
+
display: "block",
|
1912
|
+
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
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
|
+
),
|
1932
|
+
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
1933
|
+
Flex,
|
1934
|
+
{
|
1935
|
+
alignItems: "center",
|
1936
|
+
background: "alternative100",
|
1937
|
+
borderStyle: "solid",
|
1938
|
+
borderColor: "alternative200",
|
1939
|
+
borderWidth: "1px",
|
1940
|
+
height: 5,
|
1941
|
+
paddingLeft: 2,
|
1942
|
+
paddingRight: 2,
|
1943
|
+
hasRadius: true,
|
1944
|
+
color: "alternative600",
|
1945
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1946
|
+
}
|
1947
|
+
)
|
1948
|
+
] })
|
2083
1949
|
},
|
2084
|
-
|
1950
|
+
action.id
|
2085
1951
|
);
|
2086
|
-
}
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
1952
|
+
}),
|
1953
|
+
children
|
1954
|
+
] }),
|
1955
|
+
actions2.map((action) => {
|
1956
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
1957
|
+
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
|
1958
|
+
DocumentActionConfirmDialog,
|
1959
|
+
{
|
1960
|
+
...action.dialog,
|
1961
|
+
variant: action.variant,
|
1962
|
+
isOpen: dialogId === action.id,
|
1963
|
+
onClose: handleClose
|
1964
|
+
}
|
1965
|
+
) : null,
|
1966
|
+
action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
|
1967
|
+
DocumentActionModal,
|
1968
|
+
{
|
1969
|
+
...action.dialog,
|
1970
|
+
onModalClose: handleClose,
|
1971
|
+
isOpen: dialogId === action.id
|
1972
|
+
}
|
1973
|
+
) : null
|
1974
|
+
] }, action.id);
|
1975
|
+
})
|
1976
|
+
] });
|
1977
|
+
};
|
1978
|
+
const convertActionVariantToColor = (variant = "secondary") => {
|
1979
|
+
switch (variant) {
|
1980
|
+
case "danger":
|
1981
|
+
return "danger600";
|
1982
|
+
case "secondary":
|
1983
|
+
return void 0;
|
1984
|
+
case "success":
|
1985
|
+
return "success600";
|
1986
|
+
default:
|
1987
|
+
return "primary600";
|
1988
|
+
}
|
1989
|
+
};
|
1990
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1991
|
+
switch (variant) {
|
1992
|
+
case "danger":
|
1993
|
+
return "danger600";
|
1994
|
+
case "secondary":
|
1995
|
+
return "neutral500";
|
1996
|
+
case "success":
|
1997
|
+
return "success600";
|
1998
|
+
default:
|
1999
|
+
return "primary600";
|
2000
|
+
}
|
2001
|
+
};
|
2002
|
+
const DocumentActionConfirmDialog = ({
|
2003
|
+
onClose,
|
2004
|
+
onCancel,
|
2005
|
+
onConfirm,
|
2006
|
+
title,
|
2007
|
+
content,
|
2008
|
+
isOpen,
|
2009
|
+
variant = "secondary"
|
2010
|
+
}) => {
|
2011
|
+
const { formatMessage } = useIntl();
|
2012
|
+
const handleClose = async () => {
|
2013
|
+
if (onCancel) {
|
2014
|
+
await onCancel();
|
2015
|
+
}
|
2016
|
+
onClose();
|
2090
2017
|
};
|
2018
|
+
const handleConfirm = async () => {
|
2019
|
+
if (onConfirm) {
|
2020
|
+
await onConfirm();
|
2021
|
+
}
|
2022
|
+
onClose();
|
2023
|
+
};
|
2024
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2025
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2026
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
2027
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
2028
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
2029
|
+
id: "app.components.Button.cancel",
|
2030
|
+
defaultMessage: "Cancel"
|
2031
|
+
}) }) }),
|
2032
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
2033
|
+
id: "app.components.Button.confirm",
|
2034
|
+
defaultMessage: "Confirm"
|
2035
|
+
}) })
|
2036
|
+
] })
|
2037
|
+
] }) });
|
2091
2038
|
};
|
2092
|
-
|
2093
|
-
|
2039
|
+
const DocumentActionModal = ({
|
2040
|
+
isOpen,
|
2041
|
+
title,
|
2042
|
+
onClose,
|
2043
|
+
footer: Footer,
|
2044
|
+
content: Content,
|
2045
|
+
onModalClose
|
2046
|
+
}) => {
|
2047
|
+
const handleClose = () => {
|
2048
|
+
if (onClose) {
|
2049
|
+
onClose();
|
2050
|
+
}
|
2051
|
+
onModalClose();
|
2052
|
+
};
|
2053
|
+
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
2054
|
+
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
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
|
2057
|
+
] }) });
|
2058
|
+
};
|
2059
|
+
const PublishAction$1 = ({
|
2094
2060
|
activeTab,
|
2095
2061
|
documentId,
|
2096
2062
|
model,
|
2097
2063
|
collectionType,
|
2064
|
+
meta,
|
2098
2065
|
document
|
2099
2066
|
}) => {
|
2100
|
-
const { formatMessage } = useIntl();
|
2101
2067
|
const { schema } = useDoc();
|
2102
|
-
const
|
2103
|
-
const {
|
2104
|
-
const
|
2105
|
-
const
|
2106
|
-
if (!schema?.options?.draftAndPublish) {
|
2107
|
-
return null;
|
2108
|
-
}
|
2109
|
-
return {
|
2110
|
-
disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
|
2111
|
-
label: formatMessage({
|
2112
|
-
id: "content-manager.actions.discard.label",
|
2113
|
-
defaultMessage: "Discard changes"
|
2114
|
-
}),
|
2115
|
-
icon: /* @__PURE__ */ jsx(StyledCrossCircle, {}),
|
2116
|
-
position: ["panel", "table-row"],
|
2117
|
-
variant: "danger",
|
2118
|
-
dialog: {
|
2119
|
-
type: "dialog",
|
2120
|
-
title: formatMessage({
|
2121
|
-
id: "app.components.ConfirmDialog.title",
|
2122
|
-
defaultMessage: "Confirmation"
|
2123
|
-
}),
|
2124
|
-
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
2125
|
-
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2126
|
-
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2127
|
-
id: "content-manager.actions.discard.dialog.body",
|
2128
|
-
defaultMessage: "Are you sure?"
|
2129
|
-
}) })
|
2130
|
-
] }),
|
2131
|
-
onConfirm: async () => {
|
2132
|
-
await discard({
|
2133
|
-
collectionType,
|
2134
|
-
model,
|
2135
|
-
documentId,
|
2136
|
-
params
|
2137
|
-
});
|
2138
|
-
}
|
2139
|
-
}
|
2140
|
-
};
|
2141
|
-
};
|
2142
|
-
DiscardAction.type = "discard";
|
2143
|
-
const StyledCrossCircle = styled(CrossCircle)`
|
2144
|
-
path {
|
2145
|
-
fill: currentColor;
|
2146
|
-
}
|
2147
|
-
`;
|
2148
|
-
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2149
|
-
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2150
|
-
const RelativeTime = React.forwardRef(
|
2151
|
-
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
2152
|
-
const { formatRelativeTime, formatDate, formatTime } = useIntl();
|
2153
|
-
const interval = intervalToDuration({
|
2154
|
-
start: timestamp,
|
2155
|
-
end: Date.now()
|
2156
|
-
// see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
|
2157
|
-
});
|
2158
|
-
const unit = intervals.find((intervalUnit) => {
|
2159
|
-
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2160
|
-
});
|
2161
|
-
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2162
|
-
const customInterval = customIntervals.find(
|
2163
|
-
(custom) => interval[custom.unit] < custom.threshold
|
2164
|
-
);
|
2165
|
-
const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
|
2166
|
-
return /* @__PURE__ */ jsx(
|
2167
|
-
"time",
|
2168
|
-
{
|
2169
|
-
ref: forwardedRef,
|
2170
|
-
dateTime: timestamp.toISOString(),
|
2171
|
-
role: "time",
|
2172
|
-
title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
|
2173
|
-
...restProps,
|
2174
|
-
children: displayText
|
2175
|
-
}
|
2176
|
-
);
|
2177
|
-
}
|
2178
|
-
);
|
2179
|
-
const getDisplayName = ({
|
2180
|
-
firstname,
|
2181
|
-
lastname,
|
2182
|
-
username,
|
2183
|
-
email
|
2184
|
-
} = {}) => {
|
2185
|
-
if (username) {
|
2186
|
-
return username;
|
2187
|
-
}
|
2188
|
-
if (firstname) {
|
2189
|
-
return `${firstname} ${lastname ?? ""}`.trim();
|
2190
|
-
}
|
2191
|
-
return email ?? "";
|
2192
|
-
};
|
2193
|
-
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2194
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2195
|
-
const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
|
2196
|
-
return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
|
2197
|
-
};
|
2198
|
-
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2199
|
-
const { formatMessage } = useIntl();
|
2068
|
+
const navigate = useNavigate();
|
2069
|
+
const { toggleNotification } = useNotification();
|
2070
|
+
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2071
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
2200
2072
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2201
|
-
const title = isCreating ? formatMessage({
|
2202
|
-
id: "content-manager.containers.edit.title.new",
|
2203
|
-
defaultMessage: "Create an entry"
|
2204
|
-
}) : documentTitle;
|
2205
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2206
|
-
/* @__PURE__ */ jsx(BackButton, {}),
|
2207
|
-
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2208
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2209
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2210
|
-
] }),
|
2211
|
-
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2212
|
-
] });
|
2213
|
-
};
|
2214
|
-
const HeaderToolbar = () => {
|
2215
2073
|
const { formatMessage } = useIntl();
|
2216
|
-
const
|
2074
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2075
|
+
const { publish } = useDocumentActions();
|
2217
2076
|
const [
|
2218
|
-
|
2219
|
-
|
2077
|
+
countDraftRelations,
|
2078
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2079
|
+
] = useLazyGetDraftRelationCountQuery();
|
2080
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
2081
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
2082
|
+
const [{ query, rawQuery }] = useQueryParams();
|
2083
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
2084
|
+
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
2085
|
+
const setSubmitting = useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
2086
|
+
const isSubmitting = useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
2087
|
+
const validate = useForm("PublishAction", (state) => state.validate);
|
2088
|
+
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
2089
|
+
const formValues = useForm("PublishAction", ({ values }) => values);
|
2090
|
+
React.useEffect(() => {
|
2091
|
+
if (isErrorDraftRelations) {
|
2092
|
+
toggleNotification({
|
2093
|
+
type: "danger",
|
2094
|
+
message: formatMessage({
|
2095
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2096
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2097
|
+
})
|
2098
|
+
});
|
2220
2099
|
}
|
2221
|
-
|
2222
|
-
|
2223
|
-
|
2224
|
-
|
2225
|
-
|
2226
|
-
|
2227
|
-
|
2228
|
-
|
2229
|
-
activeTab: status,
|
2230
|
-
model,
|
2231
|
-
documentId: id,
|
2232
|
-
document: isCloning ? void 0 : document,
|
2233
|
-
meta: isCloning ? void 0 : meta,
|
2234
|
-
collectionType
|
2235
|
-
},
|
2236
|
-
descriptions: plugins["content-manager"].apis.getHeaderActions(),
|
2237
|
-
children: (actions2) => {
|
2238
|
-
if (actions2.length > 0) {
|
2239
|
-
return /* @__PURE__ */ jsx(HeaderActions, { actions: actions2 });
|
2240
|
-
} else {
|
2241
|
-
return null;
|
2242
|
-
}
|
2100
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2101
|
+
React.useEffect(() => {
|
2102
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2103
|
+
const extractDraftRelations = (data) => {
|
2104
|
+
const relations = data.connect || [];
|
2105
|
+
relations.forEach((relation) => {
|
2106
|
+
if (relation.status === "draft") {
|
2107
|
+
localDraftRelations.add(relation.id);
|
2243
2108
|
}
|
2244
|
-
}
|
2245
|
-
|
2246
|
-
|
2247
|
-
|
2248
|
-
|
2249
|
-
|
2250
|
-
|
2251
|
-
|
2252
|
-
documentId: id,
|
2253
|
-
document: isCloning ? void 0 : document,
|
2254
|
-
meta: isCloning ? void 0 : meta,
|
2255
|
-
collectionType
|
2256
|
-
},
|
2257
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2258
|
-
children: (actions2) => {
|
2259
|
-
const headerActions = actions2.filter((action) => {
|
2260
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2261
|
-
return positions.includes("header");
|
2262
|
-
});
|
2263
|
-
return /* @__PURE__ */ jsx(
|
2264
|
-
DocumentActionsMenu,
|
2265
|
-
{
|
2266
|
-
actions: headerActions,
|
2267
|
-
label: formatMessage({
|
2268
|
-
id: "content-manager.containers.edit.header.more-actions",
|
2269
|
-
defaultMessage: "More actions"
|
2270
|
-
}),
|
2271
|
-
children: /* @__PURE__ */ jsx(Information, { activeTab: status })
|
2272
|
-
}
|
2273
|
-
);
|
2109
|
+
});
|
2110
|
+
};
|
2111
|
+
const traverseAndExtract = (data) => {
|
2112
|
+
Object.entries(data).forEach(([key, value]) => {
|
2113
|
+
if (key === "connect" && Array.isArray(value)) {
|
2114
|
+
extractDraftRelations({ connect: value });
|
2115
|
+
} else if (typeof value === "object" && value !== null) {
|
2116
|
+
traverseAndExtract(value);
|
2274
2117
|
}
|
2118
|
+
});
|
2119
|
+
};
|
2120
|
+
if (!documentId || modified) {
|
2121
|
+
traverseAndExtract(formValues);
|
2122
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2123
|
+
}
|
2124
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2125
|
+
React.useEffect(() => {
|
2126
|
+
if (!document || !document.documentId || isListView) {
|
2127
|
+
return;
|
2128
|
+
}
|
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;
|
2275
2138
|
}
|
2276
|
-
|
2277
|
-
|
2278
|
-
}
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2139
|
+
if (data) {
|
2140
|
+
setServerCountOfDraftRelations(data.data);
|
2141
|
+
}
|
2142
|
+
};
|
2143
|
+
fetchDraftRelationsCount();
|
2144
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2145
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2146
|
+
if (!schema?.options?.draftAndPublish) {
|
2283
2147
|
return null;
|
2284
2148
|
}
|
2285
|
-
const
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2295
|
-
|
2296
|
-
|
2149
|
+
const performPublish = async () => {
|
2150
|
+
setSubmitting(true);
|
2151
|
+
try {
|
2152
|
+
const { errors } = await validate(true, {
|
2153
|
+
status: "published"
|
2154
|
+
});
|
2155
|
+
if (errors) {
|
2156
|
+
toggleNotification({
|
2157
|
+
type: "danger",
|
2158
|
+
message: formatMessage({
|
2159
|
+
id: "content-manager.validation.error",
|
2160
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2161
|
+
})
|
2162
|
+
});
|
2163
|
+
return;
|
2164
|
+
}
|
2165
|
+
const res = await publish(
|
2297
2166
|
{
|
2298
|
-
|
2299
|
-
|
2167
|
+
collectionType,
|
2168
|
+
model,
|
2169
|
+
documentId,
|
2170
|
+
params
|
2300
2171
|
},
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2306
|
-
|
2172
|
+
formValues
|
2173
|
+
);
|
2174
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2175
|
+
navigate({
|
2176
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2177
|
+
search: rawQuery
|
2178
|
+
});
|
2179
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2180
|
+
setErrors(formatValidationErrors(res.error));
|
2181
|
+
}
|
2182
|
+
} finally {
|
2183
|
+
setSubmitting(false);
|
2184
|
+
}
|
2185
|
+
};
|
2186
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2187
|
+
const enableDraftRelationsCount = false;
|
2188
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
2189
|
+
return {
|
2190
|
+
/**
|
2191
|
+
* Disabled when:
|
2192
|
+
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
2193
|
+
* - the form is submitting
|
2194
|
+
* - the active tab is the published tab
|
2195
|
+
* - the document is already published & not modified
|
2196
|
+
* - the document is being created & not modified
|
2197
|
+
* - the user doesn't have the permission to publish
|
2198
|
+
*/
|
2199
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
2200
|
+
label: formatMessage({
|
2201
|
+
id: "app.utils.publish",
|
2202
|
+
defaultMessage: "Publish"
|
2203
|
+
}),
|
2204
|
+
onClick: async () => {
|
2205
|
+
await performPublish();
|
2307
2206
|
},
|
2308
|
-
{
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2312
|
-
|
2207
|
+
dialog: hasDraftRelations ? {
|
2208
|
+
type: "dialog",
|
2209
|
+
variant: "danger",
|
2210
|
+
footer: null,
|
2211
|
+
title: formatMessage({
|
2212
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2213
|
+
defaultMessage: "Confirmation"
|
2313
2214
|
}),
|
2314
|
-
|
2215
|
+
content: formatMessage(
|
2315
2216
|
{
|
2316
|
-
id:
|
2317
|
-
defaultMessage:
|
2217
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2218
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2318
2219
|
},
|
2319
2220
|
{
|
2320
|
-
|
2321
|
-
RelativeTime,
|
2322
|
-
{
|
2323
|
-
timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
|
2324
|
-
}
|
2325
|
-
),
|
2326
|
-
isAnonymous: !updator,
|
2327
|
-
author: updator
|
2221
|
+
count: totalDraftRelations
|
2328
2222
|
}
|
2329
|
-
)
|
2330
|
-
|
2331
|
-
|
2332
|
-
|
2333
|
-
|
2334
|
-
|
2335
|
-
|
2336
|
-
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2223
|
+
),
|
2224
|
+
onConfirm: async () => {
|
2225
|
+
await performPublish();
|
2226
|
+
}
|
2227
|
+
} : void 0
|
2228
|
+
};
|
2229
|
+
};
|
2230
|
+
PublishAction$1.type = "publish";
|
2231
|
+
const UpdateAction = ({
|
2232
|
+
activeTab,
|
2233
|
+
documentId,
|
2234
|
+
model,
|
2235
|
+
collectionType
|
2236
|
+
}) => {
|
2237
|
+
const navigate = useNavigate();
|
2238
|
+
const { toggleNotification } = useNotification();
|
2239
|
+
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2240
|
+
const cloneMatch = useMatch(CLONE_PATH);
|
2241
|
+
const isCloning = cloneMatch !== null;
|
2242
|
+
const { formatMessage } = useIntl();
|
2243
|
+
const { create, update, clone } = useDocumentActions();
|
2244
|
+
const [{ query, rawQuery }] = useQueryParams();
|
2245
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
2246
|
+
const isSubmitting = useForm("UpdateAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
2247
|
+
const modified = useForm("UpdateAction", ({ modified: modified2 }) => modified2);
|
2248
|
+
const setSubmitting = useForm("UpdateAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
2249
|
+
const document = useForm("UpdateAction", ({ values }) => values);
|
2250
|
+
const validate = useForm("UpdateAction", (state) => state.validate);
|
2251
|
+
const setErrors = useForm("UpdateAction", (state) => state.setErrors);
|
2252
|
+
const resetForm = useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
2253
|
+
return {
|
2254
|
+
/**
|
2255
|
+
* Disabled when:
|
2256
|
+
* - the form is submitting
|
2257
|
+
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
2258
|
+
* - the active tab is the published tab
|
2259
|
+
*/
|
2260
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
2261
|
+
label: formatMessage({
|
2262
|
+
id: "content-manager.containers.Edit.save",
|
2263
|
+
defaultMessage: "Save"
|
2264
|
+
}),
|
2265
|
+
onClick: async () => {
|
2266
|
+
setSubmitting(true);
|
2267
|
+
try {
|
2268
|
+
const { errors } = await validate(true, {
|
2269
|
+
status: "draft"
|
2270
|
+
});
|
2271
|
+
if (errors) {
|
2272
|
+
toggleNotification({
|
2273
|
+
type: "danger",
|
2274
|
+
message: formatMessage({
|
2275
|
+
id: "content-manager.validation.error",
|
2276
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2277
|
+
})
|
2278
|
+
});
|
2279
|
+
return;
|
2351
2280
|
}
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2281
|
+
if (isCloning) {
|
2282
|
+
const res = await clone(
|
2283
|
+
{
|
2284
|
+
model,
|
2285
|
+
documentId: cloneMatch.params.origin,
|
2286
|
+
params
|
2287
|
+
},
|
2288
|
+
document
|
2289
|
+
);
|
2290
|
+
if ("data" in res) {
|
2291
|
+
navigate(
|
2292
|
+
{
|
2293
|
+
pathname: `../${res.data.documentId}`,
|
2294
|
+
search: rawQuery
|
2295
|
+
},
|
2296
|
+
{ relative: "path" }
|
2297
|
+
);
|
2298
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2299
|
+
setErrors(formatValidationErrors(res.error));
|
2300
|
+
}
|
2301
|
+
} else if (documentId || collectionType === SINGLE_TYPES) {
|
2302
|
+
const res = await update(
|
2303
|
+
{
|
2304
|
+
collectionType,
|
2305
|
+
model,
|
2306
|
+
documentId,
|
2307
|
+
params
|
2308
|
+
},
|
2309
|
+
document
|
2310
|
+
);
|
2311
|
+
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2312
|
+
setErrors(formatValidationErrors(res.error));
|
2313
|
+
} else {
|
2314
|
+
resetForm();
|
2315
|
+
}
|
2316
|
+
} else {
|
2317
|
+
const res = await create(
|
2318
|
+
{
|
2319
|
+
model,
|
2320
|
+
params
|
2321
|
+
},
|
2322
|
+
document
|
2323
|
+
);
|
2324
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2325
|
+
navigate(
|
2326
|
+
{
|
2327
|
+
pathname: `../${res.data.documentId}`,
|
2328
|
+
search: rawQuery
|
2329
|
+
},
|
2330
|
+
{ replace: true, relative: "path" }
|
2331
|
+
);
|
2332
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2333
|
+
setErrors(formatValidationErrors(res.error));
|
2334
|
+
}
|
2335
|
+
}
|
2336
|
+
} finally {
|
2337
|
+
setSubmitting(false);
|
2338
|
+
}
|
2374
2339
|
}
|
2375
|
-
|
2340
|
+
};
|
2376
2341
|
};
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
SingleSelect,
|
2382
|
-
{
|
2383
|
-
size: "S",
|
2384
|
-
disabled: action.disabled,
|
2385
|
-
"aria-label": action.label,
|
2386
|
-
onChange: action.onSelect,
|
2387
|
-
value: action.value,
|
2388
|
-
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2389
|
-
},
|
2390
|
-
action.id
|
2391
|
-
);
|
2392
|
-
} else {
|
2393
|
-
return null;
|
2394
|
-
}
|
2395
|
-
}) });
|
2342
|
+
UpdateAction.type = "update";
|
2343
|
+
const UNPUBLISH_DRAFT_OPTIONS = {
|
2344
|
+
KEEP: "keep",
|
2345
|
+
DISCARD: "discard"
|
2396
2346
|
};
|
2397
|
-
const
|
2398
|
-
|
2347
|
+
const UnpublishAction$1 = ({
|
2348
|
+
activeTab,
|
2349
|
+
documentId,
|
2350
|
+
model,
|
2351
|
+
collectionType,
|
2352
|
+
document
|
2353
|
+
}) => {
|
2399
2354
|
const { formatMessage } = useIntl();
|
2400
|
-
|
2401
|
-
|
2402
|
-
|
2403
|
-
|
2404
|
-
|
2405
|
-
|
2406
|
-
|
2407
|
-
|
2408
|
-
|
2409
|
-
|
2355
|
+
const { schema } = useDoc();
|
2356
|
+
const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2357
|
+
const { unpublish } = useDocumentActions();
|
2358
|
+
const [{ query }] = useQueryParams();
|
2359
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
2360
|
+
const { toggleNotification } = useNotification();
|
2361
|
+
const [shouldKeepDraft, setShouldKeepDraft] = React.useState(true);
|
2362
|
+
const isDocumentModified = document?.status === "modified";
|
2363
|
+
const handleChange = (value) => {
|
2364
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
2410
2365
|
};
|
2411
|
-
|
2412
|
-
|
2413
|
-
|
2414
|
-
const navigate = useNavigate();
|
2415
|
-
const { formatMessage } = useIntl();
|
2366
|
+
if (!schema?.options?.draftAndPublish) {
|
2367
|
+
return null;
|
2368
|
+
}
|
2416
2369
|
return {
|
2370
|
+
disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
|
2417
2371
|
label: formatMessage({
|
2418
|
-
id: "
|
2419
|
-
defaultMessage: "
|
2372
|
+
id: "app.utils.unpublish",
|
2373
|
+
defaultMessage: "Unpublish"
|
2420
2374
|
}),
|
2421
|
-
icon: /* @__PURE__ */ jsx(
|
2422
|
-
onClick: () => {
|
2423
|
-
|
2375
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2376
|
+
onClick: async () => {
|
2377
|
+
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2378
|
+
if (!documentId) {
|
2379
|
+
console.error(
|
2380
|
+
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2381
|
+
);
|
2382
|
+
toggleNotification({
|
2383
|
+
message: formatMessage({
|
2384
|
+
id: "content-manager.actions.unpublish.error",
|
2385
|
+
defaultMessage: "An error occurred while trying to unpublish the document."
|
2386
|
+
}),
|
2387
|
+
type: "danger"
|
2388
|
+
});
|
2389
|
+
}
|
2390
|
+
return;
|
2391
|
+
}
|
2392
|
+
await unpublish({
|
2393
|
+
collectionType,
|
2394
|
+
model,
|
2395
|
+
documentId,
|
2396
|
+
params
|
2397
|
+
});
|
2424
2398
|
},
|
2425
|
-
|
2399
|
+
dialog: isDocumentModified ? {
|
2400
|
+
type: "dialog",
|
2401
|
+
title: formatMessage({
|
2402
|
+
id: "app.components.ConfirmDialog.title",
|
2403
|
+
defaultMessage: "Confirmation"
|
2404
|
+
}),
|
2405
|
+
content: /* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
|
2406
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", direction: "column", gap: 2, children: [
|
2407
|
+
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2408
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2409
|
+
id: "content-manager.actions.unpublish.dialog.body",
|
2410
|
+
defaultMessage: "Are you sure?"
|
2411
|
+
}) })
|
2412
|
+
] }),
|
2413
|
+
/* @__PURE__ */ jsxs(
|
2414
|
+
Radio.Group,
|
2415
|
+
{
|
2416
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2417
|
+
name: "discard-options",
|
2418
|
+
"aria-label": formatMessage({
|
2419
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2420
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2421
|
+
}),
|
2422
|
+
onValueChange: handleChange,
|
2423
|
+
children: [
|
2424
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2425
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2426
|
+
defaultMessage: "Keep draft"
|
2427
|
+
}) }),
|
2428
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2429
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2430
|
+
defaultMessage: "Replace draft"
|
2431
|
+
}) })
|
2432
|
+
]
|
2433
|
+
}
|
2434
|
+
)
|
2435
|
+
] }),
|
2436
|
+
onConfirm: async () => {
|
2437
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2438
|
+
console.error(
|
2439
|
+
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2440
|
+
);
|
2441
|
+
toggleNotification({
|
2442
|
+
message: formatMessage({
|
2443
|
+
id: "content-manager.actions.unpublish.error",
|
2444
|
+
defaultMessage: "An error occurred while trying to unpublish the document."
|
2445
|
+
}),
|
2446
|
+
type: "danger"
|
2447
|
+
});
|
2448
|
+
}
|
2449
|
+
await unpublish(
|
2450
|
+
{
|
2451
|
+
collectionType,
|
2452
|
+
model,
|
2453
|
+
documentId,
|
2454
|
+
params
|
2455
|
+
},
|
2456
|
+
!shouldKeepDraft
|
2457
|
+
);
|
2458
|
+
}
|
2459
|
+
} : void 0,
|
2460
|
+
variant: "danger",
|
2461
|
+
position: ["panel", "table-row"]
|
2426
2462
|
};
|
2427
2463
|
};
|
2428
|
-
|
2429
|
-
const
|
2430
|
-
|
2464
|
+
UnpublishAction$1.type = "unpublish";
|
2465
|
+
const DiscardAction = ({
|
2466
|
+
activeTab,
|
2467
|
+
documentId,
|
2468
|
+
model,
|
2469
|
+
collectionType,
|
2470
|
+
document
|
2471
|
+
}) => {
|
2431
2472
|
const { formatMessage } = useIntl();
|
2432
|
-
const
|
2433
|
-
const
|
2434
|
-
const {
|
2435
|
-
const {
|
2436
|
-
const
|
2473
|
+
const { schema } = useDoc();
|
2474
|
+
const canUpdate = useDocumentRBAC("DiscardAction", ({ canUpdate: canUpdate2 }) => canUpdate2);
|
2475
|
+
const { discard } = useDocumentActions();
|
2476
|
+
const [{ query }] = useQueryParams();
|
2477
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
2478
|
+
if (!schema?.options?.draftAndPublish) {
|
2479
|
+
return null;
|
2480
|
+
}
|
2437
2481
|
return {
|
2438
|
-
disabled: !
|
2482
|
+
disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
|
2439
2483
|
label: formatMessage({
|
2440
|
-
id: "content-manager.actions.
|
2441
|
-
defaultMessage: "
|
2484
|
+
id: "content-manager.actions.discard.label",
|
2485
|
+
defaultMessage: "Discard changes"
|
2442
2486
|
}),
|
2443
|
-
icon: /* @__PURE__ */ jsx(
|
2487
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2488
|
+
position: ["panel", "table-row"],
|
2489
|
+
variant: "danger",
|
2444
2490
|
dialog: {
|
2445
2491
|
type: "dialog",
|
2446
2492
|
title: formatMessage({
|
@@ -2450,92 +2496,90 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2450
2496
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
2451
2497
|
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2452
2498
|
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2453
|
-
id: "content-manager.actions.
|
2499
|
+
id: "content-manager.actions.discard.dialog.body",
|
2454
2500
|
defaultMessage: "Are you sure?"
|
2455
2501
|
}) })
|
2456
2502
|
] }),
|
2457
2503
|
onConfirm: async () => {
|
2458
|
-
|
2459
|
-
|
2460
|
-
|
2461
|
-
|
2462
|
-
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
2466
|
-
|
2467
|
-
|
2468
|
-
|
2469
|
-
|
2470
|
-
|
2471
|
-
|
2472
|
-
|
2473
|
-
|
2474
|
-
|
2475
|
-
|
2476
|
-
|
2477
|
-
|
2478
|
-
|
2479
|
-
|
2480
|
-
|
2481
|
-
|
2482
|
-
|
2483
|
-
|
2484
|
-
|
2485
|
-
|
2486
|
-
|
2487
|
-
|
2488
|
-
|
2489
|
-
|
2490
|
-
|
2504
|
+
await discard({
|
2505
|
+
collectionType,
|
2506
|
+
model,
|
2507
|
+
documentId,
|
2508
|
+
params
|
2509
|
+
});
|
2510
|
+
}
|
2511
|
+
}
|
2512
|
+
};
|
2513
|
+
};
|
2514
|
+
DiscardAction.type = "discard";
|
2515
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2516
|
+
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2517
|
+
const RelativeTime = React.forwardRef(
|
2518
|
+
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
2519
|
+
const { formatRelativeTime, formatDate, formatTime } = useIntl();
|
2520
|
+
const interval = intervalToDuration({
|
2521
|
+
start: timestamp,
|
2522
|
+
end: Date.now()
|
2523
|
+
// see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
|
2524
|
+
});
|
2525
|
+
const unit = intervals.find((intervalUnit) => {
|
2526
|
+
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2527
|
+
});
|
2528
|
+
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2529
|
+
const customInterval = customIntervals.find(
|
2530
|
+
(custom) => interval[custom.unit] < custom.threshold
|
2531
|
+
);
|
2532
|
+
const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
|
2533
|
+
return /* @__PURE__ */ jsx(
|
2534
|
+
"time",
|
2535
|
+
{
|
2536
|
+
ref: forwardedRef,
|
2537
|
+
dateTime: timestamp.toISOString(),
|
2538
|
+
role: "time",
|
2539
|
+
title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
|
2540
|
+
...restProps,
|
2541
|
+
children: displayText
|
2491
2542
|
}
|
2492
|
-
|
2493
|
-
|
2494
|
-
|
2495
|
-
|
2543
|
+
);
|
2544
|
+
}
|
2545
|
+
);
|
2546
|
+
const getDisplayName = ({
|
2547
|
+
firstname,
|
2548
|
+
lastname,
|
2549
|
+
username,
|
2550
|
+
email
|
2551
|
+
} = {}) => {
|
2552
|
+
if (username) {
|
2553
|
+
return username;
|
2554
|
+
}
|
2555
|
+
if (firstname) {
|
2556
|
+
return `${firstname} ${lastname ?? ""}`.trim();
|
2557
|
+
}
|
2558
|
+
return email ?? "";
|
2496
2559
|
};
|
2497
|
-
|
2498
|
-
const
|
2499
|
-
const
|
2500
|
-
|
2501
|
-
const [
|
2502
|
-
{
|
2503
|
-
query: { status }
|
2504
|
-
}
|
2505
|
-
] = useQueryParams({
|
2506
|
-
status: "draft"
|
2507
|
-
});
|
2508
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2509
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2510
|
-
const props = {
|
2511
|
-
activeTab: status,
|
2512
|
-
model,
|
2513
|
-
documentId: id,
|
2514
|
-
document: isCloning ? void 0 : document,
|
2515
|
-
meta: isCloning ? void 0 : meta,
|
2516
|
-
collectionType
|
2517
|
-
};
|
2518
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2519
|
-
DescriptionComponentRenderer,
|
2520
|
-
{
|
2521
|
-
props,
|
2522
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2523
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2524
|
-
}
|
2525
|
-
) });
|
2560
|
+
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2561
|
+
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2562
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
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) }) });
|
2526
2564
|
};
|
2527
|
-
const
|
2565
|
+
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2528
2566
|
const { formatMessage } = useIntl();
|
2529
|
-
|
2530
|
-
|
2531
|
-
|
2532
|
-
|
2533
|
-
|
2534
|
-
|
2535
|
-
|
2567
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2568
|
+
const title = isCreating ? formatMessage({
|
2569
|
+
id: "content-manager.containers.edit.title.new",
|
2570
|
+
defaultMessage: "Create an entry"
|
2571
|
+
}) : documentTitle;
|
2572
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2573
|
+
/* @__PURE__ */ jsx(BackButton, {}),
|
2574
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2575
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2576
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2577
|
+
] }),
|
2578
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2579
|
+
] });
|
2536
2580
|
};
|
2537
|
-
|
2538
|
-
const
|
2581
|
+
const HeaderToolbar = () => {
|
2582
|
+
const { formatMessage } = useIntl();
|
2539
2583
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2540
2584
|
const [
|
2541
2585
|
{
|
@@ -2543,355 +2587,432 @@ const ActionsPanelContent = () => {
|
|
2543
2587
|
}
|
2544
2588
|
] = useQueryParams();
|
2545
2589
|
const { model, id, document, meta, collectionType } = useDoc();
|
2546
|
-
const plugins = useStrapiApp("
|
2547
|
-
|
2548
|
-
activeTab: status,
|
2549
|
-
model,
|
2550
|
-
documentId: id,
|
2551
|
-
document: isCloning ? void 0 : document,
|
2552
|
-
meta: isCloning ? void 0 : meta,
|
2553
|
-
collectionType
|
2554
|
-
};
|
2555
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2590
|
+
const plugins = useStrapiApp("HeaderToolbar", (state) => state.plugins);
|
2591
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
2556
2592
|
/* @__PURE__ */ jsx(
|
2557
2593
|
DescriptionComponentRenderer,
|
2558
2594
|
{
|
2559
|
-
props
|
2560
|
-
|
2561
|
-
|
2595
|
+
props: {
|
2596
|
+
activeTab: status,
|
2597
|
+
model,
|
2598
|
+
documentId: id,
|
2599
|
+
document: isCloning ? void 0 : document,
|
2600
|
+
meta: isCloning ? void 0 : meta,
|
2601
|
+
collectionType
|
2602
|
+
},
|
2603
|
+
descriptions: plugins["content-manager"].apis.getHeaderActions(),
|
2604
|
+
children: (actions2) => {
|
2605
|
+
if (actions2.length > 0) {
|
2606
|
+
return /* @__PURE__ */ jsx(HeaderActions, { actions: actions2 });
|
2607
|
+
} else {
|
2608
|
+
return null;
|
2609
|
+
}
|
2610
|
+
}
|
2562
2611
|
}
|
2563
2612
|
),
|
2564
|
-
/* @__PURE__ */ jsx(
|
2613
|
+
/* @__PURE__ */ jsx(
|
2614
|
+
DescriptionComponentRenderer,
|
2615
|
+
{
|
2616
|
+
props: {
|
2617
|
+
activeTab: status,
|
2618
|
+
model,
|
2619
|
+
documentId: id,
|
2620
|
+
document: isCloning ? void 0 : document,
|
2621
|
+
meta: isCloning ? void 0 : meta,
|
2622
|
+
collectionType
|
2623
|
+
},
|
2624
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2625
|
+
children: (actions2) => {
|
2626
|
+
const headerActions = actions2.filter((action) => {
|
2627
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2628
|
+
return positions.includes("header");
|
2629
|
+
});
|
2630
|
+
return /* @__PURE__ */ jsx(
|
2631
|
+
DocumentActionsMenu,
|
2632
|
+
{
|
2633
|
+
actions: headerActions,
|
2634
|
+
label: formatMessage({
|
2635
|
+
id: "content-manager.containers.edit.header.more-actions",
|
2636
|
+
defaultMessage: "More actions"
|
2637
|
+
}),
|
2638
|
+
children: /* @__PURE__ */ jsx(Information, { activeTab: status })
|
2639
|
+
}
|
2640
|
+
);
|
2641
|
+
}
|
2642
|
+
}
|
2643
|
+
)
|
2565
2644
|
] });
|
2566
2645
|
};
|
2567
|
-
const
|
2568
|
-
|
2569
|
-
|
2646
|
+
const Information = ({ activeTab }) => {
|
2647
|
+
const { formatMessage } = useIntl();
|
2648
|
+
const { document, meta } = useDoc();
|
2649
|
+
if (!document || !document.id) {
|
2650
|
+
return null;
|
2651
|
+
}
|
2652
|
+
const createAndUpdateDocument = activeTab === "draft" ? document : meta?.availableStatus.find((status) => status.publishedAt === null);
|
2653
|
+
const publishDocument = activeTab === "published" ? document : meta?.availableStatus.find((status) => status.publishedAt !== null);
|
2654
|
+
const creator = createAndUpdateDocument?.[CREATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[CREATED_BY_ATTRIBUTE_NAME]) : null;
|
2655
|
+
const updator = createAndUpdateDocument?.[UPDATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[UPDATED_BY_ATTRIBUTE_NAME]) : null;
|
2656
|
+
const information = [
|
2570
2657
|
{
|
2571
|
-
|
2572
|
-
|
2573
|
-
|
2574
|
-
|
2575
|
-
borderColor: "neutral150",
|
2576
|
-
hasRadius: true,
|
2577
|
-
paddingBottom: 4,
|
2578
|
-
paddingLeft: 4,
|
2579
|
-
paddingRight: 4,
|
2580
|
-
paddingTop: 4,
|
2581
|
-
shadow: "tableShadow",
|
2582
|
-
gap: 3,
|
2583
|
-
direction: "column",
|
2584
|
-
justifyContent: "stretch",
|
2585
|
-
alignItems: "flex-start",
|
2586
|
-
children: [
|
2587
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2588
|
-
children
|
2589
|
-
]
|
2590
|
-
}
|
2591
|
-
);
|
2592
|
-
});
|
2593
|
-
const HOOKS = {
|
2594
|
-
/**
|
2595
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2596
|
-
* @constant
|
2597
|
-
* @type {string}
|
2598
|
-
*/
|
2599
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2600
|
-
/**
|
2601
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2602
|
-
* @constant
|
2603
|
-
* @type {string}
|
2604
|
-
*/
|
2605
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2606
|
-
/**
|
2607
|
-
* Hook that allows to mutate the CM's edit view layout
|
2608
|
-
* @constant
|
2609
|
-
* @type {string}
|
2610
|
-
*/
|
2611
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2612
|
-
/**
|
2613
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2614
|
-
* @constant
|
2615
|
-
* @type {string}
|
2616
|
-
*/
|
2617
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2618
|
-
};
|
2619
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2620
|
-
endpoints: (builder) => ({
|
2621
|
-
getContentTypeConfiguration: builder.query({
|
2622
|
-
query: (uid) => ({
|
2623
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2624
|
-
method: "GET"
|
2658
|
+
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2659
|
+
label: formatMessage({
|
2660
|
+
id: "content-manager.containers.edit.information.last-published.label",
|
2661
|
+
defaultMessage: "Published"
|
2625
2662
|
}),
|
2626
|
-
|
2627
|
-
|
2628
|
-
|
2629
|
-
|
2630
|
-
|
2631
|
-
|
2632
|
-
|
2633
|
-
|
2634
|
-
|
2635
|
-
|
2636
|
-
|
2637
|
-
|
2638
|
-
|
2639
|
-
|
2640
|
-
|
2641
|
-
|
2663
|
+
value: formatMessage(
|
2664
|
+
{
|
2665
|
+
id: "content-manager.containers.edit.information.last-published.value",
|
2666
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2667
|
+
},
|
2668
|
+
{
|
2669
|
+
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
2670
|
+
isAnonymous: !publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME],
|
2671
|
+
author: publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME] ? getDisplayName(publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME]) : null
|
2672
|
+
}
|
2673
|
+
)
|
2674
|
+
},
|
2675
|
+
{
|
2676
|
+
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2677
|
+
label: formatMessage({
|
2678
|
+
id: "content-manager.containers.edit.information.last-draft.label",
|
2679
|
+
defaultMessage: "Updated"
|
2680
|
+
}),
|
2681
|
+
value: formatMessage(
|
2682
|
+
{
|
2683
|
+
id: "content-manager.containers.edit.information.last-draft.value",
|
2684
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2685
|
+
},
|
2686
|
+
{
|
2687
|
+
time: /* @__PURE__ */ jsx(
|
2688
|
+
RelativeTime,
|
2689
|
+
{
|
2690
|
+
timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
|
2691
|
+
}
|
2692
|
+
),
|
2693
|
+
isAnonymous: !updator,
|
2694
|
+
author: updator
|
2695
|
+
}
|
2696
|
+
)
|
2697
|
+
},
|
2698
|
+
{
|
2699
|
+
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2700
|
+
label: formatMessage({
|
2701
|
+
id: "content-manager.containers.edit.information.document.label",
|
2702
|
+
defaultMessage: "Created"
|
2642
2703
|
}),
|
2643
|
-
|
2644
|
-
|
2645
|
-
|
2646
|
-
|
2647
|
-
|
2648
|
-
{
|
2649
|
-
|
2650
|
-
|
2651
|
-
|
2652
|
-
|
2653
|
-
|
2654
|
-
|
2655
|
-
|
2656
|
-
|
2657
|
-
}
|
2658
|
-
|
2659
|
-
|
2660
|
-
|
2661
|
-
|
2662
|
-
|
2663
|
-
|
2664
|
-
|
2665
|
-
|
2666
|
-
|
2667
|
-
|
2668
|
-
|
2669
|
-
|
2670
|
-
|
2671
|
-
|
2704
|
+
value: formatMessage(
|
2705
|
+
{
|
2706
|
+
id: "content-manager.containers.edit.information.document.value",
|
2707
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2708
|
+
},
|
2709
|
+
{
|
2710
|
+
time: /* @__PURE__ */ jsx(
|
2711
|
+
RelativeTime,
|
2712
|
+
{
|
2713
|
+
timestamp: new Date(createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME])
|
2714
|
+
}
|
2715
|
+
),
|
2716
|
+
isAnonymous: !creator,
|
2717
|
+
author: creator
|
2718
|
+
}
|
2719
|
+
)
|
2720
|
+
}
|
2721
|
+
].filter((info) => info.isDisplayed);
|
2722
|
+
return /* @__PURE__ */ jsx(
|
2723
|
+
Flex,
|
2724
|
+
{
|
2725
|
+
borderWidth: "1px 0 0 0",
|
2726
|
+
borderStyle: "solid",
|
2727
|
+
borderColor: "neutral150",
|
2728
|
+
direction: "column",
|
2729
|
+
marginTop: 2,
|
2730
|
+
tag: "dl",
|
2731
|
+
padding: 5,
|
2732
|
+
gap: 3,
|
2733
|
+
alignItems: "flex-start",
|
2734
|
+
marginLeft: "-0.4rem",
|
2735
|
+
marginRight: "-0.4rem",
|
2736
|
+
width: "calc(100% + 8px)",
|
2737
|
+
children: information.map((info) => /* @__PURE__ */ jsxs(Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
|
2738
|
+
/* @__PURE__ */ jsx(Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2739
|
+
/* @__PURE__ */ jsx(Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2740
|
+
] }, info.label))
|
2741
|
+
}
|
2672
2742
|
);
|
2673
|
-
return {
|
2674
|
-
name: mainFieldName,
|
2675
|
-
type: mainFieldType ?? "string"
|
2676
|
-
};
|
2677
|
-
};
|
2678
|
-
const DEFAULT_SETTINGS = {
|
2679
|
-
bulkable: false,
|
2680
|
-
filterable: false,
|
2681
|
-
searchable: false,
|
2682
|
-
pagination: false,
|
2683
|
-
defaultSortBy: "",
|
2684
|
-
defaultSortOrder: "asc",
|
2685
|
-
mainField: "id",
|
2686
|
-
pageSize: 10
|
2687
2743
|
};
|
2688
|
-
const
|
2689
|
-
const
|
2690
|
-
const
|
2691
|
-
|
2692
|
-
|
2693
|
-
|
2694
|
-
|
2695
|
-
|
2696
|
-
|
2697
|
-
|
2698
|
-
error,
|
2699
|
-
isFetching: isFetchingConfigs
|
2700
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2701
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2702
|
-
React.useEffect(() => {
|
2703
|
-
if (error) {
|
2704
|
-
toggleNotification({
|
2705
|
-
type: "danger",
|
2706
|
-
message: formatAPIError(error)
|
2707
|
-
});
|
2744
|
+
const HeaderActions = ({ actions: actions2 }) => {
|
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
|
+
}
|
2708
2754
|
}
|
2709
|
-
}, [error, formatAPIError, toggleNotification]);
|
2710
|
-
const editLayout = React.useMemo(
|
2711
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2712
|
-
layout: [],
|
2713
|
-
components: {},
|
2714
|
-
metadatas: {},
|
2715
|
-
options: {},
|
2716
|
-
settings: DEFAULT_SETTINGS
|
2717
|
-
},
|
2718
|
-
[data, isLoading, schemas, schema, components]
|
2719
|
-
);
|
2720
|
-
const listLayout = React.useMemo(() => {
|
2721
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2722
|
-
layout: [],
|
2723
|
-
metadatas: {},
|
2724
|
-
options: {},
|
2725
|
-
settings: DEFAULT_SETTINGS
|
2726
|
-
};
|
2727
|
-
}, [data, isLoading, schemas, schema, components]);
|
2728
|
-
const { layout: edit } = React.useMemo(
|
2729
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2730
|
-
layout: editLayout,
|
2731
|
-
query
|
2732
|
-
}),
|
2733
|
-
[editLayout, query, runHookWaterfall]
|
2734
|
-
);
|
2735
|
-
return {
|
2736
|
-
error,
|
2737
|
-
isLoading,
|
2738
|
-
edit,
|
2739
|
-
list: listLayout
|
2740
2755
|
};
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2744
|
-
return
|
2745
|
-
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
|
2754
|
-
|
2755
|
-
|
2756
|
-
|
2757
|
-
schemas
|
2758
|
-
).reduce((panels, row) => {
|
2759
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2760
|
-
panels.push([row]);
|
2761
|
-
currentPanelIndex += 2;
|
2756
|
+
const handleClose = () => {
|
2757
|
+
setDialogId(null);
|
2758
|
+
};
|
2759
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2760
|
+
if (action.options) {
|
2761
|
+
return /* @__PURE__ */ jsx(
|
2762
|
+
SingleSelect,
|
2763
|
+
{
|
2764
|
+
size: "S",
|
2765
|
+
onChange: action.onSelect,
|
2766
|
+
"aria-label": action.label,
|
2767
|
+
...action,
|
2768
|
+
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2769
|
+
},
|
2770
|
+
action.id
|
2771
|
+
);
|
2762
2772
|
} else {
|
2763
|
-
if (
|
2764
|
-
|
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);
|
2765
2794
|
}
|
2766
|
-
panels[currentPanelIndex].push(row);
|
2767
2795
|
}
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2785
|
-
}
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2796
|
+
}) });
|
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
|
+
};
|
2816
|
+
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2817
|
+
const navigate = useNavigate();
|
2818
|
+
const { formatMessage } = useIntl();
|
2819
|
+
return {
|
2820
|
+
label: formatMessage({
|
2821
|
+
id: "app.links.configure-view",
|
2822
|
+
defaultMessage: "Configure the view"
|
2823
|
+
}),
|
2824
|
+
icon: /* @__PURE__ */ jsx(ListPlus, {}),
|
2825
|
+
onClick: () => {
|
2826
|
+
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2794
2827
|
},
|
2795
|
-
|
2796
|
-
|
2828
|
+
position: "header"
|
2829
|
+
};
|
2830
|
+
};
|
2831
|
+
ConfigureTheViewAction.type = "configure-the-view";
|
2832
|
+
const EditTheModelAction = ({ model }) => {
|
2833
|
+
const navigate = useNavigate();
|
2834
|
+
const { formatMessage } = useIntl();
|
2797
2835
|
return {
|
2798
|
-
|
2799
|
-
|
2800
|
-
|
2801
|
-
|
2802
|
-
|
2803
|
-
|
2836
|
+
label: formatMessage({
|
2837
|
+
id: "content-manager.link-to-ctb",
|
2838
|
+
defaultMessage: "Edit the model"
|
2839
|
+
}),
|
2840
|
+
icon: /* @__PURE__ */ jsx(Pencil, {}),
|
2841
|
+
onClick: () => {
|
2842
|
+
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2804
2843
|
},
|
2805
|
-
|
2806
|
-
...schema?.options,
|
2807
|
-
...schema?.pluginOptions,
|
2808
|
-
...data.contentType.options
|
2809
|
-
}
|
2844
|
+
position: "header"
|
2810
2845
|
};
|
2811
2846
|
};
|
2812
|
-
|
2813
|
-
|
2814
|
-
|
2815
|
-
|
2816
|
-
|
2817
|
-
|
2847
|
+
EditTheModelAction.type = "edit-the-model";
|
2848
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2849
|
+
const navigate = useNavigate();
|
2850
|
+
const { formatMessage } = useIntl();
|
2851
|
+
const listViewPathMatch = useMatch(LIST_PATH);
|
2852
|
+
const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
|
2853
|
+
const { delete: deleteAction } = useDocumentActions();
|
2854
|
+
const { toggleNotification } = useNotification();
|
2855
|
+
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2856
|
+
const isLocalized = document?.locale != null;
|
2857
|
+
return {
|
2858
|
+
disabled: !canDelete || !document,
|
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
|
+
),
|
2866
|
+
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2867
|
+
dialog: {
|
2868
|
+
type: "dialog",
|
2869
|
+
title: formatMessage({
|
2870
|
+
id: "app.components.ConfirmDialog.title",
|
2871
|
+
defaultMessage: "Confirmation"
|
2872
|
+
}),
|
2873
|
+
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
2874
|
+
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2875
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2876
|
+
id: "content-manager.actions.delete.dialog.body",
|
2877
|
+
defaultMessage: "Are you sure?"
|
2878
|
+
}) })
|
2879
|
+
] }),
|
2880
|
+
onConfirm: async () => {
|
2881
|
+
if (!listViewPathMatch) {
|
2882
|
+
setSubmitting(true);
|
2883
|
+
}
|
2884
|
+
try {
|
2885
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2886
|
+
console.error(
|
2887
|
+
"You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2888
|
+
);
|
2889
|
+
toggleNotification({
|
2890
|
+
message: formatMessage({
|
2891
|
+
id: "content-manager.actions.delete.error",
|
2892
|
+
defaultMessage: "An error occurred while trying to delete the document."
|
2893
|
+
}),
|
2894
|
+
type: "danger"
|
2895
|
+
});
|
2896
|
+
return;
|
2897
|
+
}
|
2898
|
+
const res = await deleteAction({
|
2899
|
+
documentId,
|
2900
|
+
model,
|
2901
|
+
collectionType,
|
2902
|
+
params: {
|
2903
|
+
locale: "*"
|
2904
|
+
}
|
2905
|
+
});
|
2906
|
+
if (!("error" in res)) {
|
2907
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2908
|
+
}
|
2909
|
+
} finally {
|
2910
|
+
if (!listViewPathMatch) {
|
2911
|
+
setSubmitting(false);
|
2912
|
+
}
|
2913
|
+
}
|
2818
2914
|
}
|
2819
|
-
const { edit: metadata } = metadatas[field.name];
|
2820
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2821
|
-
return {
|
2822
|
-
attribute,
|
2823
|
-
disabled: !metadata.editable,
|
2824
|
-
hint: metadata.description,
|
2825
|
-
label: metadata.label ?? "",
|
2826
|
-
name: field.name,
|
2827
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2828
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2829
|
-
schemas,
|
2830
|
-
components: components?.schemas ?? {}
|
2831
|
-
}),
|
2832
|
-
placeholder: metadata.placeholder ?? "",
|
2833
|
-
required: attribute.required ?? false,
|
2834
|
-
size: field.size,
|
2835
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
2836
|
-
visible: metadata.visible ?? true,
|
2837
|
-
type: attribute.type
|
2838
|
-
};
|
2839
|
-
}).filter((field) => field !== null)
|
2840
|
-
);
|
2841
|
-
};
|
2842
|
-
const formatListLayout = (data, {
|
2843
|
-
schemas,
|
2844
|
-
schema,
|
2845
|
-
components
|
2846
|
-
}) => {
|
2847
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2848
|
-
(acc, [attribute, metadata]) => {
|
2849
|
-
return {
|
2850
|
-
...acc,
|
2851
|
-
[attribute]: metadata.list
|
2852
|
-
};
|
2853
2915
|
},
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2861
|
-
|
2862
|
-
|
2863
|
-
|
2864
|
-
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2868
|
-
|
2869
|
-
|
2870
|
-
|
2916
|
+
variant: "danger",
|
2917
|
+
position: ["header", "table-row"]
|
2918
|
+
};
|
2919
|
+
};
|
2920
|
+
DeleteAction$1.type = "delete";
|
2921
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2922
|
+
const Panels = () => {
|
2923
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2924
|
+
const [
|
2925
|
+
{
|
2926
|
+
query: { status }
|
2927
|
+
}
|
2928
|
+
] = useQueryParams({
|
2929
|
+
status: "draft"
|
2930
|
+
});
|
2931
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2932
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2933
|
+
const props = {
|
2934
|
+
activeTab: status,
|
2935
|
+
model,
|
2936
|
+
documentId: id,
|
2937
|
+
document: isCloning ? void 0 : document,
|
2938
|
+
meta: isCloning ? void 0 : meta,
|
2939
|
+
collectionType
|
2940
|
+
};
|
2941
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2942
|
+
DescriptionComponentRenderer,
|
2943
|
+
{
|
2944
|
+
props,
|
2945
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2946
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2871
2947
|
}
|
2948
|
+
) });
|
2949
|
+
};
|
2950
|
+
const ActionsPanel = () => {
|
2951
|
+
const { formatMessage } = useIntl();
|
2952
|
+
return {
|
2953
|
+
title: formatMessage({
|
2954
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2955
|
+
defaultMessage: "Entry"
|
2956
|
+
}),
|
2957
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2872
2958
|
};
|
2873
2959
|
};
|
2874
|
-
|
2875
|
-
|
2876
|
-
|
2877
|
-
|
2878
|
-
|
2960
|
+
ActionsPanel.type = "actions";
|
2961
|
+
const ActionsPanelContent = () => {
|
2962
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2963
|
+
const [
|
2964
|
+
{
|
2965
|
+
query: { status = "draft" }
|
2879
2966
|
}
|
2880
|
-
|
2881
|
-
|
2882
|
-
|
2883
|
-
|
2884
|
-
|
2885
|
-
|
2886
|
-
|
2887
|
-
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2967
|
+
] = useQueryParams();
|
2968
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2969
|
+
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2970
|
+
const props = {
|
2971
|
+
activeTab: status,
|
2972
|
+
model,
|
2973
|
+
documentId: id,
|
2974
|
+
document: isCloning ? void 0 : document,
|
2975
|
+
meta: isCloning ? void 0 : meta,
|
2976
|
+
collectionType
|
2977
|
+
};
|
2978
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2979
|
+
/* @__PURE__ */ jsx(
|
2980
|
+
DescriptionComponentRenderer,
|
2981
|
+
{
|
2982
|
+
props,
|
2983
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2984
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2985
|
+
}
|
2986
|
+
),
|
2987
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2988
|
+
] });
|
2894
2989
|
};
|
2990
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2991
|
+
return /* @__PURE__ */ jsxs(
|
2992
|
+
Flex,
|
2993
|
+
{
|
2994
|
+
ref,
|
2995
|
+
tag: "aside",
|
2996
|
+
"aria-labelledby": "additional-information",
|
2997
|
+
background: "neutral0",
|
2998
|
+
borderColor: "neutral150",
|
2999
|
+
hasRadius: true,
|
3000
|
+
paddingBottom: 4,
|
3001
|
+
paddingLeft: 4,
|
3002
|
+
paddingRight: 4,
|
3003
|
+
paddingTop: 4,
|
3004
|
+
shadow: "tableShadow",
|
3005
|
+
gap: 3,
|
3006
|
+
direction: "column",
|
3007
|
+
justifyContent: "stretch",
|
3008
|
+
alignItems: "flex-start",
|
3009
|
+
children: [
|
3010
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
3011
|
+
children
|
3012
|
+
]
|
3013
|
+
}
|
3014
|
+
);
|
3015
|
+
});
|
2895
3016
|
const ConfirmBulkActionDialog = ({
|
2896
3017
|
onToggleDialog,
|
2897
3018
|
isOpen = false,
|
@@ -2930,6 +3051,7 @@ const ConfirmDialogPublishAll = ({
|
|
2930
3051
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2931
3052
|
const { model, schema } = useDoc();
|
2932
3053
|
const [{ query }] = useQueryParams();
|
3054
|
+
const enableDraftRelationsCount = false;
|
2933
3055
|
const {
|
2934
3056
|
data: countDraftRelations = 0,
|
2935
3057
|
isLoading,
|
@@ -2941,7 +3063,7 @@ const ConfirmDialogPublishAll = ({
|
|
2941
3063
|
locale: query?.plugins?.i18n?.locale
|
2942
3064
|
},
|
2943
3065
|
{
|
2944
|
-
skip:
|
3066
|
+
skip: !enableDraftRelationsCount
|
2945
3067
|
}
|
2946
3068
|
);
|
2947
3069
|
React.useEffect(() => {
|
@@ -3126,7 +3248,7 @@ const SelectedEntriesTableContent = ({
|
|
3126
3248
|
status: row.status
|
3127
3249
|
}
|
3128
3250
|
) }),
|
3129
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3251
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3130
3252
|
IconButton,
|
3131
3253
|
{
|
3132
3254
|
tag: Link,
|
@@ -3149,9 +3271,10 @@ const SelectedEntriesTableContent = ({
|
|
3149
3271
|
),
|
3150
3272
|
target: "_blank",
|
3151
3273
|
marginLeft: "auto",
|
3152
|
-
|
3274
|
+
variant: "ghost",
|
3275
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3153
3276
|
}
|
3154
|
-
) })
|
3277
|
+
) }) })
|
3155
3278
|
] }, row.id)) })
|
3156
3279
|
] });
|
3157
3280
|
};
|
@@ -3188,7 +3311,13 @@ const SelectedEntriesModalContent = ({
|
|
3188
3311
|
);
|
3189
3312
|
const { rows, validationErrors } = React.useMemo(() => {
|
3190
3313
|
if (data.length > 0 && schema) {
|
3191
|
-
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
|
+
);
|
3192
3321
|
const validationErrors2 = {};
|
3193
3322
|
const rows2 = data.map((entry) => {
|
3194
3323
|
try {
|
@@ -3538,7 +3667,7 @@ const TableActions = ({ document }) => {
|
|
3538
3667
|
DescriptionComponentRenderer,
|
3539
3668
|
{
|
3540
3669
|
props,
|
3541
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3670
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3542
3671
|
children: (actions2) => {
|
3543
3672
|
const tableRowActions = actions2.filter((action) => {
|
3544
3673
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3649,7 +3778,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3649
3778
|
}),
|
3650
3779
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3651
3780
|
footer: ({ onClose }) => {
|
3652
|
-
return /* @__PURE__ */ jsxs(
|
3781
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3653
3782
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3654
3783
|
id: "cancel",
|
3655
3784
|
defaultMessage: "Cancel"
|
@@ -3880,7 +4009,7 @@ const index = {
|
|
3880
4009
|
app.router.addRoute({
|
3881
4010
|
path: "content-manager/*",
|
3882
4011
|
lazy: async () => {
|
3883
|
-
const { Layout } = await import("./layout-
|
4012
|
+
const { Layout } = await import("./layout-2CfjL0T9.mjs");
|
3884
4013
|
return {
|
3885
4014
|
Component: Layout
|
3886
4015
|
};
|
@@ -3897,7 +4026,7 @@ const index = {
|
|
3897
4026
|
async registerTrads({ locales }) {
|
3898
4027
|
const importedTrads = await Promise.all(
|
3899
4028
|
locales.map((locale) => {
|
3900
|
-
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 }) => {
|
3901
4030
|
return {
|
3902
4031
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3903
4032
|
locale
|
@@ -3918,13 +4047,15 @@ export {
|
|
3918
4047
|
BulkActionsRenderer as B,
|
3919
4048
|
COLLECTION_TYPES as C,
|
3920
4049
|
DocumentStatus as D,
|
3921
|
-
|
3922
|
-
|
3923
|
-
|
4050
|
+
extractContentTypeComponents as E,
|
4051
|
+
DEFAULT_SETTINGS as F,
|
4052
|
+
convertEditLayoutToFieldLayouts as G,
|
3924
4053
|
HOOKS as H,
|
3925
4054
|
InjectionZone as I,
|
3926
|
-
|
3927
|
-
|
4055
|
+
useDocument as J,
|
4056
|
+
index as K,
|
4057
|
+
useContentManagerContext as L,
|
4058
|
+
useDocumentActions as M,
|
3928
4059
|
Panels as P,
|
3929
4060
|
RelativeTime as R,
|
3930
4061
|
SINGLE_TYPES as S,
|
@@ -3942,18 +4073,18 @@ export {
|
|
3942
4073
|
PERMISSIONS as k,
|
3943
4074
|
DocumentRBAC as l,
|
3944
4075
|
DOCUMENT_META_FIELDS as m,
|
3945
|
-
|
3946
|
-
|
3947
|
-
|
3948
|
-
|
3949
|
-
|
4076
|
+
CLONE_PATH as n,
|
4077
|
+
useDocLayout as o,
|
4078
|
+
useGetContentTypeConfigurationQuery as p,
|
4079
|
+
CREATOR_FIELDS as q,
|
4080
|
+
getMainField as r,
|
3950
4081
|
setInitialData as s,
|
3951
|
-
|
4082
|
+
getDisplayName as t,
|
3952
4083
|
useContentTypeSchema as u,
|
3953
|
-
|
3954
|
-
|
3955
|
-
|
3956
|
-
|
3957
|
-
|
4084
|
+
checkIfAttributeIsDisplayable as v,
|
4085
|
+
useGetAllDocumentsQuery as w,
|
4086
|
+
convertListLayoutToFieldLayouts as x,
|
4087
|
+
capitalise as y,
|
4088
|
+
useUpdateContentTypeConfigurationMutation as z
|
3958
4089
|
};
|
3959
|
-
//# sourceMappingURL=index-
|
4090
|
+
//# sourceMappingURL=index-wnqzm4Q8.mjs.map
|