Merge branch 'staging_environment'
This commit is contained in:
commit
d2fac1f335
33 changed files with 1915 additions and 116 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -42,7 +42,7 @@
|
|||
"mui-tel-input": "^7.0.0",
|
||||
"notistack": "^3.0.1",
|
||||
"openweathermap-ts": "^1.2.10",
|
||||
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#master",
|
||||
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#staging",
|
||||
"react": "^18.3.1",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-color": "^2.19.3",
|
||||
|
|
@ -10864,7 +10864,7 @@
|
|||
},
|
||||
"node_modules/protobuf-ts": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#f8704561c094b208029340cdf2ce0c510ef1eb12",
|
||||
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#3f9a71a350651fb151d18514f990794f62a8e0cc",
|
||||
"dependencies": {
|
||||
"protobufjs": "^6.8.8"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
"mui-tel-input": "^7.0.0",
|
||||
"notistack": "^3.0.1",
|
||||
"openweathermap-ts": "^1.2.10",
|
||||
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#master",
|
||||
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#staging",
|
||||
"react": "^18.3.1",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-color": "^2.19.3",
|
||||
|
|
|
|||
|
|
@ -72,14 +72,14 @@ const useStyles = makeStyles((theme: Theme) => {
|
|||
marginLeft: theme.spacing(0.05),
|
||||
marginRight: theme.spacing(0.05),
|
||||
"&:hover": {
|
||||
backgroundColor: getSecondaryColour(), //use the colour of the whitelabel
|
||||
//backgroundColor: "gold",
|
||||
//backgroundColor: getSecondaryColour(), //use the colour of the whitelabel
|
||||
backgroundColor: "gold", //for now Dustin just wants it to be gold
|
||||
color: "black",
|
||||
}
|
||||
},
|
||||
buttonToggled: {
|
||||
backgroundColor: getSecondaryColour(), //use the colour of the whitelabel
|
||||
//backgroundColor: "gold",
|
||||
//backgroundColor: getSecondaryColour(), //use the colour of the whitelabel
|
||||
backgroundColor: "gold", //for now Dustin just wants it to be gold
|
||||
color: "black",
|
||||
borderRadius: 24,
|
||||
fontWeight: "bold"
|
||||
|
|
@ -150,7 +150,7 @@ export default function ButtonGroup(props: Props){
|
|||
?
|
||||
b.icon
|
||||
:
|
||||
<Typography sx={{fontSize: textSize}}>
|
||||
<Typography sx={{fontSize: textSize ?? 13, fontWeight: checkToggled(i) ? 650 : 500}}>
|
||||
{b.title}
|
||||
</Typography>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Box, Card, Checkbox, CircularProgress, Collapse, darken, Divider, Grid2, IconButton, InputAdornment, ListItemButton, ListItemIcon, ListItemText, Menu, MenuItem, Paper, SxProps, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TextField, Theme, Typography } from "@mui/material";
|
||||
import { Box, Button, Card, Checkbox, CircularProgress, Collapse, darken, Divider, Grid2, IconButton, InputAdornment, ListItemButton, ListItemIcon, ListItemText, Menu, MenuItem, Paper, SxProps, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TextField, Theme, Typography } from "@mui/material";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { ArrowDownward, ArrowUpward, ChevronRight, Close, Search, ViewColumn } from "@mui/icons-material"
|
||||
import { useEffect, useState } from "react";
|
||||
|
|
@ -98,6 +98,8 @@ interface Props<T> {
|
|||
setOrderBy?: React.Dispatch<React.SetStateAction<string>>;
|
||||
order?: string;
|
||||
setOrder?: React.Dispatch<React.SetStateAction<"asc" | "desc">>;
|
||||
endTitleElement?: string | JSX.Element | (() => string | JSX.Element);
|
||||
loadMore?: () => void
|
||||
}
|
||||
|
||||
export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
||||
|
|
@ -130,13 +132,15 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
|||
orderBy,
|
||||
setOrderBy,
|
||||
order,
|
||||
setOrder
|
||||
setOrder,
|
||||
loadMore
|
||||
} = props
|
||||
const classes = useStyles();
|
||||
const columns = typeof(props.columns) === "function" ? props.columns() : props.columns
|
||||
const subtitle = typeof(props.subtitle) === "function" ? props.subtitle() : props.subtitle
|
||||
const title = typeof(props.title) === "function" ? props.title() : props.title
|
||||
// const order = props.order ? props.order : "asc"
|
||||
const endTitleElement = typeof(props.endTitleElement) === "function" ? props.endTitleElement() : props.endTitleElement
|
||||
|
||||
const isMobile = useMobile()
|
||||
|
||||
|
|
@ -371,6 +375,17 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
|||
</Box>
|
||||
)
|
||||
}
|
||||
{(loadMore && rows.length < total) &&
|
||||
<Box>
|
||||
<Button
|
||||
onClick={loadMore}
|
||||
color="primary"
|
||||
sx={{width: "100%"}}
|
||||
variant="contained">
|
||||
Load More
|
||||
</Button>
|
||||
</Box>
|
||||
}
|
||||
</Box>
|
||||
)
|
||||
|
||||
|
|
@ -387,8 +402,20 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
|||
const columnClick = (column: Column<T>) => {
|
||||
const sortKey = column.sortKey ? column.sortKey : column.title.toLowerCase()
|
||||
// console.log(column.sortKey)
|
||||
if (setOrderBy) setOrderBy(sortKey)
|
||||
if (setOrder && order) setOrder(order === "asc" ? "desc" : "asc")
|
||||
if (setOrderBy) {
|
||||
if (orderBy === sortKey && setOrder && order) {
|
||||
if (order === "desc") {
|
||||
setOrder("asc")
|
||||
} else {
|
||||
setOrderBy("")
|
||||
}
|
||||
// setOrder(order === "asc" ? "desc" : "asc")
|
||||
} else {
|
||||
if (setOrder) setOrder("desc")
|
||||
setOrderBy(sortKey)
|
||||
}
|
||||
}
|
||||
// if (setOrder && order) setOrder(order === "asc" ? "desc" : "asc")
|
||||
}
|
||||
|
||||
const showOrderIcon = (column: Column<T>) => {
|
||||
|
|
@ -422,6 +449,9 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
|||
<Grid2>
|
||||
{actions && actions}
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
{endTitleElement}
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
{setSearchText &&<Box className={classes.searchContainer}>
|
||||
{searchBar()}
|
||||
|
|
|
|||
149
src/common/StatusDust.tsx
Normal file
149
src/common/StatusDust.tsx
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
import { Box, Grid2, Theme, Tooltip, Typography } from "@mui/material";
|
||||
import { green } from "@mui/material/colors";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { Device } from "models";
|
||||
import PulseBox from "./PulseBox";
|
||||
import { or } from "utils";
|
||||
import { useEffect, useState } from "react";
|
||||
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(210, 210, 210)" : "rgb(50, 50, 50)",
|
||||
padding: theme.spacing(0.75),
|
||||
marginRight: "auto",
|
||||
margin: theme.spacing(1),
|
||||
width: theme.spacing(16),
|
||||
height: theme.spacing(11),
|
||||
},
|
||||
carouselContainer: {
|
||||
position: 'relative',
|
||||
height: '40px',
|
||||
overflow: 'hidden',
|
||||
textAlign: "center",
|
||||
},
|
||||
carouselItem: {
|
||||
opacity: 0,
|
||||
transform: 'translateX(100%)',
|
||||
transition: 'opacity 0.5s ease, transform 0.5s ease',
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
overflow: "hidden",
|
||||
// height: '100%',
|
||||
},
|
||||
active: {
|
||||
opacity: 1,
|
||||
transform: 'translateX(0)',
|
||||
},
|
||||
inactive: {
|
||||
transform: 'translateX(-100%)',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
export default function StatusDust(props: Props) {
|
||||
const { device } = props;
|
||||
const classes = useStyles()
|
||||
|
||||
const colors = or(device.status.sen5x?.overlays.map(overlay => overlay.color), []);
|
||||
const messages = or(device.status.sen5x?.overlays.map(overlay => overlay.message), []);
|
||||
|
||||
const [color, setColor] = useState(colors.length > 0 ? colors[0] : "");
|
||||
const [, setColorIndex] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setColorIndex(prevIndex => {
|
||||
const newIndex = prevIndex >= colors.length - 1 ? 0 : prevIndex + 1;
|
||||
setColor(colors[newIndex]); // Use the new index here
|
||||
return newIndex;
|
||||
});
|
||||
}, 7500);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
// const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
||||
// Auto-cycle through measurements every 3 seconds
|
||||
// useEffect(() => {
|
||||
// const interval = setInterval(() => {
|
||||
// setCurrentIndex((prevIndex) => (prevIndex + 1) % 2);
|
||||
// }, 3000); // Adjust timing as needed (3000ms = 3s)
|
||||
|
||||
// return () => clearInterval(interval); // Cleanup on unmount
|
||||
// }, []);
|
||||
|
||||
const tooltip = () => {
|
||||
if (messages.length === 0) return null
|
||||
if (messages.length < 2) return (
|
||||
messages[0]
|
||||
)
|
||||
return (
|
||||
<Grid2 container direction={"column"}>
|
||||
<Grid2 container direction="row">
|
||||
<Typography fontWeight={"bold"} variant="caption">
|
||||
Overlay Messages
|
||||
</Typography>
|
||||
</Grid2>
|
||||
{messages.map((message, index) => {
|
||||
return (
|
||||
<Grid2 key={"tooltip-overly-message-" + message} container direction="row" alignItems={"center"}>
|
||||
<Box
|
||||
sx={{
|
||||
width: 10, // Size of the square
|
||||
height: 10,
|
||||
backgroundColor: colors[index], // Passed color prop
|
||||
borderRadius: 1, // Optional: slight rounding, remove for sharp square
|
||||
border: "1px solid black",
|
||||
}}
|
||||
/>
|
||||
<Typography variant="caption" sx={{ marginLeft: 1 }}>
|
||||
{message}
|
||||
</Typography>
|
||||
</Grid2>
|
||||
)
|
||||
})}
|
||||
</Grid2>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip title={tooltip()}>
|
||||
<PulseBox color={color} className={classes.box} >
|
||||
<Grid2 container direction="column" >
|
||||
<Grid2 container direction="column"
|
||||
className={`${classes.carouselItem} ${classes.active }`}
|
||||
>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: green[300]}}>
|
||||
{"<1um:"} {device.status.sen5x?.dust1ug.toFixed(1)}ug/m3
|
||||
</Typography>
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: green[400]}}>
|
||||
{"<2.5um:"} {device.status.sen5x?.dust2ug.toFixed(1)}ug/m3
|
||||
</Typography>
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: green[500]}}>
|
||||
{"<4um: "}{device.status.sen5x?.dust4ug.toFixed(1)}ug/m3
|
||||
</Typography>
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: green[600]}}>
|
||||
{"<10um: "}{device.status.sen5x?.dust10ug.toFixed(1)}ug/m3
|
||||
</Typography>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</PulseBox>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
198
src/common/StatusGas.tsx
Normal file
198
src/common/StatusGas.tsx
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
import { Box, Grid2, Theme, Tooltip, Typography } from "@mui/material";
|
||||
import { blue, deepOrange, teal } from "@mui/material/colors";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { Device } from "models";
|
||||
import PulseBox from "./PulseBox";
|
||||
import { or } from "utils";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface Props {
|
||||
device: Device
|
||||
// noDust?: boolean;
|
||||
gasType: "co2" | "co" | "no2" | "o2" | "all"
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
const lightMode = theme.palette?.mode === "light";
|
||||
return ({
|
||||
box: {
|
||||
display: "inline-block",
|
||||
borderRadius: "6px",
|
||||
backgroundColor: lightMode ? "rgb(210, 210, 210)" : "rgb(50, 50, 50)",
|
||||
padding: theme.spacing(0.75),
|
||||
marginRight: "auto",
|
||||
margin: theme.spacing(1),
|
||||
width: theme.spacing(14),
|
||||
height: theme.spacing(6),
|
||||
},
|
||||
boxTall: {
|
||||
display: "inline-block",
|
||||
borderRadius: "6px",
|
||||
backgroundColor: lightMode ? "rgb(210, 210, 210)" : "rgb(50, 50, 50)",
|
||||
padding: theme.spacing(0.75),
|
||||
marginRight: "auto",
|
||||
margin: theme.spacing(1),
|
||||
width: theme.spacing(14),
|
||||
height: theme.spacing(8.5),
|
||||
},
|
||||
carouselContainer: {
|
||||
position: 'relative',
|
||||
height: '40px',
|
||||
overflow: 'hidden',
|
||||
textAlign: "center",
|
||||
},
|
||||
carouselItem: {
|
||||
opacity: 0,
|
||||
transform: 'translateX(100%)',
|
||||
transition: 'opacity 0.5s ease, transform 0.5s ease',
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
overflow: "hidden",
|
||||
// height: '100%',
|
||||
},
|
||||
active: {
|
||||
opacity: 1,
|
||||
transform: 'translateX(0)',
|
||||
},
|
||||
inactive: {
|
||||
transform: 'translateX(-100%)',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
export default function StatusGas(props: Props) {
|
||||
const { device, gasType } = props;
|
||||
const classes = useStyles()
|
||||
// console.log(noDust)
|
||||
let colors: string[] = []
|
||||
let messages: string[] = []
|
||||
if (gasType === "all") {
|
||||
colors = or(device.status.o2?.overlays.map(overlay => overlay.color), []);
|
||||
colors.push(...or(device.status.co2?.overlays.map(overlay => overlay.color), []));
|
||||
colors.push(...or(device.status.no2?.overlays.map(overlay => overlay.color), []));
|
||||
colors.push(...or(device.status.co?.overlays.map(overlay => overlay.color), []));
|
||||
messages = or(device.status.o2?.overlays.map(overlay => overlay.message), []);
|
||||
messages.push(...or(device.status.co2?.overlays.map(overlay => overlay.message), []));
|
||||
messages.push(...or(device.status.no2?.overlays.map(overlay => overlay.message), []));
|
||||
messages.push(...or(device.status.co?.overlays.map(overlay => overlay.message), []));
|
||||
} else {
|
||||
colors = or(device.status[gasType]?.overlays.map(overlay => overlay.color), []);
|
||||
messages = or(device.status[gasType]?.overlays.map(overlay => overlay.message), []);
|
||||
}
|
||||
|
||||
const [color, setColor] = useState(colors.length > 0 ? colors[0] : "");
|
||||
const [, setColorIndex] = useState(0)
|
||||
|
||||
const gasTypes: ("o2" | "no2" | "co2" | "co")[] = ["o2", "no2", "co2", "co"]
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setColorIndex(prevIndex => {
|
||||
const newIndex = prevIndex >= colors.length - 1 ? 0 : prevIndex + 1;
|
||||
setColor(colors[newIndex]); // Use the new index here
|
||||
return newIndex;
|
||||
});
|
||||
}, 7500);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
||||
// Auto-cycle through measurements every 5 seconds
|
||||
useEffect(() => {
|
||||
if (gasType !== "all") {
|
||||
setCurrentIndex(0)
|
||||
return
|
||||
}
|
||||
const interval = setInterval(() => {
|
||||
if (gasType === "all") setCurrentIndex((prevIndex) => (prevIndex + 1) % 4);
|
||||
else setCurrentIndex((prevIndex) => (prevIndex + 1) % 4);
|
||||
}, 6000);
|
||||
|
||||
return () => clearInterval(interval); // Cleanup on unmount
|
||||
}, [gasType]);
|
||||
|
||||
const tooltip = () => {
|
||||
if (messages.length === 0) return null
|
||||
if (messages.length < 2) return (
|
||||
messages[0]
|
||||
)
|
||||
return (
|
||||
<Grid2 container direction={"column"}>
|
||||
<Grid2 container direction="row">
|
||||
<Typography fontWeight={"bold"} variant="caption">
|
||||
Overlay Messages
|
||||
</Typography>
|
||||
</Grid2>
|
||||
{messages.map((message, index) => {
|
||||
return (
|
||||
<Grid2 key={"tooltip-overly-message-" + message} container direction="row" alignContent={"center"}>
|
||||
<Grid2 size={{xs: 1}} alignContent={"center"}>
|
||||
<Box
|
||||
sx={{
|
||||
width: 12, // Size of the square
|
||||
height: 12,
|
||||
backgroundColor: colors[index], // Passed color prop
|
||||
borderRadius: 3, // Optional: slight rounding, remove for sharp square
|
||||
border: "1px solid black",
|
||||
marginBottom: 0.4
|
||||
}}
|
||||
/>
|
||||
</Grid2>
|
||||
<Grid2 size={{ xs: 11 }} alignContent={"center"}>
|
||||
<Typography variant="caption">
|
||||
{message}
|
||||
</Typography>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
)
|
||||
})}
|
||||
</Grid2>
|
||||
)
|
||||
}
|
||||
|
||||
const gasDisplay = () => {
|
||||
const gas = gasType === "all" ? gasTypes[currentIndex] : gasType
|
||||
// if (gasType !== "all") {
|
||||
return (
|
||||
<Tooltip title={tooltip()}>
|
||||
<PulseBox color={color} className={gasType === "all" ? classes.boxTall : classes.box}>
|
||||
<Grid2 container direction="column" >
|
||||
{ gasType === "all" &&
|
||||
<Typography variant="body2">
|
||||
{gas.toUpperCase()}
|
||||
</Typography>
|
||||
}
|
||||
<Grid2 container direction="column">
|
||||
<Grid2>
|
||||
{gas !== "o2" ?
|
||||
<Typography variant="body2" style={{ color: teal[500]}}>
|
||||
Gas: {device.status[gas]?.ppm.toFixed(1)}ppm
|
||||
</Typography>
|
||||
:
|
||||
<Typography variant="body2" style={{ color: blue[500]}}>
|
||||
Gas: {(device.status[gas]?.ppm!/10000).toFixed(1)}%
|
||||
</Typography>
|
||||
}
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: deepOrange[800]}}>
|
||||
Volt: {device.status[gas]?.millivolts.toFixed(1)}mV
|
||||
</Typography>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</PulseBox>
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{gasDisplay()}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
@ -5,8 +5,10 @@ import { Device } from "models";
|
|||
import PulseBox from "./PulseBox";
|
||||
import { or } from "utils";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface Props {
|
||||
device: Device
|
||||
noDust?: boolean;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
|
|
@ -19,8 +21,8 @@ const useStyles = makeStyles((theme: Theme) => {
|
|||
padding: theme.spacing(0.75),
|
||||
marginRight: "auto",
|
||||
margin: theme.spacing(1),
|
||||
width: "72px",
|
||||
height: "50px",
|
||||
width: theme.spacing(16),
|
||||
height: theme.spacing(11),
|
||||
},
|
||||
carouselContainer: {
|
||||
position: 'relative',
|
||||
|
|
@ -47,10 +49,10 @@ const useStyles = makeStyles((theme: Theme) => {
|
|||
})
|
||||
})
|
||||
|
||||
export default function StatusPlenum(props: Props) {
|
||||
const { device } = props;
|
||||
export default function StatusSen5x(props: Props) {
|
||||
const { device, noDust } = props;
|
||||
const classes = useStyles()
|
||||
|
||||
// console.log(noDust)
|
||||
const colors = or(device.status.sen5x?.overlays.map(overlay => overlay.color), []);
|
||||
const messages = or(device.status.sen5x?.overlays.map(overlay => overlay.message), []);
|
||||
|
||||
|
|
@ -71,14 +73,18 @@ export default function StatusPlenum(props: Props) {
|
|||
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
||||
// Auto-cycle through measurements every 3 seconds
|
||||
// Auto-cycle through measurements every 5 seconds
|
||||
useEffect(() => {
|
||||
if (noDust) {
|
||||
setCurrentIndex(0)
|
||||
return
|
||||
}
|
||||
const interval = setInterval(() => {
|
||||
setCurrentIndex((prevIndex) => (prevIndex + 1) % 4);
|
||||
}, 3000); // Adjust timing as needed (3000ms = 3s)
|
||||
if (!noDust) setCurrentIndex((prevIndex) => (prevIndex + 1) % 2);
|
||||
}, 5000);
|
||||
|
||||
return () => clearInterval(interval); // Cleanup on unmount
|
||||
}, []);
|
||||
}, [noDust]);
|
||||
|
||||
const tooltip = () => {
|
||||
if (messages.length === 0) return null
|
||||
|
|
@ -125,66 +131,52 @@ export default function StatusPlenum(props: Props) {
|
|||
>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: orange[700]}}>
|
||||
{device.status.sen5x?.temperature.toFixed(1)}°C
|
||||
Temp: {device.status.sen5x?.temperature.toFixed(1)}°C
|
||||
</Typography>
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: blue[700]}}>
|
||||
{device.status.sen5x?.humidity.toFixed(1)}%
|
||||
Humidity: {device.status.sen5x?.humidity.toFixed(1)}%
|
||||
</Typography>
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: blue[300]}}>
|
||||
Voc: {device.status.sen5x?.voc.toFixed(1)}%
|
||||
</Typography>
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: blue[400]}}>
|
||||
Nox: {device.status.sen5x?.nox.toFixed(1)}%
|
||||
</Typography>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
|
||||
<Grid2 container direction="column"
|
||||
{!noDust && <Grid2 container direction="column"
|
||||
className={`${classes.carouselItem} ${
|
||||
1 === currentIndex ? classes.active : classes.inactive
|
||||
}`}
|
||||
>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: green[300]}}>
|
||||
{device.status.sen5x?.dust1ug.toFixed(1)}ug/m3
|
||||
{"<1um:"} {device.status.sen5x?.dust1ug.toFixed(1)}ug/m3
|
||||
</Typography>
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: green[400]}}>
|
||||
{device.status.sen5x?.dust2ug.toFixed(1)}ug/m3
|
||||
{"<2.5um:"} {device.status.sen5x?.dust2ug.toFixed(1)}ug/m3
|
||||
</Typography>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
|
||||
<Grid2 container direction="column"
|
||||
className={`${classes.carouselItem} ${
|
||||
2 === currentIndex ? classes.active : classes.inactive
|
||||
}`}
|
||||
>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: green[500]}}>
|
||||
{device.status.sen5x?.dust4ug.toFixed(1)}ug/m3
|
||||
{"<4um: "}{device.status.sen5x?.dust4ug.toFixed(1)}ug/m3
|
||||
</Typography>
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: green[600]}}>
|
||||
{device.status.sen5x?.dust10ug.toFixed(1)}ug/m3
|
||||
{"<10um: "}{device.status.sen5x?.dust10ug.toFixed(1)}ug/m3
|
||||
</Typography>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
|
||||
<Grid2 container direction="column"
|
||||
className={`${classes.carouselItem} ${
|
||||
3 === currentIndex ? classes.active : classes.inactive
|
||||
}`}
|
||||
>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: blue[300]}}>
|
||||
V: {device.status.sen5x?.voc.toFixed(1)}%
|
||||
</Typography>
|
||||
</Grid2>
|
||||
<Grid2>
|
||||
<Typography variant="body2" style={{ color: blue[400]}}>
|
||||
N: {device.status.sen5x?.nox.toFixed(1)}%
|
||||
</Typography>
|
||||
</Grid2>
|
||||
</Grid2>
|
||||
</Grid2>}
|
||||
</Grid2>
|
||||
</PulseBox>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import { isController, isSource } from "pbHelpers/ComponentType";
|
|||
import { DeviceAvailabilityMap, OffsetAvailabilityMap } from "pbHelpers/DeviceAvailability";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { useGlobalState } from "providers";
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { or } from "utils/types";
|
||||
import ComponentSettings from "./ComponentSettings";
|
||||
import { green, teal } from "@mui/material/colors";
|
||||
|
|
@ -94,6 +94,7 @@ export default function ComponentActions(props: Props) {
|
|||
};
|
||||
|
||||
const openComponentSettingsDialog = (mode: string) => {
|
||||
console.log("delete")
|
||||
setIsComponentSettingsOpen(true);
|
||||
setComponentSettingsMode(or(mode, ""));
|
||||
};
|
||||
|
|
@ -140,7 +141,7 @@ export default function ComponentActions(props: Props) {
|
|||
{canEdit && (
|
||||
<MenuItem dense onClick={() => {
|
||||
openComponentSettingsDialog("remove")
|
||||
closeMoreMenu()
|
||||
setAnchorEl(null);
|
||||
}}>
|
||||
<ListItemIcon>
|
||||
<DeleteOutline className={classes.red} />
|
||||
|
|
|
|||
|
|
@ -254,15 +254,15 @@ export default function ComponentCard(props: Props) {
|
|||
size="small"
|
||||
onTouchStart={event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
//event.preventDefault();
|
||||
}}
|
||||
onMouseDown={event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
//event.preventDefault();
|
||||
}}
|
||||
onClick={event => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
//event.preventDefault();
|
||||
}}
|
||||
disabled={!canEdit}
|
||||
onChange={(_, checked) => updateControllerState(checked)}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import {
|
|||
Check,
|
||||
PermScanWifi,
|
||||
} from "@mui/icons-material";
|
||||
import { Card, Grid2, Skeleton, Theme, Typography, useTheme } from "@mui/material";
|
||||
import { Card, Grid2, Theme, Typography } from "@mui/material";
|
||||
import { green } from "@mui/material/colors";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import classNames from "classnames";
|
||||
|
|
@ -41,7 +41,7 @@ interface Props {
|
|||
export default function DevicesSummary(props: Props) {
|
||||
const { setFieldContains, group } = props;
|
||||
const deviceAPI = useDeviceAPI()
|
||||
const theme = useTheme()
|
||||
// const theme = useTheme()
|
||||
const classes = useStyles()
|
||||
|
||||
const [stats, setStats] = useState<pond.DeviceStatistics>(pond.DeviceStatistics.create())
|
||||
|
|
@ -205,7 +205,7 @@ export default function DevicesSummary(props: Props) {
|
|||
<Grid2>
|
||||
<CircleGraphIcon
|
||||
sx={{ marginRight: 1, marginLeft: 1 }}
|
||||
progress={!loadingStats ? getPercent(stats.warning) : undefined}
|
||||
progress={!loadingStats ? getPercent(stats.offline) : undefined}
|
||||
color={green[50]}
|
||||
icon={<PermScanWifi />}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -5204,6 +5204,933 @@ export default function DeviceSVG(props: Props) {
|
|||
);
|
||||
};
|
||||
|
||||
const streamlineMonitorSVG = () => {
|
||||
return (
|
||||
<svg id="streamlineMonitor" version="1.1" viewBox="0 0 224.2 224.2">
|
||||
<g>
|
||||
<rect
|
||||
className={classes.boxBorder}
|
||||
x="4.5"
|
||||
y=".5"
|
||||
width="214.5"
|
||||
height="222.6"
|
||||
rx="10.7"
|
||||
ry="10.7"
|
||||
/>
|
||||
<path
|
||||
className={classes.grayLine}
|
||||
d="M216,122.9l-21.6-13.4c-2.5-1.6-5.7-1.6-8.3,0l-21.6,13.4c-2.3,1.4-3.7,3.9-3.7,6.7v6l-4.5-2.8c-2.3-1.4-5.1-1.4-7.3,0l-18.9,11.7c-2.1,1.3-3.3,3.5-3.3,5.9v6l-4.8-3c-2.1-1.3-4.6-1.3-6.7,0l-17,10.5c-1.9,1.2-3,3.2-3,5.4v54.3h5.1v-2.5c0-1.3,1-2.3,2.3-2.3h11.1c1.3,0,2.3,1,2.3,2.3v2.5h5.1v-2.5c0-1.3,1-2.3,2.3-2.3h3.3v4.8h5.5v-4.8h2.3c1.3,0,2.3,1,2.3,2.3v2.5h5.1v-18.3h5.3c1.5,0,2.6,1.2,2.6,2.6v15.6h5.5v-15.6c0-1.5,1.2-2.6,2.6-2.6h2.8v18.3h6.1v-18.3h3.5c1.5,0,2.6,1.2,2.6,2.6v15.6h5.5v-31.4h5.6c1.7,0,3.1,1.4,3.1,3.1v28.3h6.1v-28.3c0-1.7,1.4-3.1,3.1-3.1h14.1c1.7,0,3.1,1.4,3.1,3.1v26.9l2.2-1.5.4-.3c.2-.2.4-.4.6-.7v-.2c.6-.7,1.1-1.5,1.5-2.2.4-.8.8-1.5,1.3-2.1v-.2c.1,0,.1-85.4.1-85.4,0-2.7-1.4-5.2-3.7-6.7ZM123.3,217.4c-2.1,0-3.8,1.7-3.8,3.8v1.1h-2.2v-1.1c0-2.1-1.7-3.8-3.8-3.8h-11.1c-2.1,0-3.8,1.7-3.8,3.8v1.1h-2.2v-52.8c0-1.7.9-3.2,2.3-4.1l17-10.5c1.6-1,3.5-1,5.1,0l5.6,3.5v59.2h-3.3ZM140.4,222.2h-2.2v-1.1c0-2.1-1.7-3.8-3.8-3.8h-2.3v-9.3c0-1.5,1.2-2.6,2.6-2.6h5.6v16.8ZM158,203.9c-2.3,0-4.1,1.8-4.1,4.1v14.1h-2.6v-14.1c0-2.3-1.8-4.1-4.1-4.1h-12.3c-2.3,0-4.1,1.8-4.1,4.1v14.1h-2.6v-71.7c0-1.9,1-3.7,2.6-4.7l18.9-11.7c1.8-1.1,4-1.1,5.8,0l5.3,3.3v66.6h-2.8ZM177,222.2h-2.6v-14.1c0-2.3-1.8-4.1-4.1-4.1h-3.5v-8.6c0-1.7,1.4-3.1,3.1-3.1h7v30ZM218.2,214.6c-.5.7-.9,1.4-1.3,2.1-.4.7-.8,1.4-1.3,2.1h-.1c-.1.3-.3.5-.5.6h0c0,0,0-24,0-24,0-2.5-2.1-4.6-4.6-4.6h-14.1c-2.5,0-4.6,2.1-4.6,4.6v26.8h-3.1v-26.8c0-2.5-2.1-4.6-4.6-4.6h-14.1c-2.5,0-4.6,2.1-4.6,4.6v26.8h-3.1v-92.6c0-2.2,1.1-4.3,3-5.4l21.6-13.4c2.1-1.3,4.6-1.3,6.7,0l21.6,13.4c1.9,1.2,3,3.2,3,5.4v85Z"
|
||||
/>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M63.3,202.8l-.8.8c.7.7,1,1.5,1,2.5s-.4,1.8-1,2.5c-1.4,1.4-3.6,1.4-4.9,0-1.4-1.4-1.4-3.6,0-4.9l-.8-.8c-1.8,1.8-1.8,4.8,0,6.6.9.9,2.1,1.4,3.3,1.4s2.4-.5,3.3-1.4c.9-.9,1.4-2,1.4-3.3s-.5-2.4-1.4-3.3Z"
|
||||
/>
|
||||
<rect className={classes.whiteLine} x="59.4" y="201.2" width="1.2" height="5.5" />
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M17.8,77.5l3.1-.6v6.5h-1.5v-4.9l-1.6.4v-1.3Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M20.2,116.3c.2-.2.3-.4.4-.5.1-.2.2-.3.3-.5,0-.1,0-.3,0-.5s0-.2,0-.3c0,0,0-.2-.2-.3s-.2-.1-.3-.2c-.1,0-.2,0-.4,0s-.4,0-.5.1c-.1,0-.3.2-.3.4,0,.2-.1.4-.1.6h-1.5c0-.5,0-.9.3-1.2.2-.4.5-.7.9-.9.4-.2.8-.3,1.4-.3s.7,0,1,.2c.3.1.6.3.8.5.2.2.4.4.5.7s.2.5.2.7c0,.3,0,.7-.3,1s-.4.6-.7.8l-1.5,1.3h2.6v1.4h-5.4l2.8-2.9Z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M20.7,38.1c-3.5,0-6.3,2.8-6.3,6.3s2.8,6.3,6.3,6.3,6.3-2.8,6.3-6.3-2.8-6.3-6.3-6.3ZM20.7,48.3c-2.2,0-4-1.8-4-4s1.8-4,4-4,4,1.8,4,4-1.8,4-4,4Z"
|
||||
/>
|
||||
<circle className={classes.whiteLine} cx="20.7" cy="44.3" r="2.3" />
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M188,153.2c0-2.8-1.1-5.3-3-7.3-.8-.8-2-.8-2.8,0-.8.8-.8,2,0,2.8,1.2,1.2,1.9,2.8,1.9,4.5s-.7,3.3-1.9,4.5c-.4.4-.6.9-.6,1.4s.2,1,.6,1.4c.8.8,2,.8,2.8,0,1.9-1.9,3-4.5,3-7.3ZM194.4,153.2c0-4.5-1.7-8.7-4.9-11.8-.8-.8-2-.8-2.8,0-.8.8-.8,2,0,2.8,2.4,2.4,3.8,5.6,3.8,9.1s-1.3,6.6-3.8,9.1c-.4.4-.6.9-.6,1.4s.2,1,.6,1.4c.8.8,2,.8,2.8,0,3.2-3.2,4.9-7.4,4.9-11.8ZM194.1,169.6c4.4-4.4,6.8-10.2,6.8-16.4s-2.4-12-6.8-16.4c-.8-.8-2-.8-2.8,0-.4.4-.6.9-.6,1.4s.2,1,.6,1.4c3.6,3.6,5.6,8.5,5.6,13.6s-2,10-5.6,13.6c-.8.8-.8,2,0,2.8.8.8,2,.8,2.8,0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M179.5,148.8c-.6-.6-1.8-.6-2.4,0-.7.7-.7,1.7,0,2.4.5.5.8,1.2.8,2s-.3,1.5-.8,2c-.3.3-.5.8-.5,1.2s.2.9.5,1.2c.3.3.8.5,1.2.5s.9-.2,1.2-.5c1.2-1.2,1.8-2.7,1.8-4.4s-.6-3.2-1.8-4.4Z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M128.5,103.6v.9c0,.4.3.8.7.8v.9h.2v-.9c.4,0,.7-.4.7-.8v-.9l-.8.7-.8-.7ZM129.9,104.6c0,.3-.2.6-.5.6v-.3h-.2v.3c-.3,0-.5-.3-.5-.6v-.5l.6.5.6-.5v.5Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M128.5,102.2v.9c0,.5.4.8.8.8s.8-.4.8-.8v-.9l-.8.7-.8-.7ZM129.9,103.1c0,.3-.2.6-.5.6v-.3h-.2v.3c-.3,0-.5-.3-.5-.6v-.5l.6.5.6-.5v.5Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M128.5,100.7v.9c0,.5.4.8.8.8s.8-.4.8-.8v-.9l-.8.7-.8-.7ZM129.9,101.7c0,.3-.2.6-.5.6v-.3h-.2v.3c-.3,0-.5-.3-.5-.6v-.5l.6.5.6-.5v.5Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M129.3,101.1h0s0,0,0,0c0,0,.4,0,.5-.3.1-.3,0-.6-.4-1.1h0c0,0,0,0,0,0-.4.5-.5.8-.4,1.1.1.3.5.3.5.3ZM129.3,99.9c.3.4.4.7.3.8,0,.1-.1.2-.2.2v-.3h-.2v.3c0,0-.2,0-.2-.2,0-.1,0-.4.3-.8Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M144,103.4h-2.5v1c-.2.1-.5.2-.8.2-.9,0-1.7-.8-1.7-1.7s.8-1.7,1.7-1.7,1.7.7,1.7,1.6h1.6c0-1.8-1.5-3.3-3.3-3.3s-2.8,1-3.2,2.5c-.4-1.4-1.7-2.5-3.2-2.5s-3.3,1.5-3.3,3.3,1.5,3.3,3.3,3.3,1.2-.2,1.7-.5v.5h1.6v-2.1c.5,1.2,1.7,2.1,3.1,2.1s1.2-.2,1.7-.5v.5h1.6v-2.9h0ZM134.2,104.6c-.9,0-1.7-.8-1.7-1.7s.8-1.7,1.7-1.7,1.7.8,1.7,1.7-.8,1.7-1.7,1.7Z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M146.9,102.6l-.3-.6h-.9l-.3.6h-.4l1.2-2.5,1.1,2.5h-.4ZM145.9,101.7h.7l-.2-.5s0,0,0-.1c0,0,0,0,0-.2,0,0,0,.1,0,.1,0,0,0,0,0,.1l-.2.5Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M148.1,102.6v-2.4h.5c.3,0,.6,0,.7,0,.1,0,.3,0,.4.2.1.1.2.2.3.4,0,.2.1.4.1.6s0,.4-.1.6c0,.2-.2.3-.3.4-.1,0-.2.1-.4.2-.1,0-.3,0-.6,0h-.6ZM148.5,102.3h.3c.2,0,.3,0,.4,0,0,0,.2,0,.2-.1,0,0,.2-.2.2-.3,0-.1,0-.2,0-.4s0-.3,0-.4c0-.1-.1-.2-.2-.3,0,0-.1,0-.2-.1,0,0-.2,0-.4,0h-.3v1.7Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M152.6,102.6l-.3-.6h-.9l-.3.6h-.4l1.2-2.5,1.1,2.5h-.4ZM151.5,101.7h.7l-.2-.5s0,0,0-.1c0,0,0,0,0-.2,0,0,0,.1,0,.1,0,0,0,0,0,.1l-.2.5Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M154.1,101.6v1.1h-.4v-2.4h.6c.2,0,.3,0,.4,0,0,0,.2,0,.2,0,0,0,.1.1.2.2,0,0,0,.2,0,.3s0,.2,0,.3c0,0-.1.2-.2.2,0,0-.1,0-.2,0,0,0-.2,0-.4,0h-.2ZM154.1,101.3h0c.2,0,.4,0,.4,0s.1-.1.1-.2,0-.2-.1-.3c0,0-.2,0-.4,0h0v.7Z"
|
||||
/>
|
||||
<path className={classes.whiteLine} d="M156.8,100.6v2h-.4v-2h-.6v-.3h1.6v.3h-.6Z" />
|
||||
<path className={classes.whiteLine} d="M158.3,102.6v-2.4h.4v2.4h-.4Z" />
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M160.5,102.7l-1.1-2.5h.4l.5,1.3c0,0,0,.1,0,.2,0,0,0,.1,0,.2,0,0,0-.1,0-.2,0,0,0-.1,0-.2l.5-1.3h.4l-1.1,2.5Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M162.3,102.6v-2.4h1.3v.3h-.9v.6h.9v.3h-.9v.8h.9v.3h-1.3Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M146.9,106.2l-.3-.6h-.9l-.3.6h-.4l1.2-2.5,1.1,2.5h-.4ZM145.9,105.2h.7l-.2-.5s0,0,0-.1c0,0,0,0,0-.2,0,0,0,.1,0,.1,0,0,0,0,0,.1l-.2.5Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M149.3,105h.9s0,0,0,0c0,0,0,.1,0,.2,0,.3,0,.6-.3.8s-.5.3-.8.3-.4,0-.5,0c-.2,0-.3-.1-.4-.3-.1-.1-.2-.2-.3-.4,0-.2,0-.3,0-.5s0-.3,0-.5c0-.2.2-.3.3-.4.1-.1.3-.2.4-.3.2,0,.3,0,.5,0s.4,0,.5.1c.1,0,.3.2.4.3l-.3.2c0,0-.2-.2-.3-.2-.1,0-.2,0-.3,0-.3,0-.5,0-.6.2-.2.2-.2.4-.2.6s0,.5.2.7c.2.2.4.3.6.3s.4,0,.5-.2c.1-.1.2-.2.2-.4h0s-.6,0-.6,0v-.3Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M151.6,105.1v1.1h-.4v-2.4h.5c.2,0,.3,0,.4,0,0,0,.2,0,.2.1,0,0,.1.1.2.2,0,0,0,.2,0,.3,0,.2,0,.3-.1.4,0,.1-.2.2-.4.2l.8,1.1h-.4l-.8-1.1h0ZM151.6,104.8h0c.2,0,.3,0,.4,0,0,0,.1-.1.1-.3s0-.2-.1-.3c0,0-.2,0-.4,0h0v.7Z"
|
||||
/>
|
||||
<path className={classes.whiteLine} d="M153.6,106.2v-2.4h.4v2.4h-.4Z" />
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M157,104.4c-.1,0-.2-.2-.3-.2-.1,0-.2,0-.4,0-.3,0-.5,0-.6.2-.2.2-.2.4-.2.6s0,.5.2.6c.2.2.4.2.6.2s.3,0,.4,0c.1,0,.2-.1.4-.2v.4c-.1,0-.2.1-.3.2-.1,0-.3,0-.4,0s-.3,0-.5,0-.3-.1-.4-.3c-.1-.1-.2-.2-.3-.4,0-.2,0-.3,0-.5s0-.3,0-.5c0-.2.2-.3.3-.4.1-.1.3-.2.4-.3.2,0,.3,0,.5,0s.3,0,.4,0,.2.1.4.2v.4Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M158,103.8h.4v1.4c0,.2,0,.4.1.5,0,.1.2.2.4.2s.3,0,.4-.2c0-.1.1-.3.1-.5v-1.4h.4v1.5c0,.3,0,.6-.2.7-.2.2-.4.2-.7.2s-.6,0-.7-.2c-.2-.2-.2-.4-.2-.7v-1.5Z"
|
||||
/>
|
||||
<path className={classes.whiteLine} d="M161,106.2v-2.4h.4v2h.9v.3h-1.2Z" />
|
||||
<path className={classes.whiteLine} d="M163.7,104.1v2h-.4v-2h-.6v-.3h1.6v.3h-.6Z" />
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M165.1,103.8h.4v1.4c0,.2,0,.4.1.5,0,.1.2.2.4.2s.3,0,.4-.2c0-.1.1-.3.1-.5v-1.4h.4v1.5c0,.3,0,.6-.2.7s-.4.2-.7.2-.6,0-.7-.2c-.2-.2-.2-.4-.2-.7v-1.5Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M168.5,105.1v1.1h-.4v-2.4h.5c.2,0,.3,0,.4,0,0,0,.2,0,.2.1,0,0,.1.1.2.2,0,0,0,.2,0,.3,0,.2,0,.3-.1.4,0,.1-.2.2-.4.2l.8,1.1h-.4l-.8-1.1h0ZM168.5,104.8h0c.2,0,.3,0,.4,0,0,0,.1-.1.1-.3s0-.2-.1-.3c0,0-.2,0-.4,0h0v.7Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M170.5,106.2v-2.4h1.3v.3h-.9v.6h.9v.3h-.9v.8h.9v.3h-1.3Z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M100.4,99.1v3h-.6v-3h.6ZM99.9,100.3h2.2v.6h-2.2v-.6ZM102.4,99.1v3h-.6v-3h.6Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M103.4,101.7s0,0,.1,0c0,0,.1,0,.2,0s.2,0,.2,0c0,0,.1,0,.2-.2,0,0,0-.2,0-.2v.3c0,.1,0,.2,0,.3s-.2.2-.3.2c-.1,0-.2,0-.3,0s-.2,0-.3,0c-.1,0-.2-.1-.3-.2,0,0,0-.2,0-.3,0-.2,0-.3.2-.5.1-.1.3-.2.6-.2s.2,0,.3,0c0,0,.2,0,.2,0,0,0,.1,0,.1.1v.3c0,0-.2-.1-.3-.1,0,0-.2,0-.3,0s-.2,0-.2,0c0,0,0,0-.1,0,0,0,0,0,0,.1s0,.1,0,.1ZM103,100.4c.1,0,.2-.1.4-.2s.3,0,.5,0,.3,0,.5,0c.1,0,.2.1.3.2,0,0,.1.2.1.3v1.4h-.5v-1.3c0,0,0-.1,0-.1,0,0,0,0,0,0,0,0,0,0-.1,0,0,0-.1,0-.2,0,0,0-.2,0-.3,0,0,0-.2,0-.2,0,0,0-.1,0-.1,0l-.2-.4Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M105.8,102.2h-.6v-2h.6v2ZM106.3,100.7s0,0-.1,0-.1,0-.2,0c0,0,0,0-.1.2,0,0,0,.2,0,.2l-.2-.2c0-.2,0-.3,0-.4,0-.1.1-.2.2-.3,0,0,.2-.1.3-.1s.1,0,.2,0c0,0,.1,0,.2.1l-.3.5s0,0-.1,0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M107,100.6c0-.2.2-.3.4-.4.1,0,.3-.1.5-.1s.3,0,.4.1c.1,0,.2.2.3.4s.1.3.1.6,0,.4-.1.6-.2.3-.3.4c-.1,0-.3.1-.4.1s-.3,0-.5-.1c-.1,0-.3-.2-.4-.4,0-.2-.1-.3-.1-.6s0-.4.1-.6ZM107.5,101.5c0,0,.1.2.2.2,0,0,.2,0,.3,0s.2,0,.2,0c0,0,.1-.1.2-.2,0,0,0-.2,0-.3s0-.2,0-.3c0,0-.1-.2-.2-.2,0,0-.2,0-.2,0s-.2,0-.3,0c0,0-.2.1-.2.2,0,0,0,.2,0,.3s0,.2,0,.3ZM109,98.8v3.4h-.6v-3.4h.6Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M109.9,100.2l.4,1.1.6-1.3.6,1.3.4-1.1h.6l-1,2.1-.6-1.3-.6,1.3-1-2.1h.6Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M113.2,101.7s0,0,.1,0c0,0,.1,0,.2,0s.2,0,.2,0c0,0,.1,0,.2-.2,0,0,0-.2,0-.2v.3c0,.1,0,.2,0,.3s-.2.2-.3.2c-.1,0-.2,0-.3,0s-.2,0-.3,0c-.1,0-.2-.1-.3-.2,0,0,0-.2,0-.3,0-.2,0-.3.2-.5.1-.1.3-.2.6-.2s.2,0,.3,0c0,0,.2,0,.2,0,0,0,.1,0,.1.1v.3c0,0-.2-.1-.3-.1,0,0-.2,0-.3,0s-.2,0-.2,0c0,0,0,0-.1,0,0,0,0,0,0,.1s0,.1,0,.1ZM112.7,100.4c.1,0,.2-.1.4-.2s.3,0,.5,0,.3,0,.5,0c.1,0,.2.1.3.2,0,0,.1.2.1.3v1.4h-.5v-1.3c0,0,0-.1,0-.1,0,0,0,0,0,0,0,0,0,0-.1,0,0,0-.1,0-.2,0,0,0-.2,0-.3,0,0,0-.2,0-.2,0,0,0-.1,0-.1,0l-.2-.4Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M115.6,102.2h-.6v-2h.6v2ZM116,100.7s0,0-.1,0-.1,0-.2,0c0,0,0,0-.1.2,0,0,0,.2,0,.2l-.2-.2c0-.2,0-.3,0-.4,0-.1.1-.2.2-.3,0,0,.2-.1.3-.1s.1,0,.2,0c0,0,.1,0,.2.1l-.3.5s0,0-.1,0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M117,102.1c-.2,0-.3-.2-.4-.4,0-.2-.1-.3-.1-.5s0-.4.1-.6c0-.2.2-.3.4-.4.2,0,.4-.1.6-.1s.4,0,.6.1.3.2.4.3.1.3.1.5,0,0,0,0c0,0,0,0,0,0h-1.8v-.3h1.3l-.2.2s0,0,0,0c0,0,0,0,0,0,0,0,0-.2,0-.3,0,0,0-.1-.2-.2,0,0-.1,0-.2,0s-.2,0-.3,0c0,0-.1.1-.2.2,0,0,0,.2,0,.3,0,.1,0,.2,0,.3,0,0,0,.2.2.2,0,0,.2,0,.3,0s.2,0,.3,0,.2-.1.2-.2l.5.2c-.1.2-.2.3-.4.4-.2,0-.4.1-.6.1s-.4,0-.6-.1Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M120.9,102.2h-.6v-3.4h.6v3.4ZM122.4,101.7c0,.2-.2.3-.4.4s-.3.1-.5.1-.3,0-.4-.1c-.1,0-.2-.2-.3-.4s-.1-.3-.1-.6,0-.4.1-.6.2-.3.3-.4c.1,0,.3-.1.4-.1s.3,0,.5.1.3.2.4.4c0,.2.1.3.1.6s0,.4-.1.6ZM121.9,100.9c0,0-.1-.2-.2-.2s-.2,0-.3,0-.2,0-.2,0c0,0-.1.1-.2.2s0,.2,0,.3,0,.2,0,.3.1.2.2.2c0,0,.2,0,.2,0s.2,0,.3,0,.1-.1.2-.2c0,0,0-.2,0-.3s0-.2,0-.3Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M123.5,103.1h-.6l.5-1.2-.8-1.8h.6l.6,1.6h-.3s.6-1.6.6-1.6h.6l-1.3,3Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M125.2,100c0,0,.2-.1.3-.1s.2,0,.3.1c0,0,.1.2.1.2s0,.2-.1.2c0,0-.2.1-.3.1s-.2,0-.3-.1c0,0-.1-.2-.1-.2s0-.2.1-.2ZM125.2,101.7c0,0,.2-.1.3-.1s.2,0,.3.1c0,0,.1.2.1.3s0,.2-.1.2c0,0-.2.1-.3.1s-.2,0-.3-.1c0,0-.1-.2-.1-.2s0-.2.1-.3Z"
|
||||
/>
|
||||
</g>
|
||||
<rect className={classes.whiteLine} x="79.3" y="95.3" width="92.3" height=".8" />
|
||||
<polygon
|
||||
className={classes.whiteLine}
|
||||
points="90.1 92 90.1 93.8 92.6 95.7 90.1 97.7 90.1 99.4 94.7 95.7 90.1 92"
|
||||
/>
|
||||
<polygon
|
||||
className={classes.whiteLine}
|
||||
points="85.6 92 85.6 93.8 88.1 95.7 85.6 97.7 85.6 99.4 90.3 95.7 85.6 92"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M62.7,103.1c-.2,0-.5,0-.7,0-.2,0-.3-.1-.4-.3s0-.3,0-.5h0c.5-1,1.2-1.8,2.2-2.3,1-.5,2-.7,3.1-.6.2,0,.3.1.4.3s0,.3,0,.5c-.5,1-1.2,1.8-2.2,2.3-.7.4-1.6.6-2.4.6ZM62.1,102.6h0ZM62.2,102.5c.9,0,1.7,0,2.5-.5.8-.4,1.4-1,1.8-1.8-.9,0-1.7,0-2.5.5-.8.4-1.4,1-1.8,1.8Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M67.7,97.1s0,0-.1,0c-1.1,0-2.1-.4-3-1-.1-.1-.2-.3-.2-.4s0-.3.2-.4h0c.9-.6,1.9-.9,3-.9,1.1,0,2.1.4,3,1,.1.1.2.3.2.4,0,.2,0,.3-.2.4-.9.6-1.9.9-2.9.9ZM65.1,95.6c.7.5,1.6.8,2.5.8.9,0,1.7-.2,2.5-.7-.7-.5-1.6-.8-2.5-.8-.9,0-1.7.2-2.5.7Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M79.1,95.5c-1,0-1.9-.3-2.7-.8-.9-.6-1.6-1.4-2-2.4s0-.3,0-.5c0-.1.2-.2.4-.2h0c1.1,0,2.1.2,3,.8.9.6,1.6,1.4,2,2.4,0,.2,0,.3,0,.5,0,.1-.2.2-.4.2-.1,0-.2,0-.3,0ZM75.1,92.2c.4.8.9,1.5,1.7,2,.7.5,1.6.7,2.5.7-.4-.8-.9-1.5-1.7-2-.7-.5-1.6-.7-2.5-.7ZM74.9,92.2h0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M75,99.9c-.1,0-.2,0-.3,0-.2,0-.3-.1-.4-.2,0-.1-.1-.3,0-.5.4-1,1.1-1.8,2-2.4.9-.6,2-.9,3-.8.2,0,.3.1.4.2s.1.3,0,.5c-.4,1-1.1,1.8-2,2.4-.8.5-1.8.8-2.7.8ZM74.9,99.3c.9,0,1.7-.2,2.5-.7.7-.5,1.3-1.2,1.7-2-.9,0-1.7.2-2.5.7-.7.5-1.3,1.2-1.7,2Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M74.1,95.5c-1,0-1.9-.3-2.7-.8-.9-.6-1.6-1.4-2-2.4,0-.2,0-.3,0-.5,0-.1.2-.2.4-.2h0c1.1,0,2.1.2,3,.8.9.6,1.6,1.4,2,2.4,0,.2,0,.3,0,.5,0,.1-.2.2-.4.2-.1,0-.2,0-.3,0ZM70,92.2c.4.8.9,1.5,1.7,2,.7.5,1.6.7,2.5.7-.4-.8-.9-1.5-1.7-2s-1.6-.7-2.5-.7ZM69.8,92.2h0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M70,99.9c-.1,0-.2,0-.3,0-.2,0-.3-.1-.4-.2,0-.1-.1-.3,0-.5.4-1,1.1-1.8,2-2.4.9-.6,2-.9,3-.8.2,0,.3.1.4.2,0,.1.1.3,0,.5-.4,1-1.1,1.8-2,2.4-.8.5-1.8.8-2.7.8ZM69.9,99.3c.9,0,1.7-.2,2.5-.7.7-.5,1.3-1.2,1.7-2-.9,0-1.7.2-2.5.7-.7.5-1.3,1.2-1.7,2ZM74.2,96.6h0,0ZM74.1,96.5h0s0,0,0,0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M84.2,95.5c-1,0-1.9-.3-2.7-.8-.9-.6-1.6-1.4-2-2.4,0-.2,0-.3,0-.5,0-.1.2-.2.4-.2h0c1.1,0,2.1.2,3,.8.9.6,1.6,1.4,2,2.4,0,.2,0,.3,0,.5,0,.1-.2.2-.4.2-.1,0-.2,0-.3,0ZM80.2,92.2c.4.8.9,1.5,1.7,2,.7.5,1.6.7,2.5.7-.4-.8-.9-1.5-1.7-2s-1.6-.7-2.5-.7ZM80,92.2h0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M80.1,99.9c-.1,0-.2,0-.3,0-.2,0-.3-.1-.4-.2,0-.1-.1-.3,0-.5.4-1,1.1-1.8,2-2.4.9-.6,2-.9,3-.8.2,0,.3.1.4.2,0,.1.1.3,0,.5-.4,1-1.1,1.8-2,2.4-.8.5-1.8.8-2.7.8ZM80,99.3c.9,0,1.7-.2,2.5-.7.7-.5,1.3-1.2,1.7-2-.9,0-1.7.2-2.5.7-.7.5-1.3,1.2-1.7,2ZM84.4,96.6h0,0ZM84.2,96.5h0s0,0,0,0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M60.8,97.8c-.7,0-1.4-.1-2-.4-1-.4-1.8-1.1-2.4-2.1,0-.1,0-.3,0-.5s.2-.3.4-.3c1.1-.2,2.1-.1,3.1.3,1,.4,1.8,1.1,2.4,2.1,0,.1,0,.3,0,.5,0,.2-.2.3-.4.3-.4,0-.8.1-1.1.1ZM57.1,95.2c.5.7,1.2,1.3,2,1.7.8.3,1.7.4,2.6.3-.5-.7-1.2-1.3-2-1.7-.8-.3-1.7-.4-2.6-.3ZM56.9,95.2h0,0Z"
|
||||
/>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M64.8,86.5c0,2.1-1.7,3.3-4.2,3.3s-3.4-.6-4.3-1.2l1-2c.9.5,2.1,1,3.3,1s1.6-.2,1.6-.8c0-1.5-5.4-.5-5.5-4.1,0-2,1.6-3.3,4.2-3.3s2.5.4,3.5.9l-.9,2c-.9-.4-2-.7-2.7-.7s-1.4.4-1.4.8c0,1.6,5.6.3,5.6,4.1Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M76.7,81.8h-3v7.8h-2.6v-7.8h-3v-2.3h8.5v2.3Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M85.2,86.7h-2v2.9h-2.6v-10.1h5.4c2.4,0,3.8,1.5,3.8,3.5s-.7,2.6-1.9,3.3l2.5,3.3h-3.1l-2-2.9ZM83.1,84.4h2.2c1.3,0,1.7-.6,1.7-1.4s-.5-1.3-1.6-1.3h-2.3v2.7Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M96,83.4h5.1v2.2h-5.1v1.7h5.6v2.3h-8.2v-10.1h8.1v2.3h-5.6v1.6Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M111.5,88.1h-4.6l-.6,1.5h-2.8l4.5-10.1h2.5l4.5,10.1h-2.8l-.6-1.5ZM110.6,85.9l-1.2-2.9-.2-.7-.2.7-1.2,2.9h2.9Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M129.2,89.6h-2.6v-6l-.2.3-2.4,2.9h-.6l-2.4-2.9-.2-.3v6h-2.6v-10.1h1.9l3.4,3.8.3.4.3-.4,3.4-3.8h1.9v10.1Z"
|
||||
/>
|
||||
<path className={classes.whiteLine} d="M140.5,89.6h-7.4v-10.1h2.6v7.8h4.8v2.3Z" />
|
||||
<path className={classes.whiteLine} d="M146.3,89.6h-2.6v-10.1h2.6v10.1Z" />
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M160.5,89.6h-1.9l-4.9-5.9-.2-.4v6.3h-2.6v-10.1h2.3l4.6,5.5.2.4v-5.9h2.6v10.1Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M166.9,83.4h5.1v2.2h-5.1v1.7h5.6v2.3h-8.2v-10.1h8.1v2.3h-5.6v1.6Z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M16,186.5h10.7c.4,0,.6.3.6.6v6.6c0,.8-.7,1.5-1.5,1.5h-9c-.8,0-1.5-.7-1.5-1.5v-6.6c0-.4.3-.6.6-.6Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.boxBorder}
|
||||
d="M17.8,186.9v-1.6c0-1.9,1.6-3.5,3.5-3.5h0c1.9,0,3.5,1.6,3.5,3.5v1.6"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M16,149.9h10.7c.4,0,.6.3.6.6v6.6c0,.8-.7,1.5-1.5,1.5h-9c-.8,0-1.5-.7-1.5-1.5v-6.6c0-.4.3-.6.6-.6Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.boxBorder}
|
||||
d="M17.8,150.4v-1.6c0-1.9,1.6-3.5,3.5-3.5h0c1.9,0,3.5,1.6,3.5,3.5v1.6"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M93,203.8h10.7c.4,0,.6.3.6.6v6.6c0,.8-.7,1.5-1.5,1.5h-9c-.8,0-1.5-.7-1.5-1.5v-6.6c0-.4.3-.6.6-.6Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.boxBorder}
|
||||
d="M94.8,204.2v-1.6c0-1.9,1.6-3.5,3.5-3.5h0c1.9,0,3.5,1.6,3.5,3.5v1.6"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M134.8,203.8h10.7c.4,0,.6.3.6.6v6.6c0,.8-.7,1.5-1.5,1.5h-9c-.8,0-1.5-.7-1.5-1.5v-6.6c0-.4.3-.6.6-.6Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.boxBorder}
|
||||
d="M136.7,204.2v-1.6c0-1.9,1.6-3.5,3.5-3.5h0c1.9,0,3.5,1.6,3.5,3.5v1.6"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M176.7,203.8h10.7c.4,0,.6.3.6.6v6.6c0,.8-.7,1.5-1.5,1.5h-9c-.8,0-1.5-.7-1.5-1.5v-6.6c0-.4.3-.6.6-.6Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.boxBorder}
|
||||
d="M178.5,204.2v-1.6c0-1.9,1.6-3.5,3.5-3.5h0c1.9,0,3.5,1.6,3.5,3.5v1.6"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
{/* buttons for port selection */}
|
||||
{/* I2C PORTS */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 0, //address here is not important for I2C, the restrictions are per component not per port
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_I2C,
|
||||
label: "1",
|
||||
autoDetectable: false
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="20.5"
|
||||
cy="44"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* CONFIGURABLE PIN PORTS - Note input Ports 3 and 4 and all control ports are locked for the monitor */}
|
||||
{/* PORT 1 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 1,
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
label: "1",
|
||||
autoDetectable: true
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="20"
|
||||
cy="80"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* PORT 2 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 2,
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
label: "2",
|
||||
autoDetectable: true
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="20.5"
|
||||
cy="116"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* PORT 3 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
setLockOpen(true);
|
||||
// openMenu(e, {
|
||||
// address: 4,
|
||||
// addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
// label: "3",
|
||||
// autoDetectable: true
|
||||
// });
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="21.5"
|
||||
cy="153"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* Port 4 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
setLockOpen(true);
|
||||
// openMenu(e, {
|
||||
// address: 8,
|
||||
// addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
// label: "3",
|
||||
// autoDetectable: true
|
||||
// });
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="21.5"
|
||||
cy="189"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* Controller ports - note these are all locked for monitor devices */}
|
||||
{/* PORT C1 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
setLockOpen(true);
|
||||
// openMenu(e, {
|
||||
// address: 2,
|
||||
// addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
// label: "2",
|
||||
// autoDetectable: true
|
||||
// });
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="98"
|
||||
cy="206"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* PORT C2 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
setLockOpen(true);
|
||||
// openMenu(e, {
|
||||
// address: 4,
|
||||
// addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
// label: "3",
|
||||
// autoDetectable: true
|
||||
// });
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="140"
|
||||
cy="206"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* Port C3 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
setLockOpen(true);
|
||||
// openMenu(e, {
|
||||
// address: 8,
|
||||
// addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
// label: "3",
|
||||
// autoDetectable: true
|
||||
// });
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="182"
|
||||
cy="206"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const streamlineAutomateSVG = () => {
|
||||
return (
|
||||
<svg id="StreamlineAutomate" version="1.1" viewBox="0 0 216 224.09">
|
||||
<rect
|
||||
className={classes.boxBorder}
|
||||
x=".74"
|
||||
y=".74"
|
||||
width="214.53"
|
||||
height="222.62"
|
||||
rx="10.71"
|
||||
ry="10.71"
|
||||
/>
|
||||
<path
|
||||
className={classes.grayLine}
|
||||
d="M212.22,123.15l-21.63-13.37c-2.55-1.57-5.71-1.57-8.25,0l-21.63,13.37c-2.33,1.44-3.72,3.94-3.72,6.68v6.01l-4.52-2.79c-2.26-1.4-5.06-1.4-7.32,0l-18.95,11.71c-2.07,1.28-3.3,3.49-3.3,5.93v5.96l-4.85-3c-2.05-1.27-4.61-1.27-6.66,0l-17.04,10.53c-1.88,1.16-3.01,3.18-3.01,5.39v54.29h5.11v-2.53c0-1.27,1.03-2.3,2.31-2.3h11.1c1.27,0,2.3,1.03,2.3,2.3v2.53h5.11v-2.53c0-1.27,1.03-2.3,2.3-2.3h3.32v4.83h5.52v-4.83h2.27c1.27,0,2.3,1.03,2.3,2.3v2.53h5.11v-18.25h5.31c1.46,0,2.64,1.19,2.64,2.65v15.61h5.52v-15.61c0-1.46,1.19-2.65,2.64-2.65h2.78v18.25h6.09v-18.25h3.48c1.46,0,2.64,1.19,2.64,2.65v15.61h5.52v-31.43h5.58c1.72,0,3.12,1.4,3.12,3.12v28.31h6.09v-28.31c0-1.72,1.4-3.12,3.12-3.12h14.1c1.72,0,3.12,1.4,3.12,3.12v26.88l2.19-1.49.36-.31c.2-.19.39-.39.63-.68l.14-.18c.5-.72.92-1.47,1.33-2.2.43-.76.83-1.47,1.31-2.15l.14-.19v-85.42c0-2.74-1.39-5.24-3.72-6.68ZM119.57,217.55c-2.08,0-3.78,1.69-3.78,3.78v1.06h-2.17v-1.06c0-2.08-1.69-3.78-3.78-3.78h-11.1c-2.08,0-3.78,1.69-3.78,3.78v1.06h-2.17v-52.82c0-1.7.86-3.25,2.31-4.14l17.04-10.53c1.58-.97,3.53-.98,5.11,0l5.62,3.47v59.18h-3.32ZM136.61,222.38h-2.17v-1.06c0-2.08-1.69-3.78-3.78-3.78h-2.27v-9.3c0-1.46,1.19-2.65,2.64-2.65h5.56v16.78ZM154.2,204.13c-2.27,0-4.12,1.85-4.12,4.12v14.14h-2.58v-14.14c0-2.27-1.85-4.12-4.12-4.12h-12.35c-2.27,0-4.12,1.85-4.12,4.12v14.14h-2.57v-71.71c0-1.92.97-3.67,2.61-4.67l18.95-11.71c1.78-1.1,3.99-1.1,5.77,0l5.29,3.27v66.56h-2.78ZM173.24,222.38h-2.58v-14.14c0-2.27-1.85-4.12-4.12-4.12h-3.48v-8.58c0-1.72,1.4-3.12,3.12-3.12h7.05v29.96ZM214.47,214.78c-.46.68-.86,1.39-1.25,2.08-.4.7-.8,1.42-1.26,2.08l-.1.14c-.15.17-.29.33-.46.48l-.07.06v-24.07c0-2.53-2.06-4.6-4.59-4.6h-14.1c-2.53,0-4.6,2.06-4.6,4.6v26.83h-3.15v-26.83c0-2.53-2.06-4.6-4.59-4.6h-14.1c-2.53,0-4.59,2.06-4.59,4.6v26.83h-3.15v-92.56c0-2.23,1.13-4.25,3.03-5.42l21.63-13.37c2.07-1.28,4.64-1.28,6.7,0l21.63,13.37c1.89,1.17,3.03,3.2,3.03,5.43v84.96Z"
|
||||
/>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M59.52,202.99l-.82.82c.66.66,1.02,1.53,1.02,2.46s-.36,1.81-1.02,2.46c-1.36,1.36-3.57,1.36-4.93,0-1.36-1.36-1.36-3.57,0-4.93l-.82-.82c-1.81,1.81-1.81,4.76,0,6.57.91.91,2.1,1.36,3.28,1.36s2.38-.45,3.28-1.36c.88-.88,1.36-2.04,1.36-3.28s-.48-2.41-1.36-3.28Z"
|
||||
/>
|
||||
<rect className={classes.whiteLine} x="55.66" y="201.4" width="1.16" height="5.47" />
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M91,208.58c.18.28.41.5.7.64.29.15.61.22.95.22.3,0,.57-.04.8-.12s.44-.18.62-.31c.18-.13.34-.26.48-.41v1.66c-.26.2-.53.36-.84.47-.3.12-.69.17-1.16.17-.51,0-.98-.08-1.41-.24s-.8-.39-1.11-.68c-.31-.3-.55-.65-.72-1.06-.17-.41-.26-.86-.26-1.36s.08-.95.26-1.36c.17-.41.41-.76.72-1.06.31-.3.68-.53,1.11-.68.43-.16.9-.24,1.41-.24.47,0,.85.06,1.16.17.3.12.58.27.84.47v1.66c-.14-.15-.3-.28-.48-.41-.18-.13-.39-.23-.62-.31s-.5-.11-.8-.11c-.35,0-.66.07-.95.22s-.52.36-.7.64c-.18.28-.26.62-.26,1.01s.09.72.26,1.01Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M96.04,204.89l3.06-.62v6.5h-1.49v-4.93l-1.58.39v-1.34Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M132.85,208.58c.18.28.41.5.7.64.29.15.61.22.95.22.3,0,.57-.04.8-.12s.44-.18.62-.31c.18-.13.34-.26.48-.41v1.66c-.26.2-.53.36-.84.47-.3.12-.69.17-1.16.17-.51,0-.98-.08-1.41-.24s-.8-.39-1.11-.68c-.31-.3-.55-.65-.72-1.06-.17-.41-.26-.86-.26-1.36s.08-.95.26-1.36c.17-.41.41-.76.72-1.06.31-.3.68-.53,1.11-.68.43-.16.9-.24,1.41-.24.47,0,.85.06,1.16.17.3.12.58.27.84.47v1.66c-.14-.15-.3-.28-.48-.41-.18-.13-.39-.23-.62-.31s-.5-.11-.8-.11c-.35,0-.66.07-.95.22s-.52.36-.7.64c-.18.28-.26.62-.26,1.01s.09.72.26,1.01Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M140.31,207.82c.17-.19.32-.36.44-.51.12-.15.22-.3.28-.45.06-.15.1-.31.1-.48,0-.1-.02-.19-.05-.29-.04-.1-.09-.18-.16-.26s-.16-.14-.27-.18c-.11-.05-.24-.07-.38-.07-.19,0-.37.05-.51.15-.15.1-.26.23-.34.41-.08.18-.11.38-.11.61h-1.51c0-.46.09-.87.28-1.25.19-.38.47-.68.85-.9.38-.22.84-.34,1.39-.34.39,0,.74.06,1.05.18.3.12.56.28.76.47.2.2.36.41.46.65.1.24.15.48.15.72,0,.35-.08.66-.26.95-.17.29-.39.55-.67.79l-1.49,1.33h2.55v1.41h-5.4l2.84-2.94Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M176.05,208.58c.18.28.41.5.7.64.29.15.61.22.95.22.3,0,.57-.04.8-.12s.44-.18.62-.31c.18-.13.34-.26.48-.41v1.66c-.26.2-.53.36-.84.47-.3.12-.69.17-1.16.17-.51,0-.98-.08-1.41-.24s-.8-.39-1.11-.68c-.31-.3-.55-.65-.72-1.06-.17-.41-.26-.86-.26-1.36s.08-.95.26-1.36c.17-.41.41-.76.72-1.06.31-.3.68-.53,1.11-.68.43-.16.9-.24,1.41-.24.47,0,.85.06,1.16.17.3.12.58.27.84.47v1.66c-.14-.15-.3-.28-.48-.41-.18-.13-.39-.23-.62-.31s-.5-.11-.8-.11c-.35,0-.66.07-.95.22s-.52.36-.7.64c-.18.28-.26.62-.26,1.01s.09.72.26,1.01Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M182.34,210.74c-.3-.11-.56-.28-.77-.48s-.37-.44-.48-.7-.17-.53-.17-.81h1.51c0,.21.05.38.14.52.09.14.21.24.37.31.15.07.32.1.49.1.18,0,.34-.03.48-.08.14-.05.24-.14.32-.26s.12-.27.12-.45c0-.13-.03-.26-.08-.36s-.14-.2-.25-.29-.25-.14-.42-.19c-.17-.04-.37-.06-.6-.06v-.78c.42,0,.8.03,1.15.1s.65.18.92.33c.26.15.46.34.6.57.14.23.21.51.21.83,0,.37-.1.7-.3.98-.2.28-.49.5-.86.67-.37.16-.82.24-1.34.24-.38,0-.73-.06-1.03-.17ZM182.98,206.98c.18,0,.34-.02.48-.07s.27-.11.37-.19c.11-.08.19-.17.24-.27.05-.1.08-.21.08-.33,0-.12-.03-.23-.08-.33-.05-.1-.13-.17-.24-.22-.1-.05-.24-.08-.4-.08-.24,0-.44.07-.6.21-.16.14-.24.32-.24.55h-1.41c0-.38.09-.72.28-1.02.19-.3.45-.54.79-.71.34-.17.74-.26,1.18-.26.48,0,.89.08,1.22.24.33.16.59.37.76.64s.26.56.26.89c0,.36-.12.67-.36.91-.24.24-.56.43-.97.55-.41.12-.86.18-1.37.18v-.69Z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M14.08,77.72l3.06-.62v6.5h-1.49v-4.93l-1.58.39v-1.34Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M16.48,116.47c.17-.19.32-.36.44-.51.12-.15.22-.3.28-.45.06-.15.1-.31.1-.48,0-.1-.02-.19-.05-.29-.04-.1-.09-.18-.16-.26s-.16-.14-.27-.18c-.11-.05-.24-.07-.38-.07-.19,0-.37.05-.51.15-.15.1-.26.23-.34.41-.08.18-.11.38-.11.61h-1.51c0-.46.09-.87.28-1.25.19-.38.47-.68.85-.9.38-.22.84-.34,1.39-.34.39,0,.74.06,1.05.18.3.12.56.28.76.47.2.2.36.41.46.65s.15.48.15.72c0,.35-.08.66-.26.95s-.39.55-.67.79l-1.49,1.33h2.55v1.41h-5.4l2.84-2.94Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M15.32,155.21c-.3-.12-.56-.28-.77-.48-.21-.21-.37-.44-.48-.7s-.17-.53-.17-.81h1.51c0,.21.05.38.14.52s.21.24.37.31.32.1.49.1c.18,0,.34-.03.48-.08.14-.05.24-.14.32-.26.08-.12.12-.27.12-.45,0-.13-.03-.26-.08-.36-.05-.11-.14-.2-.25-.29s-.25-.14-.42-.19c-.17-.04-.37-.06-.6-.06v-.78c.42,0,.8.03,1.15.1.35.07.65.18.92.33.26.15.46.34.6.57.14.23.21.51.21.83,0,.37-.1.7-.3.98-.2.28-.49.5-.86.67s-.82.24-1.34.24c-.38,0-.73-.06-1.03-.17ZM15.96,151.45c.18,0,.34-.02.48-.07.14-.05.27-.11.37-.19s.19-.17.24-.27.08-.21.08-.33c0-.12-.03-.23-.08-.33s-.13-.17-.24-.22c-.1-.05-.24-.08-.4-.08-.24,0-.44.07-.6.21-.16.14-.24.32-.24.55h-1.41c0-.38.09-.72.28-1.02.19-.3.45-.54.79-.71.34-.17.74-.26,1.18-.26.48,0,.89.08,1.22.24.33.16.59.37.76.64.17.27.26.56.26.89,0,.36-.12.67-.36.91-.24.24-.56.43-.97.55-.41.12-.86.18-1.37.18v-.69Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M17.28,184.68h1.15v6.38h-1.6v-1.6l.17-.1v-2.44l-1.38,1.9h2.35l.15-.2h1.3v1.31h-5.85l3.7-5.25Z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M16.95,38.26c-3.47,0-6.28,2.81-6.28,6.28s2.81,6.28,6.28,6.28,6.28-2.81,6.28-6.28-2.81-6.28-6.28-6.28ZM16.95,48.51c-2.2,0-3.98-1.78-3.98-3.98s1.78-3.98,3.98-3.98,3.98,1.78,3.98,3.98-1.78,3.98-3.98,3.98Z"
|
||||
/>
|
||||
<circle className={classes.whiteLine} cx="16.95" cy="44.53" r="2.33" />
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M184.22,153.42c0-2.75-1.07-5.34-3.02-7.28-.76-.76-2-.76-2.76,0-.76.76-.76,2,0,2.76,1.21,1.21,1.87,2.81,1.87,4.52s-.66,3.31-1.87,4.52c-.38.38-.57.88-.57,1.38s.19,1,.57,1.38c.76.76,2,.76,2.76,0,1.95-1.94,3.02-4.53,3.02-7.28ZM190.65,153.42c0-4.47-1.74-8.67-4.9-11.83-.76-.76-2-.76-2.76,0-.76.76-.76,2,0,2.76,2.42,2.42,3.76,5.64,3.76,9.07s-1.33,6.65-3.76,9.07c-.38.38-.57.88-.57,1.38s.19,1,.57,1.38c.76.76,2,.76,2.76,0,3.16-3.16,4.9-7.36,4.9-11.83ZM190.31,169.82c4.38-4.38,6.79-10.2,6.79-16.39s-2.41-12.02-6.79-16.39c-.76-.76-2-.76-2.76,0-.38.38-.57.88-.57,1.38s.19,1,.57,1.38c3.64,3.64,5.65,8.48,5.65,13.63s-2.01,9.99-5.65,13.63c-.76.76-.76,2,0,2.76.76.76,2,.76,2.76,0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M175.74,149.01c-.62-.62-1.8-.62-2.41,0-.67.67-.67,1.75,0,2.42.53.53.83,1.24.83,2s-.29,1.46-.83,2c-.32.32-.5.75-.5,1.21s.18.88.5,1.21c.32.32.75.5,1.21.5s.88-.18,1.21-.5c1.18-1.18,1.83-2.74,1.83-4.41s-.65-3.23-1.83-4.41Z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M124.72,103.81v.94c0,.42.32.77.73.82v.86h.2v-.86c.41-.05.73-.4.73-.82v-.94l-.83.71-.83-.71ZM126.17,104.75c0,.31-.23.57-.53.62v-.3h-.2v.3c-.3-.05-.53-.31-.53-.62v-.51l.63.54.63-.54v.51Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M124.72,102.37v.94c0,.46.37.83.83.83s.83-.37.83-.83v-.94l-.83.71-.83-.71ZM126.17,103.31c0,.31-.23.57-.53.62v-.3h-.2v.3c-.3-.05-.53-.31-.53-.62v-.51l.63.54.63-.54v.51Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M124.72,100.91v.94c0,.46.37.83.83.83s.83-.37.83-.83v-.94l-.83.71-.83-.71ZM126.17,101.85c0,.31-.23.57-.53.62v-.3h-.2v.3c-.3-.05-.53-.31-.53-.62v-.51l.63.54.63-.54v.51Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M125.54,101.3h.01s.01,0,.01,0c.01,0,.36-.05.48-.33.11-.27-.03-.63-.41-1.09l-.08-.09-.08.09c-.38.46-.52.82-.41,1.09.11.29.46.33.48.33ZM125.55,100.1c.34.43.36.67.31.8-.04.1-.14.16-.22.19v-.28h-.2v.27c-.07-.03-.16-.08-.2-.18-.05-.12-.03-.36.31-.8Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M140.2,103.6h-2.45v.99c-.25.14-.54.23-.85.23-.93,0-1.69-.76-1.69-1.69s.76-1.69,1.69-1.69,1.67.73,1.69,1.65h1.64c-.02-1.82-1.51-3.29-3.33-3.29-1.54,0-2.83,1.04-3.22,2.46-.38-1.42-1.68-2.46-3.22-2.46-1.84,0-3.34,1.49-3.34,3.34s1.49,3.34,3.34,3.34c.62,0,1.2-.17,1.69-.46v.46h1.64v-2.11c.49,1.24,1.69,2.11,3.1,2.11.62,0,1.2-.17,1.69-.46v.46h1.64v-2.87h-.03ZM130.46,104.82c-.93,0-1.69-.76-1.69-1.69s.76-1.69,1.69-1.69,1.69.76,1.69,1.69-.76,1.69-1.69,1.69Z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M143.16,102.83l-.27-.61h-.94l-.28.61h-.41l1.15-2.47,1.15,2.47h-.41ZM142.09,101.9h.66l-.24-.54s-.03-.07-.04-.12c-.02-.04-.03-.09-.05-.15-.01.05-.03.1-.04.15-.01.04-.03.09-.04.12l-.24.54Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M144.32,102.83v-2.38h.52c.34,0,.58.02.71.05.14.03.26.09.36.17.14.1.24.24.31.4.07.16.11.35.11.56s-.04.4-.11.56c-.07.16-.17.3-.31.4-.1.08-.22.14-.35.17-.13.03-.34.05-.62.05h-.62ZM144.71,102.49h.32c.18,0,.31-.01.4-.04.09-.02.17-.06.23-.12.09-.08.16-.17.2-.29.04-.11.07-.25.07-.4s-.02-.28-.07-.4c-.04-.11-.11-.21-.2-.29-.07-.06-.15-.1-.24-.12-.09-.02-.24-.04-.44-.04h-.28v1.68Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M148.82,102.83l-.27-.61h-.94l-.28.61h-.41l1.15-2.47,1.15,2.47h-.41ZM147.76,101.9h.66l-.24-.54s-.03-.07-.04-.12c-.02-.04-.03-.09-.05-.15-.01.05-.03.1-.04.15-.01.04-.03.09-.04.12l-.24.54Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M150.35,101.77v1.07h-.36v-2.38h.58c.17,0,.3,0,.38.03.08.02.15.05.21.09.07.06.13.13.18.22.04.09.06.2.06.31s-.02.22-.06.31c-.04.1-.1.17-.18.22-.06.04-.13.07-.21.09-.08.02-.21.03-.38.03h-.22ZM150.37,101.45h.1c.21,0,.36-.02.43-.07s.11-.13.11-.25c0-.13-.04-.22-.11-.27-.08-.05-.22-.08-.42-.08h-.1v.66Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M153.05,100.79v2.05h-.39v-2.05h-.63v-.33h1.65v.33h-.63Z"
|
||||
/>
|
||||
<path className={classes.whiteLine} d="M154.52,102.83v-2.38h.39v2.38h-.39Z" />
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M156.74,102.93l-1.06-2.47h.4l.53,1.27c.03.07.06.14.08.2.02.06.04.12.05.18.01-.06.03-.12.05-.18.02-.06.05-.13.08-.2l.53-1.27h.4l-1.06,2.47Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M158.57,102.83v-2.38h1.33v.33h-.94v.6h.94v.34h-.94v.77h.94v.35h-1.33Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M143.16,106.36l-.27-.61h-.94l-.28.61h-.41l1.15-2.47,1.15,2.47h-.41ZM142.09,105.43h.66l-.24-.54s-.03-.07-.04-.12c-.02-.04-.03-.09-.05-.15-.01.05-.03.1-.04.15-.01.04-.03.09-.04.12l-.24.54Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M145.58,105.15h.94s0,.04,0,.07c0,.08,0,.13,0,.16,0,.33-.1.59-.29.78s-.46.28-.81.28c-.19,0-.37-.03-.52-.09-.15-.06-.29-.14-.4-.26-.11-.11-.2-.25-.26-.4-.06-.15-.09-.32-.09-.5s.03-.35.09-.5c.06-.15.15-.29.27-.4.12-.11.25-.2.41-.26.16-.06.32-.09.5-.09.19,0,.35.03.5.1.15.07.28.17.4.31l-.28.21c-.08-.09-.17-.16-.27-.21-.1-.05-.21-.07-.34-.07-.26,0-.47.08-.63.25-.16.16-.24.38-.24.64s.08.49.24.65c.16.17.37.25.63.25.22,0,.39-.05.52-.15.13-.1.19-.24.19-.42v-.03h-.57v-.33Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M147.83,105.3v1.06h-.36v-2.38h.54c.16,0,.28.01.37.03.09.02.16.05.22.1.07.06.13.13.17.22.04.09.06.19.06.3,0,.19-.05.34-.14.45-.09.11-.23.17-.41.19l.82,1.08h-.44l-.79-1.06h-.04ZM147.85,105h.07c.2,0,.34-.02.41-.07.07-.05.1-.13.1-.25,0-.13-.04-.22-.11-.28-.07-.05-.21-.08-.4-.08h-.07v.68Z"
|
||||
/>
|
||||
<path className={classes.whiteLine} d="M149.86,106.36v-2.38h.39v2.38h-.39Z" />
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M153.24,104.57c-.11-.09-.22-.16-.35-.21-.12-.05-.25-.07-.38-.07-.26,0-.47.08-.63.25-.16.17-.24.38-.24.65s.08.47.24.63c.16.17.36.25.6.25.14,0,.27-.02.4-.07.13-.05.25-.12.37-.23v.44c-.1.07-.22.13-.34.17-.12.04-.25.06-.4.06-.18,0-.35-.03-.5-.09s-.29-.15-.41-.26c-.12-.11-.2-.25-.27-.4-.06-.15-.09-.32-.09-.49s.03-.34.09-.49c.06-.15.15-.29.27-.4.12-.12.25-.21.41-.27.15-.06.32-.09.49-.09.14,0,.27.02.4.06s.25.1.37.18l-.02.39Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M154.24,103.99h.38v1.44c0,.21.05.38.15.48.1.11.25.16.44.16s.34-.05.44-.16c.1-.11.15-.27.15-.48v-1.44h.39v1.48c0,.32-.08.56-.24.72-.16.16-.41.24-.73.24s-.57-.08-.73-.24c-.16-.16-.24-.4-.24-.72v-1.48Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M157.26,106.36v-2.38h.39v2.03h.86v.35h-1.25Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M159.94,104.32v2.05h-.39v-2.05h-.63v-.33h1.65v.33h-.63Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M161.38,103.99h.38v1.44c0,.21.05.38.15.48.1.11.25.16.44.16s.34-.05.44-.16c.1-.11.15-.27.15-.48v-1.44h.39v1.48c0,.32-.08.56-.24.72s-.41.24-.73.24-.57-.08-.73-.24c-.16-.16-.24-.4-.24-.72v-1.48Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M164.76,105.3v1.06h-.36v-2.38h.54c.16,0,.28.01.37.03.09.02.16.05.22.1.07.06.13.13.17.22.04.09.06.19.06.3,0,.19-.05.34-.14.45-.09.11-.23.17-.41.19l.82,1.08h-.44l-.79-1.06h-.04ZM164.78,105h.07c.2,0,.34-.02.41-.07.07-.05.1-.13.1-.25,0-.13-.04-.22-.11-.28-.07-.05-.21-.08-.4-.08h-.07v.68Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M166.79,106.36v-2.38h1.33v.33h-.94v.6h.94v.34h-.94v.77h.94v.35h-1.33Z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M96.59,99.33v3.04h-.62v-3.04h.62ZM96.18,100.47h2.23v.56h-2.23v-.56ZM98.63,99.33v3.04h-.62v-3.04h.62Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M99.68,101.9s.07.07.12.1c.05.02.11.03.17.03.09,0,.16-.02.23-.05.07-.04.13-.09.17-.16.04-.07.06-.15.06-.25l.07.26c0,.13-.04.23-.11.32s-.16.15-.27.2c-.11.04-.23.07-.35.07s-.24-.02-.35-.07c-.11-.05-.19-.12-.26-.22-.07-.09-.1-.21-.1-.35,0-.19.07-.35.2-.46.14-.11.33-.17.58-.17.13,0,.24.01.34.04.1.03.18.06.25.1.07.04.11.07.14.11v.26c-.08-.06-.17-.1-.26-.13-.1-.03-.2-.04-.31-.04-.09,0-.16.01-.21.03-.06.02-.1.05-.12.09-.03.04-.04.09-.04.15s.01.11.04.15ZM99.21,100.55c.1-.05.23-.11.38-.16s.32-.08.5-.08c.17,0,.32.02.46.07.13.05.24.12.31.21.08.09.11.21.11.35v1.42h-.54v-1.3c0-.06,0-.1-.03-.14-.02-.04-.04-.07-.08-.1-.04-.03-.08-.04-.13-.06-.05-.01-.1-.02-.17-.02-.09,0-.18.01-.26.03-.08.02-.16.04-.22.07-.06.03-.11.05-.13.07l-.21-.38Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M102.05,102.37h-.55v-2h.55v2ZM102.52,100.88s-.09-.03-.15-.03c-.07,0-.13.02-.18.06-.05.04-.09.09-.11.16-.02.07-.04.15-.04.25l-.16-.16c0-.16.03-.3.09-.42.06-.12.14-.22.24-.3.1-.07.2-.11.3-.11.07,0,.14.01.21.04.06.03.12.07.16.12l-.26.48s-.08-.06-.12-.08Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M103.19,100.8c.09-.15.21-.27.36-.35.15-.08.3-.12.47-.12s.32.04.45.13c.13.08.23.2.3.36s.11.34.11.56-.04.4-.11.56-.18.28-.3.36c-.13.08-.28.13-.45.13s-.32-.04-.47-.12c-.15-.08-.27-.2-.36-.36-.09-.16-.13-.34-.13-.56s.04-.41.13-.57ZM103.71,101.68c.05.09.12.15.2.2.08.05.17.07.27.07.08,0,.17-.02.25-.07.08-.04.14-.11.2-.2.05-.09.08-.19.08-.31s-.03-.23-.08-.31c-.05-.09-.12-.15-.2-.2-.08-.04-.16-.07-.25-.07-.1,0-.19.02-.27.07-.08.05-.15.11-.2.2-.05.09-.07.19-.07.31s.02.22.07.31ZM105.26,98.98v3.39h-.56v-3.39h.56Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M106.11,100.37l.44,1.11.56-1.26.59,1.26.44-1.11h.59l-.98,2.13-.64-1.27-.62,1.27-.98-2.13h.6Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M109.44,101.9s.07.07.12.1c.05.02.11.03.17.03.09,0,.16-.02.23-.05.07-.04.13-.09.17-.16.04-.07.06-.15.06-.25l.07.26c0,.13-.04.23-.11.32s-.16.15-.27.2c-.11.04-.23.07-.35.07s-.24-.02-.35-.07c-.11-.05-.19-.12-.26-.22-.07-.09-.1-.21-.1-.35,0-.19.07-.35.2-.46.14-.11.33-.17.58-.17.13,0,.24.01.34.04.1.03.18.06.25.1.07.04.11.07.14.11v.26c-.08-.06-.17-.1-.26-.13-.1-.03-.2-.04-.31-.04-.09,0-.16.01-.21.03-.06.02-.1.05-.12.09-.03.04-.04.09-.04.15s.01.11.04.15ZM108.98,100.55c.1-.05.23-.11.38-.16s.32-.08.5-.08c.17,0,.32.02.46.07.13.05.24.12.31.21.08.09.11.21.11.35v1.42h-.54v-1.3c0-.06,0-.1-.03-.14-.02-.04-.04-.07-.08-.1-.04-.03-.08-.04-.13-.06-.05-.01-.1-.02-.17-.02-.09,0-.18.01-.26.03-.08.02-.16.04-.22.07-.06.03-.11.05-.13.07l-.21-.38Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M111.82,102.37h-.55v-2h.55v2ZM112.29,100.88s-.09-.03-.15-.03c-.07,0-.13.02-.18.06-.05.04-.09.09-.11.16-.02.07-.04.15-.04.25l-.16-.16c0-.16.03-.3.09-.42.06-.12.14-.22.24-.3.1-.07.2-.11.3-.11.07,0,.14.01.21.04.07.03.12.07.16.12l-.26.48s-.08-.06-.11-.08Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M113.27,102.28c-.16-.09-.29-.21-.38-.36-.09-.15-.13-.34-.13-.55s.04-.4.13-.55c.09-.15.21-.27.38-.36.16-.09.35-.13.57-.13s.41.04.56.12.27.2.35.35.12.34.12.55c0,.03,0,.05,0,.08,0,.03,0,.05,0,.07h-1.79v-.35h1.3l-.15.2s.02-.04.03-.07c.01-.03.02-.06.02-.08,0-.1-.02-.18-.05-.25-.04-.07-.09-.12-.15-.17-.07-.04-.14-.06-.23-.06-.11,0-.2.02-.28.07-.07.05-.13.12-.17.21-.04.09-.06.21-.06.35,0,.13.02.25.06.34.04.09.1.16.18.21.08.05.17.07.28.07.12,0,.23-.02.32-.07s.16-.12.22-.21l.49.15c-.1.19-.24.33-.41.42-.17.09-.38.14-.62.14-.22,0-.41-.04-.57-.13Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M117.16,102.37h-.56v-3.39h.56v3.39ZM118.66,101.93c-.09.16-.21.28-.35.36s-.3.12-.47.12-.31-.04-.44-.13c-.13-.08-.23-.2-.31-.36s-.11-.34-.11-.56.04-.4.11-.56.18-.27.31-.36c.13-.08.28-.13.44-.13s.32.04.47.12.26.2.35.35c.09.16.13.34.13.57s-.04.41-.13.56ZM118.14,101.06c-.05-.09-.11-.15-.2-.2s-.17-.07-.27-.07c-.08,0-.17.02-.25.07-.08.04-.14.11-.2.2s-.08.19-.08.31.03.23.08.31.12.15.2.2c.08.05.16.07.25.07.1,0,.19-.02.27-.07s.15-.11.2-.2c.05-.09.07-.19.07-.31s-.02-.22-.07-.31Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M119.75,103.32h-.58l.5-1.15-.83-1.8h.63l.64,1.59h-.28s.63-1.59.63-1.59h.59l-1.3,2.95Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M121.46,100.23c.07-.07.15-.1.25-.1s.19.03.26.1c.07.07.1.15.1.25s-.03.18-.1.25c-.07.07-.15.1-.26.1s-.19-.03-.25-.1c-.07-.07-.1-.15-.1-.25s.03-.18.1-.25ZM121.46,101.86c.07-.07.15-.1.25-.1s.19.03.26.1c.07.07.1.15.1.25,0,.09-.03.17-.1.24-.07.07-.15.1-.26.1s-.19-.03-.25-.1c-.07-.07-.1-.15-.1-.24,0-.1.03-.18.1-.25Z"
|
||||
/>
|
||||
</g>
|
||||
<rect className={classes.whiteLine} x="75.58" y="95.54" width="92.26" height=".81" />
|
||||
<polygon
|
||||
className={classes.whiteLine}
|
||||
points="86.33 92.24 86.33 93.96 88.81 95.94 86.33 97.92 86.33 99.64 90.96 95.94 86.33 92.24"
|
||||
/>
|
||||
<polygon
|
||||
className={classes.whiteLine}
|
||||
points="81.86 92.24 81.86 93.96 84.33 95.94 81.86 97.92 81.86 99.64 86.49 95.94 81.86 92.24"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M58.9,103.34c-.23,0-.46-.02-.69-.05-.16-.02-.31-.12-.39-.27s-.08-.33-.01-.48h0c.47-.97,1.22-1.76,2.18-2.27.95-.51,2.02-.71,3.1-.56.16.02.31.12.39.27s.08.33.01.48c-.47.97-1.22,1.76-2.18,2.27-.75.4-1.57.61-2.4.61ZM58.38,102.82h0ZM58.46,102.67c.88.09,1.75-.09,2.53-.51.78-.42,1.41-1.05,1.82-1.83-.88-.09-1.75.09-2.53.51-.78.42-1.41,1.05-1.82,1.83Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M63.9,97.27s-.07,0-.1,0c-1.08-.02-2.11-.38-2.97-1.03-.13-.1-.21-.26-.21-.43s.09-.33.22-.42h0c.89-.62,1.91-.94,3.01-.91,1.08.02,2.11.38,2.97,1.03.13.1.21.26.21.43,0,.17-.09.33-.22.42-.86.6-1.86.91-2.91.91ZM61.36,95.83c.72.5,1.57.78,2.45.8.91.02,1.74-.22,2.48-.7-.72-.5-1.57-.78-2.45-.8-.89-.02-1.74.22-2.48.7Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M75.39,95.72c-.97,0-1.91-.27-2.73-.8-.91-.58-1.61-1.42-2-2.42-.06-.15-.04-.33.05-.47.09-.14.24-.23.41-.24h0c1.08-.07,2.13.21,3.05.79.91.58,1.61,1.42,2,2.42.06.15.04.33-.05.47-.09.14-.24.23-.41.24-.11,0-.21.01-.32.01ZM71.33,92.42c.35.81.93,1.48,1.68,1.96.75.48,1.6.71,2.49.69-.35-.81-.93-1.48-1.68-1.96-.75-.48-1.59-.71-2.49-.69ZM71.15,92.43h0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M71.29,100.11c-.11,0-.21,0-.32-.01-.16,0-.32-.1-.41-.24-.09-.14-.11-.32-.05-.47.4-1.01,1.09-1.84,2-2.43.91-.58,1.96-.85,3.05-.79.17.01.32.1.41.24s.11.32.05.47c-.4,1.01-1.09,1.84-2,2.42-.82.52-1.76.8-2.73.8ZM71.18,99.46c.89.02,1.74-.22,2.49-.69.75-.48,1.33-1.15,1.68-1.96-.88-.01-1.74.22-2.49.69-.75.48-1.33,1.15-1.68,1.96Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M70.32,95.72c-.97,0-1.91-.27-2.73-.8-.91-.58-1.61-1.42-2-2.42-.06-.15-.04-.33.05-.47.09-.14.24-.23.41-.24h0c1.08-.07,2.13.21,3.05.79.91.58,1.61,1.42,2,2.42.06.15.04.33-.05.47-.09.14-.24.23-.41.24-.11,0-.21.01-.32.01ZM66.25,92.42c.35.81.93,1.48,1.68,1.96.75.48,1.59.7,2.49.69-.35-.81-.93-1.48-1.68-1.96s-1.61-.71-2.49-.69ZM66.08,92.43h0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M66.22,100.11c-.11,0-.21,0-.32-.01-.16,0-.32-.1-.41-.24-.09-.14-.11-.32-.05-.47.4-1.01,1.09-1.84,2-2.43.91-.58,1.96-.85,3.05-.79.17.01.32.1.41.24.09.14.11.32.05.47-.4,1-1.09,1.84-2,2.42-.82.52-1.76.8-2.73.8ZM66.11,99.46c.88.02,1.74-.22,2.49-.69.75-.48,1.33-1.15,1.68-1.96-.88-.01-1.74.22-2.49.69-.75.48-1.33,1.15-1.68,1.96ZM70.45,96.82h0,0ZM70.35,96.65h0s0,0,0,0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M80.46,95.72c-.97,0-1.91-.27-2.73-.8-.91-.58-1.61-1.42-2-2.42-.06-.15-.04-.33.05-.47.09-.14.24-.23.41-.24h0c1.09-.07,2.13.21,3.05.79.91.58,1.61,1.42,2,2.42.06.15.04.33-.05.47-.09.14-.24.23-.41.24-.11,0-.21.01-.32.01ZM76.4,92.42c.35.81.93,1.48,1.68,1.96.75.48,1.59.7,2.49.69-.35-.81-.93-1.48-1.68-1.96s-1.61-.71-2.49-.69ZM76.22,92.43h0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M76.36,100.11c-.11,0-.21,0-.32-.01-.16,0-.32-.1-.41-.24-.09-.14-.11-.32-.05-.47.4-1.01,1.09-1.84,2-2.43.91-.58,1.97-.85,3.05-.79.17.01.32.1.41.24.09.14.11.32.05.47-.4,1-1.09,1.84-2,2.42-.82.52-1.76.8-2.73.8ZM76.25,99.46c.88.02,1.74-.22,2.49-.69.75-.48,1.33-1.15,1.68-1.96-.87-.01-1.74.22-2.49.69-.75.48-1.33,1.15-1.68,1.96ZM80.59,96.82h0,0ZM80.49,96.65h0s0,0,0,0Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M57.02,98.03c-.68,0-1.36-.14-2-.41-1-.43-1.81-1.14-2.37-2.07-.09-.14-.1-.32-.03-.48s.2-.27.36-.31c1.05-.24,2.14-.14,3.13.28,1,.43,1.81,1.14,2.37,2.07.09.14.1.32.03.47-.07.16-.2.27-.36.31-.38.09-.76.13-1.14.13ZM53.3,95.36c.48.74,1.16,1.31,1.98,1.66.82.35,1.7.45,2.57.28-.48-.74-1.16-1.31-1.98-1.66-.82-.35-1.7-.44-2.57-.28ZM53.13,95.4h0,0Z"
|
||||
/>
|
||||
<g>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M61.04,86.66c0,2.09-1.71,3.3-4.23,3.3-1.83,0-3.37-.63-4.33-1.24l1.01-2.04c.92.52,2.13,1.02,3.3,1.02.69,0,1.6-.17,1.6-.81,0-1.54-5.44-.49-5.51-4.1-.03-1.99,1.6-3.27,4.17-3.27,1.37,0,2.46.36,3.45.89l-.94,2.01c-.92-.45-1.97-.71-2.75-.71-.92,0-1.35.39-1.35.82,0,1.58,5.58.33,5.58,4.12Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M72.92,81.95h-2.96v7.82h-2.59v-7.82h-2.96v-2.26h8.52v2.26Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M81.4,86.86h-2.01v2.91h-2.59v-10.07h5.38c2.42,0,3.77,1.47,3.77,3.47,0,1.41-.66,2.63-1.93,3.27l2.46,3.34h-3.07l-2.01-2.91ZM79.39,84.61h2.25c1.28,0,1.67-.65,1.67-1.4,0-.88-.5-1.27-1.64-1.27h-2.27v2.66Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M92.28,83.56h5.11v2.2h-5.11v1.74h5.61v2.26h-8.18v-10.07h8.15v2.26h-5.58v1.61Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M107.73,88.27h-4.65l-.6,1.5h-2.79l4.48-10.07h2.5l4.48,10.07h-2.81l-.6-1.5ZM106.86,86.09l-1.19-2.94-.24-.66-.24.66-1.19,2.94h2.88Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M125.4,89.76h-2.59v-6l-.19.33-2.43,2.89h-.63l-2.43-2.89-.2-.35v6.02h-2.59v-10.07h1.86l3.38,3.83.3.45.29-.45,3.38-3.83h1.86v10.07Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M136.7,89.76h-7.38v-10.07h2.59v7.82h4.79v2.26Z"
|
||||
/>
|
||||
<path className={classes.whiteLine} d="M142.56,89.76h-2.59v-10.07h2.59v10.07Z" />
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M156.7,89.76h-1.91l-4.94-5.94-.2-.39v6.33h-2.59v-10.07h2.26l4.59,5.51.2.37v-5.89h2.59v10.07Z"
|
||||
/>
|
||||
<path
|
||||
className={classes.whiteLine}
|
||||
d="M163.11,83.56h5.11v2.2h-5.11v1.74h5.61v2.26h-8.18v-10.07h8.15v2.26h-5.58v1.61Z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
{/* buttons for port selection */}
|
||||
{/* I2C PORTS */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 0, //address here is not important for I2C, the restrictions are per component not per port
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_I2C,
|
||||
label: "1",
|
||||
autoDetectable: false
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="17"
|
||||
cy="44"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* CONFIGURABLE PIN PORTS - Note input Ports 3 and 4 and all control ports are locked for the monitor */}
|
||||
{/* PORT 1 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 1,
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
label: "1",
|
||||
autoDetectable: true
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="17"
|
||||
cy="80"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* PORT 2 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 2,
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
label: "2",
|
||||
autoDetectable: true
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="17"
|
||||
cy="116"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* PORT 3 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 4,
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
label: "3",
|
||||
autoDetectable: true
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="17"
|
||||
cy="152"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* Port 4 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 8,
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
label: "4",
|
||||
autoDetectable: true
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="17"
|
||||
cy="188"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* Controller ports - note these are all locked for monitor devices */}
|
||||
{/* PORT C1 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 2,
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
label: "C1",
|
||||
autoDetectable: true
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="95"
|
||||
cy="207"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* PORT C2 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 4,
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
label: "C2",
|
||||
autoDetectable: true
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="138"
|
||||
cy="207"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
{/* Port C3 */}
|
||||
<ellipse
|
||||
onClick={e => {
|
||||
openMenu(e, {
|
||||
address: 8,
|
||||
addressType: quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY,
|
||||
label: "C3",
|
||||
autoDetectable: true
|
||||
});
|
||||
}}
|
||||
className={classes.testButton}
|
||||
id="button"
|
||||
cx="180"
|
||||
cy="207"
|
||||
rx={buttonSize.rxLarge}
|
||||
ry={buttonSize.ryLarge}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const getProductSVG = () => {
|
||||
switch (device.settings.product) {
|
||||
case pond.DeviceProduct.DEVICE_PRODUCT_BINDAPT_PLUS_PRO:
|
||||
|
|
@ -5232,6 +6159,10 @@ export default function DeviceSVG(props: Props) {
|
|||
return miVentSVG();
|
||||
case pond.DeviceProduct.DEVICE_PRODUCT_MIVENT_V2:
|
||||
return miVentSVG(true);
|
||||
case pond.DeviceProduct.DEVICE_PRODUCT_STREAMLINE_MONITOR:
|
||||
return streamlineMonitorSVG();
|
||||
case pond.DeviceProduct.DEVICE_PRODUCT_STREAMLINE_AUTOMATE:
|
||||
return streamlineAutomateSVG();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ class UploadFirmware extends React.Component<Props, State> {
|
|||
pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLACK,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_GREEN,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLUE,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE,
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE
|
||||
].includes(platform);
|
||||
var isChannelValid = [
|
||||
pond.UpgradeChannel.UPGRADE_CHANNEL_ALPHA,
|
||||
|
|
@ -230,6 +231,9 @@ class UploadFirmware extends React.Component<Props, State> {
|
|||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE}>
|
||||
V2 Wifi Blue
|
||||
</MenuItem>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE}>
|
||||
V2 Ethernet Blue
|
||||
</MenuItem>
|
||||
</TextField>
|
||||
<TextField
|
||||
id="channel"
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ interface Props {
|
|||
drawerView?: boolean;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default function GateDevice(props: Props) {
|
||||
const { gate, comprehensiveDevice, linkedCompList, drawerView } = props;
|
||||
const [{as}] = useGlobalState();
|
||||
|
|
@ -234,6 +236,7 @@ export default function GateDevice(props: Props) {
|
|||
return (
|
||||
<Select
|
||||
id="ambientSelect"
|
||||
variant="standard"
|
||||
value={ambientKey}
|
||||
style={{ fontSize: 8 }}
|
||||
onChange={e => {
|
||||
|
|
@ -266,6 +269,7 @@ export default function GateDevice(props: Props) {
|
|||
return (
|
||||
<Select
|
||||
id="tempSelect"
|
||||
variant="standard"
|
||||
value={tempKey}
|
||||
style={{ fontSize: 8 }}
|
||||
onChange={e => {
|
||||
|
|
@ -300,6 +304,7 @@ export default function GateDevice(props: Props) {
|
|||
return (
|
||||
<Select
|
||||
id="pressureSelect"
|
||||
variant="standard"
|
||||
value={pressureKey}
|
||||
style={{ fontSize: 8 }}
|
||||
onChange={e => {
|
||||
|
|
@ -335,9 +340,10 @@ export default function GateDevice(props: Props) {
|
|||
container
|
||||
direction="row"
|
||||
alignContent="center"
|
||||
width="100%"
|
||||
//alignItems="center"
|
||||
>
|
||||
<Grid size={{ sm: 12, lg: isMobile || drawerView ? 12 : 8}} style={{ padding: 10 }}>
|
||||
<Grid size={{ sm: 12, lg: isMobile || drawerView ? 12 : 4}} style={{ padding: 10 }}>
|
||||
<Box
|
||||
paddingLeft={1}
|
||||
display="flex"
|
||||
|
|
|
|||
|
|
@ -355,13 +355,13 @@ export default function GateSVG(props: Props) {
|
|||
{renderValues()}
|
||||
</g>
|
||||
<foreignObject height={20} width={120} x={10} y={83}>
|
||||
<Box style={{ position: "fixed" }}>{ambientSelector()}</Box>
|
||||
<Box sx={{ position: "fixed" }}>{ambientSelector()}</Box>
|
||||
</foreignObject>
|
||||
<foreignObject height={20} width={120} x={10} y={118}>
|
||||
<Box style={{ position: "fixed" }}>{tempChainSelector()}</Box>
|
||||
<Box sx={{ position: "fixed" }}>{tempChainSelector()}</Box>
|
||||
</foreignObject>
|
||||
<foreignObject height={20} width={120} x={10} y={153}>
|
||||
<Box style={{ position: "fixed" }}>{pressureChainSelector()}</Box>
|
||||
<Box sx={{ position: "fixed" }}>{pressureChainSelector()}</Box>
|
||||
</foreignObject>
|
||||
{pcaRed()}
|
||||
{pcaGreen()}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ interface FeatureVersionByPlatform {
|
|||
v2CellGreen: string;
|
||||
v2WifiBlue: string;
|
||||
v2CellBlue: string;
|
||||
v2EthBlue: string;
|
||||
}
|
||||
|
||||
const featureVersions: Map<string, FeatureVersionByPlatform> = new Map([
|
||||
|
|
@ -29,7 +30,8 @@ const featureVersions: Map<string, FeatureVersionByPlatform> = new Map([
|
|||
v2CellBlack: "2.0.44",
|
||||
v2CellGreen: "2.0.44",
|
||||
v2WifiBlue: "2.0.44",
|
||||
v2CellBlue: "2.0.44"
|
||||
v2CellBlue: "2.0.44",
|
||||
v2EthBlue: "2.0.44"
|
||||
}
|
||||
]
|
||||
]);
|
||||
|
|
@ -118,6 +120,8 @@ export class Device {
|
|||
return this.status.firmwareVersion >= versions.v2WifiBlue;
|
||||
case pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLUE:
|
||||
return this.status.firmwareVersion >= versions.v2CellBlue;
|
||||
case pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE:
|
||||
return this.status.firmwareVersion >= versions.v2EthBlue;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import { pond, quack } from "protobuf-ts/pond";
|
|||
import { cloneDeep } from "lodash";
|
||||
import DeviceOverview from "device/DeviceOverview";
|
||||
import { DeviceAvailabilityMap, FindAvailablePositions, OffsetAvailabilityMap } from "pbHelpers/DeviceAvailability";
|
||||
import AddComponentManualDialog from "component/AddComponentManualDialog";
|
||||
import ComponentCard from "component/ComponentCard";
|
||||
import { sameComponentID, sortComponents } from "pbHelpers/Component";
|
||||
import { isController } from "pbHelpers/ComponentType";
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import {
|
|||
} from "hooks";
|
||||
import InteractionChip from "interactions/InteractionChip";
|
||||
import InteractionSettings from "interactions/InteractionSettings";
|
||||
import { cloneDeep } from "lodash";
|
||||
// import MaterialTable from "material-table";
|
||||
import { Component, Device, deviceScope, Group, Interaction } from "models";
|
||||
import { convertedUnitMeasurement, MeasurementsFor, UnitMeasurement } from "models/UnitMeasurement";
|
||||
|
|
@ -450,7 +451,6 @@ export default function DeviceComponent() {
|
|||
// });
|
||||
})
|
||||
.catch((err: any) => {
|
||||
|
||||
// resolve({
|
||||
// data: [],
|
||||
// page: 0,
|
||||
|
|
@ -613,6 +613,32 @@ export default function DeviceComponent() {
|
|||
pageSize={pageSize}
|
||||
setPage={setPage}
|
||||
handleRowsPerPageChange={handleRowsPerPageChange}
|
||||
loadMore={() => {
|
||||
let currentRows = cloneDeep(rows)
|
||||
let newOffset = rows.length
|
||||
componentAPI.listUnitMeasurements(
|
||||
deviceID,
|
||||
componentID,
|
||||
startDate,
|
||||
endDate,
|
||||
pageSize,
|
||||
newOffset,
|
||||
order,
|
||||
undefined,
|
||||
getContextKeys(),
|
||||
getContextTypes(),
|
||||
showErrors,
|
||||
as)
|
||||
.then(resp => {
|
||||
let newRows = UnitMeasurement.convertMeasurements(
|
||||
resp.data.measurements.map(um => UnitMeasurement.any(um, user))
|
||||
)
|
||||
setRows(currentRows.concat(newRows))
|
||||
}).catch(err => {
|
||||
|
||||
})
|
||||
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -301,6 +301,9 @@ export default function DeviceSupport() {
|
|||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLUE}>
|
||||
V2 Cellular Blue
|
||||
</MenuItem>
|
||||
<MenuItem value={pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE}>
|
||||
V2 Ethernet Blue
|
||||
</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<Button color="primary" onClick={() => updateDevicePlatform(platform)}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { DeveloperBoard as ProvisionIcon, LibraryAdd as CreateGroupIcon } from "@mui/icons-material";
|
||||
import { Box, Chip, Grid2, IconButton, Skeleton, Tab, Tabs, Theme, Tooltip, Typography, useTheme } from "@mui/material";
|
||||
import { DeveloperBoard as ProvisionIcon, LibraryAdd as CreateGroupIcon, Tune } from "@mui/icons-material";
|
||||
import { Box, Checkbox, Chip, Grid2, IconButton, ListItemIcon, ListItemText, Menu, MenuItem, Skeleton, Tab, Tabs, Theme, Tooltip, Typography, useTheme } from "@mui/material";
|
||||
import { blue, green, orange } from "@mui/material/colors";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import ResponsiveTable, { Column } from "common/ResponsiveTable";
|
||||
|
|
@ -24,6 +24,9 @@ import { Tag as TagUI } from "common/Tag";
|
|||
import moment from "moment";
|
||||
import StatusPlenum from "common/StatusPlenum";
|
||||
import StatusSen5x from "common/StatusSen5x";
|
||||
import StatusDust from "common/StatusDust";
|
||||
import StatusGas from "common/StatusGas";
|
||||
import { cloneDeep } from "lodash";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
return ({
|
||||
|
|
@ -57,14 +60,14 @@ const useStyles = makeStyles((theme: Theme) => {
|
|||
margin: theme.spacing(1),
|
||||
marginLeft: theme.spacing(2),
|
||||
display: "flex",
|
||||
width: theme.spacing(32)
|
||||
// width: theme.spacing(26)
|
||||
// justifyContent: "center",
|
||||
},
|
||||
tagsCellContainer: {
|
||||
margin: theme.spacing(1),
|
||||
marginLeft: theme.spacing(2),
|
||||
display: "flex",
|
||||
width: theme.spacing(24)
|
||||
width: theme.spacing(18)
|
||||
// justifyContent: "center",
|
||||
},
|
||||
green: {
|
||||
|
|
@ -92,14 +95,40 @@ export default function Devices() {
|
|||
const [devicesLoading, setDevicesLoading] = useState(false)
|
||||
const [limit, setLimit] = useState(10);
|
||||
const [page, setPage] = useState(0);
|
||||
const [order, setOrder] = useState<"asc" | "desc">("asc");
|
||||
const [orderBy, setOrderBy] = useState("name");
|
||||
|
||||
const [order, setOrder] = useState<"asc" | "desc">(() => {
|
||||
// Load from sessionStorage on initial render
|
||||
const savedOrder = sessionStorage.getItem('order');
|
||||
return (savedOrder === "asc" || savedOrder === "desc") ? savedOrder : "asc";
|
||||
});
|
||||
|
||||
// Save to sessionStorage whenever order changes
|
||||
useEffect(() => {
|
||||
sessionStorage.setItem('order', order);
|
||||
}, [order]);
|
||||
|
||||
const [orderBy, setOrderBy] = useState(() => {
|
||||
// Load from sessionStorage on initial render
|
||||
const savedOrder = sessionStorage.getItem('orderBy');
|
||||
return (savedOrder && savedOrder?.length > 0) ? savedOrder : "name";
|
||||
});
|
||||
|
||||
// Save to sessionStorage whenever order changes
|
||||
useEffect(() => {
|
||||
sessionStorage.setItem('orderBy', orderBy);
|
||||
}, [orderBy]);
|
||||
|
||||
// const [orderBy, setOrderBy] = useState("name");
|
||||
const [search, setSearch] = useState("");
|
||||
const [total, setTotal] = useState(0);
|
||||
const [devices, setDevices] = useState<Device[]>([])
|
||||
const [isProvisionDialogOpen, setIsProvisionDialogOpen] = useState<boolean>(false);
|
||||
const [hasPlenums, setHasPlenums] = useState(false)
|
||||
const [hasSen5x, setHasSen5x] = useState(false)
|
||||
const [hasCo, setHasCo] = useState(false)
|
||||
const [hasCo2, setHasCo2] = useState(false)
|
||||
const [hasNo2, setHasNo2] = useState(false)
|
||||
const [hasO2, setHasO2] = useState(false)
|
||||
|
||||
const [groupsLoading, setGroupsLoading] = useState(false)
|
||||
const [groups, setGroups] = useState<Group[]>([]);
|
||||
|
|
@ -123,6 +152,26 @@ export default function Devices() {
|
|||
|
||||
const [fieldContains, setFieldContains] = useState<Map<string, string>>(new Map<string, string>())
|
||||
|
||||
const [separateDust, setSeparateDust] = useState(() => {
|
||||
const stored = localStorage.getItem('separateDust');
|
||||
return stored !== null ? stored === 'true' : false;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
localStorage.setItem('separateDust', separateDust.toString());
|
||||
}, [separateDust]);
|
||||
|
||||
const [groupGas, setGroupGas] = useState(() => {
|
||||
const stored = localStorage.getItem('groupGas');
|
||||
return stored !== null ? stored === 'true' : false;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
localStorage.setItem('groupGas', groupGas.toString());
|
||||
}, [groupGas]);
|
||||
|
||||
const [preferencesAnchor, setPreferencesAnchor] = useState<any>(null)
|
||||
|
||||
const [{ as }] = useGlobalState()
|
||||
|
||||
const updateGroups = (newGroups: Group[]) => {
|
||||
|
|
@ -250,12 +299,12 @@ export default function Devices() {
|
|||
).then(resp => {
|
||||
let newDevices: Device[] = []
|
||||
resp.data.devices.forEach(device => {
|
||||
if (device.status?.plenum?.temperature) {
|
||||
setHasPlenums(true)
|
||||
}
|
||||
if (device.status?.sen5x?.temperature) {
|
||||
setHasSen5x(true)
|
||||
}
|
||||
if (device.status?.plenum?.temperature) setHasPlenums(true)
|
||||
if (device.status?.sen5x?.temperature) setHasSen5x(true)
|
||||
if (device.status?.o2) setHasO2(true)
|
||||
if (device.status?.co) setHasCo(true)
|
||||
if (device.status?.co2) setHasCo2(true)
|
||||
if (device.status?.no2) setHasNo2(true)
|
||||
newDevices.push(Device.create(device))
|
||||
})
|
||||
setDevices(newDevices)
|
||||
|
|
@ -277,15 +326,40 @@ export default function Devices() {
|
|||
setLimit(event.target.value);
|
||||
};
|
||||
|
||||
const prependToUrl = (prependage: number | string) => {
|
||||
const basePath = location.pathname.replace(/\/$/, "");
|
||||
return(`/${prependage}/${basePath}`.replace(/\/{2,}/g, "/").replace(/(\/[^/]+)\/\1+/g, "$1"));
|
||||
};
|
||||
// const prependToUrl = (prependage: number | string) => {
|
||||
// const basePath = location.pathname.replace(/\/$/, "");
|
||||
// return(`/${prependage}/${basePath}`.replace(/\/{2,}/g, "/").replace(/(\/[^/]+)\/\1+/g, "$1"));
|
||||
// };
|
||||
|
||||
function insertGroupContext(groupID: string, deviceID: string): string {
|
||||
const path = location.pathname
|
||||
const segments = path.split('/').filter(Boolean);
|
||||
const deviceIndex = segments.findIndex(segment => segment === 'devices');
|
||||
|
||||
if (deviceIndex === -1) {
|
||||
throw new Error('Path does not contain "devices"');
|
||||
}
|
||||
|
||||
// Build the new segments
|
||||
const newSegments = [
|
||||
...segments.slice(0, deviceIndex),
|
||||
'groups',
|
||||
groupID,
|
||||
...segments.slice(deviceIndex),
|
||||
deviceID
|
||||
];
|
||||
|
||||
return '/' + newSegments.join('/');
|
||||
}
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log(devices)
|
||||
// }, [devices])
|
||||
|
||||
const toDevice = (device: Device) => {
|
||||
let url = prependToUrl(getGroup() ? "groups/" + getGroup().id() : "")
|
||||
url = url + "/" + device.id()
|
||||
navigate(url, { replace: true, state: {device: device} })
|
||||
let url = getGroup() ? insertGroupContext(getGroup().id().toString(), device.id().toString()) : ""
|
||||
if (url.length < 1) url = device.id().toString()
|
||||
navigate(url, { state: {device: device} })
|
||||
};
|
||||
|
||||
const handleTabChange = (_event: React.SyntheticEvent, newValue: string) => {
|
||||
|
|
@ -293,10 +367,6 @@ export default function Devices() {
|
|||
if (newValue === "never") openGroupSettings(undefined, "add");
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log(devices)
|
||||
}, [devices])
|
||||
|
||||
const columns = (): Column<Device>[] => {
|
||||
let columns: Column<Device>[] = [
|
||||
{
|
||||
|
|
@ -338,12 +408,13 @@ export default function Devices() {
|
|||
title: "Description",
|
||||
render: (device: Device) => {
|
||||
const description = device.settings?.description ?? ""
|
||||
let size = (hasCo2 && !groupGas) ? 26 : 36
|
||||
return (
|
||||
<Box className={classes.descriptionCellContainer}>
|
||||
<Tooltip title={device.settings?.description}>
|
||||
<Box className={classes.descriptionCellContainer} width={size*6}>
|
||||
<Tooltip title={description}>
|
||||
<span>
|
||||
{description.length > 36
|
||||
? description.substring(0, 36) + "..."
|
||||
{description.length > size
|
||||
? description.substring(0, size) + "..."
|
||||
: description}
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
|
@ -396,7 +467,95 @@ export default function Devices() {
|
|||
if (device.status.sen5x?.temperature) {
|
||||
return (
|
||||
<Box sx={{ marginLeft: 1 }}>
|
||||
<StatusSen5x device={device} />
|
||||
<StatusSen5x device={device} noDust={separateDust} />
|
||||
</Box>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<></>
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
if (separateDust) columns.push({
|
||||
title: "Dust",
|
||||
render: (device: Device) => {
|
||||
if (device.status.sen5x?.temperature) {
|
||||
return (
|
||||
<Box sx={{ marginLeft: 1 }}>
|
||||
<StatusDust device={device} />
|
||||
</Box>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<></>
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if (hasCo) {
|
||||
columns.push({
|
||||
title: groupGas ? "Gas" : "CO",
|
||||
render: (device: Device) => {
|
||||
if (device.status.co) {
|
||||
return (
|
||||
<Box sx={{ marginLeft: 1 }}>
|
||||
<StatusGas device={device} gasType={groupGas ? "all" : "co"}/>
|
||||
</Box>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<></>
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if (hasCo2 && !groupGas) {
|
||||
columns.push({
|
||||
title: "CO2",
|
||||
render: (device: Device) => {
|
||||
if (device.status.co2) {
|
||||
return (
|
||||
<Box sx={{ marginLeft: 1 }}>
|
||||
<StatusGas device={device} gasType={"co2"}/>
|
||||
</Box>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<></>
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if (hasNo2 && !groupGas) {
|
||||
columns.push({
|
||||
title: "NO2",
|
||||
render: (device: Device) => {
|
||||
if (device.status.no2) {
|
||||
return (
|
||||
<Box sx={{ marginLeft: 1 }}>
|
||||
<StatusGas device={device} gasType={"no2"}/>
|
||||
</Box>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<></>
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if (hasO2 && !groupGas) {
|
||||
columns.push({
|
||||
title: "O2",
|
||||
render: (device: Device) => {
|
||||
if (device.status.o2) {
|
||||
return (
|
||||
<Box sx={{ marginLeft: 1 }}>
|
||||
<StatusGas device={device} gasType={"o2"}/>
|
||||
</Box>
|
||||
)
|
||||
} else {
|
||||
|
|
@ -499,6 +658,51 @@ export default function Devices() {
|
|||
)
|
||||
}
|
||||
|
||||
const preferencesButton = () => {
|
||||
return (
|
||||
<IconButton onClick={(event) => setPreferencesAnchor(event.currentTarget)}>
|
||||
<Tune />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
|
||||
const preferencesMenu = () => {
|
||||
return (
|
||||
<Menu
|
||||
id="userMenu"
|
||||
anchorEl={preferencesAnchor}
|
||||
open={preferencesAnchor !== null}
|
||||
onClose={() => setPreferencesAnchor(null)}
|
||||
disableAutoFocusItem>
|
||||
<MenuItem
|
||||
onClick={() => setSeparateDust(!separateDust)}
|
||||
sx={{ marginLeft: -0.75 }}
|
||||
dense
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Checkbox
|
||||
checked={!separateDust}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={"Group Dust"} />
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => setGroupGas(!groupGas)}
|
||||
sx={{ marginLeft: -0.75 }}
|
||||
dense
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Checkbox
|
||||
checked={groupGas}
|
||||
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={"Group Gas"} />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
)
|
||||
}
|
||||
|
||||
return(
|
||||
<PageContainer padding={isMobile ? 0 : 2}>
|
||||
<Box
|
||||
|
|
@ -548,6 +752,42 @@ export default function Devices() {
|
|||
setOrder={setOrder}
|
||||
orderBy={orderBy}
|
||||
setOrderBy={setOrderBy}
|
||||
endTitleElement={preferencesButton}
|
||||
loadMore={()=>{
|
||||
let currentRows = cloneDeep(devices)
|
||||
deviceAPI.list(
|
||||
limit,
|
||||
currentRows.length,
|
||||
order,
|
||||
orderBy,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
getKeys(),
|
||||
getTypes(),
|
||||
fieldContains,
|
||||
search,
|
||||
as
|
||||
).then(resp => {
|
||||
let newDevices: Device[] = []
|
||||
resp.data.devices.forEach(device => {
|
||||
if (device.status?.plenum?.temperature) setHasPlenums(true)
|
||||
if (device.status?.sen5x?.temperature) setHasSen5x(true)
|
||||
if (device.status?.o2) setHasO2(true)
|
||||
if (device.status?.co) setHasCo(true)
|
||||
if (device.status?.co2) setHasCo2(true)
|
||||
if (device.status?.no2) setHasNo2(true)
|
||||
newDevices.push(Device.create(device))
|
||||
})
|
||||
setDevices(currentRows.concat(newDevices))
|
||||
}).catch(err => {
|
||||
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<ProvisionDevice
|
||||
isOpen={isProvisionDialogOpen}
|
||||
|
|
@ -566,6 +806,7 @@ export default function Devices() {
|
|||
removeGroupCallback={removeGroupCallback}
|
||||
addGroupCallback={addGroupCallback}
|
||||
/>
|
||||
{preferencesMenu()}
|
||||
</PageContainer>
|
||||
)
|
||||
}
|
||||
|
|
@ -339,6 +339,7 @@ export default function Gate(props: Props) {
|
|||
}}
|
||||
style={{ height: 150, width: "100%", margin: -15 }}>
|
||||
<Grid
|
||||
width="100%"
|
||||
container
|
||||
direction="row"
|
||||
spacing={2}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ export function dragerGasDongle(subtype: number = 0): ComponentTypeExtension {
|
|||
key: quack.DragerGasDongleSubtype.DRAGER_GAS_DONGLE_SUBTYPE_H2S,
|
||||
value: "DRAGER_GAS_DONGLE_SUBTYPE_H2S",
|
||||
friendlyName: "Drager Gas H2S"
|
||||
},
|
||||
{
|
||||
key: quack.DragerGasDongleSubtype.DRAGER_GAS_DONGLE_SUBTYPE_LEL,
|
||||
value: "DRAGER_GAS_DONGLE_SUBTYPE_LEL",
|
||||
friendlyName: "Drager Gas LEL"
|
||||
}
|
||||
],
|
||||
friendlyName: "Drager Gas",
|
||||
|
|
@ -162,7 +167,8 @@ export function dragerGasDongle(subtype: number = 0): ComponentTypeExtension {
|
|||
lines: [],
|
||||
average: []
|
||||
};
|
||||
if (subtype === quack.DragerGasDongleSubtype.DRAGER_GAS_DONGLE_SUBTYPE_O2) {
|
||||
//sets the value as a percent for the chart data
|
||||
if (subtype === quack.DragerGasDongleSubtype.DRAGER_GAS_DONGLE_SUBTYPE_O2 || subtype === quack.DragerGasDongleSubtype.DRAGER_GAS_DONGLE_SUBTYPE_LEL) {
|
||||
let firstTime: Moment | undefined;
|
||||
let lastTime: Moment | undefined;
|
||||
let valMap: Map<number, number[]> = new Map<number, number[]>();
|
||||
|
|
|
|||
|
|
@ -45,6 +45,11 @@ export function Pressure(subtype: number = 0): ComponentTypeExtension {
|
|||
key: quack.PressureSubtype.PRESSURE_SUBTYPE_FROG,
|
||||
value: "PRESSURE_SUBTYPE_FROG",
|
||||
friendlyName: "Pressure (Frog)"
|
||||
} as Subtype,
|
||||
{
|
||||
key: quack.PressureSubtype.PRESSURE_SUBTYPE_DIFFERENTIAL_PRESSURE,
|
||||
value: "PRESSURE_SUBTYPE_DIFFERENTIAL_PRESSURE",
|
||||
friendlyName: "Pressure Differential"
|
||||
} as Subtype
|
||||
],
|
||||
friendlyName: "Pressure",
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ function getTooltip(platform: pond.DevicePlatform): string {
|
|||
case pond.DevicePlatform.DEVICE_PLATFORM_PHOTON ||
|
||||
pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_S3:
|
||||
return "Communicates via Wi-Fi";
|
||||
case pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE:
|
||||
return "Communicates view Ethernet"
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ import {
|
|||
SignalCellular4Bar,
|
||||
SignalWifi4Bar,
|
||||
SignalCellularOff,
|
||||
SignalWifiOff
|
||||
SignalWifiOff,
|
||||
Cable,
|
||||
DoNotDisturb
|
||||
} from "@mui/icons-material";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
|
||||
|
|
@ -98,6 +100,15 @@ const V2_Wifi_Blue: DevicePlatformDescriber = {
|
|||
platformName: "v2wifiblue"
|
||||
};
|
||||
|
||||
const V2_Ethernet_Blue: DevicePlatformDescriber = {
|
||||
platform: pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE,
|
||||
label: "V2 Ethernet Blue",
|
||||
description: "Communicates via ethernet",
|
||||
icon: <Cable style={{ color: "#fff" }} />,
|
||||
offlineIcon: <DoNotDisturb style={{ color: "#fff" }} />,
|
||||
platformName: "v2ethernetblue"
|
||||
};
|
||||
|
||||
const map = new Map<pond.DevicePlatform, DevicePlatformDescriber>([
|
||||
[pond.DevicePlatform.DEVICE_PLATFORM_INVALID, Default],
|
||||
[pond.DevicePlatform.DEVICE_PLATFORM_PHOTON, Photon],
|
||||
|
|
@ -107,7 +118,8 @@ const map = new Map<pond.DevicePlatform, DevicePlatformDescriber>([
|
|||
[pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLACK, V2_Cell_Black],
|
||||
[pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_GREEN, V2_Cell_Green],
|
||||
[pond.DevicePlatform.DEVICE_PLATFORM_V2_CELLULAR_BLUE, V2_Cell_Blue],
|
||||
[pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE, V2_Wifi_Blue]
|
||||
[pond.DevicePlatform.DEVICE_PLATFORM_V2_WIFI_BLUE, V2_Wifi_Blue],
|
||||
[pond.DevicePlatform.DEVICE_PLATFORM_V2_ETHERNET_BLUE, V2_Ethernet_Blue]
|
||||
]);
|
||||
|
||||
export function getDevicePlatformDescriber(platform: pond.DevicePlatform): DevicePlatformDescriber {
|
||||
|
|
|
|||
|
|
@ -334,6 +334,7 @@ export class MeasurementDescriber {
|
|||
this.details.unit = "mV";
|
||||
break;
|
||||
case quack.DragerGasDongleSubtype.DRAGER_GAS_DONGLE_SUBTYPE_O2:
|
||||
case quack.DragerGasDongleSubtype.DRAGER_GAS_DONGLE_SUBTYPE_LEL:
|
||||
this.details.colour = blue["400"];
|
||||
this.details.decimals = 1;
|
||||
this.details.unit = "%";
|
||||
|
|
@ -342,7 +343,7 @@ export class MeasurementDescriber {
|
|||
mode: "toStored" | "toDisplay"
|
||||
): number => {
|
||||
if (mode === "toStored") {
|
||||
//for O2 dragers the display is in percentage so convert the percent to ppm
|
||||
//for O2/LEL dragers the display is in percentage so convert the percent to ppm
|
||||
return value * 10000;
|
||||
}
|
||||
return value / 10000;
|
||||
|
|
|
|||
|
|
@ -191,6 +191,38 @@ export const BindaptV2Automate: DeviceProductDescriber = {
|
|||
// ])
|
||||
};
|
||||
|
||||
export const StreamlineMonitor: DeviceProductDescriber = {
|
||||
product: pond.DeviceProduct.DEVICE_PRODUCT_STREAMLINE_MONITOR,
|
||||
label: "Streamline Monitor",
|
||||
icon: (_, theme?: "light" | "dark") => {
|
||||
return theme === "light" ? BindaptPlusDarkIcon : BindaptPlusLightIcon;
|
||||
},
|
||||
view: "controller",
|
||||
tabs: getBindaptTabs(),
|
||||
availability: BindaptV2MonitorAvailability
|
||||
//TODO not sure what the default address map for these should be yet
|
||||
// defaultAddressMap: new Map<string, string[]>([
|
||||
// ["plenum", ["9-2-64"]],
|
||||
// ["heatersFans", ["3-1-512"]] //refers to heaters and fans
|
||||
// ])
|
||||
};
|
||||
|
||||
export const StreamlineAutomate: DeviceProductDescriber = {
|
||||
product: pond.DeviceProduct.DEVICE_PRODUCT_STREAMLINE_AUTOMATE,
|
||||
label: "Streamline Automate",
|
||||
icon: (_, theme?: "light" | "dark") => {
|
||||
return theme === "light" ? BindaptPlusDarkIcon : BindaptPlusLightIcon;
|
||||
},
|
||||
view: "controller",
|
||||
tabs: getBindaptTabs(),
|
||||
availability: BindaptV2AutomateAvailability
|
||||
//TODO not sure what the default address map for these should be yet
|
||||
// defaultAddressMap: new Map<string, string[]>([
|
||||
// ["plenum", ["9-2-64"]],
|
||||
// ["heatersFans", ["3-1-512"]] //refers to heaters and fans
|
||||
// ])
|
||||
};
|
||||
|
||||
export function IsBindaptDevice(product?: pond.DeviceProduct): boolean {
|
||||
const bindaptProducts: pond.DeviceProduct[] = [
|
||||
pond.DeviceProduct.DEVICE_PRODUCT_BINDAPT_MINI,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ import {
|
|||
BindaptV2Automate,
|
||||
BinHalo,
|
||||
BinMonitor,
|
||||
BinUltimate
|
||||
BinUltimate,
|
||||
StreamlineMonitor,
|
||||
StreamlineAutomate
|
||||
} from "./Bindapt/BindaptDescriber";
|
||||
import { NexusST } from "./Nexus/NexusDescriber";
|
||||
import { MiPCAV2, OmniAir } from "./OmniAir/OmniAirDescriber";
|
||||
|
|
@ -19,6 +21,7 @@ import { ConfigurablePin } from "pbHelpers/AddressTypes";
|
|||
import { useTheme } from "@mui/material";
|
||||
import { Device } from "models";
|
||||
import { or } from "utils";
|
||||
import { MiVent, MiVentV2 } from "./MiVent/MiVentDescriber";
|
||||
|
||||
export type ProductTab = "components" | "presets";
|
||||
|
||||
|
|
@ -87,7 +90,11 @@ const DEVICE_PRODUCT_MAP = new Map<pond.DeviceProduct, DeviceProductDescriber>([
|
|||
[pond.DeviceProduct.DEVICE_PRODUCT_BINDAPT_PLUS_MOD, BindaptPlusMod],
|
||||
[pond.DeviceProduct.DEVICE_PRODUCT_BINDAPT_PLUS_PRO_MOD, BindaptPlusProMod],
|
||||
[pond.DeviceProduct.DEVICE_PRODUCT_BINDAPT_V2_MONITOR, BindaptV2Monitor],
|
||||
[pond.DeviceProduct.DEVICE_PRODUCT_BINDAPT_V2_AUTOMATE, BindaptV2Automate]
|
||||
[pond.DeviceProduct.DEVICE_PRODUCT_BINDAPT_V2_AUTOMATE, BindaptV2Automate],
|
||||
[pond.DeviceProduct.DEVICE_PRODUCT_MIVENT, MiVent],
|
||||
[pond.DeviceProduct.DEVICE_PRODUCT_MIVENT_V2, MiVentV2],
|
||||
[pond.DeviceProduct.DEVICE_PRODUCT_STREAMLINE_MONITOR, StreamlineMonitor],
|
||||
[pond.DeviceProduct.DEVICE_PRODUCT_STREAMLINE_AUTOMATE, StreamlineAutomate]
|
||||
]);
|
||||
|
||||
export function ListDeviceProductDescribers(): DeviceProductDescriber[] {
|
||||
|
|
|
|||
61
src/products/MiVent/MiVentAvailability.ts
Normal file
61
src/products/MiVent/MiVentAvailability.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import { ConfigurablePin } from "pbHelpers/AddressTypes";
|
||||
import { DeviceAvailabilityMap, DevicePositions } from "pbHelpers/DeviceAvailability";
|
||||
import { quack } from "protobuf-ts/pond";
|
||||
|
||||
const MiVentV1Pins: ConfigurablePin[] = [
|
||||
{ address: 4, label: "1" },
|
||||
{ address: 8, label: "2" },
|
||||
{ address: 16, label: "3" },
|
||||
{ address: 512, label: "C1" },
|
||||
{ address: 1024, label: "C2" }
|
||||
];
|
||||
|
||||
export const MiVentV1Availability: DeviceAvailabilityMap = new Map<
|
||||
quack.AddressType,
|
||||
DevicePositions
|
||||
>([
|
||||
[quack.AddressType.ADDRESS_TYPE_INVALID, []],
|
||||
[quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY, MiVentV1Pins],
|
||||
[
|
||||
quack.AddressType.ADDRESS_TYPE_I2C,
|
||||
new Map<quack.ComponentType, number[]>([
|
||||
[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]],
|
||||
[quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]],
|
||||
[quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]],
|
||||
[quack.ComponentType.COMPONENT_TYPE_AIRFLOW, [0x2a]]
|
||||
])
|
||||
],
|
||||
[quack.AddressType.ADDRESS_TYPE_POWER, [0]],
|
||||
[quack.AddressType.ADDRESS_TYPE_GPS, [0]],
|
||||
[quack.AddressType.ADDRESS_TYPE_MODEM, [0]]
|
||||
]);
|
||||
|
||||
/*---V2 Stuff starts here---*/
|
||||
|
||||
const MiVentV2Pins: ConfigurablePin[] = [
|
||||
{ address: 1, label: "1" },
|
||||
{ address: 2, label: "2" },
|
||||
{ address: 4, label: "3" },
|
||||
{ address: 256, label: "L1" },
|
||||
{ address: 512, label: "L2" }
|
||||
];
|
||||
|
||||
export const MiVentV2Availability: DeviceAvailabilityMap = new Map<
|
||||
quack.AddressType,
|
||||
DevicePositions
|
||||
>([
|
||||
[quack.AddressType.ADDRESS_TYPE_INVALID, []],
|
||||
[quack.AddressType.ADDRESS_TYPE_CONFIGURABLE_PIN_ARRAY, MiVentV2Pins],
|
||||
[
|
||||
quack.AddressType.ADDRESS_TYPE_I2C,
|
||||
new Map<quack.ComponentType, number[]>([
|
||||
[quack.ComponentType.COMPONENT_TYPE_PRESSURE, [0x18]],
|
||||
[quack.ComponentType.COMPONENT_TYPE_DHT, [0x40]],
|
||||
[quack.ComponentType.COMPONENT_TYPE_SEN5X, [0x69]],
|
||||
[quack.ComponentType.COMPONENT_TYPE_AIRFLOW, [0x2a]]
|
||||
])
|
||||
],
|
||||
[quack.AddressType.ADDRESS_TYPE_POWER, [0]],
|
||||
[quack.AddressType.ADDRESS_TYPE_GPS, [0]],
|
||||
[quack.AddressType.ADDRESS_TYPE_MODEM, [0]]
|
||||
]);
|
||||
29
src/products/MiVent/MiVentDescriber.ts
Normal file
29
src/products/MiVent/MiVentDescriber.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { DeviceProductDescriber } from "products/DeviceProduct";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import DeviceDarkIcon from "assets/products/Ag/device 1.png";
|
||||
import DeviceLightIcon from "assets/products/Ag/device 2.png";
|
||||
import { MiVentV1Availability, MiVentV2Availability } from "./MiVentAvailability";
|
||||
|
||||
export const MiVent: DeviceProductDescriber = {
|
||||
product: pond.DeviceProduct.DEVICE_PRODUCT_MIVENT,
|
||||
label: "MiVent V1",
|
||||
icon: (_, theme?: "light" | "dark") => {
|
||||
return theme === "light" ? DeviceDarkIcon : DeviceLightIcon;
|
||||
},
|
||||
view: "controller",
|
||||
tabs: ["components"],
|
||||
availability: MiVentV1Availability
|
||||
};
|
||||
|
||||
/*---V2 Stuff starts here---*/
|
||||
|
||||
export const MiVentV2: DeviceProductDescriber = {
|
||||
product: pond.DeviceProduct.DEVICE_PRODUCT_MIVENT_V2,
|
||||
label: "MiVent V2",
|
||||
icon: (_, theme?: "light" | "dark") => {
|
||||
return theme === "light" ? DeviceDarkIcon : DeviceLightIcon;
|
||||
},
|
||||
view: "controller",
|
||||
tabs: ["components"],
|
||||
availability: MiVentV2Availability
|
||||
};
|
||||
|
|
@ -1,14 +1,9 @@
|
|||
import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
|
||||
// import { useAuth } from "hooks";
|
||||
import moment from "moment";
|
||||
import { createContext, PropsWithChildren, useContext } from "react";
|
||||
// import BillingProvider from "./billing";
|
||||
// import GitlabProvider from "./gitlab";
|
||||
import PondProvider from "./pond/pond";
|
||||
import { useAuth0 } from "@auth0/auth0-react";
|
||||
import SnackbarProvider from "./Snackbar";
|
||||
// import SecurityProvider from "./security";
|
||||
// import { useAuth0 } from "@auth0/auth0-react";
|
||||
|
||||
interface IHTTPContext {
|
||||
get: <T>(url: string, spreadOptions?: AxiosRequestConfig) => Promise<AxiosResponse<T>>;
|
||||
|
|
@ -78,9 +73,7 @@ export default function HTTPProvider(props: Props) {
|
|||
}
|
||||
|
||||
function get<T>(url: string, spreadOptions?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
|
||||
if (isTokenExpired(token)) {
|
||||
loginWithRedirect()
|
||||
}
|
||||
if (isTokenExpired(token)) loginWithRedirect()
|
||||
return axios.get(url, {...defaultOptions(), ...spreadOptions});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -251,6 +251,47 @@ export default function TeamList() {
|
|||
isLoading={loading}
|
||||
renderGutter={isMobile ? renderGutter : undefined}
|
||||
hideKeys
|
||||
loadMore={() => {
|
||||
let current = cloneDeep(teams)
|
||||
setLoading(true);
|
||||
let newTeamPerms: Map<string | number, pond.Permission[]> = new Map();
|
||||
let newTeamPrefs: Map<string | number, pond.TeamPreferences> = new Map();
|
||||
let viewAs: string | undefined = as
|
||||
if (as === team.key()) {
|
||||
viewAs = undefined
|
||||
}
|
||||
teamAPI
|
||||
.listTeams(limit, current.length, undefined, "name", undefined, undefined, " ", search)
|
||||
.then(resp => {
|
||||
setTotal(resp.data.total ? resp.data.total : 0);
|
||||
let newTeams: Team[] = []
|
||||
resp.data.teams.forEach(team => {
|
||||
let u = viewAs ? viewAs : user.id();
|
||||
let t = Team.create(team)
|
||||
if (team.settings && u !== "") {
|
||||
userAPI
|
||||
.getUser(u, teamScope(team.settings.key))
|
||||
.then(resp => {
|
||||
newTeamPerms.set(t.key(), resp.permissions)
|
||||
newTeamPrefs.set(t.key(), resp.preferences)
|
||||
t.preferences = cloneDeep(resp.preferences)
|
||||
t.permissions = cloneDeep(resp.permissions)
|
||||
}).catch(() => {
|
||||
snackbar.error("Error loading teams.")
|
||||
})
|
||||
.finally(() => {
|
||||
setTeamPerms(newTeamPerms);
|
||||
setTeamPrefs(newTeamPrefs);
|
||||
});
|
||||
}
|
||||
newTeams.push(t)
|
||||
});
|
||||
setTeams(current.concat(newTeams));
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<TeamSettings
|
||||
teamDialogOpen={teamDialogOpen}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,20 @@ const baseTheme: ThemeOptions = {
|
|||
paper: '#f5f5f5',
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontFamily: [
|
||||
"Open Sans",
|
||||
"-apple-system",
|
||||
"BlinkMacSystemFont",
|
||||
'"Segoe UI"',
|
||||
'"Helvetica Neue"',
|
||||
"Arial",
|
||||
"sans-serif",
|
||||
'"Apple Color Emoji"',
|
||||
'"Segoe UI Emoji"',
|
||||
'"Segoe UI Symbol"'
|
||||
].join(",")
|
||||
}
|
||||
// Add other options if needed
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -73,14 +73,19 @@ export default function AccessObject(props: Props) {
|
|||
const [teamsTotal, setTeamsTotal] = useState<number>(0);
|
||||
const [devicesOffset, setDevicesOffset] = useState<number>(0);
|
||||
const [devicesTotal, setDevicesTotal] = useState<number>(0);
|
||||
const [prevAs, setPrevAs] = useState("")
|
||||
|
||||
const close = () => {
|
||||
|
||||
const close = (restoreAs?: boolean) => {
|
||||
if(restoreAs){
|
||||
dispatch({ key: "as", value: prevAs });
|
||||
}
|
||||
closeDialogCallback();
|
||||
};
|
||||
|
||||
const getAccess = (key: number | string, name: string, url: string, useImitation = false) => {
|
||||
user.settings.useTeam = false;
|
||||
dispatch({ key: "as", value: "" });
|
||||
//dispatch({ key: "as", value: "" });
|
||||
userAPI.updateUser(user.id(), user.protobuf()).then(() => {
|
||||
info("Will no longer view as team by default");
|
||||
permissionAPI
|
||||
|
|
@ -258,6 +263,12 @@ export default function AccessObject(props: Props) {
|
|||
|
||||
useEffect(() => {
|
||||
if (isOpen && (prevSearchValue !== searchValue || prevKind !== kind || isOpen !== prevOpen)) {
|
||||
//if the user is viewing as a team record who it was
|
||||
if(as){
|
||||
setPrevAs(as)
|
||||
}
|
||||
//change as so the user is viewing as themself
|
||||
dispatch({ key: "as", value: "" });
|
||||
load();
|
||||
}
|
||||
}, [
|
||||
|
|
@ -350,12 +361,12 @@ export default function AccessObject(props: Props) {
|
|||
return (
|
||||
<ResponsiveDialog
|
||||
open={isOpen}
|
||||
onClose={close}
|
||||
onClose={() => close(true)}
|
||||
aria-labelledby="access-object-dialog"
|
||||
fullScreen>
|
||||
<AppBar position="sticky">
|
||||
<Toolbar>
|
||||
<IconButton edge="start" color="inherit" onClick={close} aria-label="close">
|
||||
<IconButton edge="start" color="inherit" onClick={() => close(true)} aria-label="close">
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" noWrap>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue