@strapi/content-manager 5.0.0-rc.16 → 5.0.0-rc.18

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.
Files changed (69) hide show
  1. package/dist/_chunks/{ComponentConfigurationPage-CnL10QYC.mjs → ComponentConfigurationPage-DJ5voqEK.mjs} +3 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-CnL10QYC.mjs.map → ComponentConfigurationPage-DJ5voqEK.mjs.map} +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-G4EIirP8.js → ComponentConfigurationPage-_6osrv39.js} +3 -3
  4. package/dist/_chunks/{ComponentConfigurationPage-G4EIirP8.js.map → ComponentConfigurationPage-_6osrv39.js.map} +1 -1
  5. package/dist/_chunks/{EditConfigurationPage-I2kKh9dx.mjs → EditConfigurationPage-CZofxSLy.mjs} +3 -3
  6. package/dist/_chunks/{EditConfigurationPage-I2kKh9dx.mjs.map → EditConfigurationPage-CZofxSLy.mjs.map} +1 -1
  7. package/dist/_chunks/{EditConfigurationPage-B2AA1kVF.js → EditConfigurationPage-ZN3s568V.js} +3 -3
  8. package/dist/_chunks/{EditConfigurationPage-B2AA1kVF.js.map → EditConfigurationPage-ZN3s568V.js.map} +1 -1
  9. package/dist/_chunks/{EditViewPage-CHgoNwlc.js → EditViewPage-Co2IKQZH.js} +3 -3
  10. package/dist/_chunks/{EditViewPage-CHgoNwlc.js.map → EditViewPage-Co2IKQZH.js.map} +1 -1
  11. package/dist/_chunks/{EditViewPage-zFjJK0s8.mjs → EditViewPage-HYljoEY7.mjs} +3 -3
  12. package/dist/_chunks/{EditViewPage-zFjJK0s8.mjs.map → EditViewPage-HYljoEY7.mjs.map} +1 -1
  13. package/dist/_chunks/{Field-DPAzUS1M.mjs → Field-BOPUMZ1u.mjs} +3 -3
  14. package/dist/_chunks/{Field-DPAzUS1M.mjs.map → Field-BOPUMZ1u.mjs.map} +1 -1
  15. package/dist/_chunks/{Field-9DePZh-0.js → Field-G9CkFUtP.js} +3 -3
  16. package/dist/_chunks/{Field-9DePZh-0.js.map → Field-G9CkFUtP.js.map} +1 -1
  17. package/dist/_chunks/{Form-CEkENbkF.mjs → Form-CDwNp7pU.mjs} +2 -2
  18. package/dist/_chunks/{Form-CEkENbkF.mjs.map → Form-CDwNp7pU.mjs.map} +1 -1
  19. package/dist/_chunks/{Form-DPm-KZ1A.js → Form-crsbkGxI.js} +2 -2
  20. package/dist/_chunks/{Form-DPm-KZ1A.js.map → Form-crsbkGxI.js.map} +1 -1
  21. package/dist/_chunks/{History-utls71em.mjs → History-BDZrgfZ3.mjs} +4 -4
  22. package/dist/_chunks/{History-utls71em.mjs.map → History-BDZrgfZ3.mjs.map} +1 -1
  23. package/dist/_chunks/{History-DXSbTWez.js → History-CWcM9HnW.js} +4 -4
  24. package/dist/_chunks/{History-DXSbTWez.js.map → History-CWcM9HnW.js.map} +1 -1
  25. package/dist/_chunks/{ListConfigurationPage-CuMXWWqb.mjs → ListConfigurationPage-BZ3ScUna.mjs} +2 -2
  26. package/dist/_chunks/{ListConfigurationPage-CuMXWWqb.mjs.map → ListConfigurationPage-BZ3ScUna.mjs.map} +1 -1
  27. package/dist/_chunks/{ListConfigurationPage-D5C7ACZ_.js → ListConfigurationPage-DGzoQD_I.js} +2 -2
  28. package/dist/_chunks/{ListConfigurationPage-D5C7ACZ_.js.map → ListConfigurationPage-DGzoQD_I.js.map} +1 -1
  29. package/dist/_chunks/{ListViewPage-DfuwH1tt.js → ListViewPage-BBAC9aPu.js} +3 -3
  30. package/dist/_chunks/{ListViewPage-DfuwH1tt.js.map → ListViewPage-BBAC9aPu.js.map} +1 -1
  31. package/dist/_chunks/{ListViewPage-CdKd-PS_.mjs → ListViewPage-CsX7tWx-.mjs} +3 -3
  32. package/dist/_chunks/{ListViewPage-CdKd-PS_.mjs.map → ListViewPage-CsX7tWx-.mjs.map} +1 -1
  33. package/dist/_chunks/{NoContentTypePage-BIxlkWWi.js → NoContentTypePage-CwVDx_YC.js} +2 -2
  34. package/dist/_chunks/{NoContentTypePage-BIxlkWWi.js.map → NoContentTypePage-CwVDx_YC.js.map} +1 -1
  35. package/dist/_chunks/{NoContentTypePage-DkToTT7u.mjs → NoContentTypePage-LClTUPWs.mjs} +2 -2
  36. package/dist/_chunks/{NoContentTypePage-DkToTT7u.mjs.map → NoContentTypePage-LClTUPWs.mjs.map} +1 -1
  37. package/dist/_chunks/{NoPermissionsPage-Bu4GWYb-.js → NoPermissionsPage-D2iWw-sn.js} +2 -2
  38. package/dist/_chunks/{NoPermissionsPage-Bu4GWYb-.js.map → NoPermissionsPage-D2iWw-sn.js.map} +1 -1
  39. package/dist/_chunks/{NoPermissionsPage-DlWi4BAH.mjs → NoPermissionsPage-S4Re3FwO.mjs} +2 -2
  40. package/dist/_chunks/{NoPermissionsPage-DlWi4BAH.mjs.map → NoPermissionsPage-S4Re3FwO.mjs.map} +1 -1
  41. package/dist/_chunks/{Relations-QP5yn9_z.mjs → Relations-Dmv0Tpe5.mjs} +3 -3
  42. package/dist/_chunks/{Relations-QP5yn9_z.mjs.map → Relations-Dmv0Tpe5.mjs.map} +1 -1
  43. package/dist/_chunks/{Relations-CFjTESWQ.js → Relations-jwuTFGOV.js} +3 -3
  44. package/dist/_chunks/{Relations-CFjTESWQ.js.map → Relations-jwuTFGOV.js.map} +1 -1
  45. package/dist/_chunks/{en-BVzUkPxZ.js → en-BlhnxQfj.js} +2 -2
  46. package/dist/_chunks/{en-BVzUkPxZ.js.map → en-BlhnxQfj.js.map} +1 -1
  47. package/dist/_chunks/{en-CPTj6CjC.mjs → en-C8YBvRrK.mjs} +2 -2
  48. package/dist/_chunks/{en-CPTj6CjC.mjs.map → en-C8YBvRrK.mjs.map} +1 -1
  49. package/dist/_chunks/{index-BHfS6_D5.mjs → index-BmUAydCA.mjs} +868 -816
  50. package/dist/_chunks/index-BmUAydCA.mjs.map +1 -0
  51. package/dist/_chunks/{index-DXiHxy70.js → index-CBX6KyXv.js} +866 -814
  52. package/dist/_chunks/index-CBX6KyXv.js.map +1 -0
  53. package/dist/_chunks/{layout-DX_52HSH.mjs → layout-ClP-DC72.mjs} +3 -3
  54. package/dist/_chunks/{layout-DX_52HSH.mjs.map → layout-ClP-DC72.mjs.map} +1 -1
  55. package/dist/_chunks/{layout-bE-WUnQ0.js → layout-CxxkX9jY.js} +3 -3
  56. package/dist/_chunks/{layout-bE-WUnQ0.js.map → layout-CxxkX9jY.js.map} +1 -1
  57. package/dist/_chunks/{relations-D706vblp.js → relations-DIjTADIu.js} +2 -2
  58. package/dist/_chunks/{relations-D706vblp.js.map → relations-DIjTADIu.js.map} +1 -1
  59. package/dist/_chunks/{relations-SCVAL_aJ.mjs → relations-op89RClB.mjs} +2 -2
  60. package/dist/_chunks/{relations-SCVAL_aJ.mjs.map → relations-op89RClB.mjs.map} +1 -1
  61. package/dist/admin/index.js +2 -1
  62. package/dist/admin/index.js.map +1 -1
  63. package/dist/admin/index.mjs +3 -2
  64. package/dist/admin/src/exports.d.ts +1 -1
  65. package/dist/admin/src/hooks/useDocument.d.ts +30 -1
  66. package/package.json +8 -8
  67. package/dist/_chunks/index-BHfS6_D5.mjs.map +0 -1
  68. package/dist/_chunks/index-DXiHxy70.js.map +0 -1
  69. package/strapi-server.js +0 -3
@@ -810,19 +810,115 @@ const extractContentTypeComponents = (attributes = {}, allComponents = {}) => {
810
810
  }, {});
811
811
  return componentsByKey;
812
812
  };
813
- const useDocument = (args, opts) => {
813
+ const HOOKS = {
814
+ /**
815
+ * Hook that allows to mutate the displayed headers of the list view table
816
+ * @constant
817
+ * @type {string}
818
+ */
819
+ INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
820
+ /**
821
+ * Hook that allows to mutate the CM's collection types links pre-set filters
822
+ * @constant
823
+ * @type {string}
824
+ */
825
+ MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
826
+ /**
827
+ * Hook that allows to mutate the CM's edit view layout
828
+ * @constant
829
+ * @type {string}
830
+ */
831
+ MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
832
+ /**
833
+ * Hook that allows to mutate the CM's single types links pre-set filters
834
+ * @constant
835
+ * @type {string}
836
+ */
837
+ MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
838
+ };
839
+ const contentTypesApi = contentManagerApi.injectEndpoints({
840
+ endpoints: (builder) => ({
841
+ getContentTypeConfiguration: builder.query({
842
+ query: (uid) => ({
843
+ url: `/content-manager/content-types/${uid}/configuration`,
844
+ method: "GET"
845
+ }),
846
+ transformResponse: (response) => response.data,
847
+ providesTags: (_result, _error, uid) => [
848
+ { type: "ContentTypesConfiguration", id: uid },
849
+ { type: "ContentTypeSettings", id: "LIST" }
850
+ ]
851
+ }),
852
+ getAllContentTypeSettings: builder.query({
853
+ query: () => "/content-manager/content-types-settings",
854
+ transformResponse: (response) => response.data,
855
+ providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
856
+ }),
857
+ updateContentTypeConfiguration: builder.mutation({
858
+ query: ({ uid, ...body }) => ({
859
+ url: `/content-manager/content-types/${uid}/configuration`,
860
+ method: "PUT",
861
+ data: body
862
+ }),
863
+ transformResponse: (response) => response.data,
864
+ invalidatesTags: (_result, _error, { uid }) => [
865
+ { type: "ContentTypesConfiguration", id: uid },
866
+ { type: "ContentTypeSettings", id: "LIST" },
867
+ // Is this necessary?
868
+ { type: "InitialData" }
869
+ ]
870
+ })
871
+ })
872
+ });
873
+ const {
874
+ useGetContentTypeConfigurationQuery,
875
+ useGetAllContentTypeSettingsQuery,
876
+ useUpdateContentTypeConfigurationMutation
877
+ } = contentTypesApi;
878
+ const checkIfAttributeIsDisplayable = (attribute) => {
879
+ const { type } = attribute;
880
+ if (type === "relation") {
881
+ return !attribute.relation.toLowerCase().includes("morph");
882
+ }
883
+ return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
884
+ };
885
+ const getMainField = (attribute, mainFieldName, { schemas, components }) => {
886
+ if (!mainFieldName) {
887
+ return void 0;
888
+ }
889
+ const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
890
+ // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
891
+ schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
892
+ );
893
+ return {
894
+ name: mainFieldName,
895
+ type: mainFieldType ?? "string"
896
+ };
897
+ };
898
+ const DEFAULT_SETTINGS = {
899
+ bulkable: false,
900
+ filterable: false,
901
+ searchable: false,
902
+ pagination: false,
903
+ defaultSortBy: "",
904
+ defaultSortOrder: "asc",
905
+ mainField: "id",
906
+ pageSize: 10
907
+ };
908
+ const useDocumentLayout = (model) => {
909
+ const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
910
+ const [{ query }] = strapiAdmin.useQueryParams();
911
+ const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
814
912
  const { toggleNotification } = strapiAdmin.useNotification();
815
913
  const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
914
+ const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
816
915
  const {
817
- currentData: data,
818
- isLoading: isLoadingDocument,
819
- isFetching: isFetchingDocument,
820
- error
821
- } = useGetDocumentQuery(args, {
822
- ...opts,
823
- skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
824
- });
825
- const { components, schema, isLoading: isLoadingSchema } = useContentTypeSchema(args.model);
916
+ data,
917
+ isLoading: isLoadingConfigs,
918
+ error,
919
+ isFetching: isFetchingConfigs
920
+ } = useGetContentTypeConfigurationQuery(model);
921
+ const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
826
922
  React__namespace.useEffect(() => {
827
923
  if (error) {
828
924
  toggleNotification({
@@ -830,396 +926,435 @@ const useDocument = (args, opts) => {
830
926
  message: formatAPIError(error)
831
927
  });
832
928
  }
833
- }, [toggleNotification, error, formatAPIError, args.collectionType]);
834
- const validationSchema = React__namespace.useMemo(() => {
835
- if (!schema) {
836
- return null;
837
- }
838
- return createYupSchema(schema.attributes, components);
839
- }, [schema, components]);
840
- const validate = React__namespace.useCallback(
841
- (document) => {
842
- if (!validationSchema) {
843
- throw new Error(
844
- "There is no validation schema generated, this is likely due to the schema not being loaded yet."
845
- );
846
- }
847
- try {
848
- validationSchema.validateSync(document, { abortEarly: false, strict: true });
849
- return null;
850
- } catch (error2) {
851
- if (error2 instanceof yup.ValidationError) {
852
- return strapiAdmin.getYupValidationErrors(error2);
853
- }
854
- throw error2;
855
- }
929
+ }, [error, formatAPIError, toggleNotification]);
930
+ const editLayout = React__namespace.useMemo(
931
+ () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
932
+ layout: [],
933
+ components: {},
934
+ metadatas: {},
935
+ options: {},
936
+ settings: DEFAULT_SETTINGS
856
937
  },
857
- [validationSchema]
938
+ [data, isLoading, schemas, schema, components]
939
+ );
940
+ const listLayout = React__namespace.useMemo(() => {
941
+ return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
942
+ layout: [],
943
+ metadatas: {},
944
+ options: {},
945
+ settings: DEFAULT_SETTINGS
946
+ };
947
+ }, [data, isLoading, schemas, schema, components]);
948
+ const { layout: edit } = React__namespace.useMemo(
949
+ () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
950
+ layout: editLayout,
951
+ query
952
+ }),
953
+ [editLayout, query, runHookWaterfall]
858
954
  );
859
- const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
860
955
  return {
861
- components,
862
- document: data?.data,
863
- meta: data?.meta,
956
+ error,
864
957
  isLoading,
865
- schema,
866
- validate
867
- };
868
- };
869
- const useDoc = () => {
870
- const { id, slug, collectionType, origin } = reactRouterDom.useParams();
871
- const [{ query }] = strapiAdmin.useQueryParams();
872
- const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
873
- if (!collectionType) {
874
- throw new Error("Could not find collectionType in url params");
875
- }
876
- if (!slug) {
877
- throw new Error("Could not find model in url params");
878
- }
879
- return {
880
- collectionType,
881
- model: slug,
882
- id: origin || id === "create" ? void 0 : id,
883
- ...useDocument(
884
- { documentId: origin || id, model: slug, collectionType, params },
885
- {
886
- skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
887
- }
888
- )
958
+ edit,
959
+ list: listLayout
889
960
  };
890
961
  };
891
- const prefixPluginTranslations = (trad, pluginId) => {
892
- if (!pluginId) {
893
- throw new TypeError("pluginId can't be empty");
894
- }
895
- return Object.keys(trad).reduce((acc, current) => {
896
- acc[`${pluginId}.${current}`] = trad[current];
897
- return acc;
898
- }, {});
899
- };
900
- const getTranslation = (id) => `content-manager.${id}`;
901
- const DEFAULT_UNEXPECTED_ERROR_MSG = {
902
- id: "notification.error",
903
- defaultMessage: "An error occurred, please try again"
962
+ const useDocLayout = () => {
963
+ const { model } = useDoc();
964
+ return useDocumentLayout(model);
904
965
  };
905
- const useDocumentActions = () => {
906
- const { toggleNotification } = strapiAdmin.useNotification();
907
- const { formatMessage } = reactIntl.useIntl();
908
- const { trackUsage } = strapiAdmin.useTracking();
909
- const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
910
- const navigate = reactRouterDom.useNavigate();
911
- const [deleteDocument] = useDeleteDocumentMutation();
912
- const _delete = React__namespace.useCallback(
913
- async ({ collectionType, model, documentId, params }, trackerProperty) => {
914
- try {
915
- trackUsage("willDeleteEntry", trackerProperty);
916
- const res = await deleteDocument({
917
- collectionType,
918
- model,
919
- documentId,
920
- params
921
- });
922
- if ("error" in res) {
923
- toggleNotification({
924
- type: "danger",
925
- message: formatAPIError(res.error)
926
- });
927
- return { error: res.error };
928
- }
929
- toggleNotification({
930
- type: "success",
931
- message: formatMessage({
932
- id: getTranslation("success.record.delete"),
933
- defaultMessage: "Deleted document"
934
- })
935
- });
936
- trackUsage("didDeleteEntry", trackerProperty);
937
- return res.data;
938
- } catch (err) {
939
- toggleNotification({
940
- type: "danger",
941
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
942
- });
943
- trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
944
- throw err;
945
- }
946
- },
947
- [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
948
- );
949
- const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
950
- const deleteMany = React__namespace.useCallback(
951
- async ({ model, documentIds, params }) => {
952
- try {
953
- trackUsage("willBulkDeleteEntries");
954
- const res = await deleteManyDocuments({
955
- model,
956
- documentIds,
957
- params
958
- });
959
- if ("error" in res) {
960
- toggleNotification({
961
- type: "danger",
962
- message: formatAPIError(res.error)
963
- });
964
- return { error: res.error };
965
- }
966
- toggleNotification({
967
- type: "success",
968
- title: formatMessage({
969
- id: getTranslation("success.records.delete"),
970
- defaultMessage: "Successfully deleted."
971
- }),
972
- message: ""
973
- });
974
- trackUsage("didBulkDeleteEntries");
975
- return res.data;
976
- } catch (err) {
977
- toggleNotification({
978
- type: "danger",
979
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
980
- });
981
- trackUsage("didNotBulkDeleteEntries");
982
- throw err;
966
+ const formatEditLayout = (data, {
967
+ schemas,
968
+ schema,
969
+ components
970
+ }) => {
971
+ let currentPanelIndex = 0;
972
+ const panelledEditAttributes = convertEditLayoutToFieldLayouts(
973
+ data.contentType.layouts.edit,
974
+ schema?.attributes,
975
+ data.contentType.metadatas,
976
+ { configurations: data.components, schemas: components },
977
+ schemas
978
+ ).reduce((panels, row) => {
979
+ if (row.some((field) => field.type === "dynamiczone")) {
980
+ panels.push([row]);
981
+ currentPanelIndex += 2;
982
+ } else {
983
+ if (!panels[currentPanelIndex]) {
984
+ panels.push([]);
983
985
  }
984
- },
985
- [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
986
- );
987
- const [discardDocument] = useDiscardDocumentMutation();
988
- const discard = React__namespace.useCallback(
989
- async ({ collectionType, model, documentId, params }) => {
990
- try {
991
- const res = await discardDocument({
992
- collectionType,
993
- model,
994
- documentId,
995
- params
996
- });
997
- if ("error" in res) {
998
- toggleNotification({
999
- type: "danger",
1000
- message: formatAPIError(res.error)
1001
- });
1002
- return { error: res.error };
986
+ panels[currentPanelIndex].push(row);
987
+ }
988
+ return panels;
989
+ }, []);
990
+ const componentEditAttributes = Object.entries(data.components).reduce(
991
+ (acc, [uid, configuration]) => {
992
+ acc[uid] = {
993
+ layout: convertEditLayoutToFieldLayouts(
994
+ configuration.layouts.edit,
995
+ components[uid].attributes,
996
+ configuration.metadatas,
997
+ { configurations: data.components, schemas: components }
998
+ ),
999
+ settings: {
1000
+ ...configuration.settings,
1001
+ icon: components[uid].info.icon,
1002
+ displayName: components[uid].info.displayName
1003
1003
  }
1004
- toggleNotification({
1005
- type: "success",
1006
- message: formatMessage({
1007
- id: "content-manager.success.record.discard",
1008
- defaultMessage: "Changes discarded"
1009
- })
1010
- });
1011
- return res.data;
1012
- } catch (err) {
1013
- toggleNotification({
1014
- type: "danger",
1015
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1016
- });
1017
- throw err;
1018
- }
1004
+ };
1005
+ return acc;
1019
1006
  },
1020
- [discardDocument, formatAPIError, formatMessage, toggleNotification]
1007
+ {}
1021
1008
  );
1022
- const [publishDocument] = usePublishDocumentMutation();
1023
- const publish = React__namespace.useCallback(
1024
- async ({ collectionType, model, documentId, params }, data) => {
1025
- try {
1026
- trackUsage("willPublishEntry");
1027
- const res = await publishDocument({
1028
- collectionType,
1029
- model,
1030
- documentId,
1031
- data,
1032
- params
1033
- });
1034
- if ("error" in res) {
1035
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1036
- return { error: res.error };
1037
- }
1038
- trackUsage("didPublishEntry");
1039
- toggleNotification({
1040
- type: "success",
1041
- message: formatMessage({
1042
- id: getTranslation("success.record.publish"),
1043
- defaultMessage: "Published document"
1044
- })
1045
- });
1046
- return res.data;
1047
- } catch (err) {
1048
- toggleNotification({
1049
- type: "danger",
1050
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1051
- });
1052
- throw err;
1053
- }
1009
+ const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
1010
+ (acc, [attribute, metadata]) => {
1011
+ return {
1012
+ ...acc,
1013
+ [attribute]: metadata.edit
1014
+ };
1054
1015
  },
1055
- [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1016
+ {}
1056
1017
  );
1057
- const [publishManyDocuments] = usePublishManyDocumentsMutation();
1058
- const publishMany = React__namespace.useCallback(
1059
- async ({ model, documentIds, params }) => {
1060
- try {
1061
- const res = await publishManyDocuments({
1062
- model,
1063
- documentIds,
1064
- params
1065
- });
1066
- if ("error" in res) {
1067
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1068
- return { error: res.error };
1069
- }
1070
- toggleNotification({
1071
- type: "success",
1072
- message: formatMessage({
1073
- id: getTranslation("success.record.publish"),
1074
- defaultMessage: "Published document"
1075
- })
1076
- });
1077
- return res.data;
1078
- } catch (err) {
1079
- toggleNotification({
1080
- type: "danger",
1081
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1082
- });
1083
- throw err;
1018
+ return {
1019
+ layout: panelledEditAttributes,
1020
+ components: componentEditAttributes,
1021
+ metadatas: editMetadatas,
1022
+ settings: {
1023
+ ...data.contentType.settings,
1024
+ displayName: schema?.info.displayName
1025
+ },
1026
+ options: {
1027
+ ...schema?.options,
1028
+ ...schema?.pluginOptions,
1029
+ ...data.contentType.options
1030
+ }
1031
+ };
1032
+ };
1033
+ const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
1034
+ return rows.map(
1035
+ (row) => row.map((field) => {
1036
+ const attribute = attributes[field.name];
1037
+ if (!attribute) {
1038
+ return null;
1084
1039
  }
1040
+ const { edit: metadata } = metadatas[field.name];
1041
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1042
+ return {
1043
+ attribute,
1044
+ disabled: !metadata.editable,
1045
+ hint: metadata.description,
1046
+ label: metadata.label ?? "",
1047
+ name: field.name,
1048
+ // @ts-expect-error – mainField does exist on the metadata for a relation.
1049
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1050
+ schemas,
1051
+ components: components?.schemas ?? {}
1052
+ }),
1053
+ placeholder: metadata.placeholder ?? "",
1054
+ required: attribute.required ?? false,
1055
+ size: field.size,
1056
+ unique: "unique" in attribute ? attribute.unique : false,
1057
+ visible: metadata.visible ?? true,
1058
+ type: attribute.type
1059
+ };
1060
+ }).filter((field) => field !== null)
1061
+ );
1062
+ };
1063
+ const formatListLayout = (data, {
1064
+ schemas,
1065
+ schema,
1066
+ components
1067
+ }) => {
1068
+ const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
1069
+ (acc, [attribute, metadata]) => {
1070
+ return {
1071
+ ...acc,
1072
+ [attribute]: metadata.list
1073
+ };
1085
1074
  },
1086
- [
1087
- // trackUsage,
1088
- publishManyDocuments,
1089
- toggleNotification,
1090
- formatMessage,
1091
- formatAPIError
1092
- ]
1075
+ {}
1093
1076
  );
1094
- const [updateDocument] = useUpdateDocumentMutation();
1095
- const update = React__namespace.useCallback(
1096
- async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
1097
- try {
1098
- trackUsage("willEditEntry", trackerProperty);
1099
- const res = await updateDocument({
1100
- collectionType,
1101
- model,
1102
- documentId,
1103
- data,
1104
- params
1105
- });
1106
- if ("error" in res) {
1107
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1108
- trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
1109
- return { error: res.error };
1110
- }
1111
- trackUsage("didEditEntry", trackerProperty);
1112
- toggleNotification({
1113
- type: "success",
1114
- message: formatMessage({
1115
- id: getTranslation("success.record.save"),
1116
- defaultMessage: "Saved document"
1117
- })
1118
- });
1119
- return res.data;
1120
- } catch (err) {
1121
- trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
1122
- toggleNotification({
1123
- type: "danger",
1124
- message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1125
- });
1126
- throw err;
1077
+ const listAttributes = convertListLayoutToFieldLayouts(
1078
+ data.contentType.layouts.list,
1079
+ schema?.attributes,
1080
+ listMetadatas,
1081
+ { configurations: data.components, schemas: components },
1082
+ schemas
1083
+ );
1084
+ return {
1085
+ layout: listAttributes,
1086
+ settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
1087
+ metadatas: listMetadatas,
1088
+ options: {
1089
+ ...schema?.options,
1090
+ ...schema?.pluginOptions,
1091
+ ...data.contentType.options
1092
+ }
1093
+ };
1094
+ };
1095
+ const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
1096
+ return columns.map((name) => {
1097
+ const attribute = attributes[name];
1098
+ if (!attribute) {
1099
+ return null;
1100
+ }
1101
+ const metadata = metadatas[name];
1102
+ const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
1103
+ return {
1104
+ attribute,
1105
+ label: metadata.label ?? "",
1106
+ mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
1107
+ schemas,
1108
+ components: components?.schemas ?? {}
1109
+ }),
1110
+ name,
1111
+ searchable: metadata.searchable ?? true,
1112
+ sortable: metadata.sortable ?? true
1113
+ };
1114
+ }).filter((field) => field !== null);
1115
+ };
1116
+ const useDocument = (args, opts) => {
1117
+ const { toggleNotification } = strapiAdmin.useNotification();
1118
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1119
+ const {
1120
+ currentData: data,
1121
+ isLoading: isLoadingDocument,
1122
+ isFetching: isFetchingDocument,
1123
+ error
1124
+ } = useGetDocumentQuery(args, {
1125
+ ...opts,
1126
+ skip: !args.documentId && args.collectionType !== SINGLE_TYPES || opts?.skip
1127
+ });
1128
+ const {
1129
+ components,
1130
+ schema,
1131
+ schemas,
1132
+ isLoading: isLoadingSchema
1133
+ } = useContentTypeSchema(args.model);
1134
+ React__namespace.useEffect(() => {
1135
+ if (error) {
1136
+ toggleNotification({
1137
+ type: "danger",
1138
+ message: formatAPIError(error)
1139
+ });
1140
+ }
1141
+ }, [toggleNotification, error, formatAPIError, args.collectionType]);
1142
+ const validationSchema = React__namespace.useMemo(() => {
1143
+ if (!schema) {
1144
+ return null;
1145
+ }
1146
+ return createYupSchema(schema.attributes, components);
1147
+ }, [schema, components]);
1148
+ const validate = React__namespace.useCallback(
1149
+ (document) => {
1150
+ if (!validationSchema) {
1151
+ throw new Error(
1152
+ "There is no validation schema generated, this is likely due to the schema not being loaded yet."
1153
+ );
1154
+ }
1155
+ try {
1156
+ validationSchema.validateSync(document, { abortEarly: false, strict: true });
1157
+ return null;
1158
+ } catch (error2) {
1159
+ if (error2 instanceof yup.ValidationError) {
1160
+ return strapiAdmin.getYupValidationErrors(error2);
1161
+ }
1162
+ throw error2;
1127
1163
  }
1128
1164
  },
1129
- [trackUsage, updateDocument, toggleNotification, formatMessage, formatAPIError]
1165
+ [validationSchema]
1130
1166
  );
1131
- const [unpublishDocument] = useUnpublishDocumentMutation();
1132
- const unpublish = React__namespace.useCallback(
1133
- async ({ collectionType, model, documentId, params }, discardDraft = false) => {
1167
+ const isLoading = isLoadingDocument || isFetchingDocument || isLoadingSchema;
1168
+ return {
1169
+ components,
1170
+ document: data?.data,
1171
+ meta: data?.meta,
1172
+ isLoading,
1173
+ schema,
1174
+ schemas,
1175
+ validate
1176
+ };
1177
+ };
1178
+ const useDoc = () => {
1179
+ const { id, slug, collectionType, origin } = reactRouterDom.useParams();
1180
+ const [{ query }] = strapiAdmin.useQueryParams();
1181
+ const params = React__namespace.useMemo(() => buildValidParams(query), [query]);
1182
+ if (!collectionType) {
1183
+ throw new Error("Could not find collectionType in url params");
1184
+ }
1185
+ if (!slug) {
1186
+ throw new Error("Could not find model in url params");
1187
+ }
1188
+ return {
1189
+ collectionType,
1190
+ model: slug,
1191
+ id: origin || id === "create" ? void 0 : id,
1192
+ ...useDocument(
1193
+ { documentId: origin || id, model: slug, collectionType, params },
1194
+ {
1195
+ skip: id === "create" || !origin && !id && collectionType !== SINGLE_TYPES
1196
+ }
1197
+ )
1198
+ };
1199
+ };
1200
+ const useContentManagerContext = () => {
1201
+ const {
1202
+ collectionType,
1203
+ model,
1204
+ id,
1205
+ components,
1206
+ isLoading: isLoadingDoc,
1207
+ schema,
1208
+ schemas
1209
+ } = useDoc();
1210
+ const layout = useDocumentLayout(model);
1211
+ const form = strapiAdmin.useForm("useContentManagerContext", (state) => state);
1212
+ const isSingleType = collectionType === SINGLE_TYPES;
1213
+ const slug = model;
1214
+ const isCreatingEntry = id === "create";
1215
+ useContentTypeSchema();
1216
+ const isLoading = isLoadingDoc || layout.isLoading;
1217
+ const error = layout.error;
1218
+ return {
1219
+ error,
1220
+ isLoading,
1221
+ // Base metadata
1222
+ model,
1223
+ collectionType,
1224
+ id,
1225
+ slug,
1226
+ isCreatingEntry,
1227
+ isSingleType,
1228
+ hasDraftAndPublish: schema?.options?.draftAndPublish ?? false,
1229
+ // All schema infos
1230
+ components,
1231
+ contentType: schema,
1232
+ contentTypes: schemas,
1233
+ // Form state
1234
+ form,
1235
+ // layout infos
1236
+ layout
1237
+ };
1238
+ };
1239
+ const prefixPluginTranslations = (trad, pluginId) => {
1240
+ if (!pluginId) {
1241
+ throw new TypeError("pluginId can't be empty");
1242
+ }
1243
+ return Object.keys(trad).reduce((acc, current) => {
1244
+ acc[`${pluginId}.${current}`] = trad[current];
1245
+ return acc;
1246
+ }, {});
1247
+ };
1248
+ const getTranslation = (id) => `content-manager.${id}`;
1249
+ const DEFAULT_UNEXPECTED_ERROR_MSG = {
1250
+ id: "notification.error",
1251
+ defaultMessage: "An error occurred, please try again"
1252
+ };
1253
+ const useDocumentActions = () => {
1254
+ const { toggleNotification } = strapiAdmin.useNotification();
1255
+ const { formatMessage } = reactIntl.useIntl();
1256
+ const { trackUsage } = strapiAdmin.useTracking();
1257
+ const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
1258
+ const navigate = reactRouterDom.useNavigate();
1259
+ const setCurrentStep = strapiAdmin.useGuidedTour("useDocumentActions", (state) => state.setCurrentStep);
1260
+ const [deleteDocument] = useDeleteDocumentMutation();
1261
+ const _delete = React__namespace.useCallback(
1262
+ async ({ collectionType, model, documentId, params }, trackerProperty) => {
1134
1263
  try {
1135
- trackUsage("willUnpublishEntry");
1136
- const res = await unpublishDocument({
1264
+ trackUsage("willDeleteEntry", trackerProperty);
1265
+ const res = await deleteDocument({
1137
1266
  collectionType,
1138
1267
  model,
1139
1268
  documentId,
1140
- params,
1141
- data: {
1142
- discardDraft
1143
- }
1269
+ params
1144
1270
  });
1145
1271
  if ("error" in res) {
1146
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1272
+ toggleNotification({
1273
+ type: "danger",
1274
+ message: formatAPIError(res.error)
1275
+ });
1147
1276
  return { error: res.error };
1148
1277
  }
1149
- trackUsage("didUnpublishEntry");
1150
1278
  toggleNotification({
1151
1279
  type: "success",
1152
1280
  message: formatMessage({
1153
- id: getTranslation("success.record.unpublish"),
1154
- defaultMessage: "Unpublished document"
1281
+ id: getTranslation("success.record.delete"),
1282
+ defaultMessage: "Deleted document"
1155
1283
  })
1156
1284
  });
1285
+ trackUsage("didDeleteEntry", trackerProperty);
1157
1286
  return res.data;
1158
1287
  } catch (err) {
1159
1288
  toggleNotification({
1160
1289
  type: "danger",
1161
1290
  message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1162
1291
  });
1292
+ trackUsage("didNotDeleteEntry", { error: err, ...trackerProperty });
1163
1293
  throw err;
1164
1294
  }
1165
1295
  },
1166
- [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1296
+ [trackUsage, deleteDocument, toggleNotification, formatMessage, formatAPIError]
1167
1297
  );
1168
- const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1169
- const unpublishMany = React__namespace.useCallback(
1298
+ const [deleteManyDocuments] = useDeleteManyDocumentsMutation();
1299
+ const deleteMany = React__namespace.useCallback(
1170
1300
  async ({ model, documentIds, params }) => {
1171
1301
  try {
1172
- trackUsage("willBulkUnpublishEntries");
1173
- const res = await unpublishManyDocuments({
1302
+ trackUsage("willBulkDeleteEntries");
1303
+ const res = await deleteManyDocuments({
1174
1304
  model,
1175
1305
  documentIds,
1176
1306
  params
1177
1307
  });
1178
1308
  if ("error" in res) {
1179
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1309
+ toggleNotification({
1310
+ type: "danger",
1311
+ message: formatAPIError(res.error)
1312
+ });
1180
1313
  return { error: res.error };
1181
1314
  }
1182
- trackUsage("didBulkUnpublishEntries");
1183
1315
  toggleNotification({
1184
1316
  type: "success",
1185
1317
  title: formatMessage({
1186
- id: getTranslation("success.records.unpublish"),
1187
- defaultMessage: "Successfully unpublished."
1318
+ id: getTranslation("success.records.delete"),
1319
+ defaultMessage: "Successfully deleted."
1188
1320
  }),
1189
1321
  message: ""
1190
1322
  });
1323
+ trackUsage("didBulkDeleteEntries");
1191
1324
  return res.data;
1192
1325
  } catch (err) {
1193
1326
  toggleNotification({
1194
1327
  type: "danger",
1195
1328
  message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1196
1329
  });
1197
- trackUsage("didNotBulkUnpublishEntries");
1330
+ trackUsage("didNotBulkDeleteEntries");
1198
1331
  throw err;
1199
1332
  }
1200
1333
  },
1201
- [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1334
+ [trackUsage, deleteManyDocuments, toggleNotification, formatMessage, formatAPIError]
1202
1335
  );
1203
- const [createDocument] = useCreateDocumentMutation();
1204
- const create = React__namespace.useCallback(
1205
- async ({ model, params }, data, trackerProperty) => {
1336
+ const [discardDocument] = useDiscardDocumentMutation();
1337
+ const discard = React__namespace.useCallback(
1338
+ async ({ collectionType, model, documentId, params }) => {
1206
1339
  try {
1207
- const res = await createDocument({
1340
+ const res = await discardDocument({
1341
+ collectionType,
1208
1342
  model,
1209
- data,
1343
+ documentId,
1210
1344
  params
1211
1345
  });
1212
1346
  if ("error" in res) {
1213
- toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1214
- trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
1347
+ toggleNotification({
1348
+ type: "danger",
1349
+ message: formatAPIError(res.error)
1350
+ });
1215
1351
  return { error: res.error };
1216
1352
  }
1217
- trackUsage("didCreateEntry", trackerProperty);
1218
1353
  toggleNotification({
1219
1354
  type: "success",
1220
1355
  message: formatMessage({
1221
- id: getTranslation("success.record.save"),
1222
- defaultMessage: "Saved document"
1356
+ id: "content-manager.success.record.discard",
1357
+ defaultMessage: "Changes discarded"
1223
1358
  })
1224
1359
  });
1225
1360
  return res.data;
@@ -1228,19 +1363,234 @@ const useDocumentActions = () => {
1228
1363
  type: "danger",
1229
1364
  message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1230
1365
  });
1231
- trackUsage("didNotCreateEntry", { error: err, ...trackerProperty });
1232
1366
  throw err;
1233
1367
  }
1234
1368
  },
1235
- [createDocument, formatAPIError, formatMessage, toggleNotification, trackUsage]
1369
+ [discardDocument, formatAPIError, formatMessage, toggleNotification]
1236
1370
  );
1237
- const [autoCloneDocument] = useAutoCloneDocumentMutation();
1238
- const autoClone = React__namespace.useCallback(
1239
- async ({ model, sourceId }) => {
1371
+ const [publishDocument] = usePublishDocumentMutation();
1372
+ const publish = React__namespace.useCallback(
1373
+ async ({ collectionType, model, documentId, params }, data) => {
1240
1374
  try {
1241
- const res = await autoCloneDocument({
1375
+ trackUsage("willPublishEntry");
1376
+ const res = await publishDocument({
1377
+ collectionType,
1242
1378
  model,
1243
- sourceId
1379
+ documentId,
1380
+ data,
1381
+ params
1382
+ });
1383
+ if ("error" in res) {
1384
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1385
+ return { error: res.error };
1386
+ }
1387
+ trackUsage("didPublishEntry");
1388
+ toggleNotification({
1389
+ type: "success",
1390
+ message: formatMessage({
1391
+ id: getTranslation("success.record.publish"),
1392
+ defaultMessage: "Published document"
1393
+ })
1394
+ });
1395
+ return res.data;
1396
+ } catch (err) {
1397
+ toggleNotification({
1398
+ type: "danger",
1399
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1400
+ });
1401
+ throw err;
1402
+ }
1403
+ },
1404
+ [trackUsage, publishDocument, toggleNotification, formatMessage, formatAPIError]
1405
+ );
1406
+ const [publishManyDocuments] = usePublishManyDocumentsMutation();
1407
+ const publishMany = React__namespace.useCallback(
1408
+ async ({ model, documentIds, params }) => {
1409
+ try {
1410
+ const res = await publishManyDocuments({
1411
+ model,
1412
+ documentIds,
1413
+ params
1414
+ });
1415
+ if ("error" in res) {
1416
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1417
+ return { error: res.error };
1418
+ }
1419
+ toggleNotification({
1420
+ type: "success",
1421
+ message: formatMessage({
1422
+ id: getTranslation("success.record.publish"),
1423
+ defaultMessage: "Published document"
1424
+ })
1425
+ });
1426
+ return res.data;
1427
+ } catch (err) {
1428
+ toggleNotification({
1429
+ type: "danger",
1430
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1431
+ });
1432
+ throw err;
1433
+ }
1434
+ },
1435
+ [
1436
+ // trackUsage,
1437
+ publishManyDocuments,
1438
+ toggleNotification,
1439
+ formatMessage,
1440
+ formatAPIError
1441
+ ]
1442
+ );
1443
+ const [updateDocument] = useUpdateDocumentMutation();
1444
+ const update = React__namespace.useCallback(
1445
+ async ({ collectionType, model, documentId, params }, data, trackerProperty) => {
1446
+ try {
1447
+ trackUsage("willEditEntry", trackerProperty);
1448
+ const res = await updateDocument({
1449
+ collectionType,
1450
+ model,
1451
+ documentId,
1452
+ data,
1453
+ params
1454
+ });
1455
+ if ("error" in res) {
1456
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1457
+ trackUsage("didNotEditEntry", { error: res.error, ...trackerProperty });
1458
+ return { error: res.error };
1459
+ }
1460
+ trackUsage("didEditEntry", trackerProperty);
1461
+ toggleNotification({
1462
+ type: "success",
1463
+ message: formatMessage({
1464
+ id: getTranslation("success.record.save"),
1465
+ defaultMessage: "Saved document"
1466
+ })
1467
+ });
1468
+ return res.data;
1469
+ } catch (err) {
1470
+ trackUsage("didNotEditEntry", { error: err, ...trackerProperty });
1471
+ toggleNotification({
1472
+ type: "danger",
1473
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1474
+ });
1475
+ throw err;
1476
+ }
1477
+ },
1478
+ [trackUsage, updateDocument, toggleNotification, formatMessage, formatAPIError]
1479
+ );
1480
+ const [unpublishDocument] = useUnpublishDocumentMutation();
1481
+ const unpublish = React__namespace.useCallback(
1482
+ async ({ collectionType, model, documentId, params }, discardDraft = false) => {
1483
+ try {
1484
+ trackUsage("willUnpublishEntry");
1485
+ const res = await unpublishDocument({
1486
+ collectionType,
1487
+ model,
1488
+ documentId,
1489
+ params,
1490
+ data: {
1491
+ discardDraft
1492
+ }
1493
+ });
1494
+ if ("error" in res) {
1495
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1496
+ return { error: res.error };
1497
+ }
1498
+ trackUsage("didUnpublishEntry");
1499
+ toggleNotification({
1500
+ type: "success",
1501
+ message: formatMessage({
1502
+ id: getTranslation("success.record.unpublish"),
1503
+ defaultMessage: "Unpublished document"
1504
+ })
1505
+ });
1506
+ return res.data;
1507
+ } catch (err) {
1508
+ toggleNotification({
1509
+ type: "danger",
1510
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1511
+ });
1512
+ throw err;
1513
+ }
1514
+ },
1515
+ [trackUsage, unpublishDocument, toggleNotification, formatMessage, formatAPIError]
1516
+ );
1517
+ const [unpublishManyDocuments] = useUnpublishManyDocumentsMutation();
1518
+ const unpublishMany = React__namespace.useCallback(
1519
+ async ({ model, documentIds, params }) => {
1520
+ try {
1521
+ trackUsage("willBulkUnpublishEntries");
1522
+ const res = await unpublishManyDocuments({
1523
+ model,
1524
+ documentIds,
1525
+ params
1526
+ });
1527
+ if ("error" in res) {
1528
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1529
+ return { error: res.error };
1530
+ }
1531
+ trackUsage("didBulkUnpublishEntries");
1532
+ toggleNotification({
1533
+ type: "success",
1534
+ title: formatMessage({
1535
+ id: getTranslation("success.records.unpublish"),
1536
+ defaultMessage: "Successfully unpublished."
1537
+ }),
1538
+ message: ""
1539
+ });
1540
+ return res.data;
1541
+ } catch (err) {
1542
+ toggleNotification({
1543
+ type: "danger",
1544
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1545
+ });
1546
+ trackUsage("didNotBulkUnpublishEntries");
1547
+ throw err;
1548
+ }
1549
+ },
1550
+ [trackUsage, unpublishManyDocuments, toggleNotification, formatMessage, formatAPIError]
1551
+ );
1552
+ const [createDocument] = useCreateDocumentMutation();
1553
+ const create = React__namespace.useCallback(
1554
+ async ({ model, params }, data, trackerProperty) => {
1555
+ try {
1556
+ const res = await createDocument({
1557
+ model,
1558
+ data,
1559
+ params
1560
+ });
1561
+ if ("error" in res) {
1562
+ toggleNotification({ type: "danger", message: formatAPIError(res.error) });
1563
+ trackUsage("didNotCreateEntry", { error: res.error, ...trackerProperty });
1564
+ return { error: res.error };
1565
+ }
1566
+ trackUsage("didCreateEntry", trackerProperty);
1567
+ toggleNotification({
1568
+ type: "success",
1569
+ message: formatMessage({
1570
+ id: getTranslation("success.record.save"),
1571
+ defaultMessage: "Saved document"
1572
+ })
1573
+ });
1574
+ setCurrentStep("contentManager.success");
1575
+ return res.data;
1576
+ } catch (err) {
1577
+ toggleNotification({
1578
+ type: "danger",
1579
+ message: formatMessage(DEFAULT_UNEXPECTED_ERROR_MSG)
1580
+ });
1581
+ trackUsage("didNotCreateEntry", { error: err, ...trackerProperty });
1582
+ throw err;
1583
+ }
1584
+ },
1585
+ [createDocument, formatAPIError, formatMessage, toggleNotification, trackUsage]
1586
+ );
1587
+ const [autoCloneDocument] = useAutoCloneDocumentMutation();
1588
+ const autoClone = React__namespace.useCallback(
1589
+ async ({ model, sourceId }) => {
1590
+ try {
1591
+ const res = await autoCloneDocument({
1592
+ model,
1593
+ sourceId
1244
1594
  });
1245
1595
  if ("error" in res) {
1246
1596
  return { error: res.error };
@@ -1324,7 +1674,7 @@ const useDocumentActions = () => {
1324
1674
  };
1325
1675
  };
1326
1676
  const ProtectedHistoryPage = React.lazy(
1327
- () => Promise.resolve().then(() => require("./History-DXSbTWez.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1677
+ () => Promise.resolve().then(() => require("./History-CWcM9HnW.js")).then((mod) => ({ default: mod.ProtectedHistoryPage }))
1328
1678
  );
1329
1679
  const routes$1 = [
1330
1680
  {
@@ -1337,31 +1687,31 @@ const routes$1 = [
1337
1687
  }
1338
1688
  ];
1339
1689
  const ProtectedEditViewPage = React.lazy(
1340
- () => Promise.resolve().then(() => require("./EditViewPage-CHgoNwlc.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1690
+ () => Promise.resolve().then(() => require("./EditViewPage-Co2IKQZH.js")).then((mod) => ({ default: mod.ProtectedEditViewPage }))
1341
1691
  );
1342
1692
  const ProtectedListViewPage = React.lazy(
1343
- () => Promise.resolve().then(() => require("./ListViewPage-DfuwH1tt.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1693
+ () => Promise.resolve().then(() => require("./ListViewPage-BBAC9aPu.js")).then((mod) => ({ default: mod.ProtectedListViewPage }))
1344
1694
  );
1345
1695
  const ProtectedListConfiguration = React.lazy(
1346
- () => Promise.resolve().then(() => require("./ListConfigurationPage-D5C7ACZ_.js")).then((mod) => ({
1696
+ () => Promise.resolve().then(() => require("./ListConfigurationPage-DGzoQD_I.js")).then((mod) => ({
1347
1697
  default: mod.ProtectedListConfiguration
1348
1698
  }))
1349
1699
  );
1350
1700
  const ProtectedEditConfigurationPage = React.lazy(
1351
- () => Promise.resolve().then(() => require("./EditConfigurationPage-B2AA1kVF.js")).then((mod) => ({
1701
+ () => Promise.resolve().then(() => require("./EditConfigurationPage-ZN3s568V.js")).then((mod) => ({
1352
1702
  default: mod.ProtectedEditConfigurationPage
1353
1703
  }))
1354
1704
  );
1355
1705
  const ProtectedComponentConfigurationPage = React.lazy(
1356
- () => Promise.resolve().then(() => require("./ComponentConfigurationPage-G4EIirP8.js")).then((mod) => ({
1706
+ () => Promise.resolve().then(() => require("./ComponentConfigurationPage-_6osrv39.js")).then((mod) => ({
1357
1707
  default: mod.ProtectedComponentConfigurationPage
1358
1708
  }))
1359
1709
  );
1360
1710
  const NoPermissions = React.lazy(
1361
- () => Promise.resolve().then(() => require("./NoPermissionsPage-Bu4GWYb-.js")).then((mod) => ({ default: mod.NoPermissions }))
1711
+ () => Promise.resolve().then(() => require("./NoPermissionsPage-D2iWw-sn.js")).then((mod) => ({ default: mod.NoPermissions }))
1362
1712
  );
1363
1713
  const NoContentType = React.lazy(
1364
- () => Promise.resolve().then(() => require("./NoContentTypePage-BIxlkWWi.js")).then((mod) => ({ default: mod.NoContentType }))
1714
+ () => Promise.resolve().then(() => require("./NoContentTypePage-CwVDx_YC.js")).then((mod) => ({ default: mod.NoContentType }))
1365
1715
  );
1366
1716
  const CollectionTypePages = () => {
1367
1717
  const { collectionType } = reactRouterDom.useParams();
@@ -2486,490 +2836,191 @@ const ConfigureTheViewAction = ({ collectionType, model }) => {
2486
2836
  position: "header"
2487
2837
  };
2488
2838
  };
2489
- ConfigureTheViewAction.type = "configure-the-view";
2490
- const EditTheModelAction = ({ model }) => {
2491
- const navigate = reactRouterDom.useNavigate();
2492
- const { formatMessage } = reactIntl.useIntl();
2493
- return {
2494
- label: formatMessage({
2495
- id: "content-manager.link-to-ctb",
2496
- defaultMessage: "Edit the model"
2497
- }),
2498
- icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
2499
- onClick: () => {
2500
- navigate(`/plugins/content-type-builder/content-types/${model}`);
2501
- },
2502
- position: "header"
2503
- };
2504
- };
2505
- EditTheModelAction.type = "edit-the-model";
2506
- const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2507
- const navigate = reactRouterDom.useNavigate();
2508
- const { formatMessage } = reactIntl.useIntl();
2509
- const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
2510
- const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
2511
- const { delete: deleteAction } = useDocumentActions();
2512
- const { toggleNotification } = strapiAdmin.useNotification();
2513
- const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
2514
- return {
2515
- disabled: !canDelete || !document,
2516
- label: formatMessage({
2517
- id: "content-manager.actions.delete.label",
2518
- defaultMessage: "Delete document"
2519
- }),
2520
- icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2521
- dialog: {
2522
- type: "dialog",
2523
- title: formatMessage({
2524
- id: "app.components.ConfirmDialog.title",
2525
- defaultMessage: "Confirmation"
2526
- }),
2527
- content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
2528
- /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2529
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2530
- id: "content-manager.actions.delete.dialog.body",
2531
- defaultMessage: "Are you sure?"
2532
- }) })
2533
- ] }),
2534
- onConfirm: async () => {
2535
- if (!listViewPathMatch) {
2536
- setSubmitting(true);
2537
- }
2538
- try {
2539
- if (!documentId && collectionType !== SINGLE_TYPES) {
2540
- console.error(
2541
- "You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
2542
- );
2543
- toggleNotification({
2544
- message: formatMessage({
2545
- id: "content-manager.actions.delete.error",
2546
- defaultMessage: "An error occurred while trying to delete the document."
2547
- }),
2548
- type: "danger"
2549
- });
2550
- return;
2551
- }
2552
- const res = await deleteAction({
2553
- documentId,
2554
- model,
2555
- collectionType,
2556
- params: {
2557
- locale: "*"
2558
- }
2559
- });
2560
- if (!("error" in res)) {
2561
- navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
2562
- }
2563
- } finally {
2564
- if (!listViewPathMatch) {
2565
- setSubmitting(false);
2566
- }
2567
- }
2568
- }
2569
- },
2570
- variant: "danger",
2571
- position: ["header", "table-row"]
2572
- };
2573
- };
2574
- DeleteAction$1.type = "delete";
2575
- const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2576
- const Panels = () => {
2577
- const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2578
- const [
2579
- {
2580
- query: { status }
2581
- }
2582
- ] = strapiAdmin.useQueryParams({
2583
- status: "draft"
2584
- });
2585
- const { model, id, document, meta, collectionType } = useDoc();
2586
- const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
2587
- const props = {
2588
- activeTab: status,
2589
- model,
2590
- documentId: id,
2591
- document: isCloning ? void 0 : document,
2592
- meta: isCloning ? void 0 : meta,
2593
- collectionType
2594
- };
2595
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
2596
- strapiAdmin.DescriptionComponentRenderer,
2597
- {
2598
- props,
2599
- descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2600
- children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
2601
- }
2602
- ) });
2603
- };
2604
- const ActionsPanel = () => {
2605
- const { formatMessage } = reactIntl.useIntl();
2606
- return {
2607
- title: formatMessage({
2608
- id: "content-manager.containers.edit.panels.default.title",
2609
- defaultMessage: "Entry"
2610
- }),
2611
- content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2612
- };
2613
- };
2614
- ActionsPanel.type = "actions";
2615
- const ActionsPanelContent = () => {
2616
- const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2617
- const [
2618
- {
2619
- query: { status = "draft" }
2620
- }
2621
- ] = strapiAdmin.useQueryParams();
2622
- const { model, id, document, meta, collectionType } = useDoc();
2623
- const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
2624
- const props = {
2625
- activeTab: status,
2626
- model,
2627
- documentId: id,
2628
- document: isCloning ? void 0 : document,
2629
- meta: isCloning ? void 0 : meta,
2630
- collectionType
2631
- };
2632
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
2633
- /* @__PURE__ */ jsxRuntime.jsx(
2634
- strapiAdmin.DescriptionComponentRenderer,
2635
- {
2636
- props,
2637
- descriptions: plugins["content-manager"].apis.getDocumentActions(),
2638
- children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
2639
- }
2640
- ),
2641
- /* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
2642
- ] });
2643
- };
2644
- const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2645
- return /* @__PURE__ */ jsxRuntime.jsxs(
2646
- designSystem.Flex,
2647
- {
2648
- ref,
2649
- tag: "aside",
2650
- "aria-labelledby": "additional-information",
2651
- background: "neutral0",
2652
- borderColor: "neutral150",
2653
- hasRadius: true,
2654
- paddingBottom: 4,
2655
- paddingLeft: 4,
2656
- paddingRight: 4,
2657
- paddingTop: 4,
2658
- shadow: "tableShadow",
2659
- gap: 3,
2660
- direction: "column",
2661
- justifyContent: "stretch",
2662
- alignItems: "flex-start",
2663
- children: [
2664
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
2665
- children
2666
- ]
2667
- }
2668
- );
2669
- });
2670
- const HOOKS = {
2671
- /**
2672
- * Hook that allows to mutate the displayed headers of the list view table
2673
- * @constant
2674
- * @type {string}
2675
- */
2676
- INJECT_COLUMN_IN_TABLE: "Admin/CM/pages/ListView/inject-column-in-table",
2677
- /**
2678
- * Hook that allows to mutate the CM's collection types links pre-set filters
2679
- * @constant
2680
- * @type {string}
2681
- */
2682
- MUTATE_COLLECTION_TYPES_LINKS: "Admin/CM/pages/App/mutate-collection-types-links",
2683
- /**
2684
- * Hook that allows to mutate the CM's edit view layout
2685
- * @constant
2686
- * @type {string}
2687
- */
2688
- MUTATE_EDIT_VIEW_LAYOUT: "Admin/CM/pages/EditView/mutate-edit-view-layout",
2689
- /**
2690
- * Hook that allows to mutate the CM's single types links pre-set filters
2691
- * @constant
2692
- * @type {string}
2693
- */
2694
- MUTATE_SINGLE_TYPES_LINKS: "Admin/CM/pages/App/mutate-single-types-links"
2695
- };
2696
- const contentTypesApi = contentManagerApi.injectEndpoints({
2697
- endpoints: (builder) => ({
2698
- getContentTypeConfiguration: builder.query({
2699
- query: (uid) => ({
2700
- url: `/content-manager/content-types/${uid}/configuration`,
2701
- method: "GET"
2702
- }),
2703
- transformResponse: (response) => response.data,
2704
- providesTags: (_result, _error, uid) => [
2705
- { type: "ContentTypesConfiguration", id: uid },
2706
- { type: "ContentTypeSettings", id: "LIST" }
2707
- ]
2708
- }),
2709
- getAllContentTypeSettings: builder.query({
2710
- query: () => "/content-manager/content-types-settings",
2711
- transformResponse: (response) => response.data,
2712
- providesTags: [{ type: "ContentTypeSettings", id: "LIST" }]
2713
- }),
2714
- updateContentTypeConfiguration: builder.mutation({
2715
- query: ({ uid, ...body }) => ({
2716
- url: `/content-manager/content-types/${uid}/configuration`,
2717
- method: "PUT",
2718
- data: body
2719
- }),
2720
- transformResponse: (response) => response.data,
2721
- invalidatesTags: (_result, _error, { uid }) => [
2722
- { type: "ContentTypesConfiguration", id: uid },
2723
- { type: "ContentTypeSettings", id: "LIST" },
2724
- // Is this necessary?
2725
- { type: "InitialData" }
2726
- ]
2727
- })
2728
- })
2729
- });
2730
- const {
2731
- useGetContentTypeConfigurationQuery,
2732
- useGetAllContentTypeSettingsQuery,
2733
- useUpdateContentTypeConfigurationMutation
2734
- } = contentTypesApi;
2735
- const checkIfAttributeIsDisplayable = (attribute) => {
2736
- const { type } = attribute;
2737
- if (type === "relation") {
2738
- return !attribute.relation.toLowerCase().includes("morph");
2739
- }
2740
- return !["json", "dynamiczone", "richtext", "password", "blocks"].includes(type) && !!type;
2741
- };
2742
- const getMainField = (attribute, mainFieldName, { schemas, components }) => {
2743
- if (!mainFieldName) {
2744
- return void 0;
2745
- }
2746
- const mainFieldType = attribute.type === "component" ? components[attribute.component].attributes[mainFieldName].type : (
2747
- // @ts-expect-error – `targetModel` does exist on the attribute for a relation.
2748
- schemas.find((schema) => schema.uid === attribute.targetModel)?.attributes[mainFieldName].type
2749
- );
2750
- return {
2751
- name: mainFieldName,
2752
- type: mainFieldType ?? "string"
2753
- };
2754
- };
2755
- const DEFAULT_SETTINGS = {
2756
- bulkable: false,
2757
- filterable: false,
2758
- searchable: false,
2759
- pagination: false,
2760
- defaultSortBy: "",
2761
- defaultSortOrder: "asc",
2762
- mainField: "id",
2763
- pageSize: 10
2764
- };
2765
- const useDocumentLayout = (model) => {
2766
- const { schema, components } = useDocument({ model, collectionType: "" }, { skip: true });
2767
- const [{ query }] = strapiAdmin.useQueryParams();
2768
- const runHookWaterfall = strapiAdmin.useStrapiApp("useDocumentLayout", (state) => state.runHookWaterfall);
2769
- const { toggleNotification } = strapiAdmin.useNotification();
2770
- const { _unstableFormatAPIError: formatAPIError } = strapiAdmin.useAPIErrorHandler();
2771
- const { isLoading: isLoadingSchemas, schemas } = useContentTypeSchema();
2772
- const {
2773
- data,
2774
- isLoading: isLoadingConfigs,
2775
- error,
2776
- isFetching: isFetchingConfigs
2777
- } = useGetContentTypeConfigurationQuery(model);
2778
- const isLoading = isLoadingSchemas || isFetchingConfigs || isLoadingConfigs;
2779
- React__namespace.useEffect(() => {
2780
- if (error) {
2781
- toggleNotification({
2782
- type: "danger",
2783
- message: formatAPIError(error)
2784
- });
2785
- }
2786
- }, [error, formatAPIError, toggleNotification]);
2787
- const editLayout = React__namespace.useMemo(
2788
- () => data && !isLoading ? formatEditLayout(data, { schemas, schema, components }) : {
2789
- layout: [],
2790
- components: {},
2791
- metadatas: {},
2792
- options: {},
2793
- settings: DEFAULT_SETTINGS
2794
- },
2795
- [data, isLoading, schemas, schema, components]
2796
- );
2797
- const listLayout = React__namespace.useMemo(() => {
2798
- return data && !isLoading ? formatListLayout(data, { schemas, schema, components }) : {
2799
- layout: [],
2800
- metadatas: {},
2801
- options: {},
2802
- settings: DEFAULT_SETTINGS
2803
- };
2804
- }, [data, isLoading, schemas, schema, components]);
2805
- const { layout: edit } = React__namespace.useMemo(
2806
- () => runHookWaterfall(HOOKS.MUTATE_EDIT_VIEW_LAYOUT, {
2807
- layout: editLayout,
2808
- query
2809
- }),
2810
- [editLayout, query, runHookWaterfall]
2811
- );
2812
- return {
2813
- error,
2814
- isLoading,
2815
- edit,
2816
- list: listLayout
2817
- };
2818
- };
2819
- const useDocLayout = () => {
2820
- const { model } = useDoc();
2821
- return useDocumentLayout(model);
2822
- };
2823
- const formatEditLayout = (data, {
2824
- schemas,
2825
- schema,
2826
- components
2827
- }) => {
2828
- let currentPanelIndex = 0;
2829
- const panelledEditAttributes = convertEditLayoutToFieldLayouts(
2830
- data.contentType.layouts.edit,
2831
- schema?.attributes,
2832
- data.contentType.metadatas,
2833
- { configurations: data.components, schemas: components },
2834
- schemas
2835
- ).reduce((panels, row) => {
2836
- if (row.some((field) => field.type === "dynamiczone")) {
2837
- panels.push([row]);
2838
- currentPanelIndex += 2;
2839
- } else {
2840
- if (!panels[currentPanelIndex]) {
2841
- panels.push([]);
2842
- }
2843
- panels[currentPanelIndex].push(row);
2844
- }
2845
- return panels;
2846
- }, []);
2847
- const componentEditAttributes = Object.entries(data.components).reduce(
2848
- (acc, [uid, configuration]) => {
2849
- acc[uid] = {
2850
- layout: convertEditLayoutToFieldLayouts(
2851
- configuration.layouts.edit,
2852
- components[uid].attributes,
2853
- configuration.metadatas,
2854
- { configurations: data.components, schemas: components }
2855
- ),
2856
- settings: {
2857
- ...configuration.settings,
2858
- icon: components[uid].info.icon,
2859
- displayName: components[uid].info.displayName
2860
- }
2861
- };
2862
- return acc;
2863
- },
2864
- {}
2865
- );
2866
- const editMetadatas = Object.entries(data.contentType.metadatas).reduce(
2867
- (acc, [attribute, metadata]) => {
2868
- return {
2869
- ...acc,
2870
- [attribute]: metadata.edit
2871
- };
2872
- },
2873
- {}
2874
- );
2839
+ ConfigureTheViewAction.type = "configure-the-view";
2840
+ const EditTheModelAction = ({ model }) => {
2841
+ const navigate = reactRouterDom.useNavigate();
2842
+ const { formatMessage } = reactIntl.useIntl();
2875
2843
  return {
2876
- layout: panelledEditAttributes,
2877
- components: componentEditAttributes,
2878
- metadatas: editMetadatas,
2879
- settings: {
2880
- ...data.contentType.settings,
2881
- displayName: schema?.info.displayName
2844
+ label: formatMessage({
2845
+ id: "content-manager.link-to-ctb",
2846
+ defaultMessage: "Edit the model"
2847
+ }),
2848
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {}),
2849
+ onClick: () => {
2850
+ navigate(`/plugins/content-type-builder/content-types/${model}`);
2882
2851
  },
2883
- options: {
2884
- ...schema?.options,
2885
- ...schema?.pluginOptions,
2886
- ...data.contentType.options
2887
- }
2852
+ position: "header"
2888
2853
  };
2889
2854
  };
2890
- const convertEditLayoutToFieldLayouts = (rows, attributes = {}, metadatas, components, schemas = []) => {
2891
- return rows.map(
2892
- (row) => row.map((field) => {
2893
- const attribute = attributes[field.name];
2894
- if (!attribute) {
2895
- return null;
2855
+ EditTheModelAction.type = "edit-the-model";
2856
+ const DeleteAction$1 = ({ documentId, model, collectionType, document }) => {
2857
+ const navigate = reactRouterDom.useNavigate();
2858
+ const { formatMessage } = reactIntl.useIntl();
2859
+ const listViewPathMatch = reactRouterDom.useMatch(LIST_PATH);
2860
+ const canDelete = useDocumentRBAC("DeleteAction", (state) => state.canDelete);
2861
+ const { delete: deleteAction } = useDocumentActions();
2862
+ const { toggleNotification } = strapiAdmin.useNotification();
2863
+ const setSubmitting = strapiAdmin.useForm("DeleteAction", (state) => state.setSubmitting);
2864
+ const isLocalized = document?.locale != null;
2865
+ return {
2866
+ disabled: !canDelete || !document,
2867
+ label: formatMessage(
2868
+ {
2869
+ id: "content-manager.actions.delete.label",
2870
+ defaultMessage: "Delete entry{isLocalized, select, true { (all locales)} other {}}"
2871
+ },
2872
+ { isLocalized }
2873
+ ),
2874
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
2875
+ dialog: {
2876
+ type: "dialog",
2877
+ title: formatMessage({
2878
+ id: "app.components.ConfirmDialog.title",
2879
+ defaultMessage: "Confirmation"
2880
+ }),
2881
+ content: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
2882
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.WarningCircle, { width: "24px", height: "24px", fill: "danger600" }),
2883
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "p", variant: "omega", textAlign: "center", children: formatMessage({
2884
+ id: "content-manager.actions.delete.dialog.body",
2885
+ defaultMessage: "Are you sure?"
2886
+ }) })
2887
+ ] }),
2888
+ onConfirm: async () => {
2889
+ if (!listViewPathMatch) {
2890
+ setSubmitting(true);
2891
+ }
2892
+ try {
2893
+ if (!documentId && collectionType !== SINGLE_TYPES) {
2894
+ console.error(
2895
+ "You're trying to delete a document without an id, this is likely a bug with Strapi. Please open an issue."
2896
+ );
2897
+ toggleNotification({
2898
+ message: formatMessage({
2899
+ id: "content-manager.actions.delete.error",
2900
+ defaultMessage: "An error occurred while trying to delete the document."
2901
+ }),
2902
+ type: "danger"
2903
+ });
2904
+ return;
2905
+ }
2906
+ const res = await deleteAction({
2907
+ documentId,
2908
+ model,
2909
+ collectionType,
2910
+ params: {
2911
+ locale: "*"
2912
+ }
2913
+ });
2914
+ if (!("error" in res)) {
2915
+ navigate({ pathname: `../${collectionType}/${model}` }, { replace: true });
2916
+ }
2917
+ } finally {
2918
+ if (!listViewPathMatch) {
2919
+ setSubmitting(false);
2920
+ }
2921
+ }
2896
2922
  }
2897
- const { edit: metadata } = metadatas[field.name];
2898
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2899
- return {
2900
- attribute,
2901
- disabled: !metadata.editable,
2902
- hint: metadata.description,
2903
- label: metadata.label ?? "",
2904
- name: field.name,
2905
- // @ts-expect-error – mainField does exist on the metadata for a relation.
2906
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2907
- schemas,
2908
- components: components?.schemas ?? {}
2909
- }),
2910
- placeholder: metadata.placeholder ?? "",
2911
- required: attribute.required ?? false,
2912
- size: field.size,
2913
- unique: "unique" in attribute ? attribute.unique : false,
2914
- visible: metadata.visible ?? true,
2915
- type: attribute.type
2916
- };
2917
- }).filter((field) => field !== null)
2918
- );
2919
- };
2920
- const formatListLayout = (data, {
2921
- schemas,
2922
- schema,
2923
- components
2924
- }) => {
2925
- const listMetadatas = Object.entries(data.contentType.metadatas).reduce(
2926
- (acc, [attribute, metadata]) => {
2927
- return {
2928
- ...acc,
2929
- [attribute]: metadata.list
2930
- };
2931
2923
  },
2932
- {}
2933
- );
2934
- const listAttributes = convertListLayoutToFieldLayouts(
2935
- data.contentType.layouts.list,
2936
- schema?.attributes,
2937
- listMetadatas,
2938
- { configurations: data.components, schemas: components },
2939
- schemas
2940
- );
2941
- return {
2942
- layout: listAttributes,
2943
- settings: { ...data.contentType.settings, displayName: schema?.info.displayName },
2944
- metadatas: listMetadatas,
2945
- options: {
2946
- ...schema?.options,
2947
- ...schema?.pluginOptions,
2948
- ...data.contentType.options
2924
+ variant: "danger",
2925
+ position: ["header", "table-row"]
2926
+ };
2927
+ };
2928
+ DeleteAction$1.type = "delete";
2929
+ const DEFAULT_HEADER_ACTIONS = [EditTheModelAction, ConfigureTheViewAction, DeleteAction$1];
2930
+ const Panels = () => {
2931
+ const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2932
+ const [
2933
+ {
2934
+ query: { status }
2935
+ }
2936
+ ] = strapiAdmin.useQueryParams({
2937
+ status: "draft"
2938
+ });
2939
+ const { model, id, document, meta, collectionType } = useDoc();
2940
+ const plugins = strapiAdmin.useStrapiApp("Panels", (state) => state.plugins);
2941
+ const props = {
2942
+ activeTab: status,
2943
+ model,
2944
+ documentId: id,
2945
+ document: isCloning ? void 0 : document,
2946
+ meta: isCloning ? void 0 : meta,
2947
+ collectionType
2948
+ };
2949
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
2950
+ strapiAdmin.DescriptionComponentRenderer,
2951
+ {
2952
+ props,
2953
+ descriptions: plugins["content-manager"].apis.getEditViewSidePanels(),
2954
+ children: (panels) => panels.map(({ content, id: id2, ...description }) => /* @__PURE__ */ jsxRuntime.jsx(Panel, { ...description, children: content }, id2))
2949
2955
  }
2956
+ ) });
2957
+ };
2958
+ const ActionsPanel = () => {
2959
+ const { formatMessage } = reactIntl.useIntl();
2960
+ return {
2961
+ title: formatMessage({
2962
+ id: "content-manager.containers.edit.panels.default.title",
2963
+ defaultMessage: "Entry"
2964
+ }),
2965
+ content: /* @__PURE__ */ jsxRuntime.jsx(ActionsPanelContent, {})
2950
2966
  };
2951
2967
  };
2952
- const convertListLayoutToFieldLayouts = (columns, attributes = {}, metadatas, components, schemas = []) => {
2953
- return columns.map((name) => {
2954
- const attribute = attributes[name];
2955
- if (!attribute) {
2956
- return null;
2968
+ ActionsPanel.type = "actions";
2969
+ const ActionsPanelContent = () => {
2970
+ const isCloning = reactRouterDom.useMatch(CLONE_PATH) !== null;
2971
+ const [
2972
+ {
2973
+ query: { status = "draft" }
2957
2974
  }
2958
- const metadata = metadatas[name];
2959
- const settings = attribute.type === "component" && components ? components.configurations[attribute.component].settings : {};
2960
- return {
2961
- attribute,
2962
- label: metadata.label ?? "",
2963
- mainField: getMainField(attribute, metadata.mainField || settings.mainField, {
2964
- schemas,
2965
- components: components?.schemas ?? {}
2966
- }),
2967
- name,
2968
- searchable: metadata.searchable ?? true,
2969
- sortable: metadata.sortable ?? true
2970
- };
2971
- }).filter((field) => field !== null);
2975
+ ] = strapiAdmin.useQueryParams();
2976
+ const { model, id, document, meta, collectionType } = useDoc();
2977
+ const plugins = strapiAdmin.useStrapiApp("ActionsPanel", (state) => state.plugins);
2978
+ const props = {
2979
+ activeTab: status,
2980
+ model,
2981
+ documentId: id,
2982
+ document: isCloning ? void 0 : document,
2983
+ meta: isCloning ? void 0 : meta,
2984
+ collectionType
2985
+ };
2986
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, width: "100%", children: [
2987
+ /* @__PURE__ */ jsxRuntime.jsx(
2988
+ strapiAdmin.DescriptionComponentRenderer,
2989
+ {
2990
+ props,
2991
+ descriptions: plugins["content-manager"].apis.getDocumentActions(),
2992
+ children: (actions2) => /* @__PURE__ */ jsxRuntime.jsx(DocumentActions, { actions: actions2 })
2993
+ }
2994
+ ),
2995
+ /* @__PURE__ */ jsxRuntime.jsx(InjectionZone, { area: "editView.right-links", slug: model })
2996
+ ] });
2972
2997
  };
2998
+ const Panel = React__namespace.forwardRef(({ children, title }, ref) => {
2999
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3000
+ designSystem.Flex,
3001
+ {
3002
+ ref,
3003
+ tag: "aside",
3004
+ "aria-labelledby": "additional-information",
3005
+ background: "neutral0",
3006
+ borderColor: "neutral150",
3007
+ hasRadius: true,
3008
+ paddingBottom: 4,
3009
+ paddingLeft: 4,
3010
+ paddingRight: 4,
3011
+ paddingTop: 4,
3012
+ shadow: "tableShadow",
3013
+ gap: 3,
3014
+ direction: "column",
3015
+ justifyContent: "stretch",
3016
+ alignItems: "flex-start",
3017
+ children: [
3018
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { tag: "h2", variant: "sigma", textTransform: "uppercase", children: title }),
3019
+ children
3020
+ ]
3021
+ }
3022
+ );
3023
+ });
2973
3024
  const ConfirmBulkActionDialog = ({
2974
3025
  onToggleDialog,
2975
3026
  isOpen = false,
@@ -3966,7 +4017,7 @@ const index = {
3966
4017
  app.router.addRoute({
3967
4018
  path: "content-manager/*",
3968
4019
  lazy: async () => {
3969
- const { Layout } = await Promise.resolve().then(() => require("./layout-bE-WUnQ0.js"));
4020
+ const { Layout } = await Promise.resolve().then(() => require("./layout-CxxkX9jY.js"));
3970
4021
  return {
3971
4022
  Component: Layout
3972
4023
  };
@@ -3983,7 +4034,7 @@ const index = {
3983
4034
  async registerTrads({ locales }) {
3984
4035
  const importedTrads = await Promise.all(
3985
4036
  locales.map((locale) => {
3986
- 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-BVzUkPxZ.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 }) => {
4037
+ return __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => Promise.resolve().then(() => require("./ar-BUUWXIYu.js")), "./translations/ca.json": () => Promise.resolve().then(() => require("./ca-Cmk45QO6.js")), "./translations/cs.json": () => Promise.resolve().then(() => require("./cs-CkJy6B2v.js")), "./translations/de.json": () => Promise.resolve().then(() => require("./de-CCEmbAah.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-BlhnxQfj.js")), "./translations/es.json": () => Promise.resolve().then(() => require("./es-EUonQTon.js")), "./translations/eu.json": () => Promise.resolve().then(() => require("./eu-VDH-3ovk.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-B7kGGg3E.js")), "./translations/gu.json": () => Promise.resolve().then(() => require("./gu-BRmF601H.js")), "./translations/hi.json": () => Promise.resolve().then(() => require("./hi-CCJBptSq.js")), "./translations/hu.json": () => Promise.resolve().then(() => require("./hu-sNV_yLYy.js")), "./translations/id.json": () => Promise.resolve().then(() => require("./id-B5Ser98A.js")), "./translations/it.json": () => Promise.resolve().then(() => require("./it-DkBIs7vD.js")), "./translations/ja.json": () => Promise.resolve().then(() => require("./ja-CcFe8diO.js")), "./translations/ko.json": () => Promise.resolve().then(() => require("./ko-woFZPmLk.js")), "./translations/ml.json": () => Promise.resolve().then(() => require("./ml-C2W8N8k1.js")), "./translations/ms.json": () => Promise.resolve().then(() => require("./ms-BuFotyP_.js")), "./translations/nl.json": () => Promise.resolve().then(() => require("./nl-bbEOHChV.js")), "./translations/pl.json": () => Promise.resolve().then(() => require("./pl-uzwG-hk7.js")), "./translations/pt-BR.json": () => Promise.resolve().then(() => require("./pt-BR-BiOz37D9.js")), "./translations/pt.json": () => Promise.resolve().then(() => require("./pt-CeXQuq50.js")), "./translations/ru.json": () => Promise.resolve().then(() => require("./ru-BT3ybNny.js")), "./translations/sa.json": () => Promise.resolve().then(() => require("./sa-CcvkYInH.js")), "./translations/sk.json": () => Promise.resolve().then(() => require("./sk-CvY09Xjv.js")), "./translations/sv.json": () => Promise.resolve().then(() => require("./sv-MYDuzgvT.js")), "./translations/th.json": () => Promise.resolve().then(() => require("./th-D9_GfAjc.js")), "./translations/tr.json": () => Promise.resolve().then(() => require("./tr-D9UH-O_R.js")), "./translations/uk.json": () => Promise.resolve().then(() => require("./uk-C8EiqJY7.js")), "./translations/vi.json": () => Promise.resolve().then(() => require("./vi-CJlYDheJ.js")), "./translations/zh-Hans.json": () => Promise.resolve().then(() => require("./zh-Hans-9kOncHGw.js")), "./translations/zh.json": () => Promise.resolve().then(() => require("./zh-CQQfszqR.js")) }), `./translations/${locale}.json`).then(({ default: data }) => {
3987
4038
  return {
3988
4039
  data: prefixPluginTranslations(data, PLUGIN_ID),
3989
4040
  locale
@@ -4029,6 +4080,7 @@ exports.getMainField = getMainField;
4029
4080
  exports.getTranslation = getTranslation;
4030
4081
  exports.index = index;
4031
4082
  exports.setInitialData = setInitialData;
4083
+ exports.useContentManagerContext = useContentManagerContext;
4032
4084
  exports.useContentTypeSchema = useContentTypeSchema;
4033
4085
  exports.useDoc = useDoc;
4034
4086
  exports.useDocLayout = useDocLayout;
@@ -4041,4 +4093,4 @@ exports.useGetAllDocumentsQuery = useGetAllDocumentsQuery;
4041
4093
  exports.useGetContentTypeConfigurationQuery = useGetContentTypeConfigurationQuery;
4042
4094
  exports.useGetInitialDataQuery = useGetInitialDataQuery;
4043
4095
  exports.useUpdateContentTypeConfigurationMutation = useUpdateContentTypeConfigurationMutation;
4044
- //# sourceMappingURL=index-DXiHxy70.js.map
4096
+ //# sourceMappingURL=index-CBX6KyXv.js.map