Commit History
-
fix: graceful fallback when indicator has no grid overlay
KSvend +1: Claude Opus 4.6 (1M context)The overlay was disappearing completely when clicking between indicators if any of them hit the raster→grid fallback path — the frontend fell through to _renderStatusOverlay() which (after the AOI rectangle was removed) did nothing visible, leaving a blank map with no feedback. Backend: - raster_to_grid_dict() now handles all-NaN rasters by emitting an empty grid so the legend still renders instead of returning None - _save_spatial_json() logs the raster path + band + existence when serializing, and writes a richer raster-unavailable payload (with label, colormap, vmin, vmax) so the frontend can still show a meaningful legend Frontend: - renderSpatialOverlay() no longer falls through to the old status overlay — unknown/fallback payloads render the legend in its new "overlay not available" mode with the product name + color hint - new _activeProductId tracking drops stale spatial responses when the user clicks through indicators rapidly - addSource/addLayer calls are wra…ef89b38 -
feat: show real indicator overlay on dashboard map + fix downloads
KSvend +1: Claude Opus 4.6 (1M context)The results dashboard map was only tinting the AOI box because the frontend had no handler for map_type="raster" — all four indicators use raster spatial data, so nothing ever rendered. Map overlay: - new app/outputs/spatial_web.raster_to_grid_dict() downsamples the product raster (using NaN-aware block mean) to ~96x96, flips rows to match the frontend's ascending-lat grid convention, and emits explicit matplotlib-colormap hex stops so the browser does not need to know RdYlGn, Blues, PiYG, etc. - _save_spatial_json() converts raster SpatialData through the helper before writing, so indicators return a grid-format payload the existing _renderGrid() already understands - _renderGrid() now prefers backend-provided color stops and fits the map view to the grid extent so the overlay is always visible Download fixes: - authDownload(): anchor is appended to the DOM before .click() and objectURL revocation is deferred — the old synchronous teardown broke in Safari/Firefox a…d2a9a16