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:
Aj - Thomas
2022-05-02 15:09:39 +02:00
parent ea77bc2a18
commit c95df0a07b
8 changed files with 83 additions and 109 deletions

View File

@@ -17,7 +17,7 @@ import { useForm } from '@mantine/hooks';
import { motion } from 'framer-motion';
import { useState } from 'react';
import { Apps } from 'tabler-icons-react';
import { ServiceTypes } from '../../tools/types';
import { ServiceType, ServiceTypeList } from '../../tools/types';
export default function AddItemShelfItem(props: any) {
const { additem: addItem } = props;
@@ -94,7 +94,7 @@ export default function AddItemShelfItem(props: any) {
required
searchable
onChange={(value) => form.setFieldValue('type', value ?? 'Other')}
data={ServiceTypes}
data={ServiceTypeList}
/>
</Group>

View File

@@ -15,8 +15,9 @@ import { showNotification } from '@mantine/notifications';
import { AlertCircle, Cross, X } from 'tabler-icons-react';
import AppShelfMenu from './AppShelfMenu';
import AddItemShelfItem from './AddAppShelfItem';
import { useServices } from '../../tools/state';
import { useConfig } from '../../tools/state';
import { pingQbittorrent } from '../../tools/api';
import { Config } from '../../tools/types';
const useStyles = createStyles((theme) => ({
main: {
@@ -32,52 +33,57 @@ const useStyles = createStyles((theme) => ({
}));
const AppShelf = (props: any) => {
const { services, addService, removeService, setServicesState } = useServices();
const { config, addService, removeService, setConfig } = useConfig();
const { classes } = useStyles();
const [hovering, setHovering] = useState('none');
/* A hook that is used to load the config from local storage. */
useEffect(() => {
const localServices = localStorage.getItem('services');
if (localServices) {
setServicesState(JSON.parse(localServices));
const localConfig = localStorage.getItem('config');
if (localConfig) {
setConfig(JSON.parse(localConfig));
}
}, []);
services.forEach((service) => {
if (service.type === 'qBittorrent') {
pingQbittorrent(service);
}
});
if (config.services && config.services.length === 0) {
config.services.forEach((service) => {
if (service.type === 'qBittorrent') {
pingQbittorrent(service);
}
});
}
return (
<Grid m="xl" gutter="xl">
{services.map((service, i) => (
<Grid.Col lg={2} sm={3} key={i}>
<motion.div
onHoverStart={(e) => {
setHovering(service.name);
}}
onHoverEnd={(e) => {
setHovering('none');
}}
>
<AspectRatio ratio={4 / 3}>
<Box className={classes.main}>
<motion.div animate={{ opacity: hovering == service.name ? 1 : 0 }}>
<AppShelfMenu removeitem={removeService} name={service.name} />
</motion.div>
<Group direction="column" position="center">
<Anchor href={service.url} target="_blank">
<motion.div whileHover={{ scale: 1.2 }}>
<Image style={{ maxWidth: 60 }} src={service.icon} alt={service.name} />
{config.services
? config.services.map((service, i) => (
<Grid.Col lg={2} sm={3} key={i}>
<motion.div
onHoverStart={(e) => {
setHovering(service.name);
}}
onHoverEnd={(e) => {
setHovering('none');
}}
>
<AspectRatio ratio={4 / 3}>
<Box className={classes.main}>
<motion.div animate={{ opacity: hovering == service.name ? 1 : 0 }}>
<AppShelfMenu removeitem={removeService} name={service.name} />
</motion.div>
</Anchor>
<Text>{service.name}</Text>
</Group>
</Box>
</AspectRatio>
</motion.div>
</Grid.Col>
))}
<Group direction="column" position="center">
<Anchor href={service.url} target="_blank">
<motion.div whileHover={{ scale: 1.2 }}>
<Image style={{ maxWidth: 60 }} src={service.icon} alt={service.name} />
</motion.div>
</Anchor>
<Text>{service.name}</Text>
</Group>
</Box>
</AspectRatio>
</motion.div>
</Grid.Col>
))
: null}
<AddItemShelfItem additem={addService} />
</Grid>
);

View File

@@ -4,8 +4,8 @@ import { Dropzone, DropzoneStatus, FullScreenDropzone, IMAGE_MIME_TYPE } from '@
import { showNotification } from '@mantine/notifications';
import { useRef } from 'react';
import { useRouter } from 'next/router';
import { useServices } from '../../tools/state';
import { serviceItem } from '../../tools/types';
import { useConfig } from '../../tools/state';
import { Config, serviceItem } from '../../tools/types';
function getIconColor(status: DropzoneStatus, theme: MantineTheme) {
return status.accepted
@@ -48,7 +48,7 @@ export const dropzoneChildren = (status: DropzoneStatus, theme: MantineTheme) =>
);
export default function LoadConfigComponent(props: any) {
const { services, addService, removeService, setServicesState } = useServices();
const { saveConfig, setConfig } = useConfig();
const theme = useMantineTheme();
const router = useRouter();
const openRef = useRef<() => void>();
@@ -58,7 +58,7 @@ export default function LoadConfigComponent(props: any) {
onDrop={(files) => {
files[0].text().then((e) => {
try {
JSON.parse(e) as serviceItem[];
JSON.parse(e) as Config;
} catch (e) {
showNotification({
autoClose: 5000,
@@ -77,7 +77,7 @@ export default function LoadConfigComponent(props: any) {
icon: <Check />,
message: undefined,
});
setServicesState(JSON.parse(e));
setConfig(JSON.parse(e));
});
}}
accept={['application/json']}

View File

@@ -2,12 +2,14 @@ import { Anchor, Button, ThemeIcon, Tooltip } from '@mantine/core';
import fileDownload from 'js-file-download';
import { Dropzone, DropzoneStatus, IMAGE_MIME_TYPE } from '@mantine/dropzone';
import { Download } from 'tabler-icons-react';
import { useConfig } from '../../tools/state';
export default function SaveConfigComponent(props: any) {
const { config } = useConfig();
function onClick(e: any) {
const services = localStorage.getItem('services');
if (services) {
fileDownload(JSON.stringify(JSON.parse(services), null, '\t'), 'services.json');
if (config) {
fileDownload(JSON.stringify(config, null, '\t'), 'services.json');
}
}
return (

View File

@@ -19,38 +19,22 @@ import {
InfoCircle,
FileX,
} from 'tabler-icons-react';
import { loadSettings } from '../../tools/settings';
import { useConfig } from '../../tools/state';
import { Settings } from '../../tools/types';
export default function SearchBar(props: any) {
const { config, setConfig } = useConfig();
const [opened, setOpened] = useState(false);
const [icon, setIcon] = useState(<Search />);
const theme = useMantineTheme();
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 querryUrl = config.settings.searchUrl || 'https://www.google.com/search?q=';
const form = useForm({
initialValues: {
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;
}

View File

@@ -3,57 +3,39 @@ import { showNotification } from '@mantine/notifications';
import { motion } from 'framer-motion';
import { CSSProperties, useEffect, useState } from 'react';
import { Mail, Settings as SettingsIcon, X } from 'tabler-icons-react';
import { loadSettings } from '../../tools/settings';
import { Settings } from '../../tools/types';
import { useConfig } from '../../tools/state';
import SaveConfigComponent from '../Config/SaveConfig';
function SettingsMenu(props: any) {
const [config, setConfig] = useState<Settings>({
searchUrl: 'https://www.google.com/search?q=',
searchBar: true,
});
const { config, setConfig } = useConfig();
useEffect(() => {
const config = loadSettings('settings');
if (config) {
setConfig(config);
}
}, []);
return (
<Group direction="column" grow>
<TextInput
label="Search bar querry url"
defaultValue={config.searchUrl}
onChange={(e) => {
defaultValue={config.settings.searchUrl}
onChange={(e) =>
setConfig({
...config,
searchUrl: e.target.value,
});
localStorage.setItem(
'settings',
JSON.stringify({
...config,
settings: {
...config.settings,
searchUrl: e.target.value,
})
);
}}
},
})
}
/>
<Group direction="column">
<Switch
onChange={(e) => {
onChange={(e) =>
setConfig({
...config,
searchBar: e.target.checked,
});
localStorage.setItem(
'settings',
JSON.stringify({
...config,
searchBar: e.target.checked,
})
);
}}
checked={config.searchBar}
settings: {
...config.settings,
searchBar: e.currentTarget.checked,
},
})
}
checked={config.settings.searchBar}
label="Enable search bar"
/>
</Group>

View File

@@ -4,14 +4,14 @@ import { Calendar } from '@mantine/dates';
import dayjs from 'dayjs';
import MediaDisplay from './MediaDisplay';
import { medias } from './mediaExample';
import { useServices } from '../../tools/state';
import { useConfig } from '../../tools/state';
async function GetCalendars(endDate: Date) {
// Load context
const { services, addService, removeService, setServicesState } = useServices();
const { config, addService, removeService, setConfig } = useConfig();
// Load services that have the type to "Sonarr" or "Radarr"
const sonarrServices = services.filter((service) => service.type === 'Sonarr');
const radarrServices = services.filter((service) => service.type === 'Radarr');
const sonarrServices = config.services.filter((service) => service.type === 'Sonarr');
const radarrServices = config.services.filter((service) => service.type === 'Radarr');
// Merge the two arrays
const allServices = [...sonarrServices, ...radarrServices];
// Load the calendars for each service

View File

@@ -6,7 +6,7 @@ import Head from 'next/head';
import { MantineProvider, ColorScheme, ColorSchemeProvider } from '@mantine/core';
import { NotificationsProvider } from '@mantine/notifications';
import Layout from '../components/layout/Layout';
import { ServicesProvider } from '../tools/state';
import { ConfigProvider } from '../tools/state';
export default function App(props: AppProps & { colorScheme: ColorScheme }) {
const { Component, pageProps } = props;
@@ -29,11 +29,11 @@ export default function App(props: AppProps & { colorScheme: ColorScheme }) {
<ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>
<MantineProvider theme={{ colorScheme }} withGlobalStyles withNormalizeCSS>
<NotificationsProvider position="top-right">
<ServicesProvider>
<ConfigProvider>
<Layout>
<Component {...pageProps} />
</Layout>
</ServicesProvider>
</ConfigProvider>
</NotificationsProvider>
</MantineProvider>
</ColorSchemeProvider>