dashboard-v2 PR 2: frontend SPA + serve integration
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 16s

React 19 + Vite + Tailwind + wouter (tiny router, no external
state library). Consumes the /api/v2/* endpoints shipped in PR 1.
Serves under /v2/* so the legacy dashboard at / stays live.

Pages:
* CommandCenter (/)      — fleet strip + this-node stat tiles
* NodeDetail (/nodes/:name) — per-node deep dive
* StorageBrowser (/storage/{blobs,tags,refs,snapshots}) — tables
  with prefix filter
* RefTrackingPage (/refs/tracking) — grouped by repo

Backend changes:
* claw-store serve grows --v2-static-dir <path>
* build_app split into build_app_with_v2 for the extra static
  mount
* /v2/* falls through to index.html so wouter client routing works

New systemd unit: clawstor-dashboard.service. Points at both
static dirs; installs on any node.

dashboard/ (legacy) untouched. dashboard-v2/ built to
target/dashboard-v2/dist for deploy.

Deploy sequence per node:
1. cp target/release/claw-store  ~/clawstor-deploy/
2. rsync dashboard-v2/dist/      ~/clawstor-deploy/dashboard-v2/
3. cp deploy/systemd/clawstor-dashboard.service ~/.config/systemd/user/
4. systemctl --user daemon-reload && enable --now clawstor-dashboard.service

Cross-node fan-out for /api/v2/node/:name/status is PR 3.
Action POSTs (scrub/gc/snapshot/pin) are PR 4.
This commit is contained in:
Omar Sobh
2026-07-14 15:59:47 -07:00
parent b431475af7
commit f33468b7c2
32 changed files with 3264 additions and 5 deletions
+7 -2
View File
@@ -64,8 +64,13 @@ enum Cmd {
Serve {
#[arg(long, default_value = "7700")]
port: u16,
/// Legacy dashboard static assets (served under `/`).
#[arg(long)]
static_dir: Option<PathBuf>,
/// dashboard-v2 static assets (served under `/v2/*`).
/// See docs/dashboard-v2.md.
#[arg(long)]
v2_static_dir: Option<PathBuf>,
},
/// Mark a project as pinned — survives every GC pass (stale + LRU)
Pin { project: String },
@@ -350,8 +355,8 @@ async fn main() -> Result<()> {
Cmd::ListSnapshots { project } => cmd_list_snapshots(&cfg, &zfs, &project)?,
Cmd::Restore { project, snapshot } => cmd_restore(&cfg, &zfs, &project, &snapshot)?,
Cmd::Replicate => cmd_replicate(&cfg, &zfs)?,
Cmd::Serve { port, static_dir } =>
serve::run_server(cfg, manifest, port, static_dir).await?,
Cmd::Serve { port, static_dir, v2_static_dir } =>
serve::run_server(cfg, manifest, port, static_dir, v2_static_dir).await?,
Cmd::Pin { project } => cmd_set_pin(&manifest_path, &project, true)?,
Cmd::Unpin { project } => cmd_set_pin(&manifest_path, &project, false)?,
Cmd::ClusterProbe { peer } => cmd_cluster_probe(&cfg, &peer).await?,