feat: simplify regional end user workbench
This commit is contained in:
@@ -98,44 +98,45 @@ export function ExportCenter({
|
||||
const canExportDataset = Boolean(selectedDataset && isVectorDatasetType(selectedDataset.dataset_type))
|
||||
const geojsonExports = exports.filter((item) => item.export_type.includes('geojson')).length
|
||||
const reportExports = exports.filter((item) => item.export_type === 'project_report_html').length
|
||||
const handoffStatus = selectedProjectId ? 'project selected' : 'select project'
|
||||
const handoffStatus = selectedProjectId ? 'werkruimte gekozen' : 'kies een werkruimte'
|
||||
const exportTypes = useMemo(() => Array.from(new Set(exports.map((item) => item.export_type))).sort(), [exports])
|
||||
const exportStatuses = useMemo(() => Array.from(new Set(exports.map((item) => item.status))).sort(), [exports])
|
||||
const latestHandoffArtifacts = useMemo(
|
||||
() => [
|
||||
{
|
||||
key: 'project_report_html',
|
||||
label: 'Project report',
|
||||
detail: 'HTML report for human review',
|
||||
label: 'Leesbaar rapport',
|
||||
detail: 'HTML-rapport om te bekijken en te delen',
|
||||
item: getLatestExportByType(exports, 'project_report_html'),
|
||||
},
|
||||
{
|
||||
key: 'project_metadata_json',
|
||||
label: 'Project metadata',
|
||||
detail: 'Machine-readable project inventory',
|
||||
label: 'Werkruimtedata',
|
||||
detail: 'Technische inventaris in JSON-formaat',
|
||||
item: getLatestExportByType(exports, 'project_metadata_json'),
|
||||
},
|
||||
{
|
||||
key: 'dataset_geojson',
|
||||
label: 'Dataset GeoJSON',
|
||||
detail: 'Selected vector/reference layer',
|
||||
label: 'Kaartlaag (GeoJSON)',
|
||||
detail: 'De geselecteerde vector- of referentielaag',
|
||||
item: getLatestExportByType(exports, 'dataset_geojson'),
|
||||
},
|
||||
{
|
||||
key: 'detection_geojson',
|
||||
label: 'Detection GeoJSON',
|
||||
detail: 'Persisted detection geometries',
|
||||
label: 'Herkende gebouwen (GeoJSON)',
|
||||
detail: 'Bewaarde geometrieën uit beeldanalyse',
|
||||
item: getLatestExportByType(exports, 'detection_geojson'),
|
||||
},
|
||||
{
|
||||
key: 'segmentation_geojson',
|
||||
label: 'Segmentation GeoJSON',
|
||||
detail: 'Persisted segmentation polygons',
|
||||
label: 'Segmentaties (GeoJSON)',
|
||||
detail: 'Bewaarde segmentatiepolygonen',
|
||||
item: getLatestExportByType(exports, 'segmentation_geojson'),
|
||||
},
|
||||
],
|
||||
[exports],
|
||||
)
|
||||
const availableLatestArtifacts = latestHandoffArtifacts.filter((artifact) => artifact.item)
|
||||
const filteredExports = useMemo(
|
||||
() =>
|
||||
exports.filter((item) => {
|
||||
@@ -154,10 +155,10 @@ export function ExportCenter({
|
||||
<div className="export-center-shell">
|
||||
<div className="panel-title-row">
|
||||
<div>
|
||||
<h2>Export Center</h2>
|
||||
<p className="muted">Create handoff artifacts from persisted datasets, AI runs and project metadata.</p>
|
||||
<h2>Downloads en rapporten</h2>
|
||||
<p className="muted">Bewaar de geselecteerde kaartlaag, analyseresultaten of een leesbaar projectrapport.</p>
|
||||
</div>
|
||||
<span className="count-pill">{exports.length} exports</span>
|
||||
<span className="count-pill">{exports.length} bestanden</span>
|
||||
</div>
|
||||
|
||||
<div className="export-summary-surface" aria-label="Export summary">
|
||||
@@ -167,12 +168,12 @@ export function ExportCenter({
|
||||
<strong>{geojsonExports}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Reports</span>
|
||||
<span>Rapporten</span>
|
||||
<strong>{reportExports}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Selected dataset</span>
|
||||
<strong>{selectedDataset?.name ?? 'none'}</strong>
|
||||
<span>Geselecteerde kaartlaag</span>
|
||||
<strong>{selectedDataset?.name ?? 'geen'}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -188,20 +189,20 @@ export function ExportCenter({
|
||||
</div>
|
||||
<div className="handoff-readiness-grid">
|
||||
<div>
|
||||
<span>Vector dataset</span>
|
||||
<strong>{canExportDataset ? selectedDataset?.name : 'none ready'}</strong>
|
||||
<span>Vectorkaartlaag</span>
|
||||
<strong>{canExportDataset ? selectedDataset?.name : 'geen beschikbaar'}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Detection run</span>
|
||||
<strong>{selectedDetectionRunId || 'none'}</strong>
|
||||
<span>Gebouwanalyse</span>
|
||||
<strong>{selectedDetectionRunId || 'geen'}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Segmentation run</span>
|
||||
<strong>{selectedSegmentationRunId || 'none'}</strong>
|
||||
<span>Segmentatieanalyse</span>
|
||||
<strong>{selectedSegmentationRunId || 'geen'}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Latest handoff artifact</span>
|
||||
<strong>{latestExport ? formatExportType(latestExport.export_type) : 'none'}</strong>
|
||||
<span>Laatste bestand</span>
|
||||
<strong>{latestExport ? formatExportType(latestExport.export_type) : 'geen'}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -209,16 +210,16 @@ export function ExportCenter({
|
||||
|
||||
<div className="latest-artifact-surface" aria-label="Latest handoff artifacts">
|
||||
<div>
|
||||
<h3>Latest handoff artifacts</h3>
|
||||
<p className="muted">Open the newest artifact of each handoff type without searching the full export history.</p>
|
||||
<h3>Laatste downloads</h3>
|
||||
<p className="muted">Open de recentste bestanden zonder in de volledige geschiedenis te zoeken.</p>
|
||||
</div>
|
||||
<div className="latest-artifact-grid">
|
||||
{latestHandoffArtifacts.map((artifact) => {
|
||||
{availableLatestArtifacts.map((artifact) => {
|
||||
const item = artifact.item
|
||||
return (
|
||||
<div className={item ? 'latest-artifact-card' : 'latest-artifact-card latest-artifact-card-empty'} key={artifact.key}>
|
||||
<span>{artifact.label}</span>
|
||||
<strong>{item ? item.status : 'No artifact yet'}</strong>
|
||||
<strong>{item ? (item.status === 'ready' ? 'Beschikbaar' : item.status) : 'Nog niet gemaakt'}</strong>
|
||||
<p>{item ? compactPath(item.storage_path) : artifact.detail}</p>
|
||||
{item ? (
|
||||
<>
|
||||
@@ -226,13 +227,13 @@ export function ExportCenter({
|
||||
<div className="latest-artifact-actions">
|
||||
{canPreviewJson(item) ? (
|
||||
<button type="button" className="secondary-action" onClick={() => onPreviewContent(item.id)}>
|
||||
Preview
|
||||
Bekijken
|
||||
</button>
|
||||
) : (
|
||||
<span className="status-badge">download-only</span>
|
||||
<span className="status-badge">alleen downloaden</span>
|
||||
)}
|
||||
<button type="button" className="primary-action" onClick={() => onDownload(item.id)}>
|
||||
Download
|
||||
Downloaden
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
@@ -240,19 +241,25 @@ export function ExportCenter({
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{availableLatestArtifacts.length === 0 ? (
|
||||
<div className="result-state result-state-empty latest-download-empty">
|
||||
<strong>Nog geen downloads gemaakt</strong>
|
||||
<p>Kies hieronder een rapport of de actieve kaartlaag.</p>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="export-actions-surface" aria-label="Export artifact actions">
|
||||
<div className="panel-title-row">
|
||||
<div>
|
||||
<h3>Artifact actions</h3>
|
||||
<p className="muted">Create review artifacts from the current project, dataset or selected AI analysis run.</p>
|
||||
<h3>Wat wil je bewaren?</h3>
|
||||
<p className="muted">Maak een leesbaar rapport of download gegevens voor verder gebruik.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="export-action-grid">
|
||||
<div className="handoff-action-grid">
|
||||
<div className="handoff-action-card">
|
||||
<div className="handoff-action-card handoff-action-card-technical">
|
||||
<span>Refresh</span>
|
||||
<strong>Export registry</strong>
|
||||
<p>Reload the persisted artifact list for the selected project.</p>
|
||||
@@ -267,17 +274,17 @@ export function ExportCenter({
|
||||
</button>
|
||||
</div>
|
||||
<div className="handoff-action-card handoff-action-card-primary">
|
||||
<span>Project report</span>
|
||||
<strong>HTML summary</strong>
|
||||
<p>Generate the human-readable V1 handoff report from persisted project state.</p>
|
||||
<span>Rapport</span>
|
||||
<strong>Leesbaar projectoverzicht</strong>
|
||||
<p>Maak een HTML-rapport met de beschikbare bronnen, controles en resultaten.</p>
|
||||
<button type="button" className="primary-action" onClick={onExportProjectReport} disabled={!selectedProjectId || exporting}>
|
||||
Export project report HTML
|
||||
Projectrapport maken
|
||||
</button>
|
||||
</div>
|
||||
<div className="handoff-action-card">
|
||||
<span>Metadata</span>
|
||||
<strong>Project JSON</strong>
|
||||
<p>Export project, dataset, QA and artifact metadata for machine-readable review.</p>
|
||||
<span>Technische gegevens</span>
|
||||
<strong>Projectgegevens (JSON)</strong>
|
||||
<p>Download de volledige projectinventaris voor geautomatiseerde verwerking.</p>
|
||||
<button
|
||||
type="button"
|
||||
className="secondary-action"
|
||||
@@ -285,33 +292,33 @@ export function ExportCenter({
|
||||
disabled={!selectedProjectId || exporting}
|
||||
data-testid="export-project-metadata"
|
||||
>
|
||||
Export project metadata JSON
|
||||
Projectgegevens downloaden
|
||||
</button>
|
||||
</div>
|
||||
<div className="handoff-action-card">
|
||||
<span>Vector dataset</span>
|
||||
<strong>Selected GeoJSON</strong>
|
||||
<p>Export the active vector/reference dataset when it is selected and ready.</p>
|
||||
<span>Kaartlaag</span>
|
||||
<strong>Geselecteerde bron (GeoJSON)</strong>
|
||||
<p>Download de actieve vector- of referentielaag.</p>
|
||||
<button type="button" className="secondary-action" onClick={onExportDataset} disabled={!canExportDataset || exporting}>
|
||||
Export selected vector GeoJSON
|
||||
Kaartlaag downloaden
|
||||
</button>
|
||||
</div>
|
||||
<div className="handoff-action-card">
|
||||
{selectedDetectionRunId ? <div className="handoff-action-card">
|
||||
<span>Detection run</span>
|
||||
<strong>Detections GeoJSON</strong>
|
||||
<p>Export persisted detection geometries for the selected analysis run.</p>
|
||||
<button type="button" className="secondary-action" onClick={onExportDetectionRun} disabled={!selectedDetectionRunId || exporting}>
|
||||
Export selected detection run GeoJSON
|
||||
</button>
|
||||
</div>
|
||||
<div className="handoff-action-card">
|
||||
</div> : null}
|
||||
{selectedSegmentationRunId ? <div className="handoff-action-card">
|
||||
<span>Segmentation run</span>
|
||||
<strong>Segmentations GeoJSON</strong>
|
||||
<p>Export persisted segmentation polygons for the selected analysis run.</p>
|
||||
<button type="button" className="secondary-action" onClick={onExportSegmentationRun} disabled={!selectedSegmentationRunId || exporting}>
|
||||
Export selected segmentation run GeoJSON
|
||||
</button>
|
||||
</div>
|
||||
</div> : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -344,7 +351,12 @@ export function ExportCenter({
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="export-history-surface" aria-label="Export history">
|
||||
<details className="export-history-surface export-history-disclosure" aria-label="Export history">
|
||||
<summary>
|
||||
<span>Downloadgeschiedenis</span>
|
||||
<strong>{exports.length} bestanden</strong>
|
||||
</summary>
|
||||
<div className="export-history-body">
|
||||
<div>
|
||||
<h3>Export history</h3>
|
||||
<p className="muted">Review persisted artifacts and open JSON previews where supported.</p>
|
||||
@@ -444,7 +456,8 @@ export function ExportCenter({
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user