Polish workbench workspace usability
This commit is contained in:
@@ -61,70 +61,106 @@ export function DatasetPanel({
|
||||
onLoadDatasetDetails,
|
||||
onRefreshMetadata,
|
||||
}: DatasetPanelProps) {
|
||||
const readyDatasets = datasets.filter((dataset) => dataset.status === 'ready').length
|
||||
|
||||
return (
|
||||
<section data-testid="dataset-panel">
|
||||
<h2>Datasets</h2>
|
||||
<form onSubmit={onUploadDataset}>
|
||||
<select
|
||||
value={datasetForm.datasetType}
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, datasetType: event.target.value }))}
|
||||
>
|
||||
<option value="vector">vector</option>
|
||||
<option value="geojson">geojson</option>
|
||||
<option value="raster">raster</option>
|
||||
</select>
|
||||
<input
|
||||
value={datasetForm.source}
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, source: event.target.value }))}
|
||||
placeholder="user_upload"
|
||||
/>
|
||||
<select
|
||||
value={datasetForm.areaId}
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, areaId: event.target.value }))}
|
||||
>
|
||||
<option value="">No area</option>
|
||||
{areas.map((area) => (
|
||||
<option key={area.id} value={area.id}>
|
||||
{area.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<input
|
||||
type="file"
|
||||
accept=".geojson,.json,.tif,.tiff,.geotiff"
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, file: event.target.files?.[0] ?? null }))}
|
||||
/>
|
||||
<button type="submit" disabled={!selectedProjectId}>
|
||||
<div className="panel-title-row">
|
||||
<div>
|
||||
<p className="eyebrow">Data catalog</p>
|
||||
<h2>Datasets</h2>
|
||||
</div>
|
||||
<span className="count-pill">{readyDatasets}/{datasets.length} ready</span>
|
||||
</div>
|
||||
|
||||
<form className="dataset-upload-form" onSubmit={onUploadDataset}>
|
||||
<label>
|
||||
Type
|
||||
<select
|
||||
value={datasetForm.datasetType}
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, datasetType: event.target.value }))}
|
||||
>
|
||||
<option value="vector">vector</option>
|
||||
<option value="geojson">geojson</option>
|
||||
<option value="raster">raster</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
Source
|
||||
<input
|
||||
value={datasetForm.source}
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, source: event.target.value }))}
|
||||
placeholder="user_upload"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
AOI
|
||||
<select
|
||||
value={datasetForm.areaId}
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, areaId: event.target.value }))}
|
||||
>
|
||||
<option value="">No area</option>
|
||||
{areas.map((area) => (
|
||||
<option key={area.id} value={area.id}>
|
||||
{area.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<label className="file-input-label">
|
||||
File
|
||||
<input
|
||||
type="file"
|
||||
accept=".geojson,.json,.tif,.tiff,.geotiff"
|
||||
onChange={(event) => onDatasetFormChange((previous) => ({ ...previous, file: event.target.files?.[0] ?? null }))}
|
||||
/>
|
||||
</label>
|
||||
<button className="primary-action" type="submit" disabled={!selectedProjectId}>
|
||||
Upload dataset
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{loadingDatasets ? <p>Loading datasets...</p> : null}
|
||||
{datasets.length === 0 ? <p>No datasets yet</p> : null}
|
||||
<ul>
|
||||
<ul className="dataset-list">
|
||||
{datasets.map((dataset) => (
|
||||
<li key={dataset.id}>
|
||||
<strong>{dataset.name}</strong>
|
||||
<div>type: {dataset.dataset_type}</div>
|
||||
<div>status: {dataset.status}</div>
|
||||
<div>readiness: {dataset.status === 'ready' ? 'ready' : dataset.status === 'failed' ? 'failed' : 'pending'}</div>
|
||||
<div>size: {formatBytes(dataset.size_bytes)}</div>
|
||||
<div>features: {dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 'n/a'}</div>
|
||||
<div>bbox: {formatBounds(dataset.bounds_json ?? dataset.vector_summary?.bounds_json)}</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onLoadDatasetDetails(selectedProjectId ?? '', dataset)}
|
||||
data-testid={`dataset-select-${dataset.id}`}
|
||||
>
|
||||
Select / details
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onRefreshMetadata(dataset.id)}
|
||||
disabled={dataset.dataset_type === 'raster'}
|
||||
>
|
||||
Refresh metadata
|
||||
</button>
|
||||
<li className="dataset-card" key={dataset.id}>
|
||||
<div className="dataset-card-header">
|
||||
<div>
|
||||
<strong>{dataset.name}</strong>
|
||||
<div className="entity-meta">
|
||||
<span>{dataset.dataset_type}</span>
|
||||
<span>{dataset.dataset_role ?? 'source'}</span>
|
||||
<span>{dataset.status}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span className={dataset.status === 'ready' ? 'status-badge status-badge-ready' : 'status-badge'}>
|
||||
{dataset.status === 'ready' ? 'ready' : dataset.status === 'failed' ? 'failed' : 'pending'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="dataset-metrics">
|
||||
<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>
|
||||
<div className="button-row">
|
||||
<button
|
||||
className="primary-action"
|
||||
type="button"
|
||||
onClick={() => onLoadDatasetDetails(selectedProjectId ?? '', dataset)}
|
||||
data-testid={`dataset-select-${dataset.id}`}
|
||||
>
|
||||
Select / details
|
||||
</button>
|
||||
<button
|
||||
className="secondary-action"
|
||||
type="button"
|
||||
onClick={() => onRefreshMetadata(dataset.id)}
|
||||
disabled={dataset.dataset_type === 'raster'}
|
||||
>
|
||||
Refresh metadata
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user