@strapi/content-manager 0.0.0-experimental.f75e3c6d67cc47c64ab37479efdbb7b43be50b78 → 0.0.0-experimental.fb442e5e12dd3f611303691bf85a249520ba348b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -3
- package/dist/_chunks/{ComponentConfigurationPage-CuWgXugY.mjs → ComponentConfigurationPage-B3yDbeU1.mjs} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-CuWgXugY.mjs.map → ComponentConfigurationPage-B3yDbeU1.mjs.map} +1 -1
- package/dist/_chunks/{ComponentConfigurationPage-by0e_kNd.js → ComponentConfigurationPage-KXSuLnQD.js} +3 -3
- package/dist/_chunks/{ComponentConfigurationPage-by0e_kNd.js.map → ComponentConfigurationPage-KXSuLnQD.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-CqBeCPGH.js → EditConfigurationPage-BQ17--5R.js} +3 -3
- package/dist/_chunks/{EditConfigurationPage-CqBeCPGH.js.map → EditConfigurationPage-BQ17--5R.js.map} +1 -1
- package/dist/_chunks/{EditConfigurationPage-DbI4KMyz.mjs → EditConfigurationPage-D7PrLO8j.mjs} +3 -3
- package/dist/_chunks/{EditConfigurationPage-DbI4KMyz.mjs.map → EditConfigurationPage-D7PrLO8j.mjs.map} +1 -1
- package/dist/_chunks/{EditViewPage-dFPBya9U.mjs → EditViewPage-B7VgwJaG.mjs} +57 -46
- package/dist/_chunks/EditViewPage-B7VgwJaG.mjs.map +1 -0
- package/dist/_chunks/{EditViewPage-ChgloMyO.js → EditViewPage-BgjdnGz2.js} +56 -45
- package/dist/_chunks/EditViewPage-BgjdnGz2.js.map +1 -0
- package/dist/_chunks/{Field-dLk-vgLL.js → Field-CdK7ZLmv.js} +504 -165
- package/dist/_chunks/Field-CdK7ZLmv.js.map +1 -0
- package/dist/_chunks/{Field-C1nUKcdS.mjs → Field-tHCw4lGA.mjs} +505 -166
- package/dist/_chunks/Field-tHCw4lGA.mjs.map +1 -0
- package/dist/_chunks/{Form-DOlpi7Js.mjs → Form-BJxdTv3Q.mjs} +40 -30
- package/dist/_chunks/Form-BJxdTv3Q.mjs.map +1 -0
- package/dist/_chunks/{Form-CbXtmHC_.js → Form-C_0KTVvV.js} +38 -28
- package/dist/_chunks/Form-C_0KTVvV.js.map +1 -0
- package/dist/_chunks/{History-BFNUAiGc.mjs → History-DR2txJLE.mjs} +142 -37
- package/dist/_chunks/History-DR2txJLE.mjs.map +1 -0
- package/dist/_chunks/{History-BjDfohBr.js → History-nuEzM5qm.js} +141 -36
- package/dist/_chunks/History-nuEzM5qm.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-IQBgWTaa.js → ListConfigurationPage-CnB86Psm.js} +57 -46
- package/dist/_chunks/ListConfigurationPage-CnB86Psm.js.map +1 -0
- package/dist/_chunks/{ListConfigurationPage-DDi0KqFm.mjs → ListConfigurationPage-voFVtXu6.mjs} +58 -48
- package/dist/_chunks/ListConfigurationPage-voFVtXu6.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-BPjljUsH.mjs → ListViewPage-B_GaWgRH.mjs} +80 -71
- package/dist/_chunks/ListViewPage-B_GaWgRH.mjs.map +1 -0
- package/dist/_chunks/{ListViewPage-CZYGqlvF.js → ListViewPage-SXIXm-RM.js} +78 -69
- package/dist/_chunks/ListViewPage-SXIXm-RM.js.map +1 -0
- package/dist/_chunks/{NoContentTypePage-BOAI6VZ1.js → NoContentTypePage-BzsQ3hLZ.js} +2 -2
- package/dist/_chunks/{NoContentTypePage-BOAI6VZ1.js.map → NoContentTypePage-BzsQ3hLZ.js.map} +1 -1
- package/dist/_chunks/{NoContentTypePage-DaWw67K-.mjs → NoContentTypePage-CYiGpsbj.mjs} +2 -2
- package/dist/_chunks/{NoContentTypePage-DaWw67K-.mjs.map → NoContentTypePage-CYiGpsbj.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-CZrJH00p.mjs → NoPermissionsPage-B5baIHal.mjs} +2 -2
- package/dist/_chunks/{NoPermissionsPage-CZrJH00p.mjs.map → NoPermissionsPage-B5baIHal.mjs.map} +1 -1
- package/dist/_chunks/{NoPermissionsPage-cYEtLc_e.js → NoPermissionsPage-IGkId4C5.js} +2 -2
- package/dist/_chunks/{NoPermissionsPage-cYEtLc_e.js.map → NoPermissionsPage-IGkId4C5.js.map} +1 -1
- package/dist/_chunks/{Relations-DTowyge2.mjs → Relations-CIYDdKU-.mjs} +5 -5
- package/dist/_chunks/Relations-CIYDdKU-.mjs.map +1 -0
- package/dist/_chunks/{Relations-DU6B7irU.js → Relations-Dhuurpx2.js} +5 -5
- package/dist/_chunks/Relations-Dhuurpx2.js.map +1 -0
- package/dist/_chunks/{en-GCOTL6jR.mjs → en-BrCTWlZv.mjs} +9 -4
- package/dist/_chunks/{en-GCOTL6jR.mjs.map → en-BrCTWlZv.mjs.map} +1 -1
- package/dist/_chunks/{en-DTULi5-d.js → en-uOUIxfcQ.js} +9 -4
- package/dist/_chunks/{en-DTULi5-d.js.map → en-uOUIxfcQ.js.map} +1 -1
- package/dist/_chunks/{index-BaGHmIir.mjs → index-C9TJPyni.mjs} +1542 -1063
- package/dist/_chunks/index-C9TJPyni.mjs.map +1 -0
- package/dist/_chunks/{index-CCJeB7Rw.js → index-CdT0kHZ8.js} +1510 -1031
- package/dist/_chunks/index-CdT0kHZ8.js.map +1 -0
- package/dist/_chunks/{layout-BinjszSQ.mjs → layout-BNqvLR_b.mjs} +39 -22
- package/dist/_chunks/layout-BNqvLR_b.mjs.map +1 -0
- package/dist/_chunks/{layout-ni_L9kT1.js → layout-C6dxWYT7.js} +37 -20
- package/dist/_chunks/layout-C6dxWYT7.js.map +1 -0
- package/dist/_chunks/{relations-c91ji5eR.mjs → relations-CkKqKw65.mjs} +2 -2
- package/dist/_chunks/{relations-c91ji5eR.mjs.map → relations-CkKqKw65.mjs.map} +1 -1
- package/dist/_chunks/{relations-CeJAJc5I.js → relations-DtFaDnP1.js} +2 -2
- package/dist/_chunks/{relations-CeJAJc5I.js.map → relations-DtFaDnP1.js.map} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +8 -8
- package/dist/admin/src/history/components/VersionInputRenderer.d.ts +1 -1
- package/dist/admin/src/history/index.d.ts +3 -0
- package/dist/admin/src/hooks/useDocumentActions.d.ts +1 -1
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +8 -3
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +4 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations.d.ts +20 -0
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/EditorLayout.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygFooter.d.ts +2 -2
- package/dist/admin/src/pages/EditView/components/FormInputs/Wysiwyg/WysiwygStyles.d.ts +12 -32
- package/dist/admin/src/pages/ListView/components/BulkActions/Actions.d.ts +3 -30
- package/dist/admin/src/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.d.ts +2 -2
- package/dist/admin/src/pages/ListView/components/BulkActions/PublishAction.d.ts +14 -0
- package/dist/server/index.js +147 -93
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +148 -94
- 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/single-types.d.ts.map +1 -1
- package/dist/server/src/controllers/uid.d.ts.map +1 -1
- package/dist/server/src/controllers/validation/dimensions.d.ts +4 -2
- package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
- package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
- package/dist/server/src/history/services/utils.d.ts +1 -1
- package/dist/server/src/history/services/utils.d.ts.map +1 -1
- package/dist/server/src/services/document-manager.d.ts.map +1 -1
- package/dist/server/src/services/document-metadata.d.ts.map +1 -1
- package/dist/server/src/services/utils/populate.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/_chunks/EditViewPage-ChgloMyO.js.map +0 -1
- package/dist/_chunks/EditViewPage-dFPBya9U.mjs.map +0 -1
- package/dist/_chunks/Field-C1nUKcdS.mjs.map +0 -1
- package/dist/_chunks/Field-dLk-vgLL.js.map +0 -1
- package/dist/_chunks/Form-CbXtmHC_.js.map +0 -1
- package/dist/_chunks/Form-DOlpi7Js.mjs.map +0 -1
- package/dist/_chunks/History-BFNUAiGc.mjs.map +0 -1
- package/dist/_chunks/History-BjDfohBr.js.map +0 -1
- package/dist/_chunks/ListConfigurationPage-DDi0KqFm.mjs.map +0 -1
- package/dist/_chunks/ListConfigurationPage-IQBgWTaa.js.map +0 -1
- package/dist/_chunks/ListViewPage-BPjljUsH.mjs.map +0 -1
- package/dist/_chunks/ListViewPage-CZYGqlvF.js.map +0 -1
- package/dist/_chunks/Relations-DTowyge2.mjs.map +0 -1
- package/dist/_chunks/Relations-DU6B7irU.js.map +0 -1
- package/dist/_chunks/index-BaGHmIir.mjs.map +0 -1
- package/dist/_chunks/index-CCJeB7Rw.js.map +0 -1
- package/dist/_chunks/layout-BinjszSQ.mjs.map +0 -1
- package/dist/_chunks/layout-ni_L9kT1.js.map +0 -1
@@ -2,15 +2,15 @@
|
|
2
2
|
const Icons = require("@strapi/icons");
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
4
4
|
const strapiAdmin = require("@strapi/admin/strapi-admin");
|
5
|
-
const qs = require("qs");
|
6
|
-
const reactIntl = require("react-intl");
|
7
|
-
const reactRouterDom = require("react-router-dom");
|
8
5
|
const React = require("react");
|
9
6
|
const designSystem = require("@strapi/design-system");
|
7
|
+
const reactIntl = require("react-intl");
|
8
|
+
const reactRouterDom = require("react-router-dom");
|
10
9
|
const styledComponents = require("styled-components");
|
11
10
|
const yup = require("yup");
|
12
11
|
const pipe = require("lodash/fp/pipe");
|
13
12
|
const dateFns = require("date-fns");
|
13
|
+
const qs = require("qs");
|
14
14
|
const toolkit = require("@reduxjs/toolkit");
|
15
15
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
16
16
|
function _interopNamespace(e) {
|
@@ -70,42 +70,6 @@ const useInjectionZone = (area) => {
|
|
70
70
|
const [page, position] = area.split(".");
|
71
71
|
return contentManagerPlugin.getInjectedComponents(page, position);
|
72
72
|
};
|
73
|
-
const HistoryAction = ({ model, document }) => {
|
74
|
-
const { formatMessage } = reactIntl.useIntl();
|
75
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
76
|
-
const navigate = reactRouterDom.useNavigate();
|
77
|
-
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
78
|
-
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
79
|
-
return null;
|
80
|
-
}
|
81
|
-
return {
|
82
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
83
|
-
label: formatMessage({
|
84
|
-
id: "content-manager.history.document-action",
|
85
|
-
defaultMessage: "Content History"
|
86
|
-
}),
|
87
|
-
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
88
|
-
disabled: (
|
89
|
-
/**
|
90
|
-
* The user is creating a new document.
|
91
|
-
* It hasn't been saved yet, so there's no history to go to
|
92
|
-
*/
|
93
|
-
!document || /**
|
94
|
-
* The document has been created but the current dimension has never been saved.
|
95
|
-
* For example, the user is creating a new locale in an existing document,
|
96
|
-
* so there's no history for the document in that locale
|
97
|
-
*/
|
98
|
-
!document.id || /**
|
99
|
-
* History is only available for content types created by the user.
|
100
|
-
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
101
|
-
* which start with `admin::` or `plugin::`
|
102
|
-
*/
|
103
|
-
!model.startsWith("api::")
|
104
|
-
),
|
105
|
-
position: "header"
|
106
|
-
};
|
107
|
-
};
|
108
|
-
HistoryAction.type = "history";
|
109
73
|
const ID = "id";
|
110
74
|
const CREATED_BY_ATTRIBUTE_NAME = "createdBy";
|
111
75
|
const UPDATED_BY_ATTRIBUTE_NAME = "updatedBy";
|
@@ -219,6 +183,7 @@ const contentManagerApi = strapiAdmin.adminApi.enhanceEndpoints({
|
|
219
183
|
]
|
220
184
|
});
|
221
185
|
const documentApi = contentManagerApi.injectEndpoints({
|
186
|
+
overrideExisting: true,
|
222
187
|
endpoints: (builder) => ({
|
223
188
|
autoCloneDocument: builder.mutation({
|
224
189
|
query: ({ model, sourceId, query }) => ({
|
@@ -228,7 +193,12 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
228
193
|
params: query
|
229
194
|
}
|
230
195
|
}),
|
231
|
-
invalidatesTags: (_result,
|
196
|
+
invalidatesTags: (_result, error, { model }) => {
|
197
|
+
if (error) {
|
198
|
+
return [];
|
199
|
+
}
|
200
|
+
return [{ type: "Document", id: `${model}_LIST` }];
|
201
|
+
}
|
232
202
|
}),
|
233
203
|
cloneDocument: builder.mutation({
|
234
204
|
query: ({ model, sourceId, data, params }) => ({
|
@@ -315,6 +285,7 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
315
285
|
}),
|
316
286
|
providesTags: (result, _error, arg) => {
|
317
287
|
return [
|
288
|
+
{ type: "Document", id: `ALL_LIST` },
|
318
289
|
{ type: "Document", id: `${arg.model}_LIST` },
|
319
290
|
...result?.results.map(({ documentId }) => ({
|
320
291
|
type: "Document",
|
@@ -353,6 +324,11 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
353
324
|
{
|
354
325
|
type: "Document",
|
355
326
|
id: collectionType !== SINGLE_TYPES ? `${model}_${result && "documentId" in result ? result.documentId : documentId}` : model
|
327
|
+
},
|
328
|
+
// Make it easy to invalidate all individual documents queries for a model
|
329
|
+
{
|
330
|
+
type: "Document",
|
331
|
+
id: `${model}_ALL_ITEMS`
|
356
332
|
}
|
357
333
|
];
|
358
334
|
}
|
@@ -418,6 +394,18 @@ const documentApi = contentManagerApi.injectEndpoints({
|
|
418
394
|
},
|
419
395
|
"Relations"
|
420
396
|
];
|
397
|
+
},
|
398
|
+
async onQueryStarted({ data, ...patch }, { dispatch, queryFulfilled }) {
|
399
|
+
const patchResult = dispatch(
|
400
|
+
documentApi.util.updateQueryData("getDocument", patch, (draft) => {
|
401
|
+
Object.assign(draft.data, data);
|
402
|
+
})
|
403
|
+
);
|
404
|
+
try {
|
405
|
+
await queryFulfilled;
|
406
|
+
} catch {
|
407
|
+
patchResult.undo();
|
408
|
+
}
|
421
409
|
}
|
422
410
|
}),
|
423
411
|
unpublishDocument: builder.mutation({
|
@@ -601,6 +589,14 @@ const createAttributeSchema = (attribute) => {
|
|
601
589
|
if (!value || typeof value === "string" && value.length === 0) {
|
602
590
|
return true;
|
603
591
|
}
|
592
|
+
if (typeof value === "object") {
|
593
|
+
try {
|
594
|
+
JSON.stringify(value);
|
595
|
+
return true;
|
596
|
+
} catch (err) {
|
597
|
+
return false;
|
598
|
+
}
|
599
|
+
}
|
604
600
|
try {
|
605
601
|
JSON.parse(value);
|
606
602
|
return true;
|
@@ -620,11 +616,11 @@ const createAttributeSchema = (attribute) => {
|
|
620
616
|
}
|
621
617
|
};
|
622
618
|
const addRequiredValidation = (attribute) => (schema) => {
|
623
|
-
if (attribute.required) {
|
624
|
-
return schema.required
|
625
|
-
|
626
|
-
|
627
|
-
|
619
|
+
if ((attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") && attribute.required && "min" in schema) {
|
620
|
+
return schema.min(1, strapiAdmin.translatedErrors.required);
|
621
|
+
}
|
622
|
+
if (attribute.required && attribute.type !== "relation") {
|
623
|
+
return schema.required(strapiAdmin.translatedErrors.required);
|
628
624
|
}
|
629
625
|
return schema?.nullable ? schema.nullable() : (
|
630
626
|
// In some cases '.nullable' will not be available on the schema.
|
@@ -658,6 +654,28 @@ const addMaxLengthValidation = (attribute) => (schema) => {
|
|
658
654
|
const addMinValidation = (attribute) => (schema) => {
|
659
655
|
if ("min" in attribute) {
|
660
656
|
const min = toInteger(attribute.min);
|
657
|
+
if (attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone") {
|
658
|
+
if (!attribute.required && "test" in schema && min) {
|
659
|
+
return schema.test(
|
660
|
+
"custom-min",
|
661
|
+
{
|
662
|
+
...strapiAdmin.translatedErrors.min,
|
663
|
+
values: {
|
664
|
+
min: attribute.min
|
665
|
+
}
|
666
|
+
},
|
667
|
+
(value) => {
|
668
|
+
if (!value) {
|
669
|
+
return true;
|
670
|
+
}
|
671
|
+
if (Array.isArray(value) && value.length === 0) {
|
672
|
+
return true;
|
673
|
+
}
|
674
|
+
return value.length >= min;
|
675
|
+
}
|
676
|
+
);
|
677
|
+
}
|
678
|
+
}
|
661
679
|
if ("min" in schema && min) {
|
662
680
|
return schema.min(min, {
|
663
681
|
...strapiAdmin.translatedErrors.min,
|
@@ -784,7 +802,10 @@ const useDocument = (args, opts) => {
|
|
784
802
|
isLoading: isLoadingDocument,
|
785
803
|
isFetching: isFetchingDocument,
|
786
804
|
error
|
787
|
-
} = useGetDocumentQuery(args,
|
805
|
+
} = useGetDocumentQuery(args, {
|
806
|
+
...opts,
|
807
|
+
skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
|
808
|
+
});
|
788
809
|
const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
|
789
810
|
React__namespace.useEffect(() => {
|
790
811
|
if (error) {
|
@@ -948,12 +969,13 @@ const useDocumentActions = () => {
|
|
948
969
|
);
|
949
970
|
const [discardDocument] = useDiscardDocumentMutation();
|
950
971
|
const discard = React__namespace.useCallback(
|
951
|
-
async ({ collectionType, model, documentId }) => {
|
972
|
+
async ({ collectionType, model, documentId, params }) => {
|
952
973
|
try {
|
953
974
|
const res = await discardDocument({
|
954
975
|
collectionType,
|
955
976
|
model,
|
956
|
-
documentId
|
977
|
+
documentId,
|
978
|
+
params
|
957
979
|
});
|
958
980
|
if ("error" in res) {
|
959
981
|
toggleNotification({
|
@@ -1204,7 +1226,6 @@ const useDocumentActions = () => {
|
|
1204
1226
|
sourceId
|
1205
1227
|
});
|
1206
1228
|
if ("error" in res) {
|
1207
|
-
toggleNotification({ type: "danger", message: formatAPIError(res.error) });
|
1208
1229
|
return { error: res.error };
|
1209
1230
|
}
|
1210
1231
|
toggleNotification({
|
@@ -1285,7 +1306,7 @@ const useDocumentActions = () => {
|
|
1285
1306
|
};
|
1286
1307
|
};
|
1287
1308
|
const ProtectedHistoryPage = React.lazy(
|
1288
|
-
() => Promise.resolve().then(() => require("./History-
|
1309
|
+
() => Promise.resolve().then(() => require("./History-nuEzM5qm.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
|
1289
1310
|
);
|
1290
1311
|
const routes$1 = [
|
1291
1312
|
{
|
@@ -1298,31 +1319,31 @@ const routes$1 = [
|
|
1298
1319
|
}
|
1299
1320
|
];
|
1300
1321
|
const ProtectedEditViewPage = React.lazy(
|
1301
|
-
() => Promise.resolve().then(() => require("./EditViewPage-
|
1322
|
+
() => Promise.resolve().then(() => require("./EditViewPage-BgjdnGz2.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
|
1302
1323
|
);
|
1303
1324
|
const ProtectedListViewPage = React.lazy(
|
1304
|
-
() => Promise.resolve().then(() => require("./ListViewPage-
|
1325
|
+
() => Promise.resolve().then(() => require("./ListViewPage-SXIXm-RM.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
|
1305
1326
|
);
|
1306
1327
|
const ProtectedListConfiguration = React.lazy(
|
1307
|
-
() => Promise.resolve().then(() => require("./ListConfigurationPage-
|
1328
|
+
() => Promise.resolve().then(() => require("./ListConfigurationPage-CnB86Psm.js")).then((mod) => ({
|
1308
1329
|
default: mod.ProtectedListConfiguration
|
1309
1330
|
}))
|
1310
1331
|
);
|
1311
1332
|
const ProtectedEditConfigurationPage = React.lazy(
|
1312
|
-
() => Promise.resolve().then(() => require("./EditConfigurationPage-
|
1333
|
+
() => Promise.resolve().then(() => require("./EditConfigurationPage-BQ17--5R.js")).then((mod) => ({
|
1313
1334
|
default: mod.ProtectedEditConfigurationPage
|
1314
1335
|
}))
|
1315
1336
|
);
|
1316
1337
|
const ProtectedComponentConfigurationPage = React.lazy(
|
1317
|
-
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-
|
1338
|
+
() => Promise.resolve().then(() => require("./ComponentConfigurationPage-KXSuLnQD.js")).then((mod) => ({
|
1318
1339
|
default: mod.ProtectedComponentConfigurationPage
|
1319
1340
|
}))
|
1320
1341
|
);
|
1321
1342
|
const NoPermissions = React.lazy(
|
1322
|
-
() => Promise.resolve().then(() => require("./NoPermissionsPage-
|
1343
|
+
() => Promise.resolve().then(() => require("./NoPermissionsPage-IGkId4C5.js")).then((mod) => ({ default: mod.NoPermissions }))
|
1323
1344
|
);
|
1324
1345
|
const NoContentType = React.lazy(
|
1325
|
-
() => Promise.resolve().then(() => require("./NoContentTypePage-
|
1346
|
+
() => Promise.resolve().then(() => require("./NoContentTypePage-BzsQ3hLZ.js")).then((mod) => ({ default: mod.NoContentType }))
|
1326
1347
|
);
|
1327
1348
|
const CollectionTypePages = () => {
|
1328
1349
|
const { collectionType } = reactRouterDom.useParams();
|
@@ -1436,12 +1457,14 @@ const DocumentActionButton = (action) => {
|
|
1436
1457
|
/* @__PURE__ */ jsxRuntime.jsx(
|
1437
1458
|
designSystem.Button,
|
1438
1459
|
{
|
1439
|
-
flex:
|
1460
|
+
flex: "auto",
|
1440
1461
|
startIcon: action.icon,
|
1441
1462
|
disabled: action.disabled,
|
1442
1463
|
onClick: handleClick(action),
|
1443
1464
|
justifyContent: "center",
|
1444
1465
|
variant: action.variant || "default",
|
1466
|
+
paddingTop: "7px",
|
1467
|
+
paddingBottom: "7px",
|
1445
1468
|
children: action.label
|
1446
1469
|
}
|
1447
1470
|
),
|
@@ -1449,7 +1472,7 @@ const DocumentActionButton = (action) => {
|
|
1449
1472
|
DocumentActionConfirmDialog,
|
1450
1473
|
{
|
1451
1474
|
...action.dialog,
|
1452
|
-
variant: action.variant,
|
1475
|
+
variant: action.dialog?.variant ?? action.variant,
|
1453
1476
|
isOpen: dialogId === action.id,
|
1454
1477
|
onClose: handleClose
|
1455
1478
|
}
|
@@ -1501,14 +1524,14 @@ const DocumentActionsMenu = ({
|
|
1501
1524
|
};
|
1502
1525
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Menu.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
|
1503
1526
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
1504
|
-
|
1527
|
+
StyledMoreButton,
|
1505
1528
|
{
|
1506
1529
|
disabled: isDisabled,
|
1507
1530
|
size: "S",
|
1508
1531
|
endIcon: null,
|
1509
|
-
paddingTop: "
|
1510
|
-
paddingLeft: "
|
1511
|
-
paddingRight: "
|
1532
|
+
paddingTop: "4px",
|
1533
|
+
paddingLeft: "7px",
|
1534
|
+
paddingRight: "7px",
|
1512
1535
|
variant,
|
1513
1536
|
children: [
|
1514
1537
|
/* @__PURE__ */ jsxRuntime.jsx(Icons.More, { "aria-hidden": true, focusable: false }),
|
@@ -1528,10 +1551,25 @@ const DocumentActionsMenu = ({
|
|
1528
1551
|
onSelect: handleClick(action),
|
1529
1552
|
display: "block",
|
1530
1553
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", gap: 4, children: [
|
1531
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1554
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
1555
|
+
designSystem.Flex,
|
1556
|
+
{
|
1557
|
+
color: !action.disabled ? convertActionVariantToColor(action.variant) : "inherit",
|
1558
|
+
gap: 2,
|
1559
|
+
tag: "span",
|
1560
|
+
children: [
|
1561
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
1562
|
+
designSystem.Flex,
|
1563
|
+
{
|
1564
|
+
tag: "span",
|
1565
|
+
color: !action.disabled ? convertActionVariantToIconColor(action.variant) : "inherit",
|
1566
|
+
children: action.icon
|
1567
|
+
}
|
1568
|
+
),
|
1569
|
+
action.label
|
1570
|
+
]
|
1571
|
+
}
|
1572
|
+
),
|
1535
1573
|
action.id.startsWith("HistoryAction") && /* @__PURE__ */ jsxRuntime.jsx(
|
1536
1574
|
designSystem.Flex,
|
1537
1575
|
{
|
@@ -1590,6 +1628,23 @@ const convertActionVariantToColor = (variant = "secondary") => {
|
|
1590
1628
|
return "primary600";
|
1591
1629
|
}
|
1592
1630
|
};
|
1631
|
+
const convertActionVariantToIconColor = (variant = "secondary") => {
|
1632
|
+
switch (variant) {
|
1633
|
+
case "danger":
|
1634
|
+
return "danger600";
|
1635
|
+
case "secondary":
|
1636
|
+
return "neutral500";
|
1637
|
+
case "success":
|
1638
|
+
return "success600";
|
1639
|
+
default:
|
1640
|
+
return "primary600";
|
1641
|
+
}
|
1642
|
+
};
|
1643
|
+
const StyledMoreButton = styledComponents.styled(designSystem.Menu.Trigger)`
|
1644
|
+
& > span {
|
1645
|
+
display: flex;
|
1646
|
+
}
|
1647
|
+
`;
|
1593
1648
|
const DocumentActionConfirmDialog = ({
|
1594
1649
|
onClose,
|
1595
1650
|
onCancel,
|
@@ -1612,22 +1667,20 @@ const DocumentActionConfirmDialog = ({
|
|
1612
1667
|
}
|
1613
1668
|
onClose();
|
1614
1669
|
};
|
1615
|
-
return /* @__PURE__ */ jsxRuntime.
|
1616
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1617
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1618
|
-
|
1619
|
-
{
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
)
|
1630
|
-
] });
|
1670
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
1671
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: title }),
|
1672
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: content }),
|
1673
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
1674
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
|
1675
|
+
id: "app.components.Button.cancel",
|
1676
|
+
defaultMessage: "Cancel"
|
1677
|
+
}) }) }),
|
1678
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleConfirm, variant, children: formatMessage({
|
1679
|
+
id: "app.components.Button.confirm",
|
1680
|
+
defaultMessage: "Confirm"
|
1681
|
+
}) })
|
1682
|
+
] })
|
1683
|
+
] }) });
|
1631
1684
|
};
|
1632
1685
|
const DocumentActionModal = ({
|
1633
1686
|
isOpen,
|
@@ -1637,36 +1690,19 @@ const DocumentActionModal = ({
|
|
1637
1690
|
content: Content,
|
1638
1691
|
onModalClose
|
1639
1692
|
}) => {
|
1640
|
-
const id = React__namespace.useId();
|
1641
|
-
if (!isOpen) {
|
1642
|
-
return null;
|
1643
|
-
}
|
1644
1693
|
const handleClose = () => {
|
1645
1694
|
if (onClose) {
|
1646
1695
|
onClose();
|
1647
1696
|
}
|
1648
1697
|
onModalClose();
|
1649
1698
|
};
|
1650
|
-
return /* @__PURE__ */ jsxRuntime.
|
1651
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1652
|
-
|
1653
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1654
|
-
|
1655
|
-
{
|
1656
|
-
paddingTop: 4,
|
1657
|
-
paddingBottom: 4,
|
1658
|
-
paddingLeft: 5,
|
1659
|
-
paddingRight: 5,
|
1660
|
-
borderWidth: "1px 0 0 0",
|
1661
|
-
borderStyle: "solid",
|
1662
|
-
borderColor: "neutral150",
|
1663
|
-
background: "neutral100",
|
1664
|
-
children: typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
1665
|
-
}
|
1666
|
-
)
|
1667
|
-
] });
|
1699
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
|
1700
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: title }) }),
|
1701
|
+
typeof Content === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: Content }),
|
1702
|
+
typeof Footer === "function" ? /* @__PURE__ */ jsxRuntime.jsx(Footer, { onClose: handleClose }) : Footer
|
1703
|
+
] }) });
|
1668
1704
|
};
|
1669
|
-
const PublishAction = ({
|
1705
|
+
const PublishAction$1 = ({
|
1670
1706
|
activeTab,
|
1671
1707
|
documentId,
|
1672
1708
|
model,
|
@@ -1685,6 +1721,12 @@ const PublishAction = ({
|
|
1685
1721
|
({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 }) => ({ canPublish: canPublish2, canCreate: canCreate2, canUpdate: canUpdate2 })
|
1686
1722
|
);
|
1687
1723
|
const { publish } = useDocumentActions();
|
1724
|
+
const [
|
1725
|
+
countDraftRelations,
|
1726
|
+
{ isLoading: isLoadingDraftRelations, isError: isErrorDraftRelations }
|
1727
|
+
] = useLazyGetDraftRelationCountQuery();
|
1728
|
+
const [localCountOfDraftRelations, setLocalCountOfDraftRelations] = React__namespace.useState(0);
|
1729
|
+
const [serverCountOfDraftRelations, setServerCountOfDraftRelations] = React__namespace.useState(0);
|
1688
1730
|
const [{ query, rawQuery }] = strapiAdmin.useQueryParams();
|
1689
1731
|
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
1690
1732
|
const modified = strapiAdmin.useForm("PublishAction", ({ modified: modified2 }) => modified2);
|
@@ -1693,10 +1735,101 @@ const PublishAction = ({
|
|
1693
1735
|
const validate = strapiAdmin.useForm("PublishAction", (state) => state.validate);
|
1694
1736
|
const setErrors = strapiAdmin.useForm("PublishAction", (state) => state.setErrors);
|
1695
1737
|
const formValues = strapiAdmin.useForm("PublishAction", ({ values }) => values);
|
1738
|
+
React__namespace.useEffect(() => {
|
1739
|
+
if (isErrorDraftRelations) {
|
1740
|
+
toggleNotification({
|
1741
|
+
type: "danger",
|
1742
|
+
message: formatMessage({
|
1743
|
+
id: getTranslation("error.records.fetch-draft-relatons"),
|
1744
|
+
defaultMessage: "An error occurred while fetching draft relations on this document."
|
1745
|
+
})
|
1746
|
+
});
|
1747
|
+
}
|
1748
|
+
}, [isErrorDraftRelations, toggleNotification, formatMessage]);
|
1749
|
+
React__namespace.useEffect(() => {
|
1750
|
+
const localDraftRelations = /* @__PURE__ */ new Set();
|
1751
|
+
const extractDraftRelations = (data) => {
|
1752
|
+
const relations = data.connect || [];
|
1753
|
+
relations.forEach((relation) => {
|
1754
|
+
if (relation.status === "draft") {
|
1755
|
+
localDraftRelations.add(relation.id);
|
1756
|
+
}
|
1757
|
+
});
|
1758
|
+
};
|
1759
|
+
const traverseAndExtract = (data) => {
|
1760
|
+
Object.entries(data).forEach(([key, value]) => {
|
1761
|
+
if (key === "connect" && Array.isArray(value)) {
|
1762
|
+
extractDraftRelations({ connect: value });
|
1763
|
+
} else if (typeof value === "object" && value !== null) {
|
1764
|
+
traverseAndExtract(value);
|
1765
|
+
}
|
1766
|
+
});
|
1767
|
+
};
|
1768
|
+
if (!documentId || modified) {
|
1769
|
+
traverseAndExtract(formValues);
|
1770
|
+
setLocalCountOfDraftRelations(localDraftRelations.size);
|
1771
|
+
}
|
1772
|
+
}, [documentId, modified, formValues, setLocalCountOfDraftRelations]);
|
1773
|
+
React__namespace.useEffect(() => {
|
1774
|
+
if (documentId) {
|
1775
|
+
const fetchDraftRelationsCount = async () => {
|
1776
|
+
const { data, error } = await countDraftRelations({
|
1777
|
+
collectionType,
|
1778
|
+
model,
|
1779
|
+
documentId,
|
1780
|
+
params
|
1781
|
+
});
|
1782
|
+
if (error) {
|
1783
|
+
throw error;
|
1784
|
+
}
|
1785
|
+
if (data) {
|
1786
|
+
setServerCountOfDraftRelations(data.data);
|
1787
|
+
}
|
1788
|
+
};
|
1789
|
+
fetchDraftRelationsCount();
|
1790
|
+
}
|
1791
|
+
}, [documentId, countDraftRelations, collectionType, model, params]);
|
1696
1792
|
const isDocumentPublished = (document?.[PUBLISHED_AT_ATTRIBUTE_NAME] || meta?.availableStatus.some((doc) => doc[PUBLISHED_AT_ATTRIBUTE_NAME] !== null)) && document?.status !== "modified";
|
1697
1793
|
if (!schema?.options?.draftAndPublish) {
|
1698
1794
|
return null;
|
1699
1795
|
}
|
1796
|
+
const performPublish = async () => {
|
1797
|
+
setSubmitting(true);
|
1798
|
+
try {
|
1799
|
+
const { errors } = await validate();
|
1800
|
+
if (errors) {
|
1801
|
+
toggleNotification({
|
1802
|
+
type: "danger",
|
1803
|
+
message: formatMessage({
|
1804
|
+
id: "content-manager.validation.error",
|
1805
|
+
defaultMessage: "There are validation errors in your document. Please fix them before saving."
|
1806
|
+
})
|
1807
|
+
});
|
1808
|
+
return;
|
1809
|
+
}
|
1810
|
+
const res = await publish(
|
1811
|
+
{
|
1812
|
+
collectionType,
|
1813
|
+
model,
|
1814
|
+
documentId,
|
1815
|
+
params
|
1816
|
+
},
|
1817
|
+
formValues
|
1818
|
+
);
|
1819
|
+
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1820
|
+
navigate({
|
1821
|
+
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1822
|
+
search: rawQuery
|
1823
|
+
});
|
1824
|
+
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1825
|
+
setErrors(formatValidationErrors(res.error));
|
1826
|
+
}
|
1827
|
+
} finally {
|
1828
|
+
setSubmitting(false);
|
1829
|
+
}
|
1830
|
+
};
|
1831
|
+
const totalDraftRelations = localCountOfDraftRelations + serverCountOfDraftRelations;
|
1832
|
+
const hasDraftRelations = totalDraftRelations > 0;
|
1700
1833
|
return {
|
1701
1834
|
/**
|
1702
1835
|
* Disabled when:
|
@@ -1706,52 +1839,42 @@ const PublishAction = ({
|
|
1706
1839
|
* - the document is already published & not modified
|
1707
1840
|
* - the document is being created & not modified
|
1708
1841
|
* - the user doesn't have the permission to publish
|
1709
|
-
* - the user doesn't have the permission to create a new document
|
1710
|
-
* - the user doesn't have the permission to update the document
|
1711
1842
|
*/
|
1712
|
-
disabled: isCloning || isSubmitting || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish
|
1843
|
+
disabled: isCloning || isSubmitting || isLoadingDraftRelations || activeTab === "published" || !modified && isDocumentPublished || !modified && !document?.documentId || !canPublish,
|
1713
1844
|
label: formatMessage({
|
1714
1845
|
id: "app.utils.publish",
|
1715
1846
|
defaultMessage: "Publish"
|
1716
1847
|
}),
|
1717
1848
|
onClick: async () => {
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
formValues
|
1739
|
-
);
|
1740
|
-
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1741
|
-
navigate({
|
1742
|
-
pathname: `../${collectionType}/${model}/${res.data.documentId}`,
|
1743
|
-
search: rawQuery
|
1744
|
-
});
|
1745
|
-
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1746
|
-
setErrors(formatValidationErrors(res.error));
|
1849
|
+
if (hasDraftRelations) {
|
1850
|
+
return;
|
1851
|
+
}
|
1852
|
+
await performPublish();
|
1853
|
+
},
|
1854
|
+
dialog: hasDraftRelations ? {
|
1855
|
+
type: "dialog",
|
1856
|
+
variant: "danger",
|
1857
|
+
footer: null,
|
1858
|
+
title: formatMessage({
|
1859
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.title`),
|
1860
|
+
defaultMessage: "Confirmation"
|
1861
|
+
}),
|
1862
|
+
content: formatMessage(
|
1863
|
+
{
|
1864
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
1865
|
+
defaultMessage: "This entry is related to {count, plural, one {# draft entry} other {# draft entries}}. Publishing it could leave broken links in your app."
|
1866
|
+
},
|
1867
|
+
{
|
1868
|
+
count: totalDraftRelations
|
1747
1869
|
}
|
1748
|
-
|
1749
|
-
|
1870
|
+
),
|
1871
|
+
onConfirm: async () => {
|
1872
|
+
await performPublish();
|
1750
1873
|
}
|
1751
|
-
}
|
1874
|
+
} : void 0
|
1752
1875
|
};
|
1753
1876
|
};
|
1754
|
-
PublishAction.type = "publish";
|
1877
|
+
PublishAction$1.type = "publish";
|
1755
1878
|
const UpdateAction = ({
|
1756
1879
|
activeTab,
|
1757
1880
|
documentId,
|
@@ -1764,7 +1887,7 @@ const UpdateAction = ({
|
|
1764
1887
|
const cloneMatch = reactRouterDom.useMatch(CLONE_PATH);
|
1765
1888
|
const isCloning = cloneMatch !== null;
|
1766
1889
|
const { formatMessage } = reactIntl.useIntl();
|
1767
|
-
|
1890
|
+
useDocumentRBAC("UpdateAction", ({ canCreate: canCreate2, canUpdate: canUpdate2 }) => ({
|
1768
1891
|
canCreate: canCreate2,
|
1769
1892
|
canUpdate: canUpdate2
|
1770
1893
|
}));
|
@@ -1784,10 +1907,8 @@ const UpdateAction = ({
|
|
1784
1907
|
* - the form is submitting
|
1785
1908
|
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
1786
1909
|
* - the active tab is the published tab
|
1787
|
-
* - the user doesn't have the permission to create a new document
|
1788
|
-
* - the user doesn't have the permission to update the document
|
1789
1910
|
*/
|
1790
|
-
disabled: isSubmitting || !modified && !isCloning || activeTab === "published"
|
1911
|
+
disabled: isSubmitting || !modified && !isCloning || activeTab === "published",
|
1791
1912
|
label: formatMessage({
|
1792
1913
|
id: "content-manager.containers.Edit.save",
|
1793
1914
|
defaultMessage: "Save"
|
@@ -1816,10 +1937,13 @@ const UpdateAction = ({
|
|
1816
1937
|
document
|
1817
1938
|
);
|
1818
1939
|
if ("data" in res) {
|
1819
|
-
navigate(
|
1820
|
-
|
1821
|
-
|
1822
|
-
|
1940
|
+
navigate(
|
1941
|
+
{
|
1942
|
+
pathname: `../${res.data.documentId}`,
|
1943
|
+
search: rawQuery
|
1944
|
+
},
|
1945
|
+
{ relative: "path" }
|
1946
|
+
);
|
1823
1947
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1824
1948
|
setErrors(formatValidationErrors(res.error));
|
1825
1949
|
}
|
@@ -1847,10 +1971,13 @@ const UpdateAction = ({
|
|
1847
1971
|
document
|
1848
1972
|
);
|
1849
1973
|
if ("data" in res && collectionType !== SINGLE_TYPES) {
|
1850
|
-
navigate(
|
1851
|
-
|
1852
|
-
|
1853
|
-
|
1974
|
+
navigate(
|
1975
|
+
{
|
1976
|
+
pathname: `../${res.data.documentId}`,
|
1977
|
+
search: rawQuery
|
1978
|
+
},
|
1979
|
+
{ replace: true, relative: "path" }
|
1980
|
+
);
|
1854
1981
|
} else if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
1855
1982
|
setErrors(formatValidationErrors(res.error));
|
1856
1983
|
}
|
@@ -1882,10 +2009,8 @@ const UnpublishAction$1 = ({
|
|
1882
2009
|
const { toggleNotification } = strapiAdmin.useNotification();
|
1883
2010
|
const [shouldKeepDraft, setShouldKeepDraft] = React__namespace.useState(true);
|
1884
2011
|
const isDocumentModified = document?.status === "modified";
|
1885
|
-
const handleChange = (
|
1886
|
-
|
1887
|
-
setShouldKeepDraft(e.target.value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1888
|
-
}
|
2012
|
+
const handleChange = (value) => {
|
2013
|
+
setShouldKeepDraft(value === UNPUBLISH_DRAFT_OPTIONS.KEEP);
|
1889
2014
|
};
|
1890
2015
|
if (!schema?.options?.draftAndPublish) {
|
1891
2016
|
return null;
|
@@ -1935,40 +2060,24 @@ const UnpublishAction$1 = ({
|
|
1935
2060
|
}) })
|
1936
2061
|
] }),
|
1937
2062
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
1938
|
-
designSystem.
|
2063
|
+
designSystem.Radio.Group,
|
1939
2064
|
{
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
1943
|
-
|
1944
|
-
|
1945
|
-
|
2065
|
+
defaultValue: UNPUBLISH_DRAFT_OPTIONS.KEEP,
|
2066
|
+
name: "discard-options",
|
2067
|
+
"aria-label": formatMessage({
|
2068
|
+
id: "content-manager.actions.unpublish.dialog.radio-label",
|
2069
|
+
defaultMessage: "Choose an option to unpublish the document."
|
2070
|
+
}),
|
2071
|
+
onValueChange: handleChange,
|
1946
2072
|
children: [
|
1947
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
1948
|
-
|
1949
|
-
|
1950
|
-
|
1951
|
-
|
1952
|
-
|
1953
|
-
|
1954
|
-
|
1955
|
-
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
1956
|
-
defaultMessage: "Keep draft"
|
1957
|
-
})
|
1958
|
-
}
|
1959
|
-
),
|
1960
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
1961
|
-
designSystem.Radio,
|
1962
|
-
{
|
1963
|
-
checked: !shouldKeepDraft,
|
1964
|
-
value: UNPUBLISH_DRAFT_OPTIONS.DISCARD,
|
1965
|
-
name: "discard-options",
|
1966
|
-
children: formatMessage({
|
1967
|
-
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
1968
|
-
defaultMessage: "Replace draft"
|
1969
|
-
})
|
1970
|
-
}
|
1971
|
-
)
|
2073
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.KEEP, children: formatMessage({
|
2074
|
+
id: "content-manager.actions.unpublish.dialog.option.keep-draft",
|
2075
|
+
defaultMessage: "Keep draft"
|
2076
|
+
}) }),
|
2077
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Radio.Item, { checked: !shouldKeepDraft, value: UNPUBLISH_DRAFT_OPTIONS.DISCARD, children: formatMessage({
|
2078
|
+
id: "content-manager.actions.unpublish.dialog.option.replace-draft",
|
2079
|
+
defaultMessage: "Replace draft"
|
2080
|
+
}) })
|
1972
2081
|
]
|
1973
2082
|
}
|
1974
2083
|
)
|
@@ -2057,7 +2166,7 @@ const StyledCrossCircle = styledComponents.styled(Icons.CrossCircle)`
|
|
2057
2166
|
fill: currentColor;
|
2058
2167
|
}
|
2059
2168
|
`;
|
2060
|
-
const DEFAULT_ACTIONS = [PublishAction, UpdateAction, UnpublishAction$1, DiscardAction];
|
2169
|
+
const DEFAULT_ACTIONS = [PublishAction$1, UpdateAction, UnpublishAction$1, DiscardAction];
|
2061
2170
|
const intervals = ["years", "months", "days", "hours", "minutes", "seconds"];
|
2062
2171
|
const RelativeTime = React__namespace.forwardRef(
|
2063
2172
|
({ timestamp, customIntervals = [], ...restProps }, forwardedRef) => {
|
@@ -2114,23 +2223,13 @@ const Header = ({ isCreating, status, title: documentTitle = "Untitled" }) => {
|
|
2114
2223
|
id: "content-manager.containers.edit.title.new",
|
2115
2224
|
defaultMessage: "Create an entry"
|
2116
2225
|
}) : documentTitle;
|
2117
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop:
|
2226
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", paddingTop: 6, paddingBottom: 4, gap: 2, children: [
|
2118
2227
|
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.BackButton, {}),
|
2119
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
2120
|
-
designSystem.
|
2121
|
-
{
|
2122
|
-
|
2123
|
-
|
2124
|
-
paddingTop: 1,
|
2125
|
-
gap: "80px",
|
2126
|
-
alignItems: "flex-start",
|
2127
|
-
children: [
|
2128
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2129
|
-
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2130
|
-
]
|
2131
|
-
}
|
2132
|
-
),
|
2133
|
-
status ? /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) : null
|
2228
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { width: "100%", justifyContent: "space-between", gap: "80px", alignItems: "flex-start", children: [
|
2229
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", children: title }),
|
2230
|
+
/* @__PURE__ */ jsxRuntime.jsx(HeaderToolbar, {})
|
2231
|
+
] }),
|
2232
|
+
status ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 1, children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: isCloning ? "draft" : status }) }) : null
|
2134
2233
|
] });
|
2135
2234
|
};
|
2136
2235
|
const HeaderToolbar = () => {
|
@@ -2512,278 +2611,902 @@ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
|
|
2512
2611
|
}
|
2513
2612
|
);
|
2514
2613
|
});
|
2515
|
-
const
|
2516
|
-
|
2517
|
-
|
2518
|
-
|
2519
|
-
|
2520
|
-
|
2521
|
-
|
2522
|
-
|
2523
|
-
|
2524
|
-
|
2525
|
-
|
2526
|
-
|
2527
|
-
|
2528
|
-
|
2529
|
-
|
2530
|
-
|
2614
|
+
const HOOKS = {
|
2615
|
+
/**
|
2616
|
+
* Hook that allows to mutate the displayed headers of the list view table
|
2617
|
+
* @constant
|
2618
|
+
* @type {string}
|
2619
|
+
*/
|
2620
|
+
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
2621
|
+
/**
|
2622
|
+
* Hook that allows to mutate the CM's collection types links pre-set filters
|
2623
|
+
* @constant
|
2624
|
+
* @type {string}
|
2625
|
+
*/
|
2626
|
+
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
2627
|
+
/**
|
2628
|
+
* Hook that allows to mutate the CM's edit view layout
|
2629
|
+
* @constant
|
2630
|
+
* @type {string}
|
2631
|
+
*/
|
2632
|
+
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
2633
|
+
/**
|
2634
|
+
* Hook that allows to mutate the CM's single types links pre-set filters
|
2635
|
+
* @constant
|
2636
|
+
* @type {string}
|
2637
|
+
*/
|
2638
|
+
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
2531
2639
|
};
|
2532
|
-
const
|
2533
|
-
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2542
|
-
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
|
2553
|
-
|
2554
|
-
|
2555
|
-
|
2556
|
-
|
2557
|
-
|
2558
|
-
|
2559
|
-
|
2560
|
-
|
2561
|
-
|
2562
|
-
|
2563
|
-
}
|
2564
|
-
}
|
2565
|
-
|
2566
|
-
|
2567
|
-
|
2568
|
-
|
2569
|
-
|
2570
|
-
|
2571
|
-
|
2572
|
-
|
2573
|
-
|
2574
|
-
|
2575
|
-
|
2576
|
-
|
2577
|
-
BulkActionConfirmDialog,
|
2578
|
-
{
|
2579
|
-
...action.dialog,
|
2580
|
-
variant: action.variant,
|
2581
|
-
isOpen: dialogId === action.id,
|
2582
|
-
onClose: handleClose
|
2583
|
-
}
|
2584
|
-
) : null,
|
2585
|
-
action.dialog?.type === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(
|
2586
|
-
BulkActionModal,
|
2587
|
-
{
|
2588
|
-
...action.dialog,
|
2589
|
-
onModalClose: handleClose,
|
2590
|
-
isOpen: dialogId === action.id
|
2591
|
-
}
|
2592
|
-
) : null
|
2593
|
-
] });
|
2594
|
-
};
|
2595
|
-
const BulkActionConfirmDialog = ({
|
2596
|
-
onClose,
|
2597
|
-
onCancel,
|
2598
|
-
onConfirm,
|
2599
|
-
title,
|
2600
|
-
content,
|
2601
|
-
confirmButton,
|
2602
|
-
isOpen,
|
2603
|
-
variant = "secondary"
|
2604
|
-
}) => {
|
2605
|
-
const { formatMessage } = reactIntl.useIntl();
|
2606
|
-
const handleClose = async () => {
|
2607
|
-
if (onCancel) {
|
2608
|
-
await onCancel();
|
2609
|
-
}
|
2610
|
-
onClose();
|
2611
|
-
};
|
2612
|
-
const handleConfirm = async () => {
|
2613
|
-
if (onConfirm) {
|
2614
|
-
await onConfirm();
|
2615
|
-
}
|
2616
|
-
onClose();
|
2617
|
-
};
|
2618
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog, { isOpen, title, onClose: handleClose, children: [
|
2619
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.DialogBody, { icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, {}), children: content }),
|
2620
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2621
|
-
designSystem.DialogFooter,
|
2622
|
-
{
|
2623
|
-
startAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleClose, variant: "tertiary", children: formatMessage({
|
2624
|
-
id: "app.components.Button.cancel",
|
2625
|
-
defaultMessage: "Cancel"
|
2626
|
-
}) }),
|
2627
|
-
endAction: /* @__PURE__ */ jsxRuntime.jsx(
|
2628
|
-
designSystem.Button,
|
2629
|
-
{
|
2630
|
-
onClick: handleConfirm,
|
2631
|
-
variant: variant === "danger-light" ? variant : "secondary",
|
2632
|
-
startIcon: variant === "danger-light" ? /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}) : /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
|
2633
|
-
children: confirmButton ? confirmButton : formatMessage({
|
2634
|
-
id: "app.components.Button.confirm",
|
2635
|
-
defaultMessage: "Confirm"
|
2636
|
-
})
|
2637
|
-
}
|
2638
|
-
)
|
2639
|
-
}
|
2640
|
-
)
|
2641
|
-
] });
|
2640
|
+
const contentTypesApi = contentManagerApi.injectEndpoints({
|
2641
|
+
endpoints: (builder) => ({
|
2642
|
+
getContentTypeConfiguration: builder.query({
|
2643
|
+
query: (uid) => ({
|
2644
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
2645
|
+
method: "GET"
|
2646
|
+
}),
|
2647
|
+
transformResponse: (response) => response.data,
|
2648
|
+
providesTags: (_result, _error, uid) => [
|
2649
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
2650
|
+
{ type: "ContentTypeSettings", id: "LIST" }
|
2651
|
+
]
|
2652
|
+
}),
|
2653
|
+
getAllContentTypeSettings: builder.query({
|
2654
|
+
query: () => "/content-manager/content-types-settings",
|
2655
|
+
transformResponse: (response) => response.data,
|
2656
|
+
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
2657
|
+
}),
|
2658
|
+
updateContentTypeConfiguration: builder.mutation({
|
2659
|
+
query: ({ uid, ...body }) => ({
|
2660
|
+
url: `/content-manager/content-types/${uid}/configuration`,
|
2661
|
+
method: "PUT",
|
2662
|
+
data: body
|
2663
|
+
}),
|
2664
|
+
transformResponse: (response) => response.data,
|
2665
|
+
invalidatesTags: (_result, _error, { uid }) => [
|
2666
|
+
{ type: "ContentTypesConfiguration", id: uid },
|
2667
|
+
{ type: "ContentTypeSettings", id: "LIST" },
|
2668
|
+
// Is this necessary?
|
2669
|
+
{ type: "InitialData" }
|
2670
|
+
]
|
2671
|
+
})
|
2672
|
+
})
|
2673
|
+
});
|
2674
|
+
const {
|
2675
|
+
useGetContentTypeConfigurationQuery,
|
2676
|
+
useGetAllContentTypeSettingsQuery,
|
2677
|
+
useUpdateContentTypeConfigurationMutation
|
2678
|
+
} = contentTypesApi;
|
2679
|
+
const checkIfAttributeIsDisplayable = (attribute) => {
|
2680
|
+
const { type } = attribute;
|
2681
|
+
if (type === "relation") {
|
2682
|
+
return !attribute.relation.toLowerCase().includes("morph");
|
2683
|
+
}
|
2684
|
+
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
2642
2685
|
};
|
2643
|
-
const
|
2644
|
-
|
2645
|
-
|
2646
|
-
onClose,
|
2647
|
-
content: Content,
|
2648
|
-
onModalClose
|
2649
|
-
}) => {
|
2650
|
-
const id = React__namespace.useId();
|
2651
|
-
if (!isOpen) {
|
2652
|
-
return null;
|
2686
|
+
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
2687
|
+
if (!mainFieldName) {
|
2688
|
+
return void 0;
|
2653
2689
|
}
|
2654
|
-
const
|
2655
|
-
|
2656
|
-
|
2657
|
-
|
2658
|
-
|
2690
|
+
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
2691
|
+
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
2692
|
+
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
2693
|
+
);
|
2694
|
+
return {
|
2695
|
+
name: mainFieldName,
|
2696
|
+
type: mainFieldType ?? "string"
|
2659
2697
|
};
|
2660
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ModalLayout, { borderRadius: "4px", overflow: "hidden", onClose: handleClose, labelledBy: id, children: [
|
2661
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.ModalHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", textColor: "neutral800", tag: "h2", id, children: title }) }),
|
2662
|
-
/* @__PURE__ */ jsxRuntime.jsx(Content, { onClose: handleClose })
|
2663
|
-
] });
|
2664
2698
|
};
|
2665
|
-
const
|
2666
|
-
|
2667
|
-
|
2668
|
-
|
2669
|
-
|
2699
|
+
const DEFAULT_SETTINGS = {
|
2700
|
+
bulkable: false,
|
2701
|
+
filterable: false,
|
2702
|
+
searchable: false,
|
2703
|
+
pagination: false,
|
2704
|
+
defaultSortBy: "",
|
2705
|
+
defaultSortOrder: "asc",
|
2706
|
+
mainField: "id",
|
2707
|
+
pageSize: 10
|
2708
|
+
};
|
2709
|
+
const useDocumentLayout = (model) => {
|
2710
|
+
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
2670
2711
|
const [{ query }] = strapiAdmin.useQueryParams();
|
2671
|
-
const
|
2672
|
-
const
|
2673
|
-
const {
|
2674
|
-
const
|
2675
|
-
const
|
2676
|
-
|
2677
|
-
|
2678
|
-
|
2679
|
-
|
2680
|
-
|
2681
|
-
|
2682
|
-
|
2712
|
+
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
2713
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2714
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
|
2715
|
+
const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
|
2716
|
+
const {
|
2717
|
+
data,
|
2718
|
+
isLoading: isLoadingConfigs,
|
2719
|
+
error,
|
2720
|
+
isFetching: isFetchingConfigs
|
2721
|
+
} = useGetContentTypeConfigurationQuery(model);
|
2722
|
+
const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
|
2723
|
+
React__namespace.useEffect(() => {
|
2724
|
+
if (error) {
|
2725
|
+
toggleNotification({
|
2726
|
+
type: "danger",
|
2727
|
+
message: formatAPIError(error)
|
2728
|
+
});
|
2683
2729
|
}
|
2684
|
-
};
|
2685
|
-
|
2686
|
-
|
2730
|
+
}, [error, formatAPIError, toggleNotification]);
|
2731
|
+
const editLayout = React__namespace.useMemo(
|
2732
|
+
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
2733
|
+
layout: [],
|
2734
|
+
components: {},
|
2735
|
+
metadatas: {},
|
2736
|
+
options: {},
|
2737
|
+
settings: DEFAULT_SETTINGS
|
2738
|
+
},
|
2739
|
+
[data, isLoading, schemas, schema, components]
|
2740
|
+
);
|
2741
|
+
const listLayout = React__namespace.useMemo(() => {
|
2742
|
+
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
2743
|
+
layout: [],
|
2744
|
+
metadatas: {},
|
2745
|
+
options: {},
|
2746
|
+
settings: DEFAULT_SETTINGS
|
2747
|
+
};
|
2748
|
+
}, [data, isLoading, schemas, schema, components]);
|
2749
|
+
const { layout: edit } = React__namespace.useMemo(
|
2750
|
+
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
2751
|
+
layout: editLayout,
|
2752
|
+
query
|
2753
|
+
}),
|
2754
|
+
[editLayout, query, runHookWaterfall]
|
2755
|
+
);
|
2687
2756
|
return {
|
2688
|
-
|
2689
|
-
|
2690
|
-
|
2691
|
-
|
2692
|
-
title: formatMessage({
|
2693
|
-
id: "app.components.ConfirmDialog.title",
|
2694
|
-
defaultMessage: "Confirmation"
|
2695
|
-
}),
|
2696
|
-
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
2697
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
2698
|
-
id: "popUpWarning.bodyMessage.contentType.delete.all",
|
2699
|
-
defaultMessage: "Are you sure you want to delete these entries?"
|
2700
|
-
}) }),
|
2701
|
-
hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
|
2702
|
-
{
|
2703
|
-
id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
|
2704
|
-
defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
|
2705
|
-
},
|
2706
|
-
{
|
2707
|
-
em: Emphasis
|
2708
|
-
}
|
2709
|
-
) }) })
|
2710
|
-
] }),
|
2711
|
-
onConfirm: handleConfirmBulkDelete
|
2712
|
-
}
|
2757
|
+
error,
|
2758
|
+
isLoading,
|
2759
|
+
edit,
|
2760
|
+
list: listLayout
|
2713
2761
|
};
|
2714
2762
|
};
|
2715
|
-
|
2716
|
-
const
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2724
|
-
|
2725
|
-
const
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2763
|
+
const useDocLayout = () => {
|
2764
|
+
const { model } = useDoc();
|
2765
|
+
return useDocumentLayout(model);
|
2766
|
+
};
|
2767
|
+
const formatEditLayout = (data, {
|
2768
|
+
schemas,
|
2769
|
+
schema,
|
2770
|
+
components
|
2771
|
+
}) => {
|
2772
|
+
let currentPanelIndex = 0;
|
2773
|
+
const panelledEditAttributes = convertEditLayoutToFieldLayouts(
|
2774
|
+
data.contentType.layouts.edit,
|
2775
|
+
schema?.attributes,
|
2776
|
+
data.contentType.metadatas,
|
2777
|
+
{ configurations: data.components, schemas: components },
|
2778
|
+
schemas
|
2779
|
+
).reduce((panels, row) => {
|
2780
|
+
if (row.some((field) => field.type === "dynamiczone")) {
|
2781
|
+
panels.push([row]);
|
2782
|
+
currentPanelIndex += 2;
|
2783
|
+
} else {
|
2784
|
+
if (!panels[currentPanelIndex]) {
|
2785
|
+
panels.push([]);
|
2786
|
+
}
|
2787
|
+
panels[currentPanelIndex].push(row);
|
2788
|
+
}
|
2789
|
+
return panels;
|
2790
|
+
}, []);
|
2791
|
+
const componentEditAttributes = Object.entries(data.components).reduce(
|
2792
|
+
(acc, [uid, configuration]) => {
|
2793
|
+
acc[uid] = {
|
2794
|
+
layout: convertEditLayoutToFieldLayouts(
|
2795
|
+
configuration.layouts.edit,
|
2796
|
+
components[uid].attributes,
|
2797
|
+
configuration.metadatas
|
2798
|
+
),
|
2799
|
+
settings: {
|
2800
|
+
...configuration.settings,
|
2801
|
+
icon: components[uid].info.icon,
|
2802
|
+
displayName: components[uid].info.displayName
|
2803
|
+
}
|
2804
|
+
};
|
2805
|
+
return acc;
|
2806
|
+
},
|
2807
|
+
{}
|
2808
|
+
);
|
2809
|
+
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2810
|
+
(acc, [attribute, metadata]) => {
|
2811
|
+
return {
|
2812
|
+
...acc,
|
2813
|
+
[attribute]: metadata.edit
|
2814
|
+
};
|
2815
|
+
},
|
2816
|
+
{}
|
2817
|
+
);
|
2818
|
+
return {
|
2819
|
+
layout: panelledEditAttributes,
|
2820
|
+
components: componentEditAttributes,
|
2821
|
+
metadatas: editMetadatas,
|
2822
|
+
settings: {
|
2823
|
+
...data.contentType.settings,
|
2824
|
+
displayName: schema?.info.displayName
|
2825
|
+
},
|
2826
|
+
options: {
|
2827
|
+
...schema?.options,
|
2828
|
+
...schema?.pluginOptions,
|
2829
|
+
...data.contentType.options
|
2731
2830
|
}
|
2732
2831
|
};
|
2733
|
-
|
2734
|
-
|
2735
|
-
|
2832
|
+
};
|
2833
|
+
const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
|
2834
|
+
return rows.map(
|
2835
|
+
(row) => row.map((field) => {
|
2836
|
+
const attribute = attributes[field.name];
|
2837
|
+
if (!attribute) {
|
2838
|
+
return null;
|
2839
|
+
}
|
2840
|
+
const { edit: metadata } = metadatas[field.name];
|
2841
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2842
|
+
return {
|
2843
|
+
attribute,
|
2844
|
+
disabled: !metadata.editable,
|
2845
|
+
hint: metadata.description,
|
2846
|
+
label: metadata.label ?? "",
|
2847
|
+
name: field.name,
|
2848
|
+
// @ts-expect-error – mainField does exist on the metadata for a relation.
|
2849
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2850
|
+
schemas,
|
2851
|
+
components: components?.schemas ?? {}
|
2852
|
+
}),
|
2853
|
+
placeholder: metadata.placeholder ?? "",
|
2854
|
+
required: attribute.required ?? false,
|
2855
|
+
size: field.size,
|
2856
|
+
unique: "unique" in attribute ? attribute.unique : false,
|
2857
|
+
visible: metadata.visible ?? true,
|
2858
|
+
type: attribute.type
|
2859
|
+
};
|
2860
|
+
}).filter((field) => field !== null)
|
2861
|
+
);
|
2862
|
+
};
|
2863
|
+
const formatListLayout = (data, {
|
2864
|
+
schemas,
|
2865
|
+
schema,
|
2866
|
+
components
|
2867
|
+
}) => {
|
2868
|
+
const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
2869
|
+
(acc, [attribute, metadata]) => {
|
2870
|
+
return {
|
2871
|
+
...acc,
|
2872
|
+
[attribute]: metadata.list
|
2873
|
+
};
|
2874
|
+
},
|
2875
|
+
{}
|
2876
|
+
);
|
2877
|
+
const listAttributes = convertListLayoutToFieldLayouts(
|
2878
|
+
data.contentType.layouts.list,
|
2879
|
+
schema?.attributes,
|
2880
|
+
listMetadatas,
|
2881
|
+
{ configurations: data.components, schemas: components },
|
2882
|
+
schemas
|
2883
|
+
);
|
2736
2884
|
return {
|
2737
|
-
|
2738
|
-
|
2739
|
-
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2885
|
+
layout: listAttributes,
|
2886
|
+
settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
|
2887
|
+
metadatas: listMetadatas,
|
2888
|
+
options: {
|
2889
|
+
...schema?.options,
|
2890
|
+
...schema?.pluginOptions,
|
2891
|
+
...data.contentType.options
|
2892
|
+
}
|
2893
|
+
};
|
2894
|
+
};
|
2895
|
+
const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
|
2896
|
+
return columns.map((name) => {
|
2897
|
+
const attribute = attributes[name];
|
2898
|
+
if (!attribute) {
|
2899
|
+
return null;
|
2900
|
+
}
|
2901
|
+
const metadata = metadatas[name];
|
2902
|
+
const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
|
2903
|
+
return {
|
2904
|
+
attribute,
|
2905
|
+
label: metadata.label ?? "",
|
2906
|
+
mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
|
2907
|
+
schemas,
|
2908
|
+
components: components?.schemas ?? {}
|
2744
2909
|
}),
|
2745
|
-
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2749
|
-
|
2750
|
-
|
2910
|
+
name,
|
2911
|
+
searchable: metadata.searchable ?? true,
|
2912
|
+
sortable: metadata.sortable ?? true
|
2913
|
+
};
|
2914
|
+
}).filter((field) => field !== null);
|
2915
|
+
};
|
2916
|
+
const ConfirmBulkActionDialog = ({
|
2917
|
+
onToggleDialog,
|
2918
|
+
isOpen = false,
|
2919
|
+
dialogBody,
|
2920
|
+
endAction
|
2921
|
+
}) => {
|
2922
|
+
const { formatMessage } = reactIntl.useIntl();
|
2923
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Root, { open: isOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Content, { children: [
|
2924
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Header, { children: formatMessage({
|
2925
|
+
id: "app.components.ConfirmDialog.title",
|
2926
|
+
defaultMessage: "Confirmation"
|
2927
|
+
}) }),
|
2928
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
2929
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
2930
|
+
dialogBody
|
2931
|
+
] }) }),
|
2932
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Dialog.Footer, { children: [
|
2933
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Dialog.Cancel, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { fullWidth: true, onClick: onToggleDialog, variant: "tertiary", children: formatMessage({
|
2934
|
+
id: "app.components.Button.cancel",
|
2935
|
+
defaultMessage: "Cancel"
|
2936
|
+
}) }) }),
|
2937
|
+
endAction
|
2938
|
+
] })
|
2939
|
+
] }) });
|
2940
|
+
};
|
2941
|
+
const BoldChunk$1 = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
|
2942
|
+
const ConfirmDialogPublishAll = ({
|
2943
|
+
isOpen,
|
2944
|
+
onToggleDialog,
|
2945
|
+
isConfirmButtonLoading = false,
|
2946
|
+
onConfirm
|
2947
|
+
}) => {
|
2948
|
+
const { formatMessage } = reactIntl.useIntl();
|
2949
|
+
const selectedEntries = strapiAdmin.useTable("ConfirmDialogPublishAll", (state) => state.selectedRows);
|
2950
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
2951
|
+
const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler(getTranslation);
|
2952
|
+
const { model, schema } = useDoc();
|
2953
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
2954
|
+
const {
|
2955
|
+
data: countDraftRelations = 0,
|
2956
|
+
isLoading,
|
2957
|
+
error
|
2958
|
+
} = useGetManyDraftRelationCountQuery(
|
2959
|
+
{
|
2960
|
+
model,
|
2961
|
+
documentIds: selectedEntries.map((entry) => entry.documentId),
|
2962
|
+
locale: query?.plugins?.i18n?.locale
|
2963
|
+
},
|
2964
|
+
{
|
2965
|
+
skip: selectedEntries.length === 0
|
2966
|
+
}
|
2967
|
+
);
|
2968
|
+
React__namespace.useEffect(() => {
|
2969
|
+
if (error) {
|
2970
|
+
toggleNotification({ type: "danger", message: formatAPIError(error) });
|
2971
|
+
}
|
2972
|
+
}, [error, formatAPIError, toggleNotification]);
|
2973
|
+
if (error) {
|
2974
|
+
return null;
|
2975
|
+
}
|
2976
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
2977
|
+
ConfirmBulkActionDialog,
|
2978
|
+
{
|
2979
|
+
isOpen: isOpen && !isLoading,
|
2980
|
+
onToggleDialog,
|
2981
|
+
dialogBody: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
2982
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: [
|
2983
|
+
countDraftRelations > 0 && formatMessage(
|
2984
|
+
{
|
2985
|
+
id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`),
|
2986
|
+
defaultMessage: "<b>{count} {count, plural, one { relation } other { relations } } out of {entities} { entities, plural, one { entry } other { entries } } {count, plural, one { is } other { are } }</b> not published yet and might lead to unexpected behavior. "
|
2987
|
+
},
|
2988
|
+
{
|
2989
|
+
b: BoldChunk$1,
|
2990
|
+
count: countDraftRelations,
|
2991
|
+
entities: selectedEntries.length
|
2992
|
+
}
|
2993
|
+
),
|
2994
|
+
formatMessage({
|
2995
|
+
id: getTranslation("popUpWarning.bodyMessage.contentType.publish.all"),
|
2996
|
+
defaultMessage: "Are you sure you want to publish these entries?"
|
2997
|
+
})
|
2998
|
+
] }),
|
2999
|
+
schema?.pluginOptions && "i18n" in schema.pluginOptions && schema?.pluginOptions.i18n && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", textAlign: "center", children: formatMessage(
|
2751
3000
|
{
|
2752
|
-
id: getTranslation("Settings.list.actions.
|
2753
|
-
defaultMessage: "This will
|
3001
|
+
id: getTranslation("Settings.list.actions.publishAdditionalInfos"),
|
3002
|
+
defaultMessage: "This will publish the active locale versions <em>(from Internationalization)</em>"
|
2754
3003
|
},
|
2755
3004
|
{
|
2756
3005
|
em: Emphasis
|
2757
3006
|
}
|
2758
|
-
) })
|
3007
|
+
) })
|
2759
3008
|
] }),
|
2760
|
-
|
2761
|
-
|
2762
|
-
|
2763
|
-
|
2764
|
-
|
3009
|
+
endAction: /* @__PURE__ */ jsxRuntime.jsx(
|
3010
|
+
designSystem.Button,
|
3011
|
+
{
|
3012
|
+
onClick: onConfirm,
|
3013
|
+
variant: "secondary",
|
3014
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
|
3015
|
+
loading: isConfirmButtonLoading,
|
3016
|
+
children: formatMessage({
|
3017
|
+
id: "app.utils.publish",
|
3018
|
+
defaultMessage: "Publish"
|
3019
|
+
})
|
3020
|
+
}
|
3021
|
+
)
|
2765
3022
|
}
|
2766
|
-
|
3023
|
+
);
|
2767
3024
|
};
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
const
|
3025
|
+
const TypographyMaxWidth = styledComponents.styled(designSystem.Typography)`
|
3026
|
+
max-width: 300px;
|
3027
|
+
`;
|
3028
|
+
const formatErrorMessages = (errors, parentKey, formatMessage) => {
|
3029
|
+
const messages = [];
|
3030
|
+
Object.entries(errors).forEach(([key, value]) => {
|
3031
|
+
const currentKey = parentKey ? `${parentKey}.${key}` : key;
|
3032
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
3033
|
+
if ("id" in value && "defaultMessage" in value) {
|
3034
|
+
messages.push(
|
3035
|
+
formatMessage(
|
3036
|
+
{
|
3037
|
+
id: `${value.id}.withField`,
|
3038
|
+
defaultMessage: value.defaultMessage
|
3039
|
+
},
|
3040
|
+
{ field: currentKey }
|
3041
|
+
)
|
3042
|
+
);
|
3043
|
+
} else {
|
3044
|
+
messages.push(
|
3045
|
+
...formatErrorMessages(
|
3046
|
+
// @ts-expect-error TODO: check why value is not compatible with FormErrors
|
3047
|
+
value,
|
3048
|
+
currentKey,
|
3049
|
+
formatMessage
|
3050
|
+
)
|
3051
|
+
);
|
3052
|
+
}
|
3053
|
+
} else {
|
3054
|
+
messages.push(
|
3055
|
+
formatMessage(
|
3056
|
+
{
|
3057
|
+
id: `${value}.withField`,
|
3058
|
+
defaultMessage: value
|
3059
|
+
},
|
3060
|
+
{ field: currentKey }
|
3061
|
+
)
|
3062
|
+
);
|
3063
|
+
}
|
3064
|
+
});
|
3065
|
+
return messages;
|
3066
|
+
};
|
3067
|
+
const EntryValidationText = ({ validationErrors, status }) => {
|
2772
3068
|
const { formatMessage } = reactIntl.useIntl();
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
2779
|
-
|
2780
|
-
|
3069
|
+
if (validationErrors) {
|
3070
|
+
const validationErrorsMessages = formatErrorMessages(validationErrors, "", formatMessage).join(
|
3071
|
+
" "
|
3072
|
+
);
|
3073
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3074
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CrossCircle, { fill: "danger600" }),
|
3075
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tooltip, { description: validationErrorsMessages, children: /* @__PURE__ */ jsxRuntime.jsx(TypographyMaxWidth, { textColor: "danger600", variant: "omega", fontWeight: "semiBold", ellipsis: true, children: validationErrorsMessages }) })
|
3076
|
+
] });
|
3077
|
+
}
|
3078
|
+
if (status === "published") {
|
3079
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3080
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
|
3081
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "success600", fontWeight: "bold", children: formatMessage({
|
3082
|
+
id: "content-manager.bulk-publish.already-published",
|
3083
|
+
defaultMessage: "Already Published"
|
3084
|
+
}) })
|
3085
|
+
] });
|
3086
|
+
}
|
3087
|
+
if (status === "modified") {
|
3088
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3089
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.ArrowsCounterClockwise, { fill: "alternative600" }),
|
3090
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3091
|
+
id: "content-manager.bulk-publish.modified",
|
3092
|
+
defaultMessage: "Ready to publish changes"
|
3093
|
+
}) })
|
3094
|
+
] });
|
3095
|
+
}
|
3096
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3097
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.CheckCircle, { fill: "success600" }),
|
3098
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3099
|
+
id: "app.utils.ready-to-publish",
|
3100
|
+
defaultMessage: "Ready to publish"
|
3101
|
+
}) })
|
3102
|
+
] });
|
3103
|
+
};
|
3104
|
+
const TABLE_HEADERS = [
|
3105
|
+
{ name: "id", label: "id" },
|
3106
|
+
{ name: "name", label: "name" },
|
3107
|
+
{ name: "status", label: "status" },
|
3108
|
+
{ name: "publicationStatus", label: "Publication status" }
|
3109
|
+
];
|
3110
|
+
const SelectedEntriesTableContent = ({
|
3111
|
+
isPublishing,
|
3112
|
+
rowsToDisplay = [],
|
3113
|
+
entriesToPublish = [],
|
3114
|
+
validationErrors = {}
|
3115
|
+
}) => {
|
3116
|
+
const { pathname } = reactRouterDom.useLocation();
|
3117
|
+
const { formatMessage } = reactIntl.useIntl();
|
3118
|
+
const {
|
3119
|
+
list: {
|
3120
|
+
settings: { mainField }
|
2781
3121
|
}
|
2782
|
-
};
|
2783
|
-
|
2784
|
-
|
2785
|
-
|
2786
|
-
|
3122
|
+
} = useDocLayout();
|
3123
|
+
const shouldDisplayMainField = mainField != null && mainField !== "id";
|
3124
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Content, { children: [
|
3125
|
+
/* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Head, { children: [
|
3126
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCheckboxCell, {}),
|
3127
|
+
TABLE_HEADERS.filter((head) => head.name !== "name" || shouldDisplayMainField).map(
|
3128
|
+
(head) => /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.HeaderCell, { ...head }, head.name)
|
3129
|
+
)
|
3130
|
+
] }),
|
3131
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Loading, {}),
|
3132
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Body, { children: rowsToDisplay.map((row, index2) => /* @__PURE__ */ jsxRuntime.jsxs(strapiAdmin.Table.Row, { children: [
|
3133
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.CheckboxCell, { id: row.id }),
|
3134
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row.id }) }),
|
3135
|
+
shouldDisplayMainField && /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: row[mainField] }) }),
|
3136
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatus, { status: row.status, maxWidth: "min-content" }) }),
|
3137
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: isPublishing && entriesToPublish.includes(row.documentId) ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3138
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
|
3139
|
+
id: "content-manager.success.record.publishing",
|
3140
|
+
defaultMessage: "Publishing..."
|
3141
|
+
}) }),
|
3142
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true })
|
3143
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
3144
|
+
EntryValidationText,
|
3145
|
+
{
|
3146
|
+
validationErrors: validationErrors[row.documentId],
|
3147
|
+
status: row.status
|
3148
|
+
}
|
3149
|
+
) }),
|
3150
|
+
/* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
3151
|
+
designSystem.IconButton,
|
3152
|
+
{
|
3153
|
+
tag: reactRouterDom.Link,
|
3154
|
+
to: {
|
3155
|
+
pathname: `${pathname}/${row.documentId}`,
|
3156
|
+
search: row.locale && `?plugins[i18n][locale]=${row.locale}`
|
3157
|
+
},
|
3158
|
+
state: { from: pathname },
|
3159
|
+
label: formatMessage(
|
3160
|
+
{ id: "app.component.HelperPluginTable.edit", defaultMessage: "Edit {target}" },
|
3161
|
+
{
|
3162
|
+
target: formatMessage(
|
3163
|
+
{
|
3164
|
+
id: "content-manager.components.ListViewHelperPluginTable.row-line",
|
3165
|
+
defaultMessage: "item line {number}"
|
3166
|
+
},
|
3167
|
+
{ number: index2 + 1 }
|
3168
|
+
)
|
3169
|
+
}
|
3170
|
+
),
|
3171
|
+
target: "_blank",
|
3172
|
+
marginLeft: "auto",
|
3173
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
|
3174
|
+
}
|
3175
|
+
) })
|
3176
|
+
] }, row.id)) })
|
3177
|
+
] });
|
3178
|
+
};
|
3179
|
+
const BoldChunk = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: chunks });
|
3180
|
+
const SelectedEntriesModalContent = ({
|
3181
|
+
listViewSelectedEntries,
|
3182
|
+
toggleModal,
|
3183
|
+
setListViewSelectedDocuments,
|
3184
|
+
model
|
3185
|
+
}) => {
|
3186
|
+
const { formatMessage } = reactIntl.useIntl();
|
3187
|
+
const { schema, components } = useContentTypeSchema(model);
|
3188
|
+
const documentIds = listViewSelectedEntries.map(({ documentId }) => documentId);
|
3189
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3190
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3191
|
+
const { data, isLoading, isFetching, refetch } = useGetAllDocumentsQuery(
|
3192
|
+
{
|
3193
|
+
model,
|
3194
|
+
params: {
|
3195
|
+
page: "1",
|
3196
|
+
pageSize: documentIds.length.toString(),
|
3197
|
+
sort: query.sort,
|
3198
|
+
filters: {
|
3199
|
+
documentId: {
|
3200
|
+
$in: documentIds
|
3201
|
+
}
|
3202
|
+
},
|
3203
|
+
locale: query.plugins?.i18n?.locale
|
3204
|
+
}
|
3205
|
+
},
|
3206
|
+
{
|
3207
|
+
selectFromResult: ({ data: data2, ...restRes }) => ({ data: data2?.results ?? [], ...restRes })
|
3208
|
+
}
|
3209
|
+
);
|
3210
|
+
const { rows, validationErrors } = React__namespace.useMemo(() => {
|
3211
|
+
if (data.length > 0 && schema) {
|
3212
|
+
const validate = createYupSchema(schema.attributes, components);
|
3213
|
+
const validationErrors2 = {};
|
3214
|
+
const rows2 = data.map((entry) => {
|
3215
|
+
try {
|
3216
|
+
validate.validateSync(entry, { abortEarly: false });
|
3217
|
+
return entry;
|
3218
|
+
} catch (e) {
|
3219
|
+
if (e instanceof yup.ValidationError) {
|
3220
|
+
validationErrors2[entry.documentId] = strapiAdmin.getYupValidationErrors(e);
|
3221
|
+
}
|
3222
|
+
return entry;
|
3223
|
+
}
|
3224
|
+
});
|
3225
|
+
return { rows: rows2, validationErrors: validationErrors2 };
|
3226
|
+
}
|
3227
|
+
return {
|
3228
|
+
rows: [],
|
3229
|
+
validationErrors: {}
|
3230
|
+
};
|
3231
|
+
}, [components, data, schema]);
|
3232
|
+
const [publishedCount, setPublishedCount] = React__namespace.useState(0);
|
3233
|
+
const [isDialogOpen, setIsDialogOpen] = React__namespace.useState(false);
|
3234
|
+
const { publishMany: bulkPublishAction } = useDocumentActions();
|
3235
|
+
const [, { isLoading: isSubmittingForm }] = usePublishManyDocumentsMutation();
|
3236
|
+
const selectedRows = strapiAdmin.useTable("publishAction", (state) => state.selectedRows);
|
3237
|
+
const selectedEntries = rows.filter(
|
3238
|
+
(entry) => selectedRows.some((selectedEntry) => selectedEntry.documentId === entry.documentId)
|
3239
|
+
);
|
3240
|
+
const entriesToPublish = selectedEntries.filter((entry) => !validationErrors[entry.documentId]).map((entry) => entry.documentId);
|
3241
|
+
const selectedEntriesWithErrorsCount = selectedEntries.filter(
|
3242
|
+
({ documentId }) => validationErrors[documentId]
|
3243
|
+
).length;
|
3244
|
+
const selectedEntriesPublished = selectedEntries.filter(
|
3245
|
+
({ status }) => status === "published"
|
3246
|
+
).length;
|
3247
|
+
const selectedEntriesWithNoErrorsCount = selectedEntries.length - selectedEntriesWithErrorsCount - selectedEntriesPublished;
|
3248
|
+
const toggleDialog = () => setIsDialogOpen((prev) => !prev);
|
3249
|
+
const handleConfirmBulkPublish = async () => {
|
3250
|
+
toggleDialog();
|
3251
|
+
const res = await bulkPublishAction({ model, documentIds: entriesToPublish, params });
|
3252
|
+
if (!("error" in res)) {
|
3253
|
+
setPublishedCount(res.count);
|
3254
|
+
const unpublishedEntries = rows.filter((row) => {
|
3255
|
+
return !entriesToPublish.includes(row.documentId);
|
3256
|
+
});
|
3257
|
+
setListViewSelectedDocuments(unpublishedEntries);
|
3258
|
+
}
|
3259
|
+
};
|
3260
|
+
const getFormattedCountMessage = () => {
|
3261
|
+
if (publishedCount) {
|
3262
|
+
return formatMessage(
|
3263
|
+
{
|
3264
|
+
id: getTranslation("containers.list.selectedEntriesModal.publishedCount"),
|
3265
|
+
defaultMessage: "<b>{publishedCount}</b> {publishedCount, plural, =0 {entries} one {entry} other {entries}} published. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
|
3266
|
+
},
|
3267
|
+
{
|
3268
|
+
publishedCount,
|
3269
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3270
|
+
b: BoldChunk
|
3271
|
+
}
|
3272
|
+
);
|
3273
|
+
}
|
3274
|
+
return formatMessage(
|
3275
|
+
{
|
3276
|
+
id: getTranslation("containers.list.selectedEntriesModal.selectedCount"),
|
3277
|
+
defaultMessage: "<b>{alreadyPublishedCount}</b> {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. <b>{readyToPublishCount}</b> {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. <b>{withErrorsCount}</b> {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action."
|
3278
|
+
},
|
3279
|
+
{
|
3280
|
+
readyToPublishCount: selectedEntriesWithNoErrorsCount,
|
3281
|
+
withErrorsCount: selectedEntriesWithErrorsCount,
|
3282
|
+
alreadyPublishedCount: selectedEntriesPublished,
|
3283
|
+
b: BoldChunk
|
3284
|
+
}
|
3285
|
+
);
|
3286
|
+
};
|
3287
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
3288
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
|
3289
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: getFormattedCountMessage() }),
|
3290
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 5, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3291
|
+
SelectedEntriesTableContent,
|
3292
|
+
{
|
3293
|
+
isPublishing: isSubmittingForm,
|
3294
|
+
rowsToDisplay: rows,
|
3295
|
+
entriesToPublish,
|
3296
|
+
validationErrors
|
3297
|
+
}
|
3298
|
+
) })
|
3299
|
+
] }),
|
3300
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
|
3301
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: toggleModal, variant: "tertiary", children: formatMessage({
|
3302
|
+
id: "app.components.Button.cancel",
|
3303
|
+
defaultMessage: "Cancel"
|
3304
|
+
}) }),
|
3305
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
3306
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: refetch, variant: "tertiary", loading: isFetching, children: formatMessage({ id: "app.utils.refresh", defaultMessage: "Refresh" }) }),
|
3307
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3308
|
+
designSystem.Button,
|
3309
|
+
{
|
3310
|
+
onClick: toggleDialog,
|
3311
|
+
disabled: selectedEntries.length === 0 || selectedEntries.length === selectedEntriesWithErrorsCount || selectedEntriesPublished === selectedEntries.length || isLoading,
|
3312
|
+
loading: isSubmittingForm,
|
3313
|
+
children: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" })
|
3314
|
+
}
|
3315
|
+
)
|
3316
|
+
] })
|
3317
|
+
] }),
|
3318
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3319
|
+
ConfirmDialogPublishAll,
|
3320
|
+
{
|
3321
|
+
isOpen: isDialogOpen,
|
3322
|
+
onToggleDialog: toggleDialog,
|
3323
|
+
isConfirmButtonLoading: isSubmittingForm,
|
3324
|
+
onConfirm: handleConfirmBulkPublish
|
3325
|
+
}
|
3326
|
+
)
|
3327
|
+
] });
|
3328
|
+
};
|
3329
|
+
const PublishAction = ({ documents, model }) => {
|
3330
|
+
const { formatMessage } = reactIntl.useIntl();
|
3331
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3332
|
+
const showPublishButton = hasPublishPermission && documents.some(({ status }) => status !== "published");
|
3333
|
+
const setListViewSelectedDocuments = strapiAdmin.useTable("publishAction", (state) => state.selectRow);
|
3334
|
+
const refetchList = () => {
|
3335
|
+
contentManagerApi.util.invalidateTags([{ type: "Document", id: `${model}_LIST` }]);
|
3336
|
+
};
|
3337
|
+
if (!showPublishButton)
|
3338
|
+
return null;
|
3339
|
+
return {
|
3340
|
+
actionType: "publish",
|
3341
|
+
variant: "tertiary",
|
3342
|
+
label: formatMessage({ id: "app.utils.publish", defaultMessage: "Publish" }),
|
3343
|
+
dialog: {
|
3344
|
+
type: "modal",
|
3345
|
+
title: formatMessage({
|
3346
|
+
id: getTranslation("containers.ListPage.selectedEntriesModal.title"),
|
3347
|
+
defaultMessage: "Publish entries"
|
3348
|
+
}),
|
3349
|
+
content: ({ onClose }) => {
|
3350
|
+
return /* @__PURE__ */ jsxRuntime.jsx(strapiAdmin.Table.Root, { rows: documents, defaultSelectedRows: documents, headers: TABLE_HEADERS, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3351
|
+
SelectedEntriesModalContent,
|
3352
|
+
{
|
3353
|
+
listViewSelectedEntries: documents,
|
3354
|
+
toggleModal: () => {
|
3355
|
+
onClose();
|
3356
|
+
refetchList();
|
3357
|
+
},
|
3358
|
+
setListViewSelectedDocuments,
|
3359
|
+
model
|
3360
|
+
}
|
3361
|
+
) });
|
3362
|
+
},
|
3363
|
+
onClose: () => {
|
3364
|
+
refetchList();
|
3365
|
+
}
|
3366
|
+
}
|
3367
|
+
};
|
3368
|
+
};
|
3369
|
+
const BulkActionsRenderer = () => {
|
3370
|
+
const plugins = strapiAdmin.useStrapiApp("BulkActionsRenderer", (state) => state.plugins);
|
3371
|
+
const { model, collectionType } = useDoc();
|
3372
|
+
const { selectedRows } = strapiAdmin.useTable("BulkActionsRenderer", (state) => state);
|
3373
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
3374
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3375
|
+
{
|
3376
|
+
props: {
|
3377
|
+
model,
|
3378
|
+
collectionType,
|
3379
|
+
documents: selectedRows
|
3380
|
+
},
|
3381
|
+
descriptions: plugins["content-manager"].apis.getBulkActions(),
|
3382
|
+
children: (actions2) => actions2.map((action) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActionButton, { ...action }, action.id))
|
3383
|
+
}
|
3384
|
+
) });
|
3385
|
+
};
|
3386
|
+
const DeleteAction = ({ documents, model }) => {
|
3387
|
+
const { formatMessage } = reactIntl.useIntl();
|
3388
|
+
const { schema: contentType } = useDoc();
|
3389
|
+
const selectRow = strapiAdmin.useTable("DeleteAction", (state) => state.selectRow);
|
3390
|
+
const hasI18nEnabled = Boolean(contentType?.pluginOptions?.i18n);
|
3391
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3392
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3393
|
+
const hasDeletePermission = useDocumentRBAC("deleteAction", (state) => state.canDelete);
|
3394
|
+
const { deleteMany: bulkDeleteAction } = useDocumentActions();
|
3395
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3396
|
+
const handleConfirmBulkDelete = async () => {
|
3397
|
+
const res = await bulkDeleteAction({
|
3398
|
+
documentIds,
|
3399
|
+
model,
|
3400
|
+
params
|
3401
|
+
});
|
3402
|
+
if (!("error" in res)) {
|
3403
|
+
selectRow([]);
|
3404
|
+
}
|
3405
|
+
};
|
3406
|
+
if (!hasDeletePermission)
|
3407
|
+
return null;
|
3408
|
+
return {
|
3409
|
+
variant: "danger-light",
|
3410
|
+
label: formatMessage({ id: "global.delete", defaultMessage: "Delete" }),
|
3411
|
+
dialog: {
|
3412
|
+
type: "dialog",
|
3413
|
+
title: formatMessage({
|
3414
|
+
id: "app.components.ConfirmDialog.title",
|
3415
|
+
defaultMessage: "Confirmation"
|
3416
|
+
}),
|
3417
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3418
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3419
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3420
|
+
id: "popUpWarning.bodyMessage.contentType.delete.all",
|
3421
|
+
defaultMessage: "Are you sure you want to delete these entries?"
|
3422
|
+
}) }),
|
3423
|
+
hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
|
3424
|
+
{
|
3425
|
+
id: getTranslation("Settings.list.actions.deleteAdditionalInfos"),
|
3426
|
+
defaultMessage: "This will delete the active locale versions <em>(from Internationalization)</em>"
|
3427
|
+
},
|
3428
|
+
{
|
3429
|
+
em: Emphasis
|
3430
|
+
}
|
3431
|
+
) }) })
|
3432
|
+
] }),
|
3433
|
+
onConfirm: handleConfirmBulkDelete
|
3434
|
+
}
|
3435
|
+
};
|
3436
|
+
};
|
3437
|
+
DeleteAction.type = "delete";
|
3438
|
+
const UnpublishAction = ({ documents, model }) => {
|
3439
|
+
const { formatMessage } = reactIntl.useIntl();
|
3440
|
+
const { schema } = useDoc();
|
3441
|
+
const selectRow = strapiAdmin.useTable("UnpublishAction", (state) => state.selectRow);
|
3442
|
+
const hasPublishPermission = useDocumentRBAC("unpublishAction", (state) => state.canPublish);
|
3443
|
+
const hasI18nEnabled = Boolean(schema?.pluginOptions?.i18n);
|
3444
|
+
const hasDraftAndPublishEnabled = Boolean(schema?.options?.draftAndPublish);
|
3445
|
+
const { unpublishMany: bulkUnpublishAction } = useDocumentActions();
|
3446
|
+
const documentIds = documents.map(({ documentId }) => documentId);
|
3447
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3448
|
+
const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
|
3449
|
+
const handleConfirmBulkUnpublish = async () => {
|
3450
|
+
const data = await bulkUnpublishAction({ documentIds, model, params });
|
3451
|
+
if (!("error" in data)) {
|
3452
|
+
selectRow([]);
|
3453
|
+
}
|
3454
|
+
};
|
3455
|
+
const showUnpublishButton = hasDraftAndPublishEnabled && hasPublishPermission && documents.some((entry) => entry.status === "published" || entry.status === "modified");
|
3456
|
+
if (!showUnpublishButton)
|
3457
|
+
return null;
|
3458
|
+
return {
|
3459
|
+
variant: "tertiary",
|
3460
|
+
label: formatMessage({ id: "app.utils.unpublish", defaultMessage: "Unpublish" }),
|
3461
|
+
dialog: {
|
3462
|
+
type: "dialog",
|
3463
|
+
title: formatMessage({
|
3464
|
+
id: "app.components.ConfirmDialog.title",
|
3465
|
+
defaultMessage: "Confirmation"
|
3466
|
+
}),
|
3467
|
+
content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
3468
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", children: /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }) }),
|
3469
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { id: "confirm-description", textAlign: "center", children: formatMessage({
|
3470
|
+
id: "popUpWarning.bodyMessage.contentType.unpublish.all",
|
3471
|
+
defaultMessage: "Are you sure you want to unpublish these entries?"
|
3472
|
+
}) }),
|
3473
|
+
hasI18nEnabled && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { textAlign: "center", padding: 3, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger500", children: formatMessage(
|
3474
|
+
{
|
3475
|
+
id: getTranslation("Settings.list.actions.unpublishAdditionalInfos"),
|
3476
|
+
defaultMessage: "This will unpublish the active locale versions <em>(from Internationalization)</em>"
|
3477
|
+
},
|
3478
|
+
{
|
3479
|
+
em: Emphasis
|
3480
|
+
}
|
3481
|
+
) }) })
|
3482
|
+
] }),
|
3483
|
+
confirmButton: formatMessage({
|
3484
|
+
id: "app.utils.unpublish",
|
3485
|
+
defaultMessage: "Unpublish"
|
3486
|
+
}),
|
3487
|
+
onConfirm: handleConfirmBulkUnpublish
|
3488
|
+
}
|
3489
|
+
};
|
3490
|
+
};
|
3491
|
+
UnpublishAction.type = "unpublish";
|
3492
|
+
const Emphasis = (chunks) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "semiBold", textColor: "danger500", children: chunks });
|
3493
|
+
const DEFAULT_BULK_ACTIONS = [PublishAction, UnpublishAction, DeleteAction];
|
3494
|
+
const AutoCloneFailureModalBody = ({ prohibitedFields }) => {
|
3495
|
+
const { formatMessage } = reactIntl.useIntl();
|
3496
|
+
const getDefaultErrorMessage = (reason) => {
|
3497
|
+
switch (reason) {
|
3498
|
+
case "relation":
|
3499
|
+
return "Duplicating the relation could remove it from the original entry.";
|
3500
|
+
case "unique":
|
3501
|
+
return "Identical values in a unique field are not allowed";
|
3502
|
+
default:
|
3503
|
+
return reason;
|
3504
|
+
}
|
3505
|
+
};
|
3506
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
3507
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: formatMessage({
|
3508
|
+
id: getTranslation("containers.list.autoCloneModal.title"),
|
3509
|
+
defaultMessage: "This entry can't be duplicated directly."
|
2787
3510
|
}) }),
|
2788
3511
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { marginTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatMessage({
|
2789
3512
|
id: getTranslation("containers.list.autoCloneModal.description"),
|
@@ -2826,596 +3549,339 @@ const TableActions = ({ document }) => {
|
|
2826
3549
|
const { model, collectionType } = useDoc();
|
2827
3550
|
const plugins = strapiAdmin.useStrapiApp("TableActions", (state) => state.plugins);
|
2828
3551
|
const props = {
|
2829
|
-
activeTab: null,
|
2830
|
-
model,
|
2831
|
-
documentId: document.documentId,
|
2832
|
-
collectionType,
|
2833
|
-
document
|
2834
|
-
};
|
2835
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
2836
|
-
strapiAdmin.DescriptionComponentRenderer,
|
2837
|
-
{
|
2838
|
-
props,
|
2839
|
-
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
2840
|
-
children: (actions2) => {
|
2841
|
-
const tableRowActions = actions2.filter((action) => {
|
2842
|
-
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
2843
|
-
return positions.includes("table-row");
|
2844
|
-
});
|
2845
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
2846
|
-
DocumentActionsMenu,
|
2847
|
-
{
|
2848
|
-
actions: tableRowActions,
|
2849
|
-
label: formatMessage({
|
2850
|
-
id: "content-manager.containers.list.table.row-actions",
|
2851
|
-
defaultMessage: "Row action"
|
2852
|
-
}),
|
2853
|
-
variant: "ghost"
|
2854
|
-
}
|
2855
|
-
);
|
2856
|
-
}
|
2857
|
-
}
|
2858
|
-
);
|
2859
|
-
};
|
2860
|
-
const EditAction = ({ documentId }) => {
|
2861
|
-
const navigate = reactRouterDom.useNavigate();
|
2862
|
-
const { formatMessage } = reactIntl.useIntl();
|
2863
|
-
const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
|
2864
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
2865
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
2866
|
-
return {
|
2867
|
-
disabled: !canRead,
|
2868
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil, {}),
|
2869
|
-
label: formatMessage({
|
2870
|
-
id: "content-manager.actions.edit.label",
|
2871
|
-
defaultMessage: "Edit"
|
2872
|
-
}),
|
2873
|
-
position: "table-row",
|
2874
|
-
onClick: async () => {
|
2875
|
-
if (!documentId) {
|
2876
|
-
console.error(
|
2877
|
-
"You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
|
2878
|
-
);
|
2879
|
-
toggleNotification({
|
2880
|
-
message: formatMessage({
|
2881
|
-
id: "content-manager.actions.edit.error",
|
2882
|
-
defaultMessage: "An error occurred while trying to edit the document."
|
2883
|
-
}),
|
2884
|
-
type: "danger"
|
2885
|
-
});
|
2886
|
-
return;
|
2887
|
-
}
|
2888
|
-
navigate({
|
2889
|
-
pathname: documentId,
|
2890
|
-
search: qs.stringify({
|
2891
|
-
plugins: query.plugins
|
2892
|
-
})
|
2893
|
-
});
|
2894
|
-
}
|
2895
|
-
};
|
2896
|
-
};
|
2897
|
-
EditAction.type = "edit";
|
2898
|
-
const StyledPencil = styledComponents.styled(Icons.Pencil)`
|
2899
|
-
path {
|
2900
|
-
fill: currentColor;
|
2901
|
-
}
|
2902
|
-
`;
|
2903
|
-
const CloneAction = ({ model, documentId }) => {
|
2904
|
-
const navigate = reactRouterDom.useNavigate();
|
2905
|
-
const { formatMessage } = reactIntl.useIntl();
|
2906
|
-
const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
|
2907
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
2908
|
-
const { autoClone } = useDocumentActions();
|
2909
|
-
const [prohibitedFields, setProhibitedFields] = React__namespace.useState([]);
|
2910
|
-
return {
|
2911
|
-
disabled: !canCreate,
|
2912
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledDuplicate, {}),
|
2913
|
-
label: formatMessage({
|
2914
|
-
id: "content-manager.actions.clone.label",
|
2915
|
-
defaultMessage: "Duplicate"
|
2916
|
-
}),
|
2917
|
-
position: "table-row",
|
2918
|
-
onClick: async () => {
|
2919
|
-
if (!documentId) {
|
2920
|
-
console.error(
|
2921
|
-
"You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
|
2922
|
-
);
|
2923
|
-
toggleNotification({
|
2924
|
-
message: formatMessage({
|
2925
|
-
id: "content-manager.actions.clone.error",
|
2926
|
-
defaultMessage: "An error occurred while trying to clone the document."
|
2927
|
-
}),
|
2928
|
-
type: "danger"
|
2929
|
-
});
|
2930
|
-
return;
|
2931
|
-
}
|
2932
|
-
const res = await autoClone({ model, sourceId: documentId });
|
2933
|
-
if ("data" in res) {
|
2934
|
-
navigate(res.data.documentId);
|
2935
|
-
return true;
|
2936
|
-
}
|
2937
|
-
if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
|
2938
|
-
const prohibitedFields2 = res.error.details.prohibitedFields;
|
2939
|
-
setProhibitedFields(prohibitedFields2);
|
2940
|
-
}
|
2941
|
-
},
|
2942
|
-
dialog: {
|
2943
|
-
type: "modal",
|
2944
|
-
title: formatMessage({
|
2945
|
-
id: "content-manager.containers.list.autoCloneModal.header",
|
2946
|
-
defaultMessage: "Duplicate"
|
2947
|
-
}),
|
2948
|
-
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
2949
|
-
footer: ({ onClose }) => {
|
2950
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
|
2951
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
2952
|
-
id: "cancel",
|
2953
|
-
defaultMessage: "Cancel"
|
2954
|
-
}) }),
|
2955
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
2956
|
-
designSystem.LinkButton,
|
2957
|
-
{
|
2958
|
-
tag: reactRouterDom.NavLink,
|
2959
|
-
to: {
|
2960
|
-
pathname: `clone/${documentId}`
|
2961
|
-
},
|
2962
|
-
children: formatMessage({
|
2963
|
-
id: "content-manager.containers.list.autoCloneModal.create",
|
2964
|
-
defaultMessage: "Create"
|
2965
|
-
})
|
2966
|
-
}
|
2967
|
-
)
|
2968
|
-
] });
|
2969
|
-
}
|
2970
|
-
}
|
2971
|
-
};
|
2972
|
-
};
|
2973
|
-
CloneAction.type = "clone";
|
2974
|
-
const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
|
2975
|
-
path {
|
2976
|
-
fill: currentColor;
|
2977
|
-
}
|
2978
|
-
`;
|
2979
|
-
const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
|
2980
|
-
class ContentManagerPlugin {
|
2981
|
-
/**
|
2982
|
-
* The following properties are the stored ones provided by any plugins registering with
|
2983
|
-
* the content-manager. The function calls however, need to be called at runtime in the
|
2984
|
-
* application, so instead we collate them and run them later with the complete list incl.
|
2985
|
-
* ones already registered & the context of the view.
|
2986
|
-
*/
|
2987
|
-
bulkActions = [...DEFAULT_BULK_ACTIONS];
|
2988
|
-
documentActions = [
|
2989
|
-
...DEFAULT_ACTIONS,
|
2990
|
-
...DEFAULT_TABLE_ROW_ACTIONS,
|
2991
|
-
...DEFAULT_HEADER_ACTIONS,
|
2992
|
-
HistoryAction
|
2993
|
-
];
|
2994
|
-
editViewSidePanels = [ActionsPanel];
|
2995
|
-
headerActions = [];
|
2996
|
-
constructor() {
|
2997
|
-
}
|
2998
|
-
addEditViewSidePanel(panels) {
|
2999
|
-
if (Array.isArray(panels)) {
|
3000
|
-
this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
|
3001
|
-
} else if (typeof panels === "function") {
|
3002
|
-
this.editViewSidePanels = panels(this.editViewSidePanels);
|
3003
|
-
} else {
|
3004
|
-
throw new Error(
|
3005
|
-
`Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
|
3006
|
-
panels
|
3007
|
-
)}`
|
3008
|
-
);
|
3009
|
-
}
|
3010
|
-
}
|
3011
|
-
addDocumentAction(actions2) {
|
3012
|
-
if (Array.isArray(actions2)) {
|
3013
|
-
this.documentActions = [...this.documentActions, ...actions2];
|
3014
|
-
} else if (typeof actions2 === "function") {
|
3015
|
-
this.documentActions = actions2(this.documentActions);
|
3016
|
-
} else {
|
3017
|
-
throw new Error(
|
3018
|
-
`Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
|
3019
|
-
actions2
|
3020
|
-
)}`
|
3021
|
-
);
|
3022
|
-
}
|
3023
|
-
}
|
3024
|
-
addDocumentHeaderAction(actions2) {
|
3025
|
-
if (Array.isArray(actions2)) {
|
3026
|
-
this.headerActions = [...this.headerActions, ...actions2];
|
3027
|
-
} else if (typeof actions2 === "function") {
|
3028
|
-
this.headerActions = actions2(this.headerActions);
|
3029
|
-
} else {
|
3030
|
-
throw new Error(
|
3031
|
-
`Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
|
3032
|
-
actions2
|
3033
|
-
)}`
|
3034
|
-
);
|
3035
|
-
}
|
3036
|
-
}
|
3037
|
-
addBulkAction(actions2) {
|
3038
|
-
if (Array.isArray(actions2)) {
|
3039
|
-
this.bulkActions = [...this.bulkActions, ...actions2];
|
3040
|
-
} else if (typeof actions2 === "function") {
|
3041
|
-
this.bulkActions = actions2(this.bulkActions);
|
3042
|
-
} else {
|
3043
|
-
throw new Error(
|
3044
|
-
`Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
|
3045
|
-
actions2
|
3046
|
-
)}`
|
3047
|
-
);
|
3048
|
-
}
|
3049
|
-
}
|
3050
|
-
get config() {
|
3051
|
-
return {
|
3052
|
-
id: PLUGIN_ID,
|
3053
|
-
name: "Content Manager",
|
3054
|
-
injectionZones: INJECTION_ZONES,
|
3055
|
-
apis: {
|
3056
|
-
addBulkAction: this.addBulkAction.bind(this),
|
3057
|
-
addDocumentAction: this.addDocumentAction.bind(this),
|
3058
|
-
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3059
|
-
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3060
|
-
getBulkActions: () => this.bulkActions,
|
3061
|
-
getDocumentActions: () => this.documentActions,
|
3062
|
-
getEditViewSidePanels: () => this.editViewSidePanels,
|
3063
|
-
getHeaderActions: () => this.headerActions
|
3064
|
-
}
|
3065
|
-
};
|
3066
|
-
}
|
3067
|
-
}
|
3068
|
-
const getPrintableType = (value) => {
|
3069
|
-
const nativeType = typeof value;
|
3070
|
-
if (nativeType === "object") {
|
3071
|
-
if (value === null)
|
3072
|
-
return "null";
|
3073
|
-
if (Array.isArray(value))
|
3074
|
-
return "array";
|
3075
|
-
if (value instanceof Object && value.constructor.name !== "Object") {
|
3076
|
-
return value.constructor.name;
|
3077
|
-
}
|
3078
|
-
}
|
3079
|
-
return nativeType;
|
3080
|
-
};
|
3081
|
-
const initialState = {
|
3082
|
-
collectionTypeLinks: [],
|
3083
|
-
components: [],
|
3084
|
-
fieldSizes: {},
|
3085
|
-
models: [],
|
3086
|
-
singleTypeLinks: [],
|
3087
|
-
isLoading: true
|
3088
|
-
};
|
3089
|
-
const appSlice = toolkit.createSlice({
|
3090
|
-
name: "app",
|
3091
|
-
initialState,
|
3092
|
-
reducers: {
|
3093
|
-
setInitialData(state, action) {
|
3094
|
-
const {
|
3095
|
-
authorizedCollectionTypeLinks,
|
3096
|
-
authorizedSingleTypeLinks,
|
3097
|
-
components,
|
3098
|
-
contentTypeSchemas,
|
3099
|
-
fieldSizes
|
3100
|
-
} = action.payload;
|
3101
|
-
state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
|
3102
|
-
({ isDisplayed }) => isDisplayed
|
3103
|
-
);
|
3104
|
-
state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
|
3105
|
-
state.components = components;
|
3106
|
-
state.models = contentTypeSchemas;
|
3107
|
-
state.fieldSizes = fieldSizes;
|
3108
|
-
state.isLoading = false;
|
3109
|
-
}
|
3110
|
-
}
|
3111
|
-
});
|
3112
|
-
const { actions, reducer: reducer$1 } = appSlice;
|
3113
|
-
const { setInitialData } = actions;
|
3114
|
-
const reducer = toolkit.combineReducers({
|
3115
|
-
app: reducer$1
|
3116
|
-
});
|
3117
|
-
const HOOKS = {
|
3118
|
-
/**
|
3119
|
-
* Hook that allows to mutate the displayed headers of the list view table
|
3120
|
-
* @constant
|
3121
|
-
* @type {string}
|
3122
|
-
*/
|
3123
|
-
INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
|
3124
|
-
/**
|
3125
|
-
* Hook that allows to mutate the CM's collection types links pre-set filters
|
3126
|
-
* @constant
|
3127
|
-
* @type {string}
|
3128
|
-
*/
|
3129
|
-
MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
|
3130
|
-
/**
|
3131
|
-
* Hook that allows to mutate the CM's edit view layout
|
3132
|
-
* @constant
|
3133
|
-
* @type {string}
|
3134
|
-
*/
|
3135
|
-
MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
|
3136
|
-
/**
|
3137
|
-
* Hook that allows to mutate the CM's single types links pre-set filters
|
3138
|
-
* @constant
|
3139
|
-
* @type {string}
|
3140
|
-
*/
|
3141
|
-
MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
|
3142
|
-
};
|
3143
|
-
const contentTypesApi = contentManagerApi.injectEndpoints({
|
3144
|
-
endpoints: (builder) => ({
|
3145
|
-
getContentTypeConfiguration: builder.query({
|
3146
|
-
query: (uid) => ({
|
3147
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
3148
|
-
method: "GET"
|
3149
|
-
}),
|
3150
|
-
transformResponse: (response) => response.data,
|
3151
|
-
providesTags: (_result, _error, uid) => [
|
3152
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
3153
|
-
{ type: "ContentTypeSettings", id: "LIST" }
|
3154
|
-
]
|
3155
|
-
}),
|
3156
|
-
getAllContentTypeSettings: builder.query({
|
3157
|
-
query: () => "/content-manager/content-types-settings",
|
3158
|
-
transformResponse: (response) => response.data,
|
3159
|
-
providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
|
3160
|
-
}),
|
3161
|
-
updateContentTypeConfiguration: builder.mutation({
|
3162
|
-
query: ({ uid, ...body }) => ({
|
3163
|
-
url: `/content-manager/content-types/${uid}/configuration`,
|
3164
|
-
method: "PUT",
|
3165
|
-
data: body
|
3166
|
-
}),
|
3167
|
-
transformResponse: (response) => response.data,
|
3168
|
-
invalidatesTags: (_result, _error, { uid }) => [
|
3169
|
-
{ type: "ContentTypesConfiguration", id: uid },
|
3170
|
-
{ type: "ContentTypeSettings", id: "LIST" },
|
3171
|
-
// Is this necessary?
|
3172
|
-
{ type: "InitialData" }
|
3173
|
-
]
|
3174
|
-
})
|
3175
|
-
})
|
3176
|
-
});
|
3177
|
-
const {
|
3178
|
-
useGetContentTypeConfigurationQuery,
|
3179
|
-
useGetAllContentTypeSettingsQuery,
|
3180
|
-
useUpdateContentTypeConfigurationMutation
|
3181
|
-
} = contentTypesApi;
|
3182
|
-
const checkIfAttributeIsDisplayable = (attribute) => {
|
3183
|
-
const { type } = attribute;
|
3184
|
-
if (type === "relation") {
|
3185
|
-
return !attribute.relation.toLowerCase().includes("morph");
|
3186
|
-
}
|
3187
|
-
return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
|
3188
|
-
};
|
3189
|
-
const getMainField = (attribute, mainFieldName, { schemas, components }) => {
|
3190
|
-
if (!mainFieldName) {
|
3191
|
-
return void 0;
|
3192
|
-
}
|
3193
|
-
const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
|
3194
|
-
// @ts-expect-error – `targetModel` does exist on the attribute for a relation.
|
3195
|
-
schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
|
3196
|
-
);
|
3197
|
-
return {
|
3198
|
-
name: mainFieldName,
|
3199
|
-
type: mainFieldType ?? "string"
|
3552
|
+
activeTab: null,
|
3553
|
+
model,
|
3554
|
+
documentId: document.documentId,
|
3555
|
+
collectionType,
|
3556
|
+
document
|
3200
3557
|
};
|
3558
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
3559
|
+
strapiAdmin.DescriptionComponentRenderer,
|
3560
|
+
{
|
3561
|
+
props,
|
3562
|
+
descriptions: plugins["content-manager"].apis.getDocumentActions(),
|
3563
|
+
children: (actions2) => {
|
3564
|
+
const tableRowActions = actions2.filter((action) => {
|
3565
|
+
const positions = Array.isArray(action.position) ? action.position : [action.position];
|
3566
|
+
return positions.includes("table-row");
|
3567
|
+
});
|
3568
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
3569
|
+
DocumentActionsMenu,
|
3570
|
+
{
|
3571
|
+
actions: tableRowActions,
|
3572
|
+
label: formatMessage({
|
3573
|
+
id: "content-manager.containers.list.table.row-actions",
|
3574
|
+
defaultMessage: "Row action"
|
3575
|
+
}),
|
3576
|
+
variant: "ghost"
|
3577
|
+
}
|
3578
|
+
);
|
3579
|
+
}
|
3580
|
+
}
|
3581
|
+
);
|
3201
3582
|
};
|
3202
|
-
const
|
3203
|
-
|
3204
|
-
|
3205
|
-
|
3206
|
-
pagination: false,
|
3207
|
-
defaultSortBy: "",
|
3208
|
-
defaultSortOrder: "asc",
|
3209
|
-
mainField: "id",
|
3210
|
-
pageSize: 10
|
3211
|
-
};
|
3212
|
-
const useDocumentLayout = (model) => {
|
3213
|
-
const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
|
3214
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
3215
|
-
const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
|
3583
|
+
const EditAction = ({ documentId }) => {
|
3584
|
+
const navigate = reactRouterDom.useNavigate();
|
3585
|
+
const { formatMessage } = reactIntl.useIntl();
|
3586
|
+
const { canRead } = useDocumentRBAC("EditAction", ({ canRead: canRead2 }) => ({ canRead: canRead2 }));
|
3216
3587
|
const { toggleNotification } = strapiAdmin.useNotification();
|
3217
|
-
const {
|
3218
|
-
|
3219
|
-
|
3220
|
-
|
3221
|
-
|
3222
|
-
|
3223
|
-
|
3224
|
-
|
3225
|
-
|
3226
|
-
|
3227
|
-
|
3228
|
-
|
3229
|
-
|
3230
|
-
|
3588
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3589
|
+
return {
|
3590
|
+
disabled: !canRead,
|
3591
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledPencil, {}),
|
3592
|
+
label: formatMessage({
|
3593
|
+
id: "content-manager.actions.edit.label",
|
3594
|
+
defaultMessage: "Edit"
|
3595
|
+
}),
|
3596
|
+
position: "table-row",
|
3597
|
+
onClick: async () => {
|
3598
|
+
if (!documentId) {
|
3599
|
+
console.error(
|
3600
|
+
"You're trying to edit a document without an id, this is likely a bug with Strapi. Please open an issue."
|
3601
|
+
);
|
3602
|
+
toggleNotification({
|
3603
|
+
message: formatMessage({
|
3604
|
+
id: "content-manager.actions.edit.error",
|
3605
|
+
defaultMessage: "An error occurred while trying to edit the document."
|
3606
|
+
}),
|
3607
|
+
type: "danger"
|
3608
|
+
});
|
3609
|
+
return;
|
3610
|
+
}
|
3611
|
+
navigate({
|
3612
|
+
pathname: documentId,
|
3613
|
+
search: qs.stringify({
|
3614
|
+
plugins: query.plugins
|
3615
|
+
})
|
3231
3616
|
});
|
3232
3617
|
}
|
3233
|
-
}, [error, formatAPIError, toggleNotification]);
|
3234
|
-
const editLayout = React__namespace.useMemo(
|
3235
|
-
() => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
|
3236
|
-
layout: [],
|
3237
|
-
components: {},
|
3238
|
-
metadatas: {},
|
3239
|
-
options: {},
|
3240
|
-
settings: DEFAULT_SETTINGS
|
3241
|
-
},
|
3242
|
-
[data, isLoading, schemas, schema, components]
|
3243
|
-
);
|
3244
|
-
const listLayout = React__namespace.useMemo(() => {
|
3245
|
-
return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
|
3246
|
-
layout: [],
|
3247
|
-
metadatas: {},
|
3248
|
-
options: {},
|
3249
|
-
settings: DEFAULT_SETTINGS
|
3250
|
-
};
|
3251
|
-
}, [data, isLoading, schemas, schema, components]);
|
3252
|
-
const { layout: edit } = React__namespace.useMemo(
|
3253
|
-
() => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
|
3254
|
-
layout: editLayout,
|
3255
|
-
query
|
3256
|
-
}),
|
3257
|
-
[editLayout, query, runHookWaterfall]
|
3258
|
-
);
|
3259
|
-
return {
|
3260
|
-
error,
|
3261
|
-
isLoading,
|
3262
|
-
edit,
|
3263
|
-
list: listLayout
|
3264
3618
|
};
|
3265
3619
|
};
|
3266
|
-
|
3267
|
-
|
3268
|
-
|
3269
|
-
|
3270
|
-
|
3271
|
-
|
3272
|
-
|
3273
|
-
|
3274
|
-
}
|
3275
|
-
|
3276
|
-
const
|
3277
|
-
|
3278
|
-
|
3279
|
-
data.contentType.metadatas,
|
3280
|
-
{ configurations: data.components, schemas: components },
|
3281
|
-
schemas
|
3282
|
-
).reduce((panels, row) => {
|
3283
|
-
if (row.some((field) => field.type === "dynamiczone")) {
|
3284
|
-
panels.push([row]);
|
3285
|
-
currentPanelIndex += 2;
|
3286
|
-
} else {
|
3287
|
-
if (!panels[currentPanelIndex]) {
|
3288
|
-
panels.push([]);
|
3289
|
-
}
|
3290
|
-
panels[currentPanelIndex].push(row);
|
3291
|
-
}
|
3292
|
-
return panels;
|
3293
|
-
}, []);
|
3294
|
-
const componentEditAttributes = Object.entries(data.components).reduce(
|
3295
|
-
(acc, [uid, configuration]) => {
|
3296
|
-
acc[uid] = {
|
3297
|
-
layout: convertEditLayoutToFieldLayouts(
|
3298
|
-
configuration.layouts.edit,
|
3299
|
-
components[uid].attributes,
|
3300
|
-
configuration.metadatas
|
3301
|
-
),
|
3302
|
-
settings: {
|
3303
|
-
...configuration.settings,
|
3304
|
-
icon: components[uid].info.icon,
|
3305
|
-
displayName: components[uid].info.displayName
|
3306
|
-
}
|
3307
|
-
};
|
3308
|
-
return acc;
|
3309
|
-
},
|
3310
|
-
{}
|
3311
|
-
);
|
3312
|
-
const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
|
3313
|
-
(acc, [attribute, metadata]) => {
|
3314
|
-
return {
|
3315
|
-
...acc,
|
3316
|
-
[attribute]: metadata.edit
|
3317
|
-
};
|
3318
|
-
},
|
3319
|
-
{}
|
3320
|
-
);
|
3620
|
+
EditAction.type = "edit";
|
3621
|
+
const StyledPencil = styledComponents.styled(Icons.Pencil)`
|
3622
|
+
path {
|
3623
|
+
fill: currentColor;
|
3624
|
+
}
|
3625
|
+
`;
|
3626
|
+
const CloneAction = ({ model, documentId }) => {
|
3627
|
+
const navigate = reactRouterDom.useNavigate();
|
3628
|
+
const { formatMessage } = reactIntl.useIntl();
|
3629
|
+
const { canCreate } = useDocumentRBAC("CloneAction", ({ canCreate: canCreate2 }) => ({ canCreate: canCreate2 }));
|
3630
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
3631
|
+
const { autoClone } = useDocumentActions();
|
3632
|
+
const [prohibitedFields, setProhibitedFields] = React__namespace.useState([]);
|
3321
3633
|
return {
|
3322
|
-
|
3323
|
-
|
3324
|
-
|
3325
|
-
|
3326
|
-
|
3327
|
-
|
3634
|
+
disabled: !canCreate,
|
3635
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(StyledDuplicate, {}),
|
3636
|
+
label: formatMessage({
|
3637
|
+
id: "content-manager.actions.clone.label",
|
3638
|
+
defaultMessage: "Duplicate"
|
3639
|
+
}),
|
3640
|
+
position: "table-row",
|
3641
|
+
onClick: async () => {
|
3642
|
+
if (!documentId) {
|
3643
|
+
console.error(
|
3644
|
+
"You're trying to clone a document in the table without an id, this is likely a bug with Strapi. Please open an issue."
|
3645
|
+
);
|
3646
|
+
toggleNotification({
|
3647
|
+
message: formatMessage({
|
3648
|
+
id: "content-manager.actions.clone.error",
|
3649
|
+
defaultMessage: "An error occurred while trying to clone the document."
|
3650
|
+
}),
|
3651
|
+
type: "danger"
|
3652
|
+
});
|
3653
|
+
return;
|
3654
|
+
}
|
3655
|
+
const res = await autoClone({ model, sourceId: documentId });
|
3656
|
+
if ("data" in res) {
|
3657
|
+
navigate(res.data.documentId);
|
3658
|
+
return true;
|
3659
|
+
}
|
3660
|
+
if (isBaseQueryError(res.error) && res.error.details && typeof res.error.details === "object" && "prohibitedFields" in res.error.details && Array.isArray(res.error.details.prohibitedFields)) {
|
3661
|
+
const prohibitedFields2 = res.error.details.prohibitedFields;
|
3662
|
+
setProhibitedFields(prohibitedFields2);
|
3663
|
+
}
|
3328
3664
|
},
|
3329
|
-
|
3330
|
-
|
3331
|
-
|
3332
|
-
|
3665
|
+
dialog: {
|
3666
|
+
type: "modal",
|
3667
|
+
title: formatMessage({
|
3668
|
+
id: "content-manager.containers.list.autoCloneModal.header",
|
3669
|
+
defaultMessage: "Duplicate"
|
3670
|
+
}),
|
3671
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(AutoCloneFailureModalBody, { prohibitedFields }),
|
3672
|
+
footer: ({ onClose }) => {
|
3673
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", children: [
|
3674
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: onClose, variant: "tertiary", children: formatMessage({
|
3675
|
+
id: "cancel",
|
3676
|
+
defaultMessage: "Cancel"
|
3677
|
+
}) }),
|
3678
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
3679
|
+
designSystem.LinkButton,
|
3680
|
+
{
|
3681
|
+
tag: reactRouterDom.NavLink,
|
3682
|
+
to: {
|
3683
|
+
pathname: `clone/${documentId}`
|
3684
|
+
},
|
3685
|
+
children: formatMessage({
|
3686
|
+
id: "content-manager.containers.list.autoCloneModal.create",
|
3687
|
+
defaultMessage: "Create"
|
3688
|
+
})
|
3689
|
+
}
|
3690
|
+
)
|
3691
|
+
] });
|
3692
|
+
}
|
3333
3693
|
}
|
3334
3694
|
};
|
3335
3695
|
};
|
3336
|
-
|
3337
|
-
|
3338
|
-
|
3339
|
-
|
3340
|
-
|
3341
|
-
|
3696
|
+
CloneAction.type = "clone";
|
3697
|
+
const StyledDuplicate = styledComponents.styled(Icons.Duplicate)`
|
3698
|
+
path {
|
3699
|
+
fill: currentColor;
|
3700
|
+
}
|
3701
|
+
`;
|
3702
|
+
const DEFAULT_TABLE_ROW_ACTIONS = [EditAction, CloneAction];
|
3703
|
+
class ContentManagerPlugin {
|
3704
|
+
/**
|
3705
|
+
* The following properties are the stored ones provided by any plugins registering with
|
3706
|
+
* the content-manager. The function calls however, need to be called at runtime in the
|
3707
|
+
* application, so instead we collate them and run them later with the complete list incl.
|
3708
|
+
* ones already registered & the context of the view.
|
3709
|
+
*/
|
3710
|
+
bulkActions = [...DEFAULT_BULK_ACTIONS];
|
3711
|
+
documentActions = [
|
3712
|
+
...DEFAULT_ACTIONS,
|
3713
|
+
...DEFAULT_TABLE_ROW_ACTIONS,
|
3714
|
+
...DEFAULT_HEADER_ACTIONS
|
3715
|
+
];
|
3716
|
+
editViewSidePanels = [ActionsPanel];
|
3717
|
+
headerActions = [];
|
3718
|
+
constructor() {
|
3719
|
+
}
|
3720
|
+
addEditViewSidePanel(panels) {
|
3721
|
+
if (Array.isArray(panels)) {
|
3722
|
+
this.editViewSidePanels = [...this.editViewSidePanels, ...panels];
|
3723
|
+
} else if (typeof panels === "function") {
|
3724
|
+
this.editViewSidePanels = panels(this.editViewSidePanels);
|
3725
|
+
} else {
|
3726
|
+
throw new Error(
|
3727
|
+
`Expected the \`panels\` passed to \`addEditViewSidePanel\` to be an array or a function, but received ${getPrintableType(
|
3728
|
+
panels
|
3729
|
+
)}`
|
3730
|
+
);
|
3731
|
+
}
|
3732
|
+
}
|
3733
|
+
addDocumentAction(actions2) {
|
3734
|
+
if (Array.isArray(actions2)) {
|
3735
|
+
this.documentActions = [...this.documentActions, ...actions2];
|
3736
|
+
} else if (typeof actions2 === "function") {
|
3737
|
+
this.documentActions = actions2(this.documentActions);
|
3738
|
+
} else {
|
3739
|
+
throw new Error(
|
3740
|
+
`Expected the \`actions\` passed to \`addDocumentAction\` to be an array or a function, but received ${getPrintableType(
|
3741
|
+
actions2
|
3742
|
+
)}`
|
3743
|
+
);
|
3744
|
+
}
|
3745
|
+
}
|
3746
|
+
addDocumentHeaderAction(actions2) {
|
3747
|
+
if (Array.isArray(actions2)) {
|
3748
|
+
this.headerActions = [...this.headerActions, ...actions2];
|
3749
|
+
} else if (typeof actions2 === "function") {
|
3750
|
+
this.headerActions = actions2(this.headerActions);
|
3751
|
+
} else {
|
3752
|
+
throw new Error(
|
3753
|
+
`Expected the \`actions\` passed to \`addDocumentHeaderAction\` to be an array or a function, but received ${getPrintableType(
|
3754
|
+
actions2
|
3755
|
+
)}`
|
3756
|
+
);
|
3757
|
+
}
|
3758
|
+
}
|
3759
|
+
addBulkAction(actions2) {
|
3760
|
+
if (Array.isArray(actions2)) {
|
3761
|
+
this.bulkActions = [...this.bulkActions, ...actions2];
|
3762
|
+
} else if (typeof actions2 === "function") {
|
3763
|
+
this.bulkActions = actions2(this.bulkActions);
|
3764
|
+
} else {
|
3765
|
+
throw new Error(
|
3766
|
+
`Expected the \`actions\` passed to \`addBulkAction\` to be an array or a function, but received ${getPrintableType(
|
3767
|
+
actions2
|
3768
|
+
)}`
|
3769
|
+
);
|
3770
|
+
}
|
3771
|
+
}
|
3772
|
+
get config() {
|
3773
|
+
return {
|
3774
|
+
id: PLUGIN_ID,
|
3775
|
+
name: "Content Manager",
|
3776
|
+
injectionZones: INJECTION_ZONES,
|
3777
|
+
apis: {
|
3778
|
+
addBulkAction: this.addBulkAction.bind(this),
|
3779
|
+
addDocumentAction: this.addDocumentAction.bind(this),
|
3780
|
+
addDocumentHeaderAction: this.addDocumentHeaderAction.bind(this),
|
3781
|
+
addEditViewSidePanel: this.addEditViewSidePanel.bind(this),
|
3782
|
+
getBulkActions: () => this.bulkActions,
|
3783
|
+
getDocumentActions: () => this.documentActions,
|
3784
|
+
getEditViewSidePanels: () => this.editViewSidePanels,
|
3785
|
+
getHeaderActions: () => this.headerActions
|
3342
3786
|
}
|
3343
|
-
|
3344
|
-
|
3345
|
-
|
3346
|
-
|
3347
|
-
|
3348
|
-
|
3349
|
-
|
3350
|
-
|
3351
|
-
|
3352
|
-
|
3353
|
-
|
3354
|
-
|
3355
|
-
|
3356
|
-
|
3357
|
-
|
3358
|
-
size: field.size,
|
3359
|
-
unique: "unique" in attribute ? attribute.unique : false,
|
3360
|
-
visible: metadata.visible ?? true,
|
3361
|
-
type: attribute.type
|
3362
|
-
};
|
3363
|
-
}).filter((field) => field !== null)
|
3364
|
-
);
|
3787
|
+
};
|
3788
|
+
}
|
3789
|
+
}
|
3790
|
+
const getPrintableType = (value) => {
|
3791
|
+
const nativeType = typeof value;
|
3792
|
+
if (nativeType === "object") {
|
3793
|
+
if (value === null)
|
3794
|
+
return "null";
|
3795
|
+
if (Array.isArray(value))
|
3796
|
+
return "array";
|
3797
|
+
if (value instanceof Object && value.constructor.name !== "Object") {
|
3798
|
+
return value.constructor.name;
|
3799
|
+
}
|
3800
|
+
}
|
3801
|
+
return nativeType;
|
3365
3802
|
};
|
3366
|
-
const
|
3367
|
-
|
3368
|
-
|
3369
|
-
|
3370
|
-
}
|
3371
|
-
|
3372
|
-
|
3373
|
-
|
3374
|
-
...acc,
|
3375
|
-
[attribute]: metadata.list
|
3376
|
-
};
|
3377
|
-
},
|
3378
|
-
{}
|
3379
|
-
);
|
3380
|
-
const listAttributes = convertListLayoutToFieldLayouts(
|
3381
|
-
data.contentType.layouts.list,
|
3382
|
-
schema?.attributes,
|
3383
|
-
listMetadatas,
|
3384
|
-
{ configurations: data.components, schemas: components },
|
3385
|
-
schemas
|
3386
|
-
);
|
3803
|
+
const HistoryAction = ({ model, document }) => {
|
3804
|
+
const { formatMessage } = reactIntl.useIntl();
|
3805
|
+
const [{ query }] = strapiAdmin.useQueryParams();
|
3806
|
+
const navigate = reactRouterDom.useNavigate();
|
3807
|
+
const pluginsQueryParams = qs.stringify({ plugins: query.plugins }, { encode: false });
|
3808
|
+
if (!window.strapi.features.isEnabled("cms-content-history")) {
|
3809
|
+
return null;
|
3810
|
+
}
|
3387
3811
|
return {
|
3388
|
-
|
3389
|
-
|
3390
|
-
|
3391
|
-
|
3392
|
-
|
3393
|
-
|
3394
|
-
|
3395
|
-
|
3812
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.ClockCounterClockwise, {}),
|
3813
|
+
label: formatMessage({
|
3814
|
+
id: "content-manager.history.document-action",
|
3815
|
+
defaultMessage: "Content History"
|
3816
|
+
}),
|
3817
|
+
onClick: () => navigate({ pathname: "history", search: pluginsQueryParams }),
|
3818
|
+
disabled: (
|
3819
|
+
/**
|
3820
|
+
* The user is creating a new document.
|
3821
|
+
* It hasn't been saved yet, so there's no history to go to
|
3822
|
+
*/
|
3823
|
+
!document || /**
|
3824
|
+
* The document has been created but the current dimension has never been saved.
|
3825
|
+
* For example, the user is creating a new locale in an existing document,
|
3826
|
+
* so there's no history for the document in that locale
|
3827
|
+
*/
|
3828
|
+
!document.id || /**
|
3829
|
+
* History is only available for content types created by the user.
|
3830
|
+
* These have the `api::` prefix, as opposed to the ones created by Strapi or plugins,
|
3831
|
+
* which start with `admin::` or `plugin::`
|
3832
|
+
*/
|
3833
|
+
!model.startsWith("api::")
|
3834
|
+
),
|
3835
|
+
position: "header"
|
3396
3836
|
};
|
3397
3837
|
};
|
3398
|
-
|
3399
|
-
|
3400
|
-
|
3401
|
-
|
3402
|
-
|
3403
|
-
|
3404
|
-
|
3405
|
-
|
3406
|
-
|
3407
|
-
|
3408
|
-
|
3409
|
-
|
3410
|
-
|
3411
|
-
|
3412
|
-
|
3413
|
-
|
3414
|
-
|
3415
|
-
|
3416
|
-
};
|
3417
|
-
}).filter((field) => field !== null);
|
3838
|
+
HistoryAction.type = "history";
|
3839
|
+
const historyAdmin = {
|
3840
|
+
bootstrap(app) {
|
3841
|
+
const { addDocumentAction } = app.getPlugin("content-manager").apis;
|
3842
|
+
addDocumentAction((actions2) => {
|
3843
|
+
const indexOfDeleteAction = actions2.findIndex((action) => action.type === "delete");
|
3844
|
+
actions2.splice(indexOfDeleteAction, 0, HistoryAction);
|
3845
|
+
return actions2;
|
3846
|
+
});
|
3847
|
+
}
|
3848
|
+
};
|
3849
|
+
const initialState = {
|
3850
|
+
collectionTypeLinks: [],
|
3851
|
+
components: [],
|
3852
|
+
fieldSizes: {},
|
3853
|
+
models: [],
|
3854
|
+
singleTypeLinks: [],
|
3855
|
+
isLoading: true
|
3418
3856
|
};
|
3857
|
+
const appSlice = toolkit.createSlice({
|
3858
|
+
name: "app",
|
3859
|
+
initialState,
|
3860
|
+
reducers: {
|
3861
|
+
setInitialData(state, action) {
|
3862
|
+
const {
|
3863
|
+
authorizedCollectionTypeLinks,
|
3864
|
+
authorizedSingleTypeLinks,
|
3865
|
+
components,
|
3866
|
+
contentTypeSchemas,
|
3867
|
+
fieldSizes
|
3868
|
+
} = action.payload;
|
3869
|
+
state.collectionTypeLinks = authorizedCollectionTypeLinks.filter(
|
3870
|
+
({ isDisplayed }) => isDisplayed
|
3871
|
+
);
|
3872
|
+
state.singleTypeLinks = authorizedSingleTypeLinks.filter(({ isDisplayed }) => isDisplayed);
|
3873
|
+
state.components = components;
|
3874
|
+
state.models = contentTypeSchemas;
|
3875
|
+
state.fieldSizes = fieldSizes;
|
3876
|
+
state.isLoading = false;
|
3877
|
+
}
|
3878
|
+
}
|
3879
|
+
});
|
3880
|
+
const { actions, reducer: reducer$1 } = appSlice;
|
3881
|
+
const { setInitialData } = actions;
|
3882
|
+
const reducer = toolkit.combineReducers({
|
3883
|
+
app: reducer$1
|
3884
|
+
});
|
3419
3885
|
const index = {
|
3420
3886
|
register(app) {
|
3421
3887
|
const cm = new ContentManagerPlugin();
|
@@ -3430,15 +3896,29 @@ const index = {
|
|
3430
3896
|
defaultMessage: "Content Manager"
|
3431
3897
|
},
|
3432
3898
|
permissions: [],
|
3433
|
-
Component: () => Promise.resolve().then(() => require("./layout-ni_L9kT1.js")).then((mod) => ({ default: mod.Layout })),
|
3434
3899
|
position: 1
|
3435
3900
|
});
|
3901
|
+
app.router.addRoute({
|
3902
|
+
path: "content-manager/*",
|
3903
|
+
lazy: async () => {
|
3904
|
+
const { Layout } = await Promise.resolve().then(() => require("./layout-C6dxWYT7.js"));
|
3905
|
+
return {
|
3906
|
+
Component: Layout
|
3907
|
+
};
|
3908
|
+
},
|
3909
|
+
children: routes
|
3910
|
+
});
|
3436
3911
|
app.registerPlugin(cm.config);
|
3437
3912
|
},
|
3913
|
+
bootstrap(app) {
|
3914
|
+
if (typeof historyAdmin.bootstrap === "function") {
|
3915
|
+
historyAdmin.bootstrap(app);
|
3916
|
+
}
|
3917
|
+
},
|
3438
3918
|
async registerTrads({ locales }) {
|
3439
3919
|
const importedTrads = await Promise.all(
|
3440
3920
|
locales.map((locale) => {
|
3441
|
-
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-
|
3921
|
+
return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-uOUIxfcQ.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
|
3442
3922
|
return {
|
3443
3923
|
data: prefixPluginTranslations(data, PLUGIN_ID),
|
3444
3924
|
locale
|
@@ -3482,7 +3962,6 @@ exports.getDisplayName = getDisplayName;
|
|
3482
3962
|
exports.getMainField = getMainField;
|
3483
3963
|
exports.getTranslation = getTranslation;
|
3484
3964
|
exports.index = index;
|
3485
|
-
exports.routes = routes;
|
3486
3965
|
exports.setInitialData = setInitialData;
|
3487
3966
|
exports.useContentTypeSchema = useContentTypeSchema;
|
3488
3967
|
exports.useDoc = useDoc;
|
@@ -3496,4 +3975,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
|
|
3496
3975
|
exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
|
3497
3976
|
exports.useGetInitialDataQuery = useGetInitialDataQuery;
|
3498
3977
|
exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
|
3499
|
-
//# sourceMappingURL=index-
|
3978
|
+
//# sourceMappingURL=index-CdT0kHZ8.js.map
|