Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 40a0c2af78 |
@@ -222,10 +222,17 @@ def get_status_summary() -> dict:
|
|||||||
WHERE resolved_at IS NULL GROUP BY severity"""
|
WHERE resolved_at IS NULL GROUP BY severity"""
|
||||||
)
|
)
|
||||||
counts = {r['severity']: r['cnt'] for r in cur.fetchall()}
|
counts = {r['severity']: r['cnt'] for r in cur.fetchall()}
|
||||||
|
cur.execute(
|
||||||
|
"""SELECT COUNT(*) as cnt FROM network_events
|
||||||
|
WHERE resolved_at IS NOT NULL
|
||||||
|
AND resolved_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)"""
|
||||||
|
)
|
||||||
|
resolved_24h = cur.fetchone()['cnt']
|
||||||
return {
|
return {
|
||||||
'critical': counts.get('critical', 0),
|
'critical': counts.get('critical', 0),
|
||||||
'warning': counts.get('warning', 0),
|
'warning': counts.get('warning', 0),
|
||||||
'info': counts.get('info', 0),
|
'info': counts.get('info', 0),
|
||||||
|
'resolved_24h': resolved_24h,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -92,8 +92,10 @@ function updateStatusBar(summary, lastCheck, daemonOk) {
|
|||||||
// Update stat cards
|
// Update stat cards
|
||||||
const scCrit = document.getElementById('stat-critical-val');
|
const scCrit = document.getElementById('stat-critical-val');
|
||||||
const scWarn = document.getElementById('stat-warning-val');
|
const scWarn = document.getElementById('stat-warning-val');
|
||||||
|
const scRes = document.getElementById('stat-resolved-val');
|
||||||
if (scCrit) scCrit.textContent = critCount;
|
if (scCrit) scCrit.textContent = critCount;
|
||||||
if (scWarn) scWarn.textContent = warnCount;
|
if (scWarn) scWarn.textContent = warnCount;
|
||||||
|
if (scRes && summary.resolved_24h != null) scRes.textContent = summary.resolved_24h;
|
||||||
const statCritCard = document.getElementById('stat-critical');
|
const statCritCard = document.getElementById('stat-critical');
|
||||||
if (statCritCard) statCritCard.classList.toggle('lt-stat-card--alert', critCount > 0);
|
if (statCritCard) statCritCard.classList.toggle('lt-stat-card--alert', critCount > 0);
|
||||||
|
|
||||||
|
|||||||
@@ -706,23 +706,6 @@
|
|||||||
.poe-bar-warn { background: var(--amber); }
|
.poe-bar-warn { background: var(--amber); }
|
||||||
.poe-bar-crit { background: var(--red); }
|
.poe-bar-crit { background: var(--red); }
|
||||||
|
|
||||||
/* UniFi section divider */
|
|
||||||
.unifi-section-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
margin: 24px 0 12px;
|
|
||||||
color: var(--cyan);
|
|
||||||
font-size: .75em;
|
|
||||||
letter-spacing: .1em;
|
|
||||||
}
|
|
||||||
.unifi-section-header::before,
|
|
||||||
.unifi-section-header::after {
|
|
||||||
content: '';
|
|
||||||
flex: 1;
|
|
||||||
height: 1px;
|
|
||||||
background: linear-gradient(90deg, transparent, var(--cyan), transparent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.link-loading { padding: 20px; text-align: center; color: var(--text-muted); font-size: .8em; }
|
.link-loading { padding: 20px; text-align: center; color: var(--text-muted); font-size: .8em; }
|
||||||
|
|||||||
@@ -208,6 +208,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Host cards -->
|
<!-- Host cards -->
|
||||||
|
<div class="lt-toolbar" style="margin-bottom:10px" id="host-toolbar">
|
||||||
|
<div class="lt-toolbar-left">
|
||||||
|
<div class="lt-search">
|
||||||
|
<input type="search" class="lt-input lt-search-input" id="host-search"
|
||||||
|
placeholder="Filter hosts…" autocomplete="off" style="width:180px">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="host-grid" id="host-grid">
|
<div class="host-grid" id="host-grid">
|
||||||
{% for name, host in snapshot.hosts.items() %}
|
{% for name, host in snapshot.hosts.items() %}
|
||||||
{% set suppressed = suppressions | selectattr('target_name', 'equalto', name) | list %}
|
{% set suppressed = suppressions | selectattr('target_name', 'equalto', name) | list %}
|
||||||
@@ -568,6 +576,15 @@
|
|||||||
new MutationObserver(applyEventsFilter)
|
new MutationObserver(applyEventsFilter)
|
||||||
.observe(document.getElementById('events-table-wrap'), { childList: true, subtree: true });
|
.observe(document.getElementById('events-table-wrap'), { childList: true, subtree: true });
|
||||||
|
|
||||||
|
// Host grid search filter
|
||||||
|
document.getElementById('host-search')?.addEventListener('input', function() {
|
||||||
|
const q = this.value.trim().toLowerCase();
|
||||||
|
document.querySelectorAll('#host-grid .host-card').forEach(card => {
|
||||||
|
const name = (card.dataset.host || '').toLowerCase();
|
||||||
|
card.style.display = (!q || name.includes(q)) ? '' : 'none';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Stat card clicks — filter events table by severity
|
// Stat card clicks — filter events table by severity
|
||||||
document.querySelectorAll('.lt-stat-card[data-stat-filter]').forEach(card => {
|
document.querySelectorAll('.lt-stat-card[data-stat-filter]').forEach(card => {
|
||||||
card.addEventListener('click', () => {
|
card.addEventListener('click', () => {
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ function renderUnifiSwitches(unifiSwitches, dataUpdated) {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
|
|
||||||
return `<div class="unifi-section-header">UNIFI SWITCH PORTS</div>${html}`;
|
return `<div class="lt-divider" style="margin:20px 0 12px"><span class="lt-divider-label" style="color:var(--cyan);letter-spacing:.1em">UNIFI SWITCH PORTS</span></div>${html}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Panel collapse / expand ───────────────────────────────────────
|
// ── Panel collapse / expand ───────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user