Commit 3e60cff
Add lazy loading for layers in GeoSet Multi Map (#346)
* feat: Add lazy loading option for layers in GeoSet Multi Map
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>
* refactor: Extract layer orchestration logic and add tests
- 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>
* fix: Address lazy loading bugs, harden orchestrator, and clean up imports
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>
* fix: Resolve TypeScript build error in multiUtils generic type
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>
* fix: Batch lazy layer loading and preserve autozoom draft state
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>
* fix: Reset autozoom ref on popover reopen and improve staleness test
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>
* fix: Clarify lazyLoading comment to reflect configuration intent
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: Show legend entries immediately with loading spinners while layers 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>
* fix: Render map canvas immediately while layers load in background
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>
* feat: Three-phase layer loading — prioritize autozoom layers
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>
* docs: Update multiUtils.ts description to reflect three-phase loading
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: Pre-set hidden layer visibility from config to prevent flash
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>
* perf: Memoize layerStatesWithVisibility to prevent spurious re-renders
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>
* test: Add optimistic visibility toggle tests for MultiLegend
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>
---------
Co-authored-by: lhawkins <lhawkins@teamraft.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Ethan Bienstock <ethan.bienstock@acf.hhs.gov>1 parent 2ce704d commit 3e60cff
12 files changed
Lines changed: 1498 additions & 412 deletions
File tree
- superset-frontend
- plugins/geoset-map-chart
- src
- GeoSetMultiMap
- components
- test
- GeoSetMultiMap
- components
- layers
- src/explore/components/controls/DeckSlicesControl
- wiki
Lines changed: 437 additions & 353 deletions
Large diffs are not rendered by default.
Lines changed: 167 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
Lines changed: 31 additions & 16 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
222 | 223 | | |
223 | 224 | | |
224 | 225 | | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
225 | 235 | | |
226 | 236 | | |
227 | 237 | | |
| |||
482 | 492 | | |
483 | 493 | | |
484 | 494 | | |
| 495 | + | |
| 496 | + | |
485 | 497 | | |
486 | 498 | | |
487 | 499 | | |
488 | 500 | | |
489 | | - | |
490 | | - | |
491 | | - | |
492 | | - | |
493 | | - | |
494 | | - | |
495 | | - | |
496 | | - | |
497 | | - | |
498 | | - | |
499 | | - | |
500 | | - | |
501 | | - | |
502 | | - | |
503 | | - | |
504 | | - | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
505 | 520 | | |
506 | 521 | | |
507 | 522 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
103 | 103 | | |
104 | 104 | | |
105 | 105 | | |
| 106 | + | |
106 | 107 | | |
107 | 108 | | |
108 | 109 | | |
| |||
0 commit comments