mirror of
https://github.com/hansjone/netx.git
synced 2026-10-10 18:03:14 +08:00
Switch CLI parsing to TextFSM and polish topology/workbench UX.
Use custom cli_templates plus community ntc-templates for LLDP and port traffic across ZTE/Huawei/Cisco/H3C/Juniper/Nokia, drop regex parsers, and surface Admin/Phy/Prot on port discover. Also batch-add topology NEs and tighten workbench branding. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
60186a12e3
commit
393fd0e0b4
41 changed files with 1771 additions and 1075 deletions
|
|
@ -41,6 +41,42 @@ function statusTone(status: string): "running" | "paused" | "stopped" | "other"
|
|||
return "other";
|
||||
}
|
||||
|
||||
function upDownPillClass(value: string): string {
|
||||
const v = String(value || "").trim().toLowerCase();
|
||||
if (v === "up") return "conn-pill conn-pill--up";
|
||||
if (v === "down") return "conn-pill conn-pill--down";
|
||||
return "conn-pill conn-pill--unknown";
|
||||
}
|
||||
|
||||
function PortUpDownCell({
|
||||
admin,
|
||||
phy,
|
||||
prot,
|
||||
labels,
|
||||
}: {
|
||||
admin?: string;
|
||||
phy?: string;
|
||||
prot?: string;
|
||||
labels: { admin: string; phy: string; prot: string };
|
||||
}) {
|
||||
const a = String(admin || "").trim() || "—";
|
||||
const p = String(phy || "").trim() || "—";
|
||||
const r = String(prot || "").trim() || "—";
|
||||
return (
|
||||
<span className="pt-port-updown" title={`${labels.admin}/${labels.phy}/${labels.prot}`}>
|
||||
<span className={upDownPillClass(a)} title={labels.admin}>
|
||||
{a}
|
||||
</span>
|
||||
<span className={upDownPillClass(p)} title={labels.phy}>
|
||||
{p}
|
||||
</span>
|
||||
<span className={upDownPillClass(r)} title={labels.prot}>
|
||||
{r}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function formatPortTrafficLogMessage(
|
||||
raw: string,
|
||||
t: (key: string, vars?: Record<string, string | number>) => string,
|
||||
|
|
@ -442,6 +478,15 @@ export function PortTrafficPage() {
|
|||
};
|
||||
|
||||
const pickedList = useMemo(() => Object.values(pickedIfnames), [pickedIfnames]);
|
||||
const discoveredByIfname = useMemo(
|
||||
() => Object.fromEntries(ports.map((p) => [p.ifname, p])),
|
||||
[ports],
|
||||
);
|
||||
const upDownLabels = {
|
||||
admin: t("portTraffic.col.admin"),
|
||||
phy: t("portTraffic.col.phy"),
|
||||
prot: t("portTraffic.col.prot"),
|
||||
};
|
||||
|
||||
const submitWizard = () => {
|
||||
if (!selectedNe) {
|
||||
|
|
@ -801,10 +846,10 @@ export function PortTrafficPage() {
|
|||
<thead>
|
||||
<tr>
|
||||
<th />
|
||||
<th>Interface</th>
|
||||
<th>BW</th>
|
||||
<th>Admin/Phy/Prot</th>
|
||||
<th>Description</th>
|
||||
<th>{t("portTraffic.col.ifname")}</th>
|
||||
<th>{t("portTraffic.col.bw")}</th>
|
||||
<th>{t("portTraffic.col.upDown")}</th>
|
||||
<th>{t("portTraffic.col.description")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -820,7 +865,12 @@ export function PortTrafficPage() {
|
|||
<td>{p.ifname}</td>
|
||||
<td>{p.bw_raw || formatBw(p.bw_bps)}</td>
|
||||
<td>
|
||||
{p.admin}/{p.phy}/{p.prot}
|
||||
<PortUpDownCell
|
||||
admin={p.admin}
|
||||
phy={p.phy}
|
||||
prot={p.prot}
|
||||
labels={upDownLabels}
|
||||
/>
|
||||
</td>
|
||||
<td>{p.description || "—"}</td>
|
||||
</tr>
|
||||
|
|
@ -887,11 +937,24 @@ export function PortTrafficPage() {
|
|||
</p>
|
||||
<p>{t("portTraffic.selectedPorts", { count: String(pickedList.length) })}</p>
|
||||
<ul className="pt-wizard__confirm-list">
|
||||
{pickedList.slice(0, 40).map((p) => (
|
||||
<li key={p.ifname}>
|
||||
{p.ifname} ({formatBw(p.bw_bps || 0)})
|
||||
</li>
|
||||
))}
|
||||
{pickedList.slice(0, 40).map((p) => {
|
||||
const disc = discoveredByIfname[p.ifname];
|
||||
return (
|
||||
<li key={p.ifname} className="pt-wizard__confirm-port">
|
||||
<span>
|
||||
{p.ifname} ({formatBw(p.bw_bps || 0)})
|
||||
</span>
|
||||
{disc ? (
|
||||
<PortUpDownCell
|
||||
admin={disc.admin}
|
||||
phy={disc.phy}
|
||||
prot={disc.prot}
|
||||
labels={upDownLabels}
|
||||
/>
|
||||
) : null}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
{pickedList.length > 40 ? <li>… +{pickedList.length - 40}</li> : null}
|
||||
</ul>
|
||||
<button type="button" className="btn-primary" disabled={createMut.isPending} onClick={submitWizard}>
|
||||
|
|
@ -982,9 +1045,10 @@ export function PortTrafficPage() {
|
|||
<thead>
|
||||
<tr>
|
||||
<th />
|
||||
<th>Interface</th>
|
||||
<th>BW</th>
|
||||
<th>Description</th>
|
||||
<th>{t("portTraffic.col.ifname")}</th>
|
||||
<th>{t("portTraffic.col.bw")}</th>
|
||||
<th>{t("portTraffic.col.upDown")}</th>
|
||||
<th>{t("portTraffic.col.description")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -999,6 +1063,14 @@ export function PortTrafficPage() {
|
|||
</td>
|
||||
<td>{p.ifname}</td>
|
||||
<td>{p.bw_raw || formatBw(p.bw_bps)}</td>
|
||||
<td>
|
||||
<PortUpDownCell
|
||||
admin={p.admin}
|
||||
phy={p.phy}
|
||||
prot={p.prot}
|
||||
labels={upDownLabels}
|
||||
/>
|
||||
</td>
|
||||
<td>{p.description || "—"}</td>
|
||||
</tr>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ export function PortTrafficWallPage() {
|
|||
useEffect(() => {
|
||||
if (!board?.name) return;
|
||||
try {
|
||||
document.title = "NetX";
|
||||
document.title = "NETX";
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue