merged gas status, pulled, updated staging proto
This commit is contained in:
commit
a1a4851fd9
8 changed files with 593 additions and 67 deletions
|
|
@ -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,8 @@ 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";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
return ({
|
||||
|
|
@ -100,6 +102,10 @@ export default function Devices() {
|
|||
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[]>([]);
|
||||
|
|
@ -122,6 +128,26 @@ export default function Devices() {
|
|||
const [groupSettingsIsOpen, setGroupSettingsIsOpen] = useState<boolean>(false);
|
||||
|
||||
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()
|
||||
|
||||
|
|
@ -250,12 +276,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 +303,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) => {
|
||||
|
|
@ -396,7 +447,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 +638,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 +732,7 @@ export default function Devices() {
|
|||
setOrder={setOrder}
|
||||
orderBy={orderBy}
|
||||
setOrderBy={setOrderBy}
|
||||
endTitleElement={preferencesButton}
|
||||
/>
|
||||
<ProvisionDevice
|
||||
isOpen={isProvisionDialogOpen}
|
||||
|
|
@ -566,6 +751,7 @@ export default function Devices() {
|
|||
removeGroupCallback={removeGroupCallback}
|
||||
addGroupCallback={addGroupCallback}
|
||||
/>
|
||||
{preferencesMenu()}
|
||||
</PageContainer>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue