fix compilation of frontend

This commit is contained in:
Jörg Thalheim 2023-11-21 13:04:38 +01:00 committed by Mic92
parent 7afaaf8c5a
commit 48008c9b7f
5 changed files with 14 additions and 304 deletions

View File

@ -1,52 +1,17 @@
import { HTTPValidationError, VmConfig } from "@/api/model";
import { inspectVm } from "@/api/vm/vm";
import { HTTPValidationError } from "@/api/model";
import { AxiosError } from "axios";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
import { useState } from "react";
interface UseVmsOptions {
url: string;
attr: string;
}
export const useVms = (options: UseVmsOptions) => {
const { url, attr } = options;
const [isLoading, setIsLoading] = useState(true);
const [config, setConfig] = useState<VmConfig>();
const [error, setError] = useState<AxiosError<HTTPValidationError>>();
useEffect(() => {
const getVmInfo = async (url: string, attr: string) => {
if (url === "" || !url) {
toast.error("Flake url is missing", { id: "missing.flake.url" });
return undefined;
}
try {
const response = await inspectVm({
flake_attr: attr,
flake_url: url,
});
const {
data: { config },
} = response;
setError(undefined);
return config;
} catch (e) {
const err = e as AxiosError<HTTPValidationError>;
setError(err);
toast(
"Could not find default configuration. Please select a machine preset",
);
return undefined;
} finally {
setIsLoading(false);
}
};
getVmInfo(url, attr).then((c) => setConfig(c));
}, [url, attr]);
const [isLoading] = useState(true);
const [error] = useState<AxiosError<HTTPValidationError>>();
return {
error,
isLoading,
config,
};
};

View File

@ -1,159 +1,10 @@
import { useInspectFlakeAttrs } from "@/api/flake/flake";
import { FormValues } from "@/views/joinPrequel";
import {
Button,
InputAdornment,
LinearProgress,
ListSubheader,
MenuItem,
Select,
Switch,
TextField,
} from "@mui/material";
import { useEffect } from "react";
import { Controller, UseFormReturn } from "react-hook-form";
import { toast } from "react-hot-toast";
import { FlakeBadge } from "../flakeBadge/flakeBadge";
interface VmPropLabelProps {
children: React.ReactNode;
}
const VmPropLabel = (props: VmPropLabelProps) => (
<div className="col-span-4 flex items-center sm:col-span-1">
{props.children}
</div>
);
interface VmPropContentProps {
children: React.ReactNode;
}
const VmPropContent = (props: VmPropContentProps) => (
<div className="col-span-4 sm:col-span-3">{props.children}</div>
);
import { UseFormReturn } from "react-hook-form";
interface VmDetailsProps {
formHooks: UseFormReturn<FormValues, any, undefined>;
}
type ClanError = {
detail: {
msg: string;
loc: [];
}[];
};
export const ConfigureVM = (props: VmDetailsProps) => {
const { formHooks } = props;
const { control, watch, setValue, formState } = formHooks;
const { isLoading, data, error } = useInspectFlakeAttrs({
url: watch("flakeUrl"),
});
useEffect(() => {
if (!isLoading && data?.data) {
setValue("flake_attr", data.data.flake_attrs[0] || "");
}
}, [isLoading, setValue, data]);
if (error) {
const msg =
(error?.response?.data as unknown as ClanError)?.detail?.[0]?.msg ||
error.message;
toast.error(msg, {
id: error.name,
});
return <div>{msg}</div>;
}
return (
<div className="grid grid-cols-4 gap-y-10">
<div className="col-span-4">
<ListSubheader sx={{ bgcolor: "inherit" }}>General</ListSubheader>
</div>
<VmPropLabel>Flake</VmPropLabel>
<VmPropContent>
<FlakeBadge
flakeAttr={watch("flake_attr")}
flakeUrl={watch("flakeUrl")}
/>
</VmPropContent>
<VmPropLabel>Machine</VmPropLabel>
<VmPropContent>
{!isLoading && (
<Controller
name="flake_attr"
control={control}
defaultValue={data?.data.flake_attrs?.[0]}
render={({ field }) => (
<Select
{...field}
required
variant="standard"
fullWidth
disabled={isLoading}
>
{data?.data.flake_attrs.map((attr) => (
<MenuItem value={attr} key={attr}>
{attr}
</MenuItem>
))}
</Select>
)}
/>
)}
</VmPropContent>
<div className="col-span-4">
<ListSubheader sx={{ bgcolor: "inherit" }}>VM</ListSubheader>
</div>
<VmPropLabel>CPU Cores</VmPropLabel>
<VmPropContent>
<Controller
name="cores"
control={control}
render={({ field }) => <TextField type="number" {...field} />}
/>
</VmPropContent>
<VmPropLabel>Graphics</VmPropLabel>
<VmPropContent>
<Controller
name="graphics"
control={control}
render={({ field }) => (
<Switch {...field} defaultChecked={watch("graphics")} />
)}
/>
</VmPropContent>
<VmPropLabel>Memory Size</VmPropLabel>
<VmPropContent>
<Controller
name="memory_size"
control={control}
render={({ field }) => (
<TextField
type="number"
{...field}
InputProps={{
endAdornment: (
<InputAdornment position="end">MiB</InputAdornment>
),
}}
/>
)}
/>
</VmPropContent>
<div className="col-span-4 grid items-center">
{formState.isSubmitting && <LinearProgress />}
<Button
autoFocus
type="submit"
disabled={formState.isSubmitting}
variant="contained"
>
Join Clan
</Button>
</div>
</div>
);
return <div className="grid grid-cols-4 gap-y-10"></div>;
};

