mirror of
https://github.com/C9Glax/tranga-website.git
synced 2025-09-10 11:58:20 +02:00
Settings
This commit is contained in:
@@ -0,0 +1,35 @@
|
|||||||
|
import {ReactNode, useContext, useState} from "react";
|
||||||
|
import {SettingsContext, SettingsItem} from "./Settings.tsx";
|
||||||
|
import {ApiContext} from "../../apiClient/ApiContext.tsx";
|
||||||
|
import {ColorPaletteProp, Input} from "@mui/joy";
|
||||||
|
import * as React from "react";
|
||||||
|
import MarkdownPreview from "@uiw/react-markdown-preview";
|
||||||
|
|
||||||
|
export default function () : ReactNode {
|
||||||
|
const settings = useContext(SettingsContext);
|
||||||
|
const Api = useContext(ApiContext);
|
||||||
|
|
||||||
|
const [scheme, setScheme] = useState<ColorPaletteProp>("neutral");
|
||||||
|
const timerRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
||||||
|
const schemeChanged = (e : React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
clearTimeout(timerRef.current);
|
||||||
|
setScheme("warning");
|
||||||
|
timerRef.current = setTimeout(() => {
|
||||||
|
Api.settingsChapterNamingSchemePartialUpdate(e.target.value)
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok)
|
||||||
|
setScheme("success");
|
||||||
|
else
|
||||||
|
setScheme("danger");
|
||||||
|
})
|
||||||
|
.catch(() => setScheme("danger"));
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsItem title={"Chapter Naming Scheme"}>
|
||||||
|
<MarkdownPreview style={{backgroundColor: "transparent"}} source={"Placeholders:\n * %M Obj Name\n * %V Volume\n * %C Chapter\n * %T Title\n * %A Author (first in list)\n * %I Chapter Internal ID\n * %i Obj Internal ID\n * %Y Year (Obj)\n *\n * ?_(...) replace _ with a value from above:\n * Everything inside the braces will only be added if the value of %_ is not null"} />
|
||||||
|
<Input color={scheme} value={settings?.chapterNamingScheme as string} placeholder={"Scheme"} onChange={schemeChanged} />
|
||||||
|
</SettingsItem>
|
||||||
|
);
|
||||||
|
}
|
33
tranga-website/src/Components/Settings/DownloadLanguage.tsx
Normal file
33
tranga-website/src/Components/Settings/DownloadLanguage.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import {ReactNode, useContext, useState} from "react";
|
||||||
|
import {SettingsContext, SettingsItem} from "./Settings.tsx";
|
||||||
|
import {ApiContext} from "../../apiClient/ApiContext.tsx";
|
||||||
|
import {ColorPaletteProp, Input} from "@mui/joy";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
export default function () : ReactNode {
|
||||||
|
const settings = useContext(SettingsContext);
|
||||||
|
const Api = useContext(ApiContext);
|
||||||
|
|
||||||
|
const [color, setColor] = useState<ColorPaletteProp>("neutral");
|
||||||
|
const timerRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
||||||
|
const languageChanged = (e : React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
clearTimeout(timerRef.current);
|
||||||
|
setColor("warning");
|
||||||
|
timerRef.current = setTimeout(() => {
|
||||||
|
Api.settingsDownloadLanguagePartialUpdate(e.target.value)
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok)
|
||||||
|
setColor("success");
|
||||||
|
else
|
||||||
|
setColor("danger");
|
||||||
|
})
|
||||||
|
.catch(() => setColor("danger"));
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsItem title={"Download Language"}>
|
||||||
|
<Input color={color} value={settings?.downloadLanguage as string} placeholder={"Language code (f.e. 'en')"} onChange={languageChanged} />
|
||||||
|
</SettingsItem>
|
||||||
|
);
|
||||||
|
}
|
33
tranga-website/src/Components/Settings/FlareSolverr.tsx
Normal file
33
tranga-website/src/Components/Settings/FlareSolverr.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import {ReactNode, useContext, useState} from "react";
|
||||||
|
import {SettingsContext, SettingsItem} from "./Settings.tsx";
|
||||||
|
import {ColorPaletteProp, Input} from "@mui/joy";
|
||||||
|
import * as React from "react";
|
||||||
|
import {ApiContext} from "../../apiClient/ApiContext.tsx";
|
||||||
|
|
||||||
|
export default function () : ReactNode {
|
||||||
|
const settings = useContext(SettingsContext);
|
||||||
|
const Api = useContext(ApiContext);
|
||||||
|
|
||||||
|
const [uriColor, setUriColor] = useState<ColorPaletteProp>("neutral");
|
||||||
|
const timerRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
||||||
|
const uriChanged = (e : React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
clearTimeout(timerRef.current);
|
||||||
|
setUriColor("warning");
|
||||||
|
timerRef.current = setTimeout(() => {
|
||||||
|
Api.settingsFlareSolverrUrlCreate(e.target.value)
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok)
|
||||||
|
setUriColor("success");
|
||||||
|
else
|
||||||
|
setUriColor("danger");
|
||||||
|
})
|
||||||
|
.catch(() => setUriColor("danger"));
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsItem title={"FlareSolverr"}>
|
||||||
|
<Input color={uriColor} value={settings?.flareSolverrUrl as string} type={"url"} placeholder={"URL"} onChange={uriChanged} />
|
||||||
|
</SettingsItem>
|
||||||
|
);
|
||||||
|
}
|
13
tranga-website/src/Components/Settings/ImageCompression.tsx
Normal file
13
tranga-website/src/Components/Settings/ImageCompression.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import {ReactNode, useContext} from "react";
|
||||||
|
import {SettingsContext, SettingsItem} from "./Settings.tsx";
|
||||||
|
import {Slider} from "@mui/joy";
|
||||||
|
|
||||||
|
export default function () : ReactNode {
|
||||||
|
const settings = useContext(SettingsContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsItem title={"Image Compression"}>
|
||||||
|
<Slider sx={{marginTop: "20px"}} valueLabelDisplay={"auto"} defaultValue={settings?.imageCompression}></Slider>
|
||||||
|
</SettingsItem>
|
||||||
|
);
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
import {ReactNode} from "react";
|
||||||
|
import {SettingsItem} from "./Settings.tsx";
|
||||||
|
import {Button} from "@mui/joy";
|
||||||
|
import NotificationConnectors from "./AddNotificationConnector.tsx";
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
export default function () : ReactNode {
|
||||||
|
const [notificationConnectorsOpen, setNotificationConnectorsOpen] = React.useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsItem title={"Notification Connectors"}>
|
||||||
|
<Button onClick={() => setNotificationConnectorsOpen(true)}>Add Notification Connector</Button>
|
||||||
|
<NotificationConnectors open={notificationConnectorsOpen} setOpen={setNotificationConnectorsOpen} />
|
||||||
|
</SettingsItem>
|
||||||
|
);
|
||||||
|
}
|
@@ -10,28 +10,31 @@ import {
|
|||||||
} from "@mui/joy";
|
} from "@mui/joy";
|
||||||
import './Settings.css';
|
import './Settings.css';
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {createContext, Dispatch, useContext, useEffect, useState} from "react";
|
import {createContext, Dispatch, ReactNode, useContext, useEffect, useState} from "react";
|
||||||
import {Article} from '@mui/icons-material';
|
import {Article} from '@mui/icons-material';
|
||||||
import {TrangaSettings} from "../../apiClient/data-contracts.ts";
|
import {TrangaSettings} from "../../apiClient/data-contracts.ts";
|
||||||
import {ApiContext} from "../../apiClient/ApiContext.tsx";
|
import {ApiContext} from "../../apiClient/ApiContext.tsx";
|
||||||
import NotificationConnectors from "./AddNotificationConnector.tsx";
|
import NotificationConnectors from "./NotificationConnectors.tsx";
|
||||||
import {SxProps} from "@mui/joy/styles/types";
|
import {SxProps} from "@mui/joy/styles/types";
|
||||||
|
import ImageCompression from "./ImageCompression.tsx";
|
||||||
|
import FlareSolverr from "./FlareSolverr.tsx";
|
||||||
|
import DownloadLanguage from "./DownloadLanguage.tsx";
|
||||||
|
import ChapterNamingScheme from "./ChapterNamingScheme.tsx";
|
||||||
|
|
||||||
export const SettingsContext = createContext<TrangaSettings>({});
|
export const SettingsContext = createContext<TrangaSettings|undefined>(undefined);
|
||||||
|
|
||||||
export default function Settings({setApiUri} : {setApiUri: Dispatch<React.SetStateAction<string>>}) {
|
export default function Settings({setApiUri} : {setApiUri: Dispatch<React.SetStateAction<string>>}) {
|
||||||
const Api = useContext(ApiContext);
|
const Api = useContext(ApiContext);
|
||||||
const [settings, setSettings] = useState<TrangaSettings>({});
|
const [settings, setSettings] = useState<TrangaSettings>();
|
||||||
|
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
|
|
||||||
const [apiUriColor, setApiUriColor] = useState<ColorPaletteProp>("neutral");
|
const [apiUriColor, setApiUriColor] = useState<ColorPaletteProp>("neutral");
|
||||||
const timerRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
const timerRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
||||||
const [apiUriAccordionOpen, setApiUriAccordionOpen] = React.useState(true);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Api.settingsList().then((response) => {
|
Api.settingsList().then((response) => {
|
||||||
setSettings(response.data)
|
setSettings(response.data);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -44,15 +47,13 @@ export default function Settings({setApiUri} : {setApiUri: Dispatch<React.SetSta
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [notificationConnectorsOpen, setNotificationConnectorsOpen] = React.useState(false);
|
|
||||||
|
|
||||||
const ModalStyle : SxProps = {
|
const ModalStyle : SxProps = {
|
||||||
width: "80%",
|
width: "80%",
|
||||||
height: "80%"
|
height: "80%"
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingsContext value={settings}>
|
<SettingsContext.Provider value={settings}>
|
||||||
<Button onClick={() => setOpen(true)}>Settings</Button>
|
<Button onClick={() => setOpen(true)}>Settings</Button>
|
||||||
<Modal open={open} onClose={() => setOpen(false)}>
|
<Modal open={open} onClose={() => setOpen(false)}>
|
||||||
<ModalDialog sx={ModalStyle}>
|
<ModalDialog sx={ModalStyle}>
|
||||||
@@ -60,21 +61,19 @@ export default function Settings({setApiUri} : {setApiUri: Dispatch<React.SetSta
|
|||||||
<DialogTitle>Settings</DialogTitle>
|
<DialogTitle>Settings</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<AccordionGroup>
|
<AccordionGroup>
|
||||||
<Accordion expanded={apiUriAccordionOpen} onChange={(_e, expanded) => setApiUriAccordionOpen(expanded)}>
|
<SettingsItem title={"ApiUri"}>
|
||||||
<AccordionSummary>ApiUri</AccordionSummary>
|
|
||||||
<AccordionDetails>
|
|
||||||
<Input
|
<Input
|
||||||
color={apiUriColor}
|
color={apiUriColor}
|
||||||
placeholder={"http(s)://"}
|
placeholder={"http(s)://"}
|
||||||
type={"url"}
|
type={"url"}
|
||||||
defaultValue={Api.baseUrl}
|
defaultValue={Api.baseUrl}
|
||||||
onChange={apiUriChanged} />
|
onChange={apiUriChanged} />
|
||||||
</AccordionDetails>
|
</SettingsItem>
|
||||||
</Accordion>
|
<ImageCompression />
|
||||||
<Accordion>
|
<FlareSolverr />
|
||||||
<Button onClick={() => setNotificationConnectorsOpen(true)}>Add Notification Connector</Button>
|
<DownloadLanguage />
|
||||||
<NotificationConnectors open={notificationConnectorsOpen} setOpen={setNotificationConnectorsOpen} />
|
<ChapterNamingScheme />
|
||||||
</Accordion>
|
<NotificationConnectors />
|
||||||
</AccordionGroup>
|
</AccordionGroup>
|
||||||
<Stack spacing={2} direction="row">
|
<Stack spacing={2} direction="row">
|
||||||
<Link target={"_blank"} href={Api.baseUrl + "/swagger"}><Article />Swagger Doc</Link>
|
<Link target={"_blank"} href={Api.baseUrl + "/swagger"}><Article />Swagger Doc</Link>
|
||||||
@@ -82,6 +81,17 @@ export default function Settings({setApiUri} : {setApiUri: Dispatch<React.SetSta
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</ModalDialog>
|
</ModalDialog>
|
||||||
</Modal>
|
</Modal>
|
||||||
</SettingsContext>
|
</SettingsContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SettingsItem({title, children} : {title: string, children: ReactNode}) {
|
||||||
|
return (
|
||||||
|
<Accordion>
|
||||||
|
<AccordionSummary>{title}</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
{children}
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
);
|
);
|
||||||
}
|
}
|
Reference in New Issue
Block a user