feat: v0.6.14 - Pakettypen-Diagramm im Dashboard
Viertes Chart-Panel zeigt Pakettyp-Verteilung der letzten 24h als Doughnut-Diagramm, farblich nach portnum kodiert. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9306cce209
commit
0fd401a395
|
|
@ -1,5 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
## [0.6.14] - 2026-02-18
|
||||
|
||||
### Added
|
||||
- **Dashboard**: Viertes Diagramm "Pakettypen (24h)" – Doughnut-Chart mit Pakettyp-Verteilung
|
||||
der letzten 24h aus der `packets`-Tabelle, farblich nach Typ kodiert.
|
||||
|
||||
## [0.6.13] - 2026-02-18
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version: "0.6.13"
|
||||
version: "0.6.14"
|
||||
|
||||
bot:
|
||||
name: "MeshDD-Bot"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ let msgChannelFilter = 'all';
|
|||
let chartChannel = null;
|
||||
let chartHops = null;
|
||||
let chartHardware = null;
|
||||
let chartPacketTypes = null;
|
||||
|
||||
initPage({ onAuth: (user) => {
|
||||
currentUser = user;
|
||||
|
|
@ -203,6 +204,7 @@ function updateStats(stats) {
|
|||
updateBotStatus({ connected: stats.bot_connected, uptime: stats.uptime });
|
||||
}
|
||||
updateChannelChart(stats);
|
||||
updatePacketTypeChart(stats);
|
||||
|
||||
const chBreakdown = document.getElementById('channelBreakdown');
|
||||
const chCounts = stats.channel_breakdown || {};
|
||||
|
|
@ -424,10 +426,33 @@ _thead.addEventListener('click', (e) => {
|
|||
renderNodes();
|
||||
});
|
||||
|
||||
// ── Charts (Prio 5) ───────────────────────────────────
|
||||
// ── Charts ────────────────────────────────────────────
|
||||
const HOP_COLORS = ['#2196F3', '#4CAF50', '#FF9800', '#F44336', '#9C27B0', '#795548'];
|
||||
const CHART_COLORS = ['#0dcaf0', '#198754', '#ffc107', '#dc3545', '#6610f2', '#0d6efd', '#20c997', '#fd7e14'];
|
||||
|
||||
const PORTNUM_LABELS = {
|
||||
TEXT_MESSAGE_APP: 'Text',
|
||||
POSITION_APP: 'Position',
|
||||
NODEINFO_APP: 'NodeInfo',
|
||||
TELEMETRY_APP: 'Telemetry',
|
||||
ROUTING_APP: 'Routing',
|
||||
ADMIN_APP: 'Admin',
|
||||
TRACEROUTE_APP: 'Traceroute',
|
||||
NEIGHBORINFO_APP: 'Neighbor',
|
||||
RANGE_TEST_APP: 'RangeTest',
|
||||
};
|
||||
const PORTNUM_COLORS = {
|
||||
TEXT_MESSAGE_APP: '#0dcaf0',
|
||||
POSITION_APP: '#198754',
|
||||
NODEINFO_APP: '#0d6efd',
|
||||
TELEMETRY_APP: '#ffc107',
|
||||
ROUTING_APP: '#6c757d',
|
||||
ADMIN_APP: '#dc3545',
|
||||
TRACEROUTE_APP: '#6f42c1',
|
||||
NEIGHBORINFO_APP: '#20c997',
|
||||
RANGE_TEST_APP: '#fd7e14',
|
||||
};
|
||||
|
||||
function _chartThemeDefaults() {
|
||||
const dark = document.documentElement.getAttribute('data-bs-theme') === 'dark';
|
||||
return { color: dark ? '#adb5bd' : '#495057', borderColor: dark ? 'rgba(255,255,255,0.07)' : 'rgba(0,0,0,0.07)' };
|
||||
|
|
@ -468,6 +493,15 @@ function initCharts() {
|
|||
scales: { x: { beginAtZero: true, ticks: { stepSize: 1, font: { size: 10 } } }, y: { ticks: { font: { size: 10 } } } }
|
||||
}
|
||||
});
|
||||
|
||||
chartPacketTypes = new Chart(document.getElementById('chartPacketTypes'), {
|
||||
type: 'doughnut',
|
||||
data: { labels: [], datasets: [{ data: [], backgroundColor: [], borderWidth: 1 }] },
|
||||
options: {
|
||||
responsive: true, maintainAspectRatio: false,
|
||||
plugins: { legend: { position: 'right', labels: { boxWidth: 10, font: { size: 10 } } } }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateChannelChart(stats) {
|
||||
|
|
@ -480,6 +514,16 @@ function updateChannelChart(stats) {
|
|||
chartChannel.update('none');
|
||||
}
|
||||
|
||||
function updatePacketTypeChart(stats) {
|
||||
if (!chartPacketTypes) return;
|
||||
const breakdown = stats.packet_type_breakdown || {};
|
||||
const entries = Object.entries(breakdown).sort((a, b) => b[1] - a[1]);
|
||||
chartPacketTypes.data.labels = entries.map(([t]) => PORTNUM_LABELS[t] || (t ? t.replace(/_APP$/, '') : '?'));
|
||||
chartPacketTypes.data.datasets[0].data = entries.map(([, cnt]) => cnt);
|
||||
chartPacketTypes.data.datasets[0].backgroundColor = entries.map(([t]) => PORTNUM_COLORS[t] || '#adb5bd');
|
||||
chartPacketTypes.update('none');
|
||||
}
|
||||
|
||||
function updateNodeCharts() {
|
||||
if (!chartHops || !chartHardware) return;
|
||||
const nodeList = Object.values(nodes);
|
||||
|
|
@ -508,7 +552,7 @@ document.addEventListener('themechange', () => {
|
|||
const d = _chartThemeDefaults();
|
||||
Chart.defaults.color = d.color;
|
||||
Chart.defaults.borderColor = d.borderColor;
|
||||
[chartChannel, chartHops, chartHardware].forEach(c => c && c.update());
|
||||
[chartChannel, chartHops, chartHardware, chartPacketTypes].forEach(c => c && c.update());
|
||||
});
|
||||
|
||||
initCharts();
|
||||
|
|
|
|||
Loading…
Reference in a new issue