Skip to content

Feat/angular rewrite#183

Open
tzebrowski wants to merge 6 commits into
mainfrom
feat/angular-rewrite
Open

Feat/angular rewrite#183
tzebrowski wants to merge 6 commits into
mainfrom
feat/angular-rewrite

Conversation

@tzebrowski

Copy link
Copy Markdown
Owner

No description provided.

tzebrowski and others added 6 commits July 16, 2026 11:46
…chart view)

Moves the existing vanilla-JS/Vite/Electron app into legacy/ as a reference
and stands up a new Angular 21 app at the repo root, targeting a plain
browser SPA (Electron dropped). Ports the local-file ingestion pipeline
(JSON/CSV/AlfaOBD/Multiecuscan/columnar-JSON), IndexedDB persistence,
signal-color palette, and Chart.js-based stack/overlay chart rendering to
Angular services/components using signals for state. Drive auth, signal
registry, dyno/XY-analysis/histogram/math-channels/anomaly-scanner, map,
and project history are deferred to later milestones per the agreed plan.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ports Google Drive integration and the live signal-metadata registry from
legacy/ to Angular services. AuthService wraps Google Identity Services +
GAPI as signals, exposing signIn()/signOut() instead of the legacy pending-
action/modal flow (avoids a circular DI dependency with DriveService).
DriveService covers folder lookup, paginated file listing, search/sort, and
authenticated file download, feeding into a new
DataProcessorService.processExternal() entry point. SignalRegistryService is
now a full port (fetches + caches the ObdMetrics PID dictionaries).

A new DrivePanel component wires sign-in, an advanced Client-ID fallback
input, and the file list into the sidebar's Cloud Files section. Tagging,
public-link sharing, pagination controls, and the "recently viewed" history
are dropped for this milestone (auth + listing + registry only, per the
milestone plan) and can be revisited during the Milestone 4 styling pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…anomaly scanner

Ports the "foundations" slice of Milestone 3 (math channels + project/tag
history + anomaly scanner), deferring dyno/XY-analysis/histogram to 3b.

- MathChannelsService: full port of the derived-signal engine (linear
  interpolation, standard-formula/custom-process execution, smoothing,
  batch creation, auto-math on load) plus the ~30-formula catalog
  (math-definitions.ts). MathChannelModal replaces the legacy searchable-
  autocomplete widget with native select/checkbox controls.
- ProjectManagerService: replaces the Milestone 1 stub with a full port —
  current-project persistence, active-file session restore (respecting a
  new rememberFiles preference), library CRUD, and action-history logging/
  replay so math channels survive a reload. DataProcessorService's old
  unconditional-restore-everything behavior is removed in favor of this.
- AnalysisService: anomaly-scanner port (filter rows, templates, scan
  state machine) as a signal-based service; AnomalyScanner component
  replaces the DOM-driven UI. Result clicks now pan/zoom the chart via a
  new AppStateService.setActiveHighlight()/ChartView effect pair.
- AppStateService gains addDerivedSignal (immutable per-file signal
  mutation) and emits FILE_REMOVED itself so ProjectManagerService can
  react to any file removal, not just session-close (a deliberate fix of
  what looked like a legacy oversight).

Scope cuts, documented inline: no tagging/sharing-style UI polish beyond
what's listed above, no resetProject() UI surface, isolate-on-chart uses
exact signal-name matching rather than legacy's fuzzy resolution.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…gram

Ports the remaining Milestone 3 features: WOT-sweep dyno chart, dual-panel
XY correlation heatmaps with a synced timeline, and signal histograms.

- DynoService: full port of extractPulls (WOT sweep detection with
  forward-filled RPM/torque/pedal sampling) and the RPM-binning +
  moving-average smoothing pipeline. DynoModal replaces the DOM-injected
  overlay-signal checkboxes and header controls with native bindings;
  "View on Chart" reuses AppStateService.setActiveHighlight from M3a.
- XyAnalysisService: nearest-neighbor time-matched scatter generation and
  the heat-gradient color scale. XyModal renders two scatter panels plus a
  shared normalized timeline, using Chart.js's built-in tooltip instead of
  legacy's custom external-HTML tooltip table.
- HistogramService/HistogramModal: bin computation + bar chart, recomputing
  reactively instead of requiring a manual "Update" click.

Fixed a real bug hit while browser-verifying: native `<select>` elements
bound via `[value]="signal()"` don't reliably show a non-empty initial
selection when their `<option>`s are rendered by the same `@for` in the
same change-detection pass (the browser's `.value` setter silently no-ops
if the matching `<option>` doesn't exist yet at that instant, and Angular's
signal-diffing means it never retries once the source signal stops
changing). Replaced with `<option [selected]="...">` per-option bindings,
which are immune to this since each option's own binding evaluates after
that option exists. Applied everywhere pre-filled selects appear (this
milestone's Dyno/XY/Histogram modals, plus the Math Channel modal's signal
pickers from Milestone 3a). Also added the `datalabels: { display: false }`
plugin override the dyno/XY charts need now that ChartDataLabels is
globally registered — without it, dense scatter plots render unreadable
per-point label clutter.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ports the map/deep-link/CI slice of Milestone 4 (theme toggle and mobile
sidebar collapse are a tracked gap, deferred per plan).

- MapService: full port of legacy/src/mapmanager.js's pure GPS logic
  (LinearInterpolator, route/heatmap point generation, trip stats,
  bearing/distance math, nearest-time lookup). EmbeddedMap (per-file,
  stack mode) and OverlayMap (merged routes, overlay mode) own the
  Leaflet instance lifecycle, matching how ChartView owns Chart.js
  instances rather than a service. Gated behind a new
  PreferencesService.loadMap toggle (default off, matching legacy's
  opt-in behavior) since it makes external tile requests.
- Chart<->map cursor sync: simplified vs. legacy's custom crosshair/
  keyboard-scrub system. Chart.js's onHover computes the hovered time and
  feeds MapService.stackHover/overlayHover, which EmbeddedMap/OverlayMap
  use to move their marker; clicking or dragging a map marker calls the
  existing AppStateService.setActiveHighlight (from Milestone 3a) to pan/
  zoom the chart back. Verified round-trip in the browser with a
  synthetic GPS fixture (the real sample log has no GPS signals).
- DeepLinkService: ports the `?fileId=` GAS-proxy share-link flow
  (fetch, gzip-decompress, feed into DataProcessorService.processExternal,
  clean the URL via history.replaceState). App's initial route resolution
  now also checks DeepLinkService.hasFileId(), since that flow's URLs
  don't include `#analyzer` the way Drive-native share links do.
- CI: replaced the stale legacy pipeline (eslint --ext .js, vite build,
  Jest coverage) with the Angular one actually used throughout this
  rewrite (eslint --ext .ts, prettier --check, ng test, ng build) on
  Node 22. Dropped stylelint/coverage reporting — neither was part of
  this rewrite's verification loop, so re-adding them here would be
  scope creep; noting as a gap rather than silently deleting the concern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CLAUDE.md, angular.json, and the tsconfig files had drifted out of
Prettier's expected formatting (pre-existing, plus angular.json's recent
leaflet.css/budget edits), which was failing the CI prettier --check step.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.

1 participant