Commit Graph
146 Commits
Author SHA1 Message Date
n30nex e01c090c8e feat(stats): add hourly traffic and region-aware scope analytics (#53)
Adds the Traffic and Scopes analytics tabs. Includes the hourly traffic work from #52, which this PR contains in full.

Closes #50. Closes #51.
2026-09-20 11:41:43 -04:00
n30nex 3178713bdb feat(nodes): display the foreign-repeater indication (#49)
* feat(nodes): display the server foreign-repeater indication

* style(ws): align node update event declaration
2026-09-19 22:58:52 -04:00
n30nex 88e2c0f319 feat(stats): compare flood packets heard by two observers (#48) 2026-09-19 22:58:36 -04:00
MrAlders0n d5d9c0870c fix(layout): keep region picker right-anchored on desktop (#47) 2026-09-18 06:12:14 -04:00
n30nex 2264b3be35 fix(layout): keep header controls inside narrow viewports (#44) 2026-09-18 06:10:45 -04:00
n30nex 34bd0948bc feat(packets): display payload summaries in packet rows (#46) 2026-09-18 06:09:59 -04:00
n30nex 7549bacd21 fix(region): avoid focus zoom on small filter text (#45) 2026-09-18 06:07:54 -04:00
n30nex e43de48f0b feat(packets): surface selections outside loaded results (#41)
A ?hash selection outside the loaded or filtered results now shows an Open analyzer notice with loading, error/retry and dismiss states, using the existing detail query.
2026-09-10 09:30:01 -04:00
n30nex 4304153f8b feat(packets): search latest paths by complete hop hashes (#39) 2026-09-10 09:26:13 -04:00
n30nex 9ab1a44ae9 fix(channels): load older directory pages without losing selection (#37)
* fix(channels): page the directory without losing the open channel

* fix(channels): prefer precise server page cursors
2026-09-10 09:26:05 -04:00
n30nex d51e0a997b fix(packets): keep filtered history pageable without scrolling (#34) 2026-09-10 09:25:55 -04:00
MrAlders0n 8d963a59b3 Apply dependabot bumps; migrate to maplibre-gl 6
Named imports, Vite worker URL via setWorkerUrl, and the single
missing-image resolver replacing the styleimagemissing listeners.
2026-09-10 09:17:18 -04:00
MrAlders0n 5ec0e19eb4 stats: read renamed telemetry airtime fields (airtimeTxSecs/RxSecs) 2026-09-10 07:13:04 -04:00
MrAlders0n 12ddc8a921 Observer tab: airtime as percent, add heard-activity charts
Airtime telemetry is on-air seconds, so chart it as a percent of elapsed time.
Add channel busy, packets heard, SNR heard and payload type charts from the
new per-observer activity endpoint; hidden until the server has it.
2026-09-09 23:21:39 -04:00
MrAlders0n f43f469250 Color observation card edges by SNR, align card stats, join the expanded row 2026-09-02 22:25:03 -04:00
MrAlders0n 276ef903fb Handle API rate limiting in the client and back off WS reconnects 2026-09-02 19:50:35 -04:00
MrAlders0n d0aa7f9c8e Show observation cards in the expanded row below md 2026-07-29 23:17:09 -04:00
MrAlders0n efa3143344 Rename map live toggle to Live Map and raise its contrast 2026-07-29 23:08:52 -04:00
MrAlders0n bc3bed78e4 Preserve linebreaks in message bodies 2026-07-28 21:42:44 -04:00
MrAlders0n b74dcdb0cf Animate the live map path from source through to destination
Share the endpoint-gating chain builder with the path map so both plot
source and destination when the backend resolved them unambiguously.
2026-07-28 21:27:15 -04:00
MrAlders0n 4f0ad44d25 Filter the region picker by IATA or airport name
Typing narrows both groups: airports match on code or display name,
regions match on their name or on any member code — a code-only match
tags the row with the code that hit, so it doesn't look like a stray
result. Empty groups drop their headers so the divider never dangles.

The panel body moves into its own component so the query dies with the
dropdown, and focus returns to the trigger on close.
2026-07-27 23:07:24 -04:00
MrAlders0n b2adc5276f Open the analyzer from an observation and add a hash size column
Drops the Open analyzer and Copy link buttons from the expansion; the analyzer popup keeps its own copy link. Table rows butt up against each other now, so the whole strip is a click target.
2026-07-27 22:23:53 -04:00
MrAlders0n 1f3fb5b7c9 Collapse the packet row to a single line with hops and endpoints
The header and the rows are separate grids, so the shared track list can't use ch or auto — each resolved them differently and the columns drifted apart. Observer moves into the expansion to free the column.
2026-07-27 22:06:05 -04:00
MrAlders0n d1ba42e692 Drop a stale doc pointer from two map comments 2026-07-27 21:30:55 -04:00
MrAlders0n 9c037bc923 Close the analyzer on a mobile tab change and add an expanded-row copy link 2026-07-27 21:08:19 -04:00
MrAlders0n cdda2a00ff Keep the widest heard window when a live packet is re-observed 2026-07-27 21:08:19 -04:00
MrAlders0n 907b42e7be Keep the packet card layout below md 2026-07-27 20:47:31 -04:00
MrAlders0n 663eeef775 Stop stripping ?hash on mount, it breaks deep links to older packets
The analyzer drawer and path-map restore both read the live ?hash and
fetch by hash directly, independent of whether the packet is in the
loaded list. Deleting the param once the first page settles without a
match unmounts the drawer and can drop path-map restores, for any
shared link more than a couple of minutes old.
2026-07-27 20:41:57 -04:00
MrAlders0n f44f1ac0a1 Carry the picked observation into the analyzer and finish two other spec gaps
- Stop resetting selectedObservationId when opening the analyzer, so picking an
  observation inside an expanded row lands the drawer on it instead of observations[0]
- Disable View path on map in the expanded row when the detail has no resolvable path,
  matching the drawer's existing button
- Strip a ?hash deep link once the first page has loaded and it matches no packet
2026-07-27 20:32:31 -04:00
MrAlders0n 9582aaaa09 Wire the packet table and expandable rows into the virtual list 2026-07-27 20:04:36 -04:00
MrAlders0n 64b822f4fa Reorder PacketExpansion to show errors before empty state 2026-07-27 19:43:58 -04:00
MrAlders0n f400dc5f76 Add the expanded packet region with skeleton, error and empty states 2026-07-27 19:37:18 -04:00
MrAlders0n 16ee220abe Fix PathData sizing and add null-SNR test to ObservationTable 2026-07-27 19:30:16 -04:00
MrAlders0n 7dfb363265 Add the nested observation table for expanded packet rows 2026-07-27 19:24:39 -04:00
MrAlders0n 9300eefad1 Add the sticky packet table header 2026-07-27 19:20:10 -04:00
MrAlders0n 8bd0f92aff Restore n/a fallback in observer and IATA cells, scope the covering test 2026-07-27 19:17:03 -04:00
MrAlders0n 8795c360ff Add the two-line packet table row 2026-07-27 19:10:07 -04:00
MrAlders0n bdf7ac45e4 Render the packet path line with truncation and confidence tints 2026-07-27 18:56:03 -04:00
MrAlders0n 75124250d6 Add a pure path-summary model for the packet table's path line 2026-07-27 18:45:11 -04:00
MrAlders0n c9eb929a81 Fix ?path deep link when ?analyze is absent 2026-07-27 18:35:45 -04:00
MrAlders0n 89a8980212 Split ?hash into row expansion and ?analyze for the analyzer drawer 2026-07-27 18:19:09 -04:00
MrAlders0n 1dbbce1ad8 Extract usePacketDetail and share it across the analyzer and overlay 2026-07-27 18:08:21 -04:00
MrAlders0n 161f481576 Carry path and endpoint fields from WS observations into packet summaries 2026-07-27 18:01:32 -04:00
MrAlders0n 464e701f76 Add a toggleable IATA border layer to the map
Draw each active IATA's GeoJSON region border as an outline over a faint
fill beneath the node markers, behind a Map Settings toggle that's off by
default and shareable via a URL param. IATAs with no border answer 204
and are skipped.
2026-07-24 22:21:12 -04:00
MrAlders0n 8baa562794 Add a Clock Drift analytics tab
List repeaters and room servers whose advert-derived clock has drifted
past the server threshold, worst first, in a sortable table. It's each
node's latest reading, so there's no time range to pick.
2026-07-24 22:20:49 -04:00
MrAlders0n e6a714aed9 Split top advertisers into flood and direct adverts
Surface each advertiser's flood vs direct advert counts with a per-day
rate for the selected window, as a sortable table on the Talkers tab.
2026-07-24 22:19:24 -04:00
MrAlders0n 7a2d74b7ca Pin overview sparklines to a fixed 24h window
The Observations and Active observers KPI cards show a fixed 24h snapshot
(from /stats/overview), but their sparklines were fed by the range-driven
observations series. Switching to 7d/30d reshaped the sparklines even
though the numbers beside them stayed at 24h, since aggregateByHour drops
empty hours and slice(-24) then spans a different set of hours.

Give the sparklines their own dedicated 24h observations series so the
whole top row is a consistent 24h snapshot; the range selector now only
drives the charts below. React Query dedupes the extra call when the
selector is already on 24h.
2026-07-24 09:47:47 -04:00
MrAlders0n f1a69fa121 Mark each top advertiser with its IATA 2026-07-24 09:11:32 -04:00
MrAlders0n 34bb171429 Lay out Talkers side by side and label advertiser node types 2026-07-24 08:54:23 -04:00
MrAlders0n 45842949d4 Group top advertisers and talkers on the Talkers tab 2026-07-24 08:47:19 -04:00