From e174bd4ae182f3f4928d2999d913a3b6c22c74c3 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Sat, 4 May 2024 10:18:37 +0200 Subject: [PATCH] Use tabs to organize UI --- remote_frontend/src/App.tsx | 51 ++++++++++++++++--- remote_frontend/src/api/VMApi.ts | 27 ++++++++++ .../src/widgets/SectionContainer.tsx | 11 +--- .../src/widgets/SystemInfoWidget.tsx | 5 +- .../src/widgets/VirtualMachinesWidget.tsx | 24 ++++++++- 5 files changed, 100 insertions(+), 18 deletions(-) create mode 100644 remote_frontend/src/api/VMApi.ts diff --git a/remote_frontend/src/App.tsx b/remote_frontend/src/App.tsx index abf103d..3a39299 100644 --- a/remote_frontend/src/App.tsx +++ b/remote_frontend/src/App.tsx @@ -1,15 +1,34 @@ -import { makeStyles, typographyStyles } from "@fluentui/react-components"; +import { + Tab, + TabList, + makeStyles, + typographyStyles, +} from "@fluentui/react-components"; import { ServerApi } from "./api/ServerApi"; import { AuthRouteWidget } from "./routes/AuthRouteWidget"; import { AsyncWidget } from "./widgets/AsyncWidget"; import { MainMenu } from "./widgets/MainMenu"; import { SystemInfoWidget } from "./widgets/SystemInfoWidget"; import { VirtualMachinesWidget } from "./widgets/VirtualMachinesWidget"; +import { + DesktopFilled, + DesktopRegular, + Info12Filled, + Info12Regular, + InfoFilled, + InfoRegular, + bundleIcon, +} from "@fluentui/react-icons"; +import React from "react"; const useStyles = makeStyles({ title: typographyStyles.title2, }); +const InfoIcon = bundleIcon(InfoFilled, InfoRegular); + +const DesktopIcon = bundleIcon(DesktopFilled, DesktopRegular); + export function App() { return ( ("vm"); if (!ServerApi.Config.authenticated && !ServerApi.Config.disable_auth) return ; @@ -36,12 +56,31 @@ function AppInner(): React.ReactElement { margin: "50px auto", }} > -
- VirtWebRemote - + VirtWebRemote +
+ setTab(d.value as any)} + > + }> + Virtual machines + + }> + System info + + +
+ +
- - + {tab === "vm" && } + {tab === "info" && }
); } diff --git a/remote_frontend/src/api/VMApi.ts b/remote_frontend/src/api/VMApi.ts new file mode 100644 index 0000000..ce73b6b --- /dev/null +++ b/remote_frontend/src/api/VMApi.ts @@ -0,0 +1,27 @@ +import { APIClient } from "./ApiClient"; + +export interface VMInfo { + uiid: string; + name: string; + description?: string; + architecture: string; + memory: number; + number_vcpu: number; + can_get_state: boolean; + can_start: boolean; + can_shutdown: boolean; + can_kill: boolean; + can_reset: boolean; + can_suspend: boolean; + can_resume: boolean; + can_screenshot: boolean; +} + +export class VMApi { + /** + * Get the list of VM that can be managed by this console + */ + static async GetList(): Promise { + return (await APIClient.exec({ method: "GET", uri: "/vm/list" })).data; + } +} diff --git a/remote_frontend/src/widgets/SectionContainer.tsx b/remote_frontend/src/widgets/SectionContainer.tsx index 64ffc66..70e9a87 100644 --- a/remote_frontend/src/widgets/SectionContainer.tsx +++ b/remote_frontend/src/widgets/SectionContainer.tsx @@ -1,17 +1,10 @@ -import { makeStyles, typographyStyles } from "@fluentui/react-components"; import React from "react"; -const useStyles = makeStyles({ - title: typographyStyles.title3, -}); - export function SectionContainer( - p: React.PropsWithChildren<{ title: string }> + p: React.PropsWithChildren ): React.ReactElement { - const styles = useStyles(); return ( -
- {p.title} +
{p.children}
diff --git a/remote_frontend/src/widgets/SystemInfoWidget.tsx b/remote_frontend/src/widgets/SystemInfoWidget.tsx index 0f53a1b..258bc61 100644 --- a/remote_frontend/src/widgets/SystemInfoWidget.tsx +++ b/remote_frontend/src/widgets/SystemInfoWidget.tsx @@ -15,7 +15,7 @@ export function SystemInfoWidget(): React.ReactElement { }; return ( - + +

Load average: {status!.system.load_average.one}{" "} diff --git a/remote_frontend/src/widgets/VirtualMachinesWidget.tsx b/remote_frontend/src/widgets/VirtualMachinesWidget.tsx index 7e8145a..73dfadb 100644 --- a/remote_frontend/src/widgets/VirtualMachinesWidget.tsx +++ b/remote_frontend/src/widgets/VirtualMachinesWidget.tsx @@ -1,5 +1,27 @@ +import React from "react"; +import { VMApi, VMInfo } from "../api/VMApi"; import { SectionContainer } from "./SectionContainer"; +import { AsyncWidget } from "./AsyncWidget"; export function VirtualMachinesWidget(): React.ReactElement { - return TODO; + const [list, setList] = React.useState(); + const load = async () => { + setList(await VMApi.GetList()); + }; + + return ( + + } + /> + + ); +} + +function VirtualMachinesWidgetInner(p: { list: VMInfo[] }): React.ReactElement { + return <>build list of vms; }