🔀 Merge pull request #184 from Aimsucks/change-title-icons

Add settings to change title and icons
This commit is contained in:
Thomas Camlong
2022-06-07 16:17:50 +02:00
committed by GitHub
8 changed files with 210 additions and 130 deletions

View File

@@ -27,7 +27,7 @@ export default function SaveConfigComponent(props: any) {
} }
} }
return ( return (
<Group> <Group spacing="xs">
<Modal <Modal
radius="md" radius="md"
opened={opened} opened={opened}
@@ -59,10 +59,11 @@ export default function SaveConfigComponent(props: any) {
</Group> </Group>
</form> </form>
</Modal> </Modal>
<Button leftIcon={<Download />} variant="outline" onClick={onClick}> <Button size="xs" leftIcon={<Download />} variant="outline" onClick={onClick}>
Download config Download config
</Button> </Button>
<Button <Button
size="xs"
leftIcon={<Trash />} leftIcon={<Trash />}
variant="outline" variant="outline"
onClick={() => { onClick={() => {
@@ -93,7 +94,7 @@ export default function SaveConfigComponent(props: any) {
> >
Delete config Delete config
</Button> </Button>
<Button leftIcon={<Plus />} variant="outline" onClick={() => setOpened(true)}> <Button size="xs" leftIcon={<Plus />} variant="outline" onClick={() => setOpened(true)}>
Save a copy Save a copy
</Button> </Button>
</Group> </Group>

View File

@@ -0,0 +1,44 @@
import { TextInput, Group, Button } from '@mantine/core';
import { useForm } from '@mantine/form';
import { useConfig } from '../../tools/state';
export default function TitleChanger() {
const { config, setConfig } = useConfig();
const form = useForm({
initialValues: {
title: config.settings.title,
logo: config.settings.logo,
favicon: config.settings.favicon,
},
});
const saveChanges = (values: { title?: string; logo?: string; favicon?: string }) => {
setConfig({
...config,
settings: {
...config.settings,
title: values.title,
logo: values.logo,
favicon: values.favicon,
},
});
};
return (
<Group direction="column" grow>
<form onSubmit={form.onSubmit((values) => saveChanges(values))}>
<Group grow direction="column">
<TextInput label="Page title" placeholder="Homarr 🦞" {...form.getInputProps('title')} />
<TextInput label="Logo" placeholder="/img/logo.png" {...form.getInputProps('logo')} />
<TextInput
label="Favicon"
placeholder="/favicon.svg"
{...form.getInputProps('favicon')}
/>
<Button type="submit">Save</Button>
</Group>
</form>
</Group>
);
}

View File

@@ -0,0 +1,124 @@
import {
ActionIcon,
Group,
Text,
SegmentedControl,
TextInput,
Anchor,
} from '@mantine/core';
import { useState } from 'react';
import { IconBrandGithub as BrandGithub } from '@tabler/icons';
import { CURRENT_VERSION } from '../../../data/constants';
import { useConfig } from '../../tools/state';
import { ColorSchemeSwitch } from '../ColorSchemeToggle/ColorSchemeSwitch';
import ConfigChanger from '../Config/ConfigChanger';
import SaveConfigComponent from '../Config/SaveConfig';
import ModuleEnabler from './ModuleEnabler';
export default function CommonSettings(args: any) {
const { config, setConfig } = useConfig();
const matches = [
{ label: 'Google', value: 'https://google.com/search?q=' },
{ label: 'DuckDuckGo', value: 'https://duckduckgo.com/?q=' },
{ label: 'Bing', value: 'https://bing.com/search?q=' },
{ label: 'Custom', value: 'Custom' },
];
const [customSearchUrl, setCustomSearchUrl] = useState(config.settings.searchUrl);
const [searchUrl, setSearchUrl] = useState(
matches.find((match) => match.value === config.settings.searchUrl)?.value ?? 'Custom'
);
return (
<Group direction="column" grow>
<Group grow direction="column" spacing={0}>
<Text>Search engine</Text>
<SegmentedControl
fullWidth
title="Search engine"
value={
// Match config.settings.searchUrl with a key in the matches array
searchUrl
}
onChange={
// Set config.settings.searchUrl to the value of the selected item
(e) => {
setSearchUrl(e);
setConfig({
...config,
settings: {
...config.settings,
searchUrl: e,
},
});
}
}
data={matches}
/>
{searchUrl === 'Custom' && (
<TextInput
label="Query URL"
placeholder="Custom query url"
value={customSearchUrl}
onChange={(event) => {
setCustomSearchUrl(event.currentTarget.value);
setConfig({
...config,
settings: {
...config.settings,
searchUrl: event.currentTarget.value,
},
});
}}
/>
)}
</Group>
<ModuleEnabler />
<ColorSchemeSwitch />
<ConfigChanger />
<SaveConfigComponent />
<Text
style={{
alignSelf: 'center',
fontSize: '0.75rem',
textAlign: 'center',
color: 'gray',
}}
>
Tip: You can upload your config file by dragging and dropping it onto the page!
</Text>
<Group position="center" direction="row" mr="xs">
<Group spacing={0}>
<ActionIcon<'a'> component="a" href="https://github.com/ajnart/homarr" size="lg">
<BrandGithub size={18} />
</ActionIcon>
<Text
style={{
position: 'relative',
fontSize: '0.90rem',
color: 'gray',
}}
>
{CURRENT_VERSION}
</Text>
</Group>
<Text
style={{
fontSize: '0.90rem',
textAlign: 'center',
color: 'gray',
}}
>
Made with by @
<Anchor
href="https://github.com/ajnart"
style={{ color: 'inherit', fontStyle: 'inherit', fontSize: 'inherit' }}
>
ajnart
</Anchor>
</Text>
</Group>
</Group>
);
}

View File

@@ -1,131 +1,20 @@
import { import { ActionIcon, Title, Tooltip, Drawer, Tabs } from '@mantine/core';
ActionIcon, import { useHotkeys } from '@mantine/hooks';
Group,
Title,
Text,
Tooltip,
SegmentedControl,
TextInput,
Drawer,
Anchor,
} from '@mantine/core';
import { useColorScheme, useHotkeys } from '@mantine/hooks';
import { useState } from 'react'; import { useState } from 'react';
import { IconBrandGithub as BrandGithub, IconSettings } from '@tabler/icons'; import { IconSettings } from '@tabler/icons';
import { CURRENT_VERSION } from '../../../data/constants'; import AdvancedSettings from './AdvancedSettings';
import { useConfig } from '../../tools/state'; import CommonSettings from './CommonSettings';
import { ColorSchemeSwitch } from '../ColorSchemeToggle/ColorSchemeSwitch';
import ConfigChanger from '../Config/ConfigChanger';
import SaveConfigComponent from '../Config/SaveConfig';
import ModuleEnabler from './ModuleEnabler';
function SettingsMenu(props: any) { function SettingsMenu(props: any) {
const { config, setConfig } = useConfig();
const colorScheme = useColorScheme();
const { current, latest } = props;
const matches = [
{ label: 'Google', value: 'https://google.com/search?q=' },
{ label: 'DuckDuckGo', value: 'https://duckduckgo.com/?q=' },
{ label: 'Bing', value: 'https://bing.com/search?q=' },
{ label: 'Custom', value: 'Custom' },
];
const [customSearchUrl, setCustomSearchUrl] = useState(config.settings.searchUrl);
const [searchUrl, setSearchUrl] = useState(
matches.find((match) => match.value === config.settings.searchUrl)?.value ?? 'Custom'
);
return ( return (
<Group direction="column" grow> <Tabs grow>
<Group grow direction="column" spacing={0}> <Tabs.Tab data-autofocus label="Common">
<Text>Search engine</Text> <CommonSettings />
<SegmentedControl </Tabs.Tab>
fullWidth <Tabs.Tab label="Advanced">
title="Search engine" <AdvancedSettings />
value={ </Tabs.Tab>
// Match config.settings.searchUrl with a key in the matches array </Tabs>
searchUrl
}
onChange={
// Set config.settings.searchUrl to the value of the selected item
(e) => {
setSearchUrl(e);
setConfig({
...config,
settings: {
...config.settings,
searchUrl: e,
},
});
}
}
data={matches}
/>
{searchUrl === 'Custom' && (
<TextInput
label="Query URL"
placeholder="Custom query url"
value={customSearchUrl}
onChange={(event) => {
setCustomSearchUrl(event.currentTarget.value);
setConfig({
...config,
settings: {
...config.settings,
searchUrl: event.currentTarget.value,
},
});
}}
/>
)}
</Group>
<ModuleEnabler />
<ColorSchemeSwitch />
<ConfigChanger />
<SaveConfigComponent />
<Text
style={{
alignSelf: 'center',
fontSize: '0.75rem',
textAlign: 'center',
color: 'gray',
}}
>
Tip: You can upload your config file by dragging and dropping it onto the page!
</Text>
<Group position="center" direction="row" mr="xs">
<Group spacing={0}>
<ActionIcon<'a'> component="a" href="https://github.com/ajnart/homarr" size="lg">
<BrandGithub size={18} />
</ActionIcon>
<Text
style={{
position: 'relative',
fontSize: '0.90rem',
color: 'gray',
}}
>
{CURRENT_VERSION}
</Text>
</Group>
<Text
style={{
fontSize: '0.90rem',
textAlign: 'center',
color: 'gray',
}}
>
Made with by @
<Anchor
href="https://github.com/ajnart"
style={{ color: 'inherit', fontStyle: 'inherit', fontSize: 'inherit' }}
>
ajnart
</Anchor>
</Text>
</Group>
</Group>
); );
} }
@@ -136,7 +25,7 @@ export function SettingsMenuButton(props: any) {
return ( return (
<> <>
<Drawer <Drawer
size="auto" size="xl"
padding="xl" padding="xl"
position="right" position="right"
title={<Title order={3}>Settings</Title>} title={<Title order={3}>Settings</Title>}

View File

@@ -0,0 +1,14 @@
import React from 'react';
import Head from 'next/head';
import { useConfig } from '../../tools/state';
export function HeaderConfig(props: any) {
const { config } = useConfig();
return (
<Head>
<title>{config.settings.title || 'Homarr 🦞'}</title>
<link rel="shortcut icon" href={config.settings.favicon || '/favicon.svg'} />
</Head>
);
}

View File

@@ -2,6 +2,7 @@ import { AppShell, createStyles } from '@mantine/core';
import { Header } from './Header'; import { Header } from './Header';
import { Footer } from './Footer'; import { Footer } from './Footer';
import Aside from './Aside'; import Aside from './Aside';
import { HeaderConfig } from './HeaderConfig';
const useStyles = createStyles((theme) => ({ const useStyles = createStyles((theme) => ({
main: {}, main: {},
@@ -11,6 +12,7 @@ export default function Layout({ children, style }: any) {
const { classes, cx } = useStyles(); const { classes, cx } = useStyles();
return ( return (
<AppShell aside={<Aside />} header={<Header />} footer={<Footer links={[]} />}> <AppShell aside={<Aside />} header={<Header />} footer={<Footer links={[]} />}>
<HeaderConfig />
<main <main
className={cx(classes.main)} className={cx(classes.main)}
style={{ style={{

View File

@@ -1,13 +1,16 @@
import { Group, Image, Text } from '@mantine/core'; import { Group, Image, Text } from '@mantine/core';
import { NextLink } from '@mantine/next'; import { NextLink } from '@mantine/next';
import * as React from 'react'; import * as React from 'react';
import { useConfig } from '../../tools/state';
export function Logo({ style }: any) { export function Logo({ style }: any) {
const { config } = useConfig();
return ( return (
<Group spacing="xs"> <Group spacing="xs">
<Image <Image
width={50} width={50}
src="/imgs/logo.png" src={config.settings.logo || '/imgs/logo.png'}
style={{ style={{
position: 'relative', position: 'relative',
}} }}
@@ -25,7 +28,7 @@ export function Logo({ style }: any) {
variant="gradient" variant="gradient"
gradient={{ from: 'red', to: 'orange', deg: 145 }} gradient={{ from: 'red', to: 'orange', deg: 145 }}
> >
Homarr {config.settings.title || 'Homarr'}
</Text> </Text>
</NextLink> </NextLink>
</Group> </Group>

View File

@@ -2,6 +2,9 @@ import { OptionValues } from '../components/modules/modules';
export interface Settings { export interface Settings {
searchUrl: string; searchUrl: string;
title?: string;
logo?: string;
favicon?: string;
} }
export interface Config { export interface Config {