@strapi/content-manager 0.0.0-experimental.da85533897155e719d784f0271223c866d2f69ab → 0.0.0-experimental.dad3c50630ca4fd9eccdcbe549ee632fc572e23d
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/CardDragPreview-C0QyJgRA.js.map +1 -1
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DyDkPajU.js → ComponentConfigurationPage-BLWQy8ru.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-DyDkPajU.js.map → ComponentConfigurationPage-BLWQy8ru.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-9lRmRdIr.mjs → ComponentConfigurationPage-CtIa3aa2.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-9lRmRdIr.mjs.map → ComponentConfigurationPage-CtIa3aa2.mjs.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
- package/dist/_chunks/{EditConfigurationPage-Bk893vVY.mjs → EditConfigurationPage-DsPR2DVk.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-Bk893vVY.mjs.map → EditConfigurationPage-DsPR2DVk.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DValmA0m.js → EditConfigurationPage-RQkymxCy.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-DValmA0m.js.map → EditConfigurationPage-RQkymxCy.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-Dk7Eaft4.js → EditViewPage-B-kExt8C.js} +50 -11
- package/dist/_chunks/EditViewPage-B-kExt8C.js.map +1 -0
- package/dist/_chunks/{EditViewPage-DiNFdFqP.mjs → EditViewPage-BPyVuPfM.mjs} +50 -10
- package/dist/_chunks/EditViewPage-BPyVuPfM.mjs.map +1 -0
- package/dist/_chunks/{Field-DH2OaqUP.js → Field-DPIsQRre.js} +250 -161
- package/dist/_chunks/Field-DPIsQRre.js.map +1 -0
- package/dist/_chunks/{Field-Dv_HTFTa.mjs → Field-Dltnt1km.mjs} +244 -155
- package/dist/_chunks/Field-Dltnt1km.mjs.map +1 -0
- package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
- package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
- package/dist/_chunks/{Form-B_dUDizM.js → Form-BFi4MXMT.js} +19 -12
- package/dist/_chunks/Form-BFi4MXMT.js.map +1 -0
- package/dist/_chunks/{Form-Dy6P4HgH.mjs → Form-C1IcWm1u.mjs} +17 -9
- package/dist/_chunks/Form-C1IcWm1u.mjs.map +1 -0
- package/dist/_chunks/{History-DrwsD1Vc.mjs → History-04ChQ4pl.mjs} +71 -104
- package/dist/_chunks/History-04ChQ4pl.mjs.map +1 -0
- package/dist/_chunks/{History-BT4w83Oa.js → History-wjcK4L0C.js} +70 -104
- package/dist/_chunks/History-wjcK4L0C.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-BxIP0jRy.mjs → ListConfigurationPage-BYqPYLSU.mjs} +7 -6
- package/dist/_chunks/ListConfigurationPage-BYqPYLSU.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-CuYrMcW3.js → ListConfigurationPage-CRbxIC3J.js} +7 -7
- package/dist/_chunks/ListConfigurationPage-CRbxIC3J.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BvpwNur7.js → ListViewPage-D5NY9183.js} +88 -54
- package/dist/_chunks/ListViewPage-D5NY9183.js.map +1 -0
- package/dist/_chunks/{ListViewPage-5a1vw-OK.mjs → ListViewPage-FU2LBuhl.mjs} +83 -48
- package/dist/_chunks/ListViewPage-FU2LBuhl.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-UqEiWKkM.js → NoContentTypePage-BgQVE_Qb.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-UqEiWKkM.js.map → NoContentTypePage-BgQVE_Qb.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-Bm6tRcd3.mjs → NoContentTypePage-DCKUkwb8.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-Bm6tRcd3.mjs.map → NoContentTypePage-DCKUkwb8.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-C_vGRo8Q.js → NoPermissionsPage-C5jwn70o.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-C_vGRo8Q.js.map → NoPermissionsPage-C5jwn70o.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BHPqn_tQ.mjs → NoPermissionsPage-jqve7C8l.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BHPqn_tQ.mjs.map → NoPermissionsPage-jqve7C8l.mjs.map} +1 -1
- package/dist/_chunks/Preview-BMYN548c.mjs +294 -0
- package/dist/_chunks/Preview-BMYN548c.mjs.map +1 -0
- package/dist/_chunks/Preview-DaOihysv.js +312 -0
- package/dist/_chunks/Preview-DaOihysv.js.map +1 -0
- package/dist/_chunks/{Relations-CznVF6LS.js → Relations-CTGM7Hv5.js} +75 -42
- package/dist/_chunks/Relations-CTGM7Hv5.js.map +1 -0
- package/dist/_chunks/{Relations-C7fPyh5P.mjs → Relations-gscPkxjF.mjs} +75 -41
- package/dist/_chunks/Relations-gscPkxjF.mjs.map +1 -0
- package/dist/_chunks/{en-otD_UBJi.js → en-BzQmavmK.js} +32 -14
- package/dist/_chunks/{en-otD_UBJi.js.map → en-BzQmavmK.js.map} +1 -1
- package/dist/_chunks/{en-CbaIuYoB.mjs → en-CSxLmrh1.mjs} +32 -14
- package/dist/_chunks/{en-CbaIuYoB.mjs.map → en-CSxLmrh1.mjs.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
- package/dist/_chunks/{index-D9UmmBcM.js → index-Ca7YWlAA.js} +1063 -754
- package/dist/_chunks/index-Ca7YWlAA.js.map +1 -0
- package/dist/_chunks/{index-BJ6uTqLL.mjs → index-DqasUQ6Q.mjs} +1066 -757
- package/dist/_chunks/index-DqasUQ6Q.mjs.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout-kfu5Wtix.js → layout-BW80JSCd.js} +7 -7
- package/dist/_chunks/{layout-kfu5Wtix.js.map → layout-BW80JSCd.js.map} +1 -1
- package/dist/_chunks/{layout-uomiIGbG.mjs → layout-W3clJSCy.mjs} +6 -5
- package/dist/_chunks/{layout-uomiIGbG.mjs.map → layout-W3clJSCy.mjs.map} +1 -1
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-DiDufGSA.mjs → relations-BlDkoeWh.mjs} +6 -7
- package/dist/_chunks/relations-BlDkoeWh.mjs.map +1 -0
- package/dist/_chunks/{relations-DKENrxko.js → relations-C9Usz9k5.js} +6 -7
- package/dist/_chunks/relations-C9Usz9k5.js.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
- package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
- package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
- package/dist/admin/index.js +3 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +5 -3
- package/dist/admin/src/content-manager.d.ts +3 -2
- package/dist/admin/src/exports.d.ts +2 -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/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +3 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +4 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +4 -1
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/router.d.ts +1 -1
- 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 -20
- 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 +594 -335
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +595 -335
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +16 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/history/controllers/history-version.d.ts +1 -1
- package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts +3 -3
- 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 +6 -11
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +7 -6
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +16 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +32 -0
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +12 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +19 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +12 -10
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +7 -6
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +17 -15
- package/dist/_chunks/EditViewPage-DiNFdFqP.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-Dk7Eaft4.js.map +0 -1
- package/dist/_chunks/Field-DH2OaqUP.js.map +0 -1
- package/dist/_chunks/Field-Dv_HTFTa.mjs.map +0 -1
- package/dist/_chunks/Form-B_dUDizM.js.map +0 -1
- package/dist/_chunks/Form-Dy6P4HgH.mjs.map +0 -1
- package/dist/_chunks/History-BT4w83Oa.js.map +0 -1
- package/dist/_chunks/History-DrwsD1Vc.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-BxIP0jRy.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-CuYrMcW3.js.map +0 -1
- package/dist/_chunks/ListViewPage-5a1vw-OK.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-BvpwNur7.js.map +0 -1
- package/dist/_chunks/Relations-C7fPyh5P.mjs.map +0 -1
- package/dist/_chunks/Relations-CznVF6LS.js.map +0 -1
- package/dist/_chunks/index-BJ6uTqLL.mjs.map +0 -1
- package/dist/_chunks/index-D9UmmBcM.js.map +0 -1
- package/dist/_chunks/relations-DKENrxko.js.map +0 -1
- package/dist/_chunks/relations-DiDufGSA.mjs.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,25 +1,33 @@
|
|
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 { Menu, Button, VisuallyHidden, Flex, Dialog, Modal, Typography, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
|
7
|
+
import mapValues from "lodash/fp/mapValues";
|
7
8
|
import { useIntl } from "react-intl";
|
8
9
|
import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
9
10
|
import { styled } from "styled-components";
|
10
11
|
import * as yup from "yup";
|
11
12
|
import { ValidationError } from "yup";
|
13
|
+
import { stringify } from "qs";
|
12
14
|
import pipe from "lodash/fp/pipe";
|
13
15
|
import { intervalToDuration, isPast } from "date-fns";
|
14
|
-
import { stringify } from "qs";
|
15
16
|
import { createSlice, combineReducers } from "@reduxjs/toolkit";
|
16
|
-
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
17
|
+
const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
|
17
18
|
const v = glob[path];
|
18
19
|
if (v) {
|
19
20
|
return typeof v === "function" ? v() : Promise.resolve(v);
|
20
21
|
}
|
21
22
|
return new Promise((_, reject) => {
|
22
|
-
(typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
|
23
|
+
(typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
|
24
|
+
reject.bind(
|
25
|
+
null,
|
26
|
+
new Error(
|
27
|
+
"Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
|
28
|
+
)
|
29
|
+
)
|
30
|
+
);
|
23
31
|
});
|
24
32
|
};
|
25
33
|
const PLUGIN_ID = "content-manager";
|
@@ -100,6 +108,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
100
108
|
if (!slug) {
|
101
109
|
throw new Error("Cannot find the slug param in the URL");
|
102
110
|
}
|
111
|
+
const [{ rawQuery }] = useQueryParams();
|
103
112
|
const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
|
104
113
|
const contentTypePermissions = React.useMemo(() => {
|
105
114
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -110,7 +119,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
110
119
|
return { ...acc, [action]: [permission] };
|
111
120
|
}, {});
|
112
121
|
}, [slug, userPermissions]);
|
113
|
-
const { isLoading, allowedActions } = useRBAC(
|
122
|
+
const { isLoading, allowedActions } = useRBAC(
|
123
|
+
contentTypePermissions,
|
124
|
+
permissions ?? void 0,
|
125
|
+
// TODO: useRBAC context should be typed and built differently
|
126
|
+
// We are passing raw query as context to the hook so that it can
|
127
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
128
|
+
rawQuery
|
129
|
+
);
|
114
130
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
115
131
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
116
132
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -159,7 +175,8 @@ const contentManagerApi = adminApi.enhanceEndpoints({
|
|
159
175
|
"InitialData",
|
160
176
|
"HistoryVersion",
|
161
177
|
"Relations",
|
162
|
-
"UidAvailability"
|
178
|
+
"UidAvailability",
|
179
|
+
"RecentDocumentList"
|
163
180
|
]
|
164
181
|
});
|
165
182
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -177,7 +194,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
177
194
|
if (error) {
|
178
195
|
return [];
|
179
196
|
}
|
180
|
-
return [{ type: "Document", id: `${model}_LIST` }];
|
197
|
+
return [{ type: "Document", id: `${model}_LIST` }, "RecentDocumentList"];
|
181
198
|
}
|
182
199
|
}),
|
183
200
|
cloneDocument: builder.mutation({
|
@@ -191,7 +208,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
191
208
|
}),
|
192
209
|
invalidatesTags: (_result, _error, { model }) => [
|
193
210
|
{ type: "Document", id: `${model}_LIST` },
|
194
|
-
{ type: "UidAvailability", id: model }
|
211
|
+
{ type: "UidAvailability", id: model },
|
212
|
+
"RecentDocumentList"
|
195
213
|
]
|
196
214
|
}),
|
197
215
|
/**
|
@@ -210,8 +228,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
210
228
|
invalidatesTags: (result, _error, { model }) => [
|
211
229
|
{ type: "Document", id: `${model}_LIST` },
|
212
230
|
"Relations",
|
213
|
-
{ type: "UidAvailability", id: model }
|
214
|
-
|
231
|
+
{ type: "UidAvailability", id: model },
|
232
|
+
"RecentDocumentList"
|
233
|
+
],
|
234
|
+
transformResponse: (response, meta, arg) => {
|
235
|
+
if (!("data" in response) && arg.model === "plugin::users-permissions.user") {
|
236
|
+
return {
|
237
|
+
data: response,
|
238
|
+
meta: {
|
239
|
+
availableStatus: [],
|
240
|
+
availableLocales: []
|
241
|
+
}
|
242
|
+
};
|
243
|
+
}
|
244
|
+
return response;
|
245
|
+
}
|
215
246
|
}),
|
216
247
|
deleteDocument: builder.mutation({
|
217
248
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -222,7 +253,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
222
253
|
}
|
223
254
|
}),
|
224
255
|
invalidatesTags: (_result, _error, { collectionType, model }) => [
|
225
|
-
{ type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model }
|
256
|
+
{ type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model },
|
257
|
+
"RecentDocumentList"
|
226
258
|
]
|
227
259
|
}),
|
228
260
|
deleteManyDocuments: builder.mutation({
|
@@ -234,7 +266,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
234
266
|
params
|
235
267
|
}
|
236
268
|
}),
|
237
|
-
invalidatesTags: (_res, _error, { model }) => [
|
269
|
+
invalidatesTags: (_res, _error, { model }) => [
|
270
|
+
{ type: "Document", id: `${model}_LIST` },
|
271
|
+
"RecentDocumentList"
|
272
|
+
]
|
238
273
|
}),
|
239
274
|
discardDocument: builder.mutation({
|
240
275
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -252,7 +287,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
252
287
|
},
|
253
288
|
{ type: "Document", id: `${model}_LIST` },
|
254
289
|
"Relations",
|
255
|
-
{ type: "UidAvailability", id: model }
|
290
|
+
{ type: "UidAvailability", id: model },
|
291
|
+
"RecentDocumentList"
|
256
292
|
];
|
257
293
|
}
|
258
294
|
}),
|
@@ -265,7 +301,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
265
301
|
url: `/content-manager/collection-types/${model}`,
|
266
302
|
method: "GET",
|
267
303
|
config: {
|
268
|
-
params
|
304
|
+
params: stringify(params, { encode: true })
|
269
305
|
}
|
270
306
|
}),
|
271
307
|
providesTags: (result, _error, arg) => {
|
@@ -347,7 +383,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
347
383
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
348
384
|
},
|
349
385
|
{ type: "Document", id: `${model}_LIST` },
|
350
|
-
"Relations"
|
386
|
+
"Relations",
|
387
|
+
"RecentDocumentList"
|
351
388
|
];
|
352
389
|
}
|
353
390
|
}),
|
@@ -378,7 +415,9 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
378
415
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
379
416
|
},
|
380
417
|
"Relations",
|
381
|
-
{ type: "UidAvailability", id: model }
|
418
|
+
{ type: "UidAvailability", id: model },
|
419
|
+
"RecentDocumentList",
|
420
|
+
"RecentDocumentList"
|
382
421
|
];
|
383
422
|
},
|
384
423
|
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
@@ -408,7 +447,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
408
447
|
{
|
409
448
|
type: "Document",
|
410
449
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
411
|
-
}
|
450
|
+
},
|
451
|
+
"RecentDocumentList"
|
412
452
|
];
|
413
453
|
}
|
414
454
|
}),
|
@@ -421,7 +461,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
421
461
|
params
|
422
462
|
}
|
423
463
|
}),
|
424
|
-
invalidatesTags: (_res, _error, { model, documentIds }) =>
|
464
|
+
invalidatesTags: (_res, _error, { model, documentIds }) => [
|
465
|
+
...documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` })),
|
466
|
+
"RecentDocumentList"
|
467
|
+
]
|
425
468
|
})
|
426
469
|
})
|
427
470
|
});
|
@@ -444,8 +487,7 @@ const {
|
|
444
487
|
useUnpublishManyDocumentsMutation
|
445
488
|
} = documentApi;
|
446
489
|
const buildValidParams = (query) => {
|
447
|
-
if (!query)
|
448
|
-
return query;
|
490
|
+
if (!query) return query;
|
449
491
|
const { plugins: _, ...validQueryParams } = {
|
450
492
|
...query,
|
451
493
|
...Object.values(query?.plugins ?? {}).reduce(
|
@@ -453,14 +495,29 @@ const buildValidParams = (query) => {
|
|
453
495
|
{}
|
454
496
|
)
|
455
497
|
};
|
456
|
-
if ("_q" in validQueryParams) {
|
457
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
458
|
-
}
|
459
498
|
return validQueryParams;
|
460
499
|
};
|
461
500
|
const isBaseQueryError = (error) => {
|
462
501
|
return error.name !== void 0;
|
463
502
|
};
|
503
|
+
const arrayValidator = (attribute, options) => ({
|
504
|
+
message: translatedErrors.required,
|
505
|
+
test(value) {
|
506
|
+
if (options.status === "draft") {
|
507
|
+
return true;
|
508
|
+
}
|
509
|
+
if (!attribute.required) {
|
510
|
+
return true;
|
511
|
+
}
|
512
|
+
if (!value) {
|
513
|
+
return false;
|
514
|
+
}
|
515
|
+
if (Array.isArray(value) && value.length === 0) {
|
516
|
+
return false;
|
517
|
+
}
|
518
|
+
return true;
|
519
|
+
}
|
520
|
+
});
|
464
521
|
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
465
522
|
const createModelSchema = (attributes2) => yup.object().shape(
|
466
523
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
@@ -468,6 +525,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
468
525
|
return acc;
|
469
526
|
}
|
470
527
|
const validations = [
|
528
|
+
addNullableValidation,
|
471
529
|
addRequiredValidation,
|
472
530
|
addMinLengthValidation,
|
473
531
|
addMaxLengthValidation,
|
@@ -484,12 +542,12 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
484
542
|
...acc,
|
485
543
|
[name]: transformSchema(
|
486
544
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
487
|
-
)
|
545
|
+
).test(arrayValidator(attribute, options))
|
488
546
|
};
|
489
547
|
} else {
|
490
548
|
return {
|
491
549
|
...acc,
|
492
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
550
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
493
551
|
};
|
494
552
|
}
|
495
553
|
}
|
@@ -511,7 +569,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
511
569
|
}
|
512
570
|
)
|
513
571
|
)
|
514
|
-
)
|
572
|
+
).test(arrayValidator(attribute, options))
|
515
573
|
};
|
516
574
|
case "relation":
|
517
575
|
return {
|
@@ -523,7 +581,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
523
581
|
} else if (Array.isArray(value)) {
|
524
582
|
return yup.array().of(
|
525
583
|
yup.object().shape({
|
526
|
-
id: yup.
|
584
|
+
id: yup.number().required()
|
527
585
|
})
|
528
586
|
);
|
529
587
|
} else if (typeof value === "object") {
|
@@ -609,17 +667,17 @@ const nullableSchema = (schema) => {
|
|
609
667
|
schema
|
610
668
|
);
|
611
669
|
};
|
670
|
+
const addNullableValidation = () => (schema) => {
|
671
|
+
return nullableSchema(schema);
|
672
|
+
};
|
612
673
|
const addRequiredValidation = (attribute, options) => (schema) => {
|
613
|
-
if (options.status === "draft") {
|
614
|
-
return
|
615
|
-
}
|
616
|
-
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
617
|
-
return schema.min(1, translatedErrors.required);
|
674
|
+
if (options.status === "draft" || !attribute.required) {
|
675
|
+
return schema;
|
618
676
|
}
|
619
|
-
if (attribute.required &&
|
677
|
+
if (attribute.required && "required" in schema) {
|
620
678
|
return schema.required(translatedErrors.required);
|
621
679
|
}
|
622
|
-
return
|
680
|
+
return schema;
|
623
681
|
};
|
624
682
|
const addMinLengthValidation = (attribute, options) => (schema) => {
|
625
683
|
if (options.status === "draft") {
|
@@ -647,31 +705,12 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
647
705
|
return schema;
|
648
706
|
};
|
649
707
|
const addMinValidation = (attribute, options) => (schema) => {
|
650
|
-
if ("
|
708
|
+
if (options.status === "draft") {
|
709
|
+
return schema;
|
710
|
+
}
|
711
|
+
if ("min" in attribute && "min" in schema) {
|
651
712
|
const min = toInteger(attribute.min);
|
652
|
-
if (
|
653
|
-
if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
|
654
|
-
return schema.test(
|
655
|
-
"custom-min",
|
656
|
-
{
|
657
|
-
...translatedErrors.min,
|
658
|
-
values: {
|
659
|
-
min: attribute.min
|
660
|
-
}
|
661
|
-
},
|
662
|
-
(value) => {
|
663
|
-
if (!value) {
|
664
|
-
return true;
|
665
|
-
}
|
666
|
-
if (Array.isArray(value) && value.length === 0) {
|
667
|
-
return true;
|
668
|
-
}
|
669
|
-
return value.length >= min;
|
670
|
-
}
|
671
|
-
);
|
672
|
-
}
|
673
|
-
}
|
674
|
-
if ("min" in schema && min) {
|
713
|
+
if (min) {
|
675
714
|
return schema.min(min, {
|
676
715
|
...translatedErrors.min,
|
677
716
|
values: {
|
@@ -789,19 +828,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
789
828
|
}, {});
|
790
829
|
return componentsByKey;
|
791
830
|
};
|
792
|
-
const
|
831
|
+
const HOOKS = {
|
832
|
+
/**
|
833
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
834
|
+
* @constant
|
835
|
+
* @type {string}
|
836
|
+
*/
|
837
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
838
|
+
/**
|
839
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
840
|
+
* @constant
|
841
|
+
* @type {string}
|
842
|
+
*/
|
843
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
844
|
+
/**
|
845
|
+
* Hook that allows to mutate the CM's edit view layout
|
846
|
+
* @constant
|
847
|
+
* @type {string}
|
848
|
+
*/
|
849
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
850
|
+
/**
|
851
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
852
|
+
* @constant
|
853
|
+
* @type {string}
|
854
|
+
*/
|
855
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
856
|
+
};
|
857
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
858
|
+
endpoints: (builder) => ({
|
859
|
+
getContentTypeConfiguration: builder.query({
|
860
|
+
query: (uid) => ({
|
861
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
862
|
+
method: "GET"
|
863
|
+
}),
|
864
|
+
transformResponse: (response) => response.data,
|
865
|
+
providesTags: (_result, _error, uid) => [
|
866
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
867
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
868
|
+
]
|
869
|
+
}),
|
870
|
+
getAllContentTypeSettings: builder.query({
|
871
|
+
query: () => "/content-manager/content-types-settings",
|
872
|
+
transformResponse: (response) => response.data,
|
873
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
874
|
+
}),
|
875
|
+
updateContentTypeConfiguration: builder.mutation({
|
876
|
+
query: ({ uid, ...body }) => ({
|
877
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
878
|
+
method: "PUT",
|
879
|
+
data: body
|
880
|
+
}),
|
881
|
+
transformResponse: (response) => response.data,
|
882
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
883
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
884
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
885
|
+
// Is this necessary?
|
886
|
+
{ type: "InitialData" }
|
887
|
+
]
|
888
|
+
})
|
889
|
+
})
|
890
|
+
});
|
891
|
+
const {
|
892
|
+
useGetContentTypeConfigurationQuery,
|
893
|
+
useGetAllContentTypeSettingsQuery,
|
894
|
+
useUpdateContentTypeConfigurationMutation
|
895
|
+
} = contentTypesApi;
|
896
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
897
|
+
const { type } = attribute;
|
898
|
+
if (type === "relation") {
|
899
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
900
|
+
}
|
901
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
902
|
+
};
|
903
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
904
|
+
if (!mainFieldName) {
|
905
|
+
return void 0;
|
906
|
+
}
|
907
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
908
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
909
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
910
|
+
);
|
911
|
+
return {
|
912
|
+
name: mainFieldName,
|
913
|
+
type: mainFieldType ?? "string"
|
914
|
+
};
|
915
|
+
};
|
916
|
+
const DEFAULT_SETTINGS = {
|
917
|
+
bulkable: false,
|
918
|
+
filterable: false,
|
919
|
+
searchable: false,
|
920
|
+
pagination: false,
|
921
|
+
defaultSortBy: "",
|
922
|
+
defaultSortOrder: "asc",
|
923
|
+
mainField: "id",
|
924
|
+
pageSize: 10
|
925
|
+
};
|
926
|
+
const useDocumentLayout = (model) => {
|
927
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
928
|
+
const [{ query }] = useQueryParams();
|
929
|
+
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
793
930
|
const { toggleNotification } = useNotification();
|
794
931
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
932
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
795
933
|
const {
|
796
|
-
|
797
|
-
isLoading:
|
798
|
-
|
799
|
-
|
800
|
-
} =
|
801
|
-
|
802
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
803
|
-
});
|
804
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
934
|
+
data,
|
935
|
+
isLoading: isLoadingConfigs,
|
936
|
+
error,
|
937
|
+
isFetching: isFetchingConfigs
|
938
|
+
} = useGetContentTypeConfigurationQuery(model);
|
939
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
805
940
|
React.useEffect(() => {
|
806
941
|
if (error) {
|
807
942
|
toggleNotification({
|
@@ -809,84 +944,339 @@ const useDocument = (args, opts) => {
|
|
809
944
|
message: formatAPIError(error)
|
810
945
|
});
|
811
946
|
}
|
812
|
-
}, [
|
813
|
-
const
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
(document) => {
|
821
|
-
if (!validationSchema) {
|
822
|
-
throw new Error(
|
823
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
824
|
-
);
|
825
|
-
}
|
826
|
-
try {
|
827
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
828
|
-
return null;
|
829
|
-
} catch (error2) {
|
830
|
-
if (error2 instanceof ValidationError) {
|
831
|
-
return getYupValidationErrors(error2);
|
832
|
-
}
|
833
|
-
throw error2;
|
834
|
-
}
|
947
|
+
}, [error, formatAPIError, toggleNotification]);
|
948
|
+
const editLayout = React.useMemo(
|
949
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
950
|
+
layout: [],
|
951
|
+
components: {},
|
952
|
+
metadatas: {},
|
953
|
+
options: {},
|
954
|
+
settings: DEFAULT_SETTINGS
|
835
955
|
},
|
836
|
-
[
|
956
|
+
[data, isLoading, schemas, schema, components]
|
957
|
+
);
|
958
|
+
const listLayout = React.useMemo(() => {
|
959
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
960
|
+
layout: [],
|
961
|
+
metadatas: {},
|
962
|
+
options: {},
|
963
|
+
settings: DEFAULT_SETTINGS
|
964
|
+
};
|
965
|
+
}, [data, isLoading, schemas, schema, components]);
|
966
|
+
const { layout: edit } = React.useMemo(
|
967
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
968
|
+
layout: editLayout,
|
969
|
+
query
|
970
|
+
}),
|
971
|
+
[editLayout, query, runHookWaterfall]
|
837
972
|
);
|
838
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
839
973
|
return {
|
840
|
-
|
841
|
-
document: data?.data,
|
842
|
-
meta: data?.meta,
|
974
|
+
error,
|
843
975
|
isLoading,
|
844
|
-
|
845
|
-
|
846
|
-
};
|
847
|
-
};
|
848
|
-
const useDoc = () => {
|
849
|
-
const { id, slug, collectionType, origin } = useParams();
|
850
|
-
const [{ query }] = useQueryParams();
|
851
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
852
|
-
if (!collectionType) {
|
853
|
-
throw new Error("Could not find collectionType in url params");
|
854
|
-
}
|
855
|
-
if (!slug) {
|
856
|
-
throw new Error("Could not find model in url params");
|
857
|
-
}
|
858
|
-
return {
|
859
|
-
collectionType,
|
860
|
-
model: slug,
|
861
|
-
id: origin || id === "create" ? void 0 : id,
|
862
|
-
...useDocument(
|
863
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
864
|
-
{
|
865
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
866
|
-
}
|
867
|
-
)
|
976
|
+
edit,
|
977
|
+
list: listLayout
|
868
978
|
};
|
869
979
|
};
|
870
|
-
const
|
871
|
-
|
872
|
-
|
873
|
-
}
|
874
|
-
return Object.keys(trad).reduce((acc, current) => {
|
875
|
-
acc[`${pluginId}.${current}`] = trad[current];
|
876
|
-
return acc;
|
877
|
-
}, {});
|
878
|
-
};
|
879
|
-
const getTranslation = (id) => `content-manager.${id}`;
|
880
|
-
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
881
|
-
id: "notification.error",
|
882
|
-
defaultMessage: "An error occurred, please try again"
|
980
|
+
const useDocLayout = () => {
|
981
|
+
const { model } = useDoc();
|
982
|
+
return useDocumentLayout(model);
|
883
983
|
};
|
884
|
-
const
|
885
|
-
|
984
|
+
const formatEditLayout = (data, {
|
985
|
+
schemas,
|
986
|
+
schema,
|
987
|
+
components
|
988
|
+
}) => {
|
989
|
+
let currentPanelIndex = 0;
|
990
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
991
|
+
data.contentType.layouts.edit,
|
992
|
+
schema?.attributes,
|
993
|
+
data.contentType.metadatas,
|
994
|
+
{ configurations: data.components, schemas: components },
|
995
|
+
schemas
|
996
|
+
).reduce((panels, row) => {
|
997
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
998
|
+
panels.push([row]);
|
999
|
+
currentPanelIndex += 2;
|
1000
|
+
} else {
|
1001
|
+
if (!panels[currentPanelIndex]) {
|
1002
|
+
panels.push([row]);
|
1003
|
+
} else {
|
1004
|
+
panels[currentPanelIndex].push(row);
|
1005
|
+
}
|
1006
|
+
}
|
1007
|
+
return panels;
|
1008
|
+
}, []);
|
1009
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
1010
|
+
(acc, [uid, configuration]) => {
|
1011
|
+
acc[uid] = {
|
1012
|
+
layout: convertEditLayoutToFieldLayouts(
|
1013
|
+
configuration.layouts.edit,
|
1014
|
+
components[uid].attributes,
|
1015
|
+
configuration.metadatas,
|
1016
|
+
{ configurations: data.components, schemas: components }
|
1017
|
+
),
|
1018
|
+
settings: {
|
1019
|
+
...configuration.settings,
|
1020
|
+
icon: components[uid].info.icon,
|
1021
|
+
displayName: components[uid].info.displayName
|
1022
|
+
}
|
1023
|
+
};
|
1024
|
+
return acc;
|
1025
|
+
},
|
1026
|
+
{}
|
1027
|
+
);
|
1028
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1029
|
+
(acc, [attribute, metadata]) => {
|
1030
|
+
return {
|
1031
|
+
...acc,
|
1032
|
+
[attribute]: metadata.edit
|
1033
|
+
};
|
1034
|
+
},
|
1035
|
+
{}
|
1036
|
+
);
|
1037
|
+
return {
|
1038
|
+
layout: panelledEditAttributes,
|
1039
|
+
components: componentEditAttributes,
|
1040
|
+
metadatas: editMetadatas,
|
1041
|
+
settings: {
|
1042
|
+
...data.contentType.settings,
|
1043
|
+
displayName: schema?.info.displayName
|
1044
|
+
},
|
1045
|
+
options: {
|
1046
|
+
...schema?.options,
|
1047
|
+
...schema?.pluginOptions,
|
1048
|
+
...data.contentType.options
|
1049
|
+
}
|
1050
|
+
};
|
1051
|
+
};
|
1052
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1053
|
+
return rows.map(
|
1054
|
+
(row) => row.map((field) => {
|
1055
|
+
const attribute = attributes[field.name];
|
1056
|
+
if (!attribute) {
|
1057
|
+
return null;
|
1058
|
+
}
|
1059
|
+
const { edit: metadata } = metadatas[field.name];
|
1060
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1061
|
+
return {
|
1062
|
+
attribute,
|
1063
|
+
disabled: !metadata.editable,
|
1064
|
+
hint: metadata.description,
|
1065
|
+
label: metadata.label ?? "",
|
1066
|
+
name: field.name,
|
1067
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1068
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1069
|
+
schemas,
|
1070
|
+
components: components?.schemas ?? {}
|
1071
|
+
}),
|
1072
|
+
placeholder: metadata.placeholder ?? "",
|
1073
|
+
required: attribute.required ?? false,
|
1074
|
+
size: field.size,
|
1075
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1076
|
+
visible: metadata.visible ?? true,
|
1077
|
+
type: attribute.type
|
1078
|
+
};
|
1079
|
+
}).filter((field) => field !== null)
|
1080
|
+
);
|
1081
|
+
};
|
1082
|
+
const formatListLayout = (data, {
|
1083
|
+
schemas,
|
1084
|
+
schema,
|
1085
|
+
components
|
1086
|
+
}) => {
|
1087
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1088
|
+
(acc, [attribute, metadata]) => {
|
1089
|
+
return {
|
1090
|
+
...acc,
|
1091
|
+
[attribute]: metadata.list
|
1092
|
+
};
|
1093
|
+
},
|
1094
|
+
{}
|
1095
|
+
);
|
1096
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1097
|
+
data.contentType.layouts.list,
|
1098
|
+
schema?.attributes,
|
1099
|
+
listMetadatas,
|
1100
|
+
{ configurations: data.components, schemas: components },
|
1101
|
+
schemas
|
1102
|
+
);
|
1103
|
+
return {
|
1104
|
+
layout: listAttributes,
|
1105
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1106
|
+
metadatas: listMetadatas,
|
1107
|
+
options: {
|
1108
|
+
...schema?.options,
|
1109
|
+
...schema?.pluginOptions,
|
1110
|
+
...data.contentType.options
|
1111
|
+
}
|
1112
|
+
};
|
1113
|
+
};
|
1114
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1115
|
+
return columns.map((name) => {
|
1116
|
+
const attribute = attributes[name];
|
1117
|
+
if (!attribute) {
|
1118
|
+
return null;
|
1119
|
+
}
|
1120
|
+
const metadata = metadatas[name];
|
1121
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1122
|
+
return {
|
1123
|
+
attribute,
|
1124
|
+
label: metadata.label ?? "",
|
1125
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1126
|
+
schemas,
|
1127
|
+
components: components?.schemas ?? {}
|
1128
|
+
}),
|
1129
|
+
name,
|
1130
|
+
searchable: metadata.searchable ?? true,
|
1131
|
+
sortable: metadata.sortable ?? true
|
1132
|
+
};
|
1133
|
+
}).filter((field) => field !== null);
|
1134
|
+
};
|
1135
|
+
const useDocument = (args, opts) => {
|
1136
|
+
const { toggleNotification } = useNotification();
|
1137
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1138
|
+
const {
|
1139
|
+
currentData: data,
|
1140
|
+
isLoading: isLoadingDocument,
|
1141
|
+
isFetching: isFetchingDocument,
|
1142
|
+
error
|
1143
|
+
} = useGetDocumentQuery(args, {
|
1144
|
+
...opts,
|
1145
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1146
|
+
});
|
1147
|
+
const {
|
1148
|
+
components,
|
1149
|
+
schema,
|
1150
|
+
schemas,
|
1151
|
+
isLoading: isLoadingSchema
|
1152
|
+
} = useContentTypeSchema(args.model);
|
1153
|
+
React.useEffect(() => {
|
1154
|
+
if (error) {
|
1155
|
+
toggleNotification({
|
1156
|
+
type: "danger",
|
1157
|
+
message: formatAPIError(error)
|
1158
|
+
});
|
1159
|
+
}
|
1160
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1161
|
+
const validationSchema = React.useMemo(() => {
|
1162
|
+
if (!schema) {
|
1163
|
+
return null;
|
1164
|
+
}
|
1165
|
+
return createYupSchema(schema.attributes, components);
|
1166
|
+
}, [schema, components]);
|
1167
|
+
const validate = React.useCallback(
|
1168
|
+
(document) => {
|
1169
|
+
if (!validationSchema) {
|
1170
|
+
throw new Error(
|
1171
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1172
|
+
);
|
1173
|
+
}
|
1174
|
+
try {
|
1175
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1176
|
+
return null;
|
1177
|
+
} catch (error2) {
|
1178
|
+
if (error2 instanceof ValidationError) {
|
1179
|
+
return getYupValidationErrors(error2);
|
1180
|
+
}
|
1181
|
+
throw error2;
|
1182
|
+
}
|
1183
|
+
},
|
1184
|
+
[validationSchema]
|
1185
|
+
);
|
1186
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1187
|
+
const hasError = !!error;
|
1188
|
+
return {
|
1189
|
+
components,
|
1190
|
+
document: data?.data,
|
1191
|
+
meta: data?.meta,
|
1192
|
+
isLoading,
|
1193
|
+
hasError,
|
1194
|
+
schema,
|
1195
|
+
schemas,
|
1196
|
+
validate
|
1197
|
+
};
|
1198
|
+
};
|
1199
|
+
const useDoc = () => {
|
1200
|
+
const { id, slug, collectionType, origin } = useParams();
|
1201
|
+
const [{ query }] = useQueryParams();
|
1202
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1203
|
+
if (!collectionType) {
|
1204
|
+
throw new Error("Could not find collectionType in url params");
|
1205
|
+
}
|
1206
|
+
if (!slug) {
|
1207
|
+
throw new Error("Could not find model in url params");
|
1208
|
+
}
|
1209
|
+
const document = useDocument(
|
1210
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1211
|
+
{
|
1212
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1213
|
+
}
|
1214
|
+
);
|
1215
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
1216
|
+
return {
|
1217
|
+
collectionType,
|
1218
|
+
model: slug,
|
1219
|
+
id: returnId,
|
1220
|
+
...document
|
1221
|
+
};
|
1222
|
+
};
|
1223
|
+
const useContentManagerContext = () => {
|
1224
|
+
const {
|
1225
|
+
collectionType,
|
1226
|
+
model,
|
1227
|
+
id,
|
1228
|
+
components,
|
1229
|
+
isLoading: isLoadingDoc,
|
1230
|
+
schema,
|
1231
|
+
schemas
|
1232
|
+
} = useDoc();
|
1233
|
+
const layout = useDocumentLayout(model);
|
1234
|
+
const form = useForm("useContentManagerContext", (state) => state);
|
1235
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1236
|
+
const slug = model;
|
1237
|
+
const isCreatingEntry = id === "create";
|
1238
|
+
useContentTypeSchema();
|
1239
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1240
|
+
const error = layout.error;
|
1241
|
+
return {
|
1242
|
+
error,
|
1243
|
+
isLoading,
|
1244
|
+
// Base metadata
|
1245
|
+
model,
|
1246
|
+
collectionType,
|
1247
|
+
id,
|
1248
|
+
slug,
|
1249
|
+
isCreatingEntry,
|
1250
|
+
isSingleType,
|
1251
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1252
|
+
// All schema infos
|
1253
|
+
components,
|
1254
|
+
contentType: schema,
|
1255
|
+
contentTypes: schemas,
|
1256
|
+
// Form state
|
1257
|
+
form,
|
1258
|
+
// layout infos
|
1259
|
+
layout
|
1260
|
+
};
|
1261
|
+
};
|
1262
|
+
const prefixPluginTranslations = (trad, pluginId) => {
|
1263
|
+
return Object.keys(trad).reduce((acc, current) => {
|
1264
|
+
acc[`${pluginId}.${current}`] = trad[current];
|
1265
|
+
return acc;
|
1266
|
+
}, {});
|
1267
|
+
};
|
1268
|
+
const getTranslation = (id) => `content-manager.${id}`;
|
1269
|
+
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
1270
|
+
id: "notification.error",
|
1271
|
+
defaultMessage: "An error occurred, please try again"
|
1272
|
+
};
|
1273
|
+
const useDocumentActions = () => {
|
1274
|
+
const { toggleNotification } = useNotification();
|
886
1275
|
const { formatMessage } = useIntl();
|
887
1276
|
const { trackUsage } = useTracking();
|
888
1277
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
889
1278
|
const navigate = useNavigate();
|
1279
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
890
1280
|
const [deleteDocument] = useDeleteDocumentMutation();
|
891
1281
|
const _delete = React.useCallback(
|
892
1282
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1201,6 +1591,7 @@ const useDocumentActions = () => {
|
|
1201
1591
|
defaultMessage: "Saved document"
|
1202
1592
|
})
|
1203
1593
|
});
|
1594
|
+
setCurrentStep("contentManager.success");
|
1204
1595
|
return res.data;
|
1205
1596
|
} catch (err) {
|
1206
1597
|
toggleNotification({
|
@@ -1302,10 +1693,10 @@ const useDocumentActions = () => {
|
|
1302
1693
|
update
|
1303
1694
|
};
|
1304
1695
|
};
|
1305
|
-
const ProtectedHistoryPage = lazy(
|
1306
|
-
() => import("./History-
|
1696
|
+
const ProtectedHistoryPage = React.lazy(
|
1697
|
+
() => import("./History-04ChQ4pl.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1307
1698
|
);
|
1308
|
-
const routes$
|
1699
|
+
const routes$2 = [
|
1309
1700
|
{
|
1310
1701
|
path: ":collectionType/:slug/:id/history",
|
1311
1702
|
Component: ProtectedHistoryPage
|
@@ -1315,32 +1706,45 @@ const routes$1 = [
|
|
1315
1706
|
Component: ProtectedHistoryPage
|
1316
1707
|
}
|
1317
1708
|
];
|
1318
|
-
const
|
1319
|
-
() => import("./
|
1709
|
+
const ProtectedPreviewPage = React.lazy(
|
1710
|
+
() => import("./Preview-BMYN548c.mjs").then((mod) => ({ default: mod.ProtectedPreviewPage }))
|
1320
1711
|
);
|
1321
|
-
const
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1712
|
+
const routes$1 = [
|
1713
|
+
{
|
1714
|
+
path: ":collectionType/:slug/:id/preview",
|
1715
|
+
Component: ProtectedPreviewPage
|
1716
|
+
},
|
1717
|
+
{
|
1718
|
+
path: ":collectionType/:slug/preview",
|
1719
|
+
Component: ProtectedPreviewPage
|
1720
|
+
}
|
1721
|
+
];
|
1722
|
+
const ProtectedEditViewPage = lazy(
|
1723
|
+
() => import("./EditViewPage-BPyVuPfM.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1724
|
+
);
|
1725
|
+
const ProtectedListViewPage = lazy(
|
1726
|
+
() => import("./ListViewPage-FU2LBuhl.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1727
|
+
);
|
1728
|
+
const ProtectedListConfiguration = lazy(
|
1729
|
+
() => import("./ListConfigurationPage-BYqPYLSU.mjs").then((mod) => ({
|
1730
|
+
default: mod.ProtectedListConfiguration
|
1327
1731
|
}))
|
1328
1732
|
);
|
1329
1733
|
const ProtectedEditConfigurationPage = lazy(
|
1330
|
-
() => import("./EditConfigurationPage-
|
1734
|
+
() => import("./EditConfigurationPage-DsPR2DVk.mjs").then((mod) => ({
|
1331
1735
|
default: mod.ProtectedEditConfigurationPage
|
1332
1736
|
}))
|
1333
1737
|
);
|
1334
1738
|
const ProtectedComponentConfigurationPage = lazy(
|
1335
|
-
() => import("./ComponentConfigurationPage-
|
1739
|
+
() => import("./ComponentConfigurationPage-CtIa3aa2.mjs").then((mod) => ({
|
1336
1740
|
default: mod.ProtectedComponentConfigurationPage
|
1337
1741
|
}))
|
1338
1742
|
);
|
1339
1743
|
const NoPermissions = lazy(
|
1340
|
-
() => import("./NoPermissionsPage-
|
1744
|
+
() => import("./NoPermissionsPage-jqve7C8l.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1341
1745
|
);
|
1342
1746
|
const NoContentType = lazy(
|
1343
|
-
() => import("./NoContentTypePage-
|
1747
|
+
() => import("./NoContentTypePage-DCKUkwb8.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1344
1748
|
);
|
1345
1749
|
const CollectionTypePages = () => {
|
1346
1750
|
const { collectionType } = useParams();
|
@@ -1352,7 +1756,7 @@ const CollectionTypePages = () => {
|
|
1352
1756
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1353
1757
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1354
1758
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1355
|
-
const LIST_PATH = `/content-manager
|
1759
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1356
1760
|
const routes = [
|
1357
1761
|
{
|
1358
1762
|
path: LIST_RELATIVE_PATH,
|
@@ -1386,6 +1790,7 @@ const routes = [
|
|
1386
1790
|
path: "no-content-types",
|
1387
1791
|
Component: NoContentType
|
1388
1792
|
},
|
1793
|
+
...routes$2,
|
1389
1794
|
...routes$1
|
1390
1795
|
];
|
1391
1796
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1484,6 +1889,11 @@ const DocumentActionButton = (action) => {
|
|
1484
1889
|
) : null
|
1485
1890
|
] });
|
1486
1891
|
};
|
1892
|
+
const MenuItem = styled(Menu.Item)`
|
1893
|
+
&:hover {
|
1894
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1895
|
+
}
|
1896
|
+
`;
|
1487
1897
|
const DocumentActionsMenu = ({
|
1488
1898
|
actions: actions2,
|
1489
1899
|
children,
|
@@ -1539,51 +1949,35 @@ const DocumentActionsMenu = ({
|
|
1539
1949
|
]
|
1540
1950
|
}
|
1541
1951
|
),
|
1542
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1952
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1543
1953
|
actions2.map((action) => {
|
1544
1954
|
return /* @__PURE__ */ jsx(
|
1545
|
-
|
1955
|
+
MenuItem,
|
1546
1956
|
{
|
1547
1957
|
disabled: action.disabled,
|
1548
1958
|
onSelect: handleClick(action),
|
1549
1959
|
display: "block",
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
Flex,
|
1572
|
-
{
|
1573
|
-
alignItems: "center",
|
1574
|
-
background: "alternative100",
|
1575
|
-
borderStyle: "solid",
|
1576
|
-
borderColor: "alternative200",
|
1577
|
-
borderWidth: "1px",
|
1578
|
-
height: 5,
|
1579
|
-
paddingLeft: 2,
|
1580
|
-
paddingRight: 2,
|
1581
|
-
hasRadius: true,
|
1582
|
-
color: "alternative600",
|
1583
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1584
|
-
}
|
1585
|
-
)
|
1586
|
-
] })
|
1960
|
+
isVariantDanger: action.variant === "danger",
|
1961
|
+
isDisabled: action.disabled,
|
1962
|
+
children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxs(
|
1963
|
+
Flex,
|
1964
|
+
{
|
1965
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1966
|
+
gap: 2,
|
1967
|
+
tag: "span",
|
1968
|
+
children: [
|
1969
|
+
/* @__PURE__ */ jsx(
|
1970
|
+
Flex,
|
1971
|
+
{
|
1972
|
+
tag: "span",
|
1973
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1974
|
+
children: action.icon
|
1975
|
+
}
|
1976
|
+
),
|
1977
|
+
action.label
|
1978
|
+
]
|
1979
|
+
}
|
1980
|
+
) })
|
1587
1981
|
},
|
1588
1982
|
action.id
|
1589
1983
|
);
|
@@ -1663,11 +2057,11 @@ const DocumentActionConfirmDialog = ({
|
|
1663
2057
|
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1664
2058
|
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1665
2059
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1666
|
-
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
2060
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1667
2061
|
id: "app.components.Button.cancel",
|
1668
2062
|
defaultMessage: "Cancel"
|
1669
2063
|
}) }) }),
|
1670
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2064
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1671
2065
|
id: "app.components.Button.confirm",
|
1672
2066
|
defaultMessage: "Confirm"
|
1673
2067
|
}) })
|
@@ -1694,6 +2088,18 @@ const DocumentActionModal = ({
|
|
1694
2088
|
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1695
2089
|
] }) });
|
1696
2090
|
};
|
2091
|
+
const transformData = (data) => {
|
2092
|
+
if (Array.isArray(data)) {
|
2093
|
+
return data.map(transformData);
|
2094
|
+
}
|
2095
|
+
if (typeof data === "object" && data !== null) {
|
2096
|
+
if ("apiData" in data) {
|
2097
|
+
return data.apiData;
|
2098
|
+
}
|
2099
|
+
return mapValues(transformData)(data);
|
2100
|
+
}
|
2101
|
+
return data;
|
2102
|
+
};
|
1697
2103
|
const PublishAction$1 = ({
|
1698
2104
|
activeTab,
|
1699
2105
|
documentId,
|
@@ -1708,6 +2114,7 @@ const PublishAction$1 = ({
|
|
1708
2114
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
1709
2115
|
const isListView = useMatch(LIST_PATH) !== null;
|
1710
2116
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2117
|
+
const { id } = useParams();
|
1711
2118
|
const { formatMessage } = useIntl();
|
1712
2119
|
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1713
2120
|
const { publish } = useDocumentActions();
|
@@ -1761,24 +2168,25 @@ const PublishAction$1 = ({
|
|
1761
2168
|
}
|
1762
2169
|
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1763
2170
|
React.useEffect(() => {
|
1764
|
-
if (documentId
|
1765
|
-
|
1766
|
-
const { data, error } = await countDraftRelations({
|
1767
|
-
collectionType,
|
1768
|
-
model,
|
1769
|
-
documentId,
|
1770
|
-
params
|
1771
|
-
});
|
1772
|
-
if (error) {
|
1773
|
-
throw error;
|
1774
|
-
}
|
1775
|
-
if (data) {
|
1776
|
-
setServerCountOfDraftRelations(data.data);
|
1777
|
-
}
|
1778
|
-
};
|
1779
|
-
fetchDraftRelationsCount();
|
2171
|
+
if (!document || !document.documentId || isListView) {
|
2172
|
+
return;
|
1780
2173
|
}
|
1781
|
-
|
2174
|
+
const fetchDraftRelationsCount = async () => {
|
2175
|
+
const { data, error } = await countDraftRelations({
|
2176
|
+
collectionType,
|
2177
|
+
model,
|
2178
|
+
documentId,
|
2179
|
+
params
|
2180
|
+
});
|
2181
|
+
if (error) {
|
2182
|
+
throw error;
|
2183
|
+
}
|
2184
|
+
if (data) {
|
2185
|
+
setServerCountOfDraftRelations(data.data);
|
2186
|
+
}
|
2187
|
+
};
|
2188
|
+
fetchDraftRelationsCount();
|
2189
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
1782
2190
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1783
2191
|
if (!schema?.options?.draftAndPublish) {
|
1784
2192
|
return null;
|
@@ -1786,7 +2194,9 @@ const PublishAction$1 = ({
|
|
1786
2194
|
const performPublish = async () => {
|
1787
2195
|
setSubmitting(true);
|
1788
2196
|
try {
|
1789
|
-
const { errors } = await validate(
|
2197
|
+
const { errors } = await validate(true, {
|
2198
|
+
status: "published"
|
2199
|
+
});
|
1790
2200
|
if (errors) {
|
1791
2201
|
toggleNotification({
|
1792
2202
|
type: "danger",
|
@@ -1804,13 +2214,15 @@ const PublishAction$1 = ({
|
|
1804
2214
|
documentId,
|
1805
2215
|
params
|
1806
2216
|
},
|
1807
|
-
formValues
|
2217
|
+
transformData(formValues)
|
1808
2218
|
);
|
1809
2219
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
1813
|
-
|
2220
|
+
if (id === "create") {
|
2221
|
+
navigate({
|
2222
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2223
|
+
search: rawQuery
|
2224
|
+
});
|
2225
|
+
}
|
1814
2226
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1815
2227
|
setErrors(formatValidationErrors(res.error));
|
1816
2228
|
}
|
@@ -1863,6 +2275,7 @@ const PublishAction$1 = ({
|
|
1863
2275
|
};
|
1864
2276
|
};
|
1865
2277
|
PublishAction$1.type = "publish";
|
2278
|
+
PublishAction$1.position = "panel";
|
1866
2279
|
const UpdateAction = ({
|
1867
2280
|
activeTab,
|
1868
2281
|
documentId,
|
@@ -1885,6 +2298,117 @@ const UpdateAction = ({
|
|
1885
2298
|
const validate = useForm("UpdateAction", (state) => state.validate);
|
1886
2299
|
const setErrors = useForm("UpdateAction", (state) => state.setErrors);
|
1887
2300
|
const resetForm = useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
2301
|
+
const handleUpdate = React.useCallback(async () => {
|
2302
|
+
setSubmitting(true);
|
2303
|
+
try {
|
2304
|
+
if (!modified) {
|
2305
|
+
return;
|
2306
|
+
}
|
2307
|
+
const { errors } = await validate(true, {
|
2308
|
+
status: "draft"
|
2309
|
+
});
|
2310
|
+
if (errors) {
|
2311
|
+
toggleNotification({
|
2312
|
+
type: "danger",
|
2313
|
+
message: formatMessage({
|
2314
|
+
id: "content-manager.validation.error",
|
2315
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2316
|
+
})
|
2317
|
+
});
|
2318
|
+
return;
|
2319
|
+
}
|
2320
|
+
if (isCloning) {
|
2321
|
+
const res = await clone(
|
2322
|
+
{
|
2323
|
+
model,
|
2324
|
+
documentId: cloneMatch.params.origin,
|
2325
|
+
params
|
2326
|
+
},
|
2327
|
+
transformData(document)
|
2328
|
+
);
|
2329
|
+
if ("data" in res) {
|
2330
|
+
navigate(
|
2331
|
+
{
|
2332
|
+
pathname: `../${res.data.documentId}`,
|
2333
|
+
search: rawQuery
|
2334
|
+
},
|
2335
|
+
{ relative: "path" }
|
2336
|
+
);
|
2337
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2338
|
+
setErrors(formatValidationErrors(res.error));
|
2339
|
+
}
|
2340
|
+
} else if (documentId || collectionType === SINGLE_TYPES) {
|
2341
|
+
const res = await update(
|
2342
|
+
{
|
2343
|
+
collectionType,
|
2344
|
+
model,
|
2345
|
+
documentId,
|
2346
|
+
params
|
2347
|
+
},
|
2348
|
+
transformData(document)
|
2349
|
+
);
|
2350
|
+
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2351
|
+
setErrors(formatValidationErrors(res.error));
|
2352
|
+
} else {
|
2353
|
+
resetForm();
|
2354
|
+
}
|
2355
|
+
} else {
|
2356
|
+
const res = await create(
|
2357
|
+
{
|
2358
|
+
model,
|
2359
|
+
params
|
2360
|
+
},
|
2361
|
+
transformData(document)
|
2362
|
+
);
|
2363
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2364
|
+
navigate(
|
2365
|
+
{
|
2366
|
+
pathname: `../${res.data.documentId}`,
|
2367
|
+
search: rawQuery
|
2368
|
+
},
|
2369
|
+
{ replace: true, relative: "path" }
|
2370
|
+
);
|
2371
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2372
|
+
setErrors(formatValidationErrors(res.error));
|
2373
|
+
}
|
2374
|
+
}
|
2375
|
+
} finally {
|
2376
|
+
setSubmitting(false);
|
2377
|
+
}
|
2378
|
+
}, [
|
2379
|
+
clone,
|
2380
|
+
cloneMatch?.params.origin,
|
2381
|
+
collectionType,
|
2382
|
+
create,
|
2383
|
+
document,
|
2384
|
+
documentId,
|
2385
|
+
formatMessage,
|
2386
|
+
formatValidationErrors,
|
2387
|
+
isCloning,
|
2388
|
+
model,
|
2389
|
+
modified,
|
2390
|
+
navigate,
|
2391
|
+
params,
|
2392
|
+
rawQuery,
|
2393
|
+
resetForm,
|
2394
|
+
setErrors,
|
2395
|
+
setSubmitting,
|
2396
|
+
toggleNotification,
|
2397
|
+
update,
|
2398
|
+
validate
|
2399
|
+
]);
|
2400
|
+
React.useEffect(() => {
|
2401
|
+
const handleKeyDown = (e) => {
|
2402
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
2403
|
+
e.preventDefault();
|
2404
|
+
handleUpdate();
|
2405
|
+
}
|
2406
|
+
};
|
2407
|
+
window.addEventListener("keydown", handleKeyDown);
|
2408
|
+
return () => {
|
2409
|
+
window.removeEventListener("keydown", handleKeyDown);
|
2410
|
+
};
|
2411
|
+
}, [handleUpdate]);
|
1888
2412
|
return {
|
1889
2413
|
/**
|
1890
2414
|
* Disabled when:
|
@@ -1894,87 +2418,14 @@ const UpdateAction = ({
|
|
1894
2418
|
*/
|
1895
2419
|
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1896
2420
|
label: formatMessage({
|
1897
|
-
id: "
|
2421
|
+
id: "global.save",
|
1898
2422
|
defaultMessage: "Save"
|
1899
2423
|
}),
|
1900
|
-
onClick:
|
1901
|
-
setSubmitting(true);
|
1902
|
-
try {
|
1903
|
-
if (activeTab !== "draft") {
|
1904
|
-
const { errors } = await validate();
|
1905
|
-
if (errors) {
|
1906
|
-
toggleNotification({
|
1907
|
-
type: "danger",
|
1908
|
-
message: formatMessage({
|
1909
|
-
id: "content-manager.validation.error",
|
1910
|
-
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1911
|
-
})
|
1912
|
-
});
|
1913
|
-
return;
|
1914
|
-
}
|
1915
|
-
}
|
1916
|
-
if (isCloning) {
|
1917
|
-
const res = await clone(
|
1918
|
-
{
|
1919
|
-
model,
|
1920
|
-
documentId: cloneMatch.params.origin,
|
1921
|
-
params
|
1922
|
-
},
|
1923
|
-
document
|
1924
|
-
);
|
1925
|
-
if ("data" in res) {
|
1926
|
-
navigate(
|
1927
|
-
{
|
1928
|
-
pathname: `../${res.data.documentId}`,
|
1929
|
-
search: rawQuery
|
1930
|
-
},
|
1931
|
-
{ relative: "path" }
|
1932
|
-
);
|
1933
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1934
|
-
setErrors(formatValidationErrors(res.error));
|
1935
|
-
}
|
1936
|
-
} else if (documentId || collectionType === SINGLE_TYPES) {
|
1937
|
-
const res = await update(
|
1938
|
-
{
|
1939
|
-
collectionType,
|
1940
|
-
model,
|
1941
|
-
documentId,
|
1942
|
-
params
|
1943
|
-
},
|
1944
|
-
document
|
1945
|
-
);
|
1946
|
-
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1947
|
-
setErrors(formatValidationErrors(res.error));
|
1948
|
-
} else {
|
1949
|
-
resetForm();
|
1950
|
-
}
|
1951
|
-
} else {
|
1952
|
-
const res = await create(
|
1953
|
-
{
|
1954
|
-
model,
|
1955
|
-
params
|
1956
|
-
},
|
1957
|
-
document
|
1958
|
-
);
|
1959
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1960
|
-
navigate(
|
1961
|
-
{
|
1962
|
-
pathname: `../${res.data.documentId}`,
|
1963
|
-
search: rawQuery
|
1964
|
-
},
|
1965
|
-
{ replace: true, relative: "path" }
|
1966
|
-
);
|
1967
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1968
|
-
setErrors(formatValidationErrors(res.error));
|
1969
|
-
}
|
1970
|
-
}
|
1971
|
-
} finally {
|
1972
|
-
setSubmitting(false);
|
1973
|
-
}
|
1974
|
-
}
|
2424
|
+
onClick: handleUpdate
|
1975
2425
|
};
|
1976
2426
|
};
|
1977
2427
|
UpdateAction.type = "update";
|
2428
|
+
UpdateAction.position = "panel";
|
1978
2429
|
const UNPUBLISH_DRAFT_OPTIONS = {
|
1979
2430
|
KEEP: "keep",
|
1980
2431
|
DISCARD: "discard"
|
@@ -2007,7 +2458,7 @@ const UnpublishAction$1 = ({
|
|
2007
2458
|
id: "app.utils.unpublish",
|
2008
2459
|
defaultMessage: "Unpublish"
|
2009
2460
|
}),
|
2010
|
-
icon: /* @__PURE__ */ jsx(
|
2461
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2011
2462
|
onClick: async () => {
|
2012
2463
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2013
2464
|
if (!documentId) {
|
@@ -2097,6 +2548,7 @@ const UnpublishAction$1 = ({
|
|
2097
2548
|
};
|
2098
2549
|
};
|
2099
2550
|
UnpublishAction$1.type = "unpublish";
|
2551
|
+
UnpublishAction$1.position = "panel";
|
2100
2552
|
const DiscardAction = ({
|
2101
2553
|
activeTab,
|
2102
2554
|
documentId,
|
@@ -2119,7 +2571,7 @@ const DiscardAction = ({
|
|
2119
2571
|
id: "content-manager.actions.discard.label",
|
2120
2572
|
defaultMessage: "Discard changes"
|
2121
2573
|
}),
|
2122
|
-
icon: /* @__PURE__ */ jsx(
|
2574
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2123
2575
|
position: ["panel", "table-row"],
|
2124
2576
|
variant: "danger",
|
2125
2577
|
dialog: {
|
@@ -2147,11 +2599,7 @@ const DiscardAction = ({
|
|
2147
2599
|
};
|
2148
2600
|
};
|
2149
2601
|
DiscardAction.type = "discard";
|
2150
|
-
|
2151
|
-
path {
|
2152
|
-
fill: currentColor;
|
2153
|
-
}
|
2154
|
-
`;
|
2602
|
+
DiscardAction.position = "panel";
|
2155
2603
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2156
2604
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2157
2605
|
const RelativeTime = React.forwardRef(
|
@@ -2164,7 +2612,7 @@ const RelativeTime = React.forwardRef(
|
|
2164
2612
|
});
|
2165
2613
|
const unit = intervals.find((intervalUnit) => {
|
2166
2614
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2167
|
-
});
|
2615
|
+
}) ?? "seconds";
|
2168
2616
|
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2169
2617
|
const customInterval = customIntervals.find(
|
2170
2618
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2198,19 +2646,29 @@ const getDisplayName = ({
|
|
2198
2646
|
return email ?? "";
|
2199
2647
|
};
|
2200
2648
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2201
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2202
|
-
const statusVariant = status === "draft" ? "
|
2203
|
-
|
2649
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2650
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2651
|
+
const { formatMessage } = useIntl();
|
2652
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2653
|
+
id: `content-manager.containers.List.${status}`,
|
2654
|
+
defaultMessage: capitalise(status)
|
2655
|
+
}) }) });
|
2204
2656
|
};
|
2205
2657
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2206
2658
|
const { formatMessage } = useIntl();
|
2207
2659
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2660
|
+
const params = useParams();
|
2208
2661
|
const title = isCreating ? formatMessage({
|
2209
2662
|
id: "content-manager.containers.edit.title.new",
|
2210
2663
|
defaultMessage: "Create an entry"
|
2211
2664
|
}) : documentTitle;
|
2212
2665
|
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2213
|
-
/* @__PURE__ */ jsx(
|
2666
|
+
/* @__PURE__ */ jsx(
|
2667
|
+
BackButton,
|
2668
|
+
{
|
2669
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2670
|
+
}
|
2671
|
+
),
|
2214
2672
|
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2215
2673
|
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2216
2674
|
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
@@ -2261,7 +2719,7 @@ const HeaderToolbar = () => {
|
|
2261
2719
|
meta: isCloning ? void 0 : meta,
|
2262
2720
|
collectionType
|
2263
2721
|
},
|
2264
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2722
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
|
2265
2723
|
children: (actions2) => {
|
2266
2724
|
const headerActions = actions2.filter((action) => {
|
2267
2725
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -2298,12 +2756,12 @@ const Information = ({ activeTab }) => {
|
|
2298
2756
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2299
2757
|
label: formatMessage({
|
2300
2758
|
id: "content-manager.containers.edit.information.last-published.label",
|
2301
|
-
defaultMessage: "
|
2759
|
+
defaultMessage: "Published"
|
2302
2760
|
}),
|
2303
2761
|
value: formatMessage(
|
2304
2762
|
{
|
2305
2763
|
id: "content-manager.containers.edit.information.last-published.value",
|
2306
|
-
defaultMessage: `
|
2764
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2307
2765
|
},
|
2308
2766
|
{
|
2309
2767
|
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2316,12 +2774,12 @@ const Information = ({ activeTab }) => {
|
|
2316
2774
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2317
2775
|
label: formatMessage({
|
2318
2776
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2319
|
-
defaultMessage: "
|
2777
|
+
defaultMessage: "Updated"
|
2320
2778
|
}),
|
2321
2779
|
value: formatMessage(
|
2322
2780
|
{
|
2323
2781
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2324
|
-
defaultMessage: `
|
2782
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2325
2783
|
},
|
2326
2784
|
{
|
2327
2785
|
time: /* @__PURE__ */ jsx(
|
@@ -2339,12 +2797,12 @@ const Information = ({ activeTab }) => {
|
|
2339
2797
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2340
2798
|
label: formatMessage({
|
2341
2799
|
id: "content-manager.containers.edit.information.document.label",
|
2342
|
-
defaultMessage: "
|
2800
|
+
defaultMessage: "Created"
|
2343
2801
|
}),
|
2344
2802
|
value: formatMessage(
|
2345
2803
|
{
|
2346
2804
|
id: "content-manager.containers.edit.information.document.value",
|
2347
|
-
defaultMessage: `
|
2805
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2348
2806
|
},
|
2349
2807
|
{
|
2350
2808
|
time: /* @__PURE__ */ jsx(
|
@@ -2382,25 +2840,77 @@ const Information = ({ activeTab }) => {
|
|
2382
2840
|
);
|
2383
2841
|
};
|
2384
2842
|
const HeaderActions = ({ actions: actions2 }) => {
|
2385
|
-
|
2386
|
-
|
2843
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2844
|
+
const handleClick = (action) => async (e) => {
|
2845
|
+
if (!("options" in action)) {
|
2846
|
+
const { onClick = () => false, dialog, id } = action;
|
2847
|
+
const muteDialog = await onClick(e);
|
2848
|
+
if (dialog && !muteDialog) {
|
2849
|
+
e.preventDefault();
|
2850
|
+
setDialogId(id);
|
2851
|
+
}
|
2852
|
+
}
|
2853
|
+
};
|
2854
|
+
const handleClose = () => {
|
2855
|
+
setDialogId(null);
|
2856
|
+
};
|
2857
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2858
|
+
if (action.options) {
|
2387
2859
|
return /* @__PURE__ */ jsx(
|
2388
2860
|
SingleSelect,
|
2389
2861
|
{
|
2390
2862
|
size: "S",
|
2391
|
-
disabled: action.disabled,
|
2392
|
-
"aria-label": action.label,
|
2393
2863
|
onChange: action.onSelect,
|
2394
|
-
|
2864
|
+
"aria-label": action.label,
|
2865
|
+
...action,
|
2395
2866
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2396
2867
|
},
|
2397
2868
|
action.id
|
2398
2869
|
);
|
2399
2870
|
} else {
|
2400
|
-
|
2871
|
+
if (action.type === "icon") {
|
2872
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2873
|
+
/* @__PURE__ */ jsx(
|
2874
|
+
IconButton,
|
2875
|
+
{
|
2876
|
+
disabled: action.disabled,
|
2877
|
+
label: action.label,
|
2878
|
+
size: "S",
|
2879
|
+
onClick: handleClick(action),
|
2880
|
+
children: action.icon
|
2881
|
+
}
|
2882
|
+
),
|
2883
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2884
|
+
HeaderActionDialog,
|
2885
|
+
{
|
2886
|
+
...action.dialog,
|
2887
|
+
isOpen: dialogId === action.id,
|
2888
|
+
onClose: handleClose
|
2889
|
+
}
|
2890
|
+
) : null
|
2891
|
+
] }, action.id);
|
2892
|
+
}
|
2401
2893
|
}
|
2402
2894
|
}) });
|
2403
2895
|
};
|
2896
|
+
const HeaderActionDialog = ({
|
2897
|
+
onClose,
|
2898
|
+
onCancel,
|
2899
|
+
title,
|
2900
|
+
content: Content,
|
2901
|
+
isOpen
|
2902
|
+
}) => {
|
2903
|
+
const handleClose = async () => {
|
2904
|
+
if (onCancel) {
|
2905
|
+
await onCancel();
|
2906
|
+
}
|
2907
|
+
onClose();
|
2908
|
+
};
|
2909
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2910
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2911
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2912
|
+
] }) });
|
2913
|
+
};
|
2404
2914
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2405
2915
|
const navigate = useNavigate();
|
2406
2916
|
const { formatMessage } = useIntl();
|
@@ -2417,6 +2927,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2417
2927
|
};
|
2418
2928
|
};
|
2419
2929
|
ConfigureTheViewAction.type = "configure-the-view";
|
2930
|
+
ConfigureTheViewAction.position = "header";
|
2420
2931
|
const EditTheModelAction = ({ model }) => {
|
2421
2932
|
const navigate = useNavigate();
|
2422
2933
|
const { formatMessage } = useIntl();
|
@@ -2433,6 +2944,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2433
2944
|
};
|
2434
2945
|
};
|
2435
2946
|
EditTheModelAction.type = "edit-the-model";
|
2947
|
+
EditTheModelAction.position = "header";
|
2436
2948
|
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2437
2949
|
const navigate = useNavigate();
|
2438
2950
|
const { formatMessage } = useIntl();
|
@@ -2441,12 +2953,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2441
2953
|
const { delete: deleteAction } = useDocumentActions();
|
2442
2954
|
const { toggleNotification } = useNotification();
|
2443
2955
|
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2956
|
+
const isLocalized = document?.locale != null;
|
2444
2957
|
return {
|
2445
2958
|
disabled: !canDelete || !document,
|
2446
|
-
label: formatMessage(
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2959
|
+
label: formatMessage(
|
2960
|
+
{
|
2961
|
+
id: "content-manager.actions.delete.label",
|
2962
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2963
|
+
},
|
2964
|
+
{ isLocalized }
|
2965
|
+
),
|
2450
2966
|
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2451
2967
|
dialog: {
|
2452
2968
|
type: "dialog",
|
@@ -2484,421 +3000,120 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2484
3000
|
model,
|
2485
3001
|
collectionType,
|
2486
3002
|
params: {
|
2487
|
-
locale: "*"
|
2488
|
-
}
|
2489
|
-
});
|
2490
|
-
if (!("error" in res)) {
|
2491
|
-
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2492
|
-
}
|
2493
|
-
} finally {
|
2494
|
-
if (!listViewPathMatch) {
|
2495
|
-
setSubmitting(false);
|
2496
|
-
}
|
2497
|
-
}
|
2498
|
-
}
|
2499
|
-
},
|
2500
|
-
variant: "danger",
|
2501
|
-
position: ["header", "table-row"]
|
2502
|
-
};
|
2503
|
-
};
|
2504
|
-
DeleteAction$1.type = "delete";
|
2505
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2506
|
-
const Panels = () => {
|
2507
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2508
|
-
const [
|
2509
|
-
{
|
2510
|
-
query: { status }
|
2511
|
-
}
|
2512
|
-
] = useQueryParams({
|
2513
|
-
status: "draft"
|
2514
|
-
});
|
2515
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2516
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2517
|
-
const props = {
|
2518
|
-
activeTab: status,
|
2519
|
-
model,
|
2520
|
-
documentId: id,
|
2521
|
-
document: isCloning ? void 0 : document,
|
2522
|
-
meta: isCloning ? void 0 : meta,
|
2523
|
-
collectionType
|
2524
|
-
};
|
2525
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2526
|
-
DescriptionComponentRenderer,
|
2527
|
-
{
|
2528
|
-
props,
|
2529
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2530
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2531
|
-
}
|
2532
|
-
) });
|
2533
|
-
};
|
2534
|
-
const ActionsPanel = () => {
|
2535
|
-
const { formatMessage } = useIntl();
|
2536
|
-
return {
|
2537
|
-
title: formatMessage({
|
2538
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2539
|
-
defaultMessage: "Document"
|
2540
|
-
}),
|
2541
|
-
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2542
|
-
};
|
2543
|
-
};
|
2544
|
-
ActionsPanel.type = "actions";
|
2545
|
-
const ActionsPanelContent = () => {
|
2546
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2547
|
-
const [
|
2548
|
-
{
|
2549
|
-
query: { status = "draft" }
|
2550
|
-
}
|
2551
|
-
] = useQueryParams();
|
2552
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2553
|
-
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2554
|
-
const props = {
|
2555
|
-
activeTab: status,
|
2556
|
-
model,
|
2557
|
-
documentId: id,
|
2558
|
-
document: isCloning ? void 0 : document,
|
2559
|
-
meta: isCloning ? void 0 : meta,
|
2560
|
-
collectionType
|
2561
|
-
};
|
2562
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2563
|
-
/* @__PURE__ */ jsx(
|
2564
|
-
DescriptionComponentRenderer,
|
2565
|
-
{
|
2566
|
-
props,
|
2567
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2568
|
-
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2569
|
-
}
|
2570
|
-
),
|
2571
|
-
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2572
|
-
] });
|
2573
|
-
};
|
2574
|
-
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2575
|
-
return /* @__PURE__ */ jsxs(
|
2576
|
-
Flex,
|
2577
|
-
{
|
2578
|
-
ref,
|
2579
|
-
tag: "aside",
|
2580
|
-
"aria-labelledby": "additional-information",
|
2581
|
-
background: "neutral0",
|
2582
|
-
borderColor: "neutral150",
|
2583
|
-
hasRadius: true,
|
2584
|
-
paddingBottom: 4,
|
2585
|
-
paddingLeft: 4,
|
2586
|
-
paddingRight: 4,
|
2587
|
-
paddingTop: 4,
|
2588
|
-
shadow: "tableShadow",
|
2589
|
-
gap: 3,
|
2590
|
-
direction: "column",
|
2591
|
-
justifyContent: "stretch",
|
2592
|
-
alignItems: "flex-start",
|
2593
|
-
children: [
|
2594
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2595
|
-
children
|
2596
|
-
]
|
2597
|
-
}
|
2598
|
-
);
|
2599
|
-
});
|
2600
|
-
const HOOKS = {
|
2601
|
-
/**
|
2602
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2603
|
-
* @constant
|
2604
|
-
* @type {string}
|
2605
|
-
*/
|
2606
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2607
|
-
/**
|
2608
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2609
|
-
* @constant
|
2610
|
-
* @type {string}
|
2611
|
-
*/
|
2612
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2613
|
-
/**
|
2614
|
-
* Hook that allows to mutate the CM's edit view layout
|
2615
|
-
* @constant
|
2616
|
-
* @type {string}
|
2617
|
-
*/
|
2618
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2619
|
-
/**
|
2620
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2621
|
-
* @constant
|
2622
|
-
* @type {string}
|
2623
|
-
*/
|
2624
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2625
|
-
};
|
2626
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2627
|
-
endpoints: (builder) => ({
|
2628
|
-
getContentTypeConfiguration: builder.query({
|
2629
|
-
query: (uid) => ({
|
2630
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2631
|
-
method: "GET"
|
2632
|
-
}),
|
2633
|
-
transformResponse: (response) => response.data,
|
2634
|
-
providesTags: (_result, _error, uid) => [
|
2635
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2636
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2637
|
-
]
|
2638
|
-
}),
|
2639
|
-
getAllContentTypeSettings: builder.query({
|
2640
|
-
query: () => "/content-manager/content-types-settings",
|
2641
|
-
transformResponse: (response) => response.data,
|
2642
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2643
|
-
}),
|
2644
|
-
updateContentTypeConfiguration: builder.mutation({
|
2645
|
-
query: ({ uid, ...body }) => ({
|
2646
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2647
|
-
method: "PUT",
|
2648
|
-
data: body
|
2649
|
-
}),
|
2650
|
-
transformResponse: (response) => response.data,
|
2651
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2652
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2653
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2654
|
-
// Is this necessary?
|
2655
|
-
{ type: "InitialData" }
|
2656
|
-
]
|
2657
|
-
})
|
2658
|
-
})
|
2659
|
-
});
|
2660
|
-
const {
|
2661
|
-
useGetContentTypeConfigurationQuery,
|
2662
|
-
useGetAllContentTypeSettingsQuery,
|
2663
|
-
useUpdateContentTypeConfigurationMutation
|
2664
|
-
} = contentTypesApi;
|
2665
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2666
|
-
const { type } = attribute;
|
2667
|
-
if (type === "relation") {
|
2668
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2669
|
-
}
|
2670
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2671
|
-
};
|
2672
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2673
|
-
if (!mainFieldName) {
|
2674
|
-
return void 0;
|
2675
|
-
}
|
2676
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2677
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2678
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2679
|
-
);
|
2680
|
-
return {
|
2681
|
-
name: mainFieldName,
|
2682
|
-
type: mainFieldType ?? "string"
|
2683
|
-
};
|
2684
|
-
};
|
2685
|
-
const DEFAULT_SETTINGS = {
|
2686
|
-
bulkable: false,
|
2687
|
-
filterable: false,
|
2688
|
-
searchable: false,
|
2689
|
-
pagination: false,
|
2690
|
-
defaultSortBy: "",
|
2691
|
-
defaultSortOrder: "asc",
|
2692
|
-
mainField: "id",
|
2693
|
-
pageSize: 10
|
2694
|
-
};
|
2695
|
-
const useDocumentLayout = (model) => {
|
2696
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2697
|
-
const [{ query }] = useQueryParams();
|
2698
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2699
|
-
const { toggleNotification } = useNotification();
|
2700
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2701
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2702
|
-
const {
|
2703
|
-
data,
|
2704
|
-
isLoading: isLoadingConfigs,
|
2705
|
-
error,
|
2706
|
-
isFetching: isFetchingConfigs
|
2707
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2708
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2709
|
-
React.useEffect(() => {
|
2710
|
-
if (error) {
|
2711
|
-
toggleNotification({
|
2712
|
-
type: "danger",
|
2713
|
-
message: formatAPIError(error)
|
2714
|
-
});
|
2715
|
-
}
|
2716
|
-
}, [error, formatAPIError, toggleNotification]);
|
2717
|
-
const editLayout = React.useMemo(
|
2718
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2719
|
-
layout: [],
|
2720
|
-
components: {},
|
2721
|
-
metadatas: {},
|
2722
|
-
options: {},
|
2723
|
-
settings: DEFAULT_SETTINGS
|
2724
|
-
},
|
2725
|
-
[data, isLoading, schemas, schema, components]
|
2726
|
-
);
|
2727
|
-
const listLayout = React.useMemo(() => {
|
2728
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2729
|
-
layout: [],
|
2730
|
-
metadatas: {},
|
2731
|
-
options: {},
|
2732
|
-
settings: DEFAULT_SETTINGS
|
2733
|
-
};
|
2734
|
-
}, [data, isLoading, schemas, schema, components]);
|
2735
|
-
const { layout: edit } = React.useMemo(
|
2736
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2737
|
-
layout: editLayout,
|
2738
|
-
query
|
2739
|
-
}),
|
2740
|
-
[editLayout, query, runHookWaterfall]
|
2741
|
-
);
|
2742
|
-
return {
|
2743
|
-
error,
|
2744
|
-
isLoading,
|
2745
|
-
edit,
|
2746
|
-
list: listLayout
|
2747
|
-
};
|
2748
|
-
};
|
2749
|
-
const useDocLayout = () => {
|
2750
|
-
const { model } = useDoc();
|
2751
|
-
return useDocumentLayout(model);
|
2752
|
-
};
|
2753
|
-
const formatEditLayout = (data, {
|
2754
|
-
schemas,
|
2755
|
-
schema,
|
2756
|
-
components
|
2757
|
-
}) => {
|
2758
|
-
let currentPanelIndex = 0;
|
2759
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2760
|
-
data.contentType.layouts.edit,
|
2761
|
-
schema?.attributes,
|
2762
|
-
data.contentType.metadatas,
|
2763
|
-
{ configurations: data.components, schemas: components },
|
2764
|
-
schemas
|
2765
|
-
).reduce((panels, row) => {
|
2766
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2767
|
-
panels.push([row]);
|
2768
|
-
currentPanelIndex += 2;
|
2769
|
-
} else {
|
2770
|
-
if (!panels[currentPanelIndex]) {
|
2771
|
-
panels.push([]);
|
2772
|
-
}
|
2773
|
-
panels[currentPanelIndex].push(row);
|
2774
|
-
}
|
2775
|
-
return panels;
|
2776
|
-
}, []);
|
2777
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2778
|
-
(acc, [uid, configuration]) => {
|
2779
|
-
acc[uid] = {
|
2780
|
-
layout: convertEditLayoutToFieldLayouts(
|
2781
|
-
configuration.layouts.edit,
|
2782
|
-
components[uid].attributes,
|
2783
|
-
configuration.metadatas
|
2784
|
-
),
|
2785
|
-
settings: {
|
2786
|
-
...configuration.settings,
|
2787
|
-
icon: components[uid].info.icon,
|
2788
|
-
displayName: components[uid].info.displayName
|
3003
|
+
locale: "*"
|
3004
|
+
}
|
3005
|
+
});
|
3006
|
+
if (!("error" in res)) {
|
3007
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
3008
|
+
}
|
3009
|
+
} finally {
|
3010
|
+
if (!listViewPathMatch) {
|
3011
|
+
setSubmitting(false);
|
3012
|
+
}
|
2789
3013
|
}
|
2790
|
-
}
|
2791
|
-
return acc;
|
2792
|
-
},
|
2793
|
-
{}
|
2794
|
-
);
|
2795
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2796
|
-
(acc, [attribute, metadata]) => {
|
2797
|
-
return {
|
2798
|
-
...acc,
|
2799
|
-
[attribute]: metadata.edit
|
2800
|
-
};
|
2801
|
-
},
|
2802
|
-
{}
|
2803
|
-
);
|
2804
|
-
return {
|
2805
|
-
layout: panelledEditAttributes,
|
2806
|
-
components: componentEditAttributes,
|
2807
|
-
metadatas: editMetadatas,
|
2808
|
-
settings: {
|
2809
|
-
...data.contentType.settings,
|
2810
|
-
displayName: schema?.info.displayName
|
3014
|
+
}
|
2811
3015
|
},
|
2812
|
-
|
2813
|
-
|
2814
|
-
...schema?.pluginOptions,
|
2815
|
-
...data.contentType.options
|
2816
|
-
}
|
3016
|
+
variant: "danger",
|
3017
|
+
position: ["header", "table-row"]
|
2817
3018
|
};
|
2818
3019
|
};
|
2819
|
-
|
2820
|
-
|
2821
|
-
|
2822
|
-
|
2823
|
-
|
2824
|
-
|
2825
|
-
|
2826
|
-
|
2827
|
-
|
2828
|
-
|
2829
|
-
|
2830
|
-
|
2831
|
-
|
2832
|
-
|
2833
|
-
|
2834
|
-
|
2835
|
-
|
2836
|
-
|
2837
|
-
|
2838
|
-
|
2839
|
-
|
2840
|
-
|
2841
|
-
|
2842
|
-
|
2843
|
-
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
2847
|
-
|
3020
|
+
DeleteAction$1.type = "delete";
|
3021
|
+
DeleteAction$1.position = ["header", "table-row"];
|
3022
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
3023
|
+
const Panels = () => {
|
3024
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
3025
|
+
const [
|
3026
|
+
{
|
3027
|
+
query: { status }
|
3028
|
+
}
|
3029
|
+
] = useQueryParams({
|
3030
|
+
status: "draft"
|
3031
|
+
});
|
3032
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3033
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
3034
|
+
const props = {
|
3035
|
+
activeTab: status,
|
3036
|
+
model,
|
3037
|
+
documentId: id,
|
3038
|
+
document: isCloning ? void 0 : document,
|
3039
|
+
meta: isCloning ? void 0 : meta,
|
3040
|
+
collectionType
|
3041
|
+
};
|
3042
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
3043
|
+
DescriptionComponentRenderer,
|
3044
|
+
{
|
3045
|
+
props,
|
3046
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
3047
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
3048
|
+
}
|
3049
|
+
) });
|
2848
3050
|
};
|
2849
|
-
const
|
2850
|
-
|
2851
|
-
schema,
|
2852
|
-
components
|
2853
|
-
}) => {
|
2854
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2855
|
-
(acc, [attribute, metadata]) => {
|
2856
|
-
return {
|
2857
|
-
...acc,
|
2858
|
-
[attribute]: metadata.list
|
2859
|
-
};
|
2860
|
-
},
|
2861
|
-
{}
|
2862
|
-
);
|
2863
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2864
|
-
data.contentType.layouts.list,
|
2865
|
-
schema?.attributes,
|
2866
|
-
listMetadatas,
|
2867
|
-
{ configurations: data.components, schemas: components },
|
2868
|
-
schemas
|
2869
|
-
);
|
3051
|
+
const ActionsPanel = () => {
|
3052
|
+
const { formatMessage } = useIntl();
|
2870
3053
|
return {
|
2871
|
-
|
2872
|
-
|
2873
|
-
|
2874
|
-
|
2875
|
-
|
2876
|
-
...schema?.pluginOptions,
|
2877
|
-
...data.contentType.options
|
2878
|
-
}
|
3054
|
+
title: formatMessage({
|
3055
|
+
id: "content-manager.containers.edit.panels.default.title",
|
3056
|
+
defaultMessage: "Entry"
|
3057
|
+
}),
|
3058
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2879
3059
|
};
|
2880
3060
|
};
|
2881
|
-
|
2882
|
-
|
2883
|
-
|
2884
|
-
|
2885
|
-
|
3061
|
+
ActionsPanel.type = "actions";
|
3062
|
+
const ActionsPanelContent = () => {
|
3063
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
3064
|
+
const [
|
3065
|
+
{
|
3066
|
+
query: { status = "draft" }
|
2886
3067
|
}
|
2887
|
-
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2898
|
-
|
2899
|
-
|
2900
|
-
|
3068
|
+
] = useQueryParams();
|
3069
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3070
|
+
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
3071
|
+
const props = {
|
3072
|
+
activeTab: status,
|
3073
|
+
model,
|
3074
|
+
documentId: id,
|
3075
|
+
document: isCloning ? void 0 : document,
|
3076
|
+
meta: isCloning ? void 0 : meta,
|
3077
|
+
collectionType
|
3078
|
+
};
|
3079
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3080
|
+
/* @__PURE__ */ jsx(
|
3081
|
+
DescriptionComponentRenderer,
|
3082
|
+
{
|
3083
|
+
props,
|
3084
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
|
3085
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
3086
|
+
}
|
3087
|
+
),
|
3088
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3089
|
+
] });
|
2901
3090
|
};
|
3091
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
3092
|
+
return /* @__PURE__ */ jsxs(
|
3093
|
+
Flex,
|
3094
|
+
{
|
3095
|
+
ref,
|
3096
|
+
tag: "aside",
|
3097
|
+
"aria-labelledby": "additional-information",
|
3098
|
+
background: "neutral0",
|
3099
|
+
borderColor: "neutral150",
|
3100
|
+
hasRadius: true,
|
3101
|
+
paddingBottom: 4,
|
3102
|
+
paddingLeft: 4,
|
3103
|
+
paddingRight: 4,
|
3104
|
+
paddingTop: 4,
|
3105
|
+
shadow: "tableShadow",
|
3106
|
+
gap: 3,
|
3107
|
+
direction: "column",
|
3108
|
+
justifyContent: "stretch",
|
3109
|
+
alignItems: "flex-start",
|
3110
|
+
children: [
|
3111
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3112
|
+
children
|
3113
|
+
]
|
3114
|
+
}
|
3115
|
+
);
|
3116
|
+
});
|
2902
3117
|
const ConfirmBulkActionDialog = ({
|
2903
3118
|
onToggleDialog,
|
2904
3119
|
isOpen = false,
|
@@ -3143,18 +3358,10 @@ const SelectedEntriesTableContent = ({
|
|
3143
3358
|
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3144
3359
|
},
|
3145
3360
|
state: { from: pathname },
|
3146
|
-
label: formatMessage(
|
3147
|
-
|
3148
|
-
|
3149
|
-
|
3150
|
-
{
|
3151
|
-
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3152
|
-
defaultMessage: "item line {number}"
|
3153
|
-
},
|
3154
|
-
{ number: index2 + 1 }
|
3155
|
-
)
|
3156
|
-
}
|
3157
|
-
),
|
3361
|
+
label: formatMessage({
|
3362
|
+
id: "content-manager.bulk-publish.edit",
|
3363
|
+
defaultMessage: "Edit"
|
3364
|
+
}),
|
3158
3365
|
target: "_blank",
|
3159
3366
|
marginLeft: "auto",
|
3160
3367
|
variant: "ghost",
|
@@ -3328,8 +3535,7 @@ const PublishAction = ({ documents, model }) => {
|
|
3328
3535
|
const refetchList = () => {
|
3329
3536
|
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3330
3537
|
};
|
3331
|
-
if (!showPublishButton)
|
3332
|
-
return null;
|
3538
|
+
if (!showPublishButton) return null;
|
3333
3539
|
return {
|
3334
3540
|
actionType: "publish",
|
3335
3541
|
variant: "tertiary",
|
@@ -3397,8 +3603,7 @@ const DeleteAction = ({ documents, model }) => {
|
|
3397
3603
|
selectRow([]);
|
3398
3604
|
}
|
3399
3605
|
};
|
3400
|
-
if (!hasDeletePermission)
|
3401
|
-
return null;
|
3606
|
+
if (!hasDeletePermission) return null;
|
3402
3607
|
return {
|
3403
3608
|
variant: "danger-light",
|
3404
3609
|
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
@@ -3447,8 +3652,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
3447
3652
|
}
|
3448
3653
|
};
|
3449
3654
|
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3450
|
-
if (!showUnpublishButton)
|
3451
|
-
return null;
|
3655
|
+
if (!showUnpublishButton) return null;
|
3452
3656
|
return {
|
3453
3657
|
variant: "tertiary",
|
3454
3658
|
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
@@ -3553,7 +3757,7 @@ const TableActions = ({ document }) => {
|
|
3553
3757
|
DescriptionComponentRenderer,
|
3554
3758
|
{
|
3555
3759
|
props,
|
3556
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3760
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
|
3557
3761
|
children: (actions2) => {
|
3558
3762
|
const tableRowActions = actions2.filter((action) => {
|
3559
3763
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3612,6 +3816,7 @@ const EditAction = ({ documentId }) => {
|
|
3612
3816
|
};
|
3613
3817
|
};
|
3614
3818
|
EditAction.type = "edit";
|
3819
|
+
EditAction.position = "table-row";
|
3615
3820
|
const StyledPencil = styled(Pencil)`
|
3616
3821
|
path {
|
3617
3822
|
fill: currentColor;
|
@@ -3688,6 +3893,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3688
3893
|
};
|
3689
3894
|
};
|
3690
3895
|
CloneAction.type = "clone";
|
3896
|
+
CloneAction.position = "table-row";
|
3691
3897
|
const StyledDuplicate = styled(Duplicate)`
|
3692
3898
|
path {
|
3693
3899
|
fill: currentColor;
|
@@ -3774,7 +3980,14 @@ class ContentManagerPlugin {
|
|
3774
3980
|
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3775
3981
|
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3776
3982
|
getBulkActions: () => this.bulkActions,
|
3777
|
-
getDocumentActions: () =>
|
3983
|
+
getDocumentActions: (position) => {
|
3984
|
+
if (position) {
|
3985
|
+
return this.documentActions.filter(
|
3986
|
+
(action) => action.position == void 0 || [action.position].flat().includes(position)
|
3987
|
+
);
|
3988
|
+
}
|
3989
|
+
return this.documentActions;
|
3990
|
+
},
|
3778
3991
|
getEditViewSidePanels: () => this.editViewSidePanels,
|
3779
3992
|
getHeaderActions: () => this.headerActions
|
3780
3993
|
}
|
@@ -3784,10 +3997,8 @@ class ContentManagerPlugin {
|
|
3784
3997
|
const getPrintableType = (value) => {
|
3785
3998
|
const nativeType = typeof value;
|
3786
3999
|
if (nativeType === "object") {
|
3787
|
-
if (value === null)
|
3788
|
-
|
3789
|
-
if (Array.isArray(value))
|
3790
|
-
return "array";
|
4000
|
+
if (value === null) return "null";
|
4001
|
+
if (Array.isArray(value)) return "array";
|
3791
4002
|
if (value instanceof Object && value.constructor.name !== "Object") {
|
3792
4003
|
return value.constructor.name;
|
3793
4004
|
}
|
@@ -3798,17 +4009,27 @@ const HistoryAction = ({ model, document }) => {
|
|
3798
4009
|
const { formatMessage } = useIntl();
|
3799
4010
|
const [{ query }] = useQueryParams();
|
3800
4011
|
const navigate = useNavigate();
|
4012
|
+
const { trackUsage } = useTracking();
|
4013
|
+
const { pathname } = useLocation();
|
3801
4014
|
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3802
4015
|
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3803
4016
|
return null;
|
3804
4017
|
}
|
4018
|
+
const handleOnClick = () => {
|
4019
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
4020
|
+
trackUsage("willNavigate", {
|
4021
|
+
from: pathname,
|
4022
|
+
to: `${pathname}/${destination.pathname}`
|
4023
|
+
});
|
4024
|
+
navigate(destination);
|
4025
|
+
};
|
3805
4026
|
return {
|
3806
4027
|
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3807
4028
|
label: formatMessage({
|
3808
4029
|
id: "content-manager.history.document-action",
|
3809
4030
|
defaultMessage: "Content History"
|
3810
4031
|
}),
|
3811
|
-
onClick:
|
4032
|
+
onClick: handleOnClick,
|
3812
4033
|
disabled: (
|
3813
4034
|
/**
|
3814
4035
|
* The user is creating a new document.
|
@@ -3830,6 +4051,7 @@ const HistoryAction = ({ model, document }) => {
|
|
3830
4051
|
};
|
3831
4052
|
};
|
3832
4053
|
HistoryAction.type = "history";
|
4054
|
+
HistoryAction.position = "header";
|
3833
4055
|
const historyAdmin = {
|
3834
4056
|
bootstrap(app) {
|
3835
4057
|
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
@@ -3876,6 +4098,88 @@ const { setInitialData } = actions;
|
|
3876
4098
|
const reducer = combineReducers({
|
3877
4099
|
app: reducer$1
|
3878
4100
|
});
|
4101
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4102
|
+
endpoints: (builder) => ({
|
4103
|
+
getPreviewUrl: builder.query({
|
4104
|
+
query({ query, params }) {
|
4105
|
+
return {
|
4106
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4107
|
+
method: "GET",
|
4108
|
+
config: {
|
4109
|
+
params: query
|
4110
|
+
}
|
4111
|
+
};
|
4112
|
+
}
|
4113
|
+
})
|
4114
|
+
})
|
4115
|
+
});
|
4116
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4117
|
+
const ConditionalTooltip = ({ isShown, label, children }) => {
|
4118
|
+
if (isShown) {
|
4119
|
+
return /* @__PURE__ */ jsx(Tooltip, { label, children });
|
4120
|
+
}
|
4121
|
+
return children;
|
4122
|
+
};
|
4123
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4124
|
+
const { formatMessage } = useIntl();
|
4125
|
+
const { trackUsage } = useTracking();
|
4126
|
+
const { pathname } = useLocation();
|
4127
|
+
const [{ query }] = useQueryParams();
|
4128
|
+
const isModified = useForm("PreviewSidePanel", (state) => state.modified);
|
4129
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4130
|
+
params: {
|
4131
|
+
contentType: model
|
4132
|
+
},
|
4133
|
+
query: {
|
4134
|
+
documentId,
|
4135
|
+
locale: document?.locale,
|
4136
|
+
status: document?.status
|
4137
|
+
}
|
4138
|
+
});
|
4139
|
+
if (!data?.data?.url || error) {
|
4140
|
+
return null;
|
4141
|
+
}
|
4142
|
+
const trackNavigation = () => {
|
4143
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4144
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
4145
|
+
};
|
4146
|
+
return {
|
4147
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4148
|
+
content: /* @__PURE__ */ jsx(
|
4149
|
+
ConditionalTooltip,
|
4150
|
+
{
|
4151
|
+
label: formatMessage({
|
4152
|
+
id: "content-manager.preview.panel.button-disabled-tooltip",
|
4153
|
+
defaultMessage: "Please save to open the preview"
|
4154
|
+
}),
|
4155
|
+
isShown: isModified,
|
4156
|
+
children: /* @__PURE__ */ jsx(Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsx(
|
4157
|
+
Button,
|
4158
|
+
{
|
4159
|
+
variant: "tertiary",
|
4160
|
+
tag: Link,
|
4161
|
+
to: { pathname: "preview", search: stringify(query, { encode: false }) },
|
4162
|
+
onClick: trackNavigation,
|
4163
|
+
width: "100%",
|
4164
|
+
disabled: isModified,
|
4165
|
+
pointerEvents: isModified ? "none" : void 0,
|
4166
|
+
tabIndex: isModified ? -1 : void 0,
|
4167
|
+
children: formatMessage({
|
4168
|
+
id: "content-manager.preview.panel.button",
|
4169
|
+
defaultMessage: "Open preview"
|
4170
|
+
})
|
4171
|
+
}
|
4172
|
+
) })
|
4173
|
+
}
|
4174
|
+
)
|
4175
|
+
};
|
4176
|
+
};
|
4177
|
+
const previewAdmin = {
|
4178
|
+
bootstrap(app) {
|
4179
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4180
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4181
|
+
}
|
4182
|
+
};
|
3879
4183
|
const index = {
|
3880
4184
|
register(app) {
|
3881
4185
|
const cm = new ContentManagerPlugin();
|
@@ -3895,7 +4199,7 @@ const index = {
|
|
3895
4199
|
app.router.addRoute({
|
3896
4200
|
path: "content-manager/*",
|
3897
4201
|
lazy: async () => {
|
3898
|
-
const { Layout } = await import("./layout-
|
4202
|
+
const { Layout } = await import("./layout-W3clJSCy.mjs");
|
3899
4203
|
return {
|
3900
4204
|
Component: Layout
|
3901
4205
|
};
|
@@ -3908,11 +4212,14 @@ const index = {
|
|
3908
4212
|
if (typeof historyAdmin.bootstrap === "function") {
|
3909
4213
|
historyAdmin.bootstrap(app);
|
3910
4214
|
}
|
4215
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4216
|
+
previewAdmin.bootstrap(app);
|
4217
|
+
}
|
3911
4218
|
},
|
3912
4219
|
async registerTrads({ locales }) {
|
3913
4220
|
const importedTrads = await Promise.all(
|
3914
4221
|
locales.map((locale) => {
|
3915
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-
|
4222
|
+
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-CSxLmrh1.mjs"), "./translations/es.json": () => import("./es-D34tqjMw.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr--pg5jUbt.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-BHqhDq4V.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`, 3).then(({ default: data }) => {
|
3916
4223
|
return {
|
3917
4224
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3918
4225
|
locale
|
@@ -3939,8 +4246,10 @@ export {
|
|
3939
4246
|
HOOKS as H,
|
3940
4247
|
InjectionZone as I,
|
3941
4248
|
useDocument as J,
|
3942
|
-
|
3943
|
-
|
4249
|
+
useGetPreviewUrlQuery as K,
|
4250
|
+
index as L,
|
4251
|
+
useContentManagerContext as M,
|
4252
|
+
useDocumentActions as N,
|
3944
4253
|
Panels as P,
|
3945
4254
|
RelativeTime as R,
|
3946
4255
|
SINGLE_TYPES as S,
|
@@ -3972,4 +4281,4 @@ export {
|
|
3972
4281
|
capitalise as y,
|
3973
4282
|
useUpdateContentTypeConfigurationMutation as z
|
3974
4283
|
};
|
3975
|
-
//# sourceMappingURL=index-
|
4284
|
+
//# sourceMappingURL=index-DqasUQ6Q.mjs.map
|