feat: simplify regional end user workbench
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { Dispatch, FormEvent, SetStateAction } from 'react'
|
||||
import type { AreaRead, DatasetCreateResponse } from '../../types'
|
||||
import { getDatasetDisplayName } from '../../lib/datasetDisplay'
|
||||
|
||||
interface DatasetFormState {
|
||||
datasetType: string
|
||||
@@ -70,25 +71,25 @@ function normalizeDatasetRole(dataset: DatasetCreateResponse): 'reference' | 'ca
|
||||
|
||||
function datasetRoleLabel(role: string): string {
|
||||
if (role === 'reference') {
|
||||
return 'Reference'
|
||||
return 'Officiële referentie'
|
||||
}
|
||||
if (role === 'candidate') {
|
||||
return 'Candidate'
|
||||
return 'Analyse-resultaat'
|
||||
}
|
||||
return 'Source'
|
||||
return 'Eigen bron'
|
||||
}
|
||||
|
||||
function datasetActionHint(dataset: DatasetCreateResponse, role: string): string {
|
||||
if (role === 'reference') {
|
||||
return 'QA reference layer. Select it when comparing candidates against trusted geometry.'
|
||||
return 'Officiële laag voor kaartanalyse en kwaliteitscontrole.'
|
||||
}
|
||||
if (role === 'candidate') {
|
||||
return 'QA candidate layer. Open on the map or send to Export / QA.'
|
||||
return 'Bewaard resultaat dat opnieuw op de kaart, in kwaliteit of als download kan worden gebruikt.'
|
||||
}
|
||||
if (dataset.dataset_type === 'raster') {
|
||||
return 'Raster source. Use the raster tools in the inspector after selecting it.'
|
||||
return 'Luchtbeeld of rasterbron voor kaart- en beeldanalyse.'
|
||||
}
|
||||
return 'Source dataset. Inspect details before using it in downstream workflows.'
|
||||
return 'Ingeladen gegevensbron voor verdere analyse.'
|
||||
}
|
||||
|
||||
export function DatasetPanel({
|
||||
@@ -111,30 +112,30 @@ export function DatasetPanel({
|
||||
const roleSummaries = [
|
||||
{
|
||||
key: 'selected',
|
||||
label: 'Selected',
|
||||
label: 'Geselecteerd',
|
||||
count: selectedDatasetId ? 1 : 0,
|
||||
hint: 'Active',
|
||||
hint: 'Actief',
|
||||
className: 'dataset-role-selected',
|
||||
},
|
||||
{
|
||||
key: 'reference',
|
||||
label: 'Reference',
|
||||
label: 'Referentie',
|
||||
count: datasets.filter((dataset) => normalizeDatasetRole(dataset) === 'reference').length,
|
||||
hint: 'QA truth',
|
||||
hint: 'Officieel',
|
||||
className: 'dataset-role-reference',
|
||||
},
|
||||
{
|
||||
key: 'candidate',
|
||||
label: 'Candidate',
|
||||
label: 'Resultaat',
|
||||
count: datasets.filter((dataset) => normalizeDatasetRole(dataset) === 'candidate').length,
|
||||
hint: 'QA candidate',
|
||||
hint: 'Afgeleid',
|
||||
className: 'dataset-role-candidate',
|
||||
},
|
||||
{
|
||||
key: 'source',
|
||||
label: 'Source',
|
||||
label: 'Eigen bron',
|
||||
count: datasets.filter((dataset) => normalizeDatasetRole(dataset) === 'source').length,
|
||||
hint: 'Uploads',
|
||||
hint: 'Ingeladen',
|
||||
className: 'dataset-role-source',
|
||||
},
|
||||
]
|
||||
@@ -143,23 +144,23 @@ export function DatasetPanel({
|
||||
<section className="workspace-panel" data-testid="dataset-panel">
|
||||
<div className="panel-title-row">
|
||||
<div>
|
||||
<p className="eyebrow">Data catalog</p>
|
||||
<h2>Datasets</h2>
|
||||
<p className="eyebrow">Ingeladen gegevens</p>
|
||||
<h2>Bronnen</h2>
|
||||
</div>
|
||||
<span className="count-pill">{readyDatasets}/{datasets.length} ready</span>
|
||||
<span className="count-pill">{readyDatasets}/{datasets.length} beschikbaar</span>
|
||||
</div>
|
||||
|
||||
<div className="data-selection-summary data-selection-summary-dataset">
|
||||
<span>Selected dataset</span>
|
||||
<strong>{selectedDataset?.name ?? 'No dataset selected'}</strong>
|
||||
<small>{selectedDataset ? `${datasetRoleLabel(normalizeDatasetRole(selectedDataset))} / ${selectedDataset.status}` : 'Inspect a dataset to load details and tools.'}</small>
|
||||
<span>Actieve bron</span>
|
||||
<strong>{selectedDataset ? getDatasetDisplayName(selectedDataset) : 'Geen bron geselecteerd'}</strong>
|
||||
<small>{selectedDataset ? `${datasetRoleLabel(normalizeDatasetRole(selectedDataset))} · ${selectedDataset.status === 'ready' ? 'beschikbaar' : selectedDataset.status}` : 'Kies een bron om deze op de kaart te openen.'}</small>
|
||||
</div>
|
||||
|
||||
<details className="dataset-upload-block data-panel-form-block">
|
||||
<summary>Upload source data</summary>
|
||||
<summary>Eigen bronbestand toevoegen</summary>
|
||||
<form className="dataset-upload-form" onSubmit={onUploadDataset}>
|
||||
<label>
|
||||
Type
|
||||
Bestandstype
|
||||
<select
|
||||
value={datasetForm.datasetType}
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, datasetType: event.target.value }))}
|
||||
@@ -170,7 +171,7 @@ export function DatasetPanel({
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
Source
|
||||
Bronnaam
|
||||
<input
|
||||
value={datasetForm.source}
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, source: event.target.value }))}
|
||||
@@ -178,12 +179,12 @@ export function DatasetPanel({
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
AOI
|
||||
Gebied
|
||||
<select
|
||||
value={datasetForm.areaId}
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, areaId: event.target.value }))}
|
||||
>
|
||||
<option value="">No area</option>
|
||||
<option value="">Volledige bron</option>
|
||||
{areas.map((area) => (
|
||||
<option key={area.id} value={area.id}>
|
||||
{area.name}
|
||||
@@ -192,7 +193,7 @@ export function DatasetPanel({
|
||||
</select>
|
||||
</label>
|
||||
<label className="file-input-label">
|
||||
File
|
||||
Bestand
|
||||
<input
|
||||
type="file"
|
||||
accept=".geojson,.json,.tif,.tiff,.geotiff"
|
||||
@@ -200,7 +201,7 @@ export function DatasetPanel({
|
||||
/>
|
||||
</label>
|
||||
<button className="primary-action" type="submit" disabled={!selectedProjectId}>
|
||||
Upload dataset
|
||||
Bron inladen
|
||||
</button>
|
||||
</form>
|
||||
</details>
|
||||
@@ -215,15 +216,15 @@ export function DatasetPanel({
|
||||
))}
|
||||
</div>
|
||||
|
||||
{loadingDatasets ? <p>Loading datasets...</p> : null}
|
||||
{loadingDatasets ? <p>Bronnen laden...</p> : null}
|
||||
{datasets.length === 0 ? (
|
||||
<div className="empty-state">
|
||||
<strong>No datasets yet</strong>
|
||||
<p>Upload vector, GeoJSON or raster data after selecting a project.</p>
|
||||
<strong>Nog geen bronnen beschikbaar</strong>
|
||||
<p>Voeg een vector-, GeoJSON- of rasterbestand toe aan deze werkruimte.</p>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="data-panel-list-block dataset-catalog-block">
|
||||
<p className="data-section-label">Available datasets</p>
|
||||
<p className="data-section-label">Beschikbare bronnen</p>
|
||||
<ul className="dataset-list">
|
||||
{datasets.map((dataset) => {
|
||||
const datasetRole = normalizeDatasetRole(dataset)
|
||||
@@ -236,22 +237,16 @@ export function DatasetPanel({
|
||||
<span className={`dataset-role-badge dataset-role-${datasetRole}`}>{roleLabel}</span>
|
||||
<span>{dataset.dataset_type}</span>
|
||||
</div>
|
||||
<strong className="dataset-card-title">{dataset.name}</strong>
|
||||
<div className="entity-meta">
|
||||
<span>Source: {dataset.source_name ?? dataset.source}</span>
|
||||
{dataset.reference_layer_name ? <span>Layer: {dataset.reference_layer_name}</span> : null}
|
||||
<span>CRS: {dataset.crs ?? dataset.vector_summary?.crs ?? 'n/a'}</span>
|
||||
<strong className="dataset-card-title">{getDatasetDisplayName(dataset)}</strong>
|
||||
<div className="entity-meta dataset-card-primary-meta">
|
||||
<span>{(dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 0).toLocaleString('nl-BE')} objecten</span>
|
||||
<span>{dataset.source_name ?? dataset.source}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span className={dataset.status === 'ready' ? 'status-badge status-badge-ready' : 'status-badge'}>
|
||||
{dataset.status === 'ready' ? 'ready' : dataset.status === 'failed' ? 'failed' : 'pending'}
|
||||
{dataset.status === 'ready' ? 'beschikbaar' : dataset.status === 'failed' ? 'mislukt' : 'bezig'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="dataset-metrics data-density-grid">
|
||||
<span>size: {formatBytes(dataset.size_bytes)}</span>
|
||||
<span>features: {dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 'n/a'}</span>
|
||||
<span>bbox: {formatBounds(dataset.bounds_json ?? dataset.vector_summary?.bounds_json)}</span>
|
||||
</div>
|
||||
<p className="dataset-action-hint">{datasetActionHint(dataset, datasetRole)}</p>
|
||||
<div className="dataset-action-grid">
|
||||
<button
|
||||
@@ -261,17 +256,17 @@ export function DatasetPanel({
|
||||
onClick={() => onLoadDatasetDetails(selectedProjectId ?? '', dataset)}
|
||||
data-testid={`dataset-select-${dataset.id}`}
|
||||
>
|
||||
<span>Inspect</span>
|
||||
<small>Select / details</small>
|
||||
<span>Bekijken</span>
|
||||
<small>Details en acties</small>
|
||||
</button>
|
||||
<button
|
||||
className="secondary-action dataset-action-button"
|
||||
type="button"
|
||||
onClick={() => onOpenDatasetInMap(dataset)}
|
||||
aria-label="Open in map"
|
||||
aria-label="Open op kaart"
|
||||
>
|
||||
<span>Map</span>
|
||||
<small>Open layer</small>
|
||||
<span>Kaart</span>
|
||||
<small>Laag openen</small>
|
||||
</button>
|
||||
<button
|
||||
className="secondary-action dataset-action-button"
|
||||
@@ -279,20 +274,33 @@ export function DatasetPanel({
|
||||
onClick={() => onOpenDatasetExport(dataset)}
|
||||
disabled={!(dataset.dataset_type === 'vector' || dataset.dataset_type === 'geojson')}
|
||||
>
|
||||
<span>Export / QA</span>
|
||||
<small>{dataset.dataset_type === 'vector' || dataset.dataset_type === 'geojson' ? 'Compare or export' : 'Vector/GeoJSON only'}</small>
|
||||
<span>Downloaden</span>
|
||||
<small>{dataset.dataset_type === 'vector' || dataset.dataset_type === 'geojson' ? 'GeoJSON of rapport' : 'Enkel vectorlagen'}</small>
|
||||
</button>
|
||||
</div>
|
||||
<details className="dataset-technical-details">
|
||||
<summary>Broninformatie</summary>
|
||||
<div className="entity-meta">
|
||||
<span>Bestand: {dataset.name}</span>
|
||||
<span>Bron: {dataset.source_name ?? dataset.source}</span>
|
||||
{dataset.reference_layer_name ? <span>Laag: {dataset.reference_layer_name}</span> : null}
|
||||
<span>CRS: {dataset.crs ?? dataset.vector_summary?.crs ?? 'onbekend'}</span>
|
||||
</div>
|
||||
<div className="dataset-metrics data-density-grid">
|
||||
<span>Grootte: {formatBytes(dataset.size_bytes)}</span>
|
||||
<span>Objecten: {dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 'onbekend'}</span>
|
||||
<span>Begrenzing: {formatBounds(dataset.bounds_json ?? dataset.vector_summary?.bounds_json)}</span>
|
||||
</div>
|
||||
<button
|
||||
className="secondary-action dataset-action-button"
|
||||
className="secondary-action"
|
||||
type="button"
|
||||
onClick={() => onRefreshMetadata(dataset.id)}
|
||||
disabled={dataset.dataset_type === 'raster'}
|
||||
aria-label="Refresh metadata"
|
||||
aria-label="Bronmetadata vernieuwen"
|
||||
>
|
||||
<span>Metadata</span>
|
||||
<small>{dataset.dataset_type === 'raster' ? 'Raster metadata is automatic' : 'Refresh vector stats'}</small>
|
||||
Metadata vernieuwen
|
||||
</button>
|
||||
</div>
|
||||
</details>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user