GeoIntel release gates / Compile, test, contracts and builds (push) Successful in 1m49s
GeoIntel release gates / Python and npm vulnerability policy (push) Successful in 21s
GeoIntel release gates / Production AI image, SBOM and container scan (push) Successful in 5m39s
GeoIntel release gates / Deploy exact gated revision to Unraid (push) Failing after 58m43s
99 lines
3.8 KiB
TypeScript
99 lines
3.8 KiB
TypeScript
import { useState } from 'react'
|
|
import { analysisApi } from '../services/api'
|
|
import type { ChangeDetectionSummary, DatasetCreateResponse, VectorSelectionBBox } from '../types'
|
|
import { formatError } from '../lib/formatError'
|
|
|
|
interface ChangeDetectionWorkflowOptions {
|
|
selectedProjectId: string | null
|
|
availableVectorDatasets: DatasetCreateResponse[]
|
|
loadDatasetJobs: (projectId: string, datasetId: string) => Promise<void>
|
|
/**
|
|
* Reads the active map selection when the comparison is started. Without a
|
|
* selection the comparison covers both datasets entire, which is rarely the
|
|
* question being asked and returns a payload no map can draw.
|
|
*
|
|
* A getter rather than a value because this hook runs before the selection
|
|
* state is declared in the component; it is only ever called from a user
|
|
* event, long after that binding is initialised.
|
|
*/
|
|
getSelection?: () => { bbox: VectorSelectionBBox | null; areaId: string | null }
|
|
}
|
|
|
|
export function useChangeDetectionWorkflow({
|
|
selectedProjectId,
|
|
availableVectorDatasets,
|
|
loadDatasetJobs,
|
|
getSelection,
|
|
}: ChangeDetectionWorkflowOptions) {
|
|
const [changeSourceDatasetId, setChangeSourceDatasetId] = useState('')
|
|
const [changeTargetDatasetId, setChangeTargetDatasetId] = useState('')
|
|
const [changeIouThreshold, setChangeIouThreshold] = useState(0.8)
|
|
const [changeIncludeUnchanged, setChangeIncludeUnchanged] = useState(true)
|
|
const [runningChangeDetection, setRunningChangeDetection] = useState(false)
|
|
const [changeDetectionResult, setChangeDetectionResult] = useState<ChangeDetectionSummary | null>(null)
|
|
const [changeDetectionError, setChangeDetectionError] = useState<string | null>(null)
|
|
|
|
const runChangeDetection = async () => {
|
|
const sourceDatasetId = changeSourceDatasetId || availableVectorDatasets[0]?.id
|
|
const targetDatasetId =
|
|
changeTargetDatasetId || availableVectorDatasets.find((dataset) => dataset.id !== sourceDatasetId)?.id
|
|
if (!sourceDatasetId || !targetDatasetId) {
|
|
setChangeDetectionError('Kies twee vectorbronnen')
|
|
return
|
|
}
|
|
if (sourceDatasetId === targetDatasetId) {
|
|
setChangeDetectionError('Source and target datasets must differ')
|
|
return
|
|
}
|
|
if (changeIouThreshold < 0 || changeIouThreshold > 1) {
|
|
setChangeDetectionError('De IoU-drempel moet tussen 0 en 1 liggen.')
|
|
return
|
|
}
|
|
setChangeDetectionError(null)
|
|
setChangeDetectionResult(null)
|
|
setRunningChangeDetection(true)
|
|
const selection = getSelection?.() ?? { bbox: null, areaId: null }
|
|
try {
|
|
const job = await analysisApi.runChangeDetection({
|
|
source_dataset_id: sourceDatasetId,
|
|
target_dataset_id: targetDatasetId,
|
|
iou_threshold: changeIouThreshold,
|
|
include_unchanged: changeIncludeUnchanged,
|
|
...(selection.bbox ? { bbox: selection.bbox } : {}),
|
|
...(selection.areaId ? { area_id: selection.areaId } : {}),
|
|
})
|
|
if (job.status !== 'success') {
|
|
throw new Error(job.error_message || 'De wijzigingsanalyse is mislukt.')
|
|
}
|
|
if (!job.result_json) {
|
|
throw new Error('De wijzigingsanalyse is afgerond zonder resultaat.')
|
|
}
|
|
setChangeSourceDatasetId(sourceDatasetId)
|
|
setChangeTargetDatasetId(targetDatasetId)
|
|
setChangeDetectionResult(job.result_json)
|
|
if (selectedProjectId) {
|
|
await loadDatasetJobs(selectedProjectId, sourceDatasetId)
|
|
}
|
|
} catch (error) {
|
|
setChangeDetectionError(formatError(error, 'Change detection failed'))
|
|
} finally {
|
|
setRunningChangeDetection(false)
|
|
}
|
|
}
|
|
|
|
return {
|
|
changeSourceDatasetId,
|
|
changeTargetDatasetId,
|
|
changeIouThreshold,
|
|
changeIncludeUnchanged,
|
|
runningChangeDetection,
|
|
changeDetectionResult,
|
|
changeDetectionError,
|
|
runChangeDetection,
|
|
setChangeSourceDatasetId,
|
|
setChangeTargetDatasetId,
|
|
setChangeIouThreshold,
|
|
setChangeIncludeUnchanged,
|
|
}
|
|
}
|