/* ESPILON Honeypot Dashboard — Charts */ import { escHtml, formatTime } from './utils.js'; // ── Severity Donut ────────────────────────────────────────── export function renderSevDonut(container, stats) { if (!container) return; const sevs = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']; const rawColors = {CRITICAL: '#f43f5e', HIGH: '#fb923c', MEDIUM: '#fbbf24', LOW: '#4ade80'}; const total = sevs.reduce((s, k) => s + (stats[k] || 0), 0); if (!total) { container.innerHTML = '
No events
'; return; } let gradParts = [], angle = 0; sevs.forEach(s => { const v = stats[s] || 0; if (!v) return; const seg = (v / total) * 360; gradParts.push(rawColors[s] + ' ' + angle + 'deg ' + (angle + seg) + 'deg'); angle += seg; }); let html = '
'; html += '
' + '
' + '
' + total + '
' + '
events
'; html += '
'; sevs.forEach(s => { const v = stats[s] || 0, pct = (v / total * 100).toFixed(1); html += '
' + '' + '' + s + '' + '' + v + '' + '(' + pct + '%)
'; }); html += '
'; container.innerHTML = html; } // ── Timeline Bar Chart ────────────────────────────────────── export function renderTimeline(container, data, height) { if (!container) return; height = height || 100; if (!data || !data.length) { container.innerHTML = '
No activity
'; return; } const maxTotal = Math.max(...data.map(d => d.total || 0), 1); const barW = Math.max(Math.floor((container.offsetWidth || 600) / data.length) - 2, 3); const labelEvery = Math.max(1, Math.floor(data.length / 8)); const chartH = height - 18; let html = '
'; data.forEach((d, i) => { const t = d.total || 0, barH = t > 0 ? Math.max((t / maxTotal) * chartH, 2) : 0; const crit = d.CRITICAL || 0, high = d.HIGH || 0, med = d.MEDIUM || 0, low = d.LOW || 0; let timeLabel = ''; if (d.time && i % labelEvery === 0) { const dt = new Date(typeof d.time === 'number' ? (d.time < 1e12 ? d.time * 1000 : d.time) : d.time); timeLabel = String(dt.getHours()).padStart(2, '0') + ':' + String(dt.getMinutes()).padStart(2, '0'); } const tooltip = (timeLabel || formatTime(d.time)) + ' \u2014 Total:' + t + ' (C:' + crit + ' H:' + high + ' M:' + med + ' L:' + low + ')'; html += '
'; if (t > 0) { if (crit) html += '
'; if (high) html += '
'; if (med) html += '
'; if (low) html += '
'; } if (timeLabel) { html += '
' + timeLabel + '
'; } html += '
'; }); html += '
'; container.innerHTML = html; }