diff --git a/virtweb_frontend/src/routes/VMListRoute.tsx b/virtweb_frontend/src/routes/VMListRoute.tsx index 51fc453..4b549aa 100644 --- a/virtweb_frontend/src/routes/VMListRoute.tsx +++ b/virtweb_frontend/src/routes/VMListRoute.tsx @@ -1,3 +1,5 @@ +import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; +import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; import VisibilityIcon from "@mui/icons-material/Visibility"; import { Button, @@ -15,6 +17,7 @@ import { import { filesize } from "filesize"; import React from "react"; import { useNavigate } from "react-router-dom"; +import { GroupApi } from "../api/GroupApi"; import { VMApi, VMInfo, VMState } from "../api/VMApi"; import { AsyncWidget } from "../widgets/AsyncWidget"; import { RouterLink } from "../widgets/RouterLink"; @@ -22,11 +25,13 @@ import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer"; import { VMStatusWidget } from "../widgets/vms/VMStatusWidget"; export function VMListRoute(): React.ReactElement { + const [groups, setGroups] = React.useState>(); const [list, setList] = React.useState(); const loadKey = React.useRef(1); const load = async () => { + setGroups([undefined, ...(await GroupApi.GetList())]); setList(await VMApi.GetList()); }; @@ -52,7 +57,7 @@ export function VMListRoute(): React.ReactElement { } > - + )} /> @@ -60,13 +65,25 @@ export function VMListRoute(): React.ReactElement { } function VMListWidget(p: { + groups: Array; list: VMInfo[]; onReload: () => void; }): React.ReactElement { const navigate = useNavigate(); + const [hiddenGroups, setHiddenGroups] = React.useState< + Set + >(new Set()); + const [runningVMs, setRunningVMs] = React.useState>(new Set()); + const toggleHiddenGroup = (g: string | undefined) => { + if (hiddenGroups.has(g)) hiddenGroups.delete(g); + else hiddenGroups.add(g); + + setHiddenGroups(new Set([...hiddenGroups])); + }; + const updateVMState = (v: VMInfo, s: VMState) => { const running = s !== "Shutoff"; if (runningVMs.has(v.name) === running) { @@ -93,35 +110,58 @@ function VMListWidget(p: { - {p.list.map((row) => ( - navigate(row.ViewURL)} - > - - {row.name} - - {row.description ?? ""} - {vmMemoryToHuman(row.memory)} - {row.number_vcpu} - - updateVMState(row, s)} - /> - - - - - - - - - - - + {p.groups.map((g, num) => ( + + + + toggleHiddenGroup(g)}> + {!hiddenGroups?.has(g) ? ( + + ) : ( + + )} + + {g ?? "default"} + + + + {!hiddenGroups.has(g) && + p.list + .filter((row) => row.group === g) + .map((row) => ( + navigate(row.ViewURL)} + > + + {row.name} + + {row.description ?? ""} + {vmMemoryToHuman(row.memory)} + {row.number_vcpu} + + updateVMState(row, s)} + /> + + + + + + + + + + + + ))} + ))}