155 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			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} />
 | |
|         </>
 | |
|       )}
 | |
|     />
 | |
|   );
 | |
| }
 |