page detection and segmentation results instead of returning all of them
/detection/runs/{id}/detections and its GeoJSON sibling returned every
persisted detection, as did the segmentation equivalents. A regional run holds
tens of thousands, and these are the endpoints the results table and the map
overlay call after every run.
They now take limit and offset, default to 2.000, and report total, limit,
offset and truncated so the complete population stays visible while what is
transferred does not. The GeoJSON responses carry the same window in a
geointel_result_window foreign member.
Rows are ordered by confidence, so a capped overlay draws the strongest
detections rather than an arbitrary slice, and the lab says how many of how
many are being shown rather than silently presenting a page as the whole run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -350,6 +350,8 @@ function WorkbenchApp({ username, accessMode, loggingOut, onLogout }: WorkbenchA
|
||||
detectionRuns,
|
||||
selectedDetectionRunId,
|
||||
detectionItems,
|
||||
detectionTotal,
|
||||
detectionTruncated,
|
||||
detectionGeoJson,
|
||||
detectionClassFilter,
|
||||
detectionMinConfidenceFilter,
|
||||
@@ -1233,6 +1235,8 @@ function WorkbenchApp({ username, accessMode, loggingOut, onLogout }: WorkbenchA
|
||||
detectionWorkflowStage={detectionWorkflowStage}
|
||||
selectedDetectionRunId={selectedDetectionRunId}
|
||||
detectionItems={detectionItems}
|
||||
detectionTotal={detectionTotal}
|
||||
detectionTruncated={detectionTruncated}
|
||||
detectionClassFilter={detectionClassFilter}
|
||||
detectionMinConfidenceFilter={detectionMinConfidenceFilter}
|
||||
loadingDetectionResults={loadingDetectionResults}
|
||||
|
||||
@@ -98,6 +98,9 @@ interface DetectionLabProps {
|
||||
detectionWorkflowStage: DetectionWorkflowStage
|
||||
selectedDetectionRunId: string
|
||||
detectionItems: DetectionRead[]
|
||||
/** Complete population behind the returned page. */
|
||||
detectionTotal?: number
|
||||
detectionTruncated?: boolean
|
||||
detectionClassFilter: string
|
||||
detectionMinConfidenceFilter: number
|
||||
loadingDetectionResults: boolean
|
||||
@@ -159,6 +162,8 @@ export function DetectionLab({
|
||||
detectionWorkflowStage,
|
||||
selectedDetectionRunId,
|
||||
detectionItems,
|
||||
detectionTotal,
|
||||
detectionTruncated = false,
|
||||
detectionClassFilter,
|
||||
detectionMinConfidenceFilter,
|
||||
loadingDetectionResults,
|
||||
@@ -679,6 +684,13 @@ export function DetectionLab({
|
||||
</details> : null}
|
||||
|
||||
<div className="ai-lab-results-surface" aria-label="Resultaten van de beeldanalyse">
|
||||
{detectionTruncated ? (
|
||||
<p className="geo-data-notice">
|
||||
Deze run leverde {(detectionTotal ?? detectionItems.length).toLocaleString('nl-BE')} detecties op;
|
||||
hieronder en op de kaart staan de {detectionItems.length.toLocaleString('nl-BE')} met de hoogste
|
||||
zekerheid. De tellingen in de kwaliteitscontrole gebruiken de volledige run.
|
||||
</p>
|
||||
) : null}
|
||||
<div className="panel-title-row">
|
||||
<div>
|
||||
<h3>Gevonden objecten</h3>
|
||||
|
||||
@@ -109,6 +109,9 @@ export function useDetectionWorkflow({
|
||||
const [detectionRuns, setDetectionRuns] = useState<DetectionRunRead[]>([])
|
||||
const [selectedDetectionRunId, setSelectedDetectionRunId] = useState('')
|
||||
const [detectionItems, setDetectionItems] = useState<DetectionRead[]>([])
|
||||
// The server returns one page; a regional run holds far more than it draws.
|
||||
const [detectionTotal, setDetectionTotal] = useState(0)
|
||||
const [detectionTruncated, setDetectionTruncated] = useState(false)
|
||||
const [detectionGeoJson, setDetectionGeoJson] = useState<GeoJSON.FeatureCollection | null>(null)
|
||||
const [detectionClassFilter, setDetectionClassFilter] = useState('')
|
||||
const [detectionMinConfidenceFilter, setDetectionMinConfidenceFilter] = useState(0)
|
||||
@@ -200,6 +203,10 @@ export function useDetectionWorkflow({
|
||||
const loadDetectionResults = async (analysisRunId = selectedDetectionRunId) => {
|
||||
if (!analysisRunId) {
|
||||
setDetectionItems([])
|
||||
setDetectionTotal(0)
|
||||
setDetectionTruncated(false)
|
||||
setDetectionTotal(0)
|
||||
setDetectionTruncated(false)
|
||||
setDetectionGeoJson(null)
|
||||
return
|
||||
}
|
||||
@@ -216,6 +223,8 @@ export function useDetectionWorkflow({
|
||||
detectionApi.getRunGeoJson(analysisRunId, params),
|
||||
])
|
||||
setDetectionItems(detectionsResponse.items)
|
||||
setDetectionTotal(detectionsResponse.total)
|
||||
setDetectionTruncated(Boolean(detectionsResponse.truncated))
|
||||
setDetectionGeoJson(geoJsonResponse)
|
||||
} catch (error) {
|
||||
setDetectionRunError(formatError(error, 'Failed to load detection results'))
|
||||
@@ -563,6 +572,8 @@ export function useDetectionWorkflow({
|
||||
detectionRuns,
|
||||
selectedDetectionRunId,
|
||||
detectionItems,
|
||||
detectionTotal,
|
||||
detectionTruncated,
|
||||
detectionGeoJson,
|
||||
detectionClassFilter,
|
||||
detectionMinConfidenceFilter,
|
||||
|
||||
@@ -36,12 +36,20 @@ export const detectionApi = {
|
||||
apiGet<DetectionRunRead>(`/api/v1/detection/runs/${analysisRunId}`),
|
||||
listDetections: (
|
||||
analysisRunId: string,
|
||||
params: { project_id: string; dataset_id?: string | null; class_name?: string | null; min_confidence?: number | null },
|
||||
params: {
|
||||
project_id: string
|
||||
dataset_id?: string | null
|
||||
class_name?: string | null
|
||||
min_confidence?: number | null
|
||||
// A run holds tens of thousands of detections; the response is one page.
|
||||
limit?: number | null
|
||||
offset?: number | null
|
||||
},
|
||||
): Promise<DetectionListResponse> =>
|
||||
apiGet<DetectionListResponse>(`/api/v1/detection/runs/${analysisRunId}/detections${queryString(params)}`),
|
||||
getRunGeoJson: (
|
||||
analysisRunId: string,
|
||||
params: { project_id: string; class_name?: string | null; min_confidence?: number | null },
|
||||
params: { project_id: string; class_name?: string | null; min_confidence?: number | null; limit?: number | null },
|
||||
): Promise<GeoJSON.FeatureCollection> =>
|
||||
apiGet<GeoJSON.FeatureCollection>(`/api/v1/detection/runs/${analysisRunId}/geojson${queryString(params)}`),
|
||||
compareWithReference: (analysisRunId: string, projectId: string, payload: DetectionQaRequest): Promise<DetectionQaResult> =>
|
||||
|
||||
@@ -1418,8 +1418,12 @@ export interface DetectionRead {
|
||||
}
|
||||
|
||||
export interface DetectionListResponse {
|
||||
/** One page of results; `total` is the complete population. */
|
||||
items: DetectionRead[]
|
||||
total: number
|
||||
limit?: number | null
|
||||
offset?: number
|
||||
truncated?: boolean
|
||||
}
|
||||
|
||||
export interface DetectionQaRequest {
|
||||
@@ -1583,8 +1587,12 @@ export interface SegmentationRead {
|
||||
}
|
||||
|
||||
export interface SegmentationListResponse {
|
||||
/** One page of results; `total` is the complete population. */
|
||||
items: SegmentationRead[]
|
||||
total: number
|
||||
limit?: number | null
|
||||
offset?: number
|
||||
truncated?: boolean
|
||||
}
|
||||
|
||||
export interface SegmentationQaRequest {
|
||||
|
||||
Reference in New Issue
Block a user