View File

@ -1,11 +1,4 @@
"use client";
import { useVms } from "@/components/hooks/useVms";
import { useEffect } from "react";
import { FormValues } from "@/views/joinPrequel";
import { useFormContext } from "react-hook-form";
import { ConfigureVM } from "./configureVM";
import { LoadingOverlay } from "./loadingOverlay";
interface ConfirmVMProps {
url: string;
@ -14,35 +7,7 @@ interface ConfirmVMProps {
}
export function ConfirmVM(props: ConfirmVMProps) {
const formHooks = useFormContext<FormValues>();
const { setValue, watch } = formHooks;
const url = watch("flakeUrl");
const attr = watch("flake_attr");
const { config, isLoading } = useVms({
url,
attr,
});
useEffect(() => {
if (config) {
setValue("cores", config?.cores);
setValue("memory_size", config?.memory_size);
setValue("graphics", config?.graphics);
}
}, [config, setValue]);
return (
<div className="mb-2 flex w-full max-w-2xl flex-col items-center justify-self-center pb-2">
<div className="mb-2 w-full max-w-2xl">
{isLoading && (
<LoadingOverlay title={"Loading VM Configuration"} subtitle="" />
)}
<ConfigureVM formHooks={formHooks} />
</div>
</div>
<div className="mb-2 flex w-full max-w-2xl flex-col items-center justify-self-center pb-2"></div>
);
}

View File

@ -1,8 +1,6 @@
"use client";
import { getGetVmLogsKey } from "@/api/vm/vm";
import axios from "axios";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { useState } from "react";
import { Log } from "./log";
interface VmBuildLogsProps {
@ -10,46 +8,9 @@ interface VmBuildLogsProps {
handleClose: () => void;
}
const streamLogs = async (
uuid: string,
setter: Dispatch<SetStateAction<string>>,
onFinish: () => void,
) => {
const apiPath = getGetVmLogsKey(uuid);
const baseUrl = axios.defaults.baseURL;
const response = await fetch(`${baseUrl}${apiPath}`);
const reader = response?.body?.getReader();
if (!reader) {
console.log("could not get reader");
}
while (true) {
const stream = await reader?.read();
if (!stream || stream.done) {
console.log("stream done");
onFinish();
break;
}
const text = new TextDecoder().decode(stream.value);
setter((s) => `${s}${text}`);
console.log("Received", stream.value);
console.log("String:", text);
}
};
export const VmBuildLogs = (props: VmBuildLogsProps) => {
const { vmUuid, handleClose } = props;
const [logs, setLogs] = useState<string>("");
const [done, setDone] = useState<boolean>(false);
// Reset the logs if uuid changes
useEffect(() => {
setLogs("");
setDone(false);
}, [vmUuid]);
!done && streamLogs(vmUuid, setLogs, () => setDone(true));
const { handleClose } = props;
const [logs] = useState<string>("");
return (
<div className="w-full">

View File

@ -1,18 +1,13 @@
"use client";
import { Button, Typography } from "@mui/material";
import { useSearchParams } from "next/navigation";
import { Suspense, useState } from "react";
import { Suspense } from "react";
import { VmConfig } from "@/api/model";
import { createVm } from "@/api/vm/vm";
import { Layout } from "@/components/join/layout";
import { VmBuildLogs } from "@/components/join/vmBuildLogs";
import { AxiosError } from "axios";
import { FormProvider, useForm } from "react-hook-form";
import { toast } from "react-hot-toast";
import { JoinForm } from "./joinForm";
export type FormValues = VmConfig & {
export type FormValues = {
flakeUrl: string;
dest?: string;
};
@ -27,17 +22,11 @@ export default function JoinPrequel() {
defaultValues: {
flakeUrl: "",
dest: undefined,
cores: 4,
graphics: true,
memory_size: 2048,
},
});
const { handleSubmit } = methods;
const [vmUuid, setVmUuid] = useState<string | null>(null);
const [showLogs, setShowLogs] = useState<boolean>(false);
return (
<Layout
header={
@ -51,33 +40,12 @@ export default function JoinPrequel() {
}
>
<Suspense fallback="Loading">
{vmUuid && showLogs ? (
<VmBuildLogs vmUuid={vmUuid} handleClose={() => setShowLogs(false)} />
) : (
{
<FormProvider {...methods}>
<form
onSubmit={handleSubmit(async (values) => {
console.log("JOINING");
console.log(values);
try {
const response = await createVm({
cores: values.cores,
flake_attr: values.flake_attr,
flake_url: values.flakeUrl,
graphics: values.graphics,
memory_size: values.memory_size,
});
const { uuid } = response?.data || null;
setShowLogs(true);
setVmUuid(() => uuid);
if (response.statusText === "OK") {
toast.success(("Joined @ " + uuid) as string);
} else {
toast.error("Could not join");
}
} catch (error) {
toast.error(`Error: ${(error as AxiosError).message || ""}`);
}
})}
className="w-full max-w-2xl justify-self-center"
>
@ -85,7 +53,7 @@ export default function JoinPrequel() {
<Button type="submit">Join</Button>
</form>
</FormProvider>
)}
}
</Suspense>
</Layout>
);