mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-14 09:25:47 +01:00
Use Config provider everywhere in app
We can now load as much data as we want in the services and settings values. This solves the issue of using multiple localStorages boxes
This commit is contained in:
@@ -17,7 +17,7 @@ import { useForm } from '@mantine/hooks';
|
|||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Apps } from 'tabler-icons-react';
|
import { Apps } from 'tabler-icons-react';
|
||||||
import { ServiceTypes } from '../../tools/types';
|
import { ServiceType, ServiceTypeList } from '../../tools/types';
|
||||||
|
|
||||||
export default function AddItemShelfItem(props: any) {
|
export default function AddItemShelfItem(props: any) {
|
||||||
const { additem: addItem } = props;
|
const { additem: addItem } = props;
|
||||||
@@ -94,7 +94,7 @@ export default function AddItemShelfItem(props: any) {
|
|||||||
required
|
required
|
||||||
searchable
|
searchable
|
||||||
onChange={(value) => form.setFieldValue('type', value ?? 'Other')}
|
onChange={(value) => form.setFieldValue('type', value ?? 'Other')}
|
||||||
data={ServiceTypes}
|
data={ServiceTypeList}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ import { showNotification } from '@mantine/notifications';
|
|||||||
import { AlertCircle, Cross, X } from 'tabler-icons-react';
|
import { AlertCircle, Cross, X } from 'tabler-icons-react';
|
||||||
import AppShelfMenu from './AppShelfMenu';
|
import AppShelfMenu from './AppShelfMenu';
|
||||||
import AddItemShelfItem from './AddAppShelfItem';
|
import AddItemShelfItem from './AddAppShelfItem';
|
||||||
import { useServices } from '../../tools/state';
|
import { useConfig } from '../../tools/state';
|
||||||
import { pingQbittorrent } from '../../tools/api';
|
import { pingQbittorrent } from '../../tools/api';
|
||||||
|
import { Config } from '../../tools/types';
|
||||||
|
|
||||||
const useStyles = createStyles((theme) => ({
|
const useStyles = createStyles((theme) => ({
|
||||||
main: {
|
main: {
|
||||||
@@ -32,25 +33,29 @@ const useStyles = createStyles((theme) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const AppShelf = (props: any) => {
|
const AppShelf = (props: any) => {
|
||||||
const { services, addService, removeService, setServicesState } = useServices();
|
const { config, addService, removeService, setConfig } = useConfig();
|
||||||
const { classes } = useStyles();
|
const { classes } = useStyles();
|
||||||
const [hovering, setHovering] = useState('none');
|
const [hovering, setHovering] = useState('none');
|
||||||
|
|
||||||
|
/* A hook that is used to load the config from local storage. */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const localServices = localStorage.getItem('services');
|
const localConfig = localStorage.getItem('config');
|
||||||
if (localServices) {
|
if (localConfig) {
|
||||||
setServicesState(JSON.parse(localServices));
|
setConfig(JSON.parse(localConfig));
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
services.forEach((service) => {
|
if (config.services && config.services.length === 0) {
|
||||||
|
config.services.forEach((service) => {
|
||||||
if (service.type === 'qBittorrent') {
|
if (service.type === 'qBittorrent') {
|
||||||
pingQbittorrent(service);
|
pingQbittorrent(service);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid m="xl" gutter="xl">
|
<Grid m="xl" gutter="xl">
|
||||||
{services.map((service, i) => (
|
{config.services
|
||||||
|
? config.services.map((service, i) => (
|
||||||
<Grid.Col lg={2} sm={3} key={i}>
|
<Grid.Col lg={2} sm={3} key={i}>
|
||||||
<motion.div
|
<motion.div
|
||||||
onHoverStart={(e) => {
|
onHoverStart={(e) => {
|
||||||
@@ -77,7 +82,8 @@ const AppShelf = (props: any) => {
|
|||||||
</AspectRatio>
|
</AspectRatio>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
))}
|
))
|
||||||
|
: null}
|
||||||
<AddItemShelfItem additem={addService} />
|
<AddItemShelfItem additem={addService} />
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { Dropzone, DropzoneStatus, FullScreenDropzone, IMAGE_MIME_TYPE } from '@
|
|||||||
import { showNotification } from '@mantine/notifications';
|
import { showNotification } from '@mantine/notifications';
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useServices } from '../../tools/state';
|
import { useConfig } from '../../tools/state';
|
||||||
import { serviceItem } from '../../tools/types';
|
import { Config, serviceItem } from '../../tools/types';
|
||||||
|
|
||||||
function getIconColor(status: DropzoneStatus, theme: MantineTheme) {
|
function getIconColor(status: DropzoneStatus, theme: MantineTheme) {
|
||||||
return status.accepted
|
return status.accepted
|
||||||
@@ -48,7 +48,7 @@ export const dropzoneChildren = (status: DropzoneStatus, theme: MantineTheme) =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
export default function LoadConfigComponent(props: any) {
|
export default function LoadConfigComponent(props: any) {
|
||||||
const { services, addService, removeService, setServicesState } = useServices();
|
const { saveConfig, setConfig } = useConfig();
|
||||||
const theme = useMantineTheme();
|
const theme = useMantineTheme();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const openRef = useRef<() => void>();
|
const openRef = useRef<() => void>();
|
||||||
@@ -58,7 +58,7 @@ export default function LoadConfigComponent(props: any) {
|
|||||||
onDrop={(files) => {
|
onDrop={(files) => {
|
||||||
files[0].text().then((e) => {
|
files[0].text().then((e) => {
|
||||||
try {
|
try {
|
||||||
JSON.parse(e) as serviceItem[];
|
JSON.parse(e) as Config;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showNotification({
|
showNotification({
|
||||||
autoClose: 5000,
|
autoClose: 5000,
|
||||||
@@ -77,7 +77,7 @@ export default function LoadConfigComponent(props: any) {
|
|||||||
icon: <Check />,
|
icon: <Check />,
|
||||||
message: undefined,
|
message: undefined,
|
||||||
});
|
});
|
||||||
setServicesState(JSON.parse(e));
|
setConfig(JSON.parse(e));
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
accept={['application/json']}
|
accept={['application/json']}
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ import { Anchor, Button, ThemeIcon, Tooltip } from '@mantine/core';
|
|||||||
import fileDownload from 'js-file-download';
|
import fileDownload from 'js-file-download';
|
||||||
import { Dropzone, DropzoneStatus, IMAGE_MIME_TYPE } from '@mantine/dropzone';
|
import { Dropzone, DropzoneStatus, IMAGE_MIME_TYPE } from '@mantine/dropzone';
|
||||||
import { Download } from 'tabler-icons-react';
|
import { Download } from 'tabler-icons-react';
|
||||||
|
import { useConfig } from '../../tools/state';
|
||||||
|
|
||||||
export default function SaveConfigComponent(props: any) {
|
export default function SaveConfigComponent(props: any) {
|
||||||
|
|
||||||
|
const { config } = useConfig();
|
||||||
function onClick(e: any) {
|
function onClick(e: any) {
|
||||||
const services = localStorage.getItem('services');
|
if (config) {
|
||||||
if (services) {
|
fileDownload(JSON.stringify(config, null, '\t'), 'services.json');
|
||||||
fileDownload(JSON.stringify(JSON.parse(services), null, '\t'), 'services.json');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -19,38 +19,22 @@ import {
|
|||||||
InfoCircle,
|
InfoCircle,
|
||||||
FileX,
|
FileX,
|
||||||
} from 'tabler-icons-react';
|
} from 'tabler-icons-react';
|
||||||
import { loadSettings } from '../../tools/settings';
|
import { useConfig } from '../../tools/state';
|
||||||
import { Settings } from '../../tools/types';
|
import { Settings } from '../../tools/types';
|
||||||
|
|
||||||
export default function SearchBar(props: any) {
|
export default function SearchBar(props: any) {
|
||||||
|
const { config, setConfig } = useConfig();
|
||||||
const [opened, setOpened] = useState(false);
|
const [opened, setOpened] = useState(false);
|
||||||
const [icon, setIcon] = useState(<Search />);
|
const [icon, setIcon] = useState(<Search />);
|
||||||
const theme = useMantineTheme();
|
const querryUrl = config.settings.searchUrl || 'https://www.google.com/search?q=';
|
||||||
const [config, setConfig] = useState<Settings>({
|
|
||||||
searchBar: true,
|
|
||||||
searchUrl: 'https://www.google.com/search?q=',
|
|
||||||
});
|
|
||||||
|
|
||||||
const querryUrl = config.searchUrl || 'https://www.google.com/search?q=';
|
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
querry: '',
|
querry: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
|
||||||
const config = loadSettings('settings');
|
|
||||||
if (config) {
|
|
||||||
showNotification({
|
|
||||||
autoClose: 1000,
|
|
||||||
title: <Text>Config loaded</Text>,
|
|
||||||
message: undefined,
|
|
||||||
});
|
|
||||||
setConfig(config);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (!config.searchBar) {
|
if (config.settings.searchBar == false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,57 +3,39 @@ import { showNotification } from '@mantine/notifications';
|
|||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { CSSProperties, useEffect, useState } from 'react';
|
import { CSSProperties, useEffect, useState } from 'react';
|
||||||
import { Mail, Settings as SettingsIcon, X } from 'tabler-icons-react';
|
import { Mail, Settings as SettingsIcon, X } from 'tabler-icons-react';
|
||||||
import { loadSettings } from '../../tools/settings';
|
import { useConfig } from '../../tools/state';
|
||||||
import { Settings } from '../../tools/types';
|
|
||||||
import SaveConfigComponent from '../Config/SaveConfig';
|
import SaveConfigComponent from '../Config/SaveConfig';
|
||||||
|
|
||||||
function SettingsMenu(props: any) {
|
function SettingsMenu(props: any) {
|
||||||
const [config, setConfig] = useState<Settings>({
|
const { config, setConfig } = useConfig();
|
||||||
searchUrl: 'https://www.google.com/search?q=',
|
|
||||||
searchBar: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const config = loadSettings('settings');
|
|
||||||
if (config) {
|
|
||||||
setConfig(config);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
return (
|
return (
|
||||||
<Group direction="column" grow>
|
<Group direction="column" grow>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Search bar querry url"
|
label="Search bar querry url"
|
||||||
defaultValue={config.searchUrl}
|
defaultValue={config.settings.searchUrl}
|
||||||
onChange={(e) => {
|
onChange={(e) =>
|
||||||
setConfig({
|
setConfig({
|
||||||
...config,
|
...config,
|
||||||
|
settings: {
|
||||||
|
...config.settings,
|
||||||
searchUrl: e.target.value,
|
searchUrl: e.target.value,
|
||||||
});
|
},
|
||||||
localStorage.setItem(
|
|
||||||
'settings',
|
|
||||||
JSON.stringify({
|
|
||||||
...config,
|
|
||||||
searchUrl: e.target.value,
|
|
||||||
})
|
})
|
||||||
);
|
}
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Group direction="column">
|
<Group direction="column">
|
||||||
<Switch
|
<Switch
|
||||||
onChange={(e) => {
|
onChange={(e) =>
|
||||||
setConfig({
|
setConfig({
|
||||||
...config,
|
...config,
|
||||||
searchBar: e.target.checked,
|
settings: {
|
||||||
});
|
...config.settings,
|
||||||
localStorage.setItem(
|
searchBar: e.currentTarget.checked,
|
||||||
'settings',
|
},
|
||||||
JSON.stringify({
|
|
||||||
...config,
|
|
||||||
searchBar: e.target.checked,
|
|
||||||
})
|
})
|
||||||
);
|
}
|
||||||
}}
|
checked={config.settings.searchBar}
|
||||||
checked={config.searchBar}
|
|
||||||
label="Enable search bar"
|
label="Enable search bar"
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import { Calendar } from '@mantine/dates';
|
|||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import MediaDisplay from './MediaDisplay';
|
import MediaDisplay from './MediaDisplay';
|
||||||
import { medias } from './mediaExample';
|
import { medias } from './mediaExample';
|
||||||
import { useServices } from '../../tools/state';
|
import { useConfig } from '../../tools/state';
|
||||||
|
|
||||||
async function GetCalendars(endDate: Date) {
|
async function GetCalendars(endDate: Date) {
|
||||||
// Load context
|
// Load context
|
||||||
const { services, addService, removeService, setServicesState } = useServices();
|
const { config, addService, removeService, setConfig } = useConfig();
|
||||||
// Load services that have the type to "Sonarr" or "Radarr"
|
// Load services that have the type to "Sonarr" or "Radarr"
|
||||||
const sonarrServices = services.filter((service) => service.type === 'Sonarr');
|
const sonarrServices = config.services.filter((service) => service.type === 'Sonarr');
|
||||||
const radarrServices = services.filter((service) => service.type === 'Radarr');
|
const radarrServices = config.services.filter((service) => service.type === 'Radarr');
|
||||||
// Merge the two arrays
|
// Merge the two arrays
|
||||||
const allServices = [...sonarrServices, ...radarrServices];
|
const allServices = [...sonarrServices, ...radarrServices];
|
||||||
// Load the calendars for each service
|
// Load the calendars for each service
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import Head from 'next/head';
|
|||||||
import { MantineProvider, ColorScheme, ColorSchemeProvider } from '@mantine/core';
|
import { MantineProvider, ColorScheme, ColorSchemeProvider } from '@mantine/core';
|
||||||
import { NotificationsProvider } from '@mantine/notifications';
|
import { NotificationsProvider } from '@mantine/notifications';
|
||||||
import Layout from '../components/layout/Layout';
|
import Layout from '../components/layout/Layout';
|
||||||
import { ServicesProvider } from '../tools/state';
|
import { ConfigProvider } from '../tools/state';
|
||||||
|
|
||||||
export default function App(props: AppProps & { colorScheme: ColorScheme }) {
|
export default function App(props: AppProps & { colorScheme: ColorScheme }) {
|
||||||
const { Component, pageProps } = props;
|
const { Component, pageProps } = props;
|
||||||
@@ -29,11 +29,11 @@ export default function App(props: AppProps & { colorScheme: ColorScheme }) {
|
|||||||
<ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>
|
<ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>
|
||||||
<MantineProvider theme={{ colorScheme }} withGlobalStyles withNormalizeCSS>
|
<MantineProvider theme={{ colorScheme }} withGlobalStyles withNormalizeCSS>
|
||||||
<NotificationsProvider position="top-right">
|
<NotificationsProvider position="top-right">
|
||||||
<ServicesProvider>
|
<ConfigProvider>
|
||||||
<Layout>
|
<Layout>
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</Layout>
|
</Layout>
|
||||||
</ServicesProvider>
|
</ConfigProvider>
|
||||||
</NotificationsProvider>
|
</NotificationsProvider>
|
||||||
</MantineProvider>
|
</MantineProvider>
|
||||||
</ColorSchemeProvider>
|
</ColorSchemeProvider>
|
||||||
|
|||||||
Reference in New Issue
Block a user