@strapi/content-manager 0.0.0-experimental.745741d19e90275ca6f7c928ca19f9bb0fd9d933 → 0.0.0-experimental.76999222c105ee5da1bc2540e3b5e5f57747300c
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/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs → ComponentConfigurationPage-BUOQFZ08.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DHNM3YBz.mjs.map → ComponentConfigurationPage-BUOQFZ08.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js → ComponentConfigurationPage-WtZ2yaRP.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-BvHtG7uH.js.map → ComponentConfigurationPage-WtZ2yaRP.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js → EditConfigurationPage-BVrCP5lF.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-DOmfCEMo.js.map → EditConfigurationPage-BVrCP5lF.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs → EditConfigurationPage-D7HkxcAN.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-Cp6HAEzN.mjs.map → EditConfigurationPage-D7HkxcAN.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-BqNpC6hO.js → EditViewPage-BKQ83NAk.js} +30 -9
- package/dist/_chunks/EditViewPage-BKQ83NAk.js.map +1 -0
- package/dist/_chunks/{EditViewPage-BtkEx339.mjs → EditViewPage-zKmMBER4.mjs} +30 -9
- package/dist/_chunks/EditViewPage-zKmMBER4.mjs.map +1 -0
- package/dist/_chunks/{Field-R5NbffTB.mjs → Field-BbrX_tUG.mjs} +249 -152
- package/dist/_chunks/Field-BbrX_tUG.mjs.map +1 -0
- package/dist/_chunks/{Field-lsPFnAmH.js → Field-BhN0lyyZ.js} +251 -154
- package/dist/_chunks/Field-BhN0lyyZ.js.map +1 -0
- package/dist/_chunks/{Form-BHmXSfyy.mjs → Form-B-E8l73g.mjs} +36 -17
- package/dist/_chunks/Form-B-E8l73g.mjs.map +1 -0
- package/dist/_chunks/{Form-CcGboku8.js → Form-CkbrtNZd.js} +36 -17
- package/dist/_chunks/Form-CkbrtNZd.js.map +1 -0
- package/dist/_chunks/{History-Bsud8jwh.js → History-B2Dg9q7H.js} +61 -54
- package/dist/_chunks/History-B2Dg9q7H.js.map +1 -0
- package/dist/_chunks/{History-ByUPL3T3.mjs → History-C72HQ0-i.mjs} +62 -55
- package/dist/_chunks/History-C72HQ0-i.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DiT463qx.js → ListConfigurationPage-BQCc3BnJ.js} +21 -9
- package/dist/_chunks/ListConfigurationPage-BQCc3BnJ.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-Bm5HACXf.mjs → ListConfigurationPage-BalSo5dp.mjs} +21 -9
- package/dist/_chunks/ListConfigurationPage-BalSo5dp.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-CsrC9L_d.js → ListViewPage-Cu5dZKZe.js} +61 -41
- package/dist/_chunks/ListViewPage-Cu5dZKZe.js.map +1 -0
- package/dist/_chunks/{ListViewPage-JSyNAAYu.mjs → ListViewPage-Dfue5wQ2.mjs} +59 -39
- package/dist/_chunks/ListViewPage-Dfue5wQ2.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs → NoContentTypePage-BLC8M9U0.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CsrQUpBE.mjs.map → NoContentTypePage-BLC8M9U0.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-Bsvng4II.js → NoContentTypePage-MGzn4JPu.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-Bsvng4II.js.map → NoContentTypePage-MGzn4JPu.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs → NoPermissionsPage-BpAoEQy_.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DNmf_pj0.mjs.map → NoPermissionsPage-BpAoEQy_.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js → NoPermissionsPage-DJPwEpOD.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CdHNJtEf.js.map → NoPermissionsPage-DJPwEpOD.js.map} +1 -1
- package/dist/_chunks/{Relations-u8-37jK0.mjs → Relations-BULOkyWN.mjs} +73 -37
- package/dist/_chunks/Relations-BULOkyWN.mjs.map +1 -0
- package/dist/_chunks/{Relations-CghaPv2D.js → Relations-DTiqnyGx.js} +72 -36
- package/dist/_chunks/Relations-DTiqnyGx.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-C-J4DGEe.js} +20 -16
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-C-J4DGEe.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-DPfZ6tPQ.mjs} +20 -16
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-DPfZ6tPQ.mjs.map} +1 -1
- package/dist/_chunks/{es-EUonQTon.js → es-9K52xZIr.js} +2 -2
- package/dist/_chunks/{ja-CcFe8diO.js.map → es-9K52xZIr.js.map} +1 -1
- package/dist/_chunks/{es-CeXiYflN.mjs → es-D34tqjMw.mjs} +2 -2
- package/dist/_chunks/{es-CeXiYflN.mjs.map → es-D34tqjMw.mjs.map} +1 -1
- package/dist/_chunks/{fr-CD9VFbPM.mjs → fr--pg5jUbt.mjs} +13 -3
- package/dist/_chunks/{fr-CD9VFbPM.mjs.map → fr--pg5jUbt.mjs.map} +1 -1
- package/dist/_chunks/{fr-B7kGGg3E.js → fr-B2Kyv8Z9.js} +13 -3
- package/dist/_chunks/{fr-B7kGGg3E.js.map → fr-B2Kyv8Z9.js.map} +1 -1
- package/dist/_chunks/{index-BOZx6IMg.js → index-76eawJUd.js} +1034 -671
- package/dist/_chunks/index-76eawJUd.js.map +1 -0
- package/dist/_chunks/{index-CaE6NG4a.mjs → index-DW7xp_LG.mjs} +1052 -690
- package/dist/_chunks/index-DW7xp_LG.mjs.map +1 -0
- package/dist/_chunks/{ja-CcFe8diO.js → ja-7sfIbjxE.js} +2 -2
- package/dist/_chunks/{es-EUonQTon.js.map → ja-7sfIbjxE.js.map} +1 -1
- package/dist/_chunks/{ja-CtsUxOvk.mjs → ja-BHqhDq4V.mjs} +2 -2
- package/dist/_chunks/{ja-CtsUxOvk.mjs.map → ja-BHqhDq4V.mjs.map} +1 -1
- package/dist/_chunks/{layout-Ciz224q5.js → layout-CVz8WiDC.js} +22 -9
- package/dist/_chunks/layout-CVz8WiDC.js.map +1 -0
- package/dist/_chunks/{layout-Bx7svTbY.mjs → layout-DNfLIjbP.mjs} +23 -10
- package/dist/_chunks/layout-DNfLIjbP.mjs.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-CP8sB2YZ.js → relations-B6K4WRjW.js} +3 -7
- package/dist/_chunks/relations-B6K4WRjW.js.map +1 -0
- package/dist/_chunks/{relations-Cxc1cEv3.mjs → relations-ByHSIjSe.mjs} +3 -7
- package/dist/_chunks/relations-ByHSIjSe.mjs.map +1 -0
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +5 -4
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
- package/dist/admin/src/hooks/useDocument.d.ts +32 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +4 -48
- package/dist/admin/src/pages/EditView/components/Header.d.ts +11 -11
- package/dist/admin/src/preview/components/PreviewSidePanel.d.ts +3 -0
- package/dist/admin/src/preview/constants.d.ts +1 -0
- package/dist/admin/src/preview/index.d.ts +4 -0
- package/dist/admin/src/preview/services/preview.d.ts +3 -0
- package/dist/admin/src/services/api.d.ts +1 -1
- package/dist/admin/src/services/components.d.ts +2 -2
- package/dist/admin/src/services/contentTypes.d.ts +3 -3
- package/dist/admin/src/services/documents.d.ts +19 -17
- package/dist/admin/src/services/init.d.ts +1 -1
- package/dist/admin/src/services/relations.d.ts +2 -2
- package/dist/admin/src/services/uid.d.ts +3 -3
- package/dist/admin/src/utils/validation.d.ts +4 -1
- package/dist/server/index.js +544 -261
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +545 -262
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/utils/metadata.d.ts +15 -1
- package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
- package/dist/server/src/history/services/history.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +4 -4
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +4 -4
- package/dist/server/src/policies/hasPermissions.d.ts.map +1 -1
- package/dist/server/src/preview/constants.d.ts +2 -0
- package/dist/server/src/preview/constants.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/index.d.ts +2 -0
- package/dist/server/src/preview/controllers/index.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/preview.d.ts +13 -0
- package/dist/server/src/preview/controllers/preview.d.ts.map +1 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts +6 -0
- package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -0
- package/dist/server/src/preview/index.d.ts +4 -0
- package/dist/server/src/preview/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/index.d.ts +8 -0
- package/dist/server/src/preview/routes/index.d.ts.map +1 -0
- package/dist/server/src/preview/routes/preview.d.ts +4 -0
- package/dist/server/src/preview/routes/preview.d.ts.map +1 -0
- package/dist/server/src/preview/services/index.d.ts +15 -0
- package/dist/server/src/preview/services/index.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview-config.d.ts +30 -0
- package/dist/server/src/preview/services/preview-config.d.ts.map +1 -0
- package/dist/server/src/preview/services/preview.d.ts +12 -0
- package/dist/server/src/preview/services/preview.d.ts.map +1 -0
- package/dist/server/src/preview/utils.d.ts +18 -0
- package/dist/server/src/preview/utils.d.ts.map +1 -0
- package/dist/server/src/routes/index.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts +8 -8
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +4 -4
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
- package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/dist/server/src/utils/index.d.ts +2 -0
- package/dist/server/src/utils/index.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/dist/shared/contracts/index.d.ts +1 -0
- package/dist/shared/contracts/index.d.ts.map +1 -1
- package/dist/shared/contracts/preview.d.ts +27 -0
- package/dist/shared/contracts/preview.d.ts.map +1 -0
- package/dist/shared/index.js +4 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +4 -0
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +13 -13
- package/dist/_chunks/EditViewPage-BqNpC6hO.js.map +0 -1
- package/dist/_chunks/EditViewPage-BtkEx339.mjs.map +0 -1
- package/dist/_chunks/Field-R5NbffTB.mjs.map +0 -1
- package/dist/_chunks/Field-lsPFnAmH.js.map +0 -1
- package/dist/_chunks/Form-BHmXSfyy.mjs.map +0 -1
- package/dist/_chunks/Form-CcGboku8.js.map +0 -1
- package/dist/_chunks/History-Bsud8jwh.js.map +0 -1
- package/dist/_chunks/History-ByUPL3T3.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-Bm5HACXf.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DiT463qx.js.map +0 -1
- package/dist/_chunks/ListViewPage-CsrC9L_d.js.map +0 -1
- package/dist/_chunks/ListViewPage-JSyNAAYu.mjs.map +0 -1
- package/dist/_chunks/Relations-CghaPv2D.js.map +0 -1
- package/dist/_chunks/Relations-u8-37jK0.mjs.map +0 -1
- package/dist/_chunks/index-BOZx6IMg.js.map +0 -1
- package/dist/_chunks/index-CaE6NG4a.mjs.map +0 -1
- package/dist/_chunks/layout-Bx7svTbY.mjs.map +0 -1
- package/dist/_chunks/layout-Ciz224q5.js.map +0 -1
- package/dist/_chunks/relations-CP8sB2YZ.js.map +0 -1
- package/dist/_chunks/relations-Cxc1cEv3.mjs.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
@@ -2,15 +2,16 @@
|
|
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 mapValues = require("lodash/fp/mapValues");
|
8
|
+
const reactIntl = require("react-intl");
|
9
|
+
const reactRouterDom = require("react-router-dom");
|
11
10
|
const yup = require("yup");
|
12
11
|
const pipe = require("lodash/fp/pipe");
|
13
12
|
const dateFns = require("date-fns");
|
13
|
+
const styledComponents = require("styled-components");
|
14
|
+
const qs = require("qs");
|
14
15
|
const toolkit = require("@reduxjs/toolkit");
|
15
16
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
16
17
|
function _interopNamespace(e) {
|
@@ -32,6 +33,7 @@ function _interopNamespace(e) {
|
|
32
33
|
return Object.freeze(n);
|
33
34
|
}
|
34
35
|
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
36
|
+
const mapValues__default = /* @__PURE__ */ _interopDefault(mapValues);
|
35
37
|
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
|
36
38
|
const pipe__default = /* @__PURE__ */ _interopDefault(pipe);
|
37
39
|
const __variableDynamicImportRuntimeHelper = (glob, path) => {
|
@@ -70,42 +72,6 @@ const useInjectionZone = (area) => {
|
|
70
72
|
const [page, position] = area.split(".");
|
71
73
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
72
74
|
};
|
73
|
-
const HistoryAction = ({ model, document }) => {
|
74
|
-
const { formatMessage } = reactIntl.useIntl();
|
75
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
76
|
-
const navigate = reactRouterDom.useNavigate();
|
77
|
-
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
78
|
-
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
79
|
-
return null;
|
80
|
-
}
|
81
|
-
return {
|
82
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
83
|
-
label: formatMessage({
|
84
|
-
id: "content-manager.history.document-action",
|
85
|
-
defaultMessage: "Content History"
|
86
|
-
}),
|
87
|
-
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
88
|
-
disabled: (
|
89
|
-
/**
|
90
|
-
* The user is creating a new document.
|
91
|
-
* It hasn't been saved yet, so there's no history to go to
|
92
|
-
*/
|
93
|
-
!document || /**
|
94
|
-
* The document has been created but the current dimension has never been saved.
|
95
|
-
* For example, the user is creating a new locale in an existing document,
|
96
|
-
* so there's no history for the document in that locale
|
97
|
-
*/
|
98
|
-
!document.id || /**
|
99
|
-
* History is only available for content types created by the user.
|
100
|
-
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
101
|
-
* which start with `admin::` or `plugin::`
|
102
|
-
*/
|
103
|
-
!model.startsWith("api::")
|
104
|
-
),
|
105
|
-
position: "header"
|
106
|
-
};
|
107
|
-
};
|
108
|
-
HistoryAction.type = "history";
|
109
75
|
const ID = "id";
|
110
76
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
111
77
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -157,6 +123,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
157
123
|
if (!slug) {
|
158
124
|
throw new Error("Cannot find the slug param in the URL");
|
159
125
|
}
|
126
|
+
const [{ rawQuery }] = strapiAdmin.useQueryParams();
|
160
127
|
const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
|
161
128
|
const contentTypePermissions = React__namespace.useMemo(() => {
|
162
129
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -167,7 +134,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
167
134
|
return { ...acc, [action]: [permission] };
|
168
135
|
}, {});
|
169
136
|
}, [slug, userPermissions]);
|
170
|
-
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
137
|
+
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
138
|
+
contentTypePermissions,
|
139
|
+
permissions ?? void 0,
|
140
|
+
// TODO: useRBAC context should be typed and built differently
|
141
|
+
// We are passing raw query as context to the hook so that it can
|
142
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
143
|
+
rawQuery
|
144
|
+
);
|
171
145
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
172
146
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
173
147
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -215,7 +189,8 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
|
215
189
|
"Document",
|
216
190
|
"InitialData",
|
217
191
|
"HistoryVersion",
|
218
|
-
"Relations"
|
192
|
+
"Relations",
|
193
|
+
"UidAvailability"
|
219
194
|
]
|
220
195
|
});
|
221
196
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -229,7 +204,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
229
204
|
params: query
|
230
205
|
}
|
231
206
|
}),
|
232
|
-
invalidatesTags: (_result,
|
207
|
+
invalidatesTags: (_result, error, { model }) => {
|
208
|
+
if (error) {
|
209
|
+
return [];
|
210
|
+
}
|
211
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
212
|
+
}
|
233
213
|
}),
|
234
214
|
cloneDocument: builder.mutation({
|
235
215
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -240,7 +220,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
240
220
|
params
|
241
221
|
}
|
242
222
|
}),
|
243
|
-
invalidatesTags: (_result, _error, { model }) => [
|
223
|
+
invalidatesTags: (_result, _error, { model }) => [
|
224
|
+
{ type: "Document", id: `${model}_LIST` },
|
225
|
+
{ type: "UidAvailability", id: model }
|
226
|
+
]
|
244
227
|
}),
|
245
228
|
/**
|
246
229
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -257,7 +240,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
257
240
|
}),
|
258
241
|
invalidatesTags: (result, _error, { model }) => [
|
259
242
|
{ type: "Document", id: `${model}_LIST` },
|
260
|
-
"Relations"
|
243
|
+
"Relations",
|
244
|
+
{ type: "UidAvailability", id: model }
|
261
245
|
]
|
262
246
|
}),
|
263
247
|
deleteDocument: builder.mutation({
|
@@ -298,7 +282,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
298
282
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
299
283
|
},
|
300
284
|
{ type: "Document", id: `${model}_LIST` },
|
301
|
-
"Relations"
|
285
|
+
"Relations",
|
286
|
+
{ type: "UidAvailability", id: model }
|
302
287
|
];
|
303
288
|
}
|
304
289
|
}),
|
@@ -308,7 +293,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
308
293
|
*/
|
309
294
|
getAllDocuments: builder.query({
|
310
295
|
query: ({ model, params }) => ({
|
311
|
-
url: `/content-manager/collection-types/${model}`,
|
296
|
+
url: `/content-manager/collection-types/${model}${params ? `?${params}` : ""}`,
|
312
297
|
method: "GET",
|
313
298
|
config: {
|
314
299
|
params
|
@@ -316,6 +301,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
316
301
|
}),
|
317
302
|
providesTags: (result, _error, arg) => {
|
318
303
|
return [
|
304
|
+
{ type: "Document", id: `ALL_LIST` },
|
319
305
|
{ type: "Document", id: `${arg.model}_LIST` },
|
320
306
|
...result?.results.map(({ documentId }) => ({
|
321
307
|
type: "Document",
|
@@ -354,6 +340,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
354
340
|
{
|
355
341
|
type: "Document",
|
356
342
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
343
|
+
},
|
344
|
+
// Make it easy to invalidate all individual documents queries for a model
|
345
|
+
{
|
346
|
+
type: "Document",
|
347
|
+
id: `${model}_ALL_ITEMS`
|
357
348
|
}
|
358
349
|
];
|
359
350
|
}
|
@@ -417,8 +408,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
417
408
|
type: "Document",
|
418
409
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
419
410
|
},
|
420
|
-
"Relations"
|
411
|
+
"Relations",
|
412
|
+
{ type: "UidAvailability", id: model }
|
421
413
|
];
|
414
|
+
},
|
415
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
416
|
+
const patchResult = dispatch(
|
417
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
418
|
+
Object.assign(draft.data, data);
|
419
|
+
})
|
420
|
+
);
|
421
|
+
try {
|
422
|
+
await queryFulfilled;
|
423
|
+
} catch {
|
424
|
+
patchResult.undo();
|
425
|
+
}
|
422
426
|
}
|
423
427
|
}),
|
424
428
|
unpublishDocument: builder.mutation({
|
@@ -488,20 +492,39 @@ const buildValidParams = (query) => {
|
|
488
492
|
const isBaseQueryError = (error) => {
|
489
493
|
return error.name !== void 0;
|
490
494
|
};
|
491
|
-
const
|
495
|
+
const arrayValidator = (attribute, options) => ({
|
496
|
+
message: strapiAdmin.translatedErrors.required,
|
497
|
+
test(value) {
|
498
|
+
if (options.status === "draft") {
|
499
|
+
return true;
|
500
|
+
}
|
501
|
+
if (!attribute.required) {
|
502
|
+
return true;
|
503
|
+
}
|
504
|
+
if (!value) {
|
505
|
+
return false;
|
506
|
+
}
|
507
|
+
if (Array.isArray(value) && value.length === 0) {
|
508
|
+
return false;
|
509
|
+
}
|
510
|
+
return true;
|
511
|
+
}
|
512
|
+
});
|
513
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
492
514
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
493
515
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
494
516
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
495
517
|
return acc;
|
496
518
|
}
|
497
519
|
const validations = [
|
520
|
+
addNullableValidation,
|
498
521
|
addRequiredValidation,
|
499
522
|
addMinLengthValidation,
|
500
523
|
addMaxLengthValidation,
|
501
524
|
addMinValidation,
|
502
525
|
addMaxValidation,
|
503
526
|
addRegexValidation
|
504
|
-
].map((fn) => fn(attribute));
|
527
|
+
].map((fn) => fn(attribute, options));
|
505
528
|
const transformSchema = pipe__default.default(...validations);
|
506
529
|
switch (attribute.type) {
|
507
530
|
case "component": {
|
@@ -511,12 +534,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
511
534
|
...acc,
|
512
535
|
[name]: transformSchema(
|
513
536
|
yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
|
514
|
-
)
|
537
|
+
).test(arrayValidator(attribute, options))
|
515
538
|
};
|
516
539
|
} else {
|
517
540
|
return {
|
518
541
|
...acc,
|
519
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
542
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
520
543
|
};
|
521
544
|
}
|
522
545
|
}
|
@@ -538,7 +561,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
538
561
|
}
|
539
562
|
)
|
540
563
|
)
|
541
|
-
)
|
564
|
+
).test(arrayValidator(attribute, options))
|
542
565
|
};
|
543
566
|
case "relation":
|
544
567
|
return {
|
@@ -550,7 +573,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
550
573
|
} else if (Array.isArray(value)) {
|
551
574
|
return yup__namespace.array().of(
|
552
575
|
yup__namespace.object().shape({
|
553
|
-
id: yup__namespace.
|
576
|
+
id: yup__namespace.number().required()
|
554
577
|
})
|
555
578
|
);
|
556
579
|
} else if (typeof value === "object") {
|
@@ -602,6 +625,14 @@ const createAttributeSchema = (attribute) => {
|
|
602
625
|
if (!value || typeof value === "string" && value.length === 0) {
|
603
626
|
return true;
|
604
627
|
}
|
628
|
+
if (typeof value === "object") {
|
629
|
+
try {
|
630
|
+
JSON.stringify(value);
|
631
|
+
return true;
|
632
|
+
} catch (err) {
|
633
|
+
return false;
|
634
|
+
}
|
635
|
+
}
|
605
636
|
try {
|
606
637
|
JSON.parse(value);
|
607
638
|
return true;
|
@@ -620,13 +651,7 @@ const createAttributeSchema = (attribute) => {
|
|
620
651
|
return yup__namespace.mixed();
|
621
652
|
}
|
622
653
|
};
|
623
|
-
const
|
624
|
-
if (attribute.required && attribute.type !== "relation") {
|
625
|
-
return schema.required({
|
626
|
-
id: strapiAdmin.translatedErrors.required.id,
|
627
|
-
defaultMessage: "This field is required."
|
628
|
-
});
|
629
|
-
}
|
654
|
+
const nullableSchema = (schema) => {
|
630
655
|
return schema?.nullable ? schema.nullable() : (
|
631
656
|
// In some cases '.nullable' will not be available on the schema.
|
632
657
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -634,7 +659,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
634
659
|
schema
|
635
660
|
);
|
636
661
|
};
|
637
|
-
const
|
662
|
+
const addNullableValidation = () => (schema) => {
|
663
|
+
return nullableSchema(schema);
|
664
|
+
};
|
665
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
666
|
+
if (options.status === "draft" || !attribute.required) {
|
667
|
+
return schema;
|
668
|
+
}
|
669
|
+
if (attribute.required && "required" in schema) {
|
670
|
+
return schema.required(strapiAdmin.translatedErrors.required);
|
671
|
+
}
|
672
|
+
return schema;
|
673
|
+
};
|
674
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
675
|
+
if (options.status === "draft") {
|
676
|
+
return schema;
|
677
|
+
}
|
638
678
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
639
679
|
return schema.min(attribute.minLength, {
|
640
680
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -656,10 +696,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
656
696
|
}
|
657
697
|
return schema;
|
658
698
|
};
|
659
|
-
const addMinValidation = (attribute) => (schema) => {
|
660
|
-
if ("
|
699
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
700
|
+
if (options.status === "draft") {
|
701
|
+
return schema;
|
702
|
+
}
|
703
|
+
if ("min" in attribute && "min" in schema) {
|
661
704
|
const min = toInteger(attribute.min);
|
662
|
-
if (
|
705
|
+
if (min) {
|
663
706
|
return schema.min(min, {
|
664
707
|
...strapiAdmin.translatedErrors.min,
|
665
708
|
values: {
|
@@ -777,19 +820,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
777
820
|
}, {});
|
778
821
|
return componentsByKey;
|
779
822
|
};
|
780
|
-
const
|
823
|
+
const HOOKS = {
|
824
|
+
/**
|
825
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
826
|
+
* @constant
|
827
|
+
* @type {string}
|
828
|
+
*/
|
829
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
830
|
+
/**
|
831
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
832
|
+
* @constant
|
833
|
+
* @type {string}
|
834
|
+
*/
|
835
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
836
|
+
/**
|
837
|
+
* Hook that allows to mutate the CM's edit view layout
|
838
|
+
* @constant
|
839
|
+
* @type {string}
|
840
|
+
*/
|
841
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
842
|
+
/**
|
843
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
844
|
+
* @constant
|
845
|
+
* @type {string}
|
846
|
+
*/
|
847
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
848
|
+
};
|
849
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
850
|
+
endpoints: (builder) => ({
|
851
|
+
getContentTypeConfiguration: builder.query({
|
852
|
+
query: (uid) => ({
|
853
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
854
|
+
method: "GET"
|
855
|
+
}),
|
856
|
+
transformResponse: (response) => response.data,
|
857
|
+
providesTags: (_result, _error, uid) => [
|
858
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
859
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
860
|
+
]
|
861
|
+
}),
|
862
|
+
getAllContentTypeSettings: builder.query({
|
863
|
+
query: () => "/content-manager/content-types-settings",
|
864
|
+
transformResponse: (response) => response.data,
|
865
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
866
|
+
}),
|
867
|
+
updateContentTypeConfiguration: builder.mutation({
|
868
|
+
query: ({ uid, ...body }) => ({
|
869
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
870
|
+
method: "PUT",
|
871
|
+
data: body
|
872
|
+
}),
|
873
|
+
transformResponse: (response) => response.data,
|
874
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
875
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
876
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
877
|
+
// Is this necessary?
|
878
|
+
{ type: "InitialData" }
|
879
|
+
]
|
880
|
+
})
|
881
|
+
})
|
882
|
+
});
|
883
|
+
const {
|
884
|
+
useGetContentTypeConfigurationQuery,
|
885
|
+
useGetAllContentTypeSettingsQuery,
|
886
|
+
useUpdateContentTypeConfigurationMutation
|
887
|
+
} = contentTypesApi;
|
888
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
889
|
+
const { type } = attribute;
|
890
|
+
if (type === "relation") {
|
891
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
892
|
+
}
|
893
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
894
|
+
};
|
895
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
896
|
+
if (!mainFieldName) {
|
897
|
+
return void 0;
|
898
|
+
}
|
899
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
900
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
901
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
902
|
+
);
|
903
|
+
return {
|
904
|
+
name: mainFieldName,
|
905
|
+
type: mainFieldType ?? "string"
|
906
|
+
};
|
907
|
+
};
|
908
|
+
const DEFAULT_SETTINGS = {
|
909
|
+
bulkable: false,
|
910
|
+
filterable: false,
|
911
|
+
searchable: false,
|
912
|
+
pagination: false,
|
913
|
+
defaultSortBy: "",
|
914
|
+
defaultSortOrder: "asc",
|
915
|
+
mainField: "id",
|
916
|
+
pageSize: 10
|
917
|
+
};
|
918
|
+
const useDocumentLayout = (model) => {
|
919
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
920
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
921
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
781
922
|
const { toggleNotification } = strapiAdmin.useNotification();
|
782
923
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
924
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
783
925
|
const {
|
784
|
-
|
785
|
-
isLoading:
|
786
|
-
|
787
|
-
|
788
|
-
} =
|
789
|
-
|
790
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
791
|
-
});
|
792
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
926
|
+
data,
|
927
|
+
isLoading: isLoadingConfigs,
|
928
|
+
error,
|
929
|
+
isFetching: isFetchingConfigs
|
930
|
+
} = useGetContentTypeConfigurationQuery(model);
|
931
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
793
932
|
React__namespace.useEffect(() => {
|
794
933
|
if (error) {
|
795
934
|
toggleNotification({
|
@@ -797,45 +936,261 @@ const useDocument = (args, opts) => {
|
|
797
936
|
message: formatAPIError(error)
|
798
937
|
});
|
799
938
|
}
|
800
|
-
}, [
|
801
|
-
const
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
(document) => {
|
809
|
-
if (!validationSchema) {
|
810
|
-
throw new Error(
|
811
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
812
|
-
);
|
813
|
-
}
|
814
|
-
try {
|
815
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
816
|
-
return null;
|
817
|
-
} catch (error2) {
|
818
|
-
if (error2 instanceof yup.ValidationError) {
|
819
|
-
return strapiAdmin.getYupValidationErrors(error2);
|
820
|
-
}
|
821
|
-
throw error2;
|
822
|
-
}
|
939
|
+
}, [error, formatAPIError, toggleNotification]);
|
940
|
+
const editLayout = React__namespace.useMemo(
|
941
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
942
|
+
layout: [],
|
943
|
+
components: {},
|
944
|
+
metadatas: {},
|
945
|
+
options: {},
|
946
|
+
settings: DEFAULT_SETTINGS
|
823
947
|
},
|
824
|
-
[
|
948
|
+
[data, isLoading, schemas, schema, components]
|
949
|
+
);
|
950
|
+
const listLayout = React__namespace.useMemo(() => {
|
951
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
952
|
+
layout: [],
|
953
|
+
metadatas: {},
|
954
|
+
options: {},
|
955
|
+
settings: DEFAULT_SETTINGS
|
956
|
+
};
|
957
|
+
}, [data, isLoading, schemas, schema, components]);
|
958
|
+
const { layout: edit } = React__namespace.useMemo(
|
959
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
960
|
+
layout: editLayout,
|
961
|
+
query
|
962
|
+
}),
|
963
|
+
[editLayout, query, runHookWaterfall]
|
825
964
|
);
|
826
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
827
965
|
return {
|
828
|
-
|
829
|
-
document: data?.data,
|
830
|
-
meta: data?.meta,
|
966
|
+
error,
|
831
967
|
isLoading,
|
832
|
-
|
833
|
-
|
968
|
+
edit,
|
969
|
+
list: listLayout
|
834
970
|
};
|
835
971
|
};
|
836
|
-
const
|
837
|
-
const {
|
838
|
-
|
972
|
+
const useDocLayout = () => {
|
973
|
+
const { model } = useDoc();
|
974
|
+
return useDocumentLayout(model);
|
975
|
+
};
|
976
|
+
const formatEditLayout = (data, {
|
977
|
+
schemas,
|
978
|
+
schema,
|
979
|
+
components
|
980
|
+
}) => {
|
981
|
+
let currentPanelIndex = 0;
|
982
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
983
|
+
data.contentType.layouts.edit,
|
984
|
+
schema?.attributes,
|
985
|
+
data.contentType.metadatas,
|
986
|
+
{ configurations: data.components, schemas: components },
|
987
|
+
schemas
|
988
|
+
).reduce((panels, row) => {
|
989
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
990
|
+
panels.push([row]);
|
991
|
+
currentPanelIndex += 2;
|
992
|
+
} else {
|
993
|
+
if (!panels[currentPanelIndex]) {
|
994
|
+
panels.push([row]);
|
995
|
+
} else {
|
996
|
+
panels[currentPanelIndex].push(row);
|
997
|
+
}
|
998
|
+
}
|
999
|
+
return panels;
|
1000
|
+
}, []);
|
1001
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
1002
|
+
(acc, [uid, configuration]) => {
|
1003
|
+
acc[uid] = {
|
1004
|
+
layout: convertEditLayoutToFieldLayouts(
|
1005
|
+
configuration.layouts.edit,
|
1006
|
+
components[uid].attributes,
|
1007
|
+
configuration.metadatas,
|
1008
|
+
{ configurations: data.components, schemas: components }
|
1009
|
+
),
|
1010
|
+
settings: {
|
1011
|
+
...configuration.settings,
|
1012
|
+
icon: components[uid].info.icon,
|
1013
|
+
displayName: components[uid].info.displayName
|
1014
|
+
}
|
1015
|
+
};
|
1016
|
+
return acc;
|
1017
|
+
},
|
1018
|
+
{}
|
1019
|
+
);
|
1020
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1021
|
+
(acc, [attribute, metadata]) => {
|
1022
|
+
return {
|
1023
|
+
...acc,
|
1024
|
+
[attribute]: metadata.edit
|
1025
|
+
};
|
1026
|
+
},
|
1027
|
+
{}
|
1028
|
+
);
|
1029
|
+
return {
|
1030
|
+
layout: panelledEditAttributes,
|
1031
|
+
components: componentEditAttributes,
|
1032
|
+
metadatas: editMetadatas,
|
1033
|
+
settings: {
|
1034
|
+
...data.contentType.settings,
|
1035
|
+
displayName: schema?.info.displayName
|
1036
|
+
},
|
1037
|
+
options: {
|
1038
|
+
...schema?.options,
|
1039
|
+
...schema?.pluginOptions,
|
1040
|
+
...data.contentType.options
|
1041
|
+
}
|
1042
|
+
};
|
1043
|
+
};
|
1044
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1045
|
+
return rows.map(
|
1046
|
+
(row) => row.map((field) => {
|
1047
|
+
const attribute = attributes[field.name];
|
1048
|
+
if (!attribute) {
|
1049
|
+
return null;
|
1050
|
+
}
|
1051
|
+
const { edit: metadata } = metadatas[field.name];
|
1052
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1053
|
+
return {
|
1054
|
+
attribute,
|
1055
|
+
disabled: !metadata.editable,
|
1056
|
+
hint: metadata.description,
|
1057
|
+
label: metadata.label ?? "",
|
1058
|
+
name: field.name,
|
1059
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1060
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1061
|
+
schemas,
|
1062
|
+
components: components?.schemas ?? {}
|
1063
|
+
}),
|
1064
|
+
placeholder: metadata.placeholder ?? "",
|
1065
|
+
required: attribute.required ?? false,
|
1066
|
+
size: field.size,
|
1067
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1068
|
+
visible: metadata.visible ?? true,
|
1069
|
+
type: attribute.type
|
1070
|
+
};
|
1071
|
+
}).filter((field) => field !== null)
|
1072
|
+
);
|
1073
|
+
};
|
1074
|
+
const formatListLayout = (data, {
|
1075
|
+
schemas,
|
1076
|
+
schema,
|
1077
|
+
components
|
1078
|
+
}) => {
|
1079
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1080
|
+
(acc, [attribute, metadata]) => {
|
1081
|
+
return {
|
1082
|
+
...acc,
|
1083
|
+
[attribute]: metadata.list
|
1084
|
+
};
|
1085
|
+
},
|
1086
|
+
{}
|
1087
|
+
);
|
1088
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1089
|
+
data.contentType.layouts.list,
|
1090
|
+
schema?.attributes,
|
1091
|
+
listMetadatas,
|
1092
|
+
{ configurations: data.components, schemas: components },
|
1093
|
+
schemas
|
1094
|
+
);
|
1095
|
+
return {
|
1096
|
+
layout: listAttributes,
|
1097
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1098
|
+
metadatas: listMetadatas,
|
1099
|
+
options: {
|
1100
|
+
...schema?.options,
|
1101
|
+
...schema?.pluginOptions,
|
1102
|
+
...data.contentType.options
|
1103
|
+
}
|
1104
|
+
};
|
1105
|
+
};
|
1106
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1107
|
+
return columns.map((name) => {
|
1108
|
+
const attribute = attributes[name];
|
1109
|
+
if (!attribute) {
|
1110
|
+
return null;
|
1111
|
+
}
|
1112
|
+
const metadata = metadatas[name];
|
1113
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1114
|
+
return {
|
1115
|
+
attribute,
|
1116
|
+
label: metadata.label ?? "",
|
1117
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1118
|
+
schemas,
|
1119
|
+
components: components?.schemas ?? {}
|
1120
|
+
}),
|
1121
|
+
name,
|
1122
|
+
searchable: metadata.searchable ?? true,
|
1123
|
+
sortable: metadata.sortable ?? true
|
1124
|
+
};
|
1125
|
+
}).filter((field) => field !== null);
|
1126
|
+
};
|
1127
|
+
const useDocument = (args, opts) => {
|
1128
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1129
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1130
|
+
const {
|
1131
|
+
currentData: data,
|
1132
|
+
isLoading: isLoadingDocument,
|
1133
|
+
isFetching: isFetchingDocument,
|
1134
|
+
error
|
1135
|
+
} = useGetDocumentQuery(args, {
|
1136
|
+
...opts,
|
1137
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1138
|
+
});
|
1139
|
+
const {
|
1140
|
+
components,
|
1141
|
+
schema,
|
1142
|
+
schemas,
|
1143
|
+
isLoading: isLoadingSchema
|
1144
|
+
} = useContentTypeSchema(args.model);
|
1145
|
+
React__namespace.useEffect(() => {
|
1146
|
+
if (error) {
|
1147
|
+
toggleNotification({
|
1148
|
+
type: "danger",
|
1149
|
+
message: formatAPIError(error)
|
1150
|
+
});
|
1151
|
+
}
|
1152
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1153
|
+
const validationSchema = React__namespace.useMemo(() => {
|
1154
|
+
if (!schema) {
|
1155
|
+
return null;
|
1156
|
+
}
|
1157
|
+
return createYupSchema(schema.attributes, components);
|
1158
|
+
}, [schema, components]);
|
1159
|
+
const validate = React__namespace.useCallback(
|
1160
|
+
(document) => {
|
1161
|
+
if (!validationSchema) {
|
1162
|
+
throw new Error(
|
1163
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1164
|
+
);
|
1165
|
+
}
|
1166
|
+
try {
|
1167
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1168
|
+
return null;
|
1169
|
+
} catch (error2) {
|
1170
|
+
if (error2 instanceof yup.ValidationError) {
|
1171
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
1172
|
+
}
|
1173
|
+
throw error2;
|
1174
|
+
}
|
1175
|
+
},
|
1176
|
+
[validationSchema]
|
1177
|
+
);
|
1178
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1179
|
+
const hasError = !!error;
|
1180
|
+
return {
|
1181
|
+
components,
|
1182
|
+
document: data?.data,
|
1183
|
+
meta: data?.meta,
|
1184
|
+
isLoading,
|
1185
|
+
hasError,
|
1186
|
+
schema,
|
1187
|
+
schemas,
|
1188
|
+
validate
|
1189
|
+
};
|
1190
|
+
};
|
1191
|
+
const useDoc = () => {
|
1192
|
+
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
1193
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
839
1194
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
840
1195
|
if (!collectionType) {
|
841
1196
|
throw new Error("Could not find collectionType in url params");
|
@@ -843,22 +1198,60 @@ const useDoc = () => {
|
|
843
1198
|
if (!slug) {
|
844
1199
|
throw new Error("Could not find model in url params");
|
845
1200
|
}
|
1201
|
+
const document = useDocument(
|
1202
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1203
|
+
{
|
1204
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1205
|
+
}
|
1206
|
+
);
|
1207
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
846
1208
|
return {
|
847
1209
|
collectionType,
|
848
1210
|
model: slug,
|
849
|
-
id:
|
850
|
-
...
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
1211
|
+
id: returnId,
|
1212
|
+
...document
|
1213
|
+
};
|
1214
|
+
};
|
1215
|
+
const useContentManagerContext = () => {
|
1216
|
+
const {
|
1217
|
+
collectionType,
|
1218
|
+
model,
|
1219
|
+
id,
|
1220
|
+
components,
|
1221
|
+
isLoading: isLoadingDoc,
|
1222
|
+
schema,
|
1223
|
+
schemas
|
1224
|
+
} = useDoc();
|
1225
|
+
const layout = useDocumentLayout(model);
|
1226
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1227
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1228
|
+
const slug = model;
|
1229
|
+
const isCreatingEntry = id === "create";
|
1230
|
+
useContentTypeSchema();
|
1231
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1232
|
+
const error = layout.error;
|
1233
|
+
return {
|
1234
|
+
error,
|
1235
|
+
isLoading,
|
1236
|
+
// Base metadata
|
1237
|
+
model,
|
1238
|
+
collectionType,
|
1239
|
+
id,
|
1240
|
+
slug,
|
1241
|
+
isCreatingEntry,
|
1242
|
+
isSingleType,
|
1243
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1244
|
+
// All schema infos
|
1245
|
+
components,
|
1246
|
+
contentType: schema,
|
1247
|
+
contentTypes: schemas,
|
1248
|
+
// Form state
|
1249
|
+
form,
|
1250
|
+
// layout infos
|
1251
|
+
layout
|
856
1252
|
};
|
857
1253
|
};
|
858
1254
|
const prefixPluginTranslations = (trad, pluginId) => {
|
859
|
-
if (!pluginId) {
|
860
|
-
throw new TypeError("pluginId can't be empty");
|
861
|
-
}
|
862
1255
|
return Object.keys(trad).reduce((acc, current) => {
|
863
1256
|
acc[`${pluginId}.${current}`] = trad[current];
|
864
1257
|
return acc;
|
@@ -874,6 +1267,8 @@ const useDocumentActions = () => {
|
|
874
1267
|
const { formatMessage } = reactIntl.useIntl();
|
875
1268
|
const { trackUsage } = strapiAdmin.useTracking();
|
876
1269
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1270
|
+
const navigate = reactRouterDom.useNavigate();
|
1271
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
877
1272
|
const [deleteDocument] = useDeleteDocumentMutation();
|
878
1273
|
const _delete = React__namespace.useCallback(
|
879
1274
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1188,6 +1583,7 @@ const useDocumentActions = () => {
|
|
1188
1583
|
defaultMessage: "Saved document"
|
1189
1584
|
})
|
1190
1585
|
});
|
1586
|
+
setCurrentStep("contentManager.success");
|
1191
1587
|
return res.data;
|
1192
1588
|
} catch (err) {
|
1193
1589
|
toggleNotification({
|
@@ -1209,7 +1605,6 @@ const useDocumentActions = () => {
|
|
1209
1605
|
sourceId
|
1210
1606
|
});
|
1211
1607
|
if ("error" in res) {
|
1212
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1213
1608
|
return { error: res.error };
|
1214
1609
|
}
|
1215
1610
|
toggleNotification({
|
@@ -1228,7 +1623,7 @@ const useDocumentActions = () => {
|
|
1228
1623
|
throw err;
|
1229
1624
|
}
|
1230
1625
|
},
|
1231
|
-
[autoCloneDocument,
|
1626
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1232
1627
|
);
|
1233
1628
|
const [cloneDocument] = useCloneDocumentMutation();
|
1234
1629
|
const clone = React__namespace.useCallback(
|
@@ -1254,6 +1649,7 @@ const useDocumentActions = () => {
|
|
1254
1649
|
defaultMessage: "Cloned document"
|
1255
1650
|
})
|
1256
1651
|
});
|
1652
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1257
1653
|
return res.data;
|
1258
1654
|
} catch (err) {
|
1259
1655
|
toggleNotification({
|
@@ -1264,7 +1660,7 @@ const useDocumentActions = () => {
|
|
1264
1660
|
throw err;
|
1265
1661
|
}
|
1266
1662
|
},
|
1267
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1663
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1268
1664
|
);
|
1269
1665
|
const [getDoc] = useLazyGetDocumentQuery();
|
1270
1666
|
const getDocument = React__namespace.useCallback(
|
@@ -1290,7 +1686,7 @@ const useDocumentActions = () => {
|
|
1290
1686
|
};
|
1291
1687
|
};
|
1292
1688
|
const ProtectedHistoryPage = React.lazy(
|
1293
|
-
() => Promise.resolve().then(() => require("./History-
|
1689
|
+
() => Promise.resolve().then(() => require("./History-B2Dg9q7H.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1294
1690
|
);
|
1295
1691
|
const routes$1 = [
|
1296
1692
|
{
|
@@ -1303,31 +1699,31 @@ const routes$1 = [
|
|
1303
1699
|
}
|
1304
1700
|
];
|
1305
1701
|
const ProtectedEditViewPage = React.lazy(
|
1306
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1702
|
+
() => Promise.resolve().then(() => require("./EditViewPage-BKQ83NAk.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1307
1703
|
);
|
1308
1704
|
const ProtectedListViewPage = React.lazy(
|
1309
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1705
|
+
() => Promise.resolve().then(() => require("./ListViewPage-Cu5dZKZe.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1310
1706
|
);
|
1311
1707
|
const ProtectedListConfiguration = React.lazy(
|
1312
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1708
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-BQCc3BnJ.js")).then((mod) => ({
|
1313
1709
|
default: mod.ProtectedListConfiguration
|
1314
1710
|
}))
|
1315
1711
|
);
|
1316
1712
|
const ProtectedEditConfigurationPage = React.lazy(
|
1317
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1713
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-BVrCP5lF.js")).then((mod) => ({
|
1318
1714
|
default: mod.ProtectedEditConfigurationPage
|
1319
1715
|
}))
|
1320
1716
|
);
|
1321
1717
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1322
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1718
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-WtZ2yaRP.js")).then((mod) => ({
|
1323
1719
|
default: mod.ProtectedComponentConfigurationPage
|
1324
1720
|
}))
|
1325
1721
|
);
|
1326
1722
|
const NoPermissions = React.lazy(
|
1327
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1723
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-DJPwEpOD.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1328
1724
|
);
|
1329
1725
|
const NoContentType = React.lazy(
|
1330
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1726
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-MGzn4JPu.js")).then((mod) => ({ default: mod.NoContentType }))
|
1331
1727
|
);
|
1332
1728
|
const CollectionTypePages = () => {
|
1333
1729
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1441,12 +1837,14 @@ const DocumentActionButton = (action) => {
|
|
1441
1837
|
/* @__PURE__ */ jsxRuntime.jsx(
|
1442
1838
|
designSystem.Button,
|
1443
1839
|
{
|
1444
|
-
flex:
|
1840
|
+
flex: "auto",
|
1445
1841
|
startIcon: action.icon,
|
1446
1842
|
disabled: action.disabled,
|
1447
1843
|
onClick: handleClick(action),
|
1448
1844
|
justifyContent: "center",
|
1449
1845
|
variant: action.variant || "default",
|
1846
|
+
paddingTop: "7px",
|
1847
|
+
paddingBottom: "7px",
|
1450
1848
|
children: action.label
|
1451
1849
|
}
|
1452
1850
|
),
|
@@ -1454,7 +1852,7 @@ const DocumentActionButton = (action) => {
|
|
1454
1852
|
DocumentActionConfirmDialog,
|
1455
1853
|
{
|
1456
1854
|
...action.dialog,
|
1457
|
-
variant: action.variant,
|
1855
|
+
variant: action.dialog?.variant ?? action.variant,
|
1458
1856
|
isOpen: dialogId === action.id,
|
1459
1857
|
onClose: handleClose
|
1460
1858
|
}
|
@@ -1511,9 +1909,9 @@ const DocumentActionsMenu = ({
|
|
1511
1909
|
disabled: isDisabled,
|
1512
1910
|
size: "S",
|
1513
1911
|
endIcon: null,
|
1514
|
-
paddingTop: "
|
1515
|
-
paddingLeft: "
|
1516
|
-
paddingRight: "
|
1912
|
+
paddingTop: "4px",
|
1913
|
+
paddingLeft: "7px",
|
1914
|
+
paddingRight: "7px",
|
1517
1915
|
variant,
|
1518
1916
|
children: [
|
1519
1917
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
@@ -1524,7 +1922,7 @@ const DocumentActionsMenu = ({
|
|
1524
1922
|
]
|
1525
1923
|
}
|
1526
1924
|
),
|
1527
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, {
|
1925
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1528
1926
|
actions2.map((action) => {
|
1529
1927
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
1530
1928
|
designSystem.Menu.Item,
|
@@ -1533,10 +1931,25 @@ const DocumentActionsMenu = ({
|
|
1533
1931
|
onSelect: handleClick(action),
|
1534
1932
|
display: "block",
|
1535
1933
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1536
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1934
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1935
|
+
designSystem.Flex,
|
1936
|
+
{
|
1937
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1938
|
+
gap: 2,
|
1939
|
+
tag: "span",
|
1940
|
+
children: [
|
1941
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1942
|
+
designSystem.Flex,
|
1943
|
+
{
|
1944
|
+
tag: "span",
|
1945
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1946
|
+
children: action.icon
|
1947
|
+
}
|
1948
|
+
),
|
1949
|
+
action.label
|
1950
|
+
]
|
1951
|
+
}
|
1952
|
+
),
|
1540
1953
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1541
1954
|
designSystem.Flex,
|
1542
1955
|
{
|
@@ -1633,11 +2046,11 @@ const DocumentActionConfirmDialog = ({
|
|
1633
2046
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1634
2047
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1635
2048
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1636
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
2049
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1637
2050
|
id: "app.components.Button.cancel",
|
1638
2051
|
defaultMessage: "Cancel"
|
1639
2052
|
}) }) }),
|
1640
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2053
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1641
2054
|
id: "app.components.Button.confirm",
|
1642
2055
|
defaultMessage: "Confirm"
|
1643
2056
|
}) })
|
@@ -1660,10 +2073,22 @@ const DocumentActionModal = ({
|
|
1660
2073
|
};
|
1661
2074
|
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
1662
2075
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
1663
|
-
|
1664
|
-
|
2076
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
|
2077
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
1665
2078
|
] }) });
|
1666
2079
|
};
|
2080
|
+
const transformData = (data) => {
|
2081
|
+
if (Array.isArray(data)) {
|
2082
|
+
return data.map(transformData);
|
2083
|
+
}
|
2084
|
+
if (typeof data === "object" && data !== null) {
|
2085
|
+
if ("apiData" in data) {
|
2086
|
+
return data.apiData;
|
2087
|
+
}
|
2088
|
+
return mapValues__default.default(transformData)(data);
|
2089
|
+
}
|
2090
|
+
return data;
|
2091
|
+
};
|
1667
2092
|
const PublishAction$1 = ({
|
1668
2093
|
activeTab,
|
1669
2094
|
documentId,
|
@@ -1676,13 +2101,17 @@ const PublishAction$1 = ({
|
|
1676
2101
|
const navigate = reactRouterDom.useNavigate();
|
1677
2102
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1678
2103
|
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2104
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
1679
2105
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
1680
2106
|
const { formatMessage } = reactIntl.useIntl();
|
1681
|
-
const { canPublish
|
1682
|
-
"PublishAction",
|
1683
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1684
|
-
);
|
2107
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1685
2108
|
const { publish } = useDocumentActions();
|
2109
|
+
const [
|
2110
|
+
countDraftRelations,
|
2111
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2112
|
+
] = useLazyGetDraftRelationCountQuery();
|
2113
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2114
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1686
2115
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1687
2116
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1688
2117
|
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1691,62 +2120,144 @@ const PublishAction$1 = ({
|
|
1691
2120
|
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1692
2121
|
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1693
2122
|
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
2123
|
+
React__namespace.useEffect(() => {
|
2124
|
+
if (isErrorDraftRelations) {
|
2125
|
+
toggleNotification({
|
2126
|
+
type: "danger",
|
2127
|
+
message: formatMessage({
|
2128
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2129
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2130
|
+
})
|
2131
|
+
});
|
2132
|
+
}
|
2133
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2134
|
+
React__namespace.useEffect(() => {
|
2135
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2136
|
+
const extractDraftRelations = (data) => {
|
2137
|
+
const relations = data.connect || [];
|
2138
|
+
relations.forEach((relation) => {
|
2139
|
+
if (relation.status === "draft") {
|
2140
|
+
localDraftRelations.add(relation.id);
|
2141
|
+
}
|
2142
|
+
});
|
2143
|
+
};
|
2144
|
+
const traverseAndExtract = (data) => {
|
2145
|
+
Object.entries(data).forEach(([key, value]) => {
|
2146
|
+
if (key === "connect" && Array.isArray(value)) {
|
2147
|
+
extractDraftRelations({ connect: value });
|
2148
|
+
} else if (typeof value === "object" && value !== null) {
|
2149
|
+
traverseAndExtract(value);
|
2150
|
+
}
|
2151
|
+
});
|
2152
|
+
};
|
2153
|
+
if (!documentId || modified) {
|
2154
|
+
traverseAndExtract(formValues);
|
2155
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2156
|
+
}
|
2157
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2158
|
+
React__namespace.useEffect(() => {
|
2159
|
+
if (!document || !document.documentId || isListView) {
|
2160
|
+
return;
|
2161
|
+
}
|
2162
|
+
const fetchDraftRelationsCount = async () => {
|
2163
|
+
const { data, error } = await countDraftRelations({
|
2164
|
+
collectionType,
|
2165
|
+
model,
|
2166
|
+
documentId,
|
2167
|
+
params
|
2168
|
+
});
|
2169
|
+
if (error) {
|
2170
|
+
throw error;
|
2171
|
+
}
|
2172
|
+
if (data) {
|
2173
|
+
setServerCountOfDraftRelations(data.data);
|
2174
|
+
}
|
2175
|
+
};
|
2176
|
+
fetchDraftRelationsCount();
|
2177
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2178
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2179
|
+
if (!schema?.options?.draftAndPublish) {
|
2180
|
+
return null;
|
2181
|
+
}
|
2182
|
+
const performPublish = async () => {
|
2183
|
+
setSubmitting(true);
|
2184
|
+
try {
|
2185
|
+
const { errors } = await validate(true, {
|
2186
|
+
status: "published"
|
2187
|
+
});
|
2188
|
+
if (errors) {
|
2189
|
+
toggleNotification({
|
2190
|
+
type: "danger",
|
2191
|
+
message: formatMessage({
|
2192
|
+
id: "content-manager.validation.error",
|
2193
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2194
|
+
})
|
2195
|
+
});
|
2196
|
+
return;
|
2197
|
+
}
|
2198
|
+
const res = await publish(
|
2199
|
+
{
|
2200
|
+
collectionType,
|
2201
|
+
model,
|
2202
|
+
documentId,
|
2203
|
+
params
|
2204
|
+
},
|
2205
|
+
transformData(formValues)
|
2206
|
+
);
|
2207
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2208
|
+
navigate({
|
2209
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2210
|
+
search: rawQuery
|
2211
|
+
});
|
2212
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2213
|
+
setErrors(formatValidationErrors(res.error));
|
2214
|
+
}
|
2215
|
+
} finally {
|
2216
|
+
setSubmitting(false);
|
2217
|
+
}
|
2218
|
+
};
|
2219
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2220
|
+
const enableDraftRelationsCount = false;
|
2221
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
2222
|
+
return {
|
2223
|
+
/**
|
2224
|
+
* Disabled when:
|
2225
|
+
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
2226
|
+
* - the form is submitting
|
2227
|
+
* - the active tab is the published tab
|
1704
2228
|
* - the document is already published & not modified
|
1705
2229
|
* - the document is being created & not modified
|
1706
2230
|
* - the user doesn't have the permission to publish
|
1707
|
-
* - the user doesn't have the permission to create a new document
|
1708
|
-
* - the user doesn't have the permission to update the document
|
1709
2231
|
*/
|
1710
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2232
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1711
2233
|
label: formatMessage({
|
1712
2234
|
id: "app.utils.publish",
|
1713
2235
|
defaultMessage: "Publish"
|
1714
2236
|
}),
|
1715
2237
|
onClick: async () => {
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
documentId,
|
1734
|
-
params
|
1735
|
-
},
|
1736
|
-
formValues
|
1737
|
-
);
|
1738
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1739
|
-
navigate({
|
1740
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1741
|
-
search: rawQuery
|
1742
|
-
});
|
1743
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1744
|
-
setErrors(formatValidationErrors(res.error));
|
2238
|
+
await performPublish();
|
2239
|
+
},
|
2240
|
+
dialog: hasDraftRelations ? {
|
2241
|
+
type: "dialog",
|
2242
|
+
variant: "danger",
|
2243
|
+
footer: null,
|
2244
|
+
title: formatMessage({
|
2245
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2246
|
+
defaultMessage: "Confirmation"
|
2247
|
+
}),
|
2248
|
+
content: formatMessage(
|
2249
|
+
{
|
2250
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2251
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2252
|
+
},
|
2253
|
+
{
|
2254
|
+
count: totalDraftRelations
|
1745
2255
|
}
|
1746
|
-
|
1747
|
-
|
2256
|
+
),
|
2257
|
+
onConfirm: async () => {
|
2258
|
+
await performPublish();
|
1748
2259
|
}
|
1749
|
-
}
|
2260
|
+
} : void 0
|
1750
2261
|
};
|
1751
2262
|
};
|
1752
2263
|
PublishAction$1.type = "publish";
|
@@ -1762,10 +2273,6 @@ const UpdateAction = ({
|
|
1762
2273
|
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
1763
2274
|
const isCloning = cloneMatch !== null;
|
1764
2275
|
const { formatMessage } = reactIntl.useIntl();
|
1765
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1766
|
-
canCreate: canCreate2,
|
1767
|
-
canUpdate: canUpdate2
|
1768
|
-
}));
|
1769
2276
|
const { create, update, clone } = useDocumentActions();
|
1770
2277
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1771
2278
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
@@ -1782,10 +2289,8 @@ const UpdateAction = ({
|
|
1782
2289
|
* - the form is submitting
|
1783
2290
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1784
2291
|
* - the active tab is the published tab
|
1785
|
-
* - the user doesn't have the permission to create a new document
|
1786
|
-
* - the user doesn't have the permission to update the document
|
1787
2292
|
*/
|
1788
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2293
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1789
2294
|
label: formatMessage({
|
1790
2295
|
id: "content-manager.containers.Edit.save",
|
1791
2296
|
defaultMessage: "Save"
|
@@ -1793,7 +2298,9 @@ const UpdateAction = ({
|
|
1793
2298
|
onClick: async () => {
|
1794
2299
|
setSubmitting(true);
|
1795
2300
|
try {
|
1796
|
-
const { errors } = await validate(
|
2301
|
+
const { errors } = await validate(true, {
|
2302
|
+
status: "draft"
|
2303
|
+
});
|
1797
2304
|
if (errors) {
|
1798
2305
|
toggleNotification({
|
1799
2306
|
type: "danger",
|
@@ -1811,13 +2318,16 @@ const UpdateAction = ({
|
|
1811
2318
|
documentId: cloneMatch.params.origin,
|
1812
2319
|
params
|
1813
2320
|
},
|
1814
|
-
document
|
2321
|
+
transformData(document)
|
1815
2322
|
);
|
1816
2323
|
if ("data" in res) {
|
1817
|
-
navigate(
|
1818
|
-
|
1819
|
-
|
1820
|
-
|
2324
|
+
navigate(
|
2325
|
+
{
|
2326
|
+
pathname: `../${res.data.documentId}`,
|
2327
|
+
search: rawQuery
|
2328
|
+
},
|
2329
|
+
{ relative: "path" }
|
2330
|
+
);
|
1821
2331
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1822
2332
|
setErrors(formatValidationErrors(res.error));
|
1823
2333
|
}
|
@@ -1829,7 +2339,7 @@ const UpdateAction = ({
|
|
1829
2339
|
documentId,
|
1830
2340
|
params
|
1831
2341
|
},
|
1832
|
-
document
|
2342
|
+
transformData(document)
|
1833
2343
|
);
|
1834
2344
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1835
2345
|
setErrors(formatValidationErrors(res.error));
|
@@ -1842,15 +2352,15 @@ const UpdateAction = ({
|
|
1842
2352
|
model,
|
1843
2353
|
params
|
1844
2354
|
},
|
1845
|
-
document
|
2355
|
+
transformData(document)
|
1846
2356
|
);
|
1847
2357
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1848
2358
|
navigate(
|
1849
2359
|
{
|
1850
|
-
pathname: `../${
|
2360
|
+
pathname: `../${res.data.documentId}`,
|
1851
2361
|
search: rawQuery
|
1852
2362
|
},
|
1853
|
-
{ replace: true }
|
2363
|
+
{ replace: true, relative: "path" }
|
1854
2364
|
);
|
1855
2365
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1856
2366
|
setErrors(formatValidationErrors(res.error));
|
@@ -1895,7 +2405,7 @@ const UnpublishAction$1 = ({
|
|
1895
2405
|
id: "app.utils.unpublish",
|
1896
2406
|
defaultMessage: "Unpublish"
|
1897
2407
|
}),
|
1898
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2408
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1899
2409
|
onClick: async () => {
|
1900
2410
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1901
2411
|
if (!documentId) {
|
@@ -2007,7 +2517,7 @@ const DiscardAction = ({
|
|
2007
2517
|
id: "content-manager.actions.discard.label",
|
2008
2518
|
defaultMessage: "Discard changes"
|
2009
2519
|
}),
|
2010
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2520
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2011
2521
|
position: ["panel", "table-row"],
|
2012
2522
|
variant: "danger",
|
2013
2523
|
dialog: {
|
@@ -2035,11 +2545,6 @@ const DiscardAction = ({
|
|
2035
2545
|
};
|
2036
2546
|
};
|
2037
2547
|
DiscardAction.type = "discard";
|
2038
|
-
const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
|
2039
|
-
path {
|
2040
|
-
fill: currentColor;
|
2041
|
-
}
|
2042
|
-
`;
|
2043
2548
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2044
2549
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2045
2550
|
const RelativeTime = React__namespace.forwardRef(
|
@@ -2087,7 +2592,7 @@ const getDisplayName = ({
|
|
2087
2592
|
};
|
2088
2593
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2089
2594
|
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2090
|
-
const statusVariant = status === "draft" ? "
|
2595
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2091
2596
|
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) }) });
|
2092
2597
|
};
|
2093
2598
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
@@ -2097,23 +2602,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2097
2602
|
id: "content-manager.containers.edit.title.new",
|
2098
2603
|
defaultMessage: "Create an entry"
|
2099
2604
|
}) : documentTitle;
|
2100
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2605
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2101
2606
|
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
2102
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
2103
|
-
designSystem.
|
2104
|
-
{
|
2105
|
-
|
2106
|
-
|
2107
|
-
paddingTop: 1,
|
2108
|
-
gap: "80px",
|
2109
|
-
alignItems: "flex-start",
|
2110
|
-
children: [
|
2111
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2112
|
-
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2113
|
-
]
|
2114
|
-
}
|
2115
|
-
),
|
2116
|
-
status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2607
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2608
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2609
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2610
|
+
] }),
|
2611
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2117
2612
|
] });
|
2118
2613
|
};
|
2119
2614
|
const HeaderToolbar = () => {
|
@@ -2196,12 +2691,12 @@ const Information = ({ activeTab }) => {
|
|
2196
2691
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2197
2692
|
label: formatMessage({
|
2198
2693
|
id: "content-manager.containers.edit.information.last-published.label",
|
2199
|
-
defaultMessage: "
|
2694
|
+
defaultMessage: "Published"
|
2200
2695
|
}),
|
2201
2696
|
value: formatMessage(
|
2202
2697
|
{
|
2203
2698
|
id: "content-manager.containers.edit.information.last-published.value",
|
2204
|
-
defaultMessage: `
|
2699
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2205
2700
|
},
|
2206
2701
|
{
|
2207
2702
|
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2214,12 +2709,12 @@ const Information = ({ activeTab }) => {
|
|
2214
2709
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2215
2710
|
label: formatMessage({
|
2216
2711
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2217
|
-
defaultMessage: "
|
2712
|
+
defaultMessage: "Updated"
|
2218
2713
|
}),
|
2219
2714
|
value: formatMessage(
|
2220
2715
|
{
|
2221
2716
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2222
|
-
defaultMessage: `
|
2717
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2223
2718
|
},
|
2224
2719
|
{
|
2225
2720
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2237,12 +2732,12 @@ const Information = ({ activeTab }) => {
|
|
2237
2732
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2238
2733
|
label: formatMessage({
|
2239
2734
|
id: "content-manager.containers.edit.information.document.label",
|
2240
|
-
defaultMessage: "
|
2735
|
+
defaultMessage: "Created"
|
2241
2736
|
}),
|
2242
2737
|
value: formatMessage(
|
2243
2738
|
{
|
2244
2739
|
id: "content-manager.containers.edit.information.document.value",
|
2245
|
-
defaultMessage: `
|
2740
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2246
2741
|
},
|
2247
2742
|
{
|
2248
2743
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2280,25 +2775,77 @@ const Information = ({ activeTab }) => {
|
|
2280
2775
|
);
|
2281
2776
|
};
|
2282
2777
|
const HeaderActions = ({ actions: actions2 }) => {
|
2283
|
-
|
2284
|
-
|
2778
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2779
|
+
const handleClick = (action) => async (e) => {
|
2780
|
+
if (!("options" in action)) {
|
2781
|
+
const { onClick = () => false, dialog, id } = action;
|
2782
|
+
const muteDialog = await onClick(e);
|
2783
|
+
if (dialog && !muteDialog) {
|
2784
|
+
e.preventDefault();
|
2785
|
+
setDialogId(id);
|
2786
|
+
}
|
2787
|
+
}
|
2788
|
+
};
|
2789
|
+
const handleClose = () => {
|
2790
|
+
setDialogId(null);
|
2791
|
+
};
|
2792
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2793
|
+
if (action.options) {
|
2285
2794
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2286
2795
|
designSystem.SingleSelect,
|
2287
2796
|
{
|
2288
2797
|
size: "S",
|
2289
|
-
disabled: action.disabled,
|
2290
|
-
"aria-label": action.label,
|
2291
2798
|
onChange: action.onSelect,
|
2292
|
-
|
2799
|
+
"aria-label": action.label,
|
2800
|
+
...action,
|
2293
2801
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2294
2802
|
},
|
2295
2803
|
action.id
|
2296
2804
|
);
|
2297
2805
|
} else {
|
2298
|
-
|
2806
|
+
if (action.type === "icon") {
|
2807
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2808
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2809
|
+
designSystem.IconButton,
|
2810
|
+
{
|
2811
|
+
disabled: action.disabled,
|
2812
|
+
label: action.label,
|
2813
|
+
size: "S",
|
2814
|
+
onClick: handleClick(action),
|
2815
|
+
children: action.icon
|
2816
|
+
}
|
2817
|
+
),
|
2818
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2819
|
+
HeaderActionDialog,
|
2820
|
+
{
|
2821
|
+
...action.dialog,
|
2822
|
+
isOpen: dialogId === action.id,
|
2823
|
+
onClose: handleClose
|
2824
|
+
}
|
2825
|
+
) : null
|
2826
|
+
] }, action.id);
|
2827
|
+
}
|
2299
2828
|
}
|
2300
2829
|
}) });
|
2301
2830
|
};
|
2831
|
+
const HeaderActionDialog = ({
|
2832
|
+
onClose,
|
2833
|
+
onCancel,
|
2834
|
+
title,
|
2835
|
+
content: Content,
|
2836
|
+
isOpen
|
2837
|
+
}) => {
|
2838
|
+
const handleClose = async () => {
|
2839
|
+
if (onCancel) {
|
2840
|
+
await onCancel();
|
2841
|
+
}
|
2842
|
+
onClose();
|
2843
|
+
};
|
2844
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2845
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2846
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2847
|
+
] }) });
|
2848
|
+
};
|
2302
2849
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2303
2850
|
const navigate = reactRouterDom.useNavigate();
|
2304
2851
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2339,12 +2886,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2339
2886
|
const { delete: deleteAction } = useDocumentActions();
|
2340
2887
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2341
2888
|
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2889
|
+
const isLocalized = document?.locale != null;
|
2342
2890
|
return {
|
2343
2891
|
disabled: !canDelete || !document,
|
2344
|
-
label: formatMessage(
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
2892
|
+
label: formatMessage(
|
2893
|
+
{
|
2894
|
+
id: "content-manager.actions.delete.label",
|
2895
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2896
|
+
},
|
2897
|
+
{ isLocalized }
|
2898
|
+
),
|
2348
2899
|
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2349
2900
|
dialog: {
|
2350
2901
|
type: "dialog",
|
@@ -2379,424 +2930,122 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2379
2930
|
}
|
2380
2931
|
const res = await deleteAction({
|
2381
2932
|
documentId,
|
2382
|
-
model,
|
2383
|
-
collectionType,
|
2384
|
-
params: {
|
2385
|
-
locale: "*"
|
2386
|
-
}
|
2387
|
-
});
|
2388
|
-
if (!("error" in res)) {
|
2389
|
-
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2390
|
-
}
|
2391
|
-
} finally {
|
2392
|
-
if (!listViewPathMatch) {
|
2393
|
-
setSubmitting(false);
|
2394
|
-
}
|
2395
|
-
}
|
2396
|
-
}
|
2397
|
-
},
|
2398
|
-
variant: "danger",
|
2399
|
-
position: ["header", "table-row"]
|
2400
|
-
};
|
2401
|
-
};
|
2402
|
-
DeleteAction$1.type = "delete";
|
2403
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2404
|
-
const Panels = () => {
|
2405
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2406
|
-
const [
|
2407
|
-
{
|
2408
|
-
query: { status }
|
2409
|
-
}
|
2410
|
-
] = strapiAdmin.useQueryParams({
|
2411
|
-
status: "draft"
|
2412
|
-
});
|
2413
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2414
|
-
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2415
|
-
const props = {
|
2416
|
-
activeTab: status,
|
2417
|
-
model,
|
2418
|
-
documentId: id,
|
2419
|
-
document: isCloning ? void 0 : document,
|
2420
|
-
meta: isCloning ? void 0 : meta,
|
2421
|
-
collectionType
|
2422
|
-
};
|
2423
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2424
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2425
|
-
{
|
2426
|
-
props,
|
2427
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2428
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2429
|
-
}
|
2430
|
-
) });
|
2431
|
-
};
|
2432
|
-
const ActionsPanel = () => {
|
2433
|
-
const { formatMessage } = reactIntl.useIntl();
|
2434
|
-
return {
|
2435
|
-
title: formatMessage({
|
2436
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2437
|
-
defaultMessage: "Document"
|
2438
|
-
}),
|
2439
|
-
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2440
|
-
};
|
2441
|
-
};
|
2442
|
-
ActionsPanel.type = "actions";
|
2443
|
-
const ActionsPanelContent = () => {
|
2444
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2445
|
-
const [
|
2446
|
-
{
|
2447
|
-
query: { status = "draft" }
|
2448
|
-
}
|
2449
|
-
] = strapiAdmin.useQueryParams();
|
2450
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2451
|
-
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2452
|
-
const props = {
|
2453
|
-
activeTab: status,
|
2454
|
-
model,
|
2455
|
-
documentId: id,
|
2456
|
-
document: isCloning ? void 0 : document,
|
2457
|
-
meta: isCloning ? void 0 : meta,
|
2458
|
-
collectionType
|
2459
|
-
};
|
2460
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2461
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2462
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2463
|
-
{
|
2464
|
-
props,
|
2465
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2466
|
-
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
2467
|
-
}
|
2468
|
-
),
|
2469
|
-
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2470
|
-
] });
|
2471
|
-
};
|
2472
|
-
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
2473
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
2474
|
-
designSystem.Flex,
|
2475
|
-
{
|
2476
|
-
ref,
|
2477
|
-
tag: "aside",
|
2478
|
-
"aria-labelledby": "additional-information",
|
2479
|
-
background: "neutral0",
|
2480
|
-
borderColor: "neutral150",
|
2481
|
-
hasRadius: true,
|
2482
|
-
paddingBottom: 4,
|
2483
|
-
paddingLeft: 4,
|
2484
|
-
paddingRight: 4,
|
2485
|
-
paddingTop: 4,
|
2486
|
-
shadow: "tableShadow",
|
2487
|
-
gap: 3,
|
2488
|
-
direction: "column",
|
2489
|
-
justifyContent: "stretch",
|
2490
|
-
alignItems: "flex-start",
|
2491
|
-
children: [
|
2492
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2493
|
-
children
|
2494
|
-
]
|
2495
|
-
}
|
2496
|
-
);
|
2497
|
-
});
|
2498
|
-
const HOOKS = {
|
2499
|
-
/**
|
2500
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2501
|
-
* @constant
|
2502
|
-
* @type {string}
|
2503
|
-
*/
|
2504
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2505
|
-
/**
|
2506
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2507
|
-
* @constant
|
2508
|
-
* @type {string}
|
2509
|
-
*/
|
2510
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2511
|
-
/**
|
2512
|
-
* Hook that allows to mutate the CM's edit view layout
|
2513
|
-
* @constant
|
2514
|
-
* @type {string}
|
2515
|
-
*/
|
2516
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2517
|
-
/**
|
2518
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2519
|
-
* @constant
|
2520
|
-
* @type {string}
|
2521
|
-
*/
|
2522
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2523
|
-
};
|
2524
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2525
|
-
endpoints: (builder) => ({
|
2526
|
-
getContentTypeConfiguration: builder.query({
|
2527
|
-
query: (uid) => ({
|
2528
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2529
|
-
method: "GET"
|
2530
|
-
}),
|
2531
|
-
transformResponse: (response) => response.data,
|
2532
|
-
providesTags: (_result, _error, uid) => [
|
2533
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2534
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2535
|
-
]
|
2536
|
-
}),
|
2537
|
-
getAllContentTypeSettings: builder.query({
|
2538
|
-
query: () => "/content-manager/content-types-settings",
|
2539
|
-
transformResponse: (response) => response.data,
|
2540
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2541
|
-
}),
|
2542
|
-
updateContentTypeConfiguration: builder.mutation({
|
2543
|
-
query: ({ uid, ...body }) => ({
|
2544
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2545
|
-
method: "PUT",
|
2546
|
-
data: body
|
2547
|
-
}),
|
2548
|
-
transformResponse: (response) => response.data,
|
2549
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2550
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2551
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2552
|
-
// Is this necessary?
|
2553
|
-
{ type: "InitialData" }
|
2554
|
-
]
|
2555
|
-
})
|
2556
|
-
})
|
2557
|
-
});
|
2558
|
-
const {
|
2559
|
-
useGetContentTypeConfigurationQuery,
|
2560
|
-
useGetAllContentTypeSettingsQuery,
|
2561
|
-
useUpdateContentTypeConfigurationMutation
|
2562
|
-
} = contentTypesApi;
|
2563
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2564
|
-
const { type } = attribute;
|
2565
|
-
if (type === "relation") {
|
2566
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2567
|
-
}
|
2568
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2569
|
-
};
|
2570
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2571
|
-
if (!mainFieldName) {
|
2572
|
-
return void 0;
|
2573
|
-
}
|
2574
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2575
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2576
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2577
|
-
);
|
2578
|
-
return {
|
2579
|
-
name: mainFieldName,
|
2580
|
-
type: mainFieldType ?? "string"
|
2581
|
-
};
|
2582
|
-
};
|
2583
|
-
const DEFAULT_SETTINGS = {
|
2584
|
-
bulkable: false,
|
2585
|
-
filterable: false,
|
2586
|
-
searchable: false,
|
2587
|
-
pagination: false,
|
2588
|
-
defaultSortBy: "",
|
2589
|
-
defaultSortOrder: "asc",
|
2590
|
-
mainField: "id",
|
2591
|
-
pageSize: 10
|
2592
|
-
};
|
2593
|
-
const useDocumentLayout = (model) => {
|
2594
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2595
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
2596
|
-
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2597
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
2598
|
-
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
2599
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2600
|
-
const {
|
2601
|
-
data,
|
2602
|
-
isLoading: isLoadingConfigs,
|
2603
|
-
error,
|
2604
|
-
isFetching: isFetchingConfigs
|
2605
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2606
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2607
|
-
React__namespace.useEffect(() => {
|
2608
|
-
if (error) {
|
2609
|
-
toggleNotification({
|
2610
|
-
type: "danger",
|
2611
|
-
message: formatAPIError(error)
|
2612
|
-
});
|
2613
|
-
}
|
2614
|
-
}, [error, formatAPIError, toggleNotification]);
|
2615
|
-
const editLayout = React__namespace.useMemo(
|
2616
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2617
|
-
layout: [],
|
2618
|
-
components: {},
|
2619
|
-
metadatas: {},
|
2620
|
-
options: {},
|
2621
|
-
settings: DEFAULT_SETTINGS
|
2622
|
-
},
|
2623
|
-
[data, isLoading, schemas, schema, components]
|
2624
|
-
);
|
2625
|
-
const listLayout = React__namespace.useMemo(() => {
|
2626
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2627
|
-
layout: [],
|
2628
|
-
metadatas: {},
|
2629
|
-
options: {},
|
2630
|
-
settings: DEFAULT_SETTINGS
|
2631
|
-
};
|
2632
|
-
}, [data, isLoading, schemas, schema, components]);
|
2633
|
-
const { layout: edit } = React__namespace.useMemo(
|
2634
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2635
|
-
layout: editLayout,
|
2636
|
-
query
|
2637
|
-
}),
|
2638
|
-
[editLayout, query, runHookWaterfall]
|
2639
|
-
);
|
2640
|
-
return {
|
2641
|
-
error,
|
2642
|
-
isLoading,
|
2643
|
-
edit,
|
2644
|
-
list: listLayout
|
2645
|
-
};
|
2646
|
-
};
|
2647
|
-
const useDocLayout = () => {
|
2648
|
-
const { model } = useDoc();
|
2649
|
-
return useDocumentLayout(model);
|
2650
|
-
};
|
2651
|
-
const formatEditLayout = (data, {
|
2652
|
-
schemas,
|
2653
|
-
schema,
|
2654
|
-
components
|
2655
|
-
}) => {
|
2656
|
-
let currentPanelIndex = 0;
|
2657
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2658
|
-
data.contentType.layouts.edit,
|
2659
|
-
schema?.attributes,
|
2660
|
-
data.contentType.metadatas,
|
2661
|
-
{ configurations: data.components, schemas: components },
|
2662
|
-
schemas
|
2663
|
-
).reduce((panels, row) => {
|
2664
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2665
|
-
panels.push([row]);
|
2666
|
-
currentPanelIndex += 2;
|
2667
|
-
} else {
|
2668
|
-
if (!panels[currentPanelIndex]) {
|
2669
|
-
panels.push([]);
|
2670
|
-
}
|
2671
|
-
panels[currentPanelIndex].push(row);
|
2672
|
-
}
|
2673
|
-
return panels;
|
2674
|
-
}, []);
|
2675
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2676
|
-
(acc, [uid, configuration]) => {
|
2677
|
-
acc[uid] = {
|
2678
|
-
layout: convertEditLayoutToFieldLayouts(
|
2679
|
-
configuration.layouts.edit,
|
2680
|
-
components[uid].attributes,
|
2681
|
-
configuration.metadatas
|
2682
|
-
),
|
2683
|
-
settings: {
|
2684
|
-
...configuration.settings,
|
2685
|
-
icon: components[uid].info.icon,
|
2686
|
-
displayName: components[uid].info.displayName
|
2687
|
-
}
|
2688
|
-
};
|
2689
|
-
return acc;
|
2690
|
-
},
|
2691
|
-
{}
|
2692
|
-
);
|
2693
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2694
|
-
(acc, [attribute, metadata]) => {
|
2695
|
-
return {
|
2696
|
-
...acc,
|
2697
|
-
[attribute]: metadata.edit
|
2698
|
-
};
|
2699
|
-
},
|
2700
|
-
{}
|
2701
|
-
);
|
2702
|
-
return {
|
2703
|
-
layout: panelledEditAttributes,
|
2704
|
-
components: componentEditAttributes,
|
2705
|
-
metadatas: editMetadatas,
|
2706
|
-
settings: {
|
2707
|
-
...data.contentType.settings,
|
2708
|
-
displayName: schema?.info.displayName
|
2933
|
+
model,
|
2934
|
+
collectionType,
|
2935
|
+
params: {
|
2936
|
+
locale: "*"
|
2937
|
+
}
|
2938
|
+
});
|
2939
|
+
if (!("error" in res)) {
|
2940
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2941
|
+
}
|
2942
|
+
} finally {
|
2943
|
+
if (!listViewPathMatch) {
|
2944
|
+
setSubmitting(false);
|
2945
|
+
}
|
2946
|
+
}
|
2947
|
+
}
|
2709
2948
|
},
|
2710
|
-
|
2711
|
-
|
2712
|
-
...schema?.pluginOptions,
|
2713
|
-
...data.contentType.options
|
2714
|
-
}
|
2949
|
+
variant: "danger",
|
2950
|
+
position: ["header", "table-row"]
|
2715
2951
|
};
|
2716
2952
|
};
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
}
|
2724
|
-
|
2725
|
-
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2731
|
-
|
2732
|
-
|
2733
|
-
|
2734
|
-
|
2735
|
-
|
2736
|
-
|
2737
|
-
|
2738
|
-
|
2739
|
-
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2743
|
-
}
|
2744
|
-
}
|
2745
|
-
);
|
2953
|
+
DeleteAction$1.type = "delete";
|
2954
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2955
|
+
const Panels = () => {
|
2956
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2957
|
+
const [
|
2958
|
+
{
|
2959
|
+
query: { status }
|
2960
|
+
}
|
2961
|
+
] = strapiAdmin.useQueryParams({
|
2962
|
+
status: "draft"
|
2963
|
+
});
|
2964
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2965
|
+
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2966
|
+
const props = {
|
2967
|
+
activeTab: status,
|
2968
|
+
model,
|
2969
|
+
documentId: id,
|
2970
|
+
document: isCloning ? void 0 : document,
|
2971
|
+
meta: isCloning ? void 0 : meta,
|
2972
|
+
collectionType
|
2973
|
+
};
|
2974
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2975
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2976
|
+
{
|
2977
|
+
props,
|
2978
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2979
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2980
|
+
}
|
2981
|
+
) });
|
2746
2982
|
};
|
2747
|
-
const
|
2748
|
-
|
2749
|
-
schema,
|
2750
|
-
components
|
2751
|
-
}) => {
|
2752
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2753
|
-
(acc, [attribute, metadata]) => {
|
2754
|
-
return {
|
2755
|
-
...acc,
|
2756
|
-
[attribute]: metadata.list
|
2757
|
-
};
|
2758
|
-
},
|
2759
|
-
{}
|
2760
|
-
);
|
2761
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2762
|
-
data.contentType.layouts.list,
|
2763
|
-
schema?.attributes,
|
2764
|
-
listMetadatas,
|
2765
|
-
{ configurations: data.components, schemas: components },
|
2766
|
-
schemas
|
2767
|
-
);
|
2983
|
+
const ActionsPanel = () => {
|
2984
|
+
const { formatMessage } = reactIntl.useIntl();
|
2768
2985
|
return {
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
...schema?.pluginOptions,
|
2775
|
-
...data.contentType.options
|
2776
|
-
}
|
2986
|
+
title: formatMessage({
|
2987
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2988
|
+
defaultMessage: "Entry"
|
2989
|
+
}),
|
2990
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2777
2991
|
};
|
2778
2992
|
};
|
2779
|
-
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2993
|
+
ActionsPanel.type = "actions";
|
2994
|
+
const ActionsPanelContent = () => {
|
2995
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2996
|
+
const [
|
2997
|
+
{
|
2998
|
+
query: { status = "draft" }
|
2784
2999
|
}
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
3000
|
+
] = strapiAdmin.useQueryParams();
|
3001
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3002
|
+
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
3003
|
+
const props = {
|
3004
|
+
activeTab: status,
|
3005
|
+
model,
|
3006
|
+
documentId: id,
|
3007
|
+
document: isCloning ? void 0 : document,
|
3008
|
+
meta: isCloning ? void 0 : meta,
|
3009
|
+
collectionType
|
3010
|
+
};
|
3011
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3012
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3013
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3014
|
+
{
|
3015
|
+
props,
|
3016
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3017
|
+
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
3018
|
+
}
|
3019
|
+
),
|
3020
|
+
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3021
|
+
] });
|
2799
3022
|
};
|
3023
|
+
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
3024
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
3025
|
+
designSystem.Flex,
|
3026
|
+
{
|
3027
|
+
ref,
|
3028
|
+
tag: "aside",
|
3029
|
+
"aria-labelledby": "additional-information",
|
3030
|
+
background: "neutral0",
|
3031
|
+
borderColor: "neutral150",
|
3032
|
+
hasRadius: true,
|
3033
|
+
paddingBottom: 4,
|
3034
|
+
paddingLeft: 4,
|
3035
|
+
paddingRight: 4,
|
3036
|
+
paddingTop: 4,
|
3037
|
+
shadow: "tableShadow",
|
3038
|
+
gap: 3,
|
3039
|
+
direction: "column",
|
3040
|
+
justifyContent: "stretch",
|
3041
|
+
alignItems: "flex-start",
|
3042
|
+
children: [
|
3043
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", textColor: "neutral600", children: title }),
|
3044
|
+
children
|
3045
|
+
]
|
3046
|
+
}
|
3047
|
+
);
|
3048
|
+
});
|
2800
3049
|
const ConfirmBulkActionDialog = ({
|
2801
3050
|
onToggleDialog,
|
2802
3051
|
isOpen = false,
|
@@ -2804,7 +3053,7 @@ const ConfirmBulkActionDialog = ({
|
|
2804
3053
|
endAction
|
2805
3054
|
}) => {
|
2806
3055
|
const { formatMessage } = reactIntl.useIntl();
|
2807
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, {
|
3056
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2808
3057
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
|
2809
3058
|
id: "app.components.ConfirmDialog.title",
|
2810
3059
|
defaultMessage: "Confirmation"
|
@@ -2835,6 +3084,7 @@ const ConfirmDialogPublishAll = ({
|
|
2835
3084
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2836
3085
|
const { model, schema } = useDoc();
|
2837
3086
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3087
|
+
const enableDraftRelationsCount = false;
|
2838
3088
|
const {
|
2839
3089
|
data: countDraftRelations = 0,
|
2840
3090
|
isLoading,
|
@@ -2846,7 +3096,7 @@ const ConfirmDialogPublishAll = ({
|
|
2846
3096
|
locale: query?.plugins?.i18n?.locale
|
2847
3097
|
},
|
2848
3098
|
{
|
2849
|
-
skip:
|
3099
|
+
skip: !enableDraftRelationsCount
|
2850
3100
|
}
|
2851
3101
|
);
|
2852
3102
|
React__namespace.useEffect(() => {
|
@@ -3031,7 +3281,7 @@ const SelectedEntriesTableContent = ({
|
|
3031
3281
|
status: row.status
|
3032
3282
|
}
|
3033
3283
|
) }),
|
3034
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3284
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3035
3285
|
designSystem.IconButton,
|
3036
3286
|
{
|
3037
3287
|
tag: reactRouterDom.Link,
|
@@ -3054,9 +3304,10 @@ const SelectedEntriesTableContent = ({
|
|
3054
3304
|
),
|
3055
3305
|
target: "_blank",
|
3056
3306
|
marginLeft: "auto",
|
3057
|
-
|
3307
|
+
variant: "ghost",
|
3308
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3058
3309
|
}
|
3059
|
-
) })
|
3310
|
+
) }) })
|
3060
3311
|
] }, row.id)) })
|
3061
3312
|
] });
|
3062
3313
|
};
|
@@ -3093,7 +3344,13 @@ const SelectedEntriesModalContent = ({
|
|
3093
3344
|
);
|
3094
3345
|
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3095
3346
|
if (data.length > 0 && schema) {
|
3096
|
-
const validate = createYupSchema(
|
3347
|
+
const validate = createYupSchema(
|
3348
|
+
schema.attributes,
|
3349
|
+
components,
|
3350
|
+
// Since this is the "Publish" action, the validation
|
3351
|
+
// schema must enforce the rules for published entities
|
3352
|
+
{ status: "published" }
|
3353
|
+
);
|
3097
3354
|
const validationErrors2 = {};
|
3098
3355
|
const rows2 = data.map((entry) => {
|
3099
3356
|
try {
|
@@ -3443,7 +3700,7 @@ const TableActions = ({ document }) => {
|
|
3443
3700
|
strapiAdmin.DescriptionComponentRenderer,
|
3444
3701
|
{
|
3445
3702
|
props,
|
3446
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3703
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3447
3704
|
children: (actions2) => {
|
3448
3705
|
const tableRowActions = actions2.filter((action) => {
|
3449
3706
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3554,7 +3811,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3554
3811
|
}),
|
3555
3812
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3556
3813
|
footer: ({ onClose }) => {
|
3557
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3814
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3558
3815
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3559
3816
|
id: "cancel",
|
3560
3817
|
defaultMessage: "Cancel"
|
@@ -3595,8 +3852,7 @@ class ContentManagerPlugin {
|
|
3595
3852
|
documentActions = [
|
3596
3853
|
...DEFAULT_ACTIONS,
|
3597
3854
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3598
|
-
...DEFAULT_HEADER_ACTIONS
|
3599
|
-
HistoryAction
|
3855
|
+
...DEFAULT_HEADER_ACTIONS
|
3600
3856
|
];
|
3601
3857
|
editViewSidePanels = [ActionsPanel];
|
3602
3858
|
headerActions = [];
|
@@ -3685,6 +3941,52 @@ const getPrintableType = (value) => {
|
|
3685
3941
|
}
|
3686
3942
|
return nativeType;
|
3687
3943
|
};
|
3944
|
+
const HistoryAction = ({ model, document }) => {
|
3945
|
+
const { formatMessage } = reactIntl.useIntl();
|
3946
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3947
|
+
const navigate = reactRouterDom.useNavigate();
|
3948
|
+
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
3949
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3950
|
+
return null;
|
3951
|
+
}
|
3952
|
+
return {
|
3953
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
3954
|
+
label: formatMessage({
|
3955
|
+
id: "content-manager.history.document-action",
|
3956
|
+
defaultMessage: "Content History"
|
3957
|
+
}),
|
3958
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3959
|
+
disabled: (
|
3960
|
+
/**
|
3961
|
+
* The user is creating a new document.
|
3962
|
+
* It hasn't been saved yet, so there's no history to go to
|
3963
|
+
*/
|
3964
|
+
!document || /**
|
3965
|
+
* The document has been created but the current dimension has never been saved.
|
3966
|
+
* For example, the user is creating a new locale in an existing document,
|
3967
|
+
* so there's no history for the document in that locale
|
3968
|
+
*/
|
3969
|
+
!document.id || /**
|
3970
|
+
* History is only available for content types created by the user.
|
3971
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3972
|
+
* which start with `admin::` or `plugin::`
|
3973
|
+
*/
|
3974
|
+
!model.startsWith("api::")
|
3975
|
+
),
|
3976
|
+
position: "header"
|
3977
|
+
};
|
3978
|
+
};
|
3979
|
+
HistoryAction.type = "history";
|
3980
|
+
const historyAdmin = {
|
3981
|
+
bootstrap(app) {
|
3982
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3983
|
+
addDocumentAction((actions2) => {
|
3984
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3985
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3986
|
+
return actions2;
|
3987
|
+
});
|
3988
|
+
}
|
3989
|
+
};
|
3688
3990
|
const initialState = {
|
3689
3991
|
collectionTypeLinks: [],
|
3690
3992
|
components: [],
|
@@ -3721,6 +4023,57 @@ const { setInitialData } = actions;
|
|
3721
4023
|
const reducer = toolkit.combineReducers({
|
3722
4024
|
app: reducer$1
|
3723
4025
|
});
|
4026
|
+
const previewApi = contentManagerApi.injectEndpoints({
|
4027
|
+
endpoints: (builder) => ({
|
4028
|
+
getPreviewUrl: builder.query({
|
4029
|
+
query({ query, params }) {
|
4030
|
+
return {
|
4031
|
+
url: `/content-manager/preview/url/${params.contentType}`,
|
4032
|
+
method: "GET",
|
4033
|
+
config: {
|
4034
|
+
params: query
|
4035
|
+
}
|
4036
|
+
};
|
4037
|
+
}
|
4038
|
+
})
|
4039
|
+
})
|
4040
|
+
});
|
4041
|
+
const { useGetPreviewUrlQuery } = previewApi;
|
4042
|
+
const PreviewSidePanel = ({ model, documentId, document }) => {
|
4043
|
+
const { formatMessage } = reactIntl.useIntl();
|
4044
|
+
const { data, error } = useGetPreviewUrlQuery({
|
4045
|
+
params: {
|
4046
|
+
contentType: model
|
4047
|
+
},
|
4048
|
+
query: {
|
4049
|
+
documentId,
|
4050
|
+
locale: document?.locale,
|
4051
|
+
status: document?.status
|
4052
|
+
}
|
4053
|
+
});
|
4054
|
+
if (!data?.data?.url || error) {
|
4055
|
+
return null;
|
4056
|
+
}
|
4057
|
+
return {
|
4058
|
+
title: formatMessage({ id: "content-manager.preview.panel.title", defaultMessage: "Preview" }),
|
4059
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, tag: reactRouterDom.Link, to: data.data.url, target: "_blank", children: formatMessage({
|
4060
|
+
id: "content-manager.preview.panel.button",
|
4061
|
+
defaultMessage: "Open preview"
|
4062
|
+
}) })
|
4063
|
+
};
|
4064
|
+
};
|
4065
|
+
const FEATURE_ID = "preview";
|
4066
|
+
const previewAdmin = {
|
4067
|
+
bootstrap(app) {
|
4068
|
+
if (!window.strapi.future.isEnabled(FEATURE_ID)) {
|
4069
|
+
return;
|
4070
|
+
}
|
4071
|
+
const contentManagerPluginApis = app.getPlugin("content-manager").apis;
|
4072
|
+
if ("addEditViewSidePanel" in contentManagerPluginApis && typeof contentManagerPluginApis.addEditViewSidePanel === "function") {
|
4073
|
+
contentManagerPluginApis.addEditViewSidePanel([PreviewSidePanel]);
|
4074
|
+
}
|
4075
|
+
}
|
4076
|
+
};
|
3724
4077
|
const index = {
|
3725
4078
|
register(app) {
|
3726
4079
|
const cm = new ContentManagerPlugin();
|
@@ -3740,7 +4093,7 @@ const index = {
|
|
3740
4093
|
app.router.addRoute({
|
3741
4094
|
path: "content-manager/*",
|
3742
4095
|
lazy: async () => {
|
3743
|
-
const { Layout } = await Promise.resolve().then(() => require("./layout-
|
4096
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-CVz8WiDC.js"));
|
3744
4097
|
return {
|
3745
4098
|
Component: Layout
|
3746
4099
|
};
|
@@ -3749,10 +4102,18 @@ const index = {
|
|
3749
4102
|
});
|
3750
4103
|
app.registerPlugin(cm.config);
|
3751
4104
|
},
|
4105
|
+
bootstrap(app) {
|
4106
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4107
|
+
historyAdmin.bootstrap(app);
|
4108
|
+
}
|
4109
|
+
if (typeof previewAdmin.bootstrap === "function") {
|
4110
|
+
previewAdmin.bootstrap(app);
|
4111
|
+
}
|
4112
|
+
},
|
3752
4113
|
async registerTrads({ locales }) {
|
3753
4114
|
const importedTrads = await Promise.all(
|
3754
4115
|
locales.map((locale) => {
|
3755
|
-
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-
|
4116
|
+
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-C-J4DGEe.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-9K52xZIr.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B2Kyv8Z9.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-7sfIbjxE.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 }) => {
|
3756
4117
|
return {
|
3757
4118
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3758
4119
|
locale
|
@@ -3770,6 +4131,7 @@ const index = {
|
|
3770
4131
|
};
|
3771
4132
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
3772
4133
|
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4134
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3773
4135
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3774
4136
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3775
4137
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3797,6 +4159,7 @@ exports.getMainField = getMainField;
|
|
3797
4159
|
exports.getTranslation = getTranslation;
|
3798
4160
|
exports.index = index;
|
3799
4161
|
exports.setInitialData = setInitialData;
|
4162
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3800
4163
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3801
4164
|
exports.useDoc = useDoc;
|
3802
4165
|
exports.useDocLayout = useDocLayout;
|
@@ -3809,4 +4172,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
|
3809
4172
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3810
4173
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
3811
4174
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3812
|
-
//# sourceMappingURL=index-
|
4175
|
+
//# sourceMappingURL=index-76eawJUd.js.map
|