Display relay status on relays page
This commit is contained in:
		| @@ -45,6 +45,14 @@ export interface UpdatedInfo { | |||||||
|   enabled: boolean; |   enabled: boolean; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | export interface DeviceState { | ||||||
|  |   id: string; | ||||||
|  |   last_ping: number; | ||||||
|  |   online: boolean; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export type DevicesState = Map<string, DeviceState>; | ||||||
|  |  | ||||||
| export function DeviceURL(d: Device): string { | export function DeviceURL(d: Device): string { | ||||||
|   return `/dev/${encodeURIComponent(d.id)}`; |   return `/dev/${encodeURIComponent(d.id)}`; | ||||||
| } | } | ||||||
| @@ -74,6 +82,22 @@ export class DeviceApi { | |||||||
|     ).data; |     ).data; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Get the state of devices | ||||||
|  |    */ | ||||||
|  |   static async DevicesState(): Promise<DevicesState> { | ||||||
|  |     const devs: DeviceState[] = ( | ||||||
|  |       await APIClient.exec({ | ||||||
|  |         uri: "/devices/state", | ||||||
|  |         method: "GET", | ||||||
|  |       }) | ||||||
|  |     ).data; | ||||||
|  |  | ||||||
|  |     const m = new Map(); | ||||||
|  |     devs.forEach((d) => m.set(d.id, d)); | ||||||
|  |     return m; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Validate a device |    * Validate a device | ||||||
|    */ |    */ | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ import { | |||||||
| } from "@mui/material"; | } from "@mui/material"; | ||||||
| import React from "react"; | import React from "react"; | ||||||
| import { Link, useNavigate } from "react-router-dom"; | import { Link, useNavigate } from "react-router-dom"; | ||||||
| import { Device, DeviceApi, DeviceURL } from "../api/DeviceApi"; | import { Device, DeviceApi, DevicesState, DeviceURL } from "../api/DeviceApi"; | ||||||
| import { AsyncWidget } from "../widgets/AsyncWidget"; | import { AsyncWidget } from "../widgets/AsyncWidget"; | ||||||
| import { SolarEnergyRouteContainer } from "../widgets/SolarEnergyRouteContainer"; | import { SolarEnergyRouteContainer } from "../widgets/SolarEnergyRouteContainer"; | ||||||
| import { TimeWidget } from "../widgets/TimeWidget"; | import { TimeWidget } from "../widgets/TimeWidget"; | ||||||
| @@ -22,14 +22,17 @@ export function DevicesRoute(): React.ReactElement { | |||||||
|   const loadKey = React.useRef(1); |   const loadKey = React.useRef(1); | ||||||
|  |  | ||||||
|   const [list, setList] = React.useState<Device[] | undefined>(); |   const [list, setList] = React.useState<Device[] | undefined>(); | ||||||
|  |   const [states, setStates] = React.useState<DevicesState | undefined>(); | ||||||
|  |  | ||||||
|   const load = async () => { |   const load = async () => { | ||||||
|     setList(await DeviceApi.ValidatedList()); |     setList(await DeviceApi.ValidatedList()); | ||||||
|  |     setStates(await DeviceApi.DevicesState()); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   const reload = () => { |   const reload = () => { | ||||||
|     loadKey.current += 1; |     loadKey.current += 1; | ||||||
|     setList(undefined); |     setList(undefined); | ||||||
|  |     setStates(undefined); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
| @@ -45,10 +48,16 @@ export function DevicesRoute(): React.ReactElement { | |||||||
|     > |     > | ||||||
|       <AsyncWidget |       <AsyncWidget | ||||||
|         loadKey={loadKey.current} |         loadKey={loadKey.current} | ||||||
|         ready={!!list} |         ready={!!list && !!states} | ||||||
|         errMsg="Failed to load the list of validated devices!" |         errMsg="Failed to load the list of validated devices!" | ||||||
|         load={load} |         load={load} | ||||||
|         build={() => <ValidatedDevicesList onReload={reload} list={list!} />} |         build={() => ( | ||||||
|  |           <ValidatedDevicesList | ||||||
|  |             onReload={reload} | ||||||
|  |             list={list!} | ||||||
|  |             states={states!} | ||||||
|  |           /> | ||||||
|  |         )} | ||||||
|       /> |       /> | ||||||
|     </SolarEnergyRouteContainer> |     </SolarEnergyRouteContainer> | ||||||
|   ); |   ); | ||||||
| @@ -56,6 +65,7 @@ export function DevicesRoute(): React.ReactElement { | |||||||
|  |  | ||||||
| function ValidatedDevicesList(p: { | function ValidatedDevicesList(p: { | ||||||
|   list: Device[]; |   list: Device[]; | ||||||
|  |   states: DevicesState; | ||||||
|   onReload: () => void; |   onReload: () => void; | ||||||
| }): React.ReactElement { | }): React.ReactElement { | ||||||
|   const navigate = useNavigate(); |   const navigate = useNavigate(); | ||||||
| @@ -75,6 +85,7 @@ function ValidatedDevicesList(p: { | |||||||
|             <TableCell>Max number of relays</TableCell> |             <TableCell>Max number of relays</TableCell> | ||||||
|             <TableCell>Created</TableCell> |             <TableCell>Created</TableCell> | ||||||
|             <TableCell>Updated</TableCell> |             <TableCell>Updated</TableCell> | ||||||
|  |             <TableCell>Status</TableCell> | ||||||
|             <TableCell></TableCell> |             <TableCell></TableCell> | ||||||
|           </TableRow> |           </TableRow> | ||||||
|         </TableHead> |         </TableHead> | ||||||
| @@ -97,6 +108,15 @@ function ValidatedDevicesList(p: { | |||||||
|               <TableCell> |               <TableCell> | ||||||
|                 <TimeWidget time={dev.time_update} /> |                 <TimeWidget time={dev.time_update} /> | ||||||
|               </TableCell> |               </TableCell> | ||||||
|  |               <TableCell align="center"> | ||||||
|  |                 {p.states.get(dev.id)!.online ? ( | ||||||
|  |                   <strong>Online</strong> | ||||||
|  |                 ) : ( | ||||||
|  |                   <em>Offline</em> | ||||||
|  |                 )} | ||||||
|  |                 <br /> | ||||||
|  |                 <TimeWidget diff time={p.states.get(dev.id)!.last_ping} /> | ||||||
|  |               </TableCell> | ||||||
|               <TableCell> |               <TableCell> | ||||||
|                 <Tooltip title="Open device page"> |                 <Tooltip title="Open device page"> | ||||||
|                   <Link to={DeviceURL(dev)}> |                   <Link to={DeviceURL(dev)}> | ||||||
|   | |||||||
| @@ -55,11 +55,14 @@ export function timeDiffFromNow(t: number): string { | |||||||
|   return timeDiff(t, time()); |   return timeDiff(t, time()); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function TimeWidget(p: { time?: number }): React.ReactElement { | export function TimeWidget(p: { | ||||||
|  |   time?: number; | ||||||
|  |   diff?: boolean; | ||||||
|  | }): React.ReactElement { | ||||||
|   if (!p.time) return <></>; |   if (!p.time) return <></>; | ||||||
|   return ( |   return ( | ||||||
|     <Tooltip title={formatDate(p.time)} arrow> |     <Tooltip title={formatDate(p.time)} arrow> | ||||||
|       <span>{timeDiffFromNow(p.time)}</span> |       <span>{p.diff ? timeDiff(0, p.time) : timeDiffFromNow(p.time)}</span> | ||||||
|     </Tooltip> |     </Tooltip> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user