Add lazy loading for layers in GeoSet Multi Map#346
Conversation
Layers marked as "Lazy Loading" are loaded sequentially in the background after all eager layers have rendered, improving initial map load time for dashboards with many layers. Autozoom is automatically disabled for lazy-loaded layers. - Extract DeckSliceConfig, normalizeDeckSlices, and new resolveLayerAutozoom into multiUtils.ts for reuse and testability - Split layer loading into eager (parallel) and lazy (sequential) phases - Add Lazy Loading checkbox to per-layer settings popover in DeckSlicesControl - Add unit tests for resolveLayerAutozoom and normalizeDeckSlices Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract loadLayersOrchestrated to multiUtils.ts for testability - Add load-bearing comment on .catch in loadSingleLayer - Deduplicate normalizeValue in DeckSlicesControl (reuse normalizeDeckSlices) - Add 8 orchestration tests: mixed eager/lazy, all-lazy, staleness cancellation, null filtering, and empty slices Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…orts
Fix critical bug where lazy-loaded layers with initiallyHidden were not
hidden on arrival (the effect only fired on the first 0→N transition).
Now detects newly-added layers by comparing previous vs current slice ID
sets so both eager and lazy layers are handled correctly.
Add .catch() to fire-and-forget loadLayersOrchestrated call to prevent
unhandled promise rejections. Wrap loadFn calls with Promise.resolve()
for defensive handling of synchronous throws. Remove no-op .then(() => {}).
Re-export DeckSliceConfig and normalizeDeckSlices from the plugin barrel
and add tsconfig path mapping so DeckSlicesControl imports from the
package entry point instead of reaching into src/.
Restore autozoom to its saved value when lazy loading is toggled off.
Rename test file to multiUtils.test.ts and add error rejection tests.
Update wiki docs for multiUtils.ts and per-layer settings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use type assertion instead of type predicate in Promise.all filter to avoid Awaited<TLayer> vs TLayer mismatch in generic context. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch lazy layer loading from sequential to batched (batch size 2) for better throughput, simplify safeLoadFn, and fix autozoom restore to use the user's draft value via a ref instead of the saved prop. Update wiki to reflect batched loading behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reset autozoomBeforeLazyRef when the layer settings popover reopens so that toggling lazy loading off after a save/reopen cycle no longer restores a stale autozoom value. Also expand the lazy-chain abort test to span multiple batch boundaries for more robust coverage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ers load Build stub legend entries from slice metadata (already fetched) so the legend is fully populated when the map opens. Each stub shows an antd Spin indicator in place of checkboxes until the layer data arrives and replaces the stub with the full legend content. - Add buildStubLegendEntry() to parse legend name/icon from form_data - Add pendingLegends memo to build stubs from slicesData - Merge stubs into legendsBySlice so loaded entries replace stubs - Add loading field to LegendEntry type - Show Spin spinner for loading entries in LegendEntryContent - Show Spin spinner for group checkbox when all entries are loading Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The loading gate blocked the entire map canvas (base map, legend, controls) behind a loading GIF until all eager layers finished via Promise.all. Changed the condition to only block on slice metadata fetch so the base map is visible immediately and layers appear incrementally as they load. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Refactor two-phase loading into three phases so the map canvas renders as soon as autozoom layers finish, without waiting for all eager layers: Phase 1: Autozoom layers load in parallel (map canvas gates on this) Phase 2: Remaining eager layers load in parallel, appended incrementally Phase 3: Lazy layers load in batches, appended incrementally This prevents the viewport jump that occurred when the map rendered with a default viewport then snapped to the autozoom extent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Layer visibility for initiallyHidden layers is now set from config at the start of loadLayers, before any network requests. This eliminates the timing dependency where the old useEffect-based approach could render a hidden+lazy layer as visible for one frame before hiding it. Category visibility is still set on load (categories aren't known until data is fetched). The layerStatesWithVisibility fallback provides an additional synchronous safety net during render. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix: Hidden + Lazy layer flashWhen a layer was configured as both Hidden by Default and Lazy Loading, it would briefly flash visible on the map when loading completed. The legend checkbox would also flicker (checked → unchecked). Root cause: The old code used a Fix (b0a65ba): Layer visibility is now pre-set from config at the start of |
Wrap the layerStatesWithVisibility computation in useMemo so DeckGLContainer only receives new prop references when sortedLayers or layerVisibility actually change, avoiding unnecessary renders. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verify that group checkboxes update immediately on click via optimistic local state, without waiting for the layerVisibility prop to change from the parent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
multiUtils.ts) fromMulti.tsxfor testability and reuseDeckSliceConfigtype andnormalizeDeckSlicesfunction between the map plugin andDeckSlicesControl, eliminating duplicationFocus Score
8/10 — All changes are focused on the lazy loading feature and directly related refactoring. The shared type unification and utility extraction are necessary to support the feature cleanly. Minor scope expansion for wiki documentation updates.
Detailed Summary of Each File Changed
GeoSetMultiMap/Multi.tsxloadLayersintoloadSingleLayer(per-layer) +loadLayersOrchestrated(three-phase orchestrator). Added generation counter (loadGenerationRef) to cancel stale lazy chains. Layer visibility forinitiallyHiddenlayers is pre-set from config at the start ofloadLayers— before any network requests — so the legend checkbox and map never flash visible. Category visibility is set viahideCategoriesIfNeededwhen layers finish loading (categories aren't known until data is fetched).layerStatesWithVisibilityincludes a synchronous fallback to!entry.initiallyHiddenas a render-time safety net. Loading gate checks for autozoom layers to prevent viewport jump — if autozoom layers exist, waits for phase 1; otherwise shows map immediately after metadata fetch.GeoSetMultiMap/multiUtils.tsDeckSliceConfiginterface (withlazyLoading),resolveLayerAutozoom(disables autozoom when lazy),normalizeDeckSlices(handles legacynumber[]format), andloadLayersOrchestrated(three-phase: autozoom parallel → eager parallel → lazy batched, with staleness abort).geoset-map-chart/src/index.tsnormalizeDeckSlicesandDeckSliceConfigtype from the plugin's public API.test/GeoSetMultiMap/multiUtils.test.tsresolveLayerAutozoom,normalizeDeckSlices, andloadLayersOrchestrated(autozoom-only, eager-only, lazy-only, mixed three-phase ordering, staleness abort at phase boundaries, null filtering, batch size enforcement, sync throw handling, rejection propagation).DeckSlicesControl/index.tsxnormalizeValuewith sharednormalizeDeckSlices. Auto-disables autozoom when lazy loading is toggled on, restores prior autozoom value when toggled off. Context-dependent tooltip messaging.tsconfig.json@superset-ui/geoset-map-chartto enable direct TS imports fromDeckSlicesControlto the plugin source.wiki/Development-Guide.mdmultiUtils.tsentry to the Plugin Architecture file table. Added Layer Loading Orchestration section documenting the three-phase loading strategy and staleness handling.wiki/GeoSet-Multi-Map.mdTest Plan
npx jest multiUtils.test.ts— all 27 tests should pass covering three-phase orchestration logic, staleness, batching, null handling, and error propagation🤖 Generated with Claude Code