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 VisibilityIcon from "@mui/icons-material/Visibility";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Button,
 | 
					  Button,
 | 
				
			||||||
@@ -14,15 +13,12 @@ import {
 | 
				
			|||||||
} from "@mui/material";
 | 
					} from "@mui/material";
 | 
				
			||||||
import { filesize } from "filesize";
 | 
					import { filesize } from "filesize";
 | 
				
			||||||
import React from "react";
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import { useNavigate } from "react-router-dom";
 | 
				
			||||||
import { VMApi, VMInfo } from "../api/VMApi";
 | 
					import { VMApi, VMInfo } from "../api/VMApi";
 | 
				
			||||||
import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
					import { AsyncWidget } from "../widgets/AsyncWidget";
 | 
				
			||||||
import { RouterLink } from "../widgets/RouterLink";
 | 
					import { RouterLink } from "../widgets/RouterLink";
 | 
				
			||||||
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
 | 
					import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
 | 
				
			||||||
import { VMStatusWidget } from "../widgets/vms/VMStatusWidget";
 | 
					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 {
 | 
					export function VMListRoute(): React.ReactElement {
 | 
				
			||||||
  const [list, setList] = React.useState<VMInfo[] | undefined>();
 | 
					  const [list, setList] = React.useState<VMInfo[] | undefined>();
 | 
				
			||||||
@@ -66,39 +62,8 @@ function VMListWidget(p: {
 | 
				
			|||||||
  list: VMInfo[];
 | 
					  list: VMInfo[];
 | 
				
			||||||
  onReload: () => void;
 | 
					  onReload: () => void;
 | 
				
			||||||
}): React.ReactElement {
 | 
					}): React.ReactElement {
 | 
				
			||||||
  const confirm = useConfirm();
 | 
					 | 
				
			||||||
  const alert = useAlert();
 | 
					 | 
				
			||||||
  const snackbar = useSnackbar();
 | 
					 | 
				
			||||||
  const navigate = useNavigate();
 | 
					  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 (
 | 
					  return (
 | 
				
			||||||
    <TableContainer component={Paper}>
 | 
					    <TableContainer component={Paper}>
 | 
				
			||||||
      <Table>
 | 
					      <Table>
 | 
				
			||||||
@@ -135,11 +100,6 @@ function VMListWidget(p: {
 | 
				
			|||||||
                    </IconButton>
 | 
					                    </IconButton>
 | 
				
			||||||
                  </RouterLink>
 | 
					                  </RouterLink>
 | 
				
			||||||
                </Tooltip>
 | 
					                </Tooltip>
 | 
				
			||||||
                <Tooltip title="Delete this VM">
 | 
					 | 
				
			||||||
                  <IconButton onClick={() => deleteVM(row)}>
 | 
					 | 
				
			||||||
                    <DeleteIcon />
 | 
					 | 
				
			||||||
                  </IconButton>
 | 
					 | 
				
			||||||
                </Tooltip>
 | 
					 | 
				
			||||||
              </TableCell>
 | 
					              </TableCell>
 | 
				
			||||||
            </TableRow>
 | 
					            </TableRow>
 | 
				
			||||||
          ))}
 | 
					          ))}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { Grid } from "@mui/material";
 | 
					import { Box, Button, Grid, Tab, Tabs } from "@mui/material";
 | 
				
			||||||
import React from "react";
 | 
					import React from "react";
 | 
				
			||||||
import { validate as validateUUID } from "uuid";
 | 
					import { validate as validateUUID } from "uuid";
 | 
				
			||||||
import { IsoFile, IsoFilesApi } from "../../api/IsoFilesApi";
 | 
					import { IsoFile, IsoFilesApi } from "../../api/IsoFilesApi";
 | 
				
			||||||
@@ -16,6 +16,10 @@ import { ResAutostartInput } from "../forms/ResAutostartInput";
 | 
				
			|||||||
import { VMNetworksList } from "../forms/VMNetworksList";
 | 
					import { VMNetworksList } from "../forms/VMNetworksList";
 | 
				
			||||||
import { NetworkApi, NetworkInfo } from "../../api/NetworksApi";
 | 
					import { NetworkApi, NetworkInfo } from "../../api/NetworksApi";
 | 
				
			||||||
import { NWFilterApi, NWFilter } from "../../api/NWFilterApi";
 | 
					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 {
 | 
					interface DetailsProps {
 | 
				
			||||||
  vm: VMInfo;
 | 
					  vm: VMInfo;
 | 
				
			||||||
@@ -59,14 +63,49 @@ export function VMDetails(p: DetailsProps): React.ReactElement {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function VMDetailsInner(
 | 
					enum VMTab {
 | 
				
			||||||
  p: DetailsProps & {
 | 
					  General = 0,
 | 
				
			||||||
 | 
					  Storage,
 | 
				
			||||||
 | 
					  Network,
 | 
				
			||||||
 | 
					  Danger,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DetailsInnerProps = DetailsProps & {
 | 
				
			||||||
  isoList: IsoFile[];
 | 
					  isoList: IsoFile[];
 | 
				
			||||||
  vcpuCombinations: number[];
 | 
					  vcpuCombinations: number[];
 | 
				
			||||||
  networksList: NetworkInfo[];
 | 
					  networksList: NetworkInfo[];
 | 
				
			||||||
  networkFiltersList: NWFilter[];
 | 
					  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} />}
 | 
				
			||||||
 | 
					    </>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
): React.ReactElement {
 | 
					
 | 
				
			||||||
 | 
					function VMDetailsTabGeneral(p: DetailsInnerProps): React.ReactElement {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Grid container spacing={2}>
 | 
					    <Grid container spacing={2}>
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -215,7 +254,13 @@ function VMDetailsInner(
 | 
				
			|||||||
          />
 | 
					          />
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
      </EditSection>
 | 
					      </EditSection>
 | 
				
			||||||
 | 
					    </Grid>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function VMDetailsTabStorage(p: DetailsInnerProps): React.ReactElement {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Grid container spacing={2}>
 | 
				
			||||||
      {/* Storage section */}
 | 
					      {/* Storage section */}
 | 
				
			||||||
      <EditSection title="Storage">
 | 
					      <EditSection title="Storage">
 | 
				
			||||||
        <VMSelectIsoInput
 | 
					        <VMSelectIsoInput
 | 
				
			||||||
@@ -229,7 +274,13 @@ function VMDetailsInner(
 | 
				
			|||||||
        />
 | 
					        />
 | 
				
			||||||
        <VMDisksList {...p} />
 | 
					        <VMDisksList {...p} />
 | 
				
			||||||
      </EditSection>
 | 
					      </EditSection>
 | 
				
			||||||
 | 
					    </Grid>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function VMDetailsTabNetwork(p: DetailsInnerProps): React.ReactElement {
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Grid container spacing={2}>
 | 
				
			||||||
      {/* Networks section */}
 | 
					      {/* Networks section */}
 | 
				
			||||||
      <EditSection title="Networks">
 | 
					      <EditSection title="Networks">
 | 
				
			||||||
        <VMNetworksList {...p} />
 | 
					        <VMNetworksList {...p} />
 | 
				
			||||||
@@ -237,3 +288,53 @@ function VMDetailsInner(
 | 
				
			|||||||
    </Grid>
 | 
					    </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