Can select catchup hours
This commit is contained in:
parent
8a65687970
commit
596d22739d
@ -18,6 +18,7 @@ import { dayjsToTimeOfDay, timeOfDay } from "../utils/DateUtils";
|
|||||||
import { lenValid } from "../utils/StringsUtils";
|
import { lenValid } from "../utils/StringsUtils";
|
||||||
import { CheckboxInput } from "../widgets/forms/CheckboxInput";
|
import { CheckboxInput } from "../widgets/forms/CheckboxInput";
|
||||||
import { TextInput } from "../widgets/forms/TextInput";
|
import { TextInput } from "../widgets/forms/TextInput";
|
||||||
|
import { MultipleSelectInput } from "../widgets/forms/MultipleSelectInput";
|
||||||
|
|
||||||
export function EditDeviceRelaysDialog(p: {
|
export function EditDeviceRelaysDialog(p: {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@ -243,16 +244,23 @@ export function EditDeviceRelaysDialog(p: {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<TimePicker
|
<MultipleSelectInput
|
||||||
label="Catchup hours"
|
label="Catchup hours"
|
||||||
value={timeOfDay(relay.daily_runtime!.reset_time)}
|
helperText="The hours during which the relay should be turned on to reach expected runtime"
|
||||||
|
values={Array.apply(null, Array(24)).map((_y, i) => {
|
||||||
|
return {
|
||||||
|
label: `${i.toString().padStart(2, "0")}:00`,
|
||||||
|
value: i,
|
||||||
|
};
|
||||||
|
})}
|
||||||
|
selected={relay.daily_runtime!.catch_up_hours}
|
||||||
onChange={(d) =>
|
onChange={(d) =>
|
||||||
setRelay((r) => {
|
setRelay((r) => {
|
||||||
return {
|
return {
|
||||||
...r,
|
...r,
|
||||||
daily_runtime: {
|
daily_runtime: {
|
||||||
...r.daily_runtime!,
|
...r.daily_runtime!,
|
||||||
reset_time: d ? dayjsToTimeOfDay(d) : 0,
|
catch_up_hours: d,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
113
central_frontend/src/widgets/forms/MultipleSelectInput.tsx
Normal file
113
central_frontend/src/widgets/forms/MultipleSelectInput.tsx
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
import {
|
||||||
|
FormControl,
|
||||||
|
InputLabel,
|
||||||
|
Select,
|
||||||
|
OutlinedInput,
|
||||||
|
Box,
|
||||||
|
Chip,
|
||||||
|
MenuItem,
|
||||||
|
Theme,
|
||||||
|
useTheme,
|
||||||
|
SelectChangeEvent,
|
||||||
|
FormHelperText,
|
||||||
|
} from "@mui/material";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export interface Value<E> {
|
||||||
|
label: string;
|
||||||
|
value: E;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ITEM_HEIGHT = 48;
|
||||||
|
const ITEM_PADDING_TOP = 8;
|
||||||
|
|
||||||
|
const MenuProps = {
|
||||||
|
PaperProps: {
|
||||||
|
style: {
|
||||||
|
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
|
||||||
|
width: 250,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function getStyles<E>(v: Value<E>, selected: readonly E[], theme: Theme) {
|
||||||
|
return {
|
||||||
|
fontWeight:
|
||||||
|
selected.find((e) => e === v.value) === undefined
|
||||||
|
? theme.typography.fontWeightRegular
|
||||||
|
: theme.typography.fontWeightMedium,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MultipleSelectInput<E>(p: {
|
||||||
|
values: Value<E>[];
|
||||||
|
selected: E[];
|
||||||
|
label: string;
|
||||||
|
onChange: (selected: E[]) => void;
|
||||||
|
helperText?: string;
|
||||||
|
}): React.ReactElement {
|
||||||
|
const [labelId] = React.useState(`id-multi-${Math.random()}`);
|
||||||
|
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const handleChange = (event: SelectChangeEvent<E>) => {
|
||||||
|
const {
|
||||||
|
target: { value },
|
||||||
|
} = event;
|
||||||
|
|
||||||
|
const values: any[] =
|
||||||
|
typeof value === "string" ? value.split(",") : (value as any);
|
||||||
|
|
||||||
|
const newVals = values.map(
|
||||||
|
(v) => p.values.find((e) => String(e.value) === String(v))!.value
|
||||||
|
);
|
||||||
|
|
||||||
|
// Values that appear multiple times are toggled
|
||||||
|
const setVal = new Set<E>();
|
||||||
|
for (const el of newVals) {
|
||||||
|
if (!setVal.has(el)) setVal.add(el);
|
||||||
|
else setVal.delete(el);
|
||||||
|
}
|
||||||
|
|
||||||
|
p.onChange([...setVal]);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel id={labelId}>{p.label}</InputLabel>
|
||||||
|
<Select
|
||||||
|
multiple
|
||||||
|
labelId={labelId}
|
||||||
|
id="bad"
|
||||||
|
label={p.label}
|
||||||
|
value={p.selected as any}
|
||||||
|
onChange={handleChange}
|
||||||
|
input={<OutlinedInput id="select-multiple-chip" label="Chip" />}
|
||||||
|
renderValue={(selected) => (
|
||||||
|
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
|
||||||
|
{(selected as Array<E>).map((value) => (
|
||||||
|
<Chip
|
||||||
|
key={String(value)}
|
||||||
|
label={p.values.find((e) => e.value === value)!.label}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
MenuProps={MenuProps}
|
||||||
|
>
|
||||||
|
{p.values.map((v) => (
|
||||||
|
<MenuItem
|
||||||
|
key={v.label + String(v)}
|
||||||
|
value={String(v.value)}
|
||||||
|
style={getStyles(v, p.selected, theme)}
|
||||||
|
>
|
||||||
|
{v.label}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
{p.helperText && <FormHelperText>{p.helperText}</FormHelperText>}
|
||||||
|
</FormControl>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user