feat(web): add Ops page and proxy control on :8600

Vite listens on 8500 and proxies /ops to the control plane. Admin Ops UI
covers pause/resume, scale, drain/force restart, and restart-needed banner.

Co-authored-by: Nasyarobby Putra <nasyarobby@gmail.com>
This commit is contained in:
Cursor Agent
2026-08-19 10:55:02 +00:00
co-authored by nsrb
parent 756ba8a7ac
commit 4e6c336ae8
21 changed files with 2931 additions and 269 deletions
+24 -3
View File
@@ -1,4 +1,4 @@
import { NavLink, useNavigate } from "react-router-dom";
import { Link, NavLink, useNavigate } from "react-router-dom";
import {
LuActivity,
LuCode,
@@ -10,12 +10,13 @@ import {
LuLogOut,
LuMenu,
LuMoon,
LuServer,
LuShield,
LuSun,
LuTags,
LuUsers,
} from "react-icons/lu";
import { useLogout } from "../api/hooks.js";
import { useLogout, useOpsStatus } from "../api/hooks.js";
import { brandMark } from "../theme/brand.js";
import { useTheme } from "../theme.jsx";
@@ -34,6 +35,8 @@ export function Layout({ user, children }) {
const { theme, toggle } = useTheme();
const logout = useLogout();
const navigate = useNavigate();
const ops = useOpsStatus(user.role === "admin");
const restartNeeded = Boolean(ops.data?.desired?.restartNeeded);
const navItems = [
...links,
@@ -41,6 +44,7 @@ export function Layout({ user, children }) {
? [
{ to: "/secrets", label: "Secrets", icon: LuKey },
{ to: "/users", label: "Users", icon: LuUsers },
{ to: "/ops", label: "Ops", icon: LuServer },
]
: []),
];
@@ -88,7 +92,24 @@ export function Layout({ user, children }) {
</button>
</div>
</div>
<main className="flex-1 p-4">{children}</main>
<main className="flex-1 p-4">
{restartNeeded ? (
<div className="alert alert-warning mb-4 text-sm">
<span>
Config generation changed
{ops.data?.desired?.restartReason
? ` (${ops.data.desired.restartReason})`
: ""}
.{" "}
<Link to="/ops" className="link font-medium">
Drain restart from Ops
</Link>{" "}
to apply on HTTP + workers.
</span>
</div>
) : null}
{children}
</main>
</div>
<div className="drawer-side z-20">
<label htmlFor="nav-drawer" aria-label="Close menu" className="drawer-overlay" />