From 47c94c51b63c7d1b58983139a24ea5d22ffecf3c Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Fri, 8 Aug 2025 21:03:49 +0200 Subject: [PATCH] UI: finish up create installer subflow --- .../ui/src/workflows/Install/install.tsx | 12 +- .../Install/steps/createInstaller.tsx | 119 ++++++------------ 2 files changed, 51 insertions(+), 80 deletions(-) diff --git a/pkgs/clan-app/ui/src/workflows/Install/install.tsx b/pkgs/clan-app/ui/src/workflows/Install/install.tsx index e7bb12c94..6a9d099ec 100644 --- a/pkgs/clan-app/ui/src/workflows/Install/install.tsx +++ b/pkgs/clan-app/ui/src/workflows/Install/install.tsx @@ -1,6 +1,7 @@ import { Modal } from "@/src/components/Modal/Modal"; import { createStepper, + getStepStore, StepperProvider, useStepper, } from "@/src/hooks/stepper"; @@ -10,6 +11,7 @@ import { Dynamic } from "solid-js/web"; import { initialSteps } from "./steps/Initial"; import { createInstallerSteps } from "./steps/createInstaller"; import { installSteps } from "./steps/installSteps"; +import { ApiCall } from "@/src/hooks/api"; interface InstallForm extends FieldValues { data_from_step_1: string; @@ -54,10 +56,13 @@ const steps = [ export type InstallSteps = typeof steps; export interface InstallStoreType { flash: { - language: string; - keymap: string; ssh_file: string; device: string; + progress: ApiCall<"run_machine_flash">; + }; + install: { + targetHost: string; + machineName: string; }; } @@ -78,6 +83,9 @@ export const InstallModal = (props: InstallModalProps) => { ); }; + const [store, set] = getStepStore(stepper); + + set("install", { machineName: props.machineName }); return ( diff --git a/pkgs/clan-app/ui/src/workflows/Install/steps/createInstaller.tsx b/pkgs/clan-app/ui/src/workflows/Install/steps/createInstaller.tsx index a4b3707c8..378ea6af7 100644 --- a/pkgs/clan-app/ui/src/workflows/Install/steps/createInstaller.tsx +++ b/pkgs/clan-app/ui/src/workflows/Install/steps/createInstaller.tsx @@ -20,8 +20,9 @@ import { useMachineFlashOptions, useSystemStorageOptions, } from "@/src/hooks/queries"; -import { useClanURI } from "@/src/hooks/clan"; import { useApiClient } from "@/src/hooks/ApiClient"; +import { createEffect, onMount } from "solid-js"; +import { create } from "storybook/internal/theming"; const Prose = () => ( ; const ConfigureImage = () => { + const stepSignal = useStepper(); + const [store, set] = getStepStore(stepSignal); + const [formStore, { Form, Field }] = createForm({ validate: valiForm(ConfigureImageSchema), + initialValues: { + ssh_key: store.flash?.ssh_file, + }, }); - const stepSignal = useStepper(); - - const [store, set] = getStepStore(stepSignal); const handleSubmit: SubmitHandler = (values, event) => { // Push values to the store set("flash", (s) => ({ ...s, - language: values.language, - keymap: values.keymap, ssh_file: values.ssh_key, })); @@ -124,8 +124,9 @@ const ConfigureImage = () => { const onSelectFile = async () => { const req = client.fetch("get_system_file", { file_request: { - mode: "select_folder", + mode: "get_system_file", title: "Select a folder for you new Clan", + initial_folder: "~/.ssh", }, }); @@ -144,14 +145,20 @@ const ConfigureImage = () => { throw new Error("No data returned from api call"); }; - const currClan = useClanURI(); - const optionsQuery = useMachineFlashOptions(currClan); + const optionsQuery = useMachineFlashOptions(); + + let content: Node; return (
+
{ + content = el; + }} + >
{(field, input) => ( @@ -172,66 +179,6 @@ const ConfigureImage = () => { )}
-
- - {(field, props) => ( - { - if (!optionsQuery.data) { - await optionsQuery.refetch(); - } - - return (optionsQuery.data?.keymaps ?? []).map( - (keymap) => ({ - // TODO: Pretty label ? - value: keymap, - label: keymap, - }), - ); - }} - placeholder="Keymap" - name={field.name} - /> - )} - -
} footer={ @@ -256,11 +203,14 @@ type ChooseDiskForm = v.InferInput; const ChooseDisk = () => { const stepSignal = useStepper(); + const [store, set] = getStepStore(stepSignal); const [formStore, { Form, Field }] = createForm({ validate: valiForm(ChooseDiskSchema), + initialValues: { + disk: store.flash?.device, + }, }); - const [store, set] = getStepStore(stepSignal); const client = useApiClient(); const systemStorageQuery = useSystemStorageOptions(); @@ -273,8 +223,6 @@ const ChooseDisk = () => { })); const call = client.fetch("run_machine_flash", { system_config: { - keymap: store.flash.keymap, - language: store.flash.language, ssh_keys_path: [store.flash.ssh_file], }, disks: [ @@ -284,13 +232,15 @@ const ChooseDisk = () => { }, ], }); - // TOOD: Pass the "call" Promise to the "progress step" + + set("flash", "progress", call); console.log("Flashing", store.flash); - // Here you would typically trigger the disk selection process stepSignal.next(); }; + + const stripId = (s: string) => s.split("-")[1] ?? s; return ( { {(field, props) => (