@strapi/content-manager 0.0.0-experimental.62ce06180fe9a772eaeb3d43d238b26644f39f7c → 0.0.0-experimental.65b9961ce81496e349024ceb95be1d5946f2c429
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-CO977CPh.js} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-Cl7eB3s4.js.map → ComponentConfigurationPage-CO977CPh.js.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-DErJQEVW.mjs → ComponentConfigurationPage-CQroR9Qk.mjs} +4 -4
- package/dist/_chunks/{ComponentConfigurationPage-DErJQEVW.mjs.map → ComponentConfigurationPage-CQroR9Qk.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CyfFvH6-.js → EditConfigurationPage-BPgoE-kf.js} +4 -4
- package/dist/_chunks/{EditConfigurationPage-CyfFvH6-.js.map → EditConfigurationPage-BPgoE-kf.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CBosWqQ7.mjs → EditConfigurationPage-tVCJ5vWC.mjs} +4 -4
- package/dist/_chunks/{EditConfigurationPage-CBosWqQ7.mjs.map → EditConfigurationPage-tVCJ5vWC.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-ClIueJnM.mjs → EditViewPage-8mOu02ji.mjs} +30 -9
- package/dist/_chunks/EditViewPage-8mOu02ji.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-DxyAOItK.js → EditViewPage-BMVgUNOX.js} +30 -9
- package/dist/_chunks/EditViewPage-BMVgUNOX.js.map +1 -0
- package/dist/_chunks/{Field-BZBYmvaf.mjs → Field-CJPYzwD7.mjs} +518 -154
- package/dist/_chunks/Field-CJPYzwD7.mjs.map +1 -0
- package/dist/_chunks/{Field-C0Y_SR9e.js → Field-CdSLKFQk.js} +520 -156
- package/dist/_chunks/Field-CdSLKFQk.js.map +1 -0
- package/dist/_chunks/{Form-jwRSC2kV.mjs → Form-DJOJ-GF1.mjs} +36 -17
- package/dist/_chunks/Form-DJOJ-GF1.mjs.map +1 -0
- package/dist/_chunks/{Form-DwvGnISS.js → Form-eP5bZwap.js} +36 -17
- package/dist/_chunks/Form-eP5bZwap.js.map +1 -0
- package/dist/_chunks/{History-Cda0Yjzz.js → History-B-Mrquzu.js} +63 -25
- package/dist/_chunks/History-B-Mrquzu.js.map +1 -0
- package/dist/_chunks/{History-BgzAIj0G.mjs → History-MnQLtk1g.mjs} +64 -26
- package/dist/_chunks/History-MnQLtk1g.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-GH55qfoT.mjs → ListConfigurationPage-BcycI8Lw.mjs} +21 -9
- package/dist/_chunks/ListConfigurationPage-BcycI8Lw.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-C29EF97r.js → ListConfigurationPage-C0n4rUzH.js} +21 -9
- package/dist/_chunks/ListConfigurationPage-C0n4rUzH.js.map +1 -0
- package/dist/_chunks/{ListViewPage-QU03PFj1.mjs → ListViewPage-CRXONXwZ.mjs} +59 -41
- package/dist/_chunks/ListViewPage-CRXONXwZ.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-CnRt0UT7.js → ListViewPage-q0SHVPUS.js} +61 -43
- package/dist/_chunks/ListViewPage-q0SHVPUS.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DFDjxByI.js → NoContentTypePage-Bh3komDV.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-DFDjxByI.js.map → NoContentTypePage-Bh3komDV.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-CPs2CnzH.mjs → NoContentTypePage-ukzFRF3z.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CPs2CnzH.mjs.map → NoContentTypePage-ukzFRF3z.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-ct58lcY0.mjs → NoPermissionsPage-B4sD7Ble.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-ct58lcY0.mjs.map → NoPermissionsPage-B4sD7Ble.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BVHI-jv5.js → NoPermissionsPage-BGBpj_Y1.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BVHI-jv5.js.map → NoPermissionsPage-BGBpj_Y1.js.map} +1 -1
- package/dist/_chunks/{Relations-BjpPPCKp.js → Relations-B53wYe8g.js} +33 -24
- package/dist/_chunks/Relations-B53wYe8g.js.map +1 -0
- package/dist/_chunks/{Relations-KMf5qEN0.mjs → Relations-CIexb8gr.mjs} +33 -24
- package/dist/_chunks/Relations-CIexb8gr.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-CJ2vYwuT.mjs} +992 -689
- package/dist/_chunks/index-CJ2vYwuT.mjs.map +1 -0
- package/dist/_chunks/{index-D9ZwczCV.js → index-DbT2sx-Q.js} +984 -681
- package/dist/_chunks/index-DbT2sx-Q.js.map +1 -0
- package/dist/_chunks/{layout-BJfBoBiF.js → layout-CeBSIkmP.js} +25 -12
- package/dist/_chunks/layout-CeBSIkmP.js.map +1 -0
- package/dist/_chunks/{layout-B1Z-9koY.mjs → layout-vzKSrr7p.mjs} +27 -14
- package/dist/_chunks/layout-vzKSrr7p.mjs.map +1 -0
- package/dist/_chunks/{objects-gigeqt7s.js → objects-BcXOv6_9.js} +2 -4
- package/dist/_chunks/{objects-gigeqt7s.js.map → objects-BcXOv6_9.js.map} +1 -1
- package/dist/_chunks/{objects-mKMAmfec.mjs → objects-D6yBsdmx.mjs} +2 -4
- package/dist/_chunks/{objects-mKMAmfec.mjs.map → objects-D6yBsdmx.mjs.map} +1 -1
- package/dist/_chunks/{relations-CMvjzyU3.js → relations-Cl-6t9iz.js} +2 -2
- package/dist/_chunks/{relations-CMvjzyU3.js.map → relations-Cl-6t9iz.js.map} +1 -1
- package/dist/_chunks/{relations-CgZg7Pyx.mjs → relations-DI0lguF0.mjs} +2 -2
- package/dist/_chunks/{relations-CgZg7Pyx.mjs.map → relations-DI0lguF0.mjs.map} +1 -1
- 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 +205 -118
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +206 -119
- 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/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/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.map +1 -1
- package/dist/server/src/services/permission-checker.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.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/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,15 @@
|
|
2
2
|
const Icons = require("@strapi/icons");
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
4
4
|
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
5
|
-
const qs = require("qs");
|
6
|
-
const reactIntl = require("react-intl");
|
7
|
-
const reactRouterDom = require("react-router-dom");
|
8
5
|
const React = require("react");
|
9
6
|
const designSystem = require("@strapi/design-system");
|
10
|
-
const
|
7
|
+
const reactIntl = require("react-intl");
|
8
|
+
const reactRouterDom = require("react-router-dom");
|
11
9
|
const yup = require("yup");
|
12
10
|
const pipe = require("lodash/fp/pipe");
|
13
11
|
const dateFns = require("date-fns");
|
12
|
+
const styledComponents = require("styled-components");
|
13
|
+
const qs = require("qs");
|
14
14
|
const toolkit = require("@reduxjs/toolkit");
|
15
15
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
16
16
|
function _interopNamespace(e) {
|
@@ -70,42 +70,6 @@ const useInjectionZone = (area) => {
|
|
70
70
|
const [page, position] = area.split(".");
|
71
71
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
72
72
|
};
|
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
73
|
const ID = "id";
|
110
74
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
111
75
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -157,6 +121,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
157
121
|
if (!slug) {
|
158
122
|
throw new Error("Cannot find the slug param in the URL");
|
159
123
|
}
|
124
|
+
const [{ rawQuery }] = strapiAdmin.useQueryParams();
|
160
125
|
const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
|
161
126
|
const contentTypePermissions = React__namespace.useMemo(() => {
|
162
127
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -167,7 +132,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
167
132
|
return { ...acc, [action]: [permission] };
|
168
133
|
}, {});
|
169
134
|
}, [slug, userPermissions]);
|
170
|
-
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
135
|
+
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
136
|
+
contentTypePermissions,
|
137
|
+
permissions ?? void 0,
|
138
|
+
// TODO: useRBAC context should be typed and built differently
|
139
|
+
// We are passing raw query as context to the hook so that it can
|
140
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
141
|
+
rawQuery
|
142
|
+
);
|
171
143
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
172
144
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
173
145
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -216,8 +188,7 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
|
216
188
|
"InitialData",
|
217
189
|
"HistoryVersion",
|
218
190
|
"Relations",
|
219
|
-
"
|
220
|
-
"ReleaseAction"
|
191
|
+
"UidAvailability"
|
221
192
|
]
|
222
193
|
});
|
223
194
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -231,7 +202,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
231
202
|
params: query
|
232
203
|
}
|
233
204
|
}),
|
234
|
-
invalidatesTags: (_result,
|
205
|
+
invalidatesTags: (_result, error, { model }) => {
|
206
|
+
if (error) {
|
207
|
+
return [];
|
208
|
+
}
|
209
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
210
|
+
}
|
235
211
|
}),
|
236
212
|
cloneDocument: builder.mutation({
|
237
213
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -242,7 +218,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
242
218
|
params
|
243
219
|
}
|
244
220
|
}),
|
245
|
-
invalidatesTags: (_result, _error, { model }) => [
|
221
|
+
invalidatesTags: (_result, _error, { model }) => [
|
222
|
+
{ type: "Document", id: `${model}_LIST` },
|
223
|
+
{ type: "UidAvailability", id: model }
|
224
|
+
]
|
246
225
|
}),
|
247
226
|
/**
|
248
227
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -259,7 +238,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
259
238
|
}),
|
260
239
|
invalidatesTags: (result, _error, { model }) => [
|
261
240
|
{ type: "Document", id: `${model}_LIST` },
|
262
|
-
"Relations"
|
241
|
+
"Relations",
|
242
|
+
{ type: "UidAvailability", id: model }
|
263
243
|
]
|
264
244
|
}),
|
265
245
|
deleteDocument: builder.mutation({
|
@@ -271,9 +251,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
271
251
|
}
|
272
252
|
}),
|
273
253
|
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" }
|
254
|
+
{ type: "Document", id: collectionType !== SINGLE_TYPES ? `${model}_LIST` : model }
|
277
255
|
]
|
278
256
|
}),
|
279
257
|
deleteManyDocuments: builder.mutation({
|
@@ -285,11 +263,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
285
263
|
params
|
286
264
|
}
|
287
265
|
}),
|
288
|
-
invalidatesTags: (_res, _error, { model }) => [
|
289
|
-
{ type: "Document", id: `${model}_LIST` },
|
290
|
-
{ type: "Release", id: "LIST" },
|
291
|
-
{ type: "ReleaseAction", id: "LIST" }
|
292
|
-
]
|
266
|
+
invalidatesTags: (_res, _error, { model }) => [{ type: "Document", id: `${model}_LIST` }]
|
293
267
|
}),
|
294
268
|
discardDocument: builder.mutation({
|
295
269
|
query: ({ collectionType, model, documentId, params }) => ({
|
@@ -307,8 +281,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
307
281
|
},
|
308
282
|
{ type: "Document", id: `${model}_LIST` },
|
309
283
|
"Relations",
|
310
|
-
{ type: "
|
311
|
-
{ type: "ReleaseAction", id: "LIST" }
|
284
|
+
{ type: "UidAvailability", id: model }
|
312
285
|
];
|
313
286
|
}
|
314
287
|
}),
|
@@ -326,6 +299,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
326
299
|
}),
|
327
300
|
providesTags: (result, _error, arg) => {
|
328
301
|
return [
|
302
|
+
{ type: "Document", id: `ALL_LIST` },
|
329
303
|
{ type: "Document", id: `${arg.model}_LIST` },
|
330
304
|
...result?.results.map(({ documentId }) => ({
|
331
305
|
type: "Document",
|
@@ -364,6 +338,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
364
338
|
{
|
365
339
|
type: "Document",
|
366
340
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
341
|
+
},
|
342
|
+
// Make it easy to invalidate all individual documents queries for a model
|
343
|
+
{
|
344
|
+
type: "Document",
|
345
|
+
id: `${model}_ALL_ITEMS`
|
367
346
|
}
|
368
347
|
];
|
369
348
|
}
|
@@ -428,9 +407,20 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
428
407
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
429
408
|
},
|
430
409
|
"Relations",
|
431
|
-
{ type: "
|
432
|
-
{ type: "ReleaseAction", id: "LIST" }
|
410
|
+
{ type: "UidAvailability", id: model }
|
433
411
|
];
|
412
|
+
},
|
413
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
414
|
+
const patchResult = dispatch(
|
415
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
416
|
+
Object.assign(draft.data, data);
|
417
|
+
})
|
418
|
+
);
|
419
|
+
try {
|
420
|
+
await queryFulfilled;
|
421
|
+
} catch {
|
422
|
+
patchResult.undo();
|
423
|
+
}
|
434
424
|
}
|
435
425
|
}),
|
436
426
|
unpublishDocument: builder.mutation({
|
@@ -500,20 +490,39 @@ const buildValidParams = (query) => {
|
|
500
490
|
const isBaseQueryError = (error) => {
|
501
491
|
return error.name !== void 0;
|
502
492
|
};
|
503
|
-
const
|
493
|
+
const arrayValidator = (attribute, options) => ({
|
494
|
+
message: strapiAdmin.translatedErrors.required,
|
495
|
+
test(value) {
|
496
|
+
if (options.status === "draft") {
|
497
|
+
return true;
|
498
|
+
}
|
499
|
+
if (!attribute.required) {
|
500
|
+
return true;
|
501
|
+
}
|
502
|
+
if (!value) {
|
503
|
+
return false;
|
504
|
+
}
|
505
|
+
if (Array.isArray(value) && value.length === 0) {
|
506
|
+
return false;
|
507
|
+
}
|
508
|
+
return true;
|
509
|
+
}
|
510
|
+
});
|
511
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
504
512
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
505
513
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
506
514
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
507
515
|
return acc;
|
508
516
|
}
|
509
517
|
const validations = [
|
518
|
+
addNullableValidation,
|
510
519
|
addRequiredValidation,
|
511
520
|
addMinLengthValidation,
|
512
521
|
addMaxLengthValidation,
|
513
522
|
addMinValidation,
|
514
523
|
addMaxValidation,
|
515
524
|
addRegexValidation
|
516
|
-
].map((fn) => fn(attribute));
|
525
|
+
].map((fn) => fn(attribute, options));
|
517
526
|
const transformSchema = pipe__default.default(...validations);
|
518
527
|
switch (attribute.type) {
|
519
528
|
case "component": {
|
@@ -523,12 +532,12 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
523
532
|
...acc,
|
524
533
|
[name]: transformSchema(
|
525
534
|
yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
|
526
|
-
)
|
535
|
+
).test(arrayValidator(attribute, options))
|
527
536
|
};
|
528
537
|
} else {
|
529
538
|
return {
|
530
539
|
...acc,
|
531
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
540
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
532
541
|
};
|
533
542
|
}
|
534
543
|
}
|
@@ -550,7 +559,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
550
559
|
}
|
551
560
|
)
|
552
561
|
)
|
553
|
-
)
|
562
|
+
).test(arrayValidator(attribute, options))
|
554
563
|
};
|
555
564
|
case "relation":
|
556
565
|
return {
|
@@ -562,7 +571,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
562
571
|
} else if (Array.isArray(value)) {
|
563
572
|
return yup__namespace.array().of(
|
564
573
|
yup__namespace.object().shape({
|
565
|
-
id: yup__namespace.
|
574
|
+
id: yup__namespace.number().required()
|
566
575
|
})
|
567
576
|
);
|
568
577
|
} else if (typeof value === "object") {
|
@@ -614,6 +623,14 @@ const createAttributeSchema = (attribute) => {
|
|
614
623
|
if (!value || typeof value === "string" && value.length === 0) {
|
615
624
|
return true;
|
616
625
|
}
|
626
|
+
if (typeof value === "object") {
|
627
|
+
try {
|
628
|
+
JSON.stringify(value);
|
629
|
+
return true;
|
630
|
+
} catch (err) {
|
631
|
+
return false;
|
632
|
+
}
|
633
|
+
}
|
617
634
|
try {
|
618
635
|
JSON.parse(value);
|
619
636
|
return true;
|
@@ -632,13 +649,7 @@ const createAttributeSchema = (attribute) => {
|
|
632
649
|
return yup__namespace.mixed();
|
633
650
|
}
|
634
651
|
};
|
635
|
-
const
|
636
|
-
if (attribute.required) {
|
637
|
-
return schema.required({
|
638
|
-
id: strapiAdmin.translatedErrors.required.id,
|
639
|
-
defaultMessage: "This field is required."
|
640
|
-
});
|
641
|
-
}
|
652
|
+
const nullableSchema = (schema) => {
|
642
653
|
return schema?.nullable ? schema.nullable() : (
|
643
654
|
// In some cases '.nullable' will not be available on the schema.
|
644
655
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -646,7 +657,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
646
657
|
schema
|
647
658
|
);
|
648
659
|
};
|
649
|
-
const
|
660
|
+
const addNullableValidation = () => (schema) => {
|
661
|
+
return nullableSchema(schema);
|
662
|
+
};
|
663
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
664
|
+
if (options.status === "draft" || !attribute.required) {
|
665
|
+
return schema;
|
666
|
+
}
|
667
|
+
if (attribute.required && "required" in schema) {
|
668
|
+
return schema.required(strapiAdmin.translatedErrors.required);
|
669
|
+
}
|
670
|
+
return schema;
|
671
|
+
};
|
672
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
673
|
+
if (options.status === "draft") {
|
674
|
+
return schema;
|
675
|
+
}
|
650
676
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
651
677
|
return schema.min(attribute.minLength, {
|
652
678
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -668,10 +694,13 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
668
694
|
}
|
669
695
|
return schema;
|
670
696
|
};
|
671
|
-
const addMinValidation = (attribute) => (schema) => {
|
672
|
-
if ("
|
697
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
698
|
+
if (options.status === "draft") {
|
699
|
+
return schema;
|
700
|
+
}
|
701
|
+
if ("min" in attribute && "min" in schema) {
|
673
702
|
const min = toInteger(attribute.min);
|
674
|
-
if (
|
703
|
+
if (min) {
|
675
704
|
return schema.min(min, {
|
676
705
|
...strapiAdmin.translatedErrors.min,
|
677
706
|
values: {
|
@@ -789,16 +818,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
789
818
|
}, {});
|
790
819
|
return componentsByKey;
|
791
820
|
};
|
792
|
-
const
|
821
|
+
const HOOKS = {
|
822
|
+
/**
|
823
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
824
|
+
* @constant
|
825
|
+
* @type {string}
|
826
|
+
*/
|
827
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
828
|
+
/**
|
829
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
830
|
+
* @constant
|
831
|
+
* @type {string}
|
832
|
+
*/
|
833
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
834
|
+
/**
|
835
|
+
* Hook that allows to mutate the CM's edit view layout
|
836
|
+
* @constant
|
837
|
+
* @type {string}
|
838
|
+
*/
|
839
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
840
|
+
/**
|
841
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
842
|
+
* @constant
|
843
|
+
* @type {string}
|
844
|
+
*/
|
845
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
846
|
+
};
|
847
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
848
|
+
endpoints: (builder) => ({
|
849
|
+
getContentTypeConfiguration: builder.query({
|
850
|
+
query: (uid) => ({
|
851
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
852
|
+
method: "GET"
|
853
|
+
}),
|
854
|
+
transformResponse: (response) => response.data,
|
855
|
+
providesTags: (_result, _error, uid) => [
|
856
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
857
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
858
|
+
]
|
859
|
+
}),
|
860
|
+
getAllContentTypeSettings: builder.query({
|
861
|
+
query: () => "/content-manager/content-types-settings",
|
862
|
+
transformResponse: (response) => response.data,
|
863
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
864
|
+
}),
|
865
|
+
updateContentTypeConfiguration: builder.mutation({
|
866
|
+
query: ({ uid, ...body }) => ({
|
867
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
868
|
+
method: "PUT",
|
869
|
+
data: body
|
870
|
+
}),
|
871
|
+
transformResponse: (response) => response.data,
|
872
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
873
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
874
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
875
|
+
// Is this necessary?
|
876
|
+
{ type: "InitialData" }
|
877
|
+
]
|
878
|
+
})
|
879
|
+
})
|
880
|
+
});
|
881
|
+
const {
|
882
|
+
useGetContentTypeConfigurationQuery,
|
883
|
+
useGetAllContentTypeSettingsQuery,
|
884
|
+
useUpdateContentTypeConfigurationMutation
|
885
|
+
} = contentTypesApi;
|
886
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
887
|
+
const { type } = attribute;
|
888
|
+
if (type === "relation") {
|
889
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
890
|
+
}
|
891
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
892
|
+
};
|
893
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
894
|
+
if (!mainFieldName) {
|
895
|
+
return void 0;
|
896
|
+
}
|
897
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
898
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
899
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
900
|
+
);
|
901
|
+
return {
|
902
|
+
name: mainFieldName,
|
903
|
+
type: mainFieldType ?? "string"
|
904
|
+
};
|
905
|
+
};
|
906
|
+
const DEFAULT_SETTINGS = {
|
907
|
+
bulkable: false,
|
908
|
+
filterable: false,
|
909
|
+
searchable: false,
|
910
|
+
pagination: false,
|
911
|
+
defaultSortBy: "",
|
912
|
+
defaultSortOrder: "asc",
|
913
|
+
mainField: "id",
|
914
|
+
pageSize: 10
|
915
|
+
};
|
916
|
+
const useDocumentLayout = (model) => {
|
917
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
918
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
919
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
793
920
|
const { toggleNotification } = strapiAdmin.useNotification();
|
794
921
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
922
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
795
923
|
const {
|
796
|
-
|
797
|
-
isLoading:
|
798
|
-
|
799
|
-
|
800
|
-
} =
|
801
|
-
const
|
924
|
+
data,
|
925
|
+
isLoading: isLoadingConfigs,
|
926
|
+
error,
|
927
|
+
isFetching: isFetchingConfigs
|
928
|
+
} = useGetContentTypeConfigurationQuery(model);
|
929
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
802
930
|
React__namespace.useEffect(() => {
|
803
931
|
if (error) {
|
804
932
|
toggleNotification({
|
@@ -806,68 +934,321 @@ const useDocument = (args, opts) => {
|
|
806
934
|
message: formatAPIError(error)
|
807
935
|
});
|
808
936
|
}
|
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
|
-
}
|
937
|
+
}, [error, formatAPIError, toggleNotification]);
|
938
|
+
const editLayout = React__namespace.useMemo(
|
939
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
940
|
+
layout: [],
|
941
|
+
components: {},
|
942
|
+
metadatas: {},
|
943
|
+
options: {},
|
944
|
+
settings: DEFAULT_SETTINGS
|
832
945
|
},
|
833
|
-
[
|
946
|
+
[data, isLoading, schemas, schema, components]
|
947
|
+
);
|
948
|
+
const listLayout = React__namespace.useMemo(() => {
|
949
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
950
|
+
layout: [],
|
951
|
+
metadatas: {},
|
952
|
+
options: {},
|
953
|
+
settings: DEFAULT_SETTINGS
|
954
|
+
};
|
955
|
+
}, [data, isLoading, schemas, schema, components]);
|
956
|
+
const { layout: edit } = React__namespace.useMemo(
|
957
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
958
|
+
layout: editLayout,
|
959
|
+
query
|
960
|
+
}),
|
961
|
+
[editLayout, query, runHookWaterfall]
|
834
962
|
);
|
835
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
836
963
|
return {
|
837
|
-
|
838
|
-
document: data?.data,
|
839
|
-
meta: data?.meta,
|
964
|
+
error,
|
840
965
|
isLoading,
|
841
|
-
|
842
|
-
|
966
|
+
edit,
|
967
|
+
list: listLayout
|
843
968
|
};
|
844
969
|
};
|
845
|
-
const
|
846
|
-
const {
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
970
|
+
const useDocLayout = () => {
|
971
|
+
const { model } = useDoc();
|
972
|
+
return useDocumentLayout(model);
|
973
|
+
};
|
974
|
+
const formatEditLayout = (data, {
|
975
|
+
schemas,
|
976
|
+
schema,
|
977
|
+
components
|
978
|
+
}) => {
|
979
|
+
let currentPanelIndex = 0;
|
980
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
981
|
+
data.contentType.layouts.edit,
|
982
|
+
schema?.attributes,
|
983
|
+
data.contentType.metadatas,
|
984
|
+
{ configurations: data.components, schemas: components },
|
985
|
+
schemas
|
986
|
+
).reduce((panels, row) => {
|
987
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
988
|
+
panels.push([row]);
|
989
|
+
currentPanelIndex += 2;
|
990
|
+
} else {
|
991
|
+
if (!panels[currentPanelIndex]) {
|
992
|
+
panels.push([]);
|
993
|
+
}
|
994
|
+
panels[currentPanelIndex].push(row);
|
995
|
+
}
|
996
|
+
return panels;
|
997
|
+
}, []);
|
998
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
999
|
+
(acc, [uid, configuration]) => {
|
1000
|
+
acc[uid] = {
|
1001
|
+
layout: convertEditLayoutToFieldLayouts(
|
1002
|
+
configuration.layouts.edit,
|
1003
|
+
components[uid].attributes,
|
1004
|
+
configuration.metadatas,
|
1005
|
+
{ configurations: data.components, schemas: components }
|
1006
|
+
),
|
1007
|
+
settings: {
|
1008
|
+
...configuration.settings,
|
1009
|
+
icon: components[uid].info.icon,
|
1010
|
+
displayName: components[uid].info.displayName
|
1011
|
+
}
|
1012
|
+
};
|
1013
|
+
return acc;
|
1014
|
+
},
|
1015
|
+
{}
|
1016
|
+
);
|
1017
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1018
|
+
(acc, [attribute, metadata]) => {
|
1019
|
+
return {
|
1020
|
+
...acc,
|
1021
|
+
[attribute]: metadata.edit
|
1022
|
+
};
|
1023
|
+
},
|
1024
|
+
{}
|
1025
|
+
);
|
1026
|
+
return {
|
1027
|
+
layout: panelledEditAttributes,
|
1028
|
+
components: componentEditAttributes,
|
1029
|
+
metadatas: editMetadatas,
|
1030
|
+
settings: {
|
1031
|
+
...data.contentType.settings,
|
1032
|
+
displayName: schema?.info.displayName
|
1033
|
+
},
|
1034
|
+
options: {
|
1035
|
+
...schema?.options,
|
1036
|
+
...schema?.pluginOptions,
|
1037
|
+
...data.contentType.options
|
1038
|
+
}
|
1039
|
+
};
|
1040
|
+
};
|
1041
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1042
|
+
return rows.map(
|
1043
|
+
(row) => row.map((field) => {
|
1044
|
+
const attribute = attributes[field.name];
|
1045
|
+
if (!attribute) {
|
1046
|
+
return null;
|
1047
|
+
}
|
1048
|
+
const { edit: metadata } = metadatas[field.name];
|
1049
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1050
|
+
return {
|
1051
|
+
attribute,
|
1052
|
+
disabled: !metadata.editable,
|
1053
|
+
hint: metadata.description,
|
1054
|
+
label: metadata.label ?? "",
|
1055
|
+
name: field.name,
|
1056
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1057
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1058
|
+
schemas,
|
1059
|
+
components: components?.schemas ?? {}
|
1060
|
+
}),
|
1061
|
+
placeholder: metadata.placeholder ?? "",
|
1062
|
+
required: attribute.required ?? false,
|
1063
|
+
size: field.size,
|
1064
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1065
|
+
visible: metadata.visible ?? true,
|
1066
|
+
type: attribute.type
|
1067
|
+
};
|
1068
|
+
}).filter((field) => field !== null)
|
1069
|
+
);
|
1070
|
+
};
|
1071
|
+
const formatListLayout = (data, {
|
1072
|
+
schemas,
|
1073
|
+
schema,
|
1074
|
+
components
|
1075
|
+
}) => {
|
1076
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1077
|
+
(acc, [attribute, metadata]) => {
|
1078
|
+
return {
|
1079
|
+
...acc,
|
1080
|
+
[attribute]: metadata.list
|
1081
|
+
};
|
1082
|
+
},
|
1083
|
+
{}
|
1084
|
+
);
|
1085
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1086
|
+
data.contentType.layouts.list,
|
1087
|
+
schema?.attributes,
|
1088
|
+
listMetadatas,
|
1089
|
+
{ configurations: data.components, schemas: components },
|
1090
|
+
schemas
|
1091
|
+
);
|
1092
|
+
return {
|
1093
|
+
layout: listAttributes,
|
1094
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1095
|
+
metadatas: listMetadatas,
|
1096
|
+
options: {
|
1097
|
+
...schema?.options,
|
1098
|
+
...schema?.pluginOptions,
|
1099
|
+
...data.contentType.options
|
1100
|
+
}
|
1101
|
+
};
|
1102
|
+
};
|
1103
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1104
|
+
return columns.map((name) => {
|
1105
|
+
const attribute = attributes[name];
|
1106
|
+
if (!attribute) {
|
1107
|
+
return null;
|
1108
|
+
}
|
1109
|
+
const metadata = metadatas[name];
|
1110
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1111
|
+
return {
|
1112
|
+
attribute,
|
1113
|
+
label: metadata.label ?? "",
|
1114
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1115
|
+
schemas,
|
1116
|
+
components: components?.schemas ?? {}
|
1117
|
+
}),
|
1118
|
+
name,
|
1119
|
+
searchable: metadata.searchable ?? true,
|
1120
|
+
sortable: metadata.sortable ?? true
|
1121
|
+
};
|
1122
|
+
}).filter((field) => field !== null);
|
1123
|
+
};
|
1124
|
+
const useDocument = (args, opts) => {
|
1125
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1126
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1127
|
+
const {
|
1128
|
+
currentData: data,
|
1129
|
+
isLoading: isLoadingDocument,
|
1130
|
+
isFetching: isFetchingDocument,
|
1131
|
+
error
|
1132
|
+
} = useGetDocumentQuery(args, {
|
1133
|
+
...opts,
|
1134
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1135
|
+
});
|
1136
|
+
const {
|
1137
|
+
components,
|
1138
|
+
schema,
|
1139
|
+
schemas,
|
1140
|
+
isLoading: isLoadingSchema
|
1141
|
+
} = useContentTypeSchema(args.model);
|
1142
|
+
React__namespace.useEffect(() => {
|
1143
|
+
if (error) {
|
1144
|
+
toggleNotification({
|
1145
|
+
type: "danger",
|
1146
|
+
message: formatAPIError(error)
|
1147
|
+
});
|
1148
|
+
}
|
1149
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1150
|
+
const validationSchema = React__namespace.useMemo(() => {
|
1151
|
+
if (!schema) {
|
1152
|
+
return null;
|
1153
|
+
}
|
1154
|
+
return createYupSchema(schema.attributes, components);
|
1155
|
+
}, [schema, components]);
|
1156
|
+
const validate = React__namespace.useCallback(
|
1157
|
+
(document) => {
|
1158
|
+
if (!validationSchema) {
|
1159
|
+
throw new Error(
|
1160
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1161
|
+
);
|
1162
|
+
}
|
1163
|
+
try {
|
1164
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1165
|
+
return null;
|
1166
|
+
} catch (error2) {
|
1167
|
+
if (error2 instanceof yup.ValidationError) {
|
1168
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
1169
|
+
}
|
1170
|
+
throw error2;
|
1171
|
+
}
|
1172
|
+
},
|
1173
|
+
[validationSchema]
|
1174
|
+
);
|
1175
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1176
|
+
const hasError = !!error;
|
1177
|
+
return {
|
1178
|
+
components,
|
1179
|
+
document: data?.data,
|
1180
|
+
meta: data?.meta,
|
1181
|
+
isLoading,
|
1182
|
+
hasError,
|
1183
|
+
schema,
|
1184
|
+
schemas,
|
1185
|
+
validate
|
1186
|
+
};
|
1187
|
+
};
|
1188
|
+
const useDoc = () => {
|
1189
|
+
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
1190
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
1191
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1192
|
+
if (!collectionType) {
|
1193
|
+
throw new Error("Could not find collectionType in url params");
|
1194
|
+
}
|
1195
|
+
if (!slug) {
|
853
1196
|
throw new Error("Could not find model in url params");
|
854
1197
|
}
|
1198
|
+
const document = useDocument(
|
1199
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1200
|
+
{
|
1201
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1202
|
+
}
|
1203
|
+
);
|
1204
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
855
1205
|
return {
|
856
1206
|
collectionType,
|
857
1207
|
model: slug,
|
858
|
-
id:
|
859
|
-
...
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
1208
|
+
id: returnId,
|
1209
|
+
...document
|
1210
|
+
};
|
1211
|
+
};
|
1212
|
+
const useContentManagerContext = () => {
|
1213
|
+
const {
|
1214
|
+
collectionType,
|
1215
|
+
model,
|
1216
|
+
id,
|
1217
|
+
components,
|
1218
|
+
isLoading: isLoadingDoc,
|
1219
|
+
schema,
|
1220
|
+
schemas
|
1221
|
+
} = useDoc();
|
1222
|
+
const layout = useDocumentLayout(model);
|
1223
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1224
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1225
|
+
const slug = model;
|
1226
|
+
const isCreatingEntry = id === "create";
|
1227
|
+
useContentTypeSchema();
|
1228
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1229
|
+
const error = layout.error;
|
1230
|
+
return {
|
1231
|
+
error,
|
1232
|
+
isLoading,
|
1233
|
+
// Base metadata
|
1234
|
+
model,
|
1235
|
+
collectionType,
|
1236
|
+
id,
|
1237
|
+
slug,
|
1238
|
+
isCreatingEntry,
|
1239
|
+
isSingleType,
|
1240
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1241
|
+
// All schema infos
|
1242
|
+
components,
|
1243
|
+
contentType: schema,
|
1244
|
+
contentTypes: schemas,
|
1245
|
+
// Form state
|
1246
|
+
form,
|
1247
|
+
// layout infos
|
1248
|
+
layout
|
865
1249
|
};
|
866
1250
|
};
|
867
1251
|
const prefixPluginTranslations = (trad, pluginId) => {
|
868
|
-
if (!pluginId) {
|
869
|
-
throw new TypeError("pluginId can't be empty");
|
870
|
-
}
|
871
1252
|
return Object.keys(trad).reduce((acc, current) => {
|
872
1253
|
acc[`${pluginId}.${current}`] = trad[current];
|
873
1254
|
return acc;
|
@@ -883,6 +1264,8 @@ const useDocumentActions = () => {
|
|
883
1264
|
const { formatMessage } = reactIntl.useIntl();
|
884
1265
|
const { trackUsage } = strapiAdmin.useTracking();
|
885
1266
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1267
|
+
const navigate = reactRouterDom.useNavigate();
|
1268
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
886
1269
|
const [deleteDocument] = useDeleteDocumentMutation();
|
887
1270
|
const _delete = React__namespace.useCallback(
|
888
1271
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1197,6 +1580,7 @@ const useDocumentActions = () => {
|
|
1197
1580
|
defaultMessage: "Saved document"
|
1198
1581
|
})
|
1199
1582
|
});
|
1583
|
+
setCurrentStep("contentManager.success");
|
1200
1584
|
return res.data;
|
1201
1585
|
} catch (err) {
|
1202
1586
|
toggleNotification({
|
@@ -1218,7 +1602,6 @@ const useDocumentActions = () => {
|
|
1218
1602
|
sourceId
|
1219
1603
|
});
|
1220
1604
|
if ("error" in res) {
|
1221
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1222
1605
|
return { error: res.error };
|
1223
1606
|
}
|
1224
1607
|
toggleNotification({
|
@@ -1237,7 +1620,7 @@ const useDocumentActions = () => {
|
|
1237
1620
|
throw err;
|
1238
1621
|
}
|
1239
1622
|
},
|
1240
|
-
[autoCloneDocument,
|
1623
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1241
1624
|
);
|
1242
1625
|
const [cloneDocument] = useCloneDocumentMutation();
|
1243
1626
|
const clone = React__namespace.useCallback(
|
@@ -1263,6 +1646,7 @@ const useDocumentActions = () => {
|
|
1263
1646
|
defaultMessage: "Cloned document"
|
1264
1647
|
})
|
1265
1648
|
});
|
1649
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1266
1650
|
return res.data;
|
1267
1651
|
} catch (err) {
|
1268
1652
|
toggleNotification({
|
@@ -1273,7 +1657,7 @@ const useDocumentActions = () => {
|
|
1273
1657
|
throw err;
|
1274
1658
|
}
|
1275
1659
|
},
|
1276
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1660
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1277
1661
|
);
|
1278
1662
|
const [getDoc] = useLazyGetDocumentQuery();
|
1279
1663
|
const getDocument = React__namespace.useCallback(
|
@@ -1299,7 +1683,7 @@ const useDocumentActions = () => {
|
|
1299
1683
|
};
|
1300
1684
|
};
|
1301
1685
|
const ProtectedHistoryPage = React.lazy(
|
1302
|
-
() => Promise.resolve().then(() => require("./History-
|
1686
|
+
() => Promise.resolve().then(() => require("./History-B-Mrquzu.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1303
1687
|
);
|
1304
1688
|
const routes$1 = [
|
1305
1689
|
{
|
@@ -1312,31 +1696,31 @@ const routes$1 = [
|
|
1312
1696
|
}
|
1313
1697
|
];
|
1314
1698
|
const ProtectedEditViewPage = React.lazy(
|
1315
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1699
|
+
() => Promise.resolve().then(() => require("./EditViewPage-BMVgUNOX.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1316
1700
|
);
|
1317
1701
|
const ProtectedListViewPage = React.lazy(
|
1318
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1702
|
+
() => Promise.resolve().then(() => require("./ListViewPage-q0SHVPUS.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1319
1703
|
);
|
1320
1704
|
const ProtectedListConfiguration = React.lazy(
|
1321
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1705
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-C0n4rUzH.js")).then((mod) => ({
|
1322
1706
|
default: mod.ProtectedListConfiguration
|
1323
1707
|
}))
|
1324
1708
|
);
|
1325
1709
|
const ProtectedEditConfigurationPage = React.lazy(
|
1326
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1710
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-BPgoE-kf.js")).then((mod) => ({
|
1327
1711
|
default: mod.ProtectedEditConfigurationPage
|
1328
1712
|
}))
|
1329
1713
|
);
|
1330
1714
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1331
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1715
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-CO977CPh.js")).then((mod) => ({
|
1332
1716
|
default: mod.ProtectedComponentConfigurationPage
|
1333
1717
|
}))
|
1334
1718
|
);
|
1335
1719
|
const NoPermissions = React.lazy(
|
1336
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1720
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-BGBpj_Y1.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1337
1721
|
);
|
1338
1722
|
const NoContentType = React.lazy(
|
1339
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1723
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-Bh3komDV.js")).then((mod) => ({ default: mod.NoContentType }))
|
1340
1724
|
);
|
1341
1725
|
const CollectionTypePages = () => {
|
1342
1726
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1450,12 +1834,14 @@ const DocumentActionButton = (action) => {
|
|
1450
1834
|
/* @__PURE__ */ jsxRuntime.jsx(
|
1451
1835
|
designSystem.Button,
|
1452
1836
|
{
|
1453
|
-
flex:
|
1837
|
+
flex: "auto",
|
1454
1838
|
startIcon: action.icon,
|
1455
1839
|
disabled: action.disabled,
|
1456
1840
|
onClick: handleClick(action),
|
1457
1841
|
justifyContent: "center",
|
1458
1842
|
variant: action.variant || "default",
|
1843
|
+
paddingTop: "7px",
|
1844
|
+
paddingBottom: "7px",
|
1459
1845
|
children: action.label
|
1460
1846
|
}
|
1461
1847
|
),
|
@@ -1463,7 +1849,7 @@ const DocumentActionButton = (action) => {
|
|
1463
1849
|
DocumentActionConfirmDialog,
|
1464
1850
|
{
|
1465
1851
|
...action.dialog,
|
1466
|
-
variant: action.variant,
|
1852
|
+
variant: action.dialog?.variant ?? action.variant,
|
1467
1853
|
isOpen: dialogId === action.id,
|
1468
1854
|
onClose: handleClose
|
1469
1855
|
}
|
@@ -1520,9 +1906,9 @@ const DocumentActionsMenu = ({
|
|
1520
1906
|
disabled: isDisabled,
|
1521
1907
|
size: "S",
|
1522
1908
|
endIcon: null,
|
1523
|
-
paddingTop: "
|
1524
|
-
paddingLeft: "
|
1525
|
-
paddingRight: "
|
1909
|
+
paddingTop: "4px",
|
1910
|
+
paddingLeft: "7px",
|
1911
|
+
paddingRight: "7px",
|
1526
1912
|
variant,
|
1527
1913
|
children: [
|
1528
1914
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
@@ -1533,7 +1919,7 @@ const DocumentActionsMenu = ({
|
|
1533
1919
|
]
|
1534
1920
|
}
|
1535
1921
|
),
|
1536
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, {
|
1922
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1537
1923
|
actions2.map((action) => {
|
1538
1924
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
1539
1925
|
designSystem.Menu.Item,
|
@@ -1542,10 +1928,25 @@ const DocumentActionsMenu = ({
|
|
1542
1928
|
onSelect: handleClick(action),
|
1543
1929
|
display: "block",
|
1544
1930
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1545
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1931
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1932
|
+
designSystem.Flex,
|
1933
|
+
{
|
1934
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1935
|
+
gap: 2,
|
1936
|
+
tag: "span",
|
1937
|
+
children: [
|
1938
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1939
|
+
designSystem.Flex,
|
1940
|
+
{
|
1941
|
+
tag: "span",
|
1942
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1943
|
+
children: action.icon
|
1944
|
+
}
|
1945
|
+
),
|
1946
|
+
action.label
|
1947
|
+
]
|
1948
|
+
}
|
1949
|
+
),
|
1549
1950
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1550
1951
|
designSystem.Flex,
|
1551
1952
|
{
|
@@ -1642,11 +2043,11 @@ const DocumentActionConfirmDialog = ({
|
|
1642
2043
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1643
2044
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1644
2045
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1645
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
2046
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1646
2047
|
id: "app.components.Button.cancel",
|
1647
2048
|
defaultMessage: "Cancel"
|
1648
2049
|
}) }) }),
|
1649
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2050
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1650
2051
|
id: "app.components.Button.confirm",
|
1651
2052
|
defaultMessage: "Confirm"
|
1652
2053
|
}) })
|
@@ -1685,13 +2086,17 @@ const PublishAction$1 = ({
|
|
1685
2086
|
const navigate = reactRouterDom.useNavigate();
|
1686
2087
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1687
2088
|
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2089
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
1688
2090
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
1689
2091
|
const { formatMessage } = reactIntl.useIntl();
|
1690
|
-
const { canPublish
|
1691
|
-
"PublishAction",
|
1692
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1693
|
-
);
|
2092
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1694
2093
|
const { publish } = useDocumentActions();
|
2094
|
+
const [
|
2095
|
+
countDraftRelations,
|
2096
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2097
|
+
] = useLazyGetDraftRelationCountQuery();
|
2098
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2099
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1695
2100
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1696
2101
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1697
2102
|
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1700,62 +2105,144 @@ const PublishAction$1 = ({
|
|
1700
2105
|
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1701
2106
|
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1702
2107
|
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
2108
|
+
React__namespace.useEffect(() => {
|
2109
|
+
if (isErrorDraftRelations) {
|
2110
|
+
toggleNotification({
|
2111
|
+
type: "danger",
|
2112
|
+
message: formatMessage({
|
2113
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2114
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2115
|
+
})
|
2116
|
+
});
|
2117
|
+
}
|
2118
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2119
|
+
React__namespace.useEffect(() => {
|
2120
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2121
|
+
const extractDraftRelations = (data) => {
|
2122
|
+
const relations = data.connect || [];
|
2123
|
+
relations.forEach((relation) => {
|
2124
|
+
if (relation.status === "draft") {
|
2125
|
+
localDraftRelations.add(relation.id);
|
2126
|
+
}
|
2127
|
+
});
|
2128
|
+
};
|
2129
|
+
const traverseAndExtract = (data) => {
|
2130
|
+
Object.entries(data).forEach(([key, value]) => {
|
2131
|
+
if (key === "connect" && Array.isArray(value)) {
|
2132
|
+
extractDraftRelations({ connect: value });
|
2133
|
+
} else if (typeof value === "object" && value !== null) {
|
2134
|
+
traverseAndExtract(value);
|
2135
|
+
}
|
2136
|
+
});
|
2137
|
+
};
|
2138
|
+
if (!documentId || modified) {
|
2139
|
+
traverseAndExtract(formValues);
|
2140
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2141
|
+
}
|
2142
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2143
|
+
React__namespace.useEffect(() => {
|
2144
|
+
if (!document || !document.documentId || isListView) {
|
2145
|
+
return;
|
2146
|
+
}
|
2147
|
+
const fetchDraftRelationsCount = async () => {
|
2148
|
+
const { data, error } = await countDraftRelations({
|
2149
|
+
collectionType,
|
2150
|
+
model,
|
2151
|
+
documentId,
|
2152
|
+
params
|
2153
|
+
});
|
2154
|
+
if (error) {
|
2155
|
+
throw error;
|
2156
|
+
}
|
2157
|
+
if (data) {
|
2158
|
+
setServerCountOfDraftRelations(data.data);
|
2159
|
+
}
|
2160
|
+
};
|
2161
|
+
fetchDraftRelationsCount();
|
2162
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2163
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2164
|
+
if (!schema?.options?.draftAndPublish) {
|
2165
|
+
return null;
|
2166
|
+
}
|
2167
|
+
const performPublish = async () => {
|
2168
|
+
setSubmitting(true);
|
2169
|
+
try {
|
2170
|
+
const { errors } = await validate(true, {
|
2171
|
+
status: "published"
|
2172
|
+
});
|
2173
|
+
if (errors) {
|
2174
|
+
toggleNotification({
|
2175
|
+
type: "danger",
|
2176
|
+
message: formatMessage({
|
2177
|
+
id: "content-manager.validation.error",
|
2178
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2179
|
+
})
|
2180
|
+
});
|
2181
|
+
return;
|
2182
|
+
}
|
2183
|
+
const res = await publish(
|
2184
|
+
{
|
2185
|
+
collectionType,
|
2186
|
+
model,
|
2187
|
+
documentId,
|
2188
|
+
params
|
2189
|
+
},
|
2190
|
+
formValues
|
2191
|
+
);
|
2192
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2193
|
+
navigate({
|
2194
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2195
|
+
search: rawQuery
|
2196
|
+
});
|
2197
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2198
|
+
setErrors(formatValidationErrors(res.error));
|
2199
|
+
}
|
2200
|
+
} finally {
|
2201
|
+
setSubmitting(false);
|
2202
|
+
}
|
2203
|
+
};
|
2204
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2205
|
+
const enableDraftRelationsCount = false;
|
2206
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
2207
|
+
return {
|
2208
|
+
/**
|
2209
|
+
* Disabled when:
|
2210
|
+
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
2211
|
+
* - the form is submitting
|
2212
|
+
* - the active tab is the published tab
|
2213
|
+
* - the document is already published & not modified
|
1714
2214
|
* - the document is being created & not modified
|
1715
2215
|
* - 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
2216
|
*/
|
1719
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2217
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1720
2218
|
label: formatMessage({
|
1721
2219
|
id: "app.utils.publish",
|
1722
2220
|
defaultMessage: "Publish"
|
1723
2221
|
}),
|
1724
2222
|
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));
|
2223
|
+
await performPublish();
|
2224
|
+
},
|
2225
|
+
dialog: hasDraftRelations ? {
|
2226
|
+
type: "dialog",
|
2227
|
+
variant: "danger",
|
2228
|
+
footer: null,
|
2229
|
+
title: formatMessage({
|
2230
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2231
|
+
defaultMessage: "Confirmation"
|
2232
|
+
}),
|
2233
|
+
content: formatMessage(
|
2234
|
+
{
|
2235
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2236
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2237
|
+
},
|
2238
|
+
{
|
2239
|
+
count: totalDraftRelations
|
1754
2240
|
}
|
1755
|
-
|
1756
|
-
|
2241
|
+
),
|
2242
|
+
onConfirm: async () => {
|
2243
|
+
await performPublish();
|
1757
2244
|
}
|
1758
|
-
}
|
2245
|
+
} : void 0
|
1759
2246
|
};
|
1760
2247
|
};
|
1761
2248
|
PublishAction$1.type = "publish";
|
@@ -1771,10 +2258,6 @@ const UpdateAction = ({
|
|
1771
2258
|
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
1772
2259
|
const isCloning = cloneMatch !== null;
|
1773
2260
|
const { formatMessage } = reactIntl.useIntl();
|
1774
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1775
|
-
canCreate: canCreate2,
|
1776
|
-
canUpdate: canUpdate2
|
1777
|
-
}));
|
1778
2261
|
const { create, update, clone } = useDocumentActions();
|
1779
2262
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1780
2263
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
@@ -1791,10 +2274,8 @@ const UpdateAction = ({
|
|
1791
2274
|
* - the form is submitting
|
1792
2275
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1793
2276
|
* - 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
2277
|
*/
|
1797
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2278
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1798
2279
|
label: formatMessage({
|
1799
2280
|
id: "content-manager.containers.Edit.save",
|
1800
2281
|
defaultMessage: "Save"
|
@@ -1802,7 +2283,9 @@ const UpdateAction = ({
|
|
1802
2283
|
onClick: async () => {
|
1803
2284
|
setSubmitting(true);
|
1804
2285
|
try {
|
1805
|
-
const { errors } = await validate(
|
2286
|
+
const { errors } = await validate(true, {
|
2287
|
+
status: "draft"
|
2288
|
+
});
|
1806
2289
|
if (errors) {
|
1807
2290
|
toggleNotification({
|
1808
2291
|
type: "danger",
|
@@ -1823,10 +2306,13 @@ const UpdateAction = ({
|
|
1823
2306
|
document
|
1824
2307
|
);
|
1825
2308
|
if ("data" in res) {
|
1826
|
-
navigate(
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
2309
|
+
navigate(
|
2310
|
+
{
|
2311
|
+
pathname: `../${res.data.documentId}`,
|
2312
|
+
search: rawQuery
|
2313
|
+
},
|
2314
|
+
{ relative: "path" }
|
2315
|
+
);
|
1830
2316
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1831
2317
|
setErrors(formatValidationErrors(res.error));
|
1832
2318
|
}
|
@@ -1854,10 +2340,13 @@ const UpdateAction = ({
|
|
1854
2340
|
document
|
1855
2341
|
);
|
1856
2342
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1857
|
-
navigate(
|
1858
|
-
|
1859
|
-
|
1860
|
-
|
2343
|
+
navigate(
|
2344
|
+
{
|
2345
|
+
pathname: `../${res.data.documentId}`,
|
2346
|
+
search: rawQuery
|
2347
|
+
},
|
2348
|
+
{ replace: true, relative: "path" }
|
2349
|
+
);
|
1861
2350
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1862
2351
|
setErrors(formatValidationErrors(res.error));
|
1863
2352
|
}
|
@@ -1901,7 +2390,7 @@ const UnpublishAction$1 = ({
|
|
1901
2390
|
id: "app.utils.unpublish",
|
1902
2391
|
defaultMessage: "Unpublish"
|
1903
2392
|
}),
|
1904
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2393
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1905
2394
|
onClick: async () => {
|
1906
2395
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1907
2396
|
if (!documentId) {
|
@@ -2013,7 +2502,7 @@ const DiscardAction = ({
|
|
2013
2502
|
id: "content-manager.actions.discard.label",
|
2014
2503
|
defaultMessage: "Discard changes"
|
2015
2504
|
}),
|
2016
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2505
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2017
2506
|
position: ["panel", "table-row"],
|
2018
2507
|
variant: "danger",
|
2019
2508
|
dialog: {
|
@@ -2041,11 +2530,6 @@ const DiscardAction = ({
|
|
2041
2530
|
};
|
2042
2531
|
};
|
2043
2532
|
DiscardAction.type = "discard";
|
2044
|
-
const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
|
2045
|
-
path {
|
2046
|
-
fill: currentColor;
|
2047
|
-
}
|
2048
|
-
`;
|
2049
2533
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2050
2534
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2051
2535
|
const RelativeTime = React__namespace.forwardRef(
|
@@ -2093,7 +2577,7 @@ const getDisplayName = ({
|
|
2093
2577
|
};
|
2094
2578
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2095
2579
|
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2096
|
-
const statusVariant = status === "draft" ? "
|
2580
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2097
2581
|
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
2582
|
};
|
2099
2583
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
@@ -2103,23 +2587,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2103
2587
|
id: "content-manager.containers.edit.title.new",
|
2104
2588
|
defaultMessage: "Create an entry"
|
2105
2589
|
}) : documentTitle;
|
2106
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2590
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2107
2591
|
/* @__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
|
2592
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2593
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2594
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2595
|
+
] }),
|
2596
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2123
2597
|
] });
|
2124
2598
|
};
|
2125
2599
|
const HeaderToolbar = () => {
|
@@ -2202,12 +2676,12 @@ const Information = ({ activeTab }) => {
|
|
2202
2676
|
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2203
2677
|
label: formatMessage({
|
2204
2678
|
id: "content-manager.containers.edit.information.last-published.label",
|
2205
|
-
defaultMessage: "
|
2679
|
+
defaultMessage: "Published"
|
2206
2680
|
}),
|
2207
2681
|
value: formatMessage(
|
2208
2682
|
{
|
2209
2683
|
id: "content-manager.containers.edit.information.last-published.value",
|
2210
|
-
defaultMessage: `
|
2684
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2211
2685
|
},
|
2212
2686
|
{
|
2213
2687
|
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
@@ -2220,12 +2694,12 @@ const Information = ({ activeTab }) => {
|
|
2220
2694
|
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2221
2695
|
label: formatMessage({
|
2222
2696
|
id: "content-manager.containers.edit.information.last-draft.label",
|
2223
|
-
defaultMessage: "
|
2697
|
+
defaultMessage: "Updated"
|
2224
2698
|
}),
|
2225
2699
|
value: formatMessage(
|
2226
2700
|
{
|
2227
2701
|
id: "content-manager.containers.edit.information.last-draft.value",
|
2228
|
-
defaultMessage: `
|
2702
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2229
2703
|
},
|
2230
2704
|
{
|
2231
2705
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2243,12 +2717,12 @@ const Information = ({ activeTab }) => {
|
|
2243
2717
|
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2244
2718
|
label: formatMessage({
|
2245
2719
|
id: "content-manager.containers.edit.information.document.label",
|
2246
|
-
defaultMessage: "
|
2720
|
+
defaultMessage: "Created"
|
2247
2721
|
}),
|
2248
2722
|
value: formatMessage(
|
2249
2723
|
{
|
2250
2724
|
id: "content-manager.containers.edit.information.document.value",
|
2251
|
-
defaultMessage: `
|
2725
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2252
2726
|
},
|
2253
2727
|
{
|
2254
2728
|
time: /* @__PURE__ */ jsxRuntime.jsx(
|
@@ -2286,25 +2760,77 @@ const Information = ({ activeTab }) => {
|
|
2286
2760
|
);
|
2287
2761
|
};
|
2288
2762
|
const HeaderActions = ({ actions: actions2 }) => {
|
2289
|
-
|
2290
|
-
|
2763
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2764
|
+
const handleClick = (action) => async (e) => {
|
2765
|
+
if (!("options" in action)) {
|
2766
|
+
const { onClick = () => false, dialog, id } = action;
|
2767
|
+
const muteDialog = await onClick(e);
|
2768
|
+
if (dialog && !muteDialog) {
|
2769
|
+
e.preventDefault();
|
2770
|
+
setDialogId(id);
|
2771
|
+
}
|
2772
|
+
}
|
2773
|
+
};
|
2774
|
+
const handleClose = () => {
|
2775
|
+
setDialogId(null);
|
2776
|
+
};
|
2777
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2778
|
+
if (action.options) {
|
2291
2779
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2292
2780
|
designSystem.SingleSelect,
|
2293
2781
|
{
|
2294
2782
|
size: "S",
|
2295
|
-
disabled: action.disabled,
|
2296
|
-
"aria-label": action.label,
|
2297
2783
|
onChange: action.onSelect,
|
2298
|
-
|
2784
|
+
"aria-label": action.label,
|
2785
|
+
...action,
|
2299
2786
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2300
2787
|
},
|
2301
2788
|
action.id
|
2302
2789
|
);
|
2303
2790
|
} else {
|
2304
|
-
|
2791
|
+
if (action.type === "icon") {
|
2792
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2793
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2794
|
+
designSystem.IconButton,
|
2795
|
+
{
|
2796
|
+
disabled: action.disabled,
|
2797
|
+
label: action.label,
|
2798
|
+
size: "S",
|
2799
|
+
onClick: handleClick(action),
|
2800
|
+
children: action.icon
|
2801
|
+
}
|
2802
|
+
),
|
2803
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2804
|
+
HeaderActionDialog,
|
2805
|
+
{
|
2806
|
+
...action.dialog,
|
2807
|
+
isOpen: dialogId === action.id,
|
2808
|
+
onClose: handleClose
|
2809
|
+
}
|
2810
|
+
) : null
|
2811
|
+
] }, action.id);
|
2812
|
+
}
|
2305
2813
|
}
|
2306
2814
|
}) });
|
2307
2815
|
};
|
2816
|
+
const HeaderActionDialog = ({
|
2817
|
+
onClose,
|
2818
|
+
onCancel,
|
2819
|
+
title,
|
2820
|
+
content: Content,
|
2821
|
+
isOpen
|
2822
|
+
}) => {
|
2823
|
+
const handleClose = async () => {
|
2824
|
+
if (onCancel) {
|
2825
|
+
await onCancel();
|
2826
|
+
}
|
2827
|
+
onClose();
|
2828
|
+
};
|
2829
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2830
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2831
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2832
|
+
] }) });
|
2833
|
+
};
|
2308
2834
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2309
2835
|
const navigate = reactRouterDom.useNavigate();
|
2310
2836
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2345,12 +2871,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2345
2871
|
const { delete: deleteAction } = useDocumentActions();
|
2346
2872
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2347
2873
|
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2874
|
+
const isLocalized = document?.locale != null;
|
2348
2875
|
return {
|
2349
2876
|
disabled: !canDelete || !document,
|
2350
|
-
label: formatMessage(
|
2351
|
-
|
2352
|
-
|
2353
|
-
|
2877
|
+
label: formatMessage(
|
2878
|
+
{
|
2879
|
+
id: "content-manager.actions.delete.label",
|
2880
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2881
|
+
},
|
2882
|
+
{ isLocalized }
|
2883
|
+
),
|
2354
2884
|
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2355
2885
|
dialog: {
|
2356
2886
|
type: "dialog",
|
@@ -2386,423 +2916,121 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2386
2916
|
const res = await deleteAction({
|
2387
2917
|
documentId,
|
2388
2918
|
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
|
2919
|
+
collectionType,
|
2920
|
+
params: {
|
2921
|
+
locale: "*"
|
2922
|
+
}
|
2923
|
+
});
|
2924
|
+
if (!("error" in res)) {
|
2925
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2926
|
+
}
|
2927
|
+
} finally {
|
2928
|
+
if (!listViewPathMatch) {
|
2929
|
+
setSubmitting(false);
|
2930
|
+
}
|
2693
2931
|
}
|
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
|
2932
|
+
}
|
2715
2933
|
},
|
2716
|
-
|
2717
|
-
|
2718
|
-
...schema?.pluginOptions,
|
2719
|
-
...data.contentType.options
|
2720
|
-
}
|
2934
|
+
variant: "danger",
|
2935
|
+
position: ["header", "table-row"]
|
2721
2936
|
};
|
2722
2937
|
};
|
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
|
-
);
|
2938
|
+
DeleteAction$1.type = "delete";
|
2939
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2940
|
+
const Panels = () => {
|
2941
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2942
|
+
const [
|
2943
|
+
{
|
2944
|
+
query: { status }
|
2945
|
+
}
|
2946
|
+
] = strapiAdmin.useQueryParams({
|
2947
|
+
status: "draft"
|
2948
|
+
});
|
2949
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2950
|
+
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2951
|
+
const props = {
|
2952
|
+
activeTab: status,
|
2953
|
+
model,
|
2954
|
+
documentId: id,
|
2955
|
+
document: isCloning ? void 0 : document,
|
2956
|
+
meta: isCloning ? void 0 : meta,
|
2957
|
+
collectionType
|
2958
|
+
};
|
2959
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2960
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2961
|
+
{
|
2962
|
+
props,
|
2963
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2964
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2965
|
+
}
|
2966
|
+
) });
|
2752
2967
|
};
|
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
|
-
);
|
2968
|
+
const ActionsPanel = () => {
|
2969
|
+
const { formatMessage } = reactIntl.useIntl();
|
2774
2970
|
return {
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2780
|
-
...schema?.pluginOptions,
|
2781
|
-
...data.contentType.options
|
2782
|
-
}
|
2971
|
+
title: formatMessage({
|
2972
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2973
|
+
defaultMessage: "Entry"
|
2974
|
+
}),
|
2975
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2783
2976
|
};
|
2784
2977
|
};
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2978
|
+
ActionsPanel.type = "actions";
|
2979
|
+
const ActionsPanelContent = () => {
|
2980
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2981
|
+
const [
|
2982
|
+
{
|
2983
|
+
query: { status = "draft" }
|
2790
2984
|
}
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
|
2800
|
-
|
2801
|
-
|
2802
|
-
|
2803
|
-
|
2804
|
-
|
2985
|
+
] = strapiAdmin.useQueryParams();
|
2986
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2987
|
+
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2988
|
+
const props = {
|
2989
|
+
activeTab: status,
|
2990
|
+
model,
|
2991
|
+
documentId: id,
|
2992
|
+
document: isCloning ? void 0 : document,
|
2993
|
+
meta: isCloning ? void 0 : meta,
|
2994
|
+
collectionType
|
2995
|
+
};
|
2996
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2997
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2998
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2999
|
+
{
|
3000
|
+
props,
|
3001
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3002
|
+
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
3003
|
+
}
|
3004
|
+
),
|
3005
|
+
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3006
|
+
] });
|
2805
3007
|
};
|
3008
|
+
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
3009
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
3010
|
+
designSystem.Flex,
|
3011
|
+
{
|
3012
|
+
ref,
|
3013
|
+
tag: "aside",
|
3014
|
+
"aria-labelledby": "additional-information",
|
3015
|
+
background: "neutral0",
|
3016
|
+
borderColor: "neutral150",
|
3017
|
+
hasRadius: true,
|
3018
|
+
paddingBottom: 4,
|
3019
|
+
paddingLeft: 4,
|
3020
|
+
paddingRight: 4,
|
3021
|
+
paddingTop: 4,
|
3022
|
+
shadow: "tableShadow",
|
3023
|
+
gap: 3,
|
3024
|
+
direction: "column",
|
3025
|
+
justifyContent: "stretch",
|
3026
|
+
alignItems: "flex-start",
|
3027
|
+
children: [
|
3028
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
3029
|
+
children
|
3030
|
+
]
|
3031
|
+
}
|
3032
|
+
);
|
3033
|
+
});
|
2806
3034
|
const ConfirmBulkActionDialog = ({
|
2807
3035
|
onToggleDialog,
|
2808
3036
|
isOpen = false,
|
@@ -2810,7 +3038,7 @@ const ConfirmBulkActionDialog = ({
|
|
2810
3038
|
endAction
|
2811
3039
|
}) => {
|
2812
3040
|
const { formatMessage } = reactIntl.useIntl();
|
2813
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, {
|
3041
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2814
3042
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
|
2815
3043
|
id: "app.components.ConfirmDialog.title",
|
2816
3044
|
defaultMessage: "Confirmation"
|
@@ -2841,6 +3069,7 @@ const ConfirmDialogPublishAll = ({
|
|
2841
3069
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2842
3070
|
const { model, schema } = useDoc();
|
2843
3071
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3072
|
+
const enableDraftRelationsCount = false;
|
2844
3073
|
const {
|
2845
3074
|
data: countDraftRelations = 0,
|
2846
3075
|
isLoading,
|
@@ -2852,7 +3081,7 @@ const ConfirmDialogPublishAll = ({
|
|
2852
3081
|
locale: query?.plugins?.i18n?.locale
|
2853
3082
|
},
|
2854
3083
|
{
|
2855
|
-
skip:
|
3084
|
+
skip: !enableDraftRelationsCount
|
2856
3085
|
}
|
2857
3086
|
);
|
2858
3087
|
React__namespace.useEffect(() => {
|
@@ -2931,7 +3160,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
|
2931
3160
|
)
|
2932
3161
|
);
|
2933
3162
|
} else {
|
2934
|
-
messages.push(
|
3163
|
+
messages.push(
|
3164
|
+
...formatErrorMessages(
|
3165
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3166
|
+
value,
|
3167
|
+
currentKey,
|
3168
|
+
formatMessage
|
3169
|
+
)
|
3170
|
+
);
|
2935
3171
|
}
|
2936
3172
|
} else {
|
2937
3173
|
messages.push(
|
@@ -3030,7 +3266,7 @@ const SelectedEntriesTableContent = ({
|
|
3030
3266
|
status: row.status
|
3031
3267
|
}
|
3032
3268
|
) }),
|
3033
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3269
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3034
3270
|
designSystem.IconButton,
|
3035
3271
|
{
|
3036
3272
|
tag: reactRouterDom.Link,
|
@@ -3053,9 +3289,10 @@ const SelectedEntriesTableContent = ({
|
|
3053
3289
|
),
|
3054
3290
|
target: "_blank",
|
3055
3291
|
marginLeft: "auto",
|
3056
|
-
|
3292
|
+
variant: "ghost",
|
3293
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3057
3294
|
}
|
3058
|
-
) })
|
3295
|
+
) }) })
|
3059
3296
|
] }, row.id)) })
|
3060
3297
|
] });
|
3061
3298
|
};
|
@@ -3092,7 +3329,13 @@ const SelectedEntriesModalContent = ({
|
|
3092
3329
|
);
|
3093
3330
|
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3094
3331
|
if (data.length > 0 && schema) {
|
3095
|
-
const validate = createYupSchema(
|
3332
|
+
const validate = createYupSchema(
|
3333
|
+
schema.attributes,
|
3334
|
+
components,
|
3335
|
+
// Since this is the "Publish" action, the validation
|
3336
|
+
// schema must enforce the rules for published entities
|
3337
|
+
{ status: "published" }
|
3338
|
+
);
|
3096
3339
|
const validationErrors2 = {};
|
3097
3340
|
const rows2 = data.map((entry) => {
|
3098
3341
|
try {
|
@@ -3442,7 +3685,7 @@ const TableActions = ({ document }) => {
|
|
3442
3685
|
strapiAdmin.DescriptionComponentRenderer,
|
3443
3686
|
{
|
3444
3687
|
props,
|
3445
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3688
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3446
3689
|
children: (actions2) => {
|
3447
3690
|
const tableRowActions = actions2.filter((action) => {
|
3448
3691
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3553,7 +3796,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3553
3796
|
}),
|
3554
3797
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3555
3798
|
footer: ({ onClose }) => {
|
3556
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3799
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3557
3800
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3558
3801
|
id: "cancel",
|
3559
3802
|
defaultMessage: "Cancel"
|
@@ -3594,8 +3837,7 @@ class ContentManagerPlugin {
|
|
3594
3837
|
documentActions = [
|
3595
3838
|
...DEFAULT_ACTIONS,
|
3596
3839
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3597
|
-
...DEFAULT_HEADER_ACTIONS
|
3598
|
-
HistoryAction
|
3840
|
+
...DEFAULT_HEADER_ACTIONS
|
3599
3841
|
];
|
3600
3842
|
editViewSidePanels = [ActionsPanel];
|
3601
3843
|
headerActions = [];
|
@@ -3684,6 +3926,52 @@ const getPrintableType = (value) => {
|
|
3684
3926
|
}
|
3685
3927
|
return nativeType;
|
3686
3928
|
};
|
3929
|
+
const HistoryAction = ({ model, document }) => {
|
3930
|
+
const { formatMessage } = reactIntl.useIntl();
|
3931
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3932
|
+
const navigate = reactRouterDom.useNavigate();
|
3933
|
+
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
3934
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3935
|
+
return null;
|
3936
|
+
}
|
3937
|
+
return {
|
3938
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
3939
|
+
label: formatMessage({
|
3940
|
+
id: "content-manager.history.document-action",
|
3941
|
+
defaultMessage: "Content History"
|
3942
|
+
}),
|
3943
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3944
|
+
disabled: (
|
3945
|
+
/**
|
3946
|
+
* The user is creating a new document.
|
3947
|
+
* It hasn't been saved yet, so there's no history to go to
|
3948
|
+
*/
|
3949
|
+
!document || /**
|
3950
|
+
* The document has been created but the current dimension has never been saved.
|
3951
|
+
* For example, the user is creating a new locale in an existing document,
|
3952
|
+
* so there's no history for the document in that locale
|
3953
|
+
*/
|
3954
|
+
!document.id || /**
|
3955
|
+
* History is only available for content types created by the user.
|
3956
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3957
|
+
* which start with `admin::` or `plugin::`
|
3958
|
+
*/
|
3959
|
+
!model.startsWith("api::")
|
3960
|
+
),
|
3961
|
+
position: "header"
|
3962
|
+
};
|
3963
|
+
};
|
3964
|
+
HistoryAction.type = "history";
|
3965
|
+
const historyAdmin = {
|
3966
|
+
bootstrap(app) {
|
3967
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3968
|
+
addDocumentAction((actions2) => {
|
3969
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3970
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3971
|
+
return actions2;
|
3972
|
+
});
|
3973
|
+
}
|
3974
|
+
};
|
3687
3975
|
const initialState = {
|
3688
3976
|
collectionTypeLinks: [],
|
3689
3977
|
components: [],
|
@@ -3734,15 +4022,29 @@ const index = {
|
|
3734
4022
|
defaultMessage: "Content Manager"
|
3735
4023
|
},
|
3736
4024
|
permissions: [],
|
3737
|
-
Component: () => Promise.resolve().then(() => require("./layout-BJfBoBiF.js")).then((mod) => ({ default: mod.Layout })),
|
3738
4025
|
position: 1
|
3739
4026
|
});
|
4027
|
+
app.router.addRoute({
|
4028
|
+
path: "content-manager/*",
|
4029
|
+
lazy: async () => {
|
4030
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-CeBSIkmP.js"));
|
4031
|
+
return {
|
4032
|
+
Component: Layout
|
4033
|
+
};
|
4034
|
+
},
|
4035
|
+
children: routes
|
4036
|
+
});
|
3740
4037
|
app.registerPlugin(cm.config);
|
3741
4038
|
},
|
4039
|
+
bootstrap(app) {
|
4040
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4041
|
+
historyAdmin.bootstrap(app);
|
4042
|
+
}
|
4043
|
+
},
|
3742
4044
|
async registerTrads({ locales }) {
|
3743
4045
|
const importedTrads = await Promise.all(
|
3744
4046
|
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-
|
4047
|
+
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
4048
|
return {
|
3747
4049
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3748
4050
|
locale
|
@@ -3760,6 +4062,7 @@ const index = {
|
|
3760
4062
|
};
|
3761
4063
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
3762
4064
|
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4065
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3763
4066
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3764
4067
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3765
4068
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3786,8 +4089,8 @@ exports.getDisplayName = getDisplayName;
|
|
3786
4089
|
exports.getMainField = getMainField;
|
3787
4090
|
exports.getTranslation = getTranslation;
|
3788
4091
|
exports.index = index;
|
3789
|
-
exports.routes = routes;
|
3790
4092
|
exports.setInitialData = setInitialData;
|
4093
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3791
4094
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3792
4095
|
exports.useDoc = useDoc;
|
3793
4096
|
exports.useDocLayout = useDocLayout;
|
@@ -3800,4 +4103,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
|
3800
4103
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3801
4104
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
3802
4105
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3803
|
-
//# sourceMappingURL=index-
|
4106
|
+
//# sourceMappingURL=index-DbT2sx-Q.js.map
|