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