fixing node graph selector

This commit is contained in:
Nathan
2025-10-15 18:02:52 -07:00
parent 454c8ff6e2
commit 954cd4653d
3 changed files with 97 additions and 34 deletions

14
dbcleanup.log Normal file
View File

@@ -0,0 +1,14 @@
2025-10-14 20:13:45,221 [INFO] Daily cleanup is disabled by configuration.
2025-10-14 20:25:47,645 [INFO] Daily cleanup is disabled by configuration.
2025-10-14 20:34:48,026 [INFO] Daily cleanup is disabled by configuration.
2025-10-14 21:11:16,069 [INFO] Daily cleanup is disabled by configuration.
2025-10-14 21:19:58,777 [INFO] Daily cleanup is disabled by configuration.
2025-10-14 21:20:29,595 [INFO] Daily cleanup is disabled by configuration.
2025-10-15 10:28:37,193 [INFO] Daily cleanup is disabled by configuration.
2025-10-15 15:54:56,829 [INFO] Daily cleanup is disabled by configuration.
2025-10-15 15:59:16,304 [INFO] Daily cleanup is disabled by configuration.
2025-10-15 16:27:05,307 [INFO] Daily cleanup is disabled by configuration.
2025-10-15 16:29:14,882 [INFO] Daily cleanup is disabled by configuration.
2025-10-15 17:04:31,298 [INFO] Daily cleanup is disabled by configuration.
2025-10-15 17:11:28,215 [INFO] Daily cleanup is disabled by configuration.
2025-10-15 18:00:31,833 [INFO] Daily cleanup is disabled by configuration.

View File

@@ -216,6 +216,7 @@ const edges = [
{
source: "{{ edge.from }}", // edge source as string
target: "{{ edge.to }}", // edge target as string
type: {{ edge.type | tojson }},
originalColor: colors.edge[{{edge.type | tojson}}],
lineStyle: {
color: colors.edge[{{edge.type | tojson}}],
@@ -228,32 +229,55 @@ const edges = [
let filteredNodes = [];
let filteredEdges = [];
let lastSelectedNode = null;
const nodeChannelSet = [...new Set(nodes.map(n => n.channel).filter(Boolean))];
let channelOptions = [...nodeChannelSet].sort();
async function fetchChannelOptionsFromAPI() {
try {
const res = await fetch('/api/channels?period_type=day&length=30');
if (!res.ok) return [];
const data = await res.json();
if (!data || !Array.isArray(data.channels)) return [];
return data.channels.filter(ch => typeof ch === 'string' && ch.trim().length > 0);
} catch (err) {
console.error('Channel fetch failed:', err);
return [];
const normalizeChannel = (value) => {
const trimmed = (value || '').toString().trim();
return trimmed || 'Unknown';
};
const channelByNodeId = new Map();
nodes.forEach(n=>{
const key = String(n.name ?? n.node_id ?? '');
if(key){
channelByNodeId.set(key, normalizeChannel(n.channel));
}
});
const tracerouteChannelCounts = new Map();
edges.forEach(edge=>{
if(edge.type === 'traceroute'){
const weight = typeof edge.weight === 'number' ? edge.weight : 1;
const fromChannel = channelByNodeId.get(String(edge.source));
const toChannel = channelByNodeId.get(String(edge.target));
if(fromChannel){
tracerouteChannelCounts.set(fromChannel, (tracerouteChannelCounts.get(fromChannel) || 0) + weight);
}
if(toChannel){
tracerouteChannelCounts.set(toChannel, (tracerouteChannelCounts.get(toChannel) || 0) + weight);
}
}
});
let channelOptions = [];
if (tracerouteChannelCounts.size) {
channelOptions = Array.from(
[...tracerouteChannelCounts.entries()]
.filter(([_, count]) => count > 0)
.map(([channel]) => channel)
).sort();
}
async function initializeChannelOptions() {
const fetched = await fetchChannelOptionsFromAPI();
const merged = new Set([...nodeChannelSet, ...fetched]);
if (hasChannelSelection(selectedChannel)) {
merged.add(selectedChannel);
}
channelOptions = Array.from(merged).sort();
if (!hasChannelSelection(selectedChannel) && channelOptions.length) {
selectedChannel = channelOptions[0];
}
if (!channelOptions.length) {
channelOptions = Array.from(new Set(nodes.map(n=>normalizeChannel(n.channel)))).sort();
}
if (hasChannelSelection(selectedChannel) && channelOptions.length && !channelOptions.includes(selectedChannel)) {
channelOptions.push(selectedChannel);
channelOptions.sort();
}
if (!hasChannelSelection(selectedChannel) && channelOptions.length) {
selectedChannel = channelOptions[0];
}
function populateChannelDropdown() {

View File

@@ -223,20 +223,45 @@ function updateStatsAndChart() {
}
// Sort table
function sortTable(n) {
function sortTable(columnIndex) {
const table = document.getElementById("trafficTable");
const rows = Array.from(table.rows).slice(1);
const header = table.rows[0].cells[n];
const isNumeric = !isNaN(rows[0].cells[n].innerText.replace('%',''));
let sortedRows = rows.sort((a,b)=>{
const valA = isNumeric ? parseFloat(a.cells[n].innerText.replace('%','')) : a.cells[n].innerText.toLowerCase();
const valB = isNumeric ? parseFloat(b.cells[n].cells[n].innerText.replace('%','')) : b.cells[n].innerText.toLowerCase();
return valA > valB ? 1 : -1;
});
if(header.getAttribute('data-sort-direction')==='asc'){ sortedRows.reverse(); header.setAttribute('data-sort-direction','desc'); }
else header.setAttribute('data-sort-direction','asc');
const tbody = table.tBodies[0];
sortedRows.forEach(row=>tbody.appendChild(row));
const headerCell = table.tHead.rows[0].cells[columnIndex];
const rows = Array.from(tbody.rows);
if (!rows.length) return;
const sampleText = rows[0].cells[columnIndex].innerText.trim().replace('%','');
const isNumeric = sampleText !== '' && !isNaN(sampleText);
const currentDirection = headerCell.getAttribute('data-sort-direction') || 'none';
const sortAscending = currentDirection === 'desc' || currentDirection === 'none';
rows.sort((rowA, rowB) => {
const textA = rowA.cells[columnIndex].innerText.trim();
const textB = rowB.cells[columnIndex].innerText.trim();
let valueA = isNumeric ? parseFloat(textA.replace('%','')) : textA.toLowerCase();
let valueB = isNumeric ? parseFloat(textB.replace('%','')) : textB.toLowerCase();
if (isNumeric) {
valueA = isNaN(valueA) ? Number.NEGATIVE_INFINITY : valueA;
valueB = isNaN(valueB) ? Number.NEGATIVE_INFINITY : valueB;
}
if (valueA > valueB) return 1;
if (valueA < valueB) return -1;
return 0;
});
if (!sortAscending) {
rows.reverse();
}
Array.from(table.tHead.rows[0].cells).forEach(cell => cell.removeAttribute('data-sort-direction'));
headerCell.setAttribute('data-sort-direction', sortAscending ? 'asc' : 'desc');
rows.forEach(row => tbody.appendChild(row));
}
// Initialize