diff --git a/public/locales/en/settings/general/config-changer.json b/public/locales/en/settings/general/config-changer.json
index ccd79607a..130273158 100644
--- a/public/locales/en/settings/general/config-changer.json
+++ b/public/locales/en/settings/general/config-changer.json
@@ -18,6 +18,14 @@
"configSaved": {
"title": "Config saved",
"message": "Config saved as {{configName}}"
+ },
+ "configCopied": {
+ "title": "Config copied",
+ "message": "Config copied as {{configName}}"
+ },
+ "configNotCopied": {
+ "title": "Unable to copy config",
+ "message": "Your config was not copied as {{configName}}"
}
}
},
diff --git a/src/components/Settings/Common/Config/ConfigActions.tsx b/src/components/Settings/Common/Config/ConfigActions.tsx
index 1978c9542..46a71b03d 100644
--- a/src/components/Settings/Common/Config/ConfigActions.tsx
+++ b/src/components/Settings/Common/Config/ConfigActions.tsx
@@ -1,11 +1,10 @@
import { ActionIcon, Center, createStyles, Flex, Text, useMantineTheme } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
-import { showNotification } from '@mantine/notifications';
-import { IconCheck, IconCopy, IconDownload, IconTrash, IconX } from '@tabler/icons';
-import { useMutation } from '@tanstack/react-query';
+import { IconCopy, IconDownload, IconTrash } from '@tabler/icons';
import fileDownload from 'js-file-download';
import { useTranslation } from 'next-i18next';
import { useConfigContext } from '../../../../config/provider';
+import { useDeleteConfigMutation } from '../../../../tools/config/mutations/useDeleteConfigMutation';
import Tip from '../../../layout/Tip';
import { CreateConfigCopyModal } from './CreateCopyModal';
@@ -79,36 +78,3 @@ const useStyles = createStyles(() => ({
padding: 10,
},
}));
-
-const useDeleteConfigMutation = (configName: string) => {
- const { t } = useTranslation(['settings/general/config-changer']);
-
- return useMutation({
- mutationKey: ['config/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'),
- icon: ,
- color: 'red',
- autoClose: 1500,
- radius: 'md',
- message: t('buttons.delete.notifications.deleteFailed.message'),
- });
- },
- });
-};
-
-const fetchDeletion = async (configName: string) =>
- (await fetch(`/api/configs/${configName}`)).json();
diff --git a/src/components/Settings/Common/Config/CreateCopyModal.tsx b/src/components/Settings/Common/Config/CreateCopyModal.tsx
index b88ba736d..c5f0b874e 100644
--- a/src/components/Settings/Common/Config/CreateCopyModal.tsx
+++ b/src/components/Settings/Common/Config/CreateCopyModal.tsx
@@ -1,9 +1,7 @@
import { Button, Group, Modal, TextInput, Title } from '@mantine/core';
import { useForm } from '@mantine/form';
-import { showNotification } from '@mantine/notifications';
-import { IconCheck } from '@tabler/icons';
import { useTranslation } from 'next-i18next';
-import { useConfigContext } from '../../../../config/provider';
+import { useCopyConfigMutation } from '../../../../tools/config/mutations/useCopyConfigMutation';
interface CreateConfigCopyModalProps {
opened: boolean;
@@ -17,7 +15,7 @@ export const CreateConfigCopyModal = ({
initialConfigName,
}: CreateConfigCopyModalProps) => {
const { t } = useTranslation(['settings/general/config-changer']);
- const { config } = useConfigContext();
+
const form = useForm({
initialValues: {
configName: initialConfigName,
@@ -27,23 +25,18 @@ export const CreateConfigCopyModal = ({
},
});
+ const { mutateAsync } = useCopyConfigMutation(form.values.configName);
+
const handleClose = () => {
form.setFieldValue('configName', initialConfigName);
closeModal();
};
- const handleSubmit = (values: typeof form.values) => {
+ const handleSubmit = async (values: typeof form.values) => {
if (!form.isValid) return;
- // TODO: create config file with copied data
+
+ await mutateAsync();
closeModal();
- showNotification({
- title: t('modal.events.configSaved.title'),
- icon: ,
- color: 'green',
- autoClose: 1500,
- radius: 'md',
- message: t('modal.events.configSaved.message', { configName: values.configName }),
- });
};
return (
diff --git a/src/pages/api/configs/[slug].ts b/src/pages/api/configs/[slug].ts
index e9f14d3c1..c43309c9f 100644
--- a/src/pages/api/configs/[slug].ts
+++ b/src/pages/api/configs/[slug].ts
@@ -71,16 +71,20 @@ function Get(req: NextApiRequest, res: NextApiResponse) {
message: 'Wrong request',
});
}
+
// Loop over all the files in the /data/configs directory
const files = fs.readdirSync('data/configs');
+
// Strip the .json extension from the file name
const configs = files.map((file) => file.replace('.json', ''));
+
// If the target is not in the list of files, return an error
if (!configs.includes(slug)) {
return res.status(404).json({
message: 'Target not found',
});
}
+
// Return the content of the file
return res.status(200).json(fs.readFileSync(path.join('data/configs', `${slug}.json`), 'utf8'));
}
@@ -90,12 +94,15 @@ export default async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === 'PUT') {
return Put(req, res);
}
+
if (req.method === 'DELETE') {
return Delete(req, res);
}
+
if (req.method === 'GET') {
return Get(req, res);
}
+
return res.status(405).json({
statusCode: 405,
message: 'Method not allowed',
@@ -110,16 +117,20 @@ function Delete(req: NextApiRequest, res: NextApiResponse) {
message: 'Wrong request',
});
}
+
// Loop over all the files in the /data/configs directory
const files = fs.readdirSync('data/configs');
+
// Strip the .json extension from the file name
const configs = files.map((file) => file.replace('.json', ''));
+
// If the target is not in the list of files, return an error
if (!configs.includes(slug)) {
return res.status(404).json({
message: 'Target not found',
});
}
+
// Delete the file
fs.unlinkSync(path.join('data/configs', `${slug}.json`));
return res.status(200).json({
diff --git a/src/pages/api/configs/index.ts b/src/pages/api/configs/index.ts
index 78aabc4e8..07abc7507 100644
--- a/src/pages/api/configs/index.ts
+++ b/src/pages/api/configs/index.ts
@@ -12,12 +12,6 @@ function Get(req: NextApiRequest, res: NextApiResponse) {
export default async (req: NextApiRequest, res: NextApiResponse) => {
// Filter out if the reuqest is a POST or a GET
- if (req.method === 'POST') {
- return res.status(405).json({
- statusCode: 405,
- message: 'Method not allowed',
- });
- }
if (req.method === 'GET') {
return Get(req, res);
}
diff --git a/src/tools/config/mutations/useCopyConfigMutation.tsx b/src/tools/config/mutations/useCopyConfigMutation.tsx
new file mode 100644
index 000000000..c3af88e56
--- /dev/null
+++ b/src/tools/config/mutations/useCopyConfigMutation.tsx
@@ -0,0 +1,51 @@
+import { showNotification } from '@mantine/notifications';
+import { IconCheck, IconX } from '@tabler/icons';
+import { useMutation } from '@tanstack/react-query';
+import { useTranslation } from 'next-i18next';
+import { useConfigContext } from '../../../config/provider';
+import { ConfigType } from '../../../types/config';
+
+export const useCopyConfigMutation = (configName: string) => {
+ const { config } = useConfigContext();
+ const { t } = useTranslation(['settings/general/config-changer']);
+
+ return useMutation({
+ mutationKey: ['configs/copy', { configName }],
+ mutationFn: () => fetchCopy(configName, config),
+ onSuccess() {
+ showNotification({
+ title: t('modal.events.configCopied.title'),
+ icon: ,
+ color: 'green',
+ autoClose: 1500,
+ radius: 'md',
+ message: t('modal.events.configCopied.message', { configName }),
+ });
+ },
+ onError() {
+ showNotification({
+ title: t('modal.events.configNotCopied.title'),
+ icon: ,
+ color: 'red',
+ autoClose: 1500,
+ radius: 'md',
+ message: t('modal.events.configNotCopied.message', { configName }),
+ });
+ },
+ });
+};
+
+const fetchCopy = async (configName: string, config: ConfigType | undefined) => {
+ if (!config) {
+ throw new Error('config is not defiend');
+ }
+
+ const response = await fetch(`/api/configs/${configName}`, {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(config),
+ });
+ return response.json();
+};
diff --git a/src/tools/config/mutations/useDeleteConfigMutation.tsx b/src/tools/config/mutations/useDeleteConfigMutation.tsx
new file mode 100644
index 000000000..e642e2f13
--- /dev/null
+++ b/src/tools/config/mutations/useDeleteConfigMutation.tsx
@@ -0,0 +1,37 @@
+import { showNotification } from '@mantine/notifications';
+import { IconCheck, IconX } from '@tabler/icons';
+import { useMutation } from '@tanstack/react-query';
+import { useTranslation } from 'next-i18next';
+
+export const useDeleteConfigMutation = (configName: string) => {
+ const { t } = useTranslation(['settings/general/config-changer']);
+
+ 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'),
+ icon: ,
+ color: 'red',
+ autoClose: 1500,
+ radius: 'md',
+ message: t('buttons.delete.notifications.deleteFailed.message'),
+ });
+ },
+ });
+};
+
+const fetchDeletion = async (configName: string) =>
+ (await fetch(`/api/configs/${configName}`, { method: 'DELETE' })).json();