@strapi/content-manager 0.0.0-experimental.a65a85fdea97faae8679d3ffc5f9d79af61abd26 → 0.0.0-experimental.a6728ad43ac70ae19dabb624dbfca1f2d9610a86
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-DJ5voqEK.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage--2aLCv-G.mjs.map → ComponentConfigurationPage-DJ5voqEK.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js → ComponentConfigurationPage-_6osrv39.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-43KmCNQE.js.map → ComponentConfigurationPage-_6osrv39.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-CUcGHHvQ.mjs → EditConfigurationPage-CZofxSLy.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CUcGHHvQ.mjs.map → EditConfigurationPage-CZofxSLy.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js → EditConfigurationPage-ZN3s568V.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BfFzJ4Br.js.map → EditConfigurationPage-ZN3s568V.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-CzOT5Kpj.js → EditViewPage-Co2IKQZH.js} +58 -49
- package/dist/_chunks/EditViewPage-Co2IKQZH.js.map +1 -0
- package/dist/_chunks/{EditViewPage-Bm8lgcm6.mjs → EditViewPage-HYljoEY7.mjs} +59 -48
- package/dist/_chunks/EditViewPage-HYljoEY7.mjs.map +1 -0
- package/dist/_chunks/{Field-Dlh0uGnL.mjs → Field-BOPUMZ1u.mjs} +995 -795
- package/dist/_chunks/Field-BOPUMZ1u.mjs.map +1 -0
- package/dist/_chunks/{Field-Caef4JjM.js → Field-G9CkFUtP.js} +1041 -842
- package/dist/_chunks/Field-G9CkFUtP.js.map +1 -0
- package/dist/_chunks/{Form-EnaQL_6L.mjs → Form-CDwNp7pU.mjs} +69 -48
- package/dist/_chunks/Form-CDwNp7pU.mjs.map +1 -0
- package/dist/_chunks/{Form-BzuAjtRq.js → Form-crsbkGxI.js} +68 -48
- package/dist/_chunks/Form-crsbkGxI.js.map +1 -0
- package/dist/_chunks/{History-D6sbCJvo.mjs → History-BDZrgfZ3.mjs} +151 -57
- package/dist/_chunks/History-BDZrgfZ3.mjs.map +1 -0
- package/dist/_chunks/{History-C17LiyRg.js → History-CWcM9HnW.js} +151 -58
- package/dist/_chunks/History-CWcM9HnW.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Ce4qs7qE.mjs → ListConfigurationPage-BZ3ScUna.mjs} +67 -57
- package/dist/_chunks/ListConfigurationPage-BZ3ScUna.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Dks5SX6f.js → ListConfigurationPage-DGzoQD_I.js} +70 -61
- package/dist/_chunks/ListConfigurationPage-DGzoQD_I.js.map +1 -0
- package/dist/_chunks/{ListViewPage-BwrZrPsh.js → ListViewPage-BBAC9aPu.js} +132 -139
- package/dist/_chunks/ListViewPage-BBAC9aPu.js.map +1 -0
- package/dist/_chunks/{ListViewPage-Be7S5aKL.mjs → ListViewPage-CsX7tWx-.mjs} +129 -136
- package/dist/_chunks/ListViewPage-CsX7tWx-.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-Cu5r1-JT.js → NoContentTypePage-CwVDx_YC.js} +5 -5
- package/dist/_chunks/NoContentTypePage-CwVDx_YC.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CIPmYQMm.mjs → NoContentTypePage-LClTUPWs.mjs} +7 -7
- package/dist/_chunks/NoContentTypePage-LClTUPWs.mjs.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-C-j6TEUF.js → NoPermissionsPage-D2iWw-sn.js} +4 -5
- package/dist/_chunks/NoPermissionsPage-D2iWw-sn.js.map +1 -0
- package/dist/_chunks/{NoPermissionsPage-DhJ7LYrr.mjs → NoPermissionsPage-S4Re3FwO.mjs} +5 -6
- package/dist/_chunks/NoPermissionsPage-S4Re3FwO.mjs.map +1 -0
- package/dist/_chunks/{Relations-CY7AtkDA.mjs → Relations-Dmv0Tpe5.mjs} +67 -57
- package/dist/_chunks/Relations-Dmv0Tpe5.mjs.map +1 -0
- package/dist/_chunks/{Relations-Czs-uZ-s.js → Relations-jwuTFGOV.js} +71 -62
- package/dist/_chunks/Relations-jwuTFGOV.js.map +1 -0
- package/dist/_chunks/{en-C-V1_90f.js → en-BlhnxQfj.js} +17 -9
- package/dist/_chunks/{en-C-V1_90f.js.map → en-BlhnxQfj.js.map} +1 -1
- package/dist/_chunks/{en-MBPul9Su.mjs → en-C8YBvRrK.mjs} +17 -9
- package/dist/_chunks/{en-MBPul9Su.mjs.map → en-C8YBvRrK.mjs.map} +1 -1
- package/dist/_chunks/{index-DNVx8ssZ.mjs → index-BmUAydCA.mjs} +1715 -813
- package/dist/_chunks/index-BmUAydCA.mjs.map +1 -0
- package/dist/_chunks/{index-X_2tafck.js → index-CBX6KyXv.js} +1815 -914
- package/dist/_chunks/index-CBX6KyXv.js.map +1 -0
- package/dist/_chunks/{layout-Dnh0PNp9.mjs → layout-ClP-DC72.mjs} +47 -29
- package/dist/_chunks/layout-ClP-DC72.mjs.map +1 -0
- package/dist/_chunks/{layout-dBc7wN7L.js → layout-CxxkX9jY.js} +47 -31
- package/dist/_chunks/layout-CxxkX9jY.js.map +1 -0
- package/dist/_chunks/{relations-4pHtBrHJ.js → relations-DIjTADIu.js} +2 -2
- package/dist/_chunks/{relations-4pHtBrHJ.js.map → relations-DIjTADIu.js.map} +1 -1
- package/dist/_chunks/{relations-Dx7tMKJN.mjs → relations-op89RClB.mjs} +2 -2
- package/dist/_chunks/{relations-Dx7tMKJN.mjs.map → relations-op89RClB.mjs.map} +1 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js +28 -0
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/_chunks/useDragAndDrop-DdHgKsqq.mjs.map +1 -1
- package/dist/_chunks/useDragAndDrop-J0TUUbR6.js.map +1 -1
- package/dist/admin/index.js +3 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +9 -7
- 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 +2 -1
- package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +35 -9
- 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 +16 -53
- package/dist/admin/src/pages/EditView/components/Header.d.ts +10 -11
- 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 +31 -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 +5 -7
- package/dist/server/index.js +648 -447
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +656 -455
- 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/relations.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 +42 -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/policies/hasPermissions.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/permission-checker.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 +17 -7
- 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 +16 -17
- 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
- package/strapi-server.js +0 -3
@@ -1,19 +1,17 @@
|
|
1
|
-
import {
|
1
|
+
import { More, Cross, WarningCircle, ListPlus, Pencil, Trash, Check, CrossCircle, CheckCircle, ArrowsCounterClockwise, ChevronRight, Duplicate, ClockCounterClockwise, Feather } from "@strapi/icons";
|
2
2
|
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
3
|
-
import { useStrapiApp,
|
4
|
-
import { stringify } from "qs";
|
5
|
-
import { useIntl } from "react-intl";
|
6
|
-
import { useNavigate, useParams, Navigate, useMatch, NavLink } from "react-router-dom";
|
3
|
+
import { useStrapiApp, createContext, useAuth, useRBAC, Page, adminApi, translatedErrors, useNotification, useAPIErrorHandler, useQueryParams, getYupValidationErrors, useForm, useTracking, useGuidedTour, BackButton, DescriptionComponentRenderer, useTable, Table } from "@strapi/admin/strapi-admin";
|
7
4
|
import * as React from "react";
|
8
5
|
import { lazy } from "react";
|
9
|
-
import { Menu, VisuallyHidden, Flex, Typography, Dialog,
|
10
|
-
import
|
6
|
+
import { Button, Menu, VisuallyHidden, Flex, Typography, Dialog, Modal, Radio, Status, Box, SingleSelect, SingleSelectOption, IconButton, Loader, Tooltip, LinkButton } from "@strapi/design-system";
|
7
|
+
import { useIntl } from "react-intl";
|
8
|
+
import { useParams, useNavigate, Navigate, useMatch, useLocation, Link, NavLink } from "react-router-dom";
|
11
9
|
import * as yup from "yup";
|
12
10
|
import { ValidationError } from "yup";
|
13
|
-
import { createApi } from "@reduxjs/toolkit/query/react";
|
14
|
-
import { isAxiosError } from "axios";
|
15
11
|
import pipe from "lodash/fp/pipe";
|
16
12
|
import { intervalToDuration, isPast } from "date-fns";
|
13
|
+
import { styled } from "styled-components";
|
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,89 +150,20 @@ 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",
|
267
158
|
"Document",
|
268
159
|
"InitialData",
|
269
160
|
"HistoryVersion",
|
270
|
-
"Relations"
|
271
|
-
|
272
|
-
|
161
|
+
"Relations",
|
162
|
+
"UidAvailability"
|
163
|
+
]
|
273
164
|
});
|
274
165
|
const documentApi = contentManagerApi.injectEndpoints({
|
166
|
+
overrideExisting: true,
|
275
167
|
endpoints: (builder) => ({
|
276
168
|
autoCloneDocument: builder.mutation({
|
277
169
|
query: ({ model, sourceId, query }) => ({
|
@@ -281,7 +173,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
281
173
|
params: query
|
282
174
|
}
|
283
175
|
}),
|
284
|
-
invalidatesTags: (_result,
|
176
|
+
invalidatesTags: (_result, error, { model }) => {
|
177
|
+
if (error) {
|
178
|
+
return [];
|
179
|
+
}
|
180
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
181
|
+
}
|
285
182
|
}),
|
286
183
|
cloneDocument: builder.mutation({
|
287
184
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -292,7 +189,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
292
189
|
params
|
293
190
|
}
|
294
191
|
}),
|
295
|
-
invalidatesTags: (_result, _error, { model }) => [
|
192
|
+
invalidatesTags: (_result, _error, { model }) => [
|
193
|
+
{ type: "Document", id: `${model}_LIST` },
|
194
|
+
{ type: "UidAvailability", id: model }
|
195
|
+
]
|
296
196
|
}),
|
297
197
|
/**
|
298
198
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -309,7 +209,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
309
209
|
}),
|
310
210
|
invalidatesTags: (result, _error, { model }) => [
|
311
211
|
{ type: "Document", id: `${model}_LIST` },
|
312
|
-
"Relations"
|
212
|
+
"Relations",
|
213
|
+
{ type: "UidAvailability", id: model }
|
313
214
|
]
|
314
215
|
}),
|
315
216
|
deleteDocument: builder.mutation({
|
@@ -325,12 +226,15 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
325
226
|
]
|
326
227
|
}),
|
327
228
|
deleteManyDocuments: builder.mutation({
|
328
|
-
query: ({ model, ...body }) => ({
|
229
|
+
query: ({ model, params, ...body }) => ({
|
329
230
|
url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
|
330
231
|
method: "POST",
|
331
|
-
data: body
|
232
|
+
data: body,
|
233
|
+
config: {
|
234
|
+
params
|
235
|
+
}
|
332
236
|
}),
|
333
|
-
invalidatesTags: (_res, _error, { model
|
237
|
+
invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
|
334
238
|
}),
|
335
239
|
discardDocument: builder.mutation({
|
336
240
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -347,7 +251,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
347
251
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
348
252
|
},
|
349
253
|
{ type: "Document", id: `${model}_LIST` },
|
350
|
-
"Relations"
|
254
|
+
"Relations",
|
255
|
+
{ type: "UidAvailability", id: model }
|
351
256
|
];
|
352
257
|
}
|
353
258
|
}),
|
@@ -365,6 +270,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
365
270
|
}),
|
366
271
|
providesTags: (result, _error, arg) => {
|
367
272
|
return [
|
273
|
+
{ type: "Document", id: `ALL_LIST` },
|
368
274
|
{ type: "Document", id: `${arg.model}_LIST` },
|
369
275
|
...result?.results.map(({ documentId }) => ({
|
370
276
|
type: "Document",
|
@@ -403,6 +309,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
403
309
|
{
|
404
310
|
type: "Document",
|
405
311
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
312
|
+
},
|
313
|
+
// Make it easy to invalidate all individual documents queries for a model
|
314
|
+
{
|
315
|
+
type: "Document",
|
316
|
+
id: `${model}_ALL_ITEMS`
|
406
317
|
}
|
407
318
|
];
|
408
319
|
}
|
@@ -441,10 +352,13 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
441
352
|
}
|
442
353
|
}),
|
443
354
|
publishManyDocuments: builder.mutation({
|
444
|
-
query: ({ model, ...body }) => ({
|
355
|
+
query: ({ model, params, ...body }) => ({
|
445
356
|
url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
|
446
357
|
method: "POST",
|
447
|
-
data: body
|
358
|
+
data: body,
|
359
|
+
config: {
|
360
|
+
params
|
361
|
+
}
|
448
362
|
}),
|
449
363
|
invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
|
450
364
|
}),
|
@@ -463,8 +377,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
463
377
|
type: "Document",
|
464
378
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
465
379
|
},
|
466
|
-
"Relations"
|
380
|
+
"Relations",
|
381
|
+
{ type: "UidAvailability", id: model }
|
467
382
|
];
|
383
|
+
},
|
384
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
385
|
+
const patchResult = dispatch(
|
386
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
387
|
+
Object.assign(draft.data, data);
|
388
|
+
})
|
389
|
+
);
|
390
|
+
try {
|
391
|
+
await queryFulfilled;
|
392
|
+
} catch {
|
393
|
+
patchResult.undo();
|
394
|
+
}
|
468
395
|
}
|
469
396
|
}),
|
470
397
|
unpublishDocument: builder.mutation({
|
@@ -486,10 +413,13 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
486
413
|
}
|
487
414
|
}),
|
488
415
|
unpublishManyDocuments: builder.mutation({
|
489
|
-
query: ({ model, ...body }) => ({
|
416
|
+
query: ({ model, params, ...body }) => ({
|
490
417
|
url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
|
491
418
|
method: "POST",
|
492
|
-
data: body
|
419
|
+
data: body,
|
420
|
+
config: {
|
421
|
+
params
|
422
|
+
}
|
493
423
|
}),
|
494
424
|
invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
|
495
425
|
})
|
@@ -513,7 +443,25 @@ const {
|
|
513
443
|
useUnpublishDocumentMutation,
|
514
444
|
useUnpublishManyDocumentsMutation
|
515
445
|
} = documentApi;
|
516
|
-
const
|
446
|
+
const buildValidParams = (query) => {
|
447
|
+
if (!query)
|
448
|
+
return query;
|
449
|
+
const { plugins: _, ...validQueryParams } = {
|
450
|
+
...query,
|
451
|
+
...Object.values(query?.plugins ?? {}).reduce(
|
452
|
+
(acc, current) => Object.assign(acc, current),
|
453
|
+
{}
|
454
|
+
)
|
455
|
+
};
|
456
|
+
if ("_q" in validQueryParams) {
|
457
|
+
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
458
|
+
}
|
459
|
+
return validQueryParams;
|
460
|
+
};
|
461
|
+
const isBaseQueryError = (error) => {
|
462
|
+
return error.name !== void 0;
|
463
|
+
};
|
464
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
517
465
|
const createModelSchema = (attributes2) => yup.object().shape(
|
518
466
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
519
467
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
@@ -526,7 +474,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
526
474
|
addMinValidation,
|
527
475
|
addMaxValidation,
|
528
476
|
addRegexValidation
|
529
|
-
].map((fn) => fn(attribute));
|
477
|
+
].map((fn) => fn(attribute, options));
|
530
478
|
const transformSchema = pipe(...validations);
|
531
479
|
switch (attribute.type) {
|
532
480
|
case "component": {
|
@@ -552,10 +500,14 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
552
500
|
yup.array().of(
|
553
501
|
yup.lazy(
|
554
502
|
(data) => {
|
555
|
-
const
|
556
|
-
|
503
|
+
const attributes3 = components?.[data?.__component]?.attributes;
|
504
|
+
const validation = yup.object().shape({
|
557
505
|
__component: yup.string().required().oneOf(Object.keys(components))
|
558
|
-
}).nullable(false)
|
506
|
+
}).nullable(false);
|
507
|
+
if (!attributes3) {
|
508
|
+
return validation;
|
509
|
+
}
|
510
|
+
return validation.concat(createModelSchema(attributes3));
|
559
511
|
}
|
560
512
|
)
|
561
513
|
)
|
@@ -565,11 +517,25 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
565
517
|
return {
|
566
518
|
...acc,
|
567
519
|
[name]: transformSchema(
|
568
|
-
yup.
|
569
|
-
|
570
|
-
|
571
|
-
})
|
572
|
-
|
520
|
+
yup.lazy((value) => {
|
521
|
+
if (!value) {
|
522
|
+
return yup.mixed().nullable(true);
|
523
|
+
} else if (Array.isArray(value)) {
|
524
|
+
return yup.array().of(
|
525
|
+
yup.object().shape({
|
526
|
+
id: yup.string().required()
|
527
|
+
})
|
528
|
+
);
|
529
|
+
} else if (typeof value === "object") {
|
530
|
+
return yup.object();
|
531
|
+
} else {
|
532
|
+
return yup.mixed().test(
|
533
|
+
"type-error",
|
534
|
+
"Relation values must be either null, an array of objects with {id} or an object.",
|
535
|
+
() => false
|
536
|
+
);
|
537
|
+
}
|
538
|
+
})
|
573
539
|
)
|
574
540
|
};
|
575
541
|
default:
|
@@ -609,6 +575,14 @@ const createAttributeSchema = (attribute) => {
|
|
609
575
|
if (!value || typeof value === "string" && value.length === 0) {
|
610
576
|
return true;
|
611
577
|
}
|
578
|
+
if (typeof value === "object") {
|
579
|
+
try {
|
580
|
+
JSON.stringify(value);
|
581
|
+
return true;
|
582
|
+
} catch (err) {
|
583
|
+
return false;
|
584
|
+
}
|
585
|
+
}
|
612
586
|
try {
|
613
587
|
JSON.parse(value);
|
614
588
|
return true;
|
@@ -627,16 +601,30 @@ const createAttributeSchema = (attribute) => {
|
|
627
601
|
return yup.mixed();
|
628
602
|
}
|
629
603
|
};
|
630
|
-
const
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
604
|
+
const nullableSchema = (schema) => {
|
605
|
+
return schema?.nullable ? schema.nullable() : (
|
606
|
+
// In some cases '.nullable' will not be available on the schema.
|
607
|
+
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
608
|
+
// In these cases we should just return the schema as it is.
|
609
|
+
schema
|
610
|
+
);
|
611
|
+
};
|
612
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
613
|
+
if (options.status === "draft") {
|
614
|
+
return nullableSchema(schema);
|
636
615
|
}
|
637
|
-
|
616
|
+
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
617
|
+
return schema.min(1, translatedErrors.required);
|
618
|
+
}
|
619
|
+
if (attribute.required && attribute.type !== "relation") {
|
620
|
+
return schema.required(translatedErrors.required);
|
621
|
+
}
|
622
|
+
return nullableSchema(schema);
|
638
623
|
};
|
639
|
-
const addMinLengthValidation = (attribute) => (schema) => {
|
624
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
625
|
+
if (options.status === "draft") {
|
626
|
+
return schema;
|
627
|
+
}
|
640
628
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
641
629
|
return schema.min(attribute.minLength, {
|
642
630
|
...translatedErrors.minLength,
|
@@ -658,9 +646,31 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
658
646
|
}
|
659
647
|
return schema;
|
660
648
|
};
|
661
|
-
const addMinValidation = (attribute) => (schema) => {
|
649
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
662
650
|
if ("min" in attribute) {
|
663
651
|
const min = toInteger(attribute.min);
|
652
|
+
if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
|
653
|
+
if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
|
654
|
+
return schema.test(
|
655
|
+
"custom-min",
|
656
|
+
{
|
657
|
+
...translatedErrors.min,
|
658
|
+
values: {
|
659
|
+
min: attribute.min
|
660
|
+
}
|
661
|
+
},
|
662
|
+
(value) => {
|
663
|
+
if (!value) {
|
664
|
+
return true;
|
665
|
+
}
|
666
|
+
if (Array.isArray(value) && value.length === 0) {
|
667
|
+
return true;
|
668
|
+
}
|
669
|
+
return value.length >= min;
|
670
|
+
}
|
671
|
+
);
|
672
|
+
}
|
673
|
+
}
|
664
674
|
if ("min" in schema && min) {
|
665
675
|
return schema.min(min, {
|
666
676
|
...translatedErrors.min,
|
@@ -706,24 +716,6 @@ const addRegexValidation = (attribute) => (schema) => {
|
|
706
716
|
}
|
707
717
|
return schema;
|
708
718
|
};
|
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
719
|
const initApi = contentManagerApi.injectEndpoints({
|
728
720
|
endpoints: (builder) => ({
|
729
721
|
getInitialData: builder.query({
|
@@ -737,27 +729,20 @@ const { useGetInitialDataQuery } = initApi;
|
|
737
729
|
const useContentTypeSchema = (model) => {
|
738
730
|
const { toggleNotification } = useNotification();
|
739
731
|
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
|
-
});
|
732
|
+
const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
|
733
|
+
const { components, contentType, contentTypes } = React.useMemo(() => {
|
734
|
+
const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
|
735
|
+
const componentsByKey = data?.components.reduce((acc, component) => {
|
736
|
+
acc[component.uid] = component;
|
737
|
+
return acc;
|
738
|
+
}, {});
|
739
|
+
const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
|
740
|
+
return {
|
741
|
+
components: Object.keys(components2).length === 0 ? void 0 : components2,
|
742
|
+
contentType: contentType2,
|
743
|
+
contentTypes: data?.contentTypes ?? []
|
744
|
+
};
|
745
|
+
}, [model, data]);
|
761
746
|
React.useEffect(() => {
|
762
747
|
if (error) {
|
763
748
|
toggleNotification({
|
@@ -804,7 +789,310 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
804
789
|
}, {});
|
805
790
|
return componentsByKey;
|
806
791
|
};
|
807
|
-
const
|
792
|
+
const HOOKS = {
|
793
|
+
/**
|
794
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
795
|
+
* @constant
|
796
|
+
* @type {string}
|
797
|
+
*/
|
798
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
799
|
+
/**
|
800
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
801
|
+
* @constant
|
802
|
+
* @type {string}
|
803
|
+
*/
|
804
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
805
|
+
/**
|
806
|
+
* Hook that allows to mutate the CM's edit view layout
|
807
|
+
* @constant
|
808
|
+
* @type {string}
|
809
|
+
*/
|
810
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
811
|
+
/**
|
812
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
813
|
+
* @constant
|
814
|
+
* @type {string}
|
815
|
+
*/
|
816
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
817
|
+
};
|
818
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
819
|
+
endpoints: (builder) => ({
|
820
|
+
getContentTypeConfiguration: builder.query({
|
821
|
+
query: (uid) => ({
|
822
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
823
|
+
method: "GET"
|
824
|
+
}),
|
825
|
+
transformResponse: (response) => response.data,
|
826
|
+
providesTags: (_result, _error, uid) => [
|
827
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
828
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
829
|
+
]
|
830
|
+
}),
|
831
|
+
getAllContentTypeSettings: builder.query({
|
832
|
+
query: () => "/content-manager/content-types-settings",
|
833
|
+
transformResponse: (response) => response.data,
|
834
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
835
|
+
}),
|
836
|
+
updateContentTypeConfiguration: builder.mutation({
|
837
|
+
query: ({ uid, ...body }) => ({
|
838
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
839
|
+
method: "PUT",
|
840
|
+
data: body
|
841
|
+
}),
|
842
|
+
transformResponse: (response) => response.data,
|
843
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
844
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
845
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
846
|
+
// Is this necessary?
|
847
|
+
{ type: "InitialData" }
|
848
|
+
]
|
849
|
+
})
|
850
|
+
})
|
851
|
+
});
|
852
|
+
const {
|
853
|
+
useGetContentTypeConfigurationQuery,
|
854
|
+
useGetAllContentTypeSettingsQuery,
|
855
|
+
useUpdateContentTypeConfigurationMutation
|
856
|
+
} = contentTypesApi;
|
857
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
858
|
+
const { type } = attribute;
|
859
|
+
if (type === "relation") {
|
860
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
861
|
+
}
|
862
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
863
|
+
};
|
864
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
865
|
+
if (!mainFieldName) {
|
866
|
+
return void 0;
|
867
|
+
}
|
868
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
869
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
870
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
871
|
+
);
|
872
|
+
return {
|
873
|
+
name: mainFieldName,
|
874
|
+
type: mainFieldType ?? "string"
|
875
|
+
};
|
876
|
+
};
|
877
|
+
const DEFAULT_SETTINGS = {
|
878
|
+
bulkable: false,
|
879
|
+
filterable: false,
|
880
|
+
searchable: false,
|
881
|
+
pagination: false,
|
882
|
+
defaultSortBy: "",
|
883
|
+
defaultSortOrder: "asc",
|
884
|
+
mainField: "id",
|
885
|
+
pageSize: 10
|
886
|
+
};
|
887
|
+
const useDocumentLayout = (model) => {
|
888
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
889
|
+
const [{ query }] = useQueryParams();
|
890
|
+
const runHookWaterfall = useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
891
|
+
const { toggleNotification } = useNotification();
|
892
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
893
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
894
|
+
const {
|
895
|
+
data,
|
896
|
+
isLoading: isLoadingConfigs,
|
897
|
+
error,
|
898
|
+
isFetching: isFetchingConfigs
|
899
|
+
} = useGetContentTypeConfigurationQuery(model);
|
900
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
901
|
+
React.useEffect(() => {
|
902
|
+
if (error) {
|
903
|
+
toggleNotification({
|
904
|
+
type: "danger",
|
905
|
+
message: formatAPIError(error)
|
906
|
+
});
|
907
|
+
}
|
908
|
+
}, [error, formatAPIError, toggleNotification]);
|
909
|
+
const editLayout = React.useMemo(
|
910
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
911
|
+
layout: [],
|
912
|
+
components: {},
|
913
|
+
metadatas: {},
|
914
|
+
options: {},
|
915
|
+
settings: DEFAULT_SETTINGS
|
916
|
+
},
|
917
|
+
[data, isLoading, schemas, schema, components]
|
918
|
+
);
|
919
|
+
const listLayout = React.useMemo(() => {
|
920
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
921
|
+
layout: [],
|
922
|
+
metadatas: {},
|
923
|
+
options: {},
|
924
|
+
settings: DEFAULT_SETTINGS
|
925
|
+
};
|
926
|
+
}, [data, isLoading, schemas, schema, components]);
|
927
|
+
const { layout: edit } = React.useMemo(
|
928
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
929
|
+
layout: editLayout,
|
930
|
+
query
|
931
|
+
}),
|
932
|
+
[editLayout, query, runHookWaterfall]
|
933
|
+
);
|
934
|
+
return {
|
935
|
+
error,
|
936
|
+
isLoading,
|
937
|
+
edit,
|
938
|
+
list: listLayout
|
939
|
+
};
|
940
|
+
};
|
941
|
+
const useDocLayout = () => {
|
942
|
+
const { model } = useDoc();
|
943
|
+
return useDocumentLayout(model);
|
944
|
+
};
|
945
|
+
const formatEditLayout = (data, {
|
946
|
+
schemas,
|
947
|
+
schema,
|
948
|
+
components
|
949
|
+
}) => {
|
950
|
+
let currentPanelIndex = 0;
|
951
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
952
|
+
data.contentType.layouts.edit,
|
953
|
+
schema?.attributes,
|
954
|
+
data.contentType.metadatas,
|
955
|
+
{ configurations: data.components, schemas: components },
|
956
|
+
schemas
|
957
|
+
).reduce((panels, row) => {
|
958
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
959
|
+
panels.push([row]);
|
960
|
+
currentPanelIndex += 2;
|
961
|
+
} else {
|
962
|
+
if (!panels[currentPanelIndex]) {
|
963
|
+
panels.push([]);
|
964
|
+
}
|
965
|
+
panels[currentPanelIndex].push(row);
|
966
|
+
}
|
967
|
+
return panels;
|
968
|
+
}, []);
|
969
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
970
|
+
(acc, [uid, configuration]) => {
|
971
|
+
acc[uid] = {
|
972
|
+
layout: convertEditLayoutToFieldLayouts(
|
973
|
+
configuration.layouts.edit,
|
974
|
+
components[uid].attributes,
|
975
|
+
configuration.metadatas,
|
976
|
+
{ configurations: data.components, schemas: components }
|
977
|
+
),
|
978
|
+
settings: {
|
979
|
+
...configuration.settings,
|
980
|
+
icon: components[uid].info.icon,
|
981
|
+
displayName: components[uid].info.displayName
|
982
|
+
}
|
983
|
+
};
|
984
|
+
return acc;
|
985
|
+
},
|
986
|
+
{}
|
987
|
+
);
|
988
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
989
|
+
(acc, [attribute, metadata]) => {
|
990
|
+
return {
|
991
|
+
...acc,
|
992
|
+
[attribute]: metadata.edit
|
993
|
+
};
|
994
|
+
},
|
995
|
+
{}
|
996
|
+
);
|
997
|
+
return {
|
998
|
+
layout: panelledEditAttributes,
|
999
|
+
components: componentEditAttributes,
|
1000
|
+
metadatas: editMetadatas,
|
1001
|
+
settings: {
|
1002
|
+
...data.contentType.settings,
|
1003
|
+
displayName: schema?.info.displayName
|
1004
|
+
},
|
1005
|
+
options: {
|
1006
|
+
...schema?.options,
|
1007
|
+
...schema?.pluginOptions,
|
1008
|
+
...data.contentType.options
|
1009
|
+
}
|
1010
|
+
};
|
1011
|
+
};
|
1012
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1013
|
+
return rows.map(
|
1014
|
+
(row) => row.map((field) => {
|
1015
|
+
const attribute = attributes[field.name];
|
1016
|
+
if (!attribute) {
|
1017
|
+
return null;
|
1018
|
+
}
|
1019
|
+
const { edit: metadata } = metadatas[field.name];
|
1020
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1021
|
+
return {
|
1022
|
+
attribute,
|
1023
|
+
disabled: !metadata.editable,
|
1024
|
+
hint: metadata.description,
|
1025
|
+
label: metadata.label ?? "",
|
1026
|
+
name: field.name,
|
1027
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1028
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1029
|
+
schemas,
|
1030
|
+
components: components?.schemas ?? {}
|
1031
|
+
}),
|
1032
|
+
placeholder: metadata.placeholder ?? "",
|
1033
|
+
required: attribute.required ?? false,
|
1034
|
+
size: field.size,
|
1035
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1036
|
+
visible: metadata.visible ?? true,
|
1037
|
+
type: attribute.type
|
1038
|
+
};
|
1039
|
+
}).filter((field) => field !== null)
|
1040
|
+
);
|
1041
|
+
};
|
1042
|
+
const formatListLayout = (data, {
|
1043
|
+
schemas,
|
1044
|
+
schema,
|
1045
|
+
components
|
1046
|
+
}) => {
|
1047
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1048
|
+
(acc, [attribute, metadata]) => {
|
1049
|
+
return {
|
1050
|
+
...acc,
|
1051
|
+
[attribute]: metadata.list
|
1052
|
+
};
|
1053
|
+
},
|
1054
|
+
{}
|
1055
|
+
);
|
1056
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1057
|
+
data.contentType.layouts.list,
|
1058
|
+
schema?.attributes,
|
1059
|
+
listMetadatas,
|
1060
|
+
{ configurations: data.components, schemas: components },
|
1061
|
+
schemas
|
1062
|
+
);
|
1063
|
+
return {
|
1064
|
+
layout: listAttributes,
|
1065
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1066
|
+
metadatas: listMetadatas,
|
1067
|
+
options: {
|
1068
|
+
...schema?.options,
|
1069
|
+
...schema?.pluginOptions,
|
1070
|
+
...data.contentType.options
|
1071
|
+
}
|
1072
|
+
};
|
1073
|
+
};
|
1074
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1075
|
+
return columns.map((name) => {
|
1076
|
+
const attribute = attributes[name];
|
1077
|
+
if (!attribute) {
|
1078
|
+
return null;
|
1079
|
+
}
|
1080
|
+
const metadata = metadatas[name];
|
1081
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1082
|
+
return {
|
1083
|
+
attribute,
|
1084
|
+
label: metadata.label ?? "",
|
1085
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1086
|
+
schemas,
|
1087
|
+
components: components?.schemas ?? {}
|
1088
|
+
}),
|
1089
|
+
name,
|
1090
|
+
searchable: metadata.searchable ?? true,
|
1091
|
+
sortable: metadata.sortable ?? true
|
1092
|
+
};
|
1093
|
+
}).filter((field) => field !== null);
|
1094
|
+
};
|
1095
|
+
const useDocument = (args, opts) => {
|
808
1096
|
const { toggleNotification } = useNotification();
|
809
1097
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
810
1098
|
const {
|
@@ -812,8 +1100,16 @@ const useDocument = (args, opts) => {
|
|
812
1100
|
isLoading: isLoadingDocument,
|
813
1101
|
isFetching: isFetchingDocument,
|
814
1102
|
error
|
815
|
-
} = useGetDocumentQuery(args,
|
816
|
-
|
1103
|
+
} = useGetDocumentQuery(args, {
|
1104
|
+
...opts,
|
1105
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1106
|
+
});
|
1107
|
+
const {
|
1108
|
+
components,
|
1109
|
+
schema,
|
1110
|
+
schemas,
|
1111
|
+
isLoading: isLoadingSchema
|
1112
|
+
} = useContentTypeSchema(args.model);
|
817
1113
|
React.useEffect(() => {
|
818
1114
|
if (error) {
|
819
1115
|
toggleNotification({
|
@@ -840,7 +1136,7 @@ const useDocument = (args, opts) => {
|
|
840
1136
|
return null;
|
841
1137
|
} catch (error2) {
|
842
1138
|
if (error2 instanceof ValidationError) {
|
843
|
-
return
|
1139
|
+
return getYupValidationErrors(error2);
|
844
1140
|
}
|
845
1141
|
throw error2;
|
846
1142
|
}
|
@@ -854,6 +1150,7 @@ const useDocument = (args, opts) => {
|
|
854
1150
|
meta: data?.meta,
|
855
1151
|
isLoading,
|
856
1152
|
schema,
|
1153
|
+
schemas,
|
857
1154
|
validate
|
858
1155
|
};
|
859
1156
|
};
|
@@ -879,6 +1176,45 @@ const useDoc = () => {
|
|
879
1176
|
)
|
880
1177
|
};
|
881
1178
|
};
|
1179
|
+
const useContentManagerContext = () => {
|
1180
|
+
const {
|
1181
|
+
collectionType,
|
1182
|
+
model,
|
1183
|
+
id,
|
1184
|
+
components,
|
1185
|
+
isLoading: isLoadingDoc,
|
1186
|
+
schema,
|
1187
|
+
schemas
|
1188
|
+
} = useDoc();
|
1189
|
+
const layout = useDocumentLayout(model);
|
1190
|
+
const form = useForm("useContentManagerContext", (state) => state);
|
1191
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1192
|
+
const slug = model;
|
1193
|
+
const isCreatingEntry = id === "create";
|
1194
|
+
useContentTypeSchema();
|
1195
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1196
|
+
const error = layout.error;
|
1197
|
+
return {
|
1198
|
+
error,
|
1199
|
+
isLoading,
|
1200
|
+
// Base metadata
|
1201
|
+
model,
|
1202
|
+
collectionType,
|
1203
|
+
id,
|
1204
|
+
slug,
|
1205
|
+
isCreatingEntry,
|
1206
|
+
isSingleType,
|
1207
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1208
|
+
// All schema infos
|
1209
|
+
components,
|
1210
|
+
contentType: schema,
|
1211
|
+
contentTypes: schemas,
|
1212
|
+
// Form state
|
1213
|
+
form,
|
1214
|
+
// layout infos
|
1215
|
+
layout
|
1216
|
+
};
|
1217
|
+
};
|
882
1218
|
const prefixPluginTranslations = (trad, pluginId) => {
|
883
1219
|
if (!pluginId) {
|
884
1220
|
throw new TypeError("pluginId can't be empty");
|
@@ -898,6 +1234,8 @@ const useDocumentActions = () => {
|
|
898
1234
|
const { formatMessage } = useIntl();
|
899
1235
|
const { trackUsage } = useTracking();
|
900
1236
|
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler();
|
1237
|
+
const navigate = useNavigate();
|
1238
|
+
const setCurrentStep = useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
901
1239
|
const [deleteDocument] = useDeleteDocumentMutation();
|
902
1240
|
const _delete = React.useCallback(
|
903
1241
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -936,14 +1274,53 @@ const useDocumentActions = () => {
|
|
936
1274
|
},
|
937
1275
|
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
938
1276
|
);
|
1277
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1278
|
+
const deleteMany = React.useCallback(
|
1279
|
+
async ({ model, documentIds, params }) => {
|
1280
|
+
try {
|
1281
|
+
trackUsage("willBulkDeleteEntries");
|
1282
|
+
const res = await deleteManyDocuments({
|
1283
|
+
model,
|
1284
|
+
documentIds,
|
1285
|
+
params
|
1286
|
+
});
|
1287
|
+
if ("error" in res) {
|
1288
|
+
toggleNotification({
|
1289
|
+
type: "danger",
|
1290
|
+
message: formatAPIError(res.error)
|
1291
|
+
});
|
1292
|
+
return { error: res.error };
|
1293
|
+
}
|
1294
|
+
toggleNotification({
|
1295
|
+
type: "success",
|
1296
|
+
title: formatMessage({
|
1297
|
+
id: getTranslation("success.records.delete"),
|
1298
|
+
defaultMessage: "Successfully deleted."
|
1299
|
+
}),
|
1300
|
+
message: ""
|
1301
|
+
});
|
1302
|
+
trackUsage("didBulkDeleteEntries");
|
1303
|
+
return res.data;
|
1304
|
+
} catch (err) {
|
1305
|
+
toggleNotification({
|
1306
|
+
type: "danger",
|
1307
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1308
|
+
});
|
1309
|
+
trackUsage("didNotBulkDeleteEntries");
|
1310
|
+
throw err;
|
1311
|
+
}
|
1312
|
+
},
|
1313
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1314
|
+
);
|
939
1315
|
const [discardDocument] = useDiscardDocumentMutation();
|
940
1316
|
const discard = React.useCallback(
|
941
|
-
async ({ collectionType, model, documentId }) => {
|
1317
|
+
async ({ collectionType, model, documentId, params }) => {
|
942
1318
|
try {
|
943
1319
|
const res = await discardDocument({
|
944
1320
|
collectionType,
|
945
1321
|
model,
|
946
|
-
documentId
|
1322
|
+
documentId,
|
1323
|
+
params
|
947
1324
|
});
|
948
1325
|
if ("error" in res) {
|
949
1326
|
toggleNotification({
|
@@ -1005,15 +1382,52 @@ const useDocumentActions = () => {
|
|
1005
1382
|
},
|
1006
1383
|
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1007
1384
|
);
|
1008
|
-
const [
|
1009
|
-
const
|
1010
|
-
async ({
|
1385
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1386
|
+
const publishMany = React.useCallback(
|
1387
|
+
async ({ model, documentIds, params }) => {
|
1011
1388
|
try {
|
1012
|
-
|
1013
|
-
const res = await updateDocument({
|
1014
|
-
collectionType,
|
1389
|
+
const res = await publishManyDocuments({
|
1015
1390
|
model,
|
1016
|
-
|
1391
|
+
documentIds,
|
1392
|
+
params
|
1393
|
+
});
|
1394
|
+
if ("error" in res) {
|
1395
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1396
|
+
return { error: res.error };
|
1397
|
+
}
|
1398
|
+
toggleNotification({
|
1399
|
+
type: "success",
|
1400
|
+
message: formatMessage({
|
1401
|
+
id: getTranslation("success.record.publish"),
|
1402
|
+
defaultMessage: "Published document"
|
1403
|
+
})
|
1404
|
+
});
|
1405
|
+
return res.data;
|
1406
|
+
} catch (err) {
|
1407
|
+
toggleNotification({
|
1408
|
+
type: "danger",
|
1409
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1410
|
+
});
|
1411
|
+
throw err;
|
1412
|
+
}
|
1413
|
+
},
|
1414
|
+
[
|
1415
|
+
// trackUsage,
|
1416
|
+
publishManyDocuments,
|
1417
|
+
toggleNotification,
|
1418
|
+
formatMessage,
|
1419
|
+
formatAPIError
|
1420
|
+
]
|
1421
|
+
);
|
1422
|
+
const [updateDocument] = useUpdateDocumentMutation();
|
1423
|
+
const update = React.useCallback(
|
1424
|
+
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
1425
|
+
try {
|
1426
|
+
trackUsage("willEditEntry", trackerProperty);
|
1427
|
+
const res = await updateDocument({
|
1428
|
+
collectionType,
|
1429
|
+
model,
|
1430
|
+
documentId,
|
1017
1431
|
data,
|
1018
1432
|
params
|
1019
1433
|
});
|
@@ -1079,6 +1493,41 @@ const useDocumentActions = () => {
|
|
1079
1493
|
},
|
1080
1494
|
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1081
1495
|
);
|
1496
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1497
|
+
const unpublishMany = React.useCallback(
|
1498
|
+
async ({ model, documentIds, params }) => {
|
1499
|
+
try {
|
1500
|
+
trackUsage("willBulkUnpublishEntries");
|
1501
|
+
const res = await unpublishManyDocuments({
|
1502
|
+
model,
|
1503
|
+
documentIds,
|
1504
|
+
params
|
1505
|
+
});
|
1506
|
+
if ("error" in res) {
|
1507
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1508
|
+
return { error: res.error };
|
1509
|
+
}
|
1510
|
+
trackUsage("didBulkUnpublishEntries");
|
1511
|
+
toggleNotification({
|
1512
|
+
type: "success",
|
1513
|
+
title: formatMessage({
|
1514
|
+
id: getTranslation("success.records.unpublish"),
|
1515
|
+
defaultMessage: "Successfully unpublished."
|
1516
|
+
}),
|
1517
|
+
message: ""
|
1518
|
+
});
|
1519
|
+
return res.data;
|
1520
|
+
} catch (err) {
|
1521
|
+
toggleNotification({
|
1522
|
+
type: "danger",
|
1523
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1524
|
+
});
|
1525
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1526
|
+
throw err;
|
1527
|
+
}
|
1528
|
+
},
|
1529
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1530
|
+
);
|
1082
1531
|
const [createDocument] = useCreateDocumentMutation();
|
1083
1532
|
const create = React.useCallback(
|
1084
1533
|
async ({ model, params }, data, trackerProperty) => {
|
@@ -1101,6 +1550,7 @@ const useDocumentActions = () => {
|
|
1101
1550
|
defaultMessage: "Saved document"
|
1102
1551
|
})
|
1103
1552
|
});
|
1553
|
+
setCurrentStep("contentManager.success");
|
1104
1554
|
return res.data;
|
1105
1555
|
} catch (err) {
|
1106
1556
|
toggleNotification({
|
@@ -1122,7 +1572,6 @@ const useDocumentActions = () => {
|
|
1122
1572
|
sourceId
|
1123
1573
|
});
|
1124
1574
|
if ("error" in res) {
|
1125
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1126
1575
|
return { error: res.error };
|
1127
1576
|
}
|
1128
1577
|
toggleNotification({
|
@@ -1141,7 +1590,7 @@ const useDocumentActions = () => {
|
|
1141
1590
|
throw err;
|
1142
1591
|
}
|
1143
1592
|
},
|
1144
|
-
[autoCloneDocument,
|
1593
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1145
1594
|
);
|
1146
1595
|
const [cloneDocument] = useCloneDocumentMutation();
|
1147
1596
|
const clone = React.useCallback(
|
@@ -1167,6 +1616,7 @@ const useDocumentActions = () => {
|
|
1167
1616
|
defaultMessage: "Cloned document"
|
1168
1617
|
})
|
1169
1618
|
});
|
1619
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1170
1620
|
return res.data;
|
1171
1621
|
} catch (err) {
|
1172
1622
|
toggleNotification({
|
@@ -1177,7 +1627,7 @@ const useDocumentActions = () => {
|
|
1177
1627
|
throw err;
|
1178
1628
|
}
|
1179
1629
|
},
|
1180
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1630
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1181
1631
|
);
|
1182
1632
|
const [getDoc] = useLazyGetDocumentQuery();
|
1183
1633
|
const getDocument = React.useCallback(
|
@@ -1192,15 +1642,18 @@ const useDocumentActions = () => {
|
|
1192
1642
|
clone,
|
1193
1643
|
create,
|
1194
1644
|
delete: _delete,
|
1645
|
+
deleteMany,
|
1195
1646
|
discard,
|
1196
1647
|
getDocument,
|
1197
1648
|
publish,
|
1649
|
+
publishMany,
|
1198
1650
|
unpublish,
|
1651
|
+
unpublishMany,
|
1199
1652
|
update
|
1200
1653
|
};
|
1201
1654
|
};
|
1202
1655
|
const ProtectedHistoryPage = lazy(
|
1203
|
-
() => import("./History-
|
1656
|
+
() => import("./History-BDZrgfZ3.mjs").then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1204
1657
|
);
|
1205
1658
|
const routes$1 = [
|
1206
1659
|
{
|
@@ -1213,31 +1666,31 @@ const routes$1 = [
|
|
1213
1666
|
}
|
1214
1667
|
];
|
1215
1668
|
const ProtectedEditViewPage = lazy(
|
1216
|
-
() => import("./EditViewPage-
|
1669
|
+
() => import("./EditViewPage-HYljoEY7.mjs").then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1217
1670
|
);
|
1218
1671
|
const ProtectedListViewPage = lazy(
|
1219
|
-
() => import("./ListViewPage-
|
1672
|
+
() => import("./ListViewPage-CsX7tWx-.mjs").then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1220
1673
|
);
|
1221
1674
|
const ProtectedListConfiguration = lazy(
|
1222
|
-
() => import("./ListConfigurationPage-
|
1675
|
+
() => import("./ListConfigurationPage-BZ3ScUna.mjs").then((mod) => ({
|
1223
1676
|
default: mod.ProtectedListConfiguration
|
1224
1677
|
}))
|
1225
1678
|
);
|
1226
1679
|
const ProtectedEditConfigurationPage = lazy(
|
1227
|
-
() => import("./EditConfigurationPage-
|
1680
|
+
() => import("./EditConfigurationPage-CZofxSLy.mjs").then((mod) => ({
|
1228
1681
|
default: mod.ProtectedEditConfigurationPage
|
1229
1682
|
}))
|
1230
1683
|
);
|
1231
1684
|
const ProtectedComponentConfigurationPage = lazy(
|
1232
|
-
() => import("./ComponentConfigurationPage
|
1685
|
+
() => import("./ComponentConfigurationPage-DJ5voqEK.mjs").then((mod) => ({
|
1233
1686
|
default: mod.ProtectedComponentConfigurationPage
|
1234
1687
|
}))
|
1235
1688
|
);
|
1236
1689
|
const NoPermissions = lazy(
|
1237
|
-
() => import("./NoPermissionsPage-
|
1690
|
+
() => import("./NoPermissionsPage-S4Re3FwO.mjs").then((mod) => ({ default: mod.NoPermissions }))
|
1238
1691
|
);
|
1239
1692
|
const NoContentType = lazy(
|
1240
|
-
() => import("./NoContentTypePage-
|
1693
|
+
() => import("./NoContentTypePage-LClTUPWs.mjs").then((mod) => ({ default: mod.NoContentType }))
|
1241
1694
|
);
|
1242
1695
|
const CollectionTypePages = () => {
|
1243
1696
|
const { collectionType } = useParams();
|
@@ -1351,12 +1804,14 @@ const DocumentActionButton = (action) => {
|
|
1351
1804
|
/* @__PURE__ */ jsx(
|
1352
1805
|
Button,
|
1353
1806
|
{
|
1354
|
-
flex:
|
1807
|
+
flex: "auto",
|
1355
1808
|
startIcon: action.icon,
|
1356
1809
|
disabled: action.disabled,
|
1357
1810
|
onClick: handleClick(action),
|
1358
1811
|
justifyContent: "center",
|
1359
1812
|
variant: action.variant || "default",
|
1813
|
+
paddingTop: "7px",
|
1814
|
+
paddingBottom: "7px",
|
1360
1815
|
children: action.label
|
1361
1816
|
}
|
1362
1817
|
),
|
@@ -1364,7 +1819,7 @@ const DocumentActionButton = (action) => {
|
|
1364
1819
|
DocumentActionConfirmDialog,
|
1365
1820
|
{
|
1366
1821
|
...action.dialog,
|
1367
|
-
variant: action.variant,
|
1822
|
+
variant: action.dialog?.variant ?? action.variant,
|
1368
1823
|
isOpen: dialogId === action.id,
|
1369
1824
|
onClose: handleClose
|
1370
1825
|
}
|
@@ -1421,20 +1876,20 @@ const DocumentActionsMenu = ({
|
|
1421
1876
|
disabled: isDisabled,
|
1422
1877
|
size: "S",
|
1423
1878
|
endIcon: null,
|
1424
|
-
paddingTop: "
|
1425
|
-
paddingLeft: "
|
1426
|
-
paddingRight: "
|
1879
|
+
paddingTop: "4px",
|
1880
|
+
paddingLeft: "7px",
|
1881
|
+
paddingRight: "7px",
|
1427
1882
|
variant,
|
1428
1883
|
children: [
|
1429
1884
|
/* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
|
1430
|
-
/* @__PURE__ */ jsx(VisuallyHidden, {
|
1885
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1431
1886
|
id: "content-manager.containers.edit.panels.default.more-actions",
|
1432
1887
|
defaultMessage: "More document actions"
|
1433
1888
|
}) })
|
1434
1889
|
]
|
1435
1890
|
}
|
1436
1891
|
),
|
1437
|
-
/* @__PURE__ */ jsxs(Menu.Content, {
|
1892
|
+
/* @__PURE__ */ jsxs(Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1438
1893
|
actions2.map((action) => {
|
1439
1894
|
return /* @__PURE__ */ jsx(
|
1440
1895
|
Menu.Item,
|
@@ -1443,10 +1898,25 @@ const DocumentActionsMenu = ({
|
|
1443
1898
|
onSelect: handleClick(action),
|
1444
1899
|
display: "block",
|
1445
1900
|
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", gap: 4, children: [
|
1446
|
-
/* @__PURE__ */ jsxs(
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1901
|
+
/* @__PURE__ */ jsxs(
|
1902
|
+
Flex,
|
1903
|
+
{
|
1904
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1905
|
+
gap: 2,
|
1906
|
+
tag: "span",
|
1907
|
+
children: [
|
1908
|
+
/* @__PURE__ */ jsx(
|
1909
|
+
Flex,
|
1910
|
+
{
|
1911
|
+
tag: "span",
|
1912
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1913
|
+
children: action.icon
|
1914
|
+
}
|
1915
|
+
),
|
1916
|
+
action.label
|
1917
|
+
]
|
1918
|
+
}
|
1919
|
+
),
|
1450
1920
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsx(
|
1451
1921
|
Flex,
|
1452
1922
|
{
|
@@ -1505,6 +1975,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1505
1975
|
return "primary600";
|
1506
1976
|
}
|
1507
1977
|
};
|
1978
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1979
|
+
switch (variant) {
|
1980
|
+
case "danger":
|
1981
|
+
return "danger600";
|
1982
|
+
case "secondary":
|
1983
|
+
return "neutral500";
|
1984
|
+
case "success":
|
1985
|
+
return "success600";
|
1986
|
+
default:
|
1987
|
+
return "primary600";
|
1988
|
+
}
|
1989
|
+
};
|
1508
1990
|
const DocumentActionConfirmDialog = ({
|
1509
1991
|
onClose,
|
1510
1992
|
onCancel,
|
@@ -1527,61 +2009,42 @@ const DocumentActionConfirmDialog = ({
|
|
1527
2009
|
}
|
1528
2010
|
onClose();
|
1529
2011
|
};
|
1530
|
-
return /* @__PURE__ */
|
1531
|
-
/* @__PURE__ */ jsx(
|
1532
|
-
/* @__PURE__ */ jsx(
|
1533
|
-
|
1534
|
-
{
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
)
|
1545
|
-
] });
|
2012
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2013
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2014
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: content }),
|
2015
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
2016
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
2017
|
+
id: "app.components.Button.cancel",
|
2018
|
+
defaultMessage: "Cancel"
|
2019
|
+
}) }) }),
|
2020
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
2021
|
+
id: "app.components.Button.confirm",
|
2022
|
+
defaultMessage: "Confirm"
|
2023
|
+
}) })
|
2024
|
+
] })
|
2025
|
+
] }) });
|
1546
2026
|
};
|
1547
2027
|
const DocumentActionModal = ({
|
1548
2028
|
isOpen,
|
1549
2029
|
title,
|
1550
2030
|
onClose,
|
1551
2031
|
footer: Footer,
|
1552
|
-
content,
|
2032
|
+
content: Content,
|
1553
2033
|
onModalClose
|
1554
2034
|
}) => {
|
1555
|
-
const id = React.useId();
|
1556
|
-
if (!isOpen) {
|
1557
|
-
return null;
|
1558
|
-
}
|
1559
2035
|
const handleClose = () => {
|
1560
2036
|
if (onClose) {
|
1561
2037
|
onClose();
|
1562
2038
|
}
|
1563
2039
|
onModalClose();
|
1564
2040
|
};
|
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
|
-
] });
|
2041
|
+
return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
2042
|
+
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: title }) }),
|
2043
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsx(Modal.Body, { children: Content }),
|
2044
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsx(Footer, { onClose: handleClose }) : Footer
|
2045
|
+
] }) });
|
1583
2046
|
};
|
1584
|
-
const PublishAction = ({
|
2047
|
+
const PublishAction$1 = ({
|
1585
2048
|
activeTab,
|
1586
2049
|
documentId,
|
1587
2050
|
model,
|
@@ -1593,13 +2056,17 @@ const PublishAction = ({
|
|
1593
2056
|
const navigate = useNavigate();
|
1594
2057
|
const { toggleNotification } = useNotification();
|
1595
2058
|
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
2059
|
+
const isListView = useMatch(LIST_PATH) !== null;
|
1596
2060
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
1597
2061
|
const { formatMessage } = useIntl();
|
1598
|
-
const { canPublish
|
1599
|
-
"PublishAction",
|
1600
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1601
|
-
);
|
2062
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1602
2063
|
const { publish } = useDocumentActions();
|
2064
|
+
const [
|
2065
|
+
countDraftRelations,
|
2066
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2067
|
+
] = useLazyGetDraftRelationCountQuery();
|
2068
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React.useState(0);
|
2069
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React.useState(0);
|
1603
2070
|
const [{ query, rawQuery }] = useQueryParams();
|
1604
2071
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
1605
2072
|
const modified = useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1608,10 +2075,103 @@ const PublishAction = ({
|
|
1608
2075
|
const validate = useForm("PublishAction", (state) => state.validate);
|
1609
2076
|
const setErrors = useForm("PublishAction", (state) => state.setErrors);
|
1610
2077
|
const formValues = useForm("PublishAction", ({ values }) => values);
|
2078
|
+
React.useEffect(() => {
|
2079
|
+
if (isErrorDraftRelations) {
|
2080
|
+
toggleNotification({
|
2081
|
+
type: "danger",
|
2082
|
+
message: formatMessage({
|
2083
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2084
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2085
|
+
})
|
2086
|
+
});
|
2087
|
+
}
|
2088
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2089
|
+
React.useEffect(() => {
|
2090
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2091
|
+
const extractDraftRelations = (data) => {
|
2092
|
+
const relations = data.connect || [];
|
2093
|
+
relations.forEach((relation) => {
|
2094
|
+
if (relation.status === "draft") {
|
2095
|
+
localDraftRelations.add(relation.id);
|
2096
|
+
}
|
2097
|
+
});
|
2098
|
+
};
|
2099
|
+
const traverseAndExtract = (data) => {
|
2100
|
+
Object.entries(data).forEach(([key, value]) => {
|
2101
|
+
if (key === "connect" && Array.isArray(value)) {
|
2102
|
+
extractDraftRelations({ connect: value });
|
2103
|
+
} else if (typeof value === "object" && value !== null) {
|
2104
|
+
traverseAndExtract(value);
|
2105
|
+
}
|
2106
|
+
});
|
2107
|
+
};
|
2108
|
+
if (!documentId || modified) {
|
2109
|
+
traverseAndExtract(formValues);
|
2110
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2111
|
+
}
|
2112
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2113
|
+
React.useEffect(() => {
|
2114
|
+
if (!document || !document.documentId || isListView) {
|
2115
|
+
return;
|
2116
|
+
}
|
2117
|
+
const fetchDraftRelationsCount = async () => {
|
2118
|
+
const { data, error } = await countDraftRelations({
|
2119
|
+
collectionType,
|
2120
|
+
model,
|
2121
|
+
documentId,
|
2122
|
+
params
|
2123
|
+
});
|
2124
|
+
if (error) {
|
2125
|
+
throw error;
|
2126
|
+
}
|
2127
|
+
if (data) {
|
2128
|
+
setServerCountOfDraftRelations(data.data);
|
2129
|
+
}
|
2130
|
+
};
|
2131
|
+
fetchDraftRelationsCount();
|
2132
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
1611
2133
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1612
2134
|
if (!schema?.options?.draftAndPublish) {
|
1613
2135
|
return null;
|
1614
2136
|
}
|
2137
|
+
const performPublish = async () => {
|
2138
|
+
setSubmitting(true);
|
2139
|
+
try {
|
2140
|
+
const { errors } = await validate();
|
2141
|
+
if (errors) {
|
2142
|
+
toggleNotification({
|
2143
|
+
type: "danger",
|
2144
|
+
message: formatMessage({
|
2145
|
+
id: "content-manager.validation.error",
|
2146
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2147
|
+
})
|
2148
|
+
});
|
2149
|
+
return;
|
2150
|
+
}
|
2151
|
+
const res = await publish(
|
2152
|
+
{
|
2153
|
+
collectionType,
|
2154
|
+
model,
|
2155
|
+
documentId,
|
2156
|
+
params
|
2157
|
+
},
|
2158
|
+
formValues
|
2159
|
+
);
|
2160
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2161
|
+
navigate({
|
2162
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2163
|
+
search: rawQuery
|
2164
|
+
});
|
2165
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2166
|
+
setErrors(formatValidationErrors(res.error));
|
2167
|
+
}
|
2168
|
+
} finally {
|
2169
|
+
setSubmitting(false);
|
2170
|
+
}
|
2171
|
+
};
|
2172
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2173
|
+
const enableDraftRelationsCount = false;
|
2174
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1615
2175
|
return {
|
1616
2176
|
/**
|
1617
2177
|
* Disabled when:
|
@@ -1621,52 +2181,39 @@ const PublishAction = ({
|
|
1621
2181
|
* - the document is already published & not modified
|
1622
2182
|
* - the document is being created & not modified
|
1623
2183
|
* - 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
2184
|
*/
|
1627
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2185
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1628
2186
|
label: formatMessage({
|
1629
2187
|
id: "app.utils.publish",
|
1630
2188
|
defaultMessage: "Publish"
|
1631
2189
|
}),
|
1632
2190
|
onClick: async () => {
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
documentId,
|
1651
|
-
params
|
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));
|
2191
|
+
await performPublish();
|
2192
|
+
},
|
2193
|
+
dialog: hasDraftRelations ? {
|
2194
|
+
type: "dialog",
|
2195
|
+
variant: "danger",
|
2196
|
+
footer: null,
|
2197
|
+
title: formatMessage({
|
2198
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2199
|
+
defaultMessage: "Confirmation"
|
2200
|
+
}),
|
2201
|
+
content: formatMessage(
|
2202
|
+
{
|
2203
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2204
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2205
|
+
},
|
2206
|
+
{
|
2207
|
+
count: totalDraftRelations
|
1662
2208
|
}
|
1663
|
-
|
1664
|
-
|
2209
|
+
),
|
2210
|
+
onConfirm: async () => {
|
2211
|
+
await performPublish();
|
1665
2212
|
}
|
1666
|
-
}
|
2213
|
+
} : void 0
|
1667
2214
|
};
|
1668
2215
|
};
|
1669
|
-
PublishAction.type = "publish";
|
2216
|
+
PublishAction$1.type = "publish";
|
1670
2217
|
const UpdateAction = ({
|
1671
2218
|
activeTab,
|
1672
2219
|
documentId,
|
@@ -1679,10 +2226,6 @@ const UpdateAction = ({
|
|
1679
2226
|
const cloneMatch = useMatch(CLONE_PATH);
|
1680
2227
|
const isCloning = cloneMatch !== null;
|
1681
2228
|
const { formatMessage } = useIntl();
|
1682
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1683
|
-
canCreate: canCreate2,
|
1684
|
-
canUpdate: canUpdate2
|
1685
|
-
}));
|
1686
2229
|
const { create, update, clone } = useDocumentActions();
|
1687
2230
|
const [{ query, rawQuery }] = useQueryParams();
|
1688
2231
|
const params = React.useMemo(() => buildValidParams(query), [query]);
|
@@ -1699,10 +2242,8 @@ const UpdateAction = ({
|
|
1699
2242
|
* - the form is submitting
|
1700
2243
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1701
2244
|
* - 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
2245
|
*/
|
1705
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2246
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1706
2247
|
label: formatMessage({
|
1707
2248
|
id: "content-manager.containers.Edit.save",
|
1708
2249
|
defaultMessage: "Save"
|
@@ -1710,16 +2251,18 @@ const UpdateAction = ({
|
|
1710
2251
|
onClick: async () => {
|
1711
2252
|
setSubmitting(true);
|
1712
2253
|
try {
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
2254
|
+
if (activeTab !== "draft") {
|
2255
|
+
const { errors } = await validate();
|
2256
|
+
if (errors) {
|
2257
|
+
toggleNotification({
|
2258
|
+
type: "danger",
|
2259
|
+
message: formatMessage({
|
2260
|
+
id: "content-manager.validation.error",
|
2261
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2262
|
+
})
|
2263
|
+
});
|
2264
|
+
return;
|
2265
|
+
}
|
1723
2266
|
}
|
1724
2267
|
if (isCloning) {
|
1725
2268
|
const res = await clone(
|
@@ -1731,10 +2274,13 @@ const UpdateAction = ({
|
|
1731
2274
|
document
|
1732
2275
|
);
|
1733
2276
|
if ("data" in res) {
|
1734
|
-
navigate(
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
2277
|
+
navigate(
|
2278
|
+
{
|
2279
|
+
pathname: `../${res.data.documentId}`,
|
2280
|
+
search: rawQuery
|
2281
|
+
},
|
2282
|
+
{ relative: "path" }
|
2283
|
+
);
|
1738
2284
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1739
2285
|
setErrors(formatValidationErrors(res.error));
|
1740
2286
|
}
|
@@ -1762,10 +2308,13 @@ const UpdateAction = ({
|
|
1762
2308
|
document
|
1763
2309
|
);
|
1764
2310
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1765
|
-
navigate(
|
1766
|
-
|
1767
|
-
|
1768
|
-
|
2311
|
+
navigate(
|
2312
|
+
{
|
2313
|
+
pathname: `../${res.data.documentId}`,
|
2314
|
+
search: rawQuery
|
2315
|
+
},
|
2316
|
+
{ replace: true, relative: "path" }
|
2317
|
+
);
|
1769
2318
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1770
2319
|
setErrors(formatValidationErrors(res.error));
|
1771
2320
|
}
|
@@ -1781,7 +2330,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
|
|
1781
2330
|
KEEP: "keep",
|
1782
2331
|
DISCARD: "discard"
|
1783
2332
|
};
|
1784
|
-
const UnpublishAction = ({
|
2333
|
+
const UnpublishAction$1 = ({
|
1785
2334
|
activeTab,
|
1786
2335
|
documentId,
|
1787
2336
|
model,
|
@@ -1797,10 +2346,8 @@ const UnpublishAction = ({
|
|
1797
2346
|
const { toggleNotification } = useNotification();
|
1798
2347
|
const [shouldKeepDraft, setShouldKeepDraft] = React.useState(true);
|
1799
2348
|
const isDocumentModified = document?.status === "modified";
|
1800
|
-
const handleChange = (
|
1801
|
-
|
1802
|
-
setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1803
|
-
}
|
2349
|
+
const handleChange = (value) => {
|
2350
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1804
2351
|
};
|
1805
2352
|
if (!schema?.options?.draftAndPublish) {
|
1806
2353
|
return null;
|
@@ -1811,7 +2358,7 @@ const UnpublishAction = ({
|
|
1811
2358
|
id: "app.utils.unpublish",
|
1812
2359
|
defaultMessage: "Unpublish"
|
1813
2360
|
}),
|
1814
|
-
icon: /* @__PURE__ */ jsx(
|
2361
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1815
2362
|
onClick: async () => {
|
1816
2363
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1817
2364
|
if (!documentId) {
|
@@ -1844,45 +2391,30 @@ const UnpublishAction = ({
|
|
1844
2391
|
content: /* @__PURE__ */ jsxs(Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
|
1845
2392
|
/* @__PURE__ */ jsxs(Flex, { width: "100%", direction: "column", gap: 2, children: [
|
1846
2393
|
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
1847
|
-
/* @__PURE__ */ jsx(Typography, {
|
2394
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
1848
2395
|
id: "content-manager.actions.unpublish.dialog.body",
|
1849
2396
|
defaultMessage: "Are you sure?"
|
1850
2397
|
}) })
|
1851
2398
|
] }),
|
1852
2399
|
/* @__PURE__ */ jsxs(
|
1853
|
-
|
2400
|
+
Radio.Group,
|
1854
2401
|
{
|
1855
|
-
|
1856
|
-
|
1857
|
-
|
1858
|
-
|
1859
|
-
|
2402
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2403
|
+
name: "discard-options",
|
2404
|
+
"aria-label": formatMessage({
|
2405
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2406
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2407
|
+
}),
|
2408
|
+
onValueChange: handleChange,
|
1860
2409
|
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
|
-
)
|
2410
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2411
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2412
|
+
defaultMessage: "Keep draft"
|
2413
|
+
}) }),
|
2414
|
+
/* @__PURE__ */ jsx(Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2415
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2416
|
+
defaultMessage: "Replace draft"
|
2417
|
+
}) })
|
1886
2418
|
]
|
1887
2419
|
}
|
1888
2420
|
)
|
@@ -1915,7 +2447,7 @@ const UnpublishAction = ({
|
|
1915
2447
|
position: ["panel", "table-row"]
|
1916
2448
|
};
|
1917
2449
|
};
|
1918
|
-
UnpublishAction.type = "unpublish";
|
2450
|
+
UnpublishAction$1.type = "unpublish";
|
1919
2451
|
const DiscardAction = ({
|
1920
2452
|
activeTab,
|
1921
2453
|
documentId,
|
@@ -1938,7 +2470,7 @@ const DiscardAction = ({
|
|
1938
2470
|
id: "content-manager.actions.discard.label",
|
1939
2471
|
defaultMessage: "Discard changes"
|
1940
2472
|
}),
|
1941
|
-
icon: /* @__PURE__ */ jsx(
|
2473
|
+
icon: /* @__PURE__ */ jsx(Cross, {}),
|
1942
2474
|
position: ["panel", "table-row"],
|
1943
2475
|
variant: "danger",
|
1944
2476
|
dialog: {
|
@@ -1949,7 +2481,7 @@ const DiscardAction = ({
|
|
1949
2481
|
}),
|
1950
2482
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
1951
2483
|
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
1952
|
-
/* @__PURE__ */ jsx(Typography, {
|
2484
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
1953
2485
|
id: "content-manager.actions.discard.dialog.body",
|
1954
2486
|
defaultMessage: "Are you sure?"
|
1955
2487
|
}) })
|
@@ -1966,12 +2498,7 @@ const DiscardAction = ({
|
|
1966
2498
|
};
|
1967
2499
|
};
|
1968
2500
|
DiscardAction.type = "discard";
|
1969
|
-
const
|
1970
|
-
path {
|
1971
|
-
fill: currentColor;
|
1972
|
-
}
|
1973
|
-
`;
|
1974
|
-
const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
|
2501
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
1975
2502
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
1976
2503
|
const RelativeTime = React.forwardRef(
|
1977
2504
|
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
@@ -2018,8 +2545,8 @@ const getDisplayName = ({
|
|
2018
2545
|
};
|
2019
2546
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2020
2547
|
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2021
|
-
const statusVariant = status === "draft" ? "
|
2022
|
-
return /* @__PURE__ */ jsx(Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsx(Typography, {
|
2548
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2549
|
+
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
2550
|
};
|
2024
2551
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2025
2552
|
const { formatMessage } = useIntl();
|
@@ -2028,23 +2555,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2028
2555
|
id: "content-manager.containers.edit.title.new",
|
2029
2556
|
defaultMessage: "Create an entry"
|
2030
2557
|
}) : documentTitle;
|
2031
|
-
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2558
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2032
2559
|
/* @__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
|
2560
|
+
/* @__PURE__ */ jsxs(Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2561
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: title }),
|
2562
|
+
/* @__PURE__ */ jsx(HeaderToolbar, {})
|
2563
|
+
] }),
|
2564
|
+
status ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2048
2565
|
] });
|
2049
2566
|
};
|
2050
2567
|
const HeaderToolbar = () => {
|
@@ -2196,7 +2713,7 @@ const Information = ({ activeTab }) => {
|
|
2196
2713
|
borderColor: "neutral150",
|
2197
2714
|
direction: "column",
|
2198
2715
|
marginTop: 2,
|
2199
|
-
|
2716
|
+
tag: "dl",
|
2200
2717
|
padding: 5,
|
2201
2718
|
gap: 3,
|
2202
2719
|
alignItems: "flex-start",
|
@@ -2204,15 +2721,29 @@ const Information = ({ activeTab }) => {
|
|
2204
2721
|
marginRight: "-0.4rem",
|
2205
2722
|
width: "calc(100% + 8px)",
|
2206
2723
|
children: information.map((info) => /* @__PURE__ */ jsxs(Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
|
2207
|
-
/* @__PURE__ */ jsx(Typography, {
|
2208
|
-
/* @__PURE__ */ jsx(Typography, {
|
2724
|
+
/* @__PURE__ */ jsx(Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2725
|
+
/* @__PURE__ */ jsx(Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2209
2726
|
] }, info.label))
|
2210
2727
|
}
|
2211
2728
|
);
|
2212
2729
|
};
|
2213
2730
|
const HeaderActions = ({ actions: actions2 }) => {
|
2214
|
-
|
2215
|
-
|
2731
|
+
const [dialogId, setDialogId] = React.useState(null);
|
2732
|
+
const handleClick = (action) => async (e) => {
|
2733
|
+
if (!("options" in action)) {
|
2734
|
+
const { onClick = () => false, dialog, id } = action;
|
2735
|
+
const muteDialog = await onClick(e);
|
2736
|
+
if (dialog && !muteDialog) {
|
2737
|
+
e.preventDefault();
|
2738
|
+
setDialogId(id);
|
2739
|
+
}
|
2740
|
+
}
|
2741
|
+
};
|
2742
|
+
const handleClose = () => {
|
2743
|
+
setDialogId(null);
|
2744
|
+
};
|
2745
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 1, children: actions2.map((action) => {
|
2746
|
+
if (action.options) {
|
2216
2747
|
return /* @__PURE__ */ jsx(
|
2217
2748
|
SingleSelect,
|
2218
2749
|
{
|
@@ -2226,10 +2757,49 @@ const HeaderActions = ({ actions: actions2 }) => {
|
|
2226
2757
|
action.id
|
2227
2758
|
);
|
2228
2759
|
} else {
|
2229
|
-
|
2760
|
+
if (action.type === "icon") {
|
2761
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
2762
|
+
/* @__PURE__ */ jsx(
|
2763
|
+
IconButton,
|
2764
|
+
{
|
2765
|
+
disabled: action.disabled,
|
2766
|
+
label: action.label,
|
2767
|
+
size: "S",
|
2768
|
+
onClick: handleClick(action),
|
2769
|
+
children: action.icon
|
2770
|
+
}
|
2771
|
+
),
|
2772
|
+
action.dialog ? /* @__PURE__ */ jsx(
|
2773
|
+
HeaderActionDialog,
|
2774
|
+
{
|
2775
|
+
...action.dialog,
|
2776
|
+
isOpen: dialogId === action.id,
|
2777
|
+
onClose: handleClose
|
2778
|
+
}
|
2779
|
+
) : null
|
2780
|
+
] }, action.id);
|
2781
|
+
}
|
2230
2782
|
}
|
2231
2783
|
}) });
|
2232
2784
|
};
|
2785
|
+
const HeaderActionDialog = ({
|
2786
|
+
onClose,
|
2787
|
+
onCancel,
|
2788
|
+
title,
|
2789
|
+
content: Content,
|
2790
|
+
isOpen
|
2791
|
+
}) => {
|
2792
|
+
const handleClose = async () => {
|
2793
|
+
if (onCancel) {
|
2794
|
+
await onCancel();
|
2795
|
+
}
|
2796
|
+
onClose();
|
2797
|
+
};
|
2798
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
2799
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: title }),
|
2800
|
+
typeof Content === "function" ? /* @__PURE__ */ jsx(Content, { onClose: handleClose }) : Content
|
2801
|
+
] }) });
|
2802
|
+
};
|
2233
2803
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2234
2804
|
const navigate = useNavigate();
|
2235
2805
|
const { formatMessage } = useIntl();
|
@@ -2238,7 +2808,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2238
2808
|
id: "app.links.configure-view",
|
2239
2809
|
defaultMessage: "Configure the view"
|
2240
2810
|
}),
|
2241
|
-
icon: /* @__PURE__ */ jsx(
|
2811
|
+
icon: /* @__PURE__ */ jsx(ListPlus, {}),
|
2242
2812
|
onClick: () => {
|
2243
2813
|
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2244
2814
|
},
|
@@ -2246,11 +2816,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2246
2816
|
};
|
2247
2817
|
};
|
2248
2818
|
ConfigureTheViewAction.type = "configure-the-view";
|
2249
|
-
const StyledCog = styled(Cog)`
|
2250
|
-
path {
|
2251
|
-
fill: currentColor;
|
2252
|
-
}
|
2253
|
-
`;
|
2254
2819
|
const EditTheModelAction = ({ model }) => {
|
2255
2820
|
const navigate = useNavigate();
|
2256
2821
|
const { formatMessage } = useIntl();
|
@@ -2259,7 +2824,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2259
2824
|
id: "content-manager.link-to-ctb",
|
2260
2825
|
defaultMessage: "Edit the model"
|
2261
2826
|
}),
|
2262
|
-
icon: /* @__PURE__ */ jsx(
|
2827
|
+
icon: /* @__PURE__ */ jsx(Pencil, {}),
|
2263
2828
|
onClick: () => {
|
2264
2829
|
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2265
2830
|
},
|
@@ -2267,12 +2832,7 @@ const EditTheModelAction = ({ model }) => {
|
|
2267
2832
|
};
|
2268
2833
|
};
|
2269
2834
|
EditTheModelAction.type = "edit-the-model";
|
2270
|
-
const
|
2271
|
-
path {
|
2272
|
-
fill: currentColor;
|
2273
|
-
}
|
2274
|
-
`;
|
2275
|
-
const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
2835
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2276
2836
|
const navigate = useNavigate();
|
2277
2837
|
const { formatMessage } = useIntl();
|
2278
2838
|
const listViewPathMatch = useMatch(LIST_PATH);
|
@@ -2280,13 +2840,17 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2280
2840
|
const { delete: deleteAction } = useDocumentActions();
|
2281
2841
|
const { toggleNotification } = useNotification();
|
2282
2842
|
const setSubmitting = useForm("DeleteAction", (state) => state.setSubmitting);
|
2843
|
+
const isLocalized = document?.locale != null;
|
2283
2844
|
return {
|
2284
2845
|
disabled: !canDelete || !document,
|
2285
|
-
label: formatMessage(
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2846
|
+
label: formatMessage(
|
2847
|
+
{
|
2848
|
+
id: "content-manager.actions.delete.label",
|
2849
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2850
|
+
},
|
2851
|
+
{ isLocalized }
|
2852
|
+
),
|
2853
|
+
icon: /* @__PURE__ */ jsx(Trash, {}),
|
2290
2854
|
dialog: {
|
2291
2855
|
type: "dialog",
|
2292
2856
|
title: formatMessage({
|
@@ -2295,7 +2859,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2295
2859
|
}),
|
2296
2860
|
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
|
2297
2861
|
/* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2298
|
-
/* @__PURE__ */ jsx(Typography, {
|
2862
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2299
2863
|
id: "content-manager.actions.delete.dialog.body",
|
2300
2864
|
defaultMessage: "Are you sure?"
|
2301
2865
|
}) })
|
@@ -2340,13 +2904,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2340
2904
|
position: ["header", "table-row"]
|
2341
2905
|
};
|
2342
2906
|
};
|
2343
|
-
DeleteAction.type = "delete";
|
2344
|
-
const
|
2345
|
-
path {
|
2346
|
-
fill: currentColor;
|
2347
|
-
}
|
2348
|
-
`;
|
2349
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction];
|
2907
|
+
DeleteAction$1.type = "delete";
|
2908
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2350
2909
|
const Panels = () => {
|
2351
2910
|
const isCloning = useMatch(CLONE_PATH) !== null;
|
2352
2911
|
const [
|
@@ -2380,7 +2939,7 @@ const ActionsPanel = () => {
|
|
2380
2939
|
return {
|
2381
2940
|
title: formatMessage({
|
2382
2941
|
id: "content-manager.containers.edit.panels.default.title",
|
2383
|
-
defaultMessage: "
|
2942
|
+
defaultMessage: "Entry"
|
2384
2943
|
}),
|
2385
2944
|
content: /* @__PURE__ */ jsx(ActionsPanelContent, {})
|
2386
2945
|
};
|
@@ -2420,7 +2979,7 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
|
|
2420
2979
|
Flex,
|
2421
2980
|
{
|
2422
2981
|
ref,
|
2423
|
-
|
2982
|
+
tag: "aside",
|
2424
2983
|
"aria-labelledby": "additional-information",
|
2425
2984
|
background: "neutral0",
|
2426
2985
|
borderColor: "neutral150",
|
@@ -2435,27 +2994,612 @@ const Panel = React.forwardRef(({ children, title }, ref) => {
|
|
2435
2994
|
justifyContent: "stretch",
|
2436
2995
|
alignItems: "flex-start",
|
2437
2996
|
children: [
|
2438
|
-
/* @__PURE__ */ jsx(Typography, {
|
2997
|
+
/* @__PURE__ */ jsx(Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2439
2998
|
children
|
2440
2999
|
]
|
2441
3000
|
}
|
2442
3001
|
);
|
2443
3002
|
});
|
2444
|
-
const
|
2445
|
-
|
3003
|
+
const ConfirmBulkActionDialog = ({
|
3004
|
+
onToggleDialog,
|
3005
|
+
isOpen = false,
|
3006
|
+
dialogBody,
|
3007
|
+
endAction
|
3008
|
+
}) => {
|
2446
3009
|
const { formatMessage } = useIntl();
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2454
|
-
|
2455
|
-
}
|
2456
|
-
|
2457
|
-
|
2458
|
-
|
3010
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxs(Dialog.Content, { children: [
|
3011
|
+
/* @__PURE__ */ jsx(Dialog.Header, { children: formatMessage({
|
3012
|
+
id: "app.components.ConfirmDialog.title",
|
3013
|
+
defaultMessage: "Confirmation"
|
3014
|
+
}) }),
|
3015
|
+
/* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3016
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3017
|
+
dialogBody
|
3018
|
+
] }) }),
|
3019
|
+
/* @__PURE__ */ jsxs(Dialog.Footer, { children: [
|
3020
|
+
/* @__PURE__ */ jsx(Dialog.Cancel, { children: /* @__PURE__ */ jsx(Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
|
3021
|
+
id: "app.components.Button.cancel",
|
3022
|
+
defaultMessage: "Cancel"
|
3023
|
+
}) }) }),
|
3024
|
+
endAction
|
3025
|
+
] })
|
3026
|
+
] }) });
|
3027
|
+
};
|
3028
|
+
const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
3029
|
+
const ConfirmDialogPublishAll = ({
|
3030
|
+
isOpen,
|
3031
|
+
onToggleDialog,
|
3032
|
+
isConfirmButtonLoading = false,
|
3033
|
+
onConfirm
|
3034
|
+
}) => {
|
3035
|
+
const { formatMessage } = useIntl();
|
3036
|
+
const selectedEntries = useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
|
3037
|
+
const { toggleNotification } = useNotification();
|
3038
|
+
const { _unstableFormatAPIError: formatAPIError } = useAPIErrorHandler(getTranslation);
|
3039
|
+
const { model, schema } = useDoc();
|
3040
|
+
const [{ query }] = useQueryParams();
|
3041
|
+
const enableDraftRelationsCount = false;
|
3042
|
+
const {
|
3043
|
+
data: countDraftRelations = 0,
|
3044
|
+
isLoading,
|
3045
|
+
error
|
3046
|
+
} = useGetManyDraftRelationCountQuery(
|
3047
|
+
{
|
3048
|
+
model,
|
3049
|
+
documentIds: selectedEntries.map((entry) => entry.documentId),
|
3050
|
+
locale: query?.plugins?.i18n?.locale
|
3051
|
+
},
|
3052
|
+
{
|
3053
|
+
skip: !enableDraftRelationsCount
|
3054
|
+
}
|
3055
|
+
);
|
3056
|
+
React.useEffect(() => {
|
3057
|
+
if (error) {
|
3058
|
+
toggleNotification({ type: "danger", message: formatAPIError(error) });
|
3059
|
+
}
|
3060
|
+
}, [error, formatAPIError, toggleNotification]);
|
3061
|
+
if (error) {
|
3062
|
+
return null;
|
3063
|
+
}
|
3064
|
+
return /* @__PURE__ */ jsx(
|
3065
|
+
ConfirmBulkActionDialog,
|
3066
|
+
{
|
3067
|
+
isOpen: isOpen && !isLoading,
|
3068
|
+
onToggleDialog,
|
3069
|
+
dialogBody: /* @__PURE__ */ jsxs(Fragment, { children: [
|
3070
|
+
/* @__PURE__ */ jsxs(Typography, { id: "confirm-description", textAlign: "center", children: [
|
3071
|
+
countDraftRelations > 0 && formatMessage(
|
3072
|
+
{
|
3073
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
3074
|
+
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. "
|
3075
|
+
},
|
3076
|
+
{
|
3077
|
+
b: BoldChunk$1,
|
3078
|
+
count: countDraftRelations,
|
3079
|
+
entities: selectedEntries.length
|
3080
|
+
}
|
3081
|
+
),
|
3082
|
+
formatMessage({
|
3083
|
+
id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
|
3084
|
+
defaultMessage: "Are you sure you want to publish these entries?"
|
3085
|
+
})
|
3086
|
+
] }),
|
3087
|
+
schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsx(Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
|
3088
|
+
{
|
3089
|
+
id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
|
3090
|
+
defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
|
3091
|
+
},
|
3092
|
+
{
|
3093
|
+
em: Emphasis
|
3094
|
+
}
|
3095
|
+
) })
|
3096
|
+
] }),
|
3097
|
+
endAction: /* @__PURE__ */ jsx(
|
3098
|
+
Button,
|
3099
|
+
{
|
3100
|
+
onClick: onConfirm,
|
3101
|
+
variant: "secondary",
|
3102
|
+
startIcon: /* @__PURE__ */ jsx(Check, {}),
|
3103
|
+
loading: isConfirmButtonLoading,
|
3104
|
+
children: formatMessage({
|
3105
|
+
id: "app.utils.publish",
|
3106
|
+
defaultMessage: "Publish"
|
3107
|
+
})
|
3108
|
+
}
|
3109
|
+
)
|
3110
|
+
}
|
3111
|
+
);
|
3112
|
+
};
|
3113
|
+
const TypographyMaxWidth = styled(Typography)`
|
3114
|
+
max-width: 300px;
|
3115
|
+
`;
|
3116
|
+
const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
3117
|
+
const messages = [];
|
3118
|
+
Object.entries(errors).forEach(([key, value]) => {
|
3119
|
+
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
3120
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
3121
|
+
if ("id" in value && "defaultMessage" in value) {
|
3122
|
+
messages.push(
|
3123
|
+
formatMessage(
|
3124
|
+
{
|
3125
|
+
id: `${value.id}.withField`,
|
3126
|
+
defaultMessage: value.defaultMessage
|
3127
|
+
},
|
3128
|
+
{ field: currentKey }
|
3129
|
+
)
|
3130
|
+
);
|
3131
|
+
} else {
|
3132
|
+
messages.push(
|
3133
|
+
...formatErrorMessages(
|
3134
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3135
|
+
value,
|
3136
|
+
currentKey,
|
3137
|
+
formatMessage
|
3138
|
+
)
|
3139
|
+
);
|
3140
|
+
}
|
3141
|
+
} else {
|
3142
|
+
messages.push(
|
3143
|
+
formatMessage(
|
3144
|
+
{
|
3145
|
+
id: `${value}.withField`,
|
3146
|
+
defaultMessage: value
|
3147
|
+
},
|
3148
|
+
{ field: currentKey }
|
3149
|
+
)
|
3150
|
+
);
|
3151
|
+
}
|
3152
|
+
});
|
3153
|
+
return messages;
|
3154
|
+
};
|
3155
|
+
const EntryValidationText = ({ validationErrors, status }) => {
|
3156
|
+
const { formatMessage } = useIntl();
|
3157
|
+
if (validationErrors) {
|
3158
|
+
const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
|
3159
|
+
" "
|
3160
|
+
);
|
3161
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3162
|
+
/* @__PURE__ */ jsx(CrossCircle, { fill: "danger600" }),
|
3163
|
+
/* @__PURE__ */ jsx(Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
|
3164
|
+
] });
|
3165
|
+
}
|
3166
|
+
if (status === "published") {
|
3167
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3168
|
+
/* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
3169
|
+
/* @__PURE__ */ jsx(Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
|
3170
|
+
id: "content-manager.bulk-publish.already-published",
|
3171
|
+
defaultMessage: "Already Published"
|
3172
|
+
}) })
|
3173
|
+
] });
|
3174
|
+
}
|
3175
|
+
if (status === "modified") {
|
3176
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3177
|
+
/* @__PURE__ */ jsx(ArrowsCounterClockwise, { fill: "alternative600" }),
|
3178
|
+
/* @__PURE__ */ jsx(Typography, { children: formatMessage({
|
3179
|
+
id: "content-manager.bulk-publish.modified",
|
3180
|
+
defaultMessage: "Ready to publish changes"
|
3181
|
+
}) })
|
3182
|
+
] });
|
3183
|
+
}
|
3184
|
+
return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3185
|
+
/* @__PURE__ */ jsx(CheckCircle, { fill: "success600" }),
|
3186
|
+
/* @__PURE__ */ jsx(Typography, { children: formatMessage({
|
3187
|
+
id: "app.utils.ready-to-publish",
|
3188
|
+
defaultMessage: "Ready to publish"
|
3189
|
+
}) })
|
3190
|
+
] });
|
3191
|
+
};
|
3192
|
+
const TABLE_HEADERS = [
|
3193
|
+
{ name: "id", label: "id" },
|
3194
|
+
{ name: "name", label: "name" },
|
3195
|
+
{ name: "status", label: "status" },
|
3196
|
+
{ name: "publicationStatus", label: "Publication status" }
|
3197
|
+
];
|
3198
|
+
const SelectedEntriesTableContent = ({
|
3199
|
+
isPublishing,
|
3200
|
+
rowsToDisplay = [],
|
3201
|
+
entriesToPublish = [],
|
3202
|
+
validationErrors = {}
|
3203
|
+
}) => {
|
3204
|
+
const { pathname } = useLocation();
|
3205
|
+
const { formatMessage } = useIntl();
|
3206
|
+
const {
|
3207
|
+
list: {
|
3208
|
+
settings: { mainField }
|
3209
|
+
}
|
3210
|
+
} = useDocLayout();
|
3211
|
+
const shouldDisplayMainField = mainField != null && mainField !== "id";
|
3212
|
+
return /* @__PURE__ */ jsxs(Table.Content, { children: [
|
3213
|
+
/* @__PURE__ */ jsxs(Table.Head, { children: [
|
3214
|
+
/* @__PURE__ */ jsx(Table.HeaderCheckboxCell, {}),
|
3215
|
+
TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
|
3216
|
+
(head) => /* @__PURE__ */ jsx(Table.HeaderCell, { ...head }, head.name)
|
3217
|
+
)
|
3218
|
+
] }),
|
3219
|
+
/* @__PURE__ */ jsx(Table.Loading, {}),
|
3220
|
+
/* @__PURE__ */ jsx(Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxs(Table.Row, { children: [
|
3221
|
+
/* @__PURE__ */ jsx(Table.CheckboxCell, { id: row.id }),
|
3222
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row.id }) }),
|
3223
|
+
shouldDisplayMainField && /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Typography, { children: row[mainField] }) }),
|
3224
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
|
3225
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3226
|
+
/* @__PURE__ */ jsx(Typography, { children: formatMessage({
|
3227
|
+
id: "content-manager.success.record.publishing",
|
3228
|
+
defaultMessage: "Publishing..."
|
3229
|
+
}) }),
|
3230
|
+
/* @__PURE__ */ jsx(Loader, { small: true })
|
3231
|
+
] }) : /* @__PURE__ */ jsx(
|
3232
|
+
EntryValidationText,
|
3233
|
+
{
|
3234
|
+
validationErrors: validationErrors[row.documentId],
|
3235
|
+
status: row.status
|
3236
|
+
}
|
3237
|
+
) }),
|
3238
|
+
/* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(
|
3239
|
+
IconButton,
|
3240
|
+
{
|
3241
|
+
tag: Link,
|
3242
|
+
to: {
|
3243
|
+
pathname: `${pathname}/${row.documentId}`,
|
3244
|
+
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3245
|
+
},
|
3246
|
+
state: { from: pathname },
|
3247
|
+
label: formatMessage(
|
3248
|
+
{ id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
|
3249
|
+
{
|
3250
|
+
target: formatMessage(
|
3251
|
+
{
|
3252
|
+
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3253
|
+
defaultMessage: "item line {number}"
|
3254
|
+
},
|
3255
|
+
{ number: index2 + 1 }
|
3256
|
+
)
|
3257
|
+
}
|
3258
|
+
),
|
3259
|
+
target: "_blank",
|
3260
|
+
marginLeft: "auto",
|
3261
|
+
variant: "ghost",
|
3262
|
+
children: /* @__PURE__ */ jsx(Pencil, { width: "1.6rem", height: "1.6rem" })
|
3263
|
+
}
|
3264
|
+
) }) })
|
3265
|
+
] }, row.id)) })
|
3266
|
+
] });
|
3267
|
+
};
|
3268
|
+
const BoldChunk = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: chunks });
|
3269
|
+
const SelectedEntriesModalContent = ({
|
3270
|
+
listViewSelectedEntries,
|
3271
|
+
toggleModal,
|
3272
|
+
setListViewSelectedDocuments,
|
3273
|
+
model
|
3274
|
+
}) => {
|
3275
|
+
const { formatMessage } = useIntl();
|
3276
|
+
const { schema, components } = useContentTypeSchema(model);
|
3277
|
+
const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
|
3278
|
+
const [{ query }] = useQueryParams();
|
3279
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
3280
|
+
const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
|
3281
|
+
{
|
3282
|
+
model,
|
3283
|
+
params: {
|
3284
|
+
page: "1",
|
3285
|
+
pageSize: documentIds.length.toString(),
|
3286
|
+
sort: query.sort,
|
3287
|
+
filters: {
|
3288
|
+
documentId: {
|
3289
|
+
$in: documentIds
|
3290
|
+
}
|
3291
|
+
},
|
3292
|
+
locale: query.plugins?.i18n?.locale
|
3293
|
+
}
|
3294
|
+
},
|
3295
|
+
{
|
3296
|
+
selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
|
3297
|
+
}
|
3298
|
+
);
|
3299
|
+
const { rows, validationErrors } = React.useMemo(() => {
|
3300
|
+
if (data.length > 0 && schema) {
|
3301
|
+
const validate = createYupSchema(
|
3302
|
+
schema.attributes,
|
3303
|
+
components,
|
3304
|
+
// Since this is the "Publish" action, the validation
|
3305
|
+
// schema must enforce the rules for published entities
|
3306
|
+
{ status: "published" }
|
3307
|
+
);
|
3308
|
+
const validationErrors2 = {};
|
3309
|
+
const rows2 = data.map((entry) => {
|
3310
|
+
try {
|
3311
|
+
validate.validateSync(entry, { abortEarly: false });
|
3312
|
+
return entry;
|
3313
|
+
} catch (e) {
|
3314
|
+
if (e instanceof ValidationError) {
|
3315
|
+
validationErrors2[entry.documentId] = getYupValidationErrors(e);
|
3316
|
+
}
|
3317
|
+
return entry;
|
3318
|
+
}
|
3319
|
+
});
|
3320
|
+
return { rows: rows2, validationErrors: validationErrors2 };
|
3321
|
+
}
|
3322
|
+
return {
|
3323
|
+
rows: [],
|
3324
|
+
validationErrors: {}
|
3325
|
+
};
|
3326
|
+
}, [components, data, schema]);
|
3327
|
+
const [publishedCount, setPublishedCount] = React.useState(0);
|
3328
|
+
const [isDialogOpen, setIsDialogOpen] = React.useState(false);
|
3329
|
+
const { publishMany: bulkPublishAction } = useDocumentActions();
|
3330
|
+
const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
|
3331
|
+
const selectedRows = useTable("publishAction", (state) => state.selectedRows);
|
3332
|
+
const selectedEntries = rows.filter(
|
3333
|
+
(entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
|
3334
|
+
);
|
3335
|
+
const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
|
3336
|
+
const selectedEntriesWithErrorsCount = selectedEntries.filter(
|
3337
|
+
({ documentId }) => validationErrors[documentId]
|
3338
|
+
).length;
|
3339
|
+
const selectedEntriesPublished = selectedEntries.filter(
|
3340
|
+
({ status }) => status === "published"
|
3341
|
+
).length;
|
3342
|
+
const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
|
3343
|
+
const toggleDialog = () => setIsDialogOpen((prev) => !prev);
|
3344
|
+
const handleConfirmBulkPublish = async () => {
|
3345
|
+
toggleDialog();
|
3346
|
+
const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
|
3347
|
+
if (!("error" in res)) {
|
3348
|
+
setPublishedCount(res.count);
|
3349
|
+
const unpublishedEntries = rows.filter((row) => {
|
3350
|
+
return !entriesToPublish.includes(row.documentId);
|
3351
|
+
});
|
3352
|
+
setListViewSelectedDocuments(unpublishedEntries);
|
3353
|
+
}
|
3354
|
+
};
|
3355
|
+
const getFormattedCountMessage = () => {
|
3356
|
+
if (publishedCount) {
|
3357
|
+
return formatMessage(
|
3358
|
+
{
|
3359
|
+
id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
|
3360
|
+
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."
|
3361
|
+
},
|
3362
|
+
{
|
3363
|
+
publishedCount,
|
3364
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3365
|
+
b: BoldChunk
|
3366
|
+
}
|
3367
|
+
);
|
3368
|
+
}
|
3369
|
+
return formatMessage(
|
3370
|
+
{
|
3371
|
+
id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
|
3372
|
+
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."
|
3373
|
+
},
|
3374
|
+
{
|
3375
|
+
readyToPublishCount: selectedEntriesWithNoErrorsCount,
|
3376
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3377
|
+
alreadyPublishedCount: selectedEntriesPublished,
|
3378
|
+
b: BoldChunk
|
3379
|
+
}
|
3380
|
+
);
|
3381
|
+
};
|
3382
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
3383
|
+
/* @__PURE__ */ jsxs(Modal.Body, { children: [
|
3384
|
+
/* @__PURE__ */ jsx(Typography, { children: getFormattedCountMessage() }),
|
3385
|
+
/* @__PURE__ */ jsx(Box, { marginTop: 5, children: /* @__PURE__ */ jsx(
|
3386
|
+
SelectedEntriesTableContent,
|
3387
|
+
{
|
3388
|
+
isPublishing: isSubmittingForm,
|
3389
|
+
rowsToDisplay: rows,
|
3390
|
+
entriesToPublish,
|
3391
|
+
validationErrors
|
3392
|
+
}
|
3393
|
+
) })
|
3394
|
+
] }),
|
3395
|
+
/* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
3396
|
+
/* @__PURE__ */ jsx(Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
|
3397
|
+
id: "app.components.Button.cancel",
|
3398
|
+
defaultMessage: "Cancel"
|
3399
|
+
}) }),
|
3400
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
3401
|
+
/* @__PURE__ */ jsx(Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
|
3402
|
+
/* @__PURE__ */ jsx(
|
3403
|
+
Button,
|
3404
|
+
{
|
3405
|
+
onClick: toggleDialog,
|
3406
|
+
disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
|
3407
|
+
loading: isSubmittingForm,
|
3408
|
+
children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
|
3409
|
+
}
|
3410
|
+
)
|
3411
|
+
] })
|
3412
|
+
] }),
|
3413
|
+
/* @__PURE__ */ jsx(
|
3414
|
+
ConfirmDialogPublishAll,
|
3415
|
+
{
|
3416
|
+
isOpen: isDialogOpen,
|
3417
|
+
onToggleDialog: toggleDialog,
|
3418
|
+
isConfirmButtonLoading: isSubmittingForm,
|
3419
|
+
onConfirm: handleConfirmBulkPublish
|
3420
|
+
}
|
3421
|
+
)
|
3422
|
+
] });
|
3423
|
+
};
|
3424
|
+
const PublishAction = ({ documents, model }) => {
|
3425
|
+
const { formatMessage } = useIntl();
|
3426
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3427
|
+
const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
|
3428
|
+
const setListViewSelectedDocuments = useTable("publishAction", (state) => state.selectRow);
|
3429
|
+
const refetchList = () => {
|
3430
|
+
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3431
|
+
};
|
3432
|
+
if (!showPublishButton)
|
3433
|
+
return null;
|
3434
|
+
return {
|
3435
|
+
actionType: "publish",
|
3436
|
+
variant: "tertiary",
|
3437
|
+
label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
|
3438
|
+
dialog: {
|
3439
|
+
type: "modal",
|
3440
|
+
title: formatMessage({
|
3441
|
+
id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
|
3442
|
+
defaultMessage: "Publish entries"
|
3443
|
+
}),
|
3444
|
+
content: ({ onClose }) => {
|
3445
|
+
return /* @__PURE__ */ jsx(Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsx(
|
3446
|
+
SelectedEntriesModalContent,
|
3447
|
+
{
|
3448
|
+
listViewSelectedEntries: documents,
|
3449
|
+
toggleModal: () => {
|
3450
|
+
onClose();
|
3451
|
+
refetchList();
|
3452
|
+
},
|
3453
|
+
setListViewSelectedDocuments,
|
3454
|
+
model
|
3455
|
+
}
|
3456
|
+
) });
|
3457
|
+
},
|
3458
|
+
onClose: () => {
|
3459
|
+
refetchList();
|
3460
|
+
}
|
3461
|
+
}
|
3462
|
+
};
|
3463
|
+
};
|
3464
|
+
const BulkActionsRenderer = () => {
|
3465
|
+
const plugins = useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
|
3466
|
+
const { model, collectionType } = useDoc();
|
3467
|
+
const { selectedRows } = useTable("BulkActionsRenderer", (state) => state);
|
3468
|
+
return /* @__PURE__ */ jsx(Flex, { gap: 2, children: /* @__PURE__ */ jsx(
|
3469
|
+
DescriptionComponentRenderer,
|
3470
|
+
{
|
3471
|
+
props: {
|
3472
|
+
model,
|
3473
|
+
collectionType,
|
3474
|
+
documents: selectedRows
|
3475
|
+
},
|
3476
|
+
descriptions: plugins["content-manager"].apis.getBulkActions(),
|
3477
|
+
children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsx(DocumentActionButton, { ...action }, action.id))
|
3478
|
+
}
|
3479
|
+
) });
|
3480
|
+
};
|
3481
|
+
const DeleteAction = ({ documents, model }) => {
|
3482
|
+
const { formatMessage } = useIntl();
|
3483
|
+
const { schema: contentType } = useDoc();
|
3484
|
+
const selectRow = useTable("DeleteAction", (state) => state.selectRow);
|
3485
|
+
const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
|
3486
|
+
const [{ query }] = useQueryParams();
|
3487
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
3488
|
+
const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
|
3489
|
+
const { deleteMany: bulkDeleteAction } = useDocumentActions();
|
3490
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3491
|
+
const handleConfirmBulkDelete = async () => {
|
3492
|
+
const res = await bulkDeleteAction({
|
3493
|
+
documentIds,
|
3494
|
+
model,
|
3495
|
+
params
|
3496
|
+
});
|
3497
|
+
if (!("error" in res)) {
|
3498
|
+
selectRow([]);
|
3499
|
+
}
|
3500
|
+
};
|
3501
|
+
if (!hasDeletePermission)
|
3502
|
+
return null;
|
3503
|
+
return {
|
3504
|
+
variant: "danger-light",
|
3505
|
+
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
3506
|
+
dialog: {
|
3507
|
+
type: "dialog",
|
3508
|
+
title: formatMessage({
|
3509
|
+
id: "app.components.ConfirmDialog.title",
|
3510
|
+
defaultMessage: "Confirmation"
|
3511
|
+
}),
|
3512
|
+
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3513
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3514
|
+
/* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3515
|
+
id: "popUpWarning.bodyMessage.contentType.delete.all",
|
3516
|
+
defaultMessage: "Are you sure you want to delete these entries?"
|
3517
|
+
}) }),
|
3518
|
+
hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
|
3519
|
+
{
|
3520
|
+
id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
|
3521
|
+
defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
|
3522
|
+
},
|
3523
|
+
{
|
3524
|
+
em: Emphasis
|
3525
|
+
}
|
3526
|
+
) }) })
|
3527
|
+
] }),
|
3528
|
+
onConfirm: handleConfirmBulkDelete
|
3529
|
+
}
|
3530
|
+
};
|
3531
|
+
};
|
3532
|
+
DeleteAction.type = "delete";
|
3533
|
+
const UnpublishAction = ({ documents, model }) => {
|
3534
|
+
const { formatMessage } = useIntl();
|
3535
|
+
const { schema } = useDoc();
|
3536
|
+
const selectRow = useTable("UnpublishAction", (state) => state.selectRow);
|
3537
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3538
|
+
const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
|
3539
|
+
const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
|
3540
|
+
const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
|
3541
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3542
|
+
const [{ query }] = useQueryParams();
|
3543
|
+
const params = React.useMemo(() => buildValidParams(query), [query]);
|
3544
|
+
const handleConfirmBulkUnpublish = async () => {
|
3545
|
+
const data = await bulkUnpublishAction({ documentIds, model, params });
|
3546
|
+
if (!("error" in data)) {
|
3547
|
+
selectRow([]);
|
3548
|
+
}
|
3549
|
+
};
|
3550
|
+
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3551
|
+
if (!showUnpublishButton)
|
3552
|
+
return null;
|
3553
|
+
return {
|
3554
|
+
variant: "tertiary",
|
3555
|
+
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
3556
|
+
dialog: {
|
3557
|
+
type: "dialog",
|
3558
|
+
title: formatMessage({
|
3559
|
+
id: "app.components.ConfirmDialog.title",
|
3560
|
+
defaultMessage: "Confirmation"
|
3561
|
+
}),
|
3562
|
+
content: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3563
|
+
/* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3564
|
+
/* @__PURE__ */ jsx(Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3565
|
+
id: "popUpWarning.bodyMessage.contentType.unpublish.all",
|
3566
|
+
defaultMessage: "Are you sure you want to unpublish these entries?"
|
3567
|
+
}) }),
|
3568
|
+
hasI18nEnabled && /* @__PURE__ */ jsx(Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger500", children: formatMessage(
|
3569
|
+
{
|
3570
|
+
id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
|
3571
|
+
defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
|
3572
|
+
},
|
3573
|
+
{
|
3574
|
+
em: Emphasis
|
3575
|
+
}
|
3576
|
+
) }) })
|
3577
|
+
] }),
|
3578
|
+
confirmButton: formatMessage({
|
3579
|
+
id: "app.utils.unpublish",
|
3580
|
+
defaultMessage: "Unpublish"
|
3581
|
+
}),
|
3582
|
+
onConfirm: handleConfirmBulkUnpublish
|
3583
|
+
}
|
3584
|
+
};
|
3585
|
+
};
|
3586
|
+
UnpublishAction.type = "unpublish";
|
3587
|
+
const Emphasis = (chunks) => /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
|
3588
|
+
const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
|
3589
|
+
const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
3590
|
+
const { formatMessage } = useIntl();
|
3591
|
+
const getDefaultErrorMessage = (reason) => {
|
3592
|
+
switch (reason) {
|
3593
|
+
case "relation":
|
3594
|
+
return "Duplicating the relation could remove it from the original entry.";
|
3595
|
+
case "unique":
|
3596
|
+
return "Identical values in a unique field are not allowed";
|
3597
|
+
default:
|
3598
|
+
return reason;
|
3599
|
+
}
|
3600
|
+
};
|
3601
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
3602
|
+
/* @__PURE__ */ jsx(Typography, { variant: "beta", children: formatMessage({
|
2459
3603
|
id: getTranslation("containers.list.autoCloneModal.title"),
|
2460
3604
|
defaultMessage: "This entry can't be duplicated directly."
|
2461
3605
|
}) }),
|
@@ -2473,7 +3617,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
|
2473
3617
|
hasRadius: true,
|
2474
3618
|
padding: 6,
|
2475
3619
|
children: [
|
2476
|
-
/* @__PURE__ */ jsx(Flex, { direction: "row",
|
3620
|
+
/* @__PURE__ */ jsx(Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxs(Typography, { fontWeight: "semiBold", tag: "li", children: [
|
2477
3621
|
pathSegment,
|
2478
3622
|
index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsx(
|
2479
3623
|
ChevronRight,
|
@@ -2485,7 +3629,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
|
2485
3629
|
}
|
2486
3630
|
)
|
2487
3631
|
] }, index2)) }),
|
2488
|
-
/* @__PURE__ */ jsx(Typography, {
|
3632
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
|
2489
3633
|
id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
|
2490
3634
|
defaultMessage: getDefaultErrorMessage(reason)
|
2491
3635
|
}) })
|
@@ -2510,7 +3654,7 @@ const TableActions = ({ document }) => {
|
|
2510
3654
|
DescriptionComponentRenderer,
|
2511
3655
|
{
|
2512
3656
|
props,
|
2513
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3657
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
2514
3658
|
children: (actions2) => {
|
2515
3659
|
const tableRowActions = actions2.filter((action) => {
|
2516
3660
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -2621,7 +3765,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2621
3765
|
}),
|
2622
3766
|
content: /* @__PURE__ */ jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
2623
3767
|
footer: ({ onClose }) => {
|
2624
|
-
return /* @__PURE__ */ jsxs(
|
3768
|
+
return /* @__PURE__ */ jsxs(Modal.Footer, { children: [
|
2625
3769
|
/* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
2626
3770
|
id: "cancel",
|
2627
3771
|
defaultMessage: "Cancel"
|
@@ -2629,7 +3773,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2629
3773
|
/* @__PURE__ */ jsx(
|
2630
3774
|
LinkButton,
|
2631
3775
|
{
|
2632
|
-
|
3776
|
+
tag: NavLink,
|
2633
3777
|
to: {
|
2634
3778
|
pathname: `clone/${documentId}`
|
2635
3779
|
},
|
@@ -2662,8 +3806,7 @@ class ContentManagerPlugin {
|
|
2662
3806
|
documentActions = [
|
2663
3807
|
...DEFAULT_ACTIONS,
|
2664
3808
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
2665
|
-
...DEFAULT_HEADER_ACTIONS
|
2666
|
-
HistoryAction
|
3809
|
+
...DEFAULT_HEADER_ACTIONS
|
2667
3810
|
];
|
2668
3811
|
editViewSidePanels = [ActionsPanel];
|
2669
3812
|
headerActions = [];
|
@@ -2752,352 +3895,94 @@ const getPrintableType = (value) => {
|
|
2752
3895
|
}
|
2753
3896
|
return nativeType;
|
2754
3897
|
};
|
2755
|
-
const
|
2756
|
-
|
2757
|
-
|
2758
|
-
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
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;
|
3898
|
+
const HistoryAction = ({ model, document }) => {
|
3899
|
+
const { formatMessage } = useIntl();
|
3900
|
+
const [{ query }] = useQueryParams();
|
3901
|
+
const navigate = useNavigate();
|
3902
|
+
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
3903
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3904
|
+
return null;
|
2866
3905
|
}
|
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
3906
|
return {
|
2872
|
-
|
2873
|
-
|
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
|
3907
|
+
icon: /* @__PURE__ */ jsx(ClockCounterClockwise, {}),
|
3908
|
+
label: formatMessage({
|
3909
|
+
id: "content-manager.history.document-action",
|
3910
|
+
defaultMessage: "Content History"
|
2930
3911
|
}),
|
2931
|
-
|
2932
|
-
|
2933
|
-
|
2934
|
-
|
2935
|
-
|
2936
|
-
|
2937
|
-
|
2938
|
-
|
2939
|
-
|
2940
|
-
|
2941
|
-
|
2942
|
-
|
2943
|
-
|
2944
|
-
|
2945
|
-
|
2946
|
-
|
2947
|
-
|
2948
|
-
|
2949
|
-
|
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;
|
2960
|
-
} else {
|
2961
|
-
if (!panels[currentPanelIndex]) {
|
2962
|
-
panels.push([]);
|
2963
|
-
}
|
2964
|
-
panels[currentPanelIndex].push(row);
|
2965
|
-
}
|
2966
|
-
return panels;
|
2967
|
-
}, []);
|
2968
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2969
|
-
(acc, [uid, configuration]) => {
|
2970
|
-
acc[uid] = {
|
2971
|
-
layout: convertEditLayoutToFieldLayouts(
|
2972
|
-
configuration.layouts.edit,
|
2973
|
-
components[uid].attributes,
|
2974
|
-
configuration.metadatas
|
2975
|
-
),
|
2976
|
-
settings: {
|
2977
|
-
...configuration.settings,
|
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
|
3007
|
-
}
|
3912
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3913
|
+
disabled: (
|
3914
|
+
/**
|
3915
|
+
* The user is creating a new document.
|
3916
|
+
* It hasn't been saved yet, so there's no history to go to
|
3917
|
+
*/
|
3918
|
+
!document || /**
|
3919
|
+
* The document has been created but the current dimension has never been saved.
|
3920
|
+
* For example, the user is creating a new locale in an existing document,
|
3921
|
+
* so there's no history for the document in that locale
|
3922
|
+
*/
|
3923
|
+
!document.id || /**
|
3924
|
+
* History is only available for content types created by the user.
|
3925
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3926
|
+
* which start with `admin::` or `plugin::`
|
3927
|
+
*/
|
3928
|
+
!model.startsWith("api::")
|
3929
|
+
),
|
3930
|
+
position: "header"
|
3008
3931
|
};
|
3009
3932
|
};
|
3010
|
-
|
3011
|
-
|
3012
|
-
|
3013
|
-
|
3014
|
-
|
3015
|
-
|
3016
|
-
|
3017
|
-
|
3018
|
-
|
3019
|
-
|
3020
|
-
attribute,
|
3021
|
-
disabled: !metadata.editable,
|
3022
|
-
hint: metadata.description,
|
3023
|
-
label: metadata.label ?? "",
|
3024
|
-
name: field.name,
|
3025
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
3026
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
3027
|
-
schemas,
|
3028
|
-
components: components?.schemas ?? {}
|
3029
|
-
}),
|
3030
|
-
placeholder: metadata.placeholder ?? "",
|
3031
|
-
required: attribute.required ?? false,
|
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
|
-
);
|
3933
|
+
HistoryAction.type = "history";
|
3934
|
+
const historyAdmin = {
|
3935
|
+
bootstrap(app) {
|
3936
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3937
|
+
addDocumentAction((actions2) => {
|
3938
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3939
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3940
|
+
return actions2;
|
3941
|
+
});
|
3942
|
+
}
|
3039
3943
|
};
|
3040
|
-
const
|
3041
|
-
|
3042
|
-
|
3043
|
-
|
3044
|
-
|
3045
|
-
|
3046
|
-
|
3047
|
-
return {
|
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
|
-
);
|
3061
|
-
return {
|
3062
|
-
layout: listAttributes,
|
3063
|
-
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
3064
|
-
metadatas: listMetadatas,
|
3065
|
-
options: {
|
3066
|
-
...schema?.options,
|
3067
|
-
...schema?.pluginOptions,
|
3068
|
-
...data.contentType.options
|
3069
|
-
}
|
3070
|
-
};
|
3944
|
+
const initialState = {
|
3945
|
+
collectionTypeLinks: [],
|
3946
|
+
components: [],
|
3947
|
+
fieldSizes: {},
|
3948
|
+
models: [],
|
3949
|
+
singleTypeLinks: [],
|
3950
|
+
isLoading: true
|
3071
3951
|
};
|
3072
|
-
const
|
3073
|
-
|
3074
|
-
|
3075
|
-
|
3076
|
-
|
3952
|
+
const appSlice = createSlice({
|
3953
|
+
name: "app",
|
3954
|
+
initialState,
|
3955
|
+
reducers: {
|
3956
|
+
setInitialData(state, action) {
|
3957
|
+
const {
|
3958
|
+
authorizedCollectionTypeLinks,
|
3959
|
+
authorizedSingleTypeLinks,
|
3960
|
+
components,
|
3961
|
+
contentTypeSchemas,
|
3962
|
+
fieldSizes
|
3963
|
+
} = action.payload;
|
3964
|
+
state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
|
3965
|
+
({ isDisplayed }) => isDisplayed
|
3966
|
+
);
|
3967
|
+
state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
|
3968
|
+
state.components = components;
|
3969
|
+
state.models = contentTypeSchemas;
|
3970
|
+
state.fieldSizes = fieldSizes;
|
3971
|
+
state.isLoading = false;
|
3077
3972
|
}
|
3078
|
-
|
3079
|
-
|
3080
|
-
|
3081
|
-
|
3082
|
-
|
3083
|
-
|
3084
|
-
|
3085
|
-
components: components?.schemas ?? {}
|
3086
|
-
}),
|
3087
|
-
name,
|
3088
|
-
searchable: metadata.searchable ?? true,
|
3089
|
-
sortable: metadata.sortable ?? true
|
3090
|
-
};
|
3091
|
-
}).filter((field) => field !== null);
|
3092
|
-
};
|
3973
|
+
}
|
3974
|
+
});
|
3975
|
+
const { actions, reducer: reducer$1 } = appSlice;
|
3976
|
+
const { setInitialData } = actions;
|
3977
|
+
const reducer = combineReducers({
|
3978
|
+
app: reducer$1
|
3979
|
+
});
|
3093
3980
|
const index = {
|
3094
3981
|
register(app) {
|
3095
3982
|
const cm = new ContentManagerPlugin();
|
3096
3983
|
app.addReducers({
|
3097
|
-
[contentManagerApi.reducerPath]: contentManagerApi.reducer,
|
3098
3984
|
[PLUGIN_ID]: reducer
|
3099
3985
|
});
|
3100
|
-
app.addMiddlewares([() => contentManagerApi.middleware]);
|
3101
3986
|
app.addMenuLink({
|
3102
3987
|
to: PLUGIN_ID,
|
3103
3988
|
icon: Feather,
|
@@ -3106,14 +3991,29 @@ const index = {
|
|
3106
3991
|
defaultMessage: "Content Manager"
|
3107
3992
|
},
|
3108
3993
|
permissions: [],
|
3109
|
-
|
3994
|
+
position: 1
|
3995
|
+
});
|
3996
|
+
app.router.addRoute({
|
3997
|
+
path: "content-manager/*",
|
3998
|
+
lazy: async () => {
|
3999
|
+
const { Layout } = await import("./layout-ClP-DC72.mjs");
|
4000
|
+
return {
|
4001
|
+
Component: Layout
|
4002
|
+
};
|
4003
|
+
},
|
4004
|
+
children: routes
|
3110
4005
|
});
|
3111
4006
|
app.registerPlugin(cm.config);
|
3112
4007
|
},
|
4008
|
+
bootstrap(app) {
|
4009
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4010
|
+
historyAdmin.bootstrap(app);
|
4011
|
+
}
|
4012
|
+
},
|
3113
4013
|
async registerTrads({ locales }) {
|
3114
4014
|
const importedTrads = await Promise.all(
|
3115
4015
|
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-
|
4016
|
+
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-C8YBvRrK.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
4017
|
return {
|
3118
4018
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3119
4019
|
locale
|
@@ -3131,45 +4031,47 @@ const index = {
|
|
3131
4031
|
};
|
3132
4032
|
export {
|
3133
4033
|
ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD as A,
|
3134
|
-
|
4034
|
+
BulkActionsRenderer as B,
|
3135
4035
|
COLLECTION_TYPES as C,
|
3136
4036
|
DocumentStatus as D,
|
3137
|
-
|
3138
|
-
|
3139
|
-
|
4037
|
+
extractContentTypeComponents as E,
|
4038
|
+
DEFAULT_SETTINGS as F,
|
4039
|
+
convertEditLayoutToFieldLayouts as G,
|
3140
4040
|
HOOKS as H,
|
3141
4041
|
InjectionZone as I,
|
3142
|
-
|
3143
|
-
|
4042
|
+
useDocument as J,
|
4043
|
+
index as K,
|
4044
|
+
useContentManagerContext as L,
|
4045
|
+
useDocumentActions as M,
|
3144
4046
|
Panels as P,
|
3145
4047
|
RelativeTime as R,
|
3146
4048
|
SINGLE_TYPES as S,
|
3147
4049
|
TableActions as T,
|
3148
|
-
|
3149
|
-
|
3150
|
-
|
3151
|
-
|
3152
|
-
|
3153
|
-
|
4050
|
+
useGetInitialDataQuery as a,
|
4051
|
+
useGetAllContentTypeSettingsQuery as b,
|
4052
|
+
useDoc as c,
|
4053
|
+
buildValidParams as d,
|
4054
|
+
contentManagerApi as e,
|
4055
|
+
useDocumentRBAC as f,
|
3154
4056
|
getTranslation as g,
|
3155
|
-
|
3156
|
-
|
3157
|
-
|
3158
|
-
|
3159
|
-
|
3160
|
-
|
3161
|
-
|
3162
|
-
|
3163
|
-
|
3164
|
-
|
3165
|
-
|
4057
|
+
useDocumentLayout as h,
|
4058
|
+
createYupSchema as i,
|
4059
|
+
Header as j,
|
4060
|
+
PERMISSIONS as k,
|
4061
|
+
DocumentRBAC as l,
|
4062
|
+
DOCUMENT_META_FIELDS as m,
|
4063
|
+
CLONE_PATH as n,
|
4064
|
+
useDocLayout as o,
|
4065
|
+
useGetContentTypeConfigurationQuery as p,
|
4066
|
+
CREATOR_FIELDS as q,
|
4067
|
+
getMainField as r,
|
3166
4068
|
setInitialData as s,
|
3167
4069
|
getDisplayName as t,
|
3168
|
-
|
4070
|
+
useContentTypeSchema as u,
|
3169
4071
|
checkIfAttributeIsDisplayable as v,
|
3170
4072
|
useGetAllDocumentsQuery as w,
|
3171
4073
|
convertListLayoutToFieldLayouts as x,
|
3172
4074
|
capitalise as y,
|
3173
4075
|
useUpdateContentTypeConfigurationMutation as z
|
3174
4076
|
};
|
3175
|
-
//# sourceMappingURL=index-
|
4077
|
+
//# sourceMappingURL=index-BmUAydCA.mjs.map
|