Skip to content

1.0 release - #32

Merged
wittend merged 64 commits into
mainfrom
draft-release
Jul 31, 2026
Merged

1.0 release#32
wittend merged 64 commits into
mainfrom
draft-release

Conversation

@ContinuumLS

Copy link
Copy Markdown
Contributor

This pull request aims to tie up all remaining loose ends with the dashboard project in time for a v1.0 release coinciding with final deployment. Several issues were prematurely closed in anticipation of this pull request, with the final issue, #25 being the last GitHub issue still partially withstanding. Project documentation will continue on this repository after release; however, much focus is being dedicated to the PSWS central documentation on the HamSCI wiki.

JC

ContinuumLS and others added 30 commits June 25, 2026 19:05
delta-B (#23):
- Fixed snapshot baseline: Constant uses typed dH/dE/dZ; Moving Average
  snapshots the trailing moving average at Save. applyDeltaB is now an O(1)
  fixed subtraction, fixing the moving-dB overlay-cancels-to-0 bug and the
  O(N^2*W) slowdown
- Numeric usesDeltaB; a Reset (absolute) control; updateCoordGraphs always
  restyles H/E/Z and magnitude

dB/dt (#29):
- Rate of change via real delta-t (nT/s) from the rotated raw magnitude,
  shown in the Current Reading and as a spreadsheet column toggled by
  "Show dB/dt"

Magnitude filter correctness:
- The moving-average overlay's magnitude now smooths the displayed magnitude
  (average of per-sample magnitudes via trailingScalarMean) instead of the
  magnitude of the averaged vector, so it tracks the raw scatter under
  delta-B; H/E/Z keep the vector average

Spreadsheet polish:
- Reserve the scrollbar gutter on the header and body so column labels stay
  aligned with the data when the body scrolls

Closes #23
Closes #29

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eadsheet virtualization (#15)

Cut full-day (86,400-row) .log import from ~44s to ~3.2s:
- filter.js: slidingWindowMeans O(N) running-sum replaces O(N*W) recompute
- index.js: recomputeFiltered single-pass; virtualize spreadsheet (spacer
  rows + visible window, shared date formatter) so import populates instantly
- css: .stripe-class striping and .spacer rows for the virtualized body

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire the footer toggle into a full theming system:
- settings.theme ("system"/"light"/"dark") with migration; defaults to the OS
  prefers-color-scheme until toggled, then persists the explicit choice
- CSS tokenized into semantic color-pair vars with dark + light palettes;
  anti-flash inline <head> script sets the theme before first paint
- Plotly main + sparkline charts re-theme bg/grid/font on toggle without
  rebuilding traces or losing the axis range
- Light theme uses gunmetal (dark brushed-silver) chrome so the logo, chrome
  text, and colored connection status (incl. yellow "Failed") stay readable;
  solid gunmetal table header; bordered/tinted config inputs

Also: sparklines autosize to their container (drop fixed layout height) and the
footer theme toggle is vertically centered.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The plotly_relayout handler only detected drag/zoom inside the plot body
(xaxis.range[0]/[1]); a range-slider drag emits xaxis5.range (the slider's
bottom axis), so autofollow stayed on and the view snapped back to the trailing
window on the next reading. Detect the slider drag too, distinguishing it from
the app's own updateRange() (which sets every axis, so its asynchronously
delivered event includes xaxis.range) so live updates don't self-disable
autofollow. Also guard the time-window updateRange() with updateLock.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Expand js/tests.js into a 28-case Deno test suite covering the critical
calculations: XYZ->HEZ, Vector.rotate (deg/rad + magnitude), delta/scale,
magnitude, JSONL parsing into a Measurement, JSONL/CSV export + round-trip,
sparkline buffer aggregation (reduceBucket/minMaxOfBucket), and the trailing
and O(N) slidingWindowMeans filters (with an equivalence check).

- deno.json: add `test` task -> run everything with `deno task test`
- remove js/filter_test.js (superseded by tests.js)
- .github/workflows/ci.yml: run deno lint + tests on push/PR
- index.d.ts: type the onReading handler (was Function); main.ts: drop an
  unnecessary async on the Deno.serve handler (both would have failed CI lint)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The sparklines rendered raw HEZ and never refreshed on a transform change, so
they ignored the source's rotation and disagreed with the main plot.

- add displayHEZ(m) (rotation + delta-B) as the shared display mapper
- buildSparklineTraces(sparklines, toDisplay) renders display-space H/E/Z/mag so
  the sparklines mirror the main plot; DRY'd via a row() helper + empty guard
- refreshSparks() on Save Rotation / Save dB / Reset dB so they update live
- reuse displayHEZ in extendAllTraces / updateCurrentTable / spreadsheetRowHTML

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- ingest stores a per-bucket {avg, lo, hi} aggregate (wires up minMaxOfBucket)
- buildSparklineTraces draws a translucent min/max envelope band behind each
  average line, in display space via displayHEZ (exact for H/E/Z; the nonlinear
  magnitude band is widened to enclose its average)
- rows are H/E/Z/Magnitude (temperature dropped), each with a text label
- traces switched from scattergl (WebGL) to SVG scatter; y-tick numbers hidden
- panels laid out as a 2x2 grid with tightened gaps
- Trends box moved between Current Reading and the Spreadsheet at 15% height

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ContinuumLS and others added 25 commits July 13, 2026 10:43
- Dismiss lingering Plotly "x unified" hover readout on a tap anywhere
  outside the plot
- Landscape: vertical modebar + right-margin gutter so controls no longer
  obstruct the legend
- Connection status text stays on one line; tab strip scrolls instead
- Portrait: footer paints above the config drawer, which no longer covers it
- Add theme-aware border boxes around each of the five stacked subplots

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Open the config sidebar by reserving a layout grid column that pushes the
main plots right instead of overlaying them, so the y-axis stays visible.
On landscape tablets/small windows the data column shrinks to 350px when
open, and Current Reading + spreadsheet text scale (with transitions) to
fit; export buttons collapse to icons. Overrides are floored at
min-width: 901px so the portrait layout is unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dge, auto-update

- Templated units (gmag-webui, ws-mqtt-bridge, update) with @user@/@HOME@/
  @repo@/@BRIDGE_DIR@ placeholders
- install.sh auto-resolves the service user/home/repo, installs units + Python
  deps, no hardcoded username
- mag_mqtt.py: mag-usb WebSocket -> MQTT bridge (publishes magnetometer/data)
- gmag-webui-update.{sh,service.in,timer}: git-based auto-update that fetches
  origin and reset --hard + restarts the dashboard on new commits

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-adds the deployment tooling without the MQTT bridge (out of scope for this
repo):
- Templated units (gmag-webui, gmag-webui-update) with @user@/@HOME@/@repo@
  placeholders
- install.sh auto-resolves the service user/home/repo and renders the templates
- gmag-webui-update.{sh,service.in,timer}: git-based auto-update that fetches
  origin and reset --hard + restarts the dashboard on new commits

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
install.sh and gmag-webui-update.sh were committed non-executable, so
`sudo deploy/install.sh` failed with "command not found".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Click any column header (Date, H, E, Z, Mag, Temp, dB/dt) to sort the
table; clicking a new column sorts ascending (Date defaults to
newest-first), clicking the active column toggles direction, and the
active column shows a ▲/▼ caret via aria-sort.

The virtualized rendering now maps display positions through a sort
permutation, cached and rebuilt only when data/settings/sort change; the
default newest-first view keeps the zero-allocation fast path so live
performance is unchanged. Sort keys use display-space values (rotation +
delta-B); dB/dt stays computed against each row's chronological neighbor
and the first reading sorts last. Hiding the dB/dt column while sorted by
it falls back to the default sort.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ContinuumLS ContinuumLS added this to the v1.0 Release milestone Jul 25, 2026
@wittend
wittend merged commit 477c4ea into main Jul 31, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants