Skip to content

Mapbox migration#11

Merged
rainhead merged 39 commits into
mainfrom
mapbox-migration
Apr 27, 2026
Merged

Mapbox migration#11
rainhead merged 39 commits into
mainfrom
mapbox-migration

Conversation

@rainhead
Copy link
Copy Markdown
Owner

No description provided.

rainhead and others added 30 commits April 26, 2026 16:18
Phase 71: Base map + occurrence layer (detailed plan)
Phase 72: Boundaries and interaction (sketch)
Phase 73: OL removal and verification (sketch)

Renumbers existing v3.0 Plants Tab → v3.1, v3.1 Data Quality → v3.2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Key findings: bundle size increases (not decreases) from OL to Mapbox GL JS,
visibleIds filtering requires setData() approach with dual sources for ghost
dots, Shadow DOM CSS injection via ?raw works, clusterProperties enables
recency-tier aggregation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… layer

3 plans across 3 waves: foundation (install, config, module rewrites),
bee-map.ts Mapbox rewrite, then wiring/tests/visual verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Install mapbox-gl v3.22.0 (no @types/mapbox-gl needed -- built-in TS types)
- Create frontend/src/env.d.ts with VITE_MAPBOX_TOKEN type declaration
- Add VITE_MAPBOX_TOKEN env var to CI build step in deploy.yml
…deps

- Export recencyTier function and RECENCY_COLORS constant
- Remove all OpenLayers imports (Feature, FeatureLike, Circle, Fill, Stroke, Style, Text)
- Remove makeClusterStyleFn, hexWithOpacity, styleCache
- Zero imports -- pure TypeScript with no dependencies
…er.ts

- features.ts: replace OccurrenceSource class with loadOccurrenceGeoJSON()
  returning FeatureCollection with occId and recencyTier properties
- features.ts: coordinates are [lon, lat] WGS84 (not projected EPSG:3857)
- features.ts: summary and taxaOptions computed in single SQLite pass
- region-layer.ts: stub loadBoundaries and makeRegionStyleFn as no-ops
- Both files have zero OpenLayers imports
- SUMMARY.md documents 3 tasks: mapbox-gl install, style.ts rewrite, features.ts/region-layer.ts rewrite
- STATE.md updated to Phase 71, Plan 01 complete
- ROADMAP.md progress updated to 1/3 plans
- Replace all OpenLayers imports with Mapbox GL JS v3 (mapbox-gl)
- Clustered GeoJSON source with clusterProperties for recency aggregation
- Ghost source (occurrences-ghost) for filtered-out features at 0.2 opacity
- Selection ring layer (selected-ring) with filter-based yellow highlight
- setData-based visibleIds filtering with full GeoJSON partitioning
- ResizeObserver for container dimension changes (table-mode toggle)
- All clicks emit map-click-empty (occurrence/region clicks deferred to Phase 72)
- Preserve speicmenLayer typo per CLAUDE.md
- Zero OL imports, 162 tests passing, TypeScript clean
- SUMMARY.md documenting rewrite outcome and decisions
- STATE.md updated to plan 02 complete, 03 next
- ROADMAP.md progress updated to 2/3 plans
- Add _loadCountyEcoregionOptions() method querying DISTINCT county and
  ecoregion_l3 from occurrences table
- Call from _onDataLoaded after _loadCollectorOptions
- Remove dead @county-options-loaded and @ecoregion-options-loaded event
  bindings from bee-map template (events no longer emitted with region-
  layer stubbed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…dlers

- Replace OccurrenceSource mock with loadOccurrenceGeoJSON mock in
  bee-atlas.test.ts
- Replace OL region-layer mock (regionLayer, countySource, ecoregionSource)
  with simplified stubs (loadBoundaries, makeRegionStyleFn)
- Add mapbox-gl and mapbox-gl CSS mocks for happy-dom test environment
- Remove dead _onCountyOptionsLoaded and _onEcoregionOptionsLoaded
  handlers from bee-atlas.ts (TS6133: declared but never read)
- All 162 tests pass, tsc --noEmit clean, Vite build succeeds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SUMMARY.md with task commits, deviation (dead handler removal), self-check
- STATE.md: Phase 71 complete (3/3 plans), new decision recorded
- ROADMAP.md: Phase 71 marked complete 2026-04-27

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two plans covering boundary GeoJSON sources/layers, click interaction
chain (cluster/point/region/empty), feature-state highlighting, test
updates, and visual verification. Updated ROADMAP SC-4 and SC-8 to
match D-01 (no cluster zoom) and D-02 (SQLite options) decisions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wave 1: Boundary sources/layers, click interaction chain, feature-state highlighting
Wave 2: Test mock updates, boundary/interaction tests, visual verification

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…re-state highlighting

- Add county/ecoregion GeoJSON sources with generateId for feature-state support
- Add fill+line layers for both boundary types with selection-aware paint expressions
- Implement _loadBoundaryData to fetch boundary GeoJSON and build ID-to-name maps
- Add _applyBoundaryMode visibility toggle and _applyBoundarySelection highlighting
- Replace Phase 71 placeholder click handler with addInteraction priority chain
- Implement _handleClusterClick with getClusterLeaves (D-01: emit occurrence list, no zoom)
- Implement _handlePointClick for single unclustered point clicks
- Implement _handleRegionClick emitting map-click-region with name and shiftKey
- Add _clickConsumed flag pattern for robust empty-click fallback
- Add featureToOccurrenceRow and haversineMetres helper functions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SUMMARY.md documents boundary sources/layers, click chain, feature-state highlighting
- STATE.md advanced to plan 1/2, added boundary layer ordering decision
- ROADMAP.md updated to 1/2 plans complete for Phase 72

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update mapbox-gl mock with addInteraction, setLayoutProperty, setFeatureState, removeFeatureState
- Add getClusterLeaves to mock GeoJSON source return
- Add BOUNDARY-01 tests: boundary sources with generateId, fill/line layers, feature-state highlighting
- Add CLICK-01 tests: addInteraction chain, getClusterLeaves usage, D-01 no-zoom guard, event emissions
- Add D-02 tests: county/ecoregion options loaded from SQLite, not boundary map events
…ests

- SUMMARY.md documenting 10 new tests across BOUNDARY-01, CLICK-01, D-02 blocks
- STATE.md updated: Plan 02 Task 1 complete, awaiting visual verification
updated() fires before the Mapbox style loads, so its _applyBoundaryMode()
call returns early. Add an explicit call inside map.on('load') where the
style is guaranteed loaded, fixing boundaries disappearing on page reload
when boundaryMode is restored from URL params.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previous approach (calling _applyBoundaryMode after layer creation) still
failed because isStyleLoaded() can return false after async source updates.
Instead, compute visibility from the current boundaryMode when creating
layers, so they're correct from the start with no later toggle needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2 plans in 2 waves:
- Plan 01 (wave 1): Remove ol/ol-mapbox-style packages, delete region-layer.ts stub,
  clean stale OL-era test mocks, verify lockfile clean
- Plan 02 (wave 2): Build verification, bundle size measurement, end-to-end
  feature parity checkpoint (human verification)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Uninstall ol and ol-mapbox-style from frontend/package.json
- Delete frontend/src/region-layer.ts (no-op stub from Phase 71)
- Remove loadBoundaries import and call from bee-atlas.ts
- Remove stale frontend/package-lock.json (workspace uses root lockfile)
- Regenerate root package-lock.json without rbush/@types/rbush
…mocks

- Remove vi.mock('../region-layer.ts') from all 5 test files
- Replace stale OccurrenceSource mock with loadOccurrenceGeoJSON in 4 test files
- All 172 tests pass, TypeScript compiles cleanly
rainhead and others added 9 commits April 26, 2026 19:49
- 2/2 tasks executed, all verification passed
- 172 tests passing, TypeScript clean
…sc clean

- Production build succeeds: 66 modules, 2,018 KB main chunk (mapbox-gl ~1,700 KB)
- TypeScript compiles cleanly (tsc --noEmit exits 0)
- All 172 tests pass across 7 test files
- Task 2 (human-verify checkpoint) pending manual feature parity check
The guard prevented the filter query from re-running when GeoJSON data
loaded, because firstUpdated already set _visibleIds to new Set() (not
null). This caused a race condition where URL-restored filters would
show in the filter panel but not apply to the map if the initial query
from firstUpdated hadn't resolved before _onDataLoaded fired.

The generation counter in _runFilterQuery already protects against stale
results, so unconditionally re-running the query is safe.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
_applyVisibleIds bailed on every call because Mapbox reports
isStyleLoaded()=false while processing the clustered GeoJSON source
data added in map.on('load'). The filter query resolved correctly
(3048 Bombus IDs) but could never apply to the map.

The source null-checks (getSource()) are a sufficient guard — setData()
works fine on existing sources even during async style processing. Also
removes the overly specific _visibleIds === null guard in _onDataLoaded
(the generation counter handles the race safely).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All 7 feature areas pass after fixing isStyleLoaded guard.
Documents the filter-not-applying bug found and fixed during E2E
verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…hipped

OL fully removed, all tests pass, production build verified, human E2E
parity check passed (7/7 feature areas). Fixed isStyleLoaded guard that
blocked filter application on URL restore during verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adjacent region polygons have small gaps and overlaps from independent
edge simplification. Needs topologically-consistent simplification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@rainhead rainhead merged commit 8c4f060 into main Apr 27, 2026
3 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.

1 participant