update to the group setting for adding/removing devices

This commit is contained in:
csawatzky 2025-04-29 14:04:08 -06:00
parent 68ec1217c6
commit acbd49b907
2 changed files with 118 additions and 28 deletions

View file

@ -7,6 +7,7 @@ import {
DialogTitle, DialogTitle,
Divider, Divider,
Grid2, Grid2,
IconButton,
lighten, lighten,
List, List,
ListItem, ListItem,
@ -36,12 +37,23 @@ import { useGlobalState } from "providers";
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import RemoveGroup from "./RemoveGroup"; import RemoveGroup from "./RemoveGroup";
import { pond } from "protobuf-ts/pond"; import { pond } from "protobuf-ts/pond";
import { Add, Remove } from "@mui/icons-material";
const useStyles = makeStyles((theme: Theme) => { const useStyles = makeStyles((theme: Theme) => {
return ({ return ({
deviceListContainer: { deviceListContainer: {
marginBottom: theme.spacing(1) marginBottom: theme.spacing(1)
}, },
listTitle: {
fontSize: 20,
fontWeight: 650
},
listButton: {
cursor: "pointer",
"&:hover": {
backgroundColor: lighten(theme.palette.background.default, 0.25)
}
},
devicesList: { devicesList: {
overflow: "auto", overflow: "auto",
minHeight: "25vh", minHeight: "25vh",
@ -87,6 +99,7 @@ export default function GroupSettings(props: Props) {
const deviceAPI = useDeviceAPI(); const deviceAPI = useDeviceAPI();
const snackbar = useSnackbar() const snackbar = useSnackbar()
const [devices, setDevices] = useState<Device[]>([]); const [devices, setDevices] = useState<Device[]>([]);
const [nonGroupDevices, setNonGroupDevices] = useState<Device[]>([]);
const [group, setGroup] = useState<Group>(initialGroup ? Group.clone(initialGroup) : new Group()); const [group, setGroup] = useState<Group>(initialGroup ? Group.clone(initialGroup) : new Group());
const [isRemoveGroupOpen, setIsRemoveGroupOpen] = useState<boolean>( const [isRemoveGroupOpen, setIsRemoveGroupOpen] = useState<boolean>(
mode === "remove" ? true : false mode === "remove" ? true : false
@ -109,13 +122,14 @@ export default function GroupSettings(props: Props) {
const loadDevices = useCallback(() => { const loadDevices = useCallback(() => {
setLoadingDevices(true); setLoadingDevices(true);
//this lists the devices for the user/team viewing
deviceAPI deviceAPI
.list(1000000, 0, "asc") .list(1000000, 0, "asc")
.then((response: any) => { .then((response: any) => {
let rDevices: Device[] = response.data.devices let rDevices: Device[] = response.data.devices
? response.data.devices.map((device: any) => Device.any(device)) ? response.data.devices.map((device: any) => Device.any(device))
: []; : [];
//remove duplicates from the options
setDevices(rDevices); setDevices(rDevices);
}) })
.catch((_error: any) => { .catch((_error: any) => {
@ -124,6 +138,16 @@ export default function GroupSettings(props: Props) {
.finally(() => setLoadingDevices(false)); .finally(() => setLoadingDevices(false));
}, [deviceAPI, as]); }, [deviceAPI, as]);
useEffect(()=>{
let ungrouped: Device[] = []
devices.forEach(device => {
if(!groupDeviceNumbers.includes(device.id())){
ungrouped.push(device)
}
})
setNonGroupDevices(ungrouped)
},[groupDeviceNumbers, devices])
useEffect(() => { useEffect(() => {
if (prevInitialGroup !== initialGroup) { if (prevInitialGroup !== initialGroup) {
setGroup(initialGroup ? Group.clone(initialGroup) : new Group()); setGroup(initialGroup ? Group.clone(initialGroup) : new Group());
@ -317,27 +341,58 @@ export default function GroupSettings(props: Props) {
</ListItem> </ListItem>
</List> </List>
) : ( ) : (
<React.Fragment>
{groupDevices &&
<List dense className={classes.devicesList}> <List dense className={classes.devicesList}>
{filterDevices(deviceSearch, devices, []) {filterDevices(deviceSearch, groupDevices, [])
.sort((a, b: Device) => a.name().localeCompare(b.name())) .sort((a, b: Device) => a.name().localeCompare(b.name()))
.map(device => { .map(device => {
const label = `checkbox-list-secondary-label-${device.id()}`; const label = `checkbox-list-secondary-label-${device.id()}`;
return ( return (
<ListItem key={device.id()} onClick={() => changeDevices(device.id())}> <ListItem className={classes.listButton} key={device.id()} onClick={() => {
removeDevice(device.id())
}}>
<ListItemText id={label} primary={device.name()} /> <ListItemText id={label} primary={device.name()} />
<ListItemSecondaryAction> <ListItemSecondaryAction>
<Checkbox {/* <Checkbox
edge="end" edge="end"
onChange={() => changeDevices(device.id())} onChange={() => changeDevices(device.id())}
checked={group.settings.devices.includes(device.id())} checked={group.settings.devices.includes(device.id())}
inputProps={{ "aria-labelledby": label }} inputProps={{ "aria-labelledby": label }}
disabled={!canEdit} disabled={!canEdit}
/> /> */}
-
</ListItemSecondaryAction> </ListItemSecondaryAction>
</ListItem> </ListItem>
); );
})} })}
</List> </List>
}
<List dense className={classes.devicesList}>
{filterDevices(deviceSearch, nonGroupDevices, [])
.sort((a, b: Device) => a.name().localeCompare(b.name()))
.map(device => {
const label = `checkbox-list-secondary-label-${device.id()}`;
return (
<ListItem className={classes.listButton} key={device.id()} onClick={() => {
addDevice(device.id())
}}>
<ListItemText id={label} primary={device.name()} />
<ListItemSecondaryAction>
{/* <Checkbox
edge="end"
onChange={() => changeDevices(device.id())}
checked={group.settings.devices.includes(device.id())}
inputProps={{ "aria-labelledby": label }}
disabled={!canEdit}
/> */}
+
</ListItemSecondaryAction>
</ListItem>
);
})}
</List>
</React.Fragment>
)} )}
</Paper> </Paper>
); );
@ -383,16 +438,49 @@ export default function GroupSettings(props: Props) {
</ListItem> </ListItem>
</List> </List>
) : ( ) : (
<React.Fragment>
{groupDevices &&
<React.Fragment>
<Typography className={classes.listTitle}>Grouped Devices</Typography>
<List dense className={classes.devicesList}> <List dense className={classes.devicesList}>
{filterDevices(deviceSearch, devices, []) {filterDevices(deviceSearch, groupDevices, [])
.sort((a, b: Device) => a.name().localeCompare(b.name())) .sort((a, b: Device) => a.name().localeCompare(b.name()))
.map(device => { .map(device => {
const label = `checkbox-list-secondary-label-${device.id()}`; const label = `checkbox-list-secondary-label-${device.id()}`;
return ( return (
<ListItem key={device.id()} onClick={() => changeDevices(device.id())}> <ListItem className={classes.listButton} key={device.id()} onClick={() => {
removeDevice(device.id())
}}>
<ListItemText id={label} primary={device.name()} /> <ListItemText id={label} primary={device.name()} />
<ListItemSecondaryAction> <ListItemSecondaryAction>
<Checkbox {/* <Checkbox
edge="end"
onChange={() => changeDevices(device.id())}
checked={group.settings.devices.includes(device.id())}
inputProps={{ "aria-labelledby": label }}
disabled={!canEdit}
/> */}
<Remove />
</ListItemSecondaryAction>
</ListItem>
);
})}
</List>
</React.Fragment>
}
<Typography className={classes.listTitle}>Devices You Can Add</Typography>
<List dense className={classes.devicesList}>
{filterDevices(deviceSearch, nonGroupDevices, [])
.sort((a, b: Device) => a.name().localeCompare(b.name()))
.map(device => {
const label = `checkbox-list-secondary-label-${device.id()}`;
return (
<ListItem className={classes.listButton} key={device.id()} onClick={() => {
addDevice(device.id())
}}>
<ListItemText id={label} primary={device.name()} />
<ListItemSecondaryAction>
{/* <Checkbox
edge="end" edge="end"
onChange={(_, checked) => { onChange={(_, checked) => {
if (checked) addDevice(device.id()); if (checked) addDevice(device.id());
@ -402,12 +490,14 @@ export default function GroupSettings(props: Props) {
checked={groupDeviceNumbers.includes(device.id())} checked={groupDeviceNumbers.includes(device.id())}
inputProps={{ "aria-labelledby": label }} inputProps={{ "aria-labelledby": label }}
disabled={!canEdit} disabled={!canEdit}
/> /> */}
<Add />
</ListItemSecondaryAction> </ListItemSecondaryAction>
</ListItem> </ListItem>
); );
})} })}
</List> </List>
</React.Fragment>
)} )}
</Paper> </Paper>
); );

View file

@ -88,7 +88,7 @@ export default function GroupProvider(props: PropsWithChildren<Props>) {
const addDevice = (group: number, device: number) => { const addDevice = (group: number, device: number) => {
let url = "/groups/" + group + "/devices/" + device + "/add"; let url = "/groups/" + group + "/devices/" + device + "/add";
if (as) url = pondURL(url + as) if (as) url = url + "?as=" + as
return new Promise<AxiosResponse>((resolve, reject) => { return new Promise<AxiosResponse>((resolve, reject) => {
post(pondURL(url), group).then(resp => { post(pondURL(url), group).then(resp => {
return resolve(resp) return resolve(resp)
@ -100,7 +100,7 @@ export default function GroupProvider(props: PropsWithChildren<Props>) {
const removeDevice = (group: number, device: number) => { const removeDevice = (group: number, device: number) => {
let url = "/groups/" + group + "/devices/" + device + "/remove"; let url = "/groups/" + group + "/devices/" + device + "/remove";
if (as) url = pondURL(url + as) if (as) url = url + "?as=" + as
return new Promise<AxiosResponse>((resolve, reject) => { return new Promise<AxiosResponse>((resolve, reject) => {
post(pondURL(url), group).then(resp => { post(pondURL(url), group).then(resp => {
return resolve(resp) return resolve(resp)