diff --git a/meshview/templates/top.html b/meshview/templates/top.html index 20ec91c..5d810af 100644 --- a/meshview/templates/top.html +++ b/meshview/templates/top.html @@ -1,160 +1,150 @@ {% extends "base.html" %} {% block css %} -/* General table styling */ + {% endblock %} {% block body %} -

Top Traffic Nodes

+

Top Traffic Nodes

- -
+ + + + +

This chart shows a bell curve (normal distribution) based on the total "Times Seen" values for all nodes. It helps visualize how frequently nodes are heard, relative to the average.

-

This "Time Seen" value is the closest that we can get to Mesh utilization by node.

-
-
+

This "Time Seen" value is the closest that we can get to Mesh utilization by node.

Mean: - Standard Deviation:

-
+
- -
+ +
- {% if nodes %} + +{% if nodes %}
- - - - - - - - - - - - {% for node in nodes %} - - - - - - - - {% endfor %} - -
Long NameShort NameChannelPackets SentTimes Seen
{{ node.long_name }}{{ node.short_name }}{{ node.channel }}{{ node.total_packets_sent }}{{ node.total_times_seen }}
+ + + + + + + + + + + + {% for node in nodes %} + + + + + + + + {% endfor %} + +
Long NameShort NameChannelPackets SentTimes Seen
{{ node.long_name }}{{ node.short_name }}{{ node.channel }}{{ node.total_packets_sent }}{{ node.total_times_seen }}
- {% else %} +{% else %}

No top traffic nodes available.

- {% endif %} +{% endif %} - - + + + // Recalculate stats & chart + const { mean, stdDev, values } = calculateStats(filtered); + document.getElementById('mean').textContent = mean.toFixed(2); + document.getElementById('stdDev').textContent = stdDev.toFixed(2); + renderChart(values, mean, stdDev); +} + +function populateChannelFilter() { + const select = document.getElementById('channelFilter'); + const channels = [...new Set(nodes.map(n => n.channel))].sort(); + for (const ch of channels) { + const opt = document.createElement('option'); + opt.value = ch; + opt.textContent = ch; + select.appendChild(opt); + } + + select.addEventListener('change', filterByChannel); +} + +function sortTable(n) { + const table = document.getElementById("trafficTable"); + const rows = Array.from(table.rows).slice(1); + const isNumeric = !isNaN(rows[0].cells[n].innerText); + const dir = table.rows[0].cells[n].getAttribute('data-sort-direction') === 'asc' ? 'desc' : 'asc'; + table.rows[0].cells[n].setAttribute('data-sort-direction', dir); + + rows.sort((a, b) => { + const valA = isNumeric ? parseFloat(a.cells[n].innerText) : a.cells[n].innerText.toLowerCase(); + const valB = isNumeric ? parseFloat(b.cells[n].innerText) : b.cells[n].innerText.toLowerCase(); + return (valA > valB ? 1 : -1) * (dir === 'asc' ? 1 : -1); + }); + + rows.forEach(row => table.tBodies[0].appendChild(row)); +} + +function init() { + myChart = echarts.init(document.getElementById('bellCurveChart')); + populateChannelFilter(); + filterByChannel(); + window.addEventListener('resize', () => { + if (myChart) myChart.resize(); + }); +} + +document.addEventListener('DOMContentLoaded', init); + {% endblock %}