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