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