Merge pull request 'UI: init flash poc' (#1727) from hsjobeki/clan-core:hsjobeki-feat/clan-init into main
All checks were successful
buildbot/nix-build .#checks.aarch64-darwin.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.aarch64-darwin.nixos-test-backup Build done.
buildbot/nix-build .#checks.aarch64-darwin.nixos-minimal-inventory-machine Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-minimal-inventory-machine Build done.
buildbot/nix-build .#checks.aarch64-darwin.nixos-flash-installer Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-test-backup Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-installer-apk Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-nix Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-sshpass Build done.
buildbot/nix-build .#checks.x86_64-linux.lib-inventory-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.lib-jsonschema-example-valid Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-default Build done.
buildbot/nix-build .#checks.x86_64-linux.lib-inventory-eval Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-app-no-breakpoints Build done.
buildbot/nix-build .#checks.x86_64-linux.check-for-breakpoints Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-bash Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-installer-archlinux Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-installer-deb Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-e2fsprogs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-installer-rpm Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-git Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-age Build done.
buildbot/nix-build .#checks.x86_64-linux."clan-dep-python3.12-mypy" Build done.
buildbot/nix-build .#checks.x86_64-linux."clan-dep-python3.12-qemu" Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-rsync Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-sops Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-openssh Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-tor Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-zbar Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-app-pytest Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-flash-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-pytest-without-core Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-clan-cli Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-pytest-with-core Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-clan-app Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-webview-ui Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-inventory-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.module-clan-vars-eval Build done.
buildbot/nix-build .#checks.x86_64-linux.borgbackup Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.container Build done.
buildbot/nix-build .#checks.x86_64-linux.matrix-synapse Build done.
buildbot/nix-build .#checks.x86_64-linux.deltachat Build done.
buildbot/nix-build .#checks.x86_64-linux.package-clan-app Build done.
buildbot/nix-build .#checks.x86_64-linux.package-editor Build done.
buildbot/nix-build .#checks.x86_64-linux.flash Build done.
buildbot/nix-build .#checks.x86_64-linux.module-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.lib-jsonschema-nix-unit-tests Build done.
buildbot/nix-build .#checks.x86_64-linux.package-impure-checks Build done.
buildbot/nix-build .#checks.x86_64-linux.wayland-proxy-virtwl Build done.
buildbot/nix-build .#checks.x86_64-linux.test-backups Build done.
buildbot/nix-build .#checks.x86_64-linux.test-installation Build done.
buildbot/nix-build .#checks.x86_64-linux.syncthing Build done.
buildbot/nix-build .#checks.x86_64-linux.package-clan-cli Build done.
buildbot/nix-build .#checks.x86_64-linux.package-clan-cli-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-clan-ts-api Build done.
buildbot/nix-build .#checks.x86_64-linux.package-default Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-minimal-inventory-machine Build done.
buildbot/nix-build .#checks.x86_64-linux.package-merge-after-ci Build done.
buildbot/nix-build .#checks.x86_64-linux.package-moonlight-sunshine-accept Build done.
buildbot/nix-build .#checks.x86_64-linux.package-pending-reviews Build done.
buildbot/nix-build .#checks.x86_64-linux.package-tea-create-pr Build done.
buildbot/nix-build .#checks.x86_64-linux.package-webview-ui Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zerotier-members Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zerotierone Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zt-tcp-relay Build done.
buildbot/nix-build .#checks.x86_64-linux.package-deploy-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-test-backup Build done.
buildbot/nix-build .#checks.x86_64-linux.package-function-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.renderClanOptions Build done.
buildbot/nix-build .#checks.x86_64-linux.postgresql Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-flash-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.package-module-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-module-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.template-minimal Build done.
buildbot/nix-build .#checks.x86_64-linux.secrets Build done.
buildbot/nix-build .#checks.x86_64-linux.treefmt Build done.
buildbot/nix-build .#checks.x86_64-linux.zt-tcp-relay Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-install-test-ubuntu-22-04 Build done.
buildbot/nix-eval Build done.
checks / checks-impure (push) Successful in 4m38s
deploy / deploy-docs (push) Successful in 18s

This commit is contained in:
clan-bot 2024-07-10 09:07:09 +00:00
commit 61765fb2d2
5 changed files with 183 additions and 2 deletions

View File

@ -55,6 +55,34 @@ class _MethodRegistry:
self._orig: dict[str, Callable[[Any], Any]] = {} self._orig: dict[str, Callable[[Any], Any]] = {}
self._registry: dict[str, Callable[[Any], Any]] = {} self._registry: dict[str, Callable[[Any], Any]] = {}
def register_abstract(self, fn: Callable[..., T]) -> Callable[..., T]:
@wraps(fn)
def wrapper(
*args: Any, op_key: str | None = None, **kwargs: Any
) -> ApiResponse[T]:
raise NotImplementedError(
f"""{fn.__name__} - The platform didn't implement this function.
---
# Example
The function 'open_file()' depends on the platform.
def open_file(file_request: FileRequest) -> str | None:
# In GTK we open a file dialog window
# In Android we open a file picker dialog
# and so on.
pass
# At runtime the clan-app must override platform specific functions
API.register(open_file)
---
"""
)
self.register(wrapper)
return fn
def register(self, fn: Callable[..., T]) -> Callable[..., T]: def register(self, fn: Callable[..., T]) -> Callable[..., T]:
self._orig[fn.__name__] = fn self._orig[fn.__name__] = fn

View File

@ -28,13 +28,13 @@ class FileRequest:
filters: FileFilter | None = None filters: FileFilter | None = None
@API.register @API.register_abstract
def open_file(file_request: FileRequest) -> str | None: def open_file(file_request: FileRequest) -> str | None:
""" """
Abstract api method to open a file dialog window. Abstract api method to open a file dialog window.
It must return the name of the selected file or None if no file was selected. It must return the name of the selected file or None if no file was selected.
""" """
raise NotImplementedError("Each specific platform should implement this function.") pass
@dataclass @dataclass

View File

@ -11,6 +11,8 @@ from pathlib import Path
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
from typing import Any from typing import Any
from clan_cli.api import API
from .clan_uri import FlakeId from .clan_uri import FlakeId
from .cmd import Log, run from .cmd import Log, run
from .completions import add_dynamic_completer, complete_machines from .completions import add_dynamic_completer, complete_machines
@ -22,6 +24,7 @@ from .nix import nix_shell
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@API.register
def flash_machine( def flash_machine(
machine: Machine, machine: Machine,
*, *,

View File

@ -4,6 +4,7 @@ import { colors } from "./routes/colors/view";
import { clan } from "./routes/clan/view"; import { clan } from "./routes/clan/view";
import { HostList } from "./routes/hosts/view"; import { HostList } from "./routes/hosts/view";
import { BlockDevicesView } from "./routes/blockdevices/view"; import { BlockDevicesView } from "./routes/blockdevices/view";
import { Flash } from "./routes/flash/view";
export type Route = keyof typeof routes; export type Route = keyof typeof routes;
@ -23,6 +24,11 @@ export const routes = {
label: "hosts", label: "hosts",
icon: "devices_other", icon: "devices_other",
}, },
flash: {
child: Flash,
label: "create_flash_installer",
icon: "devices_other",
},
blockdevices: { blockdevices: {
child: BlockDevicesView, child: BlockDevicesView,
label: "blockdevices", label: "blockdevices",

View File

@ -0,0 +1,144 @@
import { route } from "@/src/App";
import { OperationArgs, OperationResponse, pyApi } from "@/src/api";
import { SubmitHandler, createForm, required } from "@modular-forms/solid";
import { For, createSignal } from "solid-js";
import { effect } from "solid-js/web";
// type FlashMachineArgs = {
// machine: Omit<OperationArgs<"flash_machine">["machine"], "cached_deployment">;
// } & Omit<Omit<OperationArgs<"flash_machine">, "machine">, "system_config">;
// type FlashMachineArgs = OperationArgs<"flash_machine">;
// type k = keyof FlashMachineArgs;
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
type FlashFormValues = {
machine: {
name: string;
flake: string;
};
disk: string;
};
type BlockDevices = Extract<
OperationResponse<"show_block_devices">,
{ status: "success" }
>["data"]["blockdevices"];
export const Flash = () => {
const [formStore, { Form, Field }] = createForm<FlashFormValues>({});
const [devices, setDevices] = createSignal<BlockDevices>([]);
pyApi.show_block_devices.receive((r) => {
console.log("block devices", r);
if (r.status === "success") {
setDevices(r.data.blockdevices);
}
});
const handleSubmit: SubmitHandler<FlashFormValues> = (values, event) => {
// pyApi.open_file.dispatch({ file_request: { mode: "save" } });
// pyApi.open_file.receive((r) => {
// if (r.status === "success") {
// if (r.data) {
// pyApi.create_clan.dispatch({
// options: { directory: r.data, meta: values },
// });
// }
// return;
// }
// });
console.log("submit", values);
};
effect(() => {
if (route() === "flash") {
pyApi.show_block_devices.dispatch({});
}
});
return (
<div class="">
<Form onSubmit={handleSubmit}>
<Field
name="machine.flake"
validate={[required("This field is required")]}
>
{(field, props) => (
<>
<label class="input input-bordered flex items-center gap-2">
<span class="material-icons">file_download</span>
<input
type="text"
class="grow"
placeholder="Clan URI"
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.name"
validate={[required("This field is required")]}
>
{(field, props) => (
<>
<label class="input input-bordered flex items-center gap-2">
<span class="material-icons">devices</span>
<input
type="text"
class="grow"
placeholder="Machine 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="disk" validate={[required("This field is required")]}>
{(field, props) => (
<>
<label class="form-control input-bordered flex w-full items-center gap-2">
<select required class="select w-full" {...props}>
{/* <span class="material-icons">devices</span> */}
<For each={devices()}>
{(device) => (
<option value={device.name}>
{device.name} / {device.size} bytes
</option>
)}
</For>
</select>
<div class="label">
{field.error && (
<span class="label-text-alt font-bold text-error">
{field.error}
</span>
)}
</div>
</label>
</>
)}
</Field>
<button class="btn btn-error" type="submit">
<span class="material-icons">bolt</span>Flash Installer
</button>
</Form>
</div>
);
};