@strapi/content-manager 0.0.0-experimental.3c73a4c6f6073abdf1608121a200c3d4d87b1aa8 → 0.0.0-experimental.3d5794391d4c2d9eddf7bd162c02f4bb836eb7a6
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/{ComponentConfigurationPage-BZIaEffq.js → ComponentConfigurationPage-Cjr64OS0.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BZIaEffq.js.map → ComponentConfigurationPage-Cjr64OS0.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-Cxz51Sve.mjs → ComponentConfigurationPage-DKuCF_uX.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-Cxz51Sve.mjs.map → ComponentConfigurationPage-DKuCF_uX.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CM62NN0L.js → EditConfigurationPage-BeikGxvq.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-CM62NN0L.js.map → EditConfigurationPage-BeikGxvq.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CZLbgfIp.mjs → EditConfigurationPage-CyqSP6ru.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-CZLbgfIp.mjs.map → EditConfigurationPage-CyqSP6ru.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-CzuJgWWp.mjs → EditViewPage-PrPHZN_9.mjs} +102 -51
- package/dist/_chunks/EditViewPage-PrPHZN_9.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-CU7724gt.js → EditViewPage-pyqEgLgP.js} +100 -49
- package/dist/_chunks/EditViewPage-pyqEgLgP.js.map +1 -0
- package/dist/_chunks/{Field-QtUSh5mU.mjs → Field-DuAYQka5.mjs} +600 -228
- package/dist/_chunks/Field-DuAYQka5.mjs.map +1 -0
- package/dist/_chunks/{Field-Dh1yZyqy.js → Field-fKtb7rWK.js} +602 -230
- package/dist/_chunks/Field-fKtb7rWK.js.map +1 -0
- package/dist/_chunks/{Form-BOR8NOe1.js → Form-BPXw-S-J.js} +52 -34
- package/dist/_chunks/Form-BPXw-S-J.js.map +1 -0
- package/dist/_chunks/{Form-COLpvlnv.mjs → Form-Dxh71ckp.mjs} +54 -36
- package/dist/_chunks/Form-Dxh71ckp.mjs.map +1 -0
- package/dist/_chunks/{History-CW2akQ6h.js → History-BGGn9JGY.js} +171 -126
- package/dist/_chunks/History-BGGn9JGY.js.map +1 -0
- package/dist/_chunks/{History-Bu53Yfw-.mjs → History-CGblSVMc.mjs} +172 -127
- package/dist/_chunks/History-CGblSVMc.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-jzdhEk_u.js → ListConfigurationPage-D3Avyi4t.js} +58 -47
- package/dist/_chunks/ListConfigurationPage-D3Avyi4t.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-TqrmwjPN.mjs → ListConfigurationPage-TIM0JveM.mjs} +59 -49
- package/dist/_chunks/ListConfigurationPage-TIM0JveM.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-BO_mOXIl.mjs → ListViewPage-C975eW-t.mjs} +128 -105
- package/dist/_chunks/ListViewPage-C975eW-t.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-B3bMOrMv.js → ListViewPage-DtAHWFMV.js} +130 -107
- package/dist/_chunks/ListViewPage-DtAHWFMV.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-D77xsNHj.js → NoContentTypePage-BFjWZX0i.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-D77xsNHj.js.map → NoContentTypePage-BFjWZX0i.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-DqB0QV0k.mjs → NoContentTypePage-SgNTVGjF.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-DqB0QV0k.mjs.map → NoContentTypePage-SgNTVGjF.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DTXi042N.mjs → NoPermissionsPage-D4XYRoPf.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DTXi042N.mjs.map → NoPermissionsPage-D4XYRoPf.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-C6qTGogm.js → NoPermissionsPage-j7oulOpl.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-C6qTGogm.js.map → NoPermissionsPage-j7oulOpl.js.map} +1 -1
- package/dist/_chunks/Preview-Bx1WfmKJ.js +256 -0
- package/dist/_chunks/Preview-Bx1WfmKJ.js.map +1 -0
- package/dist/_chunks/Preview-Cy6fuAnd.mjs +237 -0
- package/dist/_chunks/Preview-Cy6fuAnd.mjs.map +1 -0
- package/dist/_chunks/{Relations-B6fb2POW.js → Relations-CXQqwRXC.js} +72 -36
- package/dist/_chunks/Relations-CXQqwRXC.js.map +1 -0
- package/dist/_chunks/{Relations-CJ4qdkRo.mjs → Relations-DUrYWw0N.mjs} +73 -37
- package/dist/_chunks/Relations-DUrYWw0N.mjs.map +1 -0
- package/dist/_chunks/{en-9GwRW_ku.mjs → en-69jRDM9j.mjs} +31 -17
- package/dist/_chunks/{en-9GwRW_ku.mjs.map → en-69jRDM9j.mjs.map} +1 -1
- package/dist/_chunks/{en-DZXjRiWA.js → en-DAgtrRoa.js} +31 -17
- package/dist/_chunks/{en-DZXjRiWA.js.map → en-DAgtrRoa.js.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/{index-Dahjdw4h.mjs → index-Ta--2bRa.mjs} +1107 -883
- package/dist/_chunks/index-Ta--2bRa.mjs.map +1 -0
- package/dist/_chunks/{index-DcUu-_72.js → index-_j7lH3CO.js} +1099 -874
- package/dist/_chunks/index-_j7lH3CO.js.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-jcY4dyUG.js → layout-BDwU2I_y.js} +25 -12
- package/dist/_chunks/layout-BDwU2I_y.js.map +1 -0
- package/dist/_chunks/{layout-omucV6TV.mjs → layout-C8H4oKDo.mjs} +27 -14
- package/dist/_chunks/layout-C8H4oKDo.mjs.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-DGzD7ORa.js → relations-CPfMNzM6.js} +6 -7
- package/dist/_chunks/relations-CPfMNzM6.js.map +1 -0
- package/dist/_chunks/{relations-CN0-aw6p.mjs → relations-Ch70q86O.mjs} +6 -7
- package/dist/_chunks/relations-Ch70q86O.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/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +4 -3
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/components/VersionInputRenderer.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 +8 -3
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
- 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 +6 -58
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
- package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
- 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 -17
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +551 -263
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +552 -264
- 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 +15 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +30 -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 +18 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- 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 +14 -14
- package/dist/_chunks/EditViewPage-CU7724gt.js.map +0 -1
- package/dist/_chunks/EditViewPage-CzuJgWWp.mjs.map +0 -1
- package/dist/_chunks/Field-Dh1yZyqy.js.map +0 -1
- package/dist/_chunks/Field-QtUSh5mU.mjs.map +0 -1
- package/dist/_chunks/Form-BOR8NOe1.js.map +0 -1
- package/dist/_chunks/Form-COLpvlnv.mjs.map +0 -1
- package/dist/_chunks/History-Bu53Yfw-.mjs.map +0 -1
- package/dist/_chunks/History-CW2akQ6h.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-TqrmwjPN.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-jzdhEk_u.js.map +0 -1
- package/dist/_chunks/ListViewPage-B3bMOrMv.js.map +0 -1
- package/dist/_chunks/ListViewPage-BO_mOXIl.mjs.map +0 -1
- package/dist/_chunks/Relations-B6fb2POW.js.map +0 -1
- package/dist/_chunks/Relations-CJ4qdkRo.mjs.map +0 -1
- package/dist/_chunks/index-Dahjdw4h.mjs.map +0 -1
- package/dist/_chunks/index-DcUu-_72.js.map +0 -1
- package/dist/_chunks/layout-jcY4dyUG.js.map +0 -1
- package/dist/_chunks/layout-omucV6TV.mjs.map +0 -1
- package/dist/_chunks/relations-CN0-aw6p.mjs.map +0 -1
- package/dist/_chunks/relations-DGzD7ORa.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,17 +1,18 @@
|
|
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 { Menu, VisuallyHidden, Flex,
|
10
|
-
import
|
6
|
+
import { Button, Menu, 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";
|
11
10
|
import * as yup from "yup";
|
12
11
|
import { ValidationError } from "yup";
|
13
12
|
import pipe from "lodash/fp/pipe";
|
14
13
|
import { intervalToDuration, isPast } from "date-fns";
|
14
|
+
import { styled } from "styled-components";
|
15
|
+
import { stringify } from "qs";
|
15
16
|
import { createSlice, combineReducers } from "@reduxjs/toolkit";
|
16
17
|
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
17
18
|
const v = glob[path];
|
@@ -49,42 +50,6 @@ const useInjectionZone = (area) => {
|
|
49
50
|
const [page, position] = area.split(".");
|
50
51
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
51
52
|
};
|
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
53
|
const ID = "id";
|
89
54
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
90
55
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -136,6 +101,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
136
101
|
if (!slug) {
|
137
102
|
throw new Error("Cannot find the slug param in the URL");
|
138
103
|
}
|
104
|
+
const [{ rawQuery }] = useQueryParams();
|
139
105
|
const userPermissions = useAuth("DocumentRBAC", (state) => state.permissions);
|
140
106
|
const contentTypePermissions = React.useMemo(() => {
|
141
107
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -146,7 +112,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
146
112
|
return { ...acc, [action]: [permission] };
|
147
113
|
}, {});
|
148
114
|
}, [slug, userPermissions]);
|
149
|
-
const { isLoading, allowedActions } = useRBAC(
|
115
|
+
const { isLoading, allowedActions } = useRBAC(
|
116
|
+
contentTypePermissions,
|
117
|
+
permissions ?? void 0,
|
118
|
+
// TODO: useRBAC context should be typed and built differently
|
119
|
+
// We are passing raw query as context to the hook so that it can
|
120
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
121
|
+
rawQuery
|
122
|
+
);
|
150
123
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
151
124
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
152
125
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -194,10 +167,12 @@ const contentManagerApi = adminApi.enhanceEndpoints({
|
|
194
167
|
"Document",
|
195
168
|
"InitialData",
|
196
169
|
"HistoryVersion",
|
197
|
-
"Relations"
|
170
|
+
"Relations",
|
171
|
+
"UidAvailability"
|
198
172
|
]
|
199
173
|
});
|
200
174
|
const documentApi = contentManagerApi.injectEndpoints({
|
175
|
+
overrideExisting: true,
|
201
176
|
endpoints: (builder) => ({
|
202
177
|
autoCloneDocument: builder.mutation({
|
203
178
|
query: ({ model, sourceId, query }) => ({
|
@@ -207,7 +182,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
207
182
|
params: query
|
208
183
|
}
|
209
184
|
}),
|
210
|
-
invalidatesTags: (_result,
|
185
|
+
invalidatesTags: (_result, error, { model }) => {
|
186
|
+
if (error) {
|
187
|
+
return [];
|
188
|
+
}
|
189
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
190
|
+
}
|
211
191
|
}),
|
212
192
|
cloneDocument: builder.mutation({
|
213
193
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -218,7 +198,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
218
198
|
params
|
219
199
|
}
|
220
200
|
}),
|
221
|
-
invalidatesTags: (_result, _error, { model }) => [
|
201
|
+
invalidatesTags: (_result, _error, { model }) => [
|
202
|
+
{ type: "Document", id: `${model}_LIST` },
|
203
|
+
{ type: "UidAvailability", id: model }
|
204
|
+
]
|
222
205
|
}),
|
223
206
|
/**
|
224
207
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -235,7 +218,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
235
218
|
}),
|
236
219
|
invalidatesTags: (result, _error, { model }) => [
|
237
220
|
{ type: "Document", id: `${model}_LIST` },
|
238
|
-
"Relations"
|
221
|
+
"Relations",
|
222
|
+
{ type: "UidAvailability", id: model }
|
239
223
|
]
|
240
224
|
}),
|
241
225
|
deleteDocument: builder.mutation({
|
@@ -276,7 +260,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
276
260
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
277
261
|
},
|
278
262
|
{ type: "Document", id: `${model}_LIST` },
|
279
|
-
"Relations"
|
263
|
+
"Relations",
|
264
|
+
{ type: "UidAvailability", id: model }
|
280
265
|
];
|
281
266
|
}
|
282
267
|
}),
|
@@ -294,6 +279,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
294
279
|
}),
|
295
280
|
providesTags: (result, _error, arg) => {
|
296
281
|
return [
|
282
|
+
{ type: "Document", id: `ALL_LIST` },
|
297
283
|
{ type: "Document", id: `${arg.model}_LIST` },
|
298
284
|
...result?.results.map(({ documentId }) => ({
|
299
285
|
type: "Document",
|
@@ -332,6 +318,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
332
318
|
{
|
333
319
|
type: "Document",
|
334
320
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
321
|
+
},
|
322
|
+
// Make it easy to invalidate all individual documents queries for a model
|
323
|
+
{
|
324
|
+
type: "Document",
|
325
|
+
id: `${model}_ALL_ITEMS`
|
335
326
|
}
|
336
327
|
];
|
337
328
|
}
|
@@ -395,8 +386,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
395
386
|
type: "Document",
|
396
387
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
397
388
|
},
|
398
|
-
"Relations"
|
389
|
+
"Relations",
|
390
|
+
{ type: "UidAvailability", id: model }
|
399
391
|
];
|
392
|
+
},
|
393
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
394
|
+
const patchResult = dispatch(
|
395
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
396
|
+
Object.assign(draft.data, data);
|
397
|
+
})
|
398
|
+
);
|
399
|
+
try {
|
400
|
+
await queryFulfilled;
|
401
|
+
} catch {
|
402
|
+
patchResult.undo();
|
403
|
+
}
|
400
404
|
}
|
401
405
|
}),
|
402
406
|
unpublishDocument: builder.mutation({
|
@@ -466,20 +470,39 @@ const buildValidParams = (query) => {
|
|
466
470
|
const isBaseQueryError = (error) => {
|
467
471
|
return error.name !== void 0;
|
468
472
|
};
|
469
|
-
const
|
473
|
+
const arrayValidator = (attribute, options) => ({
|
474
|
+
message: translatedErrors.required,
|
475
|
+
test(value) {
|
476
|
+
if (options.status === "draft") {
|
477
|
+
return true;
|
478
|
+
}
|
479
|
+
if (!attribute.required) {
|
480
|
+
return true;
|
481
|
+
}
|
482
|
+
if (!value) {
|
483
|
+
return false;
|
484
|
+
}
|
485
|
+
if (Array.isArray(value) && value.length === 0) {
|
486
|
+
return false;
|
487
|
+
}
|
488
|
+
return true;
|
489
|
+
}
|
490
|
+
});
|
491
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
470
492
|
const createModelSchema = (attributes2) => yup.object().shape(
|
471
493
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
472
494
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
473
495
|
return acc;
|
474
496
|
}
|
475
497
|
const validations = [
|
498
|
+
addNullableValidation,
|
476
499
|
addRequiredValidation,
|
477
500
|
addMinLengthValidation,
|
478
501
|
addMaxLengthValidation,
|
479
502
|
addMinValidation,
|
480
503
|
addMaxValidation,
|
481
504
|
addRegexValidation
|
482
|
-
].map((fn) => fn(attribute));
|
505
|
+
].map((fn) => fn(attribute, options));
|
483
506
|
const transformSchema = pipe(...validations);
|
484
507
|
switch (attribute.type) {
|
485
508
|
case "component": {
|
@@ -489,12 +512,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
489
512
|
...acc,
|
490
513
|
[name]: transformSchema(
|
491
514
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
492
|
-
)
|
515
|
+
).test(arrayValidator(attribute, options))
|
493
516
|
};
|
494
517
|
} else {
|
495
518
|
return {
|
496
519
|
...acc,
|
497
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
520
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
498
521
|
};
|
499
522
|
}
|
500
523
|
}
|
@@ -516,7 +539,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
516
539
|
}
|
517
540
|
)
|
518
541
|
)
|
519
|
-
)
|
542
|
+
).test(arrayValidator(attribute, options))
|
520
543
|
};
|
521
544
|
case "relation":
|
522
545
|
return {
|
@@ -528,7 +551,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
528
551
|
} else if (Array.isArray(value)) {
|
529
552
|
return yup.array().of(
|
530
553
|
yup.object().shape({
|
531
|
-
id: yup.
|
554
|
+
id: yup.number().required()
|
532
555
|
})
|
533
556
|
);
|
534
557
|
} else if (typeof value === "object") {
|
@@ -580,6 +603,14 @@ const createAttributeSchema = (attribute) => {
|
|
580
603
|
if (!value || typeof value === "string" && value.length === 0) {
|
581
604
|
return true;
|
582
605
|
}
|
606
|
+
if (typeof value === "object") {
|
607
|
+
try {
|
608
|
+
JSON.stringify(value);
|
609
|
+
return true;
|
610
|
+
} catch (err) {
|
611
|
+
return false;
|
612
|
+
}
|
613
|
+
}
|
583
614
|
try {
|
584
615
|
JSON.parse(value);
|
585
616
|
return true;
|
@@ -598,13 +629,7 @@ const createAttributeSchema = (attribute) => {
|
|
598
629
|
return yup.mixed();
|
599
630
|
}
|
600
631
|
};
|
601
|
-
const
|
602
|
-
if (attribute.required) {
|
603
|
-
return schema.required({
|
604
|
-
id: translatedErrors.required.id,
|
605
|
-
defaultMessage: "This field is required."
|
606
|
-
});
|
607
|
-
}
|
632
|
+
const nullableSchema = (schema) => {
|
608
633
|
return schema?.nullable ? schema.nullable() : (
|
609
634
|
// In some cases '.nullable' will not be available on the schema.
|
610
635
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -612,7 +637,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
612
637
|
schema
|
613
638
|
);
|
614
639
|
};
|
615
|
-
const
|
640
|
+
const addNullableValidation = () => (schema) => {
|
641
|
+
return nullableSchema(schema);
|
642
|
+
};
|
643
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
644
|
+
if (options.status === "draft" || !attribute.required) {
|
645
|
+
return schema;
|
646
|
+
}
|
647
|
+
if (attribute.required && "required" in schema) {
|
648
|
+
return schema.required(translatedErrors.required);
|
649
|
+
}
|
650
|
+
return schema;
|
651
|
+
};
|
652
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
653
|
+
if (options.status === "draft") {
|
654
|
+
return schema;
|
655
|
+
}
|
616
656
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
617
657
|
return schema.min(attribute.minLength, {
|
618
658
|
...translatedErrors.minLength,
|
@@ -634,10 +674,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
634
674
|
}
|
635
675
|
return schema;
|
636
676
|
};
|
637
|
-
const addMinValidation = (attribute) => (schema) => {
|
638
|
-
if ("
|
677
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
678
|
+
if (options.status === "draft") {
|
679
|
+
return schema;
|
680
|
+
}
|
681
|
+
if ("min" in attribute && "min" in schema) {
|
639
682
|
const min = toInteger(attribute.min);
|
640
|
-
if (
|
683
|
+
if (min) {
|
641
684
|
return schema.min(min, {
|
642
685
|
...translatedErrors.min,
|
643
686
|
values: {
|
@@ -755,16 +798,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
755
798
|
}, {});
|
756
799
|
return componentsByKey;
|
757
800
|
};
|
758
|
-
const
|
801
|
+
const HOOKS = {
|
802
|
+
/**
|
803
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
804
|
+
* @constant
|
805
|
+
* @type {string}
|
806
|
+
*/
|
807
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
808
|
+
/**
|
809
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
810
|
+
* @constant
|
811
|
+
* @type {string}
|
812
|
+
*/
|
813
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
814
|
+
/**
|
815
|
+
* Hook that allows to mutate the CM's edit view layout
|
816
|
+
* @constant
|
817
|
+
* @type {string}
|
818
|
+
*/
|
819
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
820
|
+
/**
|
821
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
822
|
+
* @constant
|
823
|
+
* @type {string}
|
824
|
+
*/
|
825
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
826
|
+
};
|
827
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
828
|
+
endpoints: (builder) => ({
|
829
|
+
getContentTypeConfiguration: builder.query({
|
830
|
+
query: (uid) => ({
|
831
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
832
|
+
method: "GET"
|
833
|
+
}),
|
834
|
+
transformResponse: (response) => response.data,
|
835
|
+
providesTags: (_result, _error, uid) => [
|
836
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
837
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
838
|
+
]
|
839
|
+
}),
|
840
|
+
getAllContentTypeSettings: builder.query({
|
841
|
+
query: () => "/content-manager/content-types-settings",
|
842
|
+
transformResponse: (response) => response.data,
|
843
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
844
|
+
}),
|
845
|
+
updateContentTypeConfiguration: builder.mutation({
|
846
|
+
query: ({ uid, ...body }) => ({
|
847
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
848
|
+
method: "PUT",
|
849
|
+
data: body
|
850
|
+
}),
|
851
|
+
transformResponse: (response) => response.data,
|
852
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
853
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
854
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
855
|
+
// Is this necessary?
|
856
|
+
{ type: "InitialData" }
|
857
|
+
]
|
858
|
+
})
|
859
|
+
})
|
860
|
+
});
|
861
|
+
const {
|
862
|
+
useGetContentTypeConfigurationQuery,
|
863
|
+
useGetAllContentTypeSettingsQuery,
|
864
|
+
useUpdateContentTypeConfigurationMutation
|
865
|
+
} = contentTypesApi;
|
866
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
867
|
+
const { type } = attribute;
|
868
|
+
if (type === "relation") {
|
869
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
870
|
+
}
|
871
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
872
|
+
};
|
873
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
874
|
+
if (!mainFieldName) {
|
875
|
+
return void 0;
|
876
|
+
}
|
877
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
878
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
879
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
880
|
+
);
|
881
|
+
return {
|
882
|
+
name: mainFieldName,
|
883
|
+
type: mainFieldType ?? "string"
|
884
|
+
};
|
885
|
+
};
|
886
|
+
const DEFAULT_SETTINGS = {
|
887
|
+
bulkable: false,
|
888
|
+
filterable: false,
|
889
|
+
searchable: false,
|
890
|
+
pagination: false,
|
891
|
+
defaultSortBy: "",
|
892
|
+
defaultSortOrder: "asc",
|
893
|
+
mainField: "id",
|
894
|
+
pageSize: 10
|
895
|
+
};
|
896
|
+
const useDocumentLayout = (model) => {
|
897
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
898
|
+
const [{ query }] = useQueryParams();
|
899
|
+
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
759
900
|
const { toggleNotification } = useNotification();
|
760
901
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
902
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
761
903
|
const {
|
762
|
-
|
763
|
-
isLoading:
|
764
|
-
|
765
|
-
|
766
|
-
} =
|
767
|
-
const
|
904
|
+
data,
|
905
|
+
isLoading: isLoadingConfigs,
|
906
|
+
error,
|
907
|
+
isFetching: isFetchingConfigs
|
908
|
+
} = useGetContentTypeConfigurationQuery(model);
|
909
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
768
910
|
React.useEffect(() => {
|
769
911
|
if (error) {
|
770
912
|
toggleNotification({
|
@@ -772,68 +914,322 @@ const useDocument = (args, opts) => {
|
|
772
914
|
message: formatAPIError(error)
|
773
915
|
});
|
774
916
|
}
|
775
|
-
}, [
|
776
|
-
const
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
(document) => {
|
784
|
-
if (!validationSchema) {
|
785
|
-
throw new Error(
|
786
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
787
|
-
);
|
788
|
-
}
|
789
|
-
try {
|
790
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
791
|
-
return null;
|
792
|
-
} catch (error2) {
|
793
|
-
if (error2 instanceof ValidationError) {
|
794
|
-
return getYupValidationErrors(error2);
|
795
|
-
}
|
796
|
-
throw error2;
|
797
|
-
}
|
917
|
+
}, [error, formatAPIError, toggleNotification]);
|
918
|
+
const editLayout = React.useMemo(
|
919
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
920
|
+
layout: [],
|
921
|
+
components: {},
|
922
|
+
metadatas: {},
|
923
|
+
options: {},
|
924
|
+
settings: DEFAULT_SETTINGS
|
798
925
|
},
|
799
|
-
[
|
926
|
+
[data, isLoading, schemas, schema, components]
|
927
|
+
);
|
928
|
+
const listLayout = React.useMemo(() => {
|
929
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
930
|
+
layout: [],
|
931
|
+
metadatas: {},
|
932
|
+
options: {},
|
933
|
+
settings: DEFAULT_SETTINGS
|
934
|
+
};
|
935
|
+
}, [data, isLoading, schemas, schema, components]);
|
936
|
+
const { layout: edit } = React.useMemo(
|
937
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
938
|
+
layout: editLayout,
|
939
|
+
query
|
940
|
+
}),
|
941
|
+
[editLayout, query, runHookWaterfall]
|
800
942
|
);
|
801
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
802
943
|
return {
|
803
|
-
|
804
|
-
document: data?.data,
|
805
|
-
meta: data?.meta,
|
944
|
+
error,
|
806
945
|
isLoading,
|
807
|
-
|
808
|
-
|
946
|
+
edit,
|
947
|
+
list: listLayout
|
809
948
|
};
|
810
949
|
};
|
811
|
-
const
|
812
|
-
const {
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
950
|
+
const useDocLayout = () => {
|
951
|
+
const { model } = useDoc();
|
952
|
+
return useDocumentLayout(model);
|
953
|
+
};
|
954
|
+
const formatEditLayout = (data, {
|
955
|
+
schemas,
|
956
|
+
schema,
|
957
|
+
components
|
958
|
+
}) => {
|
959
|
+
let currentPanelIndex = 0;
|
960
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
961
|
+
data.contentType.layouts.edit,
|
962
|
+
schema?.attributes,
|
963
|
+
data.contentType.metadatas,
|
964
|
+
{ configurations: data.components, schemas: components },
|
965
|
+
schemas
|
966
|
+
).reduce((panels, row) => {
|
967
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
968
|
+
panels.push([row]);
|
969
|
+
currentPanelIndex += 2;
|
970
|
+
} else {
|
971
|
+
if (!panels[currentPanelIndex]) {
|
972
|
+
panels.push([row]);
|
973
|
+
} else {
|
974
|
+
panels[currentPanelIndex].push(row);
|
975
|
+
}
|
976
|
+
}
|
977
|
+
return panels;
|
978
|
+
}, []);
|
979
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
980
|
+
(acc, [uid, configuration]) => {
|
981
|
+
acc[uid] = {
|
982
|
+
layout: convertEditLayoutToFieldLayouts(
|
983
|
+
configuration.layouts.edit,
|
984
|
+
components[uid].attributes,
|
985
|
+
configuration.metadatas,
|
986
|
+
{ configurations: data.components, schemas: components }
|
987
|
+
),
|
988
|
+
settings: {
|
989
|
+
...configuration.settings,
|
990
|
+
icon: components[uid].info.icon,
|
991
|
+
displayName: components[uid].info.displayName
|
992
|
+
}
|
993
|
+
};
|
994
|
+
return acc;
|
995
|
+
},
|
996
|
+
{}
|
997
|
+
);
|
998
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
999
|
+
(acc, [attribute, metadata]) => {
|
1000
|
+
return {
|
1001
|
+
...acc,
|
1002
|
+
[attribute]: metadata.edit
|
1003
|
+
};
|
1004
|
+
},
|
1005
|
+
{}
|
1006
|
+
);
|
1007
|
+
return {
|
1008
|
+
layout: panelledEditAttributes,
|
1009
|
+
components: componentEditAttributes,
|
1010
|
+
metadatas: editMetadatas,
|
1011
|
+
settings: {
|
1012
|
+
...data.contentType.settings,
|
1013
|
+
displayName: schema?.info.displayName
|
1014
|
+
},
|
1015
|
+
options: {
|
1016
|
+
...schema?.options,
|
1017
|
+
...schema?.pluginOptions,
|
1018
|
+
...data.contentType.options
|
1019
|
+
}
|
1020
|
+
};
|
1021
|
+
};
|
1022
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1023
|
+
return rows.map(
|
1024
|
+
(row) => row.map((field) => {
|
1025
|
+
const attribute = attributes[field.name];
|
1026
|
+
if (!attribute) {
|
1027
|
+
return null;
|
1028
|
+
}
|
1029
|
+
const { edit: metadata } = metadatas[field.name];
|
1030
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1031
|
+
return {
|
1032
|
+
attribute,
|
1033
|
+
disabled: !metadata.editable,
|
1034
|
+
hint: metadata.description,
|
1035
|
+
label: metadata.label ?? "",
|
1036
|
+
name: field.name,
|
1037
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1038
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1039
|
+
schemas,
|
1040
|
+
components: components?.schemas ?? {}
|
1041
|
+
}),
|
1042
|
+
placeholder: metadata.placeholder ?? "",
|
1043
|
+
required: attribute.required ?? false,
|
1044
|
+
size: field.size,
|
1045
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1046
|
+
visible: metadata.visible ?? true,
|
1047
|
+
type: attribute.type
|
1048
|
+
};
|
1049
|
+
}).filter((field) => field !== null)
|
1050
|
+
);
|
1051
|
+
};
|
1052
|
+
const formatListLayout = (data, {
|
1053
|
+
schemas,
|
1054
|
+
schema,
|
1055
|
+
components
|
1056
|
+
}) => {
|
1057
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1058
|
+
(acc, [attribute, metadata]) => {
|
1059
|
+
return {
|
1060
|
+
...acc,
|
1061
|
+
[attribute]: metadata.list
|
1062
|
+
};
|
1063
|
+
},
|
1064
|
+
{}
|
1065
|
+
);
|
1066
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1067
|
+
data.contentType.layouts.list,
|
1068
|
+
schema?.attributes,
|
1069
|
+
listMetadatas,
|
1070
|
+
{ configurations: data.components, schemas: components },
|
1071
|
+
schemas
|
1072
|
+
);
|
1073
|
+
return {
|
1074
|
+
layout: listAttributes,
|
1075
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1076
|
+
metadatas: listMetadatas,
|
1077
|
+
options: {
|
1078
|
+
...schema?.options,
|
1079
|
+
...schema?.pluginOptions,
|
1080
|
+
...data.contentType.options
|
1081
|
+
}
|
1082
|
+
};
|
1083
|
+
};
|
1084
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1085
|
+
return columns.map((name) => {
|
1086
|
+
const attribute = attributes[name];
|
1087
|
+
if (!attribute) {
|
1088
|
+
return null;
|
1089
|
+
}
|
1090
|
+
const metadata = metadatas[name];
|
1091
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1092
|
+
return {
|
1093
|
+
attribute,
|
1094
|
+
label: metadata.label ?? "",
|
1095
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1096
|
+
schemas,
|
1097
|
+
components: components?.schemas ?? {}
|
1098
|
+
}),
|
1099
|
+
name,
|
1100
|
+
searchable: metadata.searchable ?? true,
|
1101
|
+
sortable: metadata.sortable ?? true
|
1102
|
+
};
|
1103
|
+
}).filter((field) => field !== null);
|
1104
|
+
};
|
1105
|
+
const useDocument = (args, opts) => {
|
1106
|
+
const { toggleNotification } = useNotification();
|
1107
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1108
|
+
const {
|
1109
|
+
currentData: data,
|
1110
|
+
isLoading: isLoadingDocument,
|
1111
|
+
isFetching: isFetchingDocument,
|
1112
|
+
error
|
1113
|
+
} = useGetDocumentQuery(args, {
|
1114
|
+
...opts,
|
1115
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1116
|
+
});
|
1117
|
+
const {
|
1118
|
+
components,
|
1119
|
+
schema,
|
1120
|
+
schemas,
|
1121
|
+
isLoading: isLoadingSchema
|
1122
|
+
} = useContentTypeSchema(args.model);
|
1123
|
+
React.useEffect(() => {
|
1124
|
+
if (error) {
|
1125
|
+
toggleNotification({
|
1126
|
+
type: "danger",
|
1127
|
+
message: formatAPIError(error)
|
1128
|
+
});
|
1129
|
+
}
|
1130
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1131
|
+
const validationSchema = React.useMemo(() => {
|
1132
|
+
if (!schema) {
|
1133
|
+
return null;
|
1134
|
+
}
|
1135
|
+
return createYupSchema(schema.attributes, components);
|
1136
|
+
}, [schema, components]);
|
1137
|
+
const validate = React.useCallback(
|
1138
|
+
(document) => {
|
1139
|
+
if (!validationSchema) {
|
1140
|
+
throw new Error(
|
1141
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1142
|
+
);
|
1143
|
+
}
|
1144
|
+
try {
|
1145
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1146
|
+
return null;
|
1147
|
+
} catch (error2) {
|
1148
|
+
if (error2 instanceof ValidationError) {
|
1149
|
+
return getYupValidationErrors(error2);
|
1150
|
+
}
|
1151
|
+
throw error2;
|
1152
|
+
}
|
1153
|
+
},
|
1154
|
+
[validationSchema]
|
1155
|
+
);
|
1156
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1157
|
+
const hasError = !!error;
|
1158
|
+
return {
|
1159
|
+
components,
|
1160
|
+
document: data?.data,
|
1161
|
+
meta: data?.meta,
|
1162
|
+
isLoading,
|
1163
|
+
hasError,
|
1164
|
+
schema,
|
1165
|
+
schemas,
|
1166
|
+
validate
|
1167
|
+
};
|
1168
|
+
};
|
1169
|
+
const useDoc = () => {
|
1170
|
+
const { id, slug, collectionType, origin } = useParams();
|
1171
|
+
const [{ query }] = useQueryParams();
|
1172
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1173
|
+
if (!collectionType) {
|
1174
|
+
throw new Error("Could not find collectionType in url params");
|
1175
|
+
}
|
1176
|
+
if (!slug) {
|
1177
|
+
throw new Error("Could not find model in url params");
|
1178
|
+
}
|
1179
|
+
const document = useDocument(
|
1180
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1181
|
+
{
|
1182
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1183
|
+
}
|
1184
|
+
);
|
1185
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
821
1186
|
return {
|
822
1187
|
collectionType,
|
823
1188
|
model: slug,
|
824
|
-
id:
|
825
|
-
...
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
1189
|
+
id: returnId,
|
1190
|
+
...document
|
1191
|
+
};
|
1192
|
+
};
|
1193
|
+
const useContentManagerContext = () => {
|
1194
|
+
const {
|
1195
|
+
collectionType,
|
1196
|
+
model,
|
1197
|
+
id,
|
1198
|
+
components,
|
1199
|
+
isLoading: isLoadingDoc,
|
1200
|
+
schema,
|
1201
|
+
schemas
|
1202
|
+
} = useDoc();
|
1203
|
+
const layout = useDocumentLayout(model);
|
1204
|
+
const form = useForm("useContentManagerContext", (state) => state);
|
1205
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1206
|
+
const slug = model;
|
1207
|
+
const isCreatingEntry = id === "create";
|
1208
|
+
useContentTypeSchema();
|
1209
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1210
|
+
const error = layout.error;
|
1211
|
+
return {
|
1212
|
+
error,
|
1213
|
+
isLoading,
|
1214
|
+
// Base metadata
|
1215
|
+
model,
|
1216
|
+
collectionType,
|
1217
|
+
id,
|
1218
|
+
slug,
|
1219
|
+
isCreatingEntry,
|
1220
|
+
isSingleType,
|
1221
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1222
|
+
// All schema infos
|
1223
|
+
components,
|
1224
|
+
contentType: schema,
|
1225
|
+
contentTypes: schemas,
|
1226
|
+
// Form state
|
1227
|
+
form,
|
1228
|
+
// layout infos
|
1229
|
+
layout
|
831
1230
|
};
|
832
1231
|
};
|
833
1232
|
const prefixPluginTranslations = (trad, pluginId) => {
|
834
|
-
if (!pluginId) {
|
835
|
-
throw new TypeError("pluginId can't be empty");
|
836
|
-
}
|
837
1233
|
return Object.keys(trad).reduce((acc, current) => {
|
838
1234
|
acc[`${pluginId}.${current}`] = trad[current];
|
839
1235
|
return acc;
|
@@ -849,6 +1245,8 @@ const useDocumentActions = () => {
|
|
849
1245
|
const { formatMessage } = useIntl();
|
850
1246
|
const { trackUsage } = useTracking();
|
851
1247
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1248
|
+
const navigate = useNavigate();
|
1249
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
852
1250
|
const [deleteDocument] = useDeleteDocumentMutation();
|
853
1251
|
const _delete = React.useCallback(
|
854
1252
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1163,6 +1561,7 @@ const useDocumentActions = () => {
|
|
1163
1561
|
defaultMessage: "Saved document"
|
1164
1562
|
})
|
1165
1563
|
});
|
1564
|
+
setCurrentStep("contentManager.success");
|
1166
1565
|
return res.data;
|
1167
1566
|
} catch (err) {
|
1168
1567
|
toggleNotification({
|
@@ -1184,7 +1583,6 @@ const useDocumentActions = () => {
|
|
1184
1583
|
sourceId
|
1185
1584
|
});
|
1186
1585
|
if ("error" in res) {
|
1187
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1188
1586
|
return { error: res.error };
|
1189
1587
|
}
|
1190
1588
|
toggleNotification({
|
@@ -1203,7 +1601,7 @@ const useDocumentActions = () => {
|
|
1203
1601
|
throw err;
|
1204
1602
|
}
|
1205
1603
|
},
|
1206
|
-
[autoCloneDocument,
|
1604
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1207
1605
|
);
|
1208
1606
|
const [cloneDocument] = useCloneDocumentMutation();
|
1209
1607
|
const clone = React.useCallback(
|
@@ -1229,6 +1627,7 @@ const useDocumentActions = () => {
|
|
1229
1627
|
defaultMessage: "Cloned document"
|
1230
1628
|
})
|
1231
1629
|
});
|
1630
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1232
1631
|
return res.data;
|
1233
1632
|
} catch (err) {
|
1234
1633
|
toggleNotification({
|
@@ -1239,7 +1638,7 @@ const useDocumentActions = () => {
|
|
1239
1638
|
throw err;
|
1240
1639
|
}
|
1241
1640
|
},
|
1242
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1641
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1243
1642
|
);
|
1244
1643
|
const [getDoc] = useLazyGetDocumentQuery();
|
1245
1644
|
const getDocument = React.useCallback(
|
@@ -1264,10 +1663,10 @@ const useDocumentActions = () => {
|
|
1264
1663
|
update
|
1265
1664
|
};
|
1266
1665
|
};
|
1267
|
-
const ProtectedHistoryPage = lazy(
|
1268
|
-
() => import("./History-
|
1666
|
+
const ProtectedHistoryPage = React.lazy(
|
1667
|
+
() => import("./History-CGblSVMc.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1269
1668
|
);
|
1270
|
-
const routes$
|
1669
|
+
const routes$2 = [
|
1271
1670
|
{
|
1272
1671
|
path: ":collectionType/:slug/:id/history",
|
1273
1672
|
Component: ProtectedHistoryPage
|
@@ -1277,32 +1676,45 @@ const routes$1 = [
|
|
1277
1676
|
Component: ProtectedHistoryPage
|
1278
1677
|
}
|
1279
1678
|
];
|
1679
|
+
const ProtectedPreviewPage = React.lazy(
|
1680
|
+
() => import("./Preview-Cy6fuAnd.mjs").then((mod) => ({ default: mod.ProtectedPreviewPage }))
|
1681
|
+
);
|
1682
|
+
const routes$1 = [
|
1683
|
+
{
|
1684
|
+
path: ":collectionType/:slug/:id/preview",
|
1685
|
+
Component: ProtectedPreviewPage
|
1686
|
+
},
|
1687
|
+
{
|
1688
|
+
path: ":collectionType/:slug/preview",
|
1689
|
+
Component: ProtectedPreviewPage
|
1690
|
+
}
|
1691
|
+
];
|
1280
1692
|
const ProtectedEditViewPage = lazy(
|
1281
|
-
() => import("./EditViewPage-
|
1693
|
+
() => import("./EditViewPage-PrPHZN_9.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1282
1694
|
);
|
1283
1695
|
const ProtectedListViewPage = lazy(
|
1284
|
-
() => import("./ListViewPage-
|
1696
|
+
() => import("./ListViewPage-C975eW-t.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1285
1697
|
);
|
1286
1698
|
const ProtectedListConfiguration = lazy(
|
1287
|
-
() => import("./ListConfigurationPage-
|
1699
|
+
() => import("./ListConfigurationPage-TIM0JveM.mjs").then((mod) => ({
|
1288
1700
|
default: mod.ProtectedListConfiguration
|
1289
1701
|
}))
|
1290
1702
|
);
|
1291
1703
|
const ProtectedEditConfigurationPage = lazy(
|
1292
|
-
() => import("./EditConfigurationPage-
|
1704
|
+
() => import("./EditConfigurationPage-CyqSP6ru.mjs").then((mod) => ({
|
1293
1705
|
default: mod.ProtectedEditConfigurationPage
|
1294
1706
|
}))
|
1295
1707
|
);
|
1296
1708
|
const ProtectedComponentConfigurationPage = lazy(
|
1297
|
-
() => import("./ComponentConfigurationPage-
|
1709
|
+
() => import("./ComponentConfigurationPage-DKuCF_uX.mjs").then((mod) => ({
|
1298
1710
|
default: mod.ProtectedComponentConfigurationPage
|
1299
1711
|
}))
|
1300
1712
|
);
|
1301
1713
|
const NoPermissions = lazy(
|
1302
|
-
() => import("./NoPermissionsPage-
|
1714
|
+
() => import("./NoPermissionsPage-D4XYRoPf.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1303
1715
|
);
|
1304
1716
|
const NoContentType = lazy(
|
1305
|
-
() => import("./NoContentTypePage-
|
1717
|
+
() => import("./NoContentTypePage-SgNTVGjF.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1306
1718
|
);
|
1307
1719
|
const CollectionTypePages = () => {
|
1308
1720
|
const { collectionType } = useParams();
|
@@ -1314,7 +1726,7 @@ const CollectionTypePages = () => {
|
|
1314
1726
|
const CLONE_RELATIVE_PATH = ":collectionType/:slug/clone/:origin";
|
1315
1727
|
const CLONE_PATH = `/content-manager/${CLONE_RELATIVE_PATH}`;
|
1316
1728
|
const LIST_RELATIVE_PATH = ":collectionType/:slug";
|
1317
|
-
const LIST_PATH = `/content-manager
|
1729
|
+
const LIST_PATH = `/content-manager/collection-types/:slug`;
|
1318
1730
|
const routes = [
|
1319
1731
|
{
|
1320
1732
|
path: LIST_RELATIVE_PATH,
|
@@ -1348,6 +1760,7 @@ const routes = [
|
|
1348
1760
|
path: "no-content-types",
|
1349
1761
|
Component: NoContentType
|
1350
1762
|
},
|
1763
|
+
...routes$2,
|
1351
1764
|
...routes$1
|
1352
1765
|
];
|
1353
1766
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1416,12 +1829,14 @@ const DocumentActionButton = (action) => {
|
|
1416
1829
|
/* @__PURE__ */ jsx(
|
1417
1830
|
Button,
|
1418
1831
|
{
|
1419
|
-
flex:
|
1832
|
+
flex: "auto",
|
1420
1833
|
startIcon: action.icon,
|
1421
1834
|
disabled: action.disabled,
|
1422
1835
|
onClick: handleClick(action),
|
1423
1836
|
justifyContent: "center",
|
1424
1837
|
variant: action.variant || "default",
|
1838
|
+
paddingTop: "7px",
|
1839
|
+
paddingBottom: "7px",
|
1425
1840
|
children: action.label
|
1426
1841
|
}
|
1427
1842
|
),
|
@@ -1429,7 +1844,7 @@ const DocumentActionButton = (action) => {
|
|
1429
1844
|
DocumentActionConfirmDialog,
|
1430
1845
|
{
|
1431
1846
|
...action.dialog,
|
1432
|
-
variant: action.variant,
|
1847
|
+
variant: action.dialog?.variant ?? action.variant,
|
1433
1848
|
isOpen: dialogId === action.id,
|
1434
1849
|
onClose: handleClose
|
1435
1850
|
}
|
@@ -1486,9 +1901,9 @@ const DocumentActionsMenu = ({
|
|
1486
1901
|
disabled: isDisabled,
|
1487
1902
|
size: "S",
|
1488
1903
|
endIcon: null,
|
1489
|
-
paddingTop: "
|
1490
|
-
paddingLeft: "
|
1491
|
-
paddingRight: "
|
1904
|
+
paddingTop: "4px",
|
1905
|
+
paddingLeft: "7px",
|
1906
|
+
paddingRight: "7px",
|
1492
1907
|
variant,
|
1493
1908
|
children: [
|
1494
1909
|
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
@@ -1499,7 +1914,7 @@ const DocumentActionsMenu = ({
|
|
1499
1914
|
]
|
1500
1915
|
}
|
1501
1916
|
),
|
1502
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1917
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1503
1918
|
actions2.map((action) => {
|
1504
1919
|
return /* @__PURE__ */ jsx(
|
1505
1920
|
Menu.Item,
|
@@ -1507,28 +1922,25 @@ const DocumentActionsMenu = ({
|
|
1507
1922
|
disabled: action.disabled,
|
1508
1923
|
onSelect: handleClick(action),
|
1509
1924
|
display: "block",
|
1510
|
-
children: /* @__PURE__ */
|
1511
|
-
|
1512
|
-
|
1513
|
-
action.
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
}
|
1530
|
-
)
|
1531
|
-
] })
|
1925
|
+
children: /* @__PURE__ */ jsx(Flex, { justifyContent: "space-between", gap: 4, children: /* @__PURE__ */ jsxs(
|
1926
|
+
Flex,
|
1927
|
+
{
|
1928
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1929
|
+
gap: 2,
|
1930
|
+
tag: "span",
|
1931
|
+
children: [
|
1932
|
+
/* @__PURE__ */ jsx(
|
1933
|
+
Flex,
|
1934
|
+
{
|
1935
|
+
tag: "span",
|
1936
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1937
|
+
children: action.icon
|
1938
|
+
}
|
1939
|
+
),
|
1940
|
+
action.label
|
1941
|
+
]
|
1942
|
+
}
|
1943
|
+
) })
|
1532
1944
|
},
|
1533
1945
|
action.id
|
1534
1946
|
);
|
@@ -1570,8 +1982,20 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1570
1982
|
return "primary600";
|
1571
1983
|
}
|
1572
1984
|
};
|
1573
|
-
const
|
1574
|
-
|
1985
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1986
|
+
switch (variant) {
|
1987
|
+
case "danger":
|
1988
|
+
return "danger600";
|
1989
|
+
case "secondary":
|
1990
|
+
return "neutral500";
|
1991
|
+
case "success":
|
1992
|
+
return "success600";
|
1993
|
+
default:
|
1994
|
+
return "primary600";
|
1995
|
+
}
|
1996
|
+
};
|
1997
|
+
const DocumentActionConfirmDialog = ({
|
1998
|
+
onClose,
|
1575
1999
|
onCancel,
|
1576
2000
|
onConfirm,
|
1577
2001
|
title,
|
@@ -1592,22 +2016,20 @@ const DocumentActionConfirmDialog = ({
|
|
1592
2016
|
}
|
1593
2017
|
onClose();
|
1594
2018
|
};
|
1595
|
-
return /* @__PURE__ */
|
1596
|
-
/* @__PURE__ */ jsx(
|
1597
|
-
/* @__PURE__ */ jsx(
|
1598
|
-
|
1599
|
-
{
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
)
|
1610
|
-
] });
|
2019
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2020
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2021
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
2022
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
2023
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
2024
|
+
id: "app.components.Button.cancel",
|
2025
|
+
defaultMessage: "Cancel"
|
2026
|
+
}) }) }),
|
2027
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
2028
|
+
id: "app.components.Button.confirm",
|
2029
|
+
defaultMessage: "Confirm"
|
2030
|
+
}) })
|
2031
|
+
] })
|
2032
|
+
] }) });
|
1611
2033
|
};
|
1612
2034
|
const DocumentActionModal = ({
|
1613
2035
|
isOpen,
|
@@ -1617,34 +2039,29 @@ const DocumentActionModal = ({
|
|
1617
2039
|
content: Content,
|
1618
2040
|
onModalClose
|
1619
2041
|
}) => {
|
1620
|
-
const id = React.useId();
|
1621
|
-
if (!isOpen) {
|
1622
|
-
return null;
|
1623
|
-
}
|
1624
2042
|
const handleClose = () => {
|
1625
2043
|
if (onClose) {
|
1626
2044
|
onClose();
|
1627
2045
|
}
|
1628
2046
|
onModalClose();
|
1629
2047
|
};
|
1630
|
-
return /* @__PURE__ */
|
1631
|
-
/* @__PURE__ */ jsx(
|
1632
|
-
|
1633
|
-
/* @__PURE__ */ jsx(
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
] });
|
2048
|
+
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
2049
|
+
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
2050
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
|
2051
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
2052
|
+
] }) });
|
2053
|
+
};
|
2054
|
+
const transformData = (data) => {
|
2055
|
+
if (Array.isArray(data)) {
|
2056
|
+
return data.map(transformData);
|
2057
|
+
}
|
2058
|
+
if (typeof data === "object" && data !== null) {
|
2059
|
+
if ("apiData" in data) {
|
2060
|
+
return data.apiData;
|
2061
|
+
}
|
2062
|
+
return mapValues(transformData)(data);
|
2063
|
+
}
|
2064
|
+
return data;
|
1648
2065
|
};
|
1649
2066
|
const PublishAction$1 = ({
|
1650
2067
|
activeTab,
|
@@ -1658,13 +2075,17 @@ const PublishAction$1 = ({
|
|
1658
2075
|
const navigate = useNavigate();
|
1659
2076
|
const { toggleNotification } = useNotification();
|
1660
2077
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2078
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
1661
2079
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
1662
2080
|
const { formatMessage } = useIntl();
|
1663
|
-
const { canPublish
|
1664
|
-
"PublishAction",
|
1665
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1666
|
-
);
|
2081
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1667
2082
|
const { publish } = useDocumentActions();
|
2083
|
+
const [
|
2084
|
+
countDraftRelations,
|
2085
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2086
|
+
] = useLazyGetDraftRelationCountQuery();
|
2087
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
2088
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1668
2089
|
const [{ query, rawQuery }] = useQueryParams();
|
1669
2090
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1670
2091
|
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1673,10 +2094,105 @@ const PublishAction$1 = ({
|
|
1673
2094
|
const validate = useForm("PublishAction", (state) => state.validate);
|
1674
2095
|
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1675
2096
|
const formValues = useForm("PublishAction", ({ values }) => values);
|
2097
|
+
React.useEffect(() => {
|
2098
|
+
if (isErrorDraftRelations) {
|
2099
|
+
toggleNotification({
|
2100
|
+
type: "danger",
|
2101
|
+
message: formatMessage({
|
2102
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2103
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2104
|
+
})
|
2105
|
+
});
|
2106
|
+
}
|
2107
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2108
|
+
React.useEffect(() => {
|
2109
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2110
|
+
const extractDraftRelations = (data) => {
|
2111
|
+
const relations = data.connect || [];
|
2112
|
+
relations.forEach((relation) => {
|
2113
|
+
if (relation.status === "draft") {
|
2114
|
+
localDraftRelations.add(relation.id);
|
2115
|
+
}
|
2116
|
+
});
|
2117
|
+
};
|
2118
|
+
const traverseAndExtract = (data) => {
|
2119
|
+
Object.entries(data).forEach(([key, value]) => {
|
2120
|
+
if (key === "connect" && Array.isArray(value)) {
|
2121
|
+
extractDraftRelations({ connect: value });
|
2122
|
+
} else if (typeof value === "object" && value !== null) {
|
2123
|
+
traverseAndExtract(value);
|
2124
|
+
}
|
2125
|
+
});
|
2126
|
+
};
|
2127
|
+
if (!documentId || modified) {
|
2128
|
+
traverseAndExtract(formValues);
|
2129
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2130
|
+
}
|
2131
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2132
|
+
React.useEffect(() => {
|
2133
|
+
if (!document || !document.documentId || isListView) {
|
2134
|
+
return;
|
2135
|
+
}
|
2136
|
+
const fetchDraftRelationsCount = async () => {
|
2137
|
+
const { data, error } = await countDraftRelations({
|
2138
|
+
collectionType,
|
2139
|
+
model,
|
2140
|
+
documentId,
|
2141
|
+
params
|
2142
|
+
});
|
2143
|
+
if (error) {
|
2144
|
+
throw error;
|
2145
|
+
}
|
2146
|
+
if (data) {
|
2147
|
+
setServerCountOfDraftRelations(data.data);
|
2148
|
+
}
|
2149
|
+
};
|
2150
|
+
fetchDraftRelationsCount();
|
2151
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
1676
2152
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1677
2153
|
if (!schema?.options?.draftAndPublish) {
|
1678
2154
|
return null;
|
1679
2155
|
}
|
2156
|
+
const performPublish = async () => {
|
2157
|
+
setSubmitting(true);
|
2158
|
+
try {
|
2159
|
+
const { errors } = await validate(true, {
|
2160
|
+
status: "published"
|
2161
|
+
});
|
2162
|
+
if (errors) {
|
2163
|
+
toggleNotification({
|
2164
|
+
type: "danger",
|
2165
|
+
message: formatMessage({
|
2166
|
+
id: "content-manager.validation.error",
|
2167
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2168
|
+
})
|
2169
|
+
});
|
2170
|
+
return;
|
2171
|
+
}
|
2172
|
+
const res = await publish(
|
2173
|
+
{
|
2174
|
+
collectionType,
|
2175
|
+
model,
|
2176
|
+
documentId,
|
2177
|
+
params
|
2178
|
+
},
|
2179
|
+
transformData(formValues)
|
2180
|
+
);
|
2181
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2182
|
+
navigate({
|
2183
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2184
|
+
search: rawQuery
|
2185
|
+
});
|
2186
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2187
|
+
setErrors(formatValidationErrors(res.error));
|
2188
|
+
}
|
2189
|
+
} finally {
|
2190
|
+
setSubmitting(false);
|
2191
|
+
}
|
2192
|
+
};
|
2193
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2194
|
+
const enableDraftRelationsCount = false;
|
2195
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1680
2196
|
return {
|
1681
2197
|
/**
|
1682
2198
|
* Disabled when:
|
@@ -1686,49 +2202,36 @@ const PublishAction$1 = ({
|
|
1686
2202
|
* - the document is already published & not modified
|
1687
2203
|
* - the document is being created & not modified
|
1688
2204
|
* - the user doesn't have the permission to publish
|
1689
|
-
* - the user doesn't have the permission to create a new document
|
1690
|
-
* - the user doesn't have the permission to update the document
|
1691
2205
|
*/
|
1692
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2206
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1693
2207
|
label: formatMessage({
|
1694
2208
|
id: "app.utils.publish",
|
1695
2209
|
defaultMessage: "Publish"
|
1696
2210
|
}),
|
1697
2211
|
onClick: async () => {
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
documentId,
|
1716
|
-
params
|
1717
|
-
},
|
1718
|
-
formValues
|
1719
|
-
);
|
1720
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1721
|
-
navigate({
|
1722
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1723
|
-
search: rawQuery
|
1724
|
-
});
|
1725
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1726
|
-
setErrors(formatValidationErrors(res.error));
|
2212
|
+
await performPublish();
|
2213
|
+
},
|
2214
|
+
dialog: hasDraftRelations ? {
|
2215
|
+
type: "dialog",
|
2216
|
+
variant: "danger",
|
2217
|
+
footer: null,
|
2218
|
+
title: formatMessage({
|
2219
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2220
|
+
defaultMessage: "Confirmation"
|
2221
|
+
}),
|
2222
|
+
content: formatMessage(
|
2223
|
+
{
|
2224
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2225
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2226
|
+
},
|
2227
|
+
{
|
2228
|
+
count: totalDraftRelations
|
1727
2229
|
}
|
1728
|
-
|
1729
|
-
|
2230
|
+
),
|
2231
|
+
onConfirm: async () => {
|
2232
|
+
await performPublish();
|
1730
2233
|
}
|
1731
|
-
}
|
2234
|
+
} : void 0
|
1732
2235
|
};
|
1733
2236
|
};
|
1734
2237
|
PublishAction$1.type = "publish";
|
@@ -1744,10 +2247,6 @@ const UpdateAction = ({
|
|
1744
2247
|
const cloneMatch = useMatch(CLONE_PATH);
|
1745
2248
|
const isCloning = cloneMatch !== null;
|
1746
2249
|
const { formatMessage } = useIntl();
|
1747
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1748
|
-
canCreate: canCreate2,
|
1749
|
-
canUpdate: canUpdate2
|
1750
|
-
}));
|
1751
2250
|
const { create, update, clone } = useDocumentActions();
|
1752
2251
|
const [{ query, rawQuery }] = useQueryParams();
|
1753
2252
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
@@ -1764,10 +2263,8 @@ const UpdateAction = ({
|
|
1764
2263
|
* - the form is submitting
|
1765
2264
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1766
2265
|
* - the active tab is the published tab
|
1767
|
-
* - the user doesn't have the permission to create a new document
|
1768
|
-
* - the user doesn't have the permission to update the document
|
1769
2266
|
*/
|
1770
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2267
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1771
2268
|
label: formatMessage({
|
1772
2269
|
id: "content-manager.containers.Edit.save",
|
1773
2270
|
defaultMessage: "Save"
|
@@ -1775,7 +2272,9 @@ const UpdateAction = ({
|
|
1775
2272
|
onClick: async () => {
|
1776
2273
|
setSubmitting(true);
|
1777
2274
|
try {
|
1778
|
-
const { errors } = await validate(
|
2275
|
+
const { errors } = await validate(true, {
|
2276
|
+
status: "draft"
|
2277
|
+
});
|
1779
2278
|
if (errors) {
|
1780
2279
|
toggleNotification({
|
1781
2280
|
type: "danger",
|
@@ -1793,13 +2292,16 @@ const UpdateAction = ({
|
|
1793
2292
|
documentId: cloneMatch.params.origin,
|
1794
2293
|
params
|
1795
2294
|
},
|
1796
|
-
document
|
2295
|
+
transformData(document)
|
1797
2296
|
);
|
1798
2297
|
if ("data" in res) {
|
1799
|
-
navigate(
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
2298
|
+
navigate(
|
2299
|
+
{
|
2300
|
+
pathname: `../${res.data.documentId}`,
|
2301
|
+
search: rawQuery
|
2302
|
+
},
|
2303
|
+
{ relative: "path" }
|
2304
|
+
);
|
1803
2305
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1804
2306
|
setErrors(formatValidationErrors(res.error));
|
1805
2307
|
}
|
@@ -1811,7 +2313,7 @@ const UpdateAction = ({
|
|
1811
2313
|
documentId,
|
1812
2314
|
params
|
1813
2315
|
},
|
1814
|
-
document
|
2316
|
+
transformData(document)
|
1815
2317
|
);
|
1816
2318
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1817
2319
|
setErrors(formatValidationErrors(res.error));
|
@@ -1824,13 +2326,16 @@ const UpdateAction = ({
|
|
1824
2326
|
model,
|
1825
2327
|
params
|
1826
2328
|
},
|
1827
|
-
document
|
2329
|
+
transformData(document)
|
1828
2330
|
);
|
1829
2331
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1830
|
-
navigate(
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
2332
|
+
navigate(
|
2333
|
+
{
|
2334
|
+
pathname: `../${res.data.documentId}`,
|
2335
|
+
search: rawQuery
|
2336
|
+
},
|
2337
|
+
{ replace: true, relative: "path" }
|
2338
|
+
);
|
1834
2339
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1835
2340
|
setErrors(formatValidationErrors(res.error));
|
1836
2341
|
}
|
@@ -1862,10 +2367,8 @@ const UnpublishAction$1 = ({
|
|
1862
2367
|
const { toggleNotification } = useNotification();
|
1863
2368
|
const [shouldKeepDraft, setShouldKeepDraft] = React.useState(true);
|
1864
2369
|
const isDocumentModified = document?.status === "modified";
|
1865
|
-
const handleChange = (
|
1866
|
-
|
1867
|
-
setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1868
|
-
}
|
2370
|
+
const handleChange = (value) => {
|
2371
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1869
2372
|
};
|
1870
2373
|
if (!schema?.options?.draftAndPublish) {
|
1871
2374
|
return null;
|
@@ -1876,7 +2379,7 @@ const UnpublishAction$1 = ({
|
|
1876
2379
|
id: "app.utils.unpublish",
|
1877
2380
|
defaultMessage: "Unpublish"
|
1878
2381
|
}),
|
1879
|
-
icon: /* @__PURE__ */ jsx(
|
2382
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1880
2383
|
onClick: async () => {
|
1881
2384
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1882
2385
|
if (!documentId) {
|
@@ -1915,40 +2418,24 @@ const UnpublishAction$1 = ({
|
|
1915
2418
|
}) })
|
1916
2419
|
] }),
|
1917
2420
|
/* @__PURE__ */ jsxs(
|
1918
|
-
|
2421
|
+
Radio.Group,
|
1919
2422
|
{
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
2423
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2424
|
+
name: "discard-options",
|
2425
|
+
"aria-label": formatMessage({
|
2426
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2427
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2428
|
+
}),
|
2429
|
+
onValueChange: handleChange,
|
1926
2430
|
children: [
|
1927
|
-
/* @__PURE__ */ jsx(
|
1928
|
-
|
1929
|
-
|
1930
|
-
|
1931
|
-
|
1932
|
-
|
1933
|
-
|
1934
|
-
|
1935
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
1936
|
-
defaultMessage: "Keep draft"
|
1937
|
-
})
|
1938
|
-
}
|
1939
|
-
),
|
1940
|
-
/* @__PURE__ */ jsx(
|
1941
|
-
Radio,
|
1942
|
-
{
|
1943
|
-
checked: !shouldKeepDraft,
|
1944
|
-
value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
|
1945
|
-
name: "discard-options",
|
1946
|
-
children: formatMessage({
|
1947
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
1948
|
-
defaultMessage: "Replace draft"
|
1949
|
-
})
|
1950
|
-
}
|
1951
|
-
)
|
2431
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2432
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2433
|
+
defaultMessage: "Keep draft"
|
2434
|
+
}) }),
|
2435
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2436
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2437
|
+
defaultMessage: "Replace draft"
|
2438
|
+
}) })
|
1952
2439
|
]
|
1953
2440
|
}
|
1954
2441
|
)
|
@@ -2004,7 +2491,7 @@ const DiscardAction = ({
|
|
2004
2491
|
id: "content-manager.actions.discard.label",
|
2005
2492
|
defaultMessage: "Discard changes"
|
2006
2493
|
}),
|
2007
|
-
icon: /* @__PURE__ */ jsx(
|
2494
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
2008
2495
|
position: ["panel", "table-row"],
|
2009
2496
|
variant: "danger",
|
2010
2497
|
dialog: {
|
@@ -2032,11 +2519,6 @@ const DiscardAction = ({
|
|
2032
2519
|
};
|
2033
2520
|
};
|
2034
2521
|
DiscardAction.type = "discard";
|
2035
|
-
const StyledCrossCircle = styled(CrossCircle)`
|
2036
|
-
path {
|
2037
|
-
fill: currentColor;
|
2038
|
-
}
|
2039
|
-
`;
|
2040
2522
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2041
2523
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2042
2524
|
const RelativeTime = React.forwardRef(
|
@@ -2049,7 +2531,7 @@ const RelativeTime = React.forwardRef(
|
|
2049
2531
|
});
|
2050
2532
|
const unit = intervals.find((intervalUnit) => {
|
2051
2533
|
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2052
|
-
});
|
2534
|
+
}) ?? "seconds";
|
2053
2535
|
const relativeTime = isPast(timestamp) ? -interval[unit] : interval[unit];
|
2054
2536
|
const customInterval = customIntervals.find(
|
2055
2537
|
(custom) => interval[custom.unit] < custom.threshold
|
@@ -2083,9 +2565,13 @@ const getDisplayName = ({
|
|
2083
2565
|
return email ?? "";
|
2084
2566
|
};
|
2085
2567
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2086
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2087
|
-
const statusVariant = status === "draft" ? "
|
2088
|
-
|
2568
|
+
const DocumentStatus = ({ status = "draft", size = "S", ...restProps }) => {
|
2569
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2570
|
+
const { formatMessage } = useIntl();
|
2571
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, size, variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2572
|
+
id: `content-manager.containers.List.${status}`,
|
2573
|
+
defaultMessage: capitalise(status)
|
2574
|
+
}) }) });
|
2089
2575
|
};
|
2090
2576
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2091
2577
|
const { formatMessage } = useIntl();
|
@@ -2094,23 +2580,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2094
2580
|
id: "content-manager.containers.edit.title.new",
|
2095
2581
|
defaultMessage: "Create an entry"
|
2096
2582
|
}) : documentTitle;
|
2097
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2583
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2098
2584
|
/* @__PURE__ */ jsx(BackButton, {}),
|
2099
|
-
/* @__PURE__ */ jsxs(
|
2100
|
-
|
2101
|
-
{
|
2102
|
-
|
2103
|
-
|
2104
|
-
paddingTop: 1,
|
2105
|
-
gap: "80px",
|
2106
|
-
alignItems: "flex-start",
|
2107
|
-
children: [
|
2108
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2109
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2110
|
-
]
|
2111
|
-
}
|
2112
|
-
),
|
2113
|
-
status ? /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2585
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2586
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2587
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2588
|
+
] }),
|
2589
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2114
2590
|
] });
|
2115
2591
|
};
|
2116
2592
|
const HeaderToolbar = () => {
|
@@ -2193,12 +2669,12 @@ const Information = ({ activeTab }) => {
|
|
2193
2669
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2194
2670
|
label: formatMessage({
|
2195
2671
|
id: "content-manager.containers.edit.information.last-published.label",
|
2196
|
-
defaultMessage: "
|
2672
|
+
defaultMessage: "Published"
|
2197
2673
|
}),
|
2198
2674
|
value: formatMessage(
|
2199
2675
|
{
|
2200
2676
|
id: "content-manager.containers.edit.information.last-published.value",
|
2201
|
-
defaultMessage: `
|
2677
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2202
2678
|
},
|
2203
2679
|
{
|
2204
2680
|
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2211,12 +2687,12 @@ const Information = ({ activeTab }) => {
|
|
2211
2687
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2212
2688
|
label: formatMessage({
|
2213
2689
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2214
|
-
defaultMessage: "
|
2690
|
+
defaultMessage: "Updated"
|
2215
2691
|
}),
|
2216
2692
|
value: formatMessage(
|
2217
2693
|
{
|
2218
2694
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2219
|
-
defaultMessage: `
|
2695
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2220
2696
|
},
|
2221
2697
|
{
|
2222
2698
|
time: /* @__PURE__ */ jsx(
|
@@ -2234,12 +2710,12 @@ const Information = ({ activeTab }) => {
|
|
2234
2710
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2235
2711
|
label: formatMessage({
|
2236
2712
|
id: "content-manager.containers.edit.information.document.label",
|
2237
|
-
defaultMessage: "
|
2713
|
+
defaultMessage: "Created"
|
2238
2714
|
}),
|
2239
2715
|
value: formatMessage(
|
2240
2716
|
{
|
2241
2717
|
id: "content-manager.containers.edit.information.document.value",
|
2242
|
-
defaultMessage: `
|
2718
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2243
2719
|
},
|
2244
2720
|
{
|
2245
2721
|
time: /* @__PURE__ */ jsx(
|
@@ -2277,25 +2753,77 @@ const Information = ({ activeTab }) => {
|
|
2277
2753
|
);
|
2278
2754
|
};
|
2279
2755
|
const HeaderActions = ({ actions: actions2 }) => {
|
2280
|
-
|
2281
|
-
|
2756
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2757
|
+
const handleClick = (action) => async (e) => {
|
2758
|
+
if (!("options" in action)) {
|
2759
|
+
const { onClick = () => false, dialog, id } = action;
|
2760
|
+
const muteDialog = await onClick(e);
|
2761
|
+
if (dialog && !muteDialog) {
|
2762
|
+
e.preventDefault();
|
2763
|
+
setDialogId(id);
|
2764
|
+
}
|
2765
|
+
}
|
2766
|
+
};
|
2767
|
+
const handleClose = () => {
|
2768
|
+
setDialogId(null);
|
2769
|
+
};
|
2770
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2771
|
+
if (action.options) {
|
2282
2772
|
return /* @__PURE__ */ jsx(
|
2283
2773
|
SingleSelect,
|
2284
2774
|
{
|
2285
2775
|
size: "S",
|
2286
|
-
disabled: action.disabled,
|
2287
|
-
"aria-label": action.label,
|
2288
2776
|
onChange: action.onSelect,
|
2289
|
-
|
2777
|
+
"aria-label": action.label,
|
2778
|
+
...action,
|
2290
2779
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2291
2780
|
},
|
2292
2781
|
action.id
|
2293
2782
|
);
|
2294
2783
|
} else {
|
2295
|
-
|
2784
|
+
if (action.type === "icon") {
|
2785
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2786
|
+
/* @__PURE__ */ jsx(
|
2787
|
+
IconButton,
|
2788
|
+
{
|
2789
|
+
disabled: action.disabled,
|
2790
|
+
label: action.label,
|
2791
|
+
size: "S",
|
2792
|
+
onClick: handleClick(action),
|
2793
|
+
children: action.icon
|
2794
|
+
}
|
2795
|
+
),
|
2796
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2797
|
+
HeaderActionDialog,
|
2798
|
+
{
|
2799
|
+
...action.dialog,
|
2800
|
+
isOpen: dialogId === action.id,
|
2801
|
+
onClose: handleClose
|
2802
|
+
}
|
2803
|
+
) : null
|
2804
|
+
] }, action.id);
|
2805
|
+
}
|
2296
2806
|
}
|
2297
2807
|
}) });
|
2298
2808
|
};
|
2809
|
+
const HeaderActionDialog = ({
|
2810
|
+
onClose,
|
2811
|
+
onCancel,
|
2812
|
+
title,
|
2813
|
+
content: Content,
|
2814
|
+
isOpen
|
2815
|
+
}) => {
|
2816
|
+
const handleClose = async () => {
|
2817
|
+
if (onCancel) {
|
2818
|
+
await onCancel();
|
2819
|
+
}
|
2820
|
+
onClose();
|
2821
|
+
};
|
2822
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2823
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2824
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2825
|
+
] }) });
|
2826
|
+
};
|
2299
2827
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2300
2828
|
const navigate = useNavigate();
|
2301
2829
|
const { formatMessage } = useIntl();
|
@@ -2336,12 +2864,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2336
2864
|
const { delete: deleteAction } = useDocumentActions();
|
2337
2865
|
const { toggleNotification } = useNotification();
|
2338
2866
|
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2867
|
+
const isLocalized = document?.locale != null;
|
2339
2868
|
return {
|
2340
2869
|
disabled: !canDelete || !document,
|
2341
|
-
label: formatMessage(
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2870
|
+
label: formatMessage(
|
2871
|
+
{
|
2872
|
+
id: "content-manager.actions.delete.label",
|
2873
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2874
|
+
},
|
2875
|
+
{ isLocalized }
|
2876
|
+
),
|
2345
2877
|
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2346
2878
|
dialog: {
|
2347
2879
|
type: "dialog",
|
@@ -2431,7 +2963,7 @@ const ActionsPanel = () => {
|
|
2431
2963
|
return {
|
2432
2964
|
title: formatMessage({
|
2433
2965
|
id: "content-manager.containers.edit.panels.default.title",
|
2434
|
-
defaultMessage: "
|
2966
|
+
defaultMessage: "Entry"
|
2435
2967
|
}),
|
2436
2968
|
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2437
2969
|
};
|
@@ -2466,334 +2998,32 @@ const ActionsPanelContent = () => {
|
|
2466
2998
|
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2467
2999
|
] });
|
2468
3000
|
};
|
2469
|
-
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2470
|
-
return /* @__PURE__ */ jsxs(
|
2471
|
-
Flex,
|
2472
|
-
{
|
2473
|
-
ref,
|
2474
|
-
tag: "aside",
|
2475
|
-
"aria-labelledby": "additional-information",
|
2476
|
-
background: "neutral0",
|
2477
|
-
borderColor: "neutral150",
|
2478
|
-
hasRadius: true,
|
2479
|
-
paddingBottom: 4,
|
2480
|
-
paddingLeft: 4,
|
2481
|
-
paddingRight: 4,
|
2482
|
-
paddingTop: 4,
|
2483
|
-
shadow: "tableShadow",
|
2484
|
-
gap: 3,
|
2485
|
-
direction: "column",
|
2486
|
-
justifyContent: "stretch",
|
2487
|
-
alignItems: "flex-start",
|
2488
|
-
children: [
|
2489
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2490
|
-
children
|
2491
|
-
]
|
2492
|
-
}
|
2493
|
-
);
|
2494
|
-
});
|
2495
|
-
const HOOKS = {
|
2496
|
-
/**
|
2497
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2498
|
-
* @constant
|
2499
|
-
* @type {string}
|
2500
|
-
*/
|
2501
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2502
|
-
/**
|
2503
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2504
|
-
* @constant
|
2505
|
-
* @type {string}
|
2506
|
-
*/
|
2507
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2508
|
-
/**
|
2509
|
-
* Hook that allows to mutate the CM's edit view layout
|
2510
|
-
* @constant
|
2511
|
-
* @type {string}
|
2512
|
-
*/
|
2513
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2514
|
-
/**
|
2515
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2516
|
-
* @constant
|
2517
|
-
* @type {string}
|
2518
|
-
*/
|
2519
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2520
|
-
};
|
2521
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2522
|
-
endpoints: (builder) => ({
|
2523
|
-
getContentTypeConfiguration: builder.query({
|
2524
|
-
query: (uid) => ({
|
2525
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2526
|
-
method: "GET"
|
2527
|
-
}),
|
2528
|
-
transformResponse: (response) => response.data,
|
2529
|
-
providesTags: (_result, _error, uid) => [
|
2530
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2531
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2532
|
-
]
|
2533
|
-
}),
|
2534
|
-
getAllContentTypeSettings: builder.query({
|
2535
|
-
query: () => "/content-manager/content-types-settings",
|
2536
|
-
transformResponse: (response) => response.data,
|
2537
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2538
|
-
}),
|
2539
|
-
updateContentTypeConfiguration: builder.mutation({
|
2540
|
-
query: ({ uid, ...body }) => ({
|
2541
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2542
|
-
method: "PUT",
|
2543
|
-
data: body
|
2544
|
-
}),
|
2545
|
-
transformResponse: (response) => response.data,
|
2546
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2547
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2548
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2549
|
-
// Is this necessary?
|
2550
|
-
{ type: "InitialData" }
|
2551
|
-
]
|
2552
|
-
})
|
2553
|
-
})
|
2554
|
-
});
|
2555
|
-
const {
|
2556
|
-
useGetContentTypeConfigurationQuery,
|
2557
|
-
useGetAllContentTypeSettingsQuery,
|
2558
|
-
useUpdateContentTypeConfigurationMutation
|
2559
|
-
} = contentTypesApi;
|
2560
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2561
|
-
const { type } = attribute;
|
2562
|
-
if (type === "relation") {
|
2563
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2564
|
-
}
|
2565
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2566
|
-
};
|
2567
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2568
|
-
if (!mainFieldName) {
|
2569
|
-
return void 0;
|
2570
|
-
}
|
2571
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2572
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2573
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2574
|
-
);
|
2575
|
-
return {
|
2576
|
-
name: mainFieldName,
|
2577
|
-
type: mainFieldType ?? "string"
|
2578
|
-
};
|
2579
|
-
};
|
2580
|
-
const DEFAULT_SETTINGS = {
|
2581
|
-
bulkable: false,
|
2582
|
-
filterable: false,
|
2583
|
-
searchable: false,
|
2584
|
-
pagination: false,
|
2585
|
-
defaultSortBy: "",
|
2586
|
-
defaultSortOrder: "asc",
|
2587
|
-
mainField: "id",
|
2588
|
-
pageSize: 10
|
2589
|
-
};
|
2590
|
-
const useDocumentLayout = (model) => {
|
2591
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2592
|
-
const [{ query }] = useQueryParams();
|
2593
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2594
|
-
const { toggleNotification } = useNotification();
|
2595
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2596
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2597
|
-
const {
|
2598
|
-
data,
|
2599
|
-
isLoading: isLoadingConfigs,
|
2600
|
-
error,
|
2601
|
-
isFetching: isFetchingConfigs
|
2602
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2603
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2604
|
-
React.useEffect(() => {
|
2605
|
-
if (error) {
|
2606
|
-
toggleNotification({
|
2607
|
-
type: "danger",
|
2608
|
-
message: formatAPIError(error)
|
2609
|
-
});
|
2610
|
-
}
|
2611
|
-
}, [error, formatAPIError, toggleNotification]);
|
2612
|
-
const editLayout = React.useMemo(
|
2613
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2614
|
-
layout: [],
|
2615
|
-
components: {},
|
2616
|
-
metadatas: {},
|
2617
|
-
options: {},
|
2618
|
-
settings: DEFAULT_SETTINGS
|
2619
|
-
},
|
2620
|
-
[data, isLoading, schemas, schema, components]
|
2621
|
-
);
|
2622
|
-
const listLayout = React.useMemo(() => {
|
2623
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2624
|
-
layout: [],
|
2625
|
-
metadatas: {},
|
2626
|
-
options: {},
|
2627
|
-
settings: DEFAULT_SETTINGS
|
2628
|
-
};
|
2629
|
-
}, [data, isLoading, schemas, schema, components]);
|
2630
|
-
const { layout: edit } = React.useMemo(
|
2631
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2632
|
-
layout: editLayout,
|
2633
|
-
query
|
2634
|
-
}),
|
2635
|
-
[editLayout, query, runHookWaterfall]
|
2636
|
-
);
|
2637
|
-
return {
|
2638
|
-
error,
|
2639
|
-
isLoading,
|
2640
|
-
edit,
|
2641
|
-
list: listLayout
|
2642
|
-
};
|
2643
|
-
};
|
2644
|
-
const useDocLayout = () => {
|
2645
|
-
const { model } = useDoc();
|
2646
|
-
return useDocumentLayout(model);
|
2647
|
-
};
|
2648
|
-
const formatEditLayout = (data, {
|
2649
|
-
schemas,
|
2650
|
-
schema,
|
2651
|
-
components
|
2652
|
-
}) => {
|
2653
|
-
let currentPanelIndex = 0;
|
2654
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2655
|
-
data.contentType.layouts.edit,
|
2656
|
-
schema?.attributes,
|
2657
|
-
data.contentType.metadatas,
|
2658
|
-
{ configurations: data.components, schemas: components },
|
2659
|
-
schemas
|
2660
|
-
).reduce((panels, row) => {
|
2661
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2662
|
-
panels.push([row]);
|
2663
|
-
currentPanelIndex += 2;
|
2664
|
-
} else {
|
2665
|
-
if (!panels[currentPanelIndex]) {
|
2666
|
-
panels.push([]);
|
2667
|
-
}
|
2668
|
-
panels[currentPanelIndex].push(row);
|
2669
|
-
}
|
2670
|
-
return panels;
|
2671
|
-
}, []);
|
2672
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2673
|
-
(acc, [uid, configuration]) => {
|
2674
|
-
acc[uid] = {
|
2675
|
-
layout: convertEditLayoutToFieldLayouts(
|
2676
|
-
configuration.layouts.edit,
|
2677
|
-
components[uid].attributes,
|
2678
|
-
configuration.metadatas
|
2679
|
-
),
|
2680
|
-
settings: {
|
2681
|
-
...configuration.settings,
|
2682
|
-
icon: components[uid].info.icon,
|
2683
|
-
displayName: components[uid].info.displayName
|
2684
|
-
}
|
2685
|
-
};
|
2686
|
-
return acc;
|
2687
|
-
},
|
2688
|
-
{}
|
2689
|
-
);
|
2690
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2691
|
-
(acc, [attribute, metadata]) => {
|
2692
|
-
return {
|
2693
|
-
...acc,
|
2694
|
-
[attribute]: metadata.edit
|
2695
|
-
};
|
2696
|
-
},
|
2697
|
-
{}
|
2698
|
-
);
|
2699
|
-
return {
|
2700
|
-
layout: panelledEditAttributes,
|
2701
|
-
components: componentEditAttributes,
|
2702
|
-
metadatas: editMetadatas,
|
2703
|
-
settings: {
|
2704
|
-
...data.contentType.settings,
|
2705
|
-
displayName: schema?.info.displayName
|
2706
|
-
},
|
2707
|
-
options: {
|
2708
|
-
...schema?.options,
|
2709
|
-
...schema?.pluginOptions,
|
2710
|
-
...data.contentType.options
|
2711
|
-
}
|
2712
|
-
};
|
2713
|
-
};
|
2714
|
-
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
2715
|
-
return rows.map(
|
2716
|
-
(row) => row.map((field) => {
|
2717
|
-
const attribute = attributes[field.name];
|
2718
|
-
if (!attribute) {
|
2719
|
-
return null;
|
2720
|
-
}
|
2721
|
-
const { edit: metadata } = metadatas[field.name];
|
2722
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2723
|
-
return {
|
2724
|
-
attribute,
|
2725
|
-
disabled: !metadata.editable,
|
2726
|
-
hint: metadata.description,
|
2727
|
-
label: metadata.label ?? "",
|
2728
|
-
name: field.name,
|
2729
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2730
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2731
|
-
schemas,
|
2732
|
-
components: components?.schemas ?? {}
|
2733
|
-
}),
|
2734
|
-
placeholder: metadata.placeholder ?? "",
|
2735
|
-
required: attribute.required ?? false,
|
2736
|
-
size: field.size,
|
2737
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
2738
|
-
visible: metadata.visible ?? true,
|
2739
|
-
type: attribute.type
|
2740
|
-
};
|
2741
|
-
}).filter((field) => field !== null)
|
2742
|
-
);
|
2743
|
-
};
|
2744
|
-
const formatListLayout = (data, {
|
2745
|
-
schemas,
|
2746
|
-
schema,
|
2747
|
-
components
|
2748
|
-
}) => {
|
2749
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2750
|
-
(acc, [attribute, metadata]) => {
|
2751
|
-
return {
|
2752
|
-
...acc,
|
2753
|
-
[attribute]: metadata.list
|
2754
|
-
};
|
2755
|
-
},
|
2756
|
-
{}
|
2757
|
-
);
|
2758
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2759
|
-
data.contentType.layouts.list,
|
2760
|
-
schema?.attributes,
|
2761
|
-
listMetadatas,
|
2762
|
-
{ configurations: data.components, schemas: components },
|
2763
|
-
schemas
|
2764
|
-
);
|
2765
|
-
return {
|
2766
|
-
layout: listAttributes,
|
2767
|
-
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
2768
|
-
metadatas: listMetadatas,
|
2769
|
-
options: {
|
2770
|
-
...schema?.options,
|
2771
|
-
...schema?.pluginOptions,
|
2772
|
-
...data.contentType.options
|
2773
|
-
}
|
2774
|
-
};
|
2775
|
-
};
|
2776
|
-
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
2777
|
-
return columns.map((name) => {
|
2778
|
-
const attribute = attributes[name];
|
2779
|
-
if (!attribute) {
|
2780
|
-
return null;
|
3001
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
3002
|
+
return /* @__PURE__ */ jsxs(
|
3003
|
+
Flex,
|
3004
|
+
{
|
3005
|
+
ref,
|
3006
|
+
tag: "aside",
|
3007
|
+
"aria-labelledby": "additional-information",
|
3008
|
+
background: "neutral0",
|
3009
|
+
borderColor: "neutral150",
|
3010
|
+
hasRadius: true,
|
3011
|
+
paddingBottom: 4,
|
3012
|
+
paddingLeft: 4,
|
3013
|
+
paddingRight: 4,
|
3014
|
+
paddingTop: 4,
|
3015
|
+
shadow: "tableShadow",
|
3016
|
+
gap: 3,
|
3017
|
+
direction: "column",
|
3018
|
+
justifyContent: "stretch",
|
3019
|
+
alignItems: "flex-start",
|
3020
|
+
children: [
|
3021
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3022
|
+
children
|
3023
|
+
]
|
2781
3024
|
}
|
2782
|
-
|
2783
|
-
|
2784
|
-
return {
|
2785
|
-
attribute,
|
2786
|
-
label: metadata.label ?? "",
|
2787
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2788
|
-
schemas,
|
2789
|
-
components: components?.schemas ?? {}
|
2790
|
-
}),
|
2791
|
-
name,
|
2792
|
-
searchable: metadata.searchable ?? true,
|
2793
|
-
sortable: metadata.sortable ?? true
|
2794
|
-
};
|
2795
|
-
}).filter((field) => field !== null);
|
2796
|
-
};
|
3025
|
+
);
|
3026
|
+
});
|
2797
3027
|
const ConfirmBulkActionDialog = ({
|
2798
3028
|
onToggleDialog,
|
2799
3029
|
isOpen = false,
|
@@ -2801,30 +3031,23 @@ const ConfirmBulkActionDialog = ({
|
|
2801
3031
|
endAction
|
2802
3032
|
}) => {
|
2803
3033
|
const { formatMessage } = useIntl();
|
2804
|
-
return /* @__PURE__ */ jsxs(
|
2805
|
-
Dialog,
|
2806
|
-
|
2807
|
-
|
2808
|
-
|
2809
|
-
|
2810
|
-
|
2811
|
-
|
2812
|
-
|
2813
|
-
|
2814
|
-
|
2815
|
-
|
2816
|
-
|
2817
|
-
|
2818
|
-
|
2819
|
-
|
2820
|
-
|
2821
|
-
}) }),
|
2822
|
-
endAction
|
2823
|
-
}
|
2824
|
-
)
|
2825
|
-
]
|
2826
|
-
}
|
2827
|
-
);
|
3034
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
3035
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
3036
|
+
id: "app.components.ConfirmDialog.title",
|
3037
|
+
defaultMessage: "Confirmation"
|
3038
|
+
}) }),
|
3039
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3040
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3041
|
+
dialogBody
|
3042
|
+
] }) }),
|
3043
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
3044
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
|
3045
|
+
id: "app.components.Button.cancel",
|
3046
|
+
defaultMessage: "Cancel"
|
3047
|
+
}) }) }),
|
3048
|
+
endAction
|
3049
|
+
] })
|
3050
|
+
] }) });
|
2828
3051
|
};
|
2829
3052
|
const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
2830
3053
|
const ConfirmDialogPublishAll = ({
|
@@ -2839,6 +3062,7 @@ const ConfirmDialogPublishAll = ({
|
|
2839
3062
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2840
3063
|
const { model, schema } = useDoc();
|
2841
3064
|
const [{ query }] = useQueryParams();
|
3065
|
+
const enableDraftRelationsCount = false;
|
2842
3066
|
const {
|
2843
3067
|
data: countDraftRelations = 0,
|
2844
3068
|
isLoading,
|
@@ -2850,7 +3074,7 @@ const ConfirmDialogPublishAll = ({
|
|
2850
3074
|
locale: query?.plugins?.i18n?.locale
|
2851
3075
|
},
|
2852
3076
|
{
|
2853
|
-
skip:
|
3077
|
+
skip: !enableDraftRelationsCount
|
2854
3078
|
}
|
2855
3079
|
);
|
2856
3080
|
React.useEffect(() => {
|
@@ -2929,7 +3153,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
|
2929
3153
|
)
|
2930
3154
|
);
|
2931
3155
|
} else {
|
2932
|
-
messages.push(
|
3156
|
+
messages.push(
|
3157
|
+
...formatErrorMessages(
|
3158
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3159
|
+
value,
|
3160
|
+
currentKey,
|
3161
|
+
formatMessage
|
3162
|
+
)
|
3163
|
+
);
|
2933
3164
|
}
|
2934
3165
|
} else {
|
2935
3166
|
messages.push(
|
@@ -3028,7 +3259,7 @@ const SelectedEntriesTableContent = ({
|
|
3028
3259
|
status: row.status
|
3029
3260
|
}
|
3030
3261
|
) }),
|
3031
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3262
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3032
3263
|
IconButton,
|
3033
3264
|
{
|
3034
3265
|
tag: Link,
|
@@ -3037,23 +3268,16 @@ const SelectedEntriesTableContent = ({
|
|
3037
3268
|
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3038
3269
|
},
|
3039
3270
|
state: { from: pathname },
|
3040
|
-
label: formatMessage(
|
3041
|
-
|
3042
|
-
|
3043
|
-
|
3044
|
-
{
|
3045
|
-
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3046
|
-
defaultMessage: "item line {number}"
|
3047
|
-
},
|
3048
|
-
{ number: index2 + 1 }
|
3049
|
-
)
|
3050
|
-
}
|
3051
|
-
),
|
3271
|
+
label: formatMessage({
|
3272
|
+
id: "content-manager.bulk-publish.edit",
|
3273
|
+
defaultMessage: "Edit"
|
3274
|
+
}),
|
3052
3275
|
target: "_blank",
|
3053
3276
|
marginLeft: "auto",
|
3054
|
-
|
3277
|
+
variant: "ghost",
|
3278
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3055
3279
|
}
|
3056
|
-
) })
|
3280
|
+
) }) })
|
3057
3281
|
] }, row.id)) })
|
3058
3282
|
] });
|
3059
3283
|
};
|
@@ -3090,7 +3314,13 @@ const SelectedEntriesModalContent = ({
|
|
3090
3314
|
);
|
3091
3315
|
const { rows, validationErrors } = React.useMemo(() => {
|
3092
3316
|
if (data.length > 0 && schema) {
|
3093
|
-
const validate = createYupSchema(
|
3317
|
+
const validate = createYupSchema(
|
3318
|
+
schema.attributes,
|
3319
|
+
components,
|
3320
|
+
// Since this is the "Publish" action, the validation
|
3321
|
+
// schema must enforce the rules for published entities
|
3322
|
+
{ status: "published" }
|
3323
|
+
);
|
3094
3324
|
const validationErrors2 = {};
|
3095
3325
|
const rows2 = data.map((entry) => {
|
3096
3326
|
try {
|
@@ -3166,7 +3396,7 @@ const SelectedEntriesModalContent = ({
|
|
3166
3396
|
);
|
3167
3397
|
};
|
3168
3398
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
3169
|
-
/* @__PURE__ */ jsxs(
|
3399
|
+
/* @__PURE__ */ jsxs(Modal.Body, { children: [
|
3170
3400
|
/* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
|
3171
3401
|
/* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsx(
|
3172
3402
|
SelectedEntriesTableContent,
|
@@ -3178,27 +3408,24 @@ const SelectedEntriesModalContent = ({
|
|
3178
3408
|
}
|
3179
3409
|
) })
|
3180
3410
|
] }),
|
3181
|
-
/* @__PURE__ */
|
3182
|
-
|
3183
|
-
|
3184
|
-
|
3185
|
-
|
3186
|
-
|
3187
|
-
}) }),
|
3188
|
-
|
3189
|
-
|
3190
|
-
|
3191
|
-
|
3192
|
-
|
3193
|
-
|
3194
|
-
|
3195
|
-
|
3196
|
-
|
3197
|
-
|
3198
|
-
|
3199
|
-
] })
|
3200
|
-
}
|
3201
|
-
),
|
3411
|
+
/* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3412
|
+
/* @__PURE__ */ jsx(Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
|
3413
|
+
id: "app.components.Button.cancel",
|
3414
|
+
defaultMessage: "Cancel"
|
3415
|
+
}) }),
|
3416
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3417
|
+
/* @__PURE__ */ jsx(Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
|
3418
|
+
/* @__PURE__ */ jsx(
|
3419
|
+
Button,
|
3420
|
+
{
|
3421
|
+
onClick: toggleDialog,
|
3422
|
+
disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
|
3423
|
+
loading: isSubmittingForm,
|
3424
|
+
children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
|
3425
|
+
}
|
3426
|
+
)
|
3427
|
+
] })
|
3428
|
+
] }),
|
3202
3429
|
/* @__PURE__ */ jsx(
|
3203
3430
|
ConfirmDialogPublishAll,
|
3204
3431
|
{
|
@@ -3263,143 +3490,10 @@ const BulkActionsRenderer = () => {
|
|
3263
3490
|
documents: selectedRows
|
3264
3491
|
},
|
3265
3492
|
descriptions: plugins["content-manager"].apis.getBulkActions(),
|
3266
|
-
children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsx(
|
3493
|
+
children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsx(DocumentActionButton, { ...action }, action.id))
|
3267
3494
|
}
|
3268
3495
|
) });
|
3269
3496
|
};
|
3270
|
-
const BulkActionAction = (action) => {
|
3271
|
-
const [dialogId, setDialogId] = React.useState(null);
|
3272
|
-
const { toggleNotification } = useNotification();
|
3273
|
-
const handleClick = (action2) => (e) => {
|
3274
|
-
const { onClick, dialog, id } = action2;
|
3275
|
-
if (onClick) {
|
3276
|
-
onClick(e);
|
3277
|
-
}
|
3278
|
-
if (dialog) {
|
3279
|
-
switch (dialog.type) {
|
3280
|
-
case "notification":
|
3281
|
-
toggleNotification({
|
3282
|
-
title: dialog.title,
|
3283
|
-
message: dialog.content,
|
3284
|
-
type: dialog.status,
|
3285
|
-
timeout: dialog.timeout,
|
3286
|
-
onClose: dialog.onClose
|
3287
|
-
});
|
3288
|
-
break;
|
3289
|
-
case "dialog":
|
3290
|
-
case "modal": {
|
3291
|
-
e.preventDefault();
|
3292
|
-
setDialogId(id);
|
3293
|
-
}
|
3294
|
-
}
|
3295
|
-
}
|
3296
|
-
};
|
3297
|
-
const handleClose = () => {
|
3298
|
-
setDialogId(null);
|
3299
|
-
if (action.dialog?.type === "modal" && action.dialog?.onClose) {
|
3300
|
-
action.dialog.onClose();
|
3301
|
-
}
|
3302
|
-
};
|
3303
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
3304
|
-
/* @__PURE__ */ jsx(
|
3305
|
-
Button,
|
3306
|
-
{
|
3307
|
-
disabled: action.disabled,
|
3308
|
-
startIcon: action.icon,
|
3309
|
-
variant: action.variant,
|
3310
|
-
onClick: handleClick(action),
|
3311
|
-
children: action.label
|
3312
|
-
}
|
3313
|
-
),
|
3314
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsx(
|
3315
|
-
BulkActionConfirmDialog,
|
3316
|
-
{
|
3317
|
-
...action.dialog,
|
3318
|
-
variant: action.variant,
|
3319
|
-
isOpen: dialogId === action.id,
|
3320
|
-
onClose: handleClose
|
3321
|
-
}
|
3322
|
-
) : null,
|
3323
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsx(
|
3324
|
-
BulkActionModal,
|
3325
|
-
{
|
3326
|
-
...action.dialog,
|
3327
|
-
onModalClose: handleClose,
|
3328
|
-
isOpen: dialogId === action.id
|
3329
|
-
}
|
3330
|
-
) : null
|
3331
|
-
] });
|
3332
|
-
};
|
3333
|
-
const BulkActionConfirmDialog = ({
|
3334
|
-
onClose,
|
3335
|
-
onCancel,
|
3336
|
-
onConfirm,
|
3337
|
-
title,
|
3338
|
-
content,
|
3339
|
-
confirmButton,
|
3340
|
-
isOpen,
|
3341
|
-
variant = "secondary"
|
3342
|
-
}) => {
|
3343
|
-
const { formatMessage } = useIntl();
|
3344
|
-
const handleClose = async () => {
|
3345
|
-
if (onCancel) {
|
3346
|
-
await onCancel();
|
3347
|
-
}
|
3348
|
-
onClose();
|
3349
|
-
};
|
3350
|
-
const handleConfirm = async () => {
|
3351
|
-
if (onConfirm) {
|
3352
|
-
await onConfirm();
|
3353
|
-
}
|
3354
|
-
onClose();
|
3355
|
-
};
|
3356
|
-
return /* @__PURE__ */ jsxs(Dialog, { isOpen, title, onClose: handleClose, children: [
|
3357
|
-
/* @__PURE__ */ jsx(DialogBody, { icon: /* @__PURE__ */ jsx(WarningCircle, {}), children: content }),
|
3358
|
-
/* @__PURE__ */ jsx(
|
3359
|
-
DialogFooter,
|
3360
|
-
{
|
3361
|
-
startAction: /* @__PURE__ */ jsx(Button, { onClick: handleClose, variant: "tertiary", children: formatMessage({
|
3362
|
-
id: "app.components.Button.cancel",
|
3363
|
-
defaultMessage: "Cancel"
|
3364
|
-
}) }),
|
3365
|
-
endAction: /* @__PURE__ */ jsx(
|
3366
|
-
Button,
|
3367
|
-
{
|
3368
|
-
onClick: handleConfirm,
|
3369
|
-
variant: variant === "danger-light" ? variant : "secondary",
|
3370
|
-
startIcon: variant === "danger-light" ? /* @__PURE__ */ jsx(Trash, {}) : /* @__PURE__ */ jsx(Check, {}),
|
3371
|
-
children: confirmButton ? confirmButton : formatMessage({
|
3372
|
-
id: "app.components.Button.confirm",
|
3373
|
-
defaultMessage: "Confirm"
|
3374
|
-
})
|
3375
|
-
}
|
3376
|
-
)
|
3377
|
-
}
|
3378
|
-
)
|
3379
|
-
] });
|
3380
|
-
};
|
3381
|
-
const BulkActionModal = ({
|
3382
|
-
isOpen,
|
3383
|
-
title,
|
3384
|
-
onClose,
|
3385
|
-
content: Content,
|
3386
|
-
onModalClose
|
3387
|
-
}) => {
|
3388
|
-
const id = React.useId();
|
3389
|
-
if (!isOpen) {
|
3390
|
-
return null;
|
3391
|
-
}
|
3392
|
-
const handleClose = () => {
|
3393
|
-
if (onClose) {
|
3394
|
-
onClose();
|
3395
|
-
}
|
3396
|
-
onModalClose();
|
3397
|
-
};
|
3398
|
-
return /* @__PURE__ */ jsxs(ModalLayout, { borderRadius: "4px", overflow: "hidden", onClose: handleClose, labelledBy: id, children: [
|
3399
|
-
/* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", textColor: "neutral800", tag: "h2", id, children: title }) }),
|
3400
|
-
/* @__PURE__ */ jsx(Content, { onClose: handleClose })
|
3401
|
-
] });
|
3402
|
-
};
|
3403
3497
|
const DeleteAction = ({ documents, model }) => {
|
3404
3498
|
const { formatMessage } = useIntl();
|
3405
3499
|
const { schema: contentType } = useDoc();
|
@@ -3432,6 +3526,7 @@ const DeleteAction = ({ documents, model }) => {
|
|
3432
3526
|
defaultMessage: "Confirmation"
|
3433
3527
|
}),
|
3434
3528
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3529
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3435
3530
|
/* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3436
3531
|
id: "popUpWarning.bodyMessage.contentType.delete.all",
|
3437
3532
|
defaultMessage: "Are you sure you want to delete these entries?"
|
@@ -3481,6 +3576,7 @@ const UnpublishAction = ({ documents, model }) => {
|
|
3481
3576
|
defaultMessage: "Confirmation"
|
3482
3577
|
}),
|
3483
3578
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3579
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3484
3580
|
/* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3485
3581
|
id: "popUpWarning.bodyMessage.contentType.unpublish.all",
|
3486
3582
|
defaultMessage: "Are you sure you want to unpublish these entries?"
|
@@ -3574,7 +3670,7 @@ const TableActions = ({ document }) => {
|
|
3574
3670
|
DescriptionComponentRenderer,
|
3575
3671
|
{
|
3576
3672
|
props,
|
3577
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3673
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3578
3674
|
children: (actions2) => {
|
3579
3675
|
const tableRowActions = actions2.filter((action) => {
|
3580
3676
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3685,7 +3781,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3685
3781
|
}),
|
3686
3782
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3687
3783
|
footer: ({ onClose }) => {
|
3688
|
-
return /* @__PURE__ */ jsxs(
|
3784
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3689
3785
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3690
3786
|
id: "cancel",
|
3691
3787
|
defaultMessage: "Cancel"
|
@@ -3726,8 +3822,7 @@ class ContentManagerPlugin {
|
|
3726
3822
|
documentActions = [
|
3727
3823
|
...DEFAULT_ACTIONS,
|
3728
3824
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3729
|
-
...DEFAULT_HEADER_ACTIONS
|
3730
|
-
HistoryAction
|
3825
|
+
...DEFAULT_HEADER_ACTIONS
|
3731
3826
|
];
|
3732
3827
|
editViewSidePanels = [ActionsPanel];
|
3733
3828
|
headerActions = [];
|
@@ -3816,6 +3911,52 @@ const getPrintableType = (value) => {
|
|
3816
3911
|
}
|
3817
3912
|
return nativeType;
|
3818
3913
|
};
|
3914
|
+
const HistoryAction = ({ model, document }) => {
|
3915
|
+
const { formatMessage } = useIntl();
|
3916
|
+
const [{ query }] = useQueryParams();
|
3917
|
+
const navigate = useNavigate();
|
3918
|
+
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3919
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3920
|
+
return null;
|
3921
|
+
}
|
3922
|
+
return {
|
3923
|
+
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3924
|
+
label: formatMessage({
|
3925
|
+
id: "content-manager.history.document-action",
|
3926
|
+
defaultMessage: "Content History"
|
3927
|
+
}),
|
3928
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3929
|
+
disabled: (
|
3930
|
+
/**
|
3931
|
+
* The user is creating a new document.
|
3932
|
+
* It hasn't been saved yet, so there's no history to go to
|
3933
|
+
*/
|
3934
|
+
!document || /**
|
3935
|
+
* The document has been created but the current dimension has never been saved.
|
3936
|
+
* For example, the user is creating a new locale in an existing document,
|
3937
|
+
* so there's no history for the document in that locale
|
3938
|
+
*/
|
3939
|
+
!document.id || /**
|
3940
|
+
* History is only available for content types created by the user.
|
3941
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3942
|
+
* which start with `admin::` or `plugin::`
|
3943
|
+
*/
|
3944
|
+
!model.startsWith("api::")
|
3945
|
+
),
|
3946
|
+
position: "header"
|
3947
|
+
};
|
3948
|
+
};
|
3949
|
+
HistoryAction.type = "history";
|
3950
|
+
const historyAdmin = {
|
3951
|
+
bootstrap(app) {
|
3952
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3953
|
+
addDocumentAction((actions2) => {
|
3954
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3955
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3956
|
+
return actions2;
|
3957
|
+
});
|
3958
|
+
}
|
3959
|
+
};
|
3819
3960
|
const initialState = {
|
3820
3961
|
collectionTypeLinks: [],
|
3821
3962
|
components: [],
|
@@ -3852,6 +3993,70 @@ const { setInitialData } = actions;
|
|
3852
3993
|
const reducer = combineReducers({
|
3853
3994
|
app: reducer$1
|
3854
3995
|
});
|
3996
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
3997
|
+
endpoints: (builder) => ({
|
3998
|
+
getPreviewUrl: builder.query({
|
3999
|
+
query({ query, params }) {
|
4000
|
+
return {
|
4001
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4002
|
+
method: "GET",
|
4003
|
+
config: {
|
4004
|
+
params: query
|
4005
|
+
}
|
4006
|
+
};
|
4007
|
+
}
|
4008
|
+
})
|
4009
|
+
})
|
4010
|
+
});
|
4011
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4012
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4013
|
+
const { formatMessage } = useIntl();
|
4014
|
+
const { trackUsage } = useTracking();
|
4015
|
+
const [{ query }] = useQueryParams();
|
4016
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4017
|
+
params: {
|
4018
|
+
contentType: model
|
4019
|
+
},
|
4020
|
+
query: {
|
4021
|
+
documentId,
|
4022
|
+
locale: document?.locale,
|
4023
|
+
status: document?.status
|
4024
|
+
}
|
4025
|
+
});
|
4026
|
+
if (!data?.data?.url || error) {
|
4027
|
+
return null;
|
4028
|
+
}
|
4029
|
+
const handleClick = () => {
|
4030
|
+
trackUsage("willOpenPreview");
|
4031
|
+
};
|
4032
|
+
return {
|
4033
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4034
|
+
content: /* @__PURE__ */ jsx(Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsx(
|
4035
|
+
Button,
|
4036
|
+
{
|
4037
|
+
variant: "tertiary",
|
4038
|
+
tag: Link,
|
4039
|
+
to: { pathname: "preview", search: stringify(query, { encode: false }) },
|
4040
|
+
onClick: handleClick,
|
4041
|
+
flex: "auto",
|
4042
|
+
children: formatMessage({
|
4043
|
+
id: "content-manager.preview.panel.button",
|
4044
|
+
defaultMessage: "Open preview"
|
4045
|
+
})
|
4046
|
+
}
|
4047
|
+
) })
|
4048
|
+
};
|
4049
|
+
};
|
4050
|
+
const FEATURE_ID = "preview";
|
4051
|
+
const previewAdmin = {
|
4052
|
+
bootstrap(app) {
|
4053
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4054
|
+
return;
|
4055
|
+
}
|
4056
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4057
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4058
|
+
}
|
4059
|
+
};
|
3855
4060
|
const index = {
|
3856
4061
|
register(app) {
|
3857
4062
|
const cm = new ContentManagerPlugin();
|
@@ -3866,15 +4071,32 @@ const index = {
|
|
3866
4071
|
defaultMessage: "Content Manager"
|
3867
4072
|
},
|
3868
4073
|
permissions: [],
|
3869
|
-
Component: () => import("./layout-omucV6TV.mjs").then((mod) => ({ default: mod.Layout })),
|
3870
4074
|
position: 1
|
3871
4075
|
});
|
4076
|
+
app.router.addRoute({
|
4077
|
+
path: "content-manager/*",
|
4078
|
+
lazy: async () => {
|
4079
|
+
const { Layout } = await import("./layout-C8H4oKDo.mjs");
|
4080
|
+
return {
|
4081
|
+
Component: Layout
|
4082
|
+
};
|
4083
|
+
},
|
4084
|
+
children: routes
|
4085
|
+
});
|
3872
4086
|
app.registerPlugin(cm.config);
|
3873
4087
|
},
|
4088
|
+
bootstrap(app) {
|
4089
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4090
|
+
historyAdmin.bootstrap(app);
|
4091
|
+
}
|
4092
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4093
|
+
previewAdmin.bootstrap(app);
|
4094
|
+
}
|
4095
|
+
},
|
3874
4096
|
async registerTrads({ locales }) {
|
3875
4097
|
const importedTrads = await Promise.all(
|
3876
4098
|
locales.map((locale) => {
|
3877
|
-
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-
|
4099
|
+
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-69jRDM9j.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`).then(({ default: data }) => {
|
3878
4100
|
return {
|
3879
4101
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3880
4102
|
locale
|
@@ -3901,8 +4123,10 @@ export {
|
|
3901
4123
|
HOOKS as H,
|
3902
4124
|
InjectionZone as I,
|
3903
4125
|
useDocument as J,
|
3904
|
-
|
3905
|
-
|
4126
|
+
useGetPreviewUrlQuery as K,
|
4127
|
+
index as L,
|
4128
|
+
useContentManagerContext as M,
|
4129
|
+
useDocumentActions as N,
|
3906
4130
|
Panels as P,
|
3907
4131
|
RelativeTime as R,
|
3908
4132
|
SINGLE_TYPES as S,
|
@@ -3920,11 +4144,11 @@ export {
|
|
3920
4144
|
PERMISSIONS as k,
|
3921
4145
|
DocumentRBAC as l,
|
3922
4146
|
DOCUMENT_META_FIELDS as m,
|
3923
|
-
|
3924
|
-
|
3925
|
-
|
3926
|
-
|
3927
|
-
|
4147
|
+
CLONE_PATH as n,
|
4148
|
+
useDocLayout as o,
|
4149
|
+
useGetContentTypeConfigurationQuery as p,
|
4150
|
+
CREATOR_FIELDS as q,
|
4151
|
+
getMainField as r,
|
3928
4152
|
setInitialData as s,
|
3929
4153
|
getDisplayName as t,
|
3930
4154
|
useContentTypeSchema as u,
|
@@ -3934,4 +4158,4 @@ export {
|
|
3934
4158
|
capitalise as y,
|
3935
4159
|
useUpdateContentTypeConfigurationMutation as z
|
3936
4160
|
};
|
3937
|
-
//# sourceMappingURL=index-
|
4161
|
+
//# sourceMappingURL=index-Ta--2bRa.mjs.map
|