@strapi/content-manager 0.0.0-experimental.779667bd163026468f566293decf331a0246fff9 → 0.0.0-experimental.78b47df46708173ab4833373f694257729db4b9e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{ComponentConfigurationPage-B1bIXVuX.mjs → ComponentConfigurationPage-7-qB29e7.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-B1bIXVuX.mjs.map → ComponentConfigurationPage-7-qB29e7.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-Bqgx7Mes.js → ComponentConfigurationPage-DP7AC0UU.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-Bqgx7Mes.js.map → ComponentConfigurationPage-DP7AC0UU.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-ZO0vOO8q.mjs → EditConfigurationPage-CI4XoymK.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-ZO0vOO8q.mjs.map → EditConfigurationPage-CI4XoymK.mjs.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-BFEwvdMW.js → EditConfigurationPage-DITVliEI.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-BFEwvdMW.js.map → EditConfigurationPage-DITVliEI.js.map} +1 -1
- package/dist/_chunks/{EditViewPage-DA95Ha6J.js → EditViewPage-CUS2EAhB.js} +24 -9
- package/dist/_chunks/EditViewPage-CUS2EAhB.js.map +1 -0
- package/dist/_chunks/{EditViewPage-DlLEyUL6.mjs → EditViewPage-Dzpno8xI.mjs} +24 -9
- package/dist/_chunks/EditViewPage-Dzpno8xI.mjs.map +1 -0
- package/dist/_chunks/{Field-Dq7bDnuh.mjs → Field-B_jG_EV9.mjs} +139 -99
- package/dist/_chunks/Field-B_jG_EV9.mjs.map +1 -0
- package/dist/_chunks/{Field-CnK8dO8N.js → Field-CtUU1Fg8.js} +141 -101
- package/dist/_chunks/Field-CtUU1Fg8.js.map +1 -0
- package/dist/_chunks/{Form-B_JE0dbz.mjs → Form-BXHao2mZ.mjs} +35 -16
- package/dist/_chunks/Form-BXHao2mZ.mjs.map +1 -0
- package/dist/_chunks/{Form-BpiR4piS.js → Form-DTqO0ymI.js} +35 -16
- package/dist/_chunks/Form-DTqO0ymI.js.map +1 -0
- package/dist/_chunks/{History-CBNGU7a-.mjs → History-2Ah2CQ4T.mjs} +21 -11
- package/dist/_chunks/History-2Ah2CQ4T.mjs.map +1 -0
- package/dist/_chunks/{History-DdIstl8b.js → History-C_uSGzO5.js} +21 -11
- package/dist/_chunks/History-C_uSGzO5.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-5dr4qpue.mjs → ListConfigurationPage-BjSJlaoC.mjs} +14 -4
- package/dist/_chunks/ListConfigurationPage-BjSJlaoC.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DkKRparB.js → ListConfigurationPage-nyuP7OSy.js} +14 -4
- package/dist/_chunks/ListConfigurationPage-nyuP7OSy.js.map +1 -0
- package/dist/_chunks/{ListViewPage-DecLrYV6.mjs → ListViewPage-B75x3nz2.mjs} +47 -38
- package/dist/_chunks/ListViewPage-B75x3nz2.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-wE0lXqoD.js → ListViewPage-DHgHD8Xg.js} +49 -40
- package/dist/_chunks/ListViewPage-DHgHD8Xg.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-DEKR6tf9.js → NoContentTypePage-CDUKdZ7d.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-DEKR6tf9.js.map → NoContentTypePage-CDUKdZ7d.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-CiIcfYsd.mjs → NoContentTypePage-DUacQSyF.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-CiIcfYsd.mjs.map → NoContentTypePage-DUacQSyF.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CM5UD8ee.mjs → NoPermissionsPage-SFllMekk.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CM5UD8ee.mjs.map → NoPermissionsPage-SFllMekk.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-DmNfF2Bb.js → NoPermissionsPage-zwIZydDI.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-DmNfF2Bb.js.map → NoPermissionsPage-zwIZydDI.js.map} +1 -1
- package/dist/_chunks/{Relations-Dqz0C1fz.mjs → Relations-D2NRW8fC.mjs} +14 -10
- package/dist/_chunks/Relations-D2NRW8fC.mjs.map +1 -0
- package/dist/_chunks/{Relations-L0xYRoSQ.js → Relations-NFLaRNPr.js} +14 -10
- package/dist/_chunks/Relations-NFLaRNPr.js.map +1 -0
- package/dist/_chunks/{en-uOUIxfcQ.js → en-BlhnxQfj.js} +7 -6
- package/dist/_chunks/{en-uOUIxfcQ.js.map → en-BlhnxQfj.js.map} +1 -1
- package/dist/_chunks/{en-BrCTWlZv.mjs → en-C8YBvRrK.mjs} +7 -6
- package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-C8YBvRrK.mjs.map} +1 -1
- package/dist/_chunks/{index-BSn97i8U.mjs → index-C9HxCo5R.mjs} +1947 -1777
- package/dist/_chunks/index-C9HxCo5R.mjs.map +1 -0
- package/dist/_chunks/{index-DyvUPg1a.js → index-ovJRE1FM.js} +1927 -1757
- package/dist/_chunks/index-ovJRE1FM.js.map +1 -0
- package/dist/_chunks/{layout-DPaHUusj.mjs → layout-DaUjDiWQ.mjs} +22 -9
- package/dist/_chunks/layout-DaUjDiWQ.mjs.map +1 -0
- package/dist/_chunks/{layout-TPqF2oJ5.js → layout-UNWstw_s.js} +21 -8
- package/dist/_chunks/layout-UNWstw_s.js.map +1 -0
- package/dist/_chunks/{relations-Ck7-ecDT.mjs → relations-D8iFAeRu.mjs} +2 -2
- package/dist/_chunks/{relations-Ck7-ecDT.mjs.map → relations-D8iFAeRu.mjs.map} +1 -1
- package/dist/_chunks/{relations-BWYS9gkn.js → relations-NN3coOG5.js} +2 -2
- package/dist/_chunks/{relations-BWYS9gkn.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 +5 -4
- package/dist/admin/src/exports.d.ts +1 -1
- 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/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 +184 -108
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +185 -109
- 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-DA95Ha6J.js.map +0 -1
- package/dist/_chunks/EditViewPage-DlLEyUL6.mjs.map +0 -1
- package/dist/_chunks/Field-CnK8dO8N.js.map +0 -1
- package/dist/_chunks/Field-Dq7bDnuh.mjs.map +0 -1
- package/dist/_chunks/Form-B_JE0dbz.mjs.map +0 -1
- package/dist/_chunks/Form-BpiR4piS.js.map +0 -1
- package/dist/_chunks/History-CBNGU7a-.mjs.map +0 -1
- package/dist/_chunks/History-DdIstl8b.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-5dr4qpue.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DkKRparB.js.map +0 -1
- package/dist/_chunks/ListViewPage-DecLrYV6.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-wE0lXqoD.js.map +0 -1
- package/dist/_chunks/Relations-Dqz0C1fz.mjs.map +0 -1
- package/dist/_chunks/Relations-L0xYRoSQ.js.map +0 -1
- package/dist/_chunks/index-BSn97i8U.mjs.map +0 -1
- package/dist/_chunks/index-DyvUPg1a.js.map +0 -1
- package/dist/_chunks/layout-DPaHUusj.mjs.map +0 -1
- package/dist/_chunks/layout-TPqF2oJ5.js.map +0 -1
- package/dist/_chunks/usePrev-B9w_-eYc.js.map +0 -1
- package/dist/_chunks/usePrev-DH6iah0A.mjs +0 -16
- package/dist/_chunks/usePrev-DH6iah0A.mjs.map +0 -1
- package/strapi-server.js +0 -3
@@ -6,10 +6,10 @@ const React = require("react");
|
|
6
6
|
const designSystem = require("@strapi/design-system");
|
7
7
|
const reactIntl = require("react-intl");
|
8
8
|
const reactRouterDom = require("react-router-dom");
|
9
|
-
const styledComponents = require("styled-components");
|
10
9
|
const yup = require("yup");
|
11
10
|
const pipe = require("lodash/fp/pipe");
|
12
11
|
const dateFns = require("date-fns");
|
12
|
+
const styledComponents = require("styled-components");
|
13
13
|
const qs = require("qs");
|
14
14
|
const toolkit = require("@reduxjs/toolkit");
|
15
15
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
@@ -179,7 +179,8 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
|
179
179
|
"Document",
|
180
180
|
"InitialData",
|
181
181
|
"HistoryVersion",
|
182
|
-
"Relations"
|
182
|
+
"Relations",
|
183
|
+
"UidAvailability"
|
183
184
|
]
|
184
185
|
});
|
185
186
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -193,7 +194,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
193
194
|
params: query
|
194
195
|
}
|
195
196
|
}),
|
196
|
-
invalidatesTags: (_result,
|
197
|
+
invalidatesTags: (_result, error, { model }) => {
|
198
|
+
if (error) {
|
199
|
+
return [];
|
200
|
+
}
|
201
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
202
|
+
}
|
197
203
|
}),
|
198
204
|
cloneDocument: builder.mutation({
|
199
205
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -204,7 +210,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
204
210
|
params
|
205
211
|
}
|
206
212
|
}),
|
207
|
-
invalidatesTags: (_result, _error, { model }) => [
|
213
|
+
invalidatesTags: (_result, _error, { model }) => [
|
214
|
+
{ type: "Document", id: `${model}_LIST` },
|
215
|
+
{ type: "UidAvailability", id: model }
|
216
|
+
]
|
208
217
|
}),
|
209
218
|
/**
|
210
219
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -221,7 +230,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
221
230
|
}),
|
222
231
|
invalidatesTags: (result, _error, { model }) => [
|
223
232
|
{ type: "Document", id: `${model}_LIST` },
|
224
|
-
"Relations"
|
233
|
+
"Relations",
|
234
|
+
{ type: "UidAvailability", id: model }
|
225
235
|
]
|
226
236
|
}),
|
227
237
|
deleteDocument: builder.mutation({
|
@@ -262,7 +272,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
262
272
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
263
273
|
},
|
264
274
|
{ type: "Document", id: `${model}_LIST` },
|
265
|
-
"Relations"
|
275
|
+
"Relations",
|
276
|
+
{ type: "UidAvailability", id: model }
|
266
277
|
];
|
267
278
|
}
|
268
279
|
}),
|
@@ -280,6 +291,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
280
291
|
}),
|
281
292
|
providesTags: (result, _error, arg) => {
|
282
293
|
return [
|
294
|
+
{ type: "Document", id: `ALL_LIST` },
|
283
295
|
{ type: "Document", id: `${arg.model}_LIST` },
|
284
296
|
...result?.results.map(({ documentId }) => ({
|
285
297
|
type: "Document",
|
@@ -318,6 +330,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
318
330
|
{
|
319
331
|
type: "Document",
|
320
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`
|
321
338
|
}
|
322
339
|
];
|
323
340
|
}
|
@@ -381,8 +398,21 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
381
398
|
type: "Document",
|
382
399
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
383
400
|
},
|
384
|
-
"Relations"
|
401
|
+
"Relations",
|
402
|
+
{ type: "UidAvailability", id: model }
|
385
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
|
+
}
|
386
416
|
}
|
387
417
|
}),
|
388
418
|
unpublishDocument: builder.mutation({
|
@@ -452,7 +482,7 @@ const buildValidParams = (query) => {
|
|
452
482
|
const isBaseQueryError = (error) => {
|
453
483
|
return error.name !== void 0;
|
454
484
|
};
|
455
|
-
const createYupSchema = (attributes = {}, components = {}) => {
|
485
|
+
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
456
486
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
457
487
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
458
488
|
if (DOCUMENT_META_FIELDS.includes(name)) {
|
@@ -465,7 +495,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
465
495
|
addMinValidation,
|
466
496
|
addMaxValidation,
|
467
497
|
addRegexValidation
|
468
|
-
].map((fn) => fn(attribute));
|
498
|
+
].map((fn) => fn(attribute, options));
|
469
499
|
const transformSchema = pipe__default.default(...validations);
|
470
500
|
switch (attribute.type) {
|
471
501
|
case "component": {
|
@@ -514,7 +544,7 @@ const createYupSchema = (attributes = {}, components = {}) => {
|
|
514
544
|
} else if (Array.isArray(value)) {
|
515
545
|
return yup__namespace.array().of(
|
516
546
|
yup__namespace.object().shape({
|
517
|
-
id: yup__namespace.
|
547
|
+
id: yup__namespace.number().required()
|
518
548
|
})
|
519
549
|
);
|
520
550
|
} else if (typeof value === "object") {
|
@@ -566,6 +596,14 @@ const createAttributeSchema = (attribute) => {
|
|
566
596
|
if (!value || typeof value === "string" && value.length === 0) {
|
567
597
|
return true;
|
568
598
|
}
|
599
|
+
if (typeof value === "object") {
|
600
|
+
try {
|
601
|
+
JSON.stringify(value);
|
602
|
+
return true;
|
603
|
+
} catch (err) {
|
604
|
+
return false;
|
605
|
+
}
|
606
|
+
}
|
569
607
|
try {
|
570
608
|
JSON.parse(value);
|
571
609
|
return true;
|
@@ -584,13 +622,7 @@ const createAttributeSchema = (attribute) => {
|
|
584
622
|
return yup__namespace.mixed();
|
585
623
|
}
|
586
624
|
};
|
587
|
-
const
|
588
|
-
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
589
|
-
return schema.min(1, strapiAdmin.translatedErrors.required);
|
590
|
-
}
|
591
|
-
if (attribute.required && attribute.type !== "relation") {
|
592
|
-
return schema.required(strapiAdmin.translatedErrors.required);
|
593
|
-
}
|
625
|
+
const nullableSchema = (schema) => {
|
594
626
|
return schema?.nullable ? schema.nullable() : (
|
595
627
|
// In some cases '.nullable' will not be available on the schema.
|
596
628
|
// e.g. when the schema has been built using yup.lazy (e.g. for relations).
|
@@ -598,7 +630,22 @@ const addRequiredValidation = (attribute) => (schema) => {
|
|
598
630
|
schema
|
599
631
|
);
|
600
632
|
};
|
601
|
-
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
|
+
}
|
602
649
|
if ("minLength" in attribute && attribute.minLength && Number.isInteger(attribute.minLength) && "min" in schema) {
|
603
650
|
return schema.min(attribute.minLength, {
|
604
651
|
...strapiAdmin.translatedErrors.minLength,
|
@@ -620,11 +667,11 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
620
667
|
}
|
621
668
|
return schema;
|
622
669
|
};
|
623
|
-
const addMinValidation = (attribute) => (schema) => {
|
670
|
+
const addMinValidation = (attribute, options) => (schema) => {
|
624
671
|
if ("min" in attribute) {
|
625
672
|
const min = toInteger(attribute.min);
|
626
673
|
if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
|
627
|
-
if (!attribute.required && "test" in schema && min) {
|
674
|
+
if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
|
628
675
|
return schema.test(
|
629
676
|
"custom-min",
|
630
677
|
{
|
@@ -763,19 +810,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
763
810
|
}, {});
|
764
811
|
return componentsByKey;
|
765
812
|
};
|
766
|
-
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);
|
767
912
|
const { toggleNotification } = strapiAdmin.useNotification();
|
768
913
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
914
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
769
915
|
const {
|
770
|
-
|
771
|
-
isLoading:
|
772
|
-
|
773
|
-
|
774
|
-
} =
|
775
|
-
|
776
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
777
|
-
});
|
778
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
916
|
+
data,
|
917
|
+
isLoading: isLoadingConfigs,
|
918
|
+
error,
|
919
|
+
isFetching: isFetchingConfigs
|
920
|
+
} = useGetContentTypeConfigurationQuery(model);
|
921
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
779
922
|
React__namespace.useEffect(() => {
|
780
923
|
if (error) {
|
781
924
|
toggleNotification({
|
@@ -783,382 +926,638 @@ const useDocument = (args, opts) => {
|
|
783
926
|
message: formatAPIError(error)
|
784
927
|
});
|
785
928
|
}
|
786
|
-
}, [
|
787
|
-
const
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
(document) => {
|
795
|
-
if (!validationSchema) {
|
796
|
-
throw new Error(
|
797
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
798
|
-
);
|
799
|
-
}
|
800
|
-
try {
|
801
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
802
|
-
return null;
|
803
|
-
} catch (error2) {
|
804
|
-
if (error2 instanceof yup.ValidationError) {
|
805
|
-
return strapiAdmin.getYupValidationErrors(error2);
|
806
|
-
}
|
807
|
-
throw error2;
|
808
|
-
}
|
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
|
809
937
|
},
|
810
|
-
[
|
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]
|
811
954
|
);
|
812
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
813
955
|
return {
|
814
|
-
|
815
|
-
document: data?.data,
|
816
|
-
meta: data?.meta,
|
956
|
+
error,
|
817
957
|
isLoading,
|
818
|
-
|
819
|
-
|
820
|
-
};
|
821
|
-
};
|
822
|
-
const useDoc = () => {
|
823
|
-
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
824
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
825
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
826
|
-
if (!collectionType) {
|
827
|
-
throw new Error("Could not find collectionType in url params");
|
828
|
-
}
|
829
|
-
if (!slug) {
|
830
|
-
throw new Error("Could not find model in url params");
|
831
|
-
}
|
832
|
-
return {
|
833
|
-
collectionType,
|
834
|
-
model: slug,
|
835
|
-
id: origin || id === "create" ? void 0 : id,
|
836
|
-
...useDocument(
|
837
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
838
|
-
{
|
839
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
840
|
-
}
|
841
|
-
)
|
958
|
+
edit,
|
959
|
+
list: listLayout
|
842
960
|
};
|
843
961
|
};
|
844
|
-
const
|
845
|
-
|
846
|
-
|
847
|
-
}
|
848
|
-
return Object.keys(trad).reduce((acc, current) => {
|
849
|
-
acc[`${pluginId}.${current}`] = trad[current];
|
850
|
-
return acc;
|
851
|
-
}, {});
|
852
|
-
};
|
853
|
-
const getTranslation = (id) => `content-manager.${id}`;
|
854
|
-
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
855
|
-
id: "notification.error",
|
856
|
-
defaultMessage: "An error occurred, please try again"
|
962
|
+
const useDocLayout = () => {
|
963
|
+
const { model } = useDoc();
|
964
|
+
return useDocumentLayout(model);
|
857
965
|
};
|
858
|
-
const
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
const
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
message: formatAPIError(res.error)
|
878
|
-
});
|
879
|
-
return { error: res.error };
|
880
|
-
}
|
881
|
-
toggleNotification({
|
882
|
-
type: "success",
|
883
|
-
message: formatMessage({
|
884
|
-
id: getTranslation("success.record.delete"),
|
885
|
-
defaultMessage: "Deleted document"
|
886
|
-
})
|
887
|
-
});
|
888
|
-
trackUsage("didDeleteEntry", trackerProperty);
|
889
|
-
return res.data;
|
890
|
-
} catch (err) {
|
891
|
-
toggleNotification({
|
892
|
-
type: "danger",
|
893
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
894
|
-
});
|
895
|
-
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
896
|
-
throw err;
|
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([]);
|
897
985
|
}
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
const
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
});
|
916
|
-
return { error: res.error };
|
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
|
917
1003
|
}
|
918
|
-
|
919
|
-
|
920
|
-
title: formatMessage({
|
921
|
-
id: getTranslation("success.records.delete"),
|
922
|
-
defaultMessage: "Successfully deleted."
|
923
|
-
}),
|
924
|
-
message: ""
|
925
|
-
});
|
926
|
-
trackUsage("didBulkDeleteEntries");
|
927
|
-
return res.data;
|
928
|
-
} catch (err) {
|
929
|
-
toggleNotification({
|
930
|
-
type: "danger",
|
931
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
932
|
-
});
|
933
|
-
trackUsage("didNotBulkDeleteEntries");
|
934
|
-
throw err;
|
935
|
-
}
|
1004
|
+
};
|
1005
|
+
return acc;
|
936
1006
|
},
|
937
|
-
|
1007
|
+
{}
|
938
1008
|
);
|
939
|
-
const
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
model,
|
946
|
-
documentId,
|
947
|
-
params
|
948
|
-
});
|
949
|
-
if ("error" in res) {
|
950
|
-
toggleNotification({
|
951
|
-
type: "danger",
|
952
|
-
message: formatAPIError(res.error)
|
953
|
-
});
|
954
|
-
return { error: res.error };
|
955
|
-
}
|
956
|
-
toggleNotification({
|
957
|
-
type: "success",
|
958
|
-
message: formatMessage({
|
959
|
-
id: "content-manager.success.record.discard",
|
960
|
-
defaultMessage: "Changes discarded"
|
961
|
-
})
|
962
|
-
});
|
963
|
-
return res.data;
|
964
|
-
} catch (err) {
|
965
|
-
toggleNotification({
|
966
|
-
type: "danger",
|
967
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
968
|
-
});
|
969
|
-
throw err;
|
970
|
-
}
|
1009
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1010
|
+
(acc, [attribute, metadata]) => {
|
1011
|
+
return {
|
1012
|
+
...acc,
|
1013
|
+
[attribute]: metadata.edit
|
1014
|
+
};
|
971
1015
|
},
|
972
|
-
|
1016
|
+
{}
|
973
1017
|
);
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
model,
|
982
|
-
documentId,
|
983
|
-
data,
|
984
|
-
params
|
985
|
-
});
|
986
|
-
if ("error" in res) {
|
987
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
988
|
-
return { error: res.error };
|
989
|
-
}
|
990
|
-
trackUsage("didPublishEntry");
|
991
|
-
toggleNotification({
|
992
|
-
type: "success",
|
993
|
-
message: formatMessage({
|
994
|
-
id: getTranslation("success.record.publish"),
|
995
|
-
defaultMessage: "Published document"
|
996
|
-
})
|
997
|
-
});
|
998
|
-
return res.data;
|
999
|
-
} catch (err) {
|
1000
|
-
toggleNotification({
|
1001
|
-
type: "danger",
|
1002
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1003
|
-
});
|
1004
|
-
throw err;
|
1005
|
-
}
|
1018
|
+
return {
|
1019
|
+
layout: panelledEditAttributes,
|
1020
|
+
components: componentEditAttributes,
|
1021
|
+
metadatas: editMetadatas,
|
1022
|
+
settings: {
|
1023
|
+
...data.contentType.settings,
|
1024
|
+
displayName: schema?.info.displayName
|
1006
1025
|
},
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
return { error: res.error };
|
1021
|
-
}
|
1022
|
-
toggleNotification({
|
1023
|
-
type: "success",
|
1024
|
-
message: formatMessage({
|
1025
|
-
id: getTranslation("success.record.publish"),
|
1026
|
-
defaultMessage: "Published document"
|
1027
|
-
})
|
1028
|
-
});
|
1029
|
-
return res.data;
|
1030
|
-
} catch (err) {
|
1031
|
-
toggleNotification({
|
1032
|
-
type: "danger",
|
1033
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1034
|
-
});
|
1035
|
-
throw err;
|
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;
|
1036
1039
|
}
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
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)
|
1045
1061
|
);
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
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);
|
1062
1161
|
}
|
1063
|
-
|
1064
|
-
toggleNotification({
|
1065
|
-
type: "success",
|
1066
|
-
message: formatMessage({
|
1067
|
-
id: getTranslation("success.record.save"),
|
1068
|
-
defaultMessage: "Saved document"
|
1069
|
-
})
|
1070
|
-
});
|
1071
|
-
return res.data;
|
1072
|
-
} catch (err) {
|
1073
|
-
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1074
|
-
toggleNotification({
|
1075
|
-
type: "danger",
|
1076
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1077
|
-
});
|
1078
|
-
throw err;
|
1162
|
+
throw error2;
|
1079
1163
|
}
|
1080
1164
|
},
|
1081
|
-
[
|
1165
|
+
[validationSchema]
|
1082
1166
|
);
|
1083
|
-
const
|
1084
|
-
const
|
1085
|
-
|
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,
|
1192
|
+
model: slug,
|
1193
|
+
id: origin || id === "create" ? void 0 : id,
|
1194
|
+
...useDocument(
|
1195
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1196
|
+
{
|
1197
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1198
|
+
}
|
1199
|
+
)
|
1200
|
+
};
|
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
|
+
};
|
1241
|
+
const prefixPluginTranslations = (trad, pluginId) => {
|
1242
|
+
if (!pluginId) {
|
1243
|
+
throw new TypeError("pluginId can't be empty");
|
1244
|
+
}
|
1245
|
+
return Object.keys(trad).reduce((acc, current) => {
|
1246
|
+
acc[`${pluginId}.${current}`] = trad[current];
|
1247
|
+
return acc;
|
1248
|
+
}, {});
|
1249
|
+
};
|
1250
|
+
const getTranslation = (id) => `content-manager.${id}`;
|
1251
|
+
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
1252
|
+
id: "notification.error",
|
1253
|
+
defaultMessage: "An error occurred, please try again"
|
1254
|
+
};
|
1255
|
+
const useDocumentActions = () => {
|
1256
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1257
|
+
const { formatMessage } = reactIntl.useIntl();
|
1258
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
1259
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1260
|
+
const navigate = reactRouterDom.useNavigate();
|
1261
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
1262
|
+
const [deleteDocument] = useDeleteDocumentMutation();
|
1263
|
+
const _delete = React__namespace.useCallback(
|
1264
|
+
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
1086
1265
|
try {
|
1087
|
-
trackUsage("
|
1088
|
-
const res = await
|
1266
|
+
trackUsage("willDeleteEntry", trackerProperty);
|
1267
|
+
const res = await deleteDocument({
|
1089
1268
|
collectionType,
|
1090
1269
|
model,
|
1091
1270
|
documentId,
|
1092
|
-
params
|
1093
|
-
data: {
|
1094
|
-
discardDraft
|
1095
|
-
}
|
1271
|
+
params
|
1096
1272
|
});
|
1097
1273
|
if ("error" in res) {
|
1098
|
-
toggleNotification({
|
1274
|
+
toggleNotification({
|
1275
|
+
type: "danger",
|
1276
|
+
message: formatAPIError(res.error)
|
1277
|
+
});
|
1099
1278
|
return { error: res.error };
|
1100
1279
|
}
|
1101
|
-
trackUsage("didUnpublishEntry");
|
1102
1280
|
toggleNotification({
|
1103
1281
|
type: "success",
|
1104
1282
|
message: formatMessage({
|
1105
|
-
id: getTranslation("success.record.
|
1106
|
-
defaultMessage: "
|
1283
|
+
id: getTranslation("success.record.delete"),
|
1284
|
+
defaultMessage: "Deleted document"
|
1107
1285
|
})
|
1108
1286
|
});
|
1287
|
+
trackUsage("didDeleteEntry", trackerProperty);
|
1109
1288
|
return res.data;
|
1110
1289
|
} catch (err) {
|
1111
1290
|
toggleNotification({
|
1112
1291
|
type: "danger",
|
1113
1292
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1114
1293
|
});
|
1294
|
+
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
1115
1295
|
throw err;
|
1116
1296
|
}
|
1117
1297
|
},
|
1118
|
-
[trackUsage,
|
1298
|
+
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
1119
1299
|
);
|
1120
|
-
const [
|
1121
|
-
const
|
1300
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1301
|
+
const deleteMany = React__namespace.useCallback(
|
1122
1302
|
async ({ model, documentIds, params }) => {
|
1123
1303
|
try {
|
1124
|
-
trackUsage("
|
1125
|
-
const res = await
|
1304
|
+
trackUsage("willBulkDeleteEntries");
|
1305
|
+
const res = await deleteManyDocuments({
|
1126
1306
|
model,
|
1127
1307
|
documentIds,
|
1128
1308
|
params
|
1129
1309
|
});
|
1130
1310
|
if ("error" in res) {
|
1131
|
-
toggleNotification({
|
1311
|
+
toggleNotification({
|
1312
|
+
type: "danger",
|
1313
|
+
message: formatAPIError(res.error)
|
1314
|
+
});
|
1132
1315
|
return { error: res.error };
|
1133
1316
|
}
|
1134
|
-
trackUsage("didBulkUnpublishEntries");
|
1135
1317
|
toggleNotification({
|
1136
1318
|
type: "success",
|
1137
1319
|
title: formatMessage({
|
1138
|
-
id: getTranslation("success.records.
|
1139
|
-
defaultMessage: "Successfully
|
1320
|
+
id: getTranslation("success.records.delete"),
|
1321
|
+
defaultMessage: "Successfully deleted."
|
1140
1322
|
}),
|
1141
1323
|
message: ""
|
1142
1324
|
});
|
1325
|
+
trackUsage("didBulkDeleteEntries");
|
1143
1326
|
return res.data;
|
1144
1327
|
} catch (err) {
|
1145
1328
|
toggleNotification({
|
1146
1329
|
type: "danger",
|
1147
1330
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1148
1331
|
});
|
1149
|
-
trackUsage("
|
1332
|
+
trackUsage("didNotBulkDeleteEntries");
|
1150
1333
|
throw err;
|
1151
1334
|
}
|
1152
1335
|
},
|
1153
|
-
[trackUsage,
|
1336
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1154
1337
|
);
|
1155
|
-
const [
|
1156
|
-
const
|
1157
|
-
async ({ model, params }
|
1338
|
+
const [discardDocument] = useDiscardDocumentMutation();
|
1339
|
+
const discard = React__namespace.useCallback(
|
1340
|
+
async ({ collectionType, model, documentId, params }) => {
|
1158
1341
|
try {
|
1159
|
-
const res = await
|
1342
|
+
const res = await discardDocument({
|
1343
|
+
collectionType,
|
1160
1344
|
model,
|
1161
|
-
|
1345
|
+
documentId,
|
1346
|
+
params
|
1347
|
+
});
|
1348
|
+
if ("error" in res) {
|
1349
|
+
toggleNotification({
|
1350
|
+
type: "danger",
|
1351
|
+
message: formatAPIError(res.error)
|
1352
|
+
});
|
1353
|
+
return { error: res.error };
|
1354
|
+
}
|
1355
|
+
toggleNotification({
|
1356
|
+
type: "success",
|
1357
|
+
message: formatMessage({
|
1358
|
+
id: "content-manager.success.record.discard",
|
1359
|
+
defaultMessage: "Changes discarded"
|
1360
|
+
})
|
1361
|
+
});
|
1362
|
+
return res.data;
|
1363
|
+
} catch (err) {
|
1364
|
+
toggleNotification({
|
1365
|
+
type: "danger",
|
1366
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1367
|
+
});
|
1368
|
+
throw err;
|
1369
|
+
}
|
1370
|
+
},
|
1371
|
+
[discardDocument, formatAPIError, formatMessage, toggleNotification]
|
1372
|
+
);
|
1373
|
+
const [publishDocument] = usePublishDocumentMutation();
|
1374
|
+
const publish = React__namespace.useCallback(
|
1375
|
+
async ({ collectionType, model, documentId, params }, data) => {
|
1376
|
+
try {
|
1377
|
+
trackUsage("willPublishEntry");
|
1378
|
+
const res = await publishDocument({
|
1379
|
+
collectionType,
|
1380
|
+
model,
|
1381
|
+
documentId,
|
1382
|
+
data,
|
1383
|
+
params
|
1384
|
+
});
|
1385
|
+
if ("error" in res) {
|
1386
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1387
|
+
return { error: res.error };
|
1388
|
+
}
|
1389
|
+
trackUsage("didPublishEntry");
|
1390
|
+
toggleNotification({
|
1391
|
+
type: "success",
|
1392
|
+
message: formatMessage({
|
1393
|
+
id: getTranslation("success.record.publish"),
|
1394
|
+
defaultMessage: "Published document"
|
1395
|
+
})
|
1396
|
+
});
|
1397
|
+
return res.data;
|
1398
|
+
} catch (err) {
|
1399
|
+
toggleNotification({
|
1400
|
+
type: "danger",
|
1401
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1402
|
+
});
|
1403
|
+
throw err;
|
1404
|
+
}
|
1405
|
+
},
|
1406
|
+
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1407
|
+
);
|
1408
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1409
|
+
const publishMany = React__namespace.useCallback(
|
1410
|
+
async ({ model, documentIds, params }) => {
|
1411
|
+
try {
|
1412
|
+
const res = await publishManyDocuments({
|
1413
|
+
model,
|
1414
|
+
documentIds,
|
1415
|
+
params
|
1416
|
+
});
|
1417
|
+
if ("error" in res) {
|
1418
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1419
|
+
return { error: res.error };
|
1420
|
+
}
|
1421
|
+
toggleNotification({
|
1422
|
+
type: "success",
|
1423
|
+
message: formatMessage({
|
1424
|
+
id: getTranslation("success.record.publish"),
|
1425
|
+
defaultMessage: "Published document"
|
1426
|
+
})
|
1427
|
+
});
|
1428
|
+
return res.data;
|
1429
|
+
} catch (err) {
|
1430
|
+
toggleNotification({
|
1431
|
+
type: "danger",
|
1432
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1433
|
+
});
|
1434
|
+
throw err;
|
1435
|
+
}
|
1436
|
+
},
|
1437
|
+
[
|
1438
|
+
// trackUsage,
|
1439
|
+
publishManyDocuments,
|
1440
|
+
toggleNotification,
|
1441
|
+
formatMessage,
|
1442
|
+
formatAPIError
|
1443
|
+
]
|
1444
|
+
);
|
1445
|
+
const [updateDocument] = useUpdateDocumentMutation();
|
1446
|
+
const update = React__namespace.useCallback(
|
1447
|
+
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
1448
|
+
try {
|
1449
|
+
trackUsage("willEditEntry", trackerProperty);
|
1450
|
+
const res = await updateDocument({
|
1451
|
+
collectionType,
|
1452
|
+
model,
|
1453
|
+
documentId,
|
1454
|
+
data,
|
1455
|
+
params
|
1456
|
+
});
|
1457
|
+
if ("error" in res) {
|
1458
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1459
|
+
trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
|
1460
|
+
return { error: res.error };
|
1461
|
+
}
|
1462
|
+
trackUsage("didEditEntry", trackerProperty);
|
1463
|
+
toggleNotification({
|
1464
|
+
type: "success",
|
1465
|
+
message: formatMessage({
|
1466
|
+
id: getTranslation("success.record.save"),
|
1467
|
+
defaultMessage: "Saved document"
|
1468
|
+
})
|
1469
|
+
});
|
1470
|
+
return res.data;
|
1471
|
+
} catch (err) {
|
1472
|
+
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1473
|
+
toggleNotification({
|
1474
|
+
type: "danger",
|
1475
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1476
|
+
});
|
1477
|
+
throw err;
|
1478
|
+
}
|
1479
|
+
},
|
1480
|
+
[trackUsage, updateDocument, toggleNotification, formatMessage, formatAPIError]
|
1481
|
+
);
|
1482
|
+
const [unpublishDocument] = useUnpublishDocumentMutation();
|
1483
|
+
const unpublish = React__namespace.useCallback(
|
1484
|
+
async ({ collectionType, model, documentId, params }, discardDraft = false) => {
|
1485
|
+
try {
|
1486
|
+
trackUsage("willUnpublishEntry");
|
1487
|
+
const res = await unpublishDocument({
|
1488
|
+
collectionType,
|
1489
|
+
model,
|
1490
|
+
documentId,
|
1491
|
+
params,
|
1492
|
+
data: {
|
1493
|
+
discardDraft
|
1494
|
+
}
|
1495
|
+
});
|
1496
|
+
if ("error" in res) {
|
1497
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1498
|
+
return { error: res.error };
|
1499
|
+
}
|
1500
|
+
trackUsage("didUnpublishEntry");
|
1501
|
+
toggleNotification({
|
1502
|
+
type: "success",
|
1503
|
+
message: formatMessage({
|
1504
|
+
id: getTranslation("success.record.unpublish"),
|
1505
|
+
defaultMessage: "Unpublished document"
|
1506
|
+
})
|
1507
|
+
});
|
1508
|
+
return res.data;
|
1509
|
+
} catch (err) {
|
1510
|
+
toggleNotification({
|
1511
|
+
type: "danger",
|
1512
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1513
|
+
});
|
1514
|
+
throw err;
|
1515
|
+
}
|
1516
|
+
},
|
1517
|
+
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1518
|
+
);
|
1519
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1520
|
+
const unpublishMany = React__namespace.useCallback(
|
1521
|
+
async ({ model, documentIds, params }) => {
|
1522
|
+
try {
|
1523
|
+
trackUsage("willBulkUnpublishEntries");
|
1524
|
+
const res = await unpublishManyDocuments({
|
1525
|
+
model,
|
1526
|
+
documentIds,
|
1527
|
+
params
|
1528
|
+
});
|
1529
|
+
if ("error" in res) {
|
1530
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1531
|
+
return { error: res.error };
|
1532
|
+
}
|
1533
|
+
trackUsage("didBulkUnpublishEntries");
|
1534
|
+
toggleNotification({
|
1535
|
+
type: "success",
|
1536
|
+
title: formatMessage({
|
1537
|
+
id: getTranslation("success.records.unpublish"),
|
1538
|
+
defaultMessage: "Successfully unpublished."
|
1539
|
+
}),
|
1540
|
+
message: ""
|
1541
|
+
});
|
1542
|
+
return res.data;
|
1543
|
+
} catch (err) {
|
1544
|
+
toggleNotification({
|
1545
|
+
type: "danger",
|
1546
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1547
|
+
});
|
1548
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1549
|
+
throw err;
|
1550
|
+
}
|
1551
|
+
},
|
1552
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1553
|
+
);
|
1554
|
+
const [createDocument] = useCreateDocumentMutation();
|
1555
|
+
const create = React__namespace.useCallback(
|
1556
|
+
async ({ model, params }, data, trackerProperty) => {
|
1557
|
+
try {
|
1558
|
+
const res = await createDocument({
|
1559
|
+
model,
|
1560
|
+
data,
|
1162
1561
|
params
|
1163
1562
|
});
|
1164
1563
|
if ("error" in res) {
|
@@ -1174,6 +1573,7 @@ const useDocumentActions = () => {
|
|
1174
1573
|
defaultMessage: "Saved document"
|
1175
1574
|
})
|
1176
1575
|
});
|
1576
|
+
setCurrentStep("contentManager.success");
|
1177
1577
|
return res.data;
|
1178
1578
|
} catch (err) {
|
1179
1579
|
toggleNotification({
|
@@ -1195,7 +1595,6 @@ const useDocumentActions = () => {
|
|
1195
1595
|
sourceId
|
1196
1596
|
});
|
1197
1597
|
if ("error" in res) {
|
1198
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1199
1598
|
return { error: res.error };
|
1200
1599
|
}
|
1201
1600
|
toggleNotification({
|
@@ -1214,7 +1613,7 @@ const useDocumentActions = () => {
|
|
1214
1613
|
throw err;
|
1215
1614
|
}
|
1216
1615
|
},
|
1217
|
-
[autoCloneDocument,
|
1616
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1218
1617
|
);
|
1219
1618
|
const [cloneDocument] = useCloneDocumentMutation();
|
1220
1619
|
const clone = React__namespace.useCallback(
|
@@ -1240,6 +1639,7 @@ const useDocumentActions = () => {
|
|
1240
1639
|
defaultMessage: "Cloned document"
|
1241
1640
|
})
|
1242
1641
|
});
|
1642
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1243
1643
|
return res.data;
|
1244
1644
|
} catch (err) {
|
1245
1645
|
toggleNotification({
|
@@ -1250,7 +1650,7 @@ const useDocumentActions = () => {
|
|
1250
1650
|
throw err;
|
1251
1651
|
}
|
1252
1652
|
},
|
1253
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1653
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1254
1654
|
);
|
1255
1655
|
const [getDoc] = useLazyGetDocumentQuery();
|
1256
1656
|
const getDocument = React__namespace.useCallback(
|
@@ -1276,7 +1676,7 @@ const useDocumentActions = () => {
|
|
1276
1676
|
};
|
1277
1677
|
};
|
1278
1678
|
const ProtectedHistoryPage = React.lazy(
|
1279
|
-
() => Promise.resolve().then(() => require("./History-
|
1679
|
+
() => Promise.resolve().then(() => require("./History-C_uSGzO5.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1280
1680
|
);
|
1281
1681
|
const routes$1 = [
|
1282
1682
|
{
|
@@ -1289,31 +1689,31 @@ const routes$1 = [
|
|
1289
1689
|
}
|
1290
1690
|
];
|
1291
1691
|
const ProtectedEditViewPage = React.lazy(
|
1292
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1692
|
+
() => Promise.resolve().then(() => require("./EditViewPage-CUS2EAhB.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1293
1693
|
);
|
1294
1694
|
const ProtectedListViewPage = React.lazy(
|
1295
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1695
|
+
() => Promise.resolve().then(() => require("./ListViewPage-DHgHD8Xg.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1296
1696
|
);
|
1297
1697
|
const ProtectedListConfiguration = React.lazy(
|
1298
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1698
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-nyuP7OSy.js")).then((mod) => ({
|
1299
1699
|
default: mod.ProtectedListConfiguration
|
1300
1700
|
}))
|
1301
1701
|
);
|
1302
1702
|
const ProtectedEditConfigurationPage = React.lazy(
|
1303
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1703
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-DITVliEI.js")).then((mod) => ({
|
1304
1704
|
default: mod.ProtectedEditConfigurationPage
|
1305
1705
|
}))
|
1306
1706
|
);
|
1307
1707
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1308
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1708
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-DP7AC0UU.js")).then((mod) => ({
|
1309
1709
|
default: mod.ProtectedComponentConfigurationPage
|
1310
1710
|
}))
|
1311
1711
|
);
|
1312
1712
|
const NoPermissions = React.lazy(
|
1313
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1713
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-zwIZydDI.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1314
1714
|
);
|
1315
1715
|
const NoContentType = React.lazy(
|
1316
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1716
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-CDUKdZ7d.js")).then((mod) => ({ default: mod.NoContentType }))
|
1317
1717
|
);
|
1318
1718
|
const CollectionTypePages = () => {
|
1319
1719
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1344,1073 +1744,758 @@ const routes = [
|
|
1344
1744
|
Component: ProtectedListConfiguration
|
1345
1745
|
},
|
1346
1746
|
{
|
1347
|
-
path: "components/:slug/configurations/edit",
|
1348
|
-
Component: ProtectedComponentConfigurationPage
|
1349
|
-
},
|
1350
|
-
{
|
1351
|
-
path: ":collectionType/:slug/configurations/edit",
|
1352
|
-
Component: ProtectedEditConfigurationPage
|
1353
|
-
},
|
1354
|
-
{
|
1355
|
-
path: "403",
|
1356
|
-
Component: NoPermissions
|
1357
|
-
},
|
1358
|
-
{
|
1359
|
-
path: "no-content-types",
|
1360
|
-
Component: NoContentType
|
1361
|
-
},
|
1362
|
-
...routes$1
|
1363
|
-
];
|
1364
|
-
const DocumentActions = ({ actions: actions2 }) => {
|
1365
|
-
const { formatMessage } = reactIntl.useIntl();
|
1366
|
-
const [primaryAction, secondaryAction, ...restActions] = actions2.filter((action) => {
|
1367
|
-
if (action.position === void 0) {
|
1368
|
-
return true;
|
1369
|
-
}
|
1370
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
1371
|
-
return positions.includes("panel");
|
1372
|
-
});
|
1373
|
-
if (!primaryAction) {
|
1374
|
-
return null;
|
1375
|
-
}
|
1376
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
|
1377
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
1378
|
-
/* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
|
1379
|
-
restActions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
1380
|
-
DocumentActionsMenu,
|
1381
|
-
{
|
1382
|
-
actions: restActions,
|
1383
|
-
label: formatMessage({
|
1384
|
-
id: "content-manager.containers.edit.panels.default.more-actions",
|
1385
|
-
defaultMessage: "More document actions"
|
1386
|
-
})
|
1387
|
-
}
|
1388
|
-
) : null
|
1389
|
-
] }),
|
1390
|
-
secondaryAction ? /* @__PURE__ */ jsxRuntime.jsx(
|
1391
|
-
DocumentActionButton,
|
1392
|
-
{
|
1393
|
-
...secondaryAction,
|
1394
|
-
variant: secondaryAction.variant || "secondary"
|
1395
|
-
}
|
1396
|
-
) : null
|
1397
|
-
] });
|
1398
|
-
};
|
1399
|
-
const DocumentActionButton = (action) => {
|
1400
|
-
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1401
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
1402
|
-
const handleClick = (action2) => async (e) => {
|
1403
|
-
const { onClick = () => false, dialog, id } = action2;
|
1404
|
-
const muteDialog = await onClick(e);
|
1405
|
-
if (dialog && !muteDialog) {
|
1406
|
-
switch (dialog.type) {
|
1407
|
-
case "notification":
|
1408
|
-
toggleNotification({
|
1409
|
-
title: dialog.title,
|
1410
|
-
message: dialog.content,
|
1411
|
-
type: dialog.status,
|
1412
|
-
timeout: dialog.timeout,
|
1413
|
-
onClose: dialog.onClose
|
1414
|
-
});
|
1415
|
-
break;
|
1416
|
-
case "dialog":
|
1417
|
-
case "modal":
|
1418
|
-
e.preventDefault();
|
1419
|
-
setDialogId(id);
|
1420
|
-
}
|
1421
|
-
}
|
1422
|
-
};
|
1423
|
-
const handleClose = () => {
|
1424
|
-
setDialogId(null);
|
1425
|
-
};
|
1426
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
1427
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1428
|
-
designSystem.Button,
|
1429
|
-
{
|
1430
|
-
flex: 1,
|
1431
|
-
startIcon: action.icon,
|
1432
|
-
disabled: action.disabled,
|
1433
|
-
onClick: handleClick(action),
|
1434
|
-
justifyContent: "center",
|
1435
|
-
variant: action.variant || "default",
|
1436
|
-
children: action.label
|
1437
|
-
}
|
1438
|
-
),
|
1439
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1440
|
-
DocumentActionConfirmDialog,
|
1441
|
-
{
|
1442
|
-
...action.dialog,
|
1443
|
-
variant: action.dialog?.variant ?? action.variant,
|
1444
|
-
isOpen: dialogId === action.id,
|
1445
|
-
onClose: handleClose
|
1446
|
-
}
|
1447
|
-
) : null,
|
1448
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1449
|
-
DocumentActionModal,
|
1450
|
-
{
|
1451
|
-
...action.dialog,
|
1452
|
-
onModalClose: handleClose,
|
1453
|
-
isOpen: dialogId === action.id
|
1454
|
-
}
|
1455
|
-
) : null
|
1456
|
-
] });
|
1457
|
-
};
|
1458
|
-
const DocumentActionsMenu = ({
|
1459
|
-
actions: actions2,
|
1460
|
-
children,
|
1461
|
-
label,
|
1462
|
-
variant = "tertiary"
|
1463
|
-
}) => {
|
1464
|
-
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
1465
|
-
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1466
|
-
const { formatMessage } = reactIntl.useIntl();
|
1467
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
1468
|
-
const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
|
1469
|
-
const handleClick = (action) => async (e) => {
|
1470
|
-
const { onClick = () => false, dialog, id } = action;
|
1471
|
-
const muteDialog = await onClick(e);
|
1472
|
-
if (dialog && !muteDialog) {
|
1473
|
-
switch (dialog.type) {
|
1474
|
-
case "notification":
|
1475
|
-
toggleNotification({
|
1476
|
-
title: dialog.title,
|
1477
|
-
message: dialog.content,
|
1478
|
-
type: dialog.status,
|
1479
|
-
timeout: dialog.timeout,
|
1480
|
-
onClose: dialog.onClose
|
1481
|
-
});
|
1482
|
-
break;
|
1483
|
-
case "dialog":
|
1484
|
-
case "modal":
|
1485
|
-
setDialogId(id);
|
1486
|
-
}
|
1487
|
-
}
|
1488
|
-
};
|
1489
|
-
const handleClose = () => {
|
1490
|
-
setDialogId(null);
|
1491
|
-
setIsOpen(false);
|
1492
|
-
};
|
1493
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1494
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
1495
|
-
designSystem.Menu.Trigger,
|
1496
|
-
{
|
1497
|
-
disabled: isDisabled,
|
1498
|
-
size: "S",
|
1499
|
-
endIcon: null,
|
1500
|
-
paddingTop: "7px",
|
1501
|
-
paddingLeft: "9px",
|
1502
|
-
paddingRight: "9px",
|
1503
|
-
variant,
|
1504
|
-
children: [
|
1505
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
1506
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1507
|
-
id: "content-manager.containers.edit.panels.default.more-actions",
|
1508
|
-
defaultMessage: "More document actions"
|
1509
|
-
}) })
|
1510
|
-
]
|
1511
|
-
}
|
1512
|
-
),
|
1513
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1514
|
-
actions2.map((action) => {
|
1515
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
1516
|
-
designSystem.Menu.Item,
|
1517
|
-
{
|
1518
|
-
disabled: action.disabled,
|
1519
|
-
onSelect: handleClick(action),
|
1520
|
-
display: "block",
|
1521
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1522
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { color: convertActionVariantToColor(action.variant), gap: 2, tag: "span", children: [
|
1523
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { tag: "span", color: convertActionVariantToIconColor(action.variant), children: action.icon }),
|
1524
|
-
action.label
|
1525
|
-
] }),
|
1526
|
-
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1527
|
-
designSystem.Flex,
|
1528
|
-
{
|
1529
|
-
alignItems: "center",
|
1530
|
-
background: "alternative100",
|
1531
|
-
borderStyle: "solid",
|
1532
|
-
borderColor: "alternative200",
|
1533
|
-
borderWidth: "1px",
|
1534
|
-
height: 5,
|
1535
|
-
paddingLeft: 2,
|
1536
|
-
paddingRight: 2,
|
1537
|
-
hasRadius: true,
|
1538
|
-
color: "alternative600",
|
1539
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1540
|
-
}
|
1541
|
-
)
|
1542
|
-
] })
|
1543
|
-
},
|
1544
|
-
action.id
|
1545
|
-
);
|
1546
|
-
}),
|
1547
|
-
children
|
1548
|
-
] }),
|
1549
|
-
actions2.map((action) => {
|
1550
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
1551
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1552
|
-
DocumentActionConfirmDialog,
|
1553
|
-
{
|
1554
|
-
...action.dialog,
|
1555
|
-
variant: action.variant,
|
1556
|
-
isOpen: dialogId === action.id,
|
1557
|
-
onClose: handleClose
|
1558
|
-
}
|
1559
|
-
) : null,
|
1560
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1561
|
-
DocumentActionModal,
|
1562
|
-
{
|
1563
|
-
...action.dialog,
|
1564
|
-
onModalClose: handleClose,
|
1565
|
-
isOpen: dialogId === action.id
|
1566
|
-
}
|
1567
|
-
) : null
|
1568
|
-
] }, action.id);
|
1569
|
-
})
|
1570
|
-
] });
|
1571
|
-
};
|
1572
|
-
const convertActionVariantToColor = (variant = "secondary") => {
|
1573
|
-
switch (variant) {
|
1574
|
-
case "danger":
|
1575
|
-
return "danger600";
|
1576
|
-
case "secondary":
|
1577
|
-
return void 0;
|
1578
|
-
case "success":
|
1579
|
-
return "success600";
|
1580
|
-
default:
|
1581
|
-
return "primary600";
|
1582
|
-
}
|
1583
|
-
};
|
1584
|
-
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1585
|
-
switch (variant) {
|
1586
|
-
case "danger":
|
1587
|
-
return "danger600";
|
1588
|
-
case "secondary":
|
1589
|
-
return "neutral500";
|
1590
|
-
case "success":
|
1591
|
-
return "success600";
|
1592
|
-
default:
|
1593
|
-
return "primary600";
|
1594
|
-
}
|
1595
|
-
};
|
1596
|
-
const DocumentActionConfirmDialog = ({
|
1597
|
-
onClose,
|
1598
|
-
onCancel,
|
1599
|
-
onConfirm,
|
1600
|
-
title,
|
1601
|
-
content,
|
1602
|
-
isOpen,
|
1603
|
-
variant = "secondary"
|
1604
|
-
}) => {
|
1605
|
-
const { formatMessage } = reactIntl.useIntl();
|
1606
|
-
const handleClose = async () => {
|
1607
|
-
if (onCancel) {
|
1608
|
-
await onCancel();
|
1609
|
-
}
|
1610
|
-
onClose();
|
1611
|
-
};
|
1612
|
-
const handleConfirm = async () => {
|
1613
|
-
if (onConfirm) {
|
1614
|
-
await onConfirm();
|
1615
|
-
}
|
1616
|
-
onClose();
|
1617
|
-
};
|
1618
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
1619
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1620
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1621
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1622
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
1623
|
-
id: "app.components.Button.cancel",
|
1624
|
-
defaultMessage: "Cancel"
|
1625
|
-
}) }) }),
|
1626
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
1627
|
-
id: "app.components.Button.confirm",
|
1628
|
-
defaultMessage: "Confirm"
|
1629
|
-
}) })
|
1630
|
-
] })
|
1631
|
-
] }) });
|
1632
|
-
};
|
1633
|
-
const DocumentActionModal = ({
|
1634
|
-
isOpen,
|
1635
|
-
title,
|
1636
|
-
onClose,
|
1637
|
-
footer: Footer,
|
1638
|
-
content: Content,
|
1639
|
-
onModalClose
|
1640
|
-
}) => {
|
1641
|
-
const handleClose = () => {
|
1642
|
-
if (onClose) {
|
1643
|
-
onClose();
|
1644
|
-
}
|
1645
|
-
onModalClose();
|
1646
|
-
};
|
1647
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
1648
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
1649
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content }),
|
1650
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Footer, { children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer })
|
1651
|
-
] }) });
|
1652
|
-
};
|
1653
|
-
const PublishAction$1 = ({
|
1654
|
-
activeTab,
|
1655
|
-
documentId,
|
1656
|
-
model,
|
1657
|
-
collectionType,
|
1658
|
-
meta,
|
1659
|
-
document
|
1660
|
-
}) => {
|
1661
|
-
const { schema } = useDoc();
|
1662
|
-
const navigate = reactRouterDom.useNavigate();
|
1663
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
1664
|
-
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
1665
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
1666
|
-
const { formatMessage } = reactIntl.useIntl();
|
1667
|
-
const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
|
1668
|
-
"PublishAction",
|
1669
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1670
|
-
);
|
1671
|
-
const { publish } = useDocumentActions();
|
1672
|
-
const [
|
1673
|
-
countDraftRelations,
|
1674
|
-
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
1675
|
-
] = useLazyGetDraftRelationCountQuery();
|
1676
|
-
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
1677
|
-
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1678
|
-
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1679
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1680
|
-
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
1681
|
-
const setSubmitting = strapiAdmin.useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
1682
|
-
const isSubmitting = strapiAdmin.useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
1683
|
-
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1684
|
-
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1685
|
-
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
1686
|
-
React__namespace.useEffect(() => {
|
1687
|
-
if (isErrorDraftRelations) {
|
1688
|
-
toggleNotification({
|
1689
|
-
type: "danger",
|
1690
|
-
message: formatMessage({
|
1691
|
-
id: getTranslation("error.records.fetch-draft-relatons"),
|
1692
|
-
defaultMessage: "An error occurred while fetching draft relations on this document."
|
1693
|
-
})
|
1694
|
-
});
|
1695
|
-
}
|
1696
|
-
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
1697
|
-
React__namespace.useEffect(() => {
|
1698
|
-
const localDraftRelations = /* @__PURE__ */ new Set();
|
1699
|
-
const extractDraftRelations = (data) => {
|
1700
|
-
const relations = data.connect || [];
|
1701
|
-
relations.forEach((relation) => {
|
1702
|
-
if (relation.status === "draft") {
|
1703
|
-
localDraftRelations.add(relation.id);
|
1704
|
-
}
|
1705
|
-
});
|
1706
|
-
};
|
1707
|
-
const traverseAndExtract = (data) => {
|
1708
|
-
Object.entries(data).forEach(([key, value]) => {
|
1709
|
-
if (key === "connect" && Array.isArray(value)) {
|
1710
|
-
extractDraftRelations({ connect: value });
|
1711
|
-
} else if (typeof value === "object" && value !== null) {
|
1712
|
-
traverseAndExtract(value);
|
1713
|
-
}
|
1714
|
-
});
|
1715
|
-
};
|
1716
|
-
if (!documentId || modified) {
|
1717
|
-
traverseAndExtract(formValues);
|
1718
|
-
setLocalCountOfDraftRelations(localDraftRelations.size);
|
1719
|
-
}
|
1720
|
-
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1721
|
-
React__namespace.useEffect(() => {
|
1722
|
-
if (documentId) {
|
1723
|
-
const fetchDraftRelationsCount = async () => {
|
1724
|
-
const { data, error } = await countDraftRelations({
|
1725
|
-
collectionType,
|
1726
|
-
model,
|
1727
|
-
documentId,
|
1728
|
-
params
|
1729
|
-
});
|
1730
|
-
if (error) {
|
1731
|
-
throw error;
|
1732
|
-
}
|
1733
|
-
if (data) {
|
1734
|
-
setServerCountOfDraftRelations(data.data);
|
1735
|
-
}
|
1736
|
-
};
|
1737
|
-
fetchDraftRelationsCount();
|
1747
|
+
path: "components/:slug/configurations/edit",
|
1748
|
+
Component: ProtectedComponentConfigurationPage
|
1749
|
+
},
|
1750
|
+
{
|
1751
|
+
path: ":collectionType/:slug/configurations/edit",
|
1752
|
+
Component: ProtectedEditConfigurationPage
|
1753
|
+
},
|
1754
|
+
{
|
1755
|
+
path: "403",
|
1756
|
+
Component: NoPermissions
|
1757
|
+
},
|
1758
|
+
{
|
1759
|
+
path: "no-content-types",
|
1760
|
+
Component: NoContentType
|
1761
|
+
},
|
1762
|
+
...routes$1
|
1763
|
+
];
|
1764
|
+
const DocumentActions = ({ actions: actions2 }) => {
|
1765
|
+
const { formatMessage } = reactIntl.useIntl();
|
1766
|
+
const [primaryAction, secondaryAction, ...restActions] = actions2.filter((action) => {
|
1767
|
+
if (action.position === void 0) {
|
1768
|
+
return true;
|
1738
1769
|
}
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1770
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
1771
|
+
return positions.includes("panel");
|
1772
|
+
});
|
1773
|
+
if (!primaryAction) {
|
1742
1774
|
return null;
|
1743
1775
|
}
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
toggleNotification({
|
1750
|
-
type: "danger",
|
1751
|
-
message: formatMessage({
|
1752
|
-
id: "content-manager.validation.error",
|
1753
|
-
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1754
|
-
})
|
1755
|
-
});
|
1756
|
-
return;
|
1757
|
-
}
|
1758
|
-
const res = await publish(
|
1759
|
-
{
|
1760
|
-
collectionType,
|
1761
|
-
model,
|
1762
|
-
documentId,
|
1763
|
-
params
|
1764
|
-
},
|
1765
|
-
formValues
|
1766
|
-
);
|
1767
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1768
|
-
navigate({
|
1769
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1770
|
-
search: rawQuery
|
1771
|
-
});
|
1772
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1773
|
-
setErrors(formatValidationErrors(res.error));
|
1774
|
-
}
|
1775
|
-
} finally {
|
1776
|
-
setSubmitting(false);
|
1777
|
-
}
|
1778
|
-
};
|
1779
|
-
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1780
|
-
const hasDraftRelations = totalDraftRelations > 0;
|
1781
|
-
return {
|
1782
|
-
/**
|
1783
|
-
* Disabled when:
|
1784
|
-
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
1785
|
-
* - the form is submitting
|
1786
|
-
* - the active tab is the published tab
|
1787
|
-
* - the document is already published & not modified
|
1788
|
-
* - the document is being created & not modified
|
1789
|
-
* - the user doesn't have the permission to publish
|
1790
|
-
* - the user doesn't have the permission to create a new document
|
1791
|
-
* - the user doesn't have the permission to update the document
|
1792
|
-
*/
|
1793
|
-
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish || Boolean(!document?.documentId && !canCreate || document?.documentId && !canUpdate),
|
1794
|
-
label: formatMessage({
|
1795
|
-
id: "app.utils.publish",
|
1796
|
-
defaultMessage: "Publish"
|
1797
|
-
}),
|
1798
|
-
onClick: async () => {
|
1799
|
-
if (hasDraftRelations) {
|
1800
|
-
return;
|
1801
|
-
}
|
1802
|
-
await performPublish();
|
1803
|
-
},
|
1804
|
-
dialog: hasDraftRelations ? {
|
1805
|
-
type: "dialog",
|
1806
|
-
variant: "danger",
|
1807
|
-
footer: null,
|
1808
|
-
title: formatMessage({
|
1809
|
-
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
1810
|
-
defaultMessage: "Confirmation"
|
1811
|
-
}),
|
1812
|
-
content: formatMessage(
|
1813
|
-
{
|
1814
|
-
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
1815
|
-
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
1816
|
-
},
|
1776
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
|
1777
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
1778
|
+
/* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
|
1779
|
+
restActions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
1780
|
+
DocumentActionsMenu,
|
1817
1781
|
{
|
1818
|
-
|
1782
|
+
actions: restActions,
|
1783
|
+
label: formatMessage({
|
1784
|
+
id: "content-manager.containers.edit.panels.default.more-actions",
|
1785
|
+
defaultMessage: "More document actions"
|
1786
|
+
})
|
1819
1787
|
}
|
1820
|
-
)
|
1821
|
-
|
1822
|
-
|
1788
|
+
) : null
|
1789
|
+
] }),
|
1790
|
+
secondaryAction ? /* @__PURE__ */ jsxRuntime.jsx(
|
1791
|
+
DocumentActionButton,
|
1792
|
+
{
|
1793
|
+
...secondaryAction,
|
1794
|
+
variant: secondaryAction.variant || "secondary"
|
1823
1795
|
}
|
1824
|
-
|
1825
|
-
};
|
1796
|
+
) : null
|
1797
|
+
] });
|
1826
1798
|
};
|
1827
|
-
|
1828
|
-
const
|
1829
|
-
activeTab,
|
1830
|
-
documentId,
|
1831
|
-
model,
|
1832
|
-
collectionType
|
1833
|
-
}) => {
|
1834
|
-
const navigate = reactRouterDom.useNavigate();
|
1799
|
+
const DocumentActionButton = (action) => {
|
1800
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1835
1801
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1836
|
-
const
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
canUpdate: canUpdate2
|
1843
|
-
}));
|
1844
|
-
const { create, update, clone } = useDocumentActions();
|
1845
|
-
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1846
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1847
|
-
const isSubmitting = strapiAdmin.useForm("UpdateAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
1848
|
-
const modified = strapiAdmin.useForm("UpdateAction", ({ modified: modified2 }) => modified2);
|
1849
|
-
const setSubmitting = strapiAdmin.useForm("UpdateAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
1850
|
-
const document = strapiAdmin.useForm("UpdateAction", ({ values }) => values);
|
1851
|
-
const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
|
1852
|
-
const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
|
1853
|
-
const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
1854
|
-
return {
|
1855
|
-
/**
|
1856
|
-
* Disabled when:
|
1857
|
-
* - the form is submitting
|
1858
|
-
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1859
|
-
* - the active tab is the published tab
|
1860
|
-
* - the user doesn't have the permission to create a new document
|
1861
|
-
* - the user doesn't have the permission to update the document
|
1862
|
-
*/
|
1863
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published" || Boolean(!documentId && !canCreate || documentId && !canUpdate),
|
1864
|
-
label: formatMessage({
|
1865
|
-
id: "content-manager.containers.Edit.save",
|
1866
|
-
defaultMessage: "Save"
|
1867
|
-
}),
|
1868
|
-
onClick: async () => {
|
1869
|
-
setSubmitting(true);
|
1870
|
-
try {
|
1871
|
-
const { errors } = await validate();
|
1872
|
-
if (errors) {
|
1802
|
+
const handleClick = (action2) => async (e) => {
|
1803
|
+
const { onClick = () => false, dialog, id } = action2;
|
1804
|
+
const muteDialog = await onClick(e);
|
1805
|
+
if (dialog && !muteDialog) {
|
1806
|
+
switch (dialog.type) {
|
1807
|
+
case "notification":
|
1873
1808
|
toggleNotification({
|
1874
|
-
|
1875
|
-
message:
|
1876
|
-
|
1877
|
-
|
1878
|
-
|
1809
|
+
title: dialog.title,
|
1810
|
+
message: dialog.content,
|
1811
|
+
type: dialog.status,
|
1812
|
+
timeout: dialog.timeout,
|
1813
|
+
onClose: dialog.onClose
|
1879
1814
|
});
|
1880
|
-
|
1881
|
-
|
1882
|
-
|
1883
|
-
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1888
|
-
|
1889
|
-
|
1890
|
-
|
1891
|
-
|
1892
|
-
|
1893
|
-
|
1894
|
-
|
1895
|
-
|
1896
|
-
|
1897
|
-
|
1898
|
-
|
1899
|
-
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
|
1908
|
-
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
1912
|
-
|
1913
|
-
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
1917
|
-
|
1918
|
-
|
1919
|
-
|
1920
|
-
|
1921
|
-
);
|
1922
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1923
|
-
navigate(
|
1924
|
-
{
|
1925
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1926
|
-
search: rawQuery
|
1927
|
-
},
|
1928
|
-
{ replace: true }
|
1929
|
-
);
|
1930
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1931
|
-
setErrors(formatValidationErrors(res.error));
|
1932
|
-
}
|
1933
|
-
}
|
1934
|
-
} finally {
|
1935
|
-
setSubmitting(false);
|
1815
|
+
break;
|
1816
|
+
case "dialog":
|
1817
|
+
case "modal":
|
1818
|
+
e.preventDefault();
|
1819
|
+
setDialogId(id);
|
1820
|
+
}
|
1821
|
+
}
|
1822
|
+
};
|
1823
|
+
const handleClose = () => {
|
1824
|
+
setDialogId(null);
|
1825
|
+
};
|
1826
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
1827
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1828
|
+
designSystem.Button,
|
1829
|
+
{
|
1830
|
+
flex: "auto",
|
1831
|
+
startIcon: action.icon,
|
1832
|
+
disabled: action.disabled,
|
1833
|
+
onClick: handleClick(action),
|
1834
|
+
justifyContent: "center",
|
1835
|
+
variant: action.variant || "default",
|
1836
|
+
paddingTop: "7px",
|
1837
|
+
paddingBottom: "7px",
|
1838
|
+
children: action.label
|
1839
|
+
}
|
1840
|
+
),
|
1841
|
+
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1842
|
+
DocumentActionConfirmDialog,
|
1843
|
+
{
|
1844
|
+
...action.dialog,
|
1845
|
+
variant: action.dialog?.variant ?? action.variant,
|
1846
|
+
isOpen: dialogId === action.id,
|
1847
|
+
onClose: handleClose
|
1848
|
+
}
|
1849
|
+
) : null,
|
1850
|
+
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1851
|
+
DocumentActionModal,
|
1852
|
+
{
|
1853
|
+
...action.dialog,
|
1854
|
+
onModalClose: handleClose,
|
1855
|
+
isOpen: dialogId === action.id
|
1936
1856
|
}
|
1937
|
-
|
1938
|
-
};
|
1939
|
-
};
|
1940
|
-
UpdateAction.type = "update";
|
1941
|
-
const UNPUBLISH_DRAFT_OPTIONS = {
|
1942
|
-
KEEP: "keep",
|
1943
|
-
DISCARD: "discard"
|
1857
|
+
) : null
|
1858
|
+
] });
|
1944
1859
|
};
|
1945
|
-
const
|
1946
|
-
|
1947
|
-
|
1948
|
-
|
1949
|
-
|
1950
|
-
document
|
1860
|
+
const DocumentActionsMenu = ({
|
1861
|
+
actions: actions2,
|
1862
|
+
children,
|
1863
|
+
label,
|
1864
|
+
variant = "tertiary"
|
1951
1865
|
}) => {
|
1866
|
+
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
1867
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1952
1868
|
const { formatMessage } = reactIntl.useIntl();
|
1953
|
-
const { schema } = useDoc();
|
1954
|
-
const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
1955
|
-
const { unpublish } = useDocumentActions();
|
1956
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
1957
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1958
1869
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1959
|
-
const
|
1960
|
-
const
|
1961
|
-
|
1962
|
-
|
1963
|
-
|
1964
|
-
|
1965
|
-
|
1966
|
-
}
|
1967
|
-
return {
|
1968
|
-
disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
|
1969
|
-
label: formatMessage({
|
1970
|
-
id: "app.utils.unpublish",
|
1971
|
-
defaultMessage: "Unpublish"
|
1972
|
-
}),
|
1973
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
|
1974
|
-
onClick: async () => {
|
1975
|
-
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
1976
|
-
if (!documentId) {
|
1977
|
-
console.error(
|
1978
|
-
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
1979
|
-
);
|
1870
|
+
const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
|
1871
|
+
const handleClick = (action) => async (e) => {
|
1872
|
+
const { onClick = () => false, dialog, id } = action;
|
1873
|
+
const muteDialog = await onClick(e);
|
1874
|
+
if (dialog && !muteDialog) {
|
1875
|
+
switch (dialog.type) {
|
1876
|
+
case "notification":
|
1980
1877
|
toggleNotification({
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1878
|
+
title: dialog.title,
|
1879
|
+
message: dialog.content,
|
1880
|
+
type: dialog.status,
|
1881
|
+
timeout: dialog.timeout,
|
1882
|
+
onClose: dialog.onClose
|
1986
1883
|
});
|
1987
|
-
|
1988
|
-
|
1884
|
+
break;
|
1885
|
+
case "dialog":
|
1886
|
+
case "modal":
|
1887
|
+
setDialogId(id);
|
1989
1888
|
}
|
1990
|
-
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
1995
|
-
|
1996
|
-
|
1997
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
|
2001
|
-
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
2007
|
-
|
2008
|
-
|
1889
|
+
}
|
1890
|
+
};
|
1891
|
+
const handleClose = () => {
|
1892
|
+
setDialogId(null);
|
1893
|
+
setIsOpen(false);
|
1894
|
+
};
|
1895
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1896
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1897
|
+
designSystem.Menu.Trigger,
|
1898
|
+
{
|
1899
|
+
disabled: isDisabled,
|
1900
|
+
size: "S",
|
1901
|
+
endIcon: null,
|
1902
|
+
paddingTop: "4px",
|
1903
|
+
paddingLeft: "7px",
|
1904
|
+
paddingRight: "7px",
|
1905
|
+
variant,
|
1906
|
+
children: [
|
1907
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
1908
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1909
|
+
id: "content-manager.containers.edit.panels.default.more-actions",
|
1910
|
+
defaultMessage: "More document actions"
|
2009
1911
|
}) })
|
2010
|
-
]
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
2016
|
-
|
2017
|
-
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2018
|
-
defaultMessage: "Choose an option to unpublish the document."
|
2019
|
-
}),
|
2020
|
-
onValueChange: handleChange,
|
2021
|
-
children: [
|
2022
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2023
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2024
|
-
defaultMessage: "Keep draft"
|
2025
|
-
}) }),
|
2026
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2027
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2028
|
-
defaultMessage: "Replace draft"
|
2029
|
-
}) })
|
2030
|
-
]
|
2031
|
-
}
|
2032
|
-
)
|
2033
|
-
] }),
|
2034
|
-
onConfirm: async () => {
|
2035
|
-
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2036
|
-
console.error(
|
2037
|
-
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2038
|
-
);
|
2039
|
-
toggleNotification({
|
2040
|
-
message: formatMessage({
|
2041
|
-
id: "content-manager.actions.unpublish.error",
|
2042
|
-
defaultMessage: "An error occurred while trying to unpublish the document."
|
2043
|
-
}),
|
2044
|
-
type: "danger"
|
2045
|
-
});
|
2046
|
-
}
|
2047
|
-
await unpublish(
|
1912
|
+
]
|
1913
|
+
}
|
1914
|
+
),
|
1915
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1916
|
+
actions2.map((action) => {
|
1917
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
1918
|
+
designSystem.Menu.Item,
|
2048
1919
|
{
|
2049
|
-
|
2050
|
-
|
2051
|
-
|
2052
|
-
|
1920
|
+
disabled: action.disabled,
|
1921
|
+
onSelect: handleClick(action),
|
1922
|
+
display: "block",
|
1923
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
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
|
+
),
|
1943
|
+
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1944
|
+
designSystem.Flex,
|
1945
|
+
{
|
1946
|
+
alignItems: "center",
|
1947
|
+
background: "alternative100",
|
1948
|
+
borderStyle: "solid",
|
1949
|
+
borderColor: "alternative200",
|
1950
|
+
borderWidth: "1px",
|
1951
|
+
height: 5,
|
1952
|
+
paddingLeft: 2,
|
1953
|
+
paddingRight: 2,
|
1954
|
+
hasRadius: true,
|
1955
|
+
color: "alternative600",
|
1956
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1957
|
+
}
|
1958
|
+
)
|
1959
|
+
] })
|
2053
1960
|
},
|
2054
|
-
|
1961
|
+
action.id
|
2055
1962
|
);
|
2056
|
-
}
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
1963
|
+
}),
|
1964
|
+
children
|
1965
|
+
] }),
|
1966
|
+
actions2.map((action) => {
|
1967
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
1968
|
+
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1969
|
+
DocumentActionConfirmDialog,
|
1970
|
+
{
|
1971
|
+
...action.dialog,
|
1972
|
+
variant: action.variant,
|
1973
|
+
isOpen: dialogId === action.id,
|
1974
|
+
onClose: handleClose
|
1975
|
+
}
|
1976
|
+
) : null,
|
1977
|
+
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1978
|
+
DocumentActionModal,
|
1979
|
+
{
|
1980
|
+
...action.dialog,
|
1981
|
+
onModalClose: handleClose,
|
1982
|
+
isOpen: dialogId === action.id
|
1983
|
+
}
|
1984
|
+
) : null
|
1985
|
+
] }, action.id);
|
1986
|
+
})
|
1987
|
+
] });
|
1988
|
+
};
|
1989
|
+
const convertActionVariantToColor = (variant = "secondary") => {
|
1990
|
+
switch (variant) {
|
1991
|
+
case "danger":
|
1992
|
+
return "danger600";
|
1993
|
+
case "secondary":
|
1994
|
+
return void 0;
|
1995
|
+
case "success":
|
1996
|
+
return "success600";
|
1997
|
+
default:
|
1998
|
+
return "primary600";
|
1999
|
+
}
|
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
|
+
};
|
2013
|
+
const DocumentActionConfirmDialog = ({
|
2014
|
+
onClose,
|
2015
|
+
onCancel,
|
2016
|
+
onConfirm,
|
2017
|
+
title,
|
2018
|
+
content,
|
2019
|
+
isOpen,
|
2020
|
+
variant = "secondary"
|
2021
|
+
}) => {
|
2022
|
+
const { formatMessage } = reactIntl.useIntl();
|
2023
|
+
const handleClose = async () => {
|
2024
|
+
if (onCancel) {
|
2025
|
+
await onCancel();
|
2026
|
+
}
|
2027
|
+
onClose();
|
2060
2028
|
};
|
2029
|
+
const handleConfirm = async () => {
|
2030
|
+
if (onConfirm) {
|
2031
|
+
await onConfirm();
|
2032
|
+
}
|
2033
|
+
onClose();
|
2034
|
+
};
|
2035
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2036
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2037
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
2038
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
2039
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
2040
|
+
id: "app.components.Button.cancel",
|
2041
|
+
defaultMessage: "Cancel"
|
2042
|
+
}) }) }),
|
2043
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
2044
|
+
id: "app.components.Button.confirm",
|
2045
|
+
defaultMessage: "Confirm"
|
2046
|
+
}) })
|
2047
|
+
] })
|
2048
|
+
] }) });
|
2061
2049
|
};
|
2062
|
-
|
2063
|
-
|
2050
|
+
const DocumentActionModal = ({
|
2051
|
+
isOpen,
|
2052
|
+
title,
|
2053
|
+
onClose,
|
2054
|
+
footer: Footer,
|
2055
|
+
content: Content,
|
2056
|
+
onModalClose
|
2057
|
+
}) => {
|
2058
|
+
const handleClose = () => {
|
2059
|
+
if (onClose) {
|
2060
|
+
onClose();
|
2061
|
+
}
|
2062
|
+
onModalClose();
|
2063
|
+
};
|
2064
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
2065
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
2066
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
|
2067
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
2068
|
+
] }) });
|
2069
|
+
};
|
2070
|
+
const PublishAction$1 = ({
|
2064
2071
|
activeTab,
|
2065
2072
|
documentId,
|
2066
2073
|
model,
|
2067
2074
|
collectionType,
|
2075
|
+
meta,
|
2068
2076
|
document
|
2069
2077
|
}) => {
|
2070
|
-
const { formatMessage } = reactIntl.useIntl();
|
2071
2078
|
const { schema } = useDoc();
|
2072
|
-
const
|
2073
|
-
const {
|
2074
|
-
const
|
2075
|
-
const
|
2076
|
-
if (!schema?.options?.draftAndPublish) {
|
2077
|
-
return null;
|
2078
|
-
}
|
2079
|
-
return {
|
2080
|
-
disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
|
2081
|
-
label: formatMessage({
|
2082
|
-
id: "content-manager.actions.discard.label",
|
2083
|
-
defaultMessage: "Discard changes"
|
2084
|
-
}),
|
2085
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
|
2086
|
-
position: ["panel", "table-row"],
|
2087
|
-
variant: "danger",
|
2088
|
-
dialog: {
|
2089
|
-
type: "dialog",
|
2090
|
-
title: formatMessage({
|
2091
|
-
id: "app.components.ConfirmDialog.title",
|
2092
|
-
defaultMessage: "Confirmation"
|
2093
|
-
}),
|
2094
|
-
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2095
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2096
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2097
|
-
id: "content-manager.actions.discard.dialog.body",
|
2098
|
-
defaultMessage: "Are you sure?"
|
2099
|
-
}) })
|
2100
|
-
] }),
|
2101
|
-
onConfirm: async () => {
|
2102
|
-
await discard({
|
2103
|
-
collectionType,
|
2104
|
-
model,
|
2105
|
-
documentId,
|
2106
|
-
params
|
2107
|
-
});
|
2108
|
-
}
|
2109
|
-
}
|
2110
|
-
};
|
2111
|
-
};
|
2112
|
-
DiscardAction.type = "discard";
|
2113
|
-
const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
|
2114
|
-
path {
|
2115
|
-
fill: currentColor;
|
2116
|
-
}
|
2117
|
-
`;
|
2118
|
-
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2119
|
-
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2120
|
-
const RelativeTime = React__namespace.forwardRef(
|
2121
|
-
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
2122
|
-
const { formatRelativeTime, formatDate, formatTime } = reactIntl.useIntl();
|
2123
|
-
const interval = dateFns.intervalToDuration({
|
2124
|
-
start: timestamp,
|
2125
|
-
end: Date.now()
|
2126
|
-
// see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
|
2127
|
-
});
|
2128
|
-
const unit = intervals.find((intervalUnit) => {
|
2129
|
-
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2130
|
-
});
|
2131
|
-
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2132
|
-
const customInterval = customIntervals.find(
|
2133
|
-
(custom) => interval[custom.unit] < custom.threshold
|
2134
|
-
);
|
2135
|
-
const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
|
2136
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
2137
|
-
"time",
|
2138
|
-
{
|
2139
|
-
ref: forwardedRef,
|
2140
|
-
dateTime: timestamp.toISOString(),
|
2141
|
-
role: "time",
|
2142
|
-
title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
|
2143
|
-
...restProps,
|
2144
|
-
children: displayText
|
2145
|
-
}
|
2146
|
-
);
|
2147
|
-
}
|
2148
|
-
);
|
2149
|
-
const getDisplayName = ({
|
2150
|
-
firstname,
|
2151
|
-
lastname,
|
2152
|
-
username,
|
2153
|
-
email
|
2154
|
-
} = {}) => {
|
2155
|
-
if (username) {
|
2156
|
-
return username;
|
2157
|
-
}
|
2158
|
-
if (firstname) {
|
2159
|
-
return `${firstname} ${lastname ?? ""}`.trim();
|
2160
|
-
}
|
2161
|
-
return email ?? "";
|
2162
|
-
};
|
2163
|
-
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2164
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2165
|
-
const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
|
2166
|
-
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) }) });
|
2167
|
-
};
|
2168
|
-
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2169
|
-
const { formatMessage } = reactIntl.useIntl();
|
2079
|
+
const navigate = reactRouterDom.useNavigate();
|
2080
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2081
|
+
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2082
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
2170
2083
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2171
|
-
const title = isCreating ? formatMessage({
|
2172
|
-
id: "content-manager.containers.edit.title.new",
|
2173
|
-
defaultMessage: "Create an entry"
|
2174
|
-
}) : documentTitle;
|
2175
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2176
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
2177
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2178
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2179
|
-
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2180
|
-
] }),
|
2181
|
-
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2182
|
-
] });
|
2183
|
-
};
|
2184
|
-
const HeaderToolbar = () => {
|
2185
2084
|
const { formatMessage } = reactIntl.useIntl();
|
2186
|
-
const
|
2085
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2086
|
+
const { publish } = useDocumentActions();
|
2187
2087
|
const [
|
2188
|
-
|
2189
|
-
|
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);
|
2093
|
+
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
2094
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2095
|
+
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
2096
|
+
const setSubmitting = strapiAdmin.useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
2097
|
+
const isSubmitting = strapiAdmin.useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
2098
|
+
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
2099
|
+
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
2100
|
+
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
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
|
+
});
|
2190
2110
|
}
|
2191
|
-
|
2192
|
-
|
2193
|
-
|
2194
|
-
|
2195
|
-
|
2196
|
-
|
2197
|
-
|
2198
|
-
|
2199
|
-
activeTab: status,
|
2200
|
-
model,
|
2201
|
-
documentId: id,
|
2202
|
-
document: isCloning ? void 0 : document,
|
2203
|
-
meta: isCloning ? void 0 : meta,
|
2204
|
-
collectionType
|
2205
|
-
},
|
2206
|
-
descriptions: plugins["content-manager"].apis.getHeaderActions(),
|
2207
|
-
children: (actions2) => {
|
2208
|
-
if (actions2.length > 0) {
|
2209
|
-
return /* @__PURE__ */ jsxRuntime.jsx(HeaderActions, { actions: actions2 });
|
2210
|
-
} else {
|
2211
|
-
return null;
|
2212
|
-
}
|
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);
|
2213
2119
|
}
|
2214
|
-
}
|
2215
|
-
|
2216
|
-
|
2217
|
-
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2221
|
-
|
2222
|
-
documentId: id,
|
2223
|
-
document: isCloning ? void 0 : document,
|
2224
|
-
meta: isCloning ? void 0 : meta,
|
2225
|
-
collectionType
|
2226
|
-
},
|
2227
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2228
|
-
children: (actions2) => {
|
2229
|
-
const headerActions = actions2.filter((action) => {
|
2230
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2231
|
-
return positions.includes("header");
|
2232
|
-
});
|
2233
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
2234
|
-
DocumentActionsMenu,
|
2235
|
-
{
|
2236
|
-
actions: headerActions,
|
2237
|
-
label: formatMessage({
|
2238
|
-
id: "content-manager.containers.edit.header.more-actions",
|
2239
|
-
defaultMessage: "More actions"
|
2240
|
-
}),
|
2241
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(Information, { activeTab: status })
|
2242
|
-
}
|
2243
|
-
);
|
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);
|
2244
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;
|
2245
2149
|
}
|
2246
|
-
|
2247
|
-
|
2248
|
-
}
|
2249
|
-
|
2250
|
-
|
2251
|
-
|
2252
|
-
|
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) {
|
2253
2158
|
return null;
|
2254
2159
|
}
|
2255
|
-
const
|
2256
|
-
|
2257
|
-
|
2258
|
-
|
2259
|
-
|
2260
|
-
|
2261
|
-
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
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(
|
2267
2175
|
{
|
2268
|
-
|
2269
|
-
|
2176
|
+
collectionType,
|
2177
|
+
model,
|
2178
|
+
documentId,
|
2179
|
+
params
|
2270
2180
|
},
|
2271
|
-
|
2272
|
-
|
2273
|
-
|
2274
|
-
|
2275
|
-
|
2276
|
-
|
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;
|
2198
|
+
return {
|
2199
|
+
/**
|
2200
|
+
* Disabled when:
|
2201
|
+
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
2202
|
+
* - the form is submitting
|
2203
|
+
* - the active tab is the published tab
|
2204
|
+
* - the document is already published & not modified
|
2205
|
+
* - the document is being created & not modified
|
2206
|
+
* - the user doesn't have the permission to publish
|
2207
|
+
*/
|
2208
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
2209
|
+
label: formatMessage({
|
2210
|
+
id: "app.utils.publish",
|
2211
|
+
defaultMessage: "Publish"
|
2212
|
+
}),
|
2213
|
+
onClick: async () => {
|
2214
|
+
await performPublish();
|
2277
2215
|
},
|
2278
|
-
{
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
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"
|
2283
2223
|
}),
|
2284
|
-
|
2224
|
+
content: formatMessage(
|
2285
2225
|
{
|
2286
|
-
id:
|
2287
|
-
defaultMessage:
|
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."
|
2288
2228
|
},
|
2289
2229
|
{
|
2290
|
-
|
2291
|
-
RelativeTime,
|
2292
|
-
{
|
2293
|
-
timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
|
2294
|
-
}
|
2295
|
-
),
|
2296
|
-
isAnonymous: !updator,
|
2297
|
-
author: updator
|
2230
|
+
count: totalDraftRelations
|
2298
2231
|
}
|
2299
|
-
)
|
2300
|
-
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2306
|
-
|
2307
|
-
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2315
|
-
|
2316
|
-
|
2317
|
-
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
2232
|
+
),
|
2233
|
+
onConfirm: async () => {
|
2234
|
+
await performPublish();
|
2235
|
+
}
|
2236
|
+
} : void 0
|
2237
|
+
};
|
2238
|
+
};
|
2239
|
+
PublishAction$1.type = "publish";
|
2240
|
+
const UpdateAction = ({
|
2241
|
+
activeTab,
|
2242
|
+
documentId,
|
2243
|
+
model,
|
2244
|
+
collectionType
|
2245
|
+
}) => {
|
2246
|
+
const navigate = reactRouterDom.useNavigate();
|
2247
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2248
|
+
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2249
|
+
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
2250
|
+
const isCloning = cloneMatch !== null;
|
2251
|
+
const { formatMessage } = reactIntl.useIntl();
|
2252
|
+
const { create, update, clone } = useDocumentActions();
|
2253
|
+
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
2254
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2255
|
+
const isSubmitting = strapiAdmin.useForm("UpdateAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
2256
|
+
const modified = strapiAdmin.useForm("UpdateAction", ({ modified: modified2 }) => modified2);
|
2257
|
+
const setSubmitting = strapiAdmin.useForm("UpdateAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
2258
|
+
const document = strapiAdmin.useForm("UpdateAction", ({ values }) => values);
|
2259
|
+
const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
|
2260
|
+
const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
|
2261
|
+
const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
2262
|
+
return {
|
2263
|
+
/**
|
2264
|
+
* Disabled when:
|
2265
|
+
* - the form is submitting
|
2266
|
+
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
2267
|
+
* - the active tab is the published tab
|
2268
|
+
*/
|
2269
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
2270
|
+
label: formatMessage({
|
2271
|
+
id: "content-manager.containers.Edit.save",
|
2272
|
+
defaultMessage: "Save"
|
2273
|
+
}),
|
2274
|
+
onClick: async () => {
|
2275
|
+
setSubmitting(true);
|
2276
|
+
try {
|
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
|
+
}
|
2321
2289
|
}
|
2322
|
-
|
2323
|
-
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2327
|
-
|
2328
|
-
|
2329
|
-
|
2330
|
-
|
2331
|
-
|
2332
|
-
|
2333
|
-
|
2334
|
-
|
2335
|
-
|
2336
|
-
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2290
|
+
if (isCloning) {
|
2291
|
+
const res = await clone(
|
2292
|
+
{
|
2293
|
+
model,
|
2294
|
+
documentId: cloneMatch.params.origin,
|
2295
|
+
params
|
2296
|
+
},
|
2297
|
+
document
|
2298
|
+
);
|
2299
|
+
if ("data" in res) {
|
2300
|
+
navigate(
|
2301
|
+
{
|
2302
|
+
pathname: `../${res.data.documentId}`,
|
2303
|
+
search: rawQuery
|
2304
|
+
},
|
2305
|
+
{ relative: "path" }
|
2306
|
+
);
|
2307
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2308
|
+
setErrors(formatValidationErrors(res.error));
|
2309
|
+
}
|
2310
|
+
} else if (documentId || collectionType === SINGLE_TYPES) {
|
2311
|
+
const res = await update(
|
2312
|
+
{
|
2313
|
+
collectionType,
|
2314
|
+
model,
|
2315
|
+
documentId,
|
2316
|
+
params
|
2317
|
+
},
|
2318
|
+
document
|
2319
|
+
);
|
2320
|
+
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2321
|
+
setErrors(formatValidationErrors(res.error));
|
2322
|
+
} else {
|
2323
|
+
resetForm();
|
2324
|
+
}
|
2325
|
+
} else {
|
2326
|
+
const res = await create(
|
2327
|
+
{
|
2328
|
+
model,
|
2329
|
+
params
|
2330
|
+
},
|
2331
|
+
document
|
2332
|
+
);
|
2333
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2334
|
+
navigate(
|
2335
|
+
{
|
2336
|
+
pathname: `../${res.data.documentId}`,
|
2337
|
+
search: rawQuery
|
2338
|
+
},
|
2339
|
+
{ replace: true, relative: "path" }
|
2340
|
+
);
|
2341
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2342
|
+
setErrors(formatValidationErrors(res.error));
|
2343
|
+
}
|
2344
|
+
}
|
2345
|
+
} finally {
|
2346
|
+
setSubmitting(false);
|
2347
|
+
}
|
2344
2348
|
}
|
2345
|
-
|
2349
|
+
};
|
2346
2350
|
};
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
designSystem.SingleSelect,
|
2352
|
-
{
|
2353
|
-
size: "S",
|
2354
|
-
disabled: action.disabled,
|
2355
|
-
"aria-label": action.label,
|
2356
|
-
onChange: action.onSelect,
|
2357
|
-
value: action.value,
|
2358
|
-
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2359
|
-
},
|
2360
|
-
action.id
|
2361
|
-
);
|
2362
|
-
} else {
|
2363
|
-
return null;
|
2364
|
-
}
|
2365
|
-
}) });
|
2351
|
+
UpdateAction.type = "update";
|
2352
|
+
const UNPUBLISH_DRAFT_OPTIONS = {
|
2353
|
+
KEEP: "keep",
|
2354
|
+
DISCARD: "discard"
|
2366
2355
|
};
|
2367
|
-
const
|
2368
|
-
|
2356
|
+
const UnpublishAction$1 = ({
|
2357
|
+
activeTab,
|
2358
|
+
documentId,
|
2359
|
+
model,
|
2360
|
+
collectionType,
|
2361
|
+
document
|
2362
|
+
}) => {
|
2369
2363
|
const { formatMessage } = reactIntl.useIntl();
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2364
|
+
const { schema } = useDoc();
|
2365
|
+
const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2366
|
+
const { unpublish } = useDocumentActions();
|
2367
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
2368
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2369
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2370
|
+
const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
|
2371
|
+
const isDocumentModified = document?.status === "modified";
|
2372
|
+
const handleChange = (value) => {
|
2373
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
2380
2374
|
};
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
const navigate = reactRouterDom.useNavigate();
|
2385
|
-
const { formatMessage } = reactIntl.useIntl();
|
2375
|
+
if (!schema?.options?.draftAndPublish) {
|
2376
|
+
return null;
|
2377
|
+
}
|
2386
2378
|
return {
|
2379
|
+
disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
|
2387
2380
|
label: formatMessage({
|
2388
|
-
id: "
|
2389
|
-
defaultMessage: "
|
2381
|
+
id: "app.utils.unpublish",
|
2382
|
+
defaultMessage: "Unpublish"
|
2390
2383
|
}),
|
2391
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.
|
2392
|
-
onClick: () => {
|
2393
|
-
|
2384
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2385
|
+
onClick: async () => {
|
2386
|
+
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2387
|
+
if (!documentId) {
|
2388
|
+
console.error(
|
2389
|
+
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2390
|
+
);
|
2391
|
+
toggleNotification({
|
2392
|
+
message: formatMessage({
|
2393
|
+
id: "content-manager.actions.unpublish.error",
|
2394
|
+
defaultMessage: "An error occurred while trying to unpublish the document."
|
2395
|
+
}),
|
2396
|
+
type: "danger"
|
2397
|
+
});
|
2398
|
+
}
|
2399
|
+
return;
|
2400
|
+
}
|
2401
|
+
await unpublish({
|
2402
|
+
collectionType,
|
2403
|
+
model,
|
2404
|
+
documentId,
|
2405
|
+
params
|
2406
|
+
});
|
2394
2407
|
},
|
2395
|
-
|
2408
|
+
dialog: isDocumentModified ? {
|
2409
|
+
type: "dialog",
|
2410
|
+
title: formatMessage({
|
2411
|
+
id: "app.components.ConfirmDialog.title",
|
2412
|
+
defaultMessage: "Confirmation"
|
2413
|
+
}),
|
2414
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
|
2415
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
|
2416
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2417
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2418
|
+
id: "content-manager.actions.unpublish.dialog.body",
|
2419
|
+
defaultMessage: "Are you sure?"
|
2420
|
+
}) })
|
2421
|
+
] }),
|
2422
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
2423
|
+
designSystem.Radio.Group,
|
2424
|
+
{
|
2425
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2426
|
+
name: "discard-options",
|
2427
|
+
"aria-label": formatMessage({
|
2428
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2429
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2430
|
+
}),
|
2431
|
+
onValueChange: handleChange,
|
2432
|
+
children: [
|
2433
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2434
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2435
|
+
defaultMessage: "Keep draft"
|
2436
|
+
}) }),
|
2437
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2438
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2439
|
+
defaultMessage: "Replace draft"
|
2440
|
+
}) })
|
2441
|
+
]
|
2442
|
+
}
|
2443
|
+
)
|
2444
|
+
] }),
|
2445
|
+
onConfirm: async () => {
|
2446
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2447
|
+
console.error(
|
2448
|
+
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2449
|
+
);
|
2450
|
+
toggleNotification({
|
2451
|
+
message: formatMessage({
|
2452
|
+
id: "content-manager.actions.unpublish.error",
|
2453
|
+
defaultMessage: "An error occurred while trying to unpublish the document."
|
2454
|
+
}),
|
2455
|
+
type: "danger"
|
2456
|
+
});
|
2457
|
+
}
|
2458
|
+
await unpublish(
|
2459
|
+
{
|
2460
|
+
collectionType,
|
2461
|
+
model,
|
2462
|
+
documentId,
|
2463
|
+
params
|
2464
|
+
},
|
2465
|
+
!shouldKeepDraft
|
2466
|
+
);
|
2467
|
+
}
|
2468
|
+
} : void 0,
|
2469
|
+
variant: "danger",
|
2470
|
+
position: ["panel", "table-row"]
|
2396
2471
|
};
|
2397
2472
|
};
|
2398
|
-
|
2399
|
-
const
|
2400
|
-
|
2473
|
+
UnpublishAction$1.type = "unpublish";
|
2474
|
+
const DiscardAction = ({
|
2475
|
+
activeTab,
|
2476
|
+
documentId,
|
2477
|
+
model,
|
2478
|
+
collectionType,
|
2479
|
+
document
|
2480
|
+
}) => {
|
2401
2481
|
const { formatMessage } = reactIntl.useIntl();
|
2402
|
-
const
|
2403
|
-
const
|
2404
|
-
const {
|
2405
|
-
const {
|
2406
|
-
const
|
2482
|
+
const { schema } = useDoc();
|
2483
|
+
const canUpdate = useDocumentRBAC("DiscardAction", ({ canUpdate: canUpdate2 }) => canUpdate2);
|
2484
|
+
const { discard } = useDocumentActions();
|
2485
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
2486
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2487
|
+
if (!schema?.options?.draftAndPublish) {
|
2488
|
+
return null;
|
2489
|
+
}
|
2407
2490
|
return {
|
2408
|
-
disabled: !
|
2491
|
+
disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
|
2409
2492
|
label: formatMessage({
|
2410
|
-
id: "content-manager.actions.
|
2411
|
-
defaultMessage: "
|
2493
|
+
id: "content-manager.actions.discard.label",
|
2494
|
+
defaultMessage: "Discard changes"
|
2412
2495
|
}),
|
2413
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.
|
2496
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2497
|
+
position: ["panel", "table-row"],
|
2498
|
+
variant: "danger",
|
2414
2499
|
dialog: {
|
2415
2500
|
type: "dialog",
|
2416
2501
|
title: formatMessage({
|
@@ -2420,92 +2505,90 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2420
2505
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2421
2506
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2422
2507
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2423
|
-
id: "content-manager.actions.
|
2508
|
+
id: "content-manager.actions.discard.dialog.body",
|
2424
2509
|
defaultMessage: "Are you sure?"
|
2425
2510
|
}) })
|
2426
2511
|
] }),
|
2427
2512
|
onConfirm: async () => {
|
2428
|
-
|
2429
|
-
|
2430
|
-
|
2431
|
-
|
2432
|
-
|
2433
|
-
|
2434
|
-
|
2435
|
-
|
2436
|
-
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2442
|
-
|
2443
|
-
|
2444
|
-
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2452
|
-
|
2453
|
-
|
2454
|
-
|
2455
|
-
|
2456
|
-
|
2457
|
-
|
2458
|
-
|
2459
|
-
|
2460
|
-
|
2513
|
+
await discard({
|
2514
|
+
collectionType,
|
2515
|
+
model,
|
2516
|
+
documentId,
|
2517
|
+
params
|
2518
|
+
});
|
2519
|
+
}
|
2520
|
+
}
|
2521
|
+
};
|
2522
|
+
};
|
2523
|
+
DiscardAction.type = "discard";
|
2524
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2525
|
+
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2526
|
+
const RelativeTime = React__namespace.forwardRef(
|
2527
|
+
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
2528
|
+
const { formatRelativeTime, formatDate, formatTime } = reactIntl.useIntl();
|
2529
|
+
const interval = dateFns.intervalToDuration({
|
2530
|
+
start: timestamp,
|
2531
|
+
end: Date.now()
|
2532
|
+
// see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
|
2533
|
+
});
|
2534
|
+
const unit = intervals.find((intervalUnit) => {
|
2535
|
+
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2536
|
+
});
|
2537
|
+
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2538
|
+
const customInterval = customIntervals.find(
|
2539
|
+
(custom) => interval[custom.unit] < custom.threshold
|
2540
|
+
);
|
2541
|
+
const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
|
2542
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2543
|
+
"time",
|
2544
|
+
{
|
2545
|
+
ref: forwardedRef,
|
2546
|
+
dateTime: timestamp.toISOString(),
|
2547
|
+
role: "time",
|
2548
|
+
title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
|
2549
|
+
...restProps,
|
2550
|
+
children: displayText
|
2461
2551
|
}
|
2462
|
-
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
2552
|
+
);
|
2553
|
+
}
|
2554
|
+
);
|
2555
|
+
const getDisplayName = ({
|
2556
|
+
firstname,
|
2557
|
+
lastname,
|
2558
|
+
username,
|
2559
|
+
email
|
2560
|
+
} = {}) => {
|
2561
|
+
if (username) {
|
2562
|
+
return username;
|
2563
|
+
}
|
2564
|
+
if (firstname) {
|
2565
|
+
return `${firstname} ${lastname ?? ""}`.trim();
|
2566
|
+
}
|
2567
|
+
return email ?? "";
|
2466
2568
|
};
|
2467
|
-
|
2468
|
-
const
|
2469
|
-
const
|
2470
|
-
|
2471
|
-
const [
|
2472
|
-
{
|
2473
|
-
query: { status }
|
2474
|
-
}
|
2475
|
-
] = strapiAdmin.useQueryParams({
|
2476
|
-
status: "draft"
|
2477
|
-
});
|
2478
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2479
|
-
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2480
|
-
const props = {
|
2481
|
-
activeTab: status,
|
2482
|
-
model,
|
2483
|
-
documentId: id,
|
2484
|
-
document: isCloning ? void 0 : document,
|
2485
|
-
meta: isCloning ? void 0 : meta,
|
2486
|
-
collectionType
|
2487
|
-
};
|
2488
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2489
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2490
|
-
{
|
2491
|
-
props,
|
2492
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2493
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2494
|
-
}
|
2495
|
-
) });
|
2569
|
+
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2570
|
+
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2571
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
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) }) });
|
2496
2573
|
};
|
2497
|
-
const
|
2574
|
+
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2498
2575
|
const { formatMessage } = reactIntl.useIntl();
|
2499
|
-
|
2500
|
-
|
2501
|
-
|
2502
|
-
|
2503
|
-
|
2504
|
-
|
2505
|
-
|
2576
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2577
|
+
const title = isCreating ? formatMessage({
|
2578
|
+
id: "content-manager.containers.edit.title.new",
|
2579
|
+
defaultMessage: "Create an entry"
|
2580
|
+
}) : documentTitle;
|
2581
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2582
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
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
|
2588
|
+
] });
|
2506
2589
|
};
|
2507
|
-
|
2508
|
-
const
|
2590
|
+
const HeaderToolbar = () => {
|
2591
|
+
const { formatMessage } = reactIntl.useIntl();
|
2509
2592
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2510
2593
|
const [
|
2511
2594
|
{
|
@@ -2513,355 +2596,432 @@ const ActionsPanelContent = () => {
|
|
2513
2596
|
}
|
2514
2597
|
] = strapiAdmin.useQueryParams();
|
2515
2598
|
const { model, id, document, meta, collectionType } = useDoc();
|
2516
|
-
const plugins = strapiAdmin.useStrapiApp("
|
2517
|
-
|
2518
|
-
activeTab: status,
|
2519
|
-
model,
|
2520
|
-
documentId: id,
|
2521
|
-
document: isCloning ? void 0 : document,
|
2522
|
-
meta: isCloning ? void 0 : meta,
|
2523
|
-
collectionType
|
2524
|
-
};
|
2525
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2599
|
+
const plugins = strapiAdmin.useStrapiApp("HeaderToolbar", (state) => state.plugins);
|
2600
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
2526
2601
|
/* @__PURE__ */ jsxRuntime.jsx(
|
2527
2602
|
strapiAdmin.DescriptionComponentRenderer,
|
2528
2603
|
{
|
2529
|
-
props
|
2530
|
-
|
2531
|
-
|
2604
|
+
props: {
|
2605
|
+
activeTab: status,
|
2606
|
+
model,
|
2607
|
+
documentId: id,
|
2608
|
+
document: isCloning ? void 0 : document,
|
2609
|
+
meta: isCloning ? void 0 : meta,
|
2610
|
+
collectionType
|
2611
|
+
},
|
2612
|
+
descriptions: plugins["content-manager"].apis.getHeaderActions(),
|
2613
|
+
children: (actions2) => {
|
2614
|
+
if (actions2.length > 0) {
|
2615
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HeaderActions, { actions: actions2 });
|
2616
|
+
} else {
|
2617
|
+
return null;
|
2618
|
+
}
|
2619
|
+
}
|
2532
2620
|
}
|
2533
2621
|
),
|
2534
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2622
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2623
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2624
|
+
{
|
2625
|
+
props: {
|
2626
|
+
activeTab: status,
|
2627
|
+
model,
|
2628
|
+
documentId: id,
|
2629
|
+
document: isCloning ? void 0 : document,
|
2630
|
+
meta: isCloning ? void 0 : meta,
|
2631
|
+
collectionType
|
2632
|
+
},
|
2633
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2634
|
+
children: (actions2) => {
|
2635
|
+
const headerActions = actions2.filter((action) => {
|
2636
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2637
|
+
return positions.includes("header");
|
2638
|
+
});
|
2639
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2640
|
+
DocumentActionsMenu,
|
2641
|
+
{
|
2642
|
+
actions: headerActions,
|
2643
|
+
label: formatMessage({
|
2644
|
+
id: "content-manager.containers.edit.header.more-actions",
|
2645
|
+
defaultMessage: "More actions"
|
2646
|
+
}),
|
2647
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Information, { activeTab: status })
|
2648
|
+
}
|
2649
|
+
);
|
2650
|
+
}
|
2651
|
+
}
|
2652
|
+
)
|
2535
2653
|
] });
|
2536
2654
|
};
|
2537
|
-
const
|
2538
|
-
|
2539
|
-
|
2655
|
+
const Information = ({ activeTab }) => {
|
2656
|
+
const { formatMessage } = reactIntl.useIntl();
|
2657
|
+
const { document, meta } = useDoc();
|
2658
|
+
if (!document || !document.id) {
|
2659
|
+
return null;
|
2660
|
+
}
|
2661
|
+
const createAndUpdateDocument = activeTab === "draft" ? document : meta?.availableStatus.find((status) => status.publishedAt === null);
|
2662
|
+
const publishDocument = activeTab === "published" ? document : meta?.availableStatus.find((status) => status.publishedAt !== null);
|
2663
|
+
const creator = createAndUpdateDocument?.[CREATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[CREATED_BY_ATTRIBUTE_NAME]) : null;
|
2664
|
+
const updator = createAndUpdateDocument?.[UPDATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[UPDATED_BY_ATTRIBUTE_NAME]) : null;
|
2665
|
+
const information = [
|
2540
2666
|
{
|
2541
|
-
|
2542
|
-
|
2543
|
-
|
2544
|
-
|
2545
|
-
borderColor: "neutral150",
|
2546
|
-
hasRadius: true,
|
2547
|
-
paddingBottom: 4,
|
2548
|
-
paddingLeft: 4,
|
2549
|
-
paddingRight: 4,
|
2550
|
-
paddingTop: 4,
|
2551
|
-
shadow: "tableShadow",
|
2552
|
-
gap: 3,
|
2553
|
-
direction: "column",
|
2554
|
-
justifyContent: "stretch",
|
2555
|
-
alignItems: "flex-start",
|
2556
|
-
children: [
|
2557
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2558
|
-
children
|
2559
|
-
]
|
2560
|
-
}
|
2561
|
-
);
|
2562
|
-
});
|
2563
|
-
const HOOKS = {
|
2564
|
-
/**
|
2565
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2566
|
-
* @constant
|
2567
|
-
* @type {string}
|
2568
|
-
*/
|
2569
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2570
|
-
/**
|
2571
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2572
|
-
* @constant
|
2573
|
-
* @type {string}
|
2574
|
-
*/
|
2575
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2576
|
-
/**
|
2577
|
-
* Hook that allows to mutate the CM's edit view layout
|
2578
|
-
* @constant
|
2579
|
-
* @type {string}
|
2580
|
-
*/
|
2581
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2582
|
-
/**
|
2583
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2584
|
-
* @constant
|
2585
|
-
* @type {string}
|
2586
|
-
*/
|
2587
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2588
|
-
};
|
2589
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2590
|
-
endpoints: (builder) => ({
|
2591
|
-
getContentTypeConfiguration: builder.query({
|
2592
|
-
query: (uid) => ({
|
2593
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2594
|
-
method: "GET"
|
2667
|
+
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2668
|
+
label: formatMessage({
|
2669
|
+
id: "content-manager.containers.edit.information.last-published.label",
|
2670
|
+
defaultMessage: "Last published"
|
2595
2671
|
}),
|
2596
|
-
|
2597
|
-
|
2598
|
-
|
2599
|
-
|
2600
|
-
|
2601
|
-
|
2602
|
-
|
2603
|
-
|
2604
|
-
|
2605
|
-
|
2606
|
-
|
2607
|
-
|
2608
|
-
|
2609
|
-
|
2610
|
-
|
2611
|
-
|
2672
|
+
value: formatMessage(
|
2673
|
+
{
|
2674
|
+
id: "content-manager.containers.edit.information.last-published.value",
|
2675
|
+
defaultMessage: `Published {time}{isAnonymous, select, true {} other { by {author}}}`
|
2676
|
+
},
|
2677
|
+
{
|
2678
|
+
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
2679
|
+
isAnonymous: !publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME],
|
2680
|
+
author: publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME] ? getDisplayName(publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME]) : null
|
2681
|
+
}
|
2682
|
+
)
|
2683
|
+
},
|
2684
|
+
{
|
2685
|
+
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2686
|
+
label: formatMessage({
|
2687
|
+
id: "content-manager.containers.edit.information.last-draft.label",
|
2688
|
+
defaultMessage: "Last draft"
|
2689
|
+
}),
|
2690
|
+
value: formatMessage(
|
2691
|
+
{
|
2692
|
+
id: "content-manager.containers.edit.information.last-draft.value",
|
2693
|
+
defaultMessage: `Modified {time}{isAnonymous, select, true {} other { by {author}}}`
|
2694
|
+
},
|
2695
|
+
{
|
2696
|
+
time: /* @__PURE__ */ jsxRuntime.jsx(
|
2697
|
+
RelativeTime,
|
2698
|
+
{
|
2699
|
+
timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
|
2700
|
+
}
|
2701
|
+
),
|
2702
|
+
isAnonymous: !updator,
|
2703
|
+
author: updator
|
2704
|
+
}
|
2705
|
+
)
|
2706
|
+
},
|
2707
|
+
{
|
2708
|
+
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2709
|
+
label: formatMessage({
|
2710
|
+
id: "content-manager.containers.edit.information.document.label",
|
2711
|
+
defaultMessage: "Document"
|
2612
2712
|
}),
|
2613
|
-
|
2614
|
-
|
2615
|
-
|
2616
|
-
|
2617
|
-
|
2618
|
-
{
|
2619
|
-
|
2620
|
-
|
2621
|
-
|
2622
|
-
|
2623
|
-
|
2624
|
-
|
2625
|
-
|
2626
|
-
|
2627
|
-
}
|
2628
|
-
|
2629
|
-
|
2630
|
-
|
2631
|
-
|
2632
|
-
|
2633
|
-
|
2634
|
-
|
2635
|
-
|
2636
|
-
|
2637
|
-
|
2638
|
-
|
2639
|
-
|
2640
|
-
|
2641
|
-
|
2713
|
+
value: formatMessage(
|
2714
|
+
{
|
2715
|
+
id: "content-manager.containers.edit.information.document.value",
|
2716
|
+
defaultMessage: `Created {time}{isAnonymous, select, true {} other { by {author}}}`
|
2717
|
+
},
|
2718
|
+
{
|
2719
|
+
time: /* @__PURE__ */ jsxRuntime.jsx(
|
2720
|
+
RelativeTime,
|
2721
|
+
{
|
2722
|
+
timestamp: new Date(createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME])
|
2723
|
+
}
|
2724
|
+
),
|
2725
|
+
isAnonymous: !creator,
|
2726
|
+
author: creator
|
2727
|
+
}
|
2728
|
+
)
|
2729
|
+
}
|
2730
|
+
].filter((info) => info.isDisplayed);
|
2731
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2732
|
+
designSystem.Flex,
|
2733
|
+
{
|
2734
|
+
borderWidth: "1px 0 0 0",
|
2735
|
+
borderStyle: "solid",
|
2736
|
+
borderColor: "neutral150",
|
2737
|
+
direction: "column",
|
2738
|
+
marginTop: 2,
|
2739
|
+
tag: "dl",
|
2740
|
+
padding: 5,
|
2741
|
+
gap: 3,
|
2742
|
+
alignItems: "flex-start",
|
2743
|
+
marginLeft: "-0.4rem",
|
2744
|
+
marginRight: "-0.4rem",
|
2745
|
+
width: "calc(100% + 8px)",
|
2746
|
+
children: information.map((info) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
|
2747
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2748
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2749
|
+
] }, info.label))
|
2750
|
+
}
|
2642
2751
|
);
|
2643
|
-
return {
|
2644
|
-
name: mainFieldName,
|
2645
|
-
type: mainFieldType ?? "string"
|
2646
|
-
};
|
2647
|
-
};
|
2648
|
-
const DEFAULT_SETTINGS = {
|
2649
|
-
bulkable: false,
|
2650
|
-
filterable: false,
|
2651
|
-
searchable: false,
|
2652
|
-
pagination: false,
|
2653
|
-
defaultSortBy: "",
|
2654
|
-
defaultSortOrder: "asc",
|
2655
|
-
mainField: "id",
|
2656
|
-
pageSize: 10
|
2657
2752
|
};
|
2658
|
-
const
|
2659
|
-
const
|
2660
|
-
const
|
2661
|
-
|
2662
|
-
|
2663
|
-
|
2664
|
-
|
2665
|
-
|
2666
|
-
|
2667
|
-
|
2668
|
-
error,
|
2669
|
-
isFetching: isFetchingConfigs
|
2670
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2671
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2672
|
-
React__namespace.useEffect(() => {
|
2673
|
-
if (error) {
|
2674
|
-
toggleNotification({
|
2675
|
-
type: "danger",
|
2676
|
-
message: formatAPIError(error)
|
2677
|
-
});
|
2753
|
+
const HeaderActions = ({ actions: actions2 }) => {
|
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
|
+
}
|
2678
2763
|
}
|
2679
|
-
}, [error, formatAPIError, toggleNotification]);
|
2680
|
-
const editLayout = React__namespace.useMemo(
|
2681
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2682
|
-
layout: [],
|
2683
|
-
components: {},
|
2684
|
-
metadatas: {},
|
2685
|
-
options: {},
|
2686
|
-
settings: DEFAULT_SETTINGS
|
2687
|
-
},
|
2688
|
-
[data, isLoading, schemas, schema, components]
|
2689
|
-
);
|
2690
|
-
const listLayout = React__namespace.useMemo(() => {
|
2691
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2692
|
-
layout: [],
|
2693
|
-
metadatas: {},
|
2694
|
-
options: {},
|
2695
|
-
settings: DEFAULT_SETTINGS
|
2696
|
-
};
|
2697
|
-
}, [data, isLoading, schemas, schema, components]);
|
2698
|
-
const { layout: edit } = React__namespace.useMemo(
|
2699
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2700
|
-
layout: editLayout,
|
2701
|
-
query
|
2702
|
-
}),
|
2703
|
-
[editLayout, query, runHookWaterfall]
|
2704
|
-
);
|
2705
|
-
return {
|
2706
|
-
error,
|
2707
|
-
isLoading,
|
2708
|
-
edit,
|
2709
|
-
list: listLayout
|
2710
2764
|
};
|
2711
|
-
|
2712
|
-
|
2713
|
-
|
2714
|
-
return
|
2715
|
-
|
2716
|
-
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2724
|
-
|
2725
|
-
|
2726
|
-
|
2727
|
-
schemas
|
2728
|
-
).reduce((panels, row) => {
|
2729
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2730
|
-
panels.push([row]);
|
2731
|
-
currentPanelIndex += 2;
|
2765
|
+
const handleClose = () => {
|
2766
|
+
setDialogId(null);
|
2767
|
+
};
|
2768
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2769
|
+
if (action.options) {
|
2770
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2771
|
+
designSystem.SingleSelect,
|
2772
|
+
{
|
2773
|
+
size: "S",
|
2774
|
+
onChange: action.onSelect,
|
2775
|
+
"aria-label": action.label,
|
2776
|
+
...action,
|
2777
|
+
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2778
|
+
},
|
2779
|
+
action.id
|
2780
|
+
);
|
2732
2781
|
} else {
|
2733
|
-
if (
|
2734
|
-
|
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);
|
2735
2803
|
}
|
2736
|
-
panels[currentPanelIndex].push(row);
|
2737
2804
|
}
|
2738
|
-
|
2739
|
-
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2744
|
-
|
2745
|
-
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
|
2754
|
-
|
2755
|
-
}
|
2756
|
-
|
2757
|
-
|
2758
|
-
|
2759
|
-
|
2760
|
-
|
2761
|
-
|
2762
|
-
|
2763
|
-
|
2805
|
+
}) });
|
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
|
+
};
|
2825
|
+
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2826
|
+
const navigate = reactRouterDom.useNavigate();
|
2827
|
+
const { formatMessage } = reactIntl.useIntl();
|
2828
|
+
return {
|
2829
|
+
label: formatMessage({
|
2830
|
+
id: "app.links.configure-view",
|
2831
|
+
defaultMessage: "Configure the view"
|
2832
|
+
}),
|
2833
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
|
2834
|
+
onClick: () => {
|
2835
|
+
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2764
2836
|
},
|
2765
|
-
|
2766
|
-
|
2837
|
+
position: "header"
|
2838
|
+
};
|
2839
|
+
};
|
2840
|
+
ConfigureTheViewAction.type = "configure-the-view";
|
2841
|
+
const EditTheModelAction = ({ model }) => {
|
2842
|
+
const navigate = reactRouterDom.useNavigate();
|
2843
|
+
const { formatMessage } = reactIntl.useIntl();
|
2767
2844
|
return {
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2845
|
+
label: formatMessage({
|
2846
|
+
id: "content-manager.link-to-ctb",
|
2847
|
+
defaultMessage: "Edit the model"
|
2848
|
+
}),
|
2849
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
|
2850
|
+
onClick: () => {
|
2851
|
+
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2774
2852
|
},
|
2775
|
-
|
2776
|
-
...schema?.options,
|
2777
|
-
...schema?.pluginOptions,
|
2778
|
-
...data.contentType.options
|
2779
|
-
}
|
2853
|
+
position: "header"
|
2780
2854
|
};
|
2781
2855
|
};
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2856
|
+
EditTheModelAction.type = "edit-the-model";
|
2857
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2858
|
+
const navigate = reactRouterDom.useNavigate();
|
2859
|
+
const { formatMessage } = reactIntl.useIntl();
|
2860
|
+
const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
|
2861
|
+
const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
|
2862
|
+
const { delete: deleteAction } = useDocumentActions();
|
2863
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2864
|
+
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2865
|
+
const isLocalized = document?.locale != null;
|
2866
|
+
return {
|
2867
|
+
disabled: !canDelete || !document,
|
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
|
+
),
|
2875
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2876
|
+
dialog: {
|
2877
|
+
type: "dialog",
|
2878
|
+
title: formatMessage({
|
2879
|
+
id: "app.components.ConfirmDialog.title",
|
2880
|
+
defaultMessage: "Confirmation"
|
2881
|
+
}),
|
2882
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2883
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2884
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2885
|
+
id: "content-manager.actions.delete.dialog.body",
|
2886
|
+
defaultMessage: "Are you sure?"
|
2887
|
+
}) })
|
2888
|
+
] }),
|
2889
|
+
onConfirm: async () => {
|
2890
|
+
if (!listViewPathMatch) {
|
2891
|
+
setSubmitting(true);
|
2892
|
+
}
|
2893
|
+
try {
|
2894
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2895
|
+
console.error(
|
2896
|
+
"You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2897
|
+
);
|
2898
|
+
toggleNotification({
|
2899
|
+
message: formatMessage({
|
2900
|
+
id: "content-manager.actions.delete.error",
|
2901
|
+
defaultMessage: "An error occurred while trying to delete the document."
|
2902
|
+
}),
|
2903
|
+
type: "danger"
|
2904
|
+
});
|
2905
|
+
return;
|
2906
|
+
}
|
2907
|
+
const res = await deleteAction({
|
2908
|
+
documentId,
|
2909
|
+
model,
|
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
|
+
}
|
2922
|
+
}
|
2788
2923
|
}
|
2789
|
-
const { edit: metadata } = metadatas[field.name];
|
2790
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2791
|
-
return {
|
2792
|
-
attribute,
|
2793
|
-
disabled: !metadata.editable,
|
2794
|
-
hint: metadata.description,
|
2795
|
-
label: metadata.label ?? "",
|
2796
|
-
name: field.name,
|
2797
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2798
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2799
|
-
schemas,
|
2800
|
-
components: components?.schemas ?? {}
|
2801
|
-
}),
|
2802
|
-
placeholder: metadata.placeholder ?? "",
|
2803
|
-
required: attribute.required ?? false,
|
2804
|
-
size: field.size,
|
2805
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
2806
|
-
visible: metadata.visible ?? true,
|
2807
|
-
type: attribute.type
|
2808
|
-
};
|
2809
|
-
}).filter((field) => field !== null)
|
2810
|
-
);
|
2811
|
-
};
|
2812
|
-
const formatListLayout = (data, {
|
2813
|
-
schemas,
|
2814
|
-
schema,
|
2815
|
-
components
|
2816
|
-
}) => {
|
2817
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2818
|
-
(acc, [attribute, metadata]) => {
|
2819
|
-
return {
|
2820
|
-
...acc,
|
2821
|
-
[attribute]: metadata.list
|
2822
|
-
};
|
2823
2924
|
},
|
2824
|
-
|
2825
|
-
|
2826
|
-
|
2827
|
-
|
2828
|
-
|
2829
|
-
|
2830
|
-
|
2831
|
-
|
2832
|
-
|
2833
|
-
|
2834
|
-
|
2835
|
-
|
2836
|
-
|
2837
|
-
|
2838
|
-
|
2839
|
-
|
2840
|
-
|
2925
|
+
variant: "danger",
|
2926
|
+
position: ["header", "table-row"]
|
2927
|
+
};
|
2928
|
+
};
|
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))
|
2841
2956
|
}
|
2957
|
+
) });
|
2958
|
+
};
|
2959
|
+
const ActionsPanel = () => {
|
2960
|
+
const { formatMessage } = reactIntl.useIntl();
|
2961
|
+
return {
|
2962
|
+
title: formatMessage({
|
2963
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2964
|
+
defaultMessage: "Entry"
|
2965
|
+
}),
|
2966
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2842
2967
|
};
|
2843
2968
|
};
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
2847
|
-
|
2848
|
-
|
2969
|
+
ActionsPanel.type = "actions";
|
2970
|
+
const ActionsPanelContent = () => {
|
2971
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2972
|
+
const [
|
2973
|
+
{
|
2974
|
+
query: { status = "draft" }
|
2849
2975
|
}
|
2850
|
-
|
2851
|
-
|
2852
|
-
|
2853
|
-
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2861
|
-
|
2862
|
-
|
2863
|
-
|
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
|
+
] });
|
2864
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
|
+
});
|
2865
3025
|
const ConfirmBulkActionDialog = ({
|
2866
3026
|
onToggleDialog,
|
2867
3027
|
isOpen = false,
|
@@ -2900,6 +3060,7 @@ const ConfirmDialogPublishAll = ({
|
|
2900
3060
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2901
3061
|
const { model, schema } = useDoc();
|
2902
3062
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3063
|
+
const enableDraftRelationsCount = false;
|
2903
3064
|
const {
|
2904
3065
|
data: countDraftRelations = 0,
|
2905
3066
|
isLoading,
|
@@ -2911,7 +3072,7 @@ const ConfirmDialogPublishAll = ({
|
|
2911
3072
|
locale: query?.plugins?.i18n?.locale
|
2912
3073
|
},
|
2913
3074
|
{
|
2914
|
-
skip:
|
3075
|
+
skip: !enableDraftRelationsCount
|
2915
3076
|
}
|
2916
3077
|
);
|
2917
3078
|
React__namespace.useEffect(() => {
|
@@ -3096,7 +3257,7 @@ const SelectedEntriesTableContent = ({
|
|
3096
3257
|
status: row.status
|
3097
3258
|
}
|
3098
3259
|
) }),
|
3099
|
-
/* @__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(
|
3100
3261
|
designSystem.IconButton,
|
3101
3262
|
{
|
3102
3263
|
tag: reactRouterDom.Link,
|
@@ -3119,9 +3280,10 @@ const SelectedEntriesTableContent = ({
|
|
3119
3280
|
),
|
3120
3281
|
target: "_blank",
|
3121
3282
|
marginLeft: "auto",
|
3122
|
-
|
3283
|
+
variant: "ghost",
|
3284
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3123
3285
|
}
|
3124
|
-
) })
|
3286
|
+
) }) })
|
3125
3287
|
] }, row.id)) })
|
3126
3288
|
] });
|
3127
3289
|
};
|
@@ -3158,7 +3320,13 @@ const SelectedEntriesModalContent = ({
|
|
3158
3320
|
);
|
3159
3321
|
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3160
3322
|
if (data.length > 0 && schema) {
|
3161
|
-
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
|
+
);
|
3162
3330
|
const validationErrors2 = {};
|
3163
3331
|
const rows2 = data.map((entry) => {
|
3164
3332
|
try {
|
@@ -3508,7 +3676,7 @@ const TableActions = ({ document }) => {
|
|
3508
3676
|
strapiAdmin.DescriptionComponentRenderer,
|
3509
3677
|
{
|
3510
3678
|
props,
|
3511
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3679
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3512
3680
|
children: (actions2) => {
|
3513
3681
|
const tableRowActions = actions2.filter((action) => {
|
3514
3682
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3619,7 +3787,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3619
3787
|
}),
|
3620
3788
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3621
3789
|
footer: ({ onClose }) => {
|
3622
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3790
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3623
3791
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3624
3792
|
id: "cancel",
|
3625
3793
|
defaultMessage: "Cancel"
|
@@ -3850,7 +4018,7 @@ const index = {
|
|
3850
4018
|
app.router.addRoute({
|
3851
4019
|
path: "content-manager/*",
|
3852
4020
|
lazy: async () => {
|
3853
|
-
const { Layout } = await Promise.resolve().then(() => require("./layout-
|
4021
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-UNWstw_s.js"));
|
3854
4022
|
return {
|
3855
4023
|
Component: Layout
|
3856
4024
|
};
|
@@ -3867,7 +4035,7 @@ const index = {
|
|
3867
4035
|
async registerTrads({ locales }) {
|
3868
4036
|
const importedTrads = await Promise.all(
|
3869
4037
|
locales.map((locale) => {
|
3870
|
-
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 }) => {
|
3871
4039
|
return {
|
3872
4040
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3873
4041
|
locale
|
@@ -3885,6 +4053,7 @@ const index = {
|
|
3885
4053
|
};
|
3886
4054
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
3887
4055
|
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4056
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3888
4057
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3889
4058
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3890
4059
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3912,6 +4081,7 @@ exports.getMainField = getMainField;
|
|
3912
4081
|
exports.getTranslation = getTranslation;
|
3913
4082
|
exports.index = index;
|
3914
4083
|
exports.setInitialData = setInitialData;
|
4084
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3915
4085
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3916
4086
|
exports.useDoc = useDoc;
|
3917
4087
|
exports.useDocLayout = useDocLayout;
|
@@ -3924,4 +4094,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
|
3924
4094
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3925
4095
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
3926
4096
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3927
|
-
//# sourceMappingURL=index-
|
4097
|
+
//# sourceMappingURL=index-ovJRE1FM.js.map
|