Improve VM screen
This commit is contained in:
parent
d4ef389852
commit
767d2015df
@ -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>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user