Adding new Top Users visualization

This commit is contained in:
Pablo Revilla
2025-04-11 09:18:56 -07:00
parent a8b5f75942
commit 914910fe76
+24 -27
View File
@@ -63,9 +63,9 @@ h1 {
}
#stats {
text-align: center; /* Centers the content inside the #stats container */
margin-top: 20px; /* Adds a 20px margin at the top */
color: #fff
text-align: center;
margin-top: 20px;
color: #fff;
}
{% endblock %}
@@ -73,15 +73,18 @@ h1 {
{% block body %}
<h1>Top Traffic Nodes</h1>
<!-- Chart Description -->
<div id="stats">
<p>This chart shows a bell curve (normal distribution) based on the total <strong>"Times Seen"</strong> values for all nodes. It helps visualize how frequently nodes are heard, relative to the average.</p>
<p> This "Time Seen" value is the closest that we can get to Mesh utilization by node.</p>
</div>
<div id="stats">
<p><strong>Mean: </strong><span id="mean"></span> - <strong>Standard Deviation: </strong><span id="stdDev"></span></p>
</div>
<!-- Bell Curve Chart -->
<div id="bellCurveChart"></div>
<!-- Mean and Standard Deviation Display -->
<div id="stats">
<p><strong>Mean: </strong><span id="mean"></span></p>
<p><strong>Standard Deviation: </strong><span id="stdDev"></span></p>
</div>
{% if nodes %}
<div class="container">
<table id="trafficTable">
@@ -97,7 +100,7 @@ h1 {
<tbody>
{% for node in nodes %}
<tr>
<td>{{ node.long_name }}</td>
<td><a href="/top?node_id={{ node.node_id }}">{{ node.long_name }}</a></td>
<td>{{ node.short_name }}</td>
<td>{{ node.channel }}</td>
<td>{{ node.total_packets_sent }}</td>
@@ -114,7 +117,7 @@ h1 {
<script src="https://cdn.jsdelivr.net/npm/echarts@5.3.2/dist/echarts.min.js"></script>
<script>
// Get the nodes data from the backend
const nodes = {{ nodes | tojson }}; // Converts the nodes to a JSON object in JavaScript
const nodes = {{ nodes | tojson }};
// Extract total_times_seen values
const timesSeenValues = nodes.map(node => node.total_times_seen);
@@ -127,17 +130,17 @@ h1 {
document.getElementById('mean').textContent = mean.toFixed(2);
document.getElementById('stdDev').textContent = stdDev.toFixed(2);
// Function to calculate the normal distribution value (bell curve)
// Function to calculate the normal distribution value
function normalDistribution(x, mean, stdDev) {
return (1 / (stdDev * Math.sqrt(2 * Math.PI))) * Math.exp(-0.5 * Math.pow((x - mean) / stdDev, 2));
}
// Generate x-values (range) and corresponding y-values for the bell curve
// Generate x and y values for the bell curve
const xData = [];
const yData = [];
const min = Math.min(...timesSeenValues);
const max = Math.max(...timesSeenValues);
const step = (max - min) / 100; // Number of data points for the bell curve
const step = (max - min) / 100;
for (let x = min; x <= max; x += step) {
xData.push(x);
@@ -148,7 +151,7 @@ h1 {
const myChart = echarts.init(document.getElementById('bellCurveChart'));
const option = {
animation: false,
tooltip: {
trigger: 'axis'
},
@@ -175,36 +178,30 @@ h1 {
myChart.setOption(option);
// Function to sort the table when clicking on column headers
// Function to sort the table columns
function sortTable(n) {
const table = document.getElementById("trafficTable");
const rows = Array.from(table.rows).slice(1); // Get all rows except the header
const isNumeric = !isNaN(rows[0].cells[n].innerText); // Check if column contains numeric data
const rows = Array.from(table.rows).slice(1); // Skip header
const isNumeric = !isNaN(rows[0].cells[n].innerText);
let sortedRows;
if (isNumeric) {
sortedRows = rows.sort((a, b) => {
const cellA = parseFloat(a.cells[n].innerText);
const cellB = parseFloat(b.cells[n].innerText);
return cellA - cellB; // Numeric sort
return parseFloat(a.cells[n].innerText) - parseFloat(b.cells[n].innerText);
});
} else {
sortedRows = rows.sort((a, b) => {
const cellA = a.cells[n].innerText.toLowerCase();
const cellB = b.cells[n].innerText.toLowerCase();
return cellA.localeCompare(cellB); // Alphabetic sort
return a.cells[n].innerText.toLowerCase().localeCompare(b.cells[n].innerText.toLowerCase());
});
}
// Toggle the direction of the sort (ascending or descending)
if (table.rows[0].cells[n].getAttribute('data-sort-direction') === 'asc') {
sortedRows.reverse(); // Reverse the order for descending
sortedRows.reverse();
table.rows[0].cells[n].setAttribute('data-sort-direction', 'desc');
} else {
table.rows[0].cells[n].setAttribute('data-sort-direction', 'asc');
}
// Append sorted rows back to the table body
sortedRows.forEach(row => table.tBodies[0].appendChild(row));
}
</script>