From 97b8c7a70194edc7d8a1b6da477b088df5ced9ea Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Sat, 11 Nov 2023 10:08:39 +0100 Subject: [PATCH 1/3] add & configure machine: added formular integration --- .../createMachineForm/clanModules.tsx | 135 ++++++++++++++---- .../createMachineForm/customConfig.tsx | 8 +- .../components/createMachineForm/index.tsx | 46 +++--- .../createMachineForm/interfaces.ts | 1 + .../createMachineForm/saveConfig.tsx | 0 .../createMachineForm/selectModules.tsx | 0 .../createMachineForm/selectTemplate.tsx | 0 7 files changed, 141 insertions(+), 49 deletions(-) delete mode 100644 pkgs/ui/src/components/createMachineForm/saveConfig.tsx delete mode 100644 pkgs/ui/src/components/createMachineForm/selectModules.tsx delete mode 100644 pkgs/ui/src/components/createMachineForm/selectTemplate.tsx diff --git a/pkgs/ui/src/components/createMachineForm/clanModules.tsx b/pkgs/ui/src/components/createMachineForm/clanModules.tsx index e892f5177..664b0dd37 100644 --- a/pkgs/ui/src/components/createMachineForm/clanModules.tsx +++ b/pkgs/ui/src/components/createMachineForm/clanModules.tsx @@ -1,6 +1,13 @@ import { setMachineSchema } from "@/api/machine/machine"; import { useListClanModules } from "@/api/modules/modules"; -import { Alert, AlertTitle, FormHelperText, Typography } from "@mui/material"; +import { + Alert, + AlertTitle, + Divider, + FormHelperText, + Input, + Typography, +} from "@mui/material"; import Box from "@mui/material/Box"; import Chip from "@mui/material/Chip"; import FormControl from "@mui/material/FormControl"; @@ -8,9 +15,14 @@ import InputLabel from "@mui/material/InputLabel"; import MenuItem from "@mui/material/MenuItem"; import OutlinedInput from "@mui/material/OutlinedInput"; import Select, { SelectChangeEvent } from "@mui/material/Select"; -import { useEffect } from "react"; +import { Dispatch, SetStateAction, useEffect, useState } from "react"; +import { Controller } from "react-hook-form"; import { toast } from "react-hot-toast"; -import { CreateMachineForm, FormStepContentProps } from "./interfaces"; +import { + CreateMachineForm, + FormHooks, + FormStepContentProps, +} from "./interfaces"; const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; @@ -23,51 +35,114 @@ const MenuProps = { }, }; +interface IupdateSchema { + clanName: string; + modules: string[]; + formHooks: FormHooks; + setSchemaError: Dispatch>; +} + +const updateSchema = ({ + clanName, + modules, + formHooks, + setSchemaError, +}: IupdateSchema) => { + formHooks.setValue("isSchemaLoading", true); + setMachineSchema(clanName, "example_machine", { + clanImports: modules, + }) + .then((response) => { + if (response.statusText == "OK") { + formHooks.setValue("schema", response.data.schema); + setSchemaError(null); + } + }) + .catch((error) => { + formHooks.setValue("schema", {}); + console.error({ error }); + setSchemaError(error.message); + toast.error(`${error.message}`); + }) + .finally(() => { + formHooks.setValue("isSchemaLoading", false); + }); +}; + type ClanModulesProps = FormStepContentProps; +const SchemaSuccessMsg = () => ( + + Success + + Machine configuration schema successfully created. + + +); + +interface SchemaErrorMsgProps { + msg: string | null; +} + +const SchemaErrorMsg = (props: SchemaErrorMsgProps) => ( + + Error + + Machine configuration schema could not be created. + + + {props.msg} + + +); + export default function ClanModules(props: ClanModulesProps) { const { clanName, formHooks } = props; const { data, isLoading } = useListClanModules(clanName); - + const [schemaError, setSchemaError] = useState(null); const selectedModules = formHooks.watch("modules"); - useEffect(() => { - setMachineSchema(clanName, "example_machine", { - imports: [], - }).then((response) => { - if (response.statusText == "OK") { - formHooks.setValue("schema", response.data.schema); - } + updateSchema({ + clanName, + modules: formHooks.watch("modules"), + formHooks, + setSchemaError, }); - formHooks.setValue("modules", []); + // Only re-run if global clanName has changed // eslint-disable-next-line react-hooks/exhaustive-deps }, [clanName]); + const isSchemaLoading = formHooks.watch("isSchemaLoading"); const handleChange = ( - event: SelectChangeEvent, + event: SelectChangeEvent ) => { const { target: { value }, } = event; const newValue = typeof value === "string" ? value.split(",") : value; formHooks.setValue("modules", newValue); - setMachineSchema(clanName, "example_machine", { - imports: newValue, - }) - .then((response) => { - if (response.statusText == "OK") { - formHooks.setValue("schema", response.data.schema); - } - }) - .catch((error) => { - formHooks.setValue("schema", {}); - console.error({ error }); - toast.error(`${error.message}`); - }); + + updateSchema({ + clanName, + modules: newValue, + formHooks, + setSchemaError, + }); }; + return (
+ + Machine name + } + /> + Choose a unique name for the machine. + + Info Optionally select some modules —{" "} @@ -106,6 +181,14 @@ export default function ClanModules(props: ClanModulesProps) { (Optional) Select clan modules to be added. + + {!isSchemaLoading && } + {!isSchemaLoading && + (!schemaError ? ( + + ) : ( + + ))}
); } diff --git a/pkgs/ui/src/components/createMachineForm/customConfig.tsx b/pkgs/ui/src/components/createMachineForm/customConfig.tsx index bccf78369..a0f84c91e 100644 --- a/pkgs/ui/src/components/createMachineForm/customConfig.tsx +++ b/pkgs/ui/src/components/createMachineForm/customConfig.tsx @@ -44,7 +44,7 @@ export function CustomConfig(props: FormStepContentProps) { } return acc; }, {}), - [schema], + [schema] ); return ( @@ -110,11 +110,11 @@ function PureCustomConfig(props: PureCustomConfigProps) { message: "invalid config", }); toast.error( - "Configuration is invalid. Please check the highlighted fields for details.", + "Configuration is invalid. Please check the highlighted fields for details." ); } else { formHooks.clearErrors("config"); - toast.success("Config seems valid"); + toast.success("Configuration is valid"); } }; @@ -139,7 +139,7 @@ function PureCustomConfig(props: PureCustomConfigProps) { variant="outlined" color="secondary" > - Validate + Validate configuration ), diff --git a/pkgs/ui/src/components/createMachineForm/index.tsx b/pkgs/ui/src/components/createMachineForm/index.tsx index b672cb03b..8106a207a 100644 --- a/pkgs/ui/src/components/createMachineForm/index.tsx +++ b/pkgs/ui/src/components/createMachineForm/index.tsx @@ -1,6 +1,8 @@ +import { createMachine, setMachineConfig } from "@/api/machine/machine"; import { Box, Button, + CircularProgress, LinearProgress, MobileStepper, Step, @@ -11,6 +13,7 @@ import { } from "@mui/material"; import React, { useState } from "react"; import { useForm } from "react-hook-form"; +import { toast } from "react-hot-toast"; import { useAppState } from "../hooks/useAppContext"; import ClanModules from "./clanModules"; import { CustomConfig } from "./customConfig"; @@ -22,22 +25,19 @@ export function CreateMachineForm() { } = useAppState(); const formHooks = useForm({ defaultValues: { + isSchemaLoading: false, name: "", config: {}, modules: [], }, }); - const { handleSubmit, reset } = formHooks; + + const { handleSubmit, reset, watch } = formHooks; const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); const [activeStep, setActiveStep] = useState(0); const steps: FormStep[] = [ - { - id: "template", - label: "Template", - content:
, - }, { id: "modules", label: "Modules", @@ -56,11 +56,6 @@ export function CreateMachineForm() { ), }, - { - id: "save", - label: "Save", - content:
, - }, ]; const handleNext = () => { @@ -75,14 +70,23 @@ export function CreateMachineForm() { } }; - const handleReset = () => { - setActiveStep(0); - reset(); - }; const currentStep = steps.at(activeStep); - async function onSubmit(data: any) { + async function onSubmit(data: CreateMachineForm) { console.log({ data }, "Aggregated Data; creating machine from"); + if (clanName) { + if (!data.name) { + toast.error("Machine name should not be empty"); + return; + } + await createMachine(clanName, { + name: data.name, + }); + await setMachineConfig(clanName, data.name, { + config: data.config.formData, + clanImports: data.modules, + }); + } } const BackButton = () => ( @@ -102,17 +106,21 @@ export function CreateMachineForm() { )} {activeStep === steps.length - 1 && ( - )} diff --git a/pkgs/ui/src/components/createMachineForm/interfaces.ts b/pkgs/ui/src/components/createMachineForm/interfaces.ts index 3cac40b18..77c2ed752 100644 --- a/pkgs/ui/src/components/createMachineForm/interfaces.ts +++ b/pkgs/ui/src/components/createMachineForm/interfaces.ts @@ -9,6 +9,7 @@ export type CreateMachineForm = { config: any; modules: string[]; schema: JSONSchema7; + isSchemaLoading: boolean; }; export type FormHooks = UseFormReturn; diff --git a/pkgs/ui/src/components/createMachineForm/saveConfig.tsx b/pkgs/ui/src/components/createMachineForm/saveConfig.tsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/pkgs/ui/src/components/createMachineForm/selectModules.tsx b/pkgs/ui/src/components/createMachineForm/selectModules.tsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/pkgs/ui/src/components/createMachineForm/selectTemplate.tsx b/pkgs/ui/src/components/createMachineForm/selectTemplate.tsx deleted file mode 100644 index e69de29bb..000000000 From d7476c967e6f1209618fdb57af0e384ddfe8a2bc Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Sat, 11 Nov 2023 15:01:18 +0100 Subject: [PATCH 2/3] clean up join workflow --- pkgs/ui/public/favicon.ico | Bin 1150 -> 4189 bytes pkgs/ui/src/app/favicon.ico | Bin 25931 -> 0 bytes pkgs/ui/src/app/layout.tsx | 2 +- .../createMachineForm/clanModules.tsx | 2 +- .../createMachineForm/customConfig.tsx | 4 +- pkgs/ui/src/components/hooks/useVms.tsx | 2 +- pkgs/ui/src/components/join/configureVM.tsx | 75 ++++---- pkgs/ui/src/components/join/confirmVM.tsx | 47 ++--- pkgs/ui/src/components/join/layout.tsx | 9 +- pkgs/ui/src/components/join/log.tsx | 11 +- pkgs/ui/src/components/join/vmBuildLogs.tsx | 62 ++++-- pkgs/ui/src/views/createForm.tsx | 56 ++++++ pkgs/ui/src/views/joinForm.tsx | 51 +++++ pkgs/ui/src/views/joinPrequel.tsx | 178 ++++++++++-------- 14 files changed, 319 insertions(+), 180 deletions(-) delete mode 100644 pkgs/ui/src/app/favicon.ico create mode 100644 pkgs/ui/src/views/createForm.tsx create mode 100644 pkgs/ui/src/views/joinForm.tsx diff --git a/pkgs/ui/public/favicon.ico b/pkgs/ui/public/favicon.ico index 05acd55ee42fa2197e7d4e69fa97052d1236c988..94364cd2099c056050eae182cec27a9f1b5d12e2 100644 GIT binary patch literal 4189 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 Y6gikO!PN~E|Na6%OHEI;QW+llKYUE(6#xJL literal 1150 zcmc(dF;2uV5JhJN5+$imYk} zLWBhlpkINZ$_lyH*K#=1T@!Sm`5u&^zV@fQU(jxwK~FP#m~~#Tu$EU9L7DrSUp>yI zOw=6c9qyl5>z=Xnvkx#p3mwQORPvOi`~-t%uvVt}2Wav>p|y%Mbyq0-^5{NgL{N_3 z&+=O(_qsBnH;me&@^_$$FlUfUMfbVV)te$HN18x6wd&mG%8-9=<@A|=o}jGJJvC)e z{*-k=CrF@o4K>fU$K2)rR(;m(_WUpR>&hMcHO`M_AFpP|n=9|=xXZA9%l+dWv-f77 IFM6BV7h|vec>n+a diff --git a/pkgs/ui/src/app/favicon.ico b/pkgs/ui/src/app/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 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 LrJugUA?W`A8`#=m diff --git a/pkgs/ui/src/app/layout.tsx b/pkgs/ui/src/app/layout.tsx index b9d3fa532..0dec9b405 100644 --- a/pkgs/ui/src/app/layout.tsx +++ b/pkgs/ui/src/app/layout.tsx @@ -53,7 +53,7 @@ export default function RootLayout({ Clan.lol - + diff --git a/pkgs/ui/src/components/createMachineForm/clanModules.tsx b/pkgs/ui/src/components/createMachineForm/clanModules.tsx index 664b0dd37..2b8df35a3 100644 --- a/pkgs/ui/src/components/createMachineForm/clanModules.tsx +++ b/pkgs/ui/src/components/createMachineForm/clanModules.tsx @@ -115,7 +115,7 @@ export default function ClanModules(props: ClanModulesProps) { const isSchemaLoading = formHooks.watch("isSchemaLoading"); const handleChange = ( - event: SelectChangeEvent + event: SelectChangeEvent, ) => { const { target: { value }, diff --git a/pkgs/ui/src/components/createMachineForm/customConfig.tsx b/pkgs/ui/src/components/createMachineForm/customConfig.tsx index a0f84c91e..c9086e604 100644 --- a/pkgs/ui/src/components/createMachineForm/customConfig.tsx +++ b/pkgs/ui/src/components/createMachineForm/customConfig.tsx @@ -44,7 +44,7 @@ export function CustomConfig(props: FormStepContentProps) { } return acc; }, {}), - [schema] + [schema], ); return ( @@ -110,7 +110,7 @@ function PureCustomConfig(props: PureCustomConfigProps) { message: "invalid config", }); toast.error( - "Configuration is invalid. Please check the highlighted fields for details." + "Configuration is invalid. Please check the highlighted fields for details.", ); } else { formHooks.clearErrors("config"); diff --git a/pkgs/ui/src/components/hooks/useVms.tsx b/pkgs/ui/src/components/hooks/useVms.tsx index b385a72d5..6eda02897 100644 --- a/pkgs/ui/src/components/hooks/useVms.tsx +++ b/pkgs/ui/src/components/hooks/useVms.tsx @@ -1,5 +1,5 @@ -import { inspectVm } from "@/api/vm/vm"; import { HTTPValidationError, VmConfig } from "@/api/model"; +import { inspectVm } from "@/api/vm/vm"; import { AxiosError } from "axios"; import { useEffect, useState } from "react"; import { toast } from "react-hot-toast"; diff --git a/pkgs/ui/src/components/join/configureVM.tsx b/pkgs/ui/src/components/join/configureVM.tsx index 28b56fc62..27ab0526e 100644 --- a/pkgs/ui/src/components/join/configureVM.tsx +++ b/pkgs/ui/src/components/join/configureVM.tsx @@ -1,3 +1,5 @@ +import { useInspectFlakeAttrs } from "@/api/flake/flake"; +import { FormValues } from "@/views/joinPrequel"; import { Button, InputAdornment, @@ -8,14 +10,10 @@ import { Switch, TextField, } from "@mui/material"; -import { Controller, SubmitHandler, UseFormReturn } from "react-hook-form"; -import { FlakeBadge } from "../flakeBadge/flakeBadge"; -import { createVm } from "@/api/vm/vm"; -import { useInspectFlakeAttrs } from "@/api/flake/flake"; -import { VmConfig } from "@/api/model"; -import { Dispatch, SetStateAction, useEffect, useState } from "react"; +import { useEffect } from "react"; +import { Controller, UseFormReturn } from "react-hook-form"; import { toast } from "react-hot-toast"; -import { useAppState } from "../hooks/useAppContext"; +import { FlakeBadge } from "../flakeBadge/flakeBadge"; interface VmPropLabelProps { children: React.ReactNode; @@ -34,44 +32,41 @@ const VmPropContent = (props: VmPropContentProps) => ( ); interface VmDetailsProps { - formHooks: UseFormReturn; - setVmUuid: Dispatch>; + formHooks: UseFormReturn; } +type ClanError = { + detail: { + msg: string; + loc: []; + }[]; +}; + export const ConfigureVM = (props: VmDetailsProps) => { - const { formHooks, setVmUuid } = props; - const { control, handleSubmit, watch, setValue } = formHooks; - const [isStarting, setStarting] = useState(false); - const { setAppState } = useAppState(); - const { isLoading, data } = useInspectFlakeAttrs({ url: watch("flake_url") }); + 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; - const onSubmit: SubmitHandler = async (data) => { - setStarting(true); - console.log(data); - const response = await createVm(data); - const { uuid } = response?.data || null; - - setVmUuid(() => uuid); - setStarting(false); - if (response.statusText === "OK") { - toast.success(("Joined @ " + uuid) as string); - setAppState((s) => ({ ...s, isJoined: true })); - } else { - toast.error("Could not join"); - } - }; - + toast.error(msg, { + id: error.name, + }); + return
{msg}
; + } return ( -
+
General
@@ -79,7 +74,7 @@ export const ConfigureVM = (props: VmDetailsProps) => { Machine @@ -88,6 +83,7 @@ export const ConfigureVM = (props: VmDetailsProps) => { ( Clan + } + /> + )} + /> + ( + Name + } + endAdornment={confirmAdornment} + /> + )} + /> + {isSubmitting && } +
+ ); +}; diff --git a/pkgs/ui/src/views/joinForm.tsx b/pkgs/ui/src/views/joinForm.tsx new file mode 100644 index 000000000..83f3edef8 --- /dev/null +++ b/pkgs/ui/src/views/joinForm.tsx @@ -0,0 +1,51 @@ +import { Confirm } from "@/components/join/confirm"; +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 { control, formState, reset, getValues, watch } = useFormContext(); + + return ( +
+ {watch("flakeUrl") || initialParams.flakeUrl ? ( + reset()} + flakeUrl={ + formState.isSubmitted + ? getValues("flakeUrl") + : initialParams.flakeUrl + } + flakeAttr={initialParams.flakeAttr} + /> + ) : ( + ( + Clan + } + endAdornment={confirmAdornment} + /> + )} + /> + )} +
+ ); +}; diff --git a/pkgs/ui/src/views/joinPrequel.tsx b/pkgs/ui/src/views/joinPrequel.tsx index eb039a667..294a6d506 100644 --- a/pkgs/ui/src/views/joinPrequel.tsx +++ b/pkgs/ui/src/views/joinPrequel.tsx @@ -1,23 +1,28 @@ "use client"; import { IconButton, - Input, InputAdornment, - LinearProgress, MenuItem, Select, + 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 { Confirm } from "@/components/join/confirm"; import { Layout } from "@/components/join/layout"; +import { VmBuildLogs } from "@/components/join/vmBuildLogs"; import { ChevronRight } from "@mui/icons-material"; -import { Controller, useForm } from "react-hook-form"; +import { AxiosError } from "axios"; +import { Controller, FormProvider, useForm } from "react-hook-form"; +import { toast } from "react-hot-toast"; +import { CreateForm } from "./createForm"; +import { JoinForm } from "./joinForm"; -type FormValues = { +export type FormValues = VmConfig & { workflow: "join" | "create"; flakeUrl: string; dest?: string; @@ -27,13 +32,25 @@ export default function JoinPrequel() { const queryParams = useSearchParams(); const flakeUrl = queryParams.get("flake") || ""; const flakeAttr = queryParams.get("attr") || "default"; - const [, setForkInProgress] = useState(false); + const initialParams = { flakeUrl, flakeAttr }; + const { setAppState } = useAppState(); - const { control, formState, getValues, reset, watch, handleSubmit } = - useForm({ - defaultValues: { flakeUrl: "", dest: undefined, workflow: "join" }, - }); + const methods = useForm({ + defaultValues: { + flakeUrl: "", + dest: undefined, + workflow: "join", + cores: 4, + graphics: true, + memory_size: 2048, + }, + }); + + const { control, watch, handleSubmit } = methods; + + const [vmUuid, setVmUuid] = useState(null); + const [showLogs, setShowLogs] = useState(false); const workflow = watch("workflow"); @@ -54,88 +71,85 @@ export default function JoinPrequel() { )} /> - + ); return ( - + + {workflow}{" "} + + Clan.lol + + + } + > - {!formState.isSubmitted && !flakeUrl && ( - { - console.log("submitted", { values }); - if (workflow === "create") { - setForkInProgress(true); - createFlake({ - flake_name: values.dest || "default", - url: values.flakeUrl, - }).then(() => { - setForkInProgress(false); - setAppState((s) => ({ ...s, isJoined: true })); - }); - } - })} - className="w-full max-w-2xl justify-self-center" - > - ( - Clan + {vmUuid && showLogs ? ( + setShowLogs(false)} /> + ) : ( + + { + if (workflow === "create") { + try { + await createFlake({ + flake_name: values.dest || "default", + url: values.flakeUrl, + }); + setAppState((s) => ({ ...s, isJoined: true })); + } catch (error) { + toast.error( + `Error: ${(error as AxiosError).message || ""}`, + ); } - endAdornment={ - workflow == "join" ? WorkflowAdornment : undefined + } + 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 || ""}`, + ); } + } + })} + className="w-full max-w-2xl justify-self-center" + > + {workflow == "join" && ( + )} - /> - {workflow === "create" && ( - ( - Name - } - endAdornment={ - workflow == "create" ? WorkflowAdornment : undefined - } - /> - )} - /> - )} - - )} - {formState.isSubmitted && workflow == "create" && ( -
- -
- )} - {(formState.isSubmitted || flakeUrl) && workflow == "join" && ( - reset()} - flakeUrl={formState.isSubmitted ? getValues("flakeUrl") : flakeUrl} - flakeAttr={flakeAttr} - /> + {workflow == "create" && ( + + )} + +
)}
From 74c8b85e4a0746c6e92e9280f50f8def28174dcb Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Sat, 11 Nov 2023 15:27:57 +0100 Subject: [PATCH 3/3] fix type errors --- .../createMachineForm/clanModules.tsx | 74 +++++++++---------- .../components/createMachineForm/index.tsx | 4 +- 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/pkgs/ui/src/components/createMachineForm/clanModules.tsx b/pkgs/ui/src/components/createMachineForm/clanModules.tsx index 476d58e2d..045bbc198 100644 --- a/pkgs/ui/src/components/createMachineForm/clanModules.tsx +++ b/pkgs/ui/src/components/createMachineForm/clanModules.tsx @@ -15,14 +15,10 @@ import InputLabel from "@mui/material/InputLabel"; import MenuItem from "@mui/material/MenuItem"; import OutlinedInput from "@mui/material/OutlinedInput"; import Select, { SelectChangeEvent } from "@mui/material/Select"; -import { Dispatch, SetStateAction, useEffect, useState } from "react"; +import { useEffect, useState } from "react"; import { Controller } from "react-hook-form"; import { toast } from "react-hot-toast"; -import { - CreateMachineForm, - FormHooks, - FormStepContentProps, -} from "./interfaces"; +import { CreateMachineForm, FormStepContentProps } from "./interfaces"; const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; @@ -35,39 +31,39 @@ const MenuProps = { }, }; -interface IupdateSchema { - clanName: string; - modules: string[]; - formHooks: FormHooks; - setSchemaError: Dispatch>; -} +// interface IupdateSchema { +// clanName: string; +// modules: string[]; +// formHooks: FormHooks; +// setSchemaError: Dispatch>; +// } -const updateSchema = ({ - clanName, - modules, - formHooks, - setSchemaError, -}: IupdateSchema) => { - formHooks.setValue("isSchemaLoading", true); - getMachineSchema(clanName, { - clanImports: modules, - }) - .then((response) => { - if (response.statusText == "OK") { - formHooks.setValue("schema", response.data.schema); - setSchemaError(null); - } - }) - .catch((error) => { - formHooks.setValue("schema", {}); - console.error({ error }); - setSchemaError(error.message); - toast.error(`${error.message}`); - }) - .finally(() => { - formHooks.setValue("isSchemaLoading", false); - }); -}; +// const updateSchema = ({ +// clanName, +// modules, +// formHooks, +// setSchemaError, +// }: IupdateSchema) => { +// formHooks.setValue("isSchemaLoading", true); +// getMachineSchema(clanName, { +// clanImports: modules, +// }) +// .then((response) => { +// if (response.statusText == "OK") { +// formHooks.setValue("schema", response.data.schema); +// setSchemaError(null); +// } +// }) +// .catch((error) => { +// formHooks.setValue("schema", {}); +// console.error({ error }); +// setSchemaError(error.message); +// toast.error(`${error.message}`); +// }) +// .finally(() => { +// formHooks.setValue("isSchemaLoading", false); +// }); +// }; type ClanModulesProps = FormStepContentProps; @@ -99,7 +95,7 @@ const SchemaErrorMsg = (props: SchemaErrorMsgProps) => ( export default function ClanModules(props: ClanModulesProps) { const { clanName, formHooks } = props; const { data, isLoading } = useListClanModules(clanName); - const [schemaError, setSchemaError] = useState(null); + const [schemaError] = useState(null); const selectedModules = formHooks.watch("modules"); useEffect(() => { getMachineSchema(clanName, { diff --git a/pkgs/ui/src/components/createMachineForm/index.tsx b/pkgs/ui/src/components/createMachineForm/index.tsx index 8106a207a..65b11e00d 100644 --- a/pkgs/ui/src/components/createMachineForm/index.tsx +++ b/pkgs/ui/src/components/createMachineForm/index.tsx @@ -32,7 +32,7 @@ export function CreateMachineForm() { }, }); - const { handleSubmit, reset, watch } = formHooks; + const { handleSubmit, watch } = formHooks; const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); const [activeStep, setActiveStep] = useState(0); @@ -83,7 +83,7 @@ export function CreateMachineForm() { name: data.name, }); await setMachineConfig(clanName, data.name, { - config: data.config.formData, + clan: data.config.formData, clanImports: data.modules, }); }