178 lines
4.4 KiB
TypeScript
178 lines
4.4 KiB
TypeScript
import { Button, Spinner, Toolbar, Tooltip } from "@fluentui/react-components";
|
|
import {
|
|
ArrowResetRegular,
|
|
PauseRegular,
|
|
PlayCircleRegular,
|
|
PlayFilled,
|
|
PowerRegular,
|
|
StopRegular,
|
|
} from "@fluentui/react-icons";
|
|
import React from "react";
|
|
import { GroupApi, TreatmentResult } from "../api/GroupApi";
|
|
import { VMGroup } from "../api/ServerApi";
|
|
import { VMInfo, VMState } from "../api/VMApi";
|
|
import { useAlert } from "../hooks/providers/AlertDialogProvider";
|
|
import { useConfirm } from "../hooks/providers/ConfirmDialogProvider";
|
|
import { useToast } from "../hooks/providers/ToastProvider";
|
|
|
|
export function GroupVMAction(p: {
|
|
group: VMGroup;
|
|
state?: VMState;
|
|
vm?: VMInfo;
|
|
}): React.ReactElement {
|
|
return (
|
|
<Toolbar>
|
|
<GroupVMButton
|
|
enabled={p.group.can_start}
|
|
icon={<PlayFilled />}
|
|
tooltip="Start"
|
|
group={p.group}
|
|
vm={p.vm}
|
|
allowedStates={["Shutdown", "Shutoff", "Crashed"]}
|
|
currState={p.state}
|
|
needConfirm={false}
|
|
action={GroupApi.StartVM}
|
|
/>
|
|
<GroupVMButton
|
|
enabled={p.group.can_suspend}
|
|
icon={<PauseRegular />}
|
|
tooltip="Suspend"
|
|
group={p.group}
|
|
vm={p.vm}
|
|
allowedStates={["Running"]}
|
|
currState={p.state}
|
|
needConfirm={true}
|
|
action={GroupApi.SuspendVM}
|
|
/>
|
|
<GroupVMButton
|
|
enabled={p.group.can_resume}
|
|
icon={<PlayCircleRegular />}
|
|
tooltip="Resume"
|
|
group={p.group}
|
|
vm={p.vm}
|
|
allowedStates={["Paused", "PowerManagementSuspended"]}
|
|
currState={p.state}
|
|
needConfirm={false}
|
|
action={GroupApi.ResumeVM}
|
|
/>
|
|
<GroupVMButton
|
|
enabled={p.group.can_shutdown}
|
|
icon={<PowerRegular />}
|
|
tooltip="Shutdown"
|
|
group={p.group}
|
|
vm={p.vm}
|
|
allowedStates={["Running"]}
|
|
currState={p.state}
|
|
needConfirm={true}
|
|
action={GroupApi.ShutdownVM}
|
|
/>
|
|
<GroupVMButton
|
|
enabled={p.group.can_kill}
|
|
icon={<StopRegular />}
|
|
tooltip="Kill"
|
|
group={p.group}
|
|
vm={p.vm}
|
|
allowedStates={[
|
|
"Running",
|
|
"Paused",
|
|
"PowerManagementSuspended",
|
|
"Blocked",
|
|
]}
|
|
currState={p.state}
|
|
needConfirm={true}
|
|
action={GroupApi.KillVM}
|
|
/>
|
|
<GroupVMButton
|
|
enabled={p.group.can_reset}
|
|
icon={<ArrowResetRegular />}
|
|
tooltip="Reset"
|
|
group={p.group}
|
|
vm={p.vm}
|
|
allowedStates={[
|
|
"Running",
|
|
"Paused",
|
|
"PowerManagementSuspended",
|
|
"Blocked",
|
|
]}
|
|
currState={p.state}
|
|
needConfirm={true}
|
|
action={GroupApi.ResetVM}
|
|
/>
|
|
</Toolbar>
|
|
);
|
|
}
|
|
|
|
function GroupVMButton(p: {
|
|
enabled: boolean;
|
|
icon: React.ReactElement;
|
|
action: (group: VMGroup, vm?: VMInfo) => Promise<TreatmentResult>;
|
|
tooltip: string;
|
|
currState?: VMState;
|
|
allowedStates: VMState[];
|
|
group: VMGroup;
|
|
vm?: VMInfo;
|
|
needConfirm: boolean;
|
|
}): React.ReactElement {
|
|
const toast = useToast();
|
|
const confirm = useConfirm();
|
|
const alert = useAlert();
|
|
|
|
const [running, setRunning] = React.useState(false);
|
|
|
|
const target = p.vm
|
|
? `the VM ${p.vm.name}`
|
|
: `all the VM of the group ${p.group.id}`;
|
|
|
|
const allowed =
|
|
!p.vm || (p.currState && p.allowedStates.includes(p.currState));
|
|
|
|
const perform = async () => {
|
|
if (running || !allowed) return;
|
|
try {
|
|
if (
|
|
(!p.vm || p.needConfirm) &&
|
|
!(await confirm(
|
|
`Do you want to perform ${p.tooltip} action on ${target}?`,
|
|
`Confirmation`,
|
|
p.tooltip
|
|
))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
setRunning(true);
|
|
|
|
const result = await p.action(p.group, p.vm);
|
|
|
|
toast(
|
|
p.tooltip,
|
|
`${p.tooltip} action on ${target}: ${result.ok} OK / ${result.failed} Failed`,
|
|
"success"
|
|
);
|
|
} catch (e) {
|
|
console.error("Failed to perform group action!", e);
|
|
|
|
alert(`Failed to perform ${p.tooltip} action on ${target}: ${e}`);
|
|
} finally {
|
|
setRunning(false);
|
|
}
|
|
};
|
|
|
|
if (!p.enabled) return <></>;
|
|
|
|
return (
|
|
<Tooltip
|
|
content={`${p.tooltip} ${target}`}
|
|
relationship="description"
|
|
withArrow
|
|
>
|
|
<Button
|
|
icon={running ? <Spinner size="tiny" /> : p.icon}
|
|
onClick={allowed ? perform : undefined}
|
|
disabled={!allowed}
|
|
appearance="subtle"
|
|
/>
|
|
</Tooltip>
|
|
);
|
|
}
|