diff --git a/public/analytics.js b/public/analytics.js index 366b6937..902c73f7 100644 --- a/public/analytics.js +++ b/public/analytics.js @@ -121,7 +121,7 @@ } } - function renderTab(tab) { + async function renderTab(tab) { const el = document.getElementById('analyticsContent'); const d = _analyticsData; switch (tab) { @@ -130,14 +130,14 @@ case 'topology': renderTopology(el, d.topoData); break; case 'channels': renderChannels(el, d.chanData); break; case 'hashsizes': renderHashSizes(el, d.hashData); break; - case 'collisions': renderCollisionTab(el, d.hashData); break; - case 'subpaths': renderSubpaths(el); break; + case 'collisions': await renderCollisionTab(el, d.hashData); break; + case 'subpaths': await renderSubpaths(el); break; } // Auto-apply column resizing to all analytics tables requestAnimationFrame(() => { el.querySelectorAll('.analytics-table').forEach((tbl, i) => { tbl.id = tbl.id || `analytics-tbl-${tab}-${i}`; - makeColumnsResizable('#' + tbl.id, `meshcore-analytics-${tab}-${i}-col-widths`); + if (typeof makeColumnsResizable === 'function') makeColumnsResizable('#' + tbl.id, `meshcore-analytics-${tab}-${i}-col-widths`); }); }); } @@ -728,7 +728,7 @@ `; } - function renderCollisionTab(el, data) { + async function renderCollisionTab(el, data) { el.innerHTML = `

1-Byte Hash Usage Matrix

@@ -741,8 +741,10 @@
Loading…
`; - renderHashMatrix(data.topHops); - renderCollisions(data.topHops); + let allNodes = []; + try { const nd = await api('/nodes?limit=2000'); allNodes = nd.nodes || []; } catch {} + renderHashMatrix(data.topHops, allNodes); + renderCollisions(data.topHops, allNodes); } function renderHashTimeline(hourly) { @@ -769,16 +771,9 @@ return svg; } - async function renderHashMatrix(topHops) { + async function renderHashMatrix(topHops, allNodes) { const el = document.getElementById('hashMatrix'); - // Fetch all nodes for lookup - let allNodes = []; - try { - const nd = await api('/nodes?limit=2000'); - allNodes = nd.nodes || []; - } catch {} - // Build prefix → node count map const prefixNodes = {}; for (let i = 0; i < 256; i++) { @@ -824,10 +819,10 @@ html += ''; html += `
- 0 — Available - 1 — One node - ⚠2 — Two nodes (collision) - ⚠3+ — Three+ nodes (collision) + 0 — Available + 1 — One node + ⚠2 — Two nodes (collision) + ⚠3+ — Three+ nodes (collision)
`; el.innerHTML = html; @@ -855,13 +850,12 @@ }); } - async function renderCollisions(topHops) { + async function renderCollisions(topHops, allNodes) { const el = document.getElementById('collisionList'); const oneByteHops = topHops.filter(h => h.size === 1); if (!oneByteHops.length) { el.innerHTML = '
No 1-byte hops
'; return; } try { - const nodesData = await api('/nodes?limit=2000'); - const nodes = nodesData.nodes || []; + const nodes = allNodes; const collisions = []; for (const hop of oneByteHops) { const prefix = hop.hex.toLowerCase(); diff --git a/public/channels.js b/public/channels.js index 41f8236b..54beac84 100644 --- a/public/channels.js +++ b/public/channels.js @@ -39,6 +39,7 @@ const tip = document.createElement('div'); tip.id = 'chNodeTooltip'; tip.className = 'ch-node-tooltip'; + tip.setAttribute('role', 'tooltip'); const role = node.is_repeater ? '📡 Repeater' : node.is_room ? '🏠 Room' : node.is_sensor ? '🌡 Sensor' : '📻 Companion'; const lastSeen = node.last_seen ? timeAgo(node.last_seen) : 'unknown'; tip.innerHTML = `
${escapeHtml(node.name)}
@@ -46,12 +47,16 @@
Last seen: ${lastSeen}
${(node.public_key || '').slice(0, 16)}…
`; document.body.appendChild(tip); - const rect = e.target.getBoundingClientRect(); + var trigger = e.target.closest('[data-node]') || e.target; + trigger.setAttribute('aria-describedby', 'chNodeTooltip'); + const rect = trigger.getBoundingClientRect(); tip.style.left = Math.min(rect.left, window.innerWidth - 220) + 'px'; tip.style.top = (rect.bottom + 4) + 'px'; } function hideNodeTooltip() { + var trigger = document.querySelector('[aria-describedby="chNodeTooltip"]'); + if (trigger) trigger.removeAttribute('aria-describedby'); const tip = document.getElementById('chNodeTooltip'); if (tip) tip.remove(); } @@ -205,13 +210,14 @@ function init(app) { app.innerHTML = `
-