@strapi/content-manager 0.0.0-experimental.d53e940834bf72ddc725f1d2fd36dac9abec30cb → 0.0.0-experimental.d6bba97c7ed8309e57888e84d4788fa279d473fd
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/LICENSE +18 -3
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs → ComponentConfigurationPage-D4J64ny7.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-D4J64ny7.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js → ComponentConfigurationPage-DHV8IFbd.js} +5 -6
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-DHV8IFbd.js.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
- package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs → EditConfigurationPage-DMnf8orh.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-DMnf8orh.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-q76oeVU1.js} +5 -6
- package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-q76oeVU1.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-BXoY-ITh.js} +63 -13
- package/dist/_chunks/EditViewPage-BXoY-ITh.js.map +1 -0
- package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-COVXj9bh.mjs} +63 -12
- package/dist/_chunks/EditViewPage-COVXj9bh.mjs.map +1 -0
- package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-CcppsFQR.mjs} +300 -203
- package/dist/_chunks/Field-CcppsFQR.mjs.map +1 -0
- package/dist/_chunks/{Field-Boxf9Ajp.js → Field-Dj1nOvt8.js} +303 -207
- package/dist/_chunks/Field-Dj1nOvt8.js.map +1 -0
- package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
- package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
- package/dist/_chunks/{Form-DHrru2AV.mjs → Form-DbWwH0-A.mjs} +37 -18
- package/dist/_chunks/Form-DbWwH0-A.mjs.map +1 -0
- package/dist/_chunks/{Form-y5g1SRsh.js → Form-aTchNxab.js} +39 -21
- package/dist/_chunks/Form-aTchNxab.js.map +1 -0
- package/dist/_chunks/{History-CqN6K7SX.js → History-Cs6XM6EU.js} +81 -114
- package/dist/_chunks/History-Cs6XM6EU.js.map +1 -0
- package/dist/_chunks/{History-Bru_KoeP.mjs → History-tU567_hc.mjs} +82 -114
- package/dist/_chunks/History-tU567_hc.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-7LeytuFD.js} +25 -13
- package/dist/_chunks/ListConfigurationPage-7LeytuFD.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-DQryo_4i.mjs} +25 -12
- package/dist/_chunks/ListConfigurationPage-DQryo_4i.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-B50esy_x.mjs} +118 -77
- package/dist/_chunks/ListViewPage-B50esy_x.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-CaGBu5H5.js} +121 -81
- package/dist/_chunks/ListViewPage-CaGBu5H5.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-BaBE00IO.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-BaBE00IO.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-CiPP8cLx.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-CiPP8cLx.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-0-CW106p.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-0-CW106p.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-DQn5cqZz.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-DQn5cqZz.js.map} +1 -1
- package/dist/_chunks/Preview-C1dBkhXf.mjs +272 -0
- package/dist/_chunks/Preview-C1dBkhXf.mjs.map +1 -0
- package/dist/_chunks/Preview-DH1h7kJ6.js +290 -0
- package/dist/_chunks/Preview-DH1h7kJ6.js.map +1 -0
- package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-Bvne4TvU.mjs} +76 -42
- package/dist/_chunks/Relations-Bvne4TvU.mjs.map +1 -0
- package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-CkECnBOd.js} +76 -43
- package/dist/_chunks/Relations-CkECnBOd.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-BK8Xyl5I.js} +32 -18
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-BK8Xyl5I.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-Dtk_ot79.mjs} +32 -18
- package/dist/_chunks/{en-Ux26r5pl.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-DVPWZkbS.js → index-BN1pPa5v.js} +1135 -693
- package/dist/_chunks/index-BN1pPa5v.js.map +1 -0
- package/dist/_chunks/{index-DJXJw9V5.mjs → index-ByPZ754U.mjs} +1156 -714
- package/dist/_chunks/index-ByPZ754U.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-Bau7ZfLV.mjs → layout-CUTOYU8I.mjs} +26 -13
- package/dist/_chunks/layout-CUTOYU8I.mjs.map +1 -0
- package/dist/_chunks/{layout-Dm6fbiQj.js → layout-nBPDlXjr.js} +26 -14
- package/dist/_chunks/layout-nBPDlXjr.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-CKnpRgrN.js → relations-B6B-b7lI.js} +6 -7
- package/dist/_chunks/relations-B6B-b7lI.js.map +1 -0
- package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-CBc5HYHC.mjs} +6 -7
- package/dist/_chunks/relations-CBc5HYHC.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 +5 -4
- package/dist/admin/src/content-manager.d.ts +3 -2
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +2 -1
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/constants.d.ts +1 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/router.d.ts +1 -1
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -20
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +615 -299
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +615 -298
- 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/uid.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/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.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 +4 -4
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/constants.d.ts +2 -0
- package/dist/server/src/preview/constants.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +16 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +32 -0
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +12 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +19 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -8
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
- package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +15 -15
- package/dist/_chunks/EditViewPage-CPj61RMh.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
- package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
- package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
- package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
- package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
- package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
- package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
- package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
- package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
- package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
- package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
- package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
- package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
- package/dist/_chunks/layout-Dm6fbiQj.js.map +0 -1
- package/dist/_chunks/relations-BH_kBSJ0.mjs.map +0 -1
- package/dist/_chunks/relations-CKnpRgrN.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,
|
4
|
-
import { stringify } from "qs";
|
5
|
-
import { useIntl } from "react-intl";
|
6
|
-
import { useNavigate, useParams, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
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";
|
7
4
|
import * as React from "react";
|
8
5
|
import { lazy } from "react";
|
9
|
-
import {
|
6
|
+
import { Menu, Button, VisuallyHidden, Flex, Dialog, Modal, Typography, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
|
7
|
+
import mapValues from "lodash/fp/mapValues";
|
8
|
+
import { useIntl } from "react-intl";
|
9
|
+
import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
10
10
|
import { styled } from "styled-components";
|
11
11
|
import * as yup from "yup";
|
12
12
|
import { ValidationError } from "yup";
|
13
|
+
import { stringify } from "qs";
|
13
14
|
import pipe from "lodash/fp/pipe";
|
14
15
|
import { intervalToDuration, isPast } from "date-fns";
|
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";
|
@@ -49,42 +57,6 @@ const useInjectionZone = (area) => {
|
|
49
57
|
const [page, position] = area.split(".");
|
50
58
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
51
59
|
};
|
52
|
-
const HistoryAction = ({ model, document }) => {
|
53
|
-
const { formatMessage } = useIntl();
|
54
|
-
const [{ query }] = useQueryParams();
|
55
|
-
const navigate = useNavigate();
|
56
|
-
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
57
|
-
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
58
|
-
return null;
|
59
|
-
}
|
60
|
-
return {
|
61
|
-
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
62
|
-
label: formatMessage({
|
63
|
-
id: "content-manager.history.document-action",
|
64
|
-
defaultMessage: "Content History"
|
65
|
-
}),
|
66
|
-
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
67
|
-
disabled: (
|
68
|
-
/**
|
69
|
-
* The user is creating a new document.
|
70
|
-
* It hasn't been saved yet, so there's no history to go to
|
71
|
-
*/
|
72
|
-
!document || /**
|
73
|
-
* The document has been created but the current dimension has never been saved.
|
74
|
-
* For example, the user is creating a new locale in an existing document,
|
75
|
-
* so there's no history for the document in that locale
|
76
|
-
*/
|
77
|
-
!document.id || /**
|
78
|
-
* History is only available for content types created by the user.
|
79
|
-
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
80
|
-
* which start with `admin::` or `plugin::`
|
81
|
-
*/
|
82
|
-
!model.startsWith("api::")
|
83
|
-
),
|
84
|
-
position: "header"
|
85
|
-
};
|
86
|
-
};
|
87
|
-
HistoryAction.type = "history";
|
88
60
|
const ID = "id";
|
89
61
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
90
62
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -136,6 +108,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
136
108
|
if (!slug) {
|
137
109
|
throw new Error("Cannot find the slug param in the URL");
|
138
110
|
}
|
111
|
+
const [{ rawQuery }] = useQueryParams();
|
139
112
|
const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
|
140
113
|
const contentTypePermissions = React.useMemo(() => {
|
141
114
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -146,7 +119,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
146
119
|
return { ...acc, [action]: [permission] };
|
147
120
|
}, {});
|
148
121
|
}, [slug, userPermissions]);
|
149
|
-
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
|
+
);
|
150
130
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
151
131
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
152
132
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -194,7 +174,8 @@ const contentManagerApi = adminApi.enhanceEndpoints({
|
|
194
174
|
"Document",
|
195
175
|
"InitialData",
|
196
176
|
"HistoryVersion",
|
197
|
-
"Relations"
|
177
|
+
"Relations",
|
178
|
+
"UidAvailability"
|
198
179
|
]
|
199
180
|
});
|
200
181
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -208,7 +189,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
208
189
|
params: query
|
209
190
|
}
|
210
191
|
}),
|
211
|
-
invalidatesTags: (_result,
|
192
|
+
invalidatesTags: (_result, error, { model }) => {
|
193
|
+
if (error) {
|
194
|
+
return [];
|
195
|
+
}
|
196
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
197
|
+
}
|
212
198
|
}),
|
213
199
|
cloneDocument: builder.mutation({
|
214
200
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -219,7 +205,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
219
205
|
params
|
220
206
|
}
|
221
207
|
}),
|
222
|
-
invalidatesTags: (_result, _error, { model }) => [
|
208
|
+
invalidatesTags: (_result, _error, { model }) => [
|
209
|
+
{ type: "Document", id: `${model}_LIST` },
|
210
|
+
{ type: "UidAvailability", id: model }
|
211
|
+
]
|
223
212
|
}),
|
224
213
|
/**
|
225
214
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -236,7 +225,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
236
225
|
}),
|
237
226
|
invalidatesTags: (result, _error, { model }) => [
|
238
227
|
{ type: "Document", id: `${model}_LIST` },
|
239
|
-
"Relations"
|
228
|
+
"Relations",
|
229
|
+
{ type: "UidAvailability", id: model }
|
240
230
|
]
|
241
231
|
}),
|
242
232
|
deleteDocument: builder.mutation({
|
@@ -277,7 +267,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
277
267
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
278
268
|
},
|
279
269
|
{ type: "Document", id: `${model}_LIST` },
|
280
|
-
"Relations"
|
270
|
+
"Relations",
|
271
|
+
{ type: "UidAvailability", id: model }
|
281
272
|
];
|
282
273
|
}
|
283
274
|
}),
|
@@ -290,11 +281,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
290
281
|
url: `/content-manager/collection-types/${model}`,
|
291
282
|
method: "GET",
|
292
283
|
config: {
|
293
|
-
params
|
284
|
+
params: stringify(params, { encode: true })
|
294
285
|
}
|
295
286
|
}),
|
296
287
|
providesTags: (result, _error, arg) => {
|
297
288
|
return [
|
289
|
+
{ type: "Document", id: `ALL_LIST` },
|
298
290
|
{ type: "Document", id: `${arg.model}_LIST` },
|
299
291
|
...result?.results.map(({ documentId }) => ({
|
300
292
|
type: "Document",
|
@@ -333,6 +325,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
333
325
|
{
|
334
326
|
type: "Document",
|
335
327
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
328
|
+
},
|
329
|
+
// Make it easy to invalidate all individual documents queries for a model
|
330
|
+
{
|
331
|
+
type: "Document",
|
332
|
+
id: `${model}_ALL_ITEMS`
|
336
333
|
}
|
337
334
|
];
|
338
335
|
}
|
@@ -396,8 +393,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
396
393
|
type: "Document",
|
397
394
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
398
395
|
},
|
399
|
-
"Relations"
|
396
|
+
"Relations",
|
397
|
+
{ type: "UidAvailability", id: model }
|
400
398
|
];
|
399
|
+
},
|
400
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
401
|
+
const patchResult = dispatch(
|
402
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
403
|
+
Object.assign(draft.data, data);
|
404
|
+
})
|
405
|
+
);
|
406
|
+
try {
|
407
|
+
await queryFulfilled;
|
408
|
+
} catch {
|
409
|
+
patchResult.undo();
|
410
|
+
}
|
401
411
|
}
|
402
412
|
}),
|
403
413
|
unpublishDocument: builder.mutation({
|
@@ -450,8 +460,7 @@ const {
|
|
450
460
|
useUnpublishManyDocumentsMutation
|
451
461
|
} = documentApi;
|
452
462
|
const buildValidParams = (query) => {
|
453
|
-
if (!query)
|
454
|
-
return query;
|
463
|
+
if (!query) return query;
|
455
464
|
const { plugins: _, ...validQueryParams } = {
|
456
465
|
...query,
|
457
466
|
...Object.values(query?.plugins ?? {}).reduce(
|
@@ -459,28 +468,44 @@ const buildValidParams = (query) => {
|
|
459
468
|
{}
|
460
469
|
)
|
461
470
|
};
|
462
|
-
if ("_q" in validQueryParams) {
|
463
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
464
|
-
}
|
465
471
|
return validQueryParams;
|
466
472
|
};
|
467
473
|
const isBaseQueryError = (error) => {
|
468
474
|
return error.name !== void 0;
|
469
475
|
};
|
470
|
-
const
|
476
|
+
const arrayValidator = (attribute, options) => ({
|
477
|
+
message: translatedErrors.required,
|
478
|
+
test(value) {
|
479
|
+
if (options.status === "draft") {
|
480
|
+
return true;
|
481
|
+
}
|
482
|
+
if (!attribute.required) {
|
483
|
+
return true;
|
484
|
+
}
|
485
|
+
if (!value) {
|
486
|
+
return false;
|
487
|
+
}
|
488
|
+
if (Array.isArray(value) && value.length === 0) {
|
489
|
+
return false;
|
490
|
+
}
|
491
|
+
return true;
|
492
|
+
}
|
493
|
+
});
|
494
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
471
495
|
const createModelSchema = (attributes2) => yup.object().shape(
|
472
496
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
473
497
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
474
498
|
return acc;
|
475
499
|
}
|
476
500
|
const validations = [
|
501
|
+
addNullableValidation,
|
477
502
|
addRequiredValidation,
|
478
503
|
addMinLengthValidation,
|
479
504
|
addMaxLengthValidation,
|
480
505
|
addMinValidation,
|
481
506
|
addMaxValidation,
|
482
507
|
addRegexValidation
|
483
|
-
].map((fn) => fn(attribute));
|
508
|
+
].map((fn) => fn(attribute, options));
|
484
509
|
const transformSchema = pipe(...validations);
|
485
510
|
switch (attribute.type) {
|
486
511
|
case "component": {
|
@@ -490,12 +515,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
490
515
|
...acc,
|
491
516
|
[name]: transformSchema(
|
492
517
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
493
|
-
)
|
518
|
+
).test(arrayValidator(attribute, options))
|
494
519
|
};
|
495
520
|
} else {
|
496
521
|
return {
|
497
522
|
...acc,
|
498
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
523
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
499
524
|
};
|
500
525
|
}
|
501
526
|
}
|
@@ -517,7 +542,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
517
542
|
}
|
518
543
|
)
|
519
544
|
)
|
520
|
-
)
|
545
|
+
).test(arrayValidator(attribute, options))
|
521
546
|
};
|
522
547
|
case "relation":
|
523
548
|
return {
|
@@ -529,7 +554,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
529
554
|
} else if (Array.isArray(value)) {
|
530
555
|
return yup.array().of(
|
531
556
|
yup.object().shape({
|
532
|
-
id: yup.
|
557
|
+
id: yup.number().required()
|
533
558
|
})
|
534
559
|
);
|
535
560
|
} else if (typeof value === "object") {
|
@@ -581,6 +606,14 @@ const createAttributeSchema = (attribute) => {
|
|
581
606
|
if (!value || typeof value === "string" && value.length === 0) {
|
582
607
|
return true;
|
583
608
|
}
|
609
|
+
if (typeof value === "object") {
|
610
|
+
try {
|
611
|
+
JSON.stringify(value);
|
612
|
+
return true;
|
613
|
+
} catch (err) {
|
614
|
+
return false;
|
615
|
+
}
|
616
|
+
}
|
584
617
|
try {
|
585
618
|
JSON.parse(value);
|
586
619
|
return true;
|
@@ -599,13 +632,7 @@ const createAttributeSchema = (attribute) => {
|
|
599
632
|
return yup.mixed();
|
600
633
|
}
|
601
634
|
};
|
602
|
-
const
|
603
|
-
if (attribute.required) {
|
604
|
-
return schema.required({
|
605
|
-
id: translatedErrors.required.id,
|
606
|
-
defaultMessage: "This field is required."
|
607
|
-
});
|
608
|
-
}
|
635
|
+
const nullableSchema = (schema) => {
|
609
636
|
return schema?.nullable ? schema.nullable() : (
|
610
637
|
// In some cases '.nullable' will not be available on the schema.
|
611
638
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -613,7 +640,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
613
640
|
schema
|
614
641
|
);
|
615
642
|
};
|
616
|
-
const
|
643
|
+
const addNullableValidation = () => (schema) => {
|
644
|
+
return nullableSchema(schema);
|
645
|
+
};
|
646
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
647
|
+
if (options.status === "draft" || !attribute.required) {
|
648
|
+
return schema;
|
649
|
+
}
|
650
|
+
if (attribute.required && "required" in schema) {
|
651
|
+
return schema.required(translatedErrors.required);
|
652
|
+
}
|
653
|
+
return schema;
|
654
|
+
};
|
655
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
656
|
+
if (options.status === "draft") {
|
657
|
+
return schema;
|
658
|
+
}
|
617
659
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
618
660
|
return schema.min(attribute.minLength, {
|
619
661
|
...translatedErrors.minLength,
|
@@ -635,10 +677,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
635
677
|
}
|
636
678
|
return schema;
|
637
679
|
};
|
638
|
-
const addMinValidation = (attribute) => (schema) => {
|
639
|
-
if ("
|
680
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
681
|
+
if (options.status === "draft") {
|
682
|
+
return schema;
|
683
|
+
}
|
684
|
+
if ("min" in attribute && "min" in schema) {
|
640
685
|
const min = toInteger(attribute.min);
|
641
|
-
if (
|
686
|
+
if (min) {
|
642
687
|
return schema.min(min, {
|
643
688
|
...translatedErrors.min,
|
644
689
|
values: {
|
@@ -756,16 +801,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
756
801
|
}, {});
|
757
802
|
return componentsByKey;
|
758
803
|
};
|
759
|
-
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);
|
760
903
|
const { toggleNotification } = useNotification();
|
761
904
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
905
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
762
906
|
const {
|
763
|
-
|
764
|
-
isLoading:
|
765
|
-
|
766
|
-
|
767
|
-
} =
|
768
|
-
const
|
907
|
+
data,
|
908
|
+
isLoading: isLoadingConfigs,
|
909
|
+
error,
|
910
|
+
isFetching: isFetchingConfigs
|
911
|
+
} = useGetContentTypeConfigurationQuery(model);
|
912
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
769
913
|
React.useEffect(() => {
|
770
914
|
if (error) {
|
771
915
|
toggleNotification({
|
@@ -773,68 +917,322 @@ const useDocument = (args, opts) => {
|
|
773
917
|
message: formatAPIError(error)
|
774
918
|
});
|
775
919
|
}
|
776
|
-
}, [
|
777
|
-
const
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
(document) => {
|
785
|
-
if (!validationSchema) {
|
786
|
-
throw new Error(
|
787
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
788
|
-
);
|
789
|
-
}
|
790
|
-
try {
|
791
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
792
|
-
return null;
|
793
|
-
} catch (error2) {
|
794
|
-
if (error2 instanceof ValidationError) {
|
795
|
-
return getYupValidationErrors(error2);
|
796
|
-
}
|
797
|
-
throw error2;
|
798
|
-
}
|
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
|
799
928
|
},
|
800
|
-
[
|
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]
|
801
945
|
);
|
802
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
803
946
|
return {
|
804
|
-
|
805
|
-
document: data?.data,
|
806
|
-
meta: data?.meta,
|
947
|
+
error,
|
807
948
|
isLoading,
|
808
|
-
|
809
|
-
|
949
|
+
edit,
|
950
|
+
list: listLayout
|
810
951
|
};
|
811
952
|
};
|
812
|
-
const
|
813
|
-
const {
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
953
|
+
const useDocLayout = () => {
|
954
|
+
const { model } = useDoc();
|
955
|
+
return useDocumentLayout(model);
|
956
|
+
};
|
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);
|
978
|
+
}
|
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
|
995
|
+
}
|
996
|
+
};
|
997
|
+
return acc;
|
998
|
+
},
|
999
|
+
{}
|
1000
|
+
);
|
1001
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1002
|
+
(acc, [attribute, metadata]) => {
|
1003
|
+
return {
|
1004
|
+
...acc,
|
1005
|
+
[attribute]: metadata.edit
|
1006
|
+
};
|
1007
|
+
},
|
1008
|
+
{}
|
1009
|
+
);
|
1010
|
+
return {
|
1011
|
+
layout: panelledEditAttributes,
|
1012
|
+
components: componentEditAttributes,
|
1013
|
+
metadatas: editMetadatas,
|
1014
|
+
settings: {
|
1015
|
+
...data.contentType.settings,
|
1016
|
+
displayName: schema?.info.displayName
|
1017
|
+
},
|
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;
|
1031
|
+
}
|
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)
|
1053
|
+
);
|
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);
|
1153
|
+
}
|
1154
|
+
throw error2;
|
1155
|
+
}
|
1156
|
+
},
|
1157
|
+
[validationSchema]
|
1158
|
+
);
|
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) {
|
820
1180
|
throw new Error("Could not find model in url params");
|
821
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;
|
822
1189
|
return {
|
823
1190
|
collectionType,
|
824
1191
|
model: slug,
|
825
|
-
id:
|
826
|
-
...
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
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
|
832
1233
|
};
|
833
1234
|
};
|
834
1235
|
const prefixPluginTranslations = (trad, pluginId) => {
|
835
|
-
if (!pluginId) {
|
836
|
-
throw new TypeError("pluginId can't be empty");
|
837
|
-
}
|
838
1236
|
return Object.keys(trad).reduce((acc, current) => {
|
839
1237
|
acc[`${pluginId}.${current}`] = trad[current];
|
840
1238
|
return acc;
|
@@ -850,6 +1248,8 @@ const useDocumentActions = () => {
|
|
850
1248
|
const { formatMessage } = useIntl();
|
851
1249
|
const { trackUsage } = useTracking();
|
852
1250
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1251
|
+
const navigate = useNavigate();
|
1252
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
853
1253
|
const [deleteDocument] = useDeleteDocumentMutation();
|
854
1254
|
const _delete = React.useCallback(
|
855
1255
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1164,6 +1564,7 @@ const useDocumentActions = () => {
|
|
1164
1564
|
defaultMessage: "Saved document"
|
1165
1565
|
})
|
1166
1566
|
});
|
1567
|
+
setCurrentStep("contentManager.success");
|
1167
1568
|
return res.data;
|
1168
1569
|
} catch (err) {
|
1169
1570
|
toggleNotification({
|
@@ -1185,7 +1586,6 @@ const useDocumentActions = () => {
|
|
1185
1586
|
sourceId
|
1186
1587
|
});
|
1187
1588
|
if ("error" in res) {
|
1188
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1189
1589
|
return { error: res.error };
|
1190
1590
|
}
|
1191
1591
|
toggleNotification({
|
@@ -1204,7 +1604,7 @@ const useDocumentActions = () => {
|
|
1204
1604
|
throw err;
|
1205
1605
|
}
|
1206
1606
|
},
|
1207
|
-
[autoCloneDocument,
|
1607
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1208
1608
|
);
|
1209
1609
|
const [cloneDocument] = useCloneDocumentMutation();
|
1210
1610
|
const clone = React.useCallback(
|
@@ -1230,6 +1630,7 @@ const useDocumentActions = () => {
|
|
1230
1630
|
defaultMessage: "Cloned document"
|
1231
1631
|
})
|
1232
1632
|
});
|
1633
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1233
1634
|
return res.data;
|
1234
1635
|
} catch (err) {
|
1235
1636
|
toggleNotification({
|
@@ -1240,7 +1641,7 @@ const useDocumentActions = () => {
|
|
1240
1641
|
throw err;
|
1241
1642
|
}
|
1242
1643
|
},
|
1243
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1644
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1244
1645
|
);
|
1245
1646
|
const [getDoc] = useLazyGetDocumentQuery();
|
1246
1647
|
const getDocument = React.useCallback(
|
@@ -1265,10 +1666,10 @@ const useDocumentActions = () => {
|
|
1265
1666
|
update
|
1266
1667
|
};
|
1267
1668
|
};
|
1268
|
-
const ProtectedHistoryPage = lazy(
|
1269
|
-
() => import("./History-
|
1669
|
+
const ProtectedHistoryPage = React.lazy(
|
1670
|
+
() => import("./History-tU567_hc.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1270
1671
|
);
|
1271
|
-
const routes$
|
1672
|
+
const routes$2 = [
|
1272
1673
|
{
|
1273
1674
|
path: ":collectionType/:slug/:id/history",
|
1274
1675
|
Component: ProtectedHistoryPage
|
@@ -1278,32 +1679,45 @@ const routes$1 = [
|
|
1278
1679
|
Component: ProtectedHistoryPage
|
1279
1680
|
}
|
1280
1681
|
];
|
1682
|
+
const ProtectedPreviewPage = React.lazy(
|
1683
|
+
() => import("./Preview-C1dBkhXf.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
|
+
];
|
1281
1695
|
const ProtectedEditViewPage = lazy(
|
1282
|
-
() => import("./EditViewPage-
|
1696
|
+
() => import("./EditViewPage-COVXj9bh.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1283
1697
|
);
|
1284
1698
|
const ProtectedListViewPage = lazy(
|
1285
|
-
() => import("./ListViewPage-
|
1699
|
+
() => import("./ListViewPage-B50esy_x.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1286
1700
|
);
|
1287
1701
|
const ProtectedListConfiguration = lazy(
|
1288
|
-
() => import("./ListConfigurationPage-
|
1702
|
+
() => import("./ListConfigurationPage-DQryo_4i.mjs").then((mod) => ({
|
1289
1703
|
default: mod.ProtectedListConfiguration
|
1290
1704
|
}))
|
1291
1705
|
);
|
1292
1706
|
const ProtectedEditConfigurationPage = lazy(
|
1293
|
-
() => import("./EditConfigurationPage-
|
1707
|
+
() => import("./EditConfigurationPage-DMnf8orh.mjs").then((mod) => ({
|
1294
1708
|
default: mod.ProtectedEditConfigurationPage
|
1295
1709
|
}))
|
1296
1710
|
);
|
1297
1711
|
const ProtectedComponentConfigurationPage = lazy(
|
1298
|
-
() => import("./ComponentConfigurationPage-
|
1712
|
+
() => import("./ComponentConfigurationPage-D4J64ny7.mjs").then((mod) => ({
|
1299
1713
|
default: mod.ProtectedComponentConfigurationPage
|
1300
1714
|
}))
|
1301
1715
|
);
|
1302
1716
|
const NoPermissions = lazy(
|
1303
|
-
() => import("./NoPermissionsPage-
|
1717
|
+
() => import("./NoPermissionsPage-0-CW106p.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1304
1718
|
);
|
1305
1719
|
const NoContentType = lazy(
|
1306
|
-
() => import("./NoContentTypePage-
|
1720
|
+
() => import("./NoContentTypePage-CiPP8cLx.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1307
1721
|
);
|
1308
1722
|
const CollectionTypePages = () => {
|
1309
1723
|
const { collectionType } = useParams();
|
@@ -1315,7 +1729,7 @@ const CollectionTypePages = () => {
|
|
1315
1729
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1316
1730
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1317
1731
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1318
|
-
const LIST_PATH = `/content-manager
|
1732
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1319
1733
|
const routes = [
|
1320
1734
|
{
|
1321
1735
|
path: LIST_RELATIVE_PATH,
|
@@ -1349,6 +1763,7 @@ const routes = [
|
|
1349
1763
|
path: "no-content-types",
|
1350
1764
|
Component: NoContentType
|
1351
1765
|
},
|
1766
|
+
...routes$2,
|
1352
1767
|
...routes$1
|
1353
1768
|
];
|
1354
1769
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1417,12 +1832,14 @@ const DocumentActionButton = (action) => {
|
|
1417
1832
|
/* @__PURE__ */ jsx(
|
1418
1833
|
Button,
|
1419
1834
|
{
|
1420
|
-
flex:
|
1835
|
+
flex: "auto",
|
1421
1836
|
startIcon: action.icon,
|
1422
1837
|
disabled: action.disabled,
|
1423
1838
|
onClick: handleClick(action),
|
1424
1839
|
justifyContent: "center",
|
1425
1840
|
variant: action.variant || "default",
|
1841
|
+
paddingTop: "7px",
|
1842
|
+
paddingBottom: "7px",
|
1426
1843
|
children: action.label
|
1427
1844
|
}
|
1428
1845
|
),
|
@@ -1430,7 +1847,7 @@ const DocumentActionButton = (action) => {
|
|
1430
1847
|
DocumentActionConfirmDialog,
|
1431
1848
|
{
|
1432
1849
|
...action.dialog,
|
1433
|
-
variant: action.variant,
|
1850
|
+
variant: action.dialog?.variant ?? action.variant,
|
1434
1851
|
isOpen: dialogId === action.id,
|
1435
1852
|
onClose: handleClose
|
1436
1853
|
}
|
@@ -1445,6 +1862,11 @@ const DocumentActionButton = (action) => {
|
|
1445
1862
|
) : null
|
1446
1863
|
] });
|
1447
1864
|
};
|
1865
|
+
const MenuItem = styled(Menu.Item)`
|
1866
|
+
&:hover {
|
1867
|
+
background: ${({ theme, isVariantDanger, isDisabled }) => isVariantDanger && !isDisabled ? theme.colors.danger100 : "neutral"};
|
1868
|
+
}
|
1869
|
+
`;
|
1448
1870
|
const DocumentActionsMenu = ({
|
1449
1871
|
actions: actions2,
|
1450
1872
|
children,
|
@@ -1487,9 +1909,9 @@ const DocumentActionsMenu = ({
|
|
1487
1909
|
disabled: isDisabled,
|
1488
1910
|
size: "S",
|
1489
1911
|
endIcon: null,
|
1490
|
-
paddingTop: "
|
1491
|
-
paddingLeft: "
|
1492
|
-
paddingRight: "
|
1912
|
+
paddingTop: "4px",
|
1913
|
+
paddingLeft: "7px",
|
1914
|
+
paddingRight: "7px",
|
1493
1915
|
variant,
|
1494
1916
|
children: [
|
1495
1917
|
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
@@ -1500,36 +1922,35 @@ const DocumentActionsMenu = ({
|
|
1500
1922
|
]
|
1501
1923
|
}
|
1502
1924
|
),
|
1503
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1925
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1504
1926
|
actions2.map((action) => {
|
1505
1927
|
return /* @__PURE__ */ jsx(
|
1506
|
-
|
1928
|
+
MenuItem,
|
1507
1929
|
{
|
1508
1930
|
disabled: action.disabled,
|
1509
1931
|
onSelect: handleClick(action),
|
1510
1932
|
display: "block",
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
] })
|
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
|
+
) })
|
1533
1954
|
},
|
1534
1955
|
action.id
|
1535
1956
|
);
|
@@ -1609,11 +2030,11 @@ const DocumentActionConfirmDialog = ({
|
|
1609
2030
|
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1610
2031
|
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1611
2032
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1612
|
-
/* @__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({
|
1613
2034
|
id: "app.components.Button.cancel",
|
1614
2035
|
defaultMessage: "Cancel"
|
1615
2036
|
}) }) }),
|
1616
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2037
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1617
2038
|
id: "app.components.Button.confirm",
|
1618
2039
|
defaultMessage: "Confirm"
|
1619
2040
|
}) })
|
@@ -1640,8 +2061,20 @@ const DocumentActionModal = ({
|
|
1640
2061
|
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1641
2062
|
] }) });
|
1642
2063
|
};
|
1643
|
-
const
|
1644
|
-
|
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
|
+
};
|
2076
|
+
const PublishAction$1 = ({
|
2077
|
+
activeTab,
|
1645
2078
|
documentId,
|
1646
2079
|
model,
|
1647
2080
|
collectionType,
|
@@ -1652,13 +2085,18 @@ const PublishAction$1 = ({
|
|
1652
2085
|
const navigate = useNavigate();
|
1653
2086
|
const { toggleNotification } = useNotification();
|
1654
2087
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2088
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
1655
2089
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2090
|
+
const { id } = useParams();
|
1656
2091
|
const { formatMessage } = useIntl();
|
1657
|
-
const { canPublish
|
1658
|
-
"PublishAction",
|
1659
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1660
|
-
);
|
2092
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1661
2093
|
const { publish } = useDocumentActions();
|
2094
|
+
const [
|
2095
|
+
countDraftRelations,
|
2096
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2097
|
+
] = useLazyGetDraftRelationCountQuery();
|
2098
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
2099
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1662
2100
|
const [{ query, rawQuery }] = useQueryParams();
|
1663
2101
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1664
2102
|
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1667,10 +2105,107 @@ const PublishAction$1 = ({
|
|
1667
2105
|
const validate = useForm("PublishAction", (state) => state.validate);
|
1668
2106
|
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1669
2107
|
const formValues = useForm("PublishAction", ({ values }) => values);
|
2108
|
+
React.useEffect(() => {
|
2109
|
+
if (isErrorDraftRelations) {
|
2110
|
+
toggleNotification({
|
2111
|
+
type: "danger",
|
2112
|
+
message: formatMessage({
|
2113
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2114
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2115
|
+
})
|
2116
|
+
});
|
2117
|
+
}
|
2118
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2119
|
+
React.useEffect(() => {
|
2120
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2121
|
+
const extractDraftRelations = (data) => {
|
2122
|
+
const relations = data.connect || [];
|
2123
|
+
relations.forEach((relation) => {
|
2124
|
+
if (relation.status === "draft") {
|
2125
|
+
localDraftRelations.add(relation.id);
|
2126
|
+
}
|
2127
|
+
});
|
2128
|
+
};
|
2129
|
+
const traverseAndExtract = (data) => {
|
2130
|
+
Object.entries(data).forEach(([key, value]) => {
|
2131
|
+
if (key === "connect" && Array.isArray(value)) {
|
2132
|
+
extractDraftRelations({ connect: value });
|
2133
|
+
} else if (typeof value === "object" && value !== null) {
|
2134
|
+
traverseAndExtract(value);
|
2135
|
+
}
|
2136
|
+
});
|
2137
|
+
};
|
2138
|
+
if (!documentId || modified) {
|
2139
|
+
traverseAndExtract(formValues);
|
2140
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2141
|
+
}
|
2142
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2143
|
+
React.useEffect(() => {
|
2144
|
+
if (!document || !document.documentId || isListView) {
|
2145
|
+
return;
|
2146
|
+
}
|
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]);
|
1670
2163
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1671
2164
|
if (!schema?.options?.draftAndPublish) {
|
1672
2165
|
return null;
|
1673
2166
|
}
|
2167
|
+
const performPublish = async () => {
|
2168
|
+
setSubmitting(true);
|
2169
|
+
try {
|
2170
|
+
const { errors } = await validate(true, {
|
2171
|
+
status: "published"
|
2172
|
+
});
|
2173
|
+
if (errors) {
|
2174
|
+
toggleNotification({
|
2175
|
+
type: "danger",
|
2176
|
+
message: formatMessage({
|
2177
|
+
id: "content-manager.validation.error",
|
2178
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2179
|
+
})
|
2180
|
+
});
|
2181
|
+
return;
|
2182
|
+
}
|
2183
|
+
const res = await publish(
|
2184
|
+
{
|
2185
|
+
collectionType,
|
2186
|
+
model,
|
2187
|
+
documentId,
|
2188
|
+
params
|
2189
|
+
},
|
2190
|
+
transformData(formValues)
|
2191
|
+
);
|
2192
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2193
|
+
if (id === "create") {
|
2194
|
+
navigate({
|
2195
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2196
|
+
search: rawQuery
|
2197
|
+
});
|
2198
|
+
}
|
2199
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2200
|
+
setErrors(formatValidationErrors(res.error));
|
2201
|
+
}
|
2202
|
+
} finally {
|
2203
|
+
setSubmitting(false);
|
2204
|
+
}
|
2205
|
+
};
|
2206
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2207
|
+
const enableDraftRelationsCount = false;
|
2208
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1674
2209
|
return {
|
1675
2210
|
/**
|
1676
2211
|
* Disabled when:
|
@@ -1680,52 +2215,40 @@ const PublishAction$1 = ({
|
|
1680
2215
|
* - the document is already published & not modified
|
1681
2216
|
* - the document is being created & not modified
|
1682
2217
|
* - the user doesn't have the permission to publish
|
1683
|
-
* - the user doesn't have the permission to create a new document
|
1684
|
-
* - the user doesn't have the permission to update the document
|
1685
2218
|
*/
|
1686
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2219
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1687
2220
|
label: formatMessage({
|
1688
2221
|
id: "app.utils.publish",
|
1689
2222
|
defaultMessage: "Publish"
|
1690
2223
|
}),
|
1691
2224
|
onClick: async () => {
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
documentId,
|
1710
|
-
params
|
1711
|
-
},
|
1712
|
-
formValues
|
1713
|
-
);
|
1714
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1715
|
-
navigate({
|
1716
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1717
|
-
search: rawQuery
|
1718
|
-
});
|
1719
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1720
|
-
setErrors(formatValidationErrors(res.error));
|
2225
|
+
await performPublish();
|
2226
|
+
},
|
2227
|
+
dialog: hasDraftRelations ? {
|
2228
|
+
type: "dialog",
|
2229
|
+
variant: "danger",
|
2230
|
+
footer: null,
|
2231
|
+
title: formatMessage({
|
2232
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2233
|
+
defaultMessage: "Confirmation"
|
2234
|
+
}),
|
2235
|
+
content: formatMessage(
|
2236
|
+
{
|
2237
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2238
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2239
|
+
},
|
2240
|
+
{
|
2241
|
+
count: totalDraftRelations
|
1721
2242
|
}
|
1722
|
-
|
1723
|
-
|
2243
|
+
),
|
2244
|
+
onConfirm: async () => {
|
2245
|
+
await performPublish();
|
1724
2246
|
}
|
1725
|
-
}
|
2247
|
+
} : void 0
|
1726
2248
|
};
|
1727
2249
|
};
|
1728
2250
|
PublishAction$1.type = "publish";
|
2251
|
+
PublishAction$1.position = "panel";
|
1729
2252
|
const UpdateAction = ({
|
1730
2253
|
activeTab,
|
1731
2254
|
documentId,
|
@@ -1738,10 +2261,6 @@ const UpdateAction = ({
|
|
1738
2261
|
const cloneMatch = useMatch(CLONE_PATH);
|
1739
2262
|
const isCloning = cloneMatch !== null;
|
1740
2263
|
const { formatMessage } = useIntl();
|
1741
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1742
|
-
canCreate: canCreate2,
|
1743
|
-
canUpdate: canUpdate2
|
1744
|
-
}));
|
1745
2264
|
const { create, update, clone } = useDocumentActions();
|
1746
2265
|
const [{ query, rawQuery }] = useQueryParams();
|
1747
2266
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
@@ -1758,18 +2277,18 @@ const UpdateAction = ({
|
|
1758
2277
|
* - the form is submitting
|
1759
2278
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1760
2279
|
* - the active tab is the published tab
|
1761
|
-
* - the user doesn't have the permission to create a new document
|
1762
|
-
* - the user doesn't have the permission to update the document
|
1763
2280
|
*/
|
1764
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2281
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1765
2282
|
label: formatMessage({
|
1766
|
-
id: "
|
2283
|
+
id: "global.save",
|
1767
2284
|
defaultMessage: "Save"
|
1768
2285
|
}),
|
1769
2286
|
onClick: async () => {
|
1770
2287
|
setSubmitting(true);
|
1771
2288
|
try {
|
1772
|
-
const { errors } = await validate(
|
2289
|
+
const { errors } = await validate(true, {
|
2290
|
+
status: "draft"
|
2291
|
+
});
|
1773
2292
|
if (errors) {
|
1774
2293
|
toggleNotification({
|
1775
2294
|
type: "danger",
|
@@ -1787,13 +2306,16 @@ const UpdateAction = ({
|
|
1787
2306
|
documentId: cloneMatch.params.origin,
|
1788
2307
|
params
|
1789
2308
|
},
|
1790
|
-
document
|
2309
|
+
transformData(document)
|
1791
2310
|
);
|
1792
2311
|
if ("data" in res) {
|
1793
|
-
navigate(
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
2312
|
+
navigate(
|
2313
|
+
{
|
2314
|
+
pathname: `../${res.data.documentId}`,
|
2315
|
+
search: rawQuery
|
2316
|
+
},
|
2317
|
+
{ relative: "path" }
|
2318
|
+
);
|
1797
2319
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1798
2320
|
setErrors(formatValidationErrors(res.error));
|
1799
2321
|
}
|
@@ -1805,7 +2327,7 @@ const UpdateAction = ({
|
|
1805
2327
|
documentId,
|
1806
2328
|
params
|
1807
2329
|
},
|
1808
|
-
document
|
2330
|
+
transformData(document)
|
1809
2331
|
);
|
1810
2332
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1811
2333
|
setErrors(formatValidationErrors(res.error));
|
@@ -1818,13 +2340,16 @@ const UpdateAction = ({
|
|
1818
2340
|
model,
|
1819
2341
|
params
|
1820
2342
|
},
|
1821
|
-
document
|
2343
|
+
transformData(document)
|
1822
2344
|
);
|
1823
2345
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1824
|
-
navigate(
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
2346
|
+
navigate(
|
2347
|
+
{
|
2348
|
+
pathname: `../${res.data.documentId}`,
|
2349
|
+
search: rawQuery
|
2350
|
+
},
|
2351
|
+
{ replace: true, relative: "path" }
|
2352
|
+
);
|
1828
2353
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1829
2354
|
setErrors(formatValidationErrors(res.error));
|
1830
2355
|
}
|
@@ -1836,6 +2361,7 @@ const UpdateAction = ({
|
|
1836
2361
|
};
|
1837
2362
|
};
|
1838
2363
|
UpdateAction.type = "update";
|
2364
|
+
UpdateAction.position = "panel";
|
1839
2365
|
const UNPUBLISH_DRAFT_OPTIONS = {
|
1840
2366
|
KEEP: "keep",
|
1841
2367
|
DISCARD: "discard"
|
@@ -1868,7 +2394,7 @@ const UnpublishAction$1 = ({
|
|
1868
2394
|
id: "app.utils.unpublish",
|
1869
2395
|
defaultMessage: "Unpublish"
|
1870
2396
|
}),
|
1871
|
-
icon: /* @__PURE__ */ jsx(
|
2397
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1872
2398
|
onClick: async () => {
|
1873
2399
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1874
2400
|
if (!documentId) {
|
@@ -1958,6 +2484,7 @@ const UnpublishAction$1 = ({
|
|
1958
2484
|
};
|
1959
2485
|
};
|
1960
2486
|
UnpublishAction$1.type = "unpublish";
|
2487
|
+
UnpublishAction$1.position = "panel";
|
1961
2488
|
const DiscardAction = ({
|
1962
2489
|
activeTab,
|
1963
2490
|
documentId,
|
@@ -1980,7 +2507,7 @@ const DiscardAction = ({
|
|
1980
2507
|
id: "content-manager.actions.discard.label",
|
1981
2508
|
defaultMessage: "Discard changes"
|
1982
2509
|
}),
|
1983
|
-
icon: /* @__PURE__ */ jsx(
|
2510
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1984
2511
|
position: ["panel", "table-row"],
|
1985
2512
|
variant: "danger",
|
1986
2513
|
dialog: {
|
@@ -2008,11 +2535,7 @@ const DiscardAction = ({
|
|
2008
2535
|
};
|
2009
2536
|
};
|
2010
2537
|
DiscardAction.type = "discard";
|
2011
|
-
|
2012
|
-
path {
|
2013
|
-
fill: currentColor;
|
2014
|
-
}
|
2015
|
-
`;
|
2538
|
+
DiscardAction.position = "panel";
|
2016
2539
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2017
2540
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2018
2541
|
const RelativeTime = React.forwardRef(
|
@@ -2025,7 +2548,7 @@ const RelativeTime = React.forwardRef(
|
|
2025
2548
|
});
|
2026
2549
|
const unit = intervals.find((intervalUnit) => {
|
2027
2550
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2028
|
-
});
|
2551
|
+
}) ?? "seconds";
|
2029
2552
|
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2030
2553
|
const customInterval = customIntervals.find(
|
2031
2554
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2059,34 +2582,34 @@ const getDisplayName = ({
|
|
2059
2582
|
return email ?? "";
|
2060
2583
|
};
|
2061
2584
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2062
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2063
|
-
const statusVariant = status === "draft" ? "
|
2064
|
-
|
2585
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2586
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2587
|
+
const { formatMessage } = useIntl();
|
2588
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2589
|
+
id: `content-manager.containers.List.${status}`,
|
2590
|
+
defaultMessage: capitalise(status)
|
2591
|
+
}) }) });
|
2065
2592
|
};
|
2066
2593
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2067
2594
|
const { formatMessage } = useIntl();
|
2068
2595
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2596
|
+
const params = useParams();
|
2069
2597
|
const title = isCreating ? formatMessage({
|
2070
2598
|
id: "content-manager.containers.edit.title.new",
|
2071
2599
|
defaultMessage: "Create an entry"
|
2072
2600
|
}) : documentTitle;
|
2073
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2074
|
-
/* @__PURE__ */ jsx(
|
2075
|
-
|
2076
|
-
Flex,
|
2601
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2602
|
+
/* @__PURE__ */ jsx(
|
2603
|
+
BackButton,
|
2077
2604
|
{
|
2078
|
-
|
2079
|
-
justifyContent: "space-between",
|
2080
|
-
paddingTop: 1,
|
2081
|
-
gap: "80px",
|
2082
|
-
alignItems: "flex-start",
|
2083
|
-
children: [
|
2084
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2085
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2086
|
-
]
|
2605
|
+
fallback: params.collectionType === SINGLE_TYPES ? void 0 : `../${COLLECTION_TYPES}/${params.slug}`
|
2087
2606
|
}
|
2088
2607
|
),
|
2089
|
-
|
2608
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2609
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2610
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2611
|
+
] }),
|
2612
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2090
2613
|
] });
|
2091
2614
|
};
|
2092
2615
|
const HeaderToolbar = () => {
|
@@ -2132,7 +2655,7 @@ const HeaderToolbar = () => {
|
|
2132
2655
|
meta: isCloning ? void 0 : meta,
|
2133
2656
|
collectionType
|
2134
2657
|
},
|
2135
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2658
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("header"),
|
2136
2659
|
children: (actions2) => {
|
2137
2660
|
const headerActions = actions2.filter((action) => {
|
2138
2661
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -2169,12 +2692,12 @@ const Information = ({ activeTab }) => {
|
|
2169
2692
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2170
2693
|
label: formatMessage({
|
2171
2694
|
id: "content-manager.containers.edit.information.last-published.label",
|
2172
|
-
defaultMessage: "
|
2695
|
+
defaultMessage: "Published"
|
2173
2696
|
}),
|
2174
2697
|
value: formatMessage(
|
2175
2698
|
{
|
2176
2699
|
id: "content-manager.containers.edit.information.last-published.value",
|
2177
|
-
defaultMessage: `
|
2700
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2178
2701
|
},
|
2179
2702
|
{
|
2180
2703
|
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2187,12 +2710,12 @@ const Information = ({ activeTab }) => {
|
|
2187
2710
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2188
2711
|
label: formatMessage({
|
2189
2712
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2190
|
-
defaultMessage: "
|
2713
|
+
defaultMessage: "Updated"
|
2191
2714
|
}),
|
2192
2715
|
value: formatMessage(
|
2193
2716
|
{
|
2194
2717
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2195
|
-
defaultMessage: `
|
2718
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2196
2719
|
},
|
2197
2720
|
{
|
2198
2721
|
time: /* @__PURE__ */ jsx(
|
@@ -2210,12 +2733,12 @@ const Information = ({ activeTab }) => {
|
|
2210
2733
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2211
2734
|
label: formatMessage({
|
2212
2735
|
id: "content-manager.containers.edit.information.document.label",
|
2213
|
-
defaultMessage: "
|
2736
|
+
defaultMessage: "Created"
|
2214
2737
|
}),
|
2215
2738
|
value: formatMessage(
|
2216
2739
|
{
|
2217
2740
|
id: "content-manager.containers.edit.information.document.value",
|
2218
|
-
defaultMessage: `
|
2741
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2219
2742
|
},
|
2220
2743
|
{
|
2221
2744
|
time: /* @__PURE__ */ jsx(
|
@@ -2253,25 +2776,77 @@ const Information = ({ activeTab }) => {
|
|
2253
2776
|
);
|
2254
2777
|
};
|
2255
2778
|
const HeaderActions = ({ actions: actions2 }) => {
|
2256
|
-
|
2257
|
-
|
2779
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2780
|
+
const handleClick = (action) => async (e) => {
|
2781
|
+
if (!("options" in action)) {
|
2782
|
+
const { onClick = () => false, dialog, id } = action;
|
2783
|
+
const muteDialog = await onClick(e);
|
2784
|
+
if (dialog && !muteDialog) {
|
2785
|
+
e.preventDefault();
|
2786
|
+
setDialogId(id);
|
2787
|
+
}
|
2788
|
+
}
|
2789
|
+
};
|
2790
|
+
const handleClose = () => {
|
2791
|
+
setDialogId(null);
|
2792
|
+
};
|
2793
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2794
|
+
if (action.options) {
|
2258
2795
|
return /* @__PURE__ */ jsx(
|
2259
2796
|
SingleSelect,
|
2260
2797
|
{
|
2261
2798
|
size: "S",
|
2262
|
-
disabled: action.disabled,
|
2263
|
-
"aria-label": action.label,
|
2264
2799
|
onChange: action.onSelect,
|
2265
|
-
|
2800
|
+
"aria-label": action.label,
|
2801
|
+
...action,
|
2266
2802
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2267
2803
|
},
|
2268
2804
|
action.id
|
2269
2805
|
);
|
2270
2806
|
} else {
|
2271
|
-
|
2807
|
+
if (action.type === "icon") {
|
2808
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2809
|
+
/* @__PURE__ */ jsx(
|
2810
|
+
IconButton,
|
2811
|
+
{
|
2812
|
+
disabled: action.disabled,
|
2813
|
+
label: action.label,
|
2814
|
+
size: "S",
|
2815
|
+
onClick: handleClick(action),
|
2816
|
+
children: action.icon
|
2817
|
+
}
|
2818
|
+
),
|
2819
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2820
|
+
HeaderActionDialog,
|
2821
|
+
{
|
2822
|
+
...action.dialog,
|
2823
|
+
isOpen: dialogId === action.id,
|
2824
|
+
onClose: handleClose
|
2825
|
+
}
|
2826
|
+
) : null
|
2827
|
+
] }, action.id);
|
2828
|
+
}
|
2272
2829
|
}
|
2273
2830
|
}) });
|
2274
2831
|
};
|
2832
|
+
const HeaderActionDialog = ({
|
2833
|
+
onClose,
|
2834
|
+
onCancel,
|
2835
|
+
title,
|
2836
|
+
content: Content,
|
2837
|
+
isOpen
|
2838
|
+
}) => {
|
2839
|
+
const handleClose = async () => {
|
2840
|
+
if (onCancel) {
|
2841
|
+
await onCancel();
|
2842
|
+
}
|
2843
|
+
onClose();
|
2844
|
+
};
|
2845
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2846
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2847
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2848
|
+
] }) });
|
2849
|
+
};
|
2275
2850
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2276
2851
|
const navigate = useNavigate();
|
2277
2852
|
const { formatMessage } = useIntl();
|
@@ -2288,6 +2863,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2288
2863
|
};
|
2289
2864
|
};
|
2290
2865
|
ConfigureTheViewAction.type = "configure-the-view";
|
2866
|
+
ConfigureTheViewAction.position = "header";
|
2291
2867
|
const EditTheModelAction = ({ model }) => {
|
2292
2868
|
const navigate = useNavigate();
|
2293
2869
|
const { formatMessage } = useIntl();
|
@@ -2304,6 +2880,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2304
2880
|
};
|
2305
2881
|
};
|
2306
2882
|
EditTheModelAction.type = "edit-the-model";
|
2883
|
+
EditTheModelAction.position = "header";
|
2307
2884
|
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2308
2885
|
const navigate = useNavigate();
|
2309
2886
|
const { formatMessage } = useIntl();
|
@@ -2312,12 +2889,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2312
2889
|
const { delete: deleteAction } = useDocumentActions();
|
2313
2890
|
const { toggleNotification } = useNotification();
|
2314
2891
|
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2892
|
+
const isLocalized = document?.locale != null;
|
2315
2893
|
return {
|
2316
2894
|
disabled: !canDelete || !document,
|
2317
|
-
label: formatMessage(
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
2895
|
+
label: formatMessage(
|
2896
|
+
{
|
2897
|
+
id: "content-manager.actions.delete.label",
|
2898
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2899
|
+
},
|
2900
|
+
{ isLocalized }
|
2901
|
+
),
|
2321
2902
|
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2322
2903
|
dialog: {
|
2323
2904
|
type: "dialog",
|
@@ -2373,403 +2954,102 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2373
2954
|
};
|
2374
2955
|
};
|
2375
2956
|
DeleteAction$1.type = "delete";
|
2957
|
+
DeleteAction$1.position = ["header", "table-row"];
|
2376
2958
|
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2377
2959
|
const Panels = () => {
|
2378
2960
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2379
2961
|
const [
|
2380
2962
|
{
|
2381
|
-
query: { status }
|
2382
|
-
}
|
2383
|
-
] = useQueryParams({
|
2384
|
-
status: "draft"
|
2385
|
-
});
|
2386
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2387
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2388
|
-
const props = {
|
2389
|
-
activeTab: status,
|
2390
|
-
model,
|
2391
|
-
documentId: id,
|
2392
|
-
document: isCloning ? void 0 : document,
|
2393
|
-
meta: isCloning ? void 0 : meta,
|
2394
|
-
collectionType
|
2395
|
-
};
|
2396
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2397
|
-
DescriptionComponentRenderer,
|
2398
|
-
{
|
2399
|
-
props,
|
2400
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2401
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2402
|
-
}
|
2403
|
-
) });
|
2404
|
-
};
|
2405
|
-
const ActionsPanel = () => {
|
2406
|
-
const { formatMessage } = useIntl();
|
2407
|
-
return {
|
2408
|
-
title: formatMessage({
|
2409
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2410
|
-
defaultMessage: "Document"
|
2411
|
-
}),
|
2412
|
-
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2413
|
-
};
|
2414
|
-
};
|
2415
|
-
ActionsPanel.type = "actions";
|
2416
|
-
const ActionsPanelContent = () => {
|
2417
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2418
|
-
const [
|
2419
|
-
{
|
2420
|
-
query: { status = "draft" }
|
2421
|
-
}
|
2422
|
-
] = useQueryParams();
|
2423
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2424
|
-
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2425
|
-
const props = {
|
2426
|
-
activeTab: status,
|
2427
|
-
model,
|
2428
|
-
documentId: id,
|
2429
|
-
document: isCloning ? void 0 : document,
|
2430
|
-
meta: isCloning ? void 0 : meta,
|
2431
|
-
collectionType
|
2432
|
-
};
|
2433
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2434
|
-
/* @__PURE__ */ jsx(
|
2435
|
-
DescriptionComponentRenderer,
|
2436
|
-
{
|
2437
|
-
props,
|
2438
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2439
|
-
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2440
|
-
}
|
2441
|
-
),
|
2442
|
-
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2443
|
-
] });
|
2444
|
-
};
|
2445
|
-
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2446
|
-
return /* @__PURE__ */ jsxs(
|
2447
|
-
Flex,
|
2448
|
-
{
|
2449
|
-
ref,
|
2450
|
-
tag: "aside",
|
2451
|
-
"aria-labelledby": "additional-information",
|
2452
|
-
background: "neutral0",
|
2453
|
-
borderColor: "neutral150",
|
2454
|
-
hasRadius: true,
|
2455
|
-
paddingBottom: 4,
|
2456
|
-
paddingLeft: 4,
|
2457
|
-
paddingRight: 4,
|
2458
|
-
paddingTop: 4,
|
2459
|
-
shadow: "tableShadow",
|
2460
|
-
gap: 3,
|
2461
|
-
direction: "column",
|
2462
|
-
justifyContent: "stretch",
|
2463
|
-
alignItems: "flex-start",
|
2464
|
-
children: [
|
2465
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2466
|
-
children
|
2467
|
-
]
|
2468
|
-
}
|
2469
|
-
);
|
2470
|
-
});
|
2471
|
-
const HOOKS = {
|
2472
|
-
/**
|
2473
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2474
|
-
* @constant
|
2475
|
-
* @type {string}
|
2476
|
-
*/
|
2477
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2478
|
-
/**
|
2479
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2480
|
-
* @constant
|
2481
|
-
* @type {string}
|
2482
|
-
*/
|
2483
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2484
|
-
/**
|
2485
|
-
* Hook that allows to mutate the CM's edit view layout
|
2486
|
-
* @constant
|
2487
|
-
* @type {string}
|
2488
|
-
*/
|
2489
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2490
|
-
/**
|
2491
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2492
|
-
* @constant
|
2493
|
-
* @type {string}
|
2494
|
-
*/
|
2495
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2496
|
-
};
|
2497
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2498
|
-
endpoints: (builder) => ({
|
2499
|
-
getContentTypeConfiguration: builder.query({
|
2500
|
-
query: (uid) => ({
|
2501
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2502
|
-
method: "GET"
|
2503
|
-
}),
|
2504
|
-
transformResponse: (response) => response.data,
|
2505
|
-
providesTags: (_result, _error, uid) => [
|
2506
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2507
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2508
|
-
]
|
2509
|
-
}),
|
2510
|
-
getAllContentTypeSettings: builder.query({
|
2511
|
-
query: () => "/content-manager/content-types-settings",
|
2512
|
-
transformResponse: (response) => response.data,
|
2513
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2514
|
-
}),
|
2515
|
-
updateContentTypeConfiguration: builder.mutation({
|
2516
|
-
query: ({ uid, ...body }) => ({
|
2517
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2518
|
-
method: "PUT",
|
2519
|
-
data: body
|
2520
|
-
}),
|
2521
|
-
transformResponse: (response) => response.data,
|
2522
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2523
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2524
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2525
|
-
// Is this necessary?
|
2526
|
-
{ type: "InitialData" }
|
2527
|
-
]
|
2528
|
-
})
|
2529
|
-
})
|
2530
|
-
});
|
2531
|
-
const {
|
2532
|
-
useGetContentTypeConfigurationQuery,
|
2533
|
-
useGetAllContentTypeSettingsQuery,
|
2534
|
-
useUpdateContentTypeConfigurationMutation
|
2535
|
-
} = contentTypesApi;
|
2536
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2537
|
-
const { type } = attribute;
|
2538
|
-
if (type === "relation") {
|
2539
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2540
|
-
}
|
2541
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2542
|
-
};
|
2543
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2544
|
-
if (!mainFieldName) {
|
2545
|
-
return void 0;
|
2546
|
-
}
|
2547
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2548
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2549
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2550
|
-
);
|
2551
|
-
return {
|
2552
|
-
name: mainFieldName,
|
2553
|
-
type: mainFieldType ?? "string"
|
2554
|
-
};
|
2555
|
-
};
|
2556
|
-
const DEFAULT_SETTINGS = {
|
2557
|
-
bulkable: false,
|
2558
|
-
filterable: false,
|
2559
|
-
searchable: false,
|
2560
|
-
pagination: false,
|
2561
|
-
defaultSortBy: "",
|
2562
|
-
defaultSortOrder: "asc",
|
2563
|
-
mainField: "id",
|
2564
|
-
pageSize: 10
|
2565
|
-
};
|
2566
|
-
const useDocumentLayout = (model) => {
|
2567
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2568
|
-
const [{ query }] = useQueryParams();
|
2569
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2570
|
-
const { toggleNotification } = useNotification();
|
2571
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2572
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2573
|
-
const {
|
2574
|
-
data,
|
2575
|
-
isLoading: isLoadingConfigs,
|
2576
|
-
error,
|
2577
|
-
isFetching: isFetchingConfigs
|
2578
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2579
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2580
|
-
React.useEffect(() => {
|
2581
|
-
if (error) {
|
2582
|
-
toggleNotification({
|
2583
|
-
type: "danger",
|
2584
|
-
message: formatAPIError(error)
|
2585
|
-
});
|
2586
|
-
}
|
2587
|
-
}, [error, formatAPIError, toggleNotification]);
|
2588
|
-
const editLayout = React.useMemo(
|
2589
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2590
|
-
layout: [],
|
2591
|
-
components: {},
|
2592
|
-
metadatas: {},
|
2593
|
-
options: {},
|
2594
|
-
settings: DEFAULT_SETTINGS
|
2595
|
-
},
|
2596
|
-
[data, isLoading, schemas, schema, components]
|
2597
|
-
);
|
2598
|
-
const listLayout = React.useMemo(() => {
|
2599
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2600
|
-
layout: [],
|
2601
|
-
metadatas: {},
|
2602
|
-
options: {},
|
2603
|
-
settings: DEFAULT_SETTINGS
|
2604
|
-
};
|
2605
|
-
}, [data, isLoading, schemas, schema, components]);
|
2606
|
-
const { layout: edit } = React.useMemo(
|
2607
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2608
|
-
layout: editLayout,
|
2609
|
-
query
|
2610
|
-
}),
|
2611
|
-
[editLayout, query, runHookWaterfall]
|
2612
|
-
);
|
2613
|
-
return {
|
2614
|
-
error,
|
2615
|
-
isLoading,
|
2616
|
-
edit,
|
2617
|
-
list: listLayout
|
2618
|
-
};
|
2619
|
-
};
|
2620
|
-
const useDocLayout = () => {
|
2621
|
-
const { model } = useDoc();
|
2622
|
-
return useDocumentLayout(model);
|
2623
|
-
};
|
2624
|
-
const formatEditLayout = (data, {
|
2625
|
-
schemas,
|
2626
|
-
schema,
|
2627
|
-
components
|
2628
|
-
}) => {
|
2629
|
-
let currentPanelIndex = 0;
|
2630
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2631
|
-
data.contentType.layouts.edit,
|
2632
|
-
schema?.attributes,
|
2633
|
-
data.contentType.metadatas,
|
2634
|
-
{ configurations: data.components, schemas: components },
|
2635
|
-
schemas
|
2636
|
-
).reduce((panels, row) => {
|
2637
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2638
|
-
panels.push([row]);
|
2639
|
-
currentPanelIndex += 2;
|
2640
|
-
} else {
|
2641
|
-
if (!panels[currentPanelIndex]) {
|
2642
|
-
panels.push([]);
|
2643
|
-
}
|
2644
|
-
panels[currentPanelIndex].push(row);
|
2645
|
-
}
|
2646
|
-
return panels;
|
2647
|
-
}, []);
|
2648
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2649
|
-
(acc, [uid, configuration]) => {
|
2650
|
-
acc[uid] = {
|
2651
|
-
layout: convertEditLayoutToFieldLayouts(
|
2652
|
-
configuration.layouts.edit,
|
2653
|
-
components[uid].attributes,
|
2654
|
-
configuration.metadatas
|
2655
|
-
),
|
2656
|
-
settings: {
|
2657
|
-
...configuration.settings,
|
2658
|
-
icon: components[uid].info.icon,
|
2659
|
-
displayName: components[uid].info.displayName
|
2660
|
-
}
|
2661
|
-
};
|
2662
|
-
return acc;
|
2663
|
-
},
|
2664
|
-
{}
|
2665
|
-
);
|
2666
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2667
|
-
(acc, [attribute, metadata]) => {
|
2668
|
-
return {
|
2669
|
-
...acc,
|
2670
|
-
[attribute]: metadata.edit
|
2671
|
-
};
|
2672
|
-
},
|
2673
|
-
{}
|
2674
|
-
);
|
2675
|
-
return {
|
2676
|
-
layout: panelledEditAttributes,
|
2677
|
-
components: componentEditAttributes,
|
2678
|
-
metadatas: editMetadatas,
|
2679
|
-
settings: {
|
2680
|
-
...data.contentType.settings,
|
2681
|
-
displayName: schema?.info.displayName
|
2682
|
-
},
|
2683
|
-
options: {
|
2684
|
-
...schema?.options,
|
2685
|
-
...schema?.pluginOptions,
|
2686
|
-
...data.contentType.options
|
2963
|
+
query: { status }
|
2687
2964
|
}
|
2965
|
+
] = useQueryParams({
|
2966
|
+
status: "draft"
|
2967
|
+
});
|
2968
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2969
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2970
|
+
const props = {
|
2971
|
+
activeTab: status,
|
2972
|
+
model,
|
2973
|
+
documentId: id,
|
2974
|
+
document: isCloning ? void 0 : document,
|
2975
|
+
meta: isCloning ? void 0 : meta,
|
2976
|
+
collectionType
|
2688
2977
|
};
|
2978
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2979
|
+
DescriptionComponentRenderer,
|
2980
|
+
{
|
2981
|
+
props,
|
2982
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2983
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2984
|
+
}
|
2985
|
+
) });
|
2689
2986
|
};
|
2690
|
-
const
|
2691
|
-
|
2692
|
-
(row) => row.map((field) => {
|
2693
|
-
const attribute = attributes[field.name];
|
2694
|
-
if (!attribute) {
|
2695
|
-
return null;
|
2696
|
-
}
|
2697
|
-
const { edit: metadata } = metadatas[field.name];
|
2698
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2699
|
-
return {
|
2700
|
-
attribute,
|
2701
|
-
disabled: !metadata.editable,
|
2702
|
-
hint: metadata.description,
|
2703
|
-
label: metadata.label ?? "",
|
2704
|
-
name: field.name,
|
2705
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2706
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2707
|
-
schemas,
|
2708
|
-
components: components?.schemas ?? {}
|
2709
|
-
}),
|
2710
|
-
placeholder: metadata.placeholder ?? "",
|
2711
|
-
required: attribute.required ?? false,
|
2712
|
-
size: field.size,
|
2713
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
2714
|
-
visible: metadata.visible ?? true,
|
2715
|
-
type: attribute.type
|
2716
|
-
};
|
2717
|
-
}).filter((field) => field !== null)
|
2718
|
-
);
|
2719
|
-
};
|
2720
|
-
const formatListLayout = (data, {
|
2721
|
-
schemas,
|
2722
|
-
schema,
|
2723
|
-
components
|
2724
|
-
}) => {
|
2725
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2726
|
-
(acc, [attribute, metadata]) => {
|
2727
|
-
return {
|
2728
|
-
...acc,
|
2729
|
-
[attribute]: metadata.list
|
2730
|
-
};
|
2731
|
-
},
|
2732
|
-
{}
|
2733
|
-
);
|
2734
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2735
|
-
data.contentType.layouts.list,
|
2736
|
-
schema?.attributes,
|
2737
|
-
listMetadatas,
|
2738
|
-
{ configurations: data.components, schemas: components },
|
2739
|
-
schemas
|
2740
|
-
);
|
2987
|
+
const ActionsPanel = () => {
|
2988
|
+
const { formatMessage } = useIntl();
|
2741
2989
|
return {
|
2742
|
-
|
2743
|
-
|
2744
|
-
|
2745
|
-
|
2746
|
-
|
2747
|
-
...schema?.pluginOptions,
|
2748
|
-
...data.contentType.options
|
2749
|
-
}
|
2990
|
+
title: formatMessage({
|
2991
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2992
|
+
defaultMessage: "Entry"
|
2993
|
+
}),
|
2994
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2750
2995
|
};
|
2751
2996
|
};
|
2752
|
-
|
2753
|
-
|
2754
|
-
|
2755
|
-
|
2756
|
-
|
2997
|
+
ActionsPanel.type = "actions";
|
2998
|
+
const ActionsPanelContent = () => {
|
2999
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
3000
|
+
const [
|
3001
|
+
{
|
3002
|
+
query: { status = "draft" }
|
2757
3003
|
}
|
2758
|
-
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
2762
|
-
|
2763
|
-
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
3004
|
+
] = useQueryParams();
|
3005
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3006
|
+
const plugins = useStrapiApp("ActionsPanel", (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__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3016
|
+
/* @__PURE__ */ jsx(
|
3017
|
+
DescriptionComponentRenderer,
|
3018
|
+
{
|
3019
|
+
props,
|
3020
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("panel"),
|
3021
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
3022
|
+
}
|
3023
|
+
),
|
3024
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3025
|
+
] });
|
2772
3026
|
};
|
3027
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
3028
|
+
return /* @__PURE__ */ jsxs(
|
3029
|
+
Flex,
|
3030
|
+
{
|
3031
|
+
ref,
|
3032
|
+
tag: "aside",
|
3033
|
+
"aria-labelledby": "additional-information",
|
3034
|
+
background: "neutral0",
|
3035
|
+
borderColor: "neutral150",
|
3036
|
+
hasRadius: true,
|
3037
|
+
paddingBottom: 4,
|
3038
|
+
paddingLeft: 4,
|
3039
|
+
paddingRight: 4,
|
3040
|
+
paddingTop: 4,
|
3041
|
+
shadow: "tableShadow",
|
3042
|
+
gap: 3,
|
3043
|
+
direction: "column",
|
3044
|
+
justifyContent: "stretch",
|
3045
|
+
alignItems: "flex-start",
|
3046
|
+
children: [
|
3047
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3048
|
+
children
|
3049
|
+
]
|
3050
|
+
}
|
3051
|
+
);
|
3052
|
+
});
|
2773
3053
|
const ConfirmBulkActionDialog = ({
|
2774
3054
|
onToggleDialog,
|
2775
3055
|
isOpen = false,
|
@@ -2777,7 +3057,7 @@ const ConfirmBulkActionDialog = ({
|
|
2777
3057
|
endAction
|
2778
3058
|
}) => {
|
2779
3059
|
const { formatMessage } = useIntl();
|
2780
|
-
return /* @__PURE__ */ jsx(Dialog.Root, {
|
3060
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2781
3061
|
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
2782
3062
|
id: "app.components.ConfirmDialog.title",
|
2783
3063
|
defaultMessage: "Confirmation"
|
@@ -2808,6 +3088,7 @@ const ConfirmDialogPublishAll = ({
|
|
2808
3088
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2809
3089
|
const { model, schema } = useDoc();
|
2810
3090
|
const [{ query }] = useQueryParams();
|
3091
|
+
const enableDraftRelationsCount = false;
|
2811
3092
|
const {
|
2812
3093
|
data: countDraftRelations = 0,
|
2813
3094
|
isLoading,
|
@@ -2819,7 +3100,7 @@ const ConfirmDialogPublishAll = ({
|
|
2819
3100
|
locale: query?.plugins?.i18n?.locale
|
2820
3101
|
},
|
2821
3102
|
{
|
2822
|
-
skip:
|
3103
|
+
skip: !enableDraftRelationsCount
|
2823
3104
|
}
|
2824
3105
|
);
|
2825
3106
|
React.useEffect(() => {
|
@@ -2898,7 +3179,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
|
2898
3179
|
)
|
2899
3180
|
);
|
2900
3181
|
} else {
|
2901
|
-
messages.push(
|
3182
|
+
messages.push(
|
3183
|
+
...formatErrorMessages(
|
3184
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3185
|
+
value,
|
3186
|
+
currentKey,
|
3187
|
+
formatMessage
|
3188
|
+
)
|
3189
|
+
);
|
2902
3190
|
}
|
2903
3191
|
} else {
|
2904
3192
|
messages.push(
|
@@ -2997,7 +3285,7 @@ const SelectedEntriesTableContent = ({
|
|
2997
3285
|
status: row.status
|
2998
3286
|
}
|
2999
3287
|
) }),
|
3000
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3288
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3001
3289
|
IconButton,
|
3002
3290
|
{
|
3003
3291
|
tag: Link,
|
@@ -3006,23 +3294,16 @@ const SelectedEntriesTableContent = ({
|
|
3006
3294
|
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3007
3295
|
},
|
3008
3296
|
state: { from: pathname },
|
3009
|
-
label: formatMessage(
|
3010
|
-
|
3011
|
-
|
3012
|
-
|
3013
|
-
{
|
3014
|
-
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3015
|
-
defaultMessage: "item line {number}"
|
3016
|
-
},
|
3017
|
-
{ number: index2 + 1 }
|
3018
|
-
)
|
3019
|
-
}
|
3020
|
-
),
|
3297
|
+
label: formatMessage({
|
3298
|
+
id: "content-manager.bulk-publish.edit",
|
3299
|
+
defaultMessage: "Edit"
|
3300
|
+
}),
|
3021
3301
|
target: "_blank",
|
3022
3302
|
marginLeft: "auto",
|
3023
|
-
|
3303
|
+
variant: "ghost",
|
3304
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3024
3305
|
}
|
3025
|
-
) })
|
3306
|
+
) }) })
|
3026
3307
|
] }, row.id)) })
|
3027
3308
|
] });
|
3028
3309
|
};
|
@@ -3059,7 +3340,13 @@ const SelectedEntriesModalContent = ({
|
|
3059
3340
|
);
|
3060
3341
|
const { rows, validationErrors } = React.useMemo(() => {
|
3061
3342
|
if (data.length > 0 && schema) {
|
3062
|
-
const validate = createYupSchema(
|
3343
|
+
const validate = createYupSchema(
|
3344
|
+
schema.attributes,
|
3345
|
+
components,
|
3346
|
+
// Since this is the "Publish" action, the validation
|
3347
|
+
// schema must enforce the rules for published entities
|
3348
|
+
{ status: "published" }
|
3349
|
+
);
|
3063
3350
|
const validationErrors2 = {};
|
3064
3351
|
const rows2 = data.map((entry) => {
|
3065
3352
|
try {
|
@@ -3184,8 +3471,7 @@ const PublishAction = ({ documents, model }) => {
|
|
3184
3471
|
const refetchList = () => {
|
3185
3472
|
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3186
3473
|
};
|
3187
|
-
if (!showPublishButton)
|
3188
|
-
return null;
|
3474
|
+
if (!showPublishButton) return null;
|
3189
3475
|
return {
|
3190
3476
|
actionType: "publish",
|
3191
3477
|
variant: "tertiary",
|
@@ -3253,8 +3539,7 @@ const DeleteAction = ({ documents, model }) => {
|
|
3253
3539
|
selectRow([]);
|
3254
3540
|
}
|
3255
3541
|
};
|
3256
|
-
if (!hasDeletePermission)
|
3257
|
-
return null;
|
3542
|
+
if (!hasDeletePermission) return null;
|
3258
3543
|
return {
|
3259
3544
|
variant: "danger-light",
|
3260
3545
|
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
@@ -3303,8 +3588,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
3303
3588
|
}
|
3304
3589
|
};
|
3305
3590
|
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3306
|
-
if (!showUnpublishButton)
|
3307
|
-
return null;
|
3591
|
+
if (!showUnpublishButton) return null;
|
3308
3592
|
return {
|
3309
3593
|
variant: "tertiary",
|
3310
3594
|
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
@@ -3409,7 +3693,7 @@ const TableActions = ({ document }) => {
|
|
3409
3693
|
DescriptionComponentRenderer,
|
3410
3694
|
{
|
3411
3695
|
props,
|
3412
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3696
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions("table-row").filter((action) => action.name !== "PublishAction"),
|
3413
3697
|
children: (actions2) => {
|
3414
3698
|
const tableRowActions = actions2.filter((action) => {
|
3415
3699
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3468,6 +3752,7 @@ const EditAction = ({ documentId }) => {
|
|
3468
3752
|
};
|
3469
3753
|
};
|
3470
3754
|
EditAction.type = "edit";
|
3755
|
+
EditAction.position = "table-row";
|
3471
3756
|
const StyledPencil = styled(Pencil)`
|
3472
3757
|
path {
|
3473
3758
|
fill: currentColor;
|
@@ -3520,7 +3805,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3520
3805
|
}),
|
3521
3806
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3522
3807
|
footer: ({ onClose }) => {
|
3523
|
-
return /* @__PURE__ */ jsxs(
|
3808
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3524
3809
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3525
3810
|
id: "cancel",
|
3526
3811
|
defaultMessage: "Cancel"
|
@@ -3544,6 +3829,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3544
3829
|
};
|
3545
3830
|
};
|
3546
3831
|
CloneAction.type = "clone";
|
3832
|
+
CloneAction.position = "table-row";
|
3547
3833
|
const StyledDuplicate = styled(Duplicate)`
|
3548
3834
|
path {
|
3549
3835
|
fill: currentColor;
|
@@ -3561,8 +3847,7 @@ class ContentManagerPlugin {
|
|
3561
3847
|
documentActions = [
|
3562
3848
|
...DEFAULT_ACTIONS,
|
3563
3849
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3564
|
-
...DEFAULT_HEADER_ACTIONS
|
3565
|
-
HistoryAction
|
3850
|
+
...DEFAULT_HEADER_ACTIONS
|
3566
3851
|
];
|
3567
3852
|
editViewSidePanels = [ActionsPanel];
|
3568
3853
|
headerActions = [];
|
@@ -3631,7 +3916,14 @@ class ContentManagerPlugin {
|
|
3631
3916
|
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3632
3917
|
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3633
3918
|
getBulkActions: () => this.bulkActions,
|
3634
|
-
getDocumentActions: () =>
|
3919
|
+
getDocumentActions: (position) => {
|
3920
|
+
if (position) {
|
3921
|
+
return this.documentActions.filter(
|
3922
|
+
(action) => action.position == void 0 || [action.position].flat().includes(position)
|
3923
|
+
);
|
3924
|
+
}
|
3925
|
+
return this.documentActions;
|
3926
|
+
},
|
3635
3927
|
getEditViewSidePanels: () => this.editViewSidePanels,
|
3636
3928
|
getHeaderActions: () => this.headerActions
|
3637
3929
|
}
|
@@ -3641,16 +3933,71 @@ class ContentManagerPlugin {
|
|
3641
3933
|
const getPrintableType = (value) => {
|
3642
3934
|
const nativeType = typeof value;
|
3643
3935
|
if (nativeType === "object") {
|
3644
|
-
if (value === null)
|
3645
|
-
|
3646
|
-
if (Array.isArray(value))
|
3647
|
-
return "array";
|
3936
|
+
if (value === null) return "null";
|
3937
|
+
if (Array.isArray(value)) return "array";
|
3648
3938
|
if (value instanceof Object && value.constructor.name !== "Object") {
|
3649
3939
|
return value.constructor.name;
|
3650
3940
|
}
|
3651
3941
|
}
|
3652
3942
|
return nativeType;
|
3653
3943
|
};
|
3944
|
+
const HistoryAction = ({ model, document }) => {
|
3945
|
+
const { formatMessage } = useIntl();
|
3946
|
+
const [{ query }] = useQueryParams();
|
3947
|
+
const navigate = useNavigate();
|
3948
|
+
const { trackUsage } = useTracking();
|
3949
|
+
const { pathname } = useLocation();
|
3950
|
+
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3951
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3952
|
+
return null;
|
3953
|
+
}
|
3954
|
+
const handleOnClick = () => {
|
3955
|
+
const destination = { pathname: "history", search: pluginsQueryParams };
|
3956
|
+
trackUsage("willNavigate", {
|
3957
|
+
from: pathname,
|
3958
|
+
to: `${pathname}/${destination.pathname}`
|
3959
|
+
});
|
3960
|
+
navigate(destination);
|
3961
|
+
};
|
3962
|
+
return {
|
3963
|
+
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3964
|
+
label: formatMessage({
|
3965
|
+
id: "content-manager.history.document-action",
|
3966
|
+
defaultMessage: "Content History"
|
3967
|
+
}),
|
3968
|
+
onClick: handleOnClick,
|
3969
|
+
disabled: (
|
3970
|
+
/**
|
3971
|
+
* The user is creating a new document.
|
3972
|
+
* It hasn't been saved yet, so there's no history to go to
|
3973
|
+
*/
|
3974
|
+
!document || /**
|
3975
|
+
* The document has been created but the current dimension has never been saved.
|
3976
|
+
* For example, the user is creating a new locale in an existing document,
|
3977
|
+
* so there's no history for the document in that locale
|
3978
|
+
*/
|
3979
|
+
!document.id || /**
|
3980
|
+
* History is only available for content types created by the user.
|
3981
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3982
|
+
* which start with `admin::` or `plugin::`
|
3983
|
+
*/
|
3984
|
+
!model.startsWith("api::")
|
3985
|
+
),
|
3986
|
+
position: "header"
|
3987
|
+
};
|
3988
|
+
};
|
3989
|
+
HistoryAction.type = "history";
|
3990
|
+
HistoryAction.position = "header";
|
3991
|
+
const historyAdmin = {
|
3992
|
+
bootstrap(app) {
|
3993
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3994
|
+
addDocumentAction((actions2) => {
|
3995
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3996
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3997
|
+
return actions2;
|
3998
|
+
});
|
3999
|
+
}
|
4000
|
+
};
|
3654
4001
|
const initialState = {
|
3655
4002
|
collectionTypeLinks: [],
|
3656
4003
|
components: [],
|
@@ -3687,6 +4034,90 @@ const { setInitialData } = actions;
|
|
3687
4034
|
const reducer = combineReducers({
|
3688
4035
|
app: reducer$1
|
3689
4036
|
});
|
4037
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4038
|
+
endpoints: (builder) => ({
|
4039
|
+
getPreviewUrl: builder.query({
|
4040
|
+
query({ query, params }) {
|
4041
|
+
return {
|
4042
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4043
|
+
method: "GET",
|
4044
|
+
config: {
|
4045
|
+
params: query
|
4046
|
+
}
|
4047
|
+
};
|
4048
|
+
}
|
4049
|
+
})
|
4050
|
+
})
|
4051
|
+
});
|
4052
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4053
|
+
const ConditionalTooltip = ({ isShown, label, children }) => {
|
4054
|
+
if (isShown) {
|
4055
|
+
return /* @__PURE__ */ jsx(Tooltip, { label, children });
|
4056
|
+
}
|
4057
|
+
return children;
|
4058
|
+
};
|
4059
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4060
|
+
const { formatMessage } = useIntl();
|
4061
|
+
const { trackUsage } = useTracking();
|
4062
|
+
const { pathname } = useLocation();
|
4063
|
+
const [{ query }] = useQueryParams();
|
4064
|
+
const isModified = useForm("PreviewSidePanel", (state) => state.modified);
|
4065
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4066
|
+
params: {
|
4067
|
+
contentType: model
|
4068
|
+
},
|
4069
|
+
query: {
|
4070
|
+
documentId,
|
4071
|
+
locale: document?.locale,
|
4072
|
+
status: document?.status
|
4073
|
+
}
|
4074
|
+
});
|
4075
|
+
if (!data?.data?.url || error) {
|
4076
|
+
return null;
|
4077
|
+
}
|
4078
|
+
const trackNavigation = () => {
|
4079
|
+
const destinationPathname = pathname.replace(/\/$/, "") + "/preview";
|
4080
|
+
trackUsage("willNavigate", { from: pathname, to: destinationPathname });
|
4081
|
+
};
|
4082
|
+
return {
|
4083
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4084
|
+
content: /* @__PURE__ */ jsx(Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsx(
|
4085
|
+
ConditionalTooltip,
|
4086
|
+
{
|
4087
|
+
label: formatMessage({
|
4088
|
+
id: "content-manager.preview.panel.button-disabled-tooltip",
|
4089
|
+
defaultMessage: "Please save to open the preview"
|
4090
|
+
}),
|
4091
|
+
isShown: isModified,
|
4092
|
+
children: /* @__PURE__ */ jsx(
|
4093
|
+
Button,
|
4094
|
+
{
|
4095
|
+
variant: "tertiary",
|
4096
|
+
tag: Link,
|
4097
|
+
to: { pathname: "preview", search: stringify(query, { encode: false }) },
|
4098
|
+
onClick: trackNavigation,
|
4099
|
+
flex: "auto",
|
4100
|
+
disabled: isModified,
|
4101
|
+
children: formatMessage({
|
4102
|
+
id: "content-manager.preview.panel.button",
|
4103
|
+
defaultMessage: "Open preview"
|
4104
|
+
})
|
4105
|
+
}
|
4106
|
+
)
|
4107
|
+
}
|
4108
|
+
) })
|
4109
|
+
};
|
4110
|
+
};
|
4111
|
+
const FEATURE_ID = "preview";
|
4112
|
+
const previewAdmin = {
|
4113
|
+
bootstrap(app) {
|
4114
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4115
|
+
return;
|
4116
|
+
}
|
4117
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4118
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4119
|
+
}
|
4120
|
+
};
|
3690
4121
|
const index = {
|
3691
4122
|
register(app) {
|
3692
4123
|
const cm = new ContentManagerPlugin();
|
@@ -3706,7 +4137,7 @@ const index = {
|
|
3706
4137
|
app.router.addRoute({
|
3707
4138
|
path: "content-manager/*",
|
3708
4139
|
lazy: async () => {
|
3709
|
-
const { Layout } = await import("./layout-
|
4140
|
+
const { Layout } = await import("./layout-CUTOYU8I.mjs");
|
3710
4141
|
return {
|
3711
4142
|
Component: Layout
|
3712
4143
|
};
|
@@ -3715,10 +4146,18 @@ const index = {
|
|
3715
4146
|
});
|
3716
4147
|
app.registerPlugin(cm.config);
|
3717
4148
|
},
|
4149
|
+
bootstrap(app) {
|
4150
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4151
|
+
historyAdmin.bootstrap(app);
|
4152
|
+
}
|
4153
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4154
|
+
previewAdmin.bootstrap(app);
|
4155
|
+
}
|
4156
|
+
},
|
3718
4157
|
async registerTrads({ locales }) {
|
3719
4158
|
const importedTrads = await Promise.all(
|
3720
4159
|
locales.map((locale) => {
|
3721
|
-
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-
|
4160
|
+
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 }) => {
|
3722
4161
|
return {
|
3723
4162
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3724
4163
|
locale
|
@@ -3739,13 +4178,16 @@ export {
|
|
3739
4178
|
BulkActionsRenderer as B,
|
3740
4179
|
COLLECTION_TYPES as C,
|
3741
4180
|
DocumentStatus as D,
|
3742
|
-
|
3743
|
-
|
3744
|
-
|
4181
|
+
extractContentTypeComponents as E,
|
4182
|
+
DEFAULT_SETTINGS as F,
|
4183
|
+
convertEditLayoutToFieldLayouts as G,
|
3745
4184
|
HOOKS as H,
|
3746
4185
|
InjectionZone as I,
|
3747
|
-
|
3748
|
-
|
4186
|
+
useDocument as J,
|
4187
|
+
useGetPreviewUrlQuery as K,
|
4188
|
+
index as L,
|
4189
|
+
useContentManagerContext as M,
|
4190
|
+
useDocumentActions as N,
|
3749
4191
|
Panels as P,
|
3750
4192
|
RelativeTime as R,
|
3751
4193
|
SINGLE_TYPES as S,
|
@@ -3763,18 +4205,18 @@ export {
|
|
3763
4205
|
PERMISSIONS as k,
|
3764
4206
|
DocumentRBAC as l,
|
3765
4207
|
DOCUMENT_META_FIELDS as m,
|
3766
|
-
|
3767
|
-
|
3768
|
-
|
3769
|
-
|
3770
|
-
|
4208
|
+
CLONE_PATH as n,
|
4209
|
+
useDocLayout as o,
|
4210
|
+
useGetContentTypeConfigurationQuery as p,
|
4211
|
+
CREATOR_FIELDS as q,
|
4212
|
+
getMainField as r,
|
3771
4213
|
setInitialData as s,
|
3772
|
-
|
4214
|
+
getDisplayName as t,
|
3773
4215
|
useContentTypeSchema as u,
|
3774
|
-
|
3775
|
-
|
3776
|
-
|
3777
|
-
|
3778
|
-
|
4216
|
+
checkIfAttributeIsDisplayable as v,
|
4217
|
+
useGetAllDocumentsQuery as w,
|
4218
|
+
convertListLayoutToFieldLayouts as x,
|
4219
|
+
capitalise as y,
|
4220
|
+
useUpdateContentTypeConfigurationMutation as z
|
3779
4221
|
};
|
3780
|
-
//# sourceMappingURL=index-
|
4222
|
+
//# sourceMappingURL=index-ByPZ754U.mjs.map
|