dashboard: spinners on in-flight lifecycle actions + cleaner row layout

backend:
- TransientKind grows Starting / Stopping / Restarting / Rebuilding /
  Destroying alongside the existing Spawning. each dashboard handler
  (start/restart/kill/rebuild/destroy) wraps the lifecycle call with
  set_transient + clear_transient so the dashboard knows what's in
  flight. transient kind is surfaced inline on ContainerView.pending
  (existing-container actions) — only Spawning (pre-creation) lands
  in the separate transients list.

frontend:
- container row is now two lines: identity + meta on top, action
  buttons below. less cluttered, leaves room for the pending state
  pill. pending rows dim their actions and surface a pulsing
  '◐ spawning… / starting… / stopping… / restarting… / rebuilding…
  / destroying…' indicator next to the name.
- 'needs login' / 'needs update' chips moved into a unified .badge
  styling for consistency.
- auto-refresh kicks in not only on transient spawn but on any
  container with a pending action.
This commit is contained in:
müde 2026-05-15 19:49:43 +02:00
parent 300be8afa9
commit c337cc06f8
5 changed files with 157 additions and 38 deletions

View file

@ -140,7 +140,12 @@ pub async fn destroy(coord: &Coordinator, name: &str, purge: bool) -> Result<()>
bail!("refusing to destroy the manager ({name})");
}
tracing::info!(%name, purge, "destroy");
lifecycle::destroy(name).await?;
coord.set_transient(name, TransientKind::Destroying);
let result = lifecycle::destroy(name).await;
if result.is_err() {
coord.clear_transient(name);
}
result?;
coord.unregister_agent(name);
let runtime = Coordinator::agent_dir(name);
if runtime.exists() {
@ -166,6 +171,7 @@ pub async fn destroy(coord: &Coordinator, name: &str, purge: bool) -> Result<()>
"agent destroyed"
},
);
coord.clear_transient(name);
coord.notify_manager(&HelperEvent::Destroyed {
agent: name.to_owned(),
});