Start to build VM page

This commit is contained in:
2023-10-17 18:11:31 +02:00
parent fcf66e3e93
commit 62364594c9
8 changed files with 221 additions and 148 deletions

View File

@ -6,15 +6,16 @@ export function CheckboxInput(p: {
checked: boolean | undefined;
onValueChange: (v: boolean) => void;
}): React.ReactElement {
if (!p.editable && p.checked)
return <Typography variant="body2">{p.label}</Typography>;
//if (!p.editable && p.checked)
// return <Typography variant="body2">{p.label}</Typography>;
if (!p.editable) return <></>;
//if (!p.editable) return <></>;
return (
<FormControlLabel
control={
<Checkbox
disabled={!p.editable}
checked={p.checked}
onChange={(e) => p.onValueChange(e.target.checked)}
/>

View File

@ -8,16 +8,16 @@ export interface SelectOption {
export function SelectInput(p: {
value?: string;
editing: boolean;
editable: boolean;
label: string;
options: SelectOption[];
onValueChange: (o?: string) => void;
}): React.ReactElement {
if (!p.editing && !p.value) return <></>;
if (!p.editable && !p.value) return <></>;
if (!p.editing) {
if (!p.editable) {
const value = p.options.find((o) => o.value === p.value)?.label;
return <TextInput label={p.label} editable={p.editing} value={value} />;
return <TextInput label={p.label} editable={p.editable} value={value} />;
}
return (
<FormControl fullWidth variant="standard" style={{ marginBottom: "15px" }}>

View File

@ -0,0 +1,138 @@
import { Grid, Paper, Typography } from "@mui/material";
import { PropsWithChildren } from "react";
import { validate as validateUUID } from "uuid";
import { ServerApi } from "../../api/ServerApi";
import { VMInfo } from "../../api/VMApi";
import { CheckboxInput } from "../forms/CheckboxInput";
import { SelectInput } from "../forms/SelectInput";
import { TextInput } from "../forms/TextInput";
export function VMDetails(p: {
vm: VMInfo;
editable: boolean;
onChange?: () => void;
}): React.ReactElement {
return (
<Grid container spacing={2}>
{/* Metadata section */}
<EditSection title="Metadata">
<TextInput
label="Name"
editable={p.editable}
value={p.vm.name}
onValueChange={(v) => {
p.vm.name = v ?? "";
p.onChange?.();
}}
size={ServerApi.Config.constraints.name_size}
/>
<TextInput label="UUID" editable={false} value={p.vm.uuid} />
<TextInput
label="VM genid"
editable={p.editable}
value={p.vm.genid}
onValueChange={(v) => {
p.vm.genid = v;
p.onChange?.();
}}
checkValue={(v) => validateUUID(v)}
/>
<TextInput
label="Title"
editable={p.editable}
value={p.vm.title}
onValueChange={(v) => {
p.vm.title = v;
p.onChange?.();
}}
size={ServerApi.Config.constraints.title_size}
/>
<TextInput
label="Description"
editable={p.editable}
value={p.vm.description}
onValueChange={(v) => {
p.vm.description = v;
p.onChange?.();
}}
multiline={true}
/>
</EditSection>
{/* General section */}
<EditSection title="General">
<SelectInput
editable={p.editable}
label="CPU Architecture"
onValueChange={(v) => {
p.vm.architecture = v! as any;
p.onChange?.();
}}
value={p.vm.architecture}
options={[
{ label: "i686", value: "i686" },
{ label: "x86_64", value: "x86_64" },
]}
/>
<SelectInput
editable={p.editable}
label="Boot type"
onValueChange={(v) => {
p.vm.boot_type = v! as any;
p.onChange?.();
}}
value={p.vm.boot_type}
options={[
{ label: "UEFI with Secure Boot", value: "UEFISecureBoot" },
{ label: "UEFI", value: "UEFI" },
]}
/>
<TextInput
label="Memory (MB)"
editable={p.editable}
type="number"
value={p.vm.memory.toString()}
onValueChange={(v) => {
p.vm.memory = Number(v ?? "0");
p.onChange?.();
}}
checkValue={(v) =>
Number(v) > ServerApi.Config.constraints.memory_size.min &&
Number(v) < ServerApi.Config.constraints.memory_size.max
}
/>
<CheckboxInput
editable={p.editable}
label="Enable VNC access"
checked={p.vm.vnc_access}
onValueChange={(v) => {
p.vm.vnc_access = v;
p.onChange?.();
}}
/>
</EditSection>
</Grid>
);
}
function EditSection(
p: { title: string } & PropsWithChildren
): React.ReactElement {
return (
<Grid item sm={12} md={6}>
<Paper style={{ margin: "10px", padding: "10px" }}>
<Typography variant="h5" style={{ marginBottom: "15px" }}>
{p.title}
</Typography>
{p.children}
</Paper>
</Grid>
);
}

View File

@ -11,7 +11,7 @@ import { useConfirm } from "../../hooks/providers/ConfirmDialogProvider";
import { useSnackbar } from "../../hooks/providers/SnackbarProvider";
export function VMStatusWidget(p: {
d: VMInfo;
vm: VMInfo;
onChange?: (s: VMState) => void;
}): React.ReactElement {
const snackbar = useSnackbar();
@ -20,7 +20,7 @@ export function VMStatusWidget(p: {
const refresh = async () => {
try {
const s = await VMApi.GetState(p.d);
const s = await VMApi.GetState(p.vm);
if (s !== state) p.onChange?.(s);
setState(s);
} catch (e) {
@ -32,6 +32,7 @@ export function VMStatusWidget(p: {
const changedAction = () => setState(undefined);
React.useEffect(() => {
refresh();
const i = setInterval(() => refresh(), 3000);
return () => clearInterval(i);
@ -54,7 +55,7 @@ export function VMStatusWidget(p: {
cond={["Shutdown", "Shutoff", "Crashed"]}
icon={<PlayArrowIcon />}
tooltip="Start the Virtual Machine"
performAction={() => VMApi.StartVM(p.d)}
performAction={() => VMApi.StartVM(p.vm)}
onExecuted={changedAction}
/>
@ -64,7 +65,7 @@ export function VMStatusWidget(p: {
cond={["Paused", "PowerManagementSuspended"]}
icon={<PlayArrowIcon />}
tooltip="Resume the Virtual Machine"
performAction={() => VMApi.ResumeVM(p.d)}
performAction={() => VMApi.ResumeVM(p.vm)}
onExecuted={changedAction}
/>
@ -75,7 +76,7 @@ export function VMStatusWidget(p: {
icon={<PauseIcon />}
tooltip="Suspend the Virtual Machine"
confirmMessage="Do you really want to supsend this VM?"
performAction={() => VMApi.SuspendVM(p.d)}
performAction={() => VMApi.SuspendVM(p.vm)}
onExecuted={changedAction}
/>
@ -86,7 +87,7 @@ export function VMStatusWidget(p: {
icon={<PowerSettingsNewIcon />}
tooltip="Shutdown the Virtual Machine"
confirmMessage="Do you really want to shutdown this VM?"
performAction={() => VMApi.ShutdownVM(p.d)}
performAction={() => VMApi.ShutdownVM(p.vm)}
onExecuted={changedAction}
/>
@ -97,7 +98,7 @@ export function VMStatusWidget(p: {
icon={<StopIcon />}
tooltip="Kill the Virtual Machine"
confirmMessage="Do you really want to kill this VM? This could lead to data loss / corruption!"
performAction={() => VMApi.KillVM(p.d)}
performAction={() => VMApi.KillVM(p.vm)}
onExecuted={changedAction}
/>
@ -108,7 +109,7 @@ export function VMStatusWidget(p: {
icon={<ReplayIcon />}
tooltip="Reset the Virtual Machine"
confirmMessage="Do you really want to reset this VM?"
performAction={() => VMApi.ResetVM(p.d)}
performAction={() => VMApi.ResetVM(p.vm)}
onExecuted={changedAction}
/>
</div>