feat: ability to change logo in frontend

This commit is contained in:
Elias Schneider
2023-03-08 14:47:41 +01:00
parent 8f71fd3435
commit 8403d7e14d
13 changed files with 596 additions and 45 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,39 @@
import { Box, FileInput, Group, Stack, Text, Title } from "@mantine/core";
import { useMediaQuery } from "@mantine/hooks";
import { Dispatch, SetStateAction } from "react";
import { TbUpload } from "react-icons/tb";
const LogoConfigInput = ({
logo,
setLogo,
}: {
logo: File | null;
setLogo: Dispatch<SetStateAction<File | null>>;
}) => {
const isMobile = useMediaQuery("(max-width: 560px)");
return (
<Group position="apart">
<Stack style={{ maxWidth: isMobile ? "100%" : "40%" }} spacing={0}>
<Title order={6}>Logo</Title>
<Text color="dimmed" size="sm" mb="xs">
Change your logo by uploading a new image. The image must be a PNG and
should have the format 1:1.
</Text>
</Stack>
<Stack></Stack>
<Box style={{ width: isMobile ? "100%" : "50%" }}>
<FileInput
clearable
icon={<TbUpload size={14} />}
value={logo}
onChange={(v) => setLogo(v)}
accept=".png"
placeholder="Pick image"
/>
</Box>
</Group>
);
};
export default LogoConfigInput;

View File

@@ -12,14 +12,8 @@ export default class _Document extends Document {
<Head>
<link rel="manifest" href="/manifest.json" />
<link rel="icon" type="image/x-icon" href="/img/favicon.ico" />
<link
rel="apple-touch-icon"
href="/img/icons/icon-white-128x128.png"
/>
<link rel="apple-touch-icon" href="/img/icons/icon-128x128.png" />
<meta property="og:image" content="/img/opengraph.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="/img/opengraph.png" />
<meta name="robots" content="noindex" />
<meta name="theme-color" content="#46509e" />
</Head>

View File

@@ -16,6 +16,7 @@ import { useEffect, useState } from "react";
import AdminConfigInput from "../../../components/admin/configuration/AdminConfigInput";
import ConfigurationHeader from "../../../components/admin/configuration/ConfigurationHeader";
import ConfigurationNavBar from "../../../components/admin/configuration/ConfigurationNavBar";
import LogoConfigInput from "../../../components/admin/configuration/LogoConfigInput";
import TestEmailButton from "../../../components/admin/configuration/TestEmailButton";
import CenterLoader from "../../../components/core/CenterLoader";
import Meta from "../../../components/Meta";
@@ -36,22 +37,38 @@ export default function AppShellDemo() {
const isMobile = useMediaQuery("(max-width: 560px)");
const config = useConfig();
const categoryId = router.query.category as string;
const categoryId = (router.query.category as string | undefined) ?? "general";
const [configVariables, setConfigVariables] = useState<AdminConfig[]>();
const [updatedConfigVariables, setUpdatedConfigVariables] = useState<
UpdateConfig[]
>([]);
const [logo, setLogo] = useState<File | null>(null);
const saveConfigVariables = async () => {
await configService
.updateMany(updatedConfigVariables)
.then(() => {
setUpdatedConfigVariables([]);
toast.success("Configurations updated successfully");
})
.catch(toast.axiosError);
config.refresh();
if (logo) {
configService
.changeLogo(logo)
.then(() => {
setLogo(null);
toast.success(
"Logo updated successfully. It may take a few minutes to update on the website."
);
})
.catch(toast.axiosError);
}
if (updatedConfigVariables.length > 0) {
await configService
.updateMany(updatedConfigVariables)
.then(() => {
setUpdatedConfigVariables([]);
toast.success("Configurations updated successfully");
})
.catch(toast.axiosError);
config.refresh();
}
};
const updateConfigVariable = (configVariable: UpdateConfig) => {
@@ -129,6 +146,9 @@ export default function AppShellDemo() {
</Box>
</Group>
))}
{categoryId == "general" && (
<LogoConfigInput logo={logo} setLogo={setLogo} />
)}
</Stack>
<Group mt="lg" position="right">
{categoryId == "smtp" && (

View File

@@ -1,15 +0,0 @@
export function getServerSideProps() {
return {
redirect: {
permanent: false,
destination: "/admin/config/general",
},
props: {},
};
}
const Config = () => {
return null;
};
export default Config;

View File

@@ -46,6 +46,12 @@ const isNewReleaseAvailable = async () => {
return response.tag_name.replace("v", "") != process.env.VERSION;
};
const changeLogo = async (file: File) => {
const form = new FormData();
form.append("file", file);
await api.post("/configs/admin/logo", form);
};
export default {
list,
getByCategory,
@@ -54,4 +60,5 @@ export default {
finishSetup,
sendTestEmail,
isNewReleaseAvailable,
changeLogo,
};