feat(console-web): replace TanStack UI with Solid host pages
- move the management frontend under the wasmeld-console crate\n- use a persistent Host shell with disposable iframe page documents\n- version Host/Page postMessage state and command contracts\n- migrate runtime, service, WIT, invocation, and settings workflows\n- add Tailwind CSS v4, responsive layouts, and Host-owned dialogs\n- emit a dependency-free PWA worker with API cache exclusions\n- remove the superseded root TanStack Start application
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { CloudUpload, Filter, RefreshCw } from "lucide-solid";
|
||||
import { createMemo, createSignal, Show } from "solid-js";
|
||||
import { PageHeading } from "../../components/ui/page-heading";
|
||||
import { ServiceTable } from "../../components/ui/service-table";
|
||||
import { servicesFrom } from "../../lib/view-state";
|
||||
import type { ServiceStatus } from "../../lib/model";
|
||||
import type { PageProps } from "../types";
|
||||
|
||||
export default function ServicesPage(props: PageProps) {
|
||||
const [status, setStatus] = createSignal<"all" | ServiceStatus>("all");
|
||||
const services = createMemo(() => servicesFrom(props.state()));
|
||||
const filtered = createMemo(() => {
|
||||
const query = props.state()?.query.trim().toLowerCase() ?? "";
|
||||
return services().filter(
|
||||
(service) =>
|
||||
(status() === "all" || service.status === status()) &&
|
||||
(!query ||
|
||||
service.id.toLowerCase().includes(query) ||
|
||||
service.revision.toLowerCase().includes(query) ||
|
||||
service.artifact.toLowerCase().includes(query)),
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<main class="page">
|
||||
<PageHeading
|
||||
eyebrow="COMPONENTS"
|
||||
title="服务版本"
|
||||
description="管理不可变 Component Revision、Actor 状态和对外 Deployment。"
|
||||
actions={
|
||||
<>
|
||||
<label class="relative">
|
||||
<Filter
|
||||
class="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted"
|
||||
size={14}
|
||||
/>
|
||||
<select
|
||||
class="select w-36 pl-9"
|
||||
value={status()}
|
||||
onChange={(event) => setStatus(event.currentTarget.value as "all" | ServiceStatus)}
|
||||
>
|
||||
<option value="all">全部状态</option>
|
||||
<option value="running">运行中</option>
|
||||
<option value="stopped">已停止</option>
|
||||
<option value="faulted">故障</option>
|
||||
</select>
|
||||
</label>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
onClick={() => props.command({ type: "open-register" })}
|
||||
>
|
||||
<CloudUpload size={16} />
|
||||
注册组件
|
||||
</button>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<section class="panel">
|
||||
<div class="panel-header">
|
||||
<div>
|
||||
<h2>已注册版本</h2>
|
||||
<p>{filtered().length} 个匹配项</p>
|
||||
</div>
|
||||
<button class="icon-btn" title="刷新" onClick={() => props.command({ type: "refresh" })}>
|
||||
<RefreshCw size={16} />
|
||||
</button>
|
||||
</div>
|
||||
<Show when={props.state()}>
|
||||
{(state) => (
|
||||
<ServiceTable services={filtered()} state={state()} command={props.command} />
|
||||
)}
|
||||
</Show>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user