@strapi/content-manager 0.0.0-experimental.62ce06180fe9a772eaeb3d43d238b26644f39f7c → 0.0.0-experimental.646ad2aaf2b8f9970409242af8d77b0512d19bd1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -3
- package/dist/_chunks/{ComponentConfigurationPage-Cl7eB3s4.js → ComponentConfigurationPage-D1SEOQBu.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-Cl7eB3s4.js.map → ComponentConfigurationPage-D1SEOQBu.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DErJQEVW.mjs → ComponentConfigurationPage-oqdZo6l8.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-DErJQEVW.mjs.map → ComponentConfigurationPage-oqdZo6l8.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CyfFvH6-.js → EditConfigurationPage-BP94U6vG.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CyfFvH6-.js.map → EditConfigurationPage-BP94U6vG.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CBosWqQ7.mjs → EditConfigurationPage-DVLmpXPs.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CBosWqQ7.mjs.map → EditConfigurationPage-DVLmpXPs.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-DxyAOItK.js → EditViewPage-BfAywbBE.js} +30 -9
- package/dist/_chunks/EditViewPage-BfAywbBE.js.map +1 -0
- package/dist/_chunks/{EditViewPage-ClIueJnM.mjs → EditViewPage-Cvjs7D6M.mjs} +30 -9
- package/dist/_chunks/EditViewPage-Cvjs7D6M.mjs.map +1 -0
- package/dist/_chunks/{Field-BZBYmvaf.mjs → Field-CJrfStLX.mjs} +517 -153
- package/dist/_chunks/Field-CJrfStLX.mjs.map +1 -0
- package/dist/_chunks/{Field-C0Y_SR9e.js → Field-DC7FM64m.js} +519 -155
- package/dist/_chunks/Field-DC7FM64m.js.map +1 -0
- package/dist/_chunks/{Form-DwvGnISS.js → Form-Ahp2hi7E.js} +36 -17
- package/dist/_chunks/Form-Ahp2hi7E.js.map +1 -0
- package/dist/_chunks/{Form-jwRSC2kV.mjs → Form-BTgUlCEm.mjs} +36 -17
- package/dist/_chunks/Form-BTgUlCEm.mjs.map +1 -0
- package/dist/_chunks/{History-Cda0Yjzz.js → History-DZ9T1ZL6.js} +63 -25
- package/dist/_chunks/History-DZ9T1ZL6.js.map +1 -0
- package/dist/_chunks/{History-BgzAIj0G.mjs → History-Drr6mxnK.mjs} +64 -26
- package/dist/_chunks/History-Drr6mxnK.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-C29EF97r.js → ListConfigurationPage-B8bYMcVE.js} +20 -8
- package/dist/_chunks/ListConfigurationPage-B8bYMcVE.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-GH55qfoT.mjs → ListConfigurationPage-C6calJtW.mjs} +20 -8
- package/dist/_chunks/ListConfigurationPage-C6calJtW.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-CnRt0UT7.js → ListViewPage-BfiTNTUl.js} +61 -43
- package/dist/_chunks/ListViewPage-BfiTNTUl.js.map +1 -0
- package/dist/_chunks/{ListViewPage-QU03PFj1.mjs → ListViewPage-CQb0CL40.mjs} +59 -41
- package/dist/_chunks/ListViewPage-CQb0CL40.mjs.map +1 -0
- package/dist/_chunks/{NoContentTypePage-CPs2CnzH.mjs → NoContentTypePage-C-BK38Ai.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CPs2CnzH.mjs.map → NoContentTypePage-C-BK38Ai.mjs.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-DFDjxByI.js → NoContentTypePage-wJwVyqoZ.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-DFDjxByI.js.map → NoContentTypePage-wJwVyqoZ.js.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-ct58lcY0.mjs → NoPermissionsPage-BBdxJ-4m.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-ct58lcY0.mjs.map → NoPermissionsPage-BBdxJ-4m.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BVHI-jv5.js → NoPermissionsPage-DKaXyuK9.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BVHI-jv5.js.map → NoPermissionsPage-DKaXyuK9.js.map} +1 -1
- package/dist/_chunks/{Relations-BjpPPCKp.js → Relations-D7NskJzt.js} +69 -36
- package/dist/_chunks/Relations-D7NskJzt.js.map +1 -0
- package/dist/_chunks/{Relations-KMf5qEN0.mjs → Relations-DApDLUXv.mjs} +70 -37
- package/dist/_chunks/Relations-DApDLUXv.mjs.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-Bm0D0IWz.js} +17 -15
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-Bm0D0IWz.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-DKV44jRb.mjs} +17 -15
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-DKV44jRb.mjs.map} +1 -1
- package/dist/_chunks/{index-6kKXK7y8.mjs → index-Bz1SCyIj.mjs} +1005 -686
- package/dist/_chunks/index-Bz1SCyIj.mjs.map +1 -0
- package/dist/_chunks/{index-D9ZwczCV.js → index-D3u7haqj.js} +998 -678
- package/dist/_chunks/index-D3u7haqj.js.map +1 -0
- package/dist/_chunks/{layout-BJfBoBiF.js → layout-C_0aK53L.js} +25 -12
- package/dist/_chunks/layout-C_0aK53L.js.map +1 -0
- package/dist/_chunks/{layout-B1Z-9koY.mjs → layout-PNlIceEV.mjs} +27 -14
- package/dist/_chunks/layout-PNlIceEV.mjs.map +1 -0
- package/dist/_chunks/{relations-CgZg7Pyx.mjs → relations-BAIQsBLx.mjs} +3 -7
- package/dist/_chunks/relations-BAIQsBLx.mjs.map +1 -0
- package/dist/_chunks/{relations-CMvjzyU3.js → relations-ClRXiXcM.js} +3 -7
- package/dist/_chunks/relations-ClRXiXcM.js.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 +3 -2
- 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/BlocksInput/utils/constants.d.ts +4 -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/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 +245 -132
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +246 -133
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/relations.d.ts.map +1 -1
- package/dist/server/src/controllers/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 +2 -1
- 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/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/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/package.json +12 -12
- package/dist/_chunks/EditViewPage-ClIueJnM.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-DxyAOItK.js.map +0 -1
- package/dist/_chunks/Field-BZBYmvaf.mjs.map +0 -1
- package/dist/_chunks/Field-C0Y_SR9e.js.map +0 -1
- package/dist/_chunks/Form-DwvGnISS.js.map +0 -1
- package/dist/_chunks/Form-jwRSC2kV.mjs.map +0 -1
- package/dist/_chunks/History-BgzAIj0G.mjs.map +0 -1
- package/dist/_chunks/History-Cda0Yjzz.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-C29EF97r.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-GH55qfoT.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-CnRt0UT7.js.map +0 -1
- package/dist/_chunks/ListViewPage-QU03PFj1.mjs.map +0 -1
- package/dist/_chunks/Relations-BjpPPCKp.js.map +0 -1
- package/dist/_chunks/Relations-KMf5qEN0.mjs.map +0 -1
- package/dist/_chunks/index-6kKXK7y8.mjs.map +0 -1
- package/dist/_chunks/index-D9ZwczCV.js.map +0 -1
- package/dist/_chunks/layout-B1Z-9koY.mjs.map +0 -1
- package/dist/_chunks/layout-BJfBoBiF.js.map +0 -1
- package/dist/_chunks/relations-CMvjzyU3.js.map +0 -1
- package/dist/_chunks/relations-CgZg7Pyx.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) : [];
|
@@ -216,8 +190,7 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
|
216
190
|
"InitialData",
|
217
191
|
"HistoryVersion",
|
218
192
|
"Relations",
|
219
|
-
"
|
220
|
-
"ReleaseAction"
|
193
|
+
"UidAvailability"
|
221
194
|
]
|
222
195
|
});
|
223
196
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -231,7 +204,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
231
204
|
params: query
|
232
205
|
}
|
233
206
|
}),
|
234
|
-
invalidatesTags: (_result,
|
207
|
+
invalidatesTags: (_result, error, { model }) => {
|
208
|
+
if (error) {
|
209
|
+
return [];
|
210
|
+
}
|
211
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
212
|
+
}
|
235
213
|
}),
|
236
214
|
cloneDocument: builder.mutation({
|
237
215
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -242,7 +220,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
242
220
|
params
|
243
221
|
}
|
244
222
|
}),
|
245
|
-
invalidatesTags: (_result, _error, { model }) => [
|
223
|
+
invalidatesTags: (_result, _error, { model }) => [
|
224
|
+
{ type: "Document", id: `${model}_LIST` },
|
225
|
+
{ type: "UidAvailability", id: model }
|
226
|
+
]
|
246
227
|
}),
|
247
228
|
/**
|
248
229
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -259,7 +240,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
259
240
|
}),
|
260
241
|
invalidatesTags: (result, _error, { model }) => [
|
261
242
|
{ type: "Document", id: `${model}_LIST` },
|
262
|
-
"Relations"
|
243
|
+
"Relations",
|
244
|
+
{ type: "UidAvailability", id: model }
|
263
245
|
]
|
264
246
|
}),
|
265
247
|
deleteDocument: builder.mutation({
|
@@ -271,9 +253,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
271
253
|
}
|
272
254
|
}),
|
273
255
|
invalidatesTags: (_result, _error, { collectionType, model }) => [
|
274
|
-
{ type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model }
|
275
|
-
{ type: "Release", id: "LIST" },
|
276
|
-
{ type: "ReleaseAction", id: "LIST" }
|
256
|
+
{ type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model }
|
277
257
|
]
|
278
258
|
}),
|
279
259
|
deleteManyDocuments: builder.mutation({
|
@@ -285,11 +265,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
285
265
|
params
|
286
266
|
}
|
287
267
|
}),
|
288
|
-
invalidatesTags: (_res, _error, { model }) => [
|
289
|
-
{ type: "Document", id: `${model}_LIST` },
|
290
|
-
{ type: "Release", id: "LIST" },
|
291
|
-
{ type: "ReleaseAction", id: "LIST" }
|
292
|
-
]
|
268
|
+
invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
|
293
269
|
}),
|
294
270
|
discardDocument: builder.mutation({
|
295
271
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -307,8 +283,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
307
283
|
},
|
308
284
|
{ type: "Document", id: `${model}_LIST` },
|
309
285
|
"Relations",
|
310
|
-
{ type: "
|
311
|
-
{ type: "ReleaseAction", id: "LIST" }
|
286
|
+
{ type: "UidAvailability", id: model }
|
312
287
|
];
|
313
288
|
}
|
314
289
|
}),
|
@@ -326,6 +301,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
326
301
|
}),
|
327
302
|
providesTags: (result, _error, arg) => {
|
328
303
|
return [
|
304
|
+
{ type: "Document", id: `ALL_LIST` },
|
329
305
|
{ type: "Document", id: `${arg.model}_LIST` },
|
330
306
|
...result?.results.map(({ documentId }) => ({
|
331
307
|
type: "Document",
|
@@ -364,6 +340,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
364
340
|
{
|
365
341
|
type: "Document",
|
366
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`
|
367
348
|
}
|
368
349
|
];
|
369
350
|
}
|
@@ -428,9 +409,20 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
428
409
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
429
410
|
},
|
430
411
|
"Relations",
|
431
|
-
{ type: "
|
432
|
-
{ type: "ReleaseAction", id: "LIST" }
|
412
|
+
{ type: "UidAvailability", id: model }
|
433
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
|
+
}
|
434
426
|
}
|
435
427
|
}),
|
436
428
|
unpublishDocument: builder.mutation({
|
@@ -500,20 +492,39 @@ const buildValidParams = (query) => {
|
|
500
492
|
const isBaseQueryError = (error) => {
|
501
493
|
return error.name !== void 0;
|
502
494
|
};
|
503
|
-
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 }) => {
|
504
514
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
505
515
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
506
516
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
507
517
|
return acc;
|
508
518
|
}
|
509
519
|
const validations = [
|
520
|
+
addNullableValidation,
|
510
521
|
addRequiredValidation,
|
511
522
|
addMinLengthValidation,
|
512
523
|
addMaxLengthValidation,
|
513
524
|
addMinValidation,
|
514
525
|
addMaxValidation,
|
515
526
|
addRegexValidation
|
516
|
-
].map((fn) => fn(attribute));
|
527
|
+
].map((fn) => fn(attribute, options));
|
517
528
|
const transformSchema = pipe__default.default(...validations);
|
518
529
|
switch (attribute.type) {
|
519
530
|
case "component": {
|
@@ -523,12 +534,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
523
534
|
...acc,
|
524
535
|
[name]: transformSchema(
|
525
536
|
yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
|
526
|
-
)
|
537
|
+
).test(arrayValidator(attribute, options))
|
527
538
|
};
|
528
539
|
} else {
|
529
540
|
return {
|
530
541
|
...acc,
|
531
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
542
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
532
543
|
};
|
533
544
|
}
|
534
545
|
}
|
@@ -550,7 +561,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
550
561
|
}
|
551
562
|
)
|
552
563
|
)
|
553
|
-
)
|
564
|
+
).test(arrayValidator(attribute, options))
|
554
565
|
};
|
555
566
|
case "relation":
|
556
567
|
return {
|
@@ -562,7 +573,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
562
573
|
} else if (Array.isArray(value)) {
|
563
574
|
return yup__namespace.array().of(
|
564
575
|
yup__namespace.object().shape({
|
565
|
-
id: yup__namespace.
|
576
|
+
id: yup__namespace.number().required()
|
566
577
|
})
|
567
578
|
);
|
568
579
|
} else if (typeof value === "object") {
|
@@ -614,6 +625,14 @@ const createAttributeSchema = (attribute) => {
|
|
614
625
|
if (!value || typeof value === "string" && value.length === 0) {
|
615
626
|
return true;
|
616
627
|
}
|
628
|
+
if (typeof value === "object") {
|
629
|
+
try {
|
630
|
+
JSON.stringify(value);
|
631
|
+
return true;
|
632
|
+
} catch (err) {
|
633
|
+
return false;
|
634
|
+
}
|
635
|
+
}
|
617
636
|
try {
|
618
637
|
JSON.parse(value);
|
619
638
|
return true;
|
@@ -632,13 +651,7 @@ const createAttributeSchema = (attribute) => {
|
|
632
651
|
return yup__namespace.mixed();
|
633
652
|
}
|
634
653
|
};
|
635
|
-
const
|
636
|
-
if (attribute.required) {
|
637
|
-
return schema.required({
|
638
|
-
id: strapiAdmin.translatedErrors.required.id,
|
639
|
-
defaultMessage: "This field is required."
|
640
|
-
});
|
641
|
-
}
|
654
|
+
const nullableSchema = (schema) => {
|
642
655
|
return schema?.nullable ? schema.nullable() : (
|
643
656
|
// In some cases '.nullable' will not be available on the schema.
|
644
657
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -646,7 +659,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
646
659
|
schema
|
647
660
|
);
|
648
661
|
};
|
649
|
-
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
|
+
}
|
650
678
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
651
679
|
return schema.min(attribute.minLength, {
|
652
680
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -668,10 +696,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
668
696
|
}
|
669
697
|
return schema;
|
670
698
|
};
|
671
|
-
const addMinValidation = (attribute) => (schema) => {
|
672
|
-
if ("
|
699
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
700
|
+
if (options.status === "draft") {
|
701
|
+
return schema;
|
702
|
+
}
|
703
|
+
if ("min" in attribute && "min" in schema) {
|
673
704
|
const min = toInteger(attribute.min);
|
674
|
-
if (
|
705
|
+
if (min) {
|
675
706
|
return schema.min(min, {
|
676
707
|
...strapiAdmin.translatedErrors.min,
|
677
708
|
values: {
|
@@ -789,16 +820,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
789
820
|
}, {});
|
790
821
|
return componentsByKey;
|
791
822
|
};
|
792
|
-
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);
|
793
922
|
const { toggleNotification } = strapiAdmin.useNotification();
|
794
923
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
924
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
795
925
|
const {
|
796
|
-
|
797
|
-
isLoading:
|
798
|
-
|
799
|
-
|
800
|
-
} =
|
801
|
-
const
|
926
|
+
data,
|
927
|
+
isLoading: isLoadingConfigs,
|
928
|
+
error,
|
929
|
+
isFetching: isFetchingConfigs
|
930
|
+
} = useGetContentTypeConfigurationQuery(model);
|
931
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
802
932
|
React__namespace.useEffect(() => {
|
803
933
|
if (error) {
|
804
934
|
toggleNotification({
|
@@ -806,62 +936,318 @@ const useDocument = (args, opts) => {
|
|
806
936
|
message: formatAPIError(error)
|
807
937
|
});
|
808
938
|
}
|
809
|
-
}, [
|
810
|
-
const
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
(document) => {
|
818
|
-
if (!validationSchema) {
|
819
|
-
throw new Error(
|
820
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
821
|
-
);
|
822
|
-
}
|
823
|
-
try {
|
824
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
825
|
-
return null;
|
826
|
-
} catch (error2) {
|
827
|
-
if (error2 instanceof yup.ValidationError) {
|
828
|
-
return strapiAdmin.getYupValidationErrors(error2);
|
829
|
-
}
|
830
|
-
throw error2;
|
831
|
-
}
|
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
|
832
947
|
},
|
833
|
-
[
|
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]
|
834
964
|
);
|
835
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
836
965
|
return {
|
837
|
-
|
838
|
-
document: data?.data,
|
839
|
-
meta: data?.meta,
|
966
|
+
error,
|
840
967
|
isLoading,
|
841
|
-
|
842
|
-
|
968
|
+
edit,
|
969
|
+
list: listLayout
|
843
970
|
};
|
844
971
|
};
|
845
|
-
const
|
846
|
-
const {
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
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([]);
|
995
|
+
}
|
996
|
+
panels[currentPanelIndex].push(row);
|
997
|
+
}
|
998
|
+
return panels;
|
999
|
+
}, []);
|
1000
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
1001
|
+
(acc, [uid, configuration]) => {
|
1002
|
+
acc[uid] = {
|
1003
|
+
layout: convertEditLayoutToFieldLayouts(
|
1004
|
+
configuration.layouts.edit,
|
1005
|
+
components[uid].attributes,
|
1006
|
+
configuration.metadatas,
|
1007
|
+
{ configurations: data.components, schemas: components }
|
1008
|
+
),
|
1009
|
+
settings: {
|
1010
|
+
...configuration.settings,
|
1011
|
+
icon: components[uid].info.icon,
|
1012
|
+
displayName: components[uid].info.displayName
|
1013
|
+
}
|
1014
|
+
};
|
1015
|
+
return acc;
|
1016
|
+
},
|
1017
|
+
{}
|
1018
|
+
);
|
1019
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1020
|
+
(acc, [attribute, metadata]) => {
|
1021
|
+
return {
|
1022
|
+
...acc,
|
1023
|
+
[attribute]: metadata.edit
|
1024
|
+
};
|
1025
|
+
},
|
1026
|
+
{}
|
1027
|
+
);
|
1028
|
+
return {
|
1029
|
+
layout: panelledEditAttributes,
|
1030
|
+
components: componentEditAttributes,
|
1031
|
+
metadatas: editMetadatas,
|
1032
|
+
settings: {
|
1033
|
+
...data.contentType.settings,
|
1034
|
+
displayName: schema?.info.displayName
|
1035
|
+
},
|
1036
|
+
options: {
|
1037
|
+
...schema?.options,
|
1038
|
+
...schema?.pluginOptions,
|
1039
|
+
...data.contentType.options
|
1040
|
+
}
|
1041
|
+
};
|
1042
|
+
};
|
1043
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1044
|
+
return rows.map(
|
1045
|
+
(row) => row.map((field) => {
|
1046
|
+
const attribute = attributes[field.name];
|
1047
|
+
if (!attribute) {
|
1048
|
+
return null;
|
1049
|
+
}
|
1050
|
+
const { edit: metadata } = metadatas[field.name];
|
1051
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1052
|
+
return {
|
1053
|
+
attribute,
|
1054
|
+
disabled: !metadata.editable,
|
1055
|
+
hint: metadata.description,
|
1056
|
+
label: metadata.label ?? "",
|
1057
|
+
name: field.name,
|
1058
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1059
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1060
|
+
schemas,
|
1061
|
+
components: components?.schemas ?? {}
|
1062
|
+
}),
|
1063
|
+
placeholder: metadata.placeholder ?? "",
|
1064
|
+
required: attribute.required ?? false,
|
1065
|
+
size: field.size,
|
1066
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1067
|
+
visible: metadata.visible ?? true,
|
1068
|
+
type: attribute.type
|
1069
|
+
};
|
1070
|
+
}).filter((field) => field !== null)
|
1071
|
+
);
|
1072
|
+
};
|
1073
|
+
const formatListLayout = (data, {
|
1074
|
+
schemas,
|
1075
|
+
schema,
|
1076
|
+
components
|
1077
|
+
}) => {
|
1078
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1079
|
+
(acc, [attribute, metadata]) => {
|
1080
|
+
return {
|
1081
|
+
...acc,
|
1082
|
+
[attribute]: metadata.list
|
1083
|
+
};
|
1084
|
+
},
|
1085
|
+
{}
|
1086
|
+
);
|
1087
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1088
|
+
data.contentType.layouts.list,
|
1089
|
+
schema?.attributes,
|
1090
|
+
listMetadatas,
|
1091
|
+
{ configurations: data.components, schemas: components },
|
1092
|
+
schemas
|
1093
|
+
);
|
1094
|
+
return {
|
1095
|
+
layout: listAttributes,
|
1096
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1097
|
+
metadatas: listMetadatas,
|
1098
|
+
options: {
|
1099
|
+
...schema?.options,
|
1100
|
+
...schema?.pluginOptions,
|
1101
|
+
...data.contentType.options
|
1102
|
+
}
|
1103
|
+
};
|
1104
|
+
};
|
1105
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1106
|
+
return columns.map((name) => {
|
1107
|
+
const attribute = attributes[name];
|
1108
|
+
if (!attribute) {
|
1109
|
+
return null;
|
1110
|
+
}
|
1111
|
+
const metadata = metadatas[name];
|
1112
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1113
|
+
return {
|
1114
|
+
attribute,
|
1115
|
+
label: metadata.label ?? "",
|
1116
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1117
|
+
schemas,
|
1118
|
+
components: components?.schemas ?? {}
|
1119
|
+
}),
|
1120
|
+
name,
|
1121
|
+
searchable: metadata.searchable ?? true,
|
1122
|
+
sortable: metadata.sortable ?? true
|
1123
|
+
};
|
1124
|
+
}).filter((field) => field !== null);
|
1125
|
+
};
|
1126
|
+
const useDocument = (args, opts) => {
|
1127
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1128
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1129
|
+
const {
|
1130
|
+
currentData: data,
|
1131
|
+
isLoading: isLoadingDocument,
|
1132
|
+
isFetching: isFetchingDocument,
|
1133
|
+
error
|
1134
|
+
} = useGetDocumentQuery(args, {
|
1135
|
+
...opts,
|
1136
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1137
|
+
});
|
1138
|
+
const {
|
1139
|
+
components,
|
1140
|
+
schema,
|
1141
|
+
schemas,
|
1142
|
+
isLoading: isLoadingSchema
|
1143
|
+
} = useContentTypeSchema(args.model);
|
1144
|
+
React__namespace.useEffect(() => {
|
1145
|
+
if (error) {
|
1146
|
+
toggleNotification({
|
1147
|
+
type: "danger",
|
1148
|
+
message: formatAPIError(error)
|
1149
|
+
});
|
1150
|
+
}
|
1151
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1152
|
+
const validationSchema = React__namespace.useMemo(() => {
|
1153
|
+
if (!schema) {
|
1154
|
+
return null;
|
1155
|
+
}
|
1156
|
+
return createYupSchema(schema.attributes, components);
|
1157
|
+
}, [schema, components]);
|
1158
|
+
const validate = React__namespace.useCallback(
|
1159
|
+
(document) => {
|
1160
|
+
if (!validationSchema) {
|
1161
|
+
throw new Error(
|
1162
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1163
|
+
);
|
1164
|
+
}
|
1165
|
+
try {
|
1166
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1167
|
+
return null;
|
1168
|
+
} catch (error2) {
|
1169
|
+
if (error2 instanceof yup.ValidationError) {
|
1170
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
1171
|
+
}
|
1172
|
+
throw error2;
|
1173
|
+
}
|
1174
|
+
},
|
1175
|
+
[validationSchema]
|
1176
|
+
);
|
1177
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1178
|
+
const hasError = !!error;
|
1179
|
+
return {
|
1180
|
+
components,
|
1181
|
+
document: data?.data,
|
1182
|
+
meta: data?.meta,
|
1183
|
+
isLoading,
|
1184
|
+
hasError,
|
1185
|
+
schema,
|
1186
|
+
schemas,
|
1187
|
+
validate
|
1188
|
+
};
|
1189
|
+
};
|
1190
|
+
const useDoc = () => {
|
1191
|
+
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
1192
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
1193
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1194
|
+
if (!collectionType) {
|
1195
|
+
throw new Error("Could not find collectionType in url params");
|
1196
|
+
}
|
1197
|
+
if (!slug) {
|
853
1198
|
throw new Error("Could not find model in url params");
|
854
1199
|
}
|
1200
|
+
const document = useDocument(
|
1201
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1202
|
+
{
|
1203
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1204
|
+
}
|
1205
|
+
);
|
1206
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
855
1207
|
return {
|
856
1208
|
collectionType,
|
857
1209
|
model: slug,
|
858
|
-
id:
|
859
|
-
...
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
1210
|
+
id: returnId,
|
1211
|
+
...document
|
1212
|
+
};
|
1213
|
+
};
|
1214
|
+
const useContentManagerContext = () => {
|
1215
|
+
const {
|
1216
|
+
collectionType,
|
1217
|
+
model,
|
1218
|
+
id,
|
1219
|
+
components,
|
1220
|
+
isLoading: isLoadingDoc,
|
1221
|
+
schema,
|
1222
|
+
schemas
|
1223
|
+
} = useDoc();
|
1224
|
+
const layout = useDocumentLayout(model);
|
1225
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1226
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1227
|
+
const slug = model;
|
1228
|
+
const isCreatingEntry = id === "create";
|
1229
|
+
useContentTypeSchema();
|
1230
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1231
|
+
const error = layout.error;
|
1232
|
+
return {
|
1233
|
+
error,
|
1234
|
+
isLoading,
|
1235
|
+
// Base metadata
|
1236
|
+
model,
|
1237
|
+
collectionType,
|
1238
|
+
id,
|
1239
|
+
slug,
|
1240
|
+
isCreatingEntry,
|
1241
|
+
isSingleType,
|
1242
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1243
|
+
// All schema infos
|
1244
|
+
components,
|
1245
|
+
contentType: schema,
|
1246
|
+
contentTypes: schemas,
|
1247
|
+
// Form state
|
1248
|
+
form,
|
1249
|
+
// layout infos
|
1250
|
+
layout
|
865
1251
|
};
|
866
1252
|
};
|
867
1253
|
const prefixPluginTranslations = (trad, pluginId) => {
|
@@ -883,6 +1269,8 @@ const useDocumentActions = () => {
|
|
883
1269
|
const { formatMessage } = reactIntl.useIntl();
|
884
1270
|
const { trackUsage } = strapiAdmin.useTracking();
|
885
1271
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1272
|
+
const navigate = reactRouterDom.useNavigate();
|
1273
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
886
1274
|
const [deleteDocument] = useDeleteDocumentMutation();
|
887
1275
|
const _delete = React__namespace.useCallback(
|
888
1276
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1197,6 +1585,7 @@ const useDocumentActions = () => {
|
|
1197
1585
|
defaultMessage: "Saved document"
|
1198
1586
|
})
|
1199
1587
|
});
|
1588
|
+
setCurrentStep("contentManager.success");
|
1200
1589
|
return res.data;
|
1201
1590
|
} catch (err) {
|
1202
1591
|
toggleNotification({
|
@@ -1218,7 +1607,6 @@ const useDocumentActions = () => {
|
|
1218
1607
|
sourceId
|
1219
1608
|
});
|
1220
1609
|
if ("error" in res) {
|
1221
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1222
1610
|
return { error: res.error };
|
1223
1611
|
}
|
1224
1612
|
toggleNotification({
|
@@ -1237,7 +1625,7 @@ const useDocumentActions = () => {
|
|
1237
1625
|
throw err;
|
1238
1626
|
}
|
1239
1627
|
},
|
1240
|
-
[autoCloneDocument,
|
1628
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1241
1629
|
);
|
1242
1630
|
const [cloneDocument] = useCloneDocumentMutation();
|
1243
1631
|
const clone = React__namespace.useCallback(
|
@@ -1263,6 +1651,7 @@ const useDocumentActions = () => {
|
|
1263
1651
|
defaultMessage: "Cloned document"
|
1264
1652
|
})
|
1265
1653
|
});
|
1654
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1266
1655
|
return res.data;
|
1267
1656
|
} catch (err) {
|
1268
1657
|
toggleNotification({
|
@@ -1273,7 +1662,7 @@ const useDocumentActions = () => {
|
|
1273
1662
|
throw err;
|
1274
1663
|
}
|
1275
1664
|
},
|
1276
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1665
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1277
1666
|
);
|
1278
1667
|
const [getDoc] = useLazyGetDocumentQuery();
|
1279
1668
|
const getDocument = React__namespace.useCallback(
|
@@ -1299,7 +1688,7 @@ const useDocumentActions = () => {
|
|
1299
1688
|
};
|
1300
1689
|
};
|
1301
1690
|
const ProtectedHistoryPage = React.lazy(
|
1302
|
-
() => Promise.resolve().then(() => require("./History-
|
1691
|
+
() => Promise.resolve().then(() => require("./History-DZ9T1ZL6.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1303
1692
|
);
|
1304
1693
|
const routes$1 = [
|
1305
1694
|
{
|
@@ -1312,31 +1701,31 @@ const routes$1 = [
|
|
1312
1701
|
}
|
1313
1702
|
];
|
1314
1703
|
const ProtectedEditViewPage = React.lazy(
|
1315
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1704
|
+
() => Promise.resolve().then(() => require("./EditViewPage-BfAywbBE.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1316
1705
|
);
|
1317
1706
|
const ProtectedListViewPage = React.lazy(
|
1318
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1707
|
+
() => Promise.resolve().then(() => require("./ListViewPage-BfiTNTUl.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1319
1708
|
);
|
1320
1709
|
const ProtectedListConfiguration = React.lazy(
|
1321
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1710
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-B8bYMcVE.js")).then((mod) => ({
|
1322
1711
|
default: mod.ProtectedListConfiguration
|
1323
1712
|
}))
|
1324
1713
|
);
|
1325
1714
|
const ProtectedEditConfigurationPage = React.lazy(
|
1326
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1715
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-BP94U6vG.js")).then((mod) => ({
|
1327
1716
|
default: mod.ProtectedEditConfigurationPage
|
1328
1717
|
}))
|
1329
1718
|
);
|
1330
1719
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1331
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1720
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-D1SEOQBu.js")).then((mod) => ({
|
1332
1721
|
default: mod.ProtectedComponentConfigurationPage
|
1333
1722
|
}))
|
1334
1723
|
);
|
1335
1724
|
const NoPermissions = React.lazy(
|
1336
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1725
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-DKaXyuK9.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1337
1726
|
);
|
1338
1727
|
const NoContentType = React.lazy(
|
1339
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1728
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-wJwVyqoZ.js")).then((mod) => ({ default: mod.NoContentType }))
|
1340
1729
|
);
|
1341
1730
|
const CollectionTypePages = () => {
|
1342
1731
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1450,12 +1839,14 @@ const DocumentActionButton = (action) => {
|
|
1450
1839
|
/* @__PURE__ */ jsxRuntime.jsx(
|
1451
1840
|
designSystem.Button,
|
1452
1841
|
{
|
1453
|
-
flex:
|
1842
|
+
flex: "auto",
|
1454
1843
|
startIcon: action.icon,
|
1455
1844
|
disabled: action.disabled,
|
1456
1845
|
onClick: handleClick(action),
|
1457
1846
|
justifyContent: "center",
|
1458
1847
|
variant: action.variant || "default",
|
1848
|
+
paddingTop: "7px",
|
1849
|
+
paddingBottom: "7px",
|
1459
1850
|
children: action.label
|
1460
1851
|
}
|
1461
1852
|
),
|
@@ -1463,7 +1854,7 @@ const DocumentActionButton = (action) => {
|
|
1463
1854
|
DocumentActionConfirmDialog,
|
1464
1855
|
{
|
1465
1856
|
...action.dialog,
|
1466
|
-
variant: action.variant,
|
1857
|
+
variant: action.dialog?.variant ?? action.variant,
|
1467
1858
|
isOpen: dialogId === action.id,
|
1468
1859
|
onClose: handleClose
|
1469
1860
|
}
|
@@ -1520,9 +1911,9 @@ const DocumentActionsMenu = ({
|
|
1520
1911
|
disabled: isDisabled,
|
1521
1912
|
size: "S",
|
1522
1913
|
endIcon: null,
|
1523
|
-
paddingTop: "
|
1524
|
-
paddingLeft: "
|
1525
|
-
paddingRight: "
|
1914
|
+
paddingTop: "4px",
|
1915
|
+
paddingLeft: "7px",
|
1916
|
+
paddingRight: "7px",
|
1526
1917
|
variant,
|
1527
1918
|
children: [
|
1528
1919
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
@@ -1533,7 +1924,7 @@ const DocumentActionsMenu = ({
|
|
1533
1924
|
]
|
1534
1925
|
}
|
1535
1926
|
),
|
1536
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, {
|
1927
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1537
1928
|
actions2.map((action) => {
|
1538
1929
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
1539
1930
|
designSystem.Menu.Item,
|
@@ -1542,10 +1933,25 @@ const DocumentActionsMenu = ({
|
|
1542
1933
|
onSelect: handleClick(action),
|
1543
1934
|
display: "block",
|
1544
1935
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1545
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1936
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1937
|
+
designSystem.Flex,
|
1938
|
+
{
|
1939
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1940
|
+
gap: 2,
|
1941
|
+
tag: "span",
|
1942
|
+
children: [
|
1943
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1944
|
+
designSystem.Flex,
|
1945
|
+
{
|
1946
|
+
tag: "span",
|
1947
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1948
|
+
children: action.icon
|
1949
|
+
}
|
1950
|
+
),
|
1951
|
+
action.label
|
1952
|
+
]
|
1953
|
+
}
|
1954
|
+
),
|
1549
1955
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1550
1956
|
designSystem.Flex,
|
1551
1957
|
{
|
@@ -1642,11 +2048,11 @@ const DocumentActionConfirmDialog = ({
|
|
1642
2048
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1643
2049
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1644
2050
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1645
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
2051
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1646
2052
|
id: "app.components.Button.cancel",
|
1647
2053
|
defaultMessage: "Cancel"
|
1648
2054
|
}) }) }),
|
1649
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2055
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1650
2056
|
id: "app.components.Button.confirm",
|
1651
2057
|
defaultMessage: "Confirm"
|
1652
2058
|
}) })
|
@@ -1673,6 +2079,18 @@ const DocumentActionModal = ({
|
|
1673
2079
|
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
1674
2080
|
] }) });
|
1675
2081
|
};
|
2082
|
+
const transformData = (data) => {
|
2083
|
+
if (Array.isArray(data)) {
|
2084
|
+
return data.map(transformData);
|
2085
|
+
}
|
2086
|
+
if (typeof data === "object" && data !== null) {
|
2087
|
+
if ("apiData" in data) {
|
2088
|
+
return data.apiData;
|
2089
|
+
}
|
2090
|
+
return mapValues__default.default(transformData)(data);
|
2091
|
+
}
|
2092
|
+
return data;
|
2093
|
+
};
|
1676
2094
|
const PublishAction$1 = ({
|
1677
2095
|
activeTab,
|
1678
2096
|
documentId,
|
@@ -1685,13 +2103,17 @@ const PublishAction$1 = ({
|
|
1685
2103
|
const navigate = reactRouterDom.useNavigate();
|
1686
2104
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1687
2105
|
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2106
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
1688
2107
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
1689
2108
|
const { formatMessage } = reactIntl.useIntl();
|
1690
|
-
const { canPublish
|
1691
|
-
"PublishAction",
|
1692
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1693
|
-
);
|
2109
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1694
2110
|
const { publish } = useDocumentActions();
|
2111
|
+
const [
|
2112
|
+
countDraftRelations,
|
2113
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2114
|
+
] = useLazyGetDraftRelationCountQuery();
|
2115
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2116
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1695
2117
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1696
2118
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1697
2119
|
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1700,62 +2122,144 @@ const PublishAction$1 = ({
|
|
1700
2122
|
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1701
2123
|
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1702
2124
|
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
2125
|
+
React__namespace.useEffect(() => {
|
2126
|
+
if (isErrorDraftRelations) {
|
2127
|
+
toggleNotification({
|
2128
|
+
type: "danger",
|
2129
|
+
message: formatMessage({
|
2130
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2131
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2132
|
+
})
|
2133
|
+
});
|
2134
|
+
}
|
2135
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2136
|
+
React__namespace.useEffect(() => {
|
2137
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2138
|
+
const extractDraftRelations = (data) => {
|
2139
|
+
const relations = data.connect || [];
|
2140
|
+
relations.forEach((relation) => {
|
2141
|
+
if (relation.status === "draft") {
|
2142
|
+
localDraftRelations.add(relation.id);
|
2143
|
+
}
|
2144
|
+
});
|
2145
|
+
};
|
2146
|
+
const traverseAndExtract = (data) => {
|
2147
|
+
Object.entries(data).forEach(([key, value]) => {
|
2148
|
+
if (key === "connect" && Array.isArray(value)) {
|
2149
|
+
extractDraftRelations({ connect: value });
|
2150
|
+
} else if (typeof value === "object" && value !== null) {
|
2151
|
+
traverseAndExtract(value);
|
2152
|
+
}
|
2153
|
+
});
|
2154
|
+
};
|
2155
|
+
if (!documentId || modified) {
|
2156
|
+
traverseAndExtract(formValues);
|
2157
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2158
|
+
}
|
2159
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2160
|
+
React__namespace.useEffect(() => {
|
2161
|
+
if (!document || !document.documentId || isListView) {
|
2162
|
+
return;
|
2163
|
+
}
|
2164
|
+
const fetchDraftRelationsCount = async () => {
|
2165
|
+
const { data, error } = await countDraftRelations({
|
2166
|
+
collectionType,
|
2167
|
+
model,
|
2168
|
+
documentId,
|
2169
|
+
params
|
2170
|
+
});
|
2171
|
+
if (error) {
|
2172
|
+
throw error;
|
2173
|
+
}
|
2174
|
+
if (data) {
|
2175
|
+
setServerCountOfDraftRelations(data.data);
|
2176
|
+
}
|
2177
|
+
};
|
2178
|
+
fetchDraftRelationsCount();
|
2179
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2180
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2181
|
+
if (!schema?.options?.draftAndPublish) {
|
2182
|
+
return null;
|
2183
|
+
}
|
2184
|
+
const performPublish = async () => {
|
2185
|
+
setSubmitting(true);
|
2186
|
+
try {
|
2187
|
+
const { errors } = await validate(true, {
|
2188
|
+
status: "published"
|
2189
|
+
});
|
2190
|
+
if (errors) {
|
2191
|
+
toggleNotification({
|
2192
|
+
type: "danger",
|
2193
|
+
message: formatMessage({
|
2194
|
+
id: "content-manager.validation.error",
|
2195
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2196
|
+
})
|
2197
|
+
});
|
2198
|
+
return;
|
2199
|
+
}
|
2200
|
+
const res = await publish(
|
2201
|
+
{
|
2202
|
+
collectionType,
|
2203
|
+
model,
|
2204
|
+
documentId,
|
2205
|
+
params
|
2206
|
+
},
|
2207
|
+
transformData(formValues)
|
2208
|
+
);
|
2209
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2210
|
+
navigate({
|
2211
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2212
|
+
search: rawQuery
|
2213
|
+
});
|
2214
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2215
|
+
setErrors(formatValidationErrors(res.error));
|
2216
|
+
}
|
2217
|
+
} finally {
|
2218
|
+
setSubmitting(false);
|
2219
|
+
}
|
2220
|
+
};
|
2221
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2222
|
+
const enableDraftRelationsCount = false;
|
2223
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
2224
|
+
return {
|
2225
|
+
/**
|
2226
|
+
* Disabled when:
|
2227
|
+
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
1711
2228
|
* - the form is submitting
|
1712
2229
|
* - the active tab is the published tab
|
1713
2230
|
* - the document is already published & not modified
|
1714
2231
|
* - the document is being created & not modified
|
1715
2232
|
* - the user doesn't have the permission to publish
|
1716
|
-
* - the user doesn't have the permission to create a new document
|
1717
|
-
* - the user doesn't have the permission to update the document
|
1718
2233
|
*/
|
1719
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2234
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1720
2235
|
label: formatMessage({
|
1721
2236
|
id: "app.utils.publish",
|
1722
2237
|
defaultMessage: "Publish"
|
1723
2238
|
}),
|
1724
2239
|
onClick: async () => {
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
documentId,
|
1743
|
-
params
|
1744
|
-
},
|
1745
|
-
formValues
|
1746
|
-
);
|
1747
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1748
|
-
navigate({
|
1749
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1750
|
-
search: rawQuery
|
1751
|
-
});
|
1752
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1753
|
-
setErrors(formatValidationErrors(res.error));
|
2240
|
+
await performPublish();
|
2241
|
+
},
|
2242
|
+
dialog: hasDraftRelations ? {
|
2243
|
+
type: "dialog",
|
2244
|
+
variant: "danger",
|
2245
|
+
footer: null,
|
2246
|
+
title: formatMessage({
|
2247
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2248
|
+
defaultMessage: "Confirmation"
|
2249
|
+
}),
|
2250
|
+
content: formatMessage(
|
2251
|
+
{
|
2252
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2253
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2254
|
+
},
|
2255
|
+
{
|
2256
|
+
count: totalDraftRelations
|
1754
2257
|
}
|
1755
|
-
|
1756
|
-
|
2258
|
+
),
|
2259
|
+
onConfirm: async () => {
|
2260
|
+
await performPublish();
|
1757
2261
|
}
|
1758
|
-
}
|
2262
|
+
} : void 0
|
1759
2263
|
};
|
1760
2264
|
};
|
1761
2265
|
PublishAction$1.type = "publish";
|
@@ -1771,10 +2275,6 @@ const UpdateAction = ({
|
|
1771
2275
|
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
1772
2276
|
const isCloning = cloneMatch !== null;
|
1773
2277
|
const { formatMessage } = reactIntl.useIntl();
|
1774
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1775
|
-
canCreate: canCreate2,
|
1776
|
-
canUpdate: canUpdate2
|
1777
|
-
}));
|
1778
2278
|
const { create, update, clone } = useDocumentActions();
|
1779
2279
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1780
2280
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
@@ -1791,10 +2291,8 @@ const UpdateAction = ({
|
|
1791
2291
|
* - the form is submitting
|
1792
2292
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1793
2293
|
* - the active tab is the published tab
|
1794
|
-
* - the user doesn't have the permission to create a new document
|
1795
|
-
* - the user doesn't have the permission to update the document
|
1796
2294
|
*/
|
1797
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2295
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1798
2296
|
label: formatMessage({
|
1799
2297
|
id: "content-manager.containers.Edit.save",
|
1800
2298
|
defaultMessage: "Save"
|
@@ -1802,7 +2300,9 @@ const UpdateAction = ({
|
|
1802
2300
|
onClick: async () => {
|
1803
2301
|
setSubmitting(true);
|
1804
2302
|
try {
|
1805
|
-
const { errors } = await validate(
|
2303
|
+
const { errors } = await validate(true, {
|
2304
|
+
status: "draft"
|
2305
|
+
});
|
1806
2306
|
if (errors) {
|
1807
2307
|
toggleNotification({
|
1808
2308
|
type: "danger",
|
@@ -1820,13 +2320,16 @@ const UpdateAction = ({
|
|
1820
2320
|
documentId: cloneMatch.params.origin,
|
1821
2321
|
params
|
1822
2322
|
},
|
1823
|
-
document
|
2323
|
+
transformData(document)
|
1824
2324
|
);
|
1825
2325
|
if ("data" in res) {
|
1826
|
-
navigate(
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
2326
|
+
navigate(
|
2327
|
+
{
|
2328
|
+
pathname: `../${res.data.documentId}`,
|
2329
|
+
search: rawQuery
|
2330
|
+
},
|
2331
|
+
{ relative: "path" }
|
2332
|
+
);
|
1830
2333
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1831
2334
|
setErrors(formatValidationErrors(res.error));
|
1832
2335
|
}
|
@@ -1838,7 +2341,7 @@ const UpdateAction = ({
|
|
1838
2341
|
documentId,
|
1839
2342
|
params
|
1840
2343
|
},
|
1841
|
-
document
|
2344
|
+
transformData(document)
|
1842
2345
|
);
|
1843
2346
|
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1844
2347
|
setErrors(formatValidationErrors(res.error));
|
@@ -1851,13 +2354,16 @@ const UpdateAction = ({
|
|
1851
2354
|
model,
|
1852
2355
|
params
|
1853
2356
|
},
|
1854
|
-
document
|
2357
|
+
transformData(document)
|
1855
2358
|
);
|
1856
2359
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1857
|
-
navigate(
|
1858
|
-
|
1859
|
-
|
1860
|
-
|
2360
|
+
navigate(
|
2361
|
+
{
|
2362
|
+
pathname: `../${res.data.documentId}`,
|
2363
|
+
search: rawQuery
|
2364
|
+
},
|
2365
|
+
{ replace: true, relative: "path" }
|
2366
|
+
);
|
1861
2367
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1862
2368
|
setErrors(formatValidationErrors(res.error));
|
1863
2369
|
}
|
@@ -1901,7 +2407,7 @@ const UnpublishAction$1 = ({
|
|
1901
2407
|
id: "app.utils.unpublish",
|
1902
2408
|
defaultMessage: "Unpublish"
|
1903
2409
|
}),
|
1904
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2410
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1905
2411
|
onClick: async () => {
|
1906
2412
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1907
2413
|
if (!documentId) {
|
@@ -2013,7 +2519,7 @@ const DiscardAction = ({
|
|
2013
2519
|
id: "content-manager.actions.discard.label",
|
2014
2520
|
defaultMessage: "Discard changes"
|
2015
2521
|
}),
|
2016
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2522
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2017
2523
|
position: ["panel", "table-row"],
|
2018
2524
|
variant: "danger",
|
2019
2525
|
dialog: {
|
@@ -2041,11 +2547,6 @@ const DiscardAction = ({
|
|
2041
2547
|
};
|
2042
2548
|
};
|
2043
2549
|
DiscardAction.type = "discard";
|
2044
|
-
const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
|
2045
|
-
path {
|
2046
|
-
fill: currentColor;
|
2047
|
-
}
|
2048
|
-
`;
|
2049
2550
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2050
2551
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2051
2552
|
const RelativeTime = React__namespace.forwardRef(
|
@@ -2093,7 +2594,7 @@ const getDisplayName = ({
|
|
2093
2594
|
};
|
2094
2595
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2095
2596
|
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2096
|
-
const statusVariant = status === "draft" ? "
|
2597
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2097
2598
|
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) }) });
|
2098
2599
|
};
|
2099
2600
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
@@ -2103,23 +2604,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2103
2604
|
id: "content-manager.containers.edit.title.new",
|
2104
2605
|
defaultMessage: "Create an entry"
|
2105
2606
|
}) : documentTitle;
|
2106
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2607
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2107
2608
|
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
2108
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
2109
|
-
designSystem.
|
2110
|
-
{
|
2111
|
-
|
2112
|
-
|
2113
|
-
paddingTop: 1,
|
2114
|
-
gap: "80px",
|
2115
|
-
alignItems: "flex-start",
|
2116
|
-
children: [
|
2117
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2118
|
-
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2119
|
-
]
|
2120
|
-
}
|
2121
|
-
),
|
2122
|
-
status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2609
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2610
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2611
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2612
|
+
] }),
|
2613
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2123
2614
|
] });
|
2124
2615
|
};
|
2125
2616
|
const HeaderToolbar = () => {
|
@@ -2202,12 +2693,12 @@ const Information = ({ activeTab }) => {
|
|
2202
2693
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2203
2694
|
label: formatMessage({
|
2204
2695
|
id: "content-manager.containers.edit.information.last-published.label",
|
2205
|
-
defaultMessage: "
|
2696
|
+
defaultMessage: "Published"
|
2206
2697
|
}),
|
2207
2698
|
value: formatMessage(
|
2208
2699
|
{
|
2209
2700
|
id: "content-manager.containers.edit.information.last-published.value",
|
2210
|
-
defaultMessage: `
|
2701
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2211
2702
|
},
|
2212
2703
|
{
|
2213
2704
|
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2220,12 +2711,12 @@ const Information = ({ activeTab }) => {
|
|
2220
2711
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2221
2712
|
label: formatMessage({
|
2222
2713
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2223
|
-
defaultMessage: "
|
2714
|
+
defaultMessage: "Updated"
|
2224
2715
|
}),
|
2225
2716
|
value: formatMessage(
|
2226
2717
|
{
|
2227
2718
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2228
|
-
defaultMessage: `
|
2719
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2229
2720
|
},
|
2230
2721
|
{
|
2231
2722
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2243,12 +2734,12 @@ const Information = ({ activeTab }) => {
|
|
2243
2734
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2244
2735
|
label: formatMessage({
|
2245
2736
|
id: "content-manager.containers.edit.information.document.label",
|
2246
|
-
defaultMessage: "
|
2737
|
+
defaultMessage: "Created"
|
2247
2738
|
}),
|
2248
2739
|
value: formatMessage(
|
2249
2740
|
{
|
2250
2741
|
id: "content-manager.containers.edit.information.document.value",
|
2251
|
-
defaultMessage: `
|
2742
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2252
2743
|
},
|
2253
2744
|
{
|
2254
2745
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2286,25 +2777,77 @@ const Information = ({ activeTab }) => {
|
|
2286
2777
|
);
|
2287
2778
|
};
|
2288
2779
|
const HeaderActions = ({ actions: actions2 }) => {
|
2289
|
-
|
2290
|
-
|
2780
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2781
|
+
const handleClick = (action) => async (e) => {
|
2782
|
+
if (!("options" in action)) {
|
2783
|
+
const { onClick = () => false, dialog, id } = action;
|
2784
|
+
const muteDialog = await onClick(e);
|
2785
|
+
if (dialog && !muteDialog) {
|
2786
|
+
e.preventDefault();
|
2787
|
+
setDialogId(id);
|
2788
|
+
}
|
2789
|
+
}
|
2790
|
+
};
|
2791
|
+
const handleClose = () => {
|
2792
|
+
setDialogId(null);
|
2793
|
+
};
|
2794
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2795
|
+
if (action.options) {
|
2291
2796
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2292
2797
|
designSystem.SingleSelect,
|
2293
2798
|
{
|
2294
2799
|
size: "S",
|
2295
|
-
disabled: action.disabled,
|
2296
|
-
"aria-label": action.label,
|
2297
2800
|
onChange: action.onSelect,
|
2298
|
-
|
2801
|
+
"aria-label": action.label,
|
2802
|
+
...action,
|
2299
2803
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2300
2804
|
},
|
2301
2805
|
action.id
|
2302
2806
|
);
|
2303
2807
|
} else {
|
2304
|
-
|
2808
|
+
if (action.type === "icon") {
|
2809
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2810
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2811
|
+
designSystem.IconButton,
|
2812
|
+
{
|
2813
|
+
disabled: action.disabled,
|
2814
|
+
label: action.label,
|
2815
|
+
size: "S",
|
2816
|
+
onClick: handleClick(action),
|
2817
|
+
children: action.icon
|
2818
|
+
}
|
2819
|
+
),
|
2820
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2821
|
+
HeaderActionDialog,
|
2822
|
+
{
|
2823
|
+
...action.dialog,
|
2824
|
+
isOpen: dialogId === action.id,
|
2825
|
+
onClose: handleClose
|
2826
|
+
}
|
2827
|
+
) : null
|
2828
|
+
] }, action.id);
|
2829
|
+
}
|
2305
2830
|
}
|
2306
2831
|
}) });
|
2307
2832
|
};
|
2833
|
+
const HeaderActionDialog = ({
|
2834
|
+
onClose,
|
2835
|
+
onCancel,
|
2836
|
+
title,
|
2837
|
+
content: Content,
|
2838
|
+
isOpen
|
2839
|
+
}) => {
|
2840
|
+
const handleClose = async () => {
|
2841
|
+
if (onCancel) {
|
2842
|
+
await onCancel();
|
2843
|
+
}
|
2844
|
+
onClose();
|
2845
|
+
};
|
2846
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2847
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2848
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2849
|
+
] }) });
|
2850
|
+
};
|
2308
2851
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2309
2852
|
const navigate = reactRouterDom.useNavigate();
|
2310
2853
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2345,12 +2888,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2345
2888
|
const { delete: deleteAction } = useDocumentActions();
|
2346
2889
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2347
2890
|
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2891
|
+
const isLocalized = document?.locale != null;
|
2348
2892
|
return {
|
2349
2893
|
disabled: !canDelete || !document,
|
2350
|
-
label: formatMessage(
|
2351
|
-
|
2352
|
-
|
2353
|
-
|
2894
|
+
label: formatMessage(
|
2895
|
+
{
|
2896
|
+
id: "content-manager.actions.delete.label",
|
2897
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2898
|
+
},
|
2899
|
+
{ isLocalized }
|
2900
|
+
),
|
2354
2901
|
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2355
2902
|
dialog: {
|
2356
2903
|
type: "dialog",
|
@@ -2386,423 +2933,121 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2386
2933
|
const res = await deleteAction({
|
2387
2934
|
documentId,
|
2388
2935
|
model,
|
2389
|
-
collectionType,
|
2390
|
-
params: {
|
2391
|
-
locale: "*"
|
2392
|
-
}
|
2393
|
-
});
|
2394
|
-
if (!("error" in res)) {
|
2395
|
-
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2396
|
-
}
|
2397
|
-
} finally {
|
2398
|
-
if (!listViewPathMatch) {
|
2399
|
-
setSubmitting(false);
|
2400
|
-
}
|
2401
|
-
}
|
2402
|
-
}
|
2403
|
-
},
|
2404
|
-
variant: "danger",
|
2405
|
-
position: ["header", "table-row"]
|
2406
|
-
};
|
2407
|
-
};
|
2408
|
-
DeleteAction$1.type = "delete";
|
2409
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2410
|
-
const Panels = () => {
|
2411
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2412
|
-
const [
|
2413
|
-
{
|
2414
|
-
query: { status }
|
2415
|
-
}
|
2416
|
-
] = strapiAdmin.useQueryParams({
|
2417
|
-
status: "draft"
|
2418
|
-
});
|
2419
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2420
|
-
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2421
|
-
const props = {
|
2422
|
-
activeTab: status,
|
2423
|
-
model,
|
2424
|
-
documentId: id,
|
2425
|
-
document: isCloning ? void 0 : document,
|
2426
|
-
meta: isCloning ? void 0 : meta,
|
2427
|
-
collectionType
|
2428
|
-
};
|
2429
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2430
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2431
|
-
{
|
2432
|
-
props,
|
2433
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2434
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2435
|
-
}
|
2436
|
-
) });
|
2437
|
-
};
|
2438
|
-
const ActionsPanel = () => {
|
2439
|
-
const { formatMessage } = reactIntl.useIntl();
|
2440
|
-
return {
|
2441
|
-
title: formatMessage({
|
2442
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2443
|
-
defaultMessage: "Document"
|
2444
|
-
}),
|
2445
|
-
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2446
|
-
};
|
2447
|
-
};
|
2448
|
-
ActionsPanel.type = "actions";
|
2449
|
-
const ActionsPanelContent = () => {
|
2450
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2451
|
-
const [
|
2452
|
-
{
|
2453
|
-
query: { status = "draft" }
|
2454
|
-
}
|
2455
|
-
] = strapiAdmin.useQueryParams();
|
2456
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2457
|
-
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2458
|
-
const props = {
|
2459
|
-
activeTab: status,
|
2460
|
-
model,
|
2461
|
-
documentId: id,
|
2462
|
-
document: isCloning ? void 0 : document,
|
2463
|
-
meta: isCloning ? void 0 : meta,
|
2464
|
-
collectionType
|
2465
|
-
};
|
2466
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2467
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2468
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2469
|
-
{
|
2470
|
-
props,
|
2471
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2472
|
-
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
2473
|
-
}
|
2474
|
-
),
|
2475
|
-
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2476
|
-
] });
|
2477
|
-
};
|
2478
|
-
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
2479
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
2480
|
-
designSystem.Flex,
|
2481
|
-
{
|
2482
|
-
ref,
|
2483
|
-
tag: "aside",
|
2484
|
-
"aria-labelledby": "additional-information",
|
2485
|
-
background: "neutral0",
|
2486
|
-
borderColor: "neutral150",
|
2487
|
-
hasRadius: true,
|
2488
|
-
paddingBottom: 4,
|
2489
|
-
paddingLeft: 4,
|
2490
|
-
paddingRight: 4,
|
2491
|
-
paddingTop: 4,
|
2492
|
-
shadow: "tableShadow",
|
2493
|
-
gap: 3,
|
2494
|
-
direction: "column",
|
2495
|
-
justifyContent: "stretch",
|
2496
|
-
alignItems: "flex-start",
|
2497
|
-
children: [
|
2498
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2499
|
-
children
|
2500
|
-
]
|
2501
|
-
}
|
2502
|
-
);
|
2503
|
-
});
|
2504
|
-
const HOOKS = {
|
2505
|
-
/**
|
2506
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2507
|
-
* @constant
|
2508
|
-
* @type {string}
|
2509
|
-
*/
|
2510
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2511
|
-
/**
|
2512
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2513
|
-
* @constant
|
2514
|
-
* @type {string}
|
2515
|
-
*/
|
2516
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2517
|
-
/**
|
2518
|
-
* Hook that allows to mutate the CM's edit view layout
|
2519
|
-
* @constant
|
2520
|
-
* @type {string}
|
2521
|
-
*/
|
2522
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2523
|
-
/**
|
2524
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2525
|
-
* @constant
|
2526
|
-
* @type {string}
|
2527
|
-
*/
|
2528
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2529
|
-
};
|
2530
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2531
|
-
endpoints: (builder) => ({
|
2532
|
-
getContentTypeConfiguration: builder.query({
|
2533
|
-
query: (uid) => ({
|
2534
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2535
|
-
method: "GET"
|
2536
|
-
}),
|
2537
|
-
transformResponse: (response) => response.data,
|
2538
|
-
providesTags: (_result, _error, uid) => [
|
2539
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2540
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2541
|
-
]
|
2542
|
-
}),
|
2543
|
-
getAllContentTypeSettings: builder.query({
|
2544
|
-
query: () => "/content-manager/content-types-settings",
|
2545
|
-
transformResponse: (response) => response.data,
|
2546
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2547
|
-
}),
|
2548
|
-
updateContentTypeConfiguration: builder.mutation({
|
2549
|
-
query: ({ uid, ...body }) => ({
|
2550
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2551
|
-
method: "PUT",
|
2552
|
-
data: body
|
2553
|
-
}),
|
2554
|
-
transformResponse: (response) => response.data,
|
2555
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2556
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2557
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2558
|
-
// Is this necessary?
|
2559
|
-
{ type: "InitialData" }
|
2560
|
-
]
|
2561
|
-
})
|
2562
|
-
})
|
2563
|
-
});
|
2564
|
-
const {
|
2565
|
-
useGetContentTypeConfigurationQuery,
|
2566
|
-
useGetAllContentTypeSettingsQuery,
|
2567
|
-
useUpdateContentTypeConfigurationMutation
|
2568
|
-
} = contentTypesApi;
|
2569
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2570
|
-
const { type } = attribute;
|
2571
|
-
if (type === "relation") {
|
2572
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2573
|
-
}
|
2574
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2575
|
-
};
|
2576
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2577
|
-
if (!mainFieldName) {
|
2578
|
-
return void 0;
|
2579
|
-
}
|
2580
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2581
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2582
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2583
|
-
);
|
2584
|
-
return {
|
2585
|
-
name: mainFieldName,
|
2586
|
-
type: mainFieldType ?? "string"
|
2587
|
-
};
|
2588
|
-
};
|
2589
|
-
const DEFAULT_SETTINGS = {
|
2590
|
-
bulkable: false,
|
2591
|
-
filterable: false,
|
2592
|
-
searchable: false,
|
2593
|
-
pagination: false,
|
2594
|
-
defaultSortBy: "",
|
2595
|
-
defaultSortOrder: "asc",
|
2596
|
-
mainField: "id",
|
2597
|
-
pageSize: 10
|
2598
|
-
};
|
2599
|
-
const useDocumentLayout = (model) => {
|
2600
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2601
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
2602
|
-
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2603
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
2604
|
-
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
2605
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2606
|
-
const {
|
2607
|
-
data,
|
2608
|
-
isLoading: isLoadingConfigs,
|
2609
|
-
error,
|
2610
|
-
isFetching: isFetchingConfigs
|
2611
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2612
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2613
|
-
React__namespace.useEffect(() => {
|
2614
|
-
if (error) {
|
2615
|
-
toggleNotification({
|
2616
|
-
type: "danger",
|
2617
|
-
message: formatAPIError(error)
|
2618
|
-
});
|
2619
|
-
}
|
2620
|
-
}, [error, formatAPIError, toggleNotification]);
|
2621
|
-
const editLayout = React__namespace.useMemo(
|
2622
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2623
|
-
layout: [],
|
2624
|
-
components: {},
|
2625
|
-
metadatas: {},
|
2626
|
-
options: {},
|
2627
|
-
settings: DEFAULT_SETTINGS
|
2628
|
-
},
|
2629
|
-
[data, isLoading, schemas, schema, components]
|
2630
|
-
);
|
2631
|
-
const listLayout = React__namespace.useMemo(() => {
|
2632
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2633
|
-
layout: [],
|
2634
|
-
metadatas: {},
|
2635
|
-
options: {},
|
2636
|
-
settings: DEFAULT_SETTINGS
|
2637
|
-
};
|
2638
|
-
}, [data, isLoading, schemas, schema, components]);
|
2639
|
-
const { layout: edit } = React__namespace.useMemo(
|
2640
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2641
|
-
layout: editLayout,
|
2642
|
-
query
|
2643
|
-
}),
|
2644
|
-
[editLayout, query, runHookWaterfall]
|
2645
|
-
);
|
2646
|
-
return {
|
2647
|
-
error,
|
2648
|
-
isLoading,
|
2649
|
-
edit,
|
2650
|
-
list: listLayout
|
2651
|
-
};
|
2652
|
-
};
|
2653
|
-
const useDocLayout = () => {
|
2654
|
-
const { model } = useDoc();
|
2655
|
-
return useDocumentLayout(model);
|
2656
|
-
};
|
2657
|
-
const formatEditLayout = (data, {
|
2658
|
-
schemas,
|
2659
|
-
schema,
|
2660
|
-
components
|
2661
|
-
}) => {
|
2662
|
-
let currentPanelIndex = 0;
|
2663
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2664
|
-
data.contentType.layouts.edit,
|
2665
|
-
schema?.attributes,
|
2666
|
-
data.contentType.metadatas,
|
2667
|
-
{ configurations: data.components, schemas: components },
|
2668
|
-
schemas
|
2669
|
-
).reduce((panels, row) => {
|
2670
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2671
|
-
panels.push([row]);
|
2672
|
-
currentPanelIndex += 2;
|
2673
|
-
} else {
|
2674
|
-
if (!panels[currentPanelIndex]) {
|
2675
|
-
panels.push([]);
|
2676
|
-
}
|
2677
|
-
panels[currentPanelIndex].push(row);
|
2678
|
-
}
|
2679
|
-
return panels;
|
2680
|
-
}, []);
|
2681
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2682
|
-
(acc, [uid, configuration]) => {
|
2683
|
-
acc[uid] = {
|
2684
|
-
layout: convertEditLayoutToFieldLayouts(
|
2685
|
-
configuration.layouts.edit,
|
2686
|
-
components[uid].attributes,
|
2687
|
-
configuration.metadatas
|
2688
|
-
),
|
2689
|
-
settings: {
|
2690
|
-
...configuration.settings,
|
2691
|
-
icon: components[uid].info.icon,
|
2692
|
-
displayName: components[uid].info.displayName
|
2936
|
+
collectionType,
|
2937
|
+
params: {
|
2938
|
+
locale: "*"
|
2939
|
+
}
|
2940
|
+
});
|
2941
|
+
if (!("error" in res)) {
|
2942
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2943
|
+
}
|
2944
|
+
} finally {
|
2945
|
+
if (!listViewPathMatch) {
|
2946
|
+
setSubmitting(false);
|
2947
|
+
}
|
2693
2948
|
}
|
2694
|
-
}
|
2695
|
-
return acc;
|
2696
|
-
},
|
2697
|
-
{}
|
2698
|
-
);
|
2699
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2700
|
-
(acc, [attribute, metadata]) => {
|
2701
|
-
return {
|
2702
|
-
...acc,
|
2703
|
-
[attribute]: metadata.edit
|
2704
|
-
};
|
2705
|
-
},
|
2706
|
-
{}
|
2707
|
-
);
|
2708
|
-
return {
|
2709
|
-
layout: panelledEditAttributes,
|
2710
|
-
components: componentEditAttributes,
|
2711
|
-
metadatas: editMetadatas,
|
2712
|
-
settings: {
|
2713
|
-
...data.contentType.settings,
|
2714
|
-
displayName: schema?.info.displayName
|
2949
|
+
}
|
2715
2950
|
},
|
2716
|
-
|
2717
|
-
|
2718
|
-
...schema?.pluginOptions,
|
2719
|
-
...data.contentType.options
|
2720
|
-
}
|
2951
|
+
variant: "danger",
|
2952
|
+
position: ["header", "table-row"]
|
2721
2953
|
};
|
2722
2954
|
};
|
2723
|
-
|
2724
|
-
|
2725
|
-
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
}
|
2730
|
-
|
2731
|
-
|
2732
|
-
|
2733
|
-
|
2734
|
-
|
2735
|
-
|
2736
|
-
|
2737
|
-
|
2738
|
-
|
2739
|
-
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2744
|
-
|
2745
|
-
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2749
|
-
}
|
2750
|
-
}
|
2751
|
-
);
|
2955
|
+
DeleteAction$1.type = "delete";
|
2956
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2957
|
+
const Panels = () => {
|
2958
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2959
|
+
const [
|
2960
|
+
{
|
2961
|
+
query: { status }
|
2962
|
+
}
|
2963
|
+
] = strapiAdmin.useQueryParams({
|
2964
|
+
status: "draft"
|
2965
|
+
});
|
2966
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2967
|
+
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2968
|
+
const props = {
|
2969
|
+
activeTab: status,
|
2970
|
+
model,
|
2971
|
+
documentId: id,
|
2972
|
+
document: isCloning ? void 0 : document,
|
2973
|
+
meta: isCloning ? void 0 : meta,
|
2974
|
+
collectionType
|
2975
|
+
};
|
2976
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2977
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2978
|
+
{
|
2979
|
+
props,
|
2980
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2981
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2982
|
+
}
|
2983
|
+
) });
|
2752
2984
|
};
|
2753
|
-
const
|
2754
|
-
|
2755
|
-
schema,
|
2756
|
-
components
|
2757
|
-
}) => {
|
2758
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2759
|
-
(acc, [attribute, metadata]) => {
|
2760
|
-
return {
|
2761
|
-
...acc,
|
2762
|
-
[attribute]: metadata.list
|
2763
|
-
};
|
2764
|
-
},
|
2765
|
-
{}
|
2766
|
-
);
|
2767
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2768
|
-
data.contentType.layouts.list,
|
2769
|
-
schema?.attributes,
|
2770
|
-
listMetadatas,
|
2771
|
-
{ configurations: data.components, schemas: components },
|
2772
|
-
schemas
|
2773
|
-
);
|
2985
|
+
const ActionsPanel = () => {
|
2986
|
+
const { formatMessage } = reactIntl.useIntl();
|
2774
2987
|
return {
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2780
|
-
...schema?.pluginOptions,
|
2781
|
-
...data.contentType.options
|
2782
|
-
}
|
2988
|
+
title: formatMessage({
|
2989
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2990
|
+
defaultMessage: "Entry"
|
2991
|
+
}),
|
2992
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2783
2993
|
};
|
2784
2994
|
};
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2995
|
+
ActionsPanel.type = "actions";
|
2996
|
+
const ActionsPanelContent = () => {
|
2997
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2998
|
+
const [
|
2999
|
+
{
|
3000
|
+
query: { status = "draft" }
|
2790
3001
|
}
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
|
2800
|
-
|
2801
|
-
|
2802
|
-
|
2803
|
-
|
2804
|
-
|
3002
|
+
] = strapiAdmin.useQueryParams();
|
3003
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
3004
|
+
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
3005
|
+
const props = {
|
3006
|
+
activeTab: status,
|
3007
|
+
model,
|
3008
|
+
documentId: id,
|
3009
|
+
document: isCloning ? void 0 : document,
|
3010
|
+
meta: isCloning ? void 0 : meta,
|
3011
|
+
collectionType
|
3012
|
+
};
|
3013
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3014
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3015
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3016
|
+
{
|
3017
|
+
props,
|
3018
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3019
|
+
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
3020
|
+
}
|
3021
|
+
),
|
3022
|
+
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3023
|
+
] });
|
2805
3024
|
};
|
3025
|
+
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
3026
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
3027
|
+
designSystem.Flex,
|
3028
|
+
{
|
3029
|
+
ref,
|
3030
|
+
tag: "aside",
|
3031
|
+
"aria-labelledby": "additional-information",
|
3032
|
+
background: "neutral0",
|
3033
|
+
borderColor: "neutral150",
|
3034
|
+
hasRadius: true,
|
3035
|
+
paddingBottom: 4,
|
3036
|
+
paddingLeft: 4,
|
3037
|
+
paddingRight: 4,
|
3038
|
+
paddingTop: 4,
|
3039
|
+
shadow: "tableShadow",
|
3040
|
+
gap: 3,
|
3041
|
+
direction: "column",
|
3042
|
+
justifyContent: "stretch",
|
3043
|
+
alignItems: "flex-start",
|
3044
|
+
children: [
|
3045
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
3046
|
+
children
|
3047
|
+
]
|
3048
|
+
}
|
3049
|
+
);
|
3050
|
+
});
|
2806
3051
|
const ConfirmBulkActionDialog = ({
|
2807
3052
|
onToggleDialog,
|
2808
3053
|
isOpen = false,
|
@@ -2810,7 +3055,7 @@ const ConfirmBulkActionDialog = ({
|
|
2810
3055
|
endAction
|
2811
3056
|
}) => {
|
2812
3057
|
const { formatMessage } = reactIntl.useIntl();
|
2813
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, {
|
3058
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2814
3059
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
|
2815
3060
|
id: "app.components.ConfirmDialog.title",
|
2816
3061
|
defaultMessage: "Confirmation"
|
@@ -2841,6 +3086,7 @@ const ConfirmDialogPublishAll = ({
|
|
2841
3086
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2842
3087
|
const { model, schema } = useDoc();
|
2843
3088
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3089
|
+
const enableDraftRelationsCount = false;
|
2844
3090
|
const {
|
2845
3091
|
data: countDraftRelations = 0,
|
2846
3092
|
isLoading,
|
@@ -2852,7 +3098,7 @@ const ConfirmDialogPublishAll = ({
|
|
2852
3098
|
locale: query?.plugins?.i18n?.locale
|
2853
3099
|
},
|
2854
3100
|
{
|
2855
|
-
skip:
|
3101
|
+
skip: !enableDraftRelationsCount
|
2856
3102
|
}
|
2857
3103
|
);
|
2858
3104
|
React__namespace.useEffect(() => {
|
@@ -2931,7 +3177,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
|
2931
3177
|
)
|
2932
3178
|
);
|
2933
3179
|
} else {
|
2934
|
-
messages.push(
|
3180
|
+
messages.push(
|
3181
|
+
...formatErrorMessages(
|
3182
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3183
|
+
value,
|
3184
|
+
currentKey,
|
3185
|
+
formatMessage
|
3186
|
+
)
|
3187
|
+
);
|
2935
3188
|
}
|
2936
3189
|
} else {
|
2937
3190
|
messages.push(
|
@@ -3030,7 +3283,7 @@ const SelectedEntriesTableContent = ({
|
|
3030
3283
|
status: row.status
|
3031
3284
|
}
|
3032
3285
|
) }),
|
3033
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3286
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3034
3287
|
designSystem.IconButton,
|
3035
3288
|
{
|
3036
3289
|
tag: reactRouterDom.Link,
|
@@ -3053,9 +3306,10 @@ const SelectedEntriesTableContent = ({
|
|
3053
3306
|
),
|
3054
3307
|
target: "_blank",
|
3055
3308
|
marginLeft: "auto",
|
3056
|
-
|
3309
|
+
variant: "ghost",
|
3310
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3057
3311
|
}
|
3058
|
-
) })
|
3312
|
+
) }) })
|
3059
3313
|
] }, row.id)) })
|
3060
3314
|
] });
|
3061
3315
|
};
|
@@ -3092,7 +3346,13 @@ const SelectedEntriesModalContent = ({
|
|
3092
3346
|
);
|
3093
3347
|
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3094
3348
|
if (data.length > 0 && schema) {
|
3095
|
-
const validate = createYupSchema(
|
3349
|
+
const validate = createYupSchema(
|
3350
|
+
schema.attributes,
|
3351
|
+
components,
|
3352
|
+
// Since this is the "Publish" action, the validation
|
3353
|
+
// schema must enforce the rules for published entities
|
3354
|
+
{ status: "published" }
|
3355
|
+
);
|
3096
3356
|
const validationErrors2 = {};
|
3097
3357
|
const rows2 = data.map((entry) => {
|
3098
3358
|
try {
|
@@ -3442,7 +3702,7 @@ const TableActions = ({ document }) => {
|
|
3442
3702
|
strapiAdmin.DescriptionComponentRenderer,
|
3443
3703
|
{
|
3444
3704
|
props,
|
3445
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3705
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3446
3706
|
children: (actions2) => {
|
3447
3707
|
const tableRowActions = actions2.filter((action) => {
|
3448
3708
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3553,7 +3813,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3553
3813
|
}),
|
3554
3814
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3555
3815
|
footer: ({ onClose }) => {
|
3556
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3816
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3557
3817
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3558
3818
|
id: "cancel",
|
3559
3819
|
defaultMessage: "Cancel"
|
@@ -3594,8 +3854,7 @@ class ContentManagerPlugin {
|
|
3594
3854
|
documentActions = [
|
3595
3855
|
...DEFAULT_ACTIONS,
|
3596
3856
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3597
|
-
...DEFAULT_HEADER_ACTIONS
|
3598
|
-
HistoryAction
|
3857
|
+
...DEFAULT_HEADER_ACTIONS
|
3599
3858
|
];
|
3600
3859
|
editViewSidePanels = [ActionsPanel];
|
3601
3860
|
headerActions = [];
|
@@ -3684,6 +3943,52 @@ const getPrintableType = (value) => {
|
|
3684
3943
|
}
|
3685
3944
|
return nativeType;
|
3686
3945
|
};
|
3946
|
+
const HistoryAction = ({ model, document }) => {
|
3947
|
+
const { formatMessage } = reactIntl.useIntl();
|
3948
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3949
|
+
const navigate = reactRouterDom.useNavigate();
|
3950
|
+
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
3951
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3952
|
+
return null;
|
3953
|
+
}
|
3954
|
+
return {
|
3955
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
3956
|
+
label: formatMessage({
|
3957
|
+
id: "content-manager.history.document-action",
|
3958
|
+
defaultMessage: "Content History"
|
3959
|
+
}),
|
3960
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3961
|
+
disabled: (
|
3962
|
+
/**
|
3963
|
+
* The user is creating a new document.
|
3964
|
+
* It hasn't been saved yet, so there's no history to go to
|
3965
|
+
*/
|
3966
|
+
!document || /**
|
3967
|
+
* The document has been created but the current dimension has never been saved.
|
3968
|
+
* For example, the user is creating a new locale in an existing document,
|
3969
|
+
* so there's no history for the document in that locale
|
3970
|
+
*/
|
3971
|
+
!document.id || /**
|
3972
|
+
* History is only available for content types created by the user.
|
3973
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3974
|
+
* which start with `admin::` or `plugin::`
|
3975
|
+
*/
|
3976
|
+
!model.startsWith("api::")
|
3977
|
+
),
|
3978
|
+
position: "header"
|
3979
|
+
};
|
3980
|
+
};
|
3981
|
+
HistoryAction.type = "history";
|
3982
|
+
const historyAdmin = {
|
3983
|
+
bootstrap(app) {
|
3984
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3985
|
+
addDocumentAction((actions2) => {
|
3986
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3987
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3988
|
+
return actions2;
|
3989
|
+
});
|
3990
|
+
}
|
3991
|
+
};
|
3687
3992
|
const initialState = {
|
3688
3993
|
collectionTypeLinks: [],
|
3689
3994
|
components: [],
|
@@ -3734,15 +4039,29 @@ const index = {
|
|
3734
4039
|
defaultMessage: "Content Manager"
|
3735
4040
|
},
|
3736
4041
|
permissions: [],
|
3737
|
-
Component: () => Promise.resolve().then(() => require("./layout-BJfBoBiF.js")).then((mod) => ({ default: mod.Layout })),
|
3738
4042
|
position: 1
|
3739
4043
|
});
|
4044
|
+
app.router.addRoute({
|
4045
|
+
path: "content-manager/*",
|
4046
|
+
lazy: async () => {
|
4047
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-C_0aK53L.js"));
|
4048
|
+
return {
|
4049
|
+
Component: Layout
|
4050
|
+
};
|
4051
|
+
},
|
4052
|
+
children: routes
|
4053
|
+
});
|
3740
4054
|
app.registerPlugin(cm.config);
|
3741
4055
|
},
|
4056
|
+
bootstrap(app) {
|
4057
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4058
|
+
historyAdmin.bootstrap(app);
|
4059
|
+
}
|
4060
|
+
},
|
3742
4061
|
async registerTrads({ locales }) {
|
3743
4062
|
const importedTrads = await Promise.all(
|
3744
4063
|
locales.map((locale) => {
|
3745
|
-
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-
|
4064
|
+
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-Bm0D0IWz.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
|
3746
4065
|
return {
|
3747
4066
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3748
4067
|
locale
|
@@ -3760,6 +4079,7 @@ const index = {
|
|
3760
4079
|
};
|
3761
4080
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
3762
4081
|
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4082
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3763
4083
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3764
4084
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3765
4085
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3786,8 +4106,8 @@ exports.getDisplayName = getDisplayName;
|
|
3786
4106
|
exports.getMainField = getMainField;
|
3787
4107
|
exports.getTranslation = getTranslation;
|
3788
4108
|
exports.index = index;
|
3789
|
-
exports.routes = routes;
|
3790
4109
|
exports.setInitialData = setInitialData;
|
4110
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3791
4111
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3792
4112
|
exports.useDoc = useDoc;
|
3793
4113
|
exports.useDocLayout = useDocLayout;
|
@@ -3800,4 +4120,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
|
3800
4120
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3801
4121
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
3802
4122
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3803
|
-
//# sourceMappingURL=index-
|
4123
|
+
//# sourceMappingURL=index-D3u7haqj.js.map
|