Sort VM by groups in VM list
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		@@ -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 VisibilityIcon from "@mui/icons-material/Visibility";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Button,
 | 
					  Button,
 | 
				
			||||||
@@ -15,6 +17,7 @@ import {
 | 
				
			|||||||
import { filesize } from "filesize";
 | 
					import { filesize } from "filesize";
 | 
				
			||||||
import React from "react";
 | 
					import React from "react";
 | 
				
			||||||
import { useNavigate } from "react-router-dom";
 | 
					import { useNavigate } from "react-router-dom";
 | 
				
			||||||
 | 
					import { GroupApi } from "../api/GroupApi";
 | 
				
			||||||
import { VMApi, VMInfo, VMState } from "../api/VMApi";
 | 
					import { VMApi, VMInfo, VMState } from "../api/VMApi";
 | 
				
			||||||
import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
					import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
				
			||||||
import { RouterLink } from "../widgets/RouterLink";
 | 
					import { RouterLink } from "../widgets/RouterLink";
 | 
				
			||||||
@@ -22,11 +25,13 @@ import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
 | 
				
			|||||||
import { VMStatusWidget } from "../widgets/vms/VMStatusWidget";
 | 
					import { VMStatusWidget } from "../widgets/vms/VMStatusWidget";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function VMListRoute(): React.ReactElement {
 | 
					export function VMListRoute(): React.ReactElement {
 | 
				
			||||||
 | 
					  const [groups, setGroups] = React.useState<Array<string | undefined>>();
 | 
				
			||||||
  const [list, setList] = React.useState<VMInfo[] | undefined>();
 | 
					  const [list, setList] = React.useState<VMInfo[] | undefined>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const loadKey = React.useRef(1);
 | 
					  const loadKey = React.useRef(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const load = async () => {
 | 
					  const load = async () => {
 | 
				
			||||||
 | 
					    setGroups([undefined, ...(await GroupApi.GetList())]);
 | 
				
			||||||
    setList(await VMApi.GetList());
 | 
					    setList(await VMApi.GetList());
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,7 +57,7 @@ export function VMListRoute(): React.ReactElement {
 | 
				
			|||||||
            </>
 | 
					            </>
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          <VMListWidget list={list!} onReload={reload} />
 | 
					          <VMListWidget list={list!} groups={groups!} onReload={reload} />
 | 
				
			||||||
        </VirtWebRouteContainer>
 | 
					        </VirtWebRouteContainer>
 | 
				
			||||||
      )}
 | 
					      )}
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
@@ -60,13 +65,25 @@ export function VMListRoute(): React.ReactElement {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function VMListWidget(p: {
 | 
					function VMListWidget(p: {
 | 
				
			||||||
 | 
					  groups: Array<string | undefined>;
 | 
				
			||||||
  list: VMInfo[];
 | 
					  list: VMInfo[];
 | 
				
			||||||
  onReload: () => void;
 | 
					  onReload: () => void;
 | 
				
			||||||
}): React.ReactElement {
 | 
					}): React.ReactElement {
 | 
				
			||||||
  const navigate = useNavigate();
 | 
					  const navigate = useNavigate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [hiddenGroups, setHiddenGroups] = React.useState<
 | 
				
			||||||
 | 
					    Set<string | undefined>
 | 
				
			||||||
 | 
					  >(new Set());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [runningVMs, setRunningVMs] = React.useState<Set<string>>(new Set());
 | 
					  const [runningVMs, setRunningVMs] = React.useState<Set<string>>(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 updateVMState = (v: VMInfo, s: VMState) => {
 | 
				
			||||||
    const running = s !== "Shutoff";
 | 
					    const running = s !== "Shutoff";
 | 
				
			||||||
    if (runningVMs.has(v.name) === running) {
 | 
					    if (runningVMs.has(v.name) === running) {
 | 
				
			||||||
@@ -93,35 +110,58 @@ function VMListWidget(p: {
 | 
				
			|||||||
          </TableRow>
 | 
					          </TableRow>
 | 
				
			||||||
        </TableHead>
 | 
					        </TableHead>
 | 
				
			||||||
        <TableBody>
 | 
					        <TableBody>
 | 
				
			||||||
          {p.list.map((row) => (
 | 
					          {p.groups.map((g, num) => (
 | 
				
			||||||
            <TableRow
 | 
					            <React.Fragment key={num}>
 | 
				
			||||||
              hover
 | 
					              <TableRow>
 | 
				
			||||||
              key={row.name}
 | 
					                <TableCell
 | 
				
			||||||
              sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
 | 
					                  style={{ paddingBottom: 2, paddingTop: 2 }}
 | 
				
			||||||
              onDoubleClick={() => navigate(row.ViewURL)}
 | 
					                  colSpan={6}
 | 
				
			||||||
            >
 | 
					                >
 | 
				
			||||||
              <TableCell component="th" scope="row">
 | 
					                  <IconButton size="small" onClick={() => toggleHiddenGroup(g)}>
 | 
				
			||||||
                {row.name}
 | 
					                    {!hiddenGroups?.has(g) ? (
 | 
				
			||||||
              </TableCell>
 | 
					                      <KeyboardArrowUpIcon />
 | 
				
			||||||
              <TableCell>{row.description ?? ""}</TableCell>
 | 
					                    ) : (
 | 
				
			||||||
              <TableCell>{vmMemoryToHuman(row.memory)}</TableCell>
 | 
					                      <KeyboardArrowDownIcon />
 | 
				
			||||||
              <TableCell>{row.number_vcpu}</TableCell>
 | 
					                    )}
 | 
				
			||||||
              <TableCell>
 | 
					                  </IconButton>
 | 
				
			||||||
                <VMStatusWidget
 | 
					                  {g ?? "default"}
 | 
				
			||||||
                  vm={row}
 | 
					                </TableCell>
 | 
				
			||||||
                  onChange={(s) => updateVMState(row, s)}
 | 
					              </TableRow>
 | 
				
			||||||
                />
 | 
					
 | 
				
			||||||
              </TableCell>
 | 
					              {!hiddenGroups.has(g) &&
 | 
				
			||||||
              <TableCell>
 | 
					                p.list
 | 
				
			||||||
                <Tooltip title="View this VM">
 | 
					                  .filter((row) => row.group === g)
 | 
				
			||||||
                  <RouterLink to={row.ViewURL}>
 | 
					                  .map((row) => (
 | 
				
			||||||
                    <IconButton>
 | 
					                    <TableRow
 | 
				
			||||||
                      <VisibilityIcon />
 | 
					                      hover
 | 
				
			||||||
                    </IconButton>
 | 
					                      key={row.name}
 | 
				
			||||||
                  </RouterLink>
 | 
					                      sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
 | 
				
			||||||
                </Tooltip>
 | 
					                      onDoubleClick={() => navigate(row.ViewURL)}
 | 
				
			||||||
              </TableCell>
 | 
					                    >
 | 
				
			||||||
            </TableRow>
 | 
					                      <TableCell component="th" scope="row">
 | 
				
			||||||
 | 
					                        {row.name}
 | 
				
			||||||
 | 
					                      </TableCell>
 | 
				
			||||||
 | 
					                      <TableCell>{row.description ?? ""}</TableCell>
 | 
				
			||||||
 | 
					                      <TableCell>{vmMemoryToHuman(row.memory)}</TableCell>
 | 
				
			||||||
 | 
					                      <TableCell>{row.number_vcpu}</TableCell>
 | 
				
			||||||
 | 
					                      <TableCell>
 | 
				
			||||||
 | 
					                        <VMStatusWidget
 | 
				
			||||||
 | 
					                          vm={row}
 | 
				
			||||||
 | 
					                          onChange={(s) => updateVMState(row, s)}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                      </TableCell>
 | 
				
			||||||
 | 
					                      <TableCell>
 | 
				
			||||||
 | 
					                        <Tooltip title="View this VM">
 | 
				
			||||||
 | 
					                          <RouterLink to={row.ViewURL}>
 | 
				
			||||||
 | 
					                            <IconButton>
 | 
				
			||||||
 | 
					                              <VisibilityIcon />
 | 
				
			||||||
 | 
					                            </IconButton>
 | 
				
			||||||
 | 
					                          </RouterLink>
 | 
				
			||||||
 | 
					                        </Tooltip>
 | 
				
			||||||
 | 
					                      </TableCell>
 | 
				
			||||||
 | 
					                    </TableRow>
 | 
				
			||||||
 | 
					                  ))}
 | 
				
			||||||
 | 
					            </React.Fragment>
 | 
				
			||||||
          ))}
 | 
					          ))}
 | 
				
			||||||
        </TableBody>
 | 
					        </TableBody>
 | 
				
			||||||
        <TableFooter>
 | 
					        <TableFooter>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user