@strapi/content-manager 0.0.0-experimental.cb311d9fcfbd8e441f790aea232f0a39bdd90e16 → 0.0.0-experimental.cb74730ce5154c26404d4dccca14976a22319002
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-D0dyDTwq.mjs → ComponentConfigurationPage-BgCLcjXO.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-D0dyDTwq.mjs.map → ComponentConfigurationPage-BgCLcjXO.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DL1MHO8i.js → ComponentConfigurationPage-DywpTZeV.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-DL1MHO8i.js.map → ComponentConfigurationPage-DywpTZeV.js.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-13b7S5Cq.mjs → EditConfigurationPage-BNjOAHNS.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-13b7S5Cq.mjs.map → EditConfigurationPage-BNjOAHNS.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CMaOf-A-.js → EditConfigurationPage-CxRlP5if.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-CMaOf-A-.js.map → EditConfigurationPage-CxRlP5if.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-BSVmMpRd.js → EditViewPage-BRewdTqE.js} +63 -13
- package/dist/_chunks/EditViewPage-BRewdTqE.js.map +1 -0
- package/dist/_chunks/{EditViewPage-C3tIZ8F5.mjs → EditViewPage-CD_hqc1J.mjs} +63 -12
- package/dist/_chunks/EditViewPage-CD_hqc1J.mjs.map +1 -0
- package/dist/_chunks/{Field-BvuT8cGL.mjs → Field-BPkQ-3Ku.mjs} +230 -158
- package/dist/_chunks/Field-BPkQ-3Ku.mjs.map +1 -0
- package/dist/_chunks/{Field-DUCVth4C.js → Field-DwvmENVf.js} +233 -162
- package/dist/_chunks/Field-DwvmENVf.js.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-Cpl4W1ak.js → Form-C_Gwv8P_.js} +39 -21
- package/dist/_chunks/Form-C_Gwv8P_.js.map +1 -0
- package/dist/_chunks/{Form-BZmDNVr9.mjs → Form-Czi0cf_2.mjs} +37 -18
- package/dist/_chunks/Form-Czi0cf_2.mjs.map +1 -0
- package/dist/_chunks/{History-D4U2YISB.js → History-C1TKAig-.js} +42 -100
- package/dist/_chunks/History-C1TKAig-.js.map +1 -0
- package/dist/_chunks/{History-Cq_Hrzuu.mjs → History-CIQHyi4T.mjs} +43 -100
- package/dist/_chunks/History-CIQHyi4T.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Bny6CdWe.js → ListConfigurationPage-D-NGRLYu.js} +19 -9
- package/dist/_chunks/ListConfigurationPage-D-NGRLYu.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-W-KQHmBv.mjs → ListConfigurationPage-DcZsfyEL.mjs} +19 -8
- package/dist/_chunks/ListConfigurationPage-DcZsfyEL.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-HBBnJa8K.mjs → ListViewPage-C10McTK1.mjs} +99 -72
- package/dist/_chunks/ListViewPage-C10McTK1.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-O8F1pBJo.js → ListViewPage-xv5IQoZp.js} +103 -77
- package/dist/_chunks/ListViewPage-xv5IQoZp.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-B-gIhHWM.mjs → NoContentTypePage-CPc0Cd3S.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-B-gIhHWM.mjs.map → NoContentTypePage-CPc0Cd3S.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-CQWChGPw.js → NoContentTypePage-Dzw5Yj5u.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-CQWChGPw.js.map → NoContentTypePage-Dzw5Yj5u.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CY46zxnM.js → NoPermissionsPage-DAe5CDCC.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CY46zxnM.js.map → NoPermissionsPage-DAe5CDCC.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-XhOPl8wx.mjs → NoPermissionsPage-wfPBh2_0.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-XhOPl8wx.mjs.map → NoPermissionsPage-wfPBh2_0.mjs.map} +1 -1
- package/dist/_chunks/Preview-B7LyGT_b.js +290 -0
- package/dist/_chunks/Preview-B7LyGT_b.js.map +1 -0
- package/dist/_chunks/Preview-BVFFm7uB.mjs +272 -0
- package/dist/_chunks/Preview-BVFFm7uB.mjs.map +1 -0
- package/dist/_chunks/{Relations-C4gGfZRv.js → Relations-BmYR1AjY.js} +76 -43
- package/dist/_chunks/Relations-BmYR1AjY.js.map +1 -0
- package/dist/_chunks/{Relations-vFZ6Wasg.mjs → Relations-JPhWxk-s.mjs} +76 -42
- package/dist/_chunks/Relations-JPhWxk-s.mjs.map +1 -0
- package/dist/_chunks/{en-uOUIxfcQ.js → en-BK8Xyl5I.js} +28 -15
- package/dist/_chunks/{en-uOUIxfcQ.js.map → en-BK8Xyl5I.js.map} +1 -1
- package/dist/_chunks/{en-BrCTWlZv.mjs → en-Dtk_ot79.mjs} +28 -15
- package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-Dtk_ot79.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-5EMXLEM_.js → index-C2Q_PLWj.js} +1199 -927
- package/dist/_chunks/index-C2Q_PLWj.js.map +1 -0
- package/dist/_chunks/{index-Dpxg3ctD.mjs → index-DLIkNVnQ.mjs} +1217 -945
- package/dist/_chunks/index-DLIkNVnQ.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-P3eKO1Qy.js → layout-7AsWJzZJ.js} +10 -10
- package/dist/_chunks/layout-7AsWJzZJ.js.map +1 -0
- package/dist/_chunks/{layout-C0INpKap.mjs → layout-qE8qkNH_.mjs} +9 -8
- package/dist/_chunks/layout-qE8qkNH_.mjs.map +1 -0
- 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-FBRRBWeO.mjs → relations-BjHH_1Am.mjs} +6 -7
- package/dist/_chunks/relations-BjHH_1Am.mjs.map +1 -0
- package/dist/_chunks/{relations-B1y0K6LE.js → relations-EifVzf_2.js} +6 -7
- package/dist/_chunks/relations-EifVzf_2.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 +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +5 -4
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/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/constants.d.ts +1 -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/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +486 -219
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +486 -218
- 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 +15 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +3 -3
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/constants.d.ts +2 -0
- package/dist/server/src/preview/constants.d.ts.map +1 -0
- package/dist/server/src/preview/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 +8 -8
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
- package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/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 +15 -15
- package/dist/_chunks/EditViewPage-BSVmMpRd.js.map +0 -1
- package/dist/_chunks/EditViewPage-C3tIZ8F5.mjs.map +0 -1
- package/dist/_chunks/Field-BvuT8cGL.mjs.map +0 -1
- package/dist/_chunks/Field-DUCVth4C.js.map +0 -1
- package/dist/_chunks/Form-BZmDNVr9.mjs.map +0 -1
- package/dist/_chunks/Form-Cpl4W1ak.js.map +0 -1
- package/dist/_chunks/History-Cq_Hrzuu.mjs.map +0 -1
- package/dist/_chunks/History-D4U2YISB.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Bny6CdWe.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-W-KQHmBv.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-HBBnJa8K.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-O8F1pBJo.js.map +0 -1
- package/dist/_chunks/Relations-C4gGfZRv.js.map +0 -1
- package/dist/_chunks/Relations-vFZ6Wasg.mjs.map +0 -1
- package/dist/_chunks/index-5EMXLEM_.js.map +0 -1
- package/dist/_chunks/index-Dpxg3ctD.mjs.map +0 -1
- package/dist/_chunks/layout-C0INpKap.mjs.map +0 -1
- package/dist/_chunks/layout-P3eKO1Qy.js.map +0 -1
- package/dist/_chunks/relations-B1y0K6LE.js.map +0 -1
- package/dist/_chunks/relations-FBRRBWeO.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
|
-
import { useParams,
|
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) : [];
|
@@ -158,7 +174,8 @@ const contentManagerApi = adminApi.enhanceEndpoints({
|
|
158
174
|
"Document",
|
159
175
|
"InitialData",
|
160
176
|
"HistoryVersion",
|
161
|
-
"Relations"
|
177
|
+
"Relations",
|
178
|
+
"UidAvailability"
|
162
179
|
]
|
163
180
|
});
|
164
181
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -188,7 +205,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
188
205
|
params
|
189
206
|
}
|
190
207
|
}),
|
191
|
-
invalidatesTags: (_result, _error, { model }) => [
|
208
|
+
invalidatesTags: (_result, _error, { model }) => [
|
209
|
+
{ type: "Document", id: `${model}_LIST` },
|
210
|
+
{ type: "UidAvailability", id: model }
|
211
|
+
]
|
192
212
|
}),
|
193
213
|
/**
|
194
214
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -205,7 +225,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
205
225
|
}),
|
206
226
|
invalidatesTags: (result, _error, { model }) => [
|
207
227
|
{ type: "Document", id: `${model}_LIST` },
|
208
|
-
"Relations"
|
228
|
+
"Relations",
|
229
|
+
{ type: "UidAvailability", id: model }
|
209
230
|
]
|
210
231
|
}),
|
211
232
|
deleteDocument: builder.mutation({
|
@@ -246,7 +267,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
246
267
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
247
268
|
},
|
248
269
|
{ type: "Document", id: `${model}_LIST` },
|
249
|
-
"Relations"
|
270
|
+
"Relations",
|
271
|
+
{ type: "UidAvailability", id: model }
|
250
272
|
];
|
251
273
|
}
|
252
274
|
}),
|
@@ -259,7 +281,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
259
281
|
url: `/content-manager/collection-types/${model}`,
|
260
282
|
method: "GET",
|
261
283
|
config: {
|
262
|
-
params
|
284
|
+
params: stringify(params, { encode: true })
|
263
285
|
}
|
264
286
|
}),
|
265
287
|
providesTags: (result, _error, arg) => {
|
@@ -371,7 +393,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
371
393
|
type: "Document",
|
372
394
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
373
395
|
},
|
374
|
-
"Relations"
|
396
|
+
"Relations",
|
397
|
+
{ type: "UidAvailability", id: model }
|
375
398
|
];
|
376
399
|
},
|
377
400
|
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
@@ -437,8 +460,7 @@ const {
|
|
437
460
|
useUnpublishManyDocumentsMutation
|
438
461
|
} = documentApi;
|
439
462
|
const buildValidParams = (query) => {
|
440
|
-
if (!query)
|
441
|
-
return query;
|
463
|
+
if (!query) return query;
|
442
464
|
const { plugins: _, ...validQueryParams } = {
|
443
465
|
...query,
|
444
466
|
...Object.values(query?.plugins ?? {}).reduce(
|
@@ -446,28 +468,44 @@ const buildValidParams = (query) => {
|
|
446
468
|
{}
|
447
469
|
)
|
448
470
|
};
|
449
|
-
if ("_q" in validQueryParams) {
|
450
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
451
|
-
}
|
452
471
|
return validQueryParams;
|
453
472
|
};
|
454
473
|
const isBaseQueryError = (error) => {
|
455
474
|
return error.name !== void 0;
|
456
475
|
};
|
457
|
-
const
|
476
|
+
const arrayValidator = (attribute, options) => ({
|
477
|
+
message: translatedErrors.required,
|
478
|
+
test(value) {
|
479
|
+
if (options.status === "draft") {
|
480
|
+
return true;
|
481
|
+
}
|
482
|
+
if (!attribute.required) {
|
483
|
+
return true;
|
484
|
+
}
|
485
|
+
if (!value) {
|
486
|
+
return false;
|
487
|
+
}
|
488
|
+
if (Array.isArray(value) && value.length === 0) {
|
489
|
+
return false;
|
490
|
+
}
|
491
|
+
return true;
|
492
|
+
}
|
493
|
+
});
|
494
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
458
495
|
const createModelSchema = (attributes2) => yup.object().shape(
|
459
496
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
460
497
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
461
498
|
return acc;
|
462
499
|
}
|
463
500
|
const validations = [
|
501
|
+
addNullableValidation,
|
464
502
|
addRequiredValidation,
|
465
503
|
addMinLengthValidation,
|
466
504
|
addMaxLengthValidation,
|
467
505
|
addMinValidation,
|
468
506
|
addMaxValidation,
|
469
507
|
addRegexValidation
|
470
|
-
].map((fn) => fn(attribute));
|
508
|
+
].map((fn) => fn(attribute, options));
|
471
509
|
const transformSchema = pipe(...validations);
|
472
510
|
switch (attribute.type) {
|
473
511
|
case "component": {
|
@@ -477,12 +515,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
477
515
|
...acc,
|
478
516
|
[name]: transformSchema(
|
479
517
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
480
|
-
)
|
518
|
+
).test(arrayValidator(attribute, options))
|
481
519
|
};
|
482
520
|
} else {
|
483
521
|
return {
|
484
522
|
...acc,
|
485
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
523
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
486
524
|
};
|
487
525
|
}
|
488
526
|
}
|
@@ -504,7 +542,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
504
542
|
}
|
505
543
|
)
|
506
544
|
)
|
507
|
-
)
|
545
|
+
).test(arrayValidator(attribute, options))
|
508
546
|
};
|
509
547
|
case "relation":
|
510
548
|
return {
|
@@ -516,7 +554,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
516
554
|
} else if (Array.isArray(value)) {
|
517
555
|
return yup.array().of(
|
518
556
|
yup.object().shape({
|
519
|
-
id: yup.
|
557
|
+
id: yup.number().required()
|
520
558
|
})
|
521
559
|
);
|
522
560
|
} else if (typeof value === "object") {
|
@@ -594,13 +632,7 @@ const createAttributeSchema = (attribute) => {
|
|
594
632
|
return yup.mixed();
|
595
633
|
}
|
596
634
|
};
|
597
|
-
const
|
598
|
-
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
599
|
-
return schema.min(1, translatedErrors.required);
|
600
|
-
}
|
601
|
-
if (attribute.required && attribute.type !== "relation") {
|
602
|
-
return schema.required(translatedErrors.required);
|
603
|
-
}
|
635
|
+
const nullableSchema = (schema) => {
|
604
636
|
return schema?.nullable ? schema.nullable() : (
|
605
637
|
// In some cases '.nullable' will not be available on the schema.
|
606
638
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -608,7 +640,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
608
640
|
schema
|
609
641
|
);
|
610
642
|
};
|
611
|
-
const
|
643
|
+
const addNullableValidation = () => (schema) => {
|
644
|
+
return nullableSchema(schema);
|
645
|
+
};
|
646
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
647
|
+
if (options.status === "draft" || !attribute.required) {
|
648
|
+
return schema;
|
649
|
+
}
|
650
|
+
if (attribute.required && "required" in schema) {
|
651
|
+
return schema.required(translatedErrors.required);
|
652
|
+
}
|
653
|
+
return schema;
|
654
|
+
};
|
655
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
656
|
+
if (options.status === "draft") {
|
657
|
+
return schema;
|
658
|
+
}
|
612
659
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
613
660
|
return schema.min(attribute.minLength, {
|
614
661
|
...translatedErrors.minLength,
|
@@ -630,32 +677,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
630
677
|
}
|
631
678
|
return schema;
|
632
679
|
};
|
633
|
-
const addMinValidation = (attribute) => (schema) => {
|
634
|
-
if ("
|
680
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
681
|
+
if (options.status === "draft") {
|
682
|
+
return schema;
|
683
|
+
}
|
684
|
+
if ("min" in attribute && "min" in schema) {
|
635
685
|
const min = toInteger(attribute.min);
|
636
|
-
if (
|
637
|
-
if (!attribute.required && "test" in schema && min) {
|
638
|
-
return schema.test(
|
639
|
-
"custom-min",
|
640
|
-
{
|
641
|
-
...translatedErrors.min,
|
642
|
-
values: {
|
643
|
-
min: attribute.min
|
644
|
-
}
|
645
|
-
},
|
646
|
-
(value) => {
|
647
|
-
if (!value) {
|
648
|
-
return true;
|
649
|
-
}
|
650
|
-
if (Array.isArray(value) && value.length === 0) {
|
651
|
-
return true;
|
652
|
-
}
|
653
|
-
return value.length >= min;
|
654
|
-
}
|
655
|
-
);
|
656
|
-
}
|
657
|
-
}
|
658
|
-
if ("min" in schema && min) {
|
686
|
+
if (min) {
|
659
687
|
return schema.min(min, {
|
660
688
|
...translatedErrors.min,
|
661
689
|
values: {
|
@@ -773,19 +801,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
773
801
|
}, {});
|
774
802
|
return componentsByKey;
|
775
803
|
};
|
776
|
-
const
|
804
|
+
const HOOKS = {
|
805
|
+
/**
|
806
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
807
|
+
* @constant
|
808
|
+
* @type {string}
|
809
|
+
*/
|
810
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
811
|
+
/**
|
812
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
813
|
+
* @constant
|
814
|
+
* @type {string}
|
815
|
+
*/
|
816
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
817
|
+
/**
|
818
|
+
* Hook that allows to mutate the CM's edit view layout
|
819
|
+
* @constant
|
820
|
+
* @type {string}
|
821
|
+
*/
|
822
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
823
|
+
/**
|
824
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
825
|
+
* @constant
|
826
|
+
* @type {string}
|
827
|
+
*/
|
828
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
829
|
+
};
|
830
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
831
|
+
endpoints: (builder) => ({
|
832
|
+
getContentTypeConfiguration: builder.query({
|
833
|
+
query: (uid) => ({
|
834
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
835
|
+
method: "GET"
|
836
|
+
}),
|
837
|
+
transformResponse: (response) => response.data,
|
838
|
+
providesTags: (_result, _error, uid) => [
|
839
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
840
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
841
|
+
]
|
842
|
+
}),
|
843
|
+
getAllContentTypeSettings: builder.query({
|
844
|
+
query: () => "/content-manager/content-types-settings",
|
845
|
+
transformResponse: (response) => response.data,
|
846
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
847
|
+
}),
|
848
|
+
updateContentTypeConfiguration: builder.mutation({
|
849
|
+
query: ({ uid, ...body }) => ({
|
850
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
851
|
+
method: "PUT",
|
852
|
+
data: body
|
853
|
+
}),
|
854
|
+
transformResponse: (response) => response.data,
|
855
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
856
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
857
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
858
|
+
// Is this necessary?
|
859
|
+
{ type: "InitialData" }
|
860
|
+
]
|
861
|
+
})
|
862
|
+
})
|
863
|
+
});
|
864
|
+
const {
|
865
|
+
useGetContentTypeConfigurationQuery,
|
866
|
+
useGetAllContentTypeSettingsQuery,
|
867
|
+
useUpdateContentTypeConfigurationMutation
|
868
|
+
} = contentTypesApi;
|
869
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
870
|
+
const { type } = attribute;
|
871
|
+
if (type === "relation") {
|
872
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
873
|
+
}
|
874
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
875
|
+
};
|
876
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
877
|
+
if (!mainFieldName) {
|
878
|
+
return void 0;
|
879
|
+
}
|
880
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
881
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
882
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
883
|
+
);
|
884
|
+
return {
|
885
|
+
name: mainFieldName,
|
886
|
+
type: mainFieldType ?? "string"
|
887
|
+
};
|
888
|
+
};
|
889
|
+
const DEFAULT_SETTINGS = {
|
890
|
+
bulkable: false,
|
891
|
+
filterable: false,
|
892
|
+
searchable: false,
|
893
|
+
pagination: false,
|
894
|
+
defaultSortBy: "",
|
895
|
+
defaultSortOrder: "asc",
|
896
|
+
mainField: "id",
|
897
|
+
pageSize: 10
|
898
|
+
};
|
899
|
+
const useDocumentLayout = (model) => {
|
900
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
901
|
+
const [{ query }] = useQueryParams();
|
902
|
+
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
777
903
|
const { toggleNotification } = useNotification();
|
778
904
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
905
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
779
906
|
const {
|
780
|
-
|
781
|
-
isLoading:
|
782
|
-
|
783
|
-
|
784
|
-
} =
|
785
|
-
|
786
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
787
|
-
});
|
788
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
907
|
+
data,
|
908
|
+
isLoading: isLoadingConfigs,
|
909
|
+
error,
|
910
|
+
isFetching: isFetchingConfigs
|
911
|
+
} = useGetContentTypeConfigurationQuery(model);
|
912
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
789
913
|
React.useEffect(() => {
|
790
914
|
if (error) {
|
791
915
|
toggleNotification({
|
@@ -793,397 +917,654 @@ const useDocument = (args, opts) => {
|
|
793
917
|
message: formatAPIError(error)
|
794
918
|
});
|
795
919
|
}
|
796
|
-
}, [
|
797
|
-
const
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
(document) => {
|
805
|
-
if (!validationSchema) {
|
806
|
-
throw new Error(
|
807
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
808
|
-
);
|
809
|
-
}
|
810
|
-
try {
|
811
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
812
|
-
return null;
|
813
|
-
} catch (error2) {
|
814
|
-
if (error2 instanceof ValidationError) {
|
815
|
-
return getYupValidationErrors(error2);
|
816
|
-
}
|
817
|
-
throw error2;
|
818
|
-
}
|
920
|
+
}, [error, formatAPIError, toggleNotification]);
|
921
|
+
const editLayout = React.useMemo(
|
922
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
923
|
+
layout: [],
|
924
|
+
components: {},
|
925
|
+
metadatas: {},
|
926
|
+
options: {},
|
927
|
+
settings: DEFAULT_SETTINGS
|
819
928
|
},
|
820
|
-
[
|
929
|
+
[data, isLoading, schemas, schema, components]
|
930
|
+
);
|
931
|
+
const listLayout = React.useMemo(() => {
|
932
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
933
|
+
layout: [],
|
934
|
+
metadatas: {},
|
935
|
+
options: {},
|
936
|
+
settings: DEFAULT_SETTINGS
|
937
|
+
};
|
938
|
+
}, [data, isLoading, schemas, schema, components]);
|
939
|
+
const { layout: edit } = React.useMemo(
|
940
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
941
|
+
layout: editLayout,
|
942
|
+
query
|
943
|
+
}),
|
944
|
+
[editLayout, query, runHookWaterfall]
|
821
945
|
);
|
822
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
823
946
|
return {
|
824
|
-
|
825
|
-
document: data?.data,
|
826
|
-
meta: data?.meta,
|
947
|
+
error,
|
827
948
|
isLoading,
|
828
|
-
|
829
|
-
|
830
|
-
};
|
831
|
-
};
|
832
|
-
const useDoc = () => {
|
833
|
-
const { id, slug, collectionType, origin } = useParams();
|
834
|
-
const [{ query }] = useQueryParams();
|
835
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
836
|
-
if (!collectionType) {
|
837
|
-
throw new Error("Could not find collectionType in url params");
|
838
|
-
}
|
839
|
-
if (!slug) {
|
840
|
-
throw new Error("Could not find model in url params");
|
841
|
-
}
|
842
|
-
return {
|
843
|
-
collectionType,
|
844
|
-
model: slug,
|
845
|
-
id: origin || id === "create" ? void 0 : id,
|
846
|
-
...useDocument(
|
847
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
848
|
-
{
|
849
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
850
|
-
}
|
851
|
-
)
|
949
|
+
edit,
|
950
|
+
list: listLayout
|
852
951
|
};
|
853
952
|
};
|
854
|
-
const
|
855
|
-
|
856
|
-
|
857
|
-
}
|
858
|
-
return Object.keys(trad).reduce((acc, current) => {
|
859
|
-
acc[`${pluginId}.${current}`] = trad[current];
|
860
|
-
return acc;
|
861
|
-
}, {});
|
862
|
-
};
|
863
|
-
const getTranslation = (id) => `content-manager.${id}`;
|
864
|
-
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
865
|
-
id: "notification.error",
|
866
|
-
defaultMessage: "An error occurred, please try again"
|
953
|
+
const useDocLayout = () => {
|
954
|
+
const { model } = useDoc();
|
955
|
+
return useDocumentLayout(model);
|
867
956
|
};
|
868
|
-
const
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
const
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
return { error: res.error };
|
890
|
-
}
|
891
|
-
toggleNotification({
|
892
|
-
type: "success",
|
893
|
-
message: formatMessage({
|
894
|
-
id: getTranslation("success.record.delete"),
|
895
|
-
defaultMessage: "Deleted document"
|
896
|
-
})
|
897
|
-
});
|
898
|
-
trackUsage("didDeleteEntry", trackerProperty);
|
899
|
-
return res.data;
|
900
|
-
} catch (err) {
|
901
|
-
toggleNotification({
|
902
|
-
type: "danger",
|
903
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
904
|
-
});
|
905
|
-
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
906
|
-
throw err;
|
957
|
+
const formatEditLayout = (data, {
|
958
|
+
schemas,
|
959
|
+
schema,
|
960
|
+
components
|
961
|
+
}) => {
|
962
|
+
let currentPanelIndex = 0;
|
963
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
964
|
+
data.contentType.layouts.edit,
|
965
|
+
schema?.attributes,
|
966
|
+
data.contentType.metadatas,
|
967
|
+
{ configurations: data.components, schemas: components },
|
968
|
+
schemas
|
969
|
+
).reduce((panels, row) => {
|
970
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
971
|
+
panels.push([row]);
|
972
|
+
currentPanelIndex += 2;
|
973
|
+
} else {
|
974
|
+
if (!panels[currentPanelIndex]) {
|
975
|
+
panels.push([row]);
|
976
|
+
} else {
|
977
|
+
panels[currentPanelIndex].push(row);
|
907
978
|
}
|
908
|
-
}
|
909
|
-
|
910
|
-
);
|
911
|
-
const
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
message: formatAPIError(res.error)
|
925
|
-
});
|
926
|
-
return { error: res.error };
|
979
|
+
}
|
980
|
+
return panels;
|
981
|
+
}, []);
|
982
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
983
|
+
(acc, [uid, configuration]) => {
|
984
|
+
acc[uid] = {
|
985
|
+
layout: convertEditLayoutToFieldLayouts(
|
986
|
+
configuration.layouts.edit,
|
987
|
+
components[uid].attributes,
|
988
|
+
configuration.metadatas,
|
989
|
+
{ configurations: data.components, schemas: components }
|
990
|
+
),
|
991
|
+
settings: {
|
992
|
+
...configuration.settings,
|
993
|
+
icon: components[uid].info.icon,
|
994
|
+
displayName: components[uid].info.displayName
|
927
995
|
}
|
928
|
-
|
929
|
-
|
930
|
-
title: formatMessage({
|
931
|
-
id: getTranslation("success.records.delete"),
|
932
|
-
defaultMessage: "Successfully deleted."
|
933
|
-
}),
|
934
|
-
message: ""
|
935
|
-
});
|
936
|
-
trackUsage("didBulkDeleteEntries");
|
937
|
-
return res.data;
|
938
|
-
} catch (err) {
|
939
|
-
toggleNotification({
|
940
|
-
type: "danger",
|
941
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
942
|
-
});
|
943
|
-
trackUsage("didNotBulkDeleteEntries");
|
944
|
-
throw err;
|
945
|
-
}
|
996
|
+
};
|
997
|
+
return acc;
|
946
998
|
},
|
947
|
-
|
999
|
+
{}
|
948
1000
|
);
|
949
|
-
const
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
model,
|
956
|
-
documentId,
|
957
|
-
params
|
958
|
-
});
|
959
|
-
if ("error" in res) {
|
960
|
-
toggleNotification({
|
961
|
-
type: "danger",
|
962
|
-
message: formatAPIError(res.error)
|
963
|
-
});
|
964
|
-
return { error: res.error };
|
965
|
-
}
|
966
|
-
toggleNotification({
|
967
|
-
type: "success",
|
968
|
-
message: formatMessage({
|
969
|
-
id: "content-manager.success.record.discard",
|
970
|
-
defaultMessage: "Changes discarded"
|
971
|
-
})
|
972
|
-
});
|
973
|
-
return res.data;
|
974
|
-
} catch (err) {
|
975
|
-
toggleNotification({
|
976
|
-
type: "danger",
|
977
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
978
|
-
});
|
979
|
-
throw err;
|
980
|
-
}
|
1001
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1002
|
+
(acc, [attribute, metadata]) => {
|
1003
|
+
return {
|
1004
|
+
...acc,
|
1005
|
+
[attribute]: metadata.edit
|
1006
|
+
};
|
981
1007
|
},
|
982
|
-
|
1008
|
+
{}
|
983
1009
|
);
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
model,
|
992
|
-
documentId,
|
993
|
-
data,
|
994
|
-
params
|
995
|
-
});
|
996
|
-
if ("error" in res) {
|
997
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
998
|
-
return { error: res.error };
|
999
|
-
}
|
1000
|
-
trackUsage("didPublishEntry");
|
1001
|
-
toggleNotification({
|
1002
|
-
type: "success",
|
1003
|
-
message: formatMessage({
|
1004
|
-
id: getTranslation("success.record.publish"),
|
1005
|
-
defaultMessage: "Published document"
|
1006
|
-
})
|
1007
|
-
});
|
1008
|
-
return res.data;
|
1009
|
-
} catch (err) {
|
1010
|
-
toggleNotification({
|
1011
|
-
type: "danger",
|
1012
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1013
|
-
});
|
1014
|
-
throw err;
|
1015
|
-
}
|
1010
|
+
return {
|
1011
|
+
layout: panelledEditAttributes,
|
1012
|
+
components: componentEditAttributes,
|
1013
|
+
metadatas: editMetadatas,
|
1014
|
+
settings: {
|
1015
|
+
...data.contentType.settings,
|
1016
|
+
displayName: schema?.info.displayName
|
1016
1017
|
},
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
return { error: res.error };
|
1031
|
-
}
|
1032
|
-
toggleNotification({
|
1033
|
-
type: "success",
|
1034
|
-
message: formatMessage({
|
1035
|
-
id: getTranslation("success.record.publish"),
|
1036
|
-
defaultMessage: "Published document"
|
1037
|
-
})
|
1038
|
-
});
|
1039
|
-
return res.data;
|
1040
|
-
} catch (err) {
|
1041
|
-
toggleNotification({
|
1042
|
-
type: "danger",
|
1043
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1044
|
-
});
|
1045
|
-
throw err;
|
1018
|
+
options: {
|
1019
|
+
...schema?.options,
|
1020
|
+
...schema?.pluginOptions,
|
1021
|
+
...data.contentType.options
|
1022
|
+
}
|
1023
|
+
};
|
1024
|
+
};
|
1025
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1026
|
+
return rows.map(
|
1027
|
+
(row) => row.map((field) => {
|
1028
|
+
const attribute = attributes[field.name];
|
1029
|
+
if (!attribute) {
|
1030
|
+
return null;
|
1046
1031
|
}
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1032
|
+
const { edit: metadata } = metadatas[field.name];
|
1033
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1034
|
+
return {
|
1035
|
+
attribute,
|
1036
|
+
disabled: !metadata.editable,
|
1037
|
+
hint: metadata.description,
|
1038
|
+
label: metadata.label ?? "",
|
1039
|
+
name: field.name,
|
1040
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1041
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1042
|
+
schemas,
|
1043
|
+
components: components?.schemas ?? {}
|
1044
|
+
}),
|
1045
|
+
placeholder: metadata.placeholder ?? "",
|
1046
|
+
required: attribute.required ?? false,
|
1047
|
+
size: field.size,
|
1048
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1049
|
+
visible: metadata.visible ?? true,
|
1050
|
+
type: attribute.type
|
1051
|
+
};
|
1052
|
+
}).filter((field) => field !== null)
|
1055
1053
|
);
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1054
|
+
};
|
1055
|
+
const formatListLayout = (data, {
|
1056
|
+
schemas,
|
1057
|
+
schema,
|
1058
|
+
components
|
1059
|
+
}) => {
|
1060
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1061
|
+
(acc, [attribute, metadata]) => {
|
1062
|
+
return {
|
1063
|
+
...acc,
|
1064
|
+
[attribute]: metadata.list
|
1065
|
+
};
|
1066
|
+
},
|
1067
|
+
{}
|
1068
|
+
);
|
1069
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1070
|
+
data.contentType.layouts.list,
|
1071
|
+
schema?.attributes,
|
1072
|
+
listMetadatas,
|
1073
|
+
{ configurations: data.components, schemas: components },
|
1074
|
+
schemas
|
1075
|
+
);
|
1076
|
+
return {
|
1077
|
+
layout: listAttributes,
|
1078
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1079
|
+
metadatas: listMetadatas,
|
1080
|
+
options: {
|
1081
|
+
...schema?.options,
|
1082
|
+
...schema?.pluginOptions,
|
1083
|
+
...data.contentType.options
|
1084
|
+
}
|
1085
|
+
};
|
1086
|
+
};
|
1087
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1088
|
+
return columns.map((name) => {
|
1089
|
+
const attribute = attributes[name];
|
1090
|
+
if (!attribute) {
|
1091
|
+
return null;
|
1092
|
+
}
|
1093
|
+
const metadata = metadatas[name];
|
1094
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1095
|
+
return {
|
1096
|
+
attribute,
|
1097
|
+
label: metadata.label ?? "",
|
1098
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1099
|
+
schemas,
|
1100
|
+
components: components?.schemas ?? {}
|
1101
|
+
}),
|
1102
|
+
name,
|
1103
|
+
searchable: metadata.searchable ?? true,
|
1104
|
+
sortable: metadata.sortable ?? true
|
1105
|
+
};
|
1106
|
+
}).filter((field) => field !== null);
|
1107
|
+
};
|
1108
|
+
const useDocument = (args, opts) => {
|
1109
|
+
const { toggleNotification } = useNotification();
|
1110
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1111
|
+
const {
|
1112
|
+
currentData: data,
|
1113
|
+
isLoading: isLoadingDocument,
|
1114
|
+
isFetching: isFetchingDocument,
|
1115
|
+
error
|
1116
|
+
} = useGetDocumentQuery(args, {
|
1117
|
+
...opts,
|
1118
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1119
|
+
});
|
1120
|
+
const {
|
1121
|
+
components,
|
1122
|
+
schema,
|
1123
|
+
schemas,
|
1124
|
+
isLoading: isLoadingSchema
|
1125
|
+
} = useContentTypeSchema(args.model);
|
1126
|
+
React.useEffect(() => {
|
1127
|
+
if (error) {
|
1128
|
+
toggleNotification({
|
1129
|
+
type: "danger",
|
1130
|
+
message: formatAPIError(error)
|
1131
|
+
});
|
1132
|
+
}
|
1133
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1134
|
+
const validationSchema = React.useMemo(() => {
|
1135
|
+
if (!schema) {
|
1136
|
+
return null;
|
1137
|
+
}
|
1138
|
+
return createYupSchema(schema.attributes, components);
|
1139
|
+
}, [schema, components]);
|
1140
|
+
const validate = React.useCallback(
|
1141
|
+
(document) => {
|
1142
|
+
if (!validationSchema) {
|
1143
|
+
throw new Error(
|
1144
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1145
|
+
);
|
1146
|
+
}
|
1059
1147
|
try {
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
data,
|
1066
|
-
params
|
1067
|
-
});
|
1068
|
-
if ("error" in res) {
|
1069
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1070
|
-
trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
|
1071
|
-
return { error: res.error };
|
1148
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1149
|
+
return null;
|
1150
|
+
} catch (error2) {
|
1151
|
+
if (error2 instanceof ValidationError) {
|
1152
|
+
return getYupValidationErrors(error2);
|
1072
1153
|
}
|
1073
|
-
|
1074
|
-
toggleNotification({
|
1075
|
-
type: "success",
|
1076
|
-
message: formatMessage({
|
1077
|
-
id: getTranslation("success.record.save"),
|
1078
|
-
defaultMessage: "Saved document"
|
1079
|
-
})
|
1080
|
-
});
|
1081
|
-
return res.data;
|
1082
|
-
} catch (err) {
|
1083
|
-
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1084
|
-
toggleNotification({
|
1085
|
-
type: "danger",
|
1086
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1087
|
-
});
|
1088
|
-
throw err;
|
1154
|
+
throw error2;
|
1089
1155
|
}
|
1090
1156
|
},
|
1091
|
-
[
|
1157
|
+
[validationSchema]
|
1092
1158
|
);
|
1093
|
-
const
|
1094
|
-
const
|
1095
|
-
|
1159
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1160
|
+
const hasError = !!error;
|
1161
|
+
return {
|
1162
|
+
components,
|
1163
|
+
document: data?.data,
|
1164
|
+
meta: data?.meta,
|
1165
|
+
isLoading,
|
1166
|
+
hasError,
|
1167
|
+
schema,
|
1168
|
+
schemas,
|
1169
|
+
validate
|
1170
|
+
};
|
1171
|
+
};
|
1172
|
+
const useDoc = () => {
|
1173
|
+
const { id, slug, collectionType, origin } = useParams();
|
1174
|
+
const [{ query }] = useQueryParams();
|
1175
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1176
|
+
if (!collectionType) {
|
1177
|
+
throw new Error("Could not find collectionType in url params");
|
1178
|
+
}
|
1179
|
+
if (!slug) {
|
1180
|
+
throw new Error("Could not find model in url params");
|
1181
|
+
}
|
1182
|
+
const document = useDocument(
|
1183
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1184
|
+
{
|
1185
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1186
|
+
}
|
1187
|
+
);
|
1188
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
1189
|
+
return {
|
1190
|
+
collectionType,
|
1191
|
+
model: slug,
|
1192
|
+
id: returnId,
|
1193
|
+
...document
|
1194
|
+
};
|
1195
|
+
};
|
1196
|
+
const useContentManagerContext = () => {
|
1197
|
+
const {
|
1198
|
+
collectionType,
|
1199
|
+
model,
|
1200
|
+
id,
|
1201
|
+
components,
|
1202
|
+
isLoading: isLoadingDoc,
|
1203
|
+
schema,
|
1204
|
+
schemas
|
1205
|
+
} = useDoc();
|
1206
|
+
const layout = useDocumentLayout(model);
|
1207
|
+
const form = useForm("useContentManagerContext", (state) => state);
|
1208
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1209
|
+
const slug = model;
|
1210
|
+
const isCreatingEntry = id === "create";
|
1211
|
+
useContentTypeSchema();
|
1212
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1213
|
+
const error = layout.error;
|
1214
|
+
return {
|
1215
|
+
error,
|
1216
|
+
isLoading,
|
1217
|
+
// Base metadata
|
1218
|
+
model,
|
1219
|
+
collectionType,
|
1220
|
+
id,
|
1221
|
+
slug,
|
1222
|
+
isCreatingEntry,
|
1223
|
+
isSingleType,
|
1224
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1225
|
+
// All schema infos
|
1226
|
+
components,
|
1227
|
+
contentType: schema,
|
1228
|
+
contentTypes: schemas,
|
1229
|
+
// Form state
|
1230
|
+
form,
|
1231
|
+
// layout infos
|
1232
|
+
layout
|
1233
|
+
};
|
1234
|
+
};
|
1235
|
+
const prefixPluginTranslations = (trad, pluginId) => {
|
1236
|
+
return Object.keys(trad).reduce((acc, current) => {
|
1237
|
+
acc[`${pluginId}.${current}`] = trad[current];
|
1238
|
+
return acc;
|
1239
|
+
}, {});
|
1240
|
+
};
|
1241
|
+
const getTranslation = (id) => `content-manager.${id}`;
|
1242
|
+
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
1243
|
+
id: "notification.error",
|
1244
|
+
defaultMessage: "An error occurred, please try again"
|
1245
|
+
};
|
1246
|
+
const useDocumentActions = () => {
|
1247
|
+
const { toggleNotification } = useNotification();
|
1248
|
+
const { formatMessage } = useIntl();
|
1249
|
+
const { trackUsage } = useTracking();
|
1250
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1251
|
+
const navigate = useNavigate();
|
1252
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
1253
|
+
const [deleteDocument] = useDeleteDocumentMutation();
|
1254
|
+
const _delete = React.useCallback(
|
1255
|
+
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
1096
1256
|
try {
|
1097
|
-
trackUsage("
|
1098
|
-
const res = await
|
1257
|
+
trackUsage("willDeleteEntry", trackerProperty);
|
1258
|
+
const res = await deleteDocument({
|
1099
1259
|
collectionType,
|
1100
1260
|
model,
|
1101
1261
|
documentId,
|
1102
|
-
params
|
1103
|
-
data: {
|
1104
|
-
discardDraft
|
1105
|
-
}
|
1262
|
+
params
|
1106
1263
|
});
|
1107
1264
|
if ("error" in res) {
|
1108
|
-
toggleNotification({
|
1265
|
+
toggleNotification({
|
1266
|
+
type: "danger",
|
1267
|
+
message: formatAPIError(res.error)
|
1268
|
+
});
|
1109
1269
|
return { error: res.error };
|
1110
1270
|
}
|
1111
|
-
trackUsage("didUnpublishEntry");
|
1112
1271
|
toggleNotification({
|
1113
1272
|
type: "success",
|
1114
1273
|
message: formatMessage({
|
1115
|
-
id: getTranslation("success.record.
|
1116
|
-
defaultMessage: "
|
1274
|
+
id: getTranslation("success.record.delete"),
|
1275
|
+
defaultMessage: "Deleted document"
|
1117
1276
|
})
|
1118
1277
|
});
|
1278
|
+
trackUsage("didDeleteEntry", trackerProperty);
|
1119
1279
|
return res.data;
|
1120
1280
|
} catch (err) {
|
1121
1281
|
toggleNotification({
|
1122
1282
|
type: "danger",
|
1123
1283
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1124
1284
|
});
|
1285
|
+
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
1125
1286
|
throw err;
|
1126
1287
|
}
|
1127
1288
|
},
|
1128
|
-
[trackUsage,
|
1289
|
+
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
1129
1290
|
);
|
1130
|
-
const [
|
1131
|
-
const
|
1291
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1292
|
+
const deleteMany = React.useCallback(
|
1132
1293
|
async ({ model, documentIds, params }) => {
|
1133
1294
|
try {
|
1134
|
-
trackUsage("
|
1135
|
-
const res = await
|
1295
|
+
trackUsage("willBulkDeleteEntries");
|
1296
|
+
const res = await deleteManyDocuments({
|
1136
1297
|
model,
|
1137
1298
|
documentIds,
|
1138
1299
|
params
|
1139
1300
|
});
|
1140
1301
|
if ("error" in res) {
|
1141
|
-
toggleNotification({
|
1302
|
+
toggleNotification({
|
1303
|
+
type: "danger",
|
1304
|
+
message: formatAPIError(res.error)
|
1305
|
+
});
|
1142
1306
|
return { error: res.error };
|
1143
1307
|
}
|
1144
|
-
trackUsage("didBulkUnpublishEntries");
|
1145
1308
|
toggleNotification({
|
1146
1309
|
type: "success",
|
1147
1310
|
title: formatMessage({
|
1148
|
-
id: getTranslation("success.records.
|
1149
|
-
defaultMessage: "Successfully
|
1311
|
+
id: getTranslation("success.records.delete"),
|
1312
|
+
defaultMessage: "Successfully deleted."
|
1150
1313
|
}),
|
1151
1314
|
message: ""
|
1152
1315
|
});
|
1316
|
+
trackUsage("didBulkDeleteEntries");
|
1153
1317
|
return res.data;
|
1154
1318
|
} catch (err) {
|
1155
1319
|
toggleNotification({
|
1156
1320
|
type: "danger",
|
1157
1321
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1158
1322
|
});
|
1159
|
-
trackUsage("
|
1323
|
+
trackUsage("didNotBulkDeleteEntries");
|
1160
1324
|
throw err;
|
1161
1325
|
}
|
1162
1326
|
},
|
1163
|
-
[trackUsage,
|
1327
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1164
1328
|
);
|
1165
|
-
const [
|
1166
|
-
const
|
1167
|
-
async ({ model, params }
|
1329
|
+
const [discardDocument] = useDiscardDocumentMutation();
|
1330
|
+
const discard = React.useCallback(
|
1331
|
+
async ({ collectionType, model, documentId, params }) => {
|
1168
1332
|
try {
|
1169
|
-
const res = await
|
1333
|
+
const res = await discardDocument({
|
1334
|
+
collectionType,
|
1170
1335
|
model,
|
1171
|
-
|
1336
|
+
documentId,
|
1172
1337
|
params
|
1173
1338
|
});
|
1174
1339
|
if ("error" in res) {
|
1175
|
-
toggleNotification({
|
1176
|
-
|
1340
|
+
toggleNotification({
|
1341
|
+
type: "danger",
|
1342
|
+
message: formatAPIError(res.error)
|
1343
|
+
});
|
1177
1344
|
return { error: res.error };
|
1178
1345
|
}
|
1179
|
-
trackUsage("didCreateEntry", trackerProperty);
|
1180
1346
|
toggleNotification({
|
1181
1347
|
type: "success",
|
1182
1348
|
message: formatMessage({
|
1183
|
-
id:
|
1349
|
+
id: "content-manager.success.record.discard",
|
1350
|
+
defaultMessage: "Changes discarded"
|
1351
|
+
})
|
1352
|
+
});
|
1353
|
+
return res.data;
|
1354
|
+
} catch (err) {
|
1355
|
+
toggleNotification({
|
1356
|
+
type: "danger",
|
1357
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1358
|
+
});
|
1359
|
+
throw err;
|
1360
|
+
}
|
1361
|
+
},
|
1362
|
+
[discardDocument, formatAPIError, formatMessage, toggleNotification]
|
1363
|
+
);
|
1364
|
+
const [publishDocument] = usePublishDocumentMutation();
|
1365
|
+
const publish = React.useCallback(
|
1366
|
+
async ({ collectionType, model, documentId, params }, data) => {
|
1367
|
+
try {
|
1368
|
+
trackUsage("willPublishEntry");
|
1369
|
+
const res = await publishDocument({
|
1370
|
+
collectionType,
|
1371
|
+
model,
|
1372
|
+
documentId,
|
1373
|
+
data,
|
1374
|
+
params
|
1375
|
+
});
|
1376
|
+
if ("error" in res) {
|
1377
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1378
|
+
return { error: res.error };
|
1379
|
+
}
|
1380
|
+
trackUsage("didPublishEntry");
|
1381
|
+
toggleNotification({
|
1382
|
+
type: "success",
|
1383
|
+
message: formatMessage({
|
1384
|
+
id: getTranslation("success.record.publish"),
|
1385
|
+
defaultMessage: "Published document"
|
1386
|
+
})
|
1387
|
+
});
|
1388
|
+
return res.data;
|
1389
|
+
} catch (err) {
|
1390
|
+
toggleNotification({
|
1391
|
+
type: "danger",
|
1392
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1393
|
+
});
|
1394
|
+
throw err;
|
1395
|
+
}
|
1396
|
+
},
|
1397
|
+
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1398
|
+
);
|
1399
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1400
|
+
const publishMany = React.useCallback(
|
1401
|
+
async ({ model, documentIds, params }) => {
|
1402
|
+
try {
|
1403
|
+
const res = await publishManyDocuments({
|
1404
|
+
model,
|
1405
|
+
documentIds,
|
1406
|
+
params
|
1407
|
+
});
|
1408
|
+
if ("error" in res) {
|
1409
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1410
|
+
return { error: res.error };
|
1411
|
+
}
|
1412
|
+
toggleNotification({
|
1413
|
+
type: "success",
|
1414
|
+
message: formatMessage({
|
1415
|
+
id: getTranslation("success.record.publish"),
|
1416
|
+
defaultMessage: "Published document"
|
1417
|
+
})
|
1418
|
+
});
|
1419
|
+
return res.data;
|
1420
|
+
} catch (err) {
|
1421
|
+
toggleNotification({
|
1422
|
+
type: "danger",
|
1423
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1424
|
+
});
|
1425
|
+
throw err;
|
1426
|
+
}
|
1427
|
+
},
|
1428
|
+
[
|
1429
|
+
// trackUsage,
|
1430
|
+
publishManyDocuments,
|
1431
|
+
toggleNotification,
|
1432
|
+
formatMessage,
|
1433
|
+
formatAPIError
|
1434
|
+
]
|
1435
|
+
);
|
1436
|
+
const [updateDocument] = useUpdateDocumentMutation();
|
1437
|
+
const update = React.useCallback(
|
1438
|
+
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
1439
|
+
try {
|
1440
|
+
trackUsage("willEditEntry", trackerProperty);
|
1441
|
+
const res = await updateDocument({
|
1442
|
+
collectionType,
|
1443
|
+
model,
|
1444
|
+
documentId,
|
1445
|
+
data,
|
1446
|
+
params
|
1447
|
+
});
|
1448
|
+
if ("error" in res) {
|
1449
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1450
|
+
trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
|
1451
|
+
return { error: res.error };
|
1452
|
+
}
|
1453
|
+
trackUsage("didEditEntry", trackerProperty);
|
1454
|
+
toggleNotification({
|
1455
|
+
type: "success",
|
1456
|
+
message: formatMessage({
|
1457
|
+
id: getTranslation("success.record.save"),
|
1458
|
+
defaultMessage: "Saved document"
|
1459
|
+
})
|
1460
|
+
});
|
1461
|
+
return res.data;
|
1462
|
+
} catch (err) {
|
1463
|
+
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1464
|
+
toggleNotification({
|
1465
|
+
type: "danger",
|
1466
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1467
|
+
});
|
1468
|
+
throw err;
|
1469
|
+
}
|
1470
|
+
},
|
1471
|
+
[trackUsage, updateDocument, toggleNotification, formatMessage, formatAPIError]
|
1472
|
+
);
|
1473
|
+
const [unpublishDocument] = useUnpublishDocumentMutation();
|
1474
|
+
const unpublish = React.useCallback(
|
1475
|
+
async ({ collectionType, model, documentId, params }, discardDraft = false) => {
|
1476
|
+
try {
|
1477
|
+
trackUsage("willUnpublishEntry");
|
1478
|
+
const res = await unpublishDocument({
|
1479
|
+
collectionType,
|
1480
|
+
model,
|
1481
|
+
documentId,
|
1482
|
+
params,
|
1483
|
+
data: {
|
1484
|
+
discardDraft
|
1485
|
+
}
|
1486
|
+
});
|
1487
|
+
if ("error" in res) {
|
1488
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1489
|
+
return { error: res.error };
|
1490
|
+
}
|
1491
|
+
trackUsage("didUnpublishEntry");
|
1492
|
+
toggleNotification({
|
1493
|
+
type: "success",
|
1494
|
+
message: formatMessage({
|
1495
|
+
id: getTranslation("success.record.unpublish"),
|
1496
|
+
defaultMessage: "Unpublished document"
|
1497
|
+
})
|
1498
|
+
});
|
1499
|
+
return res.data;
|
1500
|
+
} catch (err) {
|
1501
|
+
toggleNotification({
|
1502
|
+
type: "danger",
|
1503
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1504
|
+
});
|
1505
|
+
throw err;
|
1506
|
+
}
|
1507
|
+
},
|
1508
|
+
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1509
|
+
);
|
1510
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1511
|
+
const unpublishMany = React.useCallback(
|
1512
|
+
async ({ model, documentIds, params }) => {
|
1513
|
+
try {
|
1514
|
+
trackUsage("willBulkUnpublishEntries");
|
1515
|
+
const res = await unpublishManyDocuments({
|
1516
|
+
model,
|
1517
|
+
documentIds,
|
1518
|
+
params
|
1519
|
+
});
|
1520
|
+
if ("error" in res) {
|
1521
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1522
|
+
return { error: res.error };
|
1523
|
+
}
|
1524
|
+
trackUsage("didBulkUnpublishEntries");
|
1525
|
+
toggleNotification({
|
1526
|
+
type: "success",
|
1527
|
+
title: formatMessage({
|
1528
|
+
id: getTranslation("success.records.unpublish"),
|
1529
|
+
defaultMessage: "Successfully unpublished."
|
1530
|
+
}),
|
1531
|
+
message: ""
|
1532
|
+
});
|
1533
|
+
return res.data;
|
1534
|
+
} catch (err) {
|
1535
|
+
toggleNotification({
|
1536
|
+
type: "danger",
|
1537
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1538
|
+
});
|
1539
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1540
|
+
throw err;
|
1541
|
+
}
|
1542
|
+
},
|
1543
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1544
|
+
);
|
1545
|
+
const [createDocument] = useCreateDocumentMutation();
|
1546
|
+
const create = React.useCallback(
|
1547
|
+
async ({ model, params }, data, trackerProperty) => {
|
1548
|
+
try {
|
1549
|
+
const res = await createDocument({
|
1550
|
+
model,
|
1551
|
+
data,
|
1552
|
+
params
|
1553
|
+
});
|
1554
|
+
if ("error" in res) {
|
1555
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1556
|
+
trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
|
1557
|
+
return { error: res.error };
|
1558
|
+
}
|
1559
|
+
trackUsage("didCreateEntry", trackerProperty);
|
1560
|
+
toggleNotification({
|
1561
|
+
type: "success",
|
1562
|
+
message: formatMessage({
|
1563
|
+
id: getTranslation("success.record.save"),
|
1184
1564
|
defaultMessage: "Saved document"
|
1185
1565
|
})
|
1186
1566
|
});
|
1567
|
+
setCurrentStep("contentManager.success");
|
1187
1568
|
return res.data;
|
1188
1569
|
} catch (err) {
|
1189
1570
|
toggleNotification({
|
@@ -1223,7 +1604,7 @@ const useDocumentActions = () => {
|
|
1223
1604
|
throw err;
|
1224
1605
|
}
|
1225
1606
|
},
|
1226
|
-
[autoCloneDocument,
|
1607
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1227
1608
|
);
|
1228
1609
|
const [cloneDocument] = useCloneDocumentMutation();
|
1229
1610
|
const clone = React.useCallback(
|
@@ -1249,6 +1630,7 @@ const useDocumentActions = () => {
|
|
1249
1630
|
defaultMessage: "Cloned document"
|
1250
1631
|
})
|
1251
1632
|
});
|
1633
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1252
1634
|
return res.data;
|
1253
1635
|
} catch (err) {
|
1254
1636
|
toggleNotification({
|
@@ -1259,7 +1641,7 @@ const useDocumentActions = () => {
|
|
1259
1641
|
throw err;
|
1260
1642
|
}
|
1261
1643
|
},
|
1262
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1644
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1263
1645
|
);
|
1264
1646
|
const [getDoc] = useLazyGetDocumentQuery();
|
1265
1647
|
const getDocument = React.useCallback(
|
@@ -1284,10 +1666,10 @@ const useDocumentActions = () => {
|
|
1284
1666
|
update
|
1285
1667
|
};
|
1286
1668
|
};
|
1287
|
-
const ProtectedHistoryPage = lazy(
|
1288
|
-
() => import("./History-
|
1669
|
+
const ProtectedHistoryPage = React.lazy(
|
1670
|
+
() => import("./History-CIQHyi4T.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1289
1671
|
);
|
1290
|
-
const routes$
|
1672
|
+
const routes$2 = [
|
1291
1673
|
{
|
1292
1674
|
path: ":collectionType/:slug/:id/history",
|
1293
1675
|
Component: ProtectedHistoryPage
|
@@ -1297,32 +1679,45 @@ const routes$1 = [
|
|
1297
1679
|
Component: ProtectedHistoryPage
|
1298
1680
|
}
|
1299
1681
|
];
|
1682
|
+
const ProtectedPreviewPage = React.lazy(
|
1683
|
+
() => import("./Preview-BVFFm7uB.mjs").then((mod) => ({ default: mod.ProtectedPreviewPage }))
|
1684
|
+
);
|
1685
|
+
const routes$1 = [
|
1686
|
+
{
|
1687
|
+
path: ":collectionType/:slug/:id/preview",
|
1688
|
+
Component: ProtectedPreviewPage
|
1689
|
+
},
|
1690
|
+
{
|
1691
|
+
path: ":collectionType/:slug/preview",
|
1692
|
+
Component: ProtectedPreviewPage
|
1693
|
+
}
|
1694
|
+
];
|
1300
1695
|
const ProtectedEditViewPage = lazy(
|
1301
|
-
() => import("./EditViewPage-
|
1696
|
+
() => import("./EditViewPage-CD_hqc1J.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1302
1697
|
);
|
1303
1698
|
const ProtectedListViewPage = lazy(
|
1304
|
-
() => import("./ListViewPage-
|
1699
|
+
() => import("./ListViewPage-C10McTK1.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1305
1700
|
);
|
1306
1701
|
const ProtectedListConfiguration = lazy(
|
1307
|
-
() => import("./ListConfigurationPage-
|
1702
|
+
() => import("./ListConfigurationPage-DcZsfyEL.mjs").then((mod) => ({
|
1308
1703
|
default: mod.ProtectedListConfiguration
|
1309
1704
|
}))
|
1310
1705
|
);
|
1311
1706
|
const ProtectedEditConfigurationPage = lazy(
|
1312
|
-
() => import("./EditConfigurationPage-
|
1707
|
+
() => import("./EditConfigurationPage-BNjOAHNS.mjs").then((mod) => ({
|
1313
1708
|
default: mod.ProtectedEditConfigurationPage
|
1314
1709
|
}))
|
1315
1710
|
);
|
1316
1711
|
const ProtectedComponentConfigurationPage = lazy(
|
1317
|
-
() => import("./ComponentConfigurationPage-
|
1712
|
+
() => import("./ComponentConfigurationPage-BgCLcjXO.mjs").then((mod) => ({
|
1318
1713
|
default: mod.ProtectedComponentConfigurationPage
|
1319
1714
|
}))
|
1320
1715
|
);
|
1321
1716
|
const NoPermissions = lazy(
|
1322
|
-
() => import("./NoPermissionsPage-
|
1717
|
+
() => import("./NoPermissionsPage-wfPBh2_0.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1323
1718
|
);
|
1324
1719
|
const NoContentType = lazy(
|
1325
|
-
() => import("./NoContentTypePage-
|
1720
|
+
() => import("./NoContentTypePage-CPc0Cd3S.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1326
1721
|
);
|
1327
1722
|
const CollectionTypePages = () => {
|
1328
1723
|
const { collectionType } = useParams();
|
@@ -1334,7 +1729,7 @@ const CollectionTypePages = () => {
|
|
1334
1729
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1335
1730
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1336
1731
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1337
|
-
const LIST_PATH = `/content-manager
|
1732
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1338
1733
|
const routes = [
|
1339
1734
|
{
|
1340
1735
|
path: LIST_RELATIVE_PATH,
|
@@ -1368,6 +1763,7 @@ const routes = [
|
|
1368
1763
|
path: "no-content-types",
|
1369
1764
|
Component: NoContentType
|
1370
1765
|
},
|
1766
|
+
...routes$2,
|
1371
1767
|
...routes$1
|
1372
1768
|
];
|
1373
1769
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1442,6 +1838,8 @@ const DocumentActionButton = (action) => {
|
|
1442
1838
|
onClick: handleClick(action),
|
1443
1839
|
justifyContent: "center",
|
1444
1840
|
variant: action.variant || "default",
|
1841
|
+
paddingTop: "7px",
|
1842
|
+
paddingBottom: "7px",
|
1445
1843
|
children: action.label
|
1446
1844
|
}
|
1447
1845
|
),
|
@@ -1464,6 +1862,11 @@ const DocumentActionButton = (action) => {
|
|
1464
1862
|
) : null
|
1465
1863
|
] });
|
1466
1864
|
};
|
1865
|
+
const MenuItem = styled(Menu.Item)`
|
1866
|
+
&:hover {
|
1867
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1868
|
+
}
|
1869
|
+
`;
|
1467
1870
|
const DocumentActionsMenu = ({
|
1468
1871
|
actions: actions2,
|
1469
1872
|
children,
|
@@ -1519,44 +1922,35 @@ const DocumentActionsMenu = ({
|
|
1519
1922
|
]
|
1520
1923
|
}
|
1521
1924
|
),
|
1522
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1925
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1523
1926
|
actions2.map((action) => {
|
1524
1927
|
return /* @__PURE__ */ jsx(
|
1525
|
-
|
1928
|
+
MenuItem,
|
1526
1929
|
{
|
1527
1930
|
disabled: action.disabled,
|
1528
1931
|
onSelect: handleClick(action),
|
1529
1932
|
display: "block",
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
height: 5,
|
1552
|
-
paddingLeft: 2,
|
1553
|
-
paddingRight: 2,
|
1554
|
-
hasRadius: true,
|
1555
|
-
color: "alternative600",
|
1556
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1557
|
-
}
|
1558
|
-
)
|
1559
|
-
] })
|
1933
|
+
isVariantDanger: action.variant === "danger",
|
1934
|
+
isDisabled: action.disabled,
|
1935
|
+
children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxs(
|
1936
|
+
Flex,
|
1937
|
+
{
|
1938
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1939
|
+
gap: 2,
|
1940
|
+
tag: "span",
|
1941
|
+
children: [
|
1942
|
+
/* @__PURE__ */ jsx(
|
1943
|
+
Flex,
|
1944
|
+
{
|
1945
|
+
tag: "span",
|
1946
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1947
|
+
children: action.icon
|
1948
|
+
}
|
1949
|
+
),
|
1950
|
+
action.label
|
1951
|
+
]
|
1952
|
+
}
|
1953
|
+
) })
|
1560
1954
|
},
|
1561
1955
|
action.id
|
1562
1956
|
);
|
@@ -1598,6 +1992,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1598
1992
|
return "primary600";
|
1599
1993
|
}
|
1600
1994
|
};
|
1995
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1996
|
+
switch (variant) {
|
1997
|
+
case "danger":
|
1998
|
+
return "danger600";
|
1999
|
+
case "secondary":
|
2000
|
+
return "neutral500";
|
2001
|
+
case "success":
|
2002
|
+
return "success600";
|
2003
|
+
default:
|
2004
|
+
return "primary600";
|
2005
|
+
}
|
2006
|
+
};
|
1601
2007
|
const DocumentActionConfirmDialog = ({
|
1602
2008
|
onClose,
|
1603
2009
|
onCancel,
|
@@ -1624,11 +2030,11 @@ const DocumentActionConfirmDialog = ({
|
|
1624
2030
|
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1625
2031
|
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1626
2032
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1627
|
-
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
2033
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1628
2034
|
id: "app.components.Button.cancel",
|
1629
2035
|
defaultMessage: "Cancel"
|
1630
2036
|
}) }) }),
|
1631
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2037
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1632
2038
|
id: "app.components.Button.confirm",
|
1633
2039
|
defaultMessage: "Confirm"
|
1634
2040
|
}) })
|
@@ -1655,6 +2061,18 @@ const DocumentActionModal = ({
|
|
1655
2061
|
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1656
2062
|
] }) });
|
1657
2063
|
};
|
2064
|
+
const transformData = (data) => {
|
2065
|
+
if (Array.isArray(data)) {
|
2066
|
+
return data.map(transformData);
|
2067
|
+
}
|
2068
|
+
if (typeof data === "object" && data !== null) {
|
2069
|
+
if ("apiData" in data) {
|
2070
|
+
return data.apiData;
|
2071
|
+
}
|
2072
|
+
return mapValues(transformData)(data);
|
2073
|
+
}
|
2074
|
+
return data;
|
2075
|
+
};
|
1658
2076
|
const PublishAction$1 = ({
|
1659
2077
|
activeTab,
|
1660
2078
|
documentId,
|
@@ -1667,12 +2085,11 @@ const PublishAction$1 = ({
|
|
1667
2085
|
const navigate = useNavigate();
|
1668
2086
|
const { toggleNotification } = useNotification();
|
1669
2087
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2088
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
1670
2089
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2090
|
+
const { id } = useParams();
|
1671
2091
|
const { formatMessage } = useIntl();
|
1672
|
-
const { canPublish
|
1673
|
-
"PublishAction",
|
1674
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1675
|
-
);
|
2092
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1676
2093
|
const { publish } = useDocumentActions();
|
1677
2094
|
const [
|
1678
2095
|
countDraftRelations,
|
@@ -1724,32 +2141,35 @@ const PublishAction$1 = ({
|
|
1724
2141
|
}
|
1725
2142
|
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1726
2143
|
React.useEffect(() => {
|
1727
|
-
if (documentId) {
|
1728
|
-
|
1729
|
-
const { data, error } = await countDraftRelations({
|
1730
|
-
collectionType,
|
1731
|
-
model,
|
1732
|
-
documentId,
|
1733
|
-
params
|
1734
|
-
});
|
1735
|
-
if (error) {
|
1736
|
-
throw error;
|
1737
|
-
}
|
1738
|
-
if (data) {
|
1739
|
-
setServerCountOfDraftRelations(data.data);
|
1740
|
-
}
|
1741
|
-
};
|
1742
|
-
fetchDraftRelationsCount();
|
2144
|
+
if (!document || !document.documentId || isListView) {
|
2145
|
+
return;
|
1743
2146
|
}
|
1744
|
-
|
1745
|
-
|
2147
|
+
const fetchDraftRelationsCount = async () => {
|
2148
|
+
const { data, error } = await countDraftRelations({
|
2149
|
+
collectionType,
|
2150
|
+
model,
|
2151
|
+
documentId,
|
2152
|
+
params
|
2153
|
+
});
|
2154
|
+
if (error) {
|
2155
|
+
throw error;
|
2156
|
+
}
|
2157
|
+
if (data) {
|
2158
|
+
setServerCountOfDraftRelations(data.data);
|
2159
|
+
}
|
2160
|
+
};
|
2161
|
+
fetchDraftRelationsCount();
|
2162
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2163
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1746
2164
|
if (!schema?.options?.draftAndPublish) {
|
1747
2165
|
return null;
|
1748
2166
|
}
|
1749
2167
|
const performPublish = async () => {
|
1750
2168
|
setSubmitting(true);
|
1751
2169
|
try {
|
1752
|
-
const { errors } = await validate(
|
2170
|
+
const { errors } = await validate(true, {
|
2171
|
+
status: "published"
|
2172
|
+
});
|
1753
2173
|
if (errors) {
|
1754
2174
|
toggleNotification({
|
1755
2175
|
type: "danger",
|
@@ -1767,13 +2187,15 @@ const PublishAction$1 = ({
|
|
1767
2187
|
documentId,
|
1768
2188
|
params
|
1769
2189
|
},
|
1770
|
-
formValues
|
2190
|
+
transformData(formValues)
|
1771
2191
|
);
|
1772
2192
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
2193
|
+
if (id === "create") {
|
2194
|
+
navigate({
|
2195
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2196
|
+
search: rawQuery
|
2197
|
+
});
|
2198
|
+
}
|
1777
2199
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1778
2200
|
setErrors(formatValidationErrors(res.error));
|
1779
2201
|
}
|
@@ -1782,7 +2204,8 @@ const PublishAction$1 = ({
|
|
1782
2204
|
}
|
1783
2205
|
};
|
1784
2206
|
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1785
|
-
const
|
2207
|
+
const enableDraftRelationsCount = false;
|
2208
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1786
2209
|
return {
|
1787
2210
|
/**
|
1788
2211
|
* Disabled when:
|
@@ -1799,9 +2222,6 @@ const PublishAction$1 = ({
|
|
1799
2222
|
defaultMessage: "Publish"
|
1800
2223
|
}),
|
1801
2224
|
onClick: async () => {
|
1802
|
-
if (hasDraftRelations) {
|
1803
|
-
return;
|
1804
|
-
}
|
1805
2225
|
await performPublish();
|
1806
2226
|
},
|
1807
2227
|
dialog: hasDraftRelations ? {
|
@@ -1840,10 +2260,6 @@ const UpdateAction = ({
|
|
1840
2260
|
const cloneMatch = useMatch(CLONE_PATH);
|
1841
2261
|
const isCloning = cloneMatch !== null;
|
1842
2262
|
const { formatMessage } = useIntl();
|
1843
|
-
useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1844
|
-
canCreate: canCreate2,
|
1845
|
-
canUpdate: canUpdate2
|
1846
|
-
}));
|
1847
2263
|
const { create, update, clone } = useDocumentActions();
|
1848
2264
|
const [{ query, rawQuery }] = useQueryParams();
|
1849
2265
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
@@ -1863,13 +2279,15 @@ const UpdateAction = ({
|
|
1863
2279
|
*/
|
1864
2280
|
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1865
2281
|
label: formatMessage({
|
1866
|
-
id: "
|
2282
|
+
id: "global.save",
|
1867
2283
|
defaultMessage: "Save"
|
1868
2284
|
}),
|
1869
2285
|
onClick: async () => {
|
1870
2286
|
setSubmitting(true);
|
1871
2287
|
try {
|
1872
|
-
const { errors } = await validate(
|
2288
|
+
const { errors } = await validate(true, {
|
2289
|
+
status: "draft"
|
2290
|
+
});
|
1873
2291
|
if (errors) {
|
1874
2292
|
toggleNotification({
|
1875
2293
|
type: "danger",
|
@@ -1887,7 +2305,7 @@ const UpdateAction = ({
|
|
1887
2305
|
documentId: cloneMatch.params.origin,
|
1888
2306
|
params
|
1889
2307
|
},
|
1890
|
-
document
|
2308
|
+
transformData(document)
|
1891
2309
|
);
|
1892
2310
|
if ("data" in res) {
|
1893
2311
|
navigate(
|
@@ -1908,7 +2326,7 @@ const UpdateAction = ({
|
|
1908
2326
|
documentId,
|
1909
2327
|
params
|
1910
2328
|
},
|
1911
|
-
document
|
2329
|
+
transformData(document)
|
1912
2330
|
);
|
1913
2331
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1914
2332
|
setErrors(formatValidationErrors(res.error));
|
@@ -1921,7 +2339,7 @@ const UpdateAction = ({
|
|
1921
2339
|
model,
|
1922
2340
|
params
|
1923
2341
|
},
|
1924
|
-
document
|
2342
|
+
transformData(document)
|
1925
2343
|
);
|
1926
2344
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1927
2345
|
navigate(
|
@@ -1974,7 +2392,7 @@ const UnpublishAction$1 = ({
|
|
1974
2392
|
id: "app.utils.unpublish",
|
1975
2393
|
defaultMessage: "Unpublish"
|
1976
2394
|
}),
|
1977
|
-
icon: /* @__PURE__ */ jsx(
|
2395
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1978
2396
|
onClick: async () => {
|
1979
2397
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1980
2398
|
if (!documentId) {
|
@@ -2086,7 +2504,7 @@ const DiscardAction = ({
|
|
2086
2504
|
id: "content-manager.actions.discard.label",
|
2087
2505
|
defaultMessage: "Discard changes"
|
2088
2506
|
}),
|
2089
|
-
icon: /* @__PURE__ */ jsx(
|
2507
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2090
2508
|
position: ["panel", "table-row"],
|
2091
2509
|
variant: "danger",
|
2092
2510
|
dialog: {
|
@@ -2114,11 +2532,6 @@ const DiscardAction = ({
|
|
2114
2532
|
};
|
2115
2533
|
};
|
2116
2534
|
DiscardAction.type = "discard";
|
2117
|
-
const StyledCrossCircle = styled(CrossCircle)`
|
2118
|
-
path {
|
2119
|
-
fill: currentColor;
|
2120
|
-
}
|
2121
|
-
`;
|
2122
2535
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2123
2536
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2124
2537
|
const RelativeTime = React.forwardRef(
|
@@ -2131,7 +2544,7 @@ const RelativeTime = React.forwardRef(
|
|
2131
2544
|
});
|
2132
2545
|
const unit = intervals.find((intervalUnit) => {
|
2133
2546
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2134
|
-
});
|
2547
|
+
}) ?? "seconds";
|
2135
2548
|
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2136
2549
|
const customInterval = customIntervals.find(
|
2137
2550
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2165,19 +2578,29 @@ const getDisplayName = ({
|
|
2165
2578
|
return email ?? "";
|
2166
2579
|
};
|
2167
2580
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2168
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2169
|
-
const statusVariant = status === "draft" ? "
|
2170
|
-
|
2581
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2582
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2583
|
+
const { formatMessage } = useIntl();
|
2584
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2585
|
+
id: `content-manager.containers.List.${status}`,
|
2586
|
+
defaultMessage: capitalise(status)
|
2587
|
+
}) }) });
|
2171
2588
|
};
|
2172
2589
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2173
2590
|
const { formatMessage } = useIntl();
|
2174
2591
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2592
|
+
const params = useParams();
|
2175
2593
|
const title = isCreating ? formatMessage({
|
2176
2594
|
id: "content-manager.containers.edit.title.new",
|
2177
2595
|
defaultMessage: "Create an entry"
|
2178
2596
|
}) : documentTitle;
|
2179
2597
|
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2180
|
-
/* @__PURE__ */ jsx(
|
2598
|
+
/* @__PURE__ */ jsx(
|
2599
|
+
BackButton,
|
2600
|
+
{
|
2601
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2602
|
+
}
|
2603
|
+
),
|
2181
2604
|
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2182
2605
|
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2183
2606
|
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
@@ -2265,12 +2688,12 @@ const Information = ({ activeTab }) => {
|
|
2265
2688
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2266
2689
|
label: formatMessage({
|
2267
2690
|
id: "content-manager.containers.edit.information.last-published.label",
|
2268
|
-
defaultMessage: "
|
2691
|
+
defaultMessage: "Published"
|
2269
2692
|
}),
|
2270
2693
|
value: formatMessage(
|
2271
2694
|
{
|
2272
2695
|
id: "content-manager.containers.edit.information.last-published.value",
|
2273
|
-
defaultMessage: `
|
2696
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2274
2697
|
},
|
2275
2698
|
{
|
2276
2699
|
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2283,12 +2706,12 @@ const Information = ({ activeTab }) => {
|
|
2283
2706
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2284
2707
|
label: formatMessage({
|
2285
2708
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2286
|
-
defaultMessage: "
|
2709
|
+
defaultMessage: "Updated"
|
2287
2710
|
}),
|
2288
2711
|
value: formatMessage(
|
2289
2712
|
{
|
2290
2713
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2291
|
-
defaultMessage: `
|
2714
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2292
2715
|
},
|
2293
2716
|
{
|
2294
2717
|
time: /* @__PURE__ */ jsx(
|
@@ -2306,12 +2729,12 @@ const Information = ({ activeTab }) => {
|
|
2306
2729
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2307
2730
|
label: formatMessage({
|
2308
2731
|
id: "content-manager.containers.edit.information.document.label",
|
2309
|
-
defaultMessage: "
|
2732
|
+
defaultMessage: "Created"
|
2310
2733
|
}),
|
2311
2734
|
value: formatMessage(
|
2312
2735
|
{
|
2313
2736
|
id: "content-manager.containers.edit.information.document.value",
|
2314
|
-
defaultMessage: `
|
2737
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2315
2738
|
},
|
2316
2739
|
{
|
2317
2740
|
time: /* @__PURE__ */ jsx(
|
@@ -2349,25 +2772,77 @@ const Information = ({ activeTab }) => {
|
|
2349
2772
|
);
|
2350
2773
|
};
|
2351
2774
|
const HeaderActions = ({ actions: actions2 }) => {
|
2352
|
-
|
2353
|
-
|
2775
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2776
|
+
const handleClick = (action) => async (e) => {
|
2777
|
+
if (!("options" in action)) {
|
2778
|
+
const { onClick = () => false, dialog, id } = action;
|
2779
|
+
const muteDialog = await onClick(e);
|
2780
|
+
if (dialog && !muteDialog) {
|
2781
|
+
e.preventDefault();
|
2782
|
+
setDialogId(id);
|
2783
|
+
}
|
2784
|
+
}
|
2785
|
+
};
|
2786
|
+
const handleClose = () => {
|
2787
|
+
setDialogId(null);
|
2788
|
+
};
|
2789
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2790
|
+
if (action.options) {
|
2354
2791
|
return /* @__PURE__ */ jsx(
|
2355
2792
|
SingleSelect,
|
2356
2793
|
{
|
2357
2794
|
size: "S",
|
2358
|
-
disabled: action.disabled,
|
2359
|
-
"aria-label": action.label,
|
2360
2795
|
onChange: action.onSelect,
|
2361
|
-
|
2796
|
+
"aria-label": action.label,
|
2797
|
+
...action,
|
2362
2798
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2363
2799
|
},
|
2364
2800
|
action.id
|
2365
2801
|
);
|
2366
2802
|
} else {
|
2367
|
-
|
2803
|
+
if (action.type === "icon") {
|
2804
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2805
|
+
/* @__PURE__ */ jsx(
|
2806
|
+
IconButton,
|
2807
|
+
{
|
2808
|
+
disabled: action.disabled,
|
2809
|
+
label: action.label,
|
2810
|
+
size: "S",
|
2811
|
+
onClick: handleClick(action),
|
2812
|
+
children: action.icon
|
2813
|
+
}
|
2814
|
+
),
|
2815
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2816
|
+
HeaderActionDialog,
|
2817
|
+
{
|
2818
|
+
...action.dialog,
|
2819
|
+
isOpen: dialogId === action.id,
|
2820
|
+
onClose: handleClose
|
2821
|
+
}
|
2822
|
+
) : null
|
2823
|
+
] }, action.id);
|
2824
|
+
}
|
2368
2825
|
}
|
2369
2826
|
}) });
|
2370
2827
|
};
|
2828
|
+
const HeaderActionDialog = ({
|
2829
|
+
onClose,
|
2830
|
+
onCancel,
|
2831
|
+
title,
|
2832
|
+
content: Content,
|
2833
|
+
isOpen
|
2834
|
+
}) => {
|
2835
|
+
const handleClose = async () => {
|
2836
|
+
if (onCancel) {
|
2837
|
+
await onCancel();
|
2838
|
+
}
|
2839
|
+
onClose();
|
2840
|
+
};
|
2841
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2842
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2843
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2844
|
+
] }) });
|
2845
|
+
};
|
2371
2846
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2372
2847
|
const navigate = useNavigate();
|
2373
2848
|
const { formatMessage } = useIntl();
|
@@ -2408,12 +2883,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2408
2883
|
const { delete: deleteAction } = useDocumentActions();
|
2409
2884
|
const { toggleNotification } = useNotification();
|
2410
2885
|
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2886
|
+
const isLocalized = document?.locale != null;
|
2411
2887
|
return {
|
2412
2888
|
disabled: !canDelete || !document,
|
2413
|
-
label: formatMessage(
|
2414
|
-
|
2415
|
-
|
2416
|
-
|
2889
|
+
label: formatMessage(
|
2890
|
+
{
|
2891
|
+
id: "content-manager.actions.delete.label",
|
2892
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2893
|
+
},
|
2894
|
+
{ isLocalized }
|
2895
|
+
),
|
2417
2896
|
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2418
2897
|
dialog: {
|
2419
2898
|
type: "dialog",
|
@@ -2453,419 +2932,117 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2453
2932
|
params: {
|
2454
2933
|
locale: "*"
|
2455
2934
|
}
|
2456
|
-
});
|
2457
|
-
if (!("error" in res)) {
|
2458
|
-
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2459
|
-
}
|
2460
|
-
} finally {
|
2461
|
-
if (!listViewPathMatch) {
|
2462
|
-
setSubmitting(false);
|
2463
|
-
}
|
2464
|
-
}
|
2465
|
-
}
|
2466
|
-
},
|
2467
|
-
variant: "danger",
|
2468
|
-
position: ["header", "table-row"]
|
2469
|
-
};
|
2470
|
-
};
|
2471
|
-
DeleteAction$1.type = "delete";
|
2472
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2473
|
-
const Panels = () => {
|
2474
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2475
|
-
const [
|
2476
|
-
{
|
2477
|
-
query: { status }
|
2478
|
-
}
|
2479
|
-
] = useQueryParams({
|
2480
|
-
status: "draft"
|
2481
|
-
});
|
2482
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2483
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2484
|
-
const props = {
|
2485
|
-
activeTab: status,
|
2486
|
-
model,
|
2487
|
-
documentId: id,
|
2488
|
-
document: isCloning ? void 0 : document,
|
2489
|
-
meta: isCloning ? void 0 : meta,
|
2490
|
-
collectionType
|
2491
|
-
};
|
2492
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2493
|
-
DescriptionComponentRenderer,
|
2494
|
-
{
|
2495
|
-
props,
|
2496
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2497
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2498
|
-
}
|
2499
|
-
) });
|
2500
|
-
};
|
2501
|
-
const ActionsPanel = () => {
|
2502
|
-
const { formatMessage } = useIntl();
|
2503
|
-
return {
|
2504
|
-
title: formatMessage({
|
2505
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2506
|
-
defaultMessage: "Document"
|
2507
|
-
}),
|
2508
|
-
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2509
|
-
};
|
2510
|
-
};
|
2511
|
-
ActionsPanel.type = "actions";
|
2512
|
-
const ActionsPanelContent = () => {
|
2513
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2514
|
-
const [
|
2515
|
-
{
|
2516
|
-
query: { status = "draft" }
|
2517
|
-
}
|
2518
|
-
] = useQueryParams();
|
2519
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2520
|
-
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2521
|
-
const props = {
|
2522
|
-
activeTab: status,
|
2523
|
-
model,
|
2524
|
-
documentId: id,
|
2525
|
-
document: isCloning ? void 0 : document,
|
2526
|
-
meta: isCloning ? void 0 : meta,
|
2527
|
-
collectionType
|
2528
|
-
};
|
2529
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2530
|
-
/* @__PURE__ */ jsx(
|
2531
|
-
DescriptionComponentRenderer,
|
2532
|
-
{
|
2533
|
-
props,
|
2534
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2535
|
-
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2536
|
-
}
|
2537
|
-
),
|
2538
|
-
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2539
|
-
] });
|
2540
|
-
};
|
2541
|
-
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2542
|
-
return /* @__PURE__ */ jsxs(
|
2543
|
-
Flex,
|
2544
|
-
{
|
2545
|
-
ref,
|
2546
|
-
tag: "aside",
|
2547
|
-
"aria-labelledby": "additional-information",
|
2548
|
-
background: "neutral0",
|
2549
|
-
borderColor: "neutral150",
|
2550
|
-
hasRadius: true,
|
2551
|
-
paddingBottom: 4,
|
2552
|
-
paddingLeft: 4,
|
2553
|
-
paddingRight: 4,
|
2554
|
-
paddingTop: 4,
|
2555
|
-
shadow: "tableShadow",
|
2556
|
-
gap: 3,
|
2557
|
-
direction: "column",
|
2558
|
-
justifyContent: "stretch",
|
2559
|
-
alignItems: "flex-start",
|
2560
|
-
children: [
|
2561
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2562
|
-
children
|
2563
|
-
]
|
2564
|
-
}
|
2565
|
-
);
|
2566
|
-
});
|
2567
|
-
const HOOKS = {
|
2568
|
-
/**
|
2569
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2570
|
-
* @constant
|
2571
|
-
* @type {string}
|
2572
|
-
*/
|
2573
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2574
|
-
/**
|
2575
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2576
|
-
* @constant
|
2577
|
-
* @type {string}
|
2578
|
-
*/
|
2579
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2580
|
-
/**
|
2581
|
-
* Hook that allows to mutate the CM's edit view layout
|
2582
|
-
* @constant
|
2583
|
-
* @type {string}
|
2584
|
-
*/
|
2585
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2586
|
-
/**
|
2587
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2588
|
-
* @constant
|
2589
|
-
* @type {string}
|
2590
|
-
*/
|
2591
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2592
|
-
};
|
2593
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2594
|
-
endpoints: (builder) => ({
|
2595
|
-
getContentTypeConfiguration: builder.query({
|
2596
|
-
query: (uid) => ({
|
2597
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2598
|
-
method: "GET"
|
2599
|
-
}),
|
2600
|
-
transformResponse: (response) => response.data,
|
2601
|
-
providesTags: (_result, _error, uid) => [
|
2602
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2603
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2604
|
-
]
|
2605
|
-
}),
|
2606
|
-
getAllContentTypeSettings: builder.query({
|
2607
|
-
query: () => "/content-manager/content-types-settings",
|
2608
|
-
transformResponse: (response) => response.data,
|
2609
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2610
|
-
}),
|
2611
|
-
updateContentTypeConfiguration: builder.mutation({
|
2612
|
-
query: ({ uid, ...body }) => ({
|
2613
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2614
|
-
method: "PUT",
|
2615
|
-
data: body
|
2616
|
-
}),
|
2617
|
-
transformResponse: (response) => response.data,
|
2618
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2619
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2620
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2621
|
-
// Is this necessary?
|
2622
|
-
{ type: "InitialData" }
|
2623
|
-
]
|
2624
|
-
})
|
2625
|
-
})
|
2626
|
-
});
|
2627
|
-
const {
|
2628
|
-
useGetContentTypeConfigurationQuery,
|
2629
|
-
useGetAllContentTypeSettingsQuery,
|
2630
|
-
useUpdateContentTypeConfigurationMutation
|
2631
|
-
} = contentTypesApi;
|
2632
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2633
|
-
const { type } = attribute;
|
2634
|
-
if (type === "relation") {
|
2635
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2636
|
-
}
|
2637
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2638
|
-
};
|
2639
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2640
|
-
if (!mainFieldName) {
|
2641
|
-
return void 0;
|
2642
|
-
}
|
2643
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2644
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2645
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2646
|
-
);
|
2647
|
-
return {
|
2648
|
-
name: mainFieldName,
|
2649
|
-
type: mainFieldType ?? "string"
|
2650
|
-
};
|
2651
|
-
};
|
2652
|
-
const DEFAULT_SETTINGS = {
|
2653
|
-
bulkable: false,
|
2654
|
-
filterable: false,
|
2655
|
-
searchable: false,
|
2656
|
-
pagination: false,
|
2657
|
-
defaultSortBy: "",
|
2658
|
-
defaultSortOrder: "asc",
|
2659
|
-
mainField: "id",
|
2660
|
-
pageSize: 10
|
2661
|
-
};
|
2662
|
-
const useDocumentLayout = (model) => {
|
2663
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2664
|
-
const [{ query }] = useQueryParams();
|
2665
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2666
|
-
const { toggleNotification } = useNotification();
|
2667
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2668
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2669
|
-
const {
|
2670
|
-
data,
|
2671
|
-
isLoading: isLoadingConfigs,
|
2672
|
-
error,
|
2673
|
-
isFetching: isFetchingConfigs
|
2674
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2675
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2676
|
-
React.useEffect(() => {
|
2677
|
-
if (error) {
|
2678
|
-
toggleNotification({
|
2679
|
-
type: "danger",
|
2680
|
-
message: formatAPIError(error)
|
2681
|
-
});
|
2682
|
-
}
|
2683
|
-
}, [error, formatAPIError, toggleNotification]);
|
2684
|
-
const editLayout = React.useMemo(
|
2685
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2686
|
-
layout: [],
|
2687
|
-
components: {},
|
2688
|
-
metadatas: {},
|
2689
|
-
options: {},
|
2690
|
-
settings: DEFAULT_SETTINGS
|
2691
|
-
},
|
2692
|
-
[data, isLoading, schemas, schema, components]
|
2693
|
-
);
|
2694
|
-
const listLayout = React.useMemo(() => {
|
2695
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2696
|
-
layout: [],
|
2697
|
-
metadatas: {},
|
2698
|
-
options: {},
|
2699
|
-
settings: DEFAULT_SETTINGS
|
2700
|
-
};
|
2701
|
-
}, [data, isLoading, schemas, schema, components]);
|
2702
|
-
const { layout: edit } = React.useMemo(
|
2703
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2704
|
-
layout: editLayout,
|
2705
|
-
query
|
2706
|
-
}),
|
2707
|
-
[editLayout, query, runHookWaterfall]
|
2708
|
-
);
|
2709
|
-
return {
|
2710
|
-
error,
|
2711
|
-
isLoading,
|
2712
|
-
edit,
|
2713
|
-
list: listLayout
|
2714
|
-
};
|
2715
|
-
};
|
2716
|
-
const useDocLayout = () => {
|
2717
|
-
const { model } = useDoc();
|
2718
|
-
return useDocumentLayout(model);
|
2719
|
-
};
|
2720
|
-
const formatEditLayout = (data, {
|
2721
|
-
schemas,
|
2722
|
-
schema,
|
2723
|
-
components
|
2724
|
-
}) => {
|
2725
|
-
let currentPanelIndex = 0;
|
2726
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2727
|
-
data.contentType.layouts.edit,
|
2728
|
-
schema?.attributes,
|
2729
|
-
data.contentType.metadatas,
|
2730
|
-
{ configurations: data.components, schemas: components },
|
2731
|
-
schemas
|
2732
|
-
).reduce((panels, row) => {
|
2733
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2734
|
-
panels.push([row]);
|
2735
|
-
currentPanelIndex += 2;
|
2736
|
-
} else {
|
2737
|
-
if (!panels[currentPanelIndex]) {
|
2738
|
-
panels.push([]);
|
2739
|
-
}
|
2740
|
-
panels[currentPanelIndex].push(row);
|
2741
|
-
}
|
2742
|
-
return panels;
|
2743
|
-
}, []);
|
2744
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2745
|
-
(acc, [uid, configuration]) => {
|
2746
|
-
acc[uid] = {
|
2747
|
-
layout: convertEditLayoutToFieldLayouts(
|
2748
|
-
configuration.layouts.edit,
|
2749
|
-
components[uid].attributes,
|
2750
|
-
configuration.metadatas
|
2751
|
-
),
|
2752
|
-
settings: {
|
2753
|
-
...configuration.settings,
|
2754
|
-
icon: components[uid].info.icon,
|
2755
|
-
displayName: components[uid].info.displayName
|
2935
|
+
});
|
2936
|
+
if (!("error" in res)) {
|
2937
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2938
|
+
}
|
2939
|
+
} finally {
|
2940
|
+
if (!listViewPathMatch) {
|
2941
|
+
setSubmitting(false);
|
2942
|
+
}
|
2756
2943
|
}
|
2757
|
-
}
|
2758
|
-
return acc;
|
2759
|
-
},
|
2760
|
-
{}
|
2761
|
-
);
|
2762
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2763
|
-
(acc, [attribute, metadata]) => {
|
2764
|
-
return {
|
2765
|
-
...acc,
|
2766
|
-
[attribute]: metadata.edit
|
2767
|
-
};
|
2768
|
-
},
|
2769
|
-
{}
|
2770
|
-
);
|
2771
|
-
return {
|
2772
|
-
layout: panelledEditAttributes,
|
2773
|
-
components: componentEditAttributes,
|
2774
|
-
metadatas: editMetadatas,
|
2775
|
-
settings: {
|
2776
|
-
...data.contentType.settings,
|
2777
|
-
displayName: schema?.info.displayName
|
2944
|
+
}
|
2778
2945
|
},
|
2779
|
-
|
2780
|
-
|
2781
|
-
...schema?.pluginOptions,
|
2782
|
-
...data.contentType.options
|
2783
|
-
}
|
2946
|
+
variant: "danger",
|
2947
|
+
position: ["header", "table-row"]
|
2784
2948
|
};
|
2785
2949
|
};
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
}
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
|
2800
|
-
|
2801
|
-
|
2802
|
-
|
2803
|
-
|
2804
|
-
|
2805
|
-
|
2806
|
-
|
2807
|
-
|
2808
|
-
|
2809
|
-
|
2810
|
-
|
2811
|
-
|
2812
|
-
}
|
2813
|
-
}
|
2814
|
-
);
|
2950
|
+
DeleteAction$1.type = "delete";
|
2951
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2952
|
+
const Panels = () => {
|
2953
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2954
|
+
const [
|
2955
|
+
{
|
2956
|
+
query: { status }
|
2957
|
+
}
|
2958
|
+
] = useQueryParams({
|
2959
|
+
status: "draft"
|
2960
|
+
});
|
2961
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2962
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2963
|
+
const props = {
|
2964
|
+
activeTab: status,
|
2965
|
+
model,
|
2966
|
+
documentId: id,
|
2967
|
+
document: isCloning ? void 0 : document,
|
2968
|
+
meta: isCloning ? void 0 : meta,
|
2969
|
+
collectionType
|
2970
|
+
};
|
2971
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2972
|
+
DescriptionComponentRenderer,
|
2973
|
+
{
|
2974
|
+
props,
|
2975
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2976
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2977
|
+
}
|
2978
|
+
) });
|
2815
2979
|
};
|
2816
|
-
const
|
2817
|
-
|
2818
|
-
schema,
|
2819
|
-
components
|
2820
|
-
}) => {
|
2821
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2822
|
-
(acc, [attribute, metadata]) => {
|
2823
|
-
return {
|
2824
|
-
...acc,
|
2825
|
-
[attribute]: metadata.list
|
2826
|
-
};
|
2827
|
-
},
|
2828
|
-
{}
|
2829
|
-
);
|
2830
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2831
|
-
data.contentType.layouts.list,
|
2832
|
-
schema?.attributes,
|
2833
|
-
listMetadatas,
|
2834
|
-
{ configurations: data.components, schemas: components },
|
2835
|
-
schemas
|
2836
|
-
);
|
2980
|
+
const ActionsPanel = () => {
|
2981
|
+
const { formatMessage } = useIntl();
|
2837
2982
|
return {
|
2838
|
-
|
2839
|
-
|
2840
|
-
|
2841
|
-
|
2842
|
-
|
2843
|
-
...schema?.pluginOptions,
|
2844
|
-
...data.contentType.options
|
2845
|
-
}
|
2983
|
+
title: formatMessage({
|
2984
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2985
|
+
defaultMessage: "Entry"
|
2986
|
+
}),
|
2987
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2846
2988
|
};
|
2847
2989
|
};
|
2848
|
-
|
2849
|
-
|
2850
|
-
|
2851
|
-
|
2852
|
-
|
2990
|
+
ActionsPanel.type = "actions";
|
2991
|
+
const ActionsPanelContent = () => {
|
2992
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2993
|
+
const [
|
2994
|
+
{
|
2995
|
+
query: { status = "draft" }
|
2853
2996
|
}
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2861
|
-
|
2862
|
-
|
2863
|
-
|
2864
|
-
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2997
|
+
] = useQueryParams();
|
2998
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2999
|
+
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
3000
|
+
const props = {
|
3001
|
+
activeTab: status,
|
3002
|
+
model,
|
3003
|
+
documentId: id,
|
3004
|
+
document: isCloning ? void 0 : document,
|
3005
|
+
meta: isCloning ? void 0 : meta,
|
3006
|
+
collectionType
|
3007
|
+
};
|
3008
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3009
|
+
/* @__PURE__ */ jsx(
|
3010
|
+
DescriptionComponentRenderer,
|
3011
|
+
{
|
3012
|
+
props,
|
3013
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3014
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
3015
|
+
}
|
3016
|
+
),
|
3017
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3018
|
+
] });
|
2868
3019
|
};
|
3020
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
3021
|
+
return /* @__PURE__ */ jsxs(
|
3022
|
+
Flex,
|
3023
|
+
{
|
3024
|
+
ref,
|
3025
|
+
tag: "aside",
|
3026
|
+
"aria-labelledby": "additional-information",
|
3027
|
+
background: "neutral0",
|
3028
|
+
borderColor: "neutral150",
|
3029
|
+
hasRadius: true,
|
3030
|
+
paddingBottom: 4,
|
3031
|
+
paddingLeft: 4,
|
3032
|
+
paddingRight: 4,
|
3033
|
+
paddingTop: 4,
|
3034
|
+
shadow: "tableShadow",
|
3035
|
+
gap: 3,
|
3036
|
+
direction: "column",
|
3037
|
+
justifyContent: "stretch",
|
3038
|
+
alignItems: "flex-start",
|
3039
|
+
children: [
|
3040
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3041
|
+
children
|
3042
|
+
]
|
3043
|
+
}
|
3044
|
+
);
|
3045
|
+
});
|
2869
3046
|
const ConfirmBulkActionDialog = ({
|
2870
3047
|
onToggleDialog,
|
2871
3048
|
isOpen = false,
|
@@ -2904,6 +3081,7 @@ const ConfirmDialogPublishAll = ({
|
|
2904
3081
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2905
3082
|
const { model, schema } = useDoc();
|
2906
3083
|
const [{ query }] = useQueryParams();
|
3084
|
+
const enableDraftRelationsCount = false;
|
2907
3085
|
const {
|
2908
3086
|
data: countDraftRelations = 0,
|
2909
3087
|
isLoading,
|
@@ -2915,7 +3093,7 @@ const ConfirmDialogPublishAll = ({
|
|
2915
3093
|
locale: query?.plugins?.i18n?.locale
|
2916
3094
|
},
|
2917
3095
|
{
|
2918
|
-
skip:
|
3096
|
+
skip: !enableDraftRelationsCount
|
2919
3097
|
}
|
2920
3098
|
);
|
2921
3099
|
React.useEffect(() => {
|
@@ -3100,7 +3278,7 @@ const SelectedEntriesTableContent = ({
|
|
3100
3278
|
status: row.status
|
3101
3279
|
}
|
3102
3280
|
) }),
|
3103
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3281
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3104
3282
|
IconButton,
|
3105
3283
|
{
|
3106
3284
|
tag: Link,
|
@@ -3109,23 +3287,16 @@ const SelectedEntriesTableContent = ({
|
|
3109
3287
|
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3110
3288
|
},
|
3111
3289
|
state: { from: pathname },
|
3112
|
-
label: formatMessage(
|
3113
|
-
|
3114
|
-
|
3115
|
-
|
3116
|
-
{
|
3117
|
-
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3118
|
-
defaultMessage: "item line {number}"
|
3119
|
-
},
|
3120
|
-
{ number: index2 + 1 }
|
3121
|
-
)
|
3122
|
-
}
|
3123
|
-
),
|
3290
|
+
label: formatMessage({
|
3291
|
+
id: "content-manager.bulk-publish.edit",
|
3292
|
+
defaultMessage: "Edit"
|
3293
|
+
}),
|
3124
3294
|
target: "_blank",
|
3125
3295
|
marginLeft: "auto",
|
3126
|
-
|
3296
|
+
variant: "ghost",
|
3297
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3127
3298
|
}
|
3128
|
-
) })
|
3299
|
+
) }) })
|
3129
3300
|
] }, row.id)) })
|
3130
3301
|
] });
|
3131
3302
|
};
|
@@ -3162,7 +3333,13 @@ const SelectedEntriesModalContent = ({
|
|
3162
3333
|
);
|
3163
3334
|
const { rows, validationErrors } = React.useMemo(() => {
|
3164
3335
|
if (data.length > 0 && schema) {
|
3165
|
-
const validate = createYupSchema(
|
3336
|
+
const validate = createYupSchema(
|
3337
|
+
schema.attributes,
|
3338
|
+
components,
|
3339
|
+
// Since this is the "Publish" action, the validation
|
3340
|
+
// schema must enforce the rules for published entities
|
3341
|
+
{ status: "published" }
|
3342
|
+
);
|
3166
3343
|
const validationErrors2 = {};
|
3167
3344
|
const rows2 = data.map((entry) => {
|
3168
3345
|
try {
|
@@ -3287,8 +3464,7 @@ const PublishAction = ({ documents, model }) => {
|
|
3287
3464
|
const refetchList = () => {
|
3288
3465
|
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3289
3466
|
};
|
3290
|
-
if (!showPublishButton)
|
3291
|
-
return null;
|
3467
|
+
if (!showPublishButton) return null;
|
3292
3468
|
return {
|
3293
3469
|
actionType: "publish",
|
3294
3470
|
variant: "tertiary",
|
@@ -3356,8 +3532,7 @@ const DeleteAction = ({ documents, model }) => {
|
|
3356
3532
|
selectRow([]);
|
3357
3533
|
}
|
3358
3534
|
};
|
3359
|
-
if (!hasDeletePermission)
|
3360
|
-
return null;
|
3535
|
+
if (!hasDeletePermission) return null;
|
3361
3536
|
return {
|
3362
3537
|
variant: "danger-light",
|
3363
3538
|
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
@@ -3406,8 +3581,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
3406
3581
|
}
|
3407
3582
|
};
|
3408
3583
|
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3409
|
-
if (!showUnpublishButton)
|
3410
|
-
return null;
|
3584
|
+
if (!showUnpublishButton) return null;
|
3411
3585
|
return {
|
3412
3586
|
variant: "tertiary",
|
3413
3587
|
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
@@ -3512,7 +3686,7 @@ const TableActions = ({ document }) => {
|
|
3512
3686
|
DescriptionComponentRenderer,
|
3513
3687
|
{
|
3514
3688
|
props,
|
3515
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3689
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3516
3690
|
children: (actions2) => {
|
3517
3691
|
const tableRowActions = actions2.filter((action) => {
|
3518
3692
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3623,7 +3797,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3623
3797
|
}),
|
3624
3798
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3625
3799
|
footer: ({ onClose }) => {
|
3626
|
-
return /* @__PURE__ */ jsxs(
|
3800
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3627
3801
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3628
3802
|
id: "cancel",
|
3629
3803
|
defaultMessage: "Cancel"
|
@@ -3743,10 +3917,8 @@ class ContentManagerPlugin {
|
|
3743
3917
|
const getPrintableType = (value) => {
|
3744
3918
|
const nativeType = typeof value;
|
3745
3919
|
if (nativeType === "object") {
|
3746
|
-
if (value === null)
|
3747
|
-
|
3748
|
-
if (Array.isArray(value))
|
3749
|
-
return "array";
|
3920
|
+
if (value === null) return "null";
|
3921
|
+
if (Array.isArray(value)) return "array";
|
3750
3922
|
if (value instanceof Object && value.constructor.name !== "Object") {
|
3751
3923
|
return value.constructor.name;
|
3752
3924
|
}
|
@@ -3757,17 +3929,27 @@ const HistoryAction = ({ model, document }) => {
|
|
3757
3929
|
const { formatMessage } = useIntl();
|
3758
3930
|
const [{ query }] = useQueryParams();
|
3759
3931
|
const navigate = useNavigate();
|
3932
|
+
const { trackUsage } = useTracking();
|
3933
|
+
const { pathname } = useLocation();
|
3760
3934
|
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3761
3935
|
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3762
3936
|
return null;
|
3763
3937
|
}
|
3938
|
+
const handleOnClick = () => {
|
3939
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
3940
|
+
trackUsage("willNavigate", {
|
3941
|
+
from: pathname,
|
3942
|
+
to: `${pathname}/${destination.pathname}`
|
3943
|
+
});
|
3944
|
+
navigate(destination);
|
3945
|
+
};
|
3764
3946
|
return {
|
3765
3947
|
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3766
3948
|
label: formatMessage({
|
3767
3949
|
id: "content-manager.history.document-action",
|
3768
3950
|
defaultMessage: "Content History"
|
3769
3951
|
}),
|
3770
|
-
onClick:
|
3952
|
+
onClick: handleOnClick,
|
3771
3953
|
disabled: (
|
3772
3954
|
/**
|
3773
3955
|
* The user is creating a new document.
|
@@ -3835,6 +4017,90 @@ const { setInitialData } = actions;
|
|
3835
4017
|
const reducer = combineReducers({
|
3836
4018
|
app: reducer$1
|
3837
4019
|
});
|
4020
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4021
|
+
endpoints: (builder) => ({
|
4022
|
+
getPreviewUrl: builder.query({
|
4023
|
+
query({ query, params }) {
|
4024
|
+
return {
|
4025
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4026
|
+
method: "GET",
|
4027
|
+
config: {
|
4028
|
+
params: query
|
4029
|
+
}
|
4030
|
+
};
|
4031
|
+
}
|
4032
|
+
})
|
4033
|
+
})
|
4034
|
+
});
|
4035
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4036
|
+
const ConditionalTooltip = ({ isShown, label, children }) => {
|
4037
|
+
if (isShown) {
|
4038
|
+
return /* @__PURE__ */ jsx(Tooltip, { label, children });
|
4039
|
+
}
|
4040
|
+
return children;
|
4041
|
+
};
|
4042
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4043
|
+
const { formatMessage } = useIntl();
|
4044
|
+
const { trackUsage } = useTracking();
|
4045
|
+
const { pathname } = useLocation();
|
4046
|
+
const [{ query }] = useQueryParams();
|
4047
|
+
const isModified = useForm("PreviewSidePanel", (state) => state.modified);
|
4048
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4049
|
+
params: {
|
4050
|
+
contentType: model
|
4051
|
+
},
|
4052
|
+
query: {
|
4053
|
+
documentId,
|
4054
|
+
locale: document?.locale,
|
4055
|
+
status: document?.status
|
4056
|
+
}
|
4057
|
+
});
|
4058
|
+
if (!data?.data?.url || error) {
|
4059
|
+
return null;
|
4060
|
+
}
|
4061
|
+
const trackNavigation = () => {
|
4062
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4063
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
4064
|
+
};
|
4065
|
+
return {
|
4066
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4067
|
+
content: /* @__PURE__ */ jsx(Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsx(
|
4068
|
+
ConditionalTooltip,
|
4069
|
+
{
|
4070
|
+
label: formatMessage({
|
4071
|
+
id: "content-manager.preview.panel.button-disabled-tooltip",
|
4072
|
+
defaultMessage: "Please save to open the preview"
|
4073
|
+
}),
|
4074
|
+
isShown: isModified,
|
4075
|
+
children: /* @__PURE__ */ jsx(
|
4076
|
+
Button,
|
4077
|
+
{
|
4078
|
+
variant: "tertiary",
|
4079
|
+
tag: Link,
|
4080
|
+
to: { pathname: "preview", search: stringify(query, { encode: false }) },
|
4081
|
+
onClick: trackNavigation,
|
4082
|
+
flex: "auto",
|
4083
|
+
disabled: isModified,
|
4084
|
+
children: formatMessage({
|
4085
|
+
id: "content-manager.preview.panel.button",
|
4086
|
+
defaultMessage: "Open preview"
|
4087
|
+
})
|
4088
|
+
}
|
4089
|
+
)
|
4090
|
+
}
|
4091
|
+
) })
|
4092
|
+
};
|
4093
|
+
};
|
4094
|
+
const FEATURE_ID = "preview";
|
4095
|
+
const previewAdmin = {
|
4096
|
+
bootstrap(app) {
|
4097
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4098
|
+
return;
|
4099
|
+
}
|
4100
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4101
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4102
|
+
}
|
4103
|
+
};
|
3838
4104
|
const index = {
|
3839
4105
|
register(app) {
|
3840
4106
|
const cm = new ContentManagerPlugin();
|
@@ -3854,7 +4120,7 @@ const index = {
|
|
3854
4120
|
app.router.addRoute({
|
3855
4121
|
path: "content-manager/*",
|
3856
4122
|
lazy: async () => {
|
3857
|
-
const { Layout } = await import("./layout-
|
4123
|
+
const { Layout } = await import("./layout-qE8qkNH_.mjs");
|
3858
4124
|
return {
|
3859
4125
|
Component: Layout
|
3860
4126
|
};
|
@@ -3867,11 +4133,14 @@ const index = {
|
|
3867
4133
|
if (typeof historyAdmin.bootstrap === "function") {
|
3868
4134
|
historyAdmin.bootstrap(app);
|
3869
4135
|
}
|
4136
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4137
|
+
previewAdmin.bootstrap(app);
|
4138
|
+
}
|
3870
4139
|
},
|
3871
4140
|
async registerTrads({ locales }) {
|
3872
4141
|
const importedTrads = await Promise.all(
|
3873
4142
|
locales.map((locale) => {
|
3874
|
-
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-
|
4143
|
+
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-Dtk_ot79.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 }) => {
|
3875
4144
|
return {
|
3876
4145
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3877
4146
|
locale
|
@@ -3892,13 +4161,16 @@ export {
|
|
3892
4161
|
BulkActionsRenderer as B,
|
3893
4162
|
COLLECTION_TYPES as C,
|
3894
4163
|
DocumentStatus as D,
|
3895
|
-
|
3896
|
-
|
3897
|
-
|
4164
|
+
extractContentTypeComponents as E,
|
4165
|
+
DEFAULT_SETTINGS as F,
|
4166
|
+
convertEditLayoutToFieldLayouts as G,
|
3898
4167
|
HOOKS as H,
|
3899
4168
|
InjectionZone as I,
|
3900
|
-
|
3901
|
-
|
4169
|
+
useDocument as J,
|
4170
|
+
useGetPreviewUrlQuery as K,
|
4171
|
+
index as L,
|
4172
|
+
useContentManagerContext as M,
|
4173
|
+
useDocumentActions as N,
|
3902
4174
|
Panels as P,
|
3903
4175
|
RelativeTime as R,
|
3904
4176
|
SINGLE_TYPES as S,
|
@@ -3916,18 +4188,18 @@ export {
|
|
3916
4188
|
PERMISSIONS as k,
|
3917
4189
|
DocumentRBAC as l,
|
3918
4190
|
DOCUMENT_META_FIELDS as m,
|
3919
|
-
|
3920
|
-
|
3921
|
-
|
3922
|
-
|
3923
|
-
|
4191
|
+
CLONE_PATH as n,
|
4192
|
+
useDocLayout as o,
|
4193
|
+
useGetContentTypeConfigurationQuery as p,
|
4194
|
+
CREATOR_FIELDS as q,
|
4195
|
+
getMainField as r,
|
3924
4196
|
setInitialData as s,
|
3925
|
-
|
4197
|
+
getDisplayName as t,
|
3926
4198
|
useContentTypeSchema as u,
|
3927
|
-
|
3928
|
-
|
3929
|
-
|
3930
|
-
|
3931
|
-
|
4199
|
+
checkIfAttributeIsDisplayable as v,
|
4200
|
+
useGetAllDocumentsQuery as w,
|
4201
|
+
convertListLayoutToFieldLayouts as x,
|
4202
|
+
capitalise as y,
|
4203
|
+
useUpdateContentTypeConfigurationMutation as z
|
3932
4204
|
};
|
3933
|
-
//# sourceMappingURL=index-
|
4205
|
+
//# sourceMappingURL=index-DLIkNVnQ.mjs.map
|