UI: add vars step to installation flow
This commit is contained in:
@@ -22,7 +22,7 @@ import { ApiTester } from "./api_test";
|
|||||||
import { IconVariant } from "./components/icon";
|
import { IconVariant } from "./components/icon";
|
||||||
import { Components } from "./routes/components";
|
import { Components } from "./routes/components";
|
||||||
import { activeURI } from "./App";
|
import { activeURI } from "./App";
|
||||||
import { VarsForMachine, VarsStep } from "./routes/machines/install/vars-step";
|
import { VarsPage, VarsForm } from "./routes/machines/install/vars-step";
|
||||||
import { ThreePlayground } from "./three";
|
import { ThreePlayground } from "./three";
|
||||||
|
|
||||||
export const client = new QueryClient();
|
export const client = new QueryClient();
|
||||||
@@ -79,7 +79,7 @@ export const routes: AppRoute[] = [
|
|||||||
path: "/:id/vars",
|
path: "/:id/vars",
|
||||||
label: "Vars",
|
label: "Vars",
|
||||||
hidden: true,
|
hidden: true,
|
||||||
component: () => <VarsForMachine />,
|
component: () => <VarsPage />,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -293,7 +293,19 @@ const InstallMachine = (props: InstallMachineProps) => {
|
|||||||
/>
|
/>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={step() === "3"}>
|
<Match when={step() === "3"}>
|
||||||
<div>TODO: vars</div>
|
<VarsStep
|
||||||
|
// @ts-expect-error: This cannot be undefined in this context.
|
||||||
|
machine_id={props.name}
|
||||||
|
// @ts-expect-error: This cannot be undefined in this context.
|
||||||
|
dir={activeURI()}
|
||||||
|
handleNext={(data) => {
|
||||||
|
const prev = getValue(formStore, "3");
|
||||||
|
setValue(formStore, "3", { ...prev, ...data });
|
||||||
|
handleNext();
|
||||||
|
}}
|
||||||
|
initial={getValue(formStore, "3") || {}}
|
||||||
|
footer={<Footer />}
|
||||||
|
/>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={step() === "4"}>
|
<Match when={step() === "4"}>
|
||||||
<SummaryStep
|
<SummaryStep
|
||||||
@@ -433,8 +445,10 @@ const MachineForm = (props: MachineDetailsProps) => {
|
|||||||
const handleUpdateButton = async () => {
|
const handleUpdateButton = async () => {
|
||||||
await generatorsQuery.refetch();
|
await generatorsQuery.refetch();
|
||||||
|
|
||||||
if (generatorsQuery.data?.length !== 0) {
|
if (
|
||||||
navigate(`/machines/${machineName()}/vars`);
|
generatorsQuery.data?.some((generator) => generator.prompts?.length !== 0)
|
||||||
|
) {
|
||||||
|
navigate(`/machines/${machineName()}/vars?action=update`);
|
||||||
} else {
|
} else {
|
||||||
handleUpdate();
|
handleUpdate();
|
||||||
}
|
}
|
||||||
@@ -472,6 +486,7 @@ const MachineForm = (props: MachineDetailsProps) => {
|
|||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const action = searchParams.action;
|
const action = searchParams.action;
|
||||||
|
console.log({ action });
|
||||||
if (action === "update") {
|
if (action === "update") {
|
||||||
setSearchParams({ action: undefined });
|
setSearchParams({ action: undefined });
|
||||||
handleUpdate();
|
handleUpdate();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { callApi } from "@/src/api";
|
import { callApi, SuccessData } from "@/src/api";
|
||||||
import {
|
import {
|
||||||
createForm,
|
createForm,
|
||||||
FieldValues,
|
FieldValues,
|
||||||
@@ -11,24 +11,82 @@ import { Group } from "@/src/components/group";
|
|||||||
import { For, Match, Show, Switch } from "solid-js";
|
import { For, Match, Show, Switch } from "solid-js";
|
||||||
import { TextInput } from "@/src/Form/fields";
|
import { TextInput } from "@/src/Form/fields";
|
||||||
import toast from "solid-toast";
|
import toast from "solid-toast";
|
||||||
import { useNavigate, useParams } from "@solidjs/router";
|
import { useNavigate, useParams, useSearchParams } from "@solidjs/router";
|
||||||
import { activeURI } from "@/src/App";
|
import { activeURI } from "@/src/App";
|
||||||
|
import { StepProps } from "./hardware-step";
|
||||||
|
|
||||||
export type VarsValues = FieldValues & Record<string, Record<string, string>>;
|
export type VarsValues = FieldValues & Record<string, Record<string, string>>;
|
||||||
|
|
||||||
export interface VarsStepProps {
|
export const VarsStep = (props: StepProps<VarsValues>) => {
|
||||||
machine_id: string;
|
|
||||||
dir: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const VarsStep = (props: VarsStepProps) => {
|
|
||||||
const [formStore, { Form, Field }] = createForm<VarsValues>({});
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const generatorsQuery = createQuery(() => ({
|
||||||
|
queryKey: [props.dir, props.machine_id, "generators"],
|
||||||
|
queryFn: async () => {
|
||||||
|
const result = await callApi("get_generators_closure", {
|
||||||
|
base_dir: props.dir,
|
||||||
|
machine_name: props.machine_id,
|
||||||
|
});
|
||||||
|
if (result.status === "error") throw new Error("Failed to fetch data");
|
||||||
|
return result.data;
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
const handleSubmit: SubmitHandler<VarsValues> = async (values, event) => {
|
const handleSubmit: SubmitHandler<VarsValues> = async (values, event) => {
|
||||||
console.log("Submit Disk", { values });
|
const loading_toast = toast.loading("Generating vars...");
|
||||||
|
if (generatorsQuery.data === undefined) {
|
||||||
|
toast.error("Error fetching data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const result = await callApi("generate_vars_for_machine", {
|
||||||
|
machine_name: props.machine_id,
|
||||||
|
base_dir: props.dir,
|
||||||
|
generators: generatorsQuery.data.map((generator) => generator.name),
|
||||||
|
all_prompt_values: values,
|
||||||
|
});
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: [props.dir, props.machine_id, "generators"],
|
||||||
|
});
|
||||||
|
toast.dismiss(loading_toast);
|
||||||
|
if (result.status === "error") {
|
||||||
|
toast.error(result.errors[0].message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (result.status === "success") {
|
||||||
|
toast.success("Vars saved successfully");
|
||||||
|
}
|
||||||
|
props.handleNext(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Switch>
|
||||||
|
<Match when={generatorsQuery.isLoading}>Loading ...</Match>
|
||||||
|
<Match when={generatorsQuery.data}>
|
||||||
|
{(generators) => (
|
||||||
|
<VarsForm
|
||||||
|
machine_id={props.machine_id}
|
||||||
|
dir={props.dir}
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
generators={generators()}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Match>
|
||||||
|
</Switch>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface VarsFormProps {
|
||||||
|
machine_id: string;
|
||||||
|
dir: string;
|
||||||
|
handleSubmit: SubmitHandler<VarsValues>;
|
||||||
|
generators: SuccessData<"get_generators_closure">;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const VarsForm = (props: VarsFormProps) => {
|
||||||
|
const [formStore, { Form, Field }] = createForm<VarsValues>({});
|
||||||
|
|
||||||
|
const handleSubmit: SubmitHandler<VarsValues> = async (values, event) => {
|
||||||
|
console.log("Submit Vars", { values });
|
||||||
// sanitize the values back (replace __dot__)
|
// sanitize the values back (replace __dot__)
|
||||||
// This hack is needed because we are using "." in the keys of the form
|
// This hack is needed because we are using "." in the keys of the form
|
||||||
const sanitizedValues = Object.fromEntries(
|
const sanitizedValues = Object.fromEntries(
|
||||||
@@ -43,43 +101,13 @@ export const VarsStep = (props: VarsStepProps) => {
|
|||||||
]),
|
]),
|
||||||
) as VarsValues;
|
) as VarsValues;
|
||||||
const valid = await validate(formStore);
|
const valid = await validate(formStore);
|
||||||
if (generatorsQuery.data === undefined) {
|
if (!valid) {
|
||||||
toast.error("Error fetching data");
|
toast.error("Please fill all required fields");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const loading_toast = toast.loading("Generating vars...");
|
props.handleSubmit(sanitizedValues, event);
|
||||||
const result = await callApi("generate_vars_for_machine", {
|
|
||||||
machine_name: props.machine_id,
|
|
||||||
base_dir: props.dir,
|
|
||||||
generators: generatorsQuery.data.map((generator) => generator.name),
|
|
||||||
all_prompt_values: sanitizedValues,
|
|
||||||
});
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: [props.dir, props.machine_id, "generators"],
|
|
||||||
});
|
|
||||||
toast.dismiss(loading_toast);
|
|
||||||
if (result.status === "error") {
|
|
||||||
toast.error(result.errors[0].message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (result.status === "success") {
|
|
||||||
toast.success("Vars saved successfully");
|
|
||||||
navigate(`/machines/${props.machine_id}?action=update`);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const generatorsQuery = createQuery(() => ({
|
|
||||||
queryKey: [props.dir, props.machine_id, "generators"],
|
|
||||||
queryFn: async () => {
|
|
||||||
const result = await callApi("get_generators_closure", {
|
|
||||||
base_dir: props.dir,
|
|
||||||
machine_name: props.machine_id,
|
|
||||||
});
|
|
||||||
if (result.status === "error") throw new Error("Failed to fetch data");
|
|
||||||
return result.data;
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
@@ -88,19 +116,14 @@ export const VarsStep = (props: VarsStepProps) => {
|
|||||||
>
|
>
|
||||||
<div class="max-h-[calc(100vh-20rem)] overflow-y-scroll">
|
<div class="max-h-[calc(100vh-20rem)] overflow-y-scroll">
|
||||||
<div class="flex h-full flex-col gap-6 p-4">
|
<div class="flex h-full flex-col gap-6 p-4">
|
||||||
<Switch>
|
<For each={props.generators}>
|
||||||
<Match when={generatorsQuery.isLoading}>Loading ...</Match>
|
|
||||||
<Match when={generatorsQuery.data}>
|
|
||||||
{(generators) => (
|
|
||||||
<For each={generators()}>
|
|
||||||
{(generator) => (
|
{(generator) => (
|
||||||
<Group>
|
<Group>
|
||||||
<Typography hierarchy="label" size="default">
|
<Typography hierarchy="label" size="default">
|
||||||
{generator.name}
|
{generator.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
<div>
|
<div>
|
||||||
Bound to module (shared):{" "}
|
Bound to module (shared): {generator.share ? "True" : "False"}
|
||||||
{generator.share ? "True" : "False"}
|
|
||||||
</div>
|
</div>
|
||||||
<For each={generator.prompts}>
|
<For each={generator.prompts}>
|
||||||
{(prompt) => (
|
{(prompt) => (
|
||||||
@@ -111,8 +134,8 @@ export const VarsStep = (props: VarsStepProps) => {
|
|||||||
<Typography hierarchy="label" size="s">
|
<Typography hierarchy="label" size="s">
|
||||||
{prompt.name}
|
{prompt.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
{/* Avoid nesting issue in case of a "." */}
|
|
||||||
<Field
|
<Field
|
||||||
|
// Avoid nesting issue in case of a "."
|
||||||
name={`${generator.name.replaceAll(
|
name={`${generator.name.replaceAll(
|
||||||
".",
|
".",
|
||||||
"__dot__",
|
"__dot__",
|
||||||
@@ -158,9 +181,6 @@ export const VarsStep = (props: VarsStepProps) => {
|
|||||||
</Group>
|
</Group>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
)}
|
|
||||||
</Match>
|
|
||||||
</Switch>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit">Submit</button>
|
<button type="submit">Submit</button>
|
||||||
@@ -168,12 +188,27 @@ export const VarsStep = (props: VarsStepProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VarsForMachine = () => {
|
export const VarsPage = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
const handleNext = (values: VarsValues) => {
|
||||||
|
if (searchParams?.action === "update") {
|
||||||
|
navigate(`/machines/${params.id}?action=update`);
|
||||||
|
} else {
|
||||||
|
toast.error("Invalid action for vars page");
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<Show when={activeURI()}>
|
<Show when={activeURI()}>
|
||||||
{(uri) => <VarsStep machine_id={params.id} dir={uri()} />}
|
{(uri) => (
|
||||||
|
<VarsStep
|
||||||
|
machine_id={params.id}
|
||||||
|
dir={uri()}
|
||||||
|
handleNext={handleNext}
|
||||||
|
footer
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Show>
|
</Show>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user