devices stat cards can be selected to list by device state

This commit is contained in:
Carter 2025-01-27 12:15:10 -06:00
parent 3a000b0094
commit adbf83808f
3 changed files with 104 additions and 30 deletions

View file

@ -27,8 +27,6 @@ export default function CircleGraphIcon(props: Props) {
const exists = props.color ? props.color in theme.palette : false
const color = exists && props.color ? (theme.palette as any)[props.color].main : props.color
console.log(props.color)
console.log(color)
return (
<Box

View file

@ -2,26 +2,49 @@ import {
AutoAwesomeMosaic,
Battery20,
Check,
CheckCircle,
PermScanWifi,
} from "@mui/icons-material";
import { Card, Grid2, Typography, useTheme } from "@mui/material";
import { blue, green, purple, red } from "@mui/material/colors";
import { Card, Grid2, Skeleton, Theme, Typography, useTheme } from "@mui/material";
import { green } from "@mui/material/colors";
import { makeStyles } from "@mui/styles";
import classNames from "classnames";
import CircleGraphIcon from "common/CircleGraphIcon";
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
import { pond } from "protobuf-ts/pond";
import { useDeviceAPI } from "providers";
import { useEffect, useState } from "react";
interface Props {}
const useStyles = makeStyles((theme: Theme) => {
return ({
card: {
padding: theme.spacing(1),
height: theme.spacing(10),
alignContent: "center",
"&:hover": {
cursor: "pointer",
backgroundColor: "rgba(150, 150, 150, 0.15)",
// border: "1px solid rgba(255, 255, 255, 0.25)"
}
},
cardSelected: {
border: "1px solid " + green[400]
}
});
});
interface Props {
setSearch: React.Dispatch<React.SetStateAction<string>>,
}
export default function DevicesSummary(props: Props) {
const { setSearch } = props;
const deviceAPI = useDeviceAPI()
const theme = useTheme()
const classes = useStyles()
const [stats, setStats] = useState<pond.DeviceStatistics>(pond.DeviceStatistics.create())
const [loadingStats, setLoadingStats] = useState(false)
const [selected, setSelected] = useState("");
const loadDeviceStatistics = () => {
setLoadingStats(true)
@ -40,6 +63,23 @@ export default function DevicesSummary(props: Props) {
loadDeviceStatistics()
}, [])
useEffect(() => {
switch (selected) {
case "total":
setSearch("");
break;
case "active":
setSearch("DEVICE_STATE_OK");
break;
case "warning":
setSearch("DEVICE_STATE_LOW_POWER");
break;
case "offline":
setSearch("DEVICE_STATE_MISSING");
break;
}
}, [selected])
const getPercent = (devices: number) => {
const ratio = devices/stats.total
return ratio*100
@ -48,29 +88,49 @@ export default function DevicesSummary(props: Props) {
return (
<Grid2 container spacing={1} marginBlock={1} >
<Grid2 size={{xs: 6, sm: 3}}>
<Card sx={{ padding: 1 }}>
<Grid2 container spacing={1} justifyContent={"center"} alignItems={"center"} >
<Grid2>
<CircleGraphIcon
sx={{ marginRight: 1, marginLeft: 1 }}
progress={100}
color={"info"}
icon={<AutoAwesomeMosaic />}
/>
{loadingStats ?
<Skeleton className={classes.card} />
:
<Card
className={
classNames(
classes.card,
selected==="total" ? classes.cardSelected : undefined
)
}
onClick={() => setSelected("total")}
>
<Grid2 container spacing={1} justifyContent={"center"} alignItems={"center"} >
<Grid2>
<CircleGraphIcon
sx={{ marginRight: 1, marginLeft: 1 }}
progress={100}
color={"info"}
icon={<AutoAwesomeMosaic />}
/>
</Grid2>
<Grid2 marginRight={1}>
<Typography variant="h6" >
{stats.total} Devices
</Typography>
<Typography variant="subtitle2" color="textSecondary">
Total
</Typography>
</Grid2>
</Grid2>
<Grid2 marginRight={1}>
<Typography variant="h6" >
{stats.total} Devices
</Typography>
<Typography variant="subtitle2" color="textSecondary">
Total
</Typography>
</Grid2>
</Grid2>
</Card>
</Card>
}
</Grid2>
<Grid2 size={{xs: 6, sm: 3}}>
<Card sx={{ padding: 1 }}>
<Card
className={
classNames(
classes.card,
selected==="active" ? classes.cardSelected : undefined
)
}
onClick={() => setSelected("active")}
>
<Grid2 container spacing={1} justifyContent={"center"} alignItems={"center"} >
<Grid2>
<CircleGraphIcon
@ -92,7 +152,15 @@ export default function DevicesSummary(props: Props) {
</Card>
</Grid2>
<Grid2 size={{xs: 6, sm: 3}}>
<Card sx={{ padding: 1 }}>
<Card
className={
classNames(
classes.card,
selected==="warning" ? classes.cardSelected : undefined
)
}
onClick={() => setSelected("warning")}
>
<Grid2 container spacing={1} justifyContent={"center"} alignItems={"center"} >
<Grid2>
<CircleGraphIcon
@ -114,7 +182,15 @@ export default function DevicesSummary(props: Props) {
</Card>
</Grid2>
<Grid2 size={{xs: 6, sm: 3}}>
<Card sx={{ padding: 1 }}>
<Card
className={
classNames(
classes.card,
selected==="offline" ? classes.cardSelected : undefined
)
}
onClick={() => setSelected("offline")}
>
<Grid2 container spacing={1} justifyContent={"center"} alignItems={"center"} >
<Grid2>
<CircleGraphIcon

View file

@ -363,7 +363,7 @@ export default function Devices() {
<Tab wrapped value={"never"} label={<CreateGroupIcon className={classes.green} />} onClick={() => openGroupSettings(undefined, "add")} />
</Tabs>
</Box>
<DevicesSummary />
<DevicesSummary setSearch={setSearch} />
<ResponsiveTable<Device>
title={<SmartBreadcrumb prependPaths={getGroup() && ["groups", getGroup().id().toString()]} groupName={getGroup() && getGroup().name()} paddingBottom={1}/>}
subtitle={subtitle()}