Files
SolarEnergy/central_frontend/src/routes/DeviceRoute/DeviceRelays.tsx

155 lines
4.3 KiB
TypeScript

import AddIcon from "@mui/icons-material/Add";
import DeleteIcon from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit";
import {
IconButton,
ListItem,
ListItemText,
Tooltip,
Typography,
} from "@mui/material";
import React from "react";
import { Device, DeviceRelay } from "../../api/DeviceApi";
import { EditDeviceRelaysDialog } from "../../dialogs/EditDeviceRelaysDialog";
import { DeviceRouteCard } from "./DeviceRouteCard";
import { useConfirm } from "../../hooks/context_providers/ConfirmDialogProvider";
import { useLoadingMessage } from "../../hooks/context_providers/LoadingMessageProvider";
import { RelayApi, RelayStatus } from "../../api/RelayApi";
import { useSnackbar } from "../../hooks/context_providers/SnackbarProvider";
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
import { AsyncWidget } from "../../widgets/AsyncWidget";
import { TimeWidget } from "../../widgets/TimeWidget";
import { BoolText } from "../../widgets/BoolText";
export function DeviceRelays(p: {
device: Device;
onReload: () => void;
}): React.ReactElement {
const confirm = useConfirm();
const loadingMessage = useLoadingMessage();
const snackbar = useSnackbar();
const alert = useAlert();
const [dialogOpen, setDialogOpen] = React.useState(false);
const [currRelay, setCurrRelay] = React.useState<DeviceRelay | undefined>();
const createNewRelay = () => {
setDialogOpen(true);
setCurrRelay(undefined);
};
const updateRelay = async (r: DeviceRelay) => {
setDialogOpen(true);
setCurrRelay(r);
};
const deleteRelay = async (r: DeviceRelay) => {
if (
!(await confirm("Do you really want to delete this relay configuration?"))
)
return;
try {
await RelayApi.Delete(r);
p.onReload();
snackbar("The relay configuration was successfully deleted!");
} catch (e) {
console.error("Failed to delete relay!", e);
alert(`Failed to delete device relay configuration! ${e}`);
} finally {
loadingMessage.hide();
}
};
return (
<>
{dialogOpen && (
<EditDeviceRelaysDialog
device={p.device}
onClose={() => setDialogOpen(false)}
relay={currRelay}
onUpdated={() => {
setDialogOpen(false);
p.onReload();
}}
/>
)}
<DeviceRouteCard
title="Device relays"
actions={
<Tooltip title="Create new relay">
<IconButton
onClick={createNewRelay}
disabled={p.device.relays.length >= p.device.info.max_relays}
>
<AddIcon />
</IconButton>
</Tooltip>
}
>
{p.device.relays.length === 0 ? (
<Typography style={{ textAlign: "center" }}>
No relay configured yet.
</Typography>
) : (
<></>
)}
{p.device.relays.map((r, i) => (
<ListItem
alignItems="flex-start"
key={r.id}
secondaryAction={
<>
<Tooltip title="Edit the relay configuration">
<IconButton onClick={() => updateRelay(r)}>
<EditIcon />
</IconButton>
</Tooltip>
{i === p.device.relays.length - 1 && (
<Tooltip title="Delete the relay configuration">
<IconButton onClick={() => deleteRelay(r)}>
<DeleteIcon />
</IconButton>
</Tooltip>
)}
</>
}
>
<ListItemText
primary={r.name}
secondary={<RelayEntryStatus relay={r} />}
/>
</ListItem>
))}
</DeviceRouteCard>
</>
);
}
function RelayEntryStatus(
p: Readonly<{ relay: DeviceRelay }>
): React.ReactElement {
const [state, setState] = React.useState<RelayStatus | undefined>();
const load = async () => {
setState(await RelayApi.SingleStatus(p.relay));
};
return (
<AsyncWidget
loadKey={p.relay.id}
load={load}
errMsg="Failed to load relay status!"
build={() => (
<>
<BoolText val={state!.on} positive="ON" negative="OFF" /> for{" "}
<TimeWidget diff time={state!.for} />
</>
)}
/>
);
}