mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-11 07:55:52 +01:00
Refactor settings code; Add props access to every settings item
This commit is contained in:
@@ -17,6 +17,7 @@ import { Trans, useTranslation } from 'next-i18next';
|
|||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
import { useConfigContext } from '../../../../config/provider';
|
import { useConfigContext } from '../../../../config/provider';
|
||||||
import { useConfigStore } from '../../../../config/store';
|
import { useConfigStore } from '../../../../config/store';
|
||||||
|
import { mapObject } from '../../../../tools/client/objects';
|
||||||
import { useColorTheme } from '../../../../tools/color';
|
import { useColorTheme } from '../../../../tools/color';
|
||||||
import Widgets from '../../../../widgets';
|
import Widgets from '../../../../widgets';
|
||||||
import type { IDraggableListInputValue, IWidgetOptionValue } from '../../../../widgets/widgets';
|
import type { IDraggableListInputValue, IWidgetOptionValue } from '../../../../widgets/widgets';
|
||||||
@@ -176,6 +177,7 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
label={t(`descriptor.settings.${key}.label`)}
|
label={t(`descriptor.settings.${key}.label`)}
|
||||||
value={value as number}
|
value={value as number}
|
||||||
onChange={(v) => handleChange(key, v!)}
|
onChange={(v) => handleChange(key, v!)}
|
||||||
|
{...option.inputProps}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 'slider':
|
case 'slider':
|
||||||
@@ -193,55 +195,54 @@ const WidgetOptionTypeSwitch: FC<{
|
|||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
case 'draggable-list':
|
case 'draggable-list':
|
||||||
// eslint-disable-next-line no-case-declarations
|
/* eslint-disable no-case-declarations */
|
||||||
const typedVal = value as IDraggableListInputValue['defaultValue'];
|
const typedVal = value as IDraggableListInputValue['defaultValue'];
|
||||||
|
|
||||||
|
const extractSubValue = (liName: string, settingName: string) =>
|
||||||
|
typedVal.find((v) => v.key === liName)?.subValues?.[settingName];
|
||||||
|
|
||||||
|
const handleSubChange = (liName: string, settingName: string) => (_: any, newVal: any) =>
|
||||||
|
handleChange(
|
||||||
|
key,
|
||||||
|
typedVal.map((oldVal) =>
|
||||||
|
oldVal.key === liName
|
||||||
|
? {
|
||||||
|
...oldVal,
|
||||||
|
subValues: {
|
||||||
|
...oldVal.subValues,
|
||||||
|
[settingName]: newVal,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: oldVal
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack spacing="xs">
|
<Stack spacing="xs">
|
||||||
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
|
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
|
||||||
<DraggableList
|
<DraggableList
|
||||||
value={typedVal}
|
value={typedVal}
|
||||||
onChange={(v) => handleChange(key, v)}
|
onChange={(v) => handleChange(key, v)}
|
||||||
labels={Object.fromEntries(
|
labels={mapObject(option.items, (liName) =>
|
||||||
Object.entries(option.items).map(([graphName]) => [
|
t(`descriptor.settings.${key}.${liName}.label`)
|
||||||
graphName,
|
|
||||||
t(`descriptor.settings.${key}.${graphName}.label`),
|
|
||||||
])
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{Object.fromEntries(
|
{mapObject(option.items, (liName, liSettings) =>
|
||||||
Object.entries(option.items).map(([graphName, graph]) => [
|
Object.entries(liSettings).map(([settingName, setting], i) => (
|
||||||
graphName,
|
<WidgetOptionTypeSwitch
|
||||||
Object.entries(graph).map(([subKey, setting], i) => (
|
key={`${liName}.${settingName}.${i}`}
|
||||||
<WidgetOptionTypeSwitch
|
option={setting as IWidgetOptionValue}
|
||||||
key={`${graphName}.${subKey}.${i}`}
|
widgetId={widgetId}
|
||||||
option={setting as IWidgetOptionValue}
|
propName={`${key}.${liName}.${settingName}`}
|
||||||
widgetId={widgetId}
|
value={extractSubValue(liName, settingName)}
|
||||||
propName={`${key}.${graphName}.${subKey}`}
|
handleChange={handleSubChange(liName, settingName)}
|
||||||
value={typedVal.find((v) => v.key === graphName)?.subValues?.[subKey]}
|
/>
|
||||||
handleChange={(_, newVal) =>
|
))
|
||||||
handleChange(
|
|
||||||
key,
|
|
||||||
typedVal.map((oldVal) =>
|
|
||||||
oldVal.key === graphName
|
|
||||||
? {
|
|
||||||
...oldVal,
|
|
||||||
subValues: {
|
|
||||||
...oldVal.subValues,
|
|
||||||
[subKey]: newVal,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: oldVal
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)),
|
|
||||||
])
|
|
||||||
)}
|
)}
|
||||||
</DraggableList>
|
</DraggableList>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
/* eslint-enable no-case-declarations */
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
5
src/tools/client/objects.ts
Normal file
5
src/tools/client/objects.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export const mapObject = <T, R>(
|
||||||
|
items: Record<string, T>,
|
||||||
|
mapper: (prop: string, item: T) => R
|
||||||
|
): Record<string, R> =>
|
||||||
|
Object.fromEntries(Object.entries(items).map(([name, item]) => [name, mapper(name, item)]));
|
||||||
@@ -28,6 +28,11 @@ const definition = defineWidget({
|
|||||||
graphHeight: {
|
graphHeight: {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
defaultValue: 115,
|
defaultValue: 115,
|
||||||
|
inputProps: {
|
||||||
|
step: 5,
|
||||||
|
stepHoldDelay: 500,
|
||||||
|
stepHoldInterval: 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
graphsOrder: {
|
graphsOrder: {
|
||||||
type: 'draggable-list',
|
type: 'draggable-list',
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
import {
|
||||||
|
MultiSelectProps,
|
||||||
|
NumberInputProps,
|
||||||
|
SelectProps,
|
||||||
|
SliderProps,
|
||||||
|
SwitchProps,
|
||||||
|
TextInputProps,
|
||||||
|
} from '@mantine/core';
|
||||||
import { TablerIcon } from '@tabler/icons';
|
import { TablerIcon } from '@tabler/icons';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { AreaType } from '../types/area';
|
import { AreaType } from '../types/area';
|
||||||
@@ -41,31 +49,36 @@ export type IMultiSelectOptionValue = {
|
|||||||
type: 'multi-select';
|
type: 'multi-select';
|
||||||
defaultValue: string[];
|
defaultValue: string[];
|
||||||
data: DataType[];
|
data: DataType[];
|
||||||
|
inputProps?: Partial<MultiSelectProps>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// will show a multi-select with specified data
|
// will show a select with specified data
|
||||||
export type ISelectOptionValue = {
|
export type ISelectOptionValue = {
|
||||||
type: 'select';
|
type: 'select';
|
||||||
defaultValue: string;
|
defaultValue: string;
|
||||||
data: DataType[];
|
data: DataType[];
|
||||||
|
inputProps?: Partial<SelectProps>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// will show a switch
|
// will show a switch
|
||||||
export type ISwitchOptionValue = {
|
export type ISwitchOptionValue = {
|
||||||
type: 'switch';
|
type: 'switch';
|
||||||
defaultValue: boolean;
|
defaultValue: boolean;
|
||||||
|
inputProps?: Partial<SwitchProps>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// will show a text-input
|
// will show a text-input
|
||||||
export type ITextInputOptionValue = {
|
export type ITextInputOptionValue = {
|
||||||
type: 'text';
|
type: 'text';
|
||||||
defaultValue: string;
|
defaultValue: string;
|
||||||
|
inputProps?: Partial<TextInputProps>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// will show a number-input
|
// will show a number-input
|
||||||
export type INumberInputOptionValue = {
|
export type INumberInputOptionValue = {
|
||||||
type: 'number';
|
type: 'number';
|
||||||
defaultValue: number;
|
defaultValue: number;
|
||||||
|
inputProps?: Partial<NumberInputProps>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// will show a slider-input
|
// will show a slider-input
|
||||||
@@ -75,8 +88,10 @@ export type ISliderInputOptionValue = {
|
|||||||
min: number;
|
min: number;
|
||||||
max: number;
|
max: number;
|
||||||
step: number;
|
step: number;
|
||||||
|
inputProps?: Partial<SliderProps>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// will show a sortable list that can have sub settings
|
||||||
export type IDraggableListInputValue = {
|
export type IDraggableListInputValue = {
|
||||||
type: 'draggable-list';
|
type: 'draggable-list';
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
|
|||||||
Reference in New Issue
Block a user