@strapi/content-manager 0.0.0-experimental.e14656d3b8681880212c13260b9a2b340c182f2d → 0.0.0-experimental.e350eaa6073e65190102b4b798c32c287053cc02
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-D_M8iBw5.js → ComponentConfigurationPage-BTR_hQow.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-D_M8iBw5.js.map → ComponentConfigurationPage-BTR_hQow.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-qemkOlnj.mjs → ComponentConfigurationPage-bLQr82ce.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-qemkOlnj.mjs.map → ComponentConfigurationPage-bLQr82ce.mjs.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
- package/dist/_chunks/{EditConfigurationPage-CjUrEewK.mjs → EditConfigurationPage-BhRSnUsL.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-CjUrEewK.mjs.map → EditConfigurationPage-BhRSnUsL.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-BePwPuHy.js → EditConfigurationPage-z39Wv3E6.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-BePwPuHy.js.map → EditConfigurationPage-z39Wv3E6.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-De8GyU8P.mjs → EditViewPage-BCjNxNlY.mjs} +50 -10
- package/dist/_chunks/EditViewPage-BCjNxNlY.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-B-RJeiJD.js → EditViewPage-wujOq90c.js} +50 -11
- package/dist/_chunks/EditViewPage-wujOq90c.js.map +1 -0
- package/dist/_chunks/{Field-dq8Tg1M_.js → Field-B5QXnctJ.js} +238 -153
- package/dist/_chunks/Field-B5QXnctJ.js.map +1 -0
- package/dist/_chunks/{Field-pb2o8uBe.mjs → Field-Byr3mPTl.mjs} +232 -147
- package/dist/_chunks/Field-Byr3mPTl.mjs.map +1 -0
- package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
- package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
- package/dist/_chunks/{Form-DJn0Dxha.mjs → Form-BZgvE8C8.mjs} +17 -9
- package/dist/_chunks/Form-BZgvE8C8.mjs.map +1 -0
- package/dist/_chunks/{Form-DGIf4jQU.js → Form-D7mexvm3.js} +19 -12
- package/dist/_chunks/Form-D7mexvm3.js.map +1 -0
- package/dist/_chunks/{History-BowL3JKP.mjs → History-CqNgxkqK.mjs} +43 -100
- package/dist/_chunks/History-CqNgxkqK.mjs.map +1 -0
- package/dist/_chunks/{History-Dh2NEHnR.js → History-DYl2A8Z_.js} +42 -100
- package/dist/_chunks/History-DYl2A8Z_.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-BxYCWz9e.js → ListConfigurationPage-BXnu_OoY.js} +7 -7
- package/dist/_chunks/ListConfigurationPage-BXnu_OoY.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-BpVOB-hn.mjs → ListConfigurationPage-BbQjzKkQ.mjs} +7 -6
- package/dist/_chunks/ListConfigurationPage-BbQjzKkQ.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-4XsciqHZ.js → ListViewPage-BtSi8C1l.js} +103 -77
- package/dist/_chunks/ListViewPage-BtSi8C1l.js.map +1 -0
- package/dist/_chunks/{ListViewPage-CXFUjZQC.mjs → ListViewPage-D4ofkbjR.mjs} +99 -72
- package/dist/_chunks/ListViewPage-D4ofkbjR.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-C8OpoHeU.js → NoContentTypePage-CitJeOq4.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C8OpoHeU.js.map → NoContentTypePage-CitJeOq4.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-DuhOTp3x.mjs → NoContentTypePage-DyUx5mXh.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-DuhOTp3x.mjs.map → NoContentTypePage-DyUx5mXh.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DVz3mzDz.mjs → NoPermissionsPage-DhIiyWkk.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DVz3mzDz.mjs.map → NoPermissionsPage-DhIiyWkk.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-y_r7DVA2.js → NoPermissionsPage-DzgWz0M-.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-y_r7DVA2.js.map → NoPermissionsPage-DzgWz0M-.js.map} +1 -1
- package/dist/_chunks/Preview-BaYGJ0nb.mjs +293 -0
- package/dist/_chunks/Preview-BaYGJ0nb.mjs.map +1 -0
- package/dist/_chunks/Preview-DfNx8Ke-.js +311 -0
- package/dist/_chunks/Preview-DfNx8Ke-.js.map +1 -0
- package/dist/_chunks/{Relations-CVNLrn1Y.mjs → Relations-DM2yUTST.mjs} +75 -41
- package/dist/_chunks/Relations-DM2yUTST.mjs.map +1 -0
- package/dist/_chunks/{Relations-DPFCAa7b.js → Relations-DuKCaXrv.js} +75 -42
- package/dist/_chunks/Relations-DuKCaXrv.js.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-C3fJE-1-.js → index-BUWEmX8m.js} +1273 -996
- package/dist/_chunks/index-BUWEmX8m.js.map +1 -0
- package/dist/_chunks/{index-DiMrfcfy.mjs → index-DVAIIsOs.mjs} +1276 -999
- package/dist/_chunks/index-DVAIIsOs.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-ls3gxfpH.mjs → layout-Bxsv5mP7.mjs} +6 -5
- package/dist/_chunks/{layout-ls3gxfpH.mjs.map → layout-Bxsv5mP7.mjs.map} +1 -1
- package/dist/_chunks/{layout-C788OmNr.js → layout-C3fN7Ejz.js} +7 -7
- package/dist/_chunks/{layout-C788OmNr.js.map → layout-C3fN7Ejz.js.map} +1 -1
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-DYeotliT.js → relations-BPZKAoEY.js} +6 -7
- package/dist/_chunks/relations-BPZKAoEY.js.map +1 -0
- package/dist/_chunks/{relations-CLcOmGO0.mjs → relations-o3pPhzY4.mjs} +6 -7
- package/dist/_chunks/relations-o3pPhzY4.mjs.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/_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 +4 -3
- package/dist/admin/src/content-manager.d.ts +3 -2
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +0 -32
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/router.d.ts +1 -1
- package/dist/admin/src/services/documents.d.ts +3 -4
- package/dist/server/index.js +453 -201
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +453 -200
- 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/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/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 +17 -15
- package/dist/_chunks/EditViewPage-B-RJeiJD.js.map +0 -1
- package/dist/_chunks/EditViewPage-De8GyU8P.mjs.map +0 -1
- package/dist/_chunks/Field-dq8Tg1M_.js.map +0 -1
- package/dist/_chunks/Field-pb2o8uBe.mjs.map +0 -1
- package/dist/_chunks/Form-DGIf4jQU.js.map +0 -1
- package/dist/_chunks/Form-DJn0Dxha.mjs.map +0 -1
- package/dist/_chunks/History-BowL3JKP.mjs.map +0 -1
- package/dist/_chunks/History-Dh2NEHnR.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-BpVOB-hn.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-BxYCWz9e.js.map +0 -1
- package/dist/_chunks/ListViewPage-4XsciqHZ.js.map +0 -1
- package/dist/_chunks/ListViewPage-CXFUjZQC.mjs.map +0 -1
- package/dist/_chunks/Relations-CVNLrn1Y.mjs.map +0 -1
- package/dist/_chunks/Relations-DPFCAa7b.js.map +0 -1
- package/dist/_chunks/index-C3fJE-1-.js.map +0 -1
- package/dist/_chunks/index-DiMrfcfy.mjs.map +0 -1
- package/dist/_chunks/relations-CLcOmGO0.mjs.map +0 -1
- package/dist/_chunks/relations-DYeotliT.js.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
@@ -1,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 { Menu, Button, VisuallyHidden, Flex,
|
6
|
+
import { Menu, Button, VisuallyHidden, Flex, Dialog, Modal, Typography, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
|
7
|
+
import mapValues from "lodash/fp/mapValues";
|
7
8
|
import { useIntl } from "react-intl";
|
8
9
|
import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
9
10
|
import { styled } from "styled-components";
|
10
11
|
import * as yup from "yup";
|
11
12
|
import { ValidationError } from "yup";
|
13
|
+
import { stringify } from "qs";
|
12
14
|
import pipe from "lodash/fp/pipe";
|
13
15
|
import { intervalToDuration, isPast } from "date-fns";
|
14
|
-
import { stringify } from "qs";
|
15
16
|
import { createSlice, combineReducers } from "@reduxjs/toolkit";
|
16
|
-
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
17
|
+
const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
|
17
18
|
const v = glob[path];
|
18
19
|
if (v) {
|
19
20
|
return typeof v === "function" ? v() : Promise.resolve(v);
|
20
21
|
}
|
21
22
|
return new Promise((_, reject) => {
|
22
|
-
(typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
|
23
|
+
(typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)(
|
24
|
+
reject.bind(
|
25
|
+
null,
|
26
|
+
new Error(
|
27
|
+
"Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "")
|
28
|
+
)
|
29
|
+
)
|
30
|
+
);
|
23
31
|
});
|
24
32
|
};
|
25
33
|
const PLUGIN_ID = "content-manager";
|
@@ -100,6 +108,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
100
108
|
if (!slug) {
|
101
109
|
throw new Error("Cannot find the slug param in the URL");
|
102
110
|
}
|
111
|
+
const [{ rawQuery }] = useQueryParams();
|
103
112
|
const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
|
104
113
|
const contentTypePermissions = React.useMemo(() => {
|
105
114
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -110,7 +119,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
110
119
|
return { ...acc, [action]: [permission] };
|
111
120
|
}, {});
|
112
121
|
}, [slug, userPermissions]);
|
113
|
-
const { isLoading, allowedActions } = useRBAC(
|
122
|
+
const { isLoading, allowedActions } = useRBAC(
|
123
|
+
contentTypePermissions,
|
124
|
+
permissions ?? void 0,
|
125
|
+
// TODO: useRBAC context should be typed and built differently
|
126
|
+
// We are passing raw query as context to the hook so that it can
|
127
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
128
|
+
rawQuery
|
129
|
+
);
|
114
130
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
115
131
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
116
132
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -265,7 +281,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
265
281
|
url: `/content-manager/collection-types/${model}`,
|
266
282
|
method: "GET",
|
267
283
|
config: {
|
268
|
-
params
|
284
|
+
params: stringify(params, { encode: true })
|
269
285
|
}
|
270
286
|
}),
|
271
287
|
providesTags: (result, _error, arg) => {
|
@@ -444,8 +460,7 @@ const {
|
|
444
460
|
useUnpublishManyDocumentsMutation
|
445
461
|
} = documentApi;
|
446
462
|
const buildValidParams = (query) => {
|
447
|
-
if (!query)
|
448
|
-
return query;
|
463
|
+
if (!query) return query;
|
449
464
|
const { plugins: _, ...validQueryParams } = {
|
450
465
|
...query,
|
451
466
|
...Object.values(query?.plugins ?? {}).reduce(
|
@@ -453,14 +468,29 @@ const buildValidParams = (query) => {
|
|
453
468
|
{}
|
454
469
|
)
|
455
470
|
};
|
456
|
-
if ("_q" in validQueryParams) {
|
457
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
458
|
-
}
|
459
471
|
return validQueryParams;
|
460
472
|
};
|
461
473
|
const isBaseQueryError = (error) => {
|
462
474
|
return error.name !== void 0;
|
463
475
|
};
|
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
|
+
});
|
464
494
|
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
465
495
|
const createModelSchema = (attributes2) => yup.object().shape(
|
466
496
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
@@ -468,6 +498,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
468
498
|
return acc;
|
469
499
|
}
|
470
500
|
const validations = [
|
501
|
+
addNullableValidation,
|
471
502
|
addRequiredValidation,
|
472
503
|
addMinLengthValidation,
|
473
504
|
addMaxLengthValidation,
|
@@ -484,12 +515,12 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
484
515
|
...acc,
|
485
516
|
[name]: transformSchema(
|
486
517
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
487
|
-
)
|
518
|
+
).test(arrayValidator(attribute, options))
|
488
519
|
};
|
489
520
|
} else {
|
490
521
|
return {
|
491
522
|
...acc,
|
492
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
523
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
493
524
|
};
|
494
525
|
}
|
495
526
|
}
|
@@ -511,7 +542,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
511
542
|
}
|
512
543
|
)
|
513
544
|
)
|
514
|
-
)
|
545
|
+
).test(arrayValidator(attribute, options))
|
515
546
|
};
|
516
547
|
case "relation":
|
517
548
|
return {
|
@@ -523,7 +554,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
523
554
|
} else if (Array.isArray(value)) {
|
524
555
|
return yup.array().of(
|
525
556
|
yup.object().shape({
|
526
|
-
id: yup.
|
557
|
+
id: yup.number().required()
|
527
558
|
})
|
528
559
|
);
|
529
560
|
} else if (typeof value === "object") {
|
@@ -609,17 +640,17 @@ const nullableSchema = (schema) => {
|
|
609
640
|
schema
|
610
641
|
);
|
611
642
|
};
|
643
|
+
const addNullableValidation = () => (schema) => {
|
644
|
+
return nullableSchema(schema);
|
645
|
+
};
|
612
646
|
const addRequiredValidation = (attribute, options) => (schema) => {
|
613
|
-
if (options.status === "draft") {
|
614
|
-
return
|
615
|
-
}
|
616
|
-
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
617
|
-
return schema.min(1, translatedErrors.required);
|
647
|
+
if (options.status === "draft" || !attribute.required) {
|
648
|
+
return schema;
|
618
649
|
}
|
619
|
-
if (attribute.required &&
|
650
|
+
if (attribute.required && "required" in schema) {
|
620
651
|
return schema.required(translatedErrors.required);
|
621
652
|
}
|
622
|
-
return
|
653
|
+
return schema;
|
623
654
|
};
|
624
655
|
const addMinLengthValidation = (attribute, options) => (schema) => {
|
625
656
|
if (options.status === "draft") {
|
@@ -647,31 +678,12 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
647
678
|
return schema;
|
648
679
|
};
|
649
680
|
const addMinValidation = (attribute, options) => (schema) => {
|
650
|
-
if ("
|
681
|
+
if (options.status === "draft") {
|
682
|
+
return schema;
|
683
|
+
}
|
684
|
+
if ("min" in attribute && "min" in schema) {
|
651
685
|
const min = toInteger(attribute.min);
|
652
|
-
if (
|
653
|
-
if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
|
654
|
-
return schema.test(
|
655
|
-
"custom-min",
|
656
|
-
{
|
657
|
-
...translatedErrors.min,
|
658
|
-
values: {
|
659
|
-
min: attribute.min
|
660
|
-
}
|
661
|
-
},
|
662
|
-
(value) => {
|
663
|
-
if (!value) {
|
664
|
-
return true;
|
665
|
-
}
|
666
|
-
if (Array.isArray(value) && value.length === 0) {
|
667
|
-
return true;
|
668
|
-
}
|
669
|
-
return value.length >= min;
|
670
|
-
}
|
671
|
-
);
|
672
|
-
}
|
673
|
-
}
|
674
|
-
if ("min" in schema && min) {
|
686
|
+
if (min) {
|
675
687
|
return schema.min(min, {
|
676
688
|
...translatedErrors.min,
|
677
689
|
values: {
|
@@ -789,19 +801,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
789
801
|
}, {});
|
790
802
|
return componentsByKey;
|
791
803
|
};
|
792
|
-
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);
|
793
903
|
const { toggleNotification } = useNotification();
|
794
904
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
905
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
795
906
|
const {
|
796
|
-
|
797
|
-
isLoading:
|
798
|
-
|
799
|
-
|
800
|
-
} =
|
801
|
-
|
802
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
803
|
-
});
|
804
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
907
|
+
data,
|
908
|
+
isLoading: isLoadingConfigs,
|
909
|
+
error,
|
910
|
+
isFetching: isFetchingConfigs
|
911
|
+
} = useGetContentTypeConfigurationQuery(model);
|
912
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
805
913
|
React.useEffect(() => {
|
806
914
|
if (error) {
|
807
915
|
toggleNotification({
|
@@ -809,398 +917,654 @@ const useDocument = (args, opts) => {
|
|
809
917
|
message: formatAPIError(error)
|
810
918
|
});
|
811
919
|
}
|
812
|
-
}, [
|
813
|
-
const
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
(document) => {
|
821
|
-
if (!validationSchema) {
|
822
|
-
throw new Error(
|
823
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
824
|
-
);
|
825
|
-
}
|
826
|
-
try {
|
827
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
828
|
-
return null;
|
829
|
-
} catch (error2) {
|
830
|
-
if (error2 instanceof ValidationError) {
|
831
|
-
return getYupValidationErrors(error2);
|
832
|
-
}
|
833
|
-
throw error2;
|
834
|
-
}
|
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
|
835
928
|
},
|
836
|
-
[
|
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]
|
837
945
|
);
|
838
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
839
946
|
return {
|
840
|
-
|
841
|
-
document: data?.data,
|
842
|
-
meta: data?.meta,
|
947
|
+
error,
|
843
948
|
isLoading,
|
844
|
-
|
845
|
-
|
846
|
-
};
|
847
|
-
};
|
848
|
-
const useDoc = () => {
|
849
|
-
const { id, slug, collectionType, origin } = useParams();
|
850
|
-
const [{ query }] = useQueryParams();
|
851
|
-
const params = React.useMemo(() => buildValidParams(query), [query]);
|
852
|
-
if (!collectionType) {
|
853
|
-
throw new Error("Could not find collectionType in url params");
|
854
|
-
}
|
855
|
-
if (!slug) {
|
856
|
-
throw new Error("Could not find model in url params");
|
857
|
-
}
|
858
|
-
return {
|
859
|
-
collectionType,
|
860
|
-
model: slug,
|
861
|
-
id: origin || id === "create" ? void 0 : id,
|
862
|
-
...useDocument(
|
863
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
864
|
-
{
|
865
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
866
|
-
}
|
867
|
-
)
|
949
|
+
edit,
|
950
|
+
list: listLayout
|
868
951
|
};
|
869
952
|
};
|
870
|
-
const
|
871
|
-
|
872
|
-
|
873
|
-
}
|
874
|
-
return Object.keys(trad).reduce((acc, current) => {
|
875
|
-
acc[`${pluginId}.${current}`] = trad[current];
|
876
|
-
return acc;
|
877
|
-
}, {});
|
878
|
-
};
|
879
|
-
const getTranslation = (id) => `content-manager.${id}`;
|
880
|
-
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
881
|
-
id: "notification.error",
|
882
|
-
defaultMessage: "An error occurred, please try again"
|
953
|
+
const useDocLayout = () => {
|
954
|
+
const { model } = useDoc();
|
955
|
+
return useDocumentLayout(model);
|
883
956
|
};
|
884
|
-
const
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
const
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
});
|
906
|
-
return { error: res.error };
|
907
|
-
}
|
908
|
-
toggleNotification({
|
909
|
-
type: "success",
|
910
|
-
message: formatMessage({
|
911
|
-
id: getTranslation("success.record.delete"),
|
912
|
-
defaultMessage: "Deleted document"
|
913
|
-
})
|
914
|
-
});
|
915
|
-
trackUsage("didDeleteEntry", trackerProperty);
|
916
|
-
return res.data;
|
917
|
-
} catch (err) {
|
918
|
-
toggleNotification({
|
919
|
-
type: "danger",
|
920
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
921
|
-
});
|
922
|
-
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
923
|
-
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);
|
924
978
|
}
|
925
|
-
}
|
926
|
-
|
927
|
-
);
|
928
|
-
const
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
message: formatAPIError(res.error)
|
942
|
-
});
|
943
|
-
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
|
944
995
|
}
|
945
|
-
|
946
|
-
|
947
|
-
title: formatMessage({
|
948
|
-
id: getTranslation("success.records.delete"),
|
949
|
-
defaultMessage: "Successfully deleted."
|
950
|
-
}),
|
951
|
-
message: ""
|
952
|
-
});
|
953
|
-
trackUsage("didBulkDeleteEntries");
|
954
|
-
return res.data;
|
955
|
-
} catch (err) {
|
956
|
-
toggleNotification({
|
957
|
-
type: "danger",
|
958
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
959
|
-
});
|
960
|
-
trackUsage("didNotBulkDeleteEntries");
|
961
|
-
throw err;
|
962
|
-
}
|
996
|
+
};
|
997
|
+
return acc;
|
963
998
|
},
|
964
|
-
|
999
|
+
{}
|
965
1000
|
);
|
966
|
-
const
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
model,
|
973
|
-
documentId,
|
974
|
-
params
|
975
|
-
});
|
976
|
-
if ("error" in res) {
|
977
|
-
toggleNotification({
|
978
|
-
type: "danger",
|
979
|
-
message: formatAPIError(res.error)
|
980
|
-
});
|
981
|
-
return { error: res.error };
|
982
|
-
}
|
983
|
-
toggleNotification({
|
984
|
-
type: "success",
|
985
|
-
message: formatMessage({
|
986
|
-
id: "content-manager.success.record.discard",
|
987
|
-
defaultMessage: "Changes discarded"
|
988
|
-
})
|
989
|
-
});
|
990
|
-
return res.data;
|
991
|
-
} catch (err) {
|
992
|
-
toggleNotification({
|
993
|
-
type: "danger",
|
994
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
995
|
-
});
|
996
|
-
throw err;
|
997
|
-
}
|
1001
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1002
|
+
(acc, [attribute, metadata]) => {
|
1003
|
+
return {
|
1004
|
+
...acc,
|
1005
|
+
[attribute]: metadata.edit
|
1006
|
+
};
|
998
1007
|
},
|
999
|
-
|
1008
|
+
{}
|
1000
1009
|
);
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
model,
|
1009
|
-
documentId,
|
1010
|
-
data,
|
1011
|
-
params
|
1012
|
-
});
|
1013
|
-
if ("error" in res) {
|
1014
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1015
|
-
return { error: res.error };
|
1016
|
-
}
|
1017
|
-
trackUsage("didPublishEntry");
|
1018
|
-
toggleNotification({
|
1019
|
-
type: "success",
|
1020
|
-
message: formatMessage({
|
1021
|
-
id: getTranslation("success.record.publish"),
|
1022
|
-
defaultMessage: "Published document"
|
1023
|
-
})
|
1024
|
-
});
|
1025
|
-
return res.data;
|
1026
|
-
} catch (err) {
|
1027
|
-
toggleNotification({
|
1028
|
-
type: "danger",
|
1029
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1030
|
-
});
|
1031
|
-
throw err;
|
1032
|
-
}
|
1010
|
+
return {
|
1011
|
+
layout: panelledEditAttributes,
|
1012
|
+
components: componentEditAttributes,
|
1013
|
+
metadatas: editMetadatas,
|
1014
|
+
settings: {
|
1015
|
+
...data.contentType.settings,
|
1016
|
+
displayName: schema?.info.displayName
|
1033
1017
|
},
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
return { error: res.error };
|
1048
|
-
}
|
1049
|
-
toggleNotification({
|
1050
|
-
type: "success",
|
1051
|
-
message: formatMessage({
|
1052
|
-
id: getTranslation("success.record.publish"),
|
1053
|
-
defaultMessage: "Published document"
|
1054
|
-
})
|
1055
|
-
});
|
1056
|
-
return res.data;
|
1057
|
-
} catch (err) {
|
1058
|
-
toggleNotification({
|
1059
|
-
type: "danger",
|
1060
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1061
|
-
});
|
1062
|
-
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;
|
1063
1031
|
}
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
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)
|
1072
1053
|
);
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
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
|
+
}
|
1147
|
+
try {
|
1148
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1149
|
+
return null;
|
1150
|
+
} catch (error2) {
|
1151
|
+
if (error2 instanceof ValidationError) {
|
1152
|
+
return getYupValidationErrors(error2);
|
1089
1153
|
}
|
1090
|
-
|
1091
|
-
toggleNotification({
|
1092
|
-
type: "success",
|
1093
|
-
message: formatMessage({
|
1094
|
-
id: getTranslation("success.record.save"),
|
1095
|
-
defaultMessage: "Saved document"
|
1096
|
-
})
|
1097
|
-
});
|
1098
|
-
return res.data;
|
1099
|
-
} catch (err) {
|
1100
|
-
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1101
|
-
toggleNotification({
|
1102
|
-
type: "danger",
|
1103
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1104
|
-
});
|
1105
|
-
throw err;
|
1154
|
+
throw error2;
|
1106
1155
|
}
|
1107
1156
|
},
|
1108
|
-
[
|
1157
|
+
[validationSchema]
|
1109
1158
|
);
|
1110
|
-
const
|
1111
|
-
const
|
1112
|
-
|
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) => {
|
1113
1256
|
try {
|
1114
|
-
trackUsage("
|
1115
|
-
const res = await
|
1257
|
+
trackUsage("willDeleteEntry", trackerProperty);
|
1258
|
+
const res = await deleteDocument({
|
1116
1259
|
collectionType,
|
1117
1260
|
model,
|
1118
1261
|
documentId,
|
1119
|
-
params
|
1120
|
-
data: {
|
1121
|
-
discardDraft
|
1122
|
-
}
|
1262
|
+
params
|
1123
1263
|
});
|
1124
1264
|
if ("error" in res) {
|
1125
|
-
toggleNotification({
|
1265
|
+
toggleNotification({
|
1266
|
+
type: "danger",
|
1267
|
+
message: formatAPIError(res.error)
|
1268
|
+
});
|
1126
1269
|
return { error: res.error };
|
1127
1270
|
}
|
1128
|
-
trackUsage("didUnpublishEntry");
|
1129
1271
|
toggleNotification({
|
1130
1272
|
type: "success",
|
1131
1273
|
message: formatMessage({
|
1132
|
-
id: getTranslation("success.record.
|
1133
|
-
defaultMessage: "
|
1274
|
+
id: getTranslation("success.record.delete"),
|
1275
|
+
defaultMessage: "Deleted document"
|
1134
1276
|
})
|
1135
1277
|
});
|
1278
|
+
trackUsage("didDeleteEntry", trackerProperty);
|
1136
1279
|
return res.data;
|
1137
1280
|
} catch (err) {
|
1138
1281
|
toggleNotification({
|
1139
1282
|
type: "danger",
|
1140
1283
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1141
1284
|
});
|
1285
|
+
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
1142
1286
|
throw err;
|
1143
1287
|
}
|
1144
1288
|
},
|
1145
|
-
[trackUsage,
|
1289
|
+
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
1146
1290
|
);
|
1147
|
-
const [
|
1148
|
-
const
|
1291
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1292
|
+
const deleteMany = React.useCallback(
|
1149
1293
|
async ({ model, documentIds, params }) => {
|
1150
1294
|
try {
|
1151
|
-
trackUsage("
|
1152
|
-
const res = await
|
1295
|
+
trackUsage("willBulkDeleteEntries");
|
1296
|
+
const res = await deleteManyDocuments({
|
1153
1297
|
model,
|
1154
1298
|
documentIds,
|
1155
1299
|
params
|
1156
1300
|
});
|
1157
1301
|
if ("error" in res) {
|
1158
|
-
toggleNotification({
|
1302
|
+
toggleNotification({
|
1303
|
+
type: "danger",
|
1304
|
+
message: formatAPIError(res.error)
|
1305
|
+
});
|
1159
1306
|
return { error: res.error };
|
1160
1307
|
}
|
1161
|
-
trackUsage("didBulkUnpublishEntries");
|
1162
1308
|
toggleNotification({
|
1163
1309
|
type: "success",
|
1164
1310
|
title: formatMessage({
|
1165
|
-
id: getTranslation("success.records.
|
1166
|
-
defaultMessage: "Successfully
|
1311
|
+
id: getTranslation("success.records.delete"),
|
1312
|
+
defaultMessage: "Successfully deleted."
|
1167
1313
|
}),
|
1168
1314
|
message: ""
|
1169
1315
|
});
|
1316
|
+
trackUsage("didBulkDeleteEntries");
|
1170
1317
|
return res.data;
|
1171
1318
|
} catch (err) {
|
1172
1319
|
toggleNotification({
|
1173
1320
|
type: "danger",
|
1174
1321
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1175
1322
|
});
|
1176
|
-
trackUsage("
|
1323
|
+
trackUsage("didNotBulkDeleteEntries");
|
1177
1324
|
throw err;
|
1178
1325
|
}
|
1179
1326
|
},
|
1180
|
-
[trackUsage,
|
1327
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1181
1328
|
);
|
1182
|
-
const [
|
1183
|
-
const
|
1184
|
-
async ({ model, params }
|
1329
|
+
const [discardDocument] = useDiscardDocumentMutation();
|
1330
|
+
const discard = React.useCallback(
|
1331
|
+
async ({ collectionType, model, documentId, params }) => {
|
1185
1332
|
try {
|
1186
|
-
const res = await
|
1333
|
+
const res = await discardDocument({
|
1334
|
+
collectionType,
|
1187
1335
|
model,
|
1188
|
-
|
1336
|
+
documentId,
|
1189
1337
|
params
|
1190
1338
|
});
|
1191
1339
|
if ("error" in res) {
|
1192
|
-
toggleNotification({
|
1193
|
-
|
1340
|
+
toggleNotification({
|
1341
|
+
type: "danger",
|
1342
|
+
message: formatAPIError(res.error)
|
1343
|
+
});
|
1194
1344
|
return { error: res.error };
|
1195
1345
|
}
|
1196
|
-
trackUsage("didCreateEntry", trackerProperty);
|
1197
1346
|
toggleNotification({
|
1198
1347
|
type: "success",
|
1199
1348
|
message: formatMessage({
|
1200
|
-
id:
|
1201
|
-
defaultMessage: "
|
1202
|
-
})
|
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"),
|
1564
|
+
defaultMessage: "Saved document"
|
1565
|
+
})
|
1203
1566
|
});
|
1567
|
+
setCurrentStep("contentManager.success");
|
1204
1568
|
return res.data;
|
1205
1569
|
} catch (err) {
|
1206
1570
|
toggleNotification({
|
@@ -1302,10 +1666,10 @@ const useDocumentActions = () => {
|
|
1302
1666
|
update
|
1303
1667
|
};
|
1304
1668
|
};
|
1305
|
-
const ProtectedHistoryPage = lazy(
|
1306
|
-
() => import("./History-
|
1669
|
+
const ProtectedHistoryPage = React.lazy(
|
1670
|
+
() => import("./History-CqNgxkqK.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1307
1671
|
);
|
1308
|
-
const routes$
|
1672
|
+
const routes$2 = [
|
1309
1673
|
{
|
1310
1674
|
path: ":collectionType/:slug/:id/history",
|
1311
1675
|
Component: ProtectedHistoryPage
|
@@ -1315,32 +1679,45 @@ const routes$1 = [
|
|
1315
1679
|
Component: ProtectedHistoryPage
|
1316
1680
|
}
|
1317
1681
|
];
|
1682
|
+
const ProtectedPreviewPage = React.lazy(
|
1683
|
+
() => import("./Preview-BaYGJ0nb.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
|
+
];
|
1318
1695
|
const ProtectedEditViewPage = lazy(
|
1319
|
-
() => import("./EditViewPage-
|
1696
|
+
() => import("./EditViewPage-BCjNxNlY.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1320
1697
|
);
|
1321
1698
|
const ProtectedListViewPage = lazy(
|
1322
|
-
() => import("./ListViewPage-
|
1699
|
+
() => import("./ListViewPage-D4ofkbjR.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1323
1700
|
);
|
1324
1701
|
const ProtectedListConfiguration = lazy(
|
1325
|
-
() => import("./ListConfigurationPage-
|
1702
|
+
() => import("./ListConfigurationPage-BbQjzKkQ.mjs").then((mod) => ({
|
1326
1703
|
default: mod.ProtectedListConfiguration
|
1327
1704
|
}))
|
1328
1705
|
);
|
1329
1706
|
const ProtectedEditConfigurationPage = lazy(
|
1330
|
-
() => import("./EditConfigurationPage-
|
1707
|
+
() => import("./EditConfigurationPage-BhRSnUsL.mjs").then((mod) => ({
|
1331
1708
|
default: mod.ProtectedEditConfigurationPage
|
1332
1709
|
}))
|
1333
1710
|
);
|
1334
1711
|
const ProtectedComponentConfigurationPage = lazy(
|
1335
|
-
() => import("./ComponentConfigurationPage-
|
1712
|
+
() => import("./ComponentConfigurationPage-bLQr82ce.mjs").then((mod) => ({
|
1336
1713
|
default: mod.ProtectedComponentConfigurationPage
|
1337
1714
|
}))
|
1338
1715
|
);
|
1339
1716
|
const NoPermissions = lazy(
|
1340
|
-
() => import("./NoPermissionsPage-
|
1717
|
+
() => import("./NoPermissionsPage-DhIiyWkk.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1341
1718
|
);
|
1342
1719
|
const NoContentType = lazy(
|
1343
|
-
() => import("./NoContentTypePage-
|
1720
|
+
() => import("./NoContentTypePage-DyUx5mXh.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1344
1721
|
);
|
1345
1722
|
const CollectionTypePages = () => {
|
1346
1723
|
const { collectionType } = useParams();
|
@@ -1352,7 +1729,7 @@ const CollectionTypePages = () => {
|
|
1352
1729
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1353
1730
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1354
1731
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1355
|
-
const LIST_PATH = `/content-manager
|
1732
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1356
1733
|
const routes = [
|
1357
1734
|
{
|
1358
1735
|
path: LIST_RELATIVE_PATH,
|
@@ -1386,6 +1763,7 @@ const routes = [
|
|
1386
1763
|
path: "no-content-types",
|
1387
1764
|
Component: NoContentType
|
1388
1765
|
},
|
1766
|
+
...routes$2,
|
1389
1767
|
...routes$1
|
1390
1768
|
];
|
1391
1769
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1484,6 +1862,11 @@ const DocumentActionButton = (action) => {
|
|
1484
1862
|
) : null
|
1485
1863
|
] });
|
1486
1864
|
};
|
1865
|
+
const MenuItem = styled(Menu.Item)`
|
1866
|
+
&:hover {
|
1867
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1868
|
+
}
|
1869
|
+
`;
|
1487
1870
|
const DocumentActionsMenu = ({
|
1488
1871
|
actions: actions2,
|
1489
1872
|
children,
|
@@ -1521,7 +1904,7 @@ const DocumentActionsMenu = ({
|
|
1521
1904
|
};
|
1522
1905
|
return /* @__PURE__ */ jsxs(Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1523
1906
|
/* @__PURE__ */ jsxs(
|
1524
|
-
|
1907
|
+
Menu.Trigger,
|
1525
1908
|
{
|
1526
1909
|
disabled: isDisabled,
|
1527
1910
|
size: "S",
|
@@ -1539,51 +1922,35 @@ const DocumentActionsMenu = ({
|
|
1539
1922
|
]
|
1540
1923
|
}
|
1541
1924
|
),
|
1542
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1925
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1543
1926
|
actions2.map((action) => {
|
1544
1927
|
return /* @__PURE__ */ jsx(
|
1545
|
-
|
1928
|
+
MenuItem,
|
1546
1929
|
{
|
1547
1930
|
disabled: action.disabled,
|
1548
1931
|
onSelect: handleClick(action),
|
1549
1932
|
display: "block",
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
Flex,
|
1572
|
-
{
|
1573
|
-
alignItems: "center",
|
1574
|
-
background: "alternative100",
|
1575
|
-
borderStyle: "solid",
|
1576
|
-
borderColor: "alternative200",
|
1577
|
-
borderWidth: "1px",
|
1578
|
-
height: 5,
|
1579
|
-
paddingLeft: 2,
|
1580
|
-
paddingRight: 2,
|
1581
|
-
hasRadius: true,
|
1582
|
-
color: "alternative600",
|
1583
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1584
|
-
}
|
1585
|
-
)
|
1586
|
-
] })
|
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
|
+
) })
|
1587
1954
|
},
|
1588
1955
|
action.id
|
1589
1956
|
);
|
@@ -1637,11 +2004,6 @@ const convertActionVariantToIconColor = (variant = "secondary") => {
|
|
1637
2004
|
return "primary600";
|
1638
2005
|
}
|
1639
2006
|
};
|
1640
|
-
const StyledMoreButton = styled(Menu.Trigger)`
|
1641
|
-
& > span {
|
1642
|
-
display: flex;
|
1643
|
-
}
|
1644
|
-
`;
|
1645
2007
|
const DocumentActionConfirmDialog = ({
|
1646
2008
|
onClose,
|
1647
2009
|
onCancel,
|
@@ -1668,11 +2030,11 @@ const DocumentActionConfirmDialog = ({
|
|
1668
2030
|
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1669
2031
|
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1670
2032
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1671
|
-
/* @__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({
|
1672
2034
|
id: "app.components.Button.cancel",
|
1673
2035
|
defaultMessage: "Cancel"
|
1674
2036
|
}) }) }),
|
1675
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2037
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1676
2038
|
id: "app.components.Button.confirm",
|
1677
2039
|
defaultMessage: "Confirm"
|
1678
2040
|
}) })
|
@@ -1699,6 +2061,18 @@ const DocumentActionModal = ({
|
|
1699
2061
|
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1700
2062
|
] }) });
|
1701
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
|
+
};
|
1702
2076
|
const PublishAction$1 = ({
|
1703
2077
|
activeTab,
|
1704
2078
|
documentId,
|
@@ -1713,6 +2087,7 @@ const PublishAction$1 = ({
|
|
1713
2087
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
1714
2088
|
const isListView = useMatch(LIST_PATH) !== null;
|
1715
2089
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2090
|
+
const { id } = useParams();
|
1716
2091
|
const { formatMessage } = useIntl();
|
1717
2092
|
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1718
2093
|
const { publish } = useDocumentActions();
|
@@ -1766,24 +2141,25 @@ const PublishAction$1 = ({
|
|
1766
2141
|
}
|
1767
2142
|
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1768
2143
|
React.useEffect(() => {
|
1769
|
-
if (documentId
|
1770
|
-
|
1771
|
-
const { data, error } = await countDraftRelations({
|
1772
|
-
collectionType,
|
1773
|
-
model,
|
1774
|
-
documentId,
|
1775
|
-
params
|
1776
|
-
});
|
1777
|
-
if (error) {
|
1778
|
-
throw error;
|
1779
|
-
}
|
1780
|
-
if (data) {
|
1781
|
-
setServerCountOfDraftRelations(data.data);
|
1782
|
-
}
|
1783
|
-
};
|
1784
|
-
fetchDraftRelationsCount();
|
2144
|
+
if (!document || !document.documentId || isListView) {
|
2145
|
+
return;
|
1785
2146
|
}
|
1786
|
-
|
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]);
|
1787
2163
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1788
2164
|
if (!schema?.options?.draftAndPublish) {
|
1789
2165
|
return null;
|
@@ -1791,7 +2167,9 @@ const PublishAction$1 = ({
|
|
1791
2167
|
const performPublish = async () => {
|
1792
2168
|
setSubmitting(true);
|
1793
2169
|
try {
|
1794
|
-
const { errors } = await validate(
|
2170
|
+
const { errors } = await validate(true, {
|
2171
|
+
status: "published"
|
2172
|
+
});
|
1795
2173
|
if (errors) {
|
1796
2174
|
toggleNotification({
|
1797
2175
|
type: "danger",
|
@@ -1809,13 +2187,15 @@ const PublishAction$1 = ({
|
|
1809
2187
|
documentId,
|
1810
2188
|
params
|
1811
2189
|
},
|
1812
|
-
formValues
|
2190
|
+
transformData(formValues)
|
1813
2191
|
);
|
1814
2192
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1815
|
-
|
1816
|
-
|
1817
|
-
|
1818
|
-
|
2193
|
+
if (id === "create") {
|
2194
|
+
navigate({
|
2195
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2196
|
+
search: rawQuery
|
2197
|
+
});
|
2198
|
+
}
|
1819
2199
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1820
2200
|
setErrors(formatValidationErrors(res.error));
|
1821
2201
|
}
|
@@ -1824,7 +2204,8 @@ const PublishAction$1 = ({
|
|
1824
2204
|
}
|
1825
2205
|
};
|
1826
2206
|
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1827
|
-
const
|
2207
|
+
const enableDraftRelationsCount = false;
|
2208
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1828
2209
|
return {
|
1829
2210
|
/**
|
1830
2211
|
* Disabled when:
|
@@ -1841,9 +2222,6 @@ const PublishAction$1 = ({
|
|
1841
2222
|
defaultMessage: "Publish"
|
1842
2223
|
}),
|
1843
2224
|
onClick: async () => {
|
1844
|
-
if (hasDraftRelations) {
|
1845
|
-
return;
|
1846
|
-
}
|
1847
2225
|
await performPublish();
|
1848
2226
|
},
|
1849
2227
|
dialog: hasDraftRelations ? {
|
@@ -1870,6 +2248,7 @@ const PublishAction$1 = ({
|
|
1870
2248
|
};
|
1871
2249
|
};
|
1872
2250
|
PublishAction$1.type = "publish";
|
2251
|
+
PublishAction$1.position = "panel";
|
1873
2252
|
const UpdateAction = ({
|
1874
2253
|
activeTab,
|
1875
2254
|
documentId,
|
@@ -1892,6 +2271,117 @@ const UpdateAction = ({
|
|
1892
2271
|
const validate = useForm("UpdateAction", (state) => state.validate);
|
1893
2272
|
const setErrors = useForm("UpdateAction", (state) => state.setErrors);
|
1894
2273
|
const resetForm = useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
2274
|
+
const handleUpdate = React.useCallback(async () => {
|
2275
|
+
setSubmitting(true);
|
2276
|
+
try {
|
2277
|
+
if (!modified) {
|
2278
|
+
return;
|
2279
|
+
}
|
2280
|
+
const { errors } = await validate(true, {
|
2281
|
+
status: "draft"
|
2282
|
+
});
|
2283
|
+
if (errors) {
|
2284
|
+
toggleNotification({
|
2285
|
+
type: "danger",
|
2286
|
+
message: formatMessage({
|
2287
|
+
id: "content-manager.validation.error",
|
2288
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2289
|
+
})
|
2290
|
+
});
|
2291
|
+
return;
|
2292
|
+
}
|
2293
|
+
if (isCloning) {
|
2294
|
+
const res = await clone(
|
2295
|
+
{
|
2296
|
+
model,
|
2297
|
+
documentId: cloneMatch.params.origin,
|
2298
|
+
params
|
2299
|
+
},
|
2300
|
+
transformData(document)
|
2301
|
+
);
|
2302
|
+
if ("data" in res) {
|
2303
|
+
navigate(
|
2304
|
+
{
|
2305
|
+
pathname: `../${res.data.documentId}`,
|
2306
|
+
search: rawQuery
|
2307
|
+
},
|
2308
|
+
{ relative: "path" }
|
2309
|
+
);
|
2310
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2311
|
+
setErrors(formatValidationErrors(res.error));
|
2312
|
+
}
|
2313
|
+
} else if (documentId || collectionType === SINGLE_TYPES) {
|
2314
|
+
const res = await update(
|
2315
|
+
{
|
2316
|
+
collectionType,
|
2317
|
+
model,
|
2318
|
+
documentId,
|
2319
|
+
params
|
2320
|
+
},
|
2321
|
+
transformData(document)
|
2322
|
+
);
|
2323
|
+
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2324
|
+
setErrors(formatValidationErrors(res.error));
|
2325
|
+
} else {
|
2326
|
+
resetForm();
|
2327
|
+
}
|
2328
|
+
} else {
|
2329
|
+
const res = await create(
|
2330
|
+
{
|
2331
|
+
model,
|
2332
|
+
params
|
2333
|
+
},
|
2334
|
+
transformData(document)
|
2335
|
+
);
|
2336
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2337
|
+
navigate(
|
2338
|
+
{
|
2339
|
+
pathname: `../${res.data.documentId}`,
|
2340
|
+
search: rawQuery
|
2341
|
+
},
|
2342
|
+
{ replace: true, relative: "path" }
|
2343
|
+
);
|
2344
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2345
|
+
setErrors(formatValidationErrors(res.error));
|
2346
|
+
}
|
2347
|
+
}
|
2348
|
+
} finally {
|
2349
|
+
setSubmitting(false);
|
2350
|
+
}
|
2351
|
+
}, [
|
2352
|
+
clone,
|
2353
|
+
cloneMatch?.params.origin,
|
2354
|
+
collectionType,
|
2355
|
+
create,
|
2356
|
+
document,
|
2357
|
+
documentId,
|
2358
|
+
formatMessage,
|
2359
|
+
formatValidationErrors,
|
2360
|
+
isCloning,
|
2361
|
+
model,
|
2362
|
+
modified,
|
2363
|
+
navigate,
|
2364
|
+
params,
|
2365
|
+
rawQuery,
|
2366
|
+
resetForm,
|
2367
|
+
setErrors,
|
2368
|
+
setSubmitting,
|
2369
|
+
toggleNotification,
|
2370
|
+
update,
|
2371
|
+
validate
|
2372
|
+
]);
|
2373
|
+
React.useEffect(() => {
|
2374
|
+
const handleKeyDown = (e) => {
|
2375
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
2376
|
+
e.preventDefault();
|
2377
|
+
handleUpdate();
|
2378
|
+
}
|
2379
|
+
};
|
2380
|
+
window.addEventListener("keydown", handleKeyDown);
|
2381
|
+
return () => {
|
2382
|
+
window.removeEventListener("keydown", handleKeyDown);
|
2383
|
+
};
|
2384
|
+
}, [handleUpdate]);
|
1895
2385
|
return {
|
1896
2386
|
/**
|
1897
2387
|
* Disabled when:
|
@@ -1901,87 +2391,14 @@ const UpdateAction = ({
|
|
1901
2391
|
*/
|
1902
2392
|
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1903
2393
|
label: formatMessage({
|
1904
|
-
id: "
|
2394
|
+
id: "global.save",
|
1905
2395
|
defaultMessage: "Save"
|
1906
2396
|
}),
|
1907
|
-
onClick:
|
1908
|
-
setSubmitting(true);
|
1909
|
-
try {
|
1910
|
-
if (activeTab !== "draft") {
|
1911
|
-
const { errors } = await validate();
|
1912
|
-
if (errors) {
|
1913
|
-
toggleNotification({
|
1914
|
-
type: "danger",
|
1915
|
-
message: formatMessage({
|
1916
|
-
id: "content-manager.validation.error",
|
1917
|
-
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1918
|
-
})
|
1919
|
-
});
|
1920
|
-
return;
|
1921
|
-
}
|
1922
|
-
}
|
1923
|
-
if (isCloning) {
|
1924
|
-
const res = await clone(
|
1925
|
-
{
|
1926
|
-
model,
|
1927
|
-
documentId: cloneMatch.params.origin,
|
1928
|
-
params
|
1929
|
-
},
|
1930
|
-
document
|
1931
|
-
);
|
1932
|
-
if ("data" in res) {
|
1933
|
-
navigate(
|
1934
|
-
{
|
1935
|
-
pathname: `../${res.data.documentId}`,
|
1936
|
-
search: rawQuery
|
1937
|
-
},
|
1938
|
-
{ relative: "path" }
|
1939
|
-
);
|
1940
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1941
|
-
setErrors(formatValidationErrors(res.error));
|
1942
|
-
}
|
1943
|
-
} else if (documentId || collectionType === SINGLE_TYPES) {
|
1944
|
-
const res = await update(
|
1945
|
-
{
|
1946
|
-
collectionType,
|
1947
|
-
model,
|
1948
|
-
documentId,
|
1949
|
-
params
|
1950
|
-
},
|
1951
|
-
document
|
1952
|
-
);
|
1953
|
-
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1954
|
-
setErrors(formatValidationErrors(res.error));
|
1955
|
-
} else {
|
1956
|
-
resetForm();
|
1957
|
-
}
|
1958
|
-
} else {
|
1959
|
-
const res = await create(
|
1960
|
-
{
|
1961
|
-
model,
|
1962
|
-
params
|
1963
|
-
},
|
1964
|
-
document
|
1965
|
-
);
|
1966
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1967
|
-
navigate(
|
1968
|
-
{
|
1969
|
-
pathname: `../${res.data.documentId}`,
|
1970
|
-
search: rawQuery
|
1971
|
-
},
|
1972
|
-
{ replace: true, relative: "path" }
|
1973
|
-
);
|
1974
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1975
|
-
setErrors(formatValidationErrors(res.error));
|
1976
|
-
}
|
1977
|
-
}
|
1978
|
-
} finally {
|
1979
|
-
setSubmitting(false);
|
1980
|
-
}
|
1981
|
-
}
|
2397
|
+
onClick: handleUpdate
|
1982
2398
|
};
|
1983
2399
|
};
|
1984
2400
|
UpdateAction.type = "update";
|
2401
|
+
UpdateAction.position = "panel";
|
1985
2402
|
const UNPUBLISH_DRAFT_OPTIONS = {
|
1986
2403
|
KEEP: "keep",
|
1987
2404
|
DISCARD: "discard"
|
@@ -2014,7 +2431,7 @@ const UnpublishAction$1 = ({
|
|
2014
2431
|
id: "app.utils.unpublish",
|
2015
2432
|
defaultMessage: "Unpublish"
|
2016
2433
|
}),
|
2017
|
-
icon: /* @__PURE__ */ jsx(
|
2434
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2018
2435
|
onClick: async () => {
|
2019
2436
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2020
2437
|
if (!documentId) {
|
@@ -2104,6 +2521,7 @@ const UnpublishAction$1 = ({
|
|
2104
2521
|
};
|
2105
2522
|
};
|
2106
2523
|
UnpublishAction$1.type = "unpublish";
|
2524
|
+
UnpublishAction$1.position = "panel";
|
2107
2525
|
const DiscardAction = ({
|
2108
2526
|
activeTab,
|
2109
2527
|
documentId,
|
@@ -2126,7 +2544,7 @@ const DiscardAction = ({
|
|
2126
2544
|
id: "content-manager.actions.discard.label",
|
2127
2545
|
defaultMessage: "Discard changes"
|
2128
2546
|
}),
|
2129
|
-
icon: /* @__PURE__ */ jsx(
|
2547
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2130
2548
|
position: ["panel", "table-row"],
|
2131
2549
|
variant: "danger",
|
2132
2550
|
dialog: {
|
@@ -2154,11 +2572,7 @@ const DiscardAction = ({
|
|
2154
2572
|
};
|
2155
2573
|
};
|
2156
2574
|
DiscardAction.type = "discard";
|
2157
|
-
|
2158
|
-
path {
|
2159
|
-
fill: currentColor;
|
2160
|
-
}
|
2161
|
-
`;
|
2575
|
+
DiscardAction.position = "panel";
|
2162
2576
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2163
2577
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2164
2578
|
const RelativeTime = React.forwardRef(
|
@@ -2171,7 +2585,7 @@ const RelativeTime = React.forwardRef(
|
|
2171
2585
|
});
|
2172
2586
|
const unit = intervals.find((intervalUnit) => {
|
2173
2587
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2174
|
-
});
|
2588
|
+
}) ?? "seconds";
|
2175
2589
|
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2176
2590
|
const customInterval = customIntervals.find(
|
2177
2591
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2205,19 +2619,29 @@ const getDisplayName = ({
|
|
2205
2619
|
return email ?? "";
|
2206
2620
|
};
|
2207
2621
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2208
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2209
|
-
const statusVariant = status === "draft" ? "
|
2210
|
-
|
2622
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2623
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2624
|
+
const { formatMessage } = useIntl();
|
2625
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2626
|
+
id: `content-manager.containers.List.${status}`,
|
2627
|
+
defaultMessage: capitalise(status)
|
2628
|
+
}) }) });
|
2211
2629
|
};
|
2212
2630
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2213
2631
|
const { formatMessage } = useIntl();
|
2214
2632
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2633
|
+
const params = useParams();
|
2215
2634
|
const title = isCreating ? formatMessage({
|
2216
2635
|
id: "content-manager.containers.edit.title.new",
|
2217
2636
|
defaultMessage: "Create an entry"
|
2218
2637
|
}) : documentTitle;
|
2219
2638
|
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2220
|
-
/* @__PURE__ */ jsx(
|
2639
|
+
/* @__PURE__ */ jsx(
|
2640
|
+
BackButton,
|
2641
|
+
{
|
2642
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2643
|
+
}
|
2644
|
+
),
|
2221
2645
|
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2222
2646
|
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2223
2647
|
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
@@ -2268,7 +2692,7 @@ const HeaderToolbar = () => {
|
|
2268
2692
|
meta: isCloning ? void 0 : meta,
|
2269
2693
|
collectionType
|
2270
2694
|
},
|
2271
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2695
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
|
2272
2696
|
children: (actions2) => {
|
2273
2697
|
const headerActions = actions2.filter((action) => {
|
2274
2698
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -2305,12 +2729,12 @@ const Information = ({ activeTab }) => {
|
|
2305
2729
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2306
2730
|
label: formatMessage({
|
2307
2731
|
id: "content-manager.containers.edit.information.last-published.label",
|
2308
|
-
defaultMessage: "
|
2732
|
+
defaultMessage: "Published"
|
2309
2733
|
}),
|
2310
2734
|
value: formatMessage(
|
2311
2735
|
{
|
2312
2736
|
id: "content-manager.containers.edit.information.last-published.value",
|
2313
|
-
defaultMessage: `
|
2737
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2314
2738
|
},
|
2315
2739
|
{
|
2316
2740
|
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2323,12 +2747,12 @@ const Information = ({ activeTab }) => {
|
|
2323
2747
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2324
2748
|
label: formatMessage({
|
2325
2749
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2326
|
-
defaultMessage: "
|
2750
|
+
defaultMessage: "Updated"
|
2327
2751
|
}),
|
2328
2752
|
value: formatMessage(
|
2329
2753
|
{
|
2330
2754
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2331
|
-
defaultMessage: `
|
2755
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2332
2756
|
},
|
2333
2757
|
{
|
2334
2758
|
time: /* @__PURE__ */ jsx(
|
@@ -2346,12 +2770,12 @@ const Information = ({ activeTab }) => {
|
|
2346
2770
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2347
2771
|
label: formatMessage({
|
2348
2772
|
id: "content-manager.containers.edit.information.document.label",
|
2349
|
-
defaultMessage: "
|
2773
|
+
defaultMessage: "Created"
|
2350
2774
|
}),
|
2351
2775
|
value: formatMessage(
|
2352
2776
|
{
|
2353
2777
|
id: "content-manager.containers.edit.information.document.value",
|
2354
|
-
defaultMessage: `
|
2778
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2355
2779
|
},
|
2356
2780
|
{
|
2357
2781
|
time: /* @__PURE__ */ jsx(
|
@@ -2389,25 +2813,77 @@ const Information = ({ activeTab }) => {
|
|
2389
2813
|
);
|
2390
2814
|
};
|
2391
2815
|
const HeaderActions = ({ actions: actions2 }) => {
|
2392
|
-
|
2393
|
-
|
2816
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2817
|
+
const handleClick = (action) => async (e) => {
|
2818
|
+
if (!("options" in action)) {
|
2819
|
+
const { onClick = () => false, dialog, id } = action;
|
2820
|
+
const muteDialog = await onClick(e);
|
2821
|
+
if (dialog && !muteDialog) {
|
2822
|
+
e.preventDefault();
|
2823
|
+
setDialogId(id);
|
2824
|
+
}
|
2825
|
+
}
|
2826
|
+
};
|
2827
|
+
const handleClose = () => {
|
2828
|
+
setDialogId(null);
|
2829
|
+
};
|
2830
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2831
|
+
if (action.options) {
|
2394
2832
|
return /* @__PURE__ */ jsx(
|
2395
2833
|
SingleSelect,
|
2396
2834
|
{
|
2397
2835
|
size: "S",
|
2398
|
-
disabled: action.disabled,
|
2399
|
-
"aria-label": action.label,
|
2400
2836
|
onChange: action.onSelect,
|
2401
|
-
|
2837
|
+
"aria-label": action.label,
|
2838
|
+
...action,
|
2402
2839
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2403
2840
|
},
|
2404
2841
|
action.id
|
2405
2842
|
);
|
2406
2843
|
} else {
|
2407
|
-
|
2844
|
+
if (action.type === "icon") {
|
2845
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2846
|
+
/* @__PURE__ */ jsx(
|
2847
|
+
IconButton,
|
2848
|
+
{
|
2849
|
+
disabled: action.disabled,
|
2850
|
+
label: action.label,
|
2851
|
+
size: "S",
|
2852
|
+
onClick: handleClick(action),
|
2853
|
+
children: action.icon
|
2854
|
+
}
|
2855
|
+
),
|
2856
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2857
|
+
HeaderActionDialog,
|
2858
|
+
{
|
2859
|
+
...action.dialog,
|
2860
|
+
isOpen: dialogId === action.id,
|
2861
|
+
onClose: handleClose
|
2862
|
+
}
|
2863
|
+
) : null
|
2864
|
+
] }, action.id);
|
2865
|
+
}
|
2408
2866
|
}
|
2409
2867
|
}) });
|
2410
2868
|
};
|
2869
|
+
const HeaderActionDialog = ({
|
2870
|
+
onClose,
|
2871
|
+
onCancel,
|
2872
|
+
title,
|
2873
|
+
content: Content,
|
2874
|
+
isOpen
|
2875
|
+
}) => {
|
2876
|
+
const handleClose = async () => {
|
2877
|
+
if (onCancel) {
|
2878
|
+
await onCancel();
|
2879
|
+
}
|
2880
|
+
onClose();
|
2881
|
+
};
|
2882
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2883
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2884
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2885
|
+
] }) });
|
2886
|
+
};
|
2411
2887
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2412
2888
|
const navigate = useNavigate();
|
2413
2889
|
const { formatMessage } = useIntl();
|
@@ -2424,6 +2900,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2424
2900
|
};
|
2425
2901
|
};
|
2426
2902
|
ConfigureTheViewAction.type = "configure-the-view";
|
2903
|
+
ConfigureTheViewAction.position = "header";
|
2427
2904
|
const EditTheModelAction = ({ model }) => {
|
2428
2905
|
const navigate = useNavigate();
|
2429
2906
|
const { formatMessage } = useIntl();
|
@@ -2440,6 +2917,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2440
2917
|
};
|
2441
2918
|
};
|
2442
2919
|
EditTheModelAction.type = "edit-the-model";
|
2920
|
+
EditTheModelAction.position = "header";
|
2443
2921
|
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2444
2922
|
const navigate = useNavigate();
|
2445
2923
|
const { formatMessage } = useIntl();
|
@@ -2448,12 +2926,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2448
2926
|
const { delete: deleteAction } = useDocumentActions();
|
2449
2927
|
const { toggleNotification } = useNotification();
|
2450
2928
|
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2929
|
+
const isLocalized = document?.locale != null;
|
2451
2930
|
return {
|
2452
2931
|
disabled: !canDelete || !document,
|
2453
|
-
label: formatMessage(
|
2454
|
-
|
2455
|
-
|
2456
|
-
|
2932
|
+
label: formatMessage(
|
2933
|
+
{
|
2934
|
+
id: "content-manager.actions.delete.label",
|
2935
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2936
|
+
},
|
2937
|
+
{ isLocalized }
|
2938
|
+
),
|
2457
2939
|
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2458
2940
|
dialog: {
|
2459
2941
|
type: "dialog",
|
@@ -2492,420 +2974,119 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2492
2974
|
collectionType,
|
2493
2975
|
params: {
|
2494
2976
|
locale: "*"
|
2495
|
-
}
|
2496
|
-
});
|
2497
|
-
if (!("error" in res)) {
|
2498
|
-
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2499
|
-
}
|
2500
|
-
} finally {
|
2501
|
-
if (!listViewPathMatch) {
|
2502
|
-
setSubmitting(false);
|
2503
|
-
}
|
2504
|
-
}
|
2505
|
-
}
|
2506
|
-
},
|
2507
|
-
variant: "danger",
|
2508
|
-
position: ["header", "table-row"]
|
2509
|
-
};
|
2510
|
-
};
|
2511
|
-
DeleteAction$1.type = "delete";
|
2512
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2513
|
-
const Panels = () => {
|
2514
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2515
|
-
const [
|
2516
|
-
{
|
2517
|
-
query: { status }
|
2518
|
-
}
|
2519
|
-
] = useQueryParams({
|
2520
|
-
status: "draft"
|
2521
|
-
});
|
2522
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2523
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2524
|
-
const props = {
|
2525
|
-
activeTab: status,
|
2526
|
-
model,
|
2527
|
-
documentId: id,
|
2528
|
-
document: isCloning ? void 0 : document,
|
2529
|
-
meta: isCloning ? void 0 : meta,
|
2530
|
-
collectionType
|
2531
|
-
};
|
2532
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2533
|
-
DescriptionComponentRenderer,
|
2534
|
-
{
|
2535
|
-
props,
|
2536
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2537
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2538
|
-
}
|
2539
|
-
) });
|
2540
|
-
};
|
2541
|
-
const ActionsPanel = () => {
|
2542
|
-
const { formatMessage } = useIntl();
|
2543
|
-
return {
|
2544
|
-
title: formatMessage({
|
2545
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2546
|
-
defaultMessage: "Document"
|
2547
|
-
}),
|
2548
|
-
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2549
|
-
};
|
2550
|
-
};
|
2551
|
-
ActionsPanel.type = "actions";
|
2552
|
-
const ActionsPanelContent = () => {
|
2553
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2554
|
-
const [
|
2555
|
-
{
|
2556
|
-
query: { status = "draft" }
|
2557
|
-
}
|
2558
|
-
] = useQueryParams();
|
2559
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2560
|
-
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2561
|
-
const props = {
|
2562
|
-
activeTab: status,
|
2563
|
-
model,
|
2564
|
-
documentId: id,
|
2565
|
-
document: isCloning ? void 0 : document,
|
2566
|
-
meta: isCloning ? void 0 : meta,
|
2567
|
-
collectionType
|
2568
|
-
};
|
2569
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2570
|
-
/* @__PURE__ */ jsx(
|
2571
|
-
DescriptionComponentRenderer,
|
2572
|
-
{
|
2573
|
-
props,
|
2574
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2575
|
-
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2576
|
-
}
|
2577
|
-
),
|
2578
|
-
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2579
|
-
] });
|
2580
|
-
};
|
2581
|
-
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2582
|
-
return /* @__PURE__ */ jsxs(
|
2583
|
-
Flex,
|
2584
|
-
{
|
2585
|
-
ref,
|
2586
|
-
tag: "aside",
|
2587
|
-
"aria-labelledby": "additional-information",
|
2588
|
-
background: "neutral0",
|
2589
|
-
borderColor: "neutral150",
|
2590
|
-
hasRadius: true,
|
2591
|
-
paddingBottom: 4,
|
2592
|
-
paddingLeft: 4,
|
2593
|
-
paddingRight: 4,
|
2594
|
-
paddingTop: 4,
|
2595
|
-
shadow: "tableShadow",
|
2596
|
-
gap: 3,
|
2597
|
-
direction: "column",
|
2598
|
-
justifyContent: "stretch",
|
2599
|
-
alignItems: "flex-start",
|
2600
|
-
children: [
|
2601
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2602
|
-
children
|
2603
|
-
]
|
2604
|
-
}
|
2605
|
-
);
|
2606
|
-
});
|
2607
|
-
const HOOKS = {
|
2608
|
-
/**
|
2609
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2610
|
-
* @constant
|
2611
|
-
* @type {string}
|
2612
|
-
*/
|
2613
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2614
|
-
/**
|
2615
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2616
|
-
* @constant
|
2617
|
-
* @type {string}
|
2618
|
-
*/
|
2619
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2620
|
-
/**
|
2621
|
-
* Hook that allows to mutate the CM's edit view layout
|
2622
|
-
* @constant
|
2623
|
-
* @type {string}
|
2624
|
-
*/
|
2625
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2626
|
-
/**
|
2627
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2628
|
-
* @constant
|
2629
|
-
* @type {string}
|
2630
|
-
*/
|
2631
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2632
|
-
};
|
2633
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2634
|
-
endpoints: (builder) => ({
|
2635
|
-
getContentTypeConfiguration: builder.query({
|
2636
|
-
query: (uid) => ({
|
2637
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2638
|
-
method: "GET"
|
2639
|
-
}),
|
2640
|
-
transformResponse: (response) => response.data,
|
2641
|
-
providesTags: (_result, _error, uid) => [
|
2642
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2643
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2644
|
-
]
|
2645
|
-
}),
|
2646
|
-
getAllContentTypeSettings: builder.query({
|
2647
|
-
query: () => "/content-manager/content-types-settings",
|
2648
|
-
transformResponse: (response) => response.data,
|
2649
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2650
|
-
}),
|
2651
|
-
updateContentTypeConfiguration: builder.mutation({
|
2652
|
-
query: ({ uid, ...body }) => ({
|
2653
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2654
|
-
method: "PUT",
|
2655
|
-
data: body
|
2656
|
-
}),
|
2657
|
-
transformResponse: (response) => response.data,
|
2658
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2659
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2660
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2661
|
-
// Is this necessary?
|
2662
|
-
{ type: "InitialData" }
|
2663
|
-
]
|
2664
|
-
})
|
2665
|
-
})
|
2666
|
-
});
|
2667
|
-
const {
|
2668
|
-
useGetContentTypeConfigurationQuery,
|
2669
|
-
useGetAllContentTypeSettingsQuery,
|
2670
|
-
useUpdateContentTypeConfigurationMutation
|
2671
|
-
} = contentTypesApi;
|
2672
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2673
|
-
const { type } = attribute;
|
2674
|
-
if (type === "relation") {
|
2675
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2676
|
-
}
|
2677
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2678
|
-
};
|
2679
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2680
|
-
if (!mainFieldName) {
|
2681
|
-
return void 0;
|
2682
|
-
}
|
2683
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2684
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2685
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2686
|
-
);
|
2687
|
-
return {
|
2688
|
-
name: mainFieldName,
|
2689
|
-
type: mainFieldType ?? "string"
|
2690
|
-
};
|
2691
|
-
};
|
2692
|
-
const DEFAULT_SETTINGS = {
|
2693
|
-
bulkable: false,
|
2694
|
-
filterable: false,
|
2695
|
-
searchable: false,
|
2696
|
-
pagination: false,
|
2697
|
-
defaultSortBy: "",
|
2698
|
-
defaultSortOrder: "asc",
|
2699
|
-
mainField: "id",
|
2700
|
-
pageSize: 10
|
2701
|
-
};
|
2702
|
-
const useDocumentLayout = (model) => {
|
2703
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2704
|
-
const [{ query }] = useQueryParams();
|
2705
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2706
|
-
const { toggleNotification } = useNotification();
|
2707
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2708
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2709
|
-
const {
|
2710
|
-
data,
|
2711
|
-
isLoading: isLoadingConfigs,
|
2712
|
-
error,
|
2713
|
-
isFetching: isFetchingConfigs
|
2714
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2715
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2716
|
-
React.useEffect(() => {
|
2717
|
-
if (error) {
|
2718
|
-
toggleNotification({
|
2719
|
-
type: "danger",
|
2720
|
-
message: formatAPIError(error)
|
2721
|
-
});
|
2722
|
-
}
|
2723
|
-
}, [error, formatAPIError, toggleNotification]);
|
2724
|
-
const editLayout = React.useMemo(
|
2725
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2726
|
-
layout: [],
|
2727
|
-
components: {},
|
2728
|
-
metadatas: {},
|
2729
|
-
options: {},
|
2730
|
-
settings: DEFAULT_SETTINGS
|
2731
|
-
},
|
2732
|
-
[data, isLoading, schemas, schema, components]
|
2733
|
-
);
|
2734
|
-
const listLayout = React.useMemo(() => {
|
2735
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2736
|
-
layout: [],
|
2737
|
-
metadatas: {},
|
2738
|
-
options: {},
|
2739
|
-
settings: DEFAULT_SETTINGS
|
2740
|
-
};
|
2741
|
-
}, [data, isLoading, schemas, schema, components]);
|
2742
|
-
const { layout: edit } = React.useMemo(
|
2743
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2744
|
-
layout: editLayout,
|
2745
|
-
query
|
2746
|
-
}),
|
2747
|
-
[editLayout, query, runHookWaterfall]
|
2748
|
-
);
|
2749
|
-
return {
|
2750
|
-
error,
|
2751
|
-
isLoading,
|
2752
|
-
edit,
|
2753
|
-
list: listLayout
|
2754
|
-
};
|
2755
|
-
};
|
2756
|
-
const useDocLayout = () => {
|
2757
|
-
const { model } = useDoc();
|
2758
|
-
return useDocumentLayout(model);
|
2759
|
-
};
|
2760
|
-
const formatEditLayout = (data, {
|
2761
|
-
schemas,
|
2762
|
-
schema,
|
2763
|
-
components
|
2764
|
-
}) => {
|
2765
|
-
let currentPanelIndex = 0;
|
2766
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2767
|
-
data.contentType.layouts.edit,
|
2768
|
-
schema?.attributes,
|
2769
|
-
data.contentType.metadatas,
|
2770
|
-
{ configurations: data.components, schemas: components },
|
2771
|
-
schemas
|
2772
|
-
).reduce((panels, row) => {
|
2773
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2774
|
-
panels.push([row]);
|
2775
|
-
currentPanelIndex += 2;
|
2776
|
-
} else {
|
2777
|
-
if (!panels[currentPanelIndex]) {
|
2778
|
-
panels.push([]);
|
2779
|
-
}
|
2780
|
-
panels[currentPanelIndex].push(row);
|
2781
|
-
}
|
2782
|
-
return panels;
|
2783
|
-
}, []);
|
2784
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2785
|
-
(acc, [uid, configuration]) => {
|
2786
|
-
acc[uid] = {
|
2787
|
-
layout: convertEditLayoutToFieldLayouts(
|
2788
|
-
configuration.layouts.edit,
|
2789
|
-
components[uid].attributes,
|
2790
|
-
configuration.metadatas
|
2791
|
-
),
|
2792
|
-
settings: {
|
2793
|
-
...configuration.settings,
|
2794
|
-
icon: components[uid].info.icon,
|
2795
|
-
displayName: components[uid].info.displayName
|
2977
|
+
}
|
2978
|
+
});
|
2979
|
+
if (!("error" in res)) {
|
2980
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2981
|
+
}
|
2982
|
+
} finally {
|
2983
|
+
if (!listViewPathMatch) {
|
2984
|
+
setSubmitting(false);
|
2985
|
+
}
|
2796
2986
|
}
|
2797
|
-
}
|
2798
|
-
return acc;
|
2799
|
-
},
|
2800
|
-
{}
|
2801
|
-
);
|
2802
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2803
|
-
(acc, [attribute, metadata]) => {
|
2804
|
-
return {
|
2805
|
-
...acc,
|
2806
|
-
[attribute]: metadata.edit
|
2807
|
-
};
|
2808
|
-
},
|
2809
|
-
{}
|
2810
|
-
);
|
2811
|
-
return {
|
2812
|
-
layout: panelledEditAttributes,
|
2813
|
-
components: componentEditAttributes,
|
2814
|
-
metadatas: editMetadatas,
|
2815
|
-
settings: {
|
2816
|
-
...data.contentType.settings,
|
2817
|
-
displayName: schema?.info.displayName
|
2987
|
+
}
|
2818
2988
|
},
|
2819
|
-
|
2820
|
-
|
2821
|
-
...schema?.pluginOptions,
|
2822
|
-
...data.contentType.options
|
2823
|
-
}
|
2989
|
+
variant: "danger",
|
2990
|
+
position: ["header", "table-row"]
|
2824
2991
|
};
|
2825
2992
|
};
|
2826
|
-
|
2827
|
-
|
2828
|
-
|
2829
|
-
|
2830
|
-
|
2831
|
-
|
2832
|
-
|
2833
|
-
|
2834
|
-
|
2835
|
-
|
2836
|
-
|
2837
|
-
|
2838
|
-
|
2839
|
-
|
2840
|
-
|
2841
|
-
|
2842
|
-
|
2843
|
-
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
2847
|
-
|
2848
|
-
|
2849
|
-
|
2850
|
-
|
2851
|
-
|
2852
|
-
|
2853
|
-
|
2854
|
-
|
2993
|
+
DeleteAction$1.type = "delete";
|
2994
|
+
DeleteAction$1.position = ["header", "table-row"];
|
2995
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2996
|
+
const Panels = () => {
|
2997
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2998
|
+
const [
|
2999
|
+
{
|
3000
|
+
query: { status }
|
3001
|
+
}
|
3002
|
+
] = useQueryParams({
|
3003
|
+
status: "draft"
|
3004
|
+
});
|
3005
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3006
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
3007
|
+
const props = {
|
3008
|
+
activeTab: status,
|
3009
|
+
model,
|
3010
|
+
documentId: id,
|
3011
|
+
document: isCloning ? void 0 : document,
|
3012
|
+
meta: isCloning ? void 0 : meta,
|
3013
|
+
collectionType
|
3014
|
+
};
|
3015
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
3016
|
+
DescriptionComponentRenderer,
|
3017
|
+
{
|
3018
|
+
props,
|
3019
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
3020
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
3021
|
+
}
|
3022
|
+
) });
|
2855
3023
|
};
|
2856
|
-
const
|
2857
|
-
|
2858
|
-
schema,
|
2859
|
-
components
|
2860
|
-
}) => {
|
2861
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2862
|
-
(acc, [attribute, metadata]) => {
|
2863
|
-
return {
|
2864
|
-
...acc,
|
2865
|
-
[attribute]: metadata.list
|
2866
|
-
};
|
2867
|
-
},
|
2868
|
-
{}
|
2869
|
-
);
|
2870
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2871
|
-
data.contentType.layouts.list,
|
2872
|
-
schema?.attributes,
|
2873
|
-
listMetadatas,
|
2874
|
-
{ configurations: data.components, schemas: components },
|
2875
|
-
schemas
|
2876
|
-
);
|
3024
|
+
const ActionsPanel = () => {
|
3025
|
+
const { formatMessage } = useIntl();
|
2877
3026
|
return {
|
2878
|
-
|
2879
|
-
|
2880
|
-
|
2881
|
-
|
2882
|
-
|
2883
|
-
...schema?.pluginOptions,
|
2884
|
-
...data.contentType.options
|
2885
|
-
}
|
3027
|
+
title: formatMessage({
|
3028
|
+
id: "content-manager.containers.edit.panels.default.title",
|
3029
|
+
defaultMessage: "Entry"
|
3030
|
+
}),
|
3031
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2886
3032
|
};
|
2887
3033
|
};
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
3034
|
+
ActionsPanel.type = "actions";
|
3035
|
+
const ActionsPanelContent = () => {
|
3036
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
3037
|
+
const [
|
3038
|
+
{
|
3039
|
+
query: { status = "draft" }
|
2893
3040
|
}
|
2894
|
-
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2898
|
-
|
2899
|
-
|
2900
|
-
|
2901
|
-
|
2902
|
-
|
2903
|
-
|
2904
|
-
|
2905
|
-
|
2906
|
-
|
2907
|
-
|
3041
|
+
] = useQueryParams();
|
3042
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3043
|
+
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
3044
|
+
const props = {
|
3045
|
+
activeTab: status,
|
3046
|
+
model,
|
3047
|
+
documentId: id,
|
3048
|
+
document: isCloning ? void 0 : document,
|
3049
|
+
meta: isCloning ? void 0 : meta,
|
3050
|
+
collectionType
|
3051
|
+
};
|
3052
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3053
|
+
/* @__PURE__ */ jsx(
|
3054
|
+
DescriptionComponentRenderer,
|
3055
|
+
{
|
3056
|
+
props,
|
3057
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
|
3058
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
3059
|
+
}
|
3060
|
+
),
|
3061
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3062
|
+
] });
|
2908
3063
|
};
|
3064
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
3065
|
+
return /* @__PURE__ */ jsxs(
|
3066
|
+
Flex,
|
3067
|
+
{
|
3068
|
+
ref,
|
3069
|
+
tag: "aside",
|
3070
|
+
"aria-labelledby": "additional-information",
|
3071
|
+
background: "neutral0",
|
3072
|
+
borderColor: "neutral150",
|
3073
|
+
hasRadius: true,
|
3074
|
+
paddingBottom: 4,
|
3075
|
+
paddingLeft: 4,
|
3076
|
+
paddingRight: 4,
|
3077
|
+
paddingTop: 4,
|
3078
|
+
shadow: "tableShadow",
|
3079
|
+
gap: 3,
|
3080
|
+
direction: "column",
|
3081
|
+
justifyContent: "stretch",
|
3082
|
+
alignItems: "flex-start",
|
3083
|
+
children: [
|
3084
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3085
|
+
children
|
3086
|
+
]
|
3087
|
+
}
|
3088
|
+
);
|
3089
|
+
});
|
2909
3090
|
const ConfirmBulkActionDialog = ({
|
2910
3091
|
onToggleDialog,
|
2911
3092
|
isOpen = false,
|
@@ -2944,6 +3125,7 @@ const ConfirmDialogPublishAll = ({
|
|
2944
3125
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2945
3126
|
const { model, schema } = useDoc();
|
2946
3127
|
const [{ query }] = useQueryParams();
|
3128
|
+
const enableDraftRelationsCount = false;
|
2947
3129
|
const {
|
2948
3130
|
data: countDraftRelations = 0,
|
2949
3131
|
isLoading,
|
@@ -2955,7 +3137,7 @@ const ConfirmDialogPublishAll = ({
|
|
2955
3137
|
locale: query?.plugins?.i18n?.locale
|
2956
3138
|
},
|
2957
3139
|
{
|
2958
|
-
skip:
|
3140
|
+
skip: !enableDraftRelationsCount
|
2959
3141
|
}
|
2960
3142
|
);
|
2961
3143
|
React.useEffect(() => {
|
@@ -3140,7 +3322,7 @@ const SelectedEntriesTableContent = ({
|
|
3140
3322
|
status: row.status
|
3141
3323
|
}
|
3142
3324
|
) }),
|
3143
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3325
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3144
3326
|
IconButton,
|
3145
3327
|
{
|
3146
3328
|
tag: Link,
|
@@ -3149,23 +3331,16 @@ const SelectedEntriesTableContent = ({
|
|
3149
3331
|
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3150
3332
|
},
|
3151
3333
|
state: { from: pathname },
|
3152
|
-
label: formatMessage(
|
3153
|
-
|
3154
|
-
|
3155
|
-
|
3156
|
-
{
|
3157
|
-
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3158
|
-
defaultMessage: "item line {number}"
|
3159
|
-
},
|
3160
|
-
{ number: index2 + 1 }
|
3161
|
-
)
|
3162
|
-
}
|
3163
|
-
),
|
3334
|
+
label: formatMessage({
|
3335
|
+
id: "content-manager.bulk-publish.edit",
|
3336
|
+
defaultMessage: "Edit"
|
3337
|
+
}),
|
3164
3338
|
target: "_blank",
|
3165
3339
|
marginLeft: "auto",
|
3166
|
-
|
3340
|
+
variant: "ghost",
|
3341
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3167
3342
|
}
|
3168
|
-
) })
|
3343
|
+
) }) })
|
3169
3344
|
] }, row.id)) })
|
3170
3345
|
] });
|
3171
3346
|
};
|
@@ -3333,8 +3508,7 @@ const PublishAction = ({ documents, model }) => {
|
|
3333
3508
|
const refetchList = () => {
|
3334
3509
|
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3335
3510
|
};
|
3336
|
-
if (!showPublishButton)
|
3337
|
-
return null;
|
3511
|
+
if (!showPublishButton) return null;
|
3338
3512
|
return {
|
3339
3513
|
actionType: "publish",
|
3340
3514
|
variant: "tertiary",
|
@@ -3402,8 +3576,7 @@ const DeleteAction = ({ documents, model }) => {
|
|
3402
3576
|
selectRow([]);
|
3403
3577
|
}
|
3404
3578
|
};
|
3405
|
-
if (!hasDeletePermission)
|
3406
|
-
return null;
|
3579
|
+
if (!hasDeletePermission) return null;
|
3407
3580
|
return {
|
3408
3581
|
variant: "danger-light",
|
3409
3582
|
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
@@ -3452,8 +3625,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
3452
3625
|
}
|
3453
3626
|
};
|
3454
3627
|
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3455
|
-
if (!showUnpublishButton)
|
3456
|
-
return null;
|
3628
|
+
if (!showUnpublishButton) return null;
|
3457
3629
|
return {
|
3458
3630
|
variant: "tertiary",
|
3459
3631
|
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
@@ -3558,7 +3730,7 @@ const TableActions = ({ document }) => {
|
|
3558
3730
|
DescriptionComponentRenderer,
|
3559
3731
|
{
|
3560
3732
|
props,
|
3561
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3733
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
|
3562
3734
|
children: (actions2) => {
|
3563
3735
|
const tableRowActions = actions2.filter((action) => {
|
3564
3736
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3617,6 +3789,7 @@ const EditAction = ({ documentId }) => {
|
|
3617
3789
|
};
|
3618
3790
|
};
|
3619
3791
|
EditAction.type = "edit";
|
3792
|
+
EditAction.position = "table-row";
|
3620
3793
|
const StyledPencil = styled(Pencil)`
|
3621
3794
|
path {
|
3622
3795
|
fill: currentColor;
|
@@ -3693,6 +3866,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3693
3866
|
};
|
3694
3867
|
};
|
3695
3868
|
CloneAction.type = "clone";
|
3869
|
+
CloneAction.position = "table-row";
|
3696
3870
|
const StyledDuplicate = styled(Duplicate)`
|
3697
3871
|
path {
|
3698
3872
|
fill: currentColor;
|
@@ -3779,7 +3953,14 @@ class ContentManagerPlugin {
|
|
3779
3953
|
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3780
3954
|
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3781
3955
|
getBulkActions: () => this.bulkActions,
|
3782
|
-
getDocumentActions: () =>
|
3956
|
+
getDocumentActions: (position) => {
|
3957
|
+
if (position) {
|
3958
|
+
return this.documentActions.filter(
|
3959
|
+
(action) => action.position == void 0 || [action.position].flat().includes(position)
|
3960
|
+
);
|
3961
|
+
}
|
3962
|
+
return this.documentActions;
|
3963
|
+
},
|
3783
3964
|
getEditViewSidePanels: () => this.editViewSidePanels,
|
3784
3965
|
getHeaderActions: () => this.headerActions
|
3785
3966
|
}
|
@@ -3789,10 +3970,8 @@ class ContentManagerPlugin {
|
|
3789
3970
|
const getPrintableType = (value) => {
|
3790
3971
|
const nativeType = typeof value;
|
3791
3972
|
if (nativeType === "object") {
|
3792
|
-
if (value === null)
|
3793
|
-
|
3794
|
-
if (Array.isArray(value))
|
3795
|
-
return "array";
|
3973
|
+
if (value === null) return "null";
|
3974
|
+
if (Array.isArray(value)) return "array";
|
3796
3975
|
if (value instanceof Object && value.constructor.name !== "Object") {
|
3797
3976
|
return value.constructor.name;
|
3798
3977
|
}
|
@@ -3803,17 +3982,27 @@ const HistoryAction = ({ model, document }) => {
|
|
3803
3982
|
const { formatMessage } = useIntl();
|
3804
3983
|
const [{ query }] = useQueryParams();
|
3805
3984
|
const navigate = useNavigate();
|
3985
|
+
const { trackUsage } = useTracking();
|
3986
|
+
const { pathname } = useLocation();
|
3806
3987
|
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3807
3988
|
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3808
3989
|
return null;
|
3809
3990
|
}
|
3991
|
+
const handleOnClick = () => {
|
3992
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
3993
|
+
trackUsage("willNavigate", {
|
3994
|
+
from: pathname,
|
3995
|
+
to: `${pathname}/${destination.pathname}`
|
3996
|
+
});
|
3997
|
+
navigate(destination);
|
3998
|
+
};
|
3810
3999
|
return {
|
3811
4000
|
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3812
4001
|
label: formatMessage({
|
3813
4002
|
id: "content-manager.history.document-action",
|
3814
4003
|
defaultMessage: "Content History"
|
3815
4004
|
}),
|
3816
|
-
onClick:
|
4005
|
+
onClick: handleOnClick,
|
3817
4006
|
disabled: (
|
3818
4007
|
/**
|
3819
4008
|
* The user is creating a new document.
|
@@ -3835,6 +4024,7 @@ const HistoryAction = ({ model, document }) => {
|
|
3835
4024
|
};
|
3836
4025
|
};
|
3837
4026
|
HistoryAction.type = "history";
|
4027
|
+
HistoryAction.position = "header";
|
3838
4028
|
const historyAdmin = {
|
3839
4029
|
bootstrap(app) {
|
3840
4030
|
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
@@ -3881,6 +4071,88 @@ const { setInitialData } = actions;
|
|
3881
4071
|
const reducer = combineReducers({
|
3882
4072
|
app: reducer$1
|
3883
4073
|
});
|
4074
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4075
|
+
endpoints: (builder) => ({
|
4076
|
+
getPreviewUrl: builder.query({
|
4077
|
+
query({ query, params }) {
|
4078
|
+
return {
|
4079
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4080
|
+
method: "GET",
|
4081
|
+
config: {
|
4082
|
+
params: query
|
4083
|
+
}
|
4084
|
+
};
|
4085
|
+
}
|
4086
|
+
})
|
4087
|
+
})
|
4088
|
+
});
|
4089
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4090
|
+
const ConditionalTooltip = ({ isShown, label, children }) => {
|
4091
|
+
if (isShown) {
|
4092
|
+
return /* @__PURE__ */ jsx(Tooltip, { label, children });
|
4093
|
+
}
|
4094
|
+
return children;
|
4095
|
+
};
|
4096
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4097
|
+
const { formatMessage } = useIntl();
|
4098
|
+
const { trackUsage } = useTracking();
|
4099
|
+
const { pathname } = useLocation();
|
4100
|
+
const [{ query }] = useQueryParams();
|
4101
|
+
const isModified = useForm("PreviewSidePanel", (state) => state.modified);
|
4102
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4103
|
+
params: {
|
4104
|
+
contentType: model
|
4105
|
+
},
|
4106
|
+
query: {
|
4107
|
+
documentId,
|
4108
|
+
locale: document?.locale,
|
4109
|
+
status: document?.status
|
4110
|
+
}
|
4111
|
+
});
|
4112
|
+
if (!data?.data?.url || error) {
|
4113
|
+
return null;
|
4114
|
+
}
|
4115
|
+
const trackNavigation = () => {
|
4116
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4117
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
4118
|
+
};
|
4119
|
+
return {
|
4120
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4121
|
+
content: /* @__PURE__ */ jsx(
|
4122
|
+
ConditionalTooltip,
|
4123
|
+
{
|
4124
|
+
label: formatMessage({
|
4125
|
+
id: "content-manager.preview.panel.button-disabled-tooltip",
|
4126
|
+
defaultMessage: "Please save to open the preview"
|
4127
|
+
}),
|
4128
|
+
isShown: isModified,
|
4129
|
+
children: /* @__PURE__ */ jsx(Box, { cursor: "not-allowed", width: "100%", children: /* @__PURE__ */ jsx(
|
4130
|
+
Button,
|
4131
|
+
{
|
4132
|
+
variant: "tertiary",
|
4133
|
+
tag: Link,
|
4134
|
+
to: { pathname: "preview", search: stringify(query, { encode: false }) },
|
4135
|
+
onClick: trackNavigation,
|
4136
|
+
width: "100%",
|
4137
|
+
disabled: isModified,
|
4138
|
+
pointerEvents: isModified ? "none" : void 0,
|
4139
|
+
tabIndex: isModified ? -1 : void 0,
|
4140
|
+
children: formatMessage({
|
4141
|
+
id: "content-manager.preview.panel.button",
|
4142
|
+
defaultMessage: "Open preview"
|
4143
|
+
})
|
4144
|
+
}
|
4145
|
+
) })
|
4146
|
+
}
|
4147
|
+
)
|
4148
|
+
};
|
4149
|
+
};
|
4150
|
+
const previewAdmin = {
|
4151
|
+
bootstrap(app) {
|
4152
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4153
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4154
|
+
}
|
4155
|
+
};
|
3884
4156
|
const index = {
|
3885
4157
|
register(app) {
|
3886
4158
|
const cm = new ContentManagerPlugin();
|
@@ -3900,7 +4172,7 @@ const index = {
|
|
3900
4172
|
app.router.addRoute({
|
3901
4173
|
path: "content-manager/*",
|
3902
4174
|
lazy: async () => {
|
3903
|
-
const { Layout } = await import("./layout-
|
4175
|
+
const { Layout } = await import("./layout-Bxsv5mP7.mjs");
|
3904
4176
|
return {
|
3905
4177
|
Component: Layout
|
3906
4178
|
};
|
@@ -3913,11 +4185,14 @@ const index = {
|
|
3913
4185
|
if (typeof historyAdmin.bootstrap === "function") {
|
3914
4186
|
historyAdmin.bootstrap(app);
|
3915
4187
|
}
|
4188
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4189
|
+
previewAdmin.bootstrap(app);
|
4190
|
+
}
|
3916
4191
|
},
|
3917
4192
|
async registerTrads({ locales }) {
|
3918
4193
|
const importedTrads = await Promise.all(
|
3919
4194
|
locales.map((locale) => {
|
3920
|
-
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-
|
4195
|
+
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 }) => {
|
3921
4196
|
return {
|
3922
4197
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3923
4198
|
locale
|
@@ -3944,8 +4219,10 @@ export {
|
|
3944
4219
|
HOOKS as H,
|
3945
4220
|
InjectionZone as I,
|
3946
4221
|
useDocument as J,
|
3947
|
-
|
3948
|
-
|
4222
|
+
useGetPreviewUrlQuery as K,
|
4223
|
+
index as L,
|
4224
|
+
useContentManagerContext as M,
|
4225
|
+
useDocumentActions as N,
|
3949
4226
|
Panels as P,
|
3950
4227
|
RelativeTime as R,
|
3951
4228
|
SINGLE_TYPES as S,
|
@@ -3977,4 +4254,4 @@ export {
|
|
3977
4254
|
capitalise as y,
|
3978
4255
|
useUpdateContentTypeConfigurationMutation as z
|
3979
4256
|
};
|
3980
|
-
//# sourceMappingURL=index-
|
4257
|
+
//# sourceMappingURL=index-DVAIIsOs.mjs.map
|