UI: improve open clan from directory & list machines

This commit is contained in:
Johannes Kirschbauer
2024-07-10 11:03:36 +02:00
parent 61765fb2d2
commit 4e9778f7d6
11 changed files with 95 additions and 73 deletions

View File

@@ -16,7 +16,6 @@ let
> $out/config.json < ${pkgs.element-web}/config.json > $out/config.json < ${pkgs.element-web}/config.json
ln -s $out/config.json $out/config.${nginx-vhost}.json ln -s $out/config.json $out/config.${nginx-vhost}.json
''; '';
in in
# FIXME: This was taken from upstream. Drop this when our patch is upstream # FIXME: This was taken from upstream. Drop this when our patch is upstream
{ {

View File

@@ -15,7 +15,7 @@ const getFakeResponse = (method: OperationNames, data: any) => {
if (method === "open_file") { if (method === "open_file") {
return { return {
status: "success", status: "success",
data: "/path/to/clan", data: "/home/johannes/git/clan-core",
op_key, op_key,
}; };
} }

View File

@@ -4,17 +4,13 @@ import { Layout } from "./layout/layout";
import { Route, Router } from "./Routes"; import { Route, Router } from "./Routes";
import { Toaster } from "solid-toast"; import { Toaster } from "solid-toast";
// Global state // Some global state
const [route, setRoute] = createSignal<Route>("machines"); const [route, setRoute] = createSignal<Route>("machines");
const [currClanURI, setCurrClanURI] = createSignal<string>(
"/home/johannes/git/testing/xd"
);
export { currClanURI, setCurrClanURI };
export { route, setRoute }; export { route, setRoute };
const [currClanURI, setCurrClanURI] = createSignal<string | null>(null);
export { currClanURI, setCurrClanURI };
const App: Component = () => { const App: Component = () => {
return [ return [
<Toaster position="top-right" />, <Toaster position="top-right" />,

View File

@@ -26,12 +26,16 @@ export const makeMachineContext = () => {
{ loading, machines }, { loading, machines },
{ {
getMachines: () => { getMachines: () => {
const clan_dir = currClanURI();
if (clan_dir) {
setLoading(true);
pyApi.list_machines.dispatch({
debug: true,
flake_url: clan_dir,
});
}
// When the gtk function sends its data the loading state will be set to false // When the gtk function sends its data the loading state will be set to false
setLoading(true);
pyApi.list_machines.dispatch({
debug: true,
flake_url: currClanURI(),
});
}, },
}, },
] as const; ] as const;

View File

@@ -9,7 +9,7 @@ export const Sidebar = (props: SidebarProps) => {
const { route, setRoute } = props; const { route, setRoute } = props;
return ( return (
<aside class="min-h-screen w-80 bg-base-100"> <aside class="min-h-screen w-80 bg-base-100">
<div class="sticky top-0 z-20 hidden items-center gap-2 bg-base-100/90 px-4 py-2 shadow-sm backdrop-blur lg:flex"> <div class="sticky top-0 z-20 items-center gap-2 bg-base-100/90 px-4 py-2 shadow-sm backdrop-blur lg:flex">
Icon Icon
</div> </div>
<ul class="menu px-4 py-0"> <ul class="menu px-4 py-0">

View File

@@ -54,17 +54,20 @@ pyApi.show_machine_deployment_target.receive((r) => {
export const MachineListItem = (props: MachineListItemProps) => { export const MachineListItem = (props: MachineListItemProps) => {
const { name, info } = props; const { name, info } = props;
pyApi.show_machine_hardware_info.dispatch({ const clan_dir = currClanURI();
op_key: name, if (clan_dir) {
clan_dir: currClanURI(), pyApi.show_machine_hardware_info.dispatch({
machine_name: name, op_key: name,
}); clan_dir,
machine_name: name,
});
pyApi.show_machine_deployment_target.dispatch({ pyApi.show_machine_deployment_target.dispatch({
op_key: name, op_key: name,
clan_dir: currClanURI(), clan_dir,
machine_name: name, machine_name: name,
}); });
}
return ( return (
<li> <li>
@@ -91,25 +94,22 @@ export const MachineListItem = (props: MachineListItemProps) => {
</div> </div>
<div class="flex flex-row flex-wrap gap-4 py-2"> <div class="flex flex-row flex-wrap gap-4 py-2">
<div class="badge badge-primary flex flex-row gap-1 py-4 align-middle"> <div class="badge badge-primary flex flex-row gap-1 py-4 align-middle">
<span class="material-icons"> <span>System:</span>
{hwInfo()[name]?.system ? "check" : "pending"} {hwInfo()[name]?.system ? (
</span> <span class="text-primary">{hwInfo()[name]?.system}</span>
) : (
<Switch fallback={<div class="skeleton h-8 w-full"></div>}> <span class="text-warning">Not set</span>
<Match when={hwInfo()[name]?.system}> )}
{(system) => "System: " + system()}
</Match>
<Match when={hwInfo()[name]?.system === null}>
{"No hardware info"}
</Match>
</Switch>
</div> </div>
<div class="badge badge-primary flex flex-row gap-1 py-4 align-middle"> <div class="badge badge-ghost flex flex-row gap-1 py-4 align-middle">
<span class="material-icons"> <span>Target Host:</span>
{deploymentInfo()[name] ? "check" : "pending"} {deploymentInfo()[name] ? (
</span> <span class="text-primary">{deploymentInfo()[name]}</span>
<Show ) : (
<span class="text-warning">Not set</span>
)}
{/* <Show
when={deploymentInfo()[name]} when={deploymentInfo()[name]}
fallback={ fallback={
<Switch fallback={<div class="skeleton h-8 w-full"></div>}> <Switch fallback={<div class="skeleton h-8 w-full"></div>}>
@@ -119,8 +119,8 @@ export const MachineListItem = (props: MachineListItemProps) => {
</Switch> </Switch>
} }
> >
{(i) => "Deploys to: " + i()} {(i) => + i()}
</Show> </Show> */}
</div> </div>
</div> </div>
{/* Show only the first error at the bottom */} {/* Show only the first error at the bottom */}

View File

@@ -18,22 +18,24 @@ if (import.meta.env.DEV) {
console.log("Development mode"); console.log("Development mode");
// Load the debugger in development mode // Load the debugger in development mode
await import("solid-devtools"); await import("solid-devtools");
window.webkit = window.webkit || {
messageHandlers: {
gtk: {
postMessage: (postMessage) => {
const { method, data } = postMessage;
console.debug("Python API call", { method, data });
setTimeout(() => {
const mock = getFakeResponse(method, data);
console.log("Returning mock-data: ", { mock });
window.clan[method](JSON.stringify(mock)); // Uncomment this block to use the Mock API
}, 200); // window.webkit = window.webkit || {
}, // messageHandlers: {
}, // gtk: {
}, // postMessage: (postMessage) => {
}; // const { method, data } = postMessage;
// console.debug("Python API call", { method, data });
// setTimeout(() => {
// const mock = getFakeResponse(method, data);
// console.log("Returning mock-data: ", { mock });
// window.clan[method](JSON.stringify(mock));
// }, 200);
// },
// },
// },
// };
} }
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
render(() => <App />, root!); render(() => <App />, root!);

View File

@@ -1,18 +1,27 @@
import { currClanURI } from "../App";
export const Header = () => { export const Header = () => {
return ( return (
<div class="navbar bg-base-100"> <div class="navbar bg-base-100">
<div class="flex-none"> <div class="flex-none">
<button class="btn btn-square btn-ghost"> <span class="tooltip tooltip-bottom" data-tip="Menu">
<span class="material-icons">home</span> <label
</button> class="btn btn-square btn-ghost drawer-button"
for="toplevel-drawer"
>
<span class="material-icons">menu</span>
</label>
</span>
</div> </div>
<div class="flex-1"> <div class="flex-1">
<a class="btn btn-ghost text-xl">Clan</a> <a class="text-xl">{currClanURI() || "Clan"}</a>
</div> </div>
<div class="flex-none"> <div class="flex-none">
<button class="btn btn-square btn-ghost"> <span class="tooltip tooltip-bottom" data-tip="Account">
<span class="material-icons">menu</span> <button class="btn btn-square btn-ghost">
</button> <span class="material-icons">account_circle</span>
</button>
</span>
</div> </div>
</div> </div>
); );

View File

@@ -22,7 +22,7 @@ export const BlockDevicesView: Component = () => {
return ( return (
<div> <div>
<div class="tooltip" data-tip="Refresh"> <div class="tooltip tooltip-bottom" data-tip="Refresh">
<button <button
class="btn btn-ghost" class="btn btn-ghost"
onClick={() => pyApi.show_block_devices.dispatch({})} onClick={() => pyApi.show_block_devices.dispatch({})}

View File

@@ -28,7 +28,7 @@ export const HostList: Component = () => {
return ( return (
<div> <div>
<div class="tooltip" data-tip="Refresh install targets"> <div class="tooltip tooltip-bottom" data-tip="Refresh install targets">
<button <button
class="btn btn-ghost" class="btn btn-ghost"
onClick={() => pyApi.show_mdns.dispatch({})} onClick={() => pyApi.show_mdns.dispatch({})}

View File

@@ -8,7 +8,7 @@ import {
type Component, type Component,
} from "solid-js"; } from "solid-js";
import { useMachineContext } from "../../Config"; import { useMachineContext } from "../../Config";
import { route } from "@/src/App"; import { route, setCurrClanURI } from "@/src/App";
import { OperationResponse, pyApi } from "@/src/api"; import { OperationResponse, pyApi } from "@/src/api";
import toast from "solid-toast"; import toast from "solid-toast";
import { MachineListItem } from "@/src/components/MachineListItem"; import { MachineListItem } from "@/src/components/MachineListItem";
@@ -28,6 +28,17 @@ type MachinesModel = Extract<
{ status: "success" } { status: "success" }
>["data"]; >["data"];
pyApi.open_file.receive((r) => {
if (r.op_key === "open_clan") {
console.log(r);
if (r.status === "error") return console.error(r.errors);
if (r.data) {
setCurrClanURI(r.data);
}
}
});
export const MachineListView: Component = () => { export const MachineListView: Component = () => {
const [{ machines, loading }, { getMachines }] = useMachineContext(); const [{ machines, loading }, { getMachines }] = useMachineContext();
@@ -77,7 +88,7 @@ export const MachineListView: Component = () => {
return ( return (
<div class="max-w-screen-lg"> <div class="max-w-screen-lg">
<div class="tooltip" data-tip="Open Clan"> <div class="tooltip tooltip-bottom" data-tip="Open Clan">
<button <button
class="btn btn-ghost" class="btn btn-ghost"
onClick={() => onClick={() =>
@@ -86,13 +97,14 @@ export const MachineListView: Component = () => {
title: "Open Clan", title: "Open Clan",
mode: "select_folder", mode: "select_folder",
}, },
op_key: "open_clan",
}) })
} }
> >
<span class="material-icons ">folder_open</span> <span class="material-icons ">folder_open</span>
</button> </button>
</div> </div>
<div class="tooltip" data-tip="Search install targets"> <div class="tooltip tooltip-bottom" data-tip="Search install targets">
<button <button
class="btn btn-ghost" class="btn btn-ghost"
onClick={() => pyApi.show_mdns.dispatch({})} onClick={() => pyApi.show_mdns.dispatch({})}
@@ -100,7 +112,7 @@ export const MachineListView: Component = () => {
<span class="material-icons ">search</span> <span class="material-icons ">search</span>
</button> </button>
</div> </div>
<div class="tooltip" data-tip="Refresh"> <div class="tooltip tooltip-bottom" data-tip="Refresh">
<button class="btn btn-ghost" onClick={() => getMachines()}> <button class="btn btn-ghost" onClick={() => getMachines()}>
<span class="material-icons ">refresh</span> <span class="material-icons ">refresh</span>
</button> </button>