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