@strapi/content-manager 0.0.0-experimental.a65a85fdea97faae8679d3ffc5f9d79af61abd26 → 0.0.0-experimental.abc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -3
- package/dist/_chunks/{CardDragPreview-DSVYodBX.js → CardDragPreview-C0QyJgRA.js} +10 -14
- package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -0
- package/dist/_chunks/{CardDragPreview-ikSG4M46.mjs → CardDragPreview-DOxamsuj.mjs} +7 -9
- package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -0
- package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs → ComponentConfigurationPage-B3yDbeU1.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs.map → ComponentConfigurationPage-B3yDbeU1.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js → ComponentConfigurationPage-KXSuLnQD.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js.map → ComponentConfigurationPage-KXSuLnQD.js.map} +1 -1
- package/dist/_chunks/{ComponentIcon-BBQsYCVn.js → ComponentIcon-BXdiCGQp.js} +8 -2
- package/dist/_chunks/ComponentIcon-BXdiCGQp.js.map +1 -0
- package/dist/_chunks/{ComponentIcon-BOFnK76n.mjs → ComponentIcon-u4bIXTFY.mjs} +9 -3
- package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -0
- package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js → EditConfigurationPage-BQ17--5R.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js.map → EditConfigurationPage-BQ17--5R.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs → EditConfigurationPage-D7PrLO8j.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs.map → EditConfigurationPage-D7PrLO8j.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-Bm8lgcm6.mjs → EditViewPage-B7VgwJaG.mjs} +58 -47
- package/dist/_chunks/EditViewPage-B7VgwJaG.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-CzOT5Kpj.js → EditViewPage-BgjdnGz2.js} +57 -48
- package/dist/_chunks/EditViewPage-BgjdnGz2.js.map +1 -0
- package/dist/_chunks/{Field-Caef4JjM.js → Field-CdK7ZLmv.js} +1030 -800
- package/dist/_chunks/Field-CdK7ZLmv.js.map +1 -0
- package/dist/_chunks/{Field-Dlh0uGnL.mjs → Field-tHCw4lGA.mjs} +981 -750
- package/dist/_chunks/Field-tHCw4lGA.mjs.map +1 -0
- package/dist/_chunks/{Form-EnaQL_6L.mjs → Form-BJxdTv3Q.mjs} +56 -43
- package/dist/_chunks/Form-BJxdTv3Q.mjs.map +1 -0
- package/dist/_chunks/{Form-BzuAjtRq.js → Form-C_0KTVvV.js} +55 -43
- package/dist/_chunks/Form-C_0KTVvV.js.map +1 -0
- package/dist/_chunks/{History-D6sbCJvo.mjs → History-DR2txJLE.mjs} +151 -57
- package/dist/_chunks/History-DR2txJLE.mjs.map +1 -0
- package/dist/_chunks/{History-C17LiyRg.js → History-nuEzM5qm.js} +151 -58
- package/dist/_chunks/History-nuEzM5qm.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Dks5SX6f.js → ListConfigurationPage-CnB86Psm.js} +70 -61
- package/dist/_chunks/ListConfigurationPage-CnB86Psm.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Ce4qs7qE.mjs → ListConfigurationPage-voFVtXu6.mjs} +67 -57
- package/dist/_chunks/ListConfigurationPage-voFVtXu6.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-Be7S5aKL.mjs → ListViewPage-B_GaWgRH.mjs} +95 -106
- package/dist/_chunks/ListViewPage-B_GaWgRH.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-BwrZrPsh.js → ListViewPage-SXIXm-RM.js} +100 -111
- package/dist/_chunks/ListViewPage-SXIXm-RM.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-Cu5r1-JT.js → NoContentTypePage-BzsQ3hLZ.js} +5 -5
- package/dist/_chunks/NoContentTypePage-BzsQ3hLZ.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CIPmYQMm.mjs → NoContentTypePage-CYiGpsbj.mjs} +7 -7
- package/dist/_chunks/NoContentTypePage-CYiGpsbj.mjs.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-DhJ7LYrr.mjs → NoPermissionsPage-B5baIHal.mjs} +5 -6
- package/dist/_chunks/NoPermissionsPage-B5baIHal.mjs.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-C-j6TEUF.js → NoPermissionsPage-IGkId4C5.js} +4 -5
- package/dist/_chunks/NoPermissionsPage-IGkId4C5.js.map +1 -0
- package/dist/_chunks/{Relations-CY7AtkDA.mjs → Relations-CIYDdKU-.mjs} +67 -57
- package/dist/_chunks/Relations-CIYDdKU-.mjs.map +1 -0
- package/dist/_chunks/{Relations-Czs-uZ-s.js → Relations-Dhuurpx2.js} +71 -62
- package/dist/_chunks/Relations-Dhuurpx2.js.map +1 -0
- package/dist/_chunks/{en-MBPul9Su.mjs → en-BrCTWlZv.mjs} +11 -4
- package/dist/_chunks/{en-MBPul9Su.mjs.map → en-BrCTWlZv.mjs.map} +1 -1
- package/dist/_chunks/{en-C-V1_90f.js → en-uOUIxfcQ.js} +11 -4
- package/dist/_chunks/{en-C-V1_90f.js.map → en-uOUIxfcQ.js.map} +1 -1
- package/dist/_chunks/{index-DNVx8ssZ.mjs → index-C9TJPyni.mjs} +1696 -912
- package/dist/_chunks/index-C9TJPyni.mjs.map +1 -0
- package/dist/_chunks/{index-X_2tafck.js → index-CdT0kHZ8.js} +1626 -843
- package/dist/_chunks/index-CdT0kHZ8.js.map +1 -0
- package/dist/_chunks/{layout-Dnh0PNp9.mjs → layout-BNqvLR_b.mjs} +45 -28
- package/dist/_chunks/layout-BNqvLR_b.mjs.map +1 -0
- package/dist/_chunks/{layout-dBc7wN7L.js → layout-C6dxWYT7.js} +45 -30
- package/dist/_chunks/layout-C6dxWYT7.js.map +1 -0
- package/dist/_chunks/{relations-Dx7tMKJN.mjs → relations-CkKqKw65.mjs} +2 -2
- package/dist/_chunks/{relations-Dx7tMKJN.mjs.map → relations-CkKqKw65.mjs.map} +1 -1
- package/dist/_chunks/{relations-4pHtBrHJ.js → relations-DtFaDnP1.js} +2 -2
- package/dist/_chunks/{relations-4pHtBrHJ.js.map → relations-DtFaDnP1.js.map} +1 -1
- package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
- package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js +15 -0
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -0
- package/dist/_chunks/usePrev-DH6iah0A.mjs +16 -0
- package/dist/_chunks/usePrev-DH6iah0A.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/components/ComponentIcon.d.ts +6 -3
- package/dist/admin/src/content-manager.d.ts +3 -3
- package/dist/admin/src/exports.d.ts +1 -0
- package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +5 -8
- package/dist/admin/src/hooks/useDocumentActions.d.ts +24 -3
- package/dist/admin/src/hooks/useDocumentLayout.d.ts +2 -2
- package/dist/admin/src/hooks/useDragAndDrop.d.ts +4 -4
- package/dist/admin/src/hooks/useKeyboardDragAndDrop.d.ts +1 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +11 -4
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksInput.d.ts +3 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Component/Input.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/ComponentCategory.d.ts +3 -5
- package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +30 -18
- package/dist/admin/src/pages/EditView/components/FormInputs/UID.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +3 -49
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/Field.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 +48 -53
- package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +2 -10
- package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
- package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
- package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +9 -26
- package/dist/admin/src/services/api.d.ts +2 -3
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +5 -5
- package/dist/admin/src/services/documents.d.ts +29 -17
- package/dist/admin/src/services/init.d.ts +2 -2
- package/dist/admin/src/services/relations.d.ts +3 -3
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/api.d.ts +4 -18
- package/dist/admin/src/utils/validation.d.ts +1 -6
- package/dist/server/index.js +602 -426
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +610 -434
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/single-types.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 +8 -0
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/dimensions.d.ts +11 -0
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -0
- package/dist/server/src/controllers/validation/index.d.ts +1 -1
- package/dist/server/src/history/services/history.d.ts +2 -4
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/index.d.ts +6 -2
- package/dist/server/src/history/services/index.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts +9 -0
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -0
- package/dist/server/src/history/services/utils.d.ts +41 -9
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/history/utils.d.ts +6 -2
- package/dist/server/src/history/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +18 -39
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts +13 -12
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -29
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +18 -39
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts +8 -1
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +14 -6
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/relations.d.ts +2 -2
- package/dist/shared/contracts/relations.d.ts.map +1 -1
- package/package.json +13 -14
- package/dist/_chunks/CardDragPreview-DSVYodBX.js.map +0 -1
- package/dist/_chunks/CardDragPreview-ikSG4M46.mjs.map +0 -1
- package/dist/_chunks/ComponentIcon-BBQsYCVn.js.map +0 -1
- package/dist/_chunks/ComponentIcon-BOFnK76n.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-Bm8lgcm6.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-CzOT5Kpj.js.map +0 -1
- package/dist/_chunks/Field-Caef4JjM.js.map +0 -1
- package/dist/_chunks/Field-Dlh0uGnL.mjs.map +0 -1
- package/dist/_chunks/Form-BzuAjtRq.js.map +0 -1
- package/dist/_chunks/Form-EnaQL_6L.mjs.map +0 -1
- package/dist/_chunks/History-C17LiyRg.js.map +0 -1
- package/dist/_chunks/History-D6sbCJvo.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Ce4qs7qE.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Dks5SX6f.js.map +0 -1
- package/dist/_chunks/ListViewPage-Be7S5aKL.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-BwrZrPsh.js.map +0 -1
- package/dist/_chunks/NoContentTypePage-CIPmYQMm.mjs.map +0 -1
- package/dist/_chunks/NoContentTypePage-Cu5r1-JT.js.map +0 -1
- package/dist/_chunks/NoPermissionsPage-C-j6TEUF.js.map +0 -1
- package/dist/_chunks/NoPermissionsPage-DhJ7LYrr.mjs.map +0 -1
- package/dist/_chunks/Relations-CY7AtkDA.mjs.map +0 -1
- package/dist/_chunks/Relations-Czs-uZ-s.js.map +0 -1
- package/dist/_chunks/index-DNVx8ssZ.mjs.map +0 -1
- package/dist/_chunks/index-X_2tafck.js.map +0 -1
- package/dist/_chunks/layout-Dnh0PNp9.mjs.map +0 -1
- package/dist/_chunks/layout-dBc7wN7L.js.map +0 -1
- package/dist/_chunks/urls-CbOsUOoW.mjs +0 -7
- package/dist/_chunks/urls-CbOsUOoW.mjs.map +0 -1
- package/dist/_chunks/urls-DzZya_gm.js +0 -6
- package/dist/_chunks/urls-DzZya_gm.js.map +0 -1
- package/dist/server/src/controllers/utils/dimensions.d.ts +0 -5
- package/dist/server/src/controllers/utils/dimensions.d.ts.map +0 -1
@@ -1,19 +1,17 @@
|
|
1
|
-
import {
|
1
|
+
import { CrossCircle, More, WarningCircle, ListPlus, Pencil, Trash, Check, 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, NavLink } from "react-router-dom";
|
3
|
+
import { useStrapiApp, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, getYupValidationErrors, useQueryParams, useTracking, useForm, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
|
7
4
|
import * as React from "react";
|
8
5
|
import { lazy } from "react";
|
9
|
-
import { Menu, VisuallyHidden, Flex, Typography, Dialog,
|
10
|
-
import
|
6
|
+
import { Menu, Button, VisuallyHidden, Flex, Typography, Dialog, Modal, Radio, Status, Box, SingleSelect, SingleSelectOption, Loader, IconButton, Tooltip, LinkButton } from "@strapi/design-system";
|
7
|
+
import { useIntl } from "react-intl";
|
8
|
+
import { useParams, Navigate, useNavigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
9
|
+
import { styled } from "styled-components";
|
11
10
|
import * as yup from "yup";
|
12
11
|
import { ValidationError } from "yup";
|
13
|
-
import { createApi } from "@reduxjs/toolkit/query/react";
|
14
|
-
import { isAxiosError } from "axios";
|
15
12
|
import pipe from "lodash/fp/pipe";
|
16
13
|
import { intervalToDuration, isPast } from "date-fns";
|
14
|
+
import { stringify } from "qs";
|
17
15
|
import { createSlice, combineReducers } from "@reduxjs/toolkit";
|
18
16
|
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
19
17
|
const v = glob[path];
|
@@ -51,42 +49,6 @@ const useInjectionZone = (area) => {
|
|
51
49
|
const [page, position] = area.split(".");
|
52
50
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
53
51
|
};
|
54
|
-
const HistoryAction = ({ model, document }) => {
|
55
|
-
const { formatMessage } = useIntl();
|
56
|
-
const [{ query }] = useQueryParams();
|
57
|
-
const navigate = useNavigate();
|
58
|
-
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
59
|
-
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
60
|
-
return null;
|
61
|
-
}
|
62
|
-
return {
|
63
|
-
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
64
|
-
label: formatMessage({
|
65
|
-
id: "content-manager.history.document-action",
|
66
|
-
defaultMessage: "Content History"
|
67
|
-
}),
|
68
|
-
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
69
|
-
disabled: (
|
70
|
-
/**
|
71
|
-
* The user is creating a new document.
|
72
|
-
* It hasn't been saved yet, so there's no history to go to
|
73
|
-
*/
|
74
|
-
!document || /**
|
75
|
-
* The document has been created but the current dimension has never been saved.
|
76
|
-
* For example, the user is creating a new locale in an existing document,
|
77
|
-
* so there's no history for the document in that locale
|
78
|
-
*/
|
79
|
-
!document.id || /**
|
80
|
-
* History is only available for content types created by the user.
|
81
|
-
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
82
|
-
* which start with `admin::` or `plugin::`
|
83
|
-
*/
|
84
|
-
!model.startsWith("api::")
|
85
|
-
),
|
86
|
-
position: "header"
|
87
|
-
};
|
88
|
-
};
|
89
|
-
HistoryAction.type = "history";
|
90
52
|
const ID = "id";
|
91
53
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
92
54
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -157,9 +119,8 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
157
119
|
const name = removeNumericalStrings(fieldName.split("."));
|
158
120
|
const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
|
159
121
|
if (fieldType === "component") {
|
160
|
-
|
161
|
-
|
162
|
-
return field.includes(fieldName);
|
122
|
+
return componentFieldNames.some((field) => {
|
123
|
+
return field.includes(name.join("."));
|
163
124
|
});
|
164
125
|
}
|
165
126
|
if (name.length > 1) {
|
@@ -189,78 +150,8 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
|
|
189
150
|
(field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
|
190
151
|
);
|
191
152
|
const removeNumericalStrings = (arr) => arr.filter((item) => isNaN(Number(item)));
|
192
|
-
const
|
193
|
-
|
194
|
-
return query;
|
195
|
-
const { plugins: _, ...validQueryParams } = {
|
196
|
-
...query,
|
197
|
-
...Object.values(query?.plugins ?? {}).reduce(
|
198
|
-
(acc, current) => Object.assign(acc, current),
|
199
|
-
{}
|
200
|
-
)
|
201
|
-
};
|
202
|
-
if ("_q" in validQueryParams) {
|
203
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
204
|
-
}
|
205
|
-
return validQueryParams;
|
206
|
-
};
|
207
|
-
const axiosBaseQuery = () => async (query, { signal }) => {
|
208
|
-
try {
|
209
|
-
const { get, post, del, put } = getFetchClient();
|
210
|
-
if (typeof query === "string") {
|
211
|
-
const result = await get(query, { signal });
|
212
|
-
return { data: result.data };
|
213
|
-
} else {
|
214
|
-
const { url, method = "GET", data, config } = query;
|
215
|
-
if (method === "POST") {
|
216
|
-
const result2 = await post(url, data, { ...config, signal });
|
217
|
-
return { data: result2.data };
|
218
|
-
}
|
219
|
-
if (method === "DELETE") {
|
220
|
-
const result2 = await del(url, { ...config, signal });
|
221
|
-
return { data: result2.data };
|
222
|
-
}
|
223
|
-
if (method === "PUT") {
|
224
|
-
const result2 = await put(url, data, { ...config, signal });
|
225
|
-
return { data: result2.data };
|
226
|
-
}
|
227
|
-
const result = await get(url, { ...config, signal });
|
228
|
-
return { data: result.data };
|
229
|
-
}
|
230
|
-
} catch (err) {
|
231
|
-
if (isAxiosError(err)) {
|
232
|
-
if (typeof err.response?.data === "object" && err.response?.data !== null && "error" in err.response?.data) {
|
233
|
-
return { data: void 0, error: err.response?.data.error };
|
234
|
-
} else {
|
235
|
-
return {
|
236
|
-
data: void 0,
|
237
|
-
error: {
|
238
|
-
name: "UnknownError",
|
239
|
-
message: "There was an unknown error response from the API",
|
240
|
-
details: err.response?.data,
|
241
|
-
status: err.response?.status
|
242
|
-
}
|
243
|
-
};
|
244
|
-
}
|
245
|
-
}
|
246
|
-
const error = err;
|
247
|
-
return {
|
248
|
-
data: void 0,
|
249
|
-
error: {
|
250
|
-
name: error.name,
|
251
|
-
message: error.message,
|
252
|
-
stack: error.stack
|
253
|
-
}
|
254
|
-
};
|
255
|
-
}
|
256
|
-
};
|
257
|
-
const isBaseQueryError = (error) => {
|
258
|
-
return error.name !== void 0;
|
259
|
-
};
|
260
|
-
const contentManagerApi = createApi({
|
261
|
-
reducerPath: "contentManagerApi",
|
262
|
-
baseQuery: axiosBaseQuery(),
|
263
|
-
tagTypes: [
|
153
|
+
const contentManagerApi = adminApi.enhanceEndpoints({
|
154
|
+
addTagTypes: [
|
264
155
|
"ComponentConfiguration",
|
265
156
|
"ContentTypesConfiguration",
|
266
157
|
"ContentTypeSettings",
|
@@ -268,10 +159,10 @@ const contentManagerApi = createApi({
|
|
268
159
|
"InitialData",
|
269
160
|
"HistoryVersion",
|
270
161
|
"Relations"
|
271
|
-
]
|
272
|
-
endpoints: () => ({})
|
162
|
+
]
|
273
163
|
});
|
274
164
|
const documentApi = contentManagerApi.injectEndpoints({
|
165
|
+
overrideExisting: true,
|
275
166
|
endpoints: (builder) => ({
|
276
167
|
autoCloneDocument: builder.mutation({
|
277
168
|
query: ({ model, sourceId, query }) => ({
|
@@ -281,7 +172,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
281
172
|
params: query
|
282
173
|
}
|
283
174
|
}),
|
284
|
-
invalidatesTags: (_result,
|
175
|
+
invalidatesTags: (_result, error, { model }) => {
|
176
|
+
if (error) {
|
177
|
+
return [];
|
178
|
+
}
|
179
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
180
|
+
}
|
285
181
|
}),
|
286
182
|
cloneDocument: builder.mutation({
|
287
183
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -325,12 +221,15 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
325
221
|
]
|
326
222
|
}),
|
327
223
|
deleteManyDocuments: builder.mutation({
|
328
|
-
query: ({ model, ...body }) => ({
|
224
|
+
query: ({ model, params, ...body }) => ({
|
329
225
|
url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
|
330
226
|
method: "POST",
|
331
|
-
data: body
|
227
|
+
data: body,
|
228
|
+
config: {
|
229
|
+
params
|
230
|
+
}
|
332
231
|
}),
|
333
|
-
invalidatesTags: (_res, _error, { model
|
232
|
+
invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
|
334
233
|
}),
|
335
234
|
discardDocument: builder.mutation({
|
336
235
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -365,6 +264,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
365
264
|
}),
|
366
265
|
providesTags: (result, _error, arg) => {
|
367
266
|
return [
|
267
|
+
{ type: "Document", id: `ALL_LIST` },
|
368
268
|
{ type: "Document", id: `${arg.model}_LIST` },
|
369
269
|
...result?.results.map(({ documentId }) => ({
|
370
270
|
type: "Document",
|
@@ -403,6 +303,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
403
303
|
{
|
404
304
|
type: "Document",
|
405
305
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
306
|
+
},
|
307
|
+
// Make it easy to invalidate all individual documents queries for a model
|
308
|
+
{
|
309
|
+
type: "Document",
|
310
|
+
id: `${model}_ALL_ITEMS`
|
406
311
|
}
|
407
312
|
];
|
408
313
|
}
|
@@ -441,10 +346,13 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
441
346
|
}
|
442
347
|
}),
|
443
348
|
publishManyDocuments: builder.mutation({
|
444
|
-
query: ({ model, ...body }) => ({
|
349
|
+
query: ({ model, params, ...body }) => ({
|
445
350
|
url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
|
446
351
|
method: "POST",
|
447
|
-
data: body
|
352
|
+
data: body,
|
353
|
+
config: {
|
354
|
+
params
|
355
|
+
}
|
448
356
|
}),
|
449
357
|
invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
|
450
358
|
}),
|
@@ -465,6 +373,18 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
465
373
|
},
|
466
374
|
"Relations"
|
467
375
|
];
|
376
|
+
},
|
377
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
378
|
+
const patchResult = dispatch(
|
379
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
380
|
+
Object.assign(draft.data, data);
|
381
|
+
})
|
382
|
+
);
|
383
|
+
try {
|
384
|
+
await queryFulfilled;
|
385
|
+
} catch {
|
386
|
+
patchResult.undo();
|
387
|
+
}
|
468
388
|
}
|
469
389
|
}),
|
470
390
|
unpublishDocument: builder.mutation({
|
@@ -486,10 +406,13 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
486
406
|
}
|
487
407
|
}),
|
488
408
|
unpublishManyDocuments: builder.mutation({
|
489
|
-
query: ({ model, ...body }) => ({
|
409
|
+
query: ({ model, params, ...body }) => ({
|
490
410
|
url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
|
491
411
|
method: "POST",
|
492
|
-
data: body
|
412
|
+
data: body,
|
413
|
+
config: {
|
414
|
+
params
|
415
|
+
}
|
493
416
|
}),
|
494
417
|
invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
|
495
418
|
})
|
@@ -513,6 +436,24 @@ const {
|
|
513
436
|
useUnpublishDocumentMutation,
|
514
437
|
useUnpublishManyDocumentsMutation
|
515
438
|
} = documentApi;
|
439
|
+
const buildValidParams = (query) => {
|
440
|
+
if (!query)
|
441
|
+
return query;
|
442
|
+
const { plugins: _, ...validQueryParams } = {
|
443
|
+
...query,
|
444
|
+
...Object.values(query?.plugins ?? {}).reduce(
|
445
|
+
(acc, current) => Object.assign(acc, current),
|
446
|
+
{}
|
447
|
+
)
|
448
|
+
};
|
449
|
+
if ("_q" in validQueryParams) {
|
450
|
+
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
451
|
+
}
|
452
|
+
return validQueryParams;
|
453
|
+
};
|
454
|
+
const isBaseQueryError = (error) => {
|
455
|
+
return error.name !== void 0;
|
456
|
+
};
|
516
457
|
const createYupSchema = (attributes = {}, components = {}) => {
|
517
458
|
const createModelSchema = (attributes2) => yup.object().shape(
|
518
459
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
@@ -552,10 +493,14 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
552
493
|
yup.array().of(
|
553
494
|
yup.lazy(
|
554
495
|
(data) => {
|
555
|
-
const
|
556
|
-
|
496
|
+
const attributes3 = components?.[data?.__component]?.attributes;
|
497
|
+
const validation = yup.object().shape({
|
557
498
|
__component: yup.string().required().oneOf(Object.keys(components))
|
558
|
-
}).nullable(false)
|
499
|
+
}).nullable(false);
|
500
|
+
if (!attributes3) {
|
501
|
+
return validation;
|
502
|
+
}
|
503
|
+
return validation.concat(createModelSchema(attributes3));
|
559
504
|
}
|
560
505
|
)
|
561
506
|
)
|
@@ -565,11 +510,25 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
565
510
|
return {
|
566
511
|
...acc,
|
567
512
|
[name]: transformSchema(
|
568
|
-
yup.
|
569
|
-
|
570
|
-
|
571
|
-
})
|
572
|
-
|
513
|
+
yup.lazy((value) => {
|
514
|
+
if (!value) {
|
515
|
+
return yup.mixed().nullable(true);
|
516
|
+
} else if (Array.isArray(value)) {
|
517
|
+
return yup.array().of(
|
518
|
+
yup.object().shape({
|
519
|
+
id: yup.string().required()
|
520
|
+
})
|
521
|
+
);
|
522
|
+
} else if (typeof value === "object") {
|
523
|
+
return yup.object();
|
524
|
+
} else {
|
525
|
+
return yup.mixed().test(
|
526
|
+
"type-error",
|
527
|
+
"Relation values must be either null, an array of objects with {id} or an object.",
|
528
|
+
() => false
|
529
|
+
);
|
530
|
+
}
|
531
|
+
})
|
573
532
|
)
|
574
533
|
};
|
575
534
|
default:
|
@@ -609,6 +568,14 @@ const createAttributeSchema = (attribute) => {
|
|
609
568
|
if (!value || typeof value === "string" && value.length === 0) {
|
610
569
|
return true;
|
611
570
|
}
|
571
|
+
if (typeof value === "object") {
|
572
|
+
try {
|
573
|
+
JSON.stringify(value);
|
574
|
+
return true;
|
575
|
+
} catch (err) {
|
576
|
+
return false;
|
577
|
+
}
|
578
|
+
}
|
612
579
|
try {
|
613
580
|
JSON.parse(value);
|
614
581
|
return true;
|
@@ -628,13 +595,18 @@ const createAttributeSchema = (attribute) => {
|
|
628
595
|
}
|
629
596
|
};
|
630
597
|
const addRequiredValidation = (attribute) => (schema) => {
|
631
|
-
if (attribute.required) {
|
632
|
-
return schema.required
|
633
|
-
|
634
|
-
|
635
|
-
|
598
|
+
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
599
|
+
return schema.min(1, translatedErrors.required);
|
600
|
+
}
|
601
|
+
if (attribute.required && attribute.type !== "relation") {
|
602
|
+
return schema.required(translatedErrors.required);
|
636
603
|
}
|
637
|
-
return schema.nullable()
|
604
|
+
return schema?.nullable ? schema.nullable() : (
|
605
|
+
// In some cases '.nullable' will not be available on the schema.
|
606
|
+
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
607
|
+
// In these cases we should just return the schema as it is.
|
608
|
+
schema
|
609
|
+
);
|
638
610
|
};
|
639
611
|
const addMinLengthValidation = (attribute) => (schema) => {
|
640
612
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
@@ -661,6 +633,28 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
661
633
|
const addMinValidation = (attribute) => (schema) => {
|
662
634
|
if ("min" in attribute) {
|
663
635
|
const min = toInteger(attribute.min);
|
636
|
+
if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
|
637
|
+
if (!attribute.required && "test" in schema && min) {
|
638
|
+
return schema.test(
|
639
|
+
"custom-min",
|
640
|
+
{
|
641
|
+
...translatedErrors.min,
|
642
|
+
values: {
|
643
|
+
min: attribute.min
|
644
|
+
}
|
645
|
+
},
|
646
|
+
(value) => {
|
647
|
+
if (!value) {
|
648
|
+
return true;
|
649
|
+
}
|
650
|
+
if (Array.isArray(value) && value.length === 0) {
|
651
|
+
return true;
|
652
|
+
}
|
653
|
+
return value.length >= min;
|
654
|
+
}
|
655
|
+
);
|
656
|
+
}
|
657
|
+
}
|
664
658
|
if ("min" in schema && min) {
|
665
659
|
return schema.min(min, {
|
666
660
|
...translatedErrors.min,
|
@@ -706,24 +700,6 @@ const addRegexValidation = (attribute) => (schema) => {
|
|
706
700
|
}
|
707
701
|
return schema;
|
708
702
|
};
|
709
|
-
const extractValuesFromYupError = (errorType, errorParams) => {
|
710
|
-
if (!errorType || !errorParams) {
|
711
|
-
return {};
|
712
|
-
}
|
713
|
-
return {
|
714
|
-
[errorType]: errorParams[errorType]
|
715
|
-
};
|
716
|
-
};
|
717
|
-
const getInnerErrors = (error) => (error?.inner || []).reduce((acc, currentError) => {
|
718
|
-
if (currentError.path) {
|
719
|
-
acc[currentError.path.split("[").join(".").split("]").join("")] = {
|
720
|
-
id: currentError.message,
|
721
|
-
defaultMessage: currentError.message,
|
722
|
-
values: extractValuesFromYupError(currentError?.type, currentError?.params)
|
723
|
-
};
|
724
|
-
}
|
725
|
-
return acc;
|
726
|
-
}, {});
|
727
703
|
const initApi = contentManagerApi.injectEndpoints({
|
728
704
|
endpoints: (builder) => ({
|
729
705
|
getInitialData: builder.query({
|
@@ -737,27 +713,20 @@ const { useGetInitialDataQuery } = initApi;
|
|
737
713
|
const useContentTypeSchema = (model) => {
|
738
714
|
const { toggleNotification } = useNotification();
|
739
715
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
740
|
-
const {
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
)
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
error: res.error,
|
755
|
-
components: Object.keys(components2).length === 0 ? void 0 : components2,
|
756
|
-
contentType: contentType2,
|
757
|
-
contentTypes: res.data?.contentTypes ?? []
|
758
|
-
};
|
759
|
-
}
|
760
|
-
});
|
716
|
+
const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
|
717
|
+
const { components, contentType, contentTypes } = React.useMemo(() => {
|
718
|
+
const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
|
719
|
+
const componentsByKey = data?.components.reduce((acc, component) => {
|
720
|
+
acc[component.uid] = component;
|
721
|
+
return acc;
|
722
|
+
}, {});
|
723
|
+
const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
|
724
|
+
return {
|
725
|
+
components: Object.keys(components2).length === 0 ? void 0 : components2,
|
726
|
+
contentType: contentType2,
|
727
|
+
contentTypes: data?.contentTypes ?? []
|
728
|
+
};
|
729
|
+
}, [model, data]);
|
761
730
|
React.useEffect(() => {
|
762
731
|
if (error) {
|
763
732
|
toggleNotification({
|
@@ -812,7 +781,10 @@ const useDocument = (args, opts) => {
|
|
812
781
|
isLoading: isLoadingDocument,
|
813
782
|
isFetching: isFetchingDocument,
|
814
783
|
error
|
815
|
-
} = useGetDocumentQuery(args,
|
784
|
+
} = useGetDocumentQuery(args, {
|
785
|
+
...opts,
|
786
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
787
|
+
});
|
816
788
|
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
817
789
|
React.useEffect(() => {
|
818
790
|
if (error) {
|
@@ -840,7 +812,7 @@ const useDocument = (args, opts) => {
|
|
840
812
|
return null;
|
841
813
|
} catch (error2) {
|
842
814
|
if (error2 instanceof ValidationError) {
|
843
|
-
return
|
815
|
+
return getYupValidationErrors(error2);
|
844
816
|
}
|
845
817
|
throw error2;
|
846
818
|
}
|
@@ -936,14 +908,53 @@ const useDocumentActions = () => {
|
|
936
908
|
},
|
937
909
|
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
938
910
|
);
|
911
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
912
|
+
const deleteMany = React.useCallback(
|
913
|
+
async ({ model, documentIds, params }) => {
|
914
|
+
try {
|
915
|
+
trackUsage("willBulkDeleteEntries");
|
916
|
+
const res = await deleteManyDocuments({
|
917
|
+
model,
|
918
|
+
documentIds,
|
919
|
+
params
|
920
|
+
});
|
921
|
+
if ("error" in res) {
|
922
|
+
toggleNotification({
|
923
|
+
type: "danger",
|
924
|
+
message: formatAPIError(res.error)
|
925
|
+
});
|
926
|
+
return { error: res.error };
|
927
|
+
}
|
928
|
+
toggleNotification({
|
929
|
+
type: "success",
|
930
|
+
title: formatMessage({
|
931
|
+
id: getTranslation("success.records.delete"),
|
932
|
+
defaultMessage: "Successfully deleted."
|
933
|
+
}),
|
934
|
+
message: ""
|
935
|
+
});
|
936
|
+
trackUsage("didBulkDeleteEntries");
|
937
|
+
return res.data;
|
938
|
+
} catch (err) {
|
939
|
+
toggleNotification({
|
940
|
+
type: "danger",
|
941
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
942
|
+
});
|
943
|
+
trackUsage("didNotBulkDeleteEntries");
|
944
|
+
throw err;
|
945
|
+
}
|
946
|
+
},
|
947
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
948
|
+
);
|
939
949
|
const [discardDocument] = useDiscardDocumentMutation();
|
940
950
|
const discard = React.useCallback(
|
941
|
-
async ({ collectionType, model, documentId }) => {
|
951
|
+
async ({ collectionType, model, documentId, params }) => {
|
942
952
|
try {
|
943
953
|
const res = await discardDocument({
|
944
954
|
collectionType,
|
945
955
|
model,
|
946
|
-
documentId
|
956
|
+
documentId,
|
957
|
+
params
|
947
958
|
});
|
948
959
|
if ("error" in res) {
|
949
960
|
toggleNotification({
|
@@ -1005,6 +1016,43 @@ const useDocumentActions = () => {
|
|
1005
1016
|
},
|
1006
1017
|
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1007
1018
|
);
|
1019
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1020
|
+
const publishMany = React.useCallback(
|
1021
|
+
async ({ model, documentIds, params }) => {
|
1022
|
+
try {
|
1023
|
+
const res = await publishManyDocuments({
|
1024
|
+
model,
|
1025
|
+
documentIds,
|
1026
|
+
params
|
1027
|
+
});
|
1028
|
+
if ("error" in res) {
|
1029
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1030
|
+
return { error: res.error };
|
1031
|
+
}
|
1032
|
+
toggleNotification({
|
1033
|
+
type: "success",
|
1034
|
+
message: formatMessage({
|
1035
|
+
id: getTranslation("success.record.publish"),
|
1036
|
+
defaultMessage: "Published document"
|
1037
|
+
})
|
1038
|
+
});
|
1039
|
+
return res.data;
|
1040
|
+
} catch (err) {
|
1041
|
+
toggleNotification({
|
1042
|
+
type: "danger",
|
1043
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1044
|
+
});
|
1045
|
+
throw err;
|
1046
|
+
}
|
1047
|
+
},
|
1048
|
+
[
|
1049
|
+
// trackUsage,
|
1050
|
+
publishManyDocuments,
|
1051
|
+
toggleNotification,
|
1052
|
+
formatMessage,
|
1053
|
+
formatAPIError
|
1054
|
+
]
|
1055
|
+
);
|
1008
1056
|
const [updateDocument] = useUpdateDocumentMutation();
|
1009
1057
|
const update = React.useCallback(
|
1010
1058
|
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
@@ -1079,6 +1127,41 @@ const useDocumentActions = () => {
|
|
1079
1127
|
},
|
1080
1128
|
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1081
1129
|
);
|
1130
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1131
|
+
const unpublishMany = React.useCallback(
|
1132
|
+
async ({ model, documentIds, params }) => {
|
1133
|
+
try {
|
1134
|
+
trackUsage("willBulkUnpublishEntries");
|
1135
|
+
const res = await unpublishManyDocuments({
|
1136
|
+
model,
|
1137
|
+
documentIds,
|
1138
|
+
params
|
1139
|
+
});
|
1140
|
+
if ("error" in res) {
|
1141
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1142
|
+
return { error: res.error };
|
1143
|
+
}
|
1144
|
+
trackUsage("didBulkUnpublishEntries");
|
1145
|
+
toggleNotification({
|
1146
|
+
type: "success",
|
1147
|
+
title: formatMessage({
|
1148
|
+
id: getTranslation("success.records.unpublish"),
|
1149
|
+
defaultMessage: "Successfully unpublished."
|
1150
|
+
}),
|
1151
|
+
message: ""
|
1152
|
+
});
|
1153
|
+
return res.data;
|
1154
|
+
} catch (err) {
|
1155
|
+
toggleNotification({
|
1156
|
+
type: "danger",
|
1157
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1158
|
+
});
|
1159
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1160
|
+
throw err;
|
1161
|
+
}
|
1162
|
+
},
|
1163
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1164
|
+
);
|
1082
1165
|
const [createDocument] = useCreateDocumentMutation();
|
1083
1166
|
const create = React.useCallback(
|
1084
1167
|
async ({ model, params }, data, trackerProperty) => {
|
@@ -1122,7 +1205,6 @@ const useDocumentActions = () => {
|
|
1122
1205
|
sourceId
|
1123
1206
|
});
|
1124
1207
|
if ("error" in res) {
|
1125
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1126
1208
|
return { error: res.error };
|
1127
1209
|
}
|
1128
1210
|
toggleNotification({
|
@@ -1192,15 +1274,18 @@ const useDocumentActions = () => {
|
|
1192
1274
|
clone,
|
1193
1275
|
create,
|
1194
1276
|
delete: _delete,
|
1277
|
+
deleteMany,
|
1195
1278
|
discard,
|
1196
1279
|
getDocument,
|
1197
1280
|
publish,
|
1281
|
+
publishMany,
|
1198
1282
|
unpublish,
|
1283
|
+
unpublishMany,
|
1199
1284
|
update
|
1200
1285
|
};
|
1201
1286
|
};
|
1202
1287
|
const ProtectedHistoryPage = lazy(
|
1203
|
-
() => import("./History-
|
1288
|
+
() => import("./History-DR2txJLE.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1204
1289
|
);
|
1205
1290
|
const routes$1 = [
|
1206
1291
|
{
|
@@ -1213,31 +1298,31 @@ const routes$1 = [
|
|
1213
1298
|
}
|
1214
1299
|
];
|
1215
1300
|
const ProtectedEditViewPage = lazy(
|
1216
|
-
() => import("./EditViewPage-
|
1301
|
+
() => import("./EditViewPage-B7VgwJaG.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1217
1302
|
);
|
1218
1303
|
const ProtectedListViewPage = lazy(
|
1219
|
-
() => import("./ListViewPage-
|
1304
|
+
() => import("./ListViewPage-B_GaWgRH.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1220
1305
|
);
|
1221
1306
|
const ProtectedListConfiguration = lazy(
|
1222
|
-
() => import("./ListConfigurationPage-
|
1307
|
+
() => import("./ListConfigurationPage-voFVtXu6.mjs").then((mod) => ({
|
1223
1308
|
default: mod.ProtectedListConfiguration
|
1224
1309
|
}))
|
1225
1310
|
);
|
1226
1311
|
const ProtectedEditConfigurationPage = lazy(
|
1227
|
-
() => import("./EditConfigurationPage-
|
1312
|
+
() => import("./EditConfigurationPage-D7PrLO8j.mjs").then((mod) => ({
|
1228
1313
|
default: mod.ProtectedEditConfigurationPage
|
1229
1314
|
}))
|
1230
1315
|
);
|
1231
1316
|
const ProtectedComponentConfigurationPage = lazy(
|
1232
|
-
() => import("./ComponentConfigurationPage
|
1317
|
+
() => import("./ComponentConfigurationPage-B3yDbeU1.mjs").then((mod) => ({
|
1233
1318
|
default: mod.ProtectedComponentConfigurationPage
|
1234
1319
|
}))
|
1235
1320
|
);
|
1236
1321
|
const NoPermissions = lazy(
|
1237
|
-
() => import("./NoPermissionsPage-
|
1322
|
+
() => import("./NoPermissionsPage-B5baIHal.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1238
1323
|
);
|
1239
1324
|
const NoContentType = lazy(
|
1240
|
-
() => import("./NoContentTypePage-
|
1325
|
+
() => import("./NoContentTypePage-CYiGpsbj.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1241
1326
|
);
|
1242
1327
|
const CollectionTypePages = () => {
|
1243
1328
|
const { collectionType } = useParams();
|
@@ -1351,12 +1436,14 @@ const DocumentActionButton = (action) => {
|
|
1351
1436
|
/* @__PURE__ */ jsx(
|
1352
1437
|
Button,
|
1353
1438
|
{
|
1354
|
-
flex:
|
1439
|
+
flex: "auto",
|
1355
1440
|
startIcon: action.icon,
|
1356
1441
|
disabled: action.disabled,
|
1357
1442
|
onClick: handleClick(action),
|
1358
1443
|
justifyContent: "center",
|
1359
1444
|
variant: action.variant || "default",
|
1445
|
+
paddingTop: "7px",
|
1446
|
+
paddingBottom: "7px",
|
1360
1447
|
children: action.label
|
1361
1448
|
}
|
1362
1449
|
),
|
@@ -1364,7 +1451,7 @@ const DocumentActionButton = (action) => {
|
|
1364
1451
|
DocumentActionConfirmDialog,
|
1365
1452
|
{
|
1366
1453
|
...action.dialog,
|
1367
|
-
variant: action.variant,
|
1454
|
+
variant: action.dialog?.variant ?? action.variant,
|
1368
1455
|
isOpen: dialogId === action.id,
|
1369
1456
|
onClose: handleClose
|
1370
1457
|
}
|
@@ -1416,18 +1503,18 @@ const DocumentActionsMenu = ({
|
|
1416
1503
|
};
|
1417
1504
|
return /* @__PURE__ */ jsxs(Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1418
1505
|
/* @__PURE__ */ jsxs(
|
1419
|
-
|
1506
|
+
StyledMoreButton,
|
1420
1507
|
{
|
1421
1508
|
disabled: isDisabled,
|
1422
1509
|
size: "S",
|
1423
1510
|
endIcon: null,
|
1424
|
-
paddingTop: "
|
1425
|
-
paddingLeft: "
|
1426
|
-
paddingRight: "
|
1511
|
+
paddingTop: "4px",
|
1512
|
+
paddingLeft: "7px",
|
1513
|
+
paddingRight: "7px",
|
1427
1514
|
variant,
|
1428
1515
|
children: [
|
1429
1516
|
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
1430
|
-
/* @__PURE__ */ jsx(VisuallyHidden, {
|
1517
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1431
1518
|
id: "content-manager.containers.edit.panels.default.more-actions",
|
1432
1519
|
defaultMessage: "More document actions"
|
1433
1520
|
}) })
|
@@ -1443,10 +1530,25 @@ const DocumentActionsMenu = ({
|
|
1443
1530
|
onSelect: handleClick(action),
|
1444
1531
|
display: "block",
|
1445
1532
|
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
1446
|
-
/* @__PURE__ */ jsxs(
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1533
|
+
/* @__PURE__ */ jsxs(
|
1534
|
+
Flex,
|
1535
|
+
{
|
1536
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1537
|
+
gap: 2,
|
1538
|
+
tag: "span",
|
1539
|
+
children: [
|
1540
|
+
/* @__PURE__ */ jsx(
|
1541
|
+
Flex,
|
1542
|
+
{
|
1543
|
+
tag: "span",
|
1544
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1545
|
+
children: action.icon
|
1546
|
+
}
|
1547
|
+
),
|
1548
|
+
action.label
|
1549
|
+
]
|
1550
|
+
}
|
1551
|
+
),
|
1450
1552
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
1451
1553
|
Flex,
|
1452
1554
|
{
|
@@ -1505,6 +1607,23 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1505
1607
|
return "primary600";
|
1506
1608
|
}
|
1507
1609
|
};
|
1610
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1611
|
+
switch (variant) {
|
1612
|
+
case "danger":
|
1613
|
+
return "danger600";
|
1614
|
+
case "secondary":
|
1615
|
+
return "neutral500";
|
1616
|
+
case "success":
|
1617
|
+
return "success600";
|
1618
|
+
default:
|
1619
|
+
return "primary600";
|
1620
|
+
}
|
1621
|
+
};
|
1622
|
+
const StyledMoreButton = styled(Menu.Trigger)`
|
1623
|
+
& > span {
|
1624
|
+
display: flex;
|
1625
|
+
}
|
1626
|
+
`;
|
1508
1627
|
const DocumentActionConfirmDialog = ({
|
1509
1628
|
onClose,
|
1510
1629
|
onCancel,
|
@@ -1527,61 +1646,42 @@ const DocumentActionConfirmDialog = ({
|
|
1527
1646
|
}
|
1528
1647
|
onClose();
|
1529
1648
|
};
|
1530
|
-
return /* @__PURE__ */
|
1531
|
-
/* @__PURE__ */ jsx(
|
1532
|
-
/* @__PURE__ */ jsx(
|
1533
|
-
|
1534
|
-
{
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
)
|
1545
|
-
] });
|
1649
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
1650
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
1651
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
1652
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
1653
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: formatMessage({
|
1654
|
+
id: "app.components.Button.cancel",
|
1655
|
+
defaultMessage: "Cancel"
|
1656
|
+
}) }) }),
|
1657
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, children: formatMessage({
|
1658
|
+
id: "app.components.Button.confirm",
|
1659
|
+
defaultMessage: "Confirm"
|
1660
|
+
}) })
|
1661
|
+
] })
|
1662
|
+
] }) });
|
1546
1663
|
};
|
1547
1664
|
const DocumentActionModal = ({
|
1548
1665
|
isOpen,
|
1549
1666
|
title,
|
1550
1667
|
onClose,
|
1551
1668
|
footer: Footer,
|
1552
|
-
content,
|
1669
|
+
content: Content,
|
1553
1670
|
onModalClose
|
1554
1671
|
}) => {
|
1555
|
-
const id = React.useId();
|
1556
|
-
if (!isOpen) {
|
1557
|
-
return null;
|
1558
|
-
}
|
1559
1672
|
const handleClose = () => {
|
1560
1673
|
if (onClose) {
|
1561
1674
|
onClose();
|
1562
1675
|
}
|
1563
1676
|
onModalClose();
|
1564
1677
|
};
|
1565
|
-
return /* @__PURE__ */
|
1566
|
-
/* @__PURE__ */ jsx(
|
1567
|
-
/* @__PURE__ */ jsx(
|
1568
|
-
/* @__PURE__ */ jsx(
|
1569
|
-
|
1570
|
-
{
|
1571
|
-
paddingTop: 4,
|
1572
|
-
paddingBottom: 4,
|
1573
|
-
paddingLeft: 5,
|
1574
|
-
paddingRight: 5,
|
1575
|
-
borderWidth: "1px 0 0 0",
|
1576
|
-
borderStyle: "solid",
|
1577
|
-
borderColor: "neutral150",
|
1578
|
-
background: "neutral100",
|
1579
|
-
children: typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1580
|
-
}
|
1581
|
-
)
|
1582
|
-
] });
|
1678
|
+
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
1679
|
+
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
1680
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
|
1681
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
1682
|
+
] }) });
|
1583
1683
|
};
|
1584
|
-
const PublishAction = ({
|
1684
|
+
const PublishAction$1 = ({
|
1585
1685
|
activeTab,
|
1586
1686
|
documentId,
|
1587
1687
|
model,
|
@@ -1600,6 +1700,12 @@ const PublishAction = ({
|
|
1600
1700
|
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1601
1701
|
);
|
1602
1702
|
const { publish } = useDocumentActions();
|
1703
|
+
const [
|
1704
|
+
countDraftRelations,
|
1705
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
1706
|
+
] = useLazyGetDraftRelationCountQuery();
|
1707
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
1708
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1603
1709
|
const [{ query, rawQuery }] = useQueryParams();
|
1604
1710
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1605
1711
|
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1608,10 +1714,101 @@ const PublishAction = ({
|
|
1608
1714
|
const validate = useForm("PublishAction", (state) => state.validate);
|
1609
1715
|
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1610
1716
|
const formValues = useForm("PublishAction", ({ values }) => values);
|
1717
|
+
React.useEffect(() => {
|
1718
|
+
if (isErrorDraftRelations) {
|
1719
|
+
toggleNotification({
|
1720
|
+
type: "danger",
|
1721
|
+
message: formatMessage({
|
1722
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
1723
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
1724
|
+
})
|
1725
|
+
});
|
1726
|
+
}
|
1727
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
1728
|
+
React.useEffect(() => {
|
1729
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
1730
|
+
const extractDraftRelations = (data) => {
|
1731
|
+
const relations = data.connect || [];
|
1732
|
+
relations.forEach((relation) => {
|
1733
|
+
if (relation.status === "draft") {
|
1734
|
+
localDraftRelations.add(relation.id);
|
1735
|
+
}
|
1736
|
+
});
|
1737
|
+
};
|
1738
|
+
const traverseAndExtract = (data) => {
|
1739
|
+
Object.entries(data).forEach(([key, value]) => {
|
1740
|
+
if (key === "connect" && Array.isArray(value)) {
|
1741
|
+
extractDraftRelations({ connect: value });
|
1742
|
+
} else if (typeof value === "object" && value !== null) {
|
1743
|
+
traverseAndExtract(value);
|
1744
|
+
}
|
1745
|
+
});
|
1746
|
+
};
|
1747
|
+
if (!documentId || modified) {
|
1748
|
+
traverseAndExtract(formValues);
|
1749
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
1750
|
+
}
|
1751
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1752
|
+
React.useEffect(() => {
|
1753
|
+
if (documentId) {
|
1754
|
+
const fetchDraftRelationsCount = async () => {
|
1755
|
+
const { data, error } = await countDraftRelations({
|
1756
|
+
collectionType,
|
1757
|
+
model,
|
1758
|
+
documentId,
|
1759
|
+
params
|
1760
|
+
});
|
1761
|
+
if (error) {
|
1762
|
+
throw error;
|
1763
|
+
}
|
1764
|
+
if (data) {
|
1765
|
+
setServerCountOfDraftRelations(data.data);
|
1766
|
+
}
|
1767
|
+
};
|
1768
|
+
fetchDraftRelationsCount();
|
1769
|
+
}
|
1770
|
+
}, [documentId, countDraftRelations, collectionType, model, params]);
|
1611
1771
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1612
1772
|
if (!schema?.options?.draftAndPublish) {
|
1613
1773
|
return null;
|
1614
1774
|
}
|
1775
|
+
const performPublish = async () => {
|
1776
|
+
setSubmitting(true);
|
1777
|
+
try {
|
1778
|
+
const { errors } = await validate();
|
1779
|
+
if (errors) {
|
1780
|
+
toggleNotification({
|
1781
|
+
type: "danger",
|
1782
|
+
message: formatMessage({
|
1783
|
+
id: "content-manager.validation.error",
|
1784
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1785
|
+
})
|
1786
|
+
});
|
1787
|
+
return;
|
1788
|
+
}
|
1789
|
+
const res = await publish(
|
1790
|
+
{
|
1791
|
+
collectionType,
|
1792
|
+
model,
|
1793
|
+
documentId,
|
1794
|
+
params
|
1795
|
+
},
|
1796
|
+
formValues
|
1797
|
+
);
|
1798
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1799
|
+
navigate({
|
1800
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1801
|
+
search: rawQuery
|
1802
|
+
});
|
1803
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1804
|
+
setErrors(formatValidationErrors(res.error));
|
1805
|
+
}
|
1806
|
+
} finally {
|
1807
|
+
setSubmitting(false);
|
1808
|
+
}
|
1809
|
+
};
|
1810
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1811
|
+
const hasDraftRelations = totalDraftRelations > 0;
|
1615
1812
|
return {
|
1616
1813
|
/**
|
1617
1814
|
* Disabled when:
|
@@ -1621,52 +1818,42 @@ const PublishAction = ({
|
|
1621
1818
|
* - the document is already published & not modified
|
1622
1819
|
* - the document is being created & not modified
|
1623
1820
|
* - the user doesn't have the permission to publish
|
1624
|
-
* - the user doesn't have the permission to create a new document
|
1625
|
-
* - the user doesn't have the permission to update the document
|
1626
1821
|
*/
|
1627
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
1822
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1628
1823
|
label: formatMessage({
|
1629
1824
|
id: "app.utils.publish",
|
1630
1825
|
defaultMessage: "Publish"
|
1631
1826
|
}),
|
1632
1827
|
onClick: async () => {
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
formValues
|
1654
|
-
);
|
1655
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1656
|
-
navigate({
|
1657
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1658
|
-
search: rawQuery
|
1659
|
-
});
|
1660
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1661
|
-
setErrors(formatValidationErrors(res.error));
|
1828
|
+
if (hasDraftRelations) {
|
1829
|
+
return;
|
1830
|
+
}
|
1831
|
+
await performPublish();
|
1832
|
+
},
|
1833
|
+
dialog: hasDraftRelations ? {
|
1834
|
+
type: "dialog",
|
1835
|
+
variant: "danger",
|
1836
|
+
footer: null,
|
1837
|
+
title: formatMessage({
|
1838
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
1839
|
+
defaultMessage: "Confirmation"
|
1840
|
+
}),
|
1841
|
+
content: formatMessage(
|
1842
|
+
{
|
1843
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
1844
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
1845
|
+
},
|
1846
|
+
{
|
1847
|
+
count: totalDraftRelations
|
1662
1848
|
}
|
1663
|
-
|
1664
|
-
|
1849
|
+
),
|
1850
|
+
onConfirm: async () => {
|
1851
|
+
await performPublish();
|
1665
1852
|
}
|
1666
|
-
}
|
1853
|
+
} : void 0
|
1667
1854
|
};
|
1668
1855
|
};
|
1669
|
-
PublishAction.type = "publish";
|
1856
|
+
PublishAction$1.type = "publish";
|
1670
1857
|
const UpdateAction = ({
|
1671
1858
|
activeTab,
|
1672
1859
|
documentId,
|
@@ -1679,7 +1866,7 @@ const UpdateAction = ({
|
|
1679
1866
|
const cloneMatch = useMatch(CLONE_PATH);
|
1680
1867
|
const isCloning = cloneMatch !== null;
|
1681
1868
|
const { formatMessage } = useIntl();
|
1682
|
-
|
1869
|
+
useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1683
1870
|
canCreate: canCreate2,
|
1684
1871
|
canUpdate: canUpdate2
|
1685
1872
|
}));
|
@@ -1699,10 +1886,8 @@ const UpdateAction = ({
|
|
1699
1886
|
* - the form is submitting
|
1700
1887
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1701
1888
|
* - the active tab is the published tab
|
1702
|
-
* - the user doesn't have the permission to create a new document
|
1703
|
-
* - the user doesn't have the permission to update the document
|
1704
1889
|
*/
|
1705
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
1890
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1706
1891
|
label: formatMessage({
|
1707
1892
|
id: "content-manager.containers.Edit.save",
|
1708
1893
|
defaultMessage: "Save"
|
@@ -1731,10 +1916,13 @@ const UpdateAction = ({
|
|
1731
1916
|
document
|
1732
1917
|
);
|
1733
1918
|
if ("data" in res) {
|
1734
|
-
navigate(
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1919
|
+
navigate(
|
1920
|
+
{
|
1921
|
+
pathname: `../${res.data.documentId}`,
|
1922
|
+
search: rawQuery
|
1923
|
+
},
|
1924
|
+
{ relative: "path" }
|
1925
|
+
);
|
1738
1926
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1739
1927
|
setErrors(formatValidationErrors(res.error));
|
1740
1928
|
}
|
@@ -1762,10 +1950,13 @@ const UpdateAction = ({
|
|
1762
1950
|
document
|
1763
1951
|
);
|
1764
1952
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1765
|
-
navigate(
|
1766
|
-
|
1767
|
-
|
1768
|
-
|
1953
|
+
navigate(
|
1954
|
+
{
|
1955
|
+
pathname: `../${res.data.documentId}`,
|
1956
|
+
search: rawQuery
|
1957
|
+
},
|
1958
|
+
{ replace: true, relative: "path" }
|
1959
|
+
);
|
1769
1960
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1770
1961
|
setErrors(formatValidationErrors(res.error));
|
1771
1962
|
}
|
@@ -1781,7 +1972,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
|
|
1781
1972
|
KEEP: "keep",
|
1782
1973
|
DISCARD: "discard"
|
1783
1974
|
};
|
1784
|
-
const UnpublishAction = ({
|
1975
|
+
const UnpublishAction$1 = ({
|
1785
1976
|
activeTab,
|
1786
1977
|
documentId,
|
1787
1978
|
model,
|
@@ -1797,10 +1988,8 @@ const UnpublishAction = ({
|
|
1797
1988
|
const { toggleNotification } = useNotification();
|
1798
1989
|
const [shouldKeepDraft, setShouldKeepDraft] = React.useState(true);
|
1799
1990
|
const isDocumentModified = document?.status === "modified";
|
1800
|
-
const handleChange = (
|
1801
|
-
|
1802
|
-
setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1803
|
-
}
|
1991
|
+
const handleChange = (value) => {
|
1992
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1804
1993
|
};
|
1805
1994
|
if (!schema?.options?.draftAndPublish) {
|
1806
1995
|
return null;
|
@@ -1844,45 +2033,30 @@ const UnpublishAction = ({
|
|
1844
2033
|
content: /* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
|
1845
2034
|
/* @__PURE__ */ jsxs(Flex, { width: "100%", direction: "column", gap: 2, children: [
|
1846
2035
|
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
1847
|
-
/* @__PURE__ */ jsx(Typography, {
|
2036
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
1848
2037
|
id: "content-manager.actions.unpublish.dialog.body",
|
1849
2038
|
defaultMessage: "Are you sure?"
|
1850
2039
|
}) })
|
1851
2040
|
] }),
|
1852
2041
|
/* @__PURE__ */ jsxs(
|
1853
|
-
|
2042
|
+
Radio.Group,
|
1854
2043
|
{
|
1855
|
-
|
1856
|
-
|
1857
|
-
|
1858
|
-
|
1859
|
-
|
2044
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2045
|
+
name: "discard-options",
|
2046
|
+
"aria-label": formatMessage({
|
2047
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2048
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2049
|
+
}),
|
2050
|
+
onValueChange: handleChange,
|
1860
2051
|
children: [
|
1861
|
-
/* @__PURE__ */ jsx(
|
1862
|
-
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
1867
|
-
|
1868
|
-
|
1869
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
1870
|
-
defaultMessage: "Keep draft"
|
1871
|
-
})
|
1872
|
-
}
|
1873
|
-
),
|
1874
|
-
/* @__PURE__ */ jsx(
|
1875
|
-
Radio,
|
1876
|
-
{
|
1877
|
-
checked: !shouldKeepDraft,
|
1878
|
-
value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
|
1879
|
-
name: "discard-options",
|
1880
|
-
children: formatMessage({
|
1881
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
1882
|
-
defaultMessage: "Replace draft"
|
1883
|
-
})
|
1884
|
-
}
|
1885
|
-
)
|
2052
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2053
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2054
|
+
defaultMessage: "Keep draft"
|
2055
|
+
}) }),
|
2056
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2057
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2058
|
+
defaultMessage: "Replace draft"
|
2059
|
+
}) })
|
1886
2060
|
]
|
1887
2061
|
}
|
1888
2062
|
)
|
@@ -1915,7 +2089,7 @@ const UnpublishAction = ({
|
|
1915
2089
|
position: ["panel", "table-row"]
|
1916
2090
|
};
|
1917
2091
|
};
|
1918
|
-
UnpublishAction.type = "unpublish";
|
2092
|
+
UnpublishAction$1.type = "unpublish";
|
1919
2093
|
const DiscardAction = ({
|
1920
2094
|
activeTab,
|
1921
2095
|
documentId,
|
@@ -1949,7 +2123,7 @@ const DiscardAction = ({
|
|
1949
2123
|
}),
|
1950
2124
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
1951
2125
|
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
1952
|
-
/* @__PURE__ */ jsx(Typography, {
|
2126
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
1953
2127
|
id: "content-manager.actions.discard.dialog.body",
|
1954
2128
|
defaultMessage: "Are you sure?"
|
1955
2129
|
}) })
|
@@ -1971,7 +2145,7 @@ const StyledCrossCircle = styled(CrossCircle)`
|
|
1971
2145
|
fill: currentColor;
|
1972
2146
|
}
|
1973
2147
|
`;
|
1974
|
-
const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
|
2148
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
1975
2149
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
1976
2150
|
const RelativeTime = React.forwardRef(
|
1977
2151
|
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
@@ -2019,7 +2193,7 @@ const getDisplayName = ({
|
|
2019
2193
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2020
2194
|
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2021
2195
|
const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
|
2022
|
-
return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, {
|
2196
|
+
return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
|
2023
2197
|
};
|
2024
2198
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2025
2199
|
const { formatMessage } = useIntl();
|
@@ -2028,23 +2202,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2028
2202
|
id: "content-manager.containers.edit.title.new",
|
2029
2203
|
defaultMessage: "Create an entry"
|
2030
2204
|
}) : documentTitle;
|
2031
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2205
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2032
2206
|
/* @__PURE__ */ jsx(BackButton, {}),
|
2033
|
-
/* @__PURE__ */ jsxs(
|
2034
|
-
|
2035
|
-
{
|
2036
|
-
|
2037
|
-
|
2038
|
-
paddingTop: 1,
|
2039
|
-
gap: "80px",
|
2040
|
-
alignItems: "flex-start",
|
2041
|
-
children: [
|
2042
|
-
/* @__PURE__ */ jsx(Typography, { variant: "alpha", as: "h1", children: title }),
|
2043
|
-
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2044
|
-
]
|
2045
|
-
}
|
2046
|
-
),
|
2047
|
-
status ? /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2207
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2208
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2209
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2210
|
+
] }),
|
2211
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2048
2212
|
] });
|
2049
2213
|
};
|
2050
2214
|
const HeaderToolbar = () => {
|
@@ -2196,7 +2360,7 @@ const Information = ({ activeTab }) => {
|
|
2196
2360
|
borderColor: "neutral150",
|
2197
2361
|
direction: "column",
|
2198
2362
|
marginTop: 2,
|
2199
|
-
|
2363
|
+
tag: "dl",
|
2200
2364
|
padding: 5,
|
2201
2365
|
gap: 3,
|
2202
2366
|
alignItems: "flex-start",
|
@@ -2204,8 +2368,8 @@ const Information = ({ activeTab }) => {
|
|
2204
2368
|
marginRight: "-0.4rem",
|
2205
2369
|
width: "calc(100% + 8px)",
|
2206
2370
|
children: information.map((info) => /* @__PURE__ */ jsxs(Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
|
2207
|
-
/* @__PURE__ */ jsx(Typography, {
|
2208
|
-
/* @__PURE__ */ jsx(Typography, {
|
2371
|
+
/* @__PURE__ */ jsx(Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2372
|
+
/* @__PURE__ */ jsx(Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2209
2373
|
] }, info.label))
|
2210
2374
|
}
|
2211
2375
|
);
|
@@ -2238,7 +2402,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2238
2402
|
id: "app.links.configure-view",
|
2239
2403
|
defaultMessage: "Configure the view"
|
2240
2404
|
}),
|
2241
|
-
icon: /* @__PURE__ */ jsx(
|
2405
|
+
icon: /* @__PURE__ */ jsx(ListPlus, {}),
|
2242
2406
|
onClick: () => {
|
2243
2407
|
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2244
2408
|
},
|
@@ -2246,11 +2410,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2246
2410
|
};
|
2247
2411
|
};
|
2248
2412
|
ConfigureTheViewAction.type = "configure-the-view";
|
2249
|
-
const StyledCog = styled(Cog)`
|
2250
|
-
path {
|
2251
|
-
fill: currentColor;
|
2252
|
-
}
|
2253
|
-
`;
|
2254
2413
|
const EditTheModelAction = ({ model }) => {
|
2255
2414
|
const navigate = useNavigate();
|
2256
2415
|
const { formatMessage } = useIntl();
|
@@ -2259,7 +2418,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2259
2418
|
id: "content-manager.link-to-ctb",
|
2260
2419
|
defaultMessage: "Edit the model"
|
2261
2420
|
}),
|
2262
|
-
icon: /* @__PURE__ */ jsx(
|
2421
|
+
icon: /* @__PURE__ */ jsx(Pencil, {}),
|
2263
2422
|
onClick: () => {
|
2264
2423
|
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2265
2424
|
},
|
@@ -2267,12 +2426,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2267
2426
|
};
|
2268
2427
|
};
|
2269
2428
|
EditTheModelAction.type = "edit-the-model";
|
2270
|
-
const
|
2271
|
-
path {
|
2272
|
-
fill: currentColor;
|
2273
|
-
}
|
2274
|
-
`;
|
2275
|
-
const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
2429
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2276
2430
|
const navigate = useNavigate();
|
2277
2431
|
const { formatMessage } = useIntl();
|
2278
2432
|
const listViewPathMatch = useMatch(LIST_PATH);
|
@@ -2286,7 +2440,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2286
2440
|
id: "content-manager.actions.delete.label",
|
2287
2441
|
defaultMessage: "Delete document"
|
2288
2442
|
}),
|
2289
|
-
icon: /* @__PURE__ */ jsx(
|
2443
|
+
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2290
2444
|
dialog: {
|
2291
2445
|
type: "dialog",
|
2292
2446
|
title: formatMessage({
|
@@ -2295,7 +2449,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2295
2449
|
}),
|
2296
2450
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
2297
2451
|
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2298
|
-
/* @__PURE__ */ jsx(Typography, {
|
2452
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2299
2453
|
id: "content-manager.actions.delete.dialog.body",
|
2300
2454
|
defaultMessage: "Are you sure?"
|
2301
2455
|
}) })
|
@@ -2340,13 +2494,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2340
2494
|
position: ["header", "table-row"]
|
2341
2495
|
};
|
2342
2496
|
};
|
2343
|
-
DeleteAction.type = "delete";
|
2344
|
-
const
|
2345
|
-
path {
|
2346
|
-
fill: currentColor;
|
2347
|
-
}
|
2348
|
-
`;
|
2349
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction];
|
2497
|
+
DeleteAction$1.type = "delete";
|
2498
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2350
2499
|
const Panels = () => {
|
2351
2500
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2352
2501
|
const [
|
@@ -2420,7 +2569,7 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
|
|
2420
2569
|
Flex,
|
2421
2570
|
{
|
2422
2571
|
ref,
|
2423
|
-
|
2572
|
+
tag: "aside",
|
2424
2573
|
"aria-labelledby": "additional-information",
|
2425
2574
|
background: "neutral0",
|
2426
2575
|
borderColor: "neutral150",
|
@@ -2435,116 +2584,995 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
|
|
2435
2584
|
justifyContent: "stretch",
|
2436
2585
|
alignItems: "flex-start",
|
2437
2586
|
children: [
|
2438
|
-
/* @__PURE__ */ jsx(Typography, {
|
2587
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2439
2588
|
children
|
2440
2589
|
]
|
2441
2590
|
}
|
2442
2591
|
);
|
2443
2592
|
});
|
2444
|
-
const
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2454
|
-
|
2455
|
-
|
2456
|
-
|
2457
|
-
|
2458
|
-
|
2459
|
-
|
2460
|
-
|
2461
|
-
|
2462
|
-
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
2466
|
-
|
2467
|
-
|
2468
|
-
|
2469
|
-
direction: "column",
|
2470
|
-
gap: 2,
|
2471
|
-
alignItems: "flex-start",
|
2472
|
-
borderColor: "neutral200",
|
2473
|
-
hasRadius: true,
|
2474
|
-
padding: 6,
|
2475
|
-
children: [
|
2476
|
-
/* @__PURE__ */ jsx(Flex, { direction: "row", as: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxs(Typography, { fontWeight: "semiBold", as: "li", children: [
|
2477
|
-
pathSegment,
|
2478
|
-
index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsx(
|
2479
|
-
ChevronRight,
|
2480
|
-
{
|
2481
|
-
fill: "neutral500",
|
2482
|
-
height: "0.8rem",
|
2483
|
-
width: "0.8rem",
|
2484
|
-
style: { margin: "0 0.8rem" }
|
2485
|
-
}
|
2486
|
-
)
|
2487
|
-
] }, index2)) }),
|
2488
|
-
/* @__PURE__ */ jsx(Typography, { as: "p", textColor: "neutral600", children: formatMessage({
|
2489
|
-
id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
|
2490
|
-
defaultMessage: getDefaultErrorMessage(reason)
|
2491
|
-
}) })
|
2492
|
-
]
|
2493
|
-
},
|
2494
|
-
fieldPath.join()
|
2495
|
-
)) })
|
2496
|
-
] });
|
2497
|
-
};
|
2498
|
-
const TableActions = ({ document }) => {
|
2499
|
-
const { formatMessage } = useIntl();
|
2500
|
-
const { model, collectionType } = useDoc();
|
2501
|
-
const plugins = useStrapiApp("TableActions", (state) => state.plugins);
|
2502
|
-
const props = {
|
2503
|
-
activeTab: null,
|
2504
|
-
model,
|
2505
|
-
documentId: document.documentId,
|
2506
|
-
collectionType,
|
2507
|
-
document
|
2508
|
-
};
|
2509
|
-
return /* @__PURE__ */ jsx(
|
2510
|
-
DescriptionComponentRenderer,
|
2511
|
-
{
|
2512
|
-
props,
|
2513
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2514
|
-
children: (actions2) => {
|
2515
|
-
const tableRowActions = actions2.filter((action) => {
|
2516
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2517
|
-
return positions.includes("table-row");
|
2518
|
-
});
|
2519
|
-
return /* @__PURE__ */ jsx(
|
2520
|
-
DocumentActionsMenu,
|
2521
|
-
{
|
2522
|
-
actions: tableRowActions,
|
2523
|
-
label: formatMessage({
|
2524
|
-
id: "content-manager.containers.list.table.row-actions",
|
2525
|
-
defaultMessage: "Row action"
|
2526
|
-
}),
|
2527
|
-
variant: "ghost"
|
2528
|
-
}
|
2529
|
-
);
|
2530
|
-
}
|
2531
|
-
}
|
2532
|
-
);
|
2593
|
+
const HOOKS = {
|
2594
|
+
/**
|
2595
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
2596
|
+
* @constant
|
2597
|
+
* @type {string}
|
2598
|
+
*/
|
2599
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2600
|
+
/**
|
2601
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2602
|
+
* @constant
|
2603
|
+
* @type {string}
|
2604
|
+
*/
|
2605
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2606
|
+
/**
|
2607
|
+
* Hook that allows to mutate the CM's edit view layout
|
2608
|
+
* @constant
|
2609
|
+
* @type {string}
|
2610
|
+
*/
|
2611
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2612
|
+
/**
|
2613
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
2614
|
+
* @constant
|
2615
|
+
* @type {string}
|
2616
|
+
*/
|
2617
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2533
2618
|
};
|
2534
|
-
const
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2542
|
-
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2619
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2620
|
+
endpoints: (builder) => ({
|
2621
|
+
getContentTypeConfiguration: builder.query({
|
2622
|
+
query: (uid) => ({
|
2623
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
2624
|
+
method: "GET"
|
2625
|
+
}),
|
2626
|
+
transformResponse: (response) => response.data,
|
2627
|
+
providesTags: (_result, _error, uid) => [
|
2628
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
2629
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
2630
|
+
]
|
2546
2631
|
}),
|
2547
|
-
|
2632
|
+
getAllContentTypeSettings: builder.query({
|
2633
|
+
query: () => "/content-manager/content-types-settings",
|
2634
|
+
transformResponse: (response) => response.data,
|
2635
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2636
|
+
}),
|
2637
|
+
updateContentTypeConfiguration: builder.mutation({
|
2638
|
+
query: ({ uid, ...body }) => ({
|
2639
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
2640
|
+
method: "PUT",
|
2641
|
+
data: body
|
2642
|
+
}),
|
2643
|
+
transformResponse: (response) => response.data,
|
2644
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
2645
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
2646
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
2647
|
+
// Is this necessary?
|
2648
|
+
{ type: "InitialData" }
|
2649
|
+
]
|
2650
|
+
})
|
2651
|
+
})
|
2652
|
+
});
|
2653
|
+
const {
|
2654
|
+
useGetContentTypeConfigurationQuery,
|
2655
|
+
useGetAllContentTypeSettingsQuery,
|
2656
|
+
useUpdateContentTypeConfigurationMutation
|
2657
|
+
} = contentTypesApi;
|
2658
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
2659
|
+
const { type } = attribute;
|
2660
|
+
if (type === "relation") {
|
2661
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
2662
|
+
}
|
2663
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2664
|
+
};
|
2665
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2666
|
+
if (!mainFieldName) {
|
2667
|
+
return void 0;
|
2668
|
+
}
|
2669
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2670
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2671
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2672
|
+
);
|
2673
|
+
return {
|
2674
|
+
name: mainFieldName,
|
2675
|
+
type: mainFieldType ?? "string"
|
2676
|
+
};
|
2677
|
+
};
|
2678
|
+
const DEFAULT_SETTINGS = {
|
2679
|
+
bulkable: false,
|
2680
|
+
filterable: false,
|
2681
|
+
searchable: false,
|
2682
|
+
pagination: false,
|
2683
|
+
defaultSortBy: "",
|
2684
|
+
defaultSortOrder: "asc",
|
2685
|
+
mainField: "id",
|
2686
|
+
pageSize: 10
|
2687
|
+
};
|
2688
|
+
const useDocumentLayout = (model) => {
|
2689
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2690
|
+
const [{ query }] = useQueryParams();
|
2691
|
+
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2692
|
+
const { toggleNotification } = useNotification();
|
2693
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2694
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2695
|
+
const {
|
2696
|
+
data,
|
2697
|
+
isLoading: isLoadingConfigs,
|
2698
|
+
error,
|
2699
|
+
isFetching: isFetchingConfigs
|
2700
|
+
} = useGetContentTypeConfigurationQuery(model);
|
2701
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2702
|
+
React.useEffect(() => {
|
2703
|
+
if (error) {
|
2704
|
+
toggleNotification({
|
2705
|
+
type: "danger",
|
2706
|
+
message: formatAPIError(error)
|
2707
|
+
});
|
2708
|
+
}
|
2709
|
+
}, [error, formatAPIError, toggleNotification]);
|
2710
|
+
const editLayout = React.useMemo(
|
2711
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2712
|
+
layout: [],
|
2713
|
+
components: {},
|
2714
|
+
metadatas: {},
|
2715
|
+
options: {},
|
2716
|
+
settings: DEFAULT_SETTINGS
|
2717
|
+
},
|
2718
|
+
[data, isLoading, schemas, schema, components]
|
2719
|
+
);
|
2720
|
+
const listLayout = React.useMemo(() => {
|
2721
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2722
|
+
layout: [],
|
2723
|
+
metadatas: {},
|
2724
|
+
options: {},
|
2725
|
+
settings: DEFAULT_SETTINGS
|
2726
|
+
};
|
2727
|
+
}, [data, isLoading, schemas, schema, components]);
|
2728
|
+
const { layout: edit } = React.useMemo(
|
2729
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2730
|
+
layout: editLayout,
|
2731
|
+
query
|
2732
|
+
}),
|
2733
|
+
[editLayout, query, runHookWaterfall]
|
2734
|
+
);
|
2735
|
+
return {
|
2736
|
+
error,
|
2737
|
+
isLoading,
|
2738
|
+
edit,
|
2739
|
+
list: listLayout
|
2740
|
+
};
|
2741
|
+
};
|
2742
|
+
const useDocLayout = () => {
|
2743
|
+
const { model } = useDoc();
|
2744
|
+
return useDocumentLayout(model);
|
2745
|
+
};
|
2746
|
+
const formatEditLayout = (data, {
|
2747
|
+
schemas,
|
2748
|
+
schema,
|
2749
|
+
components
|
2750
|
+
}) => {
|
2751
|
+
let currentPanelIndex = 0;
|
2752
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2753
|
+
data.contentType.layouts.edit,
|
2754
|
+
schema?.attributes,
|
2755
|
+
data.contentType.metadatas,
|
2756
|
+
{ configurations: data.components, schemas: components },
|
2757
|
+
schemas
|
2758
|
+
).reduce((panels, row) => {
|
2759
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
2760
|
+
panels.push([row]);
|
2761
|
+
currentPanelIndex += 2;
|
2762
|
+
} else {
|
2763
|
+
if (!panels[currentPanelIndex]) {
|
2764
|
+
panels.push([]);
|
2765
|
+
}
|
2766
|
+
panels[currentPanelIndex].push(row);
|
2767
|
+
}
|
2768
|
+
return panels;
|
2769
|
+
}, []);
|
2770
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
2771
|
+
(acc, [uid, configuration]) => {
|
2772
|
+
acc[uid] = {
|
2773
|
+
layout: convertEditLayoutToFieldLayouts(
|
2774
|
+
configuration.layouts.edit,
|
2775
|
+
components[uid].attributes,
|
2776
|
+
configuration.metadatas
|
2777
|
+
),
|
2778
|
+
settings: {
|
2779
|
+
...configuration.settings,
|
2780
|
+
icon: components[uid].info.icon,
|
2781
|
+
displayName: components[uid].info.displayName
|
2782
|
+
}
|
2783
|
+
};
|
2784
|
+
return acc;
|
2785
|
+
},
|
2786
|
+
{}
|
2787
|
+
);
|
2788
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2789
|
+
(acc, [attribute, metadata]) => {
|
2790
|
+
return {
|
2791
|
+
...acc,
|
2792
|
+
[attribute]: metadata.edit
|
2793
|
+
};
|
2794
|
+
},
|
2795
|
+
{}
|
2796
|
+
);
|
2797
|
+
return {
|
2798
|
+
layout: panelledEditAttributes,
|
2799
|
+
components: componentEditAttributes,
|
2800
|
+
metadatas: editMetadatas,
|
2801
|
+
settings: {
|
2802
|
+
...data.contentType.settings,
|
2803
|
+
displayName: schema?.info.displayName
|
2804
|
+
},
|
2805
|
+
options: {
|
2806
|
+
...schema?.options,
|
2807
|
+
...schema?.pluginOptions,
|
2808
|
+
...data.contentType.options
|
2809
|
+
}
|
2810
|
+
};
|
2811
|
+
};
|
2812
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
2813
|
+
return rows.map(
|
2814
|
+
(row) => row.map((field) => {
|
2815
|
+
const attribute = attributes[field.name];
|
2816
|
+
if (!attribute) {
|
2817
|
+
return null;
|
2818
|
+
}
|
2819
|
+
const { edit: metadata } = metadatas[field.name];
|
2820
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2821
|
+
return {
|
2822
|
+
attribute,
|
2823
|
+
disabled: !metadata.editable,
|
2824
|
+
hint: metadata.description,
|
2825
|
+
label: metadata.label ?? "",
|
2826
|
+
name: field.name,
|
2827
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2828
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2829
|
+
schemas,
|
2830
|
+
components: components?.schemas ?? {}
|
2831
|
+
}),
|
2832
|
+
placeholder: metadata.placeholder ?? "",
|
2833
|
+
required: attribute.required ?? false,
|
2834
|
+
size: field.size,
|
2835
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
2836
|
+
visible: metadata.visible ?? true,
|
2837
|
+
type: attribute.type
|
2838
|
+
};
|
2839
|
+
}).filter((field) => field !== null)
|
2840
|
+
);
|
2841
|
+
};
|
2842
|
+
const formatListLayout = (data, {
|
2843
|
+
schemas,
|
2844
|
+
schema,
|
2845
|
+
components
|
2846
|
+
}) => {
|
2847
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2848
|
+
(acc, [attribute, metadata]) => {
|
2849
|
+
return {
|
2850
|
+
...acc,
|
2851
|
+
[attribute]: metadata.list
|
2852
|
+
};
|
2853
|
+
},
|
2854
|
+
{}
|
2855
|
+
);
|
2856
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
2857
|
+
data.contentType.layouts.list,
|
2858
|
+
schema?.attributes,
|
2859
|
+
listMetadatas,
|
2860
|
+
{ configurations: data.components, schemas: components },
|
2861
|
+
schemas
|
2862
|
+
);
|
2863
|
+
return {
|
2864
|
+
layout: listAttributes,
|
2865
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
2866
|
+
metadatas: listMetadatas,
|
2867
|
+
options: {
|
2868
|
+
...schema?.options,
|
2869
|
+
...schema?.pluginOptions,
|
2870
|
+
...data.contentType.options
|
2871
|
+
}
|
2872
|
+
};
|
2873
|
+
};
|
2874
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
2875
|
+
return columns.map((name) => {
|
2876
|
+
const attribute = attributes[name];
|
2877
|
+
if (!attribute) {
|
2878
|
+
return null;
|
2879
|
+
}
|
2880
|
+
const metadata = metadatas[name];
|
2881
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2882
|
+
return {
|
2883
|
+
attribute,
|
2884
|
+
label: metadata.label ?? "",
|
2885
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2886
|
+
schemas,
|
2887
|
+
components: components?.schemas ?? {}
|
2888
|
+
}),
|
2889
|
+
name,
|
2890
|
+
searchable: metadata.searchable ?? true,
|
2891
|
+
sortable: metadata.sortable ?? true
|
2892
|
+
};
|
2893
|
+
}).filter((field) => field !== null);
|
2894
|
+
};
|
2895
|
+
const ConfirmBulkActionDialog = ({
|
2896
|
+
onToggleDialog,
|
2897
|
+
isOpen = false,
|
2898
|
+
dialogBody,
|
2899
|
+
endAction
|
2900
|
+
}) => {
|
2901
|
+
const { formatMessage } = useIntl();
|
2902
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2903
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
2904
|
+
id: "app.components.ConfirmDialog.title",
|
2905
|
+
defaultMessage: "Confirmation"
|
2906
|
+
}) }),
|
2907
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
2908
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
2909
|
+
dialogBody
|
2910
|
+
] }) }),
|
2911
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
2912
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
|
2913
|
+
id: "app.components.Button.cancel",
|
2914
|
+
defaultMessage: "Cancel"
|
2915
|
+
}) }) }),
|
2916
|
+
endAction
|
2917
|
+
] })
|
2918
|
+
] }) });
|
2919
|
+
};
|
2920
|
+
const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
2921
|
+
const ConfirmDialogPublishAll = ({
|
2922
|
+
isOpen,
|
2923
|
+
onToggleDialog,
|
2924
|
+
isConfirmButtonLoading = false,
|
2925
|
+
onConfirm
|
2926
|
+
}) => {
|
2927
|
+
const { formatMessage } = useIntl();
|
2928
|
+
const selectedEntries = useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
|
2929
|
+
const { toggleNotification } = useNotification();
|
2930
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
2931
|
+
const { model, schema } = useDoc();
|
2932
|
+
const [{ query }] = useQueryParams();
|
2933
|
+
const {
|
2934
|
+
data: countDraftRelations = 0,
|
2935
|
+
isLoading,
|
2936
|
+
error
|
2937
|
+
} = useGetManyDraftRelationCountQuery(
|
2938
|
+
{
|
2939
|
+
model,
|
2940
|
+
documentIds: selectedEntries.map((entry) => entry.documentId),
|
2941
|
+
locale: query?.plugins?.i18n?.locale
|
2942
|
+
},
|
2943
|
+
{
|
2944
|
+
skip: selectedEntries.length === 0
|
2945
|
+
}
|
2946
|
+
);
|
2947
|
+
React.useEffect(() => {
|
2948
|
+
if (error) {
|
2949
|
+
toggleNotification({ type: "danger", message: formatAPIError(error) });
|
2950
|
+
}
|
2951
|
+
}, [error, formatAPIError, toggleNotification]);
|
2952
|
+
if (error) {
|
2953
|
+
return null;
|
2954
|
+
}
|
2955
|
+
return /* @__PURE__ */ jsx(
|
2956
|
+
ConfirmBulkActionDialog,
|
2957
|
+
{
|
2958
|
+
isOpen: isOpen && !isLoading,
|
2959
|
+
onToggleDialog,
|
2960
|
+
dialogBody: /* @__PURE__ */ jsxs(Fragment, { children: [
|
2961
|
+
/* @__PURE__ */ jsxs(Typography, { id: "confirm-description", textAlign: "center", children: [
|
2962
|
+
countDraftRelations > 0 && formatMessage(
|
2963
|
+
{
|
2964
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2965
|
+
defaultMessage: "<b>{count} {count, plural, one { relation } other { relations } } out of {entities} { entities, plural, one { entry } other { entries } } {count, plural, one { is } other { are } }</b> not published yet and might lead to unexpected behavior. "
|
2966
|
+
},
|
2967
|
+
{
|
2968
|
+
b: BoldChunk$1,
|
2969
|
+
count: countDraftRelations,
|
2970
|
+
entities: selectedEntries.length
|
2971
|
+
}
|
2972
|
+
),
|
2973
|
+
formatMessage({
|
2974
|
+
id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
|
2975
|
+
defaultMessage: "Are you sure you want to publish these entries?"
|
2976
|
+
})
|
2977
|
+
] }),
|
2978
|
+
schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsx(Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
|
2979
|
+
{
|
2980
|
+
id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
|
2981
|
+
defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
|
2982
|
+
},
|
2983
|
+
{
|
2984
|
+
em: Emphasis
|
2985
|
+
}
|
2986
|
+
) })
|
2987
|
+
] }),
|
2988
|
+
endAction: /* @__PURE__ */ jsx(
|
2989
|
+
Button,
|
2990
|
+
{
|
2991
|
+
onClick: onConfirm,
|
2992
|
+
variant: "secondary",
|
2993
|
+
startIcon: /* @__PURE__ */ jsx(Check, {}),
|
2994
|
+
loading: isConfirmButtonLoading,
|
2995
|
+
children: formatMessage({
|
2996
|
+
id: "app.utils.publish",
|
2997
|
+
defaultMessage: "Publish"
|
2998
|
+
})
|
2999
|
+
}
|
3000
|
+
)
|
3001
|
+
}
|
3002
|
+
);
|
3003
|
+
};
|
3004
|
+
const TypographyMaxWidth = styled(Typography)`
|
3005
|
+
max-width: 300px;
|
3006
|
+
`;
|
3007
|
+
const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
3008
|
+
const messages = [];
|
3009
|
+
Object.entries(errors).forEach(([key, value]) => {
|
3010
|
+
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
3011
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
3012
|
+
if ("id" in value && "defaultMessage" in value) {
|
3013
|
+
messages.push(
|
3014
|
+
formatMessage(
|
3015
|
+
{
|
3016
|
+
id: `${value.id}.withField`,
|
3017
|
+
defaultMessage: value.defaultMessage
|
3018
|
+
},
|
3019
|
+
{ field: currentKey }
|
3020
|
+
)
|
3021
|
+
);
|
3022
|
+
} else {
|
3023
|
+
messages.push(
|
3024
|
+
...formatErrorMessages(
|
3025
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3026
|
+
value,
|
3027
|
+
currentKey,
|
3028
|
+
formatMessage
|
3029
|
+
)
|
3030
|
+
);
|
3031
|
+
}
|
3032
|
+
} else {
|
3033
|
+
messages.push(
|
3034
|
+
formatMessage(
|
3035
|
+
{
|
3036
|
+
id: `${value}.withField`,
|
3037
|
+
defaultMessage: value
|
3038
|
+
},
|
3039
|
+
{ field: currentKey }
|
3040
|
+
)
|
3041
|
+
);
|
3042
|
+
}
|
3043
|
+
});
|
3044
|
+
return messages;
|
3045
|
+
};
|
3046
|
+
const EntryValidationText = ({ validationErrors, status }) => {
|
3047
|
+
const { formatMessage } = useIntl();
|
3048
|
+
if (validationErrors) {
|
3049
|
+
const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
|
3050
|
+
" "
|
3051
|
+
);
|
3052
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3053
|
+
/* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
|
3054
|
+
/* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
|
3055
|
+
] });
|
3056
|
+
}
|
3057
|
+
if (status === "published") {
|
3058
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3059
|
+
/* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
3060
|
+
/* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
|
3061
|
+
id: "content-manager.bulk-publish.already-published",
|
3062
|
+
defaultMessage: "Already Published"
|
3063
|
+
}) })
|
3064
|
+
] });
|
3065
|
+
}
|
3066
|
+
if (status === "modified") {
|
3067
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3068
|
+
/* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
|
3069
|
+
/* @__PURE__ */ jsx(Typography, { children: formatMessage({
|
3070
|
+
id: "content-manager.bulk-publish.modified",
|
3071
|
+
defaultMessage: "Ready to publish changes"
|
3072
|
+
}) })
|
3073
|
+
] });
|
3074
|
+
}
|
3075
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3076
|
+
/* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
3077
|
+
/* @__PURE__ */ jsx(Typography, { children: formatMessage({
|
3078
|
+
id: "app.utils.ready-to-publish",
|
3079
|
+
defaultMessage: "Ready to publish"
|
3080
|
+
}) })
|
3081
|
+
] });
|
3082
|
+
};
|
3083
|
+
const TABLE_HEADERS = [
|
3084
|
+
{ name: "id", label: "id" },
|
3085
|
+
{ name: "name", label: "name" },
|
3086
|
+
{ name: "status", label: "status" },
|
3087
|
+
{ name: "publicationStatus", label: "Publication status" }
|
3088
|
+
];
|
3089
|
+
const SelectedEntriesTableContent = ({
|
3090
|
+
isPublishing,
|
3091
|
+
rowsToDisplay = [],
|
3092
|
+
entriesToPublish = [],
|
3093
|
+
validationErrors = {}
|
3094
|
+
}) => {
|
3095
|
+
const { pathname } = useLocation();
|
3096
|
+
const { formatMessage } = useIntl();
|
3097
|
+
const {
|
3098
|
+
list: {
|
3099
|
+
settings: { mainField }
|
3100
|
+
}
|
3101
|
+
} = useDocLayout();
|
3102
|
+
const shouldDisplayMainField = mainField != null && mainField !== "id";
|
3103
|
+
return /* @__PURE__ */ jsxs(Table.Content, { children: [
|
3104
|
+
/* @__PURE__ */ jsxs(Table.Head, { children: [
|
3105
|
+
/* @__PURE__ */ jsx(Table.HeaderCheckboxCell, {}),
|
3106
|
+
TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
|
3107
|
+
(head) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...head }, head.name)
|
3108
|
+
)
|
3109
|
+
] }),
|
3110
|
+
/* @__PURE__ */ jsx(Table.Loading, {}),
|
3111
|
+
/* @__PURE__ */ jsx(Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxs(Table.Row, { children: [
|
3112
|
+
/* @__PURE__ */ jsx(Table.CheckboxCell, { id: row.id }),
|
3113
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row.id }) }),
|
3114
|
+
shouldDisplayMainField && /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row[mainField] }) }),
|
3115
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
|
3116
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3117
|
+
/* @__PURE__ */ jsx(Typography, { children: formatMessage({
|
3118
|
+
id: "content-manager.success.record.publishing",
|
3119
|
+
defaultMessage: "Publishing..."
|
3120
|
+
}) }),
|
3121
|
+
/* @__PURE__ */ jsx(Loader, { small: true })
|
3122
|
+
] }) : /* @__PURE__ */ jsx(
|
3123
|
+
EntryValidationText,
|
3124
|
+
{
|
3125
|
+
validationErrors: validationErrors[row.documentId],
|
3126
|
+
status: row.status
|
3127
|
+
}
|
3128
|
+
) }),
|
3129
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
|
3130
|
+
IconButton,
|
3131
|
+
{
|
3132
|
+
tag: Link,
|
3133
|
+
to: {
|
3134
|
+
pathname: `${pathname}/${row.documentId}`,
|
3135
|
+
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3136
|
+
},
|
3137
|
+
state: { from: pathname },
|
3138
|
+
label: formatMessage(
|
3139
|
+
{ id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
|
3140
|
+
{
|
3141
|
+
target: formatMessage(
|
3142
|
+
{
|
3143
|
+
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3144
|
+
defaultMessage: "item line {number}"
|
3145
|
+
},
|
3146
|
+
{ number: index2 + 1 }
|
3147
|
+
)
|
3148
|
+
}
|
3149
|
+
),
|
3150
|
+
target: "_blank",
|
3151
|
+
marginLeft: "auto",
|
3152
|
+
children: /* @__PURE__ */ jsx(Pencil, {})
|
3153
|
+
}
|
3154
|
+
) })
|
3155
|
+
] }, row.id)) })
|
3156
|
+
] });
|
3157
|
+
};
|
3158
|
+
const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
3159
|
+
const SelectedEntriesModalContent = ({
|
3160
|
+
listViewSelectedEntries,
|
3161
|
+
toggleModal,
|
3162
|
+
setListViewSelectedDocuments,
|
3163
|
+
model
|
3164
|
+
}) => {
|
3165
|
+
const { formatMessage } = useIntl();
|
3166
|
+
const { schema, components } = useContentTypeSchema(model);
|
3167
|
+
const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
|
3168
|
+
const [{ query }] = useQueryParams();
|
3169
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
3170
|
+
const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
|
3171
|
+
{
|
3172
|
+
model,
|
3173
|
+
params: {
|
3174
|
+
page: "1",
|
3175
|
+
pageSize: documentIds.length.toString(),
|
3176
|
+
sort: query.sort,
|
3177
|
+
filters: {
|
3178
|
+
documentId: {
|
3179
|
+
$in: documentIds
|
3180
|
+
}
|
3181
|
+
},
|
3182
|
+
locale: query.plugins?.i18n?.locale
|
3183
|
+
}
|
3184
|
+
},
|
3185
|
+
{
|
3186
|
+
selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
|
3187
|
+
}
|
3188
|
+
);
|
3189
|
+
const { rows, validationErrors } = React.useMemo(() => {
|
3190
|
+
if (data.length > 0 && schema) {
|
3191
|
+
const validate = createYupSchema(schema.attributes, components);
|
3192
|
+
const validationErrors2 = {};
|
3193
|
+
const rows2 = data.map((entry) => {
|
3194
|
+
try {
|
3195
|
+
validate.validateSync(entry, { abortEarly: false });
|
3196
|
+
return entry;
|
3197
|
+
} catch (e) {
|
3198
|
+
if (e instanceof ValidationError) {
|
3199
|
+
validationErrors2[entry.documentId] = getYupValidationErrors(e);
|
3200
|
+
}
|
3201
|
+
return entry;
|
3202
|
+
}
|
3203
|
+
});
|
3204
|
+
return { rows: rows2, validationErrors: validationErrors2 };
|
3205
|
+
}
|
3206
|
+
return {
|
3207
|
+
rows: [],
|
3208
|
+
validationErrors: {}
|
3209
|
+
};
|
3210
|
+
}, [components, data, schema]);
|
3211
|
+
const [publishedCount, setPublishedCount] = React.useState(0);
|
3212
|
+
const [isDialogOpen, setIsDialogOpen] = React.useState(false);
|
3213
|
+
const { publishMany: bulkPublishAction } = useDocumentActions();
|
3214
|
+
const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
|
3215
|
+
const selectedRows = useTable("publishAction", (state) => state.selectedRows);
|
3216
|
+
const selectedEntries = rows.filter(
|
3217
|
+
(entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
|
3218
|
+
);
|
3219
|
+
const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
|
3220
|
+
const selectedEntriesWithErrorsCount = selectedEntries.filter(
|
3221
|
+
({ documentId }) => validationErrors[documentId]
|
3222
|
+
).length;
|
3223
|
+
const selectedEntriesPublished = selectedEntries.filter(
|
3224
|
+
({ status }) => status === "published"
|
3225
|
+
).length;
|
3226
|
+
const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
|
3227
|
+
const toggleDialog = () => setIsDialogOpen((prev) => !prev);
|
3228
|
+
const handleConfirmBulkPublish = async () => {
|
3229
|
+
toggleDialog();
|
3230
|
+
const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
|
3231
|
+
if (!("error" in res)) {
|
3232
|
+
setPublishedCount(res.count);
|
3233
|
+
const unpublishedEntries = rows.filter((row) => {
|
3234
|
+
return !entriesToPublish.includes(row.documentId);
|
3235
|
+
});
|
3236
|
+
setListViewSelectedDocuments(unpublishedEntries);
|
3237
|
+
}
|
3238
|
+
};
|
3239
|
+
const getFormattedCountMessage = () => {
|
3240
|
+
if (publishedCount) {
|
3241
|
+
return formatMessage(
|
3242
|
+
{
|
3243
|
+
id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
|
3244
|
+
defaultMessage: "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} published. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
|
3245
|
+
},
|
3246
|
+
{
|
3247
|
+
publishedCount,
|
3248
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3249
|
+
b: BoldChunk
|
3250
|
+
}
|
3251
|
+
);
|
3252
|
+
}
|
3253
|
+
return formatMessage(
|
3254
|
+
{
|
3255
|
+
id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
|
3256
|
+
defaultMessage: "<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
|
3257
|
+
},
|
3258
|
+
{
|
3259
|
+
readyToPublishCount: selectedEntriesWithNoErrorsCount,
|
3260
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3261
|
+
alreadyPublishedCount: selectedEntriesPublished,
|
3262
|
+
b: BoldChunk
|
3263
|
+
}
|
3264
|
+
);
|
3265
|
+
};
|
3266
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
3267
|
+
/* @__PURE__ */ jsxs(Modal.Body, { children: [
|
3268
|
+
/* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
|
3269
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsx(
|
3270
|
+
SelectedEntriesTableContent,
|
3271
|
+
{
|
3272
|
+
isPublishing: isSubmittingForm,
|
3273
|
+
rowsToDisplay: rows,
|
3274
|
+
entriesToPublish,
|
3275
|
+
validationErrors
|
3276
|
+
}
|
3277
|
+
) })
|
3278
|
+
] }),
|
3279
|
+
/* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3280
|
+
/* @__PURE__ */ jsx(Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
|
3281
|
+
id: "app.components.Button.cancel",
|
3282
|
+
defaultMessage: "Cancel"
|
3283
|
+
}) }),
|
3284
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3285
|
+
/* @__PURE__ */ jsx(Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
|
3286
|
+
/* @__PURE__ */ jsx(
|
3287
|
+
Button,
|
3288
|
+
{
|
3289
|
+
onClick: toggleDialog,
|
3290
|
+
disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
|
3291
|
+
loading: isSubmittingForm,
|
3292
|
+
children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
|
3293
|
+
}
|
3294
|
+
)
|
3295
|
+
] })
|
3296
|
+
] }),
|
3297
|
+
/* @__PURE__ */ jsx(
|
3298
|
+
ConfirmDialogPublishAll,
|
3299
|
+
{
|
3300
|
+
isOpen: isDialogOpen,
|
3301
|
+
onToggleDialog: toggleDialog,
|
3302
|
+
isConfirmButtonLoading: isSubmittingForm,
|
3303
|
+
onConfirm: handleConfirmBulkPublish
|
3304
|
+
}
|
3305
|
+
)
|
3306
|
+
] });
|
3307
|
+
};
|
3308
|
+
const PublishAction = ({ documents, model }) => {
|
3309
|
+
const { formatMessage } = useIntl();
|
3310
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3311
|
+
const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
|
3312
|
+
const setListViewSelectedDocuments = useTable("publishAction", (state) => state.selectRow);
|
3313
|
+
const refetchList = () => {
|
3314
|
+
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3315
|
+
};
|
3316
|
+
if (!showPublishButton)
|
3317
|
+
return null;
|
3318
|
+
return {
|
3319
|
+
actionType: "publish",
|
3320
|
+
variant: "tertiary",
|
3321
|
+
label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
|
3322
|
+
dialog: {
|
3323
|
+
type: "modal",
|
3324
|
+
title: formatMessage({
|
3325
|
+
id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
|
3326
|
+
defaultMessage: "Publish entries"
|
3327
|
+
}),
|
3328
|
+
content: ({ onClose }) => {
|
3329
|
+
return /* @__PURE__ */ jsx(Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsx(
|
3330
|
+
SelectedEntriesModalContent,
|
3331
|
+
{
|
3332
|
+
listViewSelectedEntries: documents,
|
3333
|
+
toggleModal: () => {
|
3334
|
+
onClose();
|
3335
|
+
refetchList();
|
3336
|
+
},
|
3337
|
+
setListViewSelectedDocuments,
|
3338
|
+
model
|
3339
|
+
}
|
3340
|
+
) });
|
3341
|
+
},
|
3342
|
+
onClose: () => {
|
3343
|
+
refetchList();
|
3344
|
+
}
|
3345
|
+
}
|
3346
|
+
};
|
3347
|
+
};
|
3348
|
+
const BulkActionsRenderer = () => {
|
3349
|
+
const plugins = useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
|
3350
|
+
const { model, collectionType } = useDoc();
|
3351
|
+
const { selectedRows } = useTable("BulkActionsRenderer", (state) => state);
|
3352
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 2, children: /* @__PURE__ */ jsx(
|
3353
|
+
DescriptionComponentRenderer,
|
3354
|
+
{
|
3355
|
+
props: {
|
3356
|
+
model,
|
3357
|
+
collectionType,
|
3358
|
+
documents: selectedRows
|
3359
|
+
},
|
3360
|
+
descriptions: plugins["content-manager"].apis.getBulkActions(),
|
3361
|
+
children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsx(DocumentActionButton, { ...action }, action.id))
|
3362
|
+
}
|
3363
|
+
) });
|
3364
|
+
};
|
3365
|
+
const DeleteAction = ({ documents, model }) => {
|
3366
|
+
const { formatMessage } = useIntl();
|
3367
|
+
const { schema: contentType } = useDoc();
|
3368
|
+
const selectRow = useTable("DeleteAction", (state) => state.selectRow);
|
3369
|
+
const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
|
3370
|
+
const [{ query }] = useQueryParams();
|
3371
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
3372
|
+
const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
|
3373
|
+
const { deleteMany: bulkDeleteAction } = useDocumentActions();
|
3374
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3375
|
+
const handleConfirmBulkDelete = async () => {
|
3376
|
+
const res = await bulkDeleteAction({
|
3377
|
+
documentIds,
|
3378
|
+
model,
|
3379
|
+
params
|
3380
|
+
});
|
3381
|
+
if (!("error" in res)) {
|
3382
|
+
selectRow([]);
|
3383
|
+
}
|
3384
|
+
};
|
3385
|
+
if (!hasDeletePermission)
|
3386
|
+
return null;
|
3387
|
+
return {
|
3388
|
+
variant: "danger-light",
|
3389
|
+
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
3390
|
+
dialog: {
|
3391
|
+
type: "dialog",
|
3392
|
+
title: formatMessage({
|
3393
|
+
id: "app.components.ConfirmDialog.title",
|
3394
|
+
defaultMessage: "Confirmation"
|
3395
|
+
}),
|
3396
|
+
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3397
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3398
|
+
/* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3399
|
+
id: "popUpWarning.bodyMessage.contentType.delete.all",
|
3400
|
+
defaultMessage: "Are you sure you want to delete these entries?"
|
3401
|
+
}) }),
|
3402
|
+
hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
|
3403
|
+
{
|
3404
|
+
id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
|
3405
|
+
defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
|
3406
|
+
},
|
3407
|
+
{
|
3408
|
+
em: Emphasis
|
3409
|
+
}
|
3410
|
+
) }) })
|
3411
|
+
] }),
|
3412
|
+
onConfirm: handleConfirmBulkDelete
|
3413
|
+
}
|
3414
|
+
};
|
3415
|
+
};
|
3416
|
+
DeleteAction.type = "delete";
|
3417
|
+
const UnpublishAction = ({ documents, model }) => {
|
3418
|
+
const { formatMessage } = useIntl();
|
3419
|
+
const { schema } = useDoc();
|
3420
|
+
const selectRow = useTable("UnpublishAction", (state) => state.selectRow);
|
3421
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3422
|
+
const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
|
3423
|
+
const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
|
3424
|
+
const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
|
3425
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3426
|
+
const [{ query }] = useQueryParams();
|
3427
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
3428
|
+
const handleConfirmBulkUnpublish = async () => {
|
3429
|
+
const data = await bulkUnpublishAction({ documentIds, model, params });
|
3430
|
+
if (!("error" in data)) {
|
3431
|
+
selectRow([]);
|
3432
|
+
}
|
3433
|
+
};
|
3434
|
+
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3435
|
+
if (!showUnpublishButton)
|
3436
|
+
return null;
|
3437
|
+
return {
|
3438
|
+
variant: "tertiary",
|
3439
|
+
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
3440
|
+
dialog: {
|
3441
|
+
type: "dialog",
|
3442
|
+
title: formatMessage({
|
3443
|
+
id: "app.components.ConfirmDialog.title",
|
3444
|
+
defaultMessage: "Confirmation"
|
3445
|
+
}),
|
3446
|
+
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3447
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3448
|
+
/* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3449
|
+
id: "popUpWarning.bodyMessage.contentType.unpublish.all",
|
3450
|
+
defaultMessage: "Are you sure you want to unpublish these entries?"
|
3451
|
+
}) }),
|
3452
|
+
hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
|
3453
|
+
{
|
3454
|
+
id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
|
3455
|
+
defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
|
3456
|
+
},
|
3457
|
+
{
|
3458
|
+
em: Emphasis
|
3459
|
+
}
|
3460
|
+
) }) })
|
3461
|
+
] }),
|
3462
|
+
confirmButton: formatMessage({
|
3463
|
+
id: "app.utils.unpublish",
|
3464
|
+
defaultMessage: "Unpublish"
|
3465
|
+
}),
|
3466
|
+
onConfirm: handleConfirmBulkUnpublish
|
3467
|
+
}
|
3468
|
+
};
|
3469
|
+
};
|
3470
|
+
UnpublishAction.type = "unpublish";
|
3471
|
+
const Emphasis = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
|
3472
|
+
const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
|
3473
|
+
const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
3474
|
+
const { formatMessage } = useIntl();
|
3475
|
+
const getDefaultErrorMessage = (reason) => {
|
3476
|
+
switch (reason) {
|
3477
|
+
case "relation":
|
3478
|
+
return "Duplicating the relation could remove it from the original entry.";
|
3479
|
+
case "unique":
|
3480
|
+
return "Identical values in a unique field are not allowed";
|
3481
|
+
default:
|
3482
|
+
return reason;
|
3483
|
+
}
|
3484
|
+
};
|
3485
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
3486
|
+
/* @__PURE__ */ jsx(Typography, { variant: "beta", children: formatMessage({
|
3487
|
+
id: getTranslation("containers.list.autoCloneModal.title"),
|
3488
|
+
defaultMessage: "This entry can't be duplicated directly."
|
3489
|
+
}) }),
|
3490
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 2, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage({
|
3491
|
+
id: getTranslation("containers.list.autoCloneModal.description"),
|
3492
|
+
defaultMessage: "A new entry will be created with the same content, but you'll have to change the following fields to save it."
|
3493
|
+
}) }) }),
|
3494
|
+
/* @__PURE__ */ jsx(Flex, { marginTop: 6, gap: 2, direction: "column", alignItems: "stretch", children: prohibitedFields.map(([fieldPath, reason]) => /* @__PURE__ */ jsxs(
|
3495
|
+
Flex,
|
3496
|
+
{
|
3497
|
+
direction: "column",
|
3498
|
+
gap: 2,
|
3499
|
+
alignItems: "flex-start",
|
3500
|
+
borderColor: "neutral200",
|
3501
|
+
hasRadius: true,
|
3502
|
+
padding: 6,
|
3503
|
+
children: [
|
3504
|
+
/* @__PURE__ */ jsx(Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxs(Typography, { fontWeight: "semiBold", tag: "li", children: [
|
3505
|
+
pathSegment,
|
3506
|
+
index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsx(
|
3507
|
+
ChevronRight,
|
3508
|
+
{
|
3509
|
+
fill: "neutral500",
|
3510
|
+
height: "0.8rem",
|
3511
|
+
width: "0.8rem",
|
3512
|
+
style: { margin: "0 0.8rem" }
|
3513
|
+
}
|
3514
|
+
)
|
3515
|
+
] }, index2)) }),
|
3516
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
|
3517
|
+
id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
|
3518
|
+
defaultMessage: getDefaultErrorMessage(reason)
|
3519
|
+
}) })
|
3520
|
+
]
|
3521
|
+
},
|
3522
|
+
fieldPath.join()
|
3523
|
+
)) })
|
3524
|
+
] });
|
3525
|
+
};
|
3526
|
+
const TableActions = ({ document }) => {
|
3527
|
+
const { formatMessage } = useIntl();
|
3528
|
+
const { model, collectionType } = useDoc();
|
3529
|
+
const plugins = useStrapiApp("TableActions", (state) => state.plugins);
|
3530
|
+
const props = {
|
3531
|
+
activeTab: null,
|
3532
|
+
model,
|
3533
|
+
documentId: document.documentId,
|
3534
|
+
collectionType,
|
3535
|
+
document
|
3536
|
+
};
|
3537
|
+
return /* @__PURE__ */ jsx(
|
3538
|
+
DescriptionComponentRenderer,
|
3539
|
+
{
|
3540
|
+
props,
|
3541
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3542
|
+
children: (actions2) => {
|
3543
|
+
const tableRowActions = actions2.filter((action) => {
|
3544
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
3545
|
+
return positions.includes("table-row");
|
3546
|
+
});
|
3547
|
+
return /* @__PURE__ */ jsx(
|
3548
|
+
DocumentActionsMenu,
|
3549
|
+
{
|
3550
|
+
actions: tableRowActions,
|
3551
|
+
label: formatMessage({
|
3552
|
+
id: "content-manager.containers.list.table.row-actions",
|
3553
|
+
defaultMessage: "Row action"
|
3554
|
+
}),
|
3555
|
+
variant: "ghost"
|
3556
|
+
}
|
3557
|
+
);
|
3558
|
+
}
|
3559
|
+
}
|
3560
|
+
);
|
3561
|
+
};
|
3562
|
+
const EditAction = ({ documentId }) => {
|
3563
|
+
const navigate = useNavigate();
|
3564
|
+
const { formatMessage } = useIntl();
|
3565
|
+
const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
|
3566
|
+
const { toggleNotification } = useNotification();
|
3567
|
+
const [{ query }] = useQueryParams();
|
3568
|
+
return {
|
3569
|
+
disabled: !canRead,
|
3570
|
+
icon: /* @__PURE__ */ jsx(StyledPencil, {}),
|
3571
|
+
label: formatMessage({
|
3572
|
+
id: "content-manager.actions.edit.label",
|
3573
|
+
defaultMessage: "Edit"
|
3574
|
+
}),
|
3575
|
+
position: "table-row",
|
2548
3576
|
onClick: async () => {
|
2549
3577
|
if (!documentId) {
|
2550
3578
|
console.error(
|
@@ -2629,7 +3657,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2629
3657
|
/* @__PURE__ */ jsx(
|
2630
3658
|
LinkButton,
|
2631
3659
|
{
|
2632
|
-
|
3660
|
+
tag: NavLink,
|
2633
3661
|
to: {
|
2634
3662
|
pathname: `clone/${documentId}`
|
2635
3663
|
},
|
@@ -2662,442 +3690,183 @@ class ContentManagerPlugin {
|
|
2662
3690
|
documentActions = [
|
2663
3691
|
...DEFAULT_ACTIONS,
|
2664
3692
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
2665
|
-
...DEFAULT_HEADER_ACTIONS
|
2666
|
-
HistoryAction
|
3693
|
+
...DEFAULT_HEADER_ACTIONS
|
2667
3694
|
];
|
2668
3695
|
editViewSidePanels = [ActionsPanel];
|
2669
3696
|
headerActions = [];
|
2670
3697
|
constructor() {
|
2671
3698
|
}
|
2672
|
-
addEditViewSidePanel(panels) {
|
2673
|
-
if (Array.isArray(panels)) {
|
2674
|
-
this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
|
2675
|
-
} else if (typeof panels === "function") {
|
2676
|
-
this.editViewSidePanels = panels(this.editViewSidePanels);
|
2677
|
-
} else {
|
2678
|
-
throw new Error(
|
2679
|
-
`Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
|
2680
|
-
panels
|
2681
|
-
)}`
|
2682
|
-
);
|
2683
|
-
}
|
2684
|
-
}
|
2685
|
-
addDocumentAction(actions2) {
|
2686
|
-
if (Array.isArray(actions2)) {
|
2687
|
-
this.documentActions = [...this.documentActions, ...actions2];
|
2688
|
-
} else if (typeof actions2 === "function") {
|
2689
|
-
this.documentActions = actions2(this.documentActions);
|
2690
|
-
} else {
|
2691
|
-
throw new Error(
|
2692
|
-
`Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
|
2693
|
-
actions2
|
2694
|
-
)}`
|
2695
|
-
);
|
2696
|
-
}
|
2697
|
-
}
|
2698
|
-
addDocumentHeaderAction(actions2) {
|
2699
|
-
if (Array.isArray(actions2)) {
|
2700
|
-
this.headerActions = [...this.headerActions, ...actions2];
|
2701
|
-
} else if (typeof actions2 === "function") {
|
2702
|
-
this.headerActions = actions2(this.headerActions);
|
3699
|
+
addEditViewSidePanel(panels) {
|
3700
|
+
if (Array.isArray(panels)) {
|
3701
|
+
this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
|
3702
|
+
} else if (typeof panels === "function") {
|
3703
|
+
this.editViewSidePanels = panels(this.editViewSidePanels);
|
2703
3704
|
} else {
|
2704
3705
|
throw new Error(
|
2705
|
-
`Expected the \`
|
2706
|
-
|
3706
|
+
`Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
|
3707
|
+
panels
|
2707
3708
|
)}`
|
2708
3709
|
);
|
2709
3710
|
}
|
2710
3711
|
}
|
2711
|
-
|
3712
|
+
addDocumentAction(actions2) {
|
2712
3713
|
if (Array.isArray(actions2)) {
|
2713
|
-
this.
|
3714
|
+
this.documentActions = [...this.documentActions, ...actions2];
|
2714
3715
|
} else if (typeof actions2 === "function") {
|
2715
|
-
this.
|
3716
|
+
this.documentActions = actions2(this.documentActions);
|
2716
3717
|
} else {
|
2717
3718
|
throw new Error(
|
2718
|
-
`Expected the \`actions\` passed to \`
|
3719
|
+
`Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
|
2719
3720
|
actions2
|
2720
3721
|
)}`
|
2721
|
-
);
|
2722
|
-
}
|
2723
|
-
}
|
2724
|
-
|
2725
|
-
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
apis: {
|
2730
|
-
addBulkAction: this.addBulkAction.bind(this),
|
2731
|
-
addDocumentAction: this.addDocumentAction.bind(this),
|
2732
|
-
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
2733
|
-
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
2734
|
-
getBulkActions: () => this.bulkActions,
|
2735
|
-
getDocumentActions: () => this.documentActions,
|
2736
|
-
getEditViewSidePanels: () => this.editViewSidePanels,
|
2737
|
-
getHeaderActions: () => this.headerActions
|
2738
|
-
}
|
2739
|
-
};
|
2740
|
-
}
|
2741
|
-
}
|
2742
|
-
const getPrintableType = (value) => {
|
2743
|
-
const nativeType = typeof value;
|
2744
|
-
if (nativeType === "object") {
|
2745
|
-
if (value === null)
|
2746
|
-
return "null";
|
2747
|
-
if (Array.isArray(value))
|
2748
|
-
return "array";
|
2749
|
-
if (value instanceof Object && value.constructor.name !== "Object") {
|
2750
|
-
return value.constructor.name;
|
2751
|
-
}
|
2752
|
-
}
|
2753
|
-
return nativeType;
|
2754
|
-
};
|
2755
|
-
const initialState = {
|
2756
|
-
collectionTypeLinks: [],
|
2757
|
-
components: [],
|
2758
|
-
fieldSizes: {},
|
2759
|
-
models: [],
|
2760
|
-
singleTypeLinks: [],
|
2761
|
-
isLoading: true
|
2762
|
-
};
|
2763
|
-
const appSlice = createSlice({
|
2764
|
-
name: "app",
|
2765
|
-
initialState,
|
2766
|
-
reducers: {
|
2767
|
-
setInitialData(state, action) {
|
2768
|
-
const {
|
2769
|
-
authorizedCollectionTypeLinks,
|
2770
|
-
authorizedSingleTypeLinks,
|
2771
|
-
components,
|
2772
|
-
contentTypeSchemas,
|
2773
|
-
fieldSizes
|
2774
|
-
} = action.payload;
|
2775
|
-
state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
|
2776
|
-
({ isDisplayed }) => isDisplayed
|
2777
|
-
);
|
2778
|
-
state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
|
2779
|
-
state.components = components;
|
2780
|
-
state.models = contentTypeSchemas;
|
2781
|
-
state.fieldSizes = fieldSizes;
|
2782
|
-
state.isLoading = false;
|
2783
|
-
}
|
2784
|
-
}
|
2785
|
-
});
|
2786
|
-
const { actions, reducer: reducer$1 } = appSlice;
|
2787
|
-
const { setInitialData } = actions;
|
2788
|
-
const reducer = combineReducers({
|
2789
|
-
app: reducer$1
|
2790
|
-
});
|
2791
|
-
const HOOKS = {
|
2792
|
-
/**
|
2793
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2794
|
-
* @constant
|
2795
|
-
* @type {string}
|
2796
|
-
*/
|
2797
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2798
|
-
/**
|
2799
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2800
|
-
* @constant
|
2801
|
-
* @type {string}
|
2802
|
-
*/
|
2803
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2804
|
-
/**
|
2805
|
-
* Hook that allows to mutate the CM's edit view layout
|
2806
|
-
* @constant
|
2807
|
-
* @type {string}
|
2808
|
-
*/
|
2809
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2810
|
-
/**
|
2811
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2812
|
-
* @constant
|
2813
|
-
* @type {string}
|
2814
|
-
*/
|
2815
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2816
|
-
};
|
2817
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2818
|
-
endpoints: (builder) => ({
|
2819
|
-
getContentTypeConfiguration: builder.query({
|
2820
|
-
query: (uid) => ({
|
2821
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2822
|
-
method: "GET"
|
2823
|
-
}),
|
2824
|
-
transformResponse: (response) => response.data,
|
2825
|
-
providesTags: (_result, _error, uid) => [
|
2826
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2827
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2828
|
-
]
|
2829
|
-
}),
|
2830
|
-
getAllContentTypeSettings: builder.query({
|
2831
|
-
query: () => "/content-manager/content-types-settings",
|
2832
|
-
transformResponse: (response) => response.data,
|
2833
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2834
|
-
}),
|
2835
|
-
updateContentTypeConfiguration: builder.mutation({
|
2836
|
-
query: ({ uid, ...body }) => ({
|
2837
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2838
|
-
method: "PUT",
|
2839
|
-
data: body
|
2840
|
-
}),
|
2841
|
-
transformResponse: (response) => response.data,
|
2842
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2843
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2844
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2845
|
-
// Is this necessary?
|
2846
|
-
{ type: "InitialData" }
|
2847
|
-
]
|
2848
|
-
})
|
2849
|
-
})
|
2850
|
-
});
|
2851
|
-
const {
|
2852
|
-
useGetContentTypeConfigurationQuery,
|
2853
|
-
useGetAllContentTypeSettingsQuery,
|
2854
|
-
useUpdateContentTypeConfigurationMutation
|
2855
|
-
} = contentTypesApi;
|
2856
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2857
|
-
const { type } = attribute;
|
2858
|
-
if (type === "relation") {
|
2859
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2860
|
-
}
|
2861
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2862
|
-
};
|
2863
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2864
|
-
if (!mainFieldName) {
|
2865
|
-
return void 0;
|
2866
|
-
}
|
2867
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2868
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2869
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2870
|
-
);
|
2871
|
-
return {
|
2872
|
-
name: mainFieldName,
|
2873
|
-
type: mainFieldType ?? "string"
|
2874
|
-
};
|
2875
|
-
};
|
2876
|
-
const DEFAULT_SETTINGS = {
|
2877
|
-
bulkable: false,
|
2878
|
-
filterable: false,
|
2879
|
-
searchable: false,
|
2880
|
-
pagination: false,
|
2881
|
-
defaultSortBy: "",
|
2882
|
-
defaultSortOrder: "asc",
|
2883
|
-
mainField: "id",
|
2884
|
-
pageSize: 10
|
2885
|
-
};
|
2886
|
-
const useDocumentLayout = (model) => {
|
2887
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2888
|
-
const [{ query }] = useQueryParams();
|
2889
|
-
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2890
|
-
const { toggleNotification } = useNotification();
|
2891
|
-
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
2892
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2893
|
-
const {
|
2894
|
-
data,
|
2895
|
-
isLoading: isLoadingConfigs,
|
2896
|
-
error,
|
2897
|
-
isFetching: isFetchingConfigs
|
2898
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2899
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2900
|
-
React.useEffect(() => {
|
2901
|
-
if (error) {
|
2902
|
-
toggleNotification({
|
2903
|
-
type: "danger",
|
2904
|
-
message: formatAPIError(error)
|
2905
|
-
});
|
2906
|
-
}
|
2907
|
-
}, [error, formatAPIError, toggleNotification]);
|
2908
|
-
const editLayout = React.useMemo(
|
2909
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2910
|
-
layout: [],
|
2911
|
-
components: {},
|
2912
|
-
metadatas: {},
|
2913
|
-
options: {},
|
2914
|
-
settings: DEFAULT_SETTINGS
|
2915
|
-
},
|
2916
|
-
[data, isLoading, schemas, schema, components]
|
2917
|
-
);
|
2918
|
-
const listLayout = React.useMemo(() => {
|
2919
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2920
|
-
layout: [],
|
2921
|
-
metadatas: {},
|
2922
|
-
options: {},
|
2923
|
-
settings: DEFAULT_SETTINGS
|
2924
|
-
};
|
2925
|
-
}, [data, isLoading, schemas, schema, components]);
|
2926
|
-
const { layout: edit } = React.useMemo(
|
2927
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2928
|
-
layout: editLayout,
|
2929
|
-
query
|
2930
|
-
}),
|
2931
|
-
[editLayout, query, runHookWaterfall]
|
2932
|
-
);
|
2933
|
-
return {
|
2934
|
-
error,
|
2935
|
-
isLoading,
|
2936
|
-
edit,
|
2937
|
-
list: listLayout
|
2938
|
-
};
|
2939
|
-
};
|
2940
|
-
const useDocLayout = () => {
|
2941
|
-
const { model } = useDoc();
|
2942
|
-
return useDocumentLayout(model);
|
2943
|
-
};
|
2944
|
-
const formatEditLayout = (data, {
|
2945
|
-
schemas,
|
2946
|
-
schema,
|
2947
|
-
components
|
2948
|
-
}) => {
|
2949
|
-
let currentPanelIndex = 0;
|
2950
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2951
|
-
data.contentType.layouts.edit,
|
2952
|
-
schema?.attributes,
|
2953
|
-
data.contentType.metadatas,
|
2954
|
-
{ configurations: data.components, schemas: components },
|
2955
|
-
schemas
|
2956
|
-
).reduce((panels, row) => {
|
2957
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2958
|
-
panels.push([row]);
|
2959
|
-
currentPanelIndex += 2;
|
3722
|
+
);
|
3723
|
+
}
|
3724
|
+
}
|
3725
|
+
addDocumentHeaderAction(actions2) {
|
3726
|
+
if (Array.isArray(actions2)) {
|
3727
|
+
this.headerActions = [...this.headerActions, ...actions2];
|
3728
|
+
} else if (typeof actions2 === "function") {
|
3729
|
+
this.headerActions = actions2(this.headerActions);
|
2960
3730
|
} else {
|
2961
|
-
|
2962
|
-
|
2963
|
-
|
2964
|
-
|
3731
|
+
throw new Error(
|
3732
|
+
`Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
|
3733
|
+
actions2
|
3734
|
+
)}`
|
3735
|
+
);
|
2965
3736
|
}
|
2966
|
-
|
2967
|
-
|
2968
|
-
|
2969
|
-
|
2970
|
-
|
2971
|
-
|
2972
|
-
|
2973
|
-
|
2974
|
-
|
2975
|
-
|
2976
|
-
|
2977
|
-
|
2978
|
-
icon: components[uid].info.icon,
|
2979
|
-
displayName: components[uid].info.displayName
|
2980
|
-
}
|
2981
|
-
};
|
2982
|
-
return acc;
|
2983
|
-
},
|
2984
|
-
{}
|
2985
|
-
);
|
2986
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2987
|
-
(acc, [attribute, metadata]) => {
|
2988
|
-
return {
|
2989
|
-
...acc,
|
2990
|
-
[attribute]: metadata.edit
|
2991
|
-
};
|
2992
|
-
},
|
2993
|
-
{}
|
2994
|
-
);
|
2995
|
-
return {
|
2996
|
-
layout: panelledEditAttributes,
|
2997
|
-
components: componentEditAttributes,
|
2998
|
-
metadatas: editMetadatas,
|
2999
|
-
settings: {
|
3000
|
-
...data.contentType.settings,
|
3001
|
-
displayName: schema?.info.displayName
|
3002
|
-
},
|
3003
|
-
options: {
|
3004
|
-
...schema?.options,
|
3005
|
-
...schema?.pluginOptions,
|
3006
|
-
...data.contentType.options
|
3737
|
+
}
|
3738
|
+
addBulkAction(actions2) {
|
3739
|
+
if (Array.isArray(actions2)) {
|
3740
|
+
this.bulkActions = [...this.bulkActions, ...actions2];
|
3741
|
+
} else if (typeof actions2 === "function") {
|
3742
|
+
this.bulkActions = actions2(this.bulkActions);
|
3743
|
+
} else {
|
3744
|
+
throw new Error(
|
3745
|
+
`Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
|
3746
|
+
actions2
|
3747
|
+
)}`
|
3748
|
+
);
|
3007
3749
|
}
|
3008
|
-
}
|
3009
|
-
|
3010
|
-
|
3011
|
-
|
3012
|
-
|
3013
|
-
|
3014
|
-
|
3015
|
-
|
3750
|
+
}
|
3751
|
+
get config() {
|
3752
|
+
return {
|
3753
|
+
id: PLUGIN_ID,
|
3754
|
+
name: "Content Manager",
|
3755
|
+
injectionZones: INJECTION_ZONES,
|
3756
|
+
apis: {
|
3757
|
+
addBulkAction: this.addBulkAction.bind(this),
|
3758
|
+
addDocumentAction: this.addDocumentAction.bind(this),
|
3759
|
+
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3760
|
+
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3761
|
+
getBulkActions: () => this.bulkActions,
|
3762
|
+
getDocumentActions: () => this.documentActions,
|
3763
|
+
getEditViewSidePanels: () => this.editViewSidePanels,
|
3764
|
+
getHeaderActions: () => this.headerActions
|
3016
3765
|
}
|
3017
|
-
|
3018
|
-
|
3019
|
-
|
3020
|
-
|
3021
|
-
|
3022
|
-
|
3023
|
-
|
3024
|
-
|
3025
|
-
|
3026
|
-
|
3027
|
-
|
3028
|
-
|
3029
|
-
|
3030
|
-
|
3031
|
-
|
3032
|
-
size: field.size,
|
3033
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
3034
|
-
visible: metadata.visible ?? true,
|
3035
|
-
type: attribute.type
|
3036
|
-
};
|
3037
|
-
}).filter((field) => field !== null)
|
3038
|
-
);
|
3766
|
+
};
|
3767
|
+
}
|
3768
|
+
}
|
3769
|
+
const getPrintableType = (value) => {
|
3770
|
+
const nativeType = typeof value;
|
3771
|
+
if (nativeType === "object") {
|
3772
|
+
if (value === null)
|
3773
|
+
return "null";
|
3774
|
+
if (Array.isArray(value))
|
3775
|
+
return "array";
|
3776
|
+
if (value instanceof Object && value.constructor.name !== "Object") {
|
3777
|
+
return value.constructor.name;
|
3778
|
+
}
|
3779
|
+
}
|
3780
|
+
return nativeType;
|
3039
3781
|
};
|
3040
|
-
const
|
3041
|
-
|
3042
|
-
|
3043
|
-
|
3044
|
-
}
|
3045
|
-
|
3046
|
-
|
3047
|
-
|
3048
|
-
...acc,
|
3049
|
-
[attribute]: metadata.list
|
3050
|
-
};
|
3051
|
-
},
|
3052
|
-
{}
|
3053
|
-
);
|
3054
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
3055
|
-
data.contentType.layouts.list,
|
3056
|
-
schema?.attributes,
|
3057
|
-
listMetadatas,
|
3058
|
-
{ configurations: data.components, schemas: components },
|
3059
|
-
schemas
|
3060
|
-
);
|
3782
|
+
const HistoryAction = ({ model, document }) => {
|
3783
|
+
const { formatMessage } = useIntl();
|
3784
|
+
const [{ query }] = useQueryParams();
|
3785
|
+
const navigate = useNavigate();
|
3786
|
+
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3787
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3788
|
+
return null;
|
3789
|
+
}
|
3061
3790
|
return {
|
3062
|
-
|
3063
|
-
|
3064
|
-
|
3065
|
-
|
3066
|
-
|
3067
|
-
|
3068
|
-
|
3069
|
-
|
3791
|
+
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3792
|
+
label: formatMessage({
|
3793
|
+
id: "content-manager.history.document-action",
|
3794
|
+
defaultMessage: "Content History"
|
3795
|
+
}),
|
3796
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3797
|
+
disabled: (
|
3798
|
+
/**
|
3799
|
+
* The user is creating a new document.
|
3800
|
+
* It hasn't been saved yet, so there's no history to go to
|
3801
|
+
*/
|
3802
|
+
!document || /**
|
3803
|
+
* The document has been created but the current dimension has never been saved.
|
3804
|
+
* For example, the user is creating a new locale in an existing document,
|
3805
|
+
* so there's no history for the document in that locale
|
3806
|
+
*/
|
3807
|
+
!document.id || /**
|
3808
|
+
* History is only available for content types created by the user.
|
3809
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3810
|
+
* which start with `admin::` or `plugin::`
|
3811
|
+
*/
|
3812
|
+
!model.startsWith("api::")
|
3813
|
+
),
|
3814
|
+
position: "header"
|
3070
3815
|
};
|
3071
3816
|
};
|
3072
|
-
|
3073
|
-
|
3074
|
-
|
3075
|
-
|
3076
|
-
|
3077
|
-
|
3078
|
-
|
3079
|
-
|
3080
|
-
|
3081
|
-
|
3082
|
-
|
3083
|
-
|
3084
|
-
|
3085
|
-
|
3086
|
-
|
3087
|
-
|
3088
|
-
|
3089
|
-
|
3090
|
-
};
|
3091
|
-
}).filter((field) => field !== null);
|
3817
|
+
HistoryAction.type = "history";
|
3818
|
+
const historyAdmin = {
|
3819
|
+
bootstrap(app) {
|
3820
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3821
|
+
addDocumentAction((actions2) => {
|
3822
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3823
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3824
|
+
return actions2;
|
3825
|
+
});
|
3826
|
+
}
|
3827
|
+
};
|
3828
|
+
const initialState = {
|
3829
|
+
collectionTypeLinks: [],
|
3830
|
+
components: [],
|
3831
|
+
fieldSizes: {},
|
3832
|
+
models: [],
|
3833
|
+
singleTypeLinks: [],
|
3834
|
+
isLoading: true
|
3092
3835
|
};
|
3836
|
+
const appSlice = createSlice({
|
3837
|
+
name: "app",
|
3838
|
+
initialState,
|
3839
|
+
reducers: {
|
3840
|
+
setInitialData(state, action) {
|
3841
|
+
const {
|
3842
|
+
authorizedCollectionTypeLinks,
|
3843
|
+
authorizedSingleTypeLinks,
|
3844
|
+
components,
|
3845
|
+
contentTypeSchemas,
|
3846
|
+
fieldSizes
|
3847
|
+
} = action.payload;
|
3848
|
+
state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
|
3849
|
+
({ isDisplayed }) => isDisplayed
|
3850
|
+
);
|
3851
|
+
state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
|
3852
|
+
state.components = components;
|
3853
|
+
state.models = contentTypeSchemas;
|
3854
|
+
state.fieldSizes = fieldSizes;
|
3855
|
+
state.isLoading = false;
|
3856
|
+
}
|
3857
|
+
}
|
3858
|
+
});
|
3859
|
+
const { actions, reducer: reducer$1 } = appSlice;
|
3860
|
+
const { setInitialData } = actions;
|
3861
|
+
const reducer = combineReducers({
|
3862
|
+
app: reducer$1
|
3863
|
+
});
|
3093
3864
|
const index = {
|
3094
3865
|
register(app) {
|
3095
3866
|
const cm = new ContentManagerPlugin();
|
3096
3867
|
app.addReducers({
|
3097
|
-
[contentManagerApi.reducerPath]: contentManagerApi.reducer,
|
3098
3868
|
[PLUGIN_ID]: reducer
|
3099
3869
|
});
|
3100
|
-
app.addMiddlewares([() => contentManagerApi.middleware]);
|
3101
3870
|
app.addMenuLink({
|
3102
3871
|
to: PLUGIN_ID,
|
3103
3872
|
icon: Feather,
|
@@ -3106,14 +3875,29 @@ const index = {
|
|
3106
3875
|
defaultMessage: "Content Manager"
|
3107
3876
|
},
|
3108
3877
|
permissions: [],
|
3109
|
-
|
3878
|
+
position: 1
|
3879
|
+
});
|
3880
|
+
app.router.addRoute({
|
3881
|
+
path: "content-manager/*",
|
3882
|
+
lazy: async () => {
|
3883
|
+
const { Layout } = await import("./layout-BNqvLR_b.mjs");
|
3884
|
+
return {
|
3885
|
+
Component: Layout
|
3886
|
+
};
|
3887
|
+
},
|
3888
|
+
children: routes
|
3110
3889
|
});
|
3111
3890
|
app.registerPlugin(cm.config);
|
3112
3891
|
},
|
3892
|
+
bootstrap(app) {
|
3893
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
3894
|
+
historyAdmin.bootstrap(app);
|
3895
|
+
}
|
3896
|
+
},
|
3113
3897
|
async registerTrads({ locales }) {
|
3114
3898
|
const importedTrads = await Promise.all(
|
3115
3899
|
locales.map((locale) => {
|
3116
|
-
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-
|
3900
|
+
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-BrCTWlZv.mjs"), "./translations/es.json": () => import("./es-CeXiYflN.mjs"), "./translations/eu.json": () => import("./eu-CdALomew.mjs"), "./translations/fr.json": () => import("./fr-CD9VFbPM.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-CtsUxOvk.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 }) => {
|
3117
3901
|
return {
|
3118
3902
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3119
3903
|
locale
|
@@ -3131,7 +3915,7 @@ const index = {
|
|
3131
3915
|
};
|
3132
3916
|
export {
|
3133
3917
|
ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD as A,
|
3134
|
-
|
3918
|
+
BulkActionsRenderer as B,
|
3135
3919
|
COLLECTION_TYPES as C,
|
3136
3920
|
DocumentStatus as D,
|
3137
3921
|
DEFAULT_SETTINGS as E,
|
@@ -3145,31 +3929,31 @@ export {
|
|
3145
3929
|
RelativeTime as R,
|
3146
3930
|
SINGLE_TYPES as S,
|
3147
3931
|
TableActions as T,
|
3148
|
-
|
3149
|
-
|
3150
|
-
|
3151
|
-
|
3152
|
-
|
3153
|
-
|
3932
|
+
useGetInitialDataQuery as a,
|
3933
|
+
useGetAllContentTypeSettingsQuery as b,
|
3934
|
+
useDoc as c,
|
3935
|
+
buildValidParams as d,
|
3936
|
+
contentManagerApi as e,
|
3937
|
+
useDocumentRBAC as f,
|
3154
3938
|
getTranslation as g,
|
3155
|
-
|
3156
|
-
|
3157
|
-
|
3158
|
-
|
3159
|
-
|
3160
|
-
|
3161
|
-
|
3939
|
+
useDocumentLayout as h,
|
3940
|
+
createYupSchema as i,
|
3941
|
+
Header as j,
|
3942
|
+
PERMISSIONS as k,
|
3943
|
+
DocumentRBAC as l,
|
3944
|
+
DOCUMENT_META_FIELDS as m,
|
3945
|
+
useDocLayout as n,
|
3162
3946
|
useGetContentTypeConfigurationQuery as o,
|
3163
3947
|
CREATOR_FIELDS as p,
|
3164
3948
|
getMainField as q,
|
3165
|
-
|
3949
|
+
getDisplayName as r,
|
3166
3950
|
setInitialData as s,
|
3167
|
-
|
3168
|
-
|
3169
|
-
|
3170
|
-
|
3171
|
-
|
3172
|
-
|
3173
|
-
|
3174
|
-
};
|
3175
|
-
//# sourceMappingURL=index-
|
3951
|
+
checkIfAttributeIsDisplayable as t,
|
3952
|
+
useContentTypeSchema as u,
|
3953
|
+
useGetAllDocumentsQuery as v,
|
3954
|
+
convertListLayoutToFieldLayouts as w,
|
3955
|
+
capitalise as x,
|
3956
|
+
useUpdateContentTypeConfigurationMutation as y,
|
3957
|
+
extractContentTypeComponents as z
|
3958
|
+
};
|
3959
|
+
//# sourceMappingURL=index-C9TJPyni.mjs.map
|