Merge pull request 'API: init op_key, improve seralisation & signature typing' (#1622) from hsjobeki/clan-core:hsjobeki-main into main
All checks were successful
deploy / deploy-docs (push) Successful in 20s
buildbot/nix-build .#checks.x86_64-linux.devShell-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.x86_64-linux.flash Build done.
buildbot/nix-build .#checks.x86_64-linux.package-editor Build done.
buildbot/nix-build .#checks.x86_64-linux.module-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.package-impure-checks Build done.
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-iso-installer Build done.
buildbot/nix-build .#checks.aarch64-darwin.nixos-flash-installer Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-test-backup Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-flash-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-app-no-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-apk 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-fakeroot Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-git Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-nix Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-app-pytest Build done.
buildbot/nix-build .#checks.x86_64-linux."clan-dep-python3.11-qemu" Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-rsync Build done.
buildbot/nix-build .#checks.x86_64-linux."clan-dep-python3.11-mypy" Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-sops Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-sshpass Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-tor Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-pytest-with-core Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-pytest-without-core Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-openssh Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-zbar Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-iso-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.check-for-breakpoints Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-age Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-clan-cli Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-webview-ui Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-clan-app 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.borgbackup Build done.
buildbot/nix-build .#checks.x86_64-linux.container 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-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.matrix-synapse Build done.
buildbot/nix-build .#checks.x86_64-linux.lib-jsonschema-nix-unit-tests Build done.
buildbot/nix-build .#checks.x86_64-linux.syncthing Build done.
buildbot/nix-build .#checks.x86_64-linux.zt-tcp-relay Build done.
buildbot/nix-build .#checks.x86_64-linux.test-installation Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-install-test-ubuntu-22-04 Build done.
buildbot/nix-eval Build done.
buildbot/nix-build .#checks.x86_64-linux.package-merge-after-ci Build done.
buildbot/nix-build .#checks.x86_64-linux.package-module-docs 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-deploy-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zt-tcp-relay Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-test-backup Build done.
buildbot/nix-build .#checks.x86_64-linux.package-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.postgresql Build done.
buildbot/nix-build .#checks.x86_64-linux.package-function-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.package-module-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.renderClanOptions Build done.
buildbot/nix-build .#checks.x86_64-linux.template-minimal Build done.
buildbot/nix-build .#checks.x86_64-linux.test-backups Build done.
buildbot/nix-build .#checks.x86_64-linux.secrets Build done.
buildbot/nix-build .#checks.x86_64-linux.package-iso-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-flash-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.treefmt Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-iso-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.wayland-proxy-virtwl Build done.
checks / checks-impure (push) Successful in 2m4s
All checks were successful
deploy / deploy-docs (push) Successful in 20s
buildbot/nix-build .#checks.x86_64-linux.devShell-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.x86_64-linux.flash Build done.
buildbot/nix-build .#checks.x86_64-linux.package-editor Build done.
buildbot/nix-build .#checks.x86_64-linux.module-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.package-impure-checks Build done.
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-iso-installer Build done.
buildbot/nix-build .#checks.aarch64-darwin.nixos-flash-installer Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-test_install_machine Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-test-backup Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-flash-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-app-no-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-apk 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-fakeroot Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-git Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-nix Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-app-pytest Build done.
buildbot/nix-build .#checks.x86_64-linux."clan-dep-python3.11-qemu" Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-rsync Build done.
buildbot/nix-build .#checks.x86_64-linux."clan-dep-python3.11-mypy" Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-sops Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-sshpass Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-tor Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-pytest-with-core Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-pytest-without-core Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-openssh Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-zbar Build done.
buildbot/nix-build .#checks.aarch64-linux.nixos-iso-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.check-for-breakpoints Build done.
buildbot/nix-build .#checks.x86_64-linux.clan-dep-age Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-clan-cli Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-webview-ui Build done.
buildbot/nix-build .#checks.x86_64-linux.devShell-clan-app 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.borgbackup Build done.
buildbot/nix-build .#checks.x86_64-linux.container 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-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.matrix-synapse Build done.
buildbot/nix-build .#checks.x86_64-linux.lib-jsonschema-nix-unit-tests Build done.
buildbot/nix-build .#checks.x86_64-linux.syncthing Build done.
buildbot/nix-build .#checks.x86_64-linux.zt-tcp-relay Build done.
buildbot/nix-build .#checks.x86_64-linux.test-installation Build done.
buildbot/nix-build .#checks.x86_64-linux.package-gui-install-test-ubuntu-22-04 Build done.
buildbot/nix-eval Build done.
buildbot/nix-build .#checks.x86_64-linux.package-merge-after-ci Build done.
buildbot/nix-build .#checks.x86_64-linux.package-module-docs 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-deploy-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.package-zt-tcp-relay Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-test-backup Build done.
buildbot/nix-build .#checks.x86_64-linux.package-docs Build done.
buildbot/nix-build .#checks.x86_64-linux.postgresql Build done.
buildbot/nix-build .#checks.x86_64-linux.package-function-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.package-module-schema Build done.
buildbot/nix-build .#checks.x86_64-linux.renderClanOptions Build done.
buildbot/nix-build .#checks.x86_64-linux.template-minimal Build done.
buildbot/nix-build .#checks.x86_64-linux.test-backups Build done.
buildbot/nix-build .#checks.x86_64-linux.secrets Build done.
buildbot/nix-build .#checks.x86_64-linux.package-iso-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-flash-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.treefmt Build done.
buildbot/nix-build .#checks.x86_64-linux.nixos-iso-installer Build done.
buildbot/nix-build .#checks.x86_64-linux.wayland-proxy-virtwl Build done.
checks / checks-impure (push) Successful in 2m4s
This commit is contained in:
commit
b28950f310
|
@ -38,8 +38,10 @@ def dataclass_to_dict(obj: Any) -> Any:
|
|||
return [dataclass_to_dict(item) for item in obj]
|
||||
elif isinstance(obj, dict):
|
||||
return {k: dataclass_to_dict(v) for k, v in obj.items()}
|
||||
else:
|
||||
elif isinstance(obj, Path):
|
||||
return str(obj)
|
||||
else:
|
||||
return obj
|
||||
|
||||
|
||||
# Implement the abstract open_file function
|
||||
|
@ -265,6 +267,7 @@ class WebView:
|
|||
result = handler_fn()
|
||||
else:
|
||||
reconciled_arguments = {}
|
||||
op_key = data.pop("op_key", None)
|
||||
for k, v in data.items():
|
||||
# Some functions expect to be called with dataclass instances
|
||||
# But the js api returns dictionaries.
|
||||
|
@ -276,8 +279,13 @@ class WebView:
|
|||
else:
|
||||
reconciled_arguments[k] = v
|
||||
|
||||
result = handler_fn(**reconciled_arguments)
|
||||
serialized = json.dumps(dataclass_to_dict(result))
|
||||
r = handler_fn(**reconciled_arguments)
|
||||
# Parse the result to a serializable dictionary
|
||||
# Echo back the "op_key" to the js api
|
||||
result = dataclass_to_dict(r)
|
||||
result["op_key"] = op_key
|
||||
|
||||
serialized = json.dumps(result)
|
||||
|
||||
# Use idle_add to queue the response call to js on the main GTK thread
|
||||
GLib.idle_add(self.return_data_to_js, method_name, serialized)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from functools import wraps
|
||||
from inspect import Parameter, signature
|
||||
from typing import Annotated, Any, Generic, Literal, TypeVar, get_type_hints
|
||||
|
||||
from clan_cli.errors import ClanError
|
||||
|
@ -21,17 +22,34 @@ class ApiError:
|
|||
class SuccessDataClass(Generic[ResponseDataType]):
|
||||
status: Annotated[Literal["success"], "The status of the response."]
|
||||
data: ResponseDataType
|
||||
op_key: str | None
|
||||
|
||||
|
||||
@dataclass
|
||||
class ErrorDataClass:
|
||||
status: Literal["error"]
|
||||
errors: list[ApiError]
|
||||
op_key: str | None
|
||||
|
||||
|
||||
ApiResponse = SuccessDataClass[ResponseDataType] | ErrorDataClass
|
||||
|
||||
|
||||
def update_wrapper_signature(wrapper: Callable, wrapped: Callable) -> None:
|
||||
sig = signature(wrapped)
|
||||
params = list(sig.parameters.values())
|
||||
|
||||
# Add 'op_key' parameter
|
||||
op_key_param = Parameter(
|
||||
"op_key", Parameter.KEYWORD_ONLY, default=None, annotation=str | None
|
||||
)
|
||||
params.append(op_key_param)
|
||||
|
||||
# Create a new signature
|
||||
new_sig = sig.replace(parameters=params)
|
||||
wrapper.__signature__ = new_sig # type: ignore
|
||||
|
||||
|
||||
class _MethodRegistry:
|
||||
def __init__(self) -> None:
|
||||
self._orig: dict[str, Callable[[Any], Any]] = {}
|
||||
|
@ -41,13 +59,16 @@ class _MethodRegistry:
|
|||
self._orig[fn.__name__] = fn
|
||||
|
||||
@wraps(fn)
|
||||
def wrapper(*args: Any, **kwargs: Any) -> ApiResponse[T]:
|
||||
def wrapper(
|
||||
*args: Any, op_key: str | None = None, **kwargs: Any
|
||||
) -> ApiResponse[T]:
|
||||
try:
|
||||
data: T = fn(*args, **kwargs)
|
||||
return SuccessDataClass(status="success", data=data)
|
||||
return SuccessDataClass(status="success", data=data, op_key=op_key)
|
||||
except ClanError as e:
|
||||
return ErrorDataClass(
|
||||
status="error",
|
||||
op_key=op_key,
|
||||
errors=[
|
||||
ApiError(
|
||||
message=e.msg,
|
||||
|
@ -63,6 +84,11 @@ class _MethodRegistry:
|
|||
orig_return_type = get_type_hints(fn).get("return")
|
||||
wrapper.__annotations__["return"] = ApiResponse[orig_return_type] # type: ignore
|
||||
|
||||
# Add additional argument for the operation key
|
||||
wrapper.__annotations__["op_key"] = str | None # type: ignore
|
||||
|
||||
update_wrapper_signature(wrapper, fn)
|
||||
|
||||
self._registry[fn.__name__] = wrapper
|
||||
return fn
|
||||
|
||||
|
@ -91,6 +117,12 @@ class _MethodRegistry:
|
|||
|
||||
return_type = serialized_hints.pop("return")
|
||||
|
||||
sig = signature(func)
|
||||
required_args = []
|
||||
for n, param in sig.parameters.items():
|
||||
if param.default == Parameter.empty:
|
||||
required_args.append(n)
|
||||
|
||||
api_schema["properties"][name] = {
|
||||
"type": "object",
|
||||
"required": ["arguments", "return"],
|
||||
|
@ -99,7 +131,7 @@ class _MethodRegistry:
|
|||
"return": return_type,
|
||||
"arguments": {
|
||||
"type": "object",
|
||||
"required": [k for k in serialized_hints.keys()],
|
||||
"required": required_args,
|
||||
"additionalProperties": False,
|
||||
"properties": serialized_hints,
|
||||
},
|
||||
|
|
|
@ -11,15 +11,17 @@ faker.option({
|
|||
|
||||
const getFakeResponse = (method: OperationNames, data: any) => {
|
||||
const fakeData = faker.generate(schema.properties[method].properties.return);
|
||||
|
||||
const { op_key } = data;
|
||||
if (method === "open_file") {
|
||||
return {
|
||||
status: "success",
|
||||
data: "/path/to/clan",
|
||||
op_key,
|
||||
};
|
||||
}
|
||||
|
||||
return fakeData;
|
||||
// @ts-expect-error: fakeData is guaranteed to always be some object
|
||||
return { ...fakeData, op_key };
|
||||
};
|
||||
|
||||
export { getFakeResponse };
|
||||
|
|
|
@ -7,6 +7,12 @@ import { Toaster } from "solid-toast";
|
|||
// Global state
|
||||
const [route, setRoute] = createSignal<Route>("machines");
|
||||
|
||||
const [currClanURI, setCurrClanURI] = createSignal<string>(
|
||||
"/home/johannes/1_clans/myclan"
|
||||
);
|
||||
|
||||
export { currClanURI, setCurrClanURI };
|
||||
|
||||
export { route, setRoute };
|
||||
|
||||
const App: Component = () => {
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
createEffect,
|
||||
} from "solid-js";
|
||||
import { OperationResponse, pyApi } from "./api";
|
||||
import { currClanURI } from "./App";
|
||||
|
||||
export const makeMachineContext = () => {
|
||||
const [machines, setMachines] =
|
||||
|
@ -27,7 +28,10 @@ export const makeMachineContext = () => {
|
|||
getMachines: () => {
|
||||
// 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: "." });
|
||||
pyApi.list_machines.dispatch({
|
||||
debug: true,
|
||||
flake_url: currClanURI(),
|
||||
});
|
||||
},
|
||||
},
|
||||
] as const;
|
||||
|
|
|
@ -11,6 +11,10 @@ export type SuccessData<T extends OperationNames> = Extract<
|
|||
OperationResponse<T>,
|
||||
{ status: "success" }
|
||||
>;
|
||||
export type ErrorData<T extends OperationNames> = Extract<
|
||||
OperationResponse<T>,
|
||||
{ status: "error" }
|
||||
>;
|
||||
|
||||
export type ClanOperations = {
|
||||
[K in OperationNames]: (str: string) => void;
|
||||
|
@ -33,6 +37,27 @@ declare global {
|
|||
// Make sure window.webkit is defined although the type is not correctly filled yet.
|
||||
window.clan = {} as ClanOperations;
|
||||
|
||||
const operations = schema.properties;
|
||||
const operationNames = Object.keys(operations) as OperationNames[];
|
||||
|
||||
type ObserverRegistry = {
|
||||
[K in OperationNames]: ((response: OperationResponse<K>) => void)[];
|
||||
};
|
||||
const obs: ObserverRegistry = operationNames.reduce(
|
||||
(acc, opName) => ({
|
||||
...acc,
|
||||
[opName]: [],
|
||||
}),
|
||||
{} as ObserverRegistry
|
||||
);
|
||||
|
||||
interface ReceiveOptions {
|
||||
/**
|
||||
* Calls only the registered function that has the same key as used with dispatch
|
||||
*
|
||||
*/
|
||||
fnKey: string;
|
||||
}
|
||||
function createFunctions<K extends OperationNames>(
|
||||
operationName: K
|
||||
): {
|
||||
|
@ -41,24 +66,27 @@ function createFunctions<K extends OperationNames>(
|
|||
} {
|
||||
return {
|
||||
dispatch: (args: OperationArgs<K>) => {
|
||||
console.log(
|
||||
`Operation: ${String(operationName)}, Arguments: ${JSON.stringify(args)}`
|
||||
);
|
||||
// console.log(
|
||||
// `Operation: ${String(operationName)}, Arguments: ${JSON.stringify(args)}`
|
||||
// );
|
||||
// Send the data to the gtk app
|
||||
window.webkit.messageHandlers.gtk.postMessage({
|
||||
method: operationName,
|
||||
data: args,
|
||||
});
|
||||
},
|
||||
receive: (fn: (response: OperationResponse<K>) => void) => {
|
||||
window.clan[operationName] = deserialize(fn);
|
||||
receive: (
|
||||
fn: (response: OperationResponse<K>) => void
|
||||
// options?: ReceiveOptions
|
||||
) => {
|
||||
obs[operationName].push(fn);
|
||||
window.clan[operationName] = (s: string) => {
|
||||
obs[operationName].forEach((f) => deserialize(f)(s));
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const operations = schema.properties;
|
||||
const operationNames = Object.keys(operations) as OperationNames[];
|
||||
|
||||
type PyApi = {
|
||||
[K in OperationNames]: {
|
||||
dispatch: (args: OperationArgs<K>) => void;
|
||||
|
@ -70,7 +98,6 @@ const deserialize =
|
|||
<T>(fn: (response: T) => void) =>
|
||||
(str: string) => {
|
||||
try {
|
||||
console.debug("Received data: ", str);
|
||||
fn(JSON.parse(str) as T);
|
||||
} catch (e) {
|
||||
alert(`Error parsing JSON: ${e}`);
|
||||
|
|
83
pkgs/webview-ui/app/src/components/MachineListItem.tsx
Normal file
83
pkgs/webview-ui/app/src/components/MachineListItem.tsx
Normal file
|
@ -0,0 +1,83 @@
|
|||
import { For, Show, createSignal } from "solid-js";
|
||||
import { ErrorData, SuccessData, pyApi } from "../api";
|
||||
import { currClanURI } from "../App";
|
||||
|
||||
interface MachineListItemProps {
|
||||
name: string;
|
||||
}
|
||||
|
||||
type MachineDetails = Record<string, SuccessData<"show_machine">["data"]>;
|
||||
|
||||
type MachineErrors = Record<string, ErrorData<"show_machine">["errors"]>;
|
||||
|
||||
const [details, setDetails] = createSignal<MachineDetails>({});
|
||||
const [errors, setErrors] = createSignal<MachineErrors>({});
|
||||
|
||||
pyApi.show_machine.receive((r) => {
|
||||
if (r.status === "error") {
|
||||
const { op_key } = r;
|
||||
if (op_key) {
|
||||
setErrors((e) => ({ ...e, [op_key]: r.errors }));
|
||||
}
|
||||
console.error(r.errors);
|
||||
}
|
||||
if (r.status === "success") {
|
||||
setDetails((d) => ({ ...d, [r.data.machine_name]: r.data }));
|
||||
}
|
||||
});
|
||||
|
||||
export const MachineListItem = (props: MachineListItemProps) => {
|
||||
const { name } = props;
|
||||
|
||||
pyApi.show_machine.dispatch({
|
||||
op_key: name,
|
||||
machine_name: name,
|
||||
debug: false,
|
||||
flake_url: currClanURI(),
|
||||
});
|
||||
|
||||
return (
|
||||
<li>
|
||||
<div class="card card-side m-2 bg-base-100 shadow-lg">
|
||||
<figure class="pl-2">
|
||||
<span class="material-icons content-center text-5xl">
|
||||
devices_other
|
||||
</span>
|
||||
</figure>
|
||||
<div class="card-body flex-row justify-between">
|
||||
<div class="flex flex-col">
|
||||
<h2 class="card-title">{name}</h2>
|
||||
<Show when={errors()[name]}>
|
||||
{(errors) => (
|
||||
<For each={errors()}>
|
||||
{(error) => (
|
||||
<p class="text-red-500">
|
||||
{error.message}: {error.description}
|
||||
</p>
|
||||
)}
|
||||
</For>
|
||||
)}
|
||||
</Show>
|
||||
<Show when={details()[name]}>
|
||||
{(details) => (
|
||||
<p
|
||||
classList={{
|
||||
"text-gray-400": !details().machine_description,
|
||||
"text-gray-600": !!details().machine_description,
|
||||
}}
|
||||
>
|
||||
{details().machine_description || "No description"}
|
||||
</p>
|
||||
)}
|
||||
</Show>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-ghost">
|
||||
<span class="material-icons">more_vert</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
};
|
|
@ -14,7 +14,6 @@ if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
|
|||
);
|
||||
}
|
||||
|
||||
console.log(import.meta.env);
|
||||
if (import.meta.env.DEV) {
|
||||
console.log("Development mode");
|
||||
// Load the debugger in development mode
|
||||
|
@ -27,7 +26,7 @@ if (import.meta.env.DEV) {
|
|||
console.debug("Python API call", { method, data });
|
||||
setTimeout(() => {
|
||||
const mock = getFakeResponse(method, data);
|
||||
console.log("mock", { mock });
|
||||
console.log("Returning mock-data: ", { mock });
|
||||
|
||||
window.clan[method](JSON.stringify(mock));
|
||||
}, 200);
|
||||
|
|
|
@ -10,6 +10,7 @@ import { useMachineContext } from "../../Config";
|
|||
import { route } from "@/src/App";
|
||||
import { OperationResponse, pyApi } from "@/src/api";
|
||||
import toast from "solid-toast";
|
||||
import { MachineListItem } from "@/src/components/MachineListItem";
|
||||
|
||||
type FilesModel = Extract<
|
||||
OperationResponse<"get_directory">,
|
||||
|
@ -99,37 +100,7 @@ export const MachineListView: Component = () => {
|
|||
<Match when={!loading()}>
|
||||
<ul>
|
||||
<For each={data()}>
|
||||
{(entry) => (
|
||||
<li>
|
||||
<div class="card card-side m-2 bg-base-100 shadow-lg">
|
||||
<figure class="pl-2">
|
||||
<span class="material-icons content-center text-5xl">
|
||||
devices_other
|
||||
</span>
|
||||
</figure>
|
||||
<div class="card-body flex-row justify-between">
|
||||
<div class="flex flex-col">
|
||||
<h2 class="card-title">{entry}</h2>
|
||||
{/*
|
||||
<p
|
||||
classList={{
|
||||
"text-gray-400": !entry.machine_description,
|
||||
"text-gray-600": !!entry.machine_description,
|
||||
}}
|
||||
>
|
||||
{entry.machine_description || "No description"}
|
||||
</p>
|
||||
*/}
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-ghost">
|
||||
<span class="material-icons">more_vert</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
)}
|
||||
{(entry) => <MachineListItem name={entry} />}
|
||||
</For>
|
||||
</ul>
|
||||
</Match>
|
||||
|
|
Loading…
Reference in New Issue
Block a user