From 837661582c9c4d1fc0e144eb5d37ed12930479c9 Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Mon, 20 Nov 2023 09:22:39 +0100 Subject: [PATCH] decompose join/create clan, move to manage page --- pkgs/ui/src/app/manage/create/page.tsx | 59 +++++++++ pkgs/ui/src/app/{ => manage}/join/page.tsx | 1 + pkgs/ui/src/app/manage/page.tsx | 11 ++ .../src/components/forms/createClan/index.tsx | 77 ++++++++++++ pkgs/ui/src/views/createForm.tsx | 56 --------- pkgs/ui/src/views/joinForm.tsx | 11 +- pkgs/ui/src/views/joinPrequel.tsx | 119 ++++-------------- 7 files changed, 179 insertions(+), 155 deletions(-) create mode 100644 pkgs/ui/src/app/manage/create/page.tsx rename pkgs/ui/src/app/{ => manage}/join/page.tsx (88%) create mode 100644 pkgs/ui/src/app/manage/page.tsx create mode 100644 pkgs/ui/src/components/forms/createClan/index.tsx delete mode 100644 pkgs/ui/src/views/createForm.tsx diff --git a/pkgs/ui/src/app/manage/create/page.tsx b/pkgs/ui/src/app/manage/create/page.tsx new file mode 100644 index 000000000..7c2f4ba6e --- /dev/null +++ b/pkgs/ui/src/app/manage/create/page.tsx @@ -0,0 +1,59 @@ +"use client"; +import { createFlake } from "@/api/flake/flake"; +import { HTTPValidationError } from "@/api/model"; +import { CreateClan, CreateFormValues } from "@/components/forms/createClan"; +import { clanErrorToast } from "@/error/errorToast"; +import { AxiosError } from "axios"; +import { FormProvider, useForm } from "react-hook-form"; + +export default function Manage() { + const methods = useForm({ + defaultValues: { + flakeDir: "", + flakeTemplateUrl: "", + }, + }); + const { handleSubmit } = methods; + return ( + +
{ + console.log({ values }); + try { + await createFlake( + { + url: values.flakeTemplateUrl, + }, + { + flake_dir: values.flakeDir, + } + ); + } catch (e) { + const error = e as AxiosError; + clanErrorToast(error); + const maybeDetail = error?.response?.data?.detail?.[0]; + + if (maybeDetail?.loc && maybeDetail?.msg) { + const urlError = error.response?.data.detail?.find((detail) => + detail.loc.includes("url") + ); + urlError && + methods.setError("flakeTemplateUrl", { + message: urlError.msg, + }); + const flakeDirError = error.response?.data.detail?.find( + (detail) => detail.loc.includes("flake_dir") + ); + flakeDirError && + methods.setError("flakeDir", { + message: flakeDirError.msg, + }); + } + } + })} + > + + +
+ ); +} diff --git a/pkgs/ui/src/app/join/page.tsx b/pkgs/ui/src/app/manage/join/page.tsx similarity index 88% rename from pkgs/ui/src/app/join/page.tsx rename to pkgs/ui/src/app/manage/join/page.tsx index a693cb70a..f0c76c500 100644 --- a/pkgs/ui/src/app/join/page.tsx +++ b/pkgs/ui/src/app/manage/join/page.tsx @@ -1,3 +1,4 @@ +"use client"; import JoinPrequel from "@/views/joinPrequel"; export default function Page() { diff --git a/pkgs/ui/src/app/manage/page.tsx b/pkgs/ui/src/app/manage/page.tsx new file mode 100644 index 000000000..821506d3e --- /dev/null +++ b/pkgs/ui/src/app/manage/page.tsx @@ -0,0 +1,11 @@ +import Link from "next/link"; + +export default function Manage() { + return ( +
+ Select + Join + Create +
+ ); +} diff --git a/pkgs/ui/src/components/forms/createClan/index.tsx b/pkgs/ui/src/components/forms/createClan/index.tsx new file mode 100644 index 000000000..0f542537d --- /dev/null +++ b/pkgs/ui/src/components/forms/createClan/index.tsx @@ -0,0 +1,77 @@ +import CopyAllIcon from "@mui/icons-material/CopyAll"; +import SaveAltIcon from "@mui/icons-material/SaveAlt"; +import { + Button, + InputAdornment, + LinearProgress, + TextField, +} from "@mui/material"; +import { Controller, UseFormReturn } from "react-hook-form"; + +export type CreateFormValues = { + flakeTemplateUrl: string; + flakeDir: string; +}; + +interface CreateClanProps { + confirmAdornment?: React.ReactNode; + methods: UseFormReturn; +} + +export const CreateClan = (props: CreateClanProps) => { + const { methods } = props; + const { + control, + formState: { isSubmitting }, + } = methods; + return ( +
+ ( + + + + ), + }} + helperText={fieldState.error?.message} + {...field} + /> + )} + /> + ( + + + + ), + }} + helperText={fieldState.error?.message} + {...field} + /> + )} + /> + + {isSubmitting && } +
+ ); +}; diff --git a/pkgs/ui/src/views/createForm.tsx b/pkgs/ui/src/views/createForm.tsx deleted file mode 100644 index 8c80dee73..000000000 --- a/pkgs/ui/src/views/createForm.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { Input, InputAdornment, LinearProgress } from "@mui/material"; -import { Controller, useFormContext } from "react-hook-form"; - -interface CreateFormProps { - confirmAdornment?: React.ReactNode; -} - -export const CreateForm = (props: CreateFormProps) => { - const { confirmAdornment } = props; - const { - control, - formState: { isSubmitting }, - } = useFormContext(); - return ( -
- ( - Clan - } - /> - )} - /> - ( - Name - } - endAdornment={confirmAdornment} - /> - )} - /> - {isSubmitting && } -
- ); -}; diff --git a/pkgs/ui/src/views/joinForm.tsx b/pkgs/ui/src/views/joinForm.tsx index 83f3edef8..586c553a4 100644 --- a/pkgs/ui/src/views/joinForm.tsx +++ b/pkgs/ui/src/views/joinForm.tsx @@ -1,16 +1,16 @@ import { Confirm } from "@/components/join/confirm"; +import PublicIcon from "@mui/icons-material/Public"; import { Input, InputAdornment } from "@mui/material"; import { Controller, useFormContext } from "react-hook-form"; interface JoinFormProps { - confirmAdornment?: React.ReactNode; initialParams: { flakeUrl: string; flakeAttr: string; }; } export const JoinForm = (props: JoinFormProps) => { - const { initialParams, confirmAdornment } = props; + const { initialParams } = props; const { control, formState, reset, getValues, watch } = useFormContext(); return ( @@ -38,10 +38,11 @@ export const JoinForm = (props: JoinFormProps) => { {...field} required fullWidth - startAdornment={ - Clan + endAdornment={ + + + } - endAdornment={confirmAdornment} /> )} /> diff --git a/pkgs/ui/src/views/joinPrequel.tsx b/pkgs/ui/src/views/joinPrequel.tsx index 5d5089d96..d845d5f45 100644 --- a/pkgs/ui/src/views/joinPrequel.tsx +++ b/pkgs/ui/src/views/joinPrequel.tsx @@ -1,29 +1,18 @@ "use client"; -import { - IconButton, - InputAdornment, - MenuItem, - Select, - Typography, -} from "@mui/material"; +import { Button, Typography } from "@mui/material"; import { useSearchParams } from "next/navigation"; import { Suspense, useState } from "react"; -import { createFlake } from "@/api/flake/flake"; import { VmConfig } from "@/api/model"; import { createVm } from "@/api/vm/vm"; -import { useAppState } from "@/components/hooks/useAppContext"; import { Layout } from "@/components/join/layout"; import { VmBuildLogs } from "@/components/join/vmBuildLogs"; -import { ChevronRight } from "@mui/icons-material"; import { AxiosError } from "axios"; -import { Controller, FormProvider, useForm } from "react-hook-form"; +import { FormProvider, useForm } from "react-hook-form"; import { toast } from "react-hot-toast"; -import { CreateForm } from "./createForm"; import { JoinForm } from "./joinForm"; export type FormValues = VmConfig & { - workflow: "join" | "create"; flakeUrl: string; dest?: string; }; @@ -34,48 +23,21 @@ export default function JoinPrequel() { const flakeAttr = queryParams.get("attr") || "default"; const initialParams = { flakeUrl, flakeAttr }; - const { setAppState } = useAppState(); - const methods = useForm({ defaultValues: { flakeUrl: "", dest: undefined, - workflow: "join", cores: 4, graphics: true, memory_size: 2048, }, }); - const { control, watch, handleSubmit } = methods; + const { handleSubmit } = methods; const [vmUuid, setVmUuid] = useState(null); const [showLogs, setShowLogs] = useState(false); - const workflow = watch("workflow"); - - const WorkflowAdornment = ( - - ( - - )} - /> - - - - - ); return ( - {workflow}{" "} - - Clan.lol - + Clan.lol } > @@ -98,60 +57,32 @@ export default function JoinPrequel() {
{ - if (workflow === "create") { - try { - await createFlake( - { - url: values.flakeUrl, - }, - { - flake_dir: values.dest || "myclan", - }, - ); - setAppState((s) => ({ ...s, isJoined: true })); - } catch (error) { - toast.error( - `Error: ${(error as AxiosError).message || ""}`, - ); - } - } - if (workflow === "join") { - 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 || ""}`, - ); + 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" > - {workflow == "join" && ( - - )} - {workflow == "create" && ( - - )} + +
)}