@strapi/content-manager 0.0.0-experimental.25e22c6cc9bc6b35392bb55d09f641a0a65e7403 → 0.0.0-experimental.2bad311ac375d1115d085a9cee4fdbe11a455caf
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-gdUj_t-O.mjs → ComponentConfigurationPage-7-qB29e7.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-gdUj_t-O.mjs.map → ComponentConfigurationPage-7-qB29e7.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-WRPUXGd6.js → ComponentConfigurationPage-DP7AC0UU.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-WRPUXGd6.js.map → ComponentConfigurationPage-DP7AC0UU.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-BwuIPOJG.mjs → EditConfigurationPage-CI4XoymK.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BwuIPOJG.mjs.map → EditConfigurationPage-CI4XoymK.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-C1vjMBgy.js → EditConfigurationPage-DITVliEI.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-C1vjMBgy.js.map → EditConfigurationPage-DITVliEI.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-DbcGfyqK.js → EditViewPage-CUS2EAhB.js} +24 -9
- package/dist/_chunks/EditViewPage-CUS2EAhB.js.map +1 -0
- package/dist/_chunks/{EditViewPage-0MiFkXa8.mjs → EditViewPage-Dzpno8xI.mjs} +24 -9
- package/dist/_chunks/EditViewPage-Dzpno8xI.mjs.map +1 -0
- package/dist/_chunks/{Field-BDMSCcy5.mjs → Field-B_jG_EV9.mjs} +479 -147
- package/dist/_chunks/Field-B_jG_EV9.mjs.map +1 -0
- package/dist/_chunks/{Field-BG1xu38N.js → Field-CtUU1Fg8.js} +481 -149
- package/dist/_chunks/Field-CtUU1Fg8.js.map +1 -0
- package/dist/_chunks/{Form-CPVWavB8.mjs → Form-BXHao2mZ.mjs} +39 -17
- package/dist/_chunks/Form-BXHao2mZ.mjs.map +1 -0
- package/dist/_chunks/{Form-9BnFyUjy.js → Form-DTqO0ymI.js} +39 -17
- package/dist/_chunks/Form-DTqO0ymI.js.map +1 -0
- package/dist/_chunks/{History-BVpd8LP3.mjs → History-2Ah2CQ4T.mjs} +44 -19
- package/dist/_chunks/History-2Ah2CQ4T.mjs.map +1 -0
- package/dist/_chunks/{History-BWWxLt2Z.js → History-C_uSGzO5.js} +44 -19
- package/dist/_chunks/History-C_uSGzO5.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DozVMKcR.mjs → ListConfigurationPage-BjSJlaoC.mjs} +20 -8
- package/dist/_chunks/ListConfigurationPage-BjSJlaoC.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-6swzjdAZ.js → ListConfigurationPage-nyuP7OSy.js} +20 -8
- package/dist/_chunks/ListConfigurationPage-nyuP7OSy.js.map +1 -0
- package/dist/_chunks/{ListViewPage-Ds0ulgfG.mjs → ListViewPage-B75x3nz2.mjs} +59 -41
- package/dist/_chunks/ListViewPage-B75x3nz2.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-BlzfjS2Q.js → ListViewPage-DHgHD8Xg.js} +61 -43
- package/dist/_chunks/ListViewPage-DHgHD8Xg.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-D2nCCWEl.js → NoContentTypePage-CDUKdZ7d.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-D2nCCWEl.js.map → NoContentTypePage-CDUKdZ7d.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-BH11kaKt.mjs → NoContentTypePage-DUacQSyF.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-BH11kaKt.mjs.map → NoContentTypePage-DUacQSyF.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-BT2Tn0D_.mjs → NoPermissionsPage-SFllMekk.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-BT2Tn0D_.mjs.map → NoPermissionsPage-SFllMekk.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DN_JlsU2.js → NoPermissionsPage-zwIZydDI.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DN_JlsU2.js.map → NoPermissionsPage-zwIZydDI.js.map} +1 -1
- package/dist/_chunks/{Relations-Dnag3fhV.mjs → Relations-D2NRW8fC.mjs} +14 -10
- package/dist/_chunks/Relations-D2NRW8fC.mjs.map +1 -0
- package/dist/_chunks/{Relations-CcgFTcWo.js → Relations-NFLaRNPr.js} +14 -10
- package/dist/_chunks/Relations-NFLaRNPr.js.map +1 -0
- package/dist/_chunks/{en-fbKQxLGn.js → en-BlhnxQfj.js} +11 -9
- package/dist/_chunks/{en-fbKQxLGn.js.map → en-BlhnxQfj.js.map} +1 -1
- package/dist/_chunks/{en-Ux26r5pl.mjs → en-C8YBvRrK.mjs} +11 -9
- package/dist/_chunks/{en-Ux26r5pl.mjs.map → en-C8YBvRrK.mjs.map} +1 -1
- package/dist/_chunks/{index-JNNNKUHs.mjs → index-C9HxCo5R.mjs} +981 -662
- package/dist/_chunks/index-C9HxCo5R.mjs.map +1 -0
- package/dist/_chunks/{index-CWpLBSt0.js → index-ovJRE1FM.js} +973 -654
- package/dist/_chunks/index-ovJRE1FM.js.map +1 -0
- package/dist/_chunks/{layout-DC503LnF.mjs → layout-DaUjDiWQ.mjs} +27 -14
- package/dist/_chunks/layout-DaUjDiWQ.mjs.map +1 -0
- package/dist/_chunks/{layout--iHdZzRk.js → layout-UNWstw_s.js} +25 -12
- package/dist/_chunks/layout-UNWstw_s.js.map +1 -0
- package/dist/_chunks/{relations-CTje5t-a.mjs → relations-D8iFAeRu.mjs} +2 -2
- package/dist/_chunks/{relations-CTje5t-a.mjs.map → relations-D8iFAeRu.mjs.map} +1 -1
- package/dist/_chunks/{relations-BbHizA5K.js → relations-NN3coOG5.js} +2 -2
- package/dist/_chunks/{relations-BbHizA5K.js.map → relations-NN3coOG5.js.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 +191 -113
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +192 -114
- 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 +11 -11
- package/dist/_chunks/EditViewPage-0MiFkXa8.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-DbcGfyqK.js.map +0 -1
- package/dist/_chunks/Field-BDMSCcy5.mjs.map +0 -1
- package/dist/_chunks/Field-BG1xu38N.js.map +0 -1
- package/dist/_chunks/Form-9BnFyUjy.js.map +0 -1
- package/dist/_chunks/Form-CPVWavB8.mjs.map +0 -1
- package/dist/_chunks/History-BVpd8LP3.mjs.map +0 -1
- package/dist/_chunks/History-BWWxLt2Z.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-6swzjdAZ.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DozVMKcR.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-BlzfjS2Q.js.map +0 -1
- package/dist/_chunks/ListViewPage-Ds0ulgfG.mjs.map +0 -1
- package/dist/_chunks/Relations-CcgFTcWo.js.map +0 -1
- package/dist/_chunks/Relations-Dnag3fhV.mjs.map +0 -1
- package/dist/_chunks/index-CWpLBSt0.js.map +0 -1
- package/dist/_chunks/index-JNNNKUHs.mjs.map +0 -1
- package/dist/_chunks/layout--iHdZzRk.js.map +0 -1
- package/dist/_chunks/layout-DC503LnF.mjs.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
@@ -2,15 +2,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";
|
@@ -215,10 +179,12 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
|
215
179
|
"Document",
|
216
180
|
"InitialData",
|
217
181
|
"HistoryVersion",
|
218
|
-
"Relations"
|
182
|
+
"Relations",
|
183
|
+
"UidAvailability"
|
219
184
|
]
|
220
185
|
});
|
221
186
|
const documentApi = contentManagerApi.injectEndpoints({
|
187
|
+
overrideExisting: true,
|
222
188
|
endpoints: (builder) => ({
|
223
189
|
autoCloneDocument: builder.mutation({
|
224
190
|
query: ({ model, sourceId, query }) => ({
|
@@ -228,7 +194,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
228
194
|
params: query
|
229
195
|
}
|
230
196
|
}),
|
231
|
-
invalidatesTags: (_result,
|
197
|
+
invalidatesTags: (_result, error, { model }) => {
|
198
|
+
if (error) {
|
199
|
+
return [];
|
200
|
+
}
|
201
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
202
|
+
}
|
232
203
|
}),
|
233
204
|
cloneDocument: builder.mutation({
|
234
205
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -239,7 +210,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
239
210
|
params
|
240
211
|
}
|
241
212
|
}),
|
242
|
-
invalidatesTags: (_result, _error, { model }) => [
|
213
|
+
invalidatesTags: (_result, _error, { model }) => [
|
214
|
+
{ type: "Document", id: `${model}_LIST` },
|
215
|
+
{ type: "UidAvailability", id: model }
|
216
|
+
]
|
243
217
|
}),
|
244
218
|
/**
|
245
219
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -256,7 +230,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
256
230
|
}),
|
257
231
|
invalidatesTags: (result, _error, { model }) => [
|
258
232
|
{ type: "Document", id: `${model}_LIST` },
|
259
|
-
"Relations"
|
233
|
+
"Relations",
|
234
|
+
{ type: "UidAvailability", id: model }
|
260
235
|
]
|
261
236
|
}),
|
262
237
|
deleteDocument: builder.mutation({
|
@@ -297,7 +272,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
297
272
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
298
273
|
},
|
299
274
|
{ type: "Document", id: `${model}_LIST` },
|
300
|
-
"Relations"
|
275
|
+
"Relations",
|
276
|
+
{ type: "UidAvailability", id: model }
|
301
277
|
];
|
302
278
|
}
|
303
279
|
}),
|
@@ -315,6 +291,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
315
291
|
}),
|
316
292
|
providesTags: (result, _error, arg) => {
|
317
293
|
return [
|
294
|
+
{ type: "Document", id: `ALL_LIST` },
|
318
295
|
{ type: "Document", id: `${arg.model}_LIST` },
|
319
296
|
...result?.results.map(({ documentId }) => ({
|
320
297
|
type: "Document",
|
@@ -353,6 +330,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
353
330
|
{
|
354
331
|
type: "Document",
|
355
332
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
333
|
+
},
|
334
|
+
// Make it easy to invalidate all individual documents queries for a model
|
335
|
+
{
|
336
|
+
type: "Document",
|
337
|
+
id: `${model}_ALL_ITEMS`
|
356
338
|
}
|
357
339
|
];
|
358
340
|
}
|
@@ -416,8 +398,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
416
398
|
type: "Document",
|
417
399
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
418
400
|
},
|
419
|
-
"Relations"
|
401
|
+
"Relations",
|
402
|
+
{ type: "UidAvailability", id: model }
|
420
403
|
];
|
404
|
+
},
|
405
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
406
|
+
const patchResult = dispatch(
|
407
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
408
|
+
Object.assign(draft.data, data);
|
409
|
+
})
|
410
|
+
);
|
411
|
+
try {
|
412
|
+
await queryFulfilled;
|
413
|
+
} catch {
|
414
|
+
patchResult.undo();
|
415
|
+
}
|
421
416
|
}
|
422
417
|
}),
|
423
418
|
unpublishDocument: builder.mutation({
|
@@ -487,7 +482,7 @@ const buildValidParams = (query) => {
|
|
487
482
|
const isBaseQueryError = (error) => {
|
488
483
|
return error.name !== void 0;
|
489
484
|
};
|
490
|
-
const createYupSchema = (attributes = {}, components = {}) => {
|
485
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
491
486
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
492
487
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
493
488
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
@@ -500,7 +495,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
500
495
|
addMinValidation,
|
501
496
|
addMaxValidation,
|
502
497
|
addRegexValidation
|
503
|
-
].map((fn) => fn(attribute));
|
498
|
+
].map((fn) => fn(attribute, options));
|
504
499
|
const transformSchema = pipe__default.default(...validations);
|
505
500
|
switch (attribute.type) {
|
506
501
|
case "component": {
|
@@ -549,7 +544,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
549
544
|
} else if (Array.isArray(value)) {
|
550
545
|
return yup__namespace.array().of(
|
551
546
|
yup__namespace.object().shape({
|
552
|
-
id: yup__namespace.
|
547
|
+
id: yup__namespace.number().required()
|
553
548
|
})
|
554
549
|
);
|
555
550
|
} else if (typeof value === "object") {
|
@@ -601,6 +596,14 @@ const createAttributeSchema = (attribute) => {
|
|
601
596
|
if (!value || typeof value === "string" && value.length === 0) {
|
602
597
|
return true;
|
603
598
|
}
|
599
|
+
if (typeof value === "object") {
|
600
|
+
try {
|
601
|
+
JSON.stringify(value);
|
602
|
+
return true;
|
603
|
+
} catch (err) {
|
604
|
+
return false;
|
605
|
+
}
|
606
|
+
}
|
604
607
|
try {
|
605
608
|
JSON.parse(value);
|
606
609
|
return true;
|
@@ -619,13 +622,7 @@ const createAttributeSchema = (attribute) => {
|
|
619
622
|
return yup__namespace.mixed();
|
620
623
|
}
|
621
624
|
};
|
622
|
-
const
|
623
|
-
if (attribute.required) {
|
624
|
-
return schema.required({
|
625
|
-
id: strapiAdmin.translatedErrors.required.id,
|
626
|
-
defaultMessage: "This field is required."
|
627
|
-
});
|
628
|
-
}
|
625
|
+
const nullableSchema = (schema) => {
|
629
626
|
return schema?.nullable ? schema.nullable() : (
|
630
627
|
// In some cases '.nullable' will not be available on the schema.
|
631
628
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -633,7 +630,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
633
630
|
schema
|
634
631
|
);
|
635
632
|
};
|
636
|
-
const
|
633
|
+
const addRequiredValidation = (attribute, options) => (schema) => {
|
634
|
+
if (options.status === "draft") {
|
635
|
+
return nullableSchema(schema);
|
636
|
+
}
|
637
|
+
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
638
|
+
return schema.min(1, strapiAdmin.translatedErrors.required);
|
639
|
+
}
|
640
|
+
if (attribute.required && attribute.type !== "relation") {
|
641
|
+
return schema.required(strapiAdmin.translatedErrors.required);
|
642
|
+
}
|
643
|
+
return nullableSchema(schema);
|
644
|
+
};
|
645
|
+
const addMinLengthValidation = (attribute, options) => (schema) => {
|
646
|
+
if (options.status === "draft") {
|
647
|
+
return schema;
|
648
|
+
}
|
637
649
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
638
650
|
return schema.min(attribute.minLength, {
|
639
651
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -655,9 +667,31 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
655
667
|
}
|
656
668
|
return schema;
|
657
669
|
};
|
658
|
-
const addMinValidation = (attribute) => (schema) => {
|
670
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
659
671
|
if ("min" in attribute) {
|
660
672
|
const min = toInteger(attribute.min);
|
673
|
+
if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
|
674
|
+
if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
|
675
|
+
return schema.test(
|
676
|
+
"custom-min",
|
677
|
+
{
|
678
|
+
...strapiAdmin.translatedErrors.min,
|
679
|
+
values: {
|
680
|
+
min: attribute.min
|
681
|
+
}
|
682
|
+
},
|
683
|
+
(value) => {
|
684
|
+
if (!value) {
|
685
|
+
return true;
|
686
|
+
}
|
687
|
+
if (Array.isArray(value) && value.length === 0) {
|
688
|
+
return true;
|
689
|
+
}
|
690
|
+
return value.length >= min;
|
691
|
+
}
|
692
|
+
);
|
693
|
+
}
|
694
|
+
}
|
661
695
|
if ("min" in schema && min) {
|
662
696
|
return schema.min(min, {
|
663
697
|
...strapiAdmin.translatedErrors.min,
|
@@ -776,16 +810,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
776
810
|
}, {});
|
777
811
|
return componentsByKey;
|
778
812
|
};
|
779
|
-
const
|
813
|
+
const HOOKS = {
|
814
|
+
/**
|
815
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
816
|
+
* @constant
|
817
|
+
* @type {string}
|
818
|
+
*/
|
819
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
820
|
+
/**
|
821
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
822
|
+
* @constant
|
823
|
+
* @type {string}
|
824
|
+
*/
|
825
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
826
|
+
/**
|
827
|
+
* Hook that allows to mutate the CM's edit view layout
|
828
|
+
* @constant
|
829
|
+
* @type {string}
|
830
|
+
*/
|
831
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
832
|
+
/**
|
833
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
834
|
+
* @constant
|
835
|
+
* @type {string}
|
836
|
+
*/
|
837
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
838
|
+
};
|
839
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
840
|
+
endpoints: (builder) => ({
|
841
|
+
getContentTypeConfiguration: builder.query({
|
842
|
+
query: (uid) => ({
|
843
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
844
|
+
method: "GET"
|
845
|
+
}),
|
846
|
+
transformResponse: (response) => response.data,
|
847
|
+
providesTags: (_result, _error, uid) => [
|
848
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
849
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
850
|
+
]
|
851
|
+
}),
|
852
|
+
getAllContentTypeSettings: builder.query({
|
853
|
+
query: () => "/content-manager/content-types-settings",
|
854
|
+
transformResponse: (response) => response.data,
|
855
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
856
|
+
}),
|
857
|
+
updateContentTypeConfiguration: builder.mutation({
|
858
|
+
query: ({ uid, ...body }) => ({
|
859
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
860
|
+
method: "PUT",
|
861
|
+
data: body
|
862
|
+
}),
|
863
|
+
transformResponse: (response) => response.data,
|
864
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
865
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
866
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
867
|
+
// Is this necessary?
|
868
|
+
{ type: "InitialData" }
|
869
|
+
]
|
870
|
+
})
|
871
|
+
})
|
872
|
+
});
|
873
|
+
const {
|
874
|
+
useGetContentTypeConfigurationQuery,
|
875
|
+
useGetAllContentTypeSettingsQuery,
|
876
|
+
useUpdateContentTypeConfigurationMutation
|
877
|
+
} = contentTypesApi;
|
878
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
879
|
+
const { type } = attribute;
|
880
|
+
if (type === "relation") {
|
881
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
882
|
+
}
|
883
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
884
|
+
};
|
885
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
886
|
+
if (!mainFieldName) {
|
887
|
+
return void 0;
|
888
|
+
}
|
889
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
890
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
891
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
892
|
+
);
|
893
|
+
return {
|
894
|
+
name: mainFieldName,
|
895
|
+
type: mainFieldType ?? "string"
|
896
|
+
};
|
897
|
+
};
|
898
|
+
const DEFAULT_SETTINGS = {
|
899
|
+
bulkable: false,
|
900
|
+
filterable: false,
|
901
|
+
searchable: false,
|
902
|
+
pagination: false,
|
903
|
+
defaultSortBy: "",
|
904
|
+
defaultSortOrder: "asc",
|
905
|
+
mainField: "id",
|
906
|
+
pageSize: 10
|
907
|
+
};
|
908
|
+
const useDocumentLayout = (model) => {
|
909
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
910
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
911
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
780
912
|
const { toggleNotification } = strapiAdmin.useNotification();
|
781
913
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
914
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
782
915
|
const {
|
783
|
-
|
784
|
-
isLoading:
|
785
|
-
|
786
|
-
|
787
|
-
} =
|
788
|
-
const
|
916
|
+
data,
|
917
|
+
isLoading: isLoadingConfigs,
|
918
|
+
error,
|
919
|
+
isFetching: isFetchingConfigs
|
920
|
+
} = useGetContentTypeConfigurationQuery(model);
|
921
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
789
922
|
React__namespace.useEffect(() => {
|
790
923
|
if (error) {
|
791
924
|
toggleNotification({
|
@@ -793,54 +926,269 @@ const useDocument = (args, opts) => {
|
|
793
926
|
message: formatAPIError(error)
|
794
927
|
});
|
795
928
|
}
|
796
|
-
}, [
|
797
|
-
const
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
(document) => {
|
805
|
-
if (!validationSchema) {
|
806
|
-
throw new Error(
|
807
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
808
|
-
);
|
809
|
-
}
|
810
|
-
try {
|
811
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
812
|
-
return null;
|
813
|
-
} catch (error2) {
|
814
|
-
if (error2 instanceof yup.ValidationError) {
|
815
|
-
return strapiAdmin.getYupValidationErrors(error2);
|
816
|
-
}
|
817
|
-
throw error2;
|
818
|
-
}
|
929
|
+
}, [error, formatAPIError, toggleNotification]);
|
930
|
+
const editLayout = React__namespace.useMemo(
|
931
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
932
|
+
layout: [],
|
933
|
+
components: {},
|
934
|
+
metadatas: {},
|
935
|
+
options: {},
|
936
|
+
settings: DEFAULT_SETTINGS
|
819
937
|
},
|
820
|
-
[
|
938
|
+
[data, isLoading, schemas, schema, components]
|
939
|
+
);
|
940
|
+
const listLayout = React__namespace.useMemo(() => {
|
941
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
942
|
+
layout: [],
|
943
|
+
metadatas: {},
|
944
|
+
options: {},
|
945
|
+
settings: DEFAULT_SETTINGS
|
946
|
+
};
|
947
|
+
}, [data, isLoading, schemas, schema, components]);
|
948
|
+
const { layout: edit } = React__namespace.useMemo(
|
949
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
950
|
+
layout: editLayout,
|
951
|
+
query
|
952
|
+
}),
|
953
|
+
[editLayout, query, runHookWaterfall]
|
821
954
|
);
|
822
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
823
955
|
return {
|
824
|
-
|
825
|
-
document: data?.data,
|
826
|
-
meta: data?.meta,
|
956
|
+
error,
|
827
957
|
isLoading,
|
828
|
-
|
829
|
-
|
958
|
+
edit,
|
959
|
+
list: listLayout
|
830
960
|
};
|
831
961
|
};
|
832
|
-
const
|
833
|
-
const {
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
962
|
+
const useDocLayout = () => {
|
963
|
+
const { model } = useDoc();
|
964
|
+
return useDocumentLayout(model);
|
965
|
+
};
|
966
|
+
const formatEditLayout = (data, {
|
967
|
+
schemas,
|
968
|
+
schema,
|
969
|
+
components
|
970
|
+
}) => {
|
971
|
+
let currentPanelIndex = 0;
|
972
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
973
|
+
data.contentType.layouts.edit,
|
974
|
+
schema?.attributes,
|
975
|
+
data.contentType.metadatas,
|
976
|
+
{ configurations: data.components, schemas: components },
|
977
|
+
schemas
|
978
|
+
).reduce((panels, row) => {
|
979
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
980
|
+
panels.push([row]);
|
981
|
+
currentPanelIndex += 2;
|
982
|
+
} else {
|
983
|
+
if (!panels[currentPanelIndex]) {
|
984
|
+
panels.push([]);
|
985
|
+
}
|
986
|
+
panels[currentPanelIndex].push(row);
|
987
|
+
}
|
988
|
+
return panels;
|
989
|
+
}, []);
|
990
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
991
|
+
(acc, [uid, configuration]) => {
|
992
|
+
acc[uid] = {
|
993
|
+
layout: convertEditLayoutToFieldLayouts(
|
994
|
+
configuration.layouts.edit,
|
995
|
+
components[uid].attributes,
|
996
|
+
configuration.metadatas,
|
997
|
+
{ configurations: data.components, schemas: components }
|
998
|
+
),
|
999
|
+
settings: {
|
1000
|
+
...configuration.settings,
|
1001
|
+
icon: components[uid].info.icon,
|
1002
|
+
displayName: components[uid].info.displayName
|
1003
|
+
}
|
1004
|
+
};
|
1005
|
+
return acc;
|
1006
|
+
},
|
1007
|
+
{}
|
1008
|
+
);
|
1009
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1010
|
+
(acc, [attribute, metadata]) => {
|
1011
|
+
return {
|
1012
|
+
...acc,
|
1013
|
+
[attribute]: metadata.edit
|
1014
|
+
};
|
1015
|
+
},
|
1016
|
+
{}
|
1017
|
+
);
|
1018
|
+
return {
|
1019
|
+
layout: panelledEditAttributes,
|
1020
|
+
components: componentEditAttributes,
|
1021
|
+
metadatas: editMetadatas,
|
1022
|
+
settings: {
|
1023
|
+
...data.contentType.settings,
|
1024
|
+
displayName: schema?.info.displayName
|
1025
|
+
},
|
1026
|
+
options: {
|
1027
|
+
...schema?.options,
|
1028
|
+
...schema?.pluginOptions,
|
1029
|
+
...data.contentType.options
|
1030
|
+
}
|
1031
|
+
};
|
1032
|
+
};
|
1033
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1034
|
+
return rows.map(
|
1035
|
+
(row) => row.map((field) => {
|
1036
|
+
const attribute = attributes[field.name];
|
1037
|
+
if (!attribute) {
|
1038
|
+
return null;
|
1039
|
+
}
|
1040
|
+
const { edit: metadata } = metadatas[field.name];
|
1041
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1042
|
+
return {
|
1043
|
+
attribute,
|
1044
|
+
disabled: !metadata.editable,
|
1045
|
+
hint: metadata.description,
|
1046
|
+
label: metadata.label ?? "",
|
1047
|
+
name: field.name,
|
1048
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1049
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1050
|
+
schemas,
|
1051
|
+
components: components?.schemas ?? {}
|
1052
|
+
}),
|
1053
|
+
placeholder: metadata.placeholder ?? "",
|
1054
|
+
required: attribute.required ?? false,
|
1055
|
+
size: field.size,
|
1056
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1057
|
+
visible: metadata.visible ?? true,
|
1058
|
+
type: attribute.type
|
1059
|
+
};
|
1060
|
+
}).filter((field) => field !== null)
|
1061
|
+
);
|
1062
|
+
};
|
1063
|
+
const formatListLayout = (data, {
|
1064
|
+
schemas,
|
1065
|
+
schema,
|
1066
|
+
components
|
1067
|
+
}) => {
|
1068
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1069
|
+
(acc, [attribute, metadata]) => {
|
1070
|
+
return {
|
1071
|
+
...acc,
|
1072
|
+
[attribute]: metadata.list
|
1073
|
+
};
|
1074
|
+
},
|
1075
|
+
{}
|
1076
|
+
);
|
1077
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1078
|
+
data.contentType.layouts.list,
|
1079
|
+
schema?.attributes,
|
1080
|
+
listMetadatas,
|
1081
|
+
{ configurations: data.components, schemas: components },
|
1082
|
+
schemas
|
1083
|
+
);
|
1084
|
+
return {
|
1085
|
+
layout: listAttributes,
|
1086
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1087
|
+
metadatas: listMetadatas,
|
1088
|
+
options: {
|
1089
|
+
...schema?.options,
|
1090
|
+
...schema?.pluginOptions,
|
1091
|
+
...data.contentType.options
|
1092
|
+
}
|
1093
|
+
};
|
1094
|
+
};
|
1095
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1096
|
+
return columns.map((name) => {
|
1097
|
+
const attribute = attributes[name];
|
1098
|
+
if (!attribute) {
|
1099
|
+
return null;
|
1100
|
+
}
|
1101
|
+
const metadata = metadatas[name];
|
1102
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1103
|
+
return {
|
1104
|
+
attribute,
|
1105
|
+
label: metadata.label ?? "",
|
1106
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1107
|
+
schemas,
|
1108
|
+
components: components?.schemas ?? {}
|
1109
|
+
}),
|
1110
|
+
name,
|
1111
|
+
searchable: metadata.searchable ?? true,
|
1112
|
+
sortable: metadata.sortable ?? true
|
1113
|
+
};
|
1114
|
+
}).filter((field) => field !== null);
|
1115
|
+
};
|
1116
|
+
const useDocument = (args, opts) => {
|
1117
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1118
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1119
|
+
const {
|
1120
|
+
currentData: data,
|
1121
|
+
isLoading: isLoadingDocument,
|
1122
|
+
isFetching: isFetchingDocument,
|
1123
|
+
error
|
1124
|
+
} = useGetDocumentQuery(args, {
|
1125
|
+
...opts,
|
1126
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1127
|
+
});
|
1128
|
+
const {
|
1129
|
+
components,
|
1130
|
+
schema,
|
1131
|
+
schemas,
|
1132
|
+
isLoading: isLoadingSchema
|
1133
|
+
} = useContentTypeSchema(args.model);
|
1134
|
+
React__namespace.useEffect(() => {
|
1135
|
+
if (error) {
|
1136
|
+
toggleNotification({
|
1137
|
+
type: "danger",
|
1138
|
+
message: formatAPIError(error)
|
1139
|
+
});
|
1140
|
+
}
|
1141
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1142
|
+
const validationSchema = React__namespace.useMemo(() => {
|
1143
|
+
if (!schema) {
|
1144
|
+
return null;
|
1145
|
+
}
|
1146
|
+
return createYupSchema(schema.attributes, components);
|
1147
|
+
}, [schema, components]);
|
1148
|
+
const validate = React__namespace.useCallback(
|
1149
|
+
(document) => {
|
1150
|
+
if (!validationSchema) {
|
1151
|
+
throw new Error(
|
1152
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1153
|
+
);
|
1154
|
+
}
|
1155
|
+
try {
|
1156
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1157
|
+
return null;
|
1158
|
+
} catch (error2) {
|
1159
|
+
if (error2 instanceof yup.ValidationError) {
|
1160
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
1161
|
+
}
|
1162
|
+
throw error2;
|
1163
|
+
}
|
1164
|
+
},
|
1165
|
+
[validationSchema]
|
1166
|
+
);
|
1167
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1168
|
+
const hasError = !!error;
|
1169
|
+
return {
|
1170
|
+
components,
|
1171
|
+
document: data?.data,
|
1172
|
+
meta: data?.meta,
|
1173
|
+
isLoading,
|
1174
|
+
hasError,
|
1175
|
+
schema,
|
1176
|
+
schemas,
|
1177
|
+
validate
|
1178
|
+
};
|
1179
|
+
};
|
1180
|
+
const useDoc = () => {
|
1181
|
+
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
1182
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
1183
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1184
|
+
if (!collectionType) {
|
1185
|
+
throw new Error("Could not find collectionType in url params");
|
1186
|
+
}
|
1187
|
+
if (!slug) {
|
1188
|
+
throw new Error("Could not find model in url params");
|
1189
|
+
}
|
1190
|
+
return {
|
1191
|
+
collectionType,
|
844
1192
|
model: slug,
|
845
1193
|
id: origin || id === "create" ? void 0 : id,
|
846
1194
|
...useDocument(
|
@@ -851,6 +1199,45 @@ const useDoc = () => {
|
|
851
1199
|
)
|
852
1200
|
};
|
853
1201
|
};
|
1202
|
+
const useContentManagerContext = () => {
|
1203
|
+
const {
|
1204
|
+
collectionType,
|
1205
|
+
model,
|
1206
|
+
id,
|
1207
|
+
components,
|
1208
|
+
isLoading: isLoadingDoc,
|
1209
|
+
schema,
|
1210
|
+
schemas
|
1211
|
+
} = useDoc();
|
1212
|
+
const layout = useDocumentLayout(model);
|
1213
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1214
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1215
|
+
const slug = model;
|
1216
|
+
const isCreatingEntry = id === "create";
|
1217
|
+
useContentTypeSchema();
|
1218
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1219
|
+
const error = layout.error;
|
1220
|
+
return {
|
1221
|
+
error,
|
1222
|
+
isLoading,
|
1223
|
+
// Base metadata
|
1224
|
+
model,
|
1225
|
+
collectionType,
|
1226
|
+
id,
|
1227
|
+
slug,
|
1228
|
+
isCreatingEntry,
|
1229
|
+
isSingleType,
|
1230
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1231
|
+
// All schema infos
|
1232
|
+
components,
|
1233
|
+
contentType: schema,
|
1234
|
+
contentTypes: schemas,
|
1235
|
+
// Form state
|
1236
|
+
form,
|
1237
|
+
// layout infos
|
1238
|
+
layout
|
1239
|
+
};
|
1240
|
+
};
|
854
1241
|
const prefixPluginTranslations = (trad, pluginId) => {
|
855
1242
|
if (!pluginId) {
|
856
1243
|
throw new TypeError("pluginId can't be empty");
|
@@ -870,6 +1257,8 @@ const useDocumentActions = () => {
|
|
870
1257
|
const { formatMessage } = reactIntl.useIntl();
|
871
1258
|
const { trackUsage } = strapiAdmin.useTracking();
|
872
1259
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1260
|
+
const navigate = reactRouterDom.useNavigate();
|
1261
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
873
1262
|
const [deleteDocument] = useDeleteDocumentMutation();
|
874
1263
|
const _delete = React__namespace.useCallback(
|
875
1264
|
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
@@ -1184,6 +1573,7 @@ const useDocumentActions = () => {
|
|
1184
1573
|
defaultMessage: "Saved document"
|
1185
1574
|
})
|
1186
1575
|
});
|
1576
|
+
setCurrentStep("contentManager.success");
|
1187
1577
|
return res.data;
|
1188
1578
|
} catch (err) {
|
1189
1579
|
toggleNotification({
|
@@ -1205,7 +1595,6 @@ const useDocumentActions = () => {
|
|
1205
1595
|
sourceId
|
1206
1596
|
});
|
1207
1597
|
if ("error" in res) {
|
1208
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1209
1598
|
return { error: res.error };
|
1210
1599
|
}
|
1211
1600
|
toggleNotification({
|
@@ -1224,7 +1613,7 @@ const useDocumentActions = () => {
|
|
1224
1613
|
throw err;
|
1225
1614
|
}
|
1226
1615
|
},
|
1227
|
-
[autoCloneDocument,
|
1616
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1228
1617
|
);
|
1229
1618
|
const [cloneDocument] = useCloneDocumentMutation();
|
1230
1619
|
const clone = React__namespace.useCallback(
|
@@ -1250,6 +1639,7 @@ const useDocumentActions = () => {
|
|
1250
1639
|
defaultMessage: "Cloned document"
|
1251
1640
|
})
|
1252
1641
|
});
|
1642
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1253
1643
|
return res.data;
|
1254
1644
|
} catch (err) {
|
1255
1645
|
toggleNotification({
|
@@ -1260,7 +1650,7 @@ const useDocumentActions = () => {
|
|
1260
1650
|
throw err;
|
1261
1651
|
}
|
1262
1652
|
},
|
1263
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1653
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1264
1654
|
);
|
1265
1655
|
const [getDoc] = useLazyGetDocumentQuery();
|
1266
1656
|
const getDocument = React__namespace.useCallback(
|
@@ -1286,7 +1676,7 @@ const useDocumentActions = () => {
|
|
1286
1676
|
};
|
1287
1677
|
};
|
1288
1678
|
const ProtectedHistoryPage = React.lazy(
|
1289
|
-
() => Promise.resolve().then(() => require("./History-
|
1679
|
+
() => Promise.resolve().then(() => require("./History-C_uSGzO5.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1290
1680
|
);
|
1291
1681
|
const routes$1 = [
|
1292
1682
|
{
|
@@ -1299,31 +1689,31 @@ const routes$1 = [
|
|
1299
1689
|
}
|
1300
1690
|
];
|
1301
1691
|
const ProtectedEditViewPage = React.lazy(
|
1302
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1692
|
+
() => Promise.resolve().then(() => require("./EditViewPage-CUS2EAhB.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1303
1693
|
);
|
1304
1694
|
const ProtectedListViewPage = React.lazy(
|
1305
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1695
|
+
() => Promise.resolve().then(() => require("./ListViewPage-DHgHD8Xg.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1306
1696
|
);
|
1307
1697
|
const ProtectedListConfiguration = React.lazy(
|
1308
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1698
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-nyuP7OSy.js")).then((mod) => ({
|
1309
1699
|
default: mod.ProtectedListConfiguration
|
1310
1700
|
}))
|
1311
1701
|
);
|
1312
1702
|
const ProtectedEditConfigurationPage = React.lazy(
|
1313
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1703
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-DITVliEI.js")).then((mod) => ({
|
1314
1704
|
default: mod.ProtectedEditConfigurationPage
|
1315
1705
|
}))
|
1316
1706
|
);
|
1317
1707
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1318
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1708
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-DP7AC0UU.js")).then((mod) => ({
|
1319
1709
|
default: mod.ProtectedComponentConfigurationPage
|
1320
1710
|
}))
|
1321
1711
|
);
|
1322
1712
|
const NoPermissions = React.lazy(
|
1323
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1713
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-zwIZydDI.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1324
1714
|
);
|
1325
1715
|
const NoContentType = React.lazy(
|
1326
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1716
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-CDUKdZ7d.js")).then((mod) => ({ default: mod.NoContentType }))
|
1327
1717
|
);
|
1328
1718
|
const CollectionTypePages = () => {
|
1329
1719
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1437,12 +1827,14 @@ const DocumentActionButton = (action) => {
|
|
1437
1827
|
/* @__PURE__ */ jsxRuntime.jsx(
|
1438
1828
|
designSystem.Button,
|
1439
1829
|
{
|
1440
|
-
flex:
|
1830
|
+
flex: "auto",
|
1441
1831
|
startIcon: action.icon,
|
1442
1832
|
disabled: action.disabled,
|
1443
1833
|
onClick: handleClick(action),
|
1444
1834
|
justifyContent: "center",
|
1445
1835
|
variant: action.variant || "default",
|
1836
|
+
paddingTop: "7px",
|
1837
|
+
paddingBottom: "7px",
|
1446
1838
|
children: action.label
|
1447
1839
|
}
|
1448
1840
|
),
|
@@ -1450,7 +1842,7 @@ const DocumentActionButton = (action) => {
|
|
1450
1842
|
DocumentActionConfirmDialog,
|
1451
1843
|
{
|
1452
1844
|
...action.dialog,
|
1453
|
-
variant: action.variant,
|
1845
|
+
variant: action.dialog?.variant ?? action.variant,
|
1454
1846
|
isOpen: dialogId === action.id,
|
1455
1847
|
onClose: handleClose
|
1456
1848
|
}
|
@@ -1507,9 +1899,9 @@ const DocumentActionsMenu = ({
|
|
1507
1899
|
disabled: isDisabled,
|
1508
1900
|
size: "S",
|
1509
1901
|
endIcon: null,
|
1510
|
-
paddingTop: "
|
1511
|
-
paddingLeft: "
|
1512
|
-
paddingRight: "
|
1902
|
+
paddingTop: "4px",
|
1903
|
+
paddingLeft: "7px",
|
1904
|
+
paddingRight: "7px",
|
1513
1905
|
variant,
|
1514
1906
|
children: [
|
1515
1907
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
@@ -1520,7 +1912,7 @@ const DocumentActionsMenu = ({
|
|
1520
1912
|
]
|
1521
1913
|
}
|
1522
1914
|
),
|
1523
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, {
|
1915
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1524
1916
|
actions2.map((action) => {
|
1525
1917
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
1526
1918
|
designSystem.Menu.Item,
|
@@ -1529,10 +1921,25 @@ const DocumentActionsMenu = ({
|
|
1529
1921
|
onSelect: handleClick(action),
|
1530
1922
|
display: "block",
|
1531
1923
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1532
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1924
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1925
|
+
designSystem.Flex,
|
1926
|
+
{
|
1927
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1928
|
+
gap: 2,
|
1929
|
+
tag: "span",
|
1930
|
+
children: [
|
1931
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1932
|
+
designSystem.Flex,
|
1933
|
+
{
|
1934
|
+
tag: "span",
|
1935
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1936
|
+
children: action.icon
|
1937
|
+
}
|
1938
|
+
),
|
1939
|
+
action.label
|
1940
|
+
]
|
1941
|
+
}
|
1942
|
+
),
|
1536
1943
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1537
1944
|
designSystem.Flex,
|
1538
1945
|
{
|
@@ -1591,6 +1998,18 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1591
1998
|
return "primary600";
|
1592
1999
|
}
|
1593
2000
|
};
|
2001
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
2002
|
+
switch (variant) {
|
2003
|
+
case "danger":
|
2004
|
+
return "danger600";
|
2005
|
+
case "secondary":
|
2006
|
+
return "neutral500";
|
2007
|
+
case "success":
|
2008
|
+
return "success600";
|
2009
|
+
default:
|
2010
|
+
return "primary600";
|
2011
|
+
}
|
2012
|
+
};
|
1594
2013
|
const DocumentActionConfirmDialog = ({
|
1595
2014
|
onClose,
|
1596
2015
|
onCancel,
|
@@ -1617,11 +2036,11 @@ const DocumentActionConfirmDialog = ({
|
|
1617
2036
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1618
2037
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1619
2038
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1620
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
2039
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
1621
2040
|
id: "app.components.Button.cancel",
|
1622
2041
|
defaultMessage: "Cancel"
|
1623
2042
|
}) }) }),
|
1624
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
2043
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
1625
2044
|
id: "app.components.Button.confirm",
|
1626
2045
|
defaultMessage: "Confirm"
|
1627
2046
|
}) })
|
@@ -1660,13 +2079,17 @@ const PublishAction$1 = ({
|
|
1660
2079
|
const navigate = reactRouterDom.useNavigate();
|
1661
2080
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1662
2081
|
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2082
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
1663
2083
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
1664
2084
|
const { formatMessage } = reactIntl.useIntl();
|
1665
|
-
const { canPublish
|
1666
|
-
"PublishAction",
|
1667
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1668
|
-
);
|
2085
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1669
2086
|
const { publish } = useDocumentActions();
|
2087
|
+
const [
|
2088
|
+
countDraftRelations,
|
2089
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2090
|
+
] = useLazyGetDraftRelationCountQuery();
|
2091
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2092
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1670
2093
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1671
2094
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1672
2095
|
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1675,10 +2098,103 @@ const PublishAction$1 = ({
|
|
1675
2098
|
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1676
2099
|
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1677
2100
|
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1681
|
-
|
2101
|
+
React__namespace.useEffect(() => {
|
2102
|
+
if (isErrorDraftRelations) {
|
2103
|
+
toggleNotification({
|
2104
|
+
type: "danger",
|
2105
|
+
message: formatMessage({
|
2106
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2107
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2108
|
+
})
|
2109
|
+
});
|
2110
|
+
}
|
2111
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2112
|
+
React__namespace.useEffect(() => {
|
2113
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2114
|
+
const extractDraftRelations = (data) => {
|
2115
|
+
const relations = data.connect || [];
|
2116
|
+
relations.forEach((relation) => {
|
2117
|
+
if (relation.status === "draft") {
|
2118
|
+
localDraftRelations.add(relation.id);
|
2119
|
+
}
|
2120
|
+
});
|
2121
|
+
};
|
2122
|
+
const traverseAndExtract = (data) => {
|
2123
|
+
Object.entries(data).forEach(([key, value]) => {
|
2124
|
+
if (key === "connect" && Array.isArray(value)) {
|
2125
|
+
extractDraftRelations({ connect: value });
|
2126
|
+
} else if (typeof value === "object" && value !== null) {
|
2127
|
+
traverseAndExtract(value);
|
2128
|
+
}
|
2129
|
+
});
|
2130
|
+
};
|
2131
|
+
if (!documentId || modified) {
|
2132
|
+
traverseAndExtract(formValues);
|
2133
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2134
|
+
}
|
2135
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2136
|
+
React__namespace.useEffect(() => {
|
2137
|
+
if (!document || !document.documentId || isListView) {
|
2138
|
+
return;
|
2139
|
+
}
|
2140
|
+
const fetchDraftRelationsCount = async () => {
|
2141
|
+
const { data, error } = await countDraftRelations({
|
2142
|
+
collectionType,
|
2143
|
+
model,
|
2144
|
+
documentId,
|
2145
|
+
params
|
2146
|
+
});
|
2147
|
+
if (error) {
|
2148
|
+
throw error;
|
2149
|
+
}
|
2150
|
+
if (data) {
|
2151
|
+
setServerCountOfDraftRelations(data.data);
|
2152
|
+
}
|
2153
|
+
};
|
2154
|
+
fetchDraftRelationsCount();
|
2155
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2156
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2157
|
+
if (!schema?.options?.draftAndPublish) {
|
2158
|
+
return null;
|
2159
|
+
}
|
2160
|
+
const performPublish = async () => {
|
2161
|
+
setSubmitting(true);
|
2162
|
+
try {
|
2163
|
+
const { errors } = await validate();
|
2164
|
+
if (errors) {
|
2165
|
+
toggleNotification({
|
2166
|
+
type: "danger",
|
2167
|
+
message: formatMessage({
|
2168
|
+
id: "content-manager.validation.error",
|
2169
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2170
|
+
})
|
2171
|
+
});
|
2172
|
+
return;
|
2173
|
+
}
|
2174
|
+
const res = await publish(
|
2175
|
+
{
|
2176
|
+
collectionType,
|
2177
|
+
model,
|
2178
|
+
documentId,
|
2179
|
+
params
|
2180
|
+
},
|
2181
|
+
formValues
|
2182
|
+
);
|
2183
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2184
|
+
navigate({
|
2185
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2186
|
+
search: rawQuery
|
2187
|
+
});
|
2188
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2189
|
+
setErrors(formatValidationErrors(res.error));
|
2190
|
+
}
|
2191
|
+
} finally {
|
2192
|
+
setSubmitting(false);
|
2193
|
+
}
|
2194
|
+
};
|
2195
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2196
|
+
const enableDraftRelationsCount = false;
|
2197
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
1682
2198
|
return {
|
1683
2199
|
/**
|
1684
2200
|
* Disabled when:
|
@@ -1688,49 +2204,36 @@ const PublishAction$1 = ({
|
|
1688
2204
|
* - the document is already published & not modified
|
1689
2205
|
* - the document is being created & not modified
|
1690
2206
|
* - the user doesn't have the permission to publish
|
1691
|
-
* - the user doesn't have the permission to create a new document
|
1692
|
-
* - the user doesn't have the permission to update the document
|
1693
2207
|
*/
|
1694
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
2208
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1695
2209
|
label: formatMessage({
|
1696
2210
|
id: "app.utils.publish",
|
1697
2211
|
defaultMessage: "Publish"
|
1698
2212
|
}),
|
1699
2213
|
onClick: async () => {
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
documentId,
|
1718
|
-
params
|
1719
|
-
},
|
1720
|
-
formValues
|
1721
|
-
);
|
1722
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1723
|
-
navigate({
|
1724
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1725
|
-
search: rawQuery
|
1726
|
-
});
|
1727
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1728
|
-
setErrors(formatValidationErrors(res.error));
|
2214
|
+
await performPublish();
|
2215
|
+
},
|
2216
|
+
dialog: hasDraftRelations ? {
|
2217
|
+
type: "dialog",
|
2218
|
+
variant: "danger",
|
2219
|
+
footer: null,
|
2220
|
+
title: formatMessage({
|
2221
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2222
|
+
defaultMessage: "Confirmation"
|
2223
|
+
}),
|
2224
|
+
content: formatMessage(
|
2225
|
+
{
|
2226
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2227
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2228
|
+
},
|
2229
|
+
{
|
2230
|
+
count: totalDraftRelations
|
1729
2231
|
}
|
1730
|
-
|
1731
|
-
|
2232
|
+
),
|
2233
|
+
onConfirm: async () => {
|
2234
|
+
await performPublish();
|
1732
2235
|
}
|
1733
|
-
}
|
2236
|
+
} : void 0
|
1734
2237
|
};
|
1735
2238
|
};
|
1736
2239
|
PublishAction$1.type = "publish";
|
@@ -1746,10 +2249,6 @@ const UpdateAction = ({
|
|
1746
2249
|
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
1747
2250
|
const isCloning = cloneMatch !== null;
|
1748
2251
|
const { formatMessage } = reactIntl.useIntl();
|
1749
|
-
const { canCreate, canUpdate } = useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1750
|
-
canCreate: canCreate2,
|
1751
|
-
canUpdate: canUpdate2
|
1752
|
-
}));
|
1753
2252
|
const { create, update, clone } = useDocumentActions();
|
1754
2253
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1755
2254
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
@@ -1766,10 +2265,8 @@ const UpdateAction = ({
|
|
1766
2265
|
* - the form is submitting
|
1767
2266
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1768
2267
|
* - the active tab is the published tab
|
1769
|
-
* - the user doesn't have the permission to create a new document
|
1770
|
-
* - the user doesn't have the permission to update the document
|
1771
2268
|
*/
|
1772
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
2269
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1773
2270
|
label: formatMessage({
|
1774
2271
|
id: "content-manager.containers.Edit.save",
|
1775
2272
|
defaultMessage: "Save"
|
@@ -1777,16 +2274,18 @@ const UpdateAction = ({
|
|
1777
2274
|
onClick: async () => {
|
1778
2275
|
setSubmitting(true);
|
1779
2276
|
try {
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
2277
|
+
if (activeTab !== "draft") {
|
2278
|
+
const { errors } = await validate();
|
2279
|
+
if (errors) {
|
2280
|
+
toggleNotification({
|
2281
|
+
type: "danger",
|
2282
|
+
message: formatMessage({
|
2283
|
+
id: "content-manager.validation.error",
|
2284
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2285
|
+
})
|
2286
|
+
});
|
2287
|
+
return;
|
2288
|
+
}
|
1790
2289
|
}
|
1791
2290
|
if (isCloning) {
|
1792
2291
|
const res = await clone(
|
@@ -1798,10 +2297,13 @@ const UpdateAction = ({
|
|
1798
2297
|
document
|
1799
2298
|
);
|
1800
2299
|
if ("data" in res) {
|
1801
|
-
navigate(
|
1802
|
-
|
1803
|
-
|
1804
|
-
|
2300
|
+
navigate(
|
2301
|
+
{
|
2302
|
+
pathname: `../${res.data.documentId}`,
|
2303
|
+
search: rawQuery
|
2304
|
+
},
|
2305
|
+
{ relative: "path" }
|
2306
|
+
);
|
1805
2307
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1806
2308
|
setErrors(formatValidationErrors(res.error));
|
1807
2309
|
}
|
@@ -1829,10 +2331,13 @@ const UpdateAction = ({
|
|
1829
2331
|
document
|
1830
2332
|
);
|
1831
2333
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1832
|
-
navigate(
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
2334
|
+
navigate(
|
2335
|
+
{
|
2336
|
+
pathname: `../${res.data.documentId}`,
|
2337
|
+
search: rawQuery
|
2338
|
+
},
|
2339
|
+
{ replace: true, relative: "path" }
|
2340
|
+
);
|
1836
2341
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1837
2342
|
setErrors(formatValidationErrors(res.error));
|
1838
2343
|
}
|
@@ -1876,7 +2381,7 @@ const UnpublishAction$1 = ({
|
|
1876
2381
|
id: "app.utils.unpublish",
|
1877
2382
|
defaultMessage: "Unpublish"
|
1878
2383
|
}),
|
1879
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2384
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1880
2385
|
onClick: async () => {
|
1881
2386
|
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1882
2387
|
if (!documentId) {
|
@@ -1988,7 +2493,7 @@ const DiscardAction = ({
|
|
1988
2493
|
id: "content-manager.actions.discard.label",
|
1989
2494
|
defaultMessage: "Discard changes"
|
1990
2495
|
}),
|
1991
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
2496
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
1992
2497
|
position: ["panel", "table-row"],
|
1993
2498
|
variant: "danger",
|
1994
2499
|
dialog: {
|
@@ -2016,11 +2521,6 @@ const DiscardAction = ({
|
|
2016
2521
|
};
|
2017
2522
|
};
|
2018
2523
|
DiscardAction.type = "discard";
|
2019
|
-
const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
|
2020
|
-
path {
|
2021
|
-
fill: currentColor;
|
2022
|
-
}
|
2023
|
-
`;
|
2024
2524
|
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2025
2525
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2026
2526
|
const RelativeTime = React__namespace.forwardRef(
|
@@ -2068,7 +2568,7 @@ const getDisplayName = ({
|
|
2068
2568
|
};
|
2069
2569
|
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2070
2570
|
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2071
|
-
const statusVariant = status === "draft" ? "
|
2571
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2072
2572
|
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) }) });
|
2073
2573
|
};
|
2074
2574
|
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
@@ -2078,23 +2578,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2078
2578
|
id: "content-manager.containers.edit.title.new",
|
2079
2579
|
defaultMessage: "Create an entry"
|
2080
2580
|
}) : documentTitle;
|
2081
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2581
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2082
2582
|
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
2083
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
2084
|
-
designSystem.
|
2085
|
-
{
|
2086
|
-
|
2087
|
-
|
2088
|
-
paddingTop: 1,
|
2089
|
-
gap: "80px",
|
2090
|
-
alignItems: "flex-start",
|
2091
|
-
children: [
|
2092
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2093
|
-
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2094
|
-
]
|
2095
|
-
}
|
2096
|
-
),
|
2097
|
-
status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2583
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2584
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2585
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2586
|
+
] }),
|
2587
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2098
2588
|
] });
|
2099
2589
|
};
|
2100
2590
|
const HeaderToolbar = () => {
|
@@ -2261,25 +2751,77 @@ const Information = ({ activeTab }) => {
|
|
2261
2751
|
);
|
2262
2752
|
};
|
2263
2753
|
const HeaderActions = ({ actions: actions2 }) => {
|
2264
|
-
|
2265
|
-
|
2754
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2755
|
+
const handleClick = (action) => async (e) => {
|
2756
|
+
if (!("options" in action)) {
|
2757
|
+
const { onClick = () => false, dialog, id } = action;
|
2758
|
+
const muteDialog = await onClick(e);
|
2759
|
+
if (dialog && !muteDialog) {
|
2760
|
+
e.preventDefault();
|
2761
|
+
setDialogId(id);
|
2762
|
+
}
|
2763
|
+
}
|
2764
|
+
};
|
2765
|
+
const handleClose = () => {
|
2766
|
+
setDialogId(null);
|
2767
|
+
};
|
2768
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2769
|
+
if (action.options) {
|
2266
2770
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
2267
2771
|
designSystem.SingleSelect,
|
2268
2772
|
{
|
2269
2773
|
size: "S",
|
2270
|
-
disabled: action.disabled,
|
2271
|
-
"aria-label": action.label,
|
2272
2774
|
onChange: action.onSelect,
|
2273
|
-
|
2775
|
+
"aria-label": action.label,
|
2776
|
+
...action,
|
2274
2777
|
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2275
2778
|
},
|
2276
2779
|
action.id
|
2277
2780
|
);
|
2278
2781
|
} else {
|
2279
|
-
|
2782
|
+
if (action.type === "icon") {
|
2783
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2784
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2785
|
+
designSystem.IconButton,
|
2786
|
+
{
|
2787
|
+
disabled: action.disabled,
|
2788
|
+
label: action.label,
|
2789
|
+
size: "S",
|
2790
|
+
onClick: handleClick(action),
|
2791
|
+
children: action.icon
|
2792
|
+
}
|
2793
|
+
),
|
2794
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2795
|
+
HeaderActionDialog,
|
2796
|
+
{
|
2797
|
+
...action.dialog,
|
2798
|
+
isOpen: dialogId === action.id,
|
2799
|
+
onClose: handleClose
|
2800
|
+
}
|
2801
|
+
) : null
|
2802
|
+
] }, action.id);
|
2803
|
+
}
|
2280
2804
|
}
|
2281
2805
|
}) });
|
2282
2806
|
};
|
2807
|
+
const HeaderActionDialog = ({
|
2808
|
+
onClose,
|
2809
|
+
onCancel,
|
2810
|
+
title,
|
2811
|
+
content: Content,
|
2812
|
+
isOpen
|
2813
|
+
}) => {
|
2814
|
+
const handleClose = async () => {
|
2815
|
+
if (onCancel) {
|
2816
|
+
await onCancel();
|
2817
|
+
}
|
2818
|
+
onClose();
|
2819
|
+
};
|
2820
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2821
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2822
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2823
|
+
] }) });
|
2824
|
+
};
|
2283
2825
|
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2284
2826
|
const navigate = reactRouterDom.useNavigate();
|
2285
2827
|
const { formatMessage } = reactIntl.useIntl();
|
@@ -2320,12 +2862,16 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2320
2862
|
const { delete: deleteAction } = useDocumentActions();
|
2321
2863
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2322
2864
|
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2865
|
+
const isLocalized = document?.locale != null;
|
2323
2866
|
return {
|
2324
2867
|
disabled: !canDelete || !document,
|
2325
|
-
label: formatMessage(
|
2326
|
-
|
2327
|
-
|
2328
|
-
|
2868
|
+
label: formatMessage(
|
2869
|
+
{
|
2870
|
+
id: "content-manager.actions.delete.label",
|
2871
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2872
|
+
},
|
2873
|
+
{ isLocalized }
|
2874
|
+
),
|
2329
2875
|
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2330
2876
|
dialog: {
|
2331
2877
|
type: "dialog",
|
@@ -2361,423 +2907,121 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2361
2907
|
const res = await deleteAction({
|
2362
2908
|
documentId,
|
2363
2909
|
model,
|
2364
|
-
collectionType,
|
2365
|
-
params: {
|
2366
|
-
locale: "*"
|
2367
|
-
}
|
2368
|
-
});
|
2369
|
-
if (!("error" in res)) {
|
2370
|
-
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2371
|
-
}
|
2372
|
-
} finally {
|
2373
|
-
if (!listViewPathMatch) {
|
2374
|
-
setSubmitting(false);
|
2375
|
-
}
|
2376
|
-
}
|
2377
|
-
}
|
2378
|
-
},
|
2379
|
-
variant: "danger",
|
2380
|
-
position: ["header", "table-row"]
|
2381
|
-
};
|
2382
|
-
};
|
2383
|
-
DeleteAction$1.type = "delete";
|
2384
|
-
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2385
|
-
const Panels = () => {
|
2386
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2387
|
-
const [
|
2388
|
-
{
|
2389
|
-
query: { status }
|
2390
|
-
}
|
2391
|
-
] = strapiAdmin.useQueryParams({
|
2392
|
-
status: "draft"
|
2393
|
-
});
|
2394
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2395
|
-
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2396
|
-
const props = {
|
2397
|
-
activeTab: status,
|
2398
|
-
model,
|
2399
|
-
documentId: id,
|
2400
|
-
document: isCloning ? void 0 : document,
|
2401
|
-
meta: isCloning ? void 0 : meta,
|
2402
|
-
collectionType
|
2403
|
-
};
|
2404
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2405
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2406
|
-
{
|
2407
|
-
props,
|
2408
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2409
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2410
|
-
}
|
2411
|
-
) });
|
2412
|
-
};
|
2413
|
-
const ActionsPanel = () => {
|
2414
|
-
const { formatMessage } = reactIntl.useIntl();
|
2415
|
-
return {
|
2416
|
-
title: formatMessage({
|
2417
|
-
id: "content-manager.containers.edit.panels.default.title",
|
2418
|
-
defaultMessage: "Document"
|
2419
|
-
}),
|
2420
|
-
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2421
|
-
};
|
2422
|
-
};
|
2423
|
-
ActionsPanel.type = "actions";
|
2424
|
-
const ActionsPanelContent = () => {
|
2425
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2426
|
-
const [
|
2427
|
-
{
|
2428
|
-
query: { status = "draft" }
|
2429
|
-
}
|
2430
|
-
] = strapiAdmin.useQueryParams();
|
2431
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2432
|
-
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2433
|
-
const props = {
|
2434
|
-
activeTab: status,
|
2435
|
-
model,
|
2436
|
-
documentId: id,
|
2437
|
-
document: isCloning ? void 0 : document,
|
2438
|
-
meta: isCloning ? void 0 : meta,
|
2439
|
-
collectionType
|
2440
|
-
};
|
2441
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2442
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2443
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2444
|
-
{
|
2445
|
-
props,
|
2446
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2447
|
-
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
2448
|
-
}
|
2449
|
-
),
|
2450
|
-
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2451
|
-
] });
|
2452
|
-
};
|
2453
|
-
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
2454
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
2455
|
-
designSystem.Flex,
|
2456
|
-
{
|
2457
|
-
ref,
|
2458
|
-
tag: "aside",
|
2459
|
-
"aria-labelledby": "additional-information",
|
2460
|
-
background: "neutral0",
|
2461
|
-
borderColor: "neutral150",
|
2462
|
-
hasRadius: true,
|
2463
|
-
paddingBottom: 4,
|
2464
|
-
paddingLeft: 4,
|
2465
|
-
paddingRight: 4,
|
2466
|
-
paddingTop: 4,
|
2467
|
-
shadow: "tableShadow",
|
2468
|
-
gap: 3,
|
2469
|
-
direction: "column",
|
2470
|
-
justifyContent: "stretch",
|
2471
|
-
alignItems: "flex-start",
|
2472
|
-
children: [
|
2473
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2474
|
-
children
|
2475
|
-
]
|
2476
|
-
}
|
2477
|
-
);
|
2478
|
-
});
|
2479
|
-
const HOOKS = {
|
2480
|
-
/**
|
2481
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2482
|
-
* @constant
|
2483
|
-
* @type {string}
|
2484
|
-
*/
|
2485
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2486
|
-
/**
|
2487
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2488
|
-
* @constant
|
2489
|
-
* @type {string}
|
2490
|
-
*/
|
2491
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2492
|
-
/**
|
2493
|
-
* Hook that allows to mutate the CM's edit view layout
|
2494
|
-
* @constant
|
2495
|
-
* @type {string}
|
2496
|
-
*/
|
2497
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2498
|
-
/**
|
2499
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2500
|
-
* @constant
|
2501
|
-
* @type {string}
|
2502
|
-
*/
|
2503
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2504
|
-
};
|
2505
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2506
|
-
endpoints: (builder) => ({
|
2507
|
-
getContentTypeConfiguration: builder.query({
|
2508
|
-
query: (uid) => ({
|
2509
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2510
|
-
method: "GET"
|
2511
|
-
}),
|
2512
|
-
transformResponse: (response) => response.data,
|
2513
|
-
providesTags: (_result, _error, uid) => [
|
2514
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2515
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
2516
|
-
]
|
2517
|
-
}),
|
2518
|
-
getAllContentTypeSettings: builder.query({
|
2519
|
-
query: () => "/content-manager/content-types-settings",
|
2520
|
-
transformResponse: (response) => response.data,
|
2521
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2522
|
-
}),
|
2523
|
-
updateContentTypeConfiguration: builder.mutation({
|
2524
|
-
query: ({ uid, ...body }) => ({
|
2525
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2526
|
-
method: "PUT",
|
2527
|
-
data: body
|
2528
|
-
}),
|
2529
|
-
transformResponse: (response) => response.data,
|
2530
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
2531
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
2532
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
2533
|
-
// Is this necessary?
|
2534
|
-
{ type: "InitialData" }
|
2535
|
-
]
|
2536
|
-
})
|
2537
|
-
})
|
2538
|
-
});
|
2539
|
-
const {
|
2540
|
-
useGetContentTypeConfigurationQuery,
|
2541
|
-
useGetAllContentTypeSettingsQuery,
|
2542
|
-
useUpdateContentTypeConfigurationMutation
|
2543
|
-
} = contentTypesApi;
|
2544
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
2545
|
-
const { type } = attribute;
|
2546
|
-
if (type === "relation") {
|
2547
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
2548
|
-
}
|
2549
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2550
|
-
};
|
2551
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2552
|
-
if (!mainFieldName) {
|
2553
|
-
return void 0;
|
2554
|
-
}
|
2555
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2556
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2557
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2558
|
-
);
|
2559
|
-
return {
|
2560
|
-
name: mainFieldName,
|
2561
|
-
type: mainFieldType ?? "string"
|
2562
|
-
};
|
2563
|
-
};
|
2564
|
-
const DEFAULT_SETTINGS = {
|
2565
|
-
bulkable: false,
|
2566
|
-
filterable: false,
|
2567
|
-
searchable: false,
|
2568
|
-
pagination: false,
|
2569
|
-
defaultSortBy: "",
|
2570
|
-
defaultSortOrder: "asc",
|
2571
|
-
mainField: "id",
|
2572
|
-
pageSize: 10
|
2573
|
-
};
|
2574
|
-
const useDocumentLayout = (model) => {
|
2575
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2576
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
2577
|
-
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2578
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
2579
|
-
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
2580
|
-
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2581
|
-
const {
|
2582
|
-
data,
|
2583
|
-
isLoading: isLoadingConfigs,
|
2584
|
-
error,
|
2585
|
-
isFetching: isFetchingConfigs
|
2586
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2587
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2588
|
-
React__namespace.useEffect(() => {
|
2589
|
-
if (error) {
|
2590
|
-
toggleNotification({
|
2591
|
-
type: "danger",
|
2592
|
-
message: formatAPIError(error)
|
2593
|
-
});
|
2594
|
-
}
|
2595
|
-
}, [error, formatAPIError, toggleNotification]);
|
2596
|
-
const editLayout = React__namespace.useMemo(
|
2597
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2598
|
-
layout: [],
|
2599
|
-
components: {},
|
2600
|
-
metadatas: {},
|
2601
|
-
options: {},
|
2602
|
-
settings: DEFAULT_SETTINGS
|
2603
|
-
},
|
2604
|
-
[data, isLoading, schemas, schema, components]
|
2605
|
-
);
|
2606
|
-
const listLayout = React__namespace.useMemo(() => {
|
2607
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2608
|
-
layout: [],
|
2609
|
-
metadatas: {},
|
2610
|
-
options: {},
|
2611
|
-
settings: DEFAULT_SETTINGS
|
2612
|
-
};
|
2613
|
-
}, [data, isLoading, schemas, schema, components]);
|
2614
|
-
const { layout: edit } = React__namespace.useMemo(
|
2615
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2616
|
-
layout: editLayout,
|
2617
|
-
query
|
2618
|
-
}),
|
2619
|
-
[editLayout, query, runHookWaterfall]
|
2620
|
-
);
|
2621
|
-
return {
|
2622
|
-
error,
|
2623
|
-
isLoading,
|
2624
|
-
edit,
|
2625
|
-
list: listLayout
|
2626
|
-
};
|
2627
|
-
};
|
2628
|
-
const useDocLayout = () => {
|
2629
|
-
const { model } = useDoc();
|
2630
|
-
return useDocumentLayout(model);
|
2631
|
-
};
|
2632
|
-
const formatEditLayout = (data, {
|
2633
|
-
schemas,
|
2634
|
-
schema,
|
2635
|
-
components
|
2636
|
-
}) => {
|
2637
|
-
let currentPanelIndex = 0;
|
2638
|
-
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2639
|
-
data.contentType.layouts.edit,
|
2640
|
-
schema?.attributes,
|
2641
|
-
data.contentType.metadatas,
|
2642
|
-
{ configurations: data.components, schemas: components },
|
2643
|
-
schemas
|
2644
|
-
).reduce((panels, row) => {
|
2645
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2646
|
-
panels.push([row]);
|
2647
|
-
currentPanelIndex += 2;
|
2648
|
-
} else {
|
2649
|
-
if (!panels[currentPanelIndex]) {
|
2650
|
-
panels.push([]);
|
2651
|
-
}
|
2652
|
-
panels[currentPanelIndex].push(row);
|
2653
|
-
}
|
2654
|
-
return panels;
|
2655
|
-
}, []);
|
2656
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
2657
|
-
(acc, [uid, configuration]) => {
|
2658
|
-
acc[uid] = {
|
2659
|
-
layout: convertEditLayoutToFieldLayouts(
|
2660
|
-
configuration.layouts.edit,
|
2661
|
-
components[uid].attributes,
|
2662
|
-
configuration.metadatas
|
2663
|
-
),
|
2664
|
-
settings: {
|
2665
|
-
...configuration.settings,
|
2666
|
-
icon: components[uid].info.icon,
|
2667
|
-
displayName: components[uid].info.displayName
|
2910
|
+
collectionType,
|
2911
|
+
params: {
|
2912
|
+
locale: "*"
|
2913
|
+
}
|
2914
|
+
});
|
2915
|
+
if (!("error" in res)) {
|
2916
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2917
|
+
}
|
2918
|
+
} finally {
|
2919
|
+
if (!listViewPathMatch) {
|
2920
|
+
setSubmitting(false);
|
2921
|
+
}
|
2668
2922
|
}
|
2669
|
-
}
|
2670
|
-
return acc;
|
2671
|
-
},
|
2672
|
-
{}
|
2673
|
-
);
|
2674
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2675
|
-
(acc, [attribute, metadata]) => {
|
2676
|
-
return {
|
2677
|
-
...acc,
|
2678
|
-
[attribute]: metadata.edit
|
2679
|
-
};
|
2680
|
-
},
|
2681
|
-
{}
|
2682
|
-
);
|
2683
|
-
return {
|
2684
|
-
layout: panelledEditAttributes,
|
2685
|
-
components: componentEditAttributes,
|
2686
|
-
metadatas: editMetadatas,
|
2687
|
-
settings: {
|
2688
|
-
...data.contentType.settings,
|
2689
|
-
displayName: schema?.info.displayName
|
2923
|
+
}
|
2690
2924
|
},
|
2691
|
-
|
2692
|
-
|
2693
|
-
...schema?.pluginOptions,
|
2694
|
-
...data.contentType.options
|
2695
|
-
}
|
2925
|
+
variant: "danger",
|
2926
|
+
position: ["header", "table-row"]
|
2696
2927
|
};
|
2697
2928
|
};
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
2702
|
-
|
2703
|
-
|
2704
|
-
}
|
2705
|
-
|
2706
|
-
|
2707
|
-
|
2708
|
-
|
2709
|
-
|
2710
|
-
|
2711
|
-
|
2712
|
-
|
2713
|
-
|
2714
|
-
|
2715
|
-
|
2716
|
-
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2724
|
-
}
|
2725
|
-
}
|
2726
|
-
);
|
2929
|
+
DeleteAction$1.type = "delete";
|
2930
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2931
|
+
const Panels = () => {
|
2932
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2933
|
+
const [
|
2934
|
+
{
|
2935
|
+
query: { status }
|
2936
|
+
}
|
2937
|
+
] = strapiAdmin.useQueryParams({
|
2938
|
+
status: "draft"
|
2939
|
+
});
|
2940
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2941
|
+
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2942
|
+
const props = {
|
2943
|
+
activeTab: status,
|
2944
|
+
model,
|
2945
|
+
documentId: id,
|
2946
|
+
document: isCloning ? void 0 : document,
|
2947
|
+
meta: isCloning ? void 0 : meta,
|
2948
|
+
collectionType
|
2949
|
+
};
|
2950
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2951
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2952
|
+
{
|
2953
|
+
props,
|
2954
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2955
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2956
|
+
}
|
2957
|
+
) });
|
2727
2958
|
};
|
2728
|
-
const
|
2729
|
-
|
2730
|
-
schema,
|
2731
|
-
components
|
2732
|
-
}) => {
|
2733
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2734
|
-
(acc, [attribute, metadata]) => {
|
2735
|
-
return {
|
2736
|
-
...acc,
|
2737
|
-
[attribute]: metadata.list
|
2738
|
-
};
|
2739
|
-
},
|
2740
|
-
{}
|
2741
|
-
);
|
2742
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
2743
|
-
data.contentType.layouts.list,
|
2744
|
-
schema?.attributes,
|
2745
|
-
listMetadatas,
|
2746
|
-
{ configurations: data.components, schemas: components },
|
2747
|
-
schemas
|
2748
|
-
);
|
2959
|
+
const ActionsPanel = () => {
|
2960
|
+
const { formatMessage } = reactIntl.useIntl();
|
2749
2961
|
return {
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
|
2754
|
-
|
2755
|
-
...schema?.pluginOptions,
|
2756
|
-
...data.contentType.options
|
2757
|
-
}
|
2962
|
+
title: formatMessage({
|
2963
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2964
|
+
defaultMessage: "Entry"
|
2965
|
+
}),
|
2966
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2758
2967
|
};
|
2759
2968
|
};
|
2760
|
-
|
2761
|
-
|
2762
|
-
|
2763
|
-
|
2764
|
-
|
2969
|
+
ActionsPanel.type = "actions";
|
2970
|
+
const ActionsPanelContent = () => {
|
2971
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2972
|
+
const [
|
2973
|
+
{
|
2974
|
+
query: { status = "draft" }
|
2765
2975
|
}
|
2766
|
-
|
2767
|
-
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2976
|
+
] = strapiAdmin.useQueryParams();
|
2977
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2978
|
+
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2979
|
+
const props = {
|
2980
|
+
activeTab: status,
|
2981
|
+
model,
|
2982
|
+
documentId: id,
|
2983
|
+
document: isCloning ? void 0 : document,
|
2984
|
+
meta: isCloning ? void 0 : meta,
|
2985
|
+
collectionType
|
2986
|
+
};
|
2987
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2988
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2989
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2990
|
+
{
|
2991
|
+
props,
|
2992
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2993
|
+
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
2994
|
+
}
|
2995
|
+
),
|
2996
|
+
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
2997
|
+
] });
|
2780
2998
|
};
|
2999
|
+
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
3000
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
3001
|
+
designSystem.Flex,
|
3002
|
+
{
|
3003
|
+
ref,
|
3004
|
+
tag: "aside",
|
3005
|
+
"aria-labelledby": "additional-information",
|
3006
|
+
background: "neutral0",
|
3007
|
+
borderColor: "neutral150",
|
3008
|
+
hasRadius: true,
|
3009
|
+
paddingBottom: 4,
|
3010
|
+
paddingLeft: 4,
|
3011
|
+
paddingRight: 4,
|
3012
|
+
paddingTop: 4,
|
3013
|
+
shadow: "tableShadow",
|
3014
|
+
gap: 3,
|
3015
|
+
direction: "column",
|
3016
|
+
justifyContent: "stretch",
|
3017
|
+
alignItems: "flex-start",
|
3018
|
+
children: [
|
3019
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
3020
|
+
children
|
3021
|
+
]
|
3022
|
+
}
|
3023
|
+
);
|
3024
|
+
});
|
2781
3025
|
const ConfirmBulkActionDialog = ({
|
2782
3026
|
onToggleDialog,
|
2783
3027
|
isOpen = false,
|
@@ -2785,7 +3029,7 @@ const ConfirmBulkActionDialog = ({
|
|
2785
3029
|
endAction
|
2786
3030
|
}) => {
|
2787
3031
|
const { formatMessage } = reactIntl.useIntl();
|
2788
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, {
|
3032
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2789
3033
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
|
2790
3034
|
id: "app.components.ConfirmDialog.title",
|
2791
3035
|
defaultMessage: "Confirmation"
|
@@ -2816,6 +3060,7 @@ const ConfirmDialogPublishAll = ({
|
|
2816
3060
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2817
3061
|
const { model, schema } = useDoc();
|
2818
3062
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3063
|
+
const enableDraftRelationsCount = false;
|
2819
3064
|
const {
|
2820
3065
|
data: countDraftRelations = 0,
|
2821
3066
|
isLoading,
|
@@ -2827,7 +3072,7 @@ const ConfirmDialogPublishAll = ({
|
|
2827
3072
|
locale: query?.plugins?.i18n?.locale
|
2828
3073
|
},
|
2829
3074
|
{
|
2830
|
-
skip:
|
3075
|
+
skip: !enableDraftRelationsCount
|
2831
3076
|
}
|
2832
3077
|
);
|
2833
3078
|
React__namespace.useEffect(() => {
|
@@ -2906,7 +3151,14 @@ const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
|
2906
3151
|
)
|
2907
3152
|
);
|
2908
3153
|
} else {
|
2909
|
-
messages.push(
|
3154
|
+
messages.push(
|
3155
|
+
...formatErrorMessages(
|
3156
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3157
|
+
value,
|
3158
|
+
currentKey,
|
3159
|
+
formatMessage
|
3160
|
+
)
|
3161
|
+
);
|
2910
3162
|
}
|
2911
3163
|
} else {
|
2912
3164
|
messages.push(
|
@@ -3005,7 +3257,7 @@ const SelectedEntriesTableContent = ({
|
|
3005
3257
|
status: row.status
|
3006
3258
|
}
|
3007
3259
|
) }),
|
3008
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3260
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3009
3261
|
designSystem.IconButton,
|
3010
3262
|
{
|
3011
3263
|
tag: reactRouterDom.Link,
|
@@ -3028,9 +3280,10 @@ const SelectedEntriesTableContent = ({
|
|
3028
3280
|
),
|
3029
3281
|
target: "_blank",
|
3030
3282
|
marginLeft: "auto",
|
3031
|
-
|
3283
|
+
variant: "ghost",
|
3284
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3032
3285
|
}
|
3033
|
-
) })
|
3286
|
+
) }) })
|
3034
3287
|
] }, row.id)) })
|
3035
3288
|
] });
|
3036
3289
|
};
|
@@ -3067,7 +3320,13 @@ const SelectedEntriesModalContent = ({
|
|
3067
3320
|
);
|
3068
3321
|
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3069
3322
|
if (data.length > 0 && schema) {
|
3070
|
-
const validate = createYupSchema(
|
3323
|
+
const validate = createYupSchema(
|
3324
|
+
schema.attributes,
|
3325
|
+
components,
|
3326
|
+
// Since this is the "Publish" action, the validation
|
3327
|
+
// schema must enforce the rules for published entities
|
3328
|
+
{ status: "published" }
|
3329
|
+
);
|
3071
3330
|
const validationErrors2 = {};
|
3072
3331
|
const rows2 = data.map((entry) => {
|
3073
3332
|
try {
|
@@ -3417,7 +3676,7 @@ const TableActions = ({ document }) => {
|
|
3417
3676
|
strapiAdmin.DescriptionComponentRenderer,
|
3418
3677
|
{
|
3419
3678
|
props,
|
3420
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3679
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3421
3680
|
children: (actions2) => {
|
3422
3681
|
const tableRowActions = actions2.filter((action) => {
|
3423
3682
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3528,7 +3787,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3528
3787
|
}),
|
3529
3788
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3530
3789
|
footer: ({ onClose }) => {
|
3531
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3790
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3532
3791
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3533
3792
|
id: "cancel",
|
3534
3793
|
defaultMessage: "Cancel"
|
@@ -3569,8 +3828,7 @@ class ContentManagerPlugin {
|
|
3569
3828
|
documentActions = [
|
3570
3829
|
...DEFAULT_ACTIONS,
|
3571
3830
|
...DEFAULT_TABLE_ROW_ACTIONS,
|
3572
|
-
...DEFAULT_HEADER_ACTIONS
|
3573
|
-
HistoryAction
|
3831
|
+
...DEFAULT_HEADER_ACTIONS
|
3574
3832
|
];
|
3575
3833
|
editViewSidePanels = [ActionsPanel];
|
3576
3834
|
headerActions = [];
|
@@ -3659,6 +3917,52 @@ const getPrintableType = (value) => {
|
|
3659
3917
|
}
|
3660
3918
|
return nativeType;
|
3661
3919
|
};
|
3920
|
+
const HistoryAction = ({ model, document }) => {
|
3921
|
+
const { formatMessage } = reactIntl.useIntl();
|
3922
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3923
|
+
const navigate = reactRouterDom.useNavigate();
|
3924
|
+
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
3925
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3926
|
+
return null;
|
3927
|
+
}
|
3928
|
+
return {
|
3929
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
3930
|
+
label: formatMessage({
|
3931
|
+
id: "content-manager.history.document-action",
|
3932
|
+
defaultMessage: "Content History"
|
3933
|
+
}),
|
3934
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3935
|
+
disabled: (
|
3936
|
+
/**
|
3937
|
+
* The user is creating a new document.
|
3938
|
+
* It hasn't been saved yet, so there's no history to go to
|
3939
|
+
*/
|
3940
|
+
!document || /**
|
3941
|
+
* The document has been created but the current dimension has never been saved.
|
3942
|
+
* For example, the user is creating a new locale in an existing document,
|
3943
|
+
* so there's no history for the document in that locale
|
3944
|
+
*/
|
3945
|
+
!document.id || /**
|
3946
|
+
* History is only available for content types created by the user.
|
3947
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3948
|
+
* which start with `admin::` or `plugin::`
|
3949
|
+
*/
|
3950
|
+
!model.startsWith("api::")
|
3951
|
+
),
|
3952
|
+
position: "header"
|
3953
|
+
};
|
3954
|
+
};
|
3955
|
+
HistoryAction.type = "history";
|
3956
|
+
const historyAdmin = {
|
3957
|
+
bootstrap(app) {
|
3958
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3959
|
+
addDocumentAction((actions2) => {
|
3960
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3961
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3962
|
+
return actions2;
|
3963
|
+
});
|
3964
|
+
}
|
3965
|
+
};
|
3662
3966
|
const initialState = {
|
3663
3967
|
collectionTypeLinks: [],
|
3664
3968
|
components: [],
|
@@ -3709,15 +4013,29 @@ const index = {
|
|
3709
4013
|
defaultMessage: "Content Manager"
|
3710
4014
|
},
|
3711
4015
|
permissions: [],
|
3712
|
-
Component: () => Promise.resolve().then(() => require("./layout--iHdZzRk.js")).then((mod) => ({ default: mod.Layout })),
|
3713
4016
|
position: 1
|
3714
4017
|
});
|
4018
|
+
app.router.addRoute({
|
4019
|
+
path: "content-manager/*",
|
4020
|
+
lazy: async () => {
|
4021
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-UNWstw_s.js"));
|
4022
|
+
return {
|
4023
|
+
Component: Layout
|
4024
|
+
};
|
4025
|
+
},
|
4026
|
+
children: routes
|
4027
|
+
});
|
3715
4028
|
app.registerPlugin(cm.config);
|
3716
4029
|
},
|
4030
|
+
bootstrap(app) {
|
4031
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
4032
|
+
historyAdmin.bootstrap(app);
|
4033
|
+
}
|
4034
|
+
},
|
3717
4035
|
async registerTrads({ locales }) {
|
3718
4036
|
const importedTrads = await Promise.all(
|
3719
4037
|
locales.map((locale) => {
|
3720
|
-
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-
|
4038
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-BlhnxQfj.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
|
3721
4039
|
return {
|
3722
4040
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3723
4041
|
locale
|
@@ -3735,6 +4053,7 @@ const index = {
|
|
3735
4053
|
};
|
3736
4054
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
3737
4055
|
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4056
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3738
4057
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3739
4058
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3740
4059
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3761,8 +4080,8 @@ exports.getDisplayName = getDisplayName;
|
|
3761
4080
|
exports.getMainField = getMainField;
|
3762
4081
|
exports.getTranslation = getTranslation;
|
3763
4082
|
exports.index = index;
|
3764
|
-
exports.routes = routes;
|
3765
4083
|
exports.setInitialData = setInitialData;
|
4084
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3766
4085
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3767
4086
|
exports.useDoc = useDoc;
|
3768
4087
|
exports.useDocLayout = useDocLayout;
|
@@ -3775,4 +4094,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
|
3775
4094
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3776
4095
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
3777
4096
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3778
|
-
//# sourceMappingURL=index-
|
4097
|
+
//# sourceMappingURL=index-ovJRE1FM.js.map
|