diff --git a/src/components/Board/Customize/Layout/LayoutPreview.tsx b/src/components/Board/Customize/Layout/LayoutPreview.tsx
index 5a843fbba..ecae8cc6f 100644
--- a/src/components/Board/Customize/Layout/LayoutPreview.tsx
+++ b/src/components/Board/Customize/Layout/LayoutPreview.tsx
@@ -1,5 +1,5 @@
import { Flex, Group, Indicator, Paper, Stack, createStyles } from '@mantine/core';
-import { Logo } from '~/components/layout/Logo';
+import { Logo } from '~/components/layout/Common/Logo';
import { createDummyArray } from '~/tools/client/arrays';
type LayoutPreviewProps = {
diff --git a/src/components/Dashboard/Tiles/Apps/AppTile.tsx b/src/components/Dashboard/Tiles/Apps/AppTile.tsx
index 2610cb9b3..0fbe7ab58 100644
--- a/src/components/Dashboard/Tiles/Apps/AppTile.tsx
+++ b/src/components/Dashboard/Tiles/Apps/AppTile.tsx
@@ -4,7 +4,7 @@ import { motion } from 'framer-motion';
import Link from 'next/link';
import { AppType } from '../../../../types/app';
-import { useCardStyles } from '../../../layout/useCardStyles';
+import { useCardStyles } from '../../../layout/Common/useCardStyles';
import { useEditModeStore } from '../../Views/useEditModeStore';
import { HomarrCardWrapper } from '../HomarrCardWrapper';
import { BaseTileProps } from '../type';
diff --git a/src/components/Dashboard/Tiles/HomarrCardWrapper.tsx b/src/components/Dashboard/Tiles/HomarrCardWrapper.tsx
index 815ca892a..89b456c23 100644
--- a/src/components/Dashboard/Tiles/HomarrCardWrapper.tsx
+++ b/src/components/Dashboard/Tiles/HomarrCardWrapper.tsx
@@ -1,7 +1,7 @@
import { Card, CardProps } from '@mantine/core';
import { ReactNode } from 'react';
-import { useCardStyles } from '../../layout/useCardStyles';
+import { useCardStyles } from '../../layout/Common/useCardStyles';
import { useEditModeStore } from '../Views/useEditModeStore';
interface HomarrCardWrapperProps extends CardProps {
diff --git a/src/components/Dashboard/Wrappers/Category/Category.tsx b/src/components/Dashboard/Wrappers/Category/Category.tsx
index ca7dfd469..0819c9b91 100644
--- a/src/components/Dashboard/Wrappers/Category/Category.tsx
+++ b/src/components/Dashboard/Wrappers/Category/Category.tsx
@@ -16,7 +16,7 @@ import { useTranslation } from 'next-i18next';
import { useConfigContext } from '../../../../config/provider';
import { CategoryType } from '../../../../types/category';
-import { useCardStyles } from '../../../layout/useCardStyles';
+import { useCardStyles } from '../../../layout/Common/useCardStyles';
import { useEditModeStore } from '../../Views/useEditModeStore';
import { WrapperContent } from '../WrapperContent';
import { useGridstack } from '../gridstack/use-gridstack';
diff --git a/src/components/Dashboard/Wrappers/Sidebar/Sidebar.tsx b/src/components/Dashboard/Wrappers/Sidebar/Sidebar.tsx
index 5e604aa3d..95b955150 100644
--- a/src/components/Dashboard/Wrappers/Sidebar/Sidebar.tsx
+++ b/src/components/Dashboard/Wrappers/Sidebar/Sidebar.tsx
@@ -1,7 +1,7 @@
import { Card } from '@mantine/core';
import { RefObject } from 'react';
-import { useCardStyles } from '../../../layout/useCardStyles';
+import { useCardStyles } from '../../../layout/Common/useCardStyles';
import { WrapperContent } from '../WrapperContent';
import { useGridstack } from '../gridstack/use-gridstack';
diff --git a/src/components/Settings/Common/CommonSettings.tsx b/src/components/Settings/Common/CommonSettings.tsx
deleted file mode 100644
index b72ff76ee..000000000
--- a/src/components/Settings/Common/CommonSettings.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { ScrollArea, Space, Stack, Text } from '@mantine/core';
-import { useViewportSize } from '@mantine/hooks';
-
-import { useConfigContext } from '../../../config/provider';
-import ConfigChanger from '../../Config/ConfigChanger';
-import ConfigActions from './Config/ConfigActions';
-import LanguageSelect from './Language/LanguageSelect';
-import { SearchEngineSelector } from './SearchEngine/SearchEngineSelector';
-
-export default function CommonSettings() {
- const { config } = useConfigContext();
- const { height, width } = useViewportSize();
-
- if (!config) {
- return (
-
- No active config
-
- );
- }
- return (
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/components/Settings/Common/Config/ConfigActions.tsx b/src/components/Settings/Common/Config/ConfigActions.tsx
deleted file mode 100644
index e3bb2941d..000000000
--- a/src/components/Settings/Common/Config/ConfigActions.tsx
+++ /dev/null
@@ -1,172 +0,0 @@
-import {
- ActionIcon,
- Alert,
- Center,
- Flex,
- Text,
- createStyles,
- useMantineTheme,
-} from '@mantine/core';
-import { useDisclosure } from '@mantine/hooks';
-import { openConfirmModal } from '@mantine/modals';
-import { showNotification } from '@mantine/notifications';
-import {
- IconAlertTriangle,
- IconCheck,
- IconCopy,
- IconDownload,
- IconTrash,
- IconX,
-} from '@tabler/icons-react';
-import fileDownload from 'js-file-download';
-import { Trans, useTranslation } from 'next-i18next';
-import { useRouter } from 'next/router';
-import { api } from '~/utils/api';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-import Tip from '../../../layout/Tip';
-import { CreateConfigCopyModal } from './CreateCopyModal';
-
-export default function ConfigActions() {
- const { t } = useTranslation(['settings/general/config-changer', 'settings/common', 'common']);
- const [createCopyModalOpened, createCopyModal] = useDisclosure(false);
- const { config } = useConfigContext();
- const { mutateAsync } = useDeleteConfigMutation();
-
- if (!config) return null;
-
- const handleDownload = () => {
- fileDownload(JSON.stringify(config, null, '\t'), `${config?.configProperties.name}.json`);
- };
-
- const handleDeletion = async () => {
- openConfirmModal({
- title: t('modal.confirmDeletion.title'),
- children: (
- <>
- } mb="md">
- , code: }}
- />
-
- {t('modal.confirmDeletion.text')}
- >
- ),
- labels: {
- confirm: (
- , code: }}
- />
- ),
- cancel: t('common:cancel'),
- },
- zIndex: 201,
- onConfirm: async () => {
- const response = await mutateAsync({
- name: config?.configProperties.name ?? 'default',
- });
- },
- });
- };
-
- const { classes } = useStyles();
- const { colors } = useMantineTheme();
-
- return (
- <>
-
-
-
-
- {t('buttons.download')}
-
-
-
- {t('buttons.delete.text')}
-
-
-
- {t('buttons.saveCopy')}
-
-
-
-
- {t('settings/common:tips.configTip')}
-
- >
- );
-}
-
-const useDeleteConfigMutation = () => {
- const { t } = useTranslation(['settings/general/config-changer']);
- const router = useRouter();
- const { removeConfig } = useConfigStore();
-
- return api.config.delete.useMutation({
- onError(error) {
- if (error.data?.code === 'FORBIDDEN') {
- showNotification({
- title: t('buttons.delete.notifications.deleteFailedDefaultConfig.title'),
- icon: ,
- color: 'red',
- autoClose: 1500,
- radius: 'md',
- message: t('buttons.delete.notifications.deleteFailedDefaultConfig.message'),
- });
- }
- showNotification({
- title: t('buttons.delete.notifications.deleteFailed.title'),
- icon: ,
- color: 'red',
- autoClose: 1500,
- radius: 'md',
- message: t('buttons.delete.notifications.deleteFailed.message'),
- });
- },
- onSuccess(data, variables) {
- showNotification({
- title: t('buttons.delete.notifications.deleted.title'),
- icon: ,
- color: 'green',
- autoClose: 1500,
- radius: 'md',
- message: t('buttons.delete.notifications.deleted.message'),
- });
-
- removeConfig(variables.name);
-
- router.push('/');
- },
- });
-};
-
-const useStyles = createStyles(() => ({
- actionIcon: {
- width: 'auto',
- height: 'auto',
- maxWidth: 'auto',
- maxHeight: 'auto',
- flexGrow: 1,
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'center',
- justifyContent: 'center',
- textAlign: 'center',
- rowGap: 10,
- padding: 10,
- },
-}));
diff --git a/src/components/Settings/Common/Config/CreateCopyModal.tsx b/src/components/Settings/Common/Config/CreateCopyModal.tsx
deleted file mode 100644
index 1acdd89cc..000000000
--- a/src/components/Settings/Common/Config/CreateCopyModal.tsx
+++ /dev/null
@@ -1,123 +0,0 @@
-import { Button, Group, Modal, TextInput, Title } from '@mantine/core';
-import { useForm } from '@mantine/form';
-import { showNotification } from '@mantine/notifications';
-import { IconCheck, IconX } from '@tabler/icons-react';
-import { useTranslation } from 'next-i18next';
-import { useConfigContext } from '~/config/provider';
-import { api } from '~/utils/api';
-
-import { useConfigStore } from '../../../../config/store';
-
-interface CreateConfigCopyModalProps {
- opened: boolean;
- closeModal: () => void;
- initialConfigName: string;
-}
-
-export const CreateConfigCopyModal = ({
- opened,
- closeModal,
- initialConfigName,
-}: CreateConfigCopyModalProps) => {
- const { configs } = useConfigStore();
- const { config } = useConfigContext();
- const { t } = useTranslation(['settings/general/config-changer']);
-
- const form = useForm({
- initialValues: {
- configName: initialConfigName,
- },
- validate: {
- configName: (value) => {
- if (!value) {
- return t('modal.copy.form.configName.validation.required');
- }
-
- const configNames = configs.map((x) => x.value.configProperties.name);
- if (configNames.includes(value)) {
- return t('modal.copy.form.configName.validation.notUnique');
- }
-
- return undefined;
- },
- },
- validateInputOnChange: true,
- validateInputOnBlur: true,
- });
-
- const { mutateAsync } = useCopyConfigMutation();
-
- const handleClose = () => {
- form.setFieldValue('configName', initialConfigName);
- closeModal();
- };
-
- const handleSubmit = async (values: typeof form.values) => {
- if (!form.isValid) return;
-
- if (!config) {
- throw new Error('config is not defiend');
- }
-
- const copiedConfig = config;
- copiedConfig.configProperties.name = form.values.configName;
-
- await mutateAsync({
- name: form.values.configName,
- config: copiedConfig,
- });
- closeModal();
- };
-
- return (
- {t('modal.copy.title')}}
- >
-
-
- );
-};
-
-const useCopyConfigMutation = () => {
- const { t } = useTranslation(['settings/general/config-changer']);
- const utils = api.useContext();
-
- return api.config.save.useMutation({
- onSuccess(_data, variables) {
- showNotification({
- title: t('modal.copy.events.configCopied.title'),
- icon: ,
- color: 'green',
- autoClose: 1500,
- radius: 'md',
- message: t('modal.copy.events.configCopied.message', { configName: variables.name }),
- });
- // Invalidate a query to fetch new config
- utils.config.all.invalidate();
- },
- onError(_error, variables) {
- showNotification({
- title: t('modal.events.configNotCopied.title'),
- icon: ,
- color: 'red',
- autoClose: 1500,
- radius: 'md',
- message: t('modal.events.configNotCopied.message', { configName: variables.name }),
- });
- },
- });
-};
diff --git a/src/components/Settings/Customization/CustomizationAccordeon.tsx b/src/components/Settings/Customization/CustomizationAccordeon.tsx
deleted file mode 100644
index 33789f50c..000000000
--- a/src/components/Settings/Customization/CustomizationAccordeon.tsx
+++ /dev/null
@@ -1,156 +0,0 @@
-import { Accordion, Checkbox, Grid, Group, Stack, Text } from '@mantine/core';
-import {
- IconAccessible,
- IconBrush,
- IconChartCandle,
- IconCode,
- IconDragDrop,
- IconLayout,
-} from '@tabler/icons-react';
-import { i18n, useTranslation } from 'next-i18next';
-import { ReactNode } from 'react';
-import { env } from '~/env';
-
-import { AccessibilitySettings } from './Accessibility/AccessibilitySettings';
-import { GridstackConfiguration } from './Layout/GridstackConfiguration';
-import { LayoutSelector } from './Layout/LayoutSelector';
-import { BackgroundChanger } from './Meta/BackgroundChanger';
-import { FaviconChanger } from './Meta/FaviconChanger';
-import { LogoImageChanger } from './Meta/LogoImageChanger';
-import { BrowserTabTitle } from './Meta/MetaTitleChanger';
-import { DashboardTitleChanger } from './Meta/PageTitleChanger';
-import { ColorSelector } from './Theme/ColorSelector';
-import { CustomCssChanger } from './Theme/CustomCssChanger';
-import { DashboardTilesOpacitySelector } from './Theme/OpacitySelector';
-import { ShadeSelector } from './Theme/ShadeSelector';
-
-export const CustomizationSettingsAccordeon = () => {
- const items = getItems().map((item) => (
-
-
-
-
-
- {item.content}
-
-
- ));
- return (
-
- {items}
-
- );
-};
-
-interface AccordionLabelProps {
- label: string;
- image: ReactNode;
- description: string;
-}
-
-const AccordionLabel = ({ label, image, description }: AccordionLabelProps) => (
-
- {image}
-
- {label}
-
- {description}
-
-
-
-);
-
-const getItems = () => {
- const { t } = useTranslation([
- 'settings/customization/general',
- 'settings/customization/color-selector',
- ]);
- const items = [
- {
- id: 'layout',
- image: ,
- label: t('accordeon.layout.name'),
- description: t('accordeon.layout.description'),
- content: ,
- },
- {
- id: 'gridstack',
- image: ,
- label: t('accordeon.gridstack.name'),
- description: t('accordeon.gridstack.description'),
- content: ,
- },
- {
- id: 'accessibility',
- image: ,
- label: t('accordeon.accessibility.name'),
- description: t('accordeon.accessibility.description'),
- content: ,
- },
- {
- id: 'page_metadata',
- image: ,
- label: t('accordeon.pageMetadata.name'),
- description: t('accordeon.pageMetadata.description'),
- content: (
- <>
-
-
-
-
- >
- ),
- },
- {
- id: 'appereance',
- image: ,
- label: t('accordeon.appereance.name'),
- description: t('accordeon.appereance.description'),
- content: (
- <>
-
-
-
- {t('settings/customization/color-selector:colors')}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- ),
- },
- ];
- if (env.NEXT_PUBLIC_NODE_ENV === 'development') {
- items.push({
- id: 'dev',
- image: ,
- label: 'Developer options',
- description: 'Options to help when developing',
- content: (
-
-
- // Change to CI mode language
- i18n?.changeLanguage(e.target.checked ? 'cimode' : 'en')
- }
- />
-
- ),
- });
- }
- return items;
-};
diff --git a/src/components/Settings/Customization/CustomizationSettings.tsx b/src/components/Settings/Customization/CustomizationSettings.tsx
deleted file mode 100644
index 84d484f20..000000000
--- a/src/components/Settings/Customization/CustomizationSettings.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { ScrollArea, Stack, Text } from '@mantine/core';
-import { useViewportSize } from '@mantine/hooks';
-import { useTranslation } from 'next-i18next';
-
-import { CustomizationSettingsAccordeon } from './CustomizationAccordeon';
-
-export default function CustomizationSettings() {
- const { height } = useViewportSize();
- const { t } = useTranslation('settings/customization/general');
-
- return (
-
-
- {t('text')}
-
-
-
- );
-}
diff --git a/src/components/Settings/Customization/Layout/GridstackConfiguration.tsx b/src/components/Settings/Customization/Layout/GridstackConfiguration.tsx
deleted file mode 100644
index 31a70ce53..000000000
--- a/src/components/Settings/Customization/Layout/GridstackConfiguration.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-import { Alert, Button, Grid, Input, LoadingOverlay, Slider } from '@mantine/core';
-import { useForm } from '@mantine/form';
-import { IconCheck, IconReload } from '@tabler/icons-react';
-import { useTranslation } from 'next-i18next';
-import { useState } from 'react';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-import { GridstackBreakpoints } from '../../../../constants/gridstack-breakpoints';
-import { sleep } from '../../../../tools/client/time';
-import { GridstackSettingsType } from '../../../../types/settings';
-
-export const GridstackConfiguration = () => {
- const { t } = useTranslation(['settings/customization/gridstack', 'common']);
- const { config, name: configName } = useConfigContext();
- const updateConfig = useConfigStore((x) => x.updateConfig);
-
- if (!config || !configName) {
- return null;
- }
-
- const initialValue = config.settings.customization?.gridstack ?? {
- columnCountSmall: 3,
- columnCountMedium: 6,
- columnCountLarge: 12,
- };
-
- const form = useForm({
- initialValues: initialValue,
- });
-
- const [isSaving, setIsSaving] = useState(false);
-
- const handleSubmit = async (values: GridstackSettingsType) => {
- setIsSaving(true);
-
- await sleep(250);
- await updateConfig(
- configName,
- (previousConfig) => ({
- ...previousConfig,
- settings: {
- ...previousConfig.settings,
- customization: {
- ...previousConfig.settings.customization,
- gridstack: values,
- },
- },
- }),
- true,
- true
- );
-
- form.resetDirty();
- setIsSaving(false);
- };
-
- return (
-
- );
-};
diff --git a/src/components/Settings/Customization/Layout/LayoutSelector.tsx b/src/components/Settings/Customization/Layout/LayoutSelector.tsx
deleted file mode 100644
index f5bbd3c87..000000000
--- a/src/components/Settings/Customization/Layout/LayoutSelector.tsx
+++ /dev/null
@@ -1,210 +0,0 @@
-import {
- Checkbox,
- Divider,
- Flex,
- Group,
- Indicator,
- Paper,
- Stack,
- Text,
- Title,
- createStyles,
-} from '@mantine/core';
-import { useTranslation } from 'next-i18next';
-import { ChangeEvent, Dispatch, SetStateAction, useState } from 'react';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-import { createDummyArray } from '../../../../tools/client/arrays';
-import { CustomizationSettingsType } from '../../../../types/settings';
-import { Logo } from '../../../layout/Logo';
-
-export const LayoutSelector = () => {
- const { classes } = useStyles();
-
- const { config, name: configName } = useConfigContext();
- const updateConfig = useConfigStore((x) => x.updateConfig);
-
- const layoutSettings = config?.settings.customization.layout;
-
- const [leftSidebar, setLeftSidebar] = useState(layoutSettings?.enabledLeftSidebar ?? true);
- const [rightSidebar, setRightSidebar] = useState(layoutSettings?.enabledRightSidebar ?? true);
- const [docker, setDocker] = useState(layoutSettings?.enabledDocker ?? false);
- const [ping, setPing] = useState(layoutSettings?.enabledPing ?? false);
- const [searchBar, setSearchBar] = useState(layoutSettings?.enabledSearchbar ?? false);
- const { t } = useTranslation('settings/common');
-
- if (!configName || !config) return null;
-
- const handleChange = (
- key: keyof CustomizationSettingsType['layout'],
- event: ChangeEvent,
- setState: Dispatch>
- ) => {
- const value = event.target.checked;
- setState(value);
- updateConfig(
- configName,
- (prev) => {
- const { layout } = prev.settings.customization;
-
- layout[key] = value;
-
- return {
- ...prev,
- settings: {
- ...prev.settings,
- customization: {
- ...prev.settings.customization,
- layout,
- },
- },
- };
- },
- true
- );
- };
-
- const enabledPing = layoutSettings?.enabledPing ?? false;
-
- return (
- <>
-
- {t('layout.preview.title')}
-
- {t('layout.preview.subtitle')}
-
-
-
-
-
-
-
- {searchBar && }
- {docker && }
-
-
-
-
-
- {leftSidebar && (
-
-
- {createDummyArray(5).map((item, index) => (
-
- ))}
-
-
- )}
-
-
-
- {createDummyArray(10).map((item, index) => (
-
- ))}
-
-
-
- {rightSidebar && (
-
-
- {createDummyArray(5).map((item, index) => (
-
- ))}
-
-
- )}
-
-
-
-
- handleChange('enabledLeftSidebar', ev, setLeftSidebar)}
- />
- handleChange('enabledRightSidebar', ev, setRightSidebar)}
- />
- handleChange('enabledSearchbar', ev, setSearchBar)}
- />
- handleChange('enabledDocker', ev, setDocker)}
- />
- handleChange('enabledPing', ev, setPing)}
- />
-
-
- >
- );
-};
-
-const BaseElement = ({ height, width }: { height: number; width: number }) => (
- ({
- backgroundColor: theme.colorScheme === 'dark' ? theme.colors.gray[8] : theme.colors.gray[1],
- })}
- h={height}
- p={2}
- w={width}
- />
-);
-
-const PlaceholderElement = (props: any) => {
- const { height, width, hasPing, index } = props;
-
- if (hasPing) {
- return (
-
-
-
- );
- }
-
- return ;
-};
-
-const useStyles = createStyles((theme) => ({
- primaryWrapper: {
- flexGrow: 2,
- },
- secondaryWrapper: {
- flexGrow: 1,
- maxWidth: 100,
- },
-}));
diff --git a/src/components/Settings/Customization/Meta/BackgroundChanger.tsx b/src/components/Settings/Customization/Meta/BackgroundChanger.tsx
deleted file mode 100644
index 53aaea8f3..000000000
--- a/src/components/Settings/Customization/Meta/BackgroundChanger.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { TextInput } from '@mantine/core';
-import { useTranslation } from 'next-i18next';
-import { ChangeEventHandler, useState } from 'react';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-
-export const BackgroundChanger = () => {
- const { t } = useTranslation('settings/customization/page-appearance');
- const updateConfig = useConfigStore((x) => x.updateConfig);
- const { config, name: configName } = useConfigContext();
- const [backgroundImageUrl, setBackgroundImageUrl] = useState(
- config?.settings.customization.backgroundImageUrl
- );
-
- if (!configName) return null;
-
- const handleChange: ChangeEventHandler = (ev) => {
- const { value } = ev.currentTarget;
- const backgroundImageUrl = value.trim().length === 0 ? undefined : value;
- setBackgroundImageUrl(backgroundImageUrl);
- updateConfig(configName, (prev) => ({
- ...prev,
- settings: {
- ...prev.settings,
- customization: {
- ...prev.settings.customization,
- backgroundImageUrl,
- },
- },
- }));
- };
-
- return (
-
- );
-};
diff --git a/src/components/Settings/Customization/Meta/FaviconChanger.tsx b/src/components/Settings/Customization/Meta/FaviconChanger.tsx
deleted file mode 100644
index 5bb880d26..000000000
--- a/src/components/Settings/Customization/Meta/FaviconChanger.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import { TextInput } from '@mantine/core';
-import { useTranslation } from 'next-i18next';
-import { ChangeEventHandler, useState } from 'react';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-
-export const FaviconChanger = () => {
- const { t } = useTranslation('settings/customization/page-appearance');
- const updateConfig = useConfigStore((x) => x.updateConfig);
- const { config, name: configName } = useConfigContext();
- const [faviconUrl, setFaviconUrl] = useState(
- config?.settings.customization.faviconUrl ?? '/imgs/favicon/favicon.svg'
- );
-
- if (!configName) return null;
-
- const handleChange: ChangeEventHandler = (ev) => {
- const { value } = ev.currentTarget;
- const faviconUrl = value.trim();
- setFaviconUrl(faviconUrl);
- updateConfig(configName, (prev) => ({
- ...prev,
- settings: {
- ...prev.settings,
- customization: {
- ...prev.settings.customization,
- faviconUrl,
- },
- },
- }));
- };
-
- return (
-
- );
-};
diff --git a/src/components/Settings/Customization/Meta/LogoImageChanger.tsx b/src/components/Settings/Customization/Meta/LogoImageChanger.tsx
deleted file mode 100644
index 77074c060..000000000
--- a/src/components/Settings/Customization/Meta/LogoImageChanger.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import { TextInput } from '@mantine/core';
-import { useTranslation } from 'next-i18next';
-import { ChangeEventHandler, useState } from 'react';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-
-export const LogoImageChanger = () => {
- const { t } = useTranslation('settings/customization/page-appearance');
- const updateConfig = useConfigStore((x) => x.updateConfig);
- const { config, name: configName } = useConfigContext();
- const [logoImageSrc, setLogoImageSrc] = useState(
- config?.settings.customization.logoImageUrl ?? '/imgs/logo/logo.png'
- );
-
- if (!configName) return null;
-
- const handleChange: ChangeEventHandler = (ev) => {
- const { value } = ev.currentTarget;
- const logoImageSrc = value.trim();
- setLogoImageSrc(logoImageSrc);
- updateConfig(configName, (prev) => ({
- ...prev,
- settings: {
- ...prev.settings,
- customization: {
- ...prev.settings.customization,
- logoImageUrl: logoImageSrc,
- },
- },
- }));
- };
-
- return (
-
- );
-};
diff --git a/src/components/Settings/Customization/Meta/MetaTitleChanger.tsx b/src/components/Settings/Customization/Meta/MetaTitleChanger.tsx
deleted file mode 100644
index 90af2dd97..000000000
--- a/src/components/Settings/Customization/Meta/MetaTitleChanger.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { TextInput } from '@mantine/core';
-import { useTranslation } from 'next-i18next';
-import { ChangeEventHandler, useState } from 'react';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-
-export const BrowserTabTitle = () => {
- const { t } = useTranslation('settings/customization/page-appearance');
- const updateConfig = useConfigStore((x) => x.updateConfig);
- const { config, name: configName } = useConfigContext();
- const [metaTitle, setMetaTitle] = useState(config?.settings.customization.metaTitle ?? '');
-
- if (!configName) return null;
-
- const handleChange: ChangeEventHandler = (ev) => {
- const { value } = ev.currentTarget;
- const metaTitle = value.trim();
- setMetaTitle(metaTitle);
- updateConfig(configName, (prev) => ({
- ...prev,
- settings: {
- ...prev.settings,
- customization: {
- ...prev.settings.customization,
- metaTitle,
- },
- },
- }));
- };
-
- return (
-
- );
-};
diff --git a/src/components/Settings/Customization/Meta/PageTitleChanger.tsx b/src/components/Settings/Customization/Meta/PageTitleChanger.tsx
deleted file mode 100644
index f7745ca4e..000000000
--- a/src/components/Settings/Customization/Meta/PageTitleChanger.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { TextInput } from '@mantine/core';
-import { useTranslation } from 'next-i18next';
-import { ChangeEventHandler, useState } from 'react';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-
-export const DashboardTitleChanger = () => {
- const { t } = useTranslation('settings/customization/page-appearance');
- const updateConfig = useConfigStore((x) => x.updateConfig);
- const { config, name: configName } = useConfigContext();
- const [pageTitle, setPageTitle] = useState(config?.settings.customization.pageTitle ?? '');
-
- if (!configName) return null;
-
- const handleChange: ChangeEventHandler = (ev) => {
- const { value } = ev.currentTarget;
- const pageTitle = value.trim();
- setPageTitle(pageTitle);
- updateConfig(configName, (prev) => ({
- ...prev,
- settings: {
- ...prev.settings,
- customization: {
- ...prev.settings.customization,
- pageTitle,
- },
- },
- }));
- };
-
- return (
-
- );
-};
diff --git a/src/components/Settings/Customization/Theme/ColorSelector.tsx b/src/components/Settings/Customization/Theme/ColorSelector.tsx
deleted file mode 100644
index c3ae8aae2..000000000
--- a/src/components/Settings/Customization/Theme/ColorSelector.tsx
+++ /dev/null
@@ -1,108 +0,0 @@
-import {
- ColorSwatch,
- Grid,
- Group,
- MantineTheme,
- Popover,
- Text,
- useMantineTheme,
-} from '@mantine/core';
-import { useDisclosure } from '@mantine/hooks';
-import { useTranslation } from 'next-i18next';
-import { useState } from 'react';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-import { useColorTheme } from '../../../../tools/color';
-
-interface ColorControlProps {
- defaultValue: MantineTheme['primaryColor'] | undefined;
- type: 'primary' | 'secondary';
-}
-
-export function ColorSelector({ type, defaultValue }: ColorControlProps) {
- const { t } = useTranslation('settings/customization/color-selector');
- const { config, name: configName } = useConfigContext();
- const [color, setColor] =
- type === 'primary'
- ? useState(config?.settings.customization.colors.primary || defaultValue)
- : useState(config?.settings.customization.colors.secondary || defaultValue);
- const [popoverOpened, popover] = useDisclosure(false);
- const { setPrimaryColor, setSecondaryColor } = useColorTheme();
- const updateConfig = useConfigStore((x) => x.updateConfig);
-
- const theme = useMantineTheme();
- const colors = Object.keys(theme.colors).map((color) => ({
- swatch: theme.colors[color][6],
- color,
- }));
-
- if (!color || !configName) return null;
-
- const handleSelection = (color: MantineTheme['primaryColor']) => {
- setColor(color);
- if (type === 'primary') setPrimaryColor(color);
- else setSecondaryColor(color);
- updateConfig(configName, (prev) => {
- const { colors } = prev.settings.customization;
- colors[type] = color;
- return {
- ...prev,
- settings: {
- ...prev.settings,
- customization: {
- ...prev.settings.customization,
- colors,
- },
- },
- };
- });
- };
-
- const swatches = colors.map(({ color, swatch }) => (
-
- handleSelection(color)}
- color={swatch}
- size={22}
- style={{ cursor: 'pointer' }}
- />
-
- ));
-
- return (
-
-
-
-
-
-
-
- {swatches}
-
-
-
-
- {t('suffix', {
- color: type[0].toUpperCase() + type.slice(1),
- })}
-
-
- );
-}
diff --git a/src/components/Settings/Customization/Theme/CustomCssChanger.tsx b/src/components/Settings/Customization/Theme/CustomCssChanger.tsx
deleted file mode 100644
index 335c9cebd..000000000
--- a/src/components/Settings/Customization/Theme/CustomCssChanger.tsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import { Box, Group, Loader, Stack, Text, createStyles, useMantineTheme } from '@mantine/core';
-import { useDebouncedValue } from '@mantine/hooks';
-import { useTranslation } from 'next-i18next';
-import { highlight, languages } from 'prismjs';
-import 'prismjs/components/prism-css';
-import 'prismjs/themes/prism.css';
-import { useEffect, useState } from 'react';
-import Editor from 'react-simple-code-editor';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-
-export const CustomCssChanger = () => {
- const { t } = useTranslation('settings/customization/page-appearance');
- const updateConfig = useConfigStore((x) => x.updateConfig);
- const { colorScheme, colors } = useMantineTheme();
- const { config, name: configName } = useConfigContext();
- const [nonDebouncedCustomCSS, setNonDebouncedCustomCSS] = useState(
- config?.settings.customization.customCss ?? ''
- );
- const [debouncedCustomCSS] = useDebouncedValue(nonDebouncedCustomCSS, 696);
- const { classes } = useStyles();
-
- if (!configName) return null;
-
- useEffect(() => {
- updateConfig(configName, (prev) => ({
- ...prev,
- settings: {
- ...prev.settings,
- customization: {
- ...prev.settings.customization,
- customCss: debouncedCustomCSS,
- },
- },
- }));
- }, [debouncedCustomCSS]);
-
- const codeIsDirty = nonDebouncedCustomCSS !== debouncedCustomCSS;
- const codeEditorHeight = codeIsDirty ? 250 - 42 : 250;
-
- return (
-
- {t('customCSS.label')}
-
- {t('customCSS.description')}
-
-
- setNonDebouncedCustomCSS(code)}
- highlight={(code) => highlight(code, languages.extend('css', {}), 'css')}
- padding={10}
- style={{
- fontFamily: '"Fira code", "Fira Mono", monospace',
- fontSize: 12,
- minHeight: codeEditorHeight,
- }}
- />
- {codeIsDirty && (
-
-
-
- {t('customCSS.applying')}
-
-
- )}
-
-
- );
-};
-
-const useStyles = createStyles(({ colors, colorScheme, radius }) => ({
- codeEditorFooter: {
- borderBottomLeftRadius: radius.sm,
- borderBottomRightRadius: radius.sm,
- backgroundColor: colorScheme === 'dark' ? colors.dark[7] : undefined,
- },
- codeEditorRoot: {
- borderColor: colorScheme === 'dark' ? colors.dark[4] : colors.gray[4],
- borderWidth: 1,
- borderStyle: 'solid',
- borderRadius: radius.sm,
- },
- codeEditor: {
- backgroundColor: colorScheme === 'dark' ? colors.dark[6] : 'white',
- fontSize: 12,
-
- '& ::placeholder': {
- color: colorScheme === 'dark' ? colors.dark[3] : colors.gray[5],
- },
- },
-}));
diff --git a/src/components/Settings/Customization/Theme/OpacitySelector.tsx b/src/components/Settings/Customization/Theme/OpacitySelector.tsx
deleted file mode 100644
index ef25ef364..000000000
--- a/src/components/Settings/Customization/Theme/OpacitySelector.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import { Slider, Stack, Text } from '@mantine/core';
-import { useTranslation } from 'next-i18next';
-import { useState } from 'react';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-
-export function DashboardTilesOpacitySelector() {
- const { config, name: configName } = useConfigContext();
- const [opacity, setOpacity] = useState(config?.settings.customization.appOpacity || 100);
- const { t } = useTranslation('settings/customization/opacity-selector');
-
- const updateConfig = useConfigStore((x) => x.updateConfig);
-
- if (!configName) return null;
-
- const handleChange = (opacity: number) => {
- setOpacity(opacity);
- updateConfig(configName, (prev) => ({
- ...prev,
- settings: {
- ...prev.settings,
- customization: {
- ...prev.settings.customization,
- appOpacity: opacity,
- },
- },
- }));
- };
-
- return (
-
- {t('label')}
-
-
- );
-}
-
-const MARKS = [
- { value: 10, label: '10' },
- { value: 20, label: '20' },
- { value: 30, label: '30' },
- { value: 40, label: '40' },
- { value: 50, label: '50' },
- { value: 60, label: '60' },
- { value: 70, label: '70' },
- { value: 80, label: '80' },
- { value: 90, label: '90' },
- { value: 100, label: '100' },
-];
diff --git a/src/components/Settings/Customization/Theme/ShadeSelector.tsx b/src/components/Settings/Customization/Theme/ShadeSelector.tsx
deleted file mode 100644
index 82453c611..000000000
--- a/src/components/Settings/Customization/Theme/ShadeSelector.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import {
- ColorSwatch,
- Grid,
- Group,
- MantineTheme,
- Popover,
- Stack,
- Text,
- useMantineTheme,
-} from '@mantine/core';
-import { useDisclosure } from '@mantine/hooks';
-import { useTranslation } from 'next-i18next';
-import { useState } from 'react';
-
-import { useConfigContext } from '../../../../config/provider';
-import { useConfigStore } from '../../../../config/store';
-import { useColorTheme } from '../../../../tools/color';
-
-export function ShadeSelector() {
- const { t } = useTranslation('settings/customization/shade-selector');
- const { config, name: configName } = useConfigContext();
- const [shade, setShade] = useState(config?.settings.customization.colors.shade);
- const [popoverOpened, popover] = useDisclosure(false);
- const { primaryColor, setPrimaryShade } = useColorTheme();
-
- const updateConfig = useConfigStore((x) => x.updateConfig);
-
- const theme = useMantineTheme();
- const primaryShades = theme.colors[primaryColor].map((s, i) => ({
- swatch: theme.colors[primaryColor][i],
- shade: i as MantineTheme['primaryShade'],
- }));
-
- if (shade === undefined || !configName) return null;
-
- const handleSelection = (shade: MantineTheme['primaryShade']) => {
- setPrimaryShade(shade);
- setShade(shade);
- updateConfig(configName, (prev) => ({
- ...prev,
- settings: {
- ...prev.settings,
- customization: {
- ...prev.settings.customization,
- colors: {
- ...prev.settings.customization.colors,
- shade,
- },
- },
- },
- }));
- };
-
- const primarySwatches = primaryShades.map(({ swatch, shade }) => (
-
- handleSelection(shade)}
- color={swatch}
- size={22}
- style={{ cursor: 'pointer' }}
- />
-
- ));
-
- return (
-
-
-
-
-
-
-
-
- {primarySwatches}
-
-
-
-
- {t('label')}
-
- );
-}
diff --git a/src/components/Settings/SettingsDrawer.tsx b/src/components/Settings/SettingsDrawer.tsx
deleted file mode 100644
index f2906947b..000000000
--- a/src/components/Settings/SettingsDrawer.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import { Drawer, Tabs, Title } from '@mantine/core';
-import { useTranslation } from 'next-i18next';
-
-import { useConfigContext } from '../../config/provider';
-import { useConfigStore } from '../../config/store';
-import CommonSettings from './Common/CommonSettings';
-import CustomizationSettings from './Customization/CustomizationSettings';
-
-function SettingsMenu({ newVersionAvailable }: { newVersionAvailable: string }) {
- const { t } = useTranslation('settings/common');
-
- return (
-
-
- {t('tabs.common')}
- {t('tabs.customizations')}
-
-
-
-
-
-
-
-
- );
-}
-
-interface SettingsDrawerProps {
- opened: boolean;
- closeDrawer: () => void;
-}
-
-export function SettingsDrawer({
- opened,
- closeDrawer,
- newVersionAvailable,
-}: SettingsDrawerProps & { newVersionAvailable: string }) {
- const { t } = useTranslation('settings/common');
- const { config, name: configName } = useConfigContext();
- const { updateConfig } = useConfigStore();
-
- return (
- {t('title')}}
- opened={opened}
- onClose={() => {
- closeDrawer();
- if (!configName || !config) {
- return;
- }
-
- updateConfig(configName, (_) => config, false, true);
- }}
- transitionProps={{ transition: 'slide-left' }}
- >
-
-
- );
-}
diff --git a/src/components/Settings/Customization/Accessibility/AccessibilitySettings.tsx b/src/components/User/Preferences/AccessibilitySettings.tsx
similarity index 100%
rename from src/components/Settings/Customization/Accessibility/AccessibilitySettings.tsx
rename to src/components/User/Preferences/AccessibilitySettings.tsx
diff --git a/src/components/layout/Background.tsx b/src/components/layout/Background.tsx
deleted file mode 100644
index 0f714d1b3..000000000
--- a/src/components/layout/Background.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { Global } from '@mantine/core';
-
-import { useConfigContext } from '../../config/provider';
-
-export function Background() {
- const { config } = useConfigContext();
-
- if (!config?.settings.customization.backgroundImageUrl) {
- return null;
- }
-
- return (
-
- );
-}
diff --git a/src/components/layout/Logo.tsx b/src/components/layout/Common/Logo.tsx
similarity index 94%
rename from src/components/layout/Logo.tsx
rename to src/components/layout/Common/Logo.tsx
index 21a4833d9..f57470864 100644
--- a/src/components/layout/Logo.tsx
+++ b/src/components/layout/Common/Logo.tsx
@@ -1,7 +1,7 @@
import { Group, Image, Text } from '@mantine/core';
import { useScreenLargerThan } from '~/hooks/useScreenLargerThan';
-import { useConfigContext } from '../../config/provider';
+import { useConfigContext } from '../../../config/provider';
import { usePrimaryGradient } from './useGradient';
interface LogoProps {
diff --git a/src/components/layout/useCardStyles.ts b/src/components/layout/Common/useCardStyles.ts
similarity index 93%
rename from src/components/layout/useCardStyles.ts
rename to src/components/layout/Common/useCardStyles.ts
index d08fd1aac..d813b6bcc 100644
--- a/src/components/layout/useCardStyles.ts
+++ b/src/components/layout/Common/useCardStyles.ts
@@ -1,6 +1,6 @@
import { createStyles } from '@mantine/core';
-import { useConfigContext } from '../../config/provider';
+import { useConfigContext } from '../../../config/provider';
export const useCardStyles = (isCategory: boolean) => {
const { config } = useConfigContext();
diff --git a/src/components/layout/useGradient.tsx b/src/components/layout/Common/useGradient.tsx
similarity index 82%
rename from src/components/layout/useGradient.tsx
rename to src/components/layout/Common/useGradient.tsx
index f63e0e8bd..8675a6447 100644
--- a/src/components/layout/useGradient.tsx
+++ b/src/components/layout/Common/useGradient.tsx
@@ -1,6 +1,6 @@
import { MantineGradient } from '@mantine/core';
-import { useColorTheme } from '../../tools/color';
+import { useColorTheme } from '../../../tools/color';
export const usePrimaryGradient = (): MantineGradient => {
const { primaryColor, secondaryColor } = useColorTheme();
diff --git a/src/components/layout/Meta/BoardHead.tsx b/src/components/layout/Meta/BoardHead.tsx
new file mode 100644
index 000000000..f91e338f2
--- /dev/null
+++ b/src/components/layout/Meta/BoardHead.tsx
@@ -0,0 +1,31 @@
+import Head from 'next/head';
+import React from 'react';
+
+import { useConfigContext } from '../../../config/provider';
+
+export const BoardHeadOverride = () => {
+ const { config } = useConfigContext();
+
+ if (!config) return null;
+
+ const { metaTitle, faviconUrl } = config.settings.customization;
+
+ return (
+
+ {metaTitle && metaTitle.length > 0 && (
+ <>
+ {metaTitle}
+
+ >
+ )}
+
+ {faviconUrl && faviconUrl.length > 0 && (
+ <>
+
+
+
+ >
+ )}
+
+ );
+};
diff --git a/src/components/layout/common-header.tsx b/src/components/layout/Meta/CommonHead.tsx
similarity index 54%
rename from src/components/layout/common-header.tsx
rename to src/components/layout/Meta/CommonHead.tsx
index b8559141f..4651cae36 100644
--- a/src/components/layout/common-header.tsx
+++ b/src/components/layout/Meta/CommonHead.tsx
@@ -1,13 +1,12 @@
+import { useMantineTheme } from '@mantine/core';
import Head from 'next/head';
-import { ReactNode } from 'react';
-interface CommonHeaderProps {
- children?: ReactNode;
-}
+export const CommonHead = () => {
+ const { colorScheme } = useMantineTheme();
-export const CommonHeader = ({ children }: CommonHeaderProps) => {
return (
+
@@ -18,7 +17,10 @@ export const CommonHeader = ({ children }: CommonHeaderProps) => {
- {children}
+
);
};
diff --git a/src/components/layout/Meta/Head.tsx b/src/components/layout/Meta/Head.tsx
deleted file mode 100644
index 9a1cda3e4..000000000
--- a/src/components/layout/Meta/Head.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-/* eslint-disable react/no-invalid-html-attribute */
-import NextHead from 'next/head';
-import React from 'react';
-
-import { useConfigContext } from '../../../config/provider';
-import { SafariStatusBarStyle } from './SafariStatusBarStyle';
-
-export function Head() {
- const { config } = useConfigContext();
-
- return (
-
- {config?.settings.customization.metaTitle || 'Homarr 🦞'}
-
-
-
-
- {/* configure apple splash screen & touch icon */}
-
-
-
-
-
-
- );
-}
diff --git a/src/components/layout/Meta/SafariStatusBarStyle.tsx b/src/components/layout/Meta/SafariStatusBarStyle.tsx
deleted file mode 100644
index e712c871a..000000000
--- a/src/components/layout/Meta/SafariStatusBarStyle.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { useMantineTheme } from '@mantine/core';
-
-export const SafariStatusBarStyle = () => {
- const { colorScheme } = useMantineTheme();
- const isDark = colorScheme === 'dark';
- return (
-
- );
-};
diff --git a/src/components/layout/Templates/BoardLayout.tsx b/src/components/layout/Templates/BoardLayout.tsx
index 30c2ab0cc..d2872416b 100644
--- a/src/components/layout/Templates/BoardLayout.tsx
+++ b/src/components/layout/Templates/BoardLayout.tsx
@@ -1,4 +1,4 @@
-import { Button, Text, Title, Tooltip, clsx } from '@mantine/core';
+import { Button, Global, Text, Title, Tooltip, clsx } from '@mantine/core';
import { useHotkeys, useWindowEvent } from '@mantine/hooks';
import { openContextModal } from '@mantine/modals';
import { hideNotification, showNotification } from '@mantine/notifications';
@@ -19,8 +19,8 @@ import { useConfigContext } from '~/config/provider';
import { env } from '~/env';
import { api } from '~/utils/api';
-import { Background } from '../Background';
import { HeaderActionButton } from '../Header/ActionButton';
+import { BoardHeadOverride } from '../Meta/BoardHead';
import { MainLayout } from './MainLayout';
type BoardLayoutProps = {
@@ -32,7 +32,8 @@ export const BoardLayout = ({ children }: BoardLayoutProps) => {
return (
}>
-
+
+
{children}
@@ -195,3 +196,25 @@ const AddElementButton = () => {
);
};
+
+const BackgroundImage = () => {
+ const { config } = useConfigContext();
+
+ if (!config?.settings.customization.backgroundImageUrl) {
+ return null;
+ }
+
+ return (
+
+ );
+};
diff --git a/src/components/layout/Templates/MainLayout.tsx b/src/components/layout/Templates/MainLayout.tsx
index dd1e393f5..35831df84 100644
--- a/src/components/layout/Templates/MainLayout.tsx
+++ b/src/components/layout/Templates/MainLayout.tsx
@@ -1,7 +1,6 @@
import { AppShell, useMantineTheme } from '@mantine/core';
import { MainHeader } from '../Header/Header';
-import { Head } from '../Meta/Head';
type MainLayoutProps = {
headerActions?: React.ReactNode;
@@ -21,7 +20,6 @@ export const MainLayout = ({ headerActions, children }: MainLayoutProps) => {
header={}
className="dashboard-app-shell"
>
-
{children}
);
diff --git a/src/components/layout/Templates/ManageLayout.tsx b/src/components/layout/Templates/ManageLayout.tsx
index ff32aba6d..63ba3d303 100644
--- a/src/components/layout/Templates/ManageLayout.tsx
+++ b/src/components/layout/Templates/ManageLayout.tsx
@@ -33,7 +33,6 @@ import { useScreenLargerThan } from '~/hooks/useScreenLargerThan';
import { usePackageAttributesStore } from '~/tools/client/zustands/usePackageAttributesStore';
import { MainHeader } from '../Header/Header';
-import { CommonHeader } from '../common-header';
interface ManageLayoutProps {
children: ReactNode;
@@ -143,7 +142,6 @@ export const ManageLayout = ({ children }: ManageLayoutProps) => {
return (
<>
-
-
-
-
+
-
+
Login • Homarr
-
+
{t('title')}
diff --git a/src/pages/manage/boards/index.tsx b/src/pages/manage/boards/index.tsx
index 7d6c5831c..7335100c7 100644
--- a/src/pages/manage/boards/index.tsx
+++ b/src/pages/manage/boards/index.tsx
@@ -21,9 +21,9 @@ import {
IconPlus,
IconTrash,
} from '@tabler/icons-react';
+import Head from 'next/head';
import Link from 'next/link';
import { ManageLayout } from '~/components/layout/Templates/ManageLayout';
-import { CommonHeader } from '~/components/layout/common-header';
import { sleep } from '~/tools/client/time';
import { api } from '~/utils/api';
@@ -34,9 +34,9 @@ const BoardsPage = () => {
return (
-
+
Boards • Homarr
-
+
Boards
diff --git a/src/pages/manage/settings/index.tsx b/src/pages/manage/settings/index.tsx
index fe9d1a41f..57bc4a9a7 100644
--- a/src/pages/manage/settings/index.tsx
+++ b/src/pages/manage/settings/index.tsx
@@ -1,13 +1,13 @@
import { Text, Title } from '@mantine/core';
+import Head from 'next/head';
import { ManageLayout } from '~/components/layout/Templates/ManageLayout';
-import { CommonHeader } from '~/components/layout/common-header';
const SettingsPage = () => {
return (
-
+
Settings • Homarr
-
+
Settings
Coming soon!
diff --git a/src/pages/user/preferences.tsx b/src/pages/user/preferences.tsx
index 3205d290a..891fef13f 100644
--- a/src/pages/user/preferences.tsx
+++ b/src/pages/user/preferences.tsx
@@ -2,12 +2,12 @@ import { Button, Group, Select, Stack, Text, Title } from '@mantine/core';
import { createFormContext } from '@mantine/form';
import type { InferGetServerSidePropsType } from 'next';
import { GetServerSidePropsContext } from 'next';
+import Head from 'next/head';
import { forwardRef } from 'react';
import { useTranslation } from 'react-i18next';
import { z } from 'zod';
-import { AccessibilitySettings } from '~/components/Settings/Customization/Accessibility/AccessibilitySettings';
+import { AccessibilitySettings } from '~/components/User/Preferences/AccessibilitySettings';
import { ManageLayout } from '~/components/layout/Templates/ManageLayout';
-import { CommonHeader } from '~/components/layout/common-header';
import { languages } from '~/tools/language';
import { getServerSideTranslations } from '~/tools/server/getServerSideTranslations';
import { manageNamespaces } from '~/tools/server/translation-namespaces';
@@ -20,9 +20,9 @@ const PreferencesPage = ({ locale }: InferGetServerSidePropsType
-
+
Preferences • Homarr
-
+
Preferences
{data && }
@@ -141,7 +141,12 @@ const SelectItem = forwardRef(
);
export async function getServerSideProps({ req, res, locale }: GetServerSidePropsContext) {
- const translations = await getServerSideTranslations(manageNamespaces, locale, undefined, undefined);
+ const translations = await getServerSideTranslations(
+ manageNamespaces,
+ locale,
+ undefined,
+ undefined
+ );
return {
props: {
...translations,