Add LDAP avatar photos, UX polish, and TDS component upgrades
Lint / Python (flake8) (push) Successful in 1m13s
Lint / JS (eslint) (push) Successful in 9s
Security / Python Security (bandit) (push) Failing after 45s
Test / Python Tests (pytest) (push) Successful in 57s
Lint / Notify on failure (push) Has been skipped
Lint / Deploy (push) Successful in 5s
Lint / Python (flake8) (push) Successful in 1m13s
Lint / JS (eslint) (push) Successful in 9s
Security / Python Security (bandit) (push) Failing after 45s
Test / Python Tests (pytest) (push) Successful in 57s
Lint / Notify on failure (push) Has been skipped
Lint / Deploy (push) Successful in 5s
- Add /api/avatar endpoint querying lldap for user jpegPhoto; disk cache with sentinel pattern avoids repeat LDAP hits for users without photos - Add ldap3 dependency and ldap config block to config.json - Wire lt-avatar img overlay in base.html with capture-phase error fallback (lt-avatar-img-err) to reveal initials when image is absent - Fix lt-avatar CSS shim: position:relative + absolute inset on img (local base.css was missing these; added to style.css) - Replace all empty-state paragraphs with proper lt-empty-state markup (icon + title + body) across index, suppressions, inspector, app.js - Add lt-spinner--cyan next to refresh button; shows during refreshAll() - Replace inspector panel-section-title with lt-divider throughout - Add data-tooltip attributes to SFP DOM metrics, TX/RX/Carrier/Duplex/ Auto-neg/Error labels in links.html and inspector panel - Add tooltips to events table column headers (Sev, First Seen, Failures) - Fix links.html host panel timestamp (was reading sample.updated which is always undefined; now uses data.updated) - Fix UniFi status text casing (Online→ONLINE to match server render) - Remove dead topo-status-* class manipulation from updateTopology() - Always render alert-count-badge; toggle display:none when count is 0 - Fix double UniFi get_devices() call in monitor.py run loop - Fix chip-critical animation (was using green pulse-glow; now red) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+11
-11
@@ -114,7 +114,7 @@ function portBlockHtml(idx, port, swName, sfpBlock) {
|
||||
const speedHtml = speedTxt ? `<span class="port-speed">${speedTxt}</span>` : '';
|
||||
return `<div class="switch-port-block ${state}${sfpCls}"
|
||||
data-switch="${escHtml(swName)}" data-port-idx="${idx}"
|
||||
title="${title}"
|
||||
title="${title}" aria-label="${title}"
|
||||
data-action="select-port"><span class="port-num">${numLabel}</span>${speedHtml}${lldpHtml}</div>`;
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ function renderPanel(swName, idx) {
|
||||
const poeMaxStr = d.poe_max_power != null ? ` / max ${d.poe_max_power.toFixed(1)}W` : '';
|
||||
const poeCurStr = (d.poe_power != null && d.poe_power > 0) ? ` / draw <span class="val-amber">${d.poe_power.toFixed(1)}W</span>` : '';
|
||||
poeHtml = `
|
||||
<div class="panel-section-title">PoE</div>
|
||||
<div class="lt-divider"><span class="lt-divider-label">PoE</span></div>
|
||||
<div class="panel-row"><span class="panel-label">Class</span><span class="panel-val">class ${d.poe_class}${poeMaxStr}</span></div>
|
||||
${d.poe_power != null ? `<div class="panel-row"><span class="panel-label">Draw</span><span class="panel-val">${d.poe_power > 0 ? `<span class="val-amber">${d.poe_power.toFixed(1)}W</span>` : '0W'}</span></div>` : ''}
|
||||
${d.poe_mode ? `<div class="panel-row"><span class="panel-label">Mode</span><span class="panel-val">${escHtml(d.poe_mode)}</span></div>` : ''}`;
|
||||
@@ -269,16 +269,16 @@ function renderPanel(swName, idx) {
|
||||
let trafficHtml = '';
|
||||
if (d.tx_bytes_rate != null || d.rx_bytes_rate != null) {
|
||||
trafficHtml = `
|
||||
<div class="panel-section-title">Traffic</div>
|
||||
<div class="panel-row"><span class="panel-label">TX</span><span class="panel-val">${fmtRate(d.tx_bytes_rate)}</span></div>
|
||||
<div class="panel-row"><span class="panel-label">RX</span><span class="panel-val">${fmtRate(d.rx_bytes_rate)}</span></div>`;
|
||||
<div class="lt-divider"><span class="lt-divider-label">Traffic</span></div>
|
||||
<div class="panel-row"><span class="panel-label" data-tooltip="Transmit — outgoing from this port">TX</span><span class="panel-val">${fmtRate(d.tx_bytes_rate)}</span></div>
|
||||
<div class="panel-row"><span class="panel-label" data-tooltip="Receive — incoming to this port">RX</span><span class="panel-val">${fmtRate(d.rx_bytes_rate)}</span></div>`;
|
||||
}
|
||||
|
||||
// Errors / drops section
|
||||
let errHtml = '';
|
||||
if (d.tx_errs_rate != null || d.rx_errs_rate != null) {
|
||||
errHtml = `
|
||||
<div class="panel-section-title">Errors / Drops</div>
|
||||
<div class="lt-divider"><span class="lt-divider-label">Errors / Drops</span></div>
|
||||
<div class="panel-row"><span class="panel-label">TX Err</span><span class="panel-val">${fmtErrors(d.tx_errs_rate)}</span></div>
|
||||
<div class="panel-row"><span class="panel-label">RX Err</span><span class="panel-val">${fmtErrors(d.rx_errs_rate)}</span></div>
|
||||
<div class="panel-row"><span class="panel-label">TX Drop</span><span class="panel-val">${fmtErrors(d.tx_drops_rate)}</span></div>
|
||||
@@ -291,7 +291,7 @@ function renderPanel(swName, idx) {
|
||||
if (d.lldp && d.lldp.system_name) {
|
||||
const l = d.lldp;
|
||||
lldpHtml = `
|
||||
<div class="panel-section-title">LLDP Neighbor</div>
|
||||
<div class="lt-divider"><span class="lt-divider-label">LLDP Neighbor</span></div>
|
||||
<div class="panel-row"><span class="panel-label">System</span><span class="panel-val val-cyan">${escHtml(l.system_name)}</span></div>
|
||||
${l.port_id ? `<div class="panel-row"><span class="panel-label">Port</span><span class="panel-val">${escHtml(l.port_id)}</span></div>` : ''}
|
||||
${l.port_desc ? `<div class="panel-row"><span class="panel-label">Port Desc</span><span class="panel-val">${escHtml(l.port_desc)}</span></div>` : ''}
|
||||
@@ -333,11 +333,11 @@ function renderPanel(swName, idx) {
|
||||
<button class="panel-close" data-action="close-panel" aria-label="Close panel">✕</button>
|
||||
</div>
|
||||
|
||||
<div class="panel-section-title">Link</div>
|
||||
<div class="lt-divider"><span class="lt-divider-label">Link</span></div>
|
||||
<div class="panel-row"><span class="panel-label">Status</span><span class="panel-val">${upStr}</span></div>
|
||||
<div class="panel-row"><span class="panel-label">Speed</span><span class="panel-val">${speedStr}</span></div>
|
||||
<div class="panel-row"><span class="panel-label">Duplex</span><span class="panel-val">${duplexStr}</span></div>
|
||||
<div class="panel-row"><span class="panel-label">Auto-neg</span><span class="panel-val val-neutral">${autoneg}</span></div>
|
||||
<div class="panel-row"><span class="panel-label" data-tooltip="Full = simultaneous send/receive. Half = one direction at a time.">Duplex</span><span class="panel-val">${duplexStr}</span></div>
|
||||
<div class="panel-row"><span class="panel-label" data-tooltip="Autonegotiation: NIC and switch automatically agree speed and duplex.">Auto-neg</span><span class="panel-val val-neutral">${autoneg}</span></div>
|
||||
<div class="panel-row"><span class="panel-label">Media</span><span class="panel-val">${escHtml(mediaStr)}</span></div>
|
||||
|
||||
${poeHtml}
|
||||
@@ -392,7 +392,7 @@ function buildPathDebug(swName, swPort, serverName, ifaceName, svrData) {
|
||||
: '';
|
||||
|
||||
return `
|
||||
<div class="panel-section-title">Path Debug <span class="path-conn-type">${escHtml(connType)}</span></div>
|
||||
<div class="lt-divider"><span class="lt-divider-label">Path Debug · ${escHtml(connType)}</span></div>
|
||||
${duplexWarnHtml}${speedWarnHtml}
|
||||
<div class="path-debug-cols">
|
||||
<div class="path-col">
|
||||
|
||||
Reference in New Issue
Block a user