Mapbox migration#11
Merged
Merged
Conversation
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
- 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.