diff --git a/public/index.html b/public/index.html index 7e377610..7fa55f44 100644 --- a/public/index.html +++ b/public/index.html @@ -20,7 +20,7 @@ - + - + diff --git a/public/node-analytics.js b/public/node-analytics.js index 7f98088e..e55641ce 100644 --- a/public/node-analytics.js +++ b/public/node-analytics.js @@ -51,11 +51,11 @@ const nodeName = escapeHtml(n.name || n.public_key.slice(0, 12)); container.innerHTML = ` -
-
- โ† Back to ${nodeName} -

๐Ÿ“Š ${nodeName} โ€” Analytics

-
${n.role || 'Unknown role'} ยท ${s.totalPackets} packets in ${days}d window
+
+
+ โ† Back to ${nodeName} +

๐Ÿ“Š ${nodeName} โ€” Analytics

+
${n.role || 'Unknown role'} ยท ${s.totalPackets} packets in ${days}d window
@@ -69,56 +69,69 @@
Availability
${s.availabilityPct}%
+
% of time windows with at least one packet
Signal Grade
${s.signalGrade}
+
Aโ€“F based on average SNR across all observers
Packets / Day
${s.avgPacketsPerDay}
+
Average daily packet volume in this window
Observers
${s.uniqueObservers}
+
Distinct stations that heard this node
Relay %
${s.relayPct}%
+
Packets forwarded through repeaters vs direct
Longest Silence
-
${formatSilence(s.longestSilenceMs)}
+
${formatSilence(s.longestSilenceMs)}
+
Longest gap between consecutive packets

Activity Timeline

+
Packet count per time bucket โ€” shows when this node is most active

SNR Trend

+
Signal-to-noise ratio over time โ€” higher is better reception

Packet Types

+
Breakdown of advert, position, text, and other packet types

Observer Coverage

+
Which stations hear this node and how often

Hop Distribution

+
How many repeater hops packets take โ€” 0 means direct

Uptime Heatmap

+
Hour-by-hour activity grid โ€” darker = more packets in that slot
${data.peerInteractions.length ? `

Peer Interactions

+
Nodes this device has exchanged messages with
${data.peerInteractions.map(p => ` diff --git a/public/style.css b/public/style.css index af7eba5b..1288d1ba 100644 --- a/public/style.css +++ b/public/style.css @@ -1350,14 +1350,16 @@ tr[data-hops]:hover { background: rgba(59,130,246,0.1); } .meshcore-marker { background: none !important; border: none !important; } /* === Node Analytics === */ -.analytics-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 24px; } -.analytics-stat-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 8px; padding: 16px; text-align: center; } -.analytics-stat-label { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--text-muted); margin-bottom: 4px; } -.analytics-stat-value { font-size: 28px; font-weight: 700; } -.analytics-charts { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 24px; } -.analytics-chart-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 8px; padding: 16px; } +.analytics-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 16px; } +.analytics-stat-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 6px; padding: 10px 12px; text-align: center; } +.analytics-stat-label { font-size: 10px; text-transform: uppercase; letter-spacing: .5px; color: var(--text-muted); margin-bottom: 2px; } +.analytics-stat-value { font-size: 20px; font-weight: 700; } +.analytics-stat-desc { font-size: 10px; color: var(--text-muted); margin-top: 2px; font-style: italic; } +.analytics-charts { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; } +.analytics-chart-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 6px; padding: 12px; } .analytics-chart-card.full { grid-column: 1 / -1; } -.analytics-chart-card h4 { font-size: 12px; text-transform: uppercase; letter-spacing: .5px; color: var(--text-muted); margin-bottom: 12px; } +.analytics-chart-card h4 { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--text-muted); margin-bottom: 4px; } +.analytics-chart-desc { font-size: 10px; color: var(--text-muted); margin-bottom: 8px; font-style: italic; } .analytics-heatmap { display: grid; grid-template-columns: 40px repeat(24, 1fr); gap: 2px; } .analytics-heatmap-cell { aspect-ratio: 1; border-radius: 2px; cursor: default; } .analytics-heatmap-label { font-size: 10px; color: var(--text-muted); display: flex; align-items: center; }
PeerMessagesLast Contact