feat(web-ui): Remote Updates dashboard page — push code to workers from the UI

React component for /swarm-updates: per-host table polled every 10s,
row actions for Push Update / Update Updater / Rollback, a fleet-wide
'Push to All' modal with the include_self toggle, and toast feedback
per result.

Admin-only (both server-gated and UI-gated). Unreachable hosts surface
as an explicit state; actions are disabled on them. Rollback is
disabled when the worker has no previous release slot (previous_sha
null from /hosts).
This commit is contained in:
2026-04-19 01:03:04 -04:00
parent a266d6b17e
commit 7894b9e073
3 changed files with 334 additions and 1 deletions

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import { NavLink } from 'react-router-dom';
import { Menu, X, Search, Activity, LayoutDashboard, Terminal, Settings, LogOut, Server, Archive } from 'lucide-react';
import { Menu, X, Search, Activity, LayoutDashboard, Terminal, Settings, LogOut, Server, Archive, Package } from 'lucide-react';
import './Layout.css';
interface LayoutProps {
@@ -46,6 +46,7 @@ const Layout: React.FC<LayoutProps> = ({ children, onLogout, onSearch }) => {
<NavItem to="/live-logs" icon={<Terminal size={20} />} label="Live Logs" open={sidebarOpen} />
<NavItem to="/bounty" icon={<Archive size={20} />} label="Bounty" open={sidebarOpen} />
<NavItem to="/attackers" icon={<Activity size={20} />} label="Attackers" open={sidebarOpen} />
<NavItem to="/swarm-updates" icon={<Package size={20} />} label="Remote Updates" open={sidebarOpen} />
<NavItem to="/config" icon={<Settings size={20} />} label="Config" open={sidebarOpen} />
</nav>