diff --git a/public/locales/en/settings/general/config-changer.json b/public/locales/en/settings/general/config-changer.json index 812916aab..256f82bd9 100644 --- a/public/locales/en/settings/general/config-changer.json +++ b/public/locales/en/settings/general/config-changer.json @@ -43,6 +43,10 @@ "deleteFailed": { "title": "Config delete failed", "message": "Config delete failed" + }, + "deleteFailedDefaultConfig": { + "title": "Default config can't be deleted", + "message": "Configuration was not deleted from the file system" } } }, diff --git a/src/components/Settings/Common/Config/ConfigActions.tsx b/src/components/Settings/Common/Config/ConfigActions.tsx index 6a1232b04..77db31618 100644 --- a/src/components/Settings/Common/Config/ConfigActions.tsx +++ b/src/components/Settings/Common/Config/ConfigActions.tsx @@ -1,9 +1,11 @@ import { ActionIcon, Center, createStyles, Flex, Text, useMantineTheme } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; -import { IconCopy, IconDownload, IconTrash } from '@tabler/icons'; +import { showNotification } from '@mantine/notifications'; +import { IconCheck, IconCopy, IconDownload, IconTrash } from '@tabler/icons'; import fileDownload from 'js-file-download'; import { useTranslation } from 'next-i18next'; import { useConfigContext } from '../../../../config/provider'; +import { useConfigStore } from '../../../../config/store'; import { useDeleteConfigMutation } from '../../../../tools/config/mutations/useDeleteConfigMutation'; import Tip from '../../../layout/Tip'; import { CreateConfigCopyModal } from './CreateCopyModal'; @@ -12,6 +14,7 @@ export default function ConfigActions() { const { t } = useTranslation(['settings/general/config-changer', 'settings/common']); const [createCopyModalOpened, createCopyModal] = useDisclosure(false); const { config } = useConfigContext(); + const { removeConfig } = useConfigStore(); const { mutateAsync } = useDeleteConfigMutation(config?.configProperties.name ?? 'default'); if (!config) return null; @@ -22,7 +25,26 @@ export default function ConfigActions() { }; const handleDeletion = async () => { - await mutateAsync(); + const response = await mutateAsync(); + + if (response.message) { + showNotification({ + title: t('buttons.delete.notifications.deleteFailedDefaultConfig.title'), + message: t('buttons.delete.notifications.deleteFailedDefaultConfig.message'), + }); + return; + } + + showNotification({ + title: t('buttons.delete.notifications.deleted.title'), + icon: , + color: 'green', + autoClose: 1500, + radius: 'md', + message: t('buttons.delete.notifications.deleted.message'), + }); + + removeConfig(config?.configProperties.name ?? 'default'); }; const { classes } = useStyles(); diff --git a/src/config/store.ts b/src/config/store.ts index 4d32ef860..a3a943030 100644 --- a/src/config/store.ts +++ b/src/config/store.ts @@ -27,6 +27,12 @@ export const useConfigStore = create((set, get) => ({ } axios.put(`/api/configs/${name}`, { ...config }); }, + removeConfig: (name: string) => { + set((old) => ({ + ...old, + configs: old.configs.filter((x) => x.value.configProperties.name !== name), + })); + }, updateConfig: async ( name, updateCallback: (previous: ConfigType) => ConfigType, @@ -72,6 +78,7 @@ interface UseConfigStoreType { config: ConfigType, shouldSaveConfigToFileSystem: boolean ) => Promise; + removeConfig: (name: string) => void; updateConfig: ( name: string, updateCallback: (previous: ConfigType) => ConfigType, diff --git a/src/pages/api/configs/[slug].ts b/src/pages/api/configs/[slug].ts index 2f628d00e..4f99916fe 100644 --- a/src/pages/api/configs/[slug].ts +++ b/src/pages/api/configs/[slug].ts @@ -136,6 +136,13 @@ function Delete(req: NextApiRequest, res: NextApiResponse) { }); } + if (slug.toLowerCase() === 'default') { + Consola.error('Rejected config deletion because default configuration can\'t be deleted'); + return res.status(403).json({ + message: 'Default config can\'t be deleted', + }); + } + // Loop over all the files in the /data/configs directory // Get all the configs in the /data/configs folder // All the files that end in ".json" diff --git a/src/tools/config/mutations/useDeleteConfigMutation.tsx b/src/tools/config/mutations/useDeleteConfigMutation.tsx index e642e2f13..6885d79e6 100644 --- a/src/tools/config/mutations/useDeleteConfigMutation.tsx +++ b/src/tools/config/mutations/useDeleteConfigMutation.tsx @@ -9,17 +9,6 @@ export const useDeleteConfigMutation = (configName: string) => { return useMutation({ mutationKey: ['configs/delete', { configName }], mutationFn: () => fetchDeletion(configName), - onSuccess() { - showNotification({ - title: t('buttons.delete.notifications.deleted.title'), - icon: , - color: 'green', - autoClose: 1500, - radius: 'md', - message: t('buttons.delete.notifications.deleted.message'), - }); - // TODO: set config to default config and use fallback config if necessary - }, onError() { showNotification({ title: t('buttons.delete.notifications.deleteFailed.title'),