UI: improve open clan from directory & list machines #1728
@ -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
|
||||
{
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
@ -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" />,
|
||||
|
@ -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;
|
||||
|
@ -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">
|
||||
|
@ -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 */}
|
||||
|
@ -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!);
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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({})}
|
||||
|
@ -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({})}
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user