UI: improve open clan from directory & list machines #1728

Merged
clan-bot merged 1 commits from hsjobeki/clan-core:hsjobeki-feat/clan-init into main 2024-07-10 09:15:58 +00:00
11 changed files with 95 additions and 73 deletions

View File

@ -16,7 +16,6 @@ let
> $out/config.json < ${pkgs.element-web}/config.json
ln -s $out/config.json $out/config.${nginx-vhost}.json
'';
in
# 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") {
return {
status: "success",
data: "/path/to/clan",
data: "/home/johannes/git/clan-core",
op_key,
};
}

View File

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

View File

@ -26,12 +26,16 @@ export const makeMachineContext = () => {
{ loading, machines },
{
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
setLoading(true);
pyApi.list_machines.dispatch({
debug: true,
flake_url: currClanURI(),
});
},
},
] as const;

View File

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

View File

@ -18,22 +18,24 @@ if (import.meta.env.DEV) {
console.log("Development mode");
// Load the debugger in development mode
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));
}, 200);
},
},
},
};
// Uncomment this block to use the Mock API
// 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
render(() => <App />, root!);

View File

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

View File

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

View File

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

View File

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