feat: stream municipality vectors by viewport
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import GeoMap from '../GeoMap'
|
||||
import type { AreaRead, DatasetCreateResponse, QaComparisonResult, VectorSelectionBBox, VectorSelectionResponse } from '../../types'
|
||||
import type { AreaRead, DatasetCreateResponse, MapViewportState, QaComparisonResult, VectorSelectionBBox, VectorSelectionResponse } from '../../types'
|
||||
import { featureCollectionBounds } from '../../lib/geojsonBounds'
|
||||
|
||||
const DEFAULT_SELECTED_FEATURE_FILENAME = 'selected-feature.geojson'
|
||||
@@ -189,6 +189,10 @@ interface MapWorkspaceProps {
|
||||
areaLayerOpacity: number
|
||||
mapFeatureCount: number
|
||||
areaFeatureCount: number
|
||||
viewportVectorEnabled: boolean
|
||||
viewportVectorStatus: string | null
|
||||
viewportVectorTone: 'ready' | 'pending' | 'warning' | 'error'
|
||||
fitMapDataOnChange: boolean
|
||||
selectedMapFeature: GeoJSON.Feature | null
|
||||
selectedFeature?: GeoJSON.Feature | null
|
||||
mapSelectionBbox: VectorSelectionBBox | null
|
||||
@@ -217,6 +221,7 @@ interface MapWorkspaceProps {
|
||||
onSetMapLayerVisible: (visible: boolean) => void
|
||||
onSetMapLayerOpacity: (opacity: number) => void
|
||||
onSelectMapFeature: (feature: GeoJSON.Feature | null) => void
|
||||
onMapViewportChange: (viewport: MapViewportState) => void
|
||||
onSetMapSelectionBbox: (bbox: VectorSelectionBBox | null) => void
|
||||
onRunMapSelectionExtract: (bbox: VectorSelectionBBox) => Promise<VectorSelectionResponse | null>
|
||||
onClearMapSelectionExtract: () => void
|
||||
@@ -247,6 +252,10 @@ export function MapWorkspace({
|
||||
areaLayerOpacity,
|
||||
mapFeatureCount,
|
||||
areaFeatureCount,
|
||||
viewportVectorEnabled,
|
||||
viewportVectorStatus,
|
||||
viewportVectorTone,
|
||||
fitMapDataOnChange,
|
||||
selectedMapFeature,
|
||||
selectedFeature = selectedMapFeature,
|
||||
mapSelectionBbox,
|
||||
@@ -275,6 +284,7 @@ export function MapWorkspace({
|
||||
onSetMapLayerVisible,
|
||||
onSetMapLayerOpacity,
|
||||
onSelectMapFeature,
|
||||
onMapViewportChange,
|
||||
onSetMapSelectionBbox,
|
||||
onRunMapSelectionExtract,
|
||||
onClearMapSelectionExtract,
|
||||
@@ -485,7 +495,9 @@ export function MapWorkspace({
|
||||
<p className="eyebrow">Spatial review</p>
|
||||
<h2>Map workspace</h2>
|
||||
</div>
|
||||
<span className="count-pill">{mapFeatureCollection ? `${mapFeatureCount} features` : 'no layer'}</span>
|
||||
<span className="count-pill">
|
||||
{mapFeatureCollection ? `${mapFeatureCount} features` : viewportVectorEnabled ? 'zoom to load' : 'no layer'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="map-control-surface" aria-label="Map workspace controls">
|
||||
@@ -555,7 +567,7 @@ export function MapWorkspace({
|
||||
<label className="checkbox-row">
|
||||
<input
|
||||
checked={mapLayerVisible}
|
||||
disabled={!mapFeatureCollection}
|
||||
disabled={!mapFeatureCollection && !viewportVectorEnabled}
|
||||
type="checkbox"
|
||||
onChange={(event) => onSetMapLayerVisible(event.target.checked)}
|
||||
data-testid="map-layer-visible"
|
||||
@@ -564,7 +576,7 @@ export function MapWorkspace({
|
||||
</label>
|
||||
<input
|
||||
aria-label="Layer opacity"
|
||||
disabled={!mapFeatureCollection}
|
||||
disabled={!mapFeatureCollection && !viewportVectorEnabled}
|
||||
max="1"
|
||||
min="0.05"
|
||||
step="0.05"
|
||||
@@ -578,7 +590,18 @@ export function MapWorkspace({
|
||||
<strong>{mapLayerLabel}</strong>
|
||||
<span>{selectedMapDataset ? `DB layer: ${selectedMapDataset.name}` : 'No database layer selected'}</span>
|
||||
<span>{areaFeatureCollection ? `${areaFeatureCount} AOI loaded` : 'No AOI loaded'}</span>
|
||||
<span>{mapFeatureCollection ? `${mapFeatureCount} features loaded` : 'No vector/result layer loaded'}</span>
|
||||
<span>
|
||||
{mapFeatureCollection
|
||||
? `${mapFeatureCount} features loaded`
|
||||
: viewportVectorEnabled
|
||||
? 'Database layer selected; visible features load by viewport'
|
||||
: 'No vector/result layer loaded'}
|
||||
</span>
|
||||
{viewportVectorEnabled && viewportVectorStatus ? (
|
||||
<span className={`viewport-vector-status viewport-vector-status-${viewportVectorTone}`} role={viewportVectorTone === 'error' ? 'alert' : 'status'}>
|
||||
{viewportVectorStatus}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -596,15 +619,19 @@ export function MapWorkspace({
|
||||
opacity={mapLayerOpacity}
|
||||
areaVisible={areaLayerVisible}
|
||||
areaOpacity={areaLayerOpacity}
|
||||
fitDataOnChange={fitMapDataOnChange}
|
||||
onFeatureSelect={onSelectMapFeature}
|
||||
onMapCoordinateSelect={handleMapCoordinateSelect}
|
||||
onViewportChange={onMapViewportChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<details className="map-layer-details">
|
||||
<summary>
|
||||
<span>Layer details</span>
|
||||
<strong>{mapFeatureCollection ? `${mapFeatureCount} rendered features` : 'No active layer'}</strong>
|
||||
<strong>
|
||||
{mapFeatureCollection ? `${mapFeatureCount} rendered features` : viewportVectorEnabled ? 'Viewport layer selected' : 'No active layer'}
|
||||
</strong>
|
||||
</summary>
|
||||
<div className="map-context-summary" aria-label="Map layer status">
|
||||
<div>
|
||||
@@ -619,7 +646,9 @@ export function MapWorkspace({
|
||||
</div>
|
||||
<div>
|
||||
<span>Feature state</span>
|
||||
<strong>{mapFeatureCollection ? `${mapFeatureCount} rendered features` : 'No layer rendered'}</strong>
|
||||
<strong>
|
||||
{mapFeatureCollection ? `${mapFeatureCount} rendered features` : viewportVectorEnabled ? 'Awaiting viewport detail' : 'No layer rendered'}
|
||||
</strong>
|
||||
<small>{mapLayerProvenance}</small>
|
||||
</div>
|
||||
<div>
|
||||
@@ -639,7 +668,9 @@ export function MapWorkspace({
|
||||
</div>
|
||||
<div>
|
||||
<span>Draw state</span>
|
||||
<strong>{mapFeatureCollection ? `${mapFeatureCount} rendered features` : 'No active vector or result layer'}</strong>
|
||||
<strong>
|
||||
{mapFeatureCollection ? `${mapFeatureCount} rendered features` : viewportVectorEnabled ? 'Viewport delivery active' : 'No active vector or result layer'}
|
||||
</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>QA evidence overlay</span>
|
||||
@@ -672,7 +703,7 @@ export function MapWorkspace({
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{!mapFeatureCollection ? (
|
||||
{!mapFeatureCollection && !viewportVectorEnabled ? (
|
||||
<div className="empty-state map-empty-state">
|
||||
<strong>No active vector or result layer</strong>
|
||||
<p>Open a dataset, detection run, segmentation run or change result to draw it here.</p>
|
||||
|
||||
Reference in New Issue
Block a user