diff --git a/app/src/api.ts b/app/src/api.ts index 049c1d3..caf2990 100644 --- a/app/src/api.ts +++ b/app/src/api.ts @@ -844,6 +844,8 @@ const realApi = { }), mirror: () => request("/api/mirror"), + managementPort: () => + request("/api/management-port"), setMirror: (monitor: string, sources: string[]) => request<{ status: string }>("/api/mirror", { method: "POST", diff --git a/app/src/components/ports/EthPortsCard.tsx b/app/src/components/ports/EthPortsCard.tsx index 6b26e4c..adf4486 100644 --- a/app/src/components/ports/EthPortsCard.tsx +++ b/app/src/components/ports/EthPortsCard.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; -import { Cable, Pencil, Zap } from "lucide-react"; +import { Cable, Lock, Pencil, Zap } from "lucide-react"; import { api } from "../../api"; import type { EthPort, PhysPortsProbe, SwitchPort, SwitchProbe } from "../../types"; import { @@ -45,6 +45,19 @@ export function EthPortsCard({ ports, index = 0, className = "md:col-span-2" }: const [phys, setPhys] = useState(); const physRequested = useRef(false); + // Boca de gestion (#543): badge con candado en la baldosa. Se pide de + // forma perezosa tras montar: la deteccion (gateway -> ARP -> FDB) tarda + // unos cientos de ms en switches densos y no debe retrasar el primer + // pintado. Sin probe o sin deducir: no hay badge, el chasis queda igual. + const [mgmtPort, setMgmtPort] = useState(); + useEffect(() => { + let alive = true; + api.managementPort() + .then((r) => { if (alive && r.port) setMgmtPort(r.port); }) + .catch(() => { /* sin dato, sin badge */ }); + return () => { alive = false; }; + }, []); + const load = useCallback(async () => { try { setProbe(await api.switchPorts()); @@ -170,13 +183,14 @@ export function EthPortsCard({ ports, index = 0, className = "md:col-span-2" }: : p.devices.length > 1 ? t("ports.unmanagedN", { count: p.devices.length }) : t("ports.busy"); const tier = speedTier(p); + const isMgmt = mgmtPort === p.name; const led = adminDown ? "bg-danger" : !p.up ? "bg-border-strong" : tier.tone === "ok" ? "bg-ok" : tier.tone === "warn" ? "bg-warn" : "bg-danger"; return (