Can set relay forced state from UI
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
79
central_frontend/src/widgets/RelayForcedState.tsx
Normal file
79
central_frontend/src/widgets/RelayForcedState.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { MenuItem, Select, SelectChangeEvent } from "@mui/material";
|
||||
import { DeviceRelay } from "../api/DeviceApi";
|
||||
import { RelayApi, RelayStatus, SetRelayForcedState } from "../api/RelayApi";
|
||||
import { TimeWidget } from "./TimeWidget";
|
||||
import { useLoadingMessage } from "../hooks/context_providers/LoadingMessageProvider";
|
||||
import { useAlert } from "../hooks/context_providers/AlertDialogProvider";
|
||||
import { useSnackbar } from "../hooks/context_providers/SnackbarProvider";
|
||||
import React from "react";
|
||||
import { SelectForcedStateDurationDialog } from "../dialogs/SelectForcedStateDurationDialog";
|
||||
|
||||
export function RelayForcedState(p: {
|
||||
relay: DeviceRelay;
|
||||
state: RelayStatus;
|
||||
onUpdated: () => void;
|
||||
}): React.ReactElement {
|
||||
const loadingMessage = useLoadingMessage();
|
||||
const alert = useAlert();
|
||||
const snackbar = useSnackbar();
|
||||
|
||||
const [futureStateType, setFutureStateType] = React.useState<
|
||||
string | undefined
|
||||
>();
|
||||
|
||||
const handleChange = (event: SelectChangeEvent) => {
|
||||
if (event.target.value == "None") {
|
||||
submitChange({ type: "None" });
|
||||
} else {
|
||||
setFutureStateType(event.target.value);
|
||||
}
|
||||
};
|
||||
|
||||
const submitChange = async (state: SetRelayForcedState) => {
|
||||
try {
|
||||
loadingMessage.show("Setting forced state...");
|
||||
await RelayApi.SetForcedState(p.relay, state);
|
||||
p.onUpdated();
|
||||
snackbar("Forced state successfully updated!");
|
||||
} catch (e) {
|
||||
console.error(`Failed to set relay forced state! ${e}`);
|
||||
alert(`Failed to set loading state for relay! ${e}`);
|
||||
} finally {
|
||||
loadingMessage.hide();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Select
|
||||
value={p.state.forced_state.type}
|
||||
onChange={handleChange}
|
||||
size="small"
|
||||
variant="standard"
|
||||
>
|
||||
<MenuItem value={"None"}>None</MenuItem>
|
||||
<MenuItem value={"Off"}>Off</MenuItem>
|
||||
<MenuItem value={"On"}>On</MenuItem>
|
||||
</Select>
|
||||
{p.state.forced_state.type !== "None" && (
|
||||
<>
|
||||
<TimeWidget future time={p.state.forced_state.until} /> left
|
||||
</>
|
||||
)}
|
||||
|
||||
{futureStateType !== undefined && (
|
||||
<SelectForcedStateDurationDialog
|
||||
{...p}
|
||||
forcedState={futureStateType}
|
||||
onCancel={() => setFutureStateType(undefined)}
|
||||
onSubmit={(d) =>
|
||||
submitChange({
|
||||
type: futureStateType as any,
|
||||
for_secs: d,
|
||||
})
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -51,13 +51,14 @@ export function timeDiff(a: number, b: number): string {
|
||||
return `${diffYears} years`;
|
||||
}
|
||||
|
||||
export function timeDiffFromNow(t: number): string {
|
||||
return timeDiff(t, time());
|
||||
export function timeDiffFromNow(t: number, future?: boolean): string {
|
||||
return future ? timeDiff(time(), t) : timeDiff(t, time());
|
||||
}
|
||||
|
||||
export function TimeWidget(p: {
|
||||
time?: number;
|
||||
diff?: boolean;
|
||||
future?: boolean;
|
||||
}): React.ReactElement {
|
||||
if (!p.time) return <></>;
|
||||
return (
|
||||
@@ -65,7 +66,9 @@ export function TimeWidget(p: {
|
||||
title={formatDate(p.diff ? new Date().getTime() / 1000 - p.time : p.time)}
|
||||
arrow
|
||||
>
|
||||
<span>{p.diff ? timeDiff(0, p.time) : timeDiffFromNow(p.time)}</span>
|
||||
<span>
|
||||
{p.diff ? timeDiff(0, p.time) : timeDiffFromNow(p.time, p.future)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user