Integrate test code improvements using web_template components
Lint / Python (flake8) (push) Successful in 45s
Lint / JS (eslint) (push) Successful in 8s
Security / Python Security (bandit) (push) Successful in 41s
Test / Python Tests (pytest) (push) Successful in 52s
Lint / Notify on failure (push) Has been skipped
Lint / Deploy (push) Successful in 3s
Lint / Python (flake8) (push) Successful in 45s
Lint / JS (eslint) (push) Successful in 8s
Security / Python Security (bandit) (push) Successful in 41s
Test / Python Tests (pytest) (push) Successful in 52s
Lint / Notify on failure (push) Has been skipped
Lint / Deploy (push) Successful in 3s
lt-alert: - Replace custom .stale-banner with lt-alert lt-alert--warning in app.js and links.html; remove stale-banner CSS, reuse lt-alert margin rule lt-progress: - Replace custom .traffic-bar-track/.traffic-bar-fill in links.html with lt-progress from base.css; TX uses default (orange), RX uses --cyan, both flip to --red when utilisation >85% (trafficBarClass helper) - Keep traffic layout classes (.traffic-section/.traffic-row etc.) for structure Suppression type badges: - Map target_type to distinct badge colors: host→badge-warning (orange), interface→badge-info (cyan), unifi_device→badge-purple (new alias using --accent-purple from base.css), all→badge-critical (red) - Applied in both server-rendered table (Jinja2 dict lookup) and renderActiveRows() JS Topology animated down-wire: - Add data-host attribute to .topo-v2-wire-10g/.topo-v2-wire-1g elements - updateTopology() toggles .wire-down class on the 10G drop-wire when host.status === 'down' - .wire-down CSS: animated repeating-linear-gradient dashed red line via wire-dash-anim @keyframes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -138,8 +138,8 @@
|
||||
<div class="topo-v2-host-wrap">
|
||||
<!-- dual-homing wires: 10G solid green + 1G dashed amber -->
|
||||
<div class="topo-v2-host-wires">
|
||||
<div class="topo-v2-wire-10g" title="10G SFP+ → USW-Agg"></div>
|
||||
<div class="topo-v2-wire-1g" title="1G → Pro 24 PoE"></div>
|
||||
<div class="topo-v2-wire-10g" data-host="{{ hname }}" title="10G SFP+ → USW-Agg"></div>
|
||||
<div class="topo-v2-wire-1g" data-host="{{ hname }}" title="1G → Pro 24 PoE"></div>
|
||||
</div>
|
||||
<!-- host box -->
|
||||
<div class="topo-v2-node topo-v2-host topo-host topo-v2-status-{{ st }}{{ ' topo-v2-offrack' if off_rack else '' }}"
|
||||
|
||||
+13
-6
@@ -38,6 +38,11 @@ function fmtRateBar(bytesPerSec, linkSpeedMbps) {
|
||||
return Math.min(100, (mbps / linkSpeedMbps) * 100);
|
||||
}
|
||||
|
||||
function trafficBarClass(pct, isTx) {
|
||||
if (pct > 85) return 'lt-progress--red';
|
||||
return isTx ? '' : 'lt-progress--cyan';
|
||||
}
|
||||
|
||||
function fmtSpeed(mbps) {
|
||||
if (mbps === null || mbps === undefined) return '–';
|
||||
if (mbps >= 1000) return (mbps/1000).toFixed(0) + ' Gbps';
|
||||
@@ -226,12 +231,12 @@ function renderIfaceCard(ifaceName, d) {
|
||||
<div class="traffic-section">
|
||||
<div class="traffic-row">
|
||||
<span class="traffic-label">TX</span>
|
||||
<div class="traffic-bar-track"><div class="traffic-bar-fill traffic-tx" style="width:${txPct}%"></div></div>
|
||||
<div class="lt-progress ${trafficBarClass(txPct, true)}"><div class="lt-progress-bar" style="width:${txPct}%"></div></div>
|
||||
<span class="traffic-value">${fmtRate(d.tx_bytes_rate)}</span>
|
||||
</div>
|
||||
<div class="traffic-row">
|
||||
<span class="traffic-label">RX</span>
|
||||
<div class="traffic-bar-track"><div class="traffic-bar-fill traffic-rx" style="width:${rxPct}%"></div></div>
|
||||
<div class="lt-progress ${trafficBarClass(rxPct, false)}"><div class="lt-progress-bar" style="width:${rxPct}%"></div></div>
|
||||
<span class="traffic-value">${fmtRate(d.rx_bytes_rate)}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -289,12 +294,12 @@ function renderPortCard(portName, d) {
|
||||
<div class="traffic-section">
|
||||
<div class="traffic-row">
|
||||
<span class="traffic-label">TX</span>
|
||||
<div class="traffic-bar-track"><div class="traffic-bar-fill traffic-tx" style="width:${txPct}%"></div></div>
|
||||
<div class="lt-progress ${trafficBarClass(txPct, true)}"><div class="lt-progress-bar" style="width:${txPct}%"></div></div>
|
||||
<span class="traffic-value">${fmtRate(d.tx_bytes_rate)}</span>
|
||||
</div>
|
||||
<div class="traffic-row">
|
||||
<span class="traffic-label">RX</span>
|
||||
<div class="traffic-bar-track"><div class="traffic-bar-fill traffic-rx" style="width:${rxPct}%"></div></div>
|
||||
<div class="lt-progress ${trafficBarClass(rxPct, false)}"><div class="lt-progress-bar" style="width:${rxPct}%"></div></div>
|
||||
<span class="traffic-value">${fmtRate(d.rx_bytes_rate)}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -477,10 +482,12 @@ function checkLinksStale(updatedStr) {
|
||||
if (!banner) {
|
||||
banner = document.createElement('div');
|
||||
banner.id = 'links-stale-banner';
|
||||
banner.className = 'stale-banner';
|
||||
banner.className = 'lt-alert lt-alert--warning';
|
||||
banner.innerHTML = '<span class="lt-alert-icon">⚠</span><div class="lt-alert-body"><div class="lt-alert-msg"></div></div>';
|
||||
document.getElementById('links-container').prepend(banner);
|
||||
}
|
||||
banner.textContent = `⚠ Link data may be stale — last updated ${Math.floor(age/60)}m ago.`;
|
||||
banner.querySelector('.lt-alert-msg').textContent =
|
||||
`Link data may be stale — last updated ${Math.floor(age/60)}m ago.`;
|
||||
banner.style.display = '';
|
||||
} else if (banner) {
|
||||
banner.style.display = 'none';
|
||||
|
||||
@@ -95,7 +95,8 @@
|
||||
<tbody>
|
||||
{% for s in active %}
|
||||
<tr id="sup-row-{{ s.id }}">
|
||||
<td><span class="lt-badge badge-info">{{ s.target_type }}</span></td>
|
||||
{%- set _sup_badge = {'host':'badge-warning','interface':'badge-info','unifi_device':'badge-purple','all':'badge-critical'} -%}
|
||||
<td><span class="lt-badge {{ _sup_badge.get(s.target_type, 'badge-neutral') }}">{{ s.target_type }}</span></td>
|
||||
<td>{{ s.target_name or 'all' }}</td>
|
||||
<td>{{ s.target_detail or '–' }}</td>
|
||||
<td>{{ s.reason }}</td>
|
||||
@@ -214,9 +215,10 @@
|
||||
return;
|
||||
}
|
||||
if (badge) badge.textContent = rows.length;
|
||||
const SUP_BADGE = {host:'badge-warning', interface:'badge-info', unifi_device:'badge-purple', all:'badge-critical'};
|
||||
const tbody = rows.map(s => `
|
||||
<tr id="sup-row-${s.id}">
|
||||
<td><span class="lt-badge badge-info">${lt.escHtml(s.target_type)}</span></td>
|
||||
<td><span class="lt-badge ${SUP_BADGE[s.target_type] || 'badge-neutral'}">${lt.escHtml(s.target_type)}</span></td>
|
||||
<td>${lt.escHtml(s.target_name || 'all')}</td>
|
||||
<td>${lt.escHtml(s.target_detail || '–')}</td>
|
||||
<td>${lt.escHtml(s.reason)}</td>
|
||||
|
||||
Reference in New Issue
Block a user