(status)
| 6658 | renderIncidents((d && d.incidents) || [], elId, elId === 'dash-incidents' ? 3 : 6); |
| 6659 | } catch (e) { /* offline — leave as-is */ } |
| 6660 | } |
| 6661 | function renderWatchtower(d) { |
| 6662 | const sumEl = document.getElementById('watchtower-summary'); |
| 6663 | const srcEl = document.getElementById('watchtower-sources'); |
| 6664 | const listEl = document.getElementById('watchtower-alerts'); |
| 6665 | if (!sumEl || !listEl) return; |
| 6666 | if (!d || d.success === false) { sumEl.innerHTML = ''; listEl.innerHTML = ''; return; } |
| 6667 | if (!d.enabled) { |
| 6668 | sumEl.innerHTML = '<span class="text-xs text-gray-500">Watchtower is off — enable it to aggregate the standalone watchers into this pane.</span>'; |
| 6669 | if (srcEl) srcEl.textContent = ''; |
| 6670 | listEl.innerHTML = ''; |
| 6671 | return; |
| 6672 | } |
| 6673 | const s = d.summary || {}; |
| 6674 | const bySev = s.by_severity || {}; |
| 6675 | const chips = ['critical', 'high', 'medium', 'low', 'info'] |
| 6676 | .filter(k => bySev[k]).map(k => _wtSevChip(k, bySev[k])); |
| 6677 | const when = s.newest_ts ? new Date(s.newest_ts * 1000).toLocaleString() : '—'; |
| 6678 | sumEl.innerHTML = (chips.length ? chips.join(' ') : '<span class="text-xs text-green-400">✓ No alerts from any watcher</span>') |
| 6679 | + `<span class="text-xs text-gray-500 w-full mt-1">${s.total || 0} alert(s) held · newest: ${escapeHtml(when)}</span>`; |
| 6680 | // Source presence line: which watchers are actually logging. |
| 6681 | if (srcEl) { |
| 6682 | const srcs = (s.sources || []); |
no test coverage detected