@strapi/content-manager 0.0.0-experimental.9df68962083938acba06546a7901c68a63266aec → 0.0.0-experimental.a13c58eec89ab119f0e381fb79c0252979e9c125
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-C-49MccQ.js → ComponentConfigurationPage-CB0JNNKL.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-C-49MccQ.js.map → ComponentConfigurationPage-CB0JNNKL.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs → ComponentConfigurationPage-CTCh51QS.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DmwmiFQy.mjs.map → ComponentConfigurationPage-CTCh51QS.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js → EditConfigurationPage-BxTVjxBG.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-DjFJw56M.js.map → EditConfigurationPage-BxTVjxBG.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs → EditConfigurationPage-CVyURlPG.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-JT3E7NZy.mjs.map → EditConfigurationPage-CVyURlPG.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-zT3fBr4Y.js → EditViewPage-Cg78RUyS.js} +62 -11
- package/dist/_chunks/EditViewPage-Cg78RUyS.js.map +1 -0
- package/dist/_chunks/{EditViewPage-CPj61RMh.mjs → EditViewPage-M1OkTFHV.mjs} +63 -12
- package/dist/_chunks/EditViewPage-M1OkTFHV.mjs.map +1 -0
- package/dist/_chunks/{Field-Boxf9Ajp.js → Field-BQoMs_At.js} +271 -154
- package/dist/_chunks/Field-BQoMs_At.js.map +1 -0
- package/dist/_chunks/{Field-dha5VnIQ.mjs → Field-D1UGGscZ.mjs} +269 -152
- package/dist/_chunks/Field-D1UGGscZ.mjs.map +1 -0
- package/dist/_chunks/{Form-y5g1SRsh.js → Form-2uPHazrg.js} +36 -17
- package/dist/_chunks/Form-2uPHazrg.js.map +1 -0
- package/dist/_chunks/{Form-DHrru2AV.mjs → Form-JOjqloMg.mjs} +36 -17
- package/dist/_chunks/Form-JOjqloMg.mjs.map +1 -0
- package/dist/_chunks/{History-Bru_KoeP.mjs → History-D6LWunSa.mjs} +77 -62
- package/dist/_chunks/History-D6LWunSa.mjs.map +1 -0
- package/dist/_chunks/{History-CqN6K7SX.js → History-DoIdauuE.js} +76 -61
- package/dist/_chunks/History-DoIdauuE.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-R_p-SbHZ.js → ListConfigurationPage-C1eYSCV7.js} +21 -9
- package/dist/_chunks/ListConfigurationPage-C1eYSCV7.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-D8wGABj0.mjs → ListConfigurationPage-C8J_y4eX.mjs} +21 -9
- package/dist/_chunks/ListConfigurationPage-C8J_y4eX.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-pEw_zug9.js → ListViewPage-Nd8_ZHjF.js} +86 -46
- package/dist/_chunks/ListViewPage-Nd8_ZHjF.js.map +1 -0
- package/dist/_chunks/{ListViewPage-SID6TRb9.mjs → ListViewPage-vkipJOxG.mjs} +84 -44
- package/dist/_chunks/ListViewPage-vkipJOxG.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs → NoContentTypePage-CAxkF2Vg.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CJ7UXwrQ.mjs.map → NoContentTypePage-CAxkF2Vg.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js → NoContentTypePage-CsI4DiJk.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-C5dcQojD.js.map → NoContentTypePage-CsI4DiJk.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js → NoPermissionsPage-D7c29n-i.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BtPrImPP.js.map → NoPermissionsPage-D7c29n-i.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs → NoPermissionsPage-DA5ACuoK.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-B7syEq5E.mjs.map → NoPermissionsPage-DA5ACuoK.mjs.map} +1 -1
- package/dist/_chunks/Preview-Bwo9ft4j.mjs +288 -0
- package/dist/_chunks/Preview-Bwo9ft4j.mjs.map +1 -0
- package/dist/_chunks/Preview-DLxVMS5f.js +307 -0
- package/dist/_chunks/Preview-DLxVMS5f.js.map +1 -0
- package/dist/_chunks/{Relations-B9Crnhnn.mjs → Relations-Bddj_dxS.mjs} +73 -37
- package/dist/_chunks/Relations-Bddj_dxS.mjs.map +1 -0
- package/dist/_chunks/{Relations-DjTQ5kGB.js → Relations-CdFEx0mp.js} +72 -36
- package/dist/_chunks/Relations-CdFEx0mp.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-CHOp_xJv.js} +27 -16
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-CHOp_xJv.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-D_BMf0hT.mjs} +27 -16
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-D_BMf0hT.mjs.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/{index-DVPWZkbS.js → index-CltLAahy.js} +1066 -658
- package/dist/_chunks/index-CltLAahy.js.map +1 -0
- package/dist/_chunks/{index-DJXJw9V5.mjs → index-DmNeuXH0.mjs} +1086 -679
- package/dist/_chunks/index-DmNeuXH0.mjs.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout-Bau7ZfLV.mjs → layout-D63qmUOu.mjs} +25 -12
- package/dist/_chunks/layout-D63qmUOu.mjs.map +1 -0
- package/dist/_chunks/{layout-Dm6fbiQj.js → layout-DslPJR5e.js} +24 -11
- package/dist/_chunks/layout-DslPJR5e.js.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-CKnpRgrN.js → relations-B2h_O2Xw.js} +6 -7
- package/dist/_chunks/relations-B2h_O2Xw.js.map +1 -0
- package/dist/_chunks/{relations-BH_kBSJ0.mjs → relations-X3M9aO-m.mjs} +6 -7
- package/dist/_chunks/relations-X3M9aO-m.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 +5 -4
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/constants.d.ts +1 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/pages/Preview.d.ts +11 -0
- package/dist/admin/src/preview/routes.d.ts +3 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/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 +548 -261
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +549 -262
- 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 +13 -13
- package/dist/_chunks/EditViewPage-CPj61RMh.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-zT3fBr4Y.js.map +0 -1
- package/dist/_chunks/Field-Boxf9Ajp.js.map +0 -1
- package/dist/_chunks/Field-dha5VnIQ.mjs.map +0 -1
- package/dist/_chunks/Form-DHrru2AV.mjs.map +0 -1
- package/dist/_chunks/Form-y5g1SRsh.js.map +0 -1
- package/dist/_chunks/History-Bru_KoeP.mjs.map +0 -1
- package/dist/_chunks/History-CqN6K7SX.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-D8wGABj0.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-R_p-SbHZ.js.map +0 -1
- package/dist/_chunks/ListViewPage-SID6TRb9.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-pEw_zug9.js.map +0 -1
- package/dist/_chunks/Relations-B9Crnhnn.mjs.map +0 -1
- package/dist/_chunks/Relations-DjTQ5kGB.js.map +0 -1
- package/dist/_chunks/index-DJXJw9V5.mjs.map +0 -1
- package/dist/_chunks/index-DVPWZkbS.js.map +0 -1
- package/dist/_chunks/layout-Bau7ZfLV.mjs.map +0 -1
- package/dist/_chunks/layout-Dm6fbiQj.js.map +0 -1
- package/dist/_chunks/relations-BH_kBSJ0.mjs.map +0 -1
- package/dist/_chunks/relations-CKnpRgrN.js.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
@@ -1,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 { Button, Menu, VisuallyHidden, Flex,
|
10
|
-
import
|
6
|
+
import { Button, Menu, VisuallyHidden, Flex, Typography, Dialog, Modal, 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,7 +167,8 @@ 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({
|
@@ -208,7 +182,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
208
182
|
params: query
|
209
183
|
}
|
210
184
|
}),
|
211
|
-
invalidatesTags: (_result,
|
185
|
+
invalidatesTags: (_result, error, { model }) => {
|
186
|
+
if (error) {
|
187
|
+
return [];
|
188
|
+
}
|
189
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
190
|
+
}
|
212
191
|
}),
|
213
192
|
cloneDocument: builder.mutation({
|
214
193
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -219,7 +198,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
219
198
|
params
|
220
199
|
}
|
221
200
|
}),
|
222
|
-
invalidatesTags: (_result, _error, { model }) => [
|
201
|
+
invalidatesTags: (_result, _error, { model }) => [
|
202
|
+
{ type: "Document", id: `${model}_LIST` },
|
203
|
+
{ type: "UidAvailability", id: model }
|
204
|
+
]
|
223
205
|
}),
|
224
206
|
/**
|
225
207
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -236,7 +218,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
236
218
|
}),
|
237
219
|
invalidatesTags: (result, _error, { model }) => [
|
238
220
|
{ type: "Document", id: `${model}_LIST` },
|
239
|
-
"Relations"
|
221
|
+
"Relations",
|
222
|
+
{ type: "UidAvailability", id: model }
|
240
223
|
]
|
241
224
|
}),
|
242
225
|
deleteDocument: builder.mutation({
|
@@ -277,7 +260,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
277
260
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
278
261
|
},
|
279
262
|
{ type: "Document", id: `${model}_LIST` },
|
280
|
-
"Relations"
|
263
|
+
"Relations",
|
264
|
+
{ type: "UidAvailability", id: model }
|
281
265
|
];
|
282
266
|
}
|
283
267
|
}),
|
@@ -295,6 +279,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
295
279
|
}),
|
296
280
|
providesTags: (result, _error, arg) => {
|
297
281
|
return [
|
282
|
+
{ type: "Document", id: `ALL_LIST` },
|
298
283
|
{ type: "Document", id: `${arg.model}_LIST` },
|
299
284
|
...result?.results.map(({ documentId }) => ({
|
300
285
|
type: "Document",
|
@@ -333,6 +318,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
333
318
|
{
|
334
319
|
type: "Document",
|
335
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`
|
336
326
|
}
|
337
327
|
];
|
338
328
|
}
|
@@ -396,8 +386,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
396
386
|
type: "Document",
|
397
387
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
398
388
|
},
|
399
|
-
"Relations"
|
389
|
+
"Relations",
|
390
|
+
{ type: "UidAvailability", id: model }
|
400
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
|
+
}
|
401
404
|
}
|
402
405
|
}),
|
403
406
|
unpublishDocument: builder.mutation({
|
@@ -467,20 +470,39 @@ const buildValidParams = (query) => {
|
|
467
470
|
const isBaseQueryError = (error) => {
|
468
471
|
return error.name !== void 0;
|
469
472
|
};
|
470
|
-
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 }) => {
|
471
492
|
const createModelSchema = (attributes2) => yup.object().shape(
|
472
493
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
473
494
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
474
495
|
return acc;
|
475
496
|
}
|
476
497
|
const validations = [
|
498
|
+
addNullableValidation,
|
477
499
|
addRequiredValidation,
|
478
500
|
addMinLengthValidation,
|
479
501
|
addMaxLengthValidation,
|
480
502
|
addMinValidation,
|
481
503
|
addMaxValidation,
|
482
504
|
addRegexValidation
|
483
|
-
].map((fn) => fn(attribute));
|
505
|
+
].map((fn) => fn(attribute, options));
|
484
506
|
const transformSchema = pipe(...validations);
|
485
507
|
switch (attribute.type) {
|
486
508
|
case "component": {
|
@@ -490,12 +512,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
490
512
|
...acc,
|
491
513
|
[name]: transformSchema(
|
492
514
|
yup.array().of(createModelSchema(attributes3).nullable(false))
|
493
|
-
)
|
515
|
+
).test(arrayValidator(attribute, options))
|
494
516
|
};
|
495
517
|
} else {
|
496
518
|
return {
|
497
519
|
...acc,
|
498
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
520
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
499
521
|
};
|
500
522
|
}
|
501
523
|
}
|
@@ -517,7 +539,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
517
539
|
}
|
518
540
|
)
|
519
541
|
)
|
520
|
-
)
|
542
|
+
).test(arrayValidator(attribute, options))
|
521
543
|
};
|
522
544
|
case "relation":
|
523
545
|
return {
|
@@ -529,7 +551,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
529
551
|
} else if (Array.isArray(value)) {
|
530
552
|
return yup.array().of(
|
531
553
|
yup.object().shape({
|
532
|
-
id: yup.
|
554
|
+
id: yup.number().required()
|
533
555
|
})
|
534
556
|
);
|
535
557
|
} else if (typeof value === "object") {
|
@@ -581,6 +603,14 @@ const createAttributeSchema = (attribute) => {
|
|
581
603
|
if (!value || typeof value === "string" && value.length === 0) {
|
582
604
|
return true;
|
583
605
|
}
|
606
|
+
if (typeof value === "object") {
|
607
|
+
try {
|
608
|
+
JSON.stringify(value);
|
609
|
+
return true;
|
610
|
+
} catch (err) {
|
611
|
+
return false;
|
612
|
+
}
|
613
|
+
}
|
584
614
|
try {
|
585
615
|
JSON.parse(value);
|
586
616
|
return true;
|
@@ -599,13 +629,7 @@ const createAttributeSchema = (attribute) => {
|
|
599
629
|
return yup.mixed();
|
600
630
|
}
|
601
631
|
};
|
602
|
-
const
|
603
|
-
if (attribute.required) {
|
604
|
-
return schema.required({
|
605
|
-
id: translatedErrors.required.id,
|
606
|
-
defaultMessage: "This field is required."
|
607
|
-
});
|
608
|
-
}
|
632
|
+
const nullableSchema = (schema) => {
|
609
633
|
return schema?.nullable ? schema.nullable() : (
|
610
634
|
// In some cases '.nullable' will not be available on the schema.
|
611
635
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -613,7 +637,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
613
637
|
schema
|
614
638
|
);
|
615
639
|
};
|
616
|
-
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
|
+
}
|
617
656
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
618
657
|
return schema.min(attribute.minLength, {
|
619
658
|
...translatedErrors.minLength,
|
@@ -635,10 +674,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
635
674
|
}
|
636
675
|
return schema;
|
637
676
|
};
|
638
|
-
const addMinValidation = (attribute) => (schema) => {
|
639
|
-
if ("
|
677
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
678
|
+
if (options.status === "draft") {
|
679
|
+
return schema;
|
680
|
+
}
|
681
|
+
if ("min" in attribute && "min" in schema) {
|
640
682
|
const min = toInteger(attribute.min);
|
641
|
-
if (
|
683
|
+
if (min) {
|
642
684
|
return schema.min(min, {
|
643
685
|
...translatedErrors.min,
|
644
686
|
values: {
|
@@ -756,16 +798,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
756
798
|
}, {});
|
757
799
|
return componentsByKey;
|
758
800
|
};
|
759
|
-
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);
|
760
900
|
const { toggleNotification } = useNotification();
|
761
901
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
902
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
762
903
|
const {
|
763
|
-
|
764
|
-
isLoading:
|
765
|
-
|
766
|
-
|
767
|
-
} =
|
768
|
-
const
|
904
|
+
data,
|
905
|
+
isLoading: isLoadingConfigs,
|
906
|
+
error,
|
907
|
+
isFetching: isFetchingConfigs
|
908
|
+
} = useGetContentTypeConfigurationQuery(model);
|
909
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
769
910
|
React.useEffect(() => {
|
770
911
|
if (error) {
|
771
912
|
toggleNotification({
|
@@ -773,68 +914,322 @@ const useDocument = (args, opts) => {
|
|
773
914
|
message: formatAPIError(error)
|
774
915
|
});
|
775
916
|
}
|
776
|
-
}, [
|
777
|
-
const
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
(document) => {
|
785
|
-
if (!validationSchema) {
|
786
|
-
throw new Error(
|
787
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
788
|
-
);
|
789
|
-
}
|
790
|
-
try {
|
791
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
792
|
-
return null;
|
793
|
-
} catch (error2) {
|
794
|
-
if (error2 instanceof ValidationError) {
|
795
|
-
return getYupValidationErrors(error2);
|
796
|
-
}
|
797
|
-
throw error2;
|
798
|
-
}
|
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
|
799
925
|
},
|
800
|
-
[
|
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]
|
801
942
|
);
|
802
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
803
943
|
return {
|
804
|
-
|
805
|
-
document: data?.data,
|
806
|
-
meta: data?.meta,
|
944
|
+
error,
|
807
945
|
isLoading,
|
808
|
-
|
809
|
-
|
946
|
+
edit,
|
947
|
+
list: listLayout
|
810
948
|
};
|
811
949
|
};
|
812
|
-
const
|
813
|
-
const {
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
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;
|
822
1186
|
return {
|
823
1187
|
collectionType,
|
824
1188
|
model: slug,
|
825
|
-
id:
|
826
|
-
...
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
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
|
832
1230
|
};
|
833
1231
|
};
|
834
1232
|
const prefixPluginTranslations = (trad, pluginId) => {
|
835
|
-
if (!pluginId) {
|
836
|
-
throw new TypeError("pluginId can't be empty");
|
837
|
-
}
|
838
1233
|
return Object.keys(trad).reduce((acc, current) => {
|
839
1234
|
acc[`${pluginId}.${current}`] = trad[current];
|
840
1235
|
return acc;
|
@@ -850,6 +1245,8 @@ const useDocumentActions = () => {
|
|
850
1245
|
const { formatMessage } = useIntl();
|
851
1246
|
const { trackUsage } = useTracking();
|
852
1247
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1248
|
+
const navigate = useNavigate();
|
1249
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
853
1250
|
const [deleteDocument] = useDeleteDocumentMutation();
|
854
1251
|
const _delete = React.useCallback(
|
855
1252
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1164,6 +1561,7 @@ const useDocumentActions = () => {
|
|
1164
1561
|
defaultMessage: "Saved document"
|
1165
1562
|
})
|
1166
1563
|
});
|
1564
|
+
setCurrentStep("contentManager.success");
|
1167
1565
|
return res.data;
|
1168
1566
|
} catch (err) {
|
1169
1567
|
toggleNotification({
|
@@ -1185,7 +1583,6 @@ const useDocumentActions = () => {
|
|
1185
1583
|
sourceId
|
1186
1584
|
});
|
1187
1585
|
if ("error" in res) {
|
1188
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1189
1586
|
return { error: res.error };
|
1190
1587
|
}
|
1191
1588
|
toggleNotification({
|
@@ -1204,7 +1601,7 @@ const useDocumentActions = () => {
|
|
1204
1601
|
throw err;
|
1205
1602
|
}
|
1206
1603
|
},
|
1207
|
-
[autoCloneDocument,
|
1604
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1208
1605
|
);
|
1209
1606
|
const [cloneDocument] = useCloneDocumentMutation();
|
1210
1607
|
const clone = React.useCallback(
|
@@ -1230,6 +1627,7 @@ const useDocumentActions = () => {
|
|
1230
1627
|
defaultMessage: "Cloned document"
|
1231
1628
|
})
|
1232
1629
|
});
|
1630
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1233
1631
|
return res.data;
|
1234
1632
|
} catch (err) {
|
1235
1633
|
toggleNotification({
|
@@ -1240,7 +1638,7 @@ const useDocumentActions = () => {
|
|
1240
1638
|
throw err;
|
1241
1639
|
}
|
1242
1640
|
},
|
1243
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1641
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1244
1642
|
);
|
1245
1643
|
const [getDoc] = useLazyGetDocumentQuery();
|
1246
1644
|
const getDocument = React.useCallback(
|
@@ -1265,10 +1663,10 @@ const useDocumentActions = () => {
|
|
1265
1663
|
update
|
1266
1664
|
};
|
1267
1665
|
};
|
1268
|
-
const ProtectedHistoryPage = lazy(
|
1269
|
-
() => import("./History-
|
1666
|
+
const ProtectedHistoryPage = React.lazy(
|
1667
|
+
() => import("./History-D6LWunSa.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1270
1668
|
);
|
1271
|
-
const routes$
|
1669
|
+
const routes$2 = [
|
1272
1670
|
{
|
1273
1671
|
path: ":collectionType/:slug/:id/history",
|
1274
1672
|
Component: ProtectedHistoryPage
|
@@ -1278,32 +1676,45 @@ const routes$1 = [
|
|
1278
1676
|
Component: ProtectedHistoryPage
|
1279
1677
|
}
|
1280
1678
|
];
|
1679
|
+
const ProtectedPreviewPage = React.lazy(
|
1680
|
+
() => import("./Preview-Bwo9ft4j.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
|
+
];
|
1281
1692
|
const ProtectedEditViewPage = lazy(
|
1282
|
-
() => import("./EditViewPage-
|
1693
|
+
() => import("./EditViewPage-M1OkTFHV.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1283
1694
|
);
|
1284
1695
|
const ProtectedListViewPage = lazy(
|
1285
|
-
() => import("./ListViewPage-
|
1696
|
+
() => import("./ListViewPage-vkipJOxG.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1286
1697
|
);
|
1287
1698
|
const ProtectedListConfiguration = lazy(
|
1288
|
-
() => import("./ListConfigurationPage-
|
1699
|
+
() => import("./ListConfigurationPage-C8J_y4eX.mjs").then((mod) => ({
|
1289
1700
|
default: mod.ProtectedListConfiguration
|
1290
1701
|
}))
|
1291
1702
|
);
|
1292
1703
|
const ProtectedEditConfigurationPage = lazy(
|
1293
|
-
() => import("./EditConfigurationPage-
|
1704
|
+
() => import("./EditConfigurationPage-CVyURlPG.mjs").then((mod) => ({
|
1294
1705
|
default: mod.ProtectedEditConfigurationPage
|
1295
1706
|
}))
|
1296
1707
|
);
|
1297
1708
|
const ProtectedComponentConfigurationPage = lazy(
|
1298
|
-
() => import("./ComponentConfigurationPage-
|
1709
|
+
() => import("./ComponentConfigurationPage-CTCh51QS.mjs").then((mod) => ({
|
1299
1710
|
default: mod.ProtectedComponentConfigurationPage
|
1300
1711
|
}))
|
1301
1712
|
);
|
1302
1713
|
const NoPermissions = lazy(
|
1303
|
-
() => import("./NoPermissionsPage-
|
1714
|
+
() => import("./NoPermissionsPage-DA5ACuoK.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1304
1715
|
);
|
1305
1716
|
const NoContentType = lazy(
|
1306
|
-
() => import("./NoContentTypePage-
|
1717
|
+
() => import("./NoContentTypePage-CAxkF2Vg.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1307
1718
|
);
|
1308
1719
|
const CollectionTypePages = () => {
|
1309
1720
|
const { collectionType } = useParams();
|
@@ -1349,6 +1760,7 @@ const routes = [
|
|
1349
1760
|
path: "no-content-types",
|
1350
1761
|
Component: NoContentType
|
1351
1762
|
},
|
1763
|
+
...routes$2,
|
1352
1764
|
...routes$1
|
1353
1765
|
];
|
1354
1766
|
const DocumentActions = ({ actions: actions2 }) => {
|
@@ -1417,12 +1829,14 @@ const DocumentActionButton = (action) => {
|
|
1417
1829
|
/* @__PURE__ */ jsx(
|
1418
1830
|
Button,
|
1419
1831
|
{
|
1420
|
-
flex:
|
1832
|
+
flex: "auto",
|
1421
1833
|
startIcon: action.icon,
|
1422
1834
|
disabled: action.disabled,
|
1423
1835
|
onClick: handleClick(action),
|
1424
1836
|
justifyContent: "center",
|
1425
1837
|
variant: action.variant || "default",
|
1838
|
+
paddingTop: "7px",
|
1839
|
+
paddingBottom: "7px",
|
1426
1840
|
children: action.label
|
1427
1841
|
}
|
1428
1842
|
),
|
@@ -1430,7 +1844,7 @@ const DocumentActionButton = (action) => {
|
|
1430
1844
|
DocumentActionConfirmDialog,
|
1431
1845
|
{
|
1432
1846
|
...action.dialog,
|
1433
|
-
variant: action.variant,
|
1847
|
+
variant: action.dialog?.variant ?? action.variant,
|
1434
1848
|
isOpen: dialogId === action.id,
|
1435
1849
|
onClose: handleClose
|
1436
1850
|
}
|
@@ -1487,9 +1901,9 @@ const DocumentActionsMenu = ({
|
|
1487
1901
|
disabled: isDisabled,
|
1488
1902
|
size: "S",
|
1489
1903
|
endIcon: null,
|
1490
|
-
paddingTop: "
|
1491
|
-
paddingLeft: "
|
1492
|
-
paddingRight: "
|
1904
|
+
paddingTop: "4px",
|
1905
|
+
paddingLeft: "7px",
|
1906
|
+
paddingRight: "7px",
|
1493
1907
|
variant,
|
1494
1908
|
children: [
|
1495
1909
|
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
@@ -1500,7 +1914,7 @@ const DocumentActionsMenu = ({
|
|
1500
1914
|
]
|
1501
1915
|
}
|
1502
1916
|
),
|
1503
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1917
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1504
1918
|
actions2.map((action) => {
|
1505
1919
|
return /* @__PURE__ */ jsx(
|
1506
1920
|
Menu.Item,
|
@@ -1509,10 +1923,25 @@ const DocumentActionsMenu = ({
|
|
1509
1923
|
onSelect: handleClick(action),
|
1510
1924
|
display: "block",
|
1511
1925
|
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
1512
|
-
/* @__PURE__ */ jsxs(
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1926
|
+
/* @__PURE__ */ jsxs(
|
1927
|
+
Flex,
|
1928
|
+
{
|
1929
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1930
|
+
gap: 2,
|
1931
|
+
tag: "span",
|
1932
|
+
children: [
|
1933
|
+
/* @__PURE__ */ jsx(
|
1934
|
+
Flex,
|
1935
|
+
{
|
1936
|
+
tag: "span",
|
1937
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1938
|
+
children: action.icon
|
1939
|
+
}
|
1940
|
+
),
|
1941
|
+
action.label
|
1942
|
+
]
|
1943
|
+
}
|
1944
|
+
),
|
1516
1945
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
1517
1946
|
Flex,
|
1518
1947
|
{
|
@@ -1609,11 +2038,11 @@ const DocumentActionConfirmDialog = ({
|
|
1609
2038
|
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1610
2039
|
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1611
2040
|
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1612
|
-
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
2041
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1613
2042
|
id: "app.components.Button.cancel",
|
1614
2043
|
defaultMessage: "Cancel"
|
1615
2044
|
}) }) }),
|
1616
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2045
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1617
2046
|
id: "app.components.Button.confirm",
|
1618
2047
|
defaultMessage: "Confirm"
|
1619
2048
|
}) })
|
@@ -1640,6 +2069,18 @@ const DocumentActionModal = ({
|
|
1640
2069
|
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1641
2070
|
] }) });
|
1642
2071
|
};
|
2072
|
+
const transformData = (data) => {
|
2073
|
+
if (Array.isArray(data)) {
|
2074
|
+
return data.map(transformData);
|
2075
|
+
}
|
2076
|
+
if (typeof data === "object" && data !== null) {
|
2077
|
+
if ("apiData" in data) {
|
2078
|
+
return data.apiData;
|
2079
|
+
}
|
2080
|
+
return mapValues(transformData)(data);
|
2081
|
+
}
|
2082
|
+
return data;
|
2083
|
+
};
|
1643
2084
|
const PublishAction$1 = ({
|
1644
2085
|
activeTab,
|
1645
2086
|
documentId,
|
@@ -1652,13 +2093,17 @@ const PublishAction$1 = ({
|
|
1652
2093
|
const navigate = useNavigate();
|
1653
2094
|
const { toggleNotification } = useNotification();
|
1654
2095
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2096
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
1655
2097
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
1656
2098
|
const { formatMessage } = useIntl();
|
1657
|
-
const { canPublish
|
1658
|
-
"PublishAction",
|
1659
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1660
|
-
);
|
2099
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1661
2100
|
const { publish } = useDocumentActions();
|
2101
|
+
const [
|
2102
|
+
countDraftRelations,
|
2103
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2104
|
+
] = useLazyGetDraftRelationCountQuery();
|
2105
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
2106
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1662
2107
|
const [{ query, rawQuery }] = useQueryParams();
|
1663
2108
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1664
2109
|
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1667,10 +2112,105 @@ const PublishAction$1 = ({
|
|
1667
2112
|
const validate = useForm("PublishAction", (state) => state.validate);
|
1668
2113
|
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1669
2114
|
const formValues = useForm("PublishAction", ({ values }) => values);
|
2115
|
+
React.useEffect(() => {
|
2116
|
+
if (isErrorDraftRelations) {
|
2117
|
+
toggleNotification({
|
2118
|
+
type: "danger",
|
2119
|
+
message: formatMessage({
|
2120
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2121
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2122
|
+
})
|
2123
|
+
});
|
2124
|
+
}
|
2125
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2126
|
+
React.useEffect(() => {
|
2127
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2128
|
+
const extractDraftRelations = (data) => {
|
2129
|
+
const relations = data.connect || [];
|
2130
|
+
relations.forEach((relation) => {
|
2131
|
+
if (relation.status === "draft") {
|
2132
|
+
localDraftRelations.add(relation.id);
|
2133
|
+
}
|
2134
|
+
});
|
2135
|
+
};
|
2136
|
+
const traverseAndExtract = (data) => {
|
2137
|
+
Object.entries(data).forEach(([key, value]) => {
|
2138
|
+
if (key === "connect" && Array.isArray(value)) {
|
2139
|
+
extractDraftRelations({ connect: value });
|
2140
|
+
} else if (typeof value === "object" && value !== null) {
|
2141
|
+
traverseAndExtract(value);
|
2142
|
+
}
|
2143
|
+
});
|
2144
|
+
};
|
2145
|
+
if (!documentId || modified) {
|
2146
|
+
traverseAndExtract(formValues);
|
2147
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2148
|
+
}
|
2149
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2150
|
+
React.useEffect(() => {
|
2151
|
+
if (!document || !document.documentId || isListView) {
|
2152
|
+
return;
|
2153
|
+
}
|
2154
|
+
const fetchDraftRelationsCount = async () => {
|
2155
|
+
const { data, error } = await countDraftRelations({
|
2156
|
+
collectionType,
|
2157
|
+
model,
|
2158
|
+
documentId,
|
2159
|
+
params
|
2160
|
+
});
|
2161
|
+
if (error) {
|
2162
|
+
throw error;
|
2163
|
+
}
|
2164
|
+
if (data) {
|
2165
|
+
setServerCountOfDraftRelations(data.data);
|
2166
|
+
}
|
2167
|
+
};
|
2168
|
+
fetchDraftRelationsCount();
|
2169
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
1670
2170
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1671
2171
|
if (!schema?.options?.draftAndPublish) {
|
1672
2172
|
return null;
|
1673
2173
|
}
|
2174
|
+
const performPublish = async () => {
|
2175
|
+
setSubmitting(true);
|
2176
|
+
try {
|
2177
|
+
const { errors } = await validate(true, {
|
2178
|
+
status: "published"
|
2179
|
+
});
|
2180
|
+
if (errors) {
|
2181
|
+
toggleNotification({
|
2182
|
+
type: "danger",
|
2183
|
+
message: formatMessage({
|
2184
|
+
id: "content-manager.validation.error",
|
2185
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2186
|
+
})
|
2187
|
+
});
|
2188
|
+
return;
|
2189
|
+
}
|
2190
|
+
const res = await publish(
|
2191
|
+
{
|
2192
|
+
collectionType,
|
2193
|
+
model,
|
2194
|
+
documentId,
|
2195
|
+
params
|
2196
|
+
},
|
2197
|
+
transformData(formValues)
|
2198
|
+
);
|
2199
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2200
|
+
navigate({
|
2201
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2202
|
+
search: rawQuery
|
2203
|
+
});
|
2204
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2205
|
+
setErrors(formatValidationErrors(res.error));
|
2206
|
+
}
|
2207
|
+
} finally {
|
2208
|
+
setSubmitting(false);
|
2209
|
+
}
|
2210
|
+
};
|
2211
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2212
|
+
const enableDraftRelationsCount = false;
|
2213
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1674
2214
|
return {
|
1675
2215
|
/**
|
1676
2216
|
* Disabled when:
|
@@ -1680,49 +2220,36 @@ const PublishAction$1 = ({
|
|
1680
2220
|
* - the document is already published & not modified
|
1681
2221
|
* - the document is being created & not modified
|
1682
2222
|
* - the user doesn't have the permission to publish
|
1683
|
-
* - the user doesn't have the permission to create a new document
|
1684
|
-
* - the user doesn't have the permission to update the document
|
1685
2223
|
*/
|
1686
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2224
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1687
2225
|
label: formatMessage({
|
1688
2226
|
id: "app.utils.publish",
|
1689
2227
|
defaultMessage: "Publish"
|
1690
2228
|
}),
|
1691
2229
|
onClick: async () => {
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
documentId,
|
1710
|
-
params
|
1711
|
-
},
|
1712
|
-
formValues
|
1713
|
-
);
|
1714
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1715
|
-
navigate({
|
1716
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1717
|
-
search: rawQuery
|
1718
|
-
});
|
1719
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1720
|
-
setErrors(formatValidationErrors(res.error));
|
2230
|
+
await performPublish();
|
2231
|
+
},
|
2232
|
+
dialog: hasDraftRelations ? {
|
2233
|
+
type: "dialog",
|
2234
|
+
variant: "danger",
|
2235
|
+
footer: null,
|
2236
|
+
title: formatMessage({
|
2237
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2238
|
+
defaultMessage: "Confirmation"
|
2239
|
+
}),
|
2240
|
+
content: formatMessage(
|
2241
|
+
{
|
2242
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2243
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2244
|
+
},
|
2245
|
+
{
|
2246
|
+
count: totalDraftRelations
|
1721
2247
|
}
|
1722
|
-
|
1723
|
-
|
2248
|
+
),
|
2249
|
+
onConfirm: async () => {
|
2250
|
+
await performPublish();
|
1724
2251
|
}
|
1725
|
-
}
|
2252
|
+
} : void 0
|
1726
2253
|
};
|
1727
2254
|
};
|
1728
2255
|
PublishAction$1.type = "publish";
|
@@ -1738,10 +2265,6 @@ const UpdateAction = ({
|
|
1738
2265
|
const cloneMatch = useMatch(CLONE_PATH);
|
1739
2266
|
const isCloning = cloneMatch !== null;
|
1740
2267
|
const { formatMessage } = useIntl();
|
1741
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1742
|
-
canCreate: canCreate2,
|
1743
|
-
canUpdate: canUpdate2
|
1744
|
-
}));
|
1745
2268
|
const { create, update, clone } = useDocumentActions();
|
1746
2269
|
const [{ query, rawQuery }] = useQueryParams();
|
1747
2270
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
@@ -1758,10 +2281,8 @@ const UpdateAction = ({
|
|
1758
2281
|
* - the form is submitting
|
1759
2282
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1760
2283
|
* - the active tab is the published tab
|
1761
|
-
* - the user doesn't have the permission to create a new document
|
1762
|
-
* - the user doesn't have the permission to update the document
|
1763
2284
|
*/
|
1764
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2285
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1765
2286
|
label: formatMessage({
|
1766
2287
|
id: "content-manager.containers.Edit.save",
|
1767
2288
|
defaultMessage: "Save"
|
@@ -1769,7 +2290,9 @@ const UpdateAction = ({
|
|
1769
2290
|
onClick: async () => {
|
1770
2291
|
setSubmitting(true);
|
1771
2292
|
try {
|
1772
|
-
const { errors } = await validate(
|
2293
|
+
const { errors } = await validate(true, {
|
2294
|
+
status: "draft"
|
2295
|
+
});
|
1773
2296
|
if (errors) {
|
1774
2297
|
toggleNotification({
|
1775
2298
|
type: "danger",
|
@@ -1787,13 +2310,16 @@ const UpdateAction = ({
|
|
1787
2310
|
documentId: cloneMatch.params.origin,
|
1788
2311
|
params
|
1789
2312
|
},
|
1790
|
-
document
|
2313
|
+
transformData(document)
|
1791
2314
|
);
|
1792
2315
|
if ("data" in res) {
|
1793
|
-
navigate(
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
2316
|
+
navigate(
|
2317
|
+
{
|
2318
|
+
pathname: `../${res.data.documentId}`,
|
2319
|
+
search: rawQuery
|
2320
|
+
},
|
2321
|
+
{ relative: "path" }
|
2322
|
+
);
|
1797
2323
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1798
2324
|
setErrors(formatValidationErrors(res.error));
|
1799
2325
|
}
|
@@ -1805,7 +2331,7 @@ const UpdateAction = ({
|
|
1805
2331
|
documentId,
|
1806
2332
|
params
|
1807
2333
|
},
|
1808
|
-
document
|
2334
|
+
transformData(document)
|
1809
2335
|
);
|
1810
2336
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1811
2337
|
setErrors(formatValidationErrors(res.error));
|
@@ -1818,13 +2344,16 @@ const UpdateAction = ({
|
|
1818
2344
|
model,
|
1819
2345
|
params
|
1820
2346
|
},
|
1821
|
-
document
|
2347
|
+
transformData(document)
|
1822
2348
|
);
|
1823
2349
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1824
|
-
navigate(
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
2350
|
+
navigate(
|
2351
|
+
{
|
2352
|
+
pathname: `../${res.data.documentId}`,
|
2353
|
+
search: rawQuery
|
2354
|
+
},
|
2355
|
+
{ replace: true, relative: "path" }
|
2356
|
+
);
|
1828
2357
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1829
2358
|
setErrors(formatValidationErrors(res.error));
|
1830
2359
|
}
|
@@ -1868,7 +2397,7 @@ const UnpublishAction$1 = ({
|
|
1868
2397
|
id: "app.utils.unpublish",
|
1869
2398
|
defaultMessage: "Unpublish"
|
1870
2399
|
}),
|
1871
|
-
icon: /* @__PURE__ */ jsx(
|
2400
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1872
2401
|
onClick: async () => {
|
1873
2402
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1874
2403
|
if (!documentId) {
|
@@ -1980,7 +2509,7 @@ const DiscardAction = ({
|
|
1980
2509
|
id: "content-manager.actions.discard.label",
|
1981
2510
|
defaultMessage: "Discard changes"
|
1982
2511
|
}),
|
1983
|
-
icon: /* @__PURE__ */ jsx(
|
2512
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1984
2513
|
position: ["panel", "table-row"],
|
1985
2514
|
variant: "danger",
|
1986
2515
|
dialog: {
|
@@ -2008,11 +2537,6 @@ const DiscardAction = ({
|
|
2008
2537
|
};
|
2009
2538
|
};
|
2010
2539
|
DiscardAction.type = "discard";
|
2011
|
-
const StyledCrossCircle = styled(CrossCircle)`
|
2012
|
-
path {
|
2013
|
-
fill: currentColor;
|
2014
|
-
}
|
2015
|
-
`;
|
2016
2540
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2017
2541
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2018
2542
|
const RelativeTime = React.forwardRef(
|
@@ -2060,8 +2584,12 @@ const getDisplayName = ({
|
|
2060
2584
|
};
|
2061
2585
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2062
2586
|
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2063
|
-
const statusVariant = status === "draft" ? "
|
2064
|
-
|
2587
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2588
|
+
const { formatMessage } = useIntl();
|
2589
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: formatMessage({
|
2590
|
+
id: `content-manager.containers.List.${status}`,
|
2591
|
+
defaultMessage: capitalise(status)
|
2592
|
+
}) }) });
|
2065
2593
|
};
|
2066
2594
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2067
2595
|
const { formatMessage } = useIntl();
|
@@ -2070,23 +2598,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2070
2598
|
id: "content-manager.containers.edit.title.new",
|
2071
2599
|
defaultMessage: "Create an entry"
|
2072
2600
|
}) : documentTitle;
|
2073
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2601
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2074
2602
|
/* @__PURE__ */ jsx(BackButton, {}),
|
2075
|
-
/* @__PURE__ */ jsxs(
|
2076
|
-
|
2077
|
-
{
|
2078
|
-
|
2079
|
-
|
2080
|
-
paddingTop: 1,
|
2081
|
-
gap: "80px",
|
2082
|
-
alignItems: "flex-start",
|
2083
|
-
children: [
|
2084
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2085
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2086
|
-
]
|
2087
|
-
}
|
2088
|
-
),
|
2089
|
-
status ? /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2603
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2604
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2605
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2606
|
+
] }),
|
2607
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2090
2608
|
] });
|
2091
2609
|
};
|
2092
2610
|
const HeaderToolbar = () => {
|
@@ -2169,12 +2687,12 @@ const Information = ({ activeTab }) => {
|
|
2169
2687
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2170
2688
|
label: formatMessage({
|
2171
2689
|
id: "content-manager.containers.edit.information.last-published.label",
|
2172
|
-
defaultMessage: "
|
2690
|
+
defaultMessage: "Published"
|
2173
2691
|
}),
|
2174
2692
|
value: formatMessage(
|
2175
2693
|
{
|
2176
2694
|
id: "content-manager.containers.edit.information.last-published.value",
|
2177
|
-
defaultMessage: `
|
2695
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2178
2696
|
},
|
2179
2697
|
{
|
2180
2698
|
time: /* @__PURE__ */ jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2187,12 +2705,12 @@ const Information = ({ activeTab }) => {
|
|
2187
2705
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2188
2706
|
label: formatMessage({
|
2189
2707
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2190
|
-
defaultMessage: "
|
2708
|
+
defaultMessage: "Updated"
|
2191
2709
|
}),
|
2192
2710
|
value: formatMessage(
|
2193
2711
|
{
|
2194
2712
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2195
|
-
defaultMessage: `
|
2713
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2196
2714
|
},
|
2197
2715
|
{
|
2198
2716
|
time: /* @__PURE__ */ jsx(
|
@@ -2210,12 +2728,12 @@ const Information = ({ activeTab }) => {
|
|
2210
2728
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2211
2729
|
label: formatMessage({
|
2212
2730
|
id: "content-manager.containers.edit.information.document.label",
|
2213
|
-
defaultMessage: "
|
2731
|
+
defaultMessage: "Created"
|
2214
2732
|
}),
|
2215
2733
|
value: formatMessage(
|
2216
2734
|
{
|
2217
2735
|
id: "content-manager.containers.edit.information.document.value",
|
2218
|
-
defaultMessage: `
|
2736
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2219
2737
|
},
|
2220
2738
|
{
|
2221
2739
|
time: /* @__PURE__ */ jsx(
|
@@ -2253,25 +2771,77 @@ const Information = ({ activeTab }) => {
|
|
2253
2771
|
);
|
2254
2772
|
};
|
2255
2773
|
const HeaderActions = ({ actions: actions2 }) => {
|
2256
|
-
|
2257
|
-
|
2774
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2775
|
+
const handleClick = (action) => async (e) => {
|
2776
|
+
if (!("options" in action)) {
|
2777
|
+
const { onClick = () => false, dialog, id } = action;
|
2778
|
+
const muteDialog = await onClick(e);
|
2779
|
+
if (dialog && !muteDialog) {
|
2780
|
+
e.preventDefault();
|
2781
|
+
setDialogId(id);
|
2782
|
+
}
|
2783
|
+
}
|
2784
|
+
};
|
2785
|
+
const handleClose = () => {
|
2786
|
+
setDialogId(null);
|
2787
|
+
};
|
2788
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2789
|
+
if (action.options) {
|
2258
2790
|
return /* @__PURE__ */ jsx(
|
2259
2791
|
SingleSelect,
|
2260
2792
|
{
|
2261
2793
|
size: "S",
|
2262
|
-
disabled: action.disabled,
|
2263
|
-
"aria-label": action.label,
|
2264
2794
|
onChange: action.onSelect,
|
2265
|
-
|
2795
|
+
"aria-label": action.label,
|
2796
|
+
...action,
|
2266
2797
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsx(SingleSelectOption, { ...option, children: label }, option.value))
|
2267
2798
|
},
|
2268
2799
|
action.id
|
2269
2800
|
);
|
2270
2801
|
} else {
|
2271
|
-
|
2802
|
+
if (action.type === "icon") {
|
2803
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2804
|
+
/* @__PURE__ */ jsx(
|
2805
|
+
IconButton,
|
2806
|
+
{
|
2807
|
+
disabled: action.disabled,
|
2808
|
+
label: action.label,
|
2809
|
+
size: "S",
|
2810
|
+
onClick: handleClick(action),
|
2811
|
+
children: action.icon
|
2812
|
+
}
|
2813
|
+
),
|
2814
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2815
|
+
HeaderActionDialog,
|
2816
|
+
{
|
2817
|
+
...action.dialog,
|
2818
|
+
isOpen: dialogId === action.id,
|
2819
|
+
onClose: handleClose
|
2820
|
+
}
|
2821
|
+
) : null
|
2822
|
+
] }, action.id);
|
2823
|
+
}
|
2272
2824
|
}
|
2273
2825
|
}) });
|
2274
2826
|
};
|
2827
|
+
const HeaderActionDialog = ({
|
2828
|
+
onClose,
|
2829
|
+
onCancel,
|
2830
|
+
title,
|
2831
|
+
content: Content,
|
2832
|
+
isOpen
|
2833
|
+
}) => {
|
2834
|
+
const handleClose = async () => {
|
2835
|
+
if (onCancel) {
|
2836
|
+
await onCancel();
|
2837
|
+
}
|
2838
|
+
onClose();
|
2839
|
+
};
|
2840
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2841
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2842
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2843
|
+
] }) });
|
2844
|
+
};
|
2275
2845
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2276
2846
|
const navigate = useNavigate();
|
2277
2847
|
const { formatMessage } = useIntl();
|
@@ -2312,12 +2882,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2312
2882
|
const { delete: deleteAction } = useDocumentActions();
|
2313
2883
|
const { toggleNotification } = useNotification();
|
2314
2884
|
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2885
|
+
const isLocalized = document?.locale != null;
|
2315
2886
|
return {
|
2316
2887
|
disabled: !canDelete || !document,
|
2317
|
-
label: formatMessage(
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
2888
|
+
label: formatMessage(
|
2889
|
+
{
|
2890
|
+
id: "content-manager.actions.delete.label",
|
2891
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2892
|
+
},
|
2893
|
+
{ isLocalized }
|
2894
|
+
),
|
2321
2895
|
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2322
2896
|
dialog: {
|
2323
2897
|
type: "dialog",
|
@@ -2360,416 +2934,114 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2360
2934
|
});
|
2361
2935
|
if (!("error" in res)) {
|
2362
2936
|
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2363
|
-
}
|
2364
|
-
} finally {
|
2365
|
-
if (!listViewPathMatch) {
|
2366
|
-
setSubmitting(false);
|
2367
|
-
}
|
2368
|
-
}
|
2369
|
-
}
|
2370
|
-
},
|
2371
|
-
variant: "danger",
|
2372
|
-
position: ["header", "table-row"]
|
2373
|
-
};
|
2374
|
-
};
|
2375
|
-
DeleteAction$1.type = "delete";
|
2376
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2377
|
-
const Panels = () => {
|
2378
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2379
|
-
const [
|
2380
|
-
{
|
2381
|
-
query: { status }
|
2382
|
-
}
|
2383
|
-
] = useQueryParams({
|
2384
|
-
status: "draft"
|
2385
|
-
});
|
2386
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2387
|
-
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2388
|
-
const props = {
|
2389
|
-
activeTab: status,
|
2390
|
-
model,
|
2391
|
-
documentId: id,
|
2392
|
-
document: isCloning ? void 0 : document,
|
2393
|
-
meta: isCloning ? void 0 : meta,
|
2394
|
-
collectionType
|
2395
|
-
};
|
2396
|
-
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2397
|
-
DescriptionComponentRenderer,
|
2398
|
-
{
|
2399
|
-
props,
|
2400
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2401
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2402
|
-
}
|
2403
|
-
) });
|
2404
|
-
};
|
2405
|
-
const ActionsPanel = () => {
|
2406
|
-
const { formatMessage } = useIntl();
|
2407
|
-
return {
|
2408
|
-
title: formatMessage({
|
2409
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2410
|
-
defaultMessage: "Document"
|
2411
|
-
}),
|
2412
|
-
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2413
|
-
};
|
2414
|
-
};
|
2415
|
-
ActionsPanel.type = "actions";
|
2416
|
-
const ActionsPanelContent = () => {
|
2417
|
-
const isCloning = useMatch(CLONE_PATH) !== null;
|
2418
|
-
const [
|
2419
|
-
{
|
2420
|
-
query: { status = "draft" }
|
2421
|
-
}
|
2422
|
-
] = useQueryParams();
|
2423
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2424
|
-
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2425
|
-
const props = {
|
2426
|
-
activeTab: status,
|
2427
|
-
model,
|
2428
|
-
documentId: id,
|
2429
|
-
document: isCloning ? void 0 : document,
|
2430
|
-
meta: isCloning ? void 0 : meta,
|
2431
|
-
collectionType
|
2432
|
-
};
|
2433
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2434
|
-
/* @__PURE__ */ jsx(
|
2435
|
-
DescriptionComponentRenderer,
|
2436
|
-
{
|
2437
|
-
props,
|
2438
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2439
|
-
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
2440
|
-
}
|
2441
|
-
),
|
2442
|
-
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2443
|
-
] });
|
2444
|
-
};
|
2445
|
-
const Panel = React.forwardRef(({ children, title }, ref) => {
|
2446
|
-
return /* @__PURE__ */ jsxs(
|
2447
|
-
Flex,
|
2448
|
-
{
|
2449
|
-
ref,
|
2450
|
-
tag: "aside",
|
2451
|
-
"aria-labelledby": "additional-information",
|
2452
|
-
background: "neutral0",
|
2453
|
-
borderColor: "neutral150",
|
2454
|
-
hasRadius: true,
|
2455
|
-
paddingBottom: 4,
|
2456
|
-
paddingLeft: 4,
|
2457
|
-
paddingRight: 4,
|
2458
|
-
paddingTop: 4,
|
2459
|
-
shadow: "tableShadow",
|
2460
|
-
gap: 3,
|
2461
|
-
direction: "column",
|
2462
|
-
justifyContent: "stretch",
|
2463
|
-
alignItems: "flex-start",
|
2464
|
-
children: [
|
2465
|
-
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2466
|
-
children
|
2467
|
-
]
|
2468
|
-
}
|
2469
|
-
);
|
2470
|
-
});
|
2471
|
-
const HOOKS = {
|
2472
|
-
/**
|
2473
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2474
|
-
* @constant
|
2475
|
-
* @type {string}
|
2476
|
-
*/
|
2477
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2478
|
-
/**
|
2479
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2480
|
-
* @constant
|
2481
|
-
* @type {string}
|
2482
|
-
*/
|
2483
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2484
|
-
/**
|
2485
|
-
* Hook that allows to mutate the CM's edit view layout
|
2486
|
-
* @constant
|
2487
|
-
* @type {string}
|
2488
|
-
*/
|
2489
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2490
|
-
/**
|
2491
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2492
|
-
* @constant
|
2493
|
-
* @type {string}
|
2494
|
-
*/
|
2495
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2496
|
-
};
|
2497
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2498
|
-
endpoints: (builder) => ({
|
2499
|
-
getContentTypeConfiguration: builder.query({
|
2500
|
-
query: (uid) => ({
|
2501
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2502
|
-
method: "GET"
|
2503
|
-
}),
|
2504
|
-
transformResponse: (response) => response.data,
|
2505
|
-
providesTags: (_result, _error, uid) => [
|
2506
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2507
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2508
|
-
]
|
2509
|
-
}),
|
2510
|
-
getAllContentTypeSettings: builder.query({
|
2511
|
-
query: () => "/content-manager/content-types-settings",
|
2512
|
-
transformResponse: (response) => response.data,
|
2513
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2514
|
-
}),
|
2515
|
-
updateContentTypeConfiguration: builder.mutation({
|
2516
|
-
query: ({ uid, ...body }) => ({
|
2517
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2518
|
-
method: "PUT",
|
2519
|
-
data: body
|
2520
|
-
}),
|
2521
|
-
transformResponse: (response) => response.data,
|
2522
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2523
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2524
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2525
|
-
// Is this necessary?
|
2526
|
-
{ type: "InitialData" }
|
2527
|
-
]
|
2528
|
-
})
|
2529
|
-
})
|
2530
|
-
});
|
2531
|
-
const {
|
2532
|
-
useGetContentTypeConfigurationQuery,
|
2533
|
-
useGetAllContentTypeSettingsQuery,
|
2534
|
-
useUpdateContentTypeConfigurationMutation
|
2535
|
-
} = contentTypesApi;
|
2536
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2537
|
-
const { type } = attribute;
|
2538
|
-
if (type === "relation") {
|
2539
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2540
|
-
}
|
2541
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2542
|
-
};
|
2543
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2544
|
-
if (!mainFieldName) {
|
2545
|
-
return void 0;
|
2546
|
-
}
|
2547
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2548
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2549
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2550
|
-
);
|
2551
|
-
return {
|
2552
|
-
name: mainFieldName,
|
2553
|
-
type: mainFieldType ?? "string"
|
2554
|
-
};
|
2555
|
-
};
|
2556
|
-
const DEFAULT_SETTINGS = {
|
2557
|
-
bulkable: false,
|
2558
|
-
filterable: false,
|
2559
|
-
searchable: false,
|
2560
|
-
pagination: false,
|
2561
|
-
defaultSortBy: "",
|
2562
|
-
defaultSortOrder: "asc",
|
2563
|
-
mainField: "id",
|
2564
|
-
pageSize: 10
|
2565
|
-
};
|
2566
|
-
const useDocumentLayout = (model) => {
|
2567
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2568
|
-
const [{ query }] = useQueryParams();
|
2569
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2570
|
-
const { toggleNotification } = useNotification();
|
2571
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2572
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2573
|
-
const {
|
2574
|
-
data,
|
2575
|
-
isLoading: isLoadingConfigs,
|
2576
|
-
error,
|
2577
|
-
isFetching: isFetchingConfigs
|
2578
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2579
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2580
|
-
React.useEffect(() => {
|
2581
|
-
if (error) {
|
2582
|
-
toggleNotification({
|
2583
|
-
type: "danger",
|
2584
|
-
message: formatAPIError(error)
|
2585
|
-
});
|
2586
|
-
}
|
2587
|
-
}, [error, formatAPIError, toggleNotification]);
|
2588
|
-
const editLayout = React.useMemo(
|
2589
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2590
|
-
layout: [],
|
2591
|
-
components: {},
|
2592
|
-
metadatas: {},
|
2593
|
-
options: {},
|
2594
|
-
settings: DEFAULT_SETTINGS
|
2595
|
-
},
|
2596
|
-
[data, isLoading, schemas, schema, components]
|
2597
|
-
);
|
2598
|
-
const listLayout = React.useMemo(() => {
|
2599
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2600
|
-
layout: [],
|
2601
|
-
metadatas: {},
|
2602
|
-
options: {},
|
2603
|
-
settings: DEFAULT_SETTINGS
|
2604
|
-
};
|
2605
|
-
}, [data, isLoading, schemas, schema, components]);
|
2606
|
-
const { layout: edit } = React.useMemo(
|
2607
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2608
|
-
layout: editLayout,
|
2609
|
-
query
|
2610
|
-
}),
|
2611
|
-
[editLayout, query, runHookWaterfall]
|
2612
|
-
);
|
2613
|
-
return {
|
2614
|
-
error,
|
2615
|
-
isLoading,
|
2616
|
-
edit,
|
2617
|
-
list: listLayout
|
2618
|
-
};
|
2619
|
-
};
|
2620
|
-
const useDocLayout = () => {
|
2621
|
-
const { model } = useDoc();
|
2622
|
-
return useDocumentLayout(model);
|
2623
|
-
};
|
2624
|
-
const formatEditLayout = (data, {
|
2625
|
-
schemas,
|
2626
|
-
schema,
|
2627
|
-
components
|
2628
|
-
}) => {
|
2629
|
-
let currentPanelIndex = 0;
|
2630
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2631
|
-
data.contentType.layouts.edit,
|
2632
|
-
schema?.attributes,
|
2633
|
-
data.contentType.metadatas,
|
2634
|
-
{ configurations: data.components, schemas: components },
|
2635
|
-
schemas
|
2636
|
-
).reduce((panels, row) => {
|
2637
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2638
|
-
panels.push([row]);
|
2639
|
-
currentPanelIndex += 2;
|
2640
|
-
} else {
|
2641
|
-
if (!panels[currentPanelIndex]) {
|
2642
|
-
panels.push([]);
|
2643
|
-
}
|
2644
|
-
panels[currentPanelIndex].push(row);
|
2645
|
-
}
|
2646
|
-
return panels;
|
2647
|
-
}, []);
|
2648
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2649
|
-
(acc, [uid, configuration]) => {
|
2650
|
-
acc[uid] = {
|
2651
|
-
layout: convertEditLayoutToFieldLayouts(
|
2652
|
-
configuration.layouts.edit,
|
2653
|
-
components[uid].attributes,
|
2654
|
-
configuration.metadatas
|
2655
|
-
),
|
2656
|
-
settings: {
|
2657
|
-
...configuration.settings,
|
2658
|
-
icon: components[uid].info.icon,
|
2659
|
-
displayName: components[uid].info.displayName
|
2660
|
-
}
|
2661
|
-
};
|
2662
|
-
return acc;
|
2663
|
-
},
|
2664
|
-
{}
|
2665
|
-
);
|
2666
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2667
|
-
(acc, [attribute, metadata]) => {
|
2668
|
-
return {
|
2669
|
-
...acc,
|
2670
|
-
[attribute]: metadata.edit
|
2671
|
-
};
|
2672
|
-
},
|
2673
|
-
{}
|
2674
|
-
);
|
2675
|
-
return {
|
2676
|
-
layout: panelledEditAttributes,
|
2677
|
-
components: componentEditAttributes,
|
2678
|
-
metadatas: editMetadatas,
|
2679
|
-
settings: {
|
2680
|
-
...data.contentType.settings,
|
2681
|
-
displayName: schema?.info.displayName
|
2937
|
+
}
|
2938
|
+
} finally {
|
2939
|
+
if (!listViewPathMatch) {
|
2940
|
+
setSubmitting(false);
|
2941
|
+
}
|
2942
|
+
}
|
2943
|
+
}
|
2682
2944
|
},
|
2683
|
-
|
2684
|
-
|
2685
|
-
...schema?.pluginOptions,
|
2686
|
-
...data.contentType.options
|
2687
|
-
}
|
2945
|
+
variant: "danger",
|
2946
|
+
position: ["header", "table-row"]
|
2688
2947
|
};
|
2689
2948
|
};
|
2690
|
-
|
2691
|
-
|
2692
|
-
|
2693
|
-
|
2694
|
-
|
2695
|
-
|
2696
|
-
}
|
2697
|
-
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
2702
|
-
|
2703
|
-
|
2704
|
-
|
2705
|
-
|
2706
|
-
|
2707
|
-
|
2708
|
-
|
2709
|
-
|
2710
|
-
|
2711
|
-
|
2712
|
-
|
2713
|
-
|
2714
|
-
|
2715
|
-
|
2716
|
-
}
|
2717
|
-
}
|
2718
|
-
);
|
2949
|
+
DeleteAction$1.type = "delete";
|
2950
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2951
|
+
const Panels = () => {
|
2952
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2953
|
+
const [
|
2954
|
+
{
|
2955
|
+
query: { status }
|
2956
|
+
}
|
2957
|
+
] = useQueryParams({
|
2958
|
+
status: "draft"
|
2959
|
+
});
|
2960
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2961
|
+
const plugins = useStrapiApp("Panels", (state) => state.plugins);
|
2962
|
+
const props = {
|
2963
|
+
activeTab: status,
|
2964
|
+
model,
|
2965
|
+
documentId: id,
|
2966
|
+
document: isCloning ? void 0 : document,
|
2967
|
+
meta: isCloning ? void 0 : meta,
|
2968
|
+
collectionType
|
2969
|
+
};
|
2970
|
+
return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsx(
|
2971
|
+
DescriptionComponentRenderer,
|
2972
|
+
{
|
2973
|
+
props,
|
2974
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2975
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsx(Panel, { ...description, children: content }, id2))
|
2976
|
+
}
|
2977
|
+
) });
|
2719
2978
|
};
|
2720
|
-
const
|
2721
|
-
|
2722
|
-
schema,
|
2723
|
-
components
|
2724
|
-
}) => {
|
2725
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2726
|
-
(acc, [attribute, metadata]) => {
|
2727
|
-
return {
|
2728
|
-
...acc,
|
2729
|
-
[attribute]: metadata.list
|
2730
|
-
};
|
2731
|
-
},
|
2732
|
-
{}
|
2733
|
-
);
|
2734
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2735
|
-
data.contentType.layouts.list,
|
2736
|
-
schema?.attributes,
|
2737
|
-
listMetadatas,
|
2738
|
-
{ configurations: data.components, schemas: components },
|
2739
|
-
schemas
|
2740
|
-
);
|
2979
|
+
const ActionsPanel = () => {
|
2980
|
+
const { formatMessage } = useIntl();
|
2741
2981
|
return {
|
2742
|
-
|
2743
|
-
|
2744
|
-
|
2745
|
-
|
2746
|
-
|
2747
|
-
...schema?.pluginOptions,
|
2748
|
-
...data.contentType.options
|
2749
|
-
}
|
2982
|
+
title: formatMessage({
|
2983
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2984
|
+
defaultMessage: "Entry"
|
2985
|
+
}),
|
2986
|
+
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2750
2987
|
};
|
2751
2988
|
};
|
2752
|
-
|
2753
|
-
|
2754
|
-
|
2755
|
-
|
2756
|
-
|
2989
|
+
ActionsPanel.type = "actions";
|
2990
|
+
const ActionsPanelContent = () => {
|
2991
|
+
const isCloning = useMatch(CLONE_PATH) !== null;
|
2992
|
+
const [
|
2993
|
+
{
|
2994
|
+
query: { status = "draft" }
|
2757
2995
|
}
|
2758
|
-
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
2762
|
-
|
2763
|
-
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2996
|
+
] = useQueryParams();
|
2997
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2998
|
+
const plugins = useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2999
|
+
const props = {
|
3000
|
+
activeTab: status,
|
3001
|
+
model,
|
3002
|
+
documentId: id,
|
3003
|
+
document: isCloning ? void 0 : document,
|
3004
|
+
meta: isCloning ? void 0 : meta,
|
3005
|
+
collectionType
|
3006
|
+
};
|
3007
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3008
|
+
/* @__PURE__ */ jsx(
|
3009
|
+
DescriptionComponentRenderer,
|
3010
|
+
{
|
3011
|
+
props,
|
3012
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3013
|
+
children: (actions2) => /* @__PURE__ */ jsx(DocumentActions, { actions: actions2 })
|
3014
|
+
}
|
3015
|
+
),
|
3016
|
+
/* @__PURE__ */ jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3017
|
+
] });
|
2772
3018
|
};
|
3019
|
+
const Panel = React.forwardRef(({ children, title }, ref) => {
|
3020
|
+
return /* @__PURE__ */ jsxs(
|
3021
|
+
Flex,
|
3022
|
+
{
|
3023
|
+
ref,
|
3024
|
+
tag: "aside",
|
3025
|
+
"aria-labelledby": "additional-information",
|
3026
|
+
background: "neutral0",
|
3027
|
+
borderColor: "neutral150",
|
3028
|
+
hasRadius: true,
|
3029
|
+
paddingBottom: 4,
|
3030
|
+
paddingLeft: 4,
|
3031
|
+
paddingRight: 4,
|
3032
|
+
paddingTop: 4,
|
3033
|
+
shadow: "tableShadow",
|
3034
|
+
gap: 3,
|
3035
|
+
direction: "column",
|
3036
|
+
justifyContent: "stretch",
|
3037
|
+
alignItems: "flex-start",
|
3038
|
+
children: [
|
3039
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3040
|
+
children
|
3041
|
+
]
|
3042
|
+
}
|
3043
|
+
);
|
3044
|
+
});
|
2773
3045
|
const ConfirmBulkActionDialog = ({
|
2774
3046
|
onToggleDialog,
|
2775
3047
|
isOpen = false,
|
@@ -2777,7 +3049,7 @@ const ConfirmBulkActionDialog = ({
|
|
2777
3049
|
endAction
|
2778
3050
|
}) => {
|
2779
3051
|
const { formatMessage } = useIntl();
|
2780
|
-
return /* @__PURE__ */ jsx(Dialog.Root, {
|
3052
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2781
3053
|
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
2782
3054
|
id: "app.components.ConfirmDialog.title",
|
2783
3055
|
defaultMessage: "Confirmation"
|
@@ -2808,6 +3080,7 @@ const ConfirmDialogPublishAll = ({
|
|
2808
3080
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2809
3081
|
const { model, schema } = useDoc();
|
2810
3082
|
const [{ query }] = useQueryParams();
|
3083
|
+
const enableDraftRelationsCount = false;
|
2811
3084
|
const {
|
2812
3085
|
data: countDraftRelations = 0,
|
2813
3086
|
isLoading,
|
@@ -2819,7 +3092,7 @@ const ConfirmDialogPublishAll = ({
|
|
2819
3092
|
locale: query?.plugins?.i18n?.locale
|
2820
3093
|
},
|
2821
3094
|
{
|
2822
|
-
skip:
|
3095
|
+
skip: !enableDraftRelationsCount
|
2823
3096
|
}
|
2824
3097
|
);
|
2825
3098
|
React.useEffect(() => {
|
@@ -2898,7 +3171,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
|
2898
3171
|
)
|
2899
3172
|
);
|
2900
3173
|
} else {
|
2901
|
-
messages.push(
|
3174
|
+
messages.push(
|
3175
|
+
...formatErrorMessages(
|
3176
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3177
|
+
value,
|
3178
|
+
currentKey,
|
3179
|
+
formatMessage
|
3180
|
+
)
|
3181
|
+
);
|
2902
3182
|
}
|
2903
3183
|
} else {
|
2904
3184
|
messages.push(
|
@@ -2997,7 +3277,7 @@ const SelectedEntriesTableContent = ({
|
|
2997
3277
|
status: row.status
|
2998
3278
|
}
|
2999
3279
|
) }),
|
3000
|
-
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3280
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3001
3281
|
IconButton,
|
3002
3282
|
{
|
3003
3283
|
tag: Link,
|
@@ -3020,9 +3300,10 @@ const SelectedEntriesTableContent = ({
|
|
3020
3300
|
),
|
3021
3301
|
target: "_blank",
|
3022
3302
|
marginLeft: "auto",
|
3023
|
-
|
3303
|
+
variant: "ghost",
|
3304
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3024
3305
|
}
|
3025
|
-
) })
|
3306
|
+
) }) })
|
3026
3307
|
] }, row.id)) })
|
3027
3308
|
] });
|
3028
3309
|
};
|
@@ -3059,7 +3340,13 @@ const SelectedEntriesModalContent = ({
|
|
3059
3340
|
);
|
3060
3341
|
const { rows, validationErrors } = React.useMemo(() => {
|
3061
3342
|
if (data.length > 0 && schema) {
|
3062
|
-
const validate = createYupSchema(
|
3343
|
+
const validate = createYupSchema(
|
3344
|
+
schema.attributes,
|
3345
|
+
components,
|
3346
|
+
// Since this is the "Publish" action, the validation
|
3347
|
+
// schema must enforce the rules for published entities
|
3348
|
+
{ status: "published" }
|
3349
|
+
);
|
3063
3350
|
const validationErrors2 = {};
|
3064
3351
|
const rows2 = data.map((entry) => {
|
3065
3352
|
try {
|
@@ -3409,7 +3696,7 @@ const TableActions = ({ document }) => {
|
|
3409
3696
|
DescriptionComponentRenderer,
|
3410
3697
|
{
|
3411
3698
|
props,
|
3412
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3699
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3413
3700
|
children: (actions2) => {
|
3414
3701
|
const tableRowActions = actions2.filter((action) => {
|
3415
3702
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3520,7 +3807,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3520
3807
|
}),
|
3521
3808
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3522
3809
|
footer: ({ onClose }) => {
|
3523
|
-
return /* @__PURE__ */ jsxs(
|
3810
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3524
3811
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3525
3812
|
id: "cancel",
|
3526
3813
|
defaultMessage: "Cancel"
|
@@ -3561,8 +3848,7 @@ class ContentManagerPlugin {
|
|
3561
3848
|
documentActions = [
|
3562
3849
|
...DEFAULT_ACTIONS,
|
3563
3850
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3564
|
-
...DEFAULT_HEADER_ACTIONS
|
3565
|
-
HistoryAction
|
3851
|
+
...DEFAULT_HEADER_ACTIONS
|
3566
3852
|
];
|
3567
3853
|
editViewSidePanels = [ActionsPanel];
|
3568
3854
|
headerActions = [];
|
@@ -3651,6 +3937,52 @@ const getPrintableType = (value) => {
|
|
3651
3937
|
}
|
3652
3938
|
return nativeType;
|
3653
3939
|
};
|
3940
|
+
const HistoryAction = ({ model, document }) => {
|
3941
|
+
const { formatMessage } = useIntl();
|
3942
|
+
const [{ query }] = useQueryParams();
|
3943
|
+
const navigate = useNavigate();
|
3944
|
+
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3945
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3946
|
+
return null;
|
3947
|
+
}
|
3948
|
+
return {
|
3949
|
+
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3950
|
+
label: formatMessage({
|
3951
|
+
id: "content-manager.history.document-action",
|
3952
|
+
defaultMessage: "Content History"
|
3953
|
+
}),
|
3954
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3955
|
+
disabled: (
|
3956
|
+
/**
|
3957
|
+
* The user is creating a new document.
|
3958
|
+
* It hasn't been saved yet, so there's no history to go to
|
3959
|
+
*/
|
3960
|
+
!document || /**
|
3961
|
+
* The document has been created but the current dimension has never been saved.
|
3962
|
+
* For example, the user is creating a new locale in an existing document,
|
3963
|
+
* so there's no history for the document in that locale
|
3964
|
+
*/
|
3965
|
+
!document.id || /**
|
3966
|
+
* History is only available for content types created by the user.
|
3967
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3968
|
+
* which start with `admin::` or `plugin::`
|
3969
|
+
*/
|
3970
|
+
!model.startsWith("api::")
|
3971
|
+
),
|
3972
|
+
position: "header"
|
3973
|
+
};
|
3974
|
+
};
|
3975
|
+
HistoryAction.type = "history";
|
3976
|
+
const historyAdmin = {
|
3977
|
+
bootstrap(app) {
|
3978
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3979
|
+
addDocumentAction((actions2) => {
|
3980
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3981
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3982
|
+
return actions2;
|
3983
|
+
});
|
3984
|
+
}
|
3985
|
+
};
|
3654
3986
|
const initialState = {
|
3655
3987
|
collectionTypeLinks: [],
|
3656
3988
|
components: [],
|
@@ -3687,6 +4019,70 @@ const { setInitialData } = actions;
|
|
3687
4019
|
const reducer = combineReducers({
|
3688
4020
|
app: reducer$1
|
3689
4021
|
});
|
4022
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4023
|
+
endpoints: (builder) => ({
|
4024
|
+
getPreviewUrl: builder.query({
|
4025
|
+
query({ query, params }) {
|
4026
|
+
return {
|
4027
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4028
|
+
method: "GET",
|
4029
|
+
config: {
|
4030
|
+
params: query
|
4031
|
+
}
|
4032
|
+
};
|
4033
|
+
}
|
4034
|
+
})
|
4035
|
+
})
|
4036
|
+
});
|
4037
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4038
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4039
|
+
const { formatMessage } = useIntl();
|
4040
|
+
const { trackUsage } = useTracking();
|
4041
|
+
const [{ query }] = useQueryParams();
|
4042
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4043
|
+
params: {
|
4044
|
+
contentType: model
|
4045
|
+
},
|
4046
|
+
query: {
|
4047
|
+
documentId,
|
4048
|
+
locale: document?.locale,
|
4049
|
+
status: document?.status
|
4050
|
+
}
|
4051
|
+
});
|
4052
|
+
if (!data?.data?.url || error) {
|
4053
|
+
return null;
|
4054
|
+
}
|
4055
|
+
const handleClick = () => {
|
4056
|
+
trackUsage("willOpenPreview");
|
4057
|
+
};
|
4058
|
+
return {
|
4059
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4060
|
+
content: /* @__PURE__ */ jsx(Flex, { gap: 2, width: "100%", children: /* @__PURE__ */ jsx(
|
4061
|
+
Button,
|
4062
|
+
{
|
4063
|
+
variant: "tertiary",
|
4064
|
+
tag: Link,
|
4065
|
+
to: { pathname: "preview", search: stringify(query, { encode: false }) },
|
4066
|
+
onClick: handleClick,
|
4067
|
+
flex: "auto",
|
4068
|
+
children: formatMessage({
|
4069
|
+
id: "content-manager.preview.panel.button",
|
4070
|
+
defaultMessage: "Open preview"
|
4071
|
+
})
|
4072
|
+
}
|
4073
|
+
) })
|
4074
|
+
};
|
4075
|
+
};
|
4076
|
+
const FEATURE_ID = "preview";
|
4077
|
+
const previewAdmin = {
|
4078
|
+
bootstrap(app) {
|
4079
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4080
|
+
return;
|
4081
|
+
}
|
4082
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4083
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4084
|
+
}
|
4085
|
+
};
|
3690
4086
|
const index = {
|
3691
4087
|
register(app) {
|
3692
4088
|
const cm = new ContentManagerPlugin();
|
@@ -3706,7 +4102,7 @@ const index = {
|
|
3706
4102
|
app.router.addRoute({
|
3707
4103
|
path: "content-manager/*",
|
3708
4104
|
lazy: async () => {
|
3709
|
-
const { Layout } = await import("./layout-
|
4105
|
+
const { Layout } = await import("./layout-D63qmUOu.mjs");
|
3710
4106
|
return {
|
3711
4107
|
Component: Layout
|
3712
4108
|
};
|
@@ -3715,10 +4111,18 @@ const index = {
|
|
3715
4111
|
});
|
3716
4112
|
app.registerPlugin(cm.config);
|
3717
4113
|
},
|
4114
|
+
bootstrap(app) {
|
4115
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4116
|
+
historyAdmin.bootstrap(app);
|
4117
|
+
}
|
4118
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4119
|
+
previewAdmin.bootstrap(app);
|
4120
|
+
}
|
4121
|
+
},
|
3718
4122
|
async registerTrads({ locales }) {
|
3719
4123
|
const importedTrads = await Promise.all(
|
3720
4124
|
locales.map((locale) => {
|
3721
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-CCEVvqGG.mjs"), "./translations/ca.json": () => import("./ca-5U32ON2v.mjs"), "./translations/cs.json": () => import("./cs-CM2aBUar.mjs"), "./translations/de.json": () => import("./de-C72KDNOl.mjs"), "./translations/en.json": () => import("./en-
|
4125
|
+
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-D_BMf0hT.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 }) => {
|
3722
4126
|
return {
|
3723
4127
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3724
4128
|
locale
|
@@ -3739,13 +4143,16 @@ export {
|
|
3739
4143
|
BulkActionsRenderer as B,
|
3740
4144
|
COLLECTION_TYPES as C,
|
3741
4145
|
DocumentStatus as D,
|
3742
|
-
|
3743
|
-
|
3744
|
-
|
4146
|
+
extractContentTypeComponents as E,
|
4147
|
+
DEFAULT_SETTINGS as F,
|
4148
|
+
convertEditLayoutToFieldLayouts as G,
|
3745
4149
|
HOOKS as H,
|
3746
4150
|
InjectionZone as I,
|
3747
|
-
|
3748
|
-
|
4151
|
+
useDocument as J,
|
4152
|
+
useGetPreviewUrlQuery as K,
|
4153
|
+
index as L,
|
4154
|
+
useContentManagerContext as M,
|
4155
|
+
useDocumentActions as N,
|
3749
4156
|
Panels as P,
|
3750
4157
|
RelativeTime as R,
|
3751
4158
|
SINGLE_TYPES as S,
|
@@ -3763,18 +4170,18 @@ export {
|
|
3763
4170
|
PERMISSIONS as k,
|
3764
4171
|
DocumentRBAC as l,
|
3765
4172
|
DOCUMENT_META_FIELDS as m,
|
3766
|
-
|
3767
|
-
|
3768
|
-
|
3769
|
-
|
3770
|
-
|
4173
|
+
CLONE_PATH as n,
|
4174
|
+
useDocLayout as o,
|
4175
|
+
useGetContentTypeConfigurationQuery as p,
|
4176
|
+
CREATOR_FIELDS as q,
|
4177
|
+
getMainField as r,
|
3771
4178
|
setInitialData as s,
|
3772
|
-
|
4179
|
+
getDisplayName as t,
|
3773
4180
|
useContentTypeSchema as u,
|
3774
|
-
|
3775
|
-
|
3776
|
-
|
3777
|
-
|
3778
|
-
|
4181
|
+
checkIfAttributeIsDisplayable as v,
|
4182
|
+
useGetAllDocumentsQuery as w,
|
4183
|
+
convertListLayoutToFieldLayouts as x,
|
4184
|
+
capitalise as y,
|
4185
|
+
useUpdateContentTypeConfigurationMutation as z
|
3779
4186
|
};
|
3780
|
-
//# sourceMappingURL=index-
|
4187
|
+
//# sourceMappingURL=index-DmNeuXH0.mjs.map
|