@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
@@ -2,17 +2,15 @@
|
|
2
2
|
const Icons = require("@strapi/icons");
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
4
4
|
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
5
|
-
const qs = require("qs");
|
6
|
-
const reactIntl = require("react-intl");
|
7
|
-
const reactRouterDom = require("react-router-dom");
|
8
5
|
const React = require("react");
|
9
6
|
const designSystem = require("@strapi/design-system");
|
10
|
-
const
|
7
|
+
const reactIntl = require("react-intl");
|
8
|
+
const reactRouterDom = require("react-router-dom");
|
11
9
|
const yup = require("yup");
|
12
|
-
const react = require("@reduxjs/toolkit/query/react");
|
13
|
-
const axios = require("axios");
|
14
10
|
const pipe = require("lodash/fp/pipe");
|
15
11
|
const dateFns = require("date-fns");
|
12
|
+
const styledComponents = require("styled-components");
|
13
|
+
const qs = require("qs");
|
16
14
|
const toolkit = require("@reduxjs/toolkit");
|
17
15
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
18
16
|
function _interopNamespace(e) {
|
@@ -34,7 +32,6 @@ function _interopNamespace(e) {
|
|
34
32
|
return Object.freeze(n);
|
35
33
|
}
|
36
34
|
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
37
|
-
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
38
35
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
39
36
|
const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
|
40
37
|
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
@@ -73,42 +70,6 @@ const useInjectionZone = (area) => {
|
|
73
70
|
const [page, position] = area.split(".");
|
74
71
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
75
72
|
};
|
76
|
-
const HistoryAction = ({ model, document }) => {
|
77
|
-
const { formatMessage } = reactIntl.useIntl();
|
78
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
79
|
-
const navigate = reactRouterDom.useNavigate();
|
80
|
-
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
81
|
-
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
82
|
-
return null;
|
83
|
-
}
|
84
|
-
return {
|
85
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
86
|
-
label: formatMessage({
|
87
|
-
id: "content-manager.history.document-action",
|
88
|
-
defaultMessage: "Content History"
|
89
|
-
}),
|
90
|
-
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
91
|
-
disabled: (
|
92
|
-
/**
|
93
|
-
* The user is creating a new document.
|
94
|
-
* It hasn't been saved yet, so there's no history to go to
|
95
|
-
*/
|
96
|
-
!document || /**
|
97
|
-
* The document has been created but the current dimension has never been saved.
|
98
|
-
* For example, the user is creating a new locale in an existing document,
|
99
|
-
* so there's no history for the document in that locale
|
100
|
-
*/
|
101
|
-
!document.id || /**
|
102
|
-
* History is only available for content types created by the user.
|
103
|
-
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
104
|
-
* which start with `admin::` or `plugin::`
|
105
|
-
*/
|
106
|
-
!model.startsWith("api::")
|
107
|
-
),
|
108
|
-
position: "header"
|
109
|
-
};
|
110
|
-
};
|
111
|
-
HistoryAction.type = "history";
|
112
73
|
const ID = "id";
|
113
74
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
114
75
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -179,9 +140,8 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
179
140
|
const name = removeNumericalStrings(fieldName.split("."));
|
180
141
|
const componentFieldNames = fieldsUserCanAction.filter((field) => field.split(".").length > 1);
|
181
142
|
if (fieldType === "component") {
|
182
|
-
|
183
|
-
|
184
|
-
return field.includes(fieldName);
|
143
|
+
return componentFieldNames.some((field) => {
|
144
|
+
return field.includes(name.join("."));
|
185
145
|
});
|
186
146
|
}
|
187
147
|
if (name.length > 1) {
|
@@ -211,89 +171,20 @@ const extractAndDedupeFields = (permissions = []) => permissions.flatMap((permis
|
|
211
171
|
(field, index2, arr) => arr.indexOf(field) === index2 && typeof field === "string"
|
212
172
|
);
|
213
173
|
const removeNumericalStrings = (arr) => arr.filter((item) => isNaN(Number(item)));
|
214
|
-
const
|
215
|
-
|
216
|
-
return query;
|
217
|
-
const { plugins: _, ...validQueryParams } = {
|
218
|
-
...query,
|
219
|
-
...Object.values(query?.plugins ?? {}).reduce(
|
220
|
-
(acc, current) => Object.assign(acc, current),
|
221
|
-
{}
|
222
|
-
)
|
223
|
-
};
|
224
|
-
if ("_q" in validQueryParams) {
|
225
|
-
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
226
|
-
}
|
227
|
-
return validQueryParams;
|
228
|
-
};
|
229
|
-
const axiosBaseQuery = () => async (query, { signal }) => {
|
230
|
-
try {
|
231
|
-
const { get, post, del, put } = strapiAdmin.getFetchClient();
|
232
|
-
if (typeof query === "string") {
|
233
|
-
const result = await get(query, { signal });
|
234
|
-
return { data: result.data };
|
235
|
-
} else {
|
236
|
-
const { url, method = "GET", data, config } = query;
|
237
|
-
if (method === "POST") {
|
238
|
-
const result2 = await post(url, data, { ...config, signal });
|
239
|
-
return { data: result2.data };
|
240
|
-
}
|
241
|
-
if (method === "DELETE") {
|
242
|
-
const result2 = await del(url, { ...config, signal });
|
243
|
-
return { data: result2.data };
|
244
|
-
}
|
245
|
-
if (method === "PUT") {
|
246
|
-
const result2 = await put(url, data, { ...config, signal });
|
247
|
-
return { data: result2.data };
|
248
|
-
}
|
249
|
-
const result = await get(url, { ...config, signal });
|
250
|
-
return { data: result.data };
|
251
|
-
}
|
252
|
-
} catch (err) {
|
253
|
-
if (axios.isAxiosError(err)) {
|
254
|
-
if (typeof err.response?.data === "object" && err.response?.data !== null && "error" in err.response?.data) {
|
255
|
-
return { data: void 0, error: err.response?.data.error };
|
256
|
-
} else {
|
257
|
-
return {
|
258
|
-
data: void 0,
|
259
|
-
error: {
|
260
|
-
name: "UnknownError",
|
261
|
-
message: "There was an unknown error response from the API",
|
262
|
-
details: err.response?.data,
|
263
|
-
status: err.response?.status
|
264
|
-
}
|
265
|
-
};
|
266
|
-
}
|
267
|
-
}
|
268
|
-
const error = err;
|
269
|
-
return {
|
270
|
-
data: void 0,
|
271
|
-
error: {
|
272
|
-
name: error.name,
|
273
|
-
message: error.message,
|
274
|
-
stack: error.stack
|
275
|
-
}
|
276
|
-
};
|
277
|
-
}
|
278
|
-
};
|
279
|
-
const isBaseQueryError = (error) => {
|
280
|
-
return error.name !== void 0;
|
281
|
-
};
|
282
|
-
const contentManagerApi = react.createApi({
|
283
|
-
reducerPath: "contentManagerApi",
|
284
|
-
baseQuery: axiosBaseQuery(),
|
285
|
-
tagTypes: [
|
174
|
+
const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
175
|
+
addTagTypes: [
|
286
176
|
"ComponentConfiguration",
|
287
177
|
"ContentTypesConfiguration",
|
288
178
|
"ContentTypeSettings",
|
289
179
|
"Document",
|
290
180
|
"InitialData",
|
291
181
|
"HistoryVersion",
|
292
|
-
"Relations"
|
293
|
-
|
294
|
-
|
182
|
+
"Relations",
|
183
|
+
"UidAvailability"
|
184
|
+
]
|
295
185
|
});
|
296
186
|
const documentApi = contentManagerApi.injectEndpoints({
|
187
|
+
overrideExisting: true,
|
297
188
|
endpoints: (builder) => ({
|
298
189
|
autoCloneDocument: builder.mutation({
|
299
190
|
query: ({ model, sourceId, query }) => ({
|
@@ -303,7 +194,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
303
194
|
params: query
|
304
195
|
}
|
305
196
|
}),
|
306
|
-
invalidatesTags: (_result,
|
197
|
+
invalidatesTags: (_result, error, { model }) => {
|
198
|
+
if (error) {
|
199
|
+
return [];
|
200
|
+
}
|
201
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
202
|
+
}
|
307
203
|
}),
|
308
204
|
cloneDocument: builder.mutation({
|
309
205
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -314,7 +210,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
314
210
|
params
|
315
211
|
}
|
316
212
|
}),
|
317
|
-
invalidatesTags: (_result, _error, { model }) => [
|
213
|
+
invalidatesTags: (_result, _error, { model }) => [
|
214
|
+
{ type: "Document", id: `${model}_LIST` },
|
215
|
+
{ type: "UidAvailability", id: model }
|
216
|
+
]
|
318
217
|
}),
|
319
218
|
/**
|
320
219
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -331,7 +230,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
331
230
|
}),
|
332
231
|
invalidatesTags: (result, _error, { model }) => [
|
333
232
|
{ type: "Document", id: `${model}_LIST` },
|
334
|
-
"Relations"
|
233
|
+
"Relations",
|
234
|
+
{ type: "UidAvailability", id: model }
|
335
235
|
]
|
336
236
|
}),
|
337
237
|
deleteDocument: builder.mutation({
|
@@ -347,12 +247,15 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
347
247
|
]
|
348
248
|
}),
|
349
249
|
deleteManyDocuments: builder.mutation({
|
350
|
-
query: ({ model, ...body }) => ({
|
250
|
+
query: ({ model, params, ...body }) => ({
|
351
251
|
url: `/content-manager/collection-types/${model}/actions/bulkDelete`,
|
352
252
|
method: "POST",
|
353
|
-
data: body
|
253
|
+
data: body,
|
254
|
+
config: {
|
255
|
+
params
|
256
|
+
}
|
354
257
|
}),
|
355
|
-
invalidatesTags: (_res, _error, { model
|
258
|
+
invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
|
356
259
|
}),
|
357
260
|
discardDocument: builder.mutation({
|
358
261
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -369,7 +272,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
369
272
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
370
273
|
},
|
371
274
|
{ type: "Document", id: `${model}_LIST` },
|
372
|
-
"Relations"
|
275
|
+
"Relations",
|
276
|
+
{ type: "UidAvailability", id: model }
|
373
277
|
];
|
374
278
|
}
|
375
279
|
}),
|
@@ -387,6 +291,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
387
291
|
}),
|
388
292
|
providesTags: (result, _error, arg) => {
|
389
293
|
return [
|
294
|
+
{ type: "Document", id: `ALL_LIST` },
|
390
295
|
{ type: "Document", id: `${arg.model}_LIST` },
|
391
296
|
...result?.results.map(({ documentId }) => ({
|
392
297
|
type: "Document",
|
@@ -425,6 +330,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
425
330
|
{
|
426
331
|
type: "Document",
|
427
332
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
333
|
+
},
|
334
|
+
// Make it easy to invalidate all individual documents queries for a model
|
335
|
+
{
|
336
|
+
type: "Document",
|
337
|
+
id: `${model}_ALL_ITEMS`
|
428
338
|
}
|
429
339
|
];
|
430
340
|
}
|
@@ -463,10 +373,13 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
463
373
|
}
|
464
374
|
}),
|
465
375
|
publishManyDocuments: builder.mutation({
|
466
|
-
query: ({ model, ...body }) => ({
|
376
|
+
query: ({ model, params, ...body }) => ({
|
467
377
|
url: `/content-manager/collection-types/${model}/actions/bulkPublish`,
|
468
378
|
method: "POST",
|
469
|
-
data: body
|
379
|
+
data: body,
|
380
|
+
config: {
|
381
|
+
params
|
382
|
+
}
|
470
383
|
}),
|
471
384
|
invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
|
472
385
|
}),
|
@@ -485,8 +398,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
485
398
|
type: "Document",
|
486
399
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
487
400
|
},
|
488
|
-
"Relations"
|
401
|
+
"Relations",
|
402
|
+
{ type: "UidAvailability", id: model }
|
489
403
|
];
|
404
|
+
},
|
405
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
406
|
+
const patchResult = dispatch(
|
407
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
408
|
+
Object.assign(draft.data, data);
|
409
|
+
})
|
410
|
+
);
|
411
|
+
try {
|
412
|
+
await queryFulfilled;
|
413
|
+
} catch {
|
414
|
+
patchResult.undo();
|
415
|
+
}
|
490
416
|
}
|
491
417
|
}),
|
492
418
|
unpublishDocument: builder.mutation({
|
@@ -508,10 +434,13 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
508
434
|
}
|
509
435
|
}),
|
510
436
|
unpublishManyDocuments: builder.mutation({
|
511
|
-
query: ({ model, ...body }) => ({
|
437
|
+
query: ({ model, params, ...body }) => ({
|
512
438
|
url: `/content-manager/collection-types/${model}/actions/bulkUnpublish`,
|
513
439
|
method: "POST",
|
514
|
-
data: body
|
440
|
+
data: body,
|
441
|
+
config: {
|
442
|
+
params
|
443
|
+
}
|
515
444
|
}),
|
516
445
|
invalidatesTags: (_res, _error, { model, documentIds }) => documentIds.map((id) => ({ type: "Document", id: `${model}_${id}` }))
|
517
446
|
})
|
@@ -535,7 +464,25 @@ const {
|
|
535
464
|
useUnpublishDocumentMutation,
|
536
465
|
useUnpublishManyDocumentsMutation
|
537
466
|
} = documentApi;
|
538
|
-
const
|
467
|
+
const buildValidParams = (query) => {
|
468
|
+
if (!query)
|
469
|
+
return query;
|
470
|
+
const { plugins: _, ...validQueryParams } = {
|
471
|
+
...query,
|
472
|
+
...Object.values(query?.plugins ?? {}).reduce(
|
473
|
+
(acc, current) => Object.assign(acc, current),
|
474
|
+
{}
|
475
|
+
)
|
476
|
+
};
|
477
|
+
if ("_q" in validQueryParams) {
|
478
|
+
validQueryParams._q = encodeURIComponent(validQueryParams._q);
|
479
|
+
}
|
480
|
+
return validQueryParams;
|
481
|
+
};
|
482
|
+
const isBaseQueryError = (error) => {
|
483
|
+
return error.name !== void 0;
|
484
|
+
};
|
485
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
539
486
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
540
487
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
541
488
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
@@ -548,7 +495,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
548
495
|
addMinValidation,
|
549
496
|
addMaxValidation,
|
550
497
|
addRegexValidation
|
551
|
-
].map((fn) => fn(attribute));
|
498
|
+
].map((fn) => fn(attribute, options));
|
552
499
|
const transformSchema = pipe__default.default(...validations);
|
553
500
|
switch (attribute.type) {
|
554
501
|
case "component": {
|
@@ -574,10 +521,14 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
574
521
|
yup__namespace.array().of(
|
575
522
|
yup__namespace.lazy(
|
576
523
|
(data) => {
|
577
|
-
const
|
578
|
-
|
524
|
+
const attributes3 = components?.[data?.__component]?.attributes;
|
525
|
+
const validation = yup__namespace.object().shape({
|
579
526
|
__component: yup__namespace.string().required().oneOf(Object.keys(components))
|
580
|
-
}).nullable(false)
|
527
|
+
}).nullable(false);
|
528
|
+
if (!attributes3) {
|
529
|
+
return validation;
|
530
|
+
}
|
531
|
+
return validation.concat(createModelSchema(attributes3));
|
581
532
|
}
|
582
533
|
)
|
583
534
|
)
|
@@ -587,11 +538,25 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
587
538
|
return {
|
588
539
|
...acc,
|
589
540
|
[name]: transformSchema(
|
590
|
-
yup__namespace.
|
591
|
-
|
592
|
-
|
593
|
-
})
|
594
|
-
|
541
|
+
yup__namespace.lazy((value) => {
|
542
|
+
if (!value) {
|
543
|
+
return yup__namespace.mixed().nullable(true);
|
544
|
+
} else if (Array.isArray(value)) {
|
545
|
+
return yup__namespace.array().of(
|
546
|
+
yup__namespace.object().shape({
|
547
|
+
id: yup__namespace.string().required()
|
548
|
+
})
|
549
|
+
);
|
550
|
+
} else if (typeof value === "object") {
|
551
|
+
return yup__namespace.object();
|
552
|
+
} else {
|
553
|
+
return yup__namespace.mixed().test(
|
554
|
+
"type-error",
|
555
|
+
"Relation values must be either null, an array of objects with {id} or an object.",
|
556
|
+
() => false
|
557
|
+
);
|
558
|
+
}
|
559
|
+
})
|
595
560
|
)
|
596
561
|
};
|
597
562
|
default:
|
@@ -631,6 +596,14 @@ const createAttributeSchema = (attribute) => {
|
|
631
596
|
if (!value || typeof value === "string" && value.length === 0) {
|
632
597
|
return true;
|
633
598
|
}
|
599
|
+
if (typeof value === "object") {
|
600
|
+
try {
|
601
|
+
JSON.stringify(value);
|
602
|
+
return true;
|
603
|
+
} catch (err) {
|
604
|
+
return false;
|
605
|
+
}
|
606
|
+
}
|
634
607
|
try {
|
635
608
|
JSON.parse(value);
|
636
609
|
return true;
|
@@ -649,16 +622,30 @@ const createAttributeSchema = (attribute) => {
|
|
649
622
|
return yup__namespace.mixed();
|
650
623
|
}
|
651
624
|
};
|
652
|
-
const
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
625
|
+
const nullableSchema = (schema) => {
|
626
|
+
return schema?.nullable ? schema.nullable() : (
|
627
|
+
// In some cases '.nullable' will not be available on the schema.
|
628
|
+
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
629
|
+
// In these cases we should just return the schema as it is.
|
630
|
+
schema
|
631
|
+
);
|
632
|
+
};
|
633
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
634
|
+
if (options.status === "draft") {
|
635
|
+
return nullableSchema(schema);
|
636
|
+
}
|
637
|
+
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
638
|
+
return schema.min(1, strapiAdmin.translatedErrors.required);
|
639
|
+
}
|
640
|
+
if (attribute.required && attribute.type !== "relation") {
|
641
|
+
return schema.required(strapiAdmin.translatedErrors.required);
|
658
642
|
}
|
659
|
-
return schema
|
643
|
+
return nullableSchema(schema);
|
660
644
|
};
|
661
|
-
const addMinLengthValidation = (attribute) => (schema) => {
|
645
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
646
|
+
if (options.status === "draft") {
|
647
|
+
return schema;
|
648
|
+
}
|
662
649
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
663
650
|
return schema.min(attribute.minLength, {
|
664
651
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -680,9 +667,31 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
680
667
|
}
|
681
668
|
return schema;
|
682
669
|
};
|
683
|
-
const addMinValidation = (attribute) => (schema) => {
|
670
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
684
671
|
if ("min" in attribute) {
|
685
672
|
const min = toInteger(attribute.min);
|
673
|
+
if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
|
674
|
+
if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
|
675
|
+
return schema.test(
|
676
|
+
"custom-min",
|
677
|
+
{
|
678
|
+
...strapiAdmin.translatedErrors.min,
|
679
|
+
values: {
|
680
|
+
min: attribute.min
|
681
|
+
}
|
682
|
+
},
|
683
|
+
(value) => {
|
684
|
+
if (!value) {
|
685
|
+
return true;
|
686
|
+
}
|
687
|
+
if (Array.isArray(value) && value.length === 0) {
|
688
|
+
return true;
|
689
|
+
}
|
690
|
+
return value.length >= min;
|
691
|
+
}
|
692
|
+
);
|
693
|
+
}
|
694
|
+
}
|
686
695
|
if ("min" in schema && min) {
|
687
696
|
return schema.min(min, {
|
688
697
|
...strapiAdmin.translatedErrors.min,
|
@@ -728,24 +737,6 @@ const addRegexValidation = (attribute) => (schema) => {
|
|
728
737
|
}
|
729
738
|
return schema;
|
730
739
|
};
|
731
|
-
const extractValuesFromYupError = (errorType, errorParams) => {
|
732
|
-
if (!errorType || !errorParams) {
|
733
|
-
return {};
|
734
|
-
}
|
735
|
-
return {
|
736
|
-
[errorType]: errorParams[errorType]
|
737
|
-
};
|
738
|
-
};
|
739
|
-
const getInnerErrors = (error) => (error?.inner || []).reduce((acc, currentError) => {
|
740
|
-
if (currentError.path) {
|
741
|
-
acc[currentError.path.split("[").join(".").split("]").join("")] = {
|
742
|
-
id: currentError.message,
|
743
|
-
defaultMessage: currentError.message,
|
744
|
-
values: extractValuesFromYupError(currentError?.type, currentError?.params)
|
745
|
-
};
|
746
|
-
}
|
747
|
-
return acc;
|
748
|
-
}, {});
|
749
740
|
const initApi = contentManagerApi.injectEndpoints({
|
750
741
|
endpoints: (builder) => ({
|
751
742
|
getInitialData: builder.query({
|
@@ -759,27 +750,20 @@ const { useGetInitialDataQuery } = initApi;
|
|
759
750
|
const useContentTypeSchema = (model) => {
|
760
751
|
const { toggleNotification } = strapiAdmin.useNotification();
|
761
752
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
762
|
-
const {
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
)
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
error: res.error,
|
777
|
-
components: Object.keys(components2).length === 0 ? void 0 : components2,
|
778
|
-
contentType: contentType2,
|
779
|
-
contentTypes: res.data?.contentTypes ?? []
|
780
|
-
};
|
781
|
-
}
|
782
|
-
});
|
753
|
+
const { data, error, isLoading, isFetching } = useGetInitialDataQuery(void 0);
|
754
|
+
const { components, contentType, contentTypes } = React__namespace.useMemo(() => {
|
755
|
+
const contentType2 = data?.contentTypes.find((ct) => ct.uid === model);
|
756
|
+
const componentsByKey = data?.components.reduce((acc, component) => {
|
757
|
+
acc[component.uid] = component;
|
758
|
+
return acc;
|
759
|
+
}, {});
|
760
|
+
const components2 = extractContentTypeComponents(contentType2?.attributes, componentsByKey);
|
761
|
+
return {
|
762
|
+
components: Object.keys(components2).length === 0 ? void 0 : components2,
|
763
|
+
contentType: contentType2,
|
764
|
+
contentTypes: data?.contentTypes ?? []
|
765
|
+
};
|
766
|
+
}, [model, data]);
|
783
767
|
React__namespace.useEffect(() => {
|
784
768
|
if (error) {
|
785
769
|
toggleNotification({
|
@@ -826,83 +810,434 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
826
810
|
}, {});
|
827
811
|
return componentsByKey;
|
828
812
|
};
|
829
|
-
const
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
(document) => {
|
855
|
-
if (!validationSchema) {
|
856
|
-
throw new Error(
|
857
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
858
|
-
);
|
859
|
-
}
|
860
|
-
try {
|
861
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
862
|
-
return null;
|
863
|
-
} catch (error2) {
|
864
|
-
if (error2 instanceof yup.ValidationError) {
|
865
|
-
return getInnerErrors(error2);
|
866
|
-
}
|
867
|
-
throw error2;
|
868
|
-
}
|
869
|
-
},
|
870
|
-
[validationSchema]
|
871
|
-
);
|
872
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
873
|
-
return {
|
874
|
-
components,
|
875
|
-
document: data?.data,
|
876
|
-
meta: data?.meta,
|
877
|
-
isLoading,
|
878
|
-
schema,
|
879
|
-
validate
|
880
|
-
};
|
881
|
-
};
|
882
|
-
const useDoc = () => {
|
883
|
-
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
884
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
885
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
886
|
-
if (!collectionType) {
|
887
|
-
throw new Error("Could not find collectionType in url params");
|
888
|
-
}
|
889
|
-
if (!slug) {
|
890
|
-
throw new Error("Could not find model in url params");
|
891
|
-
}
|
892
|
-
return {
|
893
|
-
collectionType,
|
894
|
-
model: slug,
|
895
|
-
id: origin || id === "create" ? void 0 : id,
|
896
|
-
...useDocument(
|
897
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
898
|
-
{
|
899
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
900
|
-
}
|
901
|
-
)
|
902
|
-
};
|
813
|
+
const HOOKS = {
|
814
|
+
/**
|
815
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
816
|
+
* @constant
|
817
|
+
* @type {string}
|
818
|
+
*/
|
819
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
820
|
+
/**
|
821
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
822
|
+
* @constant
|
823
|
+
* @type {string}
|
824
|
+
*/
|
825
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
826
|
+
/**
|
827
|
+
* Hook that allows to mutate the CM's edit view layout
|
828
|
+
* @constant
|
829
|
+
* @type {string}
|
830
|
+
*/
|
831
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
832
|
+
/**
|
833
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
834
|
+
* @constant
|
835
|
+
* @type {string}
|
836
|
+
*/
|
837
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
903
838
|
};
|
904
|
-
const
|
905
|
-
|
839
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
840
|
+
endpoints: (builder) => ({
|
841
|
+
getContentTypeConfiguration: builder.query({
|
842
|
+
query: (uid) => ({
|
843
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
844
|
+
method: "GET"
|
845
|
+
}),
|
846
|
+
transformResponse: (response) => response.data,
|
847
|
+
providesTags: (_result, _error, uid) => [
|
848
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
849
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
850
|
+
]
|
851
|
+
}),
|
852
|
+
getAllContentTypeSettings: builder.query({
|
853
|
+
query: () => "/content-manager/content-types-settings",
|
854
|
+
transformResponse: (response) => response.data,
|
855
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
856
|
+
}),
|
857
|
+
updateContentTypeConfiguration: builder.mutation({
|
858
|
+
query: ({ uid, ...body }) => ({
|
859
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
860
|
+
method: "PUT",
|
861
|
+
data: body
|
862
|
+
}),
|
863
|
+
transformResponse: (response) => response.data,
|
864
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
865
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
866
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
867
|
+
// Is this necessary?
|
868
|
+
{ type: "InitialData" }
|
869
|
+
]
|
870
|
+
})
|
871
|
+
})
|
872
|
+
});
|
873
|
+
const {
|
874
|
+
useGetContentTypeConfigurationQuery,
|
875
|
+
useGetAllContentTypeSettingsQuery,
|
876
|
+
useUpdateContentTypeConfigurationMutation
|
877
|
+
} = contentTypesApi;
|
878
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
879
|
+
const { type } = attribute;
|
880
|
+
if (type === "relation") {
|
881
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
882
|
+
}
|
883
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
884
|
+
};
|
885
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
886
|
+
if (!mainFieldName) {
|
887
|
+
return void 0;
|
888
|
+
}
|
889
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
890
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
891
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
892
|
+
);
|
893
|
+
return {
|
894
|
+
name: mainFieldName,
|
895
|
+
type: mainFieldType ?? "string"
|
896
|
+
};
|
897
|
+
};
|
898
|
+
const DEFAULT_SETTINGS = {
|
899
|
+
bulkable: false,
|
900
|
+
filterable: false,
|
901
|
+
searchable: false,
|
902
|
+
pagination: false,
|
903
|
+
defaultSortBy: "",
|
904
|
+
defaultSortOrder: "asc",
|
905
|
+
mainField: "id",
|
906
|
+
pageSize: 10
|
907
|
+
};
|
908
|
+
const useDocumentLayout = (model) => {
|
909
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
910
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
911
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
912
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
913
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
914
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
915
|
+
const {
|
916
|
+
data,
|
917
|
+
isLoading: isLoadingConfigs,
|
918
|
+
error,
|
919
|
+
isFetching: isFetchingConfigs
|
920
|
+
} = useGetContentTypeConfigurationQuery(model);
|
921
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
922
|
+
React__namespace.useEffect(() => {
|
923
|
+
if (error) {
|
924
|
+
toggleNotification({
|
925
|
+
type: "danger",
|
926
|
+
message: formatAPIError(error)
|
927
|
+
});
|
928
|
+
}
|
929
|
+
}, [error, formatAPIError, toggleNotification]);
|
930
|
+
const editLayout = React__namespace.useMemo(
|
931
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
932
|
+
layout: [],
|
933
|
+
components: {},
|
934
|
+
metadatas: {},
|
935
|
+
options: {},
|
936
|
+
settings: DEFAULT_SETTINGS
|
937
|
+
},
|
938
|
+
[data, isLoading, schemas, schema, components]
|
939
|
+
);
|
940
|
+
const listLayout = React__namespace.useMemo(() => {
|
941
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
942
|
+
layout: [],
|
943
|
+
metadatas: {},
|
944
|
+
options: {},
|
945
|
+
settings: DEFAULT_SETTINGS
|
946
|
+
};
|
947
|
+
}, [data, isLoading, schemas, schema, components]);
|
948
|
+
const { layout: edit } = React__namespace.useMemo(
|
949
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
950
|
+
layout: editLayout,
|
951
|
+
query
|
952
|
+
}),
|
953
|
+
[editLayout, query, runHookWaterfall]
|
954
|
+
);
|
955
|
+
return {
|
956
|
+
error,
|
957
|
+
isLoading,
|
958
|
+
edit,
|
959
|
+
list: listLayout
|
960
|
+
};
|
961
|
+
};
|
962
|
+
const useDocLayout = () => {
|
963
|
+
const { model } = useDoc();
|
964
|
+
return useDocumentLayout(model);
|
965
|
+
};
|
966
|
+
const formatEditLayout = (data, {
|
967
|
+
schemas,
|
968
|
+
schema,
|
969
|
+
components
|
970
|
+
}) => {
|
971
|
+
let currentPanelIndex = 0;
|
972
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
973
|
+
data.contentType.layouts.edit,
|
974
|
+
schema?.attributes,
|
975
|
+
data.contentType.metadatas,
|
976
|
+
{ configurations: data.components, schemas: components },
|
977
|
+
schemas
|
978
|
+
).reduce((panels, row) => {
|
979
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
980
|
+
panels.push([row]);
|
981
|
+
currentPanelIndex += 2;
|
982
|
+
} else {
|
983
|
+
if (!panels[currentPanelIndex]) {
|
984
|
+
panels.push([]);
|
985
|
+
}
|
986
|
+
panels[currentPanelIndex].push(row);
|
987
|
+
}
|
988
|
+
return panels;
|
989
|
+
}, []);
|
990
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
991
|
+
(acc, [uid, configuration]) => {
|
992
|
+
acc[uid] = {
|
993
|
+
layout: convertEditLayoutToFieldLayouts(
|
994
|
+
configuration.layouts.edit,
|
995
|
+
components[uid].attributes,
|
996
|
+
configuration.metadatas,
|
997
|
+
{ configurations: data.components, schemas: components }
|
998
|
+
),
|
999
|
+
settings: {
|
1000
|
+
...configuration.settings,
|
1001
|
+
icon: components[uid].info.icon,
|
1002
|
+
displayName: components[uid].info.displayName
|
1003
|
+
}
|
1004
|
+
};
|
1005
|
+
return acc;
|
1006
|
+
},
|
1007
|
+
{}
|
1008
|
+
);
|
1009
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1010
|
+
(acc, [attribute, metadata]) => {
|
1011
|
+
return {
|
1012
|
+
...acc,
|
1013
|
+
[attribute]: metadata.edit
|
1014
|
+
};
|
1015
|
+
},
|
1016
|
+
{}
|
1017
|
+
);
|
1018
|
+
return {
|
1019
|
+
layout: panelledEditAttributes,
|
1020
|
+
components: componentEditAttributes,
|
1021
|
+
metadatas: editMetadatas,
|
1022
|
+
settings: {
|
1023
|
+
...data.contentType.settings,
|
1024
|
+
displayName: schema?.info.displayName
|
1025
|
+
},
|
1026
|
+
options: {
|
1027
|
+
...schema?.options,
|
1028
|
+
...schema?.pluginOptions,
|
1029
|
+
...data.contentType.options
|
1030
|
+
}
|
1031
|
+
};
|
1032
|
+
};
|
1033
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1034
|
+
return rows.map(
|
1035
|
+
(row) => row.map((field) => {
|
1036
|
+
const attribute = attributes[field.name];
|
1037
|
+
if (!attribute) {
|
1038
|
+
return null;
|
1039
|
+
}
|
1040
|
+
const { edit: metadata } = metadatas[field.name];
|
1041
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1042
|
+
return {
|
1043
|
+
attribute,
|
1044
|
+
disabled: !metadata.editable,
|
1045
|
+
hint: metadata.description,
|
1046
|
+
label: metadata.label ?? "",
|
1047
|
+
name: field.name,
|
1048
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1049
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1050
|
+
schemas,
|
1051
|
+
components: components?.schemas ?? {}
|
1052
|
+
}),
|
1053
|
+
placeholder: metadata.placeholder ?? "",
|
1054
|
+
required: attribute.required ?? false,
|
1055
|
+
size: field.size,
|
1056
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1057
|
+
visible: metadata.visible ?? true,
|
1058
|
+
type: attribute.type
|
1059
|
+
};
|
1060
|
+
}).filter((field) => field !== null)
|
1061
|
+
);
|
1062
|
+
};
|
1063
|
+
const formatListLayout = (data, {
|
1064
|
+
schemas,
|
1065
|
+
schema,
|
1066
|
+
components
|
1067
|
+
}) => {
|
1068
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1069
|
+
(acc, [attribute, metadata]) => {
|
1070
|
+
return {
|
1071
|
+
...acc,
|
1072
|
+
[attribute]: metadata.list
|
1073
|
+
};
|
1074
|
+
},
|
1075
|
+
{}
|
1076
|
+
);
|
1077
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1078
|
+
data.contentType.layouts.list,
|
1079
|
+
schema?.attributes,
|
1080
|
+
listMetadatas,
|
1081
|
+
{ configurations: data.components, schemas: components },
|
1082
|
+
schemas
|
1083
|
+
);
|
1084
|
+
return {
|
1085
|
+
layout: listAttributes,
|
1086
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1087
|
+
metadatas: listMetadatas,
|
1088
|
+
options: {
|
1089
|
+
...schema?.options,
|
1090
|
+
...schema?.pluginOptions,
|
1091
|
+
...data.contentType.options
|
1092
|
+
}
|
1093
|
+
};
|
1094
|
+
};
|
1095
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1096
|
+
return columns.map((name) => {
|
1097
|
+
const attribute = attributes[name];
|
1098
|
+
if (!attribute) {
|
1099
|
+
return null;
|
1100
|
+
}
|
1101
|
+
const metadata = metadatas[name];
|
1102
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1103
|
+
return {
|
1104
|
+
attribute,
|
1105
|
+
label: metadata.label ?? "",
|
1106
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1107
|
+
schemas,
|
1108
|
+
components: components?.schemas ?? {}
|
1109
|
+
}),
|
1110
|
+
name,
|
1111
|
+
searchable: metadata.searchable ?? true,
|
1112
|
+
sortable: metadata.sortable ?? true
|
1113
|
+
};
|
1114
|
+
}).filter((field) => field !== null);
|
1115
|
+
};
|
1116
|
+
const useDocument = (args, opts) => {
|
1117
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1118
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1119
|
+
const {
|
1120
|
+
currentData: data,
|
1121
|
+
isLoading: isLoadingDocument,
|
1122
|
+
isFetching: isFetchingDocument,
|
1123
|
+
error
|
1124
|
+
} = useGetDocumentQuery(args, {
|
1125
|
+
...opts,
|
1126
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1127
|
+
});
|
1128
|
+
const {
|
1129
|
+
components,
|
1130
|
+
schema,
|
1131
|
+
schemas,
|
1132
|
+
isLoading: isLoadingSchema
|
1133
|
+
} = useContentTypeSchema(args.model);
|
1134
|
+
React__namespace.useEffect(() => {
|
1135
|
+
if (error) {
|
1136
|
+
toggleNotification({
|
1137
|
+
type: "danger",
|
1138
|
+
message: formatAPIError(error)
|
1139
|
+
});
|
1140
|
+
}
|
1141
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1142
|
+
const validationSchema = React__namespace.useMemo(() => {
|
1143
|
+
if (!schema) {
|
1144
|
+
return null;
|
1145
|
+
}
|
1146
|
+
return createYupSchema(schema.attributes, components);
|
1147
|
+
}, [schema, components]);
|
1148
|
+
const validate = React__namespace.useCallback(
|
1149
|
+
(document) => {
|
1150
|
+
if (!validationSchema) {
|
1151
|
+
throw new Error(
|
1152
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1153
|
+
);
|
1154
|
+
}
|
1155
|
+
try {
|
1156
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1157
|
+
return null;
|
1158
|
+
} catch (error2) {
|
1159
|
+
if (error2 instanceof yup.ValidationError) {
|
1160
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
1161
|
+
}
|
1162
|
+
throw error2;
|
1163
|
+
}
|
1164
|
+
},
|
1165
|
+
[validationSchema]
|
1166
|
+
);
|
1167
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1168
|
+
return {
|
1169
|
+
components,
|
1170
|
+
document: data?.data,
|
1171
|
+
meta: data?.meta,
|
1172
|
+
isLoading,
|
1173
|
+
schema,
|
1174
|
+
schemas,
|
1175
|
+
validate
|
1176
|
+
};
|
1177
|
+
};
|
1178
|
+
const useDoc = () => {
|
1179
|
+
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
1180
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
1181
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1182
|
+
if (!collectionType) {
|
1183
|
+
throw new Error("Could not find collectionType in url params");
|
1184
|
+
}
|
1185
|
+
if (!slug) {
|
1186
|
+
throw new Error("Could not find model in url params");
|
1187
|
+
}
|
1188
|
+
return {
|
1189
|
+
collectionType,
|
1190
|
+
model: slug,
|
1191
|
+
id: origin || id === "create" ? void 0 : id,
|
1192
|
+
...useDocument(
|
1193
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1194
|
+
{
|
1195
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1196
|
+
}
|
1197
|
+
)
|
1198
|
+
};
|
1199
|
+
};
|
1200
|
+
const useContentManagerContext = () => {
|
1201
|
+
const {
|
1202
|
+
collectionType,
|
1203
|
+
model,
|
1204
|
+
id,
|
1205
|
+
components,
|
1206
|
+
isLoading: isLoadingDoc,
|
1207
|
+
schema,
|
1208
|
+
schemas
|
1209
|
+
} = useDoc();
|
1210
|
+
const layout = useDocumentLayout(model);
|
1211
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1212
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1213
|
+
const slug = model;
|
1214
|
+
const isCreatingEntry = id === "create";
|
1215
|
+
useContentTypeSchema();
|
1216
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1217
|
+
const error = layout.error;
|
1218
|
+
return {
|
1219
|
+
error,
|
1220
|
+
isLoading,
|
1221
|
+
// Base metadata
|
1222
|
+
model,
|
1223
|
+
collectionType,
|
1224
|
+
id,
|
1225
|
+
slug,
|
1226
|
+
isCreatingEntry,
|
1227
|
+
isSingleType,
|
1228
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1229
|
+
// All schema infos
|
1230
|
+
components,
|
1231
|
+
contentType: schema,
|
1232
|
+
contentTypes: schemas,
|
1233
|
+
// Form state
|
1234
|
+
form,
|
1235
|
+
// layout infos
|
1236
|
+
layout
|
1237
|
+
};
|
1238
|
+
};
|
1239
|
+
const prefixPluginTranslations = (trad, pluginId) => {
|
1240
|
+
if (!pluginId) {
|
906
1241
|
throw new TypeError("pluginId can't be empty");
|
907
1242
|
}
|
908
1243
|
return Object.keys(trad).reduce((acc, current) => {
|
@@ -920,6 +1255,8 @@ const useDocumentActions = () => {
|
|
920
1255
|
const { formatMessage } = reactIntl.useIntl();
|
921
1256
|
const { trackUsage } = strapiAdmin.useTracking();
|
922
1257
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1258
|
+
const navigate = reactRouterDom.useNavigate();
|
1259
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
923
1260
|
const [deleteDocument] = useDeleteDocumentMutation();
|
924
1261
|
const _delete = React__namespace.useCallback(
|
925
1262
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -958,14 +1295,53 @@ const useDocumentActions = () => {
|
|
958
1295
|
},
|
959
1296
|
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
960
1297
|
);
|
1298
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1299
|
+
const deleteMany = React__namespace.useCallback(
|
1300
|
+
async ({ model, documentIds, params }) => {
|
1301
|
+
try {
|
1302
|
+
trackUsage("willBulkDeleteEntries");
|
1303
|
+
const res = await deleteManyDocuments({
|
1304
|
+
model,
|
1305
|
+
documentIds,
|
1306
|
+
params
|
1307
|
+
});
|
1308
|
+
if ("error" in res) {
|
1309
|
+
toggleNotification({
|
1310
|
+
type: "danger",
|
1311
|
+
message: formatAPIError(res.error)
|
1312
|
+
});
|
1313
|
+
return { error: res.error };
|
1314
|
+
}
|
1315
|
+
toggleNotification({
|
1316
|
+
type: "success",
|
1317
|
+
title: formatMessage({
|
1318
|
+
id: getTranslation("success.records.delete"),
|
1319
|
+
defaultMessage: "Successfully deleted."
|
1320
|
+
}),
|
1321
|
+
message: ""
|
1322
|
+
});
|
1323
|
+
trackUsage("didBulkDeleteEntries");
|
1324
|
+
return res.data;
|
1325
|
+
} catch (err) {
|
1326
|
+
toggleNotification({
|
1327
|
+
type: "danger",
|
1328
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1329
|
+
});
|
1330
|
+
trackUsage("didNotBulkDeleteEntries");
|
1331
|
+
throw err;
|
1332
|
+
}
|
1333
|
+
},
|
1334
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1335
|
+
);
|
961
1336
|
const [discardDocument] = useDiscardDocumentMutation();
|
962
1337
|
const discard = React__namespace.useCallback(
|
963
|
-
async ({ collectionType, model, documentId }) => {
|
1338
|
+
async ({ collectionType, model, documentId, params }) => {
|
964
1339
|
try {
|
965
1340
|
const res = await discardDocument({
|
966
1341
|
collectionType,
|
967
1342
|
model,
|
968
|
-
documentId
|
1343
|
+
documentId,
|
1344
|
+
params
|
969
1345
|
});
|
970
1346
|
if ("error" in res) {
|
971
1347
|
toggleNotification({
|
@@ -1027,6 +1403,43 @@ const useDocumentActions = () => {
|
|
1027
1403
|
},
|
1028
1404
|
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1029
1405
|
);
|
1406
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1407
|
+
const publishMany = React__namespace.useCallback(
|
1408
|
+
async ({ model, documentIds, params }) => {
|
1409
|
+
try {
|
1410
|
+
const res = await publishManyDocuments({
|
1411
|
+
model,
|
1412
|
+
documentIds,
|
1413
|
+
params
|
1414
|
+
});
|
1415
|
+
if ("error" in res) {
|
1416
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1417
|
+
return { error: res.error };
|
1418
|
+
}
|
1419
|
+
toggleNotification({
|
1420
|
+
type: "success",
|
1421
|
+
message: formatMessage({
|
1422
|
+
id: getTranslation("success.record.publish"),
|
1423
|
+
defaultMessage: "Published document"
|
1424
|
+
})
|
1425
|
+
});
|
1426
|
+
return res.data;
|
1427
|
+
} catch (err) {
|
1428
|
+
toggleNotification({
|
1429
|
+
type: "danger",
|
1430
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1431
|
+
});
|
1432
|
+
throw err;
|
1433
|
+
}
|
1434
|
+
},
|
1435
|
+
[
|
1436
|
+
// trackUsage,
|
1437
|
+
publishManyDocuments,
|
1438
|
+
toggleNotification,
|
1439
|
+
formatMessage,
|
1440
|
+
formatAPIError
|
1441
|
+
]
|
1442
|
+
);
|
1030
1443
|
const [updateDocument] = useUpdateDocumentMutation();
|
1031
1444
|
const update = React__namespace.useCallback(
|
1032
1445
|
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
@@ -1101,6 +1514,41 @@ const useDocumentActions = () => {
|
|
1101
1514
|
},
|
1102
1515
|
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1103
1516
|
);
|
1517
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1518
|
+
const unpublishMany = React__namespace.useCallback(
|
1519
|
+
async ({ model, documentIds, params }) => {
|
1520
|
+
try {
|
1521
|
+
trackUsage("willBulkUnpublishEntries");
|
1522
|
+
const res = await unpublishManyDocuments({
|
1523
|
+
model,
|
1524
|
+
documentIds,
|
1525
|
+
params
|
1526
|
+
});
|
1527
|
+
if ("error" in res) {
|
1528
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1529
|
+
return { error: res.error };
|
1530
|
+
}
|
1531
|
+
trackUsage("didBulkUnpublishEntries");
|
1532
|
+
toggleNotification({
|
1533
|
+
type: "success",
|
1534
|
+
title: formatMessage({
|
1535
|
+
id: getTranslation("success.records.unpublish"),
|
1536
|
+
defaultMessage: "Successfully unpublished."
|
1537
|
+
}),
|
1538
|
+
message: ""
|
1539
|
+
});
|
1540
|
+
return res.data;
|
1541
|
+
} catch (err) {
|
1542
|
+
toggleNotification({
|
1543
|
+
type: "danger",
|
1544
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1545
|
+
});
|
1546
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1547
|
+
throw err;
|
1548
|
+
}
|
1549
|
+
},
|
1550
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1551
|
+
);
|
1104
1552
|
const [createDocument] = useCreateDocumentMutation();
|
1105
1553
|
const create = React__namespace.useCallback(
|
1106
1554
|
async ({ model, params }, data, trackerProperty) => {
|
@@ -1123,6 +1571,7 @@ const useDocumentActions = () => {
|
|
1123
1571
|
defaultMessage: "Saved document"
|
1124
1572
|
})
|
1125
1573
|
});
|
1574
|
+
setCurrentStep("contentManager.success");
|
1126
1575
|
return res.data;
|
1127
1576
|
} catch (err) {
|
1128
1577
|
toggleNotification({
|
@@ -1144,7 +1593,6 @@ const useDocumentActions = () => {
|
|
1144
1593
|
sourceId
|
1145
1594
|
});
|
1146
1595
|
if ("error" in res) {
|
1147
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1148
1596
|
return { error: res.error };
|
1149
1597
|
}
|
1150
1598
|
toggleNotification({
|
@@ -1163,7 +1611,7 @@ const useDocumentActions = () => {
|
|
1163
1611
|
throw err;
|
1164
1612
|
}
|
1165
1613
|
},
|
1166
|
-
[autoCloneDocument,
|
1614
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1167
1615
|
);
|
1168
1616
|
const [cloneDocument] = useCloneDocumentMutation();
|
1169
1617
|
const clone = React__namespace.useCallback(
|
@@ -1189,6 +1637,7 @@ const useDocumentActions = () => {
|
|
1189
1637
|
defaultMessage: "Cloned document"
|
1190
1638
|
})
|
1191
1639
|
});
|
1640
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1192
1641
|
return res.data;
|
1193
1642
|
} catch (err) {
|
1194
1643
|
toggleNotification({
|
@@ -1199,7 +1648,7 @@ const useDocumentActions = () => {
|
|
1199
1648
|
throw err;
|
1200
1649
|
}
|
1201
1650
|
},
|
1202
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1651
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1203
1652
|
);
|
1204
1653
|
const [getDoc] = useLazyGetDocumentQuery();
|
1205
1654
|
const getDocument = React__namespace.useCallback(
|
@@ -1214,15 +1663,18 @@ const useDocumentActions = () => {
|
|
1214
1663
|
clone,
|
1215
1664
|
create,
|
1216
1665
|
delete: _delete,
|
1666
|
+
deleteMany,
|
1217
1667
|
discard,
|
1218
1668
|
getDocument,
|
1219
1669
|
publish,
|
1670
|
+
publishMany,
|
1220
1671
|
unpublish,
|
1672
|
+
unpublishMany,
|
1221
1673
|
update
|
1222
1674
|
};
|
1223
1675
|
};
|
1224
1676
|
const ProtectedHistoryPage = React.lazy(
|
1225
|
-
() => Promise.resolve().then(() => require("./History-
|
1677
|
+
() => Promise.resolve().then(() => require("./History-CWcM9HnW.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1226
1678
|
);
|
1227
1679
|
const routes$1 = [
|
1228
1680
|
{
|
@@ -1235,31 +1687,31 @@ const routes$1 = [
|
|
1235
1687
|
}
|
1236
1688
|
];
|
1237
1689
|
const ProtectedEditViewPage = React.lazy(
|
1238
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1690
|
+
() => Promise.resolve().then(() => require("./EditViewPage-Co2IKQZH.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1239
1691
|
);
|
1240
1692
|
const ProtectedListViewPage = React.lazy(
|
1241
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1693
|
+
() => Promise.resolve().then(() => require("./ListViewPage-BBAC9aPu.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1242
1694
|
);
|
1243
1695
|
const ProtectedListConfiguration = React.lazy(
|
1244
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1696
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-DGzoQD_I.js")).then((mod) => ({
|
1245
1697
|
default: mod.ProtectedListConfiguration
|
1246
1698
|
}))
|
1247
1699
|
);
|
1248
1700
|
const ProtectedEditConfigurationPage = React.lazy(
|
1249
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1701
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-ZN3s568V.js")).then((mod) => ({
|
1250
1702
|
default: mod.ProtectedEditConfigurationPage
|
1251
1703
|
}))
|
1252
1704
|
);
|
1253
1705
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1254
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1706
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-_6osrv39.js")).then((mod) => ({
|
1255
1707
|
default: mod.ProtectedComponentConfigurationPage
|
1256
1708
|
}))
|
1257
1709
|
);
|
1258
1710
|
const NoPermissions = React.lazy(
|
1259
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1711
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-D2iWw-sn.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1260
1712
|
);
|
1261
1713
|
const NoContentType = React.lazy(
|
1262
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1714
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-CwVDx_YC.js")).then((mod) => ({ default: mod.NoContentType }))
|
1263
1715
|
);
|
1264
1716
|
const CollectionTypePages = () => {
|
1265
1717
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1373,12 +1825,14 @@ const DocumentActionButton = (action) => {
|
|
1373
1825
|
/* @__PURE__ */ jsxRuntime.jsx(
|
1374
1826
|
designSystem.Button,
|
1375
1827
|
{
|
1376
|
-
flex:
|
1828
|
+
flex: "auto",
|
1377
1829
|
startIcon: action.icon,
|
1378
1830
|
disabled: action.disabled,
|
1379
1831
|
onClick: handleClick(action),
|
1380
1832
|
justifyContent: "center",
|
1381
1833
|
variant: action.variant || "default",
|
1834
|
+
paddingTop: "7px",
|
1835
|
+
paddingBottom: "7px",
|
1382
1836
|
children: action.label
|
1383
1837
|
}
|
1384
1838
|
),
|
@@ -1386,7 +1840,7 @@ const DocumentActionButton = (action) => {
|
|
1386
1840
|
DocumentActionConfirmDialog,
|
1387
1841
|
{
|
1388
1842
|
...action.dialog,
|
1389
|
-
variant: action.variant,
|
1843
|
+
variant: action.dialog?.variant ?? action.variant,
|
1390
1844
|
isOpen: dialogId === action.id,
|
1391
1845
|
onClose: handleClose
|
1392
1846
|
}
|
@@ -1443,20 +1897,20 @@ const DocumentActionsMenu = ({
|
|
1443
1897
|
disabled: isDisabled,
|
1444
1898
|
size: "S",
|
1445
1899
|
endIcon: null,
|
1446
|
-
paddingTop: "
|
1447
|
-
paddingLeft: "
|
1448
|
-
paddingRight: "
|
1900
|
+
paddingTop: "4px",
|
1901
|
+
paddingLeft: "7px",
|
1902
|
+
paddingRight: "7px",
|
1449
1903
|
variant,
|
1450
1904
|
children: [
|
1451
1905
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
1452
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, {
|
1906
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1453
1907
|
id: "content-manager.containers.edit.panels.default.more-actions",
|
1454
1908
|
defaultMessage: "More document actions"
|
1455
1909
|
}) })
|
1456
1910
|
]
|
1457
1911
|
}
|
1458
1912
|
),
|
1459
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, {
|
1913
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1460
1914
|
actions2.map((action) => {
|
1461
1915
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
1462
1916
|
designSystem.Menu.Item,
|
@@ -1465,10 +1919,25 @@ const DocumentActionsMenu = ({
|
|
1465
1919
|
onSelect: handleClick(action),
|
1466
1920
|
display: "block",
|
1467
1921
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1468
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1922
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1923
|
+
designSystem.Flex,
|
1924
|
+
{
|
1925
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1926
|
+
gap: 2,
|
1927
|
+
tag: "span",
|
1928
|
+
children: [
|
1929
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1930
|
+
designSystem.Flex,
|
1931
|
+
{
|
1932
|
+
tag: "span",
|
1933
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1934
|
+
children: action.icon
|
1935
|
+
}
|
1936
|
+
),
|
1937
|
+
action.label
|
1938
|
+
]
|
1939
|
+
}
|
1940
|
+
),
|
1472
1941
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1473
1942
|
designSystem.Flex,
|
1474
1943
|
{
|
@@ -1527,6 +1996,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1527
1996
|
return "primary600";
|
1528
1997
|
}
|
1529
1998
|
};
|
1999
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
2000
|
+
switch (variant) {
|
2001
|
+
case "danger":
|
2002
|
+
return "danger600";
|
2003
|
+
case "secondary":
|
2004
|
+
return "neutral500";
|
2005
|
+
case "success":
|
2006
|
+
return "success600";
|
2007
|
+
default:
|
2008
|
+
return "primary600";
|
2009
|
+
}
|
2010
|
+
};
|
1530
2011
|
const DocumentActionConfirmDialog = ({
|
1531
2012
|
onClose,
|
1532
2013
|
onCancel,
|
@@ -1549,61 +2030,42 @@ const DocumentActionConfirmDialog = ({
|
|
1549
2030
|
}
|
1550
2031
|
onClose();
|
1551
2032
|
};
|
1552
|
-
return /* @__PURE__ */ jsxRuntime.
|
1553
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1554
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1555
|
-
|
1556
|
-
{
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
)
|
1567
|
-
] });
|
2033
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2034
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2035
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
2036
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
2037
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
2038
|
+
id: "app.components.Button.cancel",
|
2039
|
+
defaultMessage: "Cancel"
|
2040
|
+
}) }) }),
|
2041
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
2042
|
+
id: "app.components.Button.confirm",
|
2043
|
+
defaultMessage: "Confirm"
|
2044
|
+
}) })
|
2045
|
+
] })
|
2046
|
+
] }) });
|
1568
2047
|
};
|
1569
2048
|
const DocumentActionModal = ({
|
1570
2049
|
isOpen,
|
1571
2050
|
title,
|
1572
2051
|
onClose,
|
1573
2052
|
footer: Footer,
|
1574
|
-
content,
|
2053
|
+
content: Content,
|
1575
2054
|
onModalClose
|
1576
2055
|
}) => {
|
1577
|
-
const id = React__namespace.useId();
|
1578
|
-
if (!isOpen) {
|
1579
|
-
return null;
|
1580
|
-
}
|
1581
2056
|
const handleClose = () => {
|
1582
2057
|
if (onClose) {
|
1583
2058
|
onClose();
|
1584
2059
|
}
|
1585
2060
|
onModalClose();
|
1586
2061
|
};
|
1587
|
-
return /* @__PURE__ */ jsxRuntime.
|
1588
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1589
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1590
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1591
|
-
|
1592
|
-
{
|
1593
|
-
paddingTop: 4,
|
1594
|
-
paddingBottom: 4,
|
1595
|
-
paddingLeft: 5,
|
1596
|
-
paddingRight: 5,
|
1597
|
-
borderWidth: "1px 0 0 0",
|
1598
|
-
borderStyle: "solid",
|
1599
|
-
borderColor: "neutral150",
|
1600
|
-
background: "neutral100",
|
1601
|
-
children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
1602
|
-
}
|
1603
|
-
)
|
1604
|
-
] });
|
2062
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
2063
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
2064
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
|
2065
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
2066
|
+
] }) });
|
1605
2067
|
};
|
1606
|
-
const PublishAction = ({
|
2068
|
+
const PublishAction$1 = ({
|
1607
2069
|
activeTab,
|
1608
2070
|
documentId,
|
1609
2071
|
model,
|
@@ -1615,13 +2077,17 @@ const PublishAction = ({
|
|
1615
2077
|
const navigate = reactRouterDom.useNavigate();
|
1616
2078
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1617
2079
|
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2080
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
1618
2081
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
1619
2082
|
const { formatMessage } = reactIntl.useIntl();
|
1620
|
-
const { canPublish
|
1621
|
-
"PublishAction",
|
1622
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1623
|
-
);
|
2083
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1624
2084
|
const { publish } = useDocumentActions();
|
2085
|
+
const [
|
2086
|
+
countDraftRelations,
|
2087
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2088
|
+
] = useLazyGetDraftRelationCountQuery();
|
2089
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2090
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1625
2091
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1626
2092
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1627
2093
|
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1630,10 +2096,103 @@ const PublishAction = ({
|
|
1630
2096
|
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1631
2097
|
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1632
2098
|
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
2099
|
+
React__namespace.useEffect(() => {
|
2100
|
+
if (isErrorDraftRelations) {
|
2101
|
+
toggleNotification({
|
2102
|
+
type: "danger",
|
2103
|
+
message: formatMessage({
|
2104
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2105
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2106
|
+
})
|
2107
|
+
});
|
2108
|
+
}
|
2109
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2110
|
+
React__namespace.useEffect(() => {
|
2111
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2112
|
+
const extractDraftRelations = (data) => {
|
2113
|
+
const relations = data.connect || [];
|
2114
|
+
relations.forEach((relation) => {
|
2115
|
+
if (relation.status === "draft") {
|
2116
|
+
localDraftRelations.add(relation.id);
|
2117
|
+
}
|
2118
|
+
});
|
2119
|
+
};
|
2120
|
+
const traverseAndExtract = (data) => {
|
2121
|
+
Object.entries(data).forEach(([key, value]) => {
|
2122
|
+
if (key === "connect" && Array.isArray(value)) {
|
2123
|
+
extractDraftRelations({ connect: value });
|
2124
|
+
} else if (typeof value === "object" && value !== null) {
|
2125
|
+
traverseAndExtract(value);
|
2126
|
+
}
|
2127
|
+
});
|
2128
|
+
};
|
2129
|
+
if (!documentId || modified) {
|
2130
|
+
traverseAndExtract(formValues);
|
2131
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2132
|
+
}
|
2133
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2134
|
+
React__namespace.useEffect(() => {
|
2135
|
+
if (!document || !document.documentId || isListView) {
|
2136
|
+
return;
|
2137
|
+
}
|
2138
|
+
const fetchDraftRelationsCount = async () => {
|
2139
|
+
const { data, error } = await countDraftRelations({
|
2140
|
+
collectionType,
|
2141
|
+
model,
|
2142
|
+
documentId,
|
2143
|
+
params
|
2144
|
+
});
|
2145
|
+
if (error) {
|
2146
|
+
throw error;
|
2147
|
+
}
|
2148
|
+
if (data) {
|
2149
|
+
setServerCountOfDraftRelations(data.data);
|
2150
|
+
}
|
2151
|
+
};
|
2152
|
+
fetchDraftRelationsCount();
|
2153
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
1633
2154
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1634
2155
|
if (!schema?.options?.draftAndPublish) {
|
1635
2156
|
return null;
|
1636
2157
|
}
|
2158
|
+
const performPublish = async () => {
|
2159
|
+
setSubmitting(true);
|
2160
|
+
try {
|
2161
|
+
const { errors } = await validate();
|
2162
|
+
if (errors) {
|
2163
|
+
toggleNotification({
|
2164
|
+
type: "danger",
|
2165
|
+
message: formatMessage({
|
2166
|
+
id: "content-manager.validation.error",
|
2167
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2168
|
+
})
|
2169
|
+
});
|
2170
|
+
return;
|
2171
|
+
}
|
2172
|
+
const res = await publish(
|
2173
|
+
{
|
2174
|
+
collectionType,
|
2175
|
+
model,
|
2176
|
+
documentId,
|
2177
|
+
params
|
2178
|
+
},
|
2179
|
+
formValues
|
2180
|
+
);
|
2181
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2182
|
+
navigate({
|
2183
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2184
|
+
search: rawQuery
|
2185
|
+
});
|
2186
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2187
|
+
setErrors(formatValidationErrors(res.error));
|
2188
|
+
}
|
2189
|
+
} finally {
|
2190
|
+
setSubmitting(false);
|
2191
|
+
}
|
2192
|
+
};
|
2193
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2194
|
+
const enableDraftRelationsCount = false;
|
2195
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1637
2196
|
return {
|
1638
2197
|
/**
|
1639
2198
|
* Disabled when:
|
@@ -1643,52 +2202,39 @@ const PublishAction = ({
|
|
1643
2202
|
* - the document is already published & not modified
|
1644
2203
|
* - the document is being created & not modified
|
1645
2204
|
* - the user doesn't have the permission to publish
|
1646
|
-
* - the user doesn't have the permission to create a new document
|
1647
|
-
* - the user doesn't have the permission to update the document
|
1648
2205
|
*/
|
1649
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2206
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1650
2207
|
label: formatMessage({
|
1651
2208
|
id: "app.utils.publish",
|
1652
2209
|
defaultMessage: "Publish"
|
1653
2210
|
}),
|
1654
2211
|
onClick: async () => {
|
1655
|
-
|
1656
|
-
|
1657
|
-
|
1658
|
-
|
1659
|
-
|
1660
|
-
|
1661
|
-
|
1662
|
-
|
1663
|
-
|
1664
|
-
|
1665
|
-
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
1672
|
-
documentId,
|
1673
|
-
params
|
1674
|
-
},
|
1675
|
-
formValues
|
1676
|
-
);
|
1677
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1678
|
-
navigate({
|
1679
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1680
|
-
search: rawQuery
|
1681
|
-
});
|
1682
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1683
|
-
setErrors(formatValidationErrors(res.error));
|
2212
|
+
await performPublish();
|
2213
|
+
},
|
2214
|
+
dialog: hasDraftRelations ? {
|
2215
|
+
type: "dialog",
|
2216
|
+
variant: "danger",
|
2217
|
+
footer: null,
|
2218
|
+
title: formatMessage({
|
2219
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2220
|
+
defaultMessage: "Confirmation"
|
2221
|
+
}),
|
2222
|
+
content: formatMessage(
|
2223
|
+
{
|
2224
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2225
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2226
|
+
},
|
2227
|
+
{
|
2228
|
+
count: totalDraftRelations
|
1684
2229
|
}
|
1685
|
-
|
1686
|
-
|
2230
|
+
),
|
2231
|
+
onConfirm: async () => {
|
2232
|
+
await performPublish();
|
1687
2233
|
}
|
1688
|
-
}
|
2234
|
+
} : void 0
|
1689
2235
|
};
|
1690
2236
|
};
|
1691
|
-
PublishAction.type = "publish";
|
2237
|
+
PublishAction$1.type = "publish";
|
1692
2238
|
const UpdateAction = ({
|
1693
2239
|
activeTab,
|
1694
2240
|
documentId,
|
@@ -1701,10 +2247,6 @@ const UpdateAction = ({
|
|
1701
2247
|
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
1702
2248
|
const isCloning = cloneMatch !== null;
|
1703
2249
|
const { formatMessage } = reactIntl.useIntl();
|
1704
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1705
|
-
canCreate: canCreate2,
|
1706
|
-
canUpdate: canUpdate2
|
1707
|
-
}));
|
1708
2250
|
const { create, update, clone } = useDocumentActions();
|
1709
2251
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1710
2252
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
@@ -1721,10 +2263,8 @@ const UpdateAction = ({
|
|
1721
2263
|
* - the form is submitting
|
1722
2264
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1723
2265
|
* - the active tab is the published tab
|
1724
|
-
* - the user doesn't have the permission to create a new document
|
1725
|
-
* - the user doesn't have the permission to update the document
|
1726
2266
|
*/
|
1727
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2267
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1728
2268
|
label: formatMessage({
|
1729
2269
|
id: "content-manager.containers.Edit.save",
|
1730
2270
|
defaultMessage: "Save"
|
@@ -1732,16 +2272,18 @@ const UpdateAction = ({
|
|
1732
2272
|
onClick: async () => {
|
1733
2273
|
setSubmitting(true);
|
1734
2274
|
try {
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
2275
|
+
if (activeTab !== "draft") {
|
2276
|
+
const { errors } = await validate();
|
2277
|
+
if (errors) {
|
2278
|
+
toggleNotification({
|
2279
|
+
type: "danger",
|
2280
|
+
message: formatMessage({
|
2281
|
+
id: "content-manager.validation.error",
|
2282
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2283
|
+
})
|
2284
|
+
});
|
2285
|
+
return;
|
2286
|
+
}
|
1745
2287
|
}
|
1746
2288
|
if (isCloning) {
|
1747
2289
|
const res = await clone(
|
@@ -1753,10 +2295,13 @@ const UpdateAction = ({
|
|
1753
2295
|
document
|
1754
2296
|
);
|
1755
2297
|
if ("data" in res) {
|
1756
|
-
navigate(
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
2298
|
+
navigate(
|
2299
|
+
{
|
2300
|
+
pathname: `../${res.data.documentId}`,
|
2301
|
+
search: rawQuery
|
2302
|
+
},
|
2303
|
+
{ relative: "path" }
|
2304
|
+
);
|
1760
2305
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1761
2306
|
setErrors(formatValidationErrors(res.error));
|
1762
2307
|
}
|
@@ -1784,10 +2329,13 @@ const UpdateAction = ({
|
|
1784
2329
|
document
|
1785
2330
|
);
|
1786
2331
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1787
|
-
navigate(
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
2332
|
+
navigate(
|
2333
|
+
{
|
2334
|
+
pathname: `../${res.data.documentId}`,
|
2335
|
+
search: rawQuery
|
2336
|
+
},
|
2337
|
+
{ replace: true, relative: "path" }
|
2338
|
+
);
|
1791
2339
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1792
2340
|
setErrors(formatValidationErrors(res.error));
|
1793
2341
|
}
|
@@ -1803,7 +2351,7 @@ const UNPUBLISH_DRAFT_OPTIONS = {
|
|
1803
2351
|
KEEP: "keep",
|
1804
2352
|
DISCARD: "discard"
|
1805
2353
|
};
|
1806
|
-
const UnpublishAction = ({
|
2354
|
+
const UnpublishAction$1 = ({
|
1807
2355
|
activeTab,
|
1808
2356
|
documentId,
|
1809
2357
|
model,
|
@@ -1819,10 +2367,8 @@ const UnpublishAction = ({
|
|
1819
2367
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1820
2368
|
const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
|
1821
2369
|
const isDocumentModified = document?.status === "modified";
|
1822
|
-
const handleChange = (
|
1823
|
-
|
1824
|
-
setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1825
|
-
}
|
2370
|
+
const handleChange = (value) => {
|
2371
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1826
2372
|
};
|
1827
2373
|
if (!schema?.options?.draftAndPublish) {
|
1828
2374
|
return null;
|
@@ -1833,7 +2379,7 @@ const UnpublishAction = ({
|
|
1833
2379
|
id: "app.utils.unpublish",
|
1834
2380
|
defaultMessage: "Unpublish"
|
1835
2381
|
}),
|
1836
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2382
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1837
2383
|
onClick: async () => {
|
1838
2384
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1839
2385
|
if (!documentId) {
|
@@ -1866,45 +2412,30 @@ const UnpublishAction = ({
|
|
1866
2412
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
|
1867
2413
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
|
1868
2414
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
1869
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2415
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
1870
2416
|
id: "content-manager.actions.unpublish.dialog.body",
|
1871
2417
|
defaultMessage: "Are you sure?"
|
1872
2418
|
}) })
|
1873
2419
|
] }),
|
1874
2420
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
1875
|
-
designSystem.
|
2421
|
+
designSystem.Radio.Group,
|
1876
2422
|
{
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
2423
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2424
|
+
name: "discard-options",
|
2425
|
+
"aria-label": formatMessage({
|
2426
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2427
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2428
|
+
}),
|
2429
|
+
onValueChange: handleChange,
|
1882
2430
|
children: [
|
1883
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
1890
|
-
|
1891
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
1892
|
-
defaultMessage: "Keep draft"
|
1893
|
-
})
|
1894
|
-
}
|
1895
|
-
),
|
1896
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1897
|
-
designSystem.Radio,
|
1898
|
-
{
|
1899
|
-
checked: !shouldKeepDraft,
|
1900
|
-
value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
|
1901
|
-
name: "discard-options",
|
1902
|
-
children: formatMessage({
|
1903
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
1904
|
-
defaultMessage: "Replace draft"
|
1905
|
-
})
|
1906
|
-
}
|
1907
|
-
)
|
2431
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2432
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2433
|
+
defaultMessage: "Keep draft"
|
2434
|
+
}) }),
|
2435
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2436
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2437
|
+
defaultMessage: "Replace draft"
|
2438
|
+
}) })
|
1908
2439
|
]
|
1909
2440
|
}
|
1910
2441
|
)
|
@@ -1937,7 +2468,7 @@ const UnpublishAction = ({
|
|
1937
2468
|
position: ["panel", "table-row"]
|
1938
2469
|
};
|
1939
2470
|
};
|
1940
|
-
UnpublishAction.type = "unpublish";
|
2471
|
+
UnpublishAction$1.type = "unpublish";
|
1941
2472
|
const DiscardAction = ({
|
1942
2473
|
activeTab,
|
1943
2474
|
documentId,
|
@@ -1960,7 +2491,7 @@ const DiscardAction = ({
|
|
1960
2491
|
id: "content-manager.actions.discard.label",
|
1961
2492
|
defaultMessage: "Discard changes"
|
1962
2493
|
}),
|
1963
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2494
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1964
2495
|
position: ["panel", "table-row"],
|
1965
2496
|
variant: "danger",
|
1966
2497
|
dialog: {
|
@@ -1971,7 +2502,7 @@ const DiscardAction = ({
|
|
1971
2502
|
}),
|
1972
2503
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
1973
2504
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
1974
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2505
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
1975
2506
|
id: "content-manager.actions.discard.dialog.body",
|
1976
2507
|
defaultMessage: "Are you sure?"
|
1977
2508
|
}) })
|
@@ -1988,12 +2519,7 @@ const DiscardAction = ({
|
|
1988
2519
|
};
|
1989
2520
|
};
|
1990
2521
|
DiscardAction.type = "discard";
|
1991
|
-
const
|
1992
|
-
path {
|
1993
|
-
fill: currentColor;
|
1994
|
-
}
|
1995
|
-
`;
|
1996
|
-
const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction, DiscardAction];
|
2522
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
1997
2523
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
1998
2524
|
const RelativeTime = React__namespace.forwardRef(
|
1999
2525
|
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
@@ -2040,8 +2566,8 @@ const getDisplayName = ({
|
|
2040
2566
|
};
|
2041
2567
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2042
2568
|
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2043
|
-
const statusVariant = status === "draft" ? "
|
2044
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2569
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2570
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Status, { ...restProps, showBullet: false, size: "S", variant: statusVariant, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "span", variant: "omega", fontWeight: "bold", children: capitalise(status) }) });
|
2045
2571
|
};
|
2046
2572
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2047
2573
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2050,23 +2576,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2050
2576
|
id: "content-manager.containers.edit.title.new",
|
2051
2577
|
defaultMessage: "Create an entry"
|
2052
2578
|
}) : documentTitle;
|
2053
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2579
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2054
2580
|
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
2055
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
2056
|
-
designSystem.
|
2057
|
-
{
|
2058
|
-
|
2059
|
-
|
2060
|
-
paddingTop: 1,
|
2061
|
-
gap: "80px",
|
2062
|
-
alignItems: "flex-start",
|
2063
|
-
children: [
|
2064
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", children: title }),
|
2065
|
-
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2066
|
-
]
|
2067
|
-
}
|
2068
|
-
),
|
2069
|
-
status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2581
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2582
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2583
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2584
|
+
] }),
|
2585
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2070
2586
|
] });
|
2071
2587
|
};
|
2072
2588
|
const HeaderToolbar = () => {
|
@@ -2218,7 +2734,7 @@ const Information = ({ activeTab }) => {
|
|
2218
2734
|
borderColor: "neutral150",
|
2219
2735
|
direction: "column",
|
2220
2736
|
marginTop: 2,
|
2221
|
-
|
2737
|
+
tag: "dl",
|
2222
2738
|
padding: 5,
|
2223
2739
|
gap: 3,
|
2224
2740
|
alignItems: "flex-start",
|
@@ -2226,15 +2742,29 @@ const Information = ({ activeTab }) => {
|
|
2226
2742
|
marginRight: "-0.4rem",
|
2227
2743
|
width: "calc(100% + 8px)",
|
2228
2744
|
children: information.map((info) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
|
2229
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2230
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2745
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2746
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2231
2747
|
] }, info.label))
|
2232
2748
|
}
|
2233
2749
|
);
|
2234
2750
|
};
|
2235
2751
|
const HeaderActions = ({ actions: actions2 }) => {
|
2236
|
-
|
2237
|
-
|
2752
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2753
|
+
const handleClick = (action) => async (e) => {
|
2754
|
+
if (!("options" in action)) {
|
2755
|
+
const { onClick = () => false, dialog, id } = action;
|
2756
|
+
const muteDialog = await onClick(e);
|
2757
|
+
if (dialog && !muteDialog) {
|
2758
|
+
e.preventDefault();
|
2759
|
+
setDialogId(id);
|
2760
|
+
}
|
2761
|
+
}
|
2762
|
+
};
|
2763
|
+
const handleClose = () => {
|
2764
|
+
setDialogId(null);
|
2765
|
+
};
|
2766
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2767
|
+
if (action.options) {
|
2238
2768
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2239
2769
|
designSystem.SingleSelect,
|
2240
2770
|
{
|
@@ -2248,10 +2778,49 @@ const HeaderActions = ({ actions: actions2 }) => {
|
|
2248
2778
|
action.id
|
2249
2779
|
);
|
2250
2780
|
} else {
|
2251
|
-
|
2781
|
+
if (action.type === "icon") {
|
2782
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2783
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2784
|
+
designSystem.IconButton,
|
2785
|
+
{
|
2786
|
+
disabled: action.disabled,
|
2787
|
+
label: action.label,
|
2788
|
+
size: "S",
|
2789
|
+
onClick: handleClick(action),
|
2790
|
+
children: action.icon
|
2791
|
+
}
|
2792
|
+
),
|
2793
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2794
|
+
HeaderActionDialog,
|
2795
|
+
{
|
2796
|
+
...action.dialog,
|
2797
|
+
isOpen: dialogId === action.id,
|
2798
|
+
onClose: handleClose
|
2799
|
+
}
|
2800
|
+
) : null
|
2801
|
+
] }, action.id);
|
2802
|
+
}
|
2252
2803
|
}
|
2253
2804
|
}) });
|
2254
2805
|
};
|
2806
|
+
const HeaderActionDialog = ({
|
2807
|
+
onClose,
|
2808
|
+
onCancel,
|
2809
|
+
title,
|
2810
|
+
content: Content,
|
2811
|
+
isOpen
|
2812
|
+
}) => {
|
2813
|
+
const handleClose = async () => {
|
2814
|
+
if (onCancel) {
|
2815
|
+
await onCancel();
|
2816
|
+
}
|
2817
|
+
onClose();
|
2818
|
+
};
|
2819
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2820
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2821
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2822
|
+
] }) });
|
2823
|
+
};
|
2255
2824
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2256
2825
|
const navigate = reactRouterDom.useNavigate();
|
2257
2826
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2260,7 +2829,7 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2260
2829
|
id: "app.links.configure-view",
|
2261
2830
|
defaultMessage: "Configure the view"
|
2262
2831
|
}),
|
2263
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2832
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
|
2264
2833
|
onClick: () => {
|
2265
2834
|
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2266
2835
|
},
|
@@ -2268,11 +2837,6 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
|
|
2268
2837
|
};
|
2269
2838
|
};
|
2270
2839
|
ConfigureTheViewAction.type = "configure-the-view";
|
2271
|
-
const StyledCog = styled__default.default(Icons.Cog)`
|
2272
|
-
path {
|
2273
|
-
fill: currentColor;
|
2274
|
-
}
|
2275
|
-
`;
|
2276
2840
|
const EditTheModelAction = ({ model }) => {
|
2277
2841
|
const navigate = reactRouterDom.useNavigate();
|
2278
2842
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2281,20 +2845,15 @@ const EditTheModelAction = ({ model }) => {
|
|
2281
2845
|
id: "content-manager.link-to-ctb",
|
2282
2846
|
defaultMessage: "Edit the model"
|
2283
2847
|
}),
|
2284
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2848
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
|
2285
2849
|
onClick: () => {
|
2286
2850
|
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2287
2851
|
},
|
2288
2852
|
position: "header"
|
2289
2853
|
};
|
2290
|
-
};
|
2291
|
-
EditTheModelAction.type = "edit-the-model";
|
2292
|
-
const
|
2293
|
-
path {
|
2294
|
-
fill: currentColor;
|
2295
|
-
}
|
2296
|
-
`;
|
2297
|
-
const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
2854
|
+
};
|
2855
|
+
EditTheModelAction.type = "edit-the-model";
|
2856
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2298
2857
|
const navigate = reactRouterDom.useNavigate();
|
2299
2858
|
const { formatMessage } = reactIntl.useIntl();
|
2300
2859
|
const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
|
@@ -2302,13 +2861,17 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2302
2861
|
const { delete: deleteAction } = useDocumentActions();
|
2303
2862
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2304
2863
|
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2864
|
+
const isLocalized = document?.locale != null;
|
2305
2865
|
return {
|
2306
2866
|
disabled: !canDelete || !document,
|
2307
|
-
label: formatMessage(
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2867
|
+
label: formatMessage(
|
2868
|
+
{
|
2869
|
+
id: "content-manager.actions.delete.label",
|
2870
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2871
|
+
},
|
2872
|
+
{ isLocalized }
|
2873
|
+
),
|
2874
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2312
2875
|
dialog: {
|
2313
2876
|
type: "dialog",
|
2314
2877
|
title: formatMessage({
|
@@ -2317,7 +2880,7 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2317
2880
|
}),
|
2318
2881
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2319
2882
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2320
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
2883
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2321
2884
|
id: "content-manager.actions.delete.dialog.body",
|
2322
2885
|
defaultMessage: "Are you sure?"
|
2323
2886
|
}) })
|
@@ -2362,13 +2925,8 @@ const DeleteAction = ({ documentId, model, collectionType, document }) => {
|
|
2362
2925
|
position: ["header", "table-row"]
|
2363
2926
|
};
|
2364
2927
|
};
|
2365
|
-
DeleteAction.type = "delete";
|
2366
|
-
const
|
2367
|
-
path {
|
2368
|
-
fill: currentColor;
|
2369
|
-
}
|
2370
|
-
`;
|
2371
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction];
|
2928
|
+
DeleteAction$1.type = "delete";
|
2929
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2372
2930
|
const Panels = () => {
|
2373
2931
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2374
2932
|
const [
|
@@ -2402,7 +2960,7 @@ const ActionsPanel = () => {
|
|
2402
2960
|
return {
|
2403
2961
|
title: formatMessage({
|
2404
2962
|
id: "content-manager.containers.edit.panels.default.title",
|
2405
|
-
defaultMessage: "
|
2963
|
+
defaultMessage: "Entry"
|
2406
2964
|
}),
|
2407
2965
|
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2408
2966
|
};
|
@@ -2442,7 +3000,7 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
|
2442
3000
|
designSystem.Flex,
|
2443
3001
|
{
|
2444
3002
|
ref,
|
2445
|
-
|
3003
|
+
tag: "aside",
|
2446
3004
|
"aria-labelledby": "additional-information",
|
2447
3005
|
background: "neutral0",
|
2448
3006
|
borderColor: "neutral150",
|
@@ -2457,13 +3015,598 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
|
2457
3015
|
justifyContent: "stretch",
|
2458
3016
|
alignItems: "flex-start",
|
2459
3017
|
children: [
|
2460
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
3018
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2461
3019
|
children
|
2462
3020
|
]
|
2463
3021
|
}
|
2464
3022
|
);
|
2465
3023
|
});
|
2466
|
-
const
|
3024
|
+
const ConfirmBulkActionDialog = ({
|
3025
|
+
onToggleDialog,
|
3026
|
+
isOpen = false,
|
3027
|
+
dialogBody,
|
3028
|
+
endAction
|
3029
|
+
}) => {
|
3030
|
+
const { formatMessage } = reactIntl.useIntl();
|
3031
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
3032
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
|
3033
|
+
id: "app.components.ConfirmDialog.title",
|
3034
|
+
defaultMessage: "Confirmation"
|
3035
|
+
}) }),
|
3036
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3037
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3038
|
+
dialogBody
|
3039
|
+
] }) }),
|
3040
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
3041
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
|
3042
|
+
id: "app.components.Button.cancel",
|
3043
|
+
defaultMessage: "Cancel"
|
3044
|
+
}) }) }),
|
3045
|
+
endAction
|
3046
|
+
] })
|
3047
|
+
] }) });
|
3048
|
+
};
|
3049
|
+
const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
|
3050
|
+
const ConfirmDialogPublishAll = ({
|
3051
|
+
isOpen,
|
3052
|
+
onToggleDialog,
|
3053
|
+
isConfirmButtonLoading = false,
|
3054
|
+
onConfirm
|
3055
|
+
}) => {
|
3056
|
+
const { formatMessage } = reactIntl.useIntl();
|
3057
|
+
const selectedEntries = strapiAdmin.useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
|
3058
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
3059
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
3060
|
+
const { model, schema } = useDoc();
|
3061
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3062
|
+
const enableDraftRelationsCount = false;
|
3063
|
+
const {
|
3064
|
+
data: countDraftRelations = 0,
|
3065
|
+
isLoading,
|
3066
|
+
error
|
3067
|
+
} = useGetManyDraftRelationCountQuery(
|
3068
|
+
{
|
3069
|
+
model,
|
3070
|
+
documentIds: selectedEntries.map((entry) => entry.documentId),
|
3071
|
+
locale: query?.plugins?.i18n?.locale
|
3072
|
+
},
|
3073
|
+
{
|
3074
|
+
skip: !enableDraftRelationsCount
|
3075
|
+
}
|
3076
|
+
);
|
3077
|
+
React__namespace.useEffect(() => {
|
3078
|
+
if (error) {
|
3079
|
+
toggleNotification({ type: "danger", message: formatAPIError(error) });
|
3080
|
+
}
|
3081
|
+
}, [error, formatAPIError, toggleNotification]);
|
3082
|
+
if (error) {
|
3083
|
+
return null;
|
3084
|
+
}
|
3085
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
3086
|
+
ConfirmBulkActionDialog,
|
3087
|
+
{
|
3088
|
+
isOpen: isOpen && !isLoading,
|
3089
|
+
onToggleDialog,
|
3090
|
+
dialogBody: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
3091
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: [
|
3092
|
+
countDraftRelations > 0 && formatMessage(
|
3093
|
+
{
|
3094
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
3095
|
+
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. "
|
3096
|
+
},
|
3097
|
+
{
|
3098
|
+
b: BoldChunk$1,
|
3099
|
+
count: countDraftRelations,
|
3100
|
+
entities: selectedEntries.length
|
3101
|
+
}
|
3102
|
+
),
|
3103
|
+
formatMessage({
|
3104
|
+
id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
|
3105
|
+
defaultMessage: "Are you sure you want to publish these entries?"
|
3106
|
+
})
|
3107
|
+
] }),
|
3108
|
+
schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
|
3109
|
+
{
|
3110
|
+
id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
|
3111
|
+
defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
|
3112
|
+
},
|
3113
|
+
{
|
3114
|
+
em: Emphasis
|
3115
|
+
}
|
3116
|
+
) })
|
3117
|
+
] }),
|
3118
|
+
endAction: /* @__PURE__ */ jsxRuntime.jsx(
|
3119
|
+
designSystem.Button,
|
3120
|
+
{
|
3121
|
+
onClick: onConfirm,
|
3122
|
+
variant: "secondary",
|
3123
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
|
3124
|
+
loading: isConfirmButtonLoading,
|
3125
|
+
children: formatMessage({
|
3126
|
+
id: "app.utils.publish",
|
3127
|
+
defaultMessage: "Publish"
|
3128
|
+
})
|
3129
|
+
}
|
3130
|
+
)
|
3131
|
+
}
|
3132
|
+
);
|
3133
|
+
};
|
3134
|
+
const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
|
3135
|
+
max-width: 300px;
|
3136
|
+
`;
|
3137
|
+
const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
3138
|
+
const messages = [];
|
3139
|
+
Object.entries(errors).forEach(([key, value]) => {
|
3140
|
+
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
3141
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
3142
|
+
if ("id" in value && "defaultMessage" in value) {
|
3143
|
+
messages.push(
|
3144
|
+
formatMessage(
|
3145
|
+
{
|
3146
|
+
id: `${value.id}.withField`,
|
3147
|
+
defaultMessage: value.defaultMessage
|
3148
|
+
},
|
3149
|
+
{ field: currentKey }
|
3150
|
+
)
|
3151
|
+
);
|
3152
|
+
} else {
|
3153
|
+
messages.push(
|
3154
|
+
...formatErrorMessages(
|
3155
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3156
|
+
value,
|
3157
|
+
currentKey,
|
3158
|
+
formatMessage
|
3159
|
+
)
|
3160
|
+
);
|
3161
|
+
}
|
3162
|
+
} else {
|
3163
|
+
messages.push(
|
3164
|
+
formatMessage(
|
3165
|
+
{
|
3166
|
+
id: `${value}.withField`,
|
3167
|
+
defaultMessage: value
|
3168
|
+
},
|
3169
|
+
{ field: currentKey }
|
3170
|
+
)
|
3171
|
+
);
|
3172
|
+
}
|
3173
|
+
});
|
3174
|
+
return messages;
|
3175
|
+
};
|
3176
|
+
const EntryValidationText = ({ validationErrors, status }) => {
|
3177
|
+
const { formatMessage } = reactIntl.useIntl();
|
3178
|
+
if (validationErrors) {
|
3179
|
+
const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
|
3180
|
+
" "
|
3181
|
+
);
|
3182
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3183
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
|
3184
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
|
3185
|
+
] });
|
3186
|
+
}
|
3187
|
+
if (status === "published") {
|
3188
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3189
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
|
3190
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
|
3191
|
+
id: "content-manager.bulk-publish.already-published",
|
3192
|
+
defaultMessage: "Already Published"
|
3193
|
+
}) })
|
3194
|
+
] });
|
3195
|
+
}
|
3196
|
+
if (status === "modified") {
|
3197
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3198
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
|
3199
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3200
|
+
id: "content-manager.bulk-publish.modified",
|
3201
|
+
defaultMessage: "Ready to publish changes"
|
3202
|
+
}) })
|
3203
|
+
] });
|
3204
|
+
}
|
3205
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3206
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
|
3207
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3208
|
+
id: "app.utils.ready-to-publish",
|
3209
|
+
defaultMessage: "Ready to publish"
|
3210
|
+
}) })
|
3211
|
+
] });
|
3212
|
+
};
|
3213
|
+
const TABLE_HEADERS = [
|
3214
|
+
{ name: "id", label: "id" },
|
3215
|
+
{ name: "name", label: "name" },
|
3216
|
+
{ name: "status", label: "status" },
|
3217
|
+
{ name: "publicationStatus", label: "Publication status" }
|
3218
|
+
];
|
3219
|
+
const SelectedEntriesTableContent = ({
|
3220
|
+
isPublishing,
|
3221
|
+
rowsToDisplay = [],
|
3222
|
+
entriesToPublish = [],
|
3223
|
+
validationErrors = {}
|
3224
|
+
}) => {
|
3225
|
+
const { pathname } = reactRouterDom.useLocation();
|
3226
|
+
const { formatMessage } = reactIntl.useIntl();
|
3227
|
+
const {
|
3228
|
+
list: {
|
3229
|
+
settings: { mainField }
|
3230
|
+
}
|
3231
|
+
} = useDocLayout();
|
3232
|
+
const shouldDisplayMainField = mainField != null && mainField !== "id";
|
3233
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
|
3234
|
+
/* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
|
3235
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
|
3236
|
+
TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
|
3237
|
+
(head) => /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, { ...head }, head.name)
|
3238
|
+
)
|
3239
|
+
] }),
|
3240
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
|
3241
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
|
3242
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
|
3243
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
|
3244
|
+
shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
|
3245
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
|
3246
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3247
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3248
|
+
id: "content-manager.success.record.publishing",
|
3249
|
+
defaultMessage: "Publishing..."
|
3250
|
+
}) }),
|
3251
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true })
|
3252
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
3253
|
+
EntryValidationText,
|
3254
|
+
{
|
3255
|
+
validationErrors: validationErrors[row.documentId],
|
3256
|
+
status: row.status
|
3257
|
+
}
|
3258
|
+
) }),
|
3259
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3260
|
+
designSystem.IconButton,
|
3261
|
+
{
|
3262
|
+
tag: reactRouterDom.Link,
|
3263
|
+
to: {
|
3264
|
+
pathname: `${pathname}/${row.documentId}`,
|
3265
|
+
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3266
|
+
},
|
3267
|
+
state: { from: pathname },
|
3268
|
+
label: formatMessage(
|
3269
|
+
{ id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
|
3270
|
+
{
|
3271
|
+
target: formatMessage(
|
3272
|
+
{
|
3273
|
+
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3274
|
+
defaultMessage: "item line {number}"
|
3275
|
+
},
|
3276
|
+
{ number: index2 + 1 }
|
3277
|
+
)
|
3278
|
+
}
|
3279
|
+
),
|
3280
|
+
target: "_blank",
|
3281
|
+
marginLeft: "auto",
|
3282
|
+
variant: "ghost",
|
3283
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3284
|
+
}
|
3285
|
+
) }) })
|
3286
|
+
] }, row.id)) })
|
3287
|
+
] });
|
3288
|
+
};
|
3289
|
+
const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
|
3290
|
+
const SelectedEntriesModalContent = ({
|
3291
|
+
listViewSelectedEntries,
|
3292
|
+
toggleModal,
|
3293
|
+
setListViewSelectedDocuments,
|
3294
|
+
model
|
3295
|
+
}) => {
|
3296
|
+
const { formatMessage } = reactIntl.useIntl();
|
3297
|
+
const { schema, components } = useContentTypeSchema(model);
|
3298
|
+
const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
|
3299
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3300
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3301
|
+
const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
|
3302
|
+
{
|
3303
|
+
model,
|
3304
|
+
params: {
|
3305
|
+
page: "1",
|
3306
|
+
pageSize: documentIds.length.toString(),
|
3307
|
+
sort: query.sort,
|
3308
|
+
filters: {
|
3309
|
+
documentId: {
|
3310
|
+
$in: documentIds
|
3311
|
+
}
|
3312
|
+
},
|
3313
|
+
locale: query.plugins?.i18n?.locale
|
3314
|
+
}
|
3315
|
+
},
|
3316
|
+
{
|
3317
|
+
selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
|
3318
|
+
}
|
3319
|
+
);
|
3320
|
+
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3321
|
+
if (data.length > 0 && schema) {
|
3322
|
+
const validate = createYupSchema(
|
3323
|
+
schema.attributes,
|
3324
|
+
components,
|
3325
|
+
// Since this is the "Publish" action, the validation
|
3326
|
+
// schema must enforce the rules for published entities
|
3327
|
+
{ status: "published" }
|
3328
|
+
);
|
3329
|
+
const validationErrors2 = {};
|
3330
|
+
const rows2 = data.map((entry) => {
|
3331
|
+
try {
|
3332
|
+
validate.validateSync(entry, { abortEarly: false });
|
3333
|
+
return entry;
|
3334
|
+
} catch (e) {
|
3335
|
+
if (e instanceof yup.ValidationError) {
|
3336
|
+
validationErrors2[entry.documentId] = strapiAdmin.getYupValidationErrors(e);
|
3337
|
+
}
|
3338
|
+
return entry;
|
3339
|
+
}
|
3340
|
+
});
|
3341
|
+
return { rows: rows2, validationErrors: validationErrors2 };
|
3342
|
+
}
|
3343
|
+
return {
|
3344
|
+
rows: [],
|
3345
|
+
validationErrors: {}
|
3346
|
+
};
|
3347
|
+
}, [components, data, schema]);
|
3348
|
+
const [publishedCount, setPublishedCount] = React__namespace.useState(0);
|
3349
|
+
const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
|
3350
|
+
const { publishMany: bulkPublishAction } = useDocumentActions();
|
3351
|
+
const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
|
3352
|
+
const selectedRows = strapiAdmin.useTable("publishAction", (state) => state.selectedRows);
|
3353
|
+
const selectedEntries = rows.filter(
|
3354
|
+
(entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
|
3355
|
+
);
|
3356
|
+
const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
|
3357
|
+
const selectedEntriesWithErrorsCount = selectedEntries.filter(
|
3358
|
+
({ documentId }) => validationErrors[documentId]
|
3359
|
+
).length;
|
3360
|
+
const selectedEntriesPublished = selectedEntries.filter(
|
3361
|
+
({ status }) => status === "published"
|
3362
|
+
).length;
|
3363
|
+
const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
|
3364
|
+
const toggleDialog = () => setIsDialogOpen((prev) => !prev);
|
3365
|
+
const handleConfirmBulkPublish = async () => {
|
3366
|
+
toggleDialog();
|
3367
|
+
const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
|
3368
|
+
if (!("error" in res)) {
|
3369
|
+
setPublishedCount(res.count);
|
3370
|
+
const unpublishedEntries = rows.filter((row) => {
|
3371
|
+
return !entriesToPublish.includes(row.documentId);
|
3372
|
+
});
|
3373
|
+
setListViewSelectedDocuments(unpublishedEntries);
|
3374
|
+
}
|
3375
|
+
};
|
3376
|
+
const getFormattedCountMessage = () => {
|
3377
|
+
if (publishedCount) {
|
3378
|
+
return formatMessage(
|
3379
|
+
{
|
3380
|
+
id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
|
3381
|
+
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."
|
3382
|
+
},
|
3383
|
+
{
|
3384
|
+
publishedCount,
|
3385
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3386
|
+
b: BoldChunk
|
3387
|
+
}
|
3388
|
+
);
|
3389
|
+
}
|
3390
|
+
return formatMessage(
|
3391
|
+
{
|
3392
|
+
id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
|
3393
|
+
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."
|
3394
|
+
},
|
3395
|
+
{
|
3396
|
+
readyToPublishCount: selectedEntriesWithNoErrorsCount,
|
3397
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3398
|
+
alreadyPublishedCount: selectedEntriesPublished,
|
3399
|
+
b: BoldChunk
|
3400
|
+
}
|
3401
|
+
);
|
3402
|
+
};
|
3403
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
3404
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
|
3405
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
|
3406
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3407
|
+
SelectedEntriesTableContent,
|
3408
|
+
{
|
3409
|
+
isPublishing: isSubmittingForm,
|
3410
|
+
rowsToDisplay: rows,
|
3411
|
+
entriesToPublish,
|
3412
|
+
validationErrors
|
3413
|
+
}
|
3414
|
+
) })
|
3415
|
+
] }),
|
3416
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3417
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
|
3418
|
+
id: "app.components.Button.cancel",
|
3419
|
+
defaultMessage: "Cancel"
|
3420
|
+
}) }),
|
3421
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3422
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
|
3423
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3424
|
+
designSystem.Button,
|
3425
|
+
{
|
3426
|
+
onClick: toggleDialog,
|
3427
|
+
disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
|
3428
|
+
loading: isSubmittingForm,
|
3429
|
+
children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
|
3430
|
+
}
|
3431
|
+
)
|
3432
|
+
] })
|
3433
|
+
] }),
|
3434
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3435
|
+
ConfirmDialogPublishAll,
|
3436
|
+
{
|
3437
|
+
isOpen: isDialogOpen,
|
3438
|
+
onToggleDialog: toggleDialog,
|
3439
|
+
isConfirmButtonLoading: isSubmittingForm,
|
3440
|
+
onConfirm: handleConfirmBulkPublish
|
3441
|
+
}
|
3442
|
+
)
|
3443
|
+
] });
|
3444
|
+
};
|
3445
|
+
const PublishAction = ({ documents, model }) => {
|
3446
|
+
const { formatMessage } = reactIntl.useIntl();
|
3447
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3448
|
+
const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
|
3449
|
+
const setListViewSelectedDocuments = strapiAdmin.useTable("publishAction", (state) => state.selectRow);
|
3450
|
+
const refetchList = () => {
|
3451
|
+
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3452
|
+
};
|
3453
|
+
if (!showPublishButton)
|
3454
|
+
return null;
|
3455
|
+
return {
|
3456
|
+
actionType: "publish",
|
3457
|
+
variant: "tertiary",
|
3458
|
+
label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
|
3459
|
+
dialog: {
|
3460
|
+
type: "modal",
|
3461
|
+
title: formatMessage({
|
3462
|
+
id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
|
3463
|
+
defaultMessage: "Publish entries"
|
3464
|
+
}),
|
3465
|
+
content: ({ onClose }) => {
|
3466
|
+
return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3467
|
+
SelectedEntriesModalContent,
|
3468
|
+
{
|
3469
|
+
listViewSelectedEntries: documents,
|
3470
|
+
toggleModal: () => {
|
3471
|
+
onClose();
|
3472
|
+
refetchList();
|
3473
|
+
},
|
3474
|
+
setListViewSelectedDocuments,
|
3475
|
+
model
|
3476
|
+
}
|
3477
|
+
) });
|
3478
|
+
},
|
3479
|
+
onClose: () => {
|
3480
|
+
refetchList();
|
3481
|
+
}
|
3482
|
+
}
|
3483
|
+
};
|
3484
|
+
};
|
3485
|
+
const BulkActionsRenderer = () => {
|
3486
|
+
const plugins = strapiAdmin.useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
|
3487
|
+
const { model, collectionType } = useDoc();
|
3488
|
+
const { selectedRows } = strapiAdmin.useTable("BulkActionsRenderer", (state) => state);
|
3489
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3490
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3491
|
+
{
|
3492
|
+
props: {
|
3493
|
+
model,
|
3494
|
+
collectionType,
|
3495
|
+
documents: selectedRows
|
3496
|
+
},
|
3497
|
+
descriptions: plugins["content-manager"].apis.getBulkActions(),
|
3498
|
+
children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...action }, action.id))
|
3499
|
+
}
|
3500
|
+
) });
|
3501
|
+
};
|
3502
|
+
const DeleteAction = ({ documents, model }) => {
|
3503
|
+
const { formatMessage } = reactIntl.useIntl();
|
3504
|
+
const { schema: contentType } = useDoc();
|
3505
|
+
const selectRow = strapiAdmin.useTable("DeleteAction", (state) => state.selectRow);
|
3506
|
+
const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
|
3507
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3508
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3509
|
+
const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
|
3510
|
+
const { deleteMany: bulkDeleteAction } = useDocumentActions();
|
3511
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3512
|
+
const handleConfirmBulkDelete = async () => {
|
3513
|
+
const res = await bulkDeleteAction({
|
3514
|
+
documentIds,
|
3515
|
+
model,
|
3516
|
+
params
|
3517
|
+
});
|
3518
|
+
if (!("error" in res)) {
|
3519
|
+
selectRow([]);
|
3520
|
+
}
|
3521
|
+
};
|
3522
|
+
if (!hasDeletePermission)
|
3523
|
+
return null;
|
3524
|
+
return {
|
3525
|
+
variant: "danger-light",
|
3526
|
+
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
3527
|
+
dialog: {
|
3528
|
+
type: "dialog",
|
3529
|
+
title: formatMessage({
|
3530
|
+
id: "app.components.ConfirmDialog.title",
|
3531
|
+
defaultMessage: "Confirmation"
|
3532
|
+
}),
|
3533
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3534
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3535
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3536
|
+
id: "popUpWarning.bodyMessage.contentType.delete.all",
|
3537
|
+
defaultMessage: "Are you sure you want to delete these entries?"
|
3538
|
+
}) }),
|
3539
|
+
hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
|
3540
|
+
{
|
3541
|
+
id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
|
3542
|
+
defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
|
3543
|
+
},
|
3544
|
+
{
|
3545
|
+
em: Emphasis
|
3546
|
+
}
|
3547
|
+
) }) })
|
3548
|
+
] }),
|
3549
|
+
onConfirm: handleConfirmBulkDelete
|
3550
|
+
}
|
3551
|
+
};
|
3552
|
+
};
|
3553
|
+
DeleteAction.type = "delete";
|
3554
|
+
const UnpublishAction = ({ documents, model }) => {
|
3555
|
+
const { formatMessage } = reactIntl.useIntl();
|
3556
|
+
const { schema } = useDoc();
|
3557
|
+
const selectRow = strapiAdmin.useTable("UnpublishAction", (state) => state.selectRow);
|
3558
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3559
|
+
const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
|
3560
|
+
const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
|
3561
|
+
const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
|
3562
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3563
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3564
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3565
|
+
const handleConfirmBulkUnpublish = async () => {
|
3566
|
+
const data = await bulkUnpublishAction({ documentIds, model, params });
|
3567
|
+
if (!("error" in data)) {
|
3568
|
+
selectRow([]);
|
3569
|
+
}
|
3570
|
+
};
|
3571
|
+
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3572
|
+
if (!showUnpublishButton)
|
3573
|
+
return null;
|
3574
|
+
return {
|
3575
|
+
variant: "tertiary",
|
3576
|
+
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
3577
|
+
dialog: {
|
3578
|
+
type: "dialog",
|
3579
|
+
title: formatMessage({
|
3580
|
+
id: "app.components.ConfirmDialog.title",
|
3581
|
+
defaultMessage: "Confirmation"
|
3582
|
+
}),
|
3583
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3584
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3585
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3586
|
+
id: "popUpWarning.bodyMessage.contentType.unpublish.all",
|
3587
|
+
defaultMessage: "Are you sure you want to unpublish these entries?"
|
3588
|
+
}) }),
|
3589
|
+
hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
|
3590
|
+
{
|
3591
|
+
id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
|
3592
|
+
defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
|
3593
|
+
},
|
3594
|
+
{
|
3595
|
+
em: Emphasis
|
3596
|
+
}
|
3597
|
+
) }) })
|
3598
|
+
] }),
|
3599
|
+
confirmButton: formatMessage({
|
3600
|
+
id: "app.utils.unpublish",
|
3601
|
+
defaultMessage: "Unpublish"
|
3602
|
+
}),
|
3603
|
+
onConfirm: handleConfirmBulkUnpublish
|
3604
|
+
}
|
3605
|
+
};
|
3606
|
+
};
|
3607
|
+
UnpublishAction.type = "unpublish";
|
3608
|
+
const Emphasis = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
|
3609
|
+
const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
|
2467
3610
|
const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
2468
3611
|
const { formatMessage } = reactIntl.useIntl();
|
2469
3612
|
const getDefaultErrorMessage = (reason) => {
|
@@ -2495,7 +3638,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
|
2495
3638
|
hasRadius: true,
|
2496
3639
|
padding: 6,
|
2497
3640
|
children: [
|
2498
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row",
|
3641
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "row", tag: "ol", children: fieldPath.map((pathSegment, index2) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { fontWeight: "semiBold", tag: "li", children: [
|
2499
3642
|
pathSegment,
|
2500
3643
|
index2 !== fieldPath.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
2501
3644
|
Icons.ChevronRight,
|
@@ -2507,7 +3650,7 @@ const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
|
2507
3650
|
}
|
2508
3651
|
)
|
2509
3652
|
] }, index2)) }),
|
2510
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, {
|
3653
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", textColor: "neutral600", children: formatMessage({
|
2511
3654
|
id: getTranslation(`containers.list.autoCloneModal.error.${reason}`),
|
2512
3655
|
defaultMessage: getDefaultErrorMessage(reason)
|
2513
3656
|
}) })
|
@@ -2532,7 +3675,7 @@ const TableActions = ({ document }) => {
|
|
2532
3675
|
strapiAdmin.DescriptionComponentRenderer,
|
2533
3676
|
{
|
2534
3677
|
props,
|
2535
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3678
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
2536
3679
|
children: (actions2) => {
|
2537
3680
|
const tableRowActions = actions2.filter((action) => {
|
2538
3681
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -2591,7 +3734,7 @@ const EditAction = ({ documentId }) => {
|
|
2591
3734
|
};
|
2592
3735
|
};
|
2593
3736
|
EditAction.type = "edit";
|
2594
|
-
const StyledPencil =
|
3737
|
+
const StyledPencil = styledComponents.styled(Icons.Pencil)`
|
2595
3738
|
path {
|
2596
3739
|
fill: currentColor;
|
2597
3740
|
}
|
@@ -2643,7 +3786,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2643
3786
|
}),
|
2644
3787
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
2645
3788
|
footer: ({ onClose }) => {
|
2646
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3789
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
2647
3790
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
2648
3791
|
id: "cancel",
|
2649
3792
|
defaultMessage: "Cancel"
|
@@ -2651,7 +3794,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2651
3794
|
/* @__PURE__ */ jsxRuntime.jsx(
|
2652
3795
|
designSystem.LinkButton,
|
2653
3796
|
{
|
2654
|
-
|
3797
|
+
tag: reactRouterDom.NavLink,
|
2655
3798
|
to: {
|
2656
3799
|
pathname: `clone/${documentId}`
|
2657
3800
|
},
|
@@ -2667,7 +3810,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
2667
3810
|
};
|
2668
3811
|
};
|
2669
3812
|
CloneAction.type = "clone";
|
2670
|
-
const StyledDuplicate =
|
3813
|
+
const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
|
2671
3814
|
path {
|
2672
3815
|
fill: currentColor;
|
2673
3816
|
}
|
@@ -2684,442 +3827,183 @@ class ContentManagerPlugin {
|
|
2684
3827
|
documentActions = [
|
2685
3828
|
...DEFAULT_ACTIONS,
|
2686
3829
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
2687
|
-
...DEFAULT_HEADER_ACTIONS
|
2688
|
-
HistoryAction
|
3830
|
+
...DEFAULT_HEADER_ACTIONS
|
2689
3831
|
];
|
2690
3832
|
editViewSidePanels = [ActionsPanel];
|
2691
3833
|
headerActions = [];
|
2692
3834
|
constructor() {
|
2693
3835
|
}
|
2694
3836
|
addEditViewSidePanel(panels) {
|
2695
|
-
if (Array.isArray(panels)) {
|
2696
|
-
this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
|
2697
|
-
} else if (typeof panels === "function") {
|
2698
|
-
this.editViewSidePanels = panels(this.editViewSidePanels);
|
2699
|
-
} else {
|
2700
|
-
throw new Error(
|
2701
|
-
`Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
|
2702
|
-
panels
|
2703
|
-
)}`
|
2704
|
-
);
|
2705
|
-
}
|
2706
|
-
}
|
2707
|
-
addDocumentAction(actions2) {
|
2708
|
-
if (Array.isArray(actions2)) {
|
2709
|
-
this.documentActions = [...this.documentActions, ...actions2];
|
2710
|
-
} else if (typeof actions2 === "function") {
|
2711
|
-
this.documentActions = actions2(this.documentActions);
|
2712
|
-
} else {
|
2713
|
-
throw new Error(
|
2714
|
-
`Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
|
2715
|
-
actions2
|
2716
|
-
)}`
|
2717
|
-
);
|
2718
|
-
}
|
2719
|
-
}
|
2720
|
-
addDocumentHeaderAction(actions2) {
|
2721
|
-
if (Array.isArray(actions2)) {
|
2722
|
-
this.headerActions = [...this.headerActions, ...actions2];
|
2723
|
-
} else if (typeof actions2 === "function") {
|
2724
|
-
this.headerActions = actions2(this.headerActions);
|
3837
|
+
if (Array.isArray(panels)) {
|
3838
|
+
this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
|
3839
|
+
} else if (typeof panels === "function") {
|
3840
|
+
this.editViewSidePanels = panels(this.editViewSidePanels);
|
2725
3841
|
} else {
|
2726
3842
|
throw new Error(
|
2727
|
-
`Expected the \`
|
2728
|
-
|
3843
|
+
`Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
|
3844
|
+
panels
|
2729
3845
|
)}`
|
2730
3846
|
);
|
2731
3847
|
}
|
2732
3848
|
}
|
2733
|
-
|
3849
|
+
addDocumentAction(actions2) {
|
2734
3850
|
if (Array.isArray(actions2)) {
|
2735
|
-
this.
|
3851
|
+
this.documentActions = [...this.documentActions, ...actions2];
|
2736
3852
|
} else if (typeof actions2 === "function") {
|
2737
|
-
this.
|
3853
|
+
this.documentActions = actions2(this.documentActions);
|
2738
3854
|
} else {
|
2739
3855
|
throw new Error(
|
2740
|
-
`Expected the \`actions\` passed to \`
|
3856
|
+
`Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
|
2741
3857
|
actions2
|
2742
|
-
)}`
|
2743
|
-
);
|
2744
|
-
}
|
2745
|
-
}
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2749
|
-
|
2750
|
-
|
2751
|
-
apis: {
|
2752
|
-
addBulkAction: this.addBulkAction.bind(this),
|
2753
|
-
addDocumentAction: this.addDocumentAction.bind(this),
|
2754
|
-
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
2755
|
-
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
2756
|
-
getBulkActions: () => this.bulkActions,
|
2757
|
-
getDocumentActions: () => this.documentActions,
|
2758
|
-
getEditViewSidePanels: () => this.editViewSidePanels,
|
2759
|
-
getHeaderActions: () => this.headerActions
|
2760
|
-
}
|
2761
|
-
};
|
2762
|
-
}
|
2763
|
-
}
|
2764
|
-
const getPrintableType = (value) => {
|
2765
|
-
const nativeType = typeof value;
|
2766
|
-
if (nativeType === "object") {
|
2767
|
-
if (value === null)
|
2768
|
-
return "null";
|
2769
|
-
if (Array.isArray(value))
|
2770
|
-
return "array";
|
2771
|
-
if (value instanceof Object && value.constructor.name !== "Object") {
|
2772
|
-
return value.constructor.name;
|
2773
|
-
}
|
2774
|
-
}
|
2775
|
-
return nativeType;
|
2776
|
-
};
|
2777
|
-
const initialState = {
|
2778
|
-
collectionTypeLinks: [],
|
2779
|
-
components: [],
|
2780
|
-
fieldSizes: {},
|
2781
|
-
models: [],
|
2782
|
-
singleTypeLinks: [],
|
2783
|
-
isLoading: true
|
2784
|
-
};
|
2785
|
-
const appSlice = toolkit.createSlice({
|
2786
|
-
name: "app",
|
2787
|
-
initialState,
|
2788
|
-
reducers: {
|
2789
|
-
setInitialData(state, action) {
|
2790
|
-
const {
|
2791
|
-
authorizedCollectionTypeLinks,
|
2792
|
-
authorizedSingleTypeLinks,
|
2793
|
-
components,
|
2794
|
-
contentTypeSchemas,
|
2795
|
-
fieldSizes
|
2796
|
-
} = action.payload;
|
2797
|
-
state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
|
2798
|
-
({ isDisplayed }) => isDisplayed
|
2799
|
-
);
|
2800
|
-
state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
|
2801
|
-
state.components = components;
|
2802
|
-
state.models = contentTypeSchemas;
|
2803
|
-
state.fieldSizes = fieldSizes;
|
2804
|
-
state.isLoading = false;
|
2805
|
-
}
|
2806
|
-
}
|
2807
|
-
});
|
2808
|
-
const { actions, reducer: reducer$1 } = appSlice;
|
2809
|
-
const { setInitialData } = actions;
|
2810
|
-
const reducer = toolkit.combineReducers({
|
2811
|
-
app: reducer$1
|
2812
|
-
});
|
2813
|
-
const HOOKS = {
|
2814
|
-
/**
|
2815
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2816
|
-
* @constant
|
2817
|
-
* @type {string}
|
2818
|
-
*/
|
2819
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2820
|
-
/**
|
2821
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2822
|
-
* @constant
|
2823
|
-
* @type {string}
|
2824
|
-
*/
|
2825
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2826
|
-
/**
|
2827
|
-
* Hook that allows to mutate the CM's edit view layout
|
2828
|
-
* @constant
|
2829
|
-
* @type {string}
|
2830
|
-
*/
|
2831
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2832
|
-
/**
|
2833
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2834
|
-
* @constant
|
2835
|
-
* @type {string}
|
2836
|
-
*/
|
2837
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2838
|
-
};
|
2839
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2840
|
-
endpoints: (builder) => ({
|
2841
|
-
getContentTypeConfiguration: builder.query({
|
2842
|
-
query: (uid) => ({
|
2843
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2844
|
-
method: "GET"
|
2845
|
-
}),
|
2846
|
-
transformResponse: (response) => response.data,
|
2847
|
-
providesTags: (_result, _error, uid) => [
|
2848
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2849
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2850
|
-
]
|
2851
|
-
}),
|
2852
|
-
getAllContentTypeSettings: builder.query({
|
2853
|
-
query: () => "/content-manager/content-types-settings",
|
2854
|
-
transformResponse: (response) => response.data,
|
2855
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2856
|
-
}),
|
2857
|
-
updateContentTypeConfiguration: builder.mutation({
|
2858
|
-
query: ({ uid, ...body }) => ({
|
2859
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2860
|
-
method: "PUT",
|
2861
|
-
data: body
|
2862
|
-
}),
|
2863
|
-
transformResponse: (response) => response.data,
|
2864
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2865
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2866
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2867
|
-
// Is this necessary?
|
2868
|
-
{ type: "InitialData" }
|
2869
|
-
]
|
2870
|
-
})
|
2871
|
-
})
|
2872
|
-
});
|
2873
|
-
const {
|
2874
|
-
useGetContentTypeConfigurationQuery,
|
2875
|
-
useGetAllContentTypeSettingsQuery,
|
2876
|
-
useUpdateContentTypeConfigurationMutation
|
2877
|
-
} = contentTypesApi;
|
2878
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2879
|
-
const { type } = attribute;
|
2880
|
-
if (type === "relation") {
|
2881
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2882
|
-
}
|
2883
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2884
|
-
};
|
2885
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2886
|
-
if (!mainFieldName) {
|
2887
|
-
return void 0;
|
2888
|
-
}
|
2889
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2890
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2891
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2892
|
-
);
|
2893
|
-
return {
|
2894
|
-
name: mainFieldName,
|
2895
|
-
type: mainFieldType ?? "string"
|
2896
|
-
};
|
2897
|
-
};
|
2898
|
-
const DEFAULT_SETTINGS = {
|
2899
|
-
bulkable: false,
|
2900
|
-
filterable: false,
|
2901
|
-
searchable: false,
|
2902
|
-
pagination: false,
|
2903
|
-
defaultSortBy: "",
|
2904
|
-
defaultSortOrder: "asc",
|
2905
|
-
mainField: "id",
|
2906
|
-
pageSize: 10
|
2907
|
-
};
|
2908
|
-
const useDocumentLayout = (model) => {
|
2909
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2910
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
2911
|
-
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2912
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
2913
|
-
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
2914
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2915
|
-
const {
|
2916
|
-
data,
|
2917
|
-
isLoading: isLoadingConfigs,
|
2918
|
-
error,
|
2919
|
-
isFetching: isFetchingConfigs
|
2920
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2921
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2922
|
-
React__namespace.useEffect(() => {
|
2923
|
-
if (error) {
|
2924
|
-
toggleNotification({
|
2925
|
-
type: "danger",
|
2926
|
-
message: formatAPIError(error)
|
2927
|
-
});
|
2928
|
-
}
|
2929
|
-
}, [error, formatAPIError, toggleNotification]);
|
2930
|
-
const editLayout = React__namespace.useMemo(
|
2931
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2932
|
-
layout: [],
|
2933
|
-
components: {},
|
2934
|
-
metadatas: {},
|
2935
|
-
options: {},
|
2936
|
-
settings: DEFAULT_SETTINGS
|
2937
|
-
},
|
2938
|
-
[data, isLoading, schemas, schema, components]
|
2939
|
-
);
|
2940
|
-
const listLayout = React__namespace.useMemo(() => {
|
2941
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2942
|
-
layout: [],
|
2943
|
-
metadatas: {},
|
2944
|
-
options: {},
|
2945
|
-
settings: DEFAULT_SETTINGS
|
2946
|
-
};
|
2947
|
-
}, [data, isLoading, schemas, schema, components]);
|
2948
|
-
const { layout: edit } = React__namespace.useMemo(
|
2949
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2950
|
-
layout: editLayout,
|
2951
|
-
query
|
2952
|
-
}),
|
2953
|
-
[editLayout, query, runHookWaterfall]
|
2954
|
-
);
|
2955
|
-
return {
|
2956
|
-
error,
|
2957
|
-
isLoading,
|
2958
|
-
edit,
|
2959
|
-
list: listLayout
|
2960
|
-
};
|
2961
|
-
};
|
2962
|
-
const useDocLayout = () => {
|
2963
|
-
const { model } = useDoc();
|
2964
|
-
return useDocumentLayout(model);
|
2965
|
-
};
|
2966
|
-
const formatEditLayout = (data, {
|
2967
|
-
schemas,
|
2968
|
-
schema,
|
2969
|
-
components
|
2970
|
-
}) => {
|
2971
|
-
let currentPanelIndex = 0;
|
2972
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2973
|
-
data.contentType.layouts.edit,
|
2974
|
-
schema?.attributes,
|
2975
|
-
data.contentType.metadatas,
|
2976
|
-
{ configurations: data.components, schemas: components },
|
2977
|
-
schemas
|
2978
|
-
).reduce((panels, row) => {
|
2979
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2980
|
-
panels.push([row]);
|
2981
|
-
currentPanelIndex += 2;
|
3858
|
+
)}`
|
3859
|
+
);
|
3860
|
+
}
|
3861
|
+
}
|
3862
|
+
addDocumentHeaderAction(actions2) {
|
3863
|
+
if (Array.isArray(actions2)) {
|
3864
|
+
this.headerActions = [...this.headerActions, ...actions2];
|
3865
|
+
} else if (typeof actions2 === "function") {
|
3866
|
+
this.headerActions = actions2(this.headerActions);
|
2982
3867
|
} else {
|
2983
|
-
|
2984
|
-
|
2985
|
-
|
2986
|
-
|
3868
|
+
throw new Error(
|
3869
|
+
`Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
|
3870
|
+
actions2
|
3871
|
+
)}`
|
3872
|
+
);
|
2987
3873
|
}
|
2988
|
-
|
2989
|
-
|
2990
|
-
|
2991
|
-
|
2992
|
-
|
2993
|
-
|
2994
|
-
|
2995
|
-
|
2996
|
-
|
2997
|
-
|
2998
|
-
|
2999
|
-
|
3000
|
-
icon: components[uid].info.icon,
|
3001
|
-
displayName: components[uid].info.displayName
|
3002
|
-
}
|
3003
|
-
};
|
3004
|
-
return acc;
|
3005
|
-
},
|
3006
|
-
{}
|
3007
|
-
);
|
3008
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
3009
|
-
(acc, [attribute, metadata]) => {
|
3010
|
-
return {
|
3011
|
-
...acc,
|
3012
|
-
[attribute]: metadata.edit
|
3013
|
-
};
|
3014
|
-
},
|
3015
|
-
{}
|
3016
|
-
);
|
3017
|
-
return {
|
3018
|
-
layout: panelledEditAttributes,
|
3019
|
-
components: componentEditAttributes,
|
3020
|
-
metadatas: editMetadatas,
|
3021
|
-
settings: {
|
3022
|
-
...data.contentType.settings,
|
3023
|
-
displayName: schema?.info.displayName
|
3024
|
-
},
|
3025
|
-
options: {
|
3026
|
-
...schema?.options,
|
3027
|
-
...schema?.pluginOptions,
|
3028
|
-
...data.contentType.options
|
3874
|
+
}
|
3875
|
+
addBulkAction(actions2) {
|
3876
|
+
if (Array.isArray(actions2)) {
|
3877
|
+
this.bulkActions = [...this.bulkActions, ...actions2];
|
3878
|
+
} else if (typeof actions2 === "function") {
|
3879
|
+
this.bulkActions = actions2(this.bulkActions);
|
3880
|
+
} else {
|
3881
|
+
throw new Error(
|
3882
|
+
`Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
|
3883
|
+
actions2
|
3884
|
+
)}`
|
3885
|
+
);
|
3029
3886
|
}
|
3030
|
-
}
|
3031
|
-
|
3032
|
-
|
3033
|
-
|
3034
|
-
|
3035
|
-
|
3036
|
-
|
3037
|
-
|
3887
|
+
}
|
3888
|
+
get config() {
|
3889
|
+
return {
|
3890
|
+
id: PLUGIN_ID,
|
3891
|
+
name: "Content Manager",
|
3892
|
+
injectionZones: INJECTION_ZONES,
|
3893
|
+
apis: {
|
3894
|
+
addBulkAction: this.addBulkAction.bind(this),
|
3895
|
+
addDocumentAction: this.addDocumentAction.bind(this),
|
3896
|
+
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3897
|
+
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3898
|
+
getBulkActions: () => this.bulkActions,
|
3899
|
+
getDocumentActions: () => this.documentActions,
|
3900
|
+
getEditViewSidePanels: () => this.editViewSidePanels,
|
3901
|
+
getHeaderActions: () => this.headerActions
|
3038
3902
|
}
|
3039
|
-
|
3040
|
-
|
3041
|
-
|
3042
|
-
|
3043
|
-
|
3044
|
-
|
3045
|
-
|
3046
|
-
|
3047
|
-
|
3048
|
-
|
3049
|
-
|
3050
|
-
|
3051
|
-
|
3052
|
-
|
3053
|
-
|
3054
|
-
size: field.size,
|
3055
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
3056
|
-
visible: metadata.visible ?? true,
|
3057
|
-
type: attribute.type
|
3058
|
-
};
|
3059
|
-
}).filter((field) => field !== null)
|
3060
|
-
);
|
3903
|
+
};
|
3904
|
+
}
|
3905
|
+
}
|
3906
|
+
const getPrintableType = (value) => {
|
3907
|
+
const nativeType = typeof value;
|
3908
|
+
if (nativeType === "object") {
|
3909
|
+
if (value === null)
|
3910
|
+
return "null";
|
3911
|
+
if (Array.isArray(value))
|
3912
|
+
return "array";
|
3913
|
+
if (value instanceof Object && value.constructor.name !== "Object") {
|
3914
|
+
return value.constructor.name;
|
3915
|
+
}
|
3916
|
+
}
|
3917
|
+
return nativeType;
|
3061
3918
|
};
|
3062
|
-
const
|
3063
|
-
|
3064
|
-
|
3065
|
-
|
3066
|
-
}
|
3067
|
-
|
3068
|
-
|
3069
|
-
|
3070
|
-
...acc,
|
3071
|
-
[attribute]: metadata.list
|
3072
|
-
};
|
3073
|
-
},
|
3074
|
-
{}
|
3075
|
-
);
|
3076
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
3077
|
-
data.contentType.layouts.list,
|
3078
|
-
schema?.attributes,
|
3079
|
-
listMetadatas,
|
3080
|
-
{ configurations: data.components, schemas: components },
|
3081
|
-
schemas
|
3082
|
-
);
|
3919
|
+
const HistoryAction = ({ model, document }) => {
|
3920
|
+
const { formatMessage } = reactIntl.useIntl();
|
3921
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3922
|
+
const navigate = reactRouterDom.useNavigate();
|
3923
|
+
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
3924
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3925
|
+
return null;
|
3926
|
+
}
|
3083
3927
|
return {
|
3084
|
-
|
3085
|
-
|
3086
|
-
|
3087
|
-
|
3088
|
-
|
3089
|
-
|
3090
|
-
|
3091
|
-
|
3928
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
3929
|
+
label: formatMessage({
|
3930
|
+
id: "content-manager.history.document-action",
|
3931
|
+
defaultMessage: "Content History"
|
3932
|
+
}),
|
3933
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3934
|
+
disabled: (
|
3935
|
+
/**
|
3936
|
+
* The user is creating a new document.
|
3937
|
+
* It hasn't been saved yet, so there's no history to go to
|
3938
|
+
*/
|
3939
|
+
!document || /**
|
3940
|
+
* The document has been created but the current dimension has never been saved.
|
3941
|
+
* For example, the user is creating a new locale in an existing document,
|
3942
|
+
* so there's no history for the document in that locale
|
3943
|
+
*/
|
3944
|
+
!document.id || /**
|
3945
|
+
* History is only available for content types created by the user.
|
3946
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3947
|
+
* which start with `admin::` or `plugin::`
|
3948
|
+
*/
|
3949
|
+
!model.startsWith("api::")
|
3950
|
+
),
|
3951
|
+
position: "header"
|
3092
3952
|
};
|
3093
3953
|
};
|
3094
|
-
|
3095
|
-
|
3096
|
-
|
3097
|
-
|
3098
|
-
|
3099
|
-
|
3100
|
-
|
3101
|
-
|
3102
|
-
|
3103
|
-
|
3104
|
-
|
3105
|
-
|
3106
|
-
|
3107
|
-
|
3108
|
-
|
3109
|
-
|
3110
|
-
|
3111
|
-
|
3112
|
-
};
|
3113
|
-
}).filter((field) => field !== null);
|
3954
|
+
HistoryAction.type = "history";
|
3955
|
+
const historyAdmin = {
|
3956
|
+
bootstrap(app) {
|
3957
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3958
|
+
addDocumentAction((actions2) => {
|
3959
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3960
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3961
|
+
return actions2;
|
3962
|
+
});
|
3963
|
+
}
|
3964
|
+
};
|
3965
|
+
const initialState = {
|
3966
|
+
collectionTypeLinks: [],
|
3967
|
+
components: [],
|
3968
|
+
fieldSizes: {},
|
3969
|
+
models: [],
|
3970
|
+
singleTypeLinks: [],
|
3971
|
+
isLoading: true
|
3114
3972
|
};
|
3973
|
+
const appSlice = toolkit.createSlice({
|
3974
|
+
name: "app",
|
3975
|
+
initialState,
|
3976
|
+
reducers: {
|
3977
|
+
setInitialData(state, action) {
|
3978
|
+
const {
|
3979
|
+
authorizedCollectionTypeLinks,
|
3980
|
+
authorizedSingleTypeLinks,
|
3981
|
+
components,
|
3982
|
+
contentTypeSchemas,
|
3983
|
+
fieldSizes
|
3984
|
+
} = action.payload;
|
3985
|
+
state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
|
3986
|
+
({ isDisplayed }) => isDisplayed
|
3987
|
+
);
|
3988
|
+
state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
|
3989
|
+
state.components = components;
|
3990
|
+
state.models = contentTypeSchemas;
|
3991
|
+
state.fieldSizes = fieldSizes;
|
3992
|
+
state.isLoading = false;
|
3993
|
+
}
|
3994
|
+
}
|
3995
|
+
});
|
3996
|
+
const { actions, reducer: reducer$1 } = appSlice;
|
3997
|
+
const { setInitialData } = actions;
|
3998
|
+
const reducer = toolkit.combineReducers({
|
3999
|
+
app: reducer$1
|
4000
|
+
});
|
3115
4001
|
const index = {
|
3116
4002
|
register(app) {
|
3117
4003
|
const cm = new ContentManagerPlugin();
|
3118
4004
|
app.addReducers({
|
3119
|
-
[contentManagerApi.reducerPath]: contentManagerApi.reducer,
|
3120
4005
|
[PLUGIN_ID]: reducer
|
3121
4006
|
});
|
3122
|
-
app.addMiddlewares([() => contentManagerApi.middleware]);
|
3123
4007
|
app.addMenuLink({
|
3124
4008
|
to: PLUGIN_ID,
|
3125
4009
|
icon: Icons.Feather,
|
@@ -3128,14 +4012,29 @@ const index = {
|
|
3128
4012
|
defaultMessage: "Content Manager"
|
3129
4013
|
},
|
3130
4014
|
permissions: [],
|
3131
|
-
|
4015
|
+
position: 1
|
4016
|
+
});
|
4017
|
+
app.router.addRoute({
|
4018
|
+
path: "content-manager/*",
|
4019
|
+
lazy: async () => {
|
4020
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-CxxkX9jY.js"));
|
4021
|
+
return {
|
4022
|
+
Component: Layout
|
4023
|
+
};
|
4024
|
+
},
|
4025
|
+
children: routes
|
3132
4026
|
});
|
3133
4027
|
app.registerPlugin(cm.config);
|
3134
4028
|
},
|
4029
|
+
bootstrap(app) {
|
4030
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4031
|
+
historyAdmin.bootstrap(app);
|
4032
|
+
}
|
4033
|
+
},
|
3135
4034
|
async registerTrads({ locales }) {
|
3136
4035
|
const importedTrads = await Promise.all(
|
3137
4036
|
locales.map((locale) => {
|
3138
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-
|
4037
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-BlhnxQfj.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
|
3139
4038
|
return {
|
3140
4039
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3141
4040
|
locale
|
@@ -3152,6 +4051,8 @@ const index = {
|
|
3152
4051
|
}
|
3153
4052
|
};
|
3154
4053
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
4054
|
+
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4055
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3155
4056
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3156
4057
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3157
4058
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3178,8 +4079,8 @@ exports.getDisplayName = getDisplayName;
|
|
3178
4079
|
exports.getMainField = getMainField;
|
3179
4080
|
exports.getTranslation = getTranslation;
|
3180
4081
|
exports.index = index;
|
3181
|
-
exports.routes = routes;
|
3182
4082
|
exports.setInitialData = setInitialData;
|
4083
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3183
4084
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3184
4085
|
exports.useDoc = useDoc;
|
3185
4086
|
exports.useDocLayout = useDocLayout;
|
@@ -3192,4 +4093,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
|
3192
4093
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3193
4094
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
3194
4095
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3195
|
-
//# sourceMappingURL=index-
|
4096
|
+
//# sourceMappingURL=index-CBX6KyXv.js.map
|