Create machine: init view with api
This commit is contained in:
parent
f787acdaa4
commit
d38983c784
@ -1,13 +1,17 @@
|
||||
import argparse
|
||||
import logging
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from ..api import API
|
||||
from ..clan_uri import FlakeId
|
||||
from ..errors import ClanError
|
||||
from ..git import commit_file
|
||||
from ..inventory import Machine, MachineDeploy, get_path, load_inventory, save_inventory
|
||||
from ..inventory import (
|
||||
Machine,
|
||||
MachineDeploy,
|
||||
load_inventory_eval,
|
||||
load_inventory_json,
|
||||
save_inventory,
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -20,12 +24,15 @@ def create_machine(flake: FlakeId, machine: Machine) -> None:
|
||||
"Machine name must be a valid hostname", location="Create Machine"
|
||||
)
|
||||
|
||||
inventory = load_inventory(flake.path)
|
||||
inventory = load_inventory_json(flake.path)
|
||||
full_inventory = load_inventory_eval(flake.path)
|
||||
|
||||
if machine.name in full_inventory.machines.keys():
|
||||
raise ClanError(f"Machine with the name {machine.name} already exists")
|
||||
|
||||
inventory.machines.update({machine.name: machine})
|
||||
save_inventory(inventory, flake.path, f"Create machine {machine.name}")
|
||||
|
||||
commit_file(get_path(flake.path), Path(flake.path))
|
||||
|
||||
|
||||
def create_command(args: argparse.Namespace) -> None:
|
||||
create_machine(
|
||||
|
4
pkgs/webview-ui/.gitignore
vendored
4
pkgs/webview-ui/.gitignore
vendored
@ -1 +1,3 @@
|
||||
api
|
||||
api
|
||||
|
||||
.vite
|
@ -8,6 +8,7 @@ import { Flash } from "./routes/flash/view";
|
||||
import { Settings } from "./routes/settings";
|
||||
import { Welcome } from "./routes/welcome";
|
||||
import { Deploy } from "./routes/deploy";
|
||||
import { CreateMachine } from "./routes/machines/create";
|
||||
|
||||
export type Route = keyof typeof routes;
|
||||
|
||||
@ -22,6 +23,11 @@ export const routes = {
|
||||
label: "Machines",
|
||||
icon: "devices_other",
|
||||
},
|
||||
"machines/add": {
|
||||
child: CreateMachine,
|
||||
label: "create Machine",
|
||||
icon: "add",
|
||||
},
|
||||
hosts: {
|
||||
child: HostList,
|
||||
label: "hosts",
|
||||
|
@ -67,6 +67,17 @@ function createFunctions<K extends OperationNames>(
|
||||
dispatch: (args: OperationArgs<K>) => void;
|
||||
receive: (fn: (response: OperationResponse<K>) => void, id: string) => void;
|
||||
} {
|
||||
window.clan[operationName] = (s: string) => {
|
||||
const f = (response: OperationResponse<K>) => {
|
||||
// Get the correct receiver function for the op_key
|
||||
const receiver = registry[operationName][response.op_key];
|
||||
if (receiver) {
|
||||
receiver(response);
|
||||
}
|
||||
};
|
||||
deserialize(f)(s);
|
||||
};
|
||||
|
||||
return {
|
||||
dispatch: (args: OperationArgs<K>) => {
|
||||
// Send the data to the gtk app
|
||||
@ -78,15 +89,6 @@ function createFunctions<K extends OperationNames>(
|
||||
receive: (fn: (response: OperationResponse<K>) => void, id: string) => {
|
||||
// @ts-expect-error: This should work although typescript doesn't let us write
|
||||
registry[operationName][id] = fn;
|
||||
|
||||
window.clan[operationName] = (s: string) => {
|
||||
const f = (response: OperationResponse<K>) => {
|
||||
if (response.op_key === id) {
|
||||
registry[operationName][id](response);
|
||||
}
|
||||
};
|
||||
deserialize(f)(s);
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
|
||||
html {
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
|
124
pkgs/webview-ui/app/src/routes/machines/create.tsx
Normal file
124
pkgs/webview-ui/app/src/routes/machines/create.tsx
Normal file
@ -0,0 +1,124 @@
|
||||
import { callApi, OperationArgs, pyApi } from "@/src/api";
|
||||
import { activeURI } from "@/src/App";
|
||||
import { createForm, required } from "@modular-forms/solid";
|
||||
import toast from "solid-toast";
|
||||
|
||||
type CreateMachineForm = OperationArgs<"create_machine">;
|
||||
|
||||
export function CreateMachine() {
|
||||
const [formStore, { Form, Field }] = createForm<CreateMachineForm>({});
|
||||
|
||||
const handleSubmit = async (values: CreateMachineForm) => {
|
||||
const active_dir = activeURI();
|
||||
if (!active_dir) {
|
||||
toast.error("Open a clan to create the machine in");
|
||||
return;
|
||||
}
|
||||
|
||||
callApi("create_machine", {
|
||||
flake: {
|
||||
loc: active_dir,
|
||||
},
|
||||
machine: {
|
||||
name: "jon",
|
||||
deploy: {
|
||||
targetHost: null,
|
||||
},
|
||||
},
|
||||
});
|
||||
console.log("submit", values);
|
||||
};
|
||||
return (
|
||||
<div class="px-1">
|
||||
Create new Machine
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<Field
|
||||
name="machine.name"
|
||||
validate={[required("This field is required")]}
|
||||
>
|
||||
{(field, props) => (
|
||||
<>
|
||||
<label class="input input-bordered flex items-center gap-2">
|
||||
<input
|
||||
type="text"
|
||||
class="grow"
|
||||
placeholder="name"
|
||||
required
|
||||
{...props}
|
||||
/>
|
||||
</label>
|
||||
<div class="label">
|
||||
{field.error && (
|
||||
<span class="label-text-alt font-bold text-error">
|
||||
{field.error}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<Field name="machine.description">
|
||||
{(field, props) => (
|
||||
<>
|
||||
<label class="input input-bordered flex items-center gap-2">
|
||||
<input
|
||||
type="text"
|
||||
class="grow"
|
||||
placeholder="description"
|
||||
required
|
||||
{...props}
|
||||
/>
|
||||
</label>
|
||||
<div class="label">
|
||||
{field.error && (
|
||||
<span class="label-text-alt font-bold text-error">
|
||||
{field.error}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<Field name="machine.deploy.targetHost">
|
||||
{(field, props) => (
|
||||
<>
|
||||
<label class="input input-bordered flex items-center gap-2">
|
||||
<input
|
||||
type="text"
|
||||
class="grow"
|
||||
placeholder="root@flash-installer.local"
|
||||
required
|
||||
{...props}
|
||||
/>
|
||||
</label>
|
||||
<div class="label">
|
||||
<span class="label-text-alt text-neutral">
|
||||
Must be set before deployment for the following tasks:
|
||||
<ul>
|
||||
<li>
|
||||
<span>Detect hardware config</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Detect disk layout</span>
|
||||
</li>
|
||||
<li>
|
||||
<span>Remote installation</span>
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
{field.error && (
|
||||
<span class="label-text-alt font-bold text-error">
|
||||
{field.error}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Field>
|
||||
<button class="btn btn-error float-right" type="submit">
|
||||
<span class="material-icons">add</span>Create
|
||||
</button>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -7,7 +7,7 @@ import {
|
||||
createSignal,
|
||||
type Component,
|
||||
} from "solid-js";
|
||||
import { activeURI, route, setActiveURI } from "@/src/App";
|
||||
import { activeURI, route, setActiveURI, setRoute } from "@/src/App";
|
||||
import { OperationResponse, callApi, pyApi } from "@/src/api";
|
||||
import toast from "solid-toast";
|
||||
import { MachineListItem } from "@/src/components/MachineListItem";
|
||||
@ -86,6 +86,11 @@ export const MachineListView: Component = () => {
|
||||
<span class="material-icons ">refresh</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="tooltip tooltip-bottom" data-tip="Create machine">
|
||||
<button class="btn btn-ghost" onClick={() => setRoute("machines/add")}>
|
||||
<span class="material-icons ">add</span>
|
||||
</button>
|
||||
</div>
|
||||
{/* <Show when={services()}>
|
||||
{(services) => (
|
||||
<For each={Object.values(services())}>
|
||||
|
Loading…
Reference in New Issue
Block a user