Improve VM screen
This commit is contained in:
		@@ -1,4 +1,3 @@
 | 
			
		||||
import DeleteIcon from "@mui/icons-material/Delete";
 | 
			
		||||
import VisibilityIcon from "@mui/icons-material/Visibility";
 | 
			
		||||
import {
 | 
			
		||||
  Button,
 | 
			
		||||
@@ -14,15 +13,12 @@ import {
 | 
			
		||||
} from "@mui/material";
 | 
			
		||||
import { filesize } from "filesize";
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { useNavigate } from "react-router-dom";
 | 
			
		||||
import { VMApi, VMInfo } from "../api/VMApi";
 | 
			
		||||
import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
			
		||||
import { RouterLink } from "../widgets/RouterLink";
 | 
			
		||||
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
 | 
			
		||||
import { VMStatusWidget } from "../widgets/vms/VMStatusWidget";
 | 
			
		||||
import { useSnackbar } from "../hooks/providers/SnackbarProvider";
 | 
			
		||||
import { useConfirm } from "../hooks/providers/ConfirmDialogProvider";
 | 
			
		||||
import { useNavigate } from "react-router-dom";
 | 
			
		||||
import { useAlert } from "../hooks/providers/AlertDialogProvider";
 | 
			
		||||
 | 
			
		||||
export function VMListRoute(): React.ReactElement {
 | 
			
		||||
  const [list, setList] = React.useState<VMInfo[] | undefined>();
 | 
			
		||||
@@ -66,39 +62,8 @@ function VMListWidget(p: {
 | 
			
		||||
  list: VMInfo[];
 | 
			
		||||
  onReload: () => void;
 | 
			
		||||
}): React.ReactElement {
 | 
			
		||||
  const confirm = useConfirm();
 | 
			
		||||
  const alert = useAlert();
 | 
			
		||||
  const snackbar = useSnackbar();
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  const deleteVM = async (v: VMInfo) => {
 | 
			
		||||
    try {
 | 
			
		||||
      if (
 | 
			
		||||
        !(await confirm(
 | 
			
		||||
          `Do you really want to delete the vm ${v.name}? The operation CANNOT be undone!`,
 | 
			
		||||
          "Delete a VM",
 | 
			
		||||
          "DELETE"
 | 
			
		||||
        ))
 | 
			
		||||
      )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      const keepData = !(await confirm(
 | 
			
		||||
        "Do you want to delete the files of the VM?",
 | 
			
		||||
        "Delete a VM",
 | 
			
		||||
        "Delete the data",
 | 
			
		||||
        "keep the data"
 | 
			
		||||
      ));
 | 
			
		||||
 | 
			
		||||
      await VMApi.Delete(v, keepData);
 | 
			
		||||
      snackbar("The VM was successfully deleted!");
 | 
			
		||||
 | 
			
		||||
      p.onReload();
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      console.error(e);
 | 
			
		||||
      alert(`Failed to delete VM!\n${e}`);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <TableContainer component={Paper}>
 | 
			
		||||
      <Table>
 | 
			
		||||
@@ -135,11 +100,6 @@ function VMListWidget(p: {
 | 
			
		||||
                    </IconButton>
 | 
			
		||||
                  </RouterLink>
 | 
			
		||||
                </Tooltip>
 | 
			
		||||
                <Tooltip title="Delete this VM">
 | 
			
		||||
                  <IconButton onClick={() => deleteVM(row)}>
 | 
			
		||||
                    <DeleteIcon />
 | 
			
		||||
                  </IconButton>
 | 
			
		||||
                </Tooltip>
 | 
			
		||||
              </TableCell>
 | 
			
		||||
            </TableRow>
 | 
			
		||||
          ))}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { Grid } from "@mui/material";
 | 
			
		||||
import { Box, Button, Grid, Tab, Tabs } from "@mui/material";
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { validate as validateUUID } from "uuid";
 | 
			
		||||
import { IsoFile, IsoFilesApi } from "../../api/IsoFilesApi";
 | 
			
		||||
@@ -16,6 +16,10 @@ import { ResAutostartInput } from "../forms/ResAutostartInput";
 | 
			
		||||
import { VMNetworksList } from "../forms/VMNetworksList";
 | 
			
		||||
import { NetworkApi, NetworkInfo } from "../../api/NetworksApi";
 | 
			
		||||
import { NWFilterApi, NWFilter } from "../../api/NWFilterApi";
 | 
			
		||||
import { useNavigate } from "react-router-dom";
 | 
			
		||||
import { useAlert } from "../../hooks/providers/AlertDialogProvider";
 | 
			
		||||
import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider";
 | 
			
		||||
import { useSnackbar } from "../../hooks/providers/SnackbarProvider";
 | 
			
		||||
 | 
			
		||||
interface DetailsProps {
 | 
			
		||||
  vm: VMInfo;
 | 
			
		||||
@@ -59,14 +63,49 @@ export function VMDetails(p: DetailsProps): React.ReactElement {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function VMDetailsInner(
 | 
			
		||||
  p: DetailsProps & {
 | 
			
		||||
    isoList: IsoFile[];
 | 
			
		||||
    vcpuCombinations: number[];
 | 
			
		||||
    networksList: NetworkInfo[];
 | 
			
		||||
    networkFiltersList: NWFilter[];
 | 
			
		||||
  }
 | 
			
		||||
): React.ReactElement {
 | 
			
		||||
enum VMTab {
 | 
			
		||||
  General = 0,
 | 
			
		||||
  Storage,
 | 
			
		||||
  Network,
 | 
			
		||||
  Danger,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type DetailsInnerProps = DetailsProps & {
 | 
			
		||||
  isoList: IsoFile[];
 | 
			
		||||
  vcpuCombinations: number[];
 | 
			
		||||
  networksList: NetworkInfo[];
 | 
			
		||||
  networkFiltersList: NWFilter[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function VMDetailsInner(p: DetailsInnerProps): React.ReactElement {
 | 
			
		||||
  const [currTab, setCurrTab] = React.useState(VMTab.General);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <Box sx={{ borderBottom: 1, borderColor: "divider" }}>
 | 
			
		||||
        <Tabs value={currTab} onChange={(_ev, newVal) => setCurrTab(newVal)}>
 | 
			
		||||
          <Tab label="General" tabIndex={VMTab.General} />
 | 
			
		||||
          <Tab label="Storage" tabIndex={VMTab.Storage} />
 | 
			
		||||
          <Tab label="Network" tabIndex={VMTab.Network} />
 | 
			
		||||
          {!p.editable && (
 | 
			
		||||
            <Tab
 | 
			
		||||
              label="Danger zone"
 | 
			
		||||
              style={{ color: "red" }}
 | 
			
		||||
              tabIndex={VMTab.Danger}
 | 
			
		||||
            />
 | 
			
		||||
          )}
 | 
			
		||||
        </Tabs>
 | 
			
		||||
      </Box>
 | 
			
		||||
 | 
			
		||||
      {currTab === VMTab.General && <VMDetailsTabGeneral {...p} />}
 | 
			
		||||
      {currTab === VMTab.Storage && <VMDetailsTabStorage {...p} />}
 | 
			
		||||
      {currTab === VMTab.Network && <VMDetailsTabNetwork {...p} />}
 | 
			
		||||
      {currTab === VMTab.Danger && <VMDetailsTabDanger {...p} />}
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function VMDetailsTabGeneral(p: DetailsInnerProps): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <Grid container spacing={2}>
 | 
			
		||||
      {
 | 
			
		||||
@@ -215,7 +254,13 @@ function VMDetailsInner(
 | 
			
		||||
          />
 | 
			
		||||
        )}
 | 
			
		||||
      </EditSection>
 | 
			
		||||
    </Grid>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function VMDetailsTabStorage(p: DetailsInnerProps): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <Grid container spacing={2}>
 | 
			
		||||
      {/* Storage section */}
 | 
			
		||||
      <EditSection title="Storage">
 | 
			
		||||
        <VMSelectIsoInput
 | 
			
		||||
@@ -229,7 +274,13 @@ function VMDetailsInner(
 | 
			
		||||
        />
 | 
			
		||||
        <VMDisksList {...p} />
 | 
			
		||||
      </EditSection>
 | 
			
		||||
    </Grid>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function VMDetailsTabNetwork(p: DetailsInnerProps): React.ReactElement {
 | 
			
		||||
  return (
 | 
			
		||||
    <Grid container spacing={2}>
 | 
			
		||||
      {/* Networks section */}
 | 
			
		||||
      <EditSection title="Networks">
 | 
			
		||||
        <VMNetworksList {...p} />
 | 
			
		||||
@@ -237,3 +288,53 @@ function VMDetailsInner(
 | 
			
		||||
    </Grid>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function VMDetailsTabDanger(p: DetailsInnerProps): React.ReactElement {
 | 
			
		||||
  const confirm = useConfirm();
 | 
			
		||||
  const alert = useAlert();
 | 
			
		||||
  const snackbar = useSnackbar();
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  const deleteVM = async () => {
 | 
			
		||||
    try {
 | 
			
		||||
      if (
 | 
			
		||||
        !(await confirm(
 | 
			
		||||
          `Do you really want to delete the vm ${p.vm.name}? The operation CANNOT be undone!`,
 | 
			
		||||
          "Delete a VM",
 | 
			
		||||
          "DELETE"
 | 
			
		||||
        ))
 | 
			
		||||
      )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      const keepData = !(await confirm(
 | 
			
		||||
        "Do you want to delete the files of the VM?",
 | 
			
		||||
        "Delete a VM",
 | 
			
		||||
        "Delete the data",
 | 
			
		||||
        "keep the data"
 | 
			
		||||
      ));
 | 
			
		||||
 | 
			
		||||
      if (
 | 
			
		||||
        !(await confirm(
 | 
			
		||||
          `[LAST CALL] Do you really want to procede with removal? Again, the operation CANNOT be undone!`,
 | 
			
		||||
          "Delete a VM",
 | 
			
		||||
          "DELETE"
 | 
			
		||||
        ))
 | 
			
		||||
      )
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      await VMApi.Delete(p.vm, keepData);
 | 
			
		||||
      snackbar("The VM was successfully deleted!");
 | 
			
		||||
 | 
			
		||||
      navigate("/vms");
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      console.error(e);
 | 
			
		||||
      alert(`Failed to delete VM!\n${e}`);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Button color="error" onClick={deleteVM}>
 | 
			
		||||
      Delete the VM
 | 
			
		||||
    </Button>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user