@strapi/content-manager 5.0.0-rc.9 → 5.0.1
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-BwnO0su2.mjs → ComponentConfigurationPage-DfFSZQxe.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-BwnO0su2.mjs.map → ComponentConfigurationPage-DfFSZQxe.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-BOKmq7mz.js → ComponentConfigurationPage-FqfsxQ1j.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-BOKmq7mz.js.map → ComponentConfigurationPage-FqfsxQ1j.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-N3OaN53v.js → EditConfigurationPage-Cn0e8t3I.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-N3OaN53v.js.map → EditConfigurationPage-Cn0e8t3I.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DJDSIf3D.mjs → EditConfigurationPage-DdPNAbl3.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-DJDSIf3D.mjs.map → EditConfigurationPage-DdPNAbl3.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-IZbGSeL3.mjs → EditViewPage-B82x_x1b.mjs} +15 -5
- package/dist/_chunks/EditViewPage-B82x_x1b.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-l9qOdDUI.js → EditViewPage-DlxEHhUt.js} +15 -5
- package/dist/_chunks/EditViewPage-DlxEHhUt.js.map +1 -0
- package/dist/_chunks/{Field-CWjyW47-.js → Field-COL25JiC.js} +100 -87
- package/dist/_chunks/Field-COL25JiC.js.map +1 -0
- package/dist/_chunks/{Field-D3mNj-iY.mjs → Field-DufHXW17.mjs} +97 -84
- package/dist/_chunks/Field-DufHXW17.mjs.map +1 -0
- package/dist/_chunks/{Form-DFXXFrJV.js → Form-BssUwrTO.js} +16 -8
- package/dist/_chunks/Form-BssUwrTO.js.map +1 -0
- package/dist/_chunks/{Form-Ddy3XYS-.mjs → Form-u_kAOhwB.mjs} +16 -8
- package/dist/_chunks/Form-u_kAOhwB.mjs.map +1 -0
- package/dist/_chunks/{History-pesEeFFT.js → History-C9t9UqpO.js} +23 -10
- package/dist/_chunks/History-C9t9UqpO.js.map +1 -0
- package/dist/_chunks/{History-BEFrLZfz.mjs → History-DRwA3oMM.mjs} +24 -11
- package/dist/_chunks/History-DRwA3oMM.mjs.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-BIoi-Sog.js → ListConfigurationPage-BXYPohh-.js} +2 -2
- package/dist/_chunks/{ListConfigurationPage-BIoi-Sog.js.map → ListConfigurationPage-BXYPohh-.js.map} +1 -1
- package/dist/_chunks/{ListConfigurationPage-CB_lBFVX.mjs → ListConfigurationPage-BxfQJzPk.mjs} +2 -2
- package/dist/_chunks/{ListConfigurationPage-CB_lBFVX.mjs.map → ListConfigurationPage-BxfQJzPk.mjs.map} +1 -1
- package/dist/_chunks/{ListViewPage-DBbH7Esr.mjs → ListViewPage-CELx2ysp.mjs} +40 -36
- package/dist/_chunks/ListViewPage-CELx2ysp.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-C6FK36UI.js → ListViewPage-D2VD8Szg.js} +43 -39
- package/dist/_chunks/ListViewPage-D2VD8Szg.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-Dod8M_xM.js → NoContentTypePage-BV9IjJSM.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-Dod8M_xM.js.map → NoContentTypePage-BV9IjJSM.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-BU9Omzp4.mjs → NoContentTypePage-DtJ9jcfk.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-BU9Omzp4.mjs.map → NoContentTypePage-DtJ9jcfk.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-B88W05rh.mjs → NoPermissionsPage-DWleVYK7.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-B88W05rh.mjs.map → NoPermissionsPage-DWleVYK7.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CMLH3uMk.js → NoPermissionsPage-Dp8NpF9I.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CMLH3uMk.js.map → NoPermissionsPage-Dp8NpF9I.js.map} +1 -1
- package/dist/_chunks/{Relations-BBJRxopY.mjs → Relations-BTcf5xaw.mjs} +32 -23
- package/dist/_chunks/Relations-BTcf5xaw.mjs.map +1 -0
- package/dist/_chunks/{Relations-OXbsEvNt.js → Relations-DR7EUgyC.js} +32 -23
- package/dist/_chunks/Relations-DR7EUgyC.js.map +1 -0
- package/dist/_chunks/{en-uOUIxfcQ.js → en-Bm0D0IWz.js} +13 -12
- package/dist/_chunks/{en-uOUIxfcQ.js.map → en-Bm0D0IWz.js.map} +1 -1
- package/dist/_chunks/{en-BrCTWlZv.mjs → en-DKV44jRb.mjs} +13 -12
- package/dist/_chunks/{en-BrCTWlZv.mjs.map → en-DKV44jRb.mjs.map} +1 -1
- package/dist/_chunks/{index-Bj8wwbdx.js → index-BdMf2lfT.js} +1879 -1765
- package/dist/_chunks/index-BdMf2lfT.js.map +1 -0
- package/dist/_chunks/{index-BgiNQ7Q9.mjs → index-wnqzm4Q8.mjs} +1899 -1785
- package/dist/_chunks/index-wnqzm4Q8.mjs.map +1 -0
- package/dist/_chunks/{layout-LOFMsdWo.mjs → layout-2CfjL0T9.mjs} +5 -4
- package/dist/_chunks/{layout-LOFMsdWo.mjs.map → layout-2CfjL0T9.mjs.map} +1 -1
- package/dist/_chunks/{layout-DBvOIgWG.js → layout-B2MyZU-_.js} +5 -4
- package/dist/_chunks/{layout-DBvOIgWG.js.map → layout-B2MyZU-_.js.map} +1 -1
- package/dist/_chunks/{relations-BLilXMyN.js → relations-BH7JJGGe.js} +2 -2
- package/dist/_chunks/{relations-BLilXMyN.js.map → relations-BH7JJGGe.js.map} +1 -1
- package/dist/_chunks/{relations-BTQKCDqX.mjs → relations-C0w0GcXi.mjs} +2 -2
- package/dist/_chunks/{relations-BTQKCDqX.mjs.map → relations-C0w0GcXi.mjs.map} +1 -1
- package/dist/_chunks/{usePrev-B9w_-eYc.js → useDebounce-CtcjDB3L.js} +14 -1
- package/dist/_chunks/useDebounce-CtcjDB3L.js.map +1 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs +29 -0
- package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +1 -0
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +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/WysiwygStyles.d.ts +0 -32
- 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/server/index.js +48 -21
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +48 -21
- 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/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 +1 -0
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/shared/contracts/collection-types.d.ts +3 -1
- package/dist/shared/contracts/collection-types.d.ts.map +1 -1
- package/package.json +12 -12
- package/dist/_chunks/EditViewPage-IZbGSeL3.mjs.map +0 -1
- package/dist/_chunks/EditViewPage-l9qOdDUI.js.map +0 -1
- package/dist/_chunks/Field-CWjyW47-.js.map +0 -1
- package/dist/_chunks/Field-D3mNj-iY.mjs.map +0 -1
- package/dist/_chunks/Form-DFXXFrJV.js.map +0 -1
- package/dist/_chunks/Form-Ddy3XYS-.mjs.map +0 -1
- package/dist/_chunks/History-BEFrLZfz.mjs.map +0 -1
- package/dist/_chunks/History-pesEeFFT.js.map +0 -1
- package/dist/_chunks/ListViewPage-C6FK36UI.js.map +0 -1
- package/dist/_chunks/ListViewPage-DBbH7Esr.mjs.map +0 -1
- package/dist/_chunks/Relations-BBJRxopY.mjs.map +0 -1
- package/dist/_chunks/Relations-OXbsEvNt.js.map +0 -1
- package/dist/_chunks/index-BgiNQ7Q9.mjs.map +0 -1
- package/dist/_chunks/index-Bj8wwbdx.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 };
|
@@ -121,6 +121,7 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
121
121
|
if (!slug) {
|
122
122
|
throw new Error("Cannot find the slug param in the URL");
|
123
123
|
}
|
124
|
+
const [{ rawQuery }] = strapiAdmin.useQueryParams();
|
124
125
|
const userPermissions = strapiAdmin.useAuth("DocumentRBAC", (state) => state.permissions);
|
125
126
|
const contentTypePermissions = React__namespace.useMemo(() => {
|
126
127
|
const contentTypePermissions2 = userPermissions.filter(
|
@@ -131,7 +132,14 @@ const DocumentRBAC = ({ children, permissions }) => {
|
|
131
132
|
return { ...acc, [action]: [permission] };
|
132
133
|
}, {});
|
133
134
|
}, [slug, userPermissions]);
|
134
|
-
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
135
|
+
const { isLoading, allowedActions } = strapiAdmin.useRBAC(
|
136
|
+
contentTypePermissions,
|
137
|
+
permissions ?? void 0,
|
138
|
+
// TODO: useRBAC context should be typed and built differently
|
139
|
+
// We are passing raw query as context to the hook so that it can
|
140
|
+
// rely on the locale provided from DocumentRBAC for its permission calculations.
|
141
|
+
rawQuery
|
142
|
+
);
|
135
143
|
const canCreateFields = !isLoading && allowedActions.canCreate ? extractAndDedupeFields(contentTypePermissions.create) : [];
|
136
144
|
const canReadFields = !isLoading && allowedActions.canRead ? extractAndDedupeFields(contentTypePermissions.read) : [];
|
137
145
|
const canUpdateFields = !isLoading && allowedActions.canUpdate ? extractAndDedupeFields(contentTypePermissions.update) : [];
|
@@ -179,7 +187,8 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
|
179
187
|
"Document",
|
180
188
|
"InitialData",
|
181
189
|
"HistoryVersion",
|
182
|
-
"Relations"
|
190
|
+
"Relations",
|
191
|
+
"UidAvailability"
|
183
192
|
]
|
184
193
|
});
|
185
194
|
const documentApi = contentManagerApi.injectEndpoints({
|
@@ -209,7 +218,10 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
209
218
|
params
|
210
219
|
}
|
211
220
|
}),
|
212
|
-
invalidatesTags: (_result, _error, { model }) => [
|
221
|
+
invalidatesTags: (_result, _error, { model }) => [
|
222
|
+
{ type: "Document", id: `${model}_LIST` },
|
223
|
+
{ type: "UidAvailability", id: model }
|
224
|
+
]
|
213
225
|
}),
|
214
226
|
/**
|
215
227
|
* Creates a new collection-type document. This should ONLY be used for collection-types.
|
@@ -226,7 +238,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
226
238
|
}),
|
227
239
|
invalidatesTags: (result, _error, { model }) => [
|
228
240
|
{ type: "Document", id: `${model}_LIST` },
|
229
|
-
"Relations"
|
241
|
+
"Relations",
|
242
|
+
{ type: "UidAvailability", id: model }
|
230
243
|
]
|
231
244
|
}),
|
232
245
|
deleteDocument: builder.mutation({
|
@@ -267,7 +280,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
267
280
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
268
281
|
},
|
269
282
|
{ type: "Document", id: `${model}_LIST` },
|
270
|
-
"Relations"
|
283
|
+
"Relations",
|
284
|
+
{ type: "UidAvailability", id: model }
|
271
285
|
];
|
272
286
|
}
|
273
287
|
}),
|
@@ -392,7 +406,8 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
392
406
|
type: "Document",
|
393
407
|
id: collectionType !== SINGLE_TYPES ? `${model}_${documentId}` : model
|
394
408
|
},
|
395
|
-
"Relations"
|
409
|
+
"Relations",
|
410
|
+
{ type: "UidAvailability", id: model }
|
396
411
|
];
|
397
412
|
},
|
398
413
|
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
@@ -475,6 +490,24 @@ const buildValidParams = (query) => {
|
|
475
490
|
const isBaseQueryError = (error) => {
|
476
491
|
return error.name !== void 0;
|
477
492
|
};
|
493
|
+
const arrayValidator = (attribute, options) => ({
|
494
|
+
message: strapiAdmin.translatedErrors.required,
|
495
|
+
test(value) {
|
496
|
+
if (options.status === "draft") {
|
497
|
+
return true;
|
498
|
+
}
|
499
|
+
if (!attribute.required) {
|
500
|
+
return true;
|
501
|
+
}
|
502
|
+
if (!value) {
|
503
|
+
return false;
|
504
|
+
}
|
505
|
+
if (Array.isArray(value) && value.length === 0) {
|
506
|
+
return false;
|
507
|
+
}
|
508
|
+
return true;
|
509
|
+
}
|
510
|
+
});
|
478
511
|
const createYupSchema = (attributes = {}, components = {}, options = { status: null }) => {
|
479
512
|
const createModelSchema = (attributes2) => yup__namespace.object().shape(
|
480
513
|
Object.entries(attributes2).reduce((acc, [name, attribute]) => {
|
@@ -482,6 +515,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
482
515
|
return acc;
|
483
516
|
}
|
484
517
|
const validations = [
|
518
|
+
addNullableValidation,
|
485
519
|
addRequiredValidation,
|
486
520
|
addMinLengthValidation,
|
487
521
|
addMaxLengthValidation,
|
@@ -498,12 +532,12 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
498
532
|
...acc,
|
499
533
|
[name]: transformSchema(
|
500
534
|
yup__namespace.array().of(createModelSchema(attributes3).nullable(false))
|
501
|
-
)
|
535
|
+
).test(arrayValidator(attribute, options))
|
502
536
|
};
|
503
537
|
} else {
|
504
538
|
return {
|
505
539
|
...acc,
|
506
|
-
[name]: transformSchema(createModelSchema(attributes3))
|
540
|
+
[name]: transformSchema(createModelSchema(attributes3).nullable())
|
507
541
|
};
|
508
542
|
}
|
509
543
|
}
|
@@ -525,7 +559,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
525
559
|
}
|
526
560
|
)
|
527
561
|
)
|
528
|
-
)
|
562
|
+
).test(arrayValidator(attribute, options))
|
529
563
|
};
|
530
564
|
case "relation":
|
531
565
|
return {
|
@@ -537,7 +571,7 @@ const createYupSchema = (attributes = {}, components = {}, options = { status: n
|
|
537
571
|
} else if (Array.isArray(value)) {
|
538
572
|
return yup__namespace.array().of(
|
539
573
|
yup__namespace.object().shape({
|
540
|
-
id: yup__namespace.
|
574
|
+
id: yup__namespace.number().required()
|
541
575
|
})
|
542
576
|
);
|
543
577
|
} else if (typeof value === "object") {
|
@@ -623,17 +657,17 @@ const nullableSchema = (schema) => {
|
|
623
657
|
schema
|
624
658
|
);
|
625
659
|
};
|
660
|
+
const addNullableValidation = () => (schema) => {
|
661
|
+
return nullableSchema(schema);
|
662
|
+
};
|
626
663
|
const addRequiredValidation = (attribute, options) => (schema) => {
|
627
|
-
if (options.status === "draft") {
|
628
|
-
return
|
629
|
-
}
|
630
|
-
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
631
|
-
return schema.min(1, strapiAdmin.translatedErrors.required);
|
664
|
+
if (options.status === "draft" || !attribute.required) {
|
665
|
+
return schema;
|
632
666
|
}
|
633
|
-
if (attribute.required &&
|
667
|
+
if (attribute.required && "required" in schema) {
|
634
668
|
return schema.required(strapiAdmin.translatedErrors.required);
|
635
669
|
}
|
636
|
-
return
|
670
|
+
return schema;
|
637
671
|
};
|
638
672
|
const addMinLengthValidation = (attribute, options) => (schema) => {
|
639
673
|
if (options.status === "draft") {
|
@@ -661,31 +695,12 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
661
695
|
return schema;
|
662
696
|
};
|
663
697
|
const addMinValidation = (attribute, options) => (schema) => {
|
664
|
-
if ("
|
698
|
+
if (options.status === "draft") {
|
699
|
+
return schema;
|
700
|
+
}
|
701
|
+
if ("min" in attribute && "min" in schema) {
|
665
702
|
const min = toInteger(attribute.min);
|
666
|
-
if (
|
667
|
-
if (options.status !== "draft" && !attribute.required && "test" in schema && min) {
|
668
|
-
return schema.test(
|
669
|
-
"custom-min",
|
670
|
-
{
|
671
|
-
...strapiAdmin.translatedErrors.min,
|
672
|
-
values: {
|
673
|
-
min: attribute.min
|
674
|
-
}
|
675
|
-
},
|
676
|
-
(value) => {
|
677
|
-
if (!value) {
|
678
|
-
return true;
|
679
|
-
}
|
680
|
-
if (Array.isArray(value) && value.length === 0) {
|
681
|
-
return true;
|
682
|
-
}
|
683
|
-
return value.length >= min;
|
684
|
-
}
|
685
|
-
);
|
686
|
-
}
|
687
|
-
}
|
688
|
-
if ("min" in schema && min) {
|
703
|
+
if (min) {
|
689
704
|
return schema.min(min, {
|
690
705
|
...strapiAdmin.translatedErrors.min,
|
691
706
|
values: {
|
@@ -803,19 +818,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
|
|
803
818
|
}, {});
|
804
819
|
return componentsByKey;
|
805
820
|
};
|
806
|
-
const
|
821
|
+
const HOOKS = {
|
822
|
+
/**
|
823
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
824
|
+
* @constant
|
825
|
+
* @type {string}
|
826
|
+
*/
|
827
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
828
|
+
/**
|
829
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
830
|
+
* @constant
|
831
|
+
* @type {string}
|
832
|
+
*/
|
833
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
834
|
+
/**
|
835
|
+
* Hook that allows to mutate the CM's edit view layout
|
836
|
+
* @constant
|
837
|
+
* @type {string}
|
838
|
+
*/
|
839
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
840
|
+
/**
|
841
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
842
|
+
* @constant
|
843
|
+
* @type {string}
|
844
|
+
*/
|
845
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
846
|
+
};
|
847
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
848
|
+
endpoints: (builder) => ({
|
849
|
+
getContentTypeConfiguration: builder.query({
|
850
|
+
query: (uid) => ({
|
851
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
852
|
+
method: "GET"
|
853
|
+
}),
|
854
|
+
transformResponse: (response) => response.data,
|
855
|
+
providesTags: (_result, _error, uid) => [
|
856
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
857
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
858
|
+
]
|
859
|
+
}),
|
860
|
+
getAllContentTypeSettings: builder.query({
|
861
|
+
query: () => "/content-manager/content-types-settings",
|
862
|
+
transformResponse: (response) => response.data,
|
863
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
864
|
+
}),
|
865
|
+
updateContentTypeConfiguration: builder.mutation({
|
866
|
+
query: ({ uid, ...body }) => ({
|
867
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
868
|
+
method: "PUT",
|
869
|
+
data: body
|
870
|
+
}),
|
871
|
+
transformResponse: (response) => response.data,
|
872
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
873
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
874
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
875
|
+
// Is this necessary?
|
876
|
+
{ type: "InitialData" }
|
877
|
+
]
|
878
|
+
})
|
879
|
+
})
|
880
|
+
});
|
881
|
+
const {
|
882
|
+
useGetContentTypeConfigurationQuery,
|
883
|
+
useGetAllContentTypeSettingsQuery,
|
884
|
+
useUpdateContentTypeConfigurationMutation
|
885
|
+
} = contentTypesApi;
|
886
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
887
|
+
const { type } = attribute;
|
888
|
+
if (type === "relation") {
|
889
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
890
|
+
}
|
891
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
892
|
+
};
|
893
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
894
|
+
if (!mainFieldName) {
|
895
|
+
return void 0;
|
896
|
+
}
|
897
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
898
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
899
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
900
|
+
);
|
901
|
+
return {
|
902
|
+
name: mainFieldName,
|
903
|
+
type: mainFieldType ?? "string"
|
904
|
+
};
|
905
|
+
};
|
906
|
+
const DEFAULT_SETTINGS = {
|
907
|
+
bulkable: false,
|
908
|
+
filterable: false,
|
909
|
+
searchable: false,
|
910
|
+
pagination: false,
|
911
|
+
defaultSortBy: "",
|
912
|
+
defaultSortOrder: "asc",
|
913
|
+
mainField: "id",
|
914
|
+
pageSize: 10
|
915
|
+
};
|
916
|
+
const useDocumentLayout = (model) => {
|
917
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
918
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
919
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
807
920
|
const { toggleNotification } = strapiAdmin.useNotification();
|
808
921
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
922
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
809
923
|
const {
|
810
|
-
|
811
|
-
isLoading:
|
812
|
-
|
813
|
-
|
814
|
-
} =
|
815
|
-
|
816
|
-
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
817
|
-
});
|
818
|
-
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
924
|
+
data,
|
925
|
+
isLoading: isLoadingConfigs,
|
926
|
+
error,
|
927
|
+
isFetching: isFetchingConfigs
|
928
|
+
} = useGetContentTypeConfigurationQuery(model);
|
929
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
819
930
|
React__namespace.useEffect(() => {
|
820
931
|
if (error) {
|
821
932
|
toggleNotification({
|
@@ -823,362 +934,440 @@ const useDocument = (args, opts) => {
|
|
823
934
|
message: formatAPIError(error)
|
824
935
|
});
|
825
936
|
}
|
826
|
-
}, [
|
827
|
-
const
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
(document) => {
|
835
|
-
if (!validationSchema) {
|
836
|
-
throw new Error(
|
837
|
-
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
838
|
-
);
|
839
|
-
}
|
840
|
-
try {
|
841
|
-
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
842
|
-
return null;
|
843
|
-
} catch (error2) {
|
844
|
-
if (error2 instanceof yup.ValidationError) {
|
845
|
-
return strapiAdmin.getYupValidationErrors(error2);
|
846
|
-
}
|
847
|
-
throw error2;
|
848
|
-
}
|
937
|
+
}, [error, formatAPIError, toggleNotification]);
|
938
|
+
const editLayout = React__namespace.useMemo(
|
939
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
940
|
+
layout: [],
|
941
|
+
components: {},
|
942
|
+
metadatas: {},
|
943
|
+
options: {},
|
944
|
+
settings: DEFAULT_SETTINGS
|
849
945
|
},
|
850
|
-
[
|
946
|
+
[data, isLoading, schemas, schema, components]
|
947
|
+
);
|
948
|
+
const listLayout = React__namespace.useMemo(() => {
|
949
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
950
|
+
layout: [],
|
951
|
+
metadatas: {},
|
952
|
+
options: {},
|
953
|
+
settings: DEFAULT_SETTINGS
|
954
|
+
};
|
955
|
+
}, [data, isLoading, schemas, schema, components]);
|
956
|
+
const { layout: edit } = React__namespace.useMemo(
|
957
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
958
|
+
layout: editLayout,
|
959
|
+
query
|
960
|
+
}),
|
961
|
+
[editLayout, query, runHookWaterfall]
|
851
962
|
);
|
852
|
-
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
853
963
|
return {
|
854
|
-
|
855
|
-
document: data?.data,
|
856
|
-
meta: data?.meta,
|
964
|
+
error,
|
857
965
|
isLoading,
|
858
|
-
|
859
|
-
|
860
|
-
};
|
861
|
-
};
|
862
|
-
const useDoc = () => {
|
863
|
-
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
864
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
865
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
866
|
-
if (!collectionType) {
|
867
|
-
throw new Error("Could not find collectionType in url params");
|
868
|
-
}
|
869
|
-
if (!slug) {
|
870
|
-
throw new Error("Could not find model in url params");
|
871
|
-
}
|
872
|
-
return {
|
873
|
-
collectionType,
|
874
|
-
model: slug,
|
875
|
-
id: origin || id === "create" ? void 0 : id,
|
876
|
-
...useDocument(
|
877
|
-
{ documentId: origin || id, model: slug, collectionType, params },
|
878
|
-
{
|
879
|
-
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
880
|
-
}
|
881
|
-
)
|
966
|
+
edit,
|
967
|
+
list: listLayout
|
882
968
|
};
|
883
969
|
};
|
884
|
-
const
|
885
|
-
|
886
|
-
|
887
|
-
}
|
888
|
-
return Object.keys(trad).reduce((acc, current) => {
|
889
|
-
acc[`${pluginId}.${current}`] = trad[current];
|
890
|
-
return acc;
|
891
|
-
}, {});
|
892
|
-
};
|
893
|
-
const getTranslation = (id) => `content-manager.${id}`;
|
894
|
-
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
895
|
-
id: "notification.error",
|
896
|
-
defaultMessage: "An error occurred, please try again"
|
970
|
+
const useDocLayout = () => {
|
971
|
+
const { model } = useDoc();
|
972
|
+
return useDocumentLayout(model);
|
897
973
|
};
|
898
|
-
const
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
const
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
message: formatAPIError(res.error)
|
918
|
-
});
|
919
|
-
return { error: res.error };
|
920
|
-
}
|
921
|
-
toggleNotification({
|
922
|
-
type: "success",
|
923
|
-
message: formatMessage({
|
924
|
-
id: getTranslation("success.record.delete"),
|
925
|
-
defaultMessage: "Deleted document"
|
926
|
-
})
|
927
|
-
});
|
928
|
-
trackUsage("didDeleteEntry", trackerProperty);
|
929
|
-
return res.data;
|
930
|
-
} catch (err) {
|
931
|
-
toggleNotification({
|
932
|
-
type: "danger",
|
933
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
934
|
-
});
|
935
|
-
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
936
|
-
throw err;
|
974
|
+
const formatEditLayout = (data, {
|
975
|
+
schemas,
|
976
|
+
schema,
|
977
|
+
components
|
978
|
+
}) => {
|
979
|
+
let currentPanelIndex = 0;
|
980
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
981
|
+
data.contentType.layouts.edit,
|
982
|
+
schema?.attributes,
|
983
|
+
data.contentType.metadatas,
|
984
|
+
{ configurations: data.components, schemas: components },
|
985
|
+
schemas
|
986
|
+
).reduce((panels, row) => {
|
987
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
988
|
+
panels.push([row]);
|
989
|
+
currentPanelIndex += 2;
|
990
|
+
} else {
|
991
|
+
if (!panels[currentPanelIndex]) {
|
992
|
+
panels.push([]);
|
937
993
|
}
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
const
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
});
|
956
|
-
return { error: res.error };
|
994
|
+
panels[currentPanelIndex].push(row);
|
995
|
+
}
|
996
|
+
return panels;
|
997
|
+
}, []);
|
998
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
999
|
+
(acc, [uid, configuration]) => {
|
1000
|
+
acc[uid] = {
|
1001
|
+
layout: convertEditLayoutToFieldLayouts(
|
1002
|
+
configuration.layouts.edit,
|
1003
|
+
components[uid].attributes,
|
1004
|
+
configuration.metadatas,
|
1005
|
+
{ configurations: data.components, schemas: components }
|
1006
|
+
),
|
1007
|
+
settings: {
|
1008
|
+
...configuration.settings,
|
1009
|
+
icon: components[uid].info.icon,
|
1010
|
+
displayName: components[uid].info.displayName
|
957
1011
|
}
|
958
|
-
|
959
|
-
|
960
|
-
title: formatMessage({
|
961
|
-
id: getTranslation("success.records.delete"),
|
962
|
-
defaultMessage: "Successfully deleted."
|
963
|
-
}),
|
964
|
-
message: ""
|
965
|
-
});
|
966
|
-
trackUsage("didBulkDeleteEntries");
|
967
|
-
return res.data;
|
968
|
-
} catch (err) {
|
969
|
-
toggleNotification({
|
970
|
-
type: "danger",
|
971
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
972
|
-
});
|
973
|
-
trackUsage("didNotBulkDeleteEntries");
|
974
|
-
throw err;
|
975
|
-
}
|
1012
|
+
};
|
1013
|
+
return acc;
|
976
1014
|
},
|
977
|
-
|
1015
|
+
{}
|
978
1016
|
);
|
979
|
-
const
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
model,
|
986
|
-
documentId,
|
987
|
-
params
|
988
|
-
});
|
989
|
-
if ("error" in res) {
|
990
|
-
toggleNotification({
|
991
|
-
type: "danger",
|
992
|
-
message: formatAPIError(res.error)
|
993
|
-
});
|
994
|
-
return { error: res.error };
|
995
|
-
}
|
996
|
-
toggleNotification({
|
997
|
-
type: "success",
|
998
|
-
message: formatMessage({
|
999
|
-
id: "content-manager.success.record.discard",
|
1000
|
-
defaultMessage: "Changes discarded"
|
1001
|
-
})
|
1002
|
-
});
|
1003
|
-
return res.data;
|
1004
|
-
} catch (err) {
|
1005
|
-
toggleNotification({
|
1006
|
-
type: "danger",
|
1007
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1008
|
-
});
|
1009
|
-
throw err;
|
1010
|
-
}
|
1017
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1018
|
+
(acc, [attribute, metadata]) => {
|
1019
|
+
return {
|
1020
|
+
...acc,
|
1021
|
+
[attribute]: metadata.edit
|
1022
|
+
};
|
1011
1023
|
},
|
1012
|
-
|
1024
|
+
{}
|
1013
1025
|
);
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
model,
|
1022
|
-
documentId,
|
1023
|
-
data,
|
1024
|
-
params
|
1025
|
-
});
|
1026
|
-
if ("error" in res) {
|
1027
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1028
|
-
return { error: res.error };
|
1029
|
-
}
|
1030
|
-
trackUsage("didPublishEntry");
|
1031
|
-
toggleNotification({
|
1032
|
-
type: "success",
|
1033
|
-
message: formatMessage({
|
1034
|
-
id: getTranslation("success.record.publish"),
|
1035
|
-
defaultMessage: "Published document"
|
1036
|
-
})
|
1037
|
-
});
|
1038
|
-
return res.data;
|
1039
|
-
} catch (err) {
|
1040
|
-
toggleNotification({
|
1041
|
-
type: "danger",
|
1042
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1043
|
-
});
|
1044
|
-
throw err;
|
1045
|
-
}
|
1026
|
+
return {
|
1027
|
+
layout: panelledEditAttributes,
|
1028
|
+
components: componentEditAttributes,
|
1029
|
+
metadatas: editMetadatas,
|
1030
|
+
settings: {
|
1031
|
+
...data.contentType.settings,
|
1032
|
+
displayName: schema?.info.displayName
|
1046
1033
|
},
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
return { error: res.error };
|
1061
|
-
}
|
1062
|
-
toggleNotification({
|
1063
|
-
type: "success",
|
1064
|
-
message: formatMessage({
|
1065
|
-
id: getTranslation("success.record.publish"),
|
1066
|
-
defaultMessage: "Published document"
|
1067
|
-
})
|
1068
|
-
});
|
1069
|
-
return res.data;
|
1070
|
-
} catch (err) {
|
1071
|
-
toggleNotification({
|
1072
|
-
type: "danger",
|
1073
|
-
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1074
|
-
});
|
1075
|
-
throw err;
|
1034
|
+
options: {
|
1035
|
+
...schema?.options,
|
1036
|
+
...schema?.pluginOptions,
|
1037
|
+
...data.contentType.options
|
1038
|
+
}
|
1039
|
+
};
|
1040
|
+
};
|
1041
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
1042
|
+
return rows.map(
|
1043
|
+
(row) => row.map((field) => {
|
1044
|
+
const attribute = attributes[field.name];
|
1045
|
+
if (!attribute) {
|
1046
|
+
return null;
|
1076
1047
|
}
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1048
|
+
const { edit: metadata } = metadatas[field.name];
|
1049
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1050
|
+
return {
|
1051
|
+
attribute,
|
1052
|
+
disabled: !metadata.editable,
|
1053
|
+
hint: metadata.description,
|
1054
|
+
label: metadata.label ?? "",
|
1055
|
+
name: field.name,
|
1056
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
1057
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1058
|
+
schemas,
|
1059
|
+
components: components?.schemas ?? {}
|
1060
|
+
}),
|
1061
|
+
placeholder: metadata.placeholder ?? "",
|
1062
|
+
required: attribute.required ?? false,
|
1063
|
+
size: field.size,
|
1064
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
1065
|
+
visible: metadata.visible ?? true,
|
1066
|
+
type: attribute.type
|
1067
|
+
};
|
1068
|
+
}).filter((field) => field !== null)
|
1085
1069
|
);
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1070
|
+
};
|
1071
|
+
const formatListLayout = (data, {
|
1072
|
+
schemas,
|
1073
|
+
schema,
|
1074
|
+
components
|
1075
|
+
}) => {
|
1076
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
1077
|
+
(acc, [attribute, metadata]) => {
|
1078
|
+
return {
|
1079
|
+
...acc,
|
1080
|
+
[attribute]: metadata.list
|
1081
|
+
};
|
1082
|
+
},
|
1083
|
+
{}
|
1084
|
+
);
|
1085
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
1086
|
+
data.contentType.layouts.list,
|
1087
|
+
schema?.attributes,
|
1088
|
+
listMetadatas,
|
1089
|
+
{ configurations: data.components, schemas: components },
|
1090
|
+
schemas
|
1091
|
+
);
|
1092
|
+
return {
|
1093
|
+
layout: listAttributes,
|
1094
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
1095
|
+
metadatas: listMetadatas,
|
1096
|
+
options: {
|
1097
|
+
...schema?.options,
|
1098
|
+
...schema?.pluginOptions,
|
1099
|
+
...data.contentType.options
|
1100
|
+
}
|
1101
|
+
};
|
1102
|
+
};
|
1103
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
1104
|
+
return columns.map((name) => {
|
1105
|
+
const attribute = attributes[name];
|
1106
|
+
if (!attribute) {
|
1107
|
+
return null;
|
1108
|
+
}
|
1109
|
+
const metadata = metadatas[name];
|
1110
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
1111
|
+
return {
|
1112
|
+
attribute,
|
1113
|
+
label: metadata.label ?? "",
|
1114
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
1115
|
+
schemas,
|
1116
|
+
components: components?.schemas ?? {}
|
1117
|
+
}),
|
1118
|
+
name,
|
1119
|
+
searchable: metadata.searchable ?? true,
|
1120
|
+
sortable: metadata.sortable ?? true
|
1121
|
+
};
|
1122
|
+
}).filter((field) => field !== null);
|
1123
|
+
};
|
1124
|
+
const useDocument = (args, opts) => {
|
1125
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1126
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1127
|
+
const {
|
1128
|
+
currentData: data,
|
1129
|
+
isLoading: isLoadingDocument,
|
1130
|
+
isFetching: isFetchingDocument,
|
1131
|
+
error
|
1132
|
+
} = useGetDocumentQuery(args, {
|
1133
|
+
...opts,
|
1134
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
1135
|
+
});
|
1136
|
+
const {
|
1137
|
+
components,
|
1138
|
+
schema,
|
1139
|
+
schemas,
|
1140
|
+
isLoading: isLoadingSchema
|
1141
|
+
} = useContentTypeSchema(args.model);
|
1142
|
+
React__namespace.useEffect(() => {
|
1143
|
+
if (error) {
|
1144
|
+
toggleNotification({
|
1145
|
+
type: "danger",
|
1146
|
+
message: formatAPIError(error)
|
1147
|
+
});
|
1148
|
+
}
|
1149
|
+
}, [toggleNotification, error, formatAPIError, args.collectionType]);
|
1150
|
+
const validationSchema = React__namespace.useMemo(() => {
|
1151
|
+
if (!schema) {
|
1152
|
+
return null;
|
1153
|
+
}
|
1154
|
+
return createYupSchema(schema.attributes, components);
|
1155
|
+
}, [schema, components]);
|
1156
|
+
const validate = React__namespace.useCallback(
|
1157
|
+
(document) => {
|
1158
|
+
if (!validationSchema) {
|
1159
|
+
throw new Error(
|
1160
|
+
"There is no validation schema generated, this is likely due to the schema not being loaded yet."
|
1161
|
+
);
|
1162
|
+
}
|
1163
|
+
try {
|
1164
|
+
validationSchema.validateSync(document, { abortEarly: false, strict: true });
|
1165
|
+
return null;
|
1166
|
+
} catch (error2) {
|
1167
|
+
if (error2 instanceof yup.ValidationError) {
|
1168
|
+
return strapiAdmin.getYupValidationErrors(error2);
|
1169
|
+
}
|
1170
|
+
throw error2;
|
1171
|
+
}
|
1172
|
+
},
|
1173
|
+
[validationSchema]
|
1174
|
+
);
|
1175
|
+
const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
|
1176
|
+
const hasError = !!error;
|
1177
|
+
return {
|
1178
|
+
components,
|
1179
|
+
document: data?.data,
|
1180
|
+
meta: data?.meta,
|
1181
|
+
isLoading,
|
1182
|
+
hasError,
|
1183
|
+
schema,
|
1184
|
+
schemas,
|
1185
|
+
validate
|
1186
|
+
};
|
1187
|
+
};
|
1188
|
+
const useDoc = () => {
|
1189
|
+
const { id, slug, collectionType, origin } = reactRouterDom.useParams();
|
1190
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
1191
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1192
|
+
if (!collectionType) {
|
1193
|
+
throw new Error("Could not find collectionType in url params");
|
1194
|
+
}
|
1195
|
+
if (!slug) {
|
1196
|
+
throw new Error("Could not find model in url params");
|
1197
|
+
}
|
1198
|
+
const document = useDocument(
|
1199
|
+
{ documentId: origin || id, model: slug, collectionType, params },
|
1200
|
+
{
|
1201
|
+
skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
|
1202
|
+
}
|
1203
|
+
);
|
1204
|
+
const returnId = origin || id === "create" ? void 0 : id;
|
1205
|
+
return {
|
1206
|
+
collectionType,
|
1207
|
+
model: slug,
|
1208
|
+
id: returnId,
|
1209
|
+
...document
|
1210
|
+
};
|
1211
|
+
};
|
1212
|
+
const useContentManagerContext = () => {
|
1213
|
+
const {
|
1214
|
+
collectionType,
|
1215
|
+
model,
|
1216
|
+
id,
|
1217
|
+
components,
|
1218
|
+
isLoading: isLoadingDoc,
|
1219
|
+
schema,
|
1220
|
+
schemas
|
1221
|
+
} = useDoc();
|
1222
|
+
const layout = useDocumentLayout(model);
|
1223
|
+
const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
|
1224
|
+
const isSingleType = collectionType === SINGLE_TYPES;
|
1225
|
+
const slug = model;
|
1226
|
+
const isCreatingEntry = id === "create";
|
1227
|
+
useContentTypeSchema();
|
1228
|
+
const isLoading = isLoadingDoc || layout.isLoading;
|
1229
|
+
const error = layout.error;
|
1230
|
+
return {
|
1231
|
+
error,
|
1232
|
+
isLoading,
|
1233
|
+
// Base metadata
|
1234
|
+
model,
|
1235
|
+
collectionType,
|
1236
|
+
id,
|
1237
|
+
slug,
|
1238
|
+
isCreatingEntry,
|
1239
|
+
isSingleType,
|
1240
|
+
hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
|
1241
|
+
// All schema infos
|
1242
|
+
components,
|
1243
|
+
contentType: schema,
|
1244
|
+
contentTypes: schemas,
|
1245
|
+
// Form state
|
1246
|
+
form,
|
1247
|
+
// layout infos
|
1248
|
+
layout
|
1249
|
+
};
|
1250
|
+
};
|
1251
|
+
const prefixPluginTranslations = (trad, pluginId) => {
|
1252
|
+
if (!pluginId) {
|
1253
|
+
throw new TypeError("pluginId can't be empty");
|
1254
|
+
}
|
1255
|
+
return Object.keys(trad).reduce((acc, current) => {
|
1256
|
+
acc[`${pluginId}.${current}`] = trad[current];
|
1257
|
+
return acc;
|
1258
|
+
}, {});
|
1259
|
+
};
|
1260
|
+
const getTranslation = (id) => `content-manager.${id}`;
|
1261
|
+
const DEFAULT_UNEXPECTED_ERROR_MSG = {
|
1262
|
+
id: "notification.error",
|
1263
|
+
defaultMessage: "An error occurred, please try again"
|
1264
|
+
};
|
1265
|
+
const useDocumentActions = () => {
|
1266
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
1267
|
+
const { formatMessage } = reactIntl.useIntl();
|
1268
|
+
const { trackUsage } = strapiAdmin.useTracking();
|
1269
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
1270
|
+
const navigate = reactRouterDom.useNavigate();
|
1271
|
+
const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
|
1272
|
+
const [deleteDocument] = useDeleteDocumentMutation();
|
1273
|
+
const _delete = React__namespace.useCallback(
|
1274
|
+
async ({ collectionType, model, documentId, params }, trackerProperty) => {
|
1275
|
+
try {
|
1276
|
+
trackUsage("willDeleteEntry", trackerProperty);
|
1277
|
+
const res = await deleteDocument({
|
1092
1278
|
collectionType,
|
1093
1279
|
model,
|
1094
1280
|
documentId,
|
1095
|
-
data,
|
1096
1281
|
params
|
1097
1282
|
});
|
1098
1283
|
if ("error" in res) {
|
1099
|
-
toggleNotification({
|
1100
|
-
|
1284
|
+
toggleNotification({
|
1285
|
+
type: "danger",
|
1286
|
+
message: formatAPIError(res.error)
|
1287
|
+
});
|
1101
1288
|
return { error: res.error };
|
1102
1289
|
}
|
1103
|
-
trackUsage("didEditEntry", trackerProperty);
|
1104
1290
|
toggleNotification({
|
1105
1291
|
type: "success",
|
1106
1292
|
message: formatMessage({
|
1107
|
-
id: getTranslation("success.record.
|
1108
|
-
defaultMessage: "
|
1293
|
+
id: getTranslation("success.record.delete"),
|
1294
|
+
defaultMessage: "Deleted document"
|
1109
1295
|
})
|
1110
1296
|
});
|
1297
|
+
trackUsage("didDeleteEntry", trackerProperty);
|
1111
1298
|
return res.data;
|
1112
1299
|
} catch (err) {
|
1113
|
-
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1114
1300
|
toggleNotification({
|
1115
1301
|
type: "danger",
|
1116
1302
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1117
1303
|
});
|
1304
|
+
trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
|
1118
1305
|
throw err;
|
1119
1306
|
}
|
1120
1307
|
},
|
1121
|
-
[trackUsage,
|
1308
|
+
[trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
|
1122
1309
|
);
|
1123
|
-
const [
|
1124
|
-
const
|
1125
|
-
async ({
|
1310
|
+
const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
|
1311
|
+
const deleteMany = React__namespace.useCallback(
|
1312
|
+
async ({ model, documentIds, params }) => {
|
1126
1313
|
try {
|
1127
|
-
trackUsage("
|
1128
|
-
const res = await
|
1129
|
-
collectionType,
|
1314
|
+
trackUsage("willBulkDeleteEntries");
|
1315
|
+
const res = await deleteManyDocuments({
|
1130
1316
|
model,
|
1131
|
-
|
1132
|
-
params
|
1133
|
-
data: {
|
1134
|
-
discardDraft
|
1135
|
-
}
|
1317
|
+
documentIds,
|
1318
|
+
params
|
1136
1319
|
});
|
1137
1320
|
if ("error" in res) {
|
1138
|
-
toggleNotification({
|
1321
|
+
toggleNotification({
|
1322
|
+
type: "danger",
|
1323
|
+
message: formatAPIError(res.error)
|
1324
|
+
});
|
1139
1325
|
return { error: res.error };
|
1140
1326
|
}
|
1141
|
-
trackUsage("didUnpublishEntry");
|
1142
1327
|
toggleNotification({
|
1143
1328
|
type: "success",
|
1144
|
-
|
1145
|
-
id: getTranslation("success.
|
1146
|
-
defaultMessage: "
|
1147
|
-
})
|
1329
|
+
title: formatMessage({
|
1330
|
+
id: getTranslation("success.records.delete"),
|
1331
|
+
defaultMessage: "Successfully deleted."
|
1332
|
+
}),
|
1333
|
+
message: ""
|
1148
1334
|
});
|
1335
|
+
trackUsage("didBulkDeleteEntries");
|
1149
1336
|
return res.data;
|
1150
1337
|
} catch (err) {
|
1151
1338
|
toggleNotification({
|
1152
1339
|
type: "danger",
|
1153
1340
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1154
1341
|
});
|
1342
|
+
trackUsage("didNotBulkDeleteEntries");
|
1155
1343
|
throw err;
|
1156
1344
|
}
|
1157
1345
|
},
|
1158
|
-
[trackUsage,
|
1346
|
+
[trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1159
1347
|
);
|
1160
|
-
const [
|
1161
|
-
const
|
1162
|
-
async ({ model,
|
1348
|
+
const [discardDocument] = useDiscardDocumentMutation();
|
1349
|
+
const discard = React__namespace.useCallback(
|
1350
|
+
async ({ collectionType, model, documentId, params }) => {
|
1163
1351
|
try {
|
1164
|
-
|
1165
|
-
|
1352
|
+
const res = await discardDocument({
|
1353
|
+
collectionType,
|
1166
1354
|
model,
|
1167
|
-
|
1355
|
+
documentId,
|
1168
1356
|
params
|
1169
1357
|
});
|
1170
1358
|
if ("error" in res) {
|
1171
|
-
toggleNotification({
|
1359
|
+
toggleNotification({
|
1360
|
+
type: "danger",
|
1361
|
+
message: formatAPIError(res.error)
|
1362
|
+
});
|
1172
1363
|
return { error: res.error };
|
1173
1364
|
}
|
1174
|
-
trackUsage("didBulkUnpublishEntries");
|
1175
1365
|
toggleNotification({
|
1176
1366
|
type: "success",
|
1177
|
-
|
1178
|
-
id:
|
1179
|
-
defaultMessage: "
|
1180
|
-
})
|
1181
|
-
message: ""
|
1367
|
+
message: formatMessage({
|
1368
|
+
id: "content-manager.success.record.discard",
|
1369
|
+
defaultMessage: "Changes discarded"
|
1370
|
+
})
|
1182
1371
|
});
|
1183
1372
|
return res.data;
|
1184
1373
|
} catch (err) {
|
@@ -1186,14 +1375,194 @@ const useDocumentActions = () => {
|
|
1186
1375
|
type: "danger",
|
1187
1376
|
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1188
1377
|
});
|
1189
|
-
trackUsage("didNotBulkUnpublishEntries");
|
1190
1378
|
throw err;
|
1191
1379
|
}
|
1192
1380
|
},
|
1193
|
-
[
|
1381
|
+
[discardDocument, formatAPIError, formatMessage, toggleNotification]
|
1194
1382
|
);
|
1195
|
-
const [
|
1196
|
-
const
|
1383
|
+
const [publishDocument] = usePublishDocumentMutation();
|
1384
|
+
const publish = React__namespace.useCallback(
|
1385
|
+
async ({ collectionType, model, documentId, params }, data) => {
|
1386
|
+
try {
|
1387
|
+
trackUsage("willPublishEntry");
|
1388
|
+
const res = await publishDocument({
|
1389
|
+
collectionType,
|
1390
|
+
model,
|
1391
|
+
documentId,
|
1392
|
+
data,
|
1393
|
+
params
|
1394
|
+
});
|
1395
|
+
if ("error" in res) {
|
1396
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1397
|
+
return { error: res.error };
|
1398
|
+
}
|
1399
|
+
trackUsage("didPublishEntry");
|
1400
|
+
toggleNotification({
|
1401
|
+
type: "success",
|
1402
|
+
message: formatMessage({
|
1403
|
+
id: getTranslation("success.record.publish"),
|
1404
|
+
defaultMessage: "Published document"
|
1405
|
+
})
|
1406
|
+
});
|
1407
|
+
return res.data;
|
1408
|
+
} catch (err) {
|
1409
|
+
toggleNotification({
|
1410
|
+
type: "danger",
|
1411
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1412
|
+
});
|
1413
|
+
throw err;
|
1414
|
+
}
|
1415
|
+
},
|
1416
|
+
[trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
|
1417
|
+
);
|
1418
|
+
const [publishManyDocuments] = usePublishManyDocumentsMutation();
|
1419
|
+
const publishMany = React__namespace.useCallback(
|
1420
|
+
async ({ model, documentIds, params }) => {
|
1421
|
+
try {
|
1422
|
+
const res = await publishManyDocuments({
|
1423
|
+
model,
|
1424
|
+
documentIds,
|
1425
|
+
params
|
1426
|
+
});
|
1427
|
+
if ("error" in res) {
|
1428
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1429
|
+
return { error: res.error };
|
1430
|
+
}
|
1431
|
+
toggleNotification({
|
1432
|
+
type: "success",
|
1433
|
+
message: formatMessage({
|
1434
|
+
id: getTranslation("success.record.publish"),
|
1435
|
+
defaultMessage: "Published document"
|
1436
|
+
})
|
1437
|
+
});
|
1438
|
+
return res.data;
|
1439
|
+
} catch (err) {
|
1440
|
+
toggleNotification({
|
1441
|
+
type: "danger",
|
1442
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1443
|
+
});
|
1444
|
+
throw err;
|
1445
|
+
}
|
1446
|
+
},
|
1447
|
+
[
|
1448
|
+
// trackUsage,
|
1449
|
+
publishManyDocuments,
|
1450
|
+
toggleNotification,
|
1451
|
+
formatMessage,
|
1452
|
+
formatAPIError
|
1453
|
+
]
|
1454
|
+
);
|
1455
|
+
const [updateDocument] = useUpdateDocumentMutation();
|
1456
|
+
const update = React__namespace.useCallback(
|
1457
|
+
async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
|
1458
|
+
try {
|
1459
|
+
trackUsage("willEditEntry", trackerProperty);
|
1460
|
+
const res = await updateDocument({
|
1461
|
+
collectionType,
|
1462
|
+
model,
|
1463
|
+
documentId,
|
1464
|
+
data,
|
1465
|
+
params
|
1466
|
+
});
|
1467
|
+
if ("error" in res) {
|
1468
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1469
|
+
trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
|
1470
|
+
return { error: res.error };
|
1471
|
+
}
|
1472
|
+
trackUsage("didEditEntry", trackerProperty);
|
1473
|
+
toggleNotification({
|
1474
|
+
type: "success",
|
1475
|
+
message: formatMessage({
|
1476
|
+
id: getTranslation("success.record.save"),
|
1477
|
+
defaultMessage: "Saved document"
|
1478
|
+
})
|
1479
|
+
});
|
1480
|
+
return res.data;
|
1481
|
+
} catch (err) {
|
1482
|
+
trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
|
1483
|
+
toggleNotification({
|
1484
|
+
type: "danger",
|
1485
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1486
|
+
});
|
1487
|
+
throw err;
|
1488
|
+
}
|
1489
|
+
},
|
1490
|
+
[trackUsage, updateDocument, toggleNotification, formatMessage, formatAPIError]
|
1491
|
+
);
|
1492
|
+
const [unpublishDocument] = useUnpublishDocumentMutation();
|
1493
|
+
const unpublish = React__namespace.useCallback(
|
1494
|
+
async ({ collectionType, model, documentId, params }, discardDraft = false) => {
|
1495
|
+
try {
|
1496
|
+
trackUsage("willUnpublishEntry");
|
1497
|
+
const res = await unpublishDocument({
|
1498
|
+
collectionType,
|
1499
|
+
model,
|
1500
|
+
documentId,
|
1501
|
+
params,
|
1502
|
+
data: {
|
1503
|
+
discardDraft
|
1504
|
+
}
|
1505
|
+
});
|
1506
|
+
if ("error" in res) {
|
1507
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1508
|
+
return { error: res.error };
|
1509
|
+
}
|
1510
|
+
trackUsage("didUnpublishEntry");
|
1511
|
+
toggleNotification({
|
1512
|
+
type: "success",
|
1513
|
+
message: formatMessage({
|
1514
|
+
id: getTranslation("success.record.unpublish"),
|
1515
|
+
defaultMessage: "Unpublished document"
|
1516
|
+
})
|
1517
|
+
});
|
1518
|
+
return res.data;
|
1519
|
+
} catch (err) {
|
1520
|
+
toggleNotification({
|
1521
|
+
type: "danger",
|
1522
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1523
|
+
});
|
1524
|
+
throw err;
|
1525
|
+
}
|
1526
|
+
},
|
1527
|
+
[trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
|
1528
|
+
);
|
1529
|
+
const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
|
1530
|
+
const unpublishMany = React__namespace.useCallback(
|
1531
|
+
async ({ model, documentIds, params }) => {
|
1532
|
+
try {
|
1533
|
+
trackUsage("willBulkUnpublishEntries");
|
1534
|
+
const res = await unpublishManyDocuments({
|
1535
|
+
model,
|
1536
|
+
documentIds,
|
1537
|
+
params
|
1538
|
+
});
|
1539
|
+
if ("error" in res) {
|
1540
|
+
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1541
|
+
return { error: res.error };
|
1542
|
+
}
|
1543
|
+
trackUsage("didBulkUnpublishEntries");
|
1544
|
+
toggleNotification({
|
1545
|
+
type: "success",
|
1546
|
+
title: formatMessage({
|
1547
|
+
id: getTranslation("success.records.unpublish"),
|
1548
|
+
defaultMessage: "Successfully unpublished."
|
1549
|
+
}),
|
1550
|
+
message: ""
|
1551
|
+
});
|
1552
|
+
return res.data;
|
1553
|
+
} catch (err) {
|
1554
|
+
toggleNotification({
|
1555
|
+
type: "danger",
|
1556
|
+
message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
|
1557
|
+
});
|
1558
|
+
trackUsage("didNotBulkUnpublishEntries");
|
1559
|
+
throw err;
|
1560
|
+
}
|
1561
|
+
},
|
1562
|
+
[trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
|
1563
|
+
);
|
1564
|
+
const [createDocument] = useCreateDocumentMutation();
|
1565
|
+
const create = React__namespace.useCallback(
|
1197
1566
|
async ({ model, params }, data, trackerProperty) => {
|
1198
1567
|
try {
|
1199
1568
|
const res = await createDocument({
|
@@ -1214,6 +1583,7 @@ const useDocumentActions = () => {
|
|
1214
1583
|
defaultMessage: "Saved document"
|
1215
1584
|
})
|
1216
1585
|
});
|
1586
|
+
setCurrentStep("contentManager.success");
|
1217
1587
|
return res.data;
|
1218
1588
|
} catch (err) {
|
1219
1589
|
toggleNotification({
|
@@ -1253,7 +1623,7 @@ const useDocumentActions = () => {
|
|
1253
1623
|
throw err;
|
1254
1624
|
}
|
1255
1625
|
},
|
1256
|
-
[autoCloneDocument,
|
1626
|
+
[autoCloneDocument, formatMessage, toggleNotification]
|
1257
1627
|
);
|
1258
1628
|
const [cloneDocument] = useCloneDocumentMutation();
|
1259
1629
|
const clone = React__namespace.useCallback(
|
@@ -1279,6 +1649,7 @@ const useDocumentActions = () => {
|
|
1279
1649
|
defaultMessage: "Cloned document"
|
1280
1650
|
})
|
1281
1651
|
});
|
1652
|
+
navigate(`../../${res.data.data.documentId}`, { relative: "path" });
|
1282
1653
|
return res.data;
|
1283
1654
|
} catch (err) {
|
1284
1655
|
toggleNotification({
|
@@ -1289,7 +1660,7 @@ const useDocumentActions = () => {
|
|
1289
1660
|
throw err;
|
1290
1661
|
}
|
1291
1662
|
},
|
1292
|
-
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError]
|
1663
|
+
[cloneDocument, trackUsage, toggleNotification, formatMessage, formatAPIError, navigate]
|
1293
1664
|
);
|
1294
1665
|
const [getDoc] = useLazyGetDocumentQuery();
|
1295
1666
|
const getDocument = React__namespace.useCallback(
|
@@ -1315,7 +1686,7 @@ const useDocumentActions = () => {
|
|
1315
1686
|
};
|
1316
1687
|
};
|
1317
1688
|
const ProtectedHistoryPage = React.lazy(
|
1318
|
-
() => Promise.resolve().then(() => require("./History-
|
1689
|
+
() => Promise.resolve().then(() => require("./History-C9t9UqpO.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1319
1690
|
);
|
1320
1691
|
const routes$1 = [
|
1321
1692
|
{
|
@@ -1328,31 +1699,31 @@ const routes$1 = [
|
|
1328
1699
|
}
|
1329
1700
|
];
|
1330
1701
|
const ProtectedEditViewPage = React.lazy(
|
1331
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1702
|
+
() => Promise.resolve().then(() => require("./EditViewPage-DlxEHhUt.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1332
1703
|
);
|
1333
1704
|
const ProtectedListViewPage = React.lazy(
|
1334
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1705
|
+
() => Promise.resolve().then(() => require("./ListViewPage-D2VD8Szg.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1335
1706
|
);
|
1336
1707
|
const ProtectedListConfiguration = React.lazy(
|
1337
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1708
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-BXYPohh-.js")).then((mod) => ({
|
1338
1709
|
default: mod.ProtectedListConfiguration
|
1339
1710
|
}))
|
1340
1711
|
);
|
1341
1712
|
const ProtectedEditConfigurationPage = React.lazy(
|
1342
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1713
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-Cn0e8t3I.js")).then((mod) => ({
|
1343
1714
|
default: mod.ProtectedEditConfigurationPage
|
1344
1715
|
}))
|
1345
1716
|
);
|
1346
1717
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1347
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1718
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-FqfsxQ1j.js")).then((mod) => ({
|
1348
1719
|
default: mod.ProtectedComponentConfigurationPage
|
1349
1720
|
}))
|
1350
1721
|
);
|
1351
1722
|
const NoPermissions = React.lazy(
|
1352
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1723
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-Dp8NpF9I.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1353
1724
|
);
|
1354
1725
|
const NoContentType = React.lazy(
|
1355
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1726
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-BV9IjJSM.js")).then((mod) => ({ default: mod.NoContentType }))
|
1356
1727
|
);
|
1357
1728
|
const CollectionTypePages = () => {
|
1358
1729
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1406,1073 +1777,737 @@ const DocumentActions = ({ actions: actions2 }) => {
|
|
1406
1777
|
if (action.position === void 0) {
|
1407
1778
|
return true;
|
1408
1779
|
}
|
1409
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
1410
|
-
return positions.includes("panel");
|
1411
|
-
});
|
1412
|
-
if (!primaryAction) {
|
1413
|
-
return null;
|
1414
|
-
}
|
1415
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
|
1416
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
1417
|
-
/* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
|
1418
|
-
restActions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
1419
|
-
DocumentActionsMenu,
|
1420
|
-
{
|
1421
|
-
actions: restActions,
|
1422
|
-
label: formatMessage({
|
1423
|
-
id: "content-manager.containers.edit.panels.default.more-actions",
|
1424
|
-
defaultMessage: "More document actions"
|
1425
|
-
})
|
1426
|
-
}
|
1427
|
-
) : null
|
1428
|
-
] }),
|
1429
|
-
secondaryAction ? /* @__PURE__ */ jsxRuntime.jsx(
|
1430
|
-
DocumentActionButton,
|
1431
|
-
{
|
1432
|
-
...secondaryAction,
|
1433
|
-
variant: secondaryAction.variant || "secondary"
|
1434
|
-
}
|
1435
|
-
) : null
|
1436
|
-
] });
|
1437
|
-
};
|
1438
|
-
const DocumentActionButton = (action) => {
|
1439
|
-
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1440
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
1441
|
-
const handleClick = (action2) => async (e) => {
|
1442
|
-
const { onClick = () => false, dialog, id } = action2;
|
1443
|
-
const muteDialog = await onClick(e);
|
1444
|
-
if (dialog && !muteDialog) {
|
1445
|
-
switch (dialog.type) {
|
1446
|
-
case "notification":
|
1447
|
-
toggleNotification({
|
1448
|
-
title: dialog.title,
|
1449
|
-
message: dialog.content,
|
1450
|
-
type: dialog.status,
|
1451
|
-
timeout: dialog.timeout,
|
1452
|
-
onClose: dialog.onClose
|
1453
|
-
});
|
1454
|
-
break;
|
1455
|
-
case "dialog":
|
1456
|
-
case "modal":
|
1457
|
-
e.preventDefault();
|
1458
|
-
setDialogId(id);
|
1459
|
-
}
|
1460
|
-
}
|
1461
|
-
};
|
1462
|
-
const handleClose = () => {
|
1463
|
-
setDialogId(null);
|
1464
|
-
};
|
1465
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
1466
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1467
|
-
designSystem.Button,
|
1468
|
-
{
|
1469
|
-
flex: "auto",
|
1470
|
-
startIcon: action.icon,
|
1471
|
-
disabled: action.disabled,
|
1472
|
-
onClick: handleClick(action),
|
1473
|
-
justifyContent: "center",
|
1474
|
-
variant: action.variant || "default",
|
1475
|
-
paddingTop: "7px",
|
1476
|
-
paddingBottom: "7px",
|
1477
|
-
children: action.label
|
1478
|
-
}
|
1479
|
-
),
|
1480
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1481
|
-
DocumentActionConfirmDialog,
|
1482
|
-
{
|
1483
|
-
...action.dialog,
|
1484
|
-
variant: action.dialog?.variant ?? action.variant,
|
1485
|
-
isOpen: dialogId === action.id,
|
1486
|
-
onClose: handleClose
|
1487
|
-
}
|
1488
|
-
) : null,
|
1489
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1490
|
-
DocumentActionModal,
|
1491
|
-
{
|
1492
|
-
...action.dialog,
|
1493
|
-
onModalClose: handleClose,
|
1494
|
-
isOpen: dialogId === action.id
|
1495
|
-
}
|
1496
|
-
) : null
|
1497
|
-
] });
|
1498
|
-
};
|
1499
|
-
const DocumentActionsMenu = ({
|
1500
|
-
actions: actions2,
|
1501
|
-
children,
|
1502
|
-
label,
|
1503
|
-
variant = "tertiary"
|
1504
|
-
}) => {
|
1505
|
-
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
1506
|
-
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1507
|
-
const { formatMessage } = reactIntl.useIntl();
|
1508
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
1509
|
-
const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
|
1510
|
-
const handleClick = (action) => async (e) => {
|
1511
|
-
const { onClick = () => false, dialog, id } = action;
|
1512
|
-
const muteDialog = await onClick(e);
|
1513
|
-
if (dialog && !muteDialog) {
|
1514
|
-
switch (dialog.type) {
|
1515
|
-
case "notification":
|
1516
|
-
toggleNotification({
|
1517
|
-
title: dialog.title,
|
1518
|
-
message: dialog.content,
|
1519
|
-
type: dialog.status,
|
1520
|
-
timeout: dialog.timeout,
|
1521
|
-
onClose: dialog.onClose
|
1522
|
-
});
|
1523
|
-
break;
|
1524
|
-
case "dialog":
|
1525
|
-
case "modal":
|
1526
|
-
setDialogId(id);
|
1527
|
-
}
|
1528
|
-
}
|
1529
|
-
};
|
1530
|
-
const handleClose = () => {
|
1531
|
-
setDialogId(null);
|
1532
|
-
setIsOpen(false);
|
1533
|
-
};
|
1534
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1535
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
1536
|
-
StyledMoreButton,
|
1537
|
-
{
|
1538
|
-
disabled: isDisabled,
|
1539
|
-
size: "S",
|
1540
|
-
endIcon: null,
|
1541
|
-
paddingTop: "4px",
|
1542
|
-
paddingLeft: "7px",
|
1543
|
-
paddingRight: "7px",
|
1544
|
-
variant,
|
1545
|
-
children: [
|
1546
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
1547
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1548
|
-
id: "content-manager.containers.edit.panels.default.more-actions",
|
1549
|
-
defaultMessage: "More document actions"
|
1550
|
-
}) })
|
1551
|
-
]
|
1552
|
-
}
|
1553
|
-
),
|
1554
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { top: "4px", maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1555
|
-
actions2.map((action) => {
|
1556
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
1557
|
-
designSystem.Menu.Item,
|
1558
|
-
{
|
1559
|
-
disabled: action.disabled,
|
1560
|
-
onSelect: handleClick(action),
|
1561
|
-
display: "block",
|
1562
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1563
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
1564
|
-
designSystem.Flex,
|
1565
|
-
{
|
1566
|
-
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1567
|
-
gap: 2,
|
1568
|
-
tag: "span",
|
1569
|
-
children: [
|
1570
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1571
|
-
designSystem.Flex,
|
1572
|
-
{
|
1573
|
-
tag: "span",
|
1574
|
-
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1575
|
-
children: action.icon
|
1576
|
-
}
|
1577
|
-
),
|
1578
|
-
action.label
|
1579
|
-
]
|
1580
|
-
}
|
1581
|
-
),
|
1582
|
-
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1583
|
-
designSystem.Flex,
|
1584
|
-
{
|
1585
|
-
alignItems: "center",
|
1586
|
-
background: "alternative100",
|
1587
|
-
borderStyle: "solid",
|
1588
|
-
borderColor: "alternative200",
|
1589
|
-
borderWidth: "1px",
|
1590
|
-
height: 5,
|
1591
|
-
paddingLeft: 2,
|
1592
|
-
paddingRight: 2,
|
1593
|
-
hasRadius: true,
|
1594
|
-
color: "alternative600",
|
1595
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1596
|
-
}
|
1597
|
-
)
|
1598
|
-
] })
|
1599
|
-
},
|
1600
|
-
action.id
|
1601
|
-
);
|
1602
|
-
}),
|
1603
|
-
children
|
1604
|
-
] }),
|
1605
|
-
actions2.map((action) => {
|
1606
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
1607
|
-
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1608
|
-
DocumentActionConfirmDialog,
|
1609
|
-
{
|
1610
|
-
...action.dialog,
|
1611
|
-
variant: action.variant,
|
1612
|
-
isOpen: dialogId === action.id,
|
1613
|
-
onClose: handleClose
|
1614
|
-
}
|
1615
|
-
) : null,
|
1616
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1617
|
-
DocumentActionModal,
|
1618
|
-
{
|
1619
|
-
...action.dialog,
|
1620
|
-
onModalClose: handleClose,
|
1621
|
-
isOpen: dialogId === action.id
|
1622
|
-
}
|
1623
|
-
) : null
|
1624
|
-
] }, action.id);
|
1625
|
-
})
|
1626
|
-
] });
|
1627
|
-
};
|
1628
|
-
const convertActionVariantToColor = (variant = "secondary") => {
|
1629
|
-
switch (variant) {
|
1630
|
-
case "danger":
|
1631
|
-
return "danger600";
|
1632
|
-
case "secondary":
|
1633
|
-
return void 0;
|
1634
|
-
case "success":
|
1635
|
-
return "success600";
|
1636
|
-
default:
|
1637
|
-
return "primary600";
|
1638
|
-
}
|
1639
|
-
};
|
1640
|
-
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1641
|
-
switch (variant) {
|
1642
|
-
case "danger":
|
1643
|
-
return "danger600";
|
1644
|
-
case "secondary":
|
1645
|
-
return "neutral500";
|
1646
|
-
case "success":
|
1647
|
-
return "success600";
|
1648
|
-
default:
|
1649
|
-
return "primary600";
|
1650
|
-
}
|
1651
|
-
};
|
1652
|
-
const StyledMoreButton = styledComponents.styled(designSystem.Menu.Trigger)`
|
1653
|
-
& > span {
|
1654
|
-
display: flex;
|
1655
|
-
}
|
1656
|
-
`;
|
1657
|
-
const DocumentActionConfirmDialog = ({
|
1658
|
-
onClose,
|
1659
|
-
onCancel,
|
1660
|
-
onConfirm,
|
1661
|
-
title,
|
1662
|
-
content,
|
1663
|
-
isOpen,
|
1664
|
-
variant = "secondary"
|
1665
|
-
}) => {
|
1666
|
-
const { formatMessage } = reactIntl.useIntl();
|
1667
|
-
const handleClose = async () => {
|
1668
|
-
if (onCancel) {
|
1669
|
-
await onCancel();
|
1670
|
-
}
|
1671
|
-
onClose();
|
1672
|
-
};
|
1673
|
-
const handleConfirm = async () => {
|
1674
|
-
if (onConfirm) {
|
1675
|
-
await onConfirm();
|
1676
|
-
}
|
1677
|
-
onClose();
|
1678
|
-
};
|
1679
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
1680
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1681
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1682
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1683
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
1684
|
-
id: "app.components.Button.cancel",
|
1685
|
-
defaultMessage: "Cancel"
|
1686
|
-
}) }) }),
|
1687
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
1688
|
-
id: "app.components.Button.confirm",
|
1689
|
-
defaultMessage: "Confirm"
|
1690
|
-
}) })
|
1691
|
-
] })
|
1692
|
-
] }) });
|
1693
|
-
};
|
1694
|
-
const DocumentActionModal = ({
|
1695
|
-
isOpen,
|
1696
|
-
title,
|
1697
|
-
onClose,
|
1698
|
-
footer: Footer,
|
1699
|
-
content: Content,
|
1700
|
-
onModalClose
|
1701
|
-
}) => {
|
1702
|
-
const handleClose = () => {
|
1703
|
-
if (onClose) {
|
1704
|
-
onClose();
|
1705
|
-
}
|
1706
|
-
onModalClose();
|
1707
|
-
};
|
1708
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
1709
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
1710
|
-
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
|
1711
|
-
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
1712
|
-
] }) });
|
1713
|
-
};
|
1714
|
-
const PublishAction$1 = ({
|
1715
|
-
activeTab,
|
1716
|
-
documentId,
|
1717
|
-
model,
|
1718
|
-
collectionType,
|
1719
|
-
meta,
|
1720
|
-
document
|
1721
|
-
}) => {
|
1722
|
-
const { schema } = useDoc();
|
1723
|
-
const navigate = reactRouterDom.useNavigate();
|
1724
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
1725
|
-
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
1726
|
-
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
1727
|
-
const { formatMessage } = reactIntl.useIntl();
|
1728
|
-
const { canPublish, canCreate, canUpdate } = useDocumentRBAC(
|
1729
|
-
"PublishAction",
|
1730
|
-
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1731
|
-
);
|
1732
|
-
const { publish } = useDocumentActions();
|
1733
|
-
const [
|
1734
|
-
countDraftRelations,
|
1735
|
-
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
1736
|
-
] = useLazyGetDraftRelationCountQuery();
|
1737
|
-
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
1738
|
-
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1739
|
-
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1740
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1741
|
-
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
1742
|
-
const setSubmitting = strapiAdmin.useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
1743
|
-
const isSubmitting = strapiAdmin.useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
1744
|
-
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1745
|
-
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1746
|
-
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
1747
|
-
React__namespace.useEffect(() => {
|
1748
|
-
if (isErrorDraftRelations) {
|
1749
|
-
toggleNotification({
|
1750
|
-
type: "danger",
|
1751
|
-
message: formatMessage({
|
1752
|
-
id: getTranslation("error.records.fetch-draft-relatons"),
|
1753
|
-
defaultMessage: "An error occurred while fetching draft relations on this document."
|
1754
|
-
})
|
1755
|
-
});
|
1756
|
-
}
|
1757
|
-
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
1758
|
-
React__namespace.useEffect(() => {
|
1759
|
-
const localDraftRelations = /* @__PURE__ */ new Set();
|
1760
|
-
const extractDraftRelations = (data) => {
|
1761
|
-
const relations = data.connect || [];
|
1762
|
-
relations.forEach((relation) => {
|
1763
|
-
if (relation.status === "draft") {
|
1764
|
-
localDraftRelations.add(relation.id);
|
1765
|
-
}
|
1766
|
-
});
|
1767
|
-
};
|
1768
|
-
const traverseAndExtract = (data) => {
|
1769
|
-
Object.entries(data).forEach(([key, value]) => {
|
1770
|
-
if (key === "connect" && Array.isArray(value)) {
|
1771
|
-
extractDraftRelations({ connect: value });
|
1772
|
-
} else if (typeof value === "object" && value !== null) {
|
1773
|
-
traverseAndExtract(value);
|
1774
|
-
}
|
1775
|
-
});
|
1776
|
-
};
|
1777
|
-
if (!documentId || modified) {
|
1778
|
-
traverseAndExtract(formValues);
|
1779
|
-
setLocalCountOfDraftRelations(localDraftRelations.size);
|
1780
|
-
}
|
1781
|
-
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1782
|
-
React__namespace.useEffect(() => {
|
1783
|
-
if (documentId) {
|
1784
|
-
const fetchDraftRelationsCount = async () => {
|
1785
|
-
const { data, error } = await countDraftRelations({
|
1786
|
-
collectionType,
|
1787
|
-
model,
|
1788
|
-
documentId,
|
1789
|
-
params
|
1790
|
-
});
|
1791
|
-
if (error) {
|
1792
|
-
throw error;
|
1793
|
-
}
|
1794
|
-
if (data) {
|
1795
|
-
setServerCountOfDraftRelations(data.data);
|
1796
|
-
}
|
1797
|
-
};
|
1798
|
-
fetchDraftRelationsCount();
|
1799
|
-
}
|
1800
|
-
}, [documentId, countDraftRelations, collectionType, model, params]);
|
1801
|
-
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1802
|
-
if (!schema?.options?.draftAndPublish) {
|
1780
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
1781
|
+
return positions.includes("panel");
|
1782
|
+
});
|
1783
|
+
if (!primaryAction) {
|
1803
1784
|
return null;
|
1804
1785
|
}
|
1805
|
-
|
1806
|
-
|
1807
|
-
|
1808
|
-
|
1809
|
-
|
1810
|
-
toggleNotification({
|
1811
|
-
type: "danger",
|
1812
|
-
message: formatMessage({
|
1813
|
-
id: "content-manager.validation.error",
|
1814
|
-
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1815
|
-
})
|
1816
|
-
});
|
1817
|
-
return;
|
1818
|
-
}
|
1819
|
-
const res = await publish(
|
1820
|
-
{
|
1821
|
-
collectionType,
|
1822
|
-
model,
|
1823
|
-
documentId,
|
1824
|
-
params
|
1825
|
-
},
|
1826
|
-
formValues
|
1827
|
-
);
|
1828
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1829
|
-
navigate({
|
1830
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1831
|
-
search: rawQuery
|
1832
|
-
});
|
1833
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1834
|
-
setErrors(formatValidationErrors(res.error));
|
1835
|
-
}
|
1836
|
-
} finally {
|
1837
|
-
setSubmitting(false);
|
1838
|
-
}
|
1839
|
-
};
|
1840
|
-
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1841
|
-
const hasDraftRelations = totalDraftRelations > 0;
|
1842
|
-
return {
|
1843
|
-
/**
|
1844
|
-
* Disabled when:
|
1845
|
-
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
1846
|
-
* - the form is submitting
|
1847
|
-
* - the active tab is the published tab
|
1848
|
-
* - the document is already published & not modified
|
1849
|
-
* - the document is being created & not modified
|
1850
|
-
* - the user doesn't have the permission to publish
|
1851
|
-
*/
|
1852
|
-
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1853
|
-
label: formatMessage({
|
1854
|
-
id: "app.utils.publish",
|
1855
|
-
defaultMessage: "Publish"
|
1856
|
-
}),
|
1857
|
-
onClick: async () => {
|
1858
|
-
if (hasDraftRelations) {
|
1859
|
-
return;
|
1860
|
-
}
|
1861
|
-
await performPublish();
|
1862
|
-
},
|
1863
|
-
dialog: hasDraftRelations ? {
|
1864
|
-
type: "dialog",
|
1865
|
-
variant: "danger",
|
1866
|
-
footer: null,
|
1867
|
-
title: formatMessage({
|
1868
|
-
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
1869
|
-
defaultMessage: "Confirmation"
|
1870
|
-
}),
|
1871
|
-
content: formatMessage(
|
1872
|
-
{
|
1873
|
-
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
1874
|
-
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
1875
|
-
},
|
1786
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, alignItems: "stretch", width: "100%", children: [
|
1787
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
1788
|
+
/* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...primaryAction, variant: primaryAction.variant || "default" }),
|
1789
|
+
restActions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
1790
|
+
DocumentActionsMenu,
|
1876
1791
|
{
|
1877
|
-
|
1792
|
+
actions: restActions,
|
1793
|
+
label: formatMessage({
|
1794
|
+
id: "content-manager.containers.edit.panels.default.more-actions",
|
1795
|
+
defaultMessage: "More document actions"
|
1796
|
+
})
|
1878
1797
|
}
|
1879
|
-
)
|
1880
|
-
|
1881
|
-
|
1798
|
+
) : null
|
1799
|
+
] }),
|
1800
|
+
secondaryAction ? /* @__PURE__ */ jsxRuntime.jsx(
|
1801
|
+
DocumentActionButton,
|
1802
|
+
{
|
1803
|
+
...secondaryAction,
|
1804
|
+
variant: secondaryAction.variant || "secondary"
|
1882
1805
|
}
|
1883
|
-
|
1884
|
-
};
|
1806
|
+
) : null
|
1807
|
+
] });
|
1885
1808
|
};
|
1886
|
-
|
1887
|
-
const
|
1888
|
-
activeTab,
|
1889
|
-
documentId,
|
1890
|
-
model,
|
1891
|
-
collectionType
|
1892
|
-
}) => {
|
1893
|
-
const navigate = reactRouterDom.useNavigate();
|
1809
|
+
const DocumentActionButton = (action) => {
|
1810
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
1894
1811
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1895
|
-
const
|
1896
|
-
|
1897
|
-
|
1898
|
-
|
1899
|
-
|
1900
|
-
|
1901
|
-
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
|
1908
|
-
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
1912
|
-
|
1913
|
-
return {
|
1914
|
-
/**
|
1915
|
-
* Disabled when:
|
1916
|
-
* - the form is submitting
|
1917
|
-
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1918
|
-
* - the active tab is the published tab
|
1919
|
-
*/
|
1920
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1921
|
-
label: formatMessage({
|
1922
|
-
id: "content-manager.containers.Edit.save",
|
1923
|
-
defaultMessage: "Save"
|
1924
|
-
}),
|
1925
|
-
onClick: async () => {
|
1926
|
-
setSubmitting(true);
|
1927
|
-
try {
|
1928
|
-
if (activeTab !== "draft") {
|
1929
|
-
const { errors } = await validate();
|
1930
|
-
if (errors) {
|
1931
|
-
toggleNotification({
|
1932
|
-
type: "danger",
|
1933
|
-
message: formatMessage({
|
1934
|
-
id: "content-manager.validation.error",
|
1935
|
-
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1936
|
-
})
|
1937
|
-
});
|
1938
|
-
return;
|
1939
|
-
}
|
1940
|
-
}
|
1941
|
-
if (isCloning) {
|
1942
|
-
const res = await clone(
|
1943
|
-
{
|
1944
|
-
model,
|
1945
|
-
documentId: cloneMatch.params.origin,
|
1946
|
-
params
|
1947
|
-
},
|
1948
|
-
document
|
1949
|
-
);
|
1950
|
-
if ("data" in res) {
|
1951
|
-
navigate(
|
1952
|
-
{
|
1953
|
-
pathname: `../${res.data.documentId}`,
|
1954
|
-
search: rawQuery
|
1955
|
-
},
|
1956
|
-
{ relative: "path" }
|
1957
|
-
);
|
1958
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1959
|
-
setErrors(formatValidationErrors(res.error));
|
1960
|
-
}
|
1961
|
-
} else if (documentId || collectionType === SINGLE_TYPES) {
|
1962
|
-
const res = await update(
|
1963
|
-
{
|
1964
|
-
collectionType,
|
1965
|
-
model,
|
1966
|
-
documentId,
|
1967
|
-
params
|
1968
|
-
},
|
1969
|
-
document
|
1970
|
-
);
|
1971
|
-
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1972
|
-
setErrors(formatValidationErrors(res.error));
|
1973
|
-
} else {
|
1974
|
-
resetForm();
|
1975
|
-
}
|
1976
|
-
} else {
|
1977
|
-
const res = await create(
|
1978
|
-
{
|
1979
|
-
model,
|
1980
|
-
params
|
1981
|
-
},
|
1982
|
-
document
|
1983
|
-
);
|
1984
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1985
|
-
navigate(
|
1986
|
-
{
|
1987
|
-
pathname: `../${res.data.documentId}`,
|
1988
|
-
search: rawQuery
|
1989
|
-
},
|
1990
|
-
{ replace: true, relative: "path" }
|
1991
|
-
);
|
1992
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1993
|
-
setErrors(formatValidationErrors(res.error));
|
1994
|
-
}
|
1995
|
-
}
|
1996
|
-
} finally {
|
1997
|
-
setSubmitting(false);
|
1812
|
+
const handleClick = (action2) => async (e) => {
|
1813
|
+
const { onClick = () => false, dialog, id } = action2;
|
1814
|
+
const muteDialog = await onClick(e);
|
1815
|
+
if (dialog && !muteDialog) {
|
1816
|
+
switch (dialog.type) {
|
1817
|
+
case "notification":
|
1818
|
+
toggleNotification({
|
1819
|
+
title: dialog.title,
|
1820
|
+
message: dialog.content,
|
1821
|
+
type: dialog.status,
|
1822
|
+
timeout: dialog.timeout,
|
1823
|
+
onClose: dialog.onClose
|
1824
|
+
});
|
1825
|
+
break;
|
1826
|
+
case "dialog":
|
1827
|
+
case "modal":
|
1828
|
+
e.preventDefault();
|
1829
|
+
setDialogId(id);
|
1998
1830
|
}
|
1999
1831
|
}
|
2000
1832
|
};
|
1833
|
+
const handleClose = () => {
|
1834
|
+
setDialogId(null);
|
1835
|
+
};
|
1836
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
1837
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1838
|
+
designSystem.Button,
|
1839
|
+
{
|
1840
|
+
flex: "auto",
|
1841
|
+
startIcon: action.icon,
|
1842
|
+
disabled: action.disabled,
|
1843
|
+
onClick: handleClick(action),
|
1844
|
+
justifyContent: "center",
|
1845
|
+
variant: action.variant || "default",
|
1846
|
+
paddingTop: "7px",
|
1847
|
+
paddingBottom: "7px",
|
1848
|
+
children: action.label
|
1849
|
+
}
|
1850
|
+
),
|
1851
|
+
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1852
|
+
DocumentActionConfirmDialog,
|
1853
|
+
{
|
1854
|
+
...action.dialog,
|
1855
|
+
variant: action.dialog?.variant ?? action.variant,
|
1856
|
+
isOpen: dialogId === action.id,
|
1857
|
+
onClose: handleClose
|
1858
|
+
}
|
1859
|
+
) : null,
|
1860
|
+
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1861
|
+
DocumentActionModal,
|
1862
|
+
{
|
1863
|
+
...action.dialog,
|
1864
|
+
onModalClose: handleClose,
|
1865
|
+
isOpen: dialogId === action.id
|
1866
|
+
}
|
1867
|
+
) : null
|
1868
|
+
] });
|
2001
1869
|
};
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
2007
|
-
const UnpublishAction$1 = ({
|
2008
|
-
activeTab,
|
2009
|
-
documentId,
|
2010
|
-
model,
|
2011
|
-
collectionType,
|
2012
|
-
document
|
1870
|
+
const DocumentActionsMenu = ({
|
1871
|
+
actions: actions2,
|
1872
|
+
children,
|
1873
|
+
label,
|
1874
|
+
variant = "tertiary"
|
2013
1875
|
}) => {
|
1876
|
+
const [isOpen, setIsOpen] = React__namespace.useState(false);
|
1877
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2014
1878
|
const { formatMessage } = reactIntl.useIntl();
|
2015
|
-
const { schema } = useDoc();
|
2016
|
-
const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2017
|
-
const { unpublish } = useDocumentActions();
|
2018
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
2019
|
-
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2020
1879
|
const { toggleNotification } = strapiAdmin.useNotification();
|
2021
|
-
const
|
2022
|
-
const
|
2023
|
-
|
2024
|
-
|
2025
|
-
|
2026
|
-
|
2027
|
-
|
2028
|
-
}
|
2029
|
-
return {
|
2030
|
-
disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
|
2031
|
-
label: formatMessage({
|
2032
|
-
id: "app.utils.unpublish",
|
2033
|
-
defaultMessage: "Unpublish"
|
2034
|
-
}),
|
2035
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
|
2036
|
-
onClick: async () => {
|
2037
|
-
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2038
|
-
if (!documentId) {
|
2039
|
-
console.error(
|
2040
|
-
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2041
|
-
);
|
1880
|
+
const isDisabled = actions2.every((action) => action.disabled) || actions2.length === 0;
|
1881
|
+
const handleClick = (action) => async (e) => {
|
1882
|
+
const { onClick = () => false, dialog, id } = action;
|
1883
|
+
const muteDialog = await onClick(e);
|
1884
|
+
if (dialog && !muteDialog) {
|
1885
|
+
switch (dialog.type) {
|
1886
|
+
case "notification":
|
2042
1887
|
toggleNotification({
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
1888
|
+
title: dialog.title,
|
1889
|
+
message: dialog.content,
|
1890
|
+
type: dialog.status,
|
1891
|
+
timeout: dialog.timeout,
|
1892
|
+
onClose: dialog.onClose
|
2048
1893
|
});
|
2049
|
-
|
2050
|
-
|
1894
|
+
break;
|
1895
|
+
case "dialog":
|
1896
|
+
case "modal":
|
1897
|
+
setDialogId(id);
|
2051
1898
|
}
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
2056
|
-
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
2060
|
-
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
2064
|
-
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
|
1899
|
+
}
|
1900
|
+
};
|
1901
|
+
const handleClose = () => {
|
1902
|
+
setDialogId(null);
|
1903
|
+
setIsOpen(false);
|
1904
|
+
};
|
1905
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1906
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1907
|
+
designSystem.Menu.Trigger,
|
1908
|
+
{
|
1909
|
+
disabled: isDisabled,
|
1910
|
+
size: "S",
|
1911
|
+
endIcon: null,
|
1912
|
+
paddingTop: "4px",
|
1913
|
+
paddingLeft: "7px",
|
1914
|
+
paddingRight: "7px",
|
1915
|
+
variant,
|
1916
|
+
children: [
|
1917
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
1918
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { tag: "span", children: label || formatMessage({
|
1919
|
+
id: "content-manager.containers.edit.panels.default.more-actions",
|
1920
|
+
defaultMessage: "More document actions"
|
2071
1921
|
}) })
|
2072
|
-
]
|
2073
|
-
|
2074
|
-
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2079
|
-
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2080
|
-
defaultMessage: "Choose an option to unpublish the document."
|
2081
|
-
}),
|
2082
|
-
onValueChange: handleChange,
|
2083
|
-
children: [
|
2084
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2085
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2086
|
-
defaultMessage: "Keep draft"
|
2087
|
-
}) }),
|
2088
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2089
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2090
|
-
defaultMessage: "Replace draft"
|
2091
|
-
}) })
|
2092
|
-
]
|
2093
|
-
}
|
2094
|
-
)
|
2095
|
-
] }),
|
2096
|
-
onConfirm: async () => {
|
2097
|
-
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2098
|
-
console.error(
|
2099
|
-
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2100
|
-
);
|
2101
|
-
toggleNotification({
|
2102
|
-
message: formatMessage({
|
2103
|
-
id: "content-manager.actions.unpublish.error",
|
2104
|
-
defaultMessage: "An error occurred while trying to unpublish the document."
|
2105
|
-
}),
|
2106
|
-
type: "danger"
|
2107
|
-
});
|
2108
|
-
}
|
2109
|
-
await unpublish(
|
1922
|
+
]
|
1923
|
+
}
|
1924
|
+
),
|
1925
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Content, { maxHeight: void 0, popoverPlacement: "bottom-end", children: [
|
1926
|
+
actions2.map((action) => {
|
1927
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
1928
|
+
designSystem.Menu.Item,
|
2110
1929
|
{
|
2111
|
-
|
2112
|
-
|
2113
|
-
|
2114
|
-
|
1930
|
+
disabled: action.disabled,
|
1931
|
+
onSelect: handleClick(action),
|
1932
|
+
display: "block",
|
1933
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1934
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1935
|
+
designSystem.Flex,
|
1936
|
+
{
|
1937
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1938
|
+
gap: 2,
|
1939
|
+
tag: "span",
|
1940
|
+
children: [
|
1941
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1942
|
+
designSystem.Flex,
|
1943
|
+
{
|
1944
|
+
tag: "span",
|
1945
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1946
|
+
children: action.icon
|
1947
|
+
}
|
1948
|
+
),
|
1949
|
+
action.label
|
1950
|
+
]
|
1951
|
+
}
|
1952
|
+
),
|
1953
|
+
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1954
|
+
designSystem.Flex,
|
1955
|
+
{
|
1956
|
+
alignItems: "center",
|
1957
|
+
background: "alternative100",
|
1958
|
+
borderStyle: "solid",
|
1959
|
+
borderColor: "alternative200",
|
1960
|
+
borderWidth: "1px",
|
1961
|
+
height: 5,
|
1962
|
+
paddingLeft: 2,
|
1963
|
+
paddingRight: 2,
|
1964
|
+
hasRadius: true,
|
1965
|
+
color: "alternative600",
|
1966
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", lineHeight: 1, children: formatMessage({ id: "global.new", defaultMessage: "New" }) })
|
1967
|
+
}
|
1968
|
+
)
|
1969
|
+
] })
|
2115
1970
|
},
|
2116
|
-
|
1971
|
+
action.id
|
2117
1972
|
);
|
2118
|
-
}
|
2119
|
-
|
2120
|
-
|
2121
|
-
|
1973
|
+
}),
|
1974
|
+
children
|
1975
|
+
] }),
|
1976
|
+
actions2.map((action) => {
|
1977
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
1978
|
+
action.dialog?.type === "dialog" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1979
|
+
DocumentActionConfirmDialog,
|
1980
|
+
{
|
1981
|
+
...action.dialog,
|
1982
|
+
variant: action.variant,
|
1983
|
+
isOpen: dialogId === action.id,
|
1984
|
+
onClose: handleClose
|
1985
|
+
}
|
1986
|
+
) : null,
|
1987
|
+
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
1988
|
+
DocumentActionModal,
|
1989
|
+
{
|
1990
|
+
...action.dialog,
|
1991
|
+
onModalClose: handleClose,
|
1992
|
+
isOpen: dialogId === action.id
|
1993
|
+
}
|
1994
|
+
) : null
|
1995
|
+
] }, action.id);
|
1996
|
+
})
|
1997
|
+
] });
|
1998
|
+
};
|
1999
|
+
const convertActionVariantToColor = (variant = "secondary") => {
|
2000
|
+
switch (variant) {
|
2001
|
+
case "danger":
|
2002
|
+
return "danger600";
|
2003
|
+
case "secondary":
|
2004
|
+
return void 0;
|
2005
|
+
case "success":
|
2006
|
+
return "success600";
|
2007
|
+
default:
|
2008
|
+
return "primary600";
|
2009
|
+
}
|
2010
|
+
};
|
2011
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
2012
|
+
switch (variant) {
|
2013
|
+
case "danger":
|
2014
|
+
return "danger600";
|
2015
|
+
case "secondary":
|
2016
|
+
return "neutral500";
|
2017
|
+
case "success":
|
2018
|
+
return "success600";
|
2019
|
+
default:
|
2020
|
+
return "primary600";
|
2021
|
+
}
|
2022
|
+
};
|
2023
|
+
const DocumentActionConfirmDialog = ({
|
2024
|
+
onClose,
|
2025
|
+
onCancel,
|
2026
|
+
onConfirm,
|
2027
|
+
title,
|
2028
|
+
content,
|
2029
|
+
isOpen,
|
2030
|
+
variant = "secondary"
|
2031
|
+
}) => {
|
2032
|
+
const { formatMessage } = reactIntl.useIntl();
|
2033
|
+
const handleClose = async () => {
|
2034
|
+
if (onCancel) {
|
2035
|
+
await onCancel();
|
2036
|
+
}
|
2037
|
+
onClose();
|
2038
|
+
};
|
2039
|
+
const handleConfirm = async () => {
|
2040
|
+
if (onConfirm) {
|
2041
|
+
await onConfirm();
|
2042
|
+
}
|
2043
|
+
onClose();
|
2122
2044
|
};
|
2045
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2046
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2047
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
2048
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
2049
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", fullWidth: true, children: formatMessage({
|
2050
|
+
id: "app.components.Button.cancel",
|
2051
|
+
defaultMessage: "Cancel"
|
2052
|
+
}) }) }),
|
2053
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, fullWidth: true, children: formatMessage({
|
2054
|
+
id: "app.components.Button.confirm",
|
2055
|
+
defaultMessage: "Confirm"
|
2056
|
+
}) })
|
2057
|
+
] })
|
2058
|
+
] }) });
|
2123
2059
|
};
|
2124
|
-
|
2125
|
-
|
2060
|
+
const DocumentActionModal = ({
|
2061
|
+
isOpen,
|
2062
|
+
title,
|
2063
|
+
onClose,
|
2064
|
+
footer: Footer,
|
2065
|
+
content: Content,
|
2066
|
+
onModalClose
|
2067
|
+
}) => {
|
2068
|
+
const handleClose = () => {
|
2069
|
+
if (onClose) {
|
2070
|
+
onClose();
|
2071
|
+
}
|
2072
|
+
onModalClose();
|
2073
|
+
};
|
2074
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
2075
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
2076
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
|
2077
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
2078
|
+
] }) });
|
2079
|
+
};
|
2080
|
+
const PublishAction$1 = ({
|
2126
2081
|
activeTab,
|
2127
2082
|
documentId,
|
2128
2083
|
model,
|
2129
2084
|
collectionType,
|
2085
|
+
meta,
|
2130
2086
|
document
|
2131
2087
|
}) => {
|
2132
|
-
const { formatMessage } = reactIntl.useIntl();
|
2133
2088
|
const { schema } = useDoc();
|
2134
|
-
const
|
2135
|
-
const {
|
2136
|
-
const
|
2137
|
-
const
|
2138
|
-
if (!schema?.options?.draftAndPublish) {
|
2139
|
-
return null;
|
2140
|
-
}
|
2141
|
-
return {
|
2142
|
-
disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
|
2143
|
-
label: formatMessage({
|
2144
|
-
id: "content-manager.actions.discard.label",
|
2145
|
-
defaultMessage: "Discard changes"
|
2146
|
-
}),
|
2147
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledCrossCircle, {}),
|
2148
|
-
position: ["panel", "table-row"],
|
2149
|
-
variant: "danger",
|
2150
|
-
dialog: {
|
2151
|
-
type: "dialog",
|
2152
|
-
title: formatMessage({
|
2153
|
-
id: "app.components.ConfirmDialog.title",
|
2154
|
-
defaultMessage: "Confirmation"
|
2155
|
-
}),
|
2156
|
-
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2157
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2158
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2159
|
-
id: "content-manager.actions.discard.dialog.body",
|
2160
|
-
defaultMessage: "Are you sure?"
|
2161
|
-
}) })
|
2162
|
-
] }),
|
2163
|
-
onConfirm: async () => {
|
2164
|
-
await discard({
|
2165
|
-
collectionType,
|
2166
|
-
model,
|
2167
|
-
documentId,
|
2168
|
-
params
|
2169
|
-
});
|
2170
|
-
}
|
2171
|
-
}
|
2172
|
-
};
|
2173
|
-
};
|
2174
|
-
DiscardAction.type = "discard";
|
2175
|
-
const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
|
2176
|
-
path {
|
2177
|
-
fill: currentColor;
|
2178
|
-
}
|
2179
|
-
`;
|
2180
|
-
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2181
|
-
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2182
|
-
const RelativeTime = React__namespace.forwardRef(
|
2183
|
-
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
2184
|
-
const { formatRelativeTime, formatDate, formatTime } = reactIntl.useIntl();
|
2185
|
-
const interval = dateFns.intervalToDuration({
|
2186
|
-
start: timestamp,
|
2187
|
-
end: Date.now()
|
2188
|
-
// see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
|
2189
|
-
});
|
2190
|
-
const unit = intervals.find((intervalUnit) => {
|
2191
|
-
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2192
|
-
});
|
2193
|
-
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2194
|
-
const customInterval = customIntervals.find(
|
2195
|
-
(custom) => interval[custom.unit] < custom.threshold
|
2196
|
-
);
|
2197
|
-
const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
|
2198
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
2199
|
-
"time",
|
2200
|
-
{
|
2201
|
-
ref: forwardedRef,
|
2202
|
-
dateTime: timestamp.toISOString(),
|
2203
|
-
role: "time",
|
2204
|
-
title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
|
2205
|
-
...restProps,
|
2206
|
-
children: displayText
|
2207
|
-
}
|
2208
|
-
);
|
2209
|
-
}
|
2210
|
-
);
|
2211
|
-
const getDisplayName = ({
|
2212
|
-
firstname,
|
2213
|
-
lastname,
|
2214
|
-
username,
|
2215
|
-
email
|
2216
|
-
} = {}) => {
|
2217
|
-
if (username) {
|
2218
|
-
return username;
|
2219
|
-
}
|
2220
|
-
if (firstname) {
|
2221
|
-
return `${firstname} ${lastname ?? ""}`.trim();
|
2222
|
-
}
|
2223
|
-
return email ?? "";
|
2224
|
-
};
|
2225
|
-
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2226
|
-
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2227
|
-
const statusVariant = status === "draft" ? "primary" : status === "published" ? "success" : "alternative";
|
2228
|
-
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) }) });
|
2229
|
-
};
|
2230
|
-
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2231
|
-
const { formatMessage } = reactIntl.useIntl();
|
2089
|
+
const navigate = reactRouterDom.useNavigate();
|
2090
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2091
|
+
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2092
|
+
const isListView = reactRouterDom.useMatch(LIST_PATH) !== null;
|
2232
2093
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2233
|
-
const title = isCreating ? formatMessage({
|
2234
|
-
id: "content-manager.containers.edit.title.new",
|
2235
|
-
defaultMessage: "Create an entry"
|
2236
|
-
}) : documentTitle;
|
2237
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2238
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
2239
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2240
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2241
|
-
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2242
|
-
] }),
|
2243
|
-
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2244
|
-
] });
|
2245
|
-
};
|
2246
|
-
const HeaderToolbar = () => {
|
2247
2094
|
const { formatMessage } = reactIntl.useIntl();
|
2248
|
-
const
|
2095
|
+
const canPublish = useDocumentRBAC("PublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2096
|
+
const { publish } = useDocumentActions();
|
2249
2097
|
const [
|
2250
|
-
|
2251
|
-
|
2098
|
+
countDraftRelations,
|
2099
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
2100
|
+
] = useLazyGetDraftRelationCountQuery();
|
2101
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
2102
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
2103
|
+
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
2104
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2105
|
+
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
2106
|
+
const setSubmitting = strapiAdmin.useForm("PublishAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
2107
|
+
const isSubmitting = strapiAdmin.useForm("PublishAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
2108
|
+
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
2109
|
+
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
2110
|
+
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
2111
|
+
React__namespace.useEffect(() => {
|
2112
|
+
if (isErrorDraftRelations) {
|
2113
|
+
toggleNotification({
|
2114
|
+
type: "danger",
|
2115
|
+
message: formatMessage({
|
2116
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
2117
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
2118
|
+
})
|
2119
|
+
});
|
2252
2120
|
}
|
2253
|
-
|
2254
|
-
|
2255
|
-
|
2256
|
-
|
2257
|
-
|
2258
|
-
|
2259
|
-
|
2260
|
-
|
2261
|
-
activeTab: status,
|
2262
|
-
model,
|
2263
|
-
documentId: id,
|
2264
|
-
document: isCloning ? void 0 : document,
|
2265
|
-
meta: isCloning ? void 0 : meta,
|
2266
|
-
collectionType
|
2267
|
-
},
|
2268
|
-
descriptions: plugins["content-manager"].apis.getHeaderActions(),
|
2269
|
-
children: (actions2) => {
|
2270
|
-
if (actions2.length > 0) {
|
2271
|
-
return /* @__PURE__ */ jsxRuntime.jsx(HeaderActions, { actions: actions2 });
|
2272
|
-
} else {
|
2273
|
-
return null;
|
2274
|
-
}
|
2121
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
2122
|
+
React__namespace.useEffect(() => {
|
2123
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
2124
|
+
const extractDraftRelations = (data) => {
|
2125
|
+
const relations = data.connect || [];
|
2126
|
+
relations.forEach((relation) => {
|
2127
|
+
if (relation.status === "draft") {
|
2128
|
+
localDraftRelations.add(relation.id);
|
2275
2129
|
}
|
2276
|
-
}
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
documentId: id,
|
2285
|
-
document: isCloning ? void 0 : document,
|
2286
|
-
meta: isCloning ? void 0 : meta,
|
2287
|
-
collectionType
|
2288
|
-
},
|
2289
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2290
|
-
children: (actions2) => {
|
2291
|
-
const headerActions = actions2.filter((action) => {
|
2292
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2293
|
-
return positions.includes("header");
|
2294
|
-
});
|
2295
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
2296
|
-
DocumentActionsMenu,
|
2297
|
-
{
|
2298
|
-
actions: headerActions,
|
2299
|
-
label: formatMessage({
|
2300
|
-
id: "content-manager.containers.edit.header.more-actions",
|
2301
|
-
defaultMessage: "More actions"
|
2302
|
-
}),
|
2303
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(Information, { activeTab: status })
|
2304
|
-
}
|
2305
|
-
);
|
2130
|
+
});
|
2131
|
+
};
|
2132
|
+
const traverseAndExtract = (data) => {
|
2133
|
+
Object.entries(data).forEach(([key, value]) => {
|
2134
|
+
if (key === "connect" && Array.isArray(value)) {
|
2135
|
+
extractDraftRelations({ connect: value });
|
2136
|
+
} else if (typeof value === "object" && value !== null) {
|
2137
|
+
traverseAndExtract(value);
|
2306
2138
|
}
|
2139
|
+
});
|
2140
|
+
};
|
2141
|
+
if (!documentId || modified) {
|
2142
|
+
traverseAndExtract(formValues);
|
2143
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
2144
|
+
}
|
2145
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
2146
|
+
React__namespace.useEffect(() => {
|
2147
|
+
if (!document || !document.documentId || isListView) {
|
2148
|
+
return;
|
2149
|
+
}
|
2150
|
+
const fetchDraftRelationsCount = async () => {
|
2151
|
+
const { data, error } = await countDraftRelations({
|
2152
|
+
collectionType,
|
2153
|
+
model,
|
2154
|
+
documentId,
|
2155
|
+
params
|
2156
|
+
});
|
2157
|
+
if (error) {
|
2158
|
+
throw error;
|
2307
2159
|
}
|
2308
|
-
|
2309
|
-
|
2310
|
-
}
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2160
|
+
if (data) {
|
2161
|
+
setServerCountOfDraftRelations(data.data);
|
2162
|
+
}
|
2163
|
+
};
|
2164
|
+
fetchDraftRelationsCount();
|
2165
|
+
}, [isListView, document, documentId, countDraftRelations, collectionType, model, params]);
|
2166
|
+
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
2167
|
+
if (!schema?.options?.draftAndPublish) {
|
2315
2168
|
return null;
|
2316
2169
|
}
|
2317
|
-
const
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
2321
|
-
|
2322
|
-
|
2323
|
-
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2327
|
-
|
2328
|
-
|
2170
|
+
const performPublish = async () => {
|
2171
|
+
setSubmitting(true);
|
2172
|
+
try {
|
2173
|
+
const { errors } = await validate(true, {
|
2174
|
+
status: "published"
|
2175
|
+
});
|
2176
|
+
if (errors) {
|
2177
|
+
toggleNotification({
|
2178
|
+
type: "danger",
|
2179
|
+
message: formatMessage({
|
2180
|
+
id: "content-manager.validation.error",
|
2181
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2182
|
+
})
|
2183
|
+
});
|
2184
|
+
return;
|
2185
|
+
}
|
2186
|
+
const res = await publish(
|
2329
2187
|
{
|
2330
|
-
|
2331
|
-
|
2188
|
+
collectionType,
|
2189
|
+
model,
|
2190
|
+
documentId,
|
2191
|
+
params
|
2332
2192
|
},
|
2333
|
-
|
2334
|
-
|
2335
|
-
|
2336
|
-
|
2337
|
-
|
2338
|
-
|
2193
|
+
formValues
|
2194
|
+
);
|
2195
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2196
|
+
navigate({
|
2197
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
2198
|
+
search: rawQuery
|
2199
|
+
});
|
2200
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2201
|
+
setErrors(formatValidationErrors(res.error));
|
2202
|
+
}
|
2203
|
+
} finally {
|
2204
|
+
setSubmitting(false);
|
2205
|
+
}
|
2206
|
+
};
|
2207
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
2208
|
+
const enableDraftRelationsCount = false;
|
2209
|
+
const hasDraftRelations = enableDraftRelationsCount;
|
2210
|
+
return {
|
2211
|
+
/**
|
2212
|
+
* Disabled when:
|
2213
|
+
* - currently if you're cloning a document we don't support publish & clone at the same time.
|
2214
|
+
* - the form is submitting
|
2215
|
+
* - the active tab is the published tab
|
2216
|
+
* - the document is already published & not modified
|
2217
|
+
* - the document is being created & not modified
|
2218
|
+
* - the user doesn't have the permission to publish
|
2219
|
+
*/
|
2220
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
2221
|
+
label: formatMessage({
|
2222
|
+
id: "app.utils.publish",
|
2223
|
+
defaultMessage: "Publish"
|
2224
|
+
}),
|
2225
|
+
onClick: async () => {
|
2226
|
+
await performPublish();
|
2339
2227
|
},
|
2340
|
-
{
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2228
|
+
dialog: hasDraftRelations ? {
|
2229
|
+
type: "dialog",
|
2230
|
+
variant: "danger",
|
2231
|
+
footer: null,
|
2232
|
+
title: formatMessage({
|
2233
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
2234
|
+
defaultMessage: "Confirmation"
|
2345
2235
|
}),
|
2346
|
-
|
2236
|
+
content: formatMessage(
|
2347
2237
|
{
|
2348
|
-
id:
|
2349
|
-
defaultMessage:
|
2238
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2239
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
2350
2240
|
},
|
2351
2241
|
{
|
2352
|
-
|
2353
|
-
RelativeTime,
|
2354
|
-
{
|
2355
|
-
timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
|
2356
|
-
}
|
2357
|
-
),
|
2358
|
-
isAnonymous: !updator,
|
2359
|
-
author: updator
|
2242
|
+
count: totalDraftRelations
|
2360
2243
|
}
|
2361
|
-
)
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2244
|
+
),
|
2245
|
+
onConfirm: async () => {
|
2246
|
+
await performPublish();
|
2247
|
+
}
|
2248
|
+
} : void 0
|
2249
|
+
};
|
2250
|
+
};
|
2251
|
+
PublishAction$1.type = "publish";
|
2252
|
+
const UpdateAction = ({
|
2253
|
+
activeTab,
|
2254
|
+
documentId,
|
2255
|
+
model,
|
2256
|
+
collectionType
|
2257
|
+
}) => {
|
2258
|
+
const navigate = reactRouterDom.useNavigate();
|
2259
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2260
|
+
const { _unstableFormatValidationErrors: formatValidationErrors } = strapiAdmin.useAPIErrorHandler();
|
2261
|
+
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
2262
|
+
const isCloning = cloneMatch !== null;
|
2263
|
+
const { formatMessage } = reactIntl.useIntl();
|
2264
|
+
const { create, update, clone } = useDocumentActions();
|
2265
|
+
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
2266
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2267
|
+
const isSubmitting = strapiAdmin.useForm("UpdateAction", ({ isSubmitting: isSubmitting2 }) => isSubmitting2);
|
2268
|
+
const modified = strapiAdmin.useForm("UpdateAction", ({ modified: modified2 }) => modified2);
|
2269
|
+
const setSubmitting = strapiAdmin.useForm("UpdateAction", ({ setSubmitting: setSubmitting2 }) => setSubmitting2);
|
2270
|
+
const document = strapiAdmin.useForm("UpdateAction", ({ values }) => values);
|
2271
|
+
const validate = strapiAdmin.useForm("UpdateAction", (state) => state.validate);
|
2272
|
+
const setErrors = strapiAdmin.useForm("UpdateAction", (state) => state.setErrors);
|
2273
|
+
const resetForm = strapiAdmin.useForm("PublishAction", ({ resetForm: resetForm2 }) => resetForm2);
|
2274
|
+
return {
|
2275
|
+
/**
|
2276
|
+
* Disabled when:
|
2277
|
+
* - the form is submitting
|
2278
|
+
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
2279
|
+
* - the active tab is the published tab
|
2280
|
+
*/
|
2281
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
2282
|
+
label: formatMessage({
|
2283
|
+
id: "content-manager.containers.Edit.save",
|
2284
|
+
defaultMessage: "Save"
|
2285
|
+
}),
|
2286
|
+
onClick: async () => {
|
2287
|
+
setSubmitting(true);
|
2288
|
+
try {
|
2289
|
+
const { errors } = await validate(true, {
|
2290
|
+
status: "draft"
|
2291
|
+
});
|
2292
|
+
if (errors) {
|
2293
|
+
toggleNotification({
|
2294
|
+
type: "danger",
|
2295
|
+
message: formatMessage({
|
2296
|
+
id: "content-manager.validation.error",
|
2297
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
2298
|
+
})
|
2299
|
+
});
|
2300
|
+
return;
|
2383
2301
|
}
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
2395
|
-
|
2396
|
-
|
2397
|
-
|
2398
|
-
|
2399
|
-
|
2400
|
-
|
2401
|
-
|
2402
|
-
|
2403
|
-
|
2404
|
-
|
2405
|
-
|
2302
|
+
if (isCloning) {
|
2303
|
+
const res = await clone(
|
2304
|
+
{
|
2305
|
+
model,
|
2306
|
+
documentId: cloneMatch.params.origin,
|
2307
|
+
params
|
2308
|
+
},
|
2309
|
+
document
|
2310
|
+
);
|
2311
|
+
if ("data" in res) {
|
2312
|
+
navigate(
|
2313
|
+
{
|
2314
|
+
pathname: `../${res.data.documentId}`,
|
2315
|
+
search: rawQuery
|
2316
|
+
},
|
2317
|
+
{ relative: "path" }
|
2318
|
+
);
|
2319
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2320
|
+
setErrors(formatValidationErrors(res.error));
|
2321
|
+
}
|
2322
|
+
} else if (documentId || collectionType === SINGLE_TYPES) {
|
2323
|
+
const res = await update(
|
2324
|
+
{
|
2325
|
+
collectionType,
|
2326
|
+
model,
|
2327
|
+
documentId,
|
2328
|
+
params
|
2329
|
+
},
|
2330
|
+
document
|
2331
|
+
);
|
2332
|
+
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2333
|
+
setErrors(formatValidationErrors(res.error));
|
2334
|
+
} else {
|
2335
|
+
resetForm();
|
2336
|
+
}
|
2337
|
+
} else {
|
2338
|
+
const res = await create(
|
2339
|
+
{
|
2340
|
+
model,
|
2341
|
+
params
|
2342
|
+
},
|
2343
|
+
document
|
2344
|
+
);
|
2345
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
2346
|
+
navigate(
|
2347
|
+
{
|
2348
|
+
pathname: `../${res.data.documentId}`,
|
2349
|
+
search: rawQuery
|
2350
|
+
},
|
2351
|
+
{ replace: true, relative: "path" }
|
2352
|
+
);
|
2353
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
2354
|
+
setErrors(formatValidationErrors(res.error));
|
2355
|
+
}
|
2356
|
+
}
|
2357
|
+
} finally {
|
2358
|
+
setSubmitting(false);
|
2359
|
+
}
|
2406
2360
|
}
|
2407
|
-
|
2361
|
+
};
|
2408
2362
|
};
|
2409
|
-
|
2410
|
-
|
2411
|
-
|
2412
|
-
|
2413
|
-
designSystem.SingleSelect,
|
2414
|
-
{
|
2415
|
-
size: "S",
|
2416
|
-
disabled: action.disabled,
|
2417
|
-
"aria-label": action.label,
|
2418
|
-
onChange: action.onSelect,
|
2419
|
-
value: action.value,
|
2420
|
-
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2421
|
-
},
|
2422
|
-
action.id
|
2423
|
-
);
|
2424
|
-
} else {
|
2425
|
-
return null;
|
2426
|
-
}
|
2427
|
-
}) });
|
2363
|
+
UpdateAction.type = "update";
|
2364
|
+
const UNPUBLISH_DRAFT_OPTIONS = {
|
2365
|
+
KEEP: "keep",
|
2366
|
+
DISCARD: "discard"
|
2428
2367
|
};
|
2429
|
-
const
|
2430
|
-
|
2368
|
+
const UnpublishAction$1 = ({
|
2369
|
+
activeTab,
|
2370
|
+
documentId,
|
2371
|
+
model,
|
2372
|
+
collectionType,
|
2373
|
+
document
|
2374
|
+
}) => {
|
2431
2375
|
const { formatMessage } = reactIntl.useIntl();
|
2432
|
-
|
2433
|
-
|
2434
|
-
|
2435
|
-
|
2436
|
-
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2376
|
+
const { schema } = useDoc();
|
2377
|
+
const canPublish = useDocumentRBAC("UnpublishAction", ({ canPublish: canPublish2 }) => canPublish2);
|
2378
|
+
const { unpublish } = useDocumentActions();
|
2379
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
2380
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2381
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2382
|
+
const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
|
2383
|
+
const isDocumentModified = document?.status === "modified";
|
2384
|
+
const handleChange = (value) => {
|
2385
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
2442
2386
|
};
|
2443
|
-
|
2444
|
-
|
2445
|
-
|
2446
|
-
const navigate = reactRouterDom.useNavigate();
|
2447
|
-
const { formatMessage } = reactIntl.useIntl();
|
2387
|
+
if (!schema?.options?.draftAndPublish) {
|
2388
|
+
return null;
|
2389
|
+
}
|
2448
2390
|
return {
|
2391
|
+
disabled: !canPublish || activeTab === "published" || document?.status !== "published" && document?.status !== "modified",
|
2449
2392
|
label: formatMessage({
|
2450
|
-
id: "
|
2451
|
-
defaultMessage: "
|
2393
|
+
id: "app.utils.unpublish",
|
2394
|
+
defaultMessage: "Unpublish"
|
2452
2395
|
}),
|
2453
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.
|
2454
|
-
onClick: () => {
|
2455
|
-
|
2396
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2397
|
+
onClick: async () => {
|
2398
|
+
if (!documentId && collectionType !== SINGLE_TYPES || isDocumentModified) {
|
2399
|
+
if (!documentId) {
|
2400
|
+
console.error(
|
2401
|
+
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2402
|
+
);
|
2403
|
+
toggleNotification({
|
2404
|
+
message: formatMessage({
|
2405
|
+
id: "content-manager.actions.unpublish.error",
|
2406
|
+
defaultMessage: "An error occurred while trying to unpublish the document."
|
2407
|
+
}),
|
2408
|
+
type: "danger"
|
2409
|
+
});
|
2410
|
+
}
|
2411
|
+
return;
|
2412
|
+
}
|
2413
|
+
await unpublish({
|
2414
|
+
collectionType,
|
2415
|
+
model,
|
2416
|
+
documentId,
|
2417
|
+
params
|
2418
|
+
});
|
2456
2419
|
},
|
2457
|
-
|
2420
|
+
dialog: isDocumentModified ? {
|
2421
|
+
type: "dialog",
|
2422
|
+
title: formatMessage({
|
2423
|
+
id: "app.components.ConfirmDialog.title",
|
2424
|
+
defaultMessage: "Confirmation"
|
2425
|
+
}),
|
2426
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "flex-start", direction: "column", gap: 6, children: [
|
2427
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", direction: "column", gap: 2, children: [
|
2428
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2429
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2430
|
+
id: "content-manager.actions.unpublish.dialog.body",
|
2431
|
+
defaultMessage: "Are you sure?"
|
2432
|
+
}) })
|
2433
|
+
] }),
|
2434
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
2435
|
+
designSystem.Radio.Group,
|
2436
|
+
{
|
2437
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2438
|
+
name: "discard-options",
|
2439
|
+
"aria-label": formatMessage({
|
2440
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2441
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2442
|
+
}),
|
2443
|
+
onValueChange: handleChange,
|
2444
|
+
children: [
|
2445
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2446
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2447
|
+
defaultMessage: "Keep draft"
|
2448
|
+
}) }),
|
2449
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2450
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2451
|
+
defaultMessage: "Replace draft"
|
2452
|
+
}) })
|
2453
|
+
]
|
2454
|
+
}
|
2455
|
+
)
|
2456
|
+
] }),
|
2457
|
+
onConfirm: async () => {
|
2458
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2459
|
+
console.error(
|
2460
|
+
"You're trying to unpublish a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2461
|
+
);
|
2462
|
+
toggleNotification({
|
2463
|
+
message: formatMessage({
|
2464
|
+
id: "content-manager.actions.unpublish.error",
|
2465
|
+
defaultMessage: "An error occurred while trying to unpublish the document."
|
2466
|
+
}),
|
2467
|
+
type: "danger"
|
2468
|
+
});
|
2469
|
+
}
|
2470
|
+
await unpublish(
|
2471
|
+
{
|
2472
|
+
collectionType,
|
2473
|
+
model,
|
2474
|
+
documentId,
|
2475
|
+
params
|
2476
|
+
},
|
2477
|
+
!shouldKeepDraft
|
2478
|
+
);
|
2479
|
+
}
|
2480
|
+
} : void 0,
|
2481
|
+
variant: "danger",
|
2482
|
+
position: ["panel", "table-row"]
|
2458
2483
|
};
|
2459
2484
|
};
|
2460
|
-
|
2461
|
-
const
|
2462
|
-
|
2485
|
+
UnpublishAction$1.type = "unpublish";
|
2486
|
+
const DiscardAction = ({
|
2487
|
+
activeTab,
|
2488
|
+
documentId,
|
2489
|
+
model,
|
2490
|
+
collectionType,
|
2491
|
+
document
|
2492
|
+
}) => {
|
2463
2493
|
const { formatMessage } = reactIntl.useIntl();
|
2464
|
-
const
|
2465
|
-
const
|
2466
|
-
const {
|
2467
|
-
const {
|
2468
|
-
const
|
2494
|
+
const { schema } = useDoc();
|
2495
|
+
const canUpdate = useDocumentRBAC("DiscardAction", ({ canUpdate: canUpdate2 }) => canUpdate2);
|
2496
|
+
const { discard } = useDocumentActions();
|
2497
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
2498
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
2499
|
+
if (!schema?.options?.draftAndPublish) {
|
2500
|
+
return null;
|
2501
|
+
}
|
2469
2502
|
return {
|
2470
|
-
disabled: !
|
2503
|
+
disabled: !canUpdate || activeTab === "published" || document?.status !== "modified",
|
2471
2504
|
label: formatMessage({
|
2472
|
-
id: "content-manager.actions.
|
2473
|
-
defaultMessage: "
|
2505
|
+
id: "content-manager.actions.discard.label",
|
2506
|
+
defaultMessage: "Discard changes"
|
2474
2507
|
}),
|
2475
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.
|
2508
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Cross, {}),
|
2509
|
+
position: ["panel", "table-row"],
|
2510
|
+
variant: "danger",
|
2476
2511
|
dialog: {
|
2477
2512
|
type: "dialog",
|
2478
2513
|
title: formatMessage({
|
@@ -2482,92 +2517,90 @@ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
|
2482
2517
|
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2483
2518
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2484
2519
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2485
|
-
id: "content-manager.actions.
|
2520
|
+
id: "content-manager.actions.discard.dialog.body",
|
2486
2521
|
defaultMessage: "Are you sure?"
|
2487
2522
|
}) })
|
2488
2523
|
] }),
|
2489
2524
|
onConfirm: async () => {
|
2490
|
-
|
2491
|
-
|
2492
|
-
|
2493
|
-
|
2494
|
-
|
2495
|
-
|
2496
|
-
|
2497
|
-
|
2498
|
-
|
2499
|
-
|
2500
|
-
|
2501
|
-
|
2502
|
-
|
2503
|
-
|
2504
|
-
|
2505
|
-
|
2506
|
-
|
2507
|
-
|
2508
|
-
|
2509
|
-
|
2510
|
-
|
2511
|
-
|
2512
|
-
|
2513
|
-
|
2514
|
-
|
2515
|
-
|
2516
|
-
|
2517
|
-
|
2518
|
-
|
2519
|
-
|
2520
|
-
|
2521
|
-
|
2522
|
-
|
2525
|
+
await discard({
|
2526
|
+
collectionType,
|
2527
|
+
model,
|
2528
|
+
documentId,
|
2529
|
+
params
|
2530
|
+
});
|
2531
|
+
}
|
2532
|
+
}
|
2533
|
+
};
|
2534
|
+
};
|
2535
|
+
DiscardAction.type = "discard";
|
2536
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2537
|
+
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2538
|
+
const RelativeTime = React__namespace.forwardRef(
|
2539
|
+
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
2540
|
+
const { formatRelativeTime, formatDate, formatTime } = reactIntl.useIntl();
|
2541
|
+
const interval = dateFns.intervalToDuration({
|
2542
|
+
start: timestamp,
|
2543
|
+
end: Date.now()
|
2544
|
+
// see https://github.com/date-fns/date-fns/issues/2891 – No idea why it's all partial it returns it every time.
|
2545
|
+
});
|
2546
|
+
const unit = intervals.find((intervalUnit) => {
|
2547
|
+
return interval[intervalUnit] > 0 && Object.keys(interval).includes(intervalUnit);
|
2548
|
+
});
|
2549
|
+
const relativeTime = dateFns.isPast(timestamp) ? -interval[unit] : interval[unit];
|
2550
|
+
const customInterval = customIntervals.find(
|
2551
|
+
(custom) => interval[custom.unit] < custom.threshold
|
2552
|
+
);
|
2553
|
+
const displayText = customInterval ? customInterval.text : formatRelativeTime(relativeTime, unit, { numeric: "auto" });
|
2554
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2555
|
+
"time",
|
2556
|
+
{
|
2557
|
+
ref: forwardedRef,
|
2558
|
+
dateTime: timestamp.toISOString(),
|
2559
|
+
role: "time",
|
2560
|
+
title: `${formatDate(timestamp)} ${formatTime(timestamp)}`,
|
2561
|
+
...restProps,
|
2562
|
+
children: displayText
|
2523
2563
|
}
|
2524
|
-
|
2525
|
-
|
2526
|
-
|
2527
|
-
|
2564
|
+
);
|
2565
|
+
}
|
2566
|
+
);
|
2567
|
+
const getDisplayName = ({
|
2568
|
+
firstname,
|
2569
|
+
lastname,
|
2570
|
+
username,
|
2571
|
+
email
|
2572
|
+
} = {}) => {
|
2573
|
+
if (username) {
|
2574
|
+
return username;
|
2575
|
+
}
|
2576
|
+
if (firstname) {
|
2577
|
+
return `${firstname} ${lastname ?? ""}`.trim();
|
2578
|
+
}
|
2579
|
+
return email ?? "";
|
2528
2580
|
};
|
2529
|
-
|
2530
|
-
const
|
2531
|
-
const
|
2532
|
-
|
2533
|
-
const [
|
2534
|
-
{
|
2535
|
-
query: { status }
|
2536
|
-
}
|
2537
|
-
] = strapiAdmin.useQueryParams({
|
2538
|
-
status: "draft"
|
2539
|
-
});
|
2540
|
-
const { model, id, document, meta, collectionType } = useDoc();
|
2541
|
-
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2542
|
-
const props = {
|
2543
|
-
activeTab: status,
|
2544
|
-
model,
|
2545
|
-
documentId: id,
|
2546
|
-
document: isCloning ? void 0 : document,
|
2547
|
-
meta: isCloning ? void 0 : meta,
|
2548
|
-
collectionType
|
2549
|
-
};
|
2550
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2551
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2552
|
-
{
|
2553
|
-
props,
|
2554
|
-
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2555
|
-
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2556
|
-
}
|
2557
|
-
) });
|
2581
|
+
const capitalise = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
2582
|
+
const DocumentStatus = ({ status = "draft", ...restProps }) => {
|
2583
|
+
const statusVariant = status === "draft" ? "secondary" : status === "published" ? "success" : "alternative";
|
2584
|
+
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) }) });
|
2558
2585
|
};
|
2559
|
-
const
|
2586
|
+
const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
2560
2587
|
const { formatMessage } = reactIntl.useIntl();
|
2561
|
-
|
2562
|
-
|
2563
|
-
|
2564
|
-
|
2565
|
-
|
2566
|
-
|
2567
|
-
|
2588
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2589
|
+
const title = isCreating ? formatMessage({
|
2590
|
+
id: "content-manager.containers.edit.title.new",
|
2591
|
+
defaultMessage: "Create an entry"
|
2592
|
+
}) : documentTitle;
|
2593
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2594
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
2595
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2596
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2597
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2598
|
+
] }),
|
2599
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2600
|
+
] });
|
2568
2601
|
};
|
2569
|
-
|
2570
|
-
const
|
2602
|
+
const HeaderToolbar = () => {
|
2603
|
+
const { formatMessage } = reactIntl.useIntl();
|
2571
2604
|
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2572
2605
|
const [
|
2573
2606
|
{
|
@@ -2575,355 +2608,432 @@ const ActionsPanelContent = () => {
|
|
2575
2608
|
}
|
2576
2609
|
] = strapiAdmin.useQueryParams();
|
2577
2610
|
const { model, id, document, meta, collectionType } = useDoc();
|
2578
|
-
const plugins = strapiAdmin.useStrapiApp("
|
2579
|
-
|
2580
|
-
activeTab: status,
|
2581
|
-
model,
|
2582
|
-
documentId: id,
|
2583
|
-
document: isCloning ? void 0 : document,
|
2584
|
-
meta: isCloning ? void 0 : meta,
|
2585
|
-
collectionType
|
2586
|
-
};
|
2587
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
2611
|
+
const plugins = strapiAdmin.useStrapiApp("HeaderToolbar", (state) => state.plugins);
|
2612
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
2588
2613
|
/* @__PURE__ */ jsxRuntime.jsx(
|
2589
2614
|
strapiAdmin.DescriptionComponentRenderer,
|
2590
2615
|
{
|
2591
|
-
props
|
2592
|
-
|
2593
|
-
|
2616
|
+
props: {
|
2617
|
+
activeTab: status,
|
2618
|
+
model,
|
2619
|
+
documentId: id,
|
2620
|
+
document: isCloning ? void 0 : document,
|
2621
|
+
meta: isCloning ? void 0 : meta,
|
2622
|
+
collectionType
|
2623
|
+
},
|
2624
|
+
descriptions: plugins["content-manager"].apis.getHeaderActions(),
|
2625
|
+
children: (actions2) => {
|
2626
|
+
if (actions2.length > 0) {
|
2627
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HeaderActions, { actions: actions2 });
|
2628
|
+
} else {
|
2629
|
+
return null;
|
2630
|
+
}
|
2631
|
+
}
|
2594
2632
|
}
|
2595
2633
|
),
|
2596
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2634
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2635
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2636
|
+
{
|
2637
|
+
props: {
|
2638
|
+
activeTab: status,
|
2639
|
+
model,
|
2640
|
+
documentId: id,
|
2641
|
+
document: isCloning ? void 0 : document,
|
2642
|
+
meta: isCloning ? void 0 : meta,
|
2643
|
+
collectionType
|
2644
|
+
},
|
2645
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2646
|
+
children: (actions2) => {
|
2647
|
+
const headerActions = actions2.filter((action) => {
|
2648
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2649
|
+
return positions.includes("header");
|
2650
|
+
});
|
2651
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2652
|
+
DocumentActionsMenu,
|
2653
|
+
{
|
2654
|
+
actions: headerActions,
|
2655
|
+
label: formatMessage({
|
2656
|
+
id: "content-manager.containers.edit.header.more-actions",
|
2657
|
+
defaultMessage: "More actions"
|
2658
|
+
}),
|
2659
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Information, { activeTab: status })
|
2660
|
+
}
|
2661
|
+
);
|
2662
|
+
}
|
2663
|
+
}
|
2664
|
+
)
|
2597
2665
|
] });
|
2598
2666
|
};
|
2599
|
-
const
|
2600
|
-
|
2601
|
-
|
2667
|
+
const Information = ({ activeTab }) => {
|
2668
|
+
const { formatMessage } = reactIntl.useIntl();
|
2669
|
+
const { document, meta } = useDoc();
|
2670
|
+
if (!document || !document.id) {
|
2671
|
+
return null;
|
2672
|
+
}
|
2673
|
+
const createAndUpdateDocument = activeTab === "draft" ? document : meta?.availableStatus.find((status) => status.publishedAt === null);
|
2674
|
+
const publishDocument = activeTab === "published" ? document : meta?.availableStatus.find((status) => status.publishedAt !== null);
|
2675
|
+
const creator = createAndUpdateDocument?.[CREATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[CREATED_BY_ATTRIBUTE_NAME]) : null;
|
2676
|
+
const updator = createAndUpdateDocument?.[UPDATED_BY_ATTRIBUTE_NAME] ? getDisplayName(createAndUpdateDocument[UPDATED_BY_ATTRIBUTE_NAME]) : null;
|
2677
|
+
const information = [
|
2602
2678
|
{
|
2603
|
-
|
2604
|
-
|
2605
|
-
|
2606
|
-
|
2607
|
-
borderColor: "neutral150",
|
2608
|
-
hasRadius: true,
|
2609
|
-
paddingBottom: 4,
|
2610
|
-
paddingLeft: 4,
|
2611
|
-
paddingRight: 4,
|
2612
|
-
paddingTop: 4,
|
2613
|
-
shadow: "tableShadow",
|
2614
|
-
gap: 3,
|
2615
|
-
direction: "column",
|
2616
|
-
justifyContent: "stretch",
|
2617
|
-
alignItems: "flex-start",
|
2618
|
-
children: [
|
2619
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
2620
|
-
children
|
2621
|
-
]
|
2622
|
-
}
|
2623
|
-
);
|
2624
|
-
});
|
2625
|
-
const HOOKS = {
|
2626
|
-
/**
|
2627
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
2628
|
-
* @constant
|
2629
|
-
* @type {string}
|
2630
|
-
*/
|
2631
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2632
|
-
/**
|
2633
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2634
|
-
* @constant
|
2635
|
-
* @type {string}
|
2636
|
-
*/
|
2637
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2638
|
-
/**
|
2639
|
-
* Hook that allows to mutate the CM's edit view layout
|
2640
|
-
* @constant
|
2641
|
-
* @type {string}
|
2642
|
-
*/
|
2643
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2644
|
-
/**
|
2645
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
2646
|
-
* @constant
|
2647
|
-
* @type {string}
|
2648
|
-
*/
|
2649
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2650
|
-
};
|
2651
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2652
|
-
endpoints: (builder) => ({
|
2653
|
-
getContentTypeConfiguration: builder.query({
|
2654
|
-
query: (uid) => ({
|
2655
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
2656
|
-
method: "GET"
|
2679
|
+
isDisplayed: !!publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME],
|
2680
|
+
label: formatMessage({
|
2681
|
+
id: "content-manager.containers.edit.information.last-published.label",
|
2682
|
+
defaultMessage: "Published"
|
2657
2683
|
}),
|
2658
|
-
|
2659
|
-
|
2660
|
-
|
2661
|
-
|
2662
|
-
|
2663
|
-
|
2664
|
-
|
2665
|
-
|
2666
|
-
|
2667
|
-
|
2668
|
-
|
2669
|
-
|
2670
|
-
|
2671
|
-
|
2672
|
-
|
2673
|
-
|
2684
|
+
value: formatMessage(
|
2685
|
+
{
|
2686
|
+
id: "content-manager.containers.edit.information.last-published.value",
|
2687
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2688
|
+
},
|
2689
|
+
{
|
2690
|
+
time: /* @__PURE__ */ jsxRuntime.jsx(RelativeTime, { timestamp: new Date(publishDocument?.[PUBLISHED_AT_ATTRIBUTE_NAME]) }),
|
2691
|
+
isAnonymous: !publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME],
|
2692
|
+
author: publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME] ? getDisplayName(publishDocument?.[PUBLISHED_BY_ATTRIBUTE_NAME]) : null
|
2693
|
+
}
|
2694
|
+
)
|
2695
|
+
},
|
2696
|
+
{
|
2697
|
+
isDisplayed: !!createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME],
|
2698
|
+
label: formatMessage({
|
2699
|
+
id: "content-manager.containers.edit.information.last-draft.label",
|
2700
|
+
defaultMessage: "Updated"
|
2701
|
+
}),
|
2702
|
+
value: formatMessage(
|
2703
|
+
{
|
2704
|
+
id: "content-manager.containers.edit.information.last-draft.value",
|
2705
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2706
|
+
},
|
2707
|
+
{
|
2708
|
+
time: /* @__PURE__ */ jsxRuntime.jsx(
|
2709
|
+
RelativeTime,
|
2710
|
+
{
|
2711
|
+
timestamp: new Date(createAndUpdateDocument?.[UPDATED_AT_ATTRIBUTE_NAME])
|
2712
|
+
}
|
2713
|
+
),
|
2714
|
+
isAnonymous: !updator,
|
2715
|
+
author: updator
|
2716
|
+
}
|
2717
|
+
)
|
2718
|
+
},
|
2719
|
+
{
|
2720
|
+
isDisplayed: !!createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME],
|
2721
|
+
label: formatMessage({
|
2722
|
+
id: "content-manager.containers.edit.information.document.label",
|
2723
|
+
defaultMessage: "Created"
|
2674
2724
|
}),
|
2675
|
-
|
2676
|
-
|
2677
|
-
|
2678
|
-
|
2679
|
-
|
2680
|
-
{
|
2681
|
-
|
2682
|
-
|
2683
|
-
|
2684
|
-
|
2685
|
-
|
2686
|
-
|
2687
|
-
|
2688
|
-
|
2689
|
-
}
|
2690
|
-
|
2691
|
-
|
2692
|
-
|
2693
|
-
|
2694
|
-
|
2695
|
-
|
2696
|
-
|
2697
|
-
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
2702
|
-
|
2703
|
-
|
2725
|
+
value: formatMessage(
|
2726
|
+
{
|
2727
|
+
id: "content-manager.containers.edit.information.document.value",
|
2728
|
+
defaultMessage: `{time}{isAnonymous, select, true {} other { by {author}}}`
|
2729
|
+
},
|
2730
|
+
{
|
2731
|
+
time: /* @__PURE__ */ jsxRuntime.jsx(
|
2732
|
+
RelativeTime,
|
2733
|
+
{
|
2734
|
+
timestamp: new Date(createAndUpdateDocument?.[CREATED_AT_ATTRIBUTE_NAME])
|
2735
|
+
}
|
2736
|
+
),
|
2737
|
+
isAnonymous: !creator,
|
2738
|
+
author: creator
|
2739
|
+
}
|
2740
|
+
)
|
2741
|
+
}
|
2742
|
+
].filter((info) => info.isDisplayed);
|
2743
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2744
|
+
designSystem.Flex,
|
2745
|
+
{
|
2746
|
+
borderWidth: "1px 0 0 0",
|
2747
|
+
borderStyle: "solid",
|
2748
|
+
borderColor: "neutral150",
|
2749
|
+
direction: "column",
|
2750
|
+
marginTop: 2,
|
2751
|
+
tag: "dl",
|
2752
|
+
padding: 5,
|
2753
|
+
gap: 3,
|
2754
|
+
alignItems: "flex-start",
|
2755
|
+
marginLeft: "-0.4rem",
|
2756
|
+
marginRight: "-0.4rem",
|
2757
|
+
width: "calc(100% + 8px)",
|
2758
|
+
children: information.map((info) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, direction: "column", alignItems: "flex-start", children: [
|
2759
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dt", variant: "pi", fontWeight: "bold", children: info.label }),
|
2760
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "dd", variant: "pi", textColor: "neutral600", children: info.value })
|
2761
|
+
] }, info.label))
|
2762
|
+
}
|
2704
2763
|
);
|
2705
|
-
return {
|
2706
|
-
name: mainFieldName,
|
2707
|
-
type: mainFieldType ?? "string"
|
2708
|
-
};
|
2709
|
-
};
|
2710
|
-
const DEFAULT_SETTINGS = {
|
2711
|
-
bulkable: false,
|
2712
|
-
filterable: false,
|
2713
|
-
searchable: false,
|
2714
|
-
pagination: false,
|
2715
|
-
defaultSortBy: "",
|
2716
|
-
defaultSortOrder: "asc",
|
2717
|
-
mainField: "id",
|
2718
|
-
pageSize: 10
|
2719
2764
|
};
|
2720
|
-
const
|
2721
|
-
const
|
2722
|
-
const
|
2723
|
-
|
2724
|
-
|
2725
|
-
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
error,
|
2731
|
-
isFetching: isFetchingConfigs
|
2732
|
-
} = useGetContentTypeConfigurationQuery(model);
|
2733
|
-
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2734
|
-
React__namespace.useEffect(() => {
|
2735
|
-
if (error) {
|
2736
|
-
toggleNotification({
|
2737
|
-
type: "danger",
|
2738
|
-
message: formatAPIError(error)
|
2739
|
-
});
|
2765
|
+
const HeaderActions = ({ actions: actions2 }) => {
|
2766
|
+
const [dialogId, setDialogId] = React__namespace.useState(null);
|
2767
|
+
const handleClick = (action) => async (e) => {
|
2768
|
+
if (!("options" in action)) {
|
2769
|
+
const { onClick = () => false, dialog, id } = action;
|
2770
|
+
const muteDialog = await onClick(e);
|
2771
|
+
if (dialog && !muteDialog) {
|
2772
|
+
e.preventDefault();
|
2773
|
+
setDialogId(id);
|
2774
|
+
}
|
2740
2775
|
}
|
2741
|
-
}, [error, formatAPIError, toggleNotification]);
|
2742
|
-
const editLayout = React__namespace.useMemo(
|
2743
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2744
|
-
layout: [],
|
2745
|
-
components: {},
|
2746
|
-
metadatas: {},
|
2747
|
-
options: {},
|
2748
|
-
settings: DEFAULT_SETTINGS
|
2749
|
-
},
|
2750
|
-
[data, isLoading, schemas, schema, components]
|
2751
|
-
);
|
2752
|
-
const listLayout = React__namespace.useMemo(() => {
|
2753
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2754
|
-
layout: [],
|
2755
|
-
metadatas: {},
|
2756
|
-
options: {},
|
2757
|
-
settings: DEFAULT_SETTINGS
|
2758
|
-
};
|
2759
|
-
}, [data, isLoading, schemas, schema, components]);
|
2760
|
-
const { layout: edit } = React__namespace.useMemo(
|
2761
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2762
|
-
layout: editLayout,
|
2763
|
-
query
|
2764
|
-
}),
|
2765
|
-
[editLayout, query, runHookWaterfall]
|
2766
|
-
);
|
2767
|
-
return {
|
2768
|
-
error,
|
2769
|
-
isLoading,
|
2770
|
-
edit,
|
2771
|
-
list: listLayout
|
2772
2776
|
};
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
return
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
schemas
|
2790
|
-
).reduce((panels, row) => {
|
2791
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
2792
|
-
panels.push([row]);
|
2793
|
-
currentPanelIndex += 2;
|
2777
|
+
const handleClose = () => {
|
2778
|
+
setDialogId(null);
|
2779
|
+
};
|
2780
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 1, children: actions2.map((action) => {
|
2781
|
+
if (action.options) {
|
2782
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2783
|
+
designSystem.SingleSelect,
|
2784
|
+
{
|
2785
|
+
size: "S",
|
2786
|
+
onChange: action.onSelect,
|
2787
|
+
"aria-label": action.label,
|
2788
|
+
...action,
|
2789
|
+
children: action.options.map(({ label, ...option }) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { ...option, children: label }, option.value))
|
2790
|
+
},
|
2791
|
+
action.id
|
2792
|
+
);
|
2794
2793
|
} else {
|
2795
|
-
if (
|
2796
|
-
|
2794
|
+
if (action.type === "icon") {
|
2795
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
|
2796
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
2797
|
+
designSystem.IconButton,
|
2798
|
+
{
|
2799
|
+
disabled: action.disabled,
|
2800
|
+
label: action.label,
|
2801
|
+
size: "S",
|
2802
|
+
onClick: handleClick(action),
|
2803
|
+
children: action.icon
|
2804
|
+
}
|
2805
|
+
),
|
2806
|
+
action.dialog ? /* @__PURE__ */ jsxRuntime.jsx(
|
2807
|
+
HeaderActionDialog,
|
2808
|
+
{
|
2809
|
+
...action.dialog,
|
2810
|
+
isOpen: dialogId === action.id,
|
2811
|
+
onClose: handleClose
|
2812
|
+
}
|
2813
|
+
) : null
|
2814
|
+
] }, action.id);
|
2797
2815
|
}
|
2798
|
-
panels[currentPanelIndex].push(row);
|
2799
2816
|
}
|
2800
|
-
|
2801
|
-
|
2802
|
-
|
2803
|
-
|
2804
|
-
|
2805
|
-
|
2806
|
-
|
2807
|
-
|
2808
|
-
|
2809
|
-
|
2810
|
-
|
2811
|
-
|
2812
|
-
|
2813
|
-
|
2814
|
-
|
2815
|
-
|
2816
|
-
|
2817
|
-
}
|
2818
|
-
|
2819
|
-
|
2820
|
-
|
2821
|
-
|
2822
|
-
|
2823
|
-
|
2824
|
-
|
2825
|
-
|
2817
|
+
}) });
|
2818
|
+
};
|
2819
|
+
const HeaderActionDialog = ({
|
2820
|
+
onClose,
|
2821
|
+
onCancel,
|
2822
|
+
title,
|
2823
|
+
content: Content,
|
2824
|
+
isOpen
|
2825
|
+
}) => {
|
2826
|
+
const handleClose = async () => {
|
2827
|
+
if (onCancel) {
|
2828
|
+
await onCancel();
|
2829
|
+
}
|
2830
|
+
onClose();
|
2831
|
+
};
|
2832
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2833
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
2834
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : Content
|
2835
|
+
] }) });
|
2836
|
+
};
|
2837
|
+
const ConfigureTheViewAction = ({ collectionType, model }) => {
|
2838
|
+
const navigate = reactRouterDom.useNavigate();
|
2839
|
+
const { formatMessage } = reactIntl.useIntl();
|
2840
|
+
return {
|
2841
|
+
label: formatMessage({
|
2842
|
+
id: "app.links.configure-view",
|
2843
|
+
defaultMessage: "Configure the view"
|
2844
|
+
}),
|
2845
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ListPlus, {}),
|
2846
|
+
onClick: () => {
|
2847
|
+
navigate(`../${collectionType}/${model}/configurations/edit`);
|
2826
2848
|
},
|
2827
|
-
|
2828
|
-
|
2849
|
+
position: "header"
|
2850
|
+
};
|
2851
|
+
};
|
2852
|
+
ConfigureTheViewAction.type = "configure-the-view";
|
2853
|
+
const EditTheModelAction = ({ model }) => {
|
2854
|
+
const navigate = reactRouterDom.useNavigate();
|
2855
|
+
const { formatMessage } = reactIntl.useIntl();
|
2829
2856
|
return {
|
2830
|
-
|
2831
|
-
|
2832
|
-
|
2833
|
-
|
2834
|
-
|
2835
|
-
|
2857
|
+
label: formatMessage({
|
2858
|
+
id: "content-manager.link-to-ctb",
|
2859
|
+
defaultMessage: "Edit the model"
|
2860
|
+
}),
|
2861
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
|
2862
|
+
onClick: () => {
|
2863
|
+
navigate(`/plugins/content-type-builder/content-types/${model}`);
|
2836
2864
|
},
|
2837
|
-
|
2838
|
-
...schema?.options,
|
2839
|
-
...schema?.pluginOptions,
|
2840
|
-
...data.contentType.options
|
2841
|
-
}
|
2865
|
+
position: "header"
|
2842
2866
|
};
|
2843
2867
|
};
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
2847
|
-
|
2848
|
-
|
2849
|
-
|
2868
|
+
EditTheModelAction.type = "edit-the-model";
|
2869
|
+
const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
|
2870
|
+
const navigate = reactRouterDom.useNavigate();
|
2871
|
+
const { formatMessage } = reactIntl.useIntl();
|
2872
|
+
const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
|
2873
|
+
const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
|
2874
|
+
const { delete: deleteAction } = useDocumentActions();
|
2875
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2876
|
+
const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
|
2877
|
+
const isLocalized = document?.locale != null;
|
2878
|
+
return {
|
2879
|
+
disabled: !canDelete || !document,
|
2880
|
+
label: formatMessage(
|
2881
|
+
{
|
2882
|
+
id: "content-manager.actions.delete.label",
|
2883
|
+
defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
|
2884
|
+
},
|
2885
|
+
{ isLocalized }
|
2886
|
+
),
|
2887
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
2888
|
+
dialog: {
|
2889
|
+
type: "dialog",
|
2890
|
+
title: formatMessage({
|
2891
|
+
id: "app.components.ConfirmDialog.title",
|
2892
|
+
defaultMessage: "Confirmation"
|
2893
|
+
}),
|
2894
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
|
2895
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
|
2896
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
|
2897
|
+
id: "content-manager.actions.delete.dialog.body",
|
2898
|
+
defaultMessage: "Are you sure?"
|
2899
|
+
}) })
|
2900
|
+
] }),
|
2901
|
+
onConfirm: async () => {
|
2902
|
+
if (!listViewPathMatch) {
|
2903
|
+
setSubmitting(true);
|
2904
|
+
}
|
2905
|
+
try {
|
2906
|
+
if (!documentId && collectionType !== SINGLE_TYPES) {
|
2907
|
+
console.error(
|
2908
|
+
"You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2909
|
+
);
|
2910
|
+
toggleNotification({
|
2911
|
+
message: formatMessage({
|
2912
|
+
id: "content-manager.actions.delete.error",
|
2913
|
+
defaultMessage: "An error occurred while trying to delete the document."
|
2914
|
+
}),
|
2915
|
+
type: "danger"
|
2916
|
+
});
|
2917
|
+
return;
|
2918
|
+
}
|
2919
|
+
const res = await deleteAction({
|
2920
|
+
documentId,
|
2921
|
+
model,
|
2922
|
+
collectionType,
|
2923
|
+
params: {
|
2924
|
+
locale: "*"
|
2925
|
+
}
|
2926
|
+
});
|
2927
|
+
if (!("error" in res)) {
|
2928
|
+
navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
|
2929
|
+
}
|
2930
|
+
} finally {
|
2931
|
+
if (!listViewPathMatch) {
|
2932
|
+
setSubmitting(false);
|
2933
|
+
}
|
2934
|
+
}
|
2850
2935
|
}
|
2851
|
-
const { edit: metadata } = metadatas[field.name];
|
2852
|
-
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2853
|
-
return {
|
2854
|
-
attribute,
|
2855
|
-
disabled: !metadata.editable,
|
2856
|
-
hint: metadata.description,
|
2857
|
-
label: metadata.label ?? "",
|
2858
|
-
name: field.name,
|
2859
|
-
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2860
|
-
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2861
|
-
schemas,
|
2862
|
-
components: components?.schemas ?? {}
|
2863
|
-
}),
|
2864
|
-
placeholder: metadata.placeholder ?? "",
|
2865
|
-
required: attribute.required ?? false,
|
2866
|
-
size: field.size,
|
2867
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
2868
|
-
visible: metadata.visible ?? true,
|
2869
|
-
type: attribute.type
|
2870
|
-
};
|
2871
|
-
}).filter((field) => field !== null)
|
2872
|
-
);
|
2873
|
-
};
|
2874
|
-
const formatListLayout = (data, {
|
2875
|
-
schemas,
|
2876
|
-
schema,
|
2877
|
-
components
|
2878
|
-
}) => {
|
2879
|
-
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2880
|
-
(acc, [attribute, metadata]) => {
|
2881
|
-
return {
|
2882
|
-
...acc,
|
2883
|
-
[attribute]: metadata.list
|
2884
|
-
};
|
2885
2936
|
},
|
2886
|
-
|
2887
|
-
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2898
|
-
|
2899
|
-
|
2900
|
-
|
2901
|
-
|
2902
|
-
|
2937
|
+
variant: "danger",
|
2938
|
+
position: ["header", "table-row"]
|
2939
|
+
};
|
2940
|
+
};
|
2941
|
+
DeleteAction$1.type = "delete";
|
2942
|
+
const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
|
2943
|
+
const Panels = () => {
|
2944
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2945
|
+
const [
|
2946
|
+
{
|
2947
|
+
query: { status }
|
2948
|
+
}
|
2949
|
+
] = strapiAdmin.useQueryParams({
|
2950
|
+
status: "draft"
|
2951
|
+
});
|
2952
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2953
|
+
const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
|
2954
|
+
const props = {
|
2955
|
+
activeTab: status,
|
2956
|
+
model,
|
2957
|
+
documentId: id,
|
2958
|
+
document: isCloning ? void 0 : document,
|
2959
|
+
meta: isCloning ? void 0 : meta,
|
2960
|
+
collectionType
|
2961
|
+
};
|
2962
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
2963
|
+
strapiAdmin.DescriptionComponentRenderer,
|
2964
|
+
{
|
2965
|
+
props,
|
2966
|
+
descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
|
2967
|
+
children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
|
2903
2968
|
}
|
2969
|
+
) });
|
2970
|
+
};
|
2971
|
+
const ActionsPanel = () => {
|
2972
|
+
const { formatMessage } = reactIntl.useIntl();
|
2973
|
+
return {
|
2974
|
+
title: formatMessage({
|
2975
|
+
id: "content-manager.containers.edit.panels.default.title",
|
2976
|
+
defaultMessage: "Entry"
|
2977
|
+
}),
|
2978
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
|
2904
2979
|
};
|
2905
2980
|
};
|
2906
|
-
|
2907
|
-
|
2908
|
-
|
2909
|
-
|
2910
|
-
|
2981
|
+
ActionsPanel.type = "actions";
|
2982
|
+
const ActionsPanelContent = () => {
|
2983
|
+
const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
|
2984
|
+
const [
|
2985
|
+
{
|
2986
|
+
query: { status = "draft" }
|
2911
2987
|
}
|
2912
|
-
|
2913
|
-
|
2914
|
-
|
2915
|
-
|
2916
|
-
|
2917
|
-
|
2918
|
-
|
2919
|
-
|
2920
|
-
|
2921
|
-
|
2922
|
-
|
2923
|
-
|
2924
|
-
|
2925
|
-
|
2988
|
+
] = strapiAdmin.useQueryParams();
|
2989
|
+
const { model, id, document, meta, collectionType } = useDoc();
|
2990
|
+
const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
|
2991
|
+
const props = {
|
2992
|
+
activeTab: status,
|
2993
|
+
model,
|
2994
|
+
documentId: id,
|
2995
|
+
document: isCloning ? void 0 : document,
|
2996
|
+
meta: isCloning ? void 0 : meta,
|
2997
|
+
collectionType
|
2998
|
+
};
|
2999
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
|
3000
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3001
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3002
|
+
{
|
3003
|
+
props,
|
3004
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3005
|
+
children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
|
3006
|
+
}
|
3007
|
+
),
|
3008
|
+
/* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
|
3009
|
+
] });
|
2926
3010
|
};
|
3011
|
+
const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
3012
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
3013
|
+
designSystem.Flex,
|
3014
|
+
{
|
3015
|
+
ref,
|
3016
|
+
tag: "aside",
|
3017
|
+
"aria-labelledby": "additional-information",
|
3018
|
+
background: "neutral0",
|
3019
|
+
borderColor: "neutral150",
|
3020
|
+
hasRadius: true,
|
3021
|
+
paddingBottom: 4,
|
3022
|
+
paddingLeft: 4,
|
3023
|
+
paddingRight: 4,
|
3024
|
+
paddingTop: 4,
|
3025
|
+
shadow: "tableShadow",
|
3026
|
+
gap: 3,
|
3027
|
+
direction: "column",
|
3028
|
+
justifyContent: "stretch",
|
3029
|
+
alignItems: "flex-start",
|
3030
|
+
children: [
|
3031
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
|
3032
|
+
children
|
3033
|
+
]
|
3034
|
+
}
|
3035
|
+
);
|
3036
|
+
});
|
2927
3037
|
const ConfirmBulkActionDialog = ({
|
2928
3038
|
onToggleDialog,
|
2929
3039
|
isOpen = false,
|
@@ -2962,6 +3072,7 @@ const ConfirmDialogPublishAll = ({
|
|
2962
3072
|
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2963
3073
|
const { model, schema } = useDoc();
|
2964
3074
|
const [{ query }] = strapiAdmin.useQueryParams();
|
3075
|
+
const enableDraftRelationsCount = false;
|
2965
3076
|
const {
|
2966
3077
|
data: countDraftRelations = 0,
|
2967
3078
|
isLoading,
|
@@ -2973,7 +3084,7 @@ const ConfirmDialogPublishAll = ({
|
|
2973
3084
|
locale: query?.plugins?.i18n?.locale
|
2974
3085
|
},
|
2975
3086
|
{
|
2976
|
-
skip:
|
3087
|
+
skip: !enableDraftRelationsCount
|
2977
3088
|
}
|
2978
3089
|
);
|
2979
3090
|
React__namespace.useEffect(() => {
|
@@ -3158,7 +3269,7 @@ const SelectedEntriesTableContent = ({
|
|
3158
3269
|
status: row.status
|
3159
3270
|
}
|
3160
3271
|
) }),
|
3161
|
-
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3272
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3162
3273
|
designSystem.IconButton,
|
3163
3274
|
{
|
3164
3275
|
tag: reactRouterDom.Link,
|
@@ -3181,9 +3292,10 @@ const SelectedEntriesTableContent = ({
|
|
3181
3292
|
),
|
3182
3293
|
target: "_blank",
|
3183
3294
|
marginLeft: "auto",
|
3184
|
-
|
3295
|
+
variant: "ghost",
|
3296
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, { width: "1.6rem", height: "1.6rem" })
|
3185
3297
|
}
|
3186
|
-
) })
|
3298
|
+
) }) })
|
3187
3299
|
] }, row.id)) })
|
3188
3300
|
] });
|
3189
3301
|
};
|
@@ -3576,7 +3688,7 @@ const TableActions = ({ document }) => {
|
|
3576
3688
|
strapiAdmin.DescriptionComponentRenderer,
|
3577
3689
|
{
|
3578
3690
|
props,
|
3579
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3691
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions().filter((action) => action.name !== "PublishAction"),
|
3580
3692
|
children: (actions2) => {
|
3581
3693
|
const tableRowActions = actions2.filter((action) => {
|
3582
3694
|
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
@@ -3687,7 +3799,7 @@ const CloneAction = ({ model, documentId }) => {
|
|
3687
3799
|
}),
|
3688
3800
|
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3689
3801
|
footer: ({ onClose }) => {
|
3690
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.
|
3802
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3691
3803
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3692
3804
|
id: "cancel",
|
3693
3805
|
defaultMessage: "Cancel"
|
@@ -3918,7 +4030,7 @@ const index = {
|
|
3918
4030
|
app.router.addRoute({
|
3919
4031
|
path: "content-manager/*",
|
3920
4032
|
lazy: async () => {
|
3921
|
-
const { Layout } = await Promise.resolve().then(() => require("./layout-
|
4033
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-B2MyZU-_.js"));
|
3922
4034
|
return {
|
3923
4035
|
Component: Layout
|
3924
4036
|
};
|
@@ -3935,7 +4047,7 @@ const index = {
|
|
3935
4047
|
async registerTrads({ locales }) {
|
3936
4048
|
const importedTrads = await Promise.all(
|
3937
4049
|
locales.map((locale) => {
|
3938
|
-
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-
|
4050
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-Bm0D0IWz.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
|
3939
4051
|
return {
|
3940
4052
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3941
4053
|
locale
|
@@ -3953,6 +4065,7 @@ const index = {
|
|
3953
4065
|
};
|
3954
4066
|
exports.ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD = ATTRIBUTE_TYPES_THAT_CANNOT_BE_MAIN_FIELD;
|
3955
4067
|
exports.BulkActionsRenderer = BulkActionsRenderer;
|
4068
|
+
exports.CLONE_PATH = CLONE_PATH;
|
3956
4069
|
exports.COLLECTION_TYPES = COLLECTION_TYPES;
|
3957
4070
|
exports.CREATOR_FIELDS = CREATOR_FIELDS;
|
3958
4071
|
exports.DEFAULT_SETTINGS = DEFAULT_SETTINGS;
|
@@ -3980,6 +4093,7 @@ exports.getMainField = getMainField;
|
|
3980
4093
|
exports.getTranslation = getTranslation;
|
3981
4094
|
exports.index = index;
|
3982
4095
|
exports.setInitialData = setInitialData;
|
4096
|
+
exports.useContentManagerContext = useContentManagerContext;
|
3983
4097
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3984
4098
|
exports.useDoc = useDoc;
|
3985
4099
|
exports.useDocLayout = useDocLayout;
|
@@ -3992,4 +4106,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
|
3992
4106
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3993
4107
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
3994
4108
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3995
|
-
//# sourceMappingURL=index-
|
4109
|
+
//# sourceMappingURL=index-BdMf2lfT.js.map
|