mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-08 22:45:49 +01:00
✨ Add new config format
Should be WAAAAY easier to work with modules now
This commit is contained in:
@@ -5,34 +5,25 @@ import { useConfig } from '../../tools/state';
|
||||
export default function ModuleEnabler(props: any) {
|
||||
const { config, setConfig } = useConfig();
|
||||
const modules = Object.values(Modules).map((module) => module);
|
||||
const enabledModules = config.settings.enabledModules ?? [];
|
||||
modules.filter((module) => enabledModules.includes(module.title));
|
||||
return (
|
||||
<Group direction="column">
|
||||
{modules.map((module) => (
|
||||
<Switch
|
||||
key={module.title}
|
||||
size="md"
|
||||
checked={enabledModules.includes(module.title)}
|
||||
checked={config.modules?.[module.title]?.enabled ?? false}
|
||||
label={`Enable ${module.title} module`}
|
||||
onChange={(e) => {
|
||||
if (e.currentTarget.checked) {
|
||||
setConfig({
|
||||
...config,
|
||||
settings: {
|
||||
...config.settings,
|
||||
enabledModules: [...enabledModules, module.title],
|
||||
modules: {
|
||||
...config.modules,
|
||||
[module.title]: {
|
||||
...config.modules?.[module.title],
|
||||
enabled: e.currentTarget.checked,
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
setConfig({
|
||||
...config,
|
||||
settings: {
|
||||
...config.settings,
|
||||
enabledModules: enabledModules.filter((m) => m !== module.title),
|
||||
},
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -21,12 +21,7 @@ export const DateModule: IModule = {
|
||||
export default function DateComponent(props: any) {
|
||||
const [date, setDate] = useState(new Date());
|
||||
const { config } = useConfig();
|
||||
const hours = date.getHours();
|
||||
const minutes = date.getMinutes();
|
||||
const isFullTime =
|
||||
config.settings[`${DateModule.title}.full`] === undefined
|
||||
? true
|
||||
: config.settings[`${DateModule.title}.full`];
|
||||
const isFullTime = config?.modules?.[DateModule.title]?.options?.full?.value ?? false;
|
||||
const formatString = isFullTime ? 'HH:mm' : 'h:mm A';
|
||||
// Change date on minute change
|
||||
// Note: Using 10 000ms instead of 1000ms to chill a little :)
|
||||
|
||||
@@ -5,9 +5,9 @@ import { IModule } from './modules';
|
||||
export function ModuleWrapper(props: any) {
|
||||
const { module }: { module: IModule } = props;
|
||||
const { config, setConfig } = useConfig();
|
||||
const enabledModules = config.settings.enabledModules ?? [];
|
||||
const enabledModules = config.modules ?? {};
|
||||
// Remove 'Module' from enabled modules titles
|
||||
const isShown = enabledModules.includes(module.title);
|
||||
const isShown = enabledModules[module.title]?.enabled ?? false;
|
||||
const theme = useMantineTheme();
|
||||
const items: JSX.Element[] = [];
|
||||
if (module.options) {
|
||||
@@ -18,25 +18,31 @@ export function ModuleWrapper(props: any) {
|
||||
// Loop over all the types with a for each loop
|
||||
types.forEach((type, index) => {
|
||||
const optionName = `${module.title}.${keys[index]}`;
|
||||
const moduleInConfig = config.modules?.[module.title];
|
||||
// TODO: Add support for other types
|
||||
if (type === 'boolean') {
|
||||
items.push(
|
||||
<Switch
|
||||
defaultChecked={
|
||||
// Set default checked to the value of the option if it exists
|
||||
config.settings[optionName] ??
|
||||
(module.options && module.options[keys[index]].value) ??
|
||||
false
|
||||
moduleInConfig?.options?.[keys[index]]?.value ?? false
|
||||
}
|
||||
defaultValue={config.settings[optionName] ?? false}
|
||||
key={keys[index]}
|
||||
onClick={(e) => {
|
||||
setConfig({
|
||||
...config,
|
||||
settings: {
|
||||
...config.settings,
|
||||
enabledModules: [...config.settings.enabledModules],
|
||||
[optionName]: e.currentTarget.checked,
|
||||
modules: {
|
||||
...config.modules,
|
||||
[module.title]: {
|
||||
...config.modules[module.title],
|
||||
options: {
|
||||
...config.modules[module.title].options,
|
||||
[keys[index]]: {
|
||||
...config.modules[module.title].options?.[keys[index]],
|
||||
value: e.currentTarget.checked,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}}
|
||||
@@ -46,7 +52,6 @@ export function ModuleWrapper(props: any) {
|
||||
}
|
||||
});
|
||||
}
|
||||
// Sussy baka
|
||||
if (!isShown) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ interface Option {
|
||||
[x: string]: OptionValues;
|
||||
}
|
||||
|
||||
interface OptionValues {
|
||||
export interface OptionValues {
|
||||
name: string;
|
||||
value: boolean;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@ export default function PingComponent(props: any) {
|
||||
|
||||
const { url }: { url: string } = props;
|
||||
const [isOnline, setOnline] = useState<State>('loading');
|
||||
const exists = config.modules?.[PingModule.title]?.enabled ?? false;
|
||||
useEffect(() => {
|
||||
if (!config.settings.enabledModules.includes('Ping Services')) {
|
||||
if (!exists) {
|
||||
return;
|
||||
}
|
||||
axios
|
||||
@@ -32,7 +33,7 @@ export default function PingComponent(props: any) {
|
||||
setOnline('down');
|
||||
});
|
||||
}, []);
|
||||
if (!config.settings.enabledModules.includes('Ping Services')) {
|
||||
if (!exists) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
|
||||
@@ -46,7 +46,10 @@ export default function SearchBar(props: any) {
|
||||
});
|
||||
|
||||
// If enabled modules doesn't contain the module, return null
|
||||
if (!config.settings.enabledModules.includes(SearchModule.title)) {
|
||||
// If module in enabled
|
||||
|
||||
const exists = config.modules?.[SearchModule.title]?.enabled ?? false;
|
||||
if (!exists) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,9 +132,7 @@ export default function WeatherComponent(props: any) {
|
||||
const { config } = useConfig();
|
||||
const [weather, setWeather] = useState({} as WeatherResponse);
|
||||
const isFahrenheit: boolean =
|
||||
config.settings[`${WeatherModule.title}.freedomunit`] === undefined
|
||||
? false
|
||||
: config.settings[`${WeatherModule.title}.freedomunit`];
|
||||
config?.modules?.[WeatherModule.title]?.options?.freedomunit?.value ?? false;
|
||||
|
||||
if ('geolocation' in navigator && location.lat === 0 && location.lng === 0) {
|
||||
navigator.geolocation.getCurrentPosition((position) => {
|
||||
@@ -163,10 +161,10 @@ export default function WeatherComponent(props: any) {
|
||||
<Group spacing={0}>
|
||||
<WeatherIcon code={weather.current_weather.weathercode} />
|
||||
<Space mx="sm" />
|
||||
<span>{weather.daily.temperature_2m_max[0]}°C</span>
|
||||
<span>{usePerferedUnit(weather.daily.temperature_2m_max[0])}</span>
|
||||
<ArrowUpRight size={16} style={{ right: 15 }} />
|
||||
<Space mx="sm" />
|
||||
<span>{weather.daily.temperature_2m_min[0]}°C</span>
|
||||
<span>{usePerferedUnit(weather.daily.temperature_2m_min[0])}</span>
|
||||
<ArrowDownRight size={16} />
|
||||
</Group>
|
||||
</Group>
|
||||
|
||||
@@ -20,12 +20,12 @@ export async function getServerSideProps(
|
||||
return {
|
||||
props: {
|
||||
config: {
|
||||
name: '',
|
||||
name: 'Default config',
|
||||
services: [],
|
||||
settings: {
|
||||
enabledModules: [],
|
||||
searchUrl: 'https://www.google.com/search?q=',
|
||||
},
|
||||
modules: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -27,10 +27,9 @@ export async function getServerSideProps({
|
||||
name: cookie.toString(),
|
||||
services: [],
|
||||
settings: {
|
||||
enabledModules: [],
|
||||
searchBar: true,
|
||||
searchUrl: 'https://www.google.com/search?q=',
|
||||
},
|
||||
modules: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
33
src/pages/tryconfig.tsx
Normal file
33
src/pages/tryconfig.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Button } from '@mantine/core';
|
||||
import { Prism } from '@mantine/prism';
|
||||
import { useState } from 'react';
|
||||
import { DateModule } from '../components/modules';
|
||||
import { useConfig } from '../tools/state';
|
||||
|
||||
export default function TryConfig(props: any) {
|
||||
const { config } = useConfig();
|
||||
const [tempConfig, setTempConfig] = useState(config);
|
||||
return (
|
||||
<>
|
||||
<Prism language="json">{JSON.stringify(tempConfig, null, 2)}</Prism>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setTempConfig({
|
||||
...tempConfig,
|
||||
modules: {
|
||||
[DateModule.title]: {
|
||||
enabled: true,
|
||||
title: DateModule.title,
|
||||
options: {
|
||||
...DateModule.options,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
Add a module to the modules thingy
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -17,10 +17,9 @@ const configContext = createContext<configContextType>({
|
||||
name: 'default',
|
||||
services: [],
|
||||
settings: {
|
||||
searchBar: true,
|
||||
searchUrl: 'https://www.google.com/search?q=',
|
||||
enabledModules: [],
|
||||
searchUrl: 'https://google.com/search?q=',
|
||||
},
|
||||
modules: {},
|
||||
},
|
||||
setConfig: () => {},
|
||||
loadConfig: async (name: string) => {},
|
||||
@@ -44,10 +43,9 @@ export function ConfigProvider({ children }: Props) {
|
||||
name: 'default',
|
||||
services: [],
|
||||
settings: {
|
||||
searchBar: true,
|
||||
searchUrl: 'https://www.google.com/search?q=',
|
||||
enabledModules: [],
|
||||
},
|
||||
modules: {},
|
||||
});
|
||||
|
||||
async function loadConfig(configName: string) {
|
||||
|
||||
@@ -1,32 +1,43 @@
|
||||
import { OptionValues } from '../components/modules/modules';
|
||||
|
||||
export interface Settings {
|
||||
searchUrl: string;
|
||||
enabledModules: string[];
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
name: string;
|
||||
services: serviceItem[];
|
||||
settings: Settings;
|
||||
modules: {
|
||||
[key: string]: ConfigModule;
|
||||
};
|
||||
}
|
||||
|
||||
interface ConfigModule {
|
||||
title: string;
|
||||
enabled: boolean;
|
||||
options: {
|
||||
[key: string]: OptionValues;
|
||||
};
|
||||
}
|
||||
|
||||
export const ServiceTypeList = [
|
||||
'Other',
|
||||
'Sonarr',
|
||||
'Radarr',
|
||||
'Lidarr',
|
||||
'qBittorrent',
|
||||
'Plex',
|
||||
'Emby',
|
||||
'Lidarr',
|
||||
'Plex',
|
||||
'Radarr',
|
||||
'Sonarr',
|
||||
'qBittorrent',
|
||||
];
|
||||
export type ServiceType =
|
||||
| 'Other'
|
||||
| 'Sonarr'
|
||||
| 'Radarr'
|
||||
| 'Emby'
|
||||
| 'Lidarr'
|
||||
| 'qBittorrent'
|
||||
| 'Plex'
|
||||
| 'Emby';
|
||||
| 'Radarr'
|
||||
| 'Sonarr'
|
||||
| 'qBittorrent';
|
||||
|
||||
export interface serviceItem {
|
||||
id: string;
|
||||
|
||||
Reference in New Issue
Block a user