added status plenum to display plenum data, added pulseBox to extend the mui box and give it a pulsing animation of a given color
This commit is contained in:
parent
6d21ec0fc6
commit
14c1acd17c
6 changed files with 121 additions and 20 deletions
8
package-lock.json
generated
8
package-lock.json
generated
|
|
@ -10770,7 +10770,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/protobuf-ts": {
|
"node_modules/protobuf-ts": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#6cbc16a8de336d72e2e65619327e4462d26ce05d",
|
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#9074fe327f799b1faef10374bd7ede55f3eb6a17",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"protobufjs": "^6.8.8"
|
"protobufjs": "^6.8.8"
|
||||||
}
|
}
|
||||||
|
|
@ -13551,9 +13551,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "6.2.0",
|
"version": "6.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz",
|
||||||
"integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==",
|
"integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { darken, Tabs, TabsProps } from "@mui/material";
|
import { Tabs, TabsProps } from "@mui/material";
|
||||||
import React, { useEffect, useState, useRef } from "react";
|
import React, { useEffect, useState, useRef } from "react";
|
||||||
// import AnimatedTabs from "./AnimatedTabs";
|
// import AnimatedTabs from "./AnimatedTabs";
|
||||||
|
|
||||||
|
|
|
||||||
56
src/common/PulseBox.tsx
Normal file
56
src/common/PulseBox.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { Box, BoxProps, Theme } from "@mui/material";
|
||||||
|
import { makeStyles } from "@mui/styles";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
const useStyles = makeStyles((_theme: Theme) => ({
|
||||||
|
pulseWrapper: {
|
||||||
|
position: 'relative',
|
||||||
|
display: 'block', // Changed to block to respect Box margins
|
||||||
|
width: 'fit-content', // Shrinks to child width
|
||||||
|
'&::after': {
|
||||||
|
content: '""',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
border: '2px solid var(--pulse-color)',
|
||||||
|
borderRadius: 'inherit', // Should inherit from Box
|
||||||
|
animation: '$pulse 1.5s infinite ease-in-out',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'@keyframes pulse': {
|
||||||
|
from: {
|
||||||
|
transform: "scale(1)",
|
||||||
|
opacity: 1
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
transform: "scale(1.25)",
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface Props extends BoxProps {
|
||||||
|
color: string;
|
||||||
|
children: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PulseBox(props: Props) {
|
||||||
|
const { color, children, className, ...boxProps } = props;
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
{...boxProps}
|
||||||
|
className={classNames([classes.pulseWrapper, className])}
|
||||||
|
style={{ '--pulse-color': color } as React.CSSProperties}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -10,7 +10,7 @@ const useStyles = makeStyles((theme: Theme) => {
|
||||||
// const isMobile = useMobile()
|
// const isMobile = useMobile()
|
||||||
return ({
|
return ({
|
||||||
gutter: {
|
gutter: {
|
||||||
backgroundColor: darken(theme.palette.background.paper, 0.03),
|
backgroundColor: darken(theme.palette.background.paper, 0.05),
|
||||||
border: "none"
|
border: "none"
|
||||||
},
|
},
|
||||||
tableContainer: {
|
tableContainer: {
|
||||||
|
|
@ -55,7 +55,7 @@ const useStyles = makeStyles((theme: Theme) => {
|
||||||
rowHover: {
|
rowHover: {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: "rgba(150, 150, 150, 0.05)"
|
backgroundColor: "rgba(150, 150, 150, 0.15)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})},
|
})},
|
||||||
|
|
@ -323,7 +323,7 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "center"
|
justifyContent: "center",
|
||||||
}}
|
}}
|
||||||
onClick={(event) => handleCollapse(index, event)}
|
onClick={(event) => handleCollapse(index, event)}
|
||||||
// style={{pre}}
|
// style={{pre}}
|
||||||
|
|
|
||||||
51
src/common/StatusPlenum.tsx
Normal file
51
src/common/StatusPlenum.tsx
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { Grid2, Theme, Typography } from "@mui/material";
|
||||||
|
import { blue, orange } from "@mui/material/colors";
|
||||||
|
import { makeStyles } from "@mui/styles";
|
||||||
|
import { Device } from "models";
|
||||||
|
import PulseBox from "./PulseBox";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
device: Device
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
|
const lightMode = theme.palette?.mode === "light";
|
||||||
|
return ({
|
||||||
|
box: {
|
||||||
|
display: "inline-block",
|
||||||
|
borderRadius: "6px",
|
||||||
|
backgroundColor: lightMode ? "rgb(170, 170, 170)" : "rgb(34, 34, 34)",
|
||||||
|
padding: theme.spacing(0.5),
|
||||||
|
marginRight: "auto",
|
||||||
|
margin: theme.spacing(1),
|
||||||
|
},
|
||||||
|
pulse: {
|
||||||
|
// padding: theme.spacing(2)
|
||||||
|
paddingLeft: theme.spacing(-6)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
export default function StatusPlenum(props: Props) {
|
||||||
|
const { device } = props;
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PulseBox color="blue" className={classes.box} >
|
||||||
|
{/* <Box className={classes.box}> */}
|
||||||
|
<Grid2 container direction="column" >
|
||||||
|
<Grid2>
|
||||||
|
<Typography variant="body2" style={{ color: orange[500]}}>
|
||||||
|
{device.status.plenum?.temperature.toFixed(1)}°C
|
||||||
|
</Typography>
|
||||||
|
</Grid2>
|
||||||
|
<Grid2>
|
||||||
|
<Typography variant="body2" style={{ color: blue[800]}}>
|
||||||
|
{device.status.plenum?.humidity.toFixed(1)}%
|
||||||
|
</Typography>
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
{/* </Box> */}
|
||||||
|
</PulseBox>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,7 @@ import BindaptIcon from "products/Bindapt/BindaptIcon";
|
||||||
import { describePower } from "pbHelpers/Power";
|
import { describePower } from "pbHelpers/Power";
|
||||||
import { Tag as TagUI } from "common/Tag";
|
import { Tag as TagUI } from "common/Tag";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import StatusPlenum from "common/StatusPlenum";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => {
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
return ({
|
return ({
|
||||||
|
|
@ -214,6 +215,8 @@ export default function Devices() {
|
||||||
).then(resp => {
|
).then(resp => {
|
||||||
let newDevices: Device[] = []
|
let newDevices: Device[] = []
|
||||||
resp.data.devices.forEach(device => {
|
resp.data.devices.forEach(device => {
|
||||||
|
console.log(device.status)
|
||||||
|
console.log(device.status?.plenum?.overlays)
|
||||||
if (device.status?.plenum?.temperature) {
|
if (device.status?.plenum?.temperature) {
|
||||||
setHasPlenums(true)
|
setHasPlenums(true)
|
||||||
}
|
}
|
||||||
|
|
@ -325,18 +328,9 @@ export default function Devices() {
|
||||||
render: (device: Device) => {
|
render: (device: Device) => {
|
||||||
if (device.status.plenum?.temperature) {
|
if (device.status.plenum?.temperature) {
|
||||||
return (
|
return (
|
||||||
<Grid2 container direction="column" marginLeft={2}>
|
<Box sx={{ marginLeft: 1 }}>
|
||||||
<Grid2>
|
<StatusPlenum device={device} />
|
||||||
<Typography variant="body2" style={{ color: orange[300]}}>
|
</Box>
|
||||||
{device.status.plenum.temperature.toFixed(1)}°C
|
|
||||||
</Typography>
|
|
||||||
</Grid2>
|
|
||||||
<Grid2>
|
|
||||||
<Typography variant="body2" color="info">
|
|
||||||
{device.status.plenum.humidity.toFixed(1)}%
|
|
||||||
</Typography>
|
|
||||||
</Grid2>
|
|
||||||
</Grid2>
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue