Complete operational map result workflow
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-17 12:35:50 +02:00
parent 8266929b2e
commit a29c787238
33 changed files with 1121 additions and 107 deletions
+27 -2
View File
@@ -1,6 +1,12 @@
import { useState } from 'react'
import { exportsApi } from '../services/api'
import type { DatasetCreateResponse, ExportCreateResponse, ExportRead, VectorSelectionBBox } from '../types'
import type {
DatasetCreateResponse,
ExportCreateResponse,
ExportRead,
MapResultExportRequest,
VectorSelectionBBox,
} from '../types'
import { formatError } from '../lib/formatError'
interface ExportWorkflowOptions {
@@ -109,7 +115,7 @@ export function useExportWorkflow({
}
}
const exportMapSelectionGeoJson = async (bbox: VectorSelectionBBox) => {
const exportMapSelectionGeoJson = async (bbox: VectorSelectionBBox, areaId?: string) => {
if (!selectedDataset || !isVectorDatasetType(selectedDataset.dataset_type)) {
setSelectionExportError('Select a vector dataset before saving an area export.')
return null
@@ -119,6 +125,7 @@ export function useExportWorkflow({
try {
const response = await exportsApi.exportGeojson({
dataset_id: selectedDataset.id,
area_id: areaId,
export_kind: 'vector_selection',
bbox: { ...bbox, crs: 'EPSG:4326' },
limit: 250,
@@ -172,6 +179,23 @@ export function useExportWorkflow({
}
}
const persistMapResult = async (payload: MapResultExportRequest) => {
setSelectionExporting(true)
setSelectionExportError(null)
try {
const response = await exportsApi.exportMapResult(payload)
setLatestExport(response)
setLatestSelectionExport(response)
await loadExports(payload.project_id)
return response
} catch (error) {
setSelectionExportError(formatError(error, 'Het kaartresultaat kon niet worden bewaard.'))
return null
} finally {
setSelectionExporting(false)
}
}
const previewExportContent = async (exportId: string) => {
setExportError(null)
try {
@@ -209,6 +233,7 @@ export function useExportWorkflow({
exportSelectedDetectionRunGeoJson,
exportSelectedSegmentationRunGeoJson,
exportMapSelectionGeoJson,
persistMapResult,
exportProjectMetadata,
exportProjectReport,
previewExportContent,
@@ -97,14 +97,27 @@ export function useMapThemeSelectionInsights<TThemeId extends string>(
})),
)
const successful = settled.flatMap((item) => (item.status === 'fulfilled' ? [item.value] : []))
const failureCount = settled.length - successful.length
const failures = settled.flatMap((item, index) => (
item.status === 'rejected'
? [{
dataset: queries[index]?.dataset.name ?? queries[index]?.themeId ?? 'Onbekende bron',
reason: formatError(item.reason, 'Bron kon niet worden bevraagd.'),
}]
: []
))
const failureCount = failures.length
if (requestSequence.current !== sequence) {
return []
}
setThemeInsights(successful)
if (failureCount > 0) {
const details = failures
.slice(0, 4)
.map((failure) => `${failure.dataset}: ${failure.reason}`)
.join(' · ')
const remainder = failureCount > 4 ? ` · en ${failureCount - 4} andere` : ''
setThemeInsightsError(
`${failureCount} beschikbare databron${failureCount === 1 ? '' : 'nen'} kon niet worden bevraagd.`,
`${failureCount} beschikbare databron${failureCount === 1 ? '' : 'nen'} kon niet worden bevraagd. ${details}${remainder}`,
)
}
return successful
+11 -3
View File
@@ -144,9 +144,17 @@ export function useProjectWorkspace() {
setLoadingProjects(true)
setErrorMessage(null)
try {
const response = await projectsApi.list()
setProjects(response.items)
const nextProjectId = await pickInitialProjectId(response.items, preferredProjectId)
const [response, canonicalResponse] = await Promise.all([
projectsApi.list(),
projectsApi.list({ name: REGIONAL_WORKSPACE_PROJECT_NAME, limit: 1 }),
])
const items = Array.from(
new Map(
[...canonicalResponse.items, ...response.items].map((project) => [project.id, project]),
).values(),
)
setProjects(items)
const nextProjectId = await pickInitialProjectId(items, preferredProjectId)
if (nextProjectId && nextProjectId !== selectedProjectId) {
setSelectedProjectId(nextProjectId)
}