Close full operational audit findings
This commit is contained in:
@@ -73,7 +73,7 @@ export interface DatasetDetailPanelProps {
|
||||
|
||||
function formatBytes(value: number | null | undefined): string {
|
||||
if (!value && value !== 0) {
|
||||
return 'n/a'
|
||||
return 'n.v.t.'
|
||||
}
|
||||
const units = ['B', 'KB', 'MB', 'GB']
|
||||
let size = value
|
||||
@@ -87,11 +87,11 @@ function formatBytes(value: number | null | undefined): string {
|
||||
|
||||
function formatBounds(bounds: Record<string, number> | null | undefined): string {
|
||||
if (!bounds) {
|
||||
return 'n/a'
|
||||
return 'n.v.t.'
|
||||
}
|
||||
const keys = ['min_x', 'min_y', 'max_x', 'max_y']
|
||||
if (!keys.every((key) => key in bounds)) {
|
||||
return 'n/a'
|
||||
return 'n.v.t.'
|
||||
}
|
||||
return `${bounds.min_x?.toFixed(4)}, ${bounds.min_y?.toFixed(4)} -> ${bounds.max_x?.toFixed(4)}, ${bounds.max_y?.toFixed(4)}`
|
||||
}
|
||||
@@ -157,8 +157,8 @@ export function DatasetDetailPanel({
|
||||
}: DatasetDetailPanelProps) {
|
||||
return (
|
||||
<section className="dataset-detail-panel">
|
||||
<h2>Dataset details</h2>
|
||||
{selectedDatasetId ? <p>Selected dataset: {selectedDatasetId}</p> : <p>No dataset selected</p>}
|
||||
<h2>Details van de databron</h2>
|
||||
{!selectedDatasetId ? <p>Geen databron geselecteerd.</p> : null}
|
||||
{selectedDataset ? (
|
||||
<div>
|
||||
<p>
|
||||
@@ -166,13 +166,19 @@ export function DatasetDetailPanel({
|
||||
</p>
|
||||
<p>Type: {selectedDataset.dataset_type}</p>
|
||||
<p>Status: {selectedDataset.status}</p>
|
||||
<p>Original file: {selectedDataset.original_filename ?? 'n/a'}</p>
|
||||
<p>Stored file: {selectedDataset.stored_filename ?? 'n/a'}</p>
|
||||
<p>Content type: {selectedDataset.content_type ?? 'n/a'}</p>
|
||||
<p>File size: {formatBytes(selectedDataset.size_bytes)}</p>
|
||||
<p>SHA256: {selectedDataset.checksum_sha256 ?? 'n/a'}</p>
|
||||
<p>Feature count: {selectedDatasetSummary?.feature_count ?? selectedDataset.feature_count ?? 'n/a'}</p>
|
||||
<p>BBox: {formatBounds(selectedDatasetSummary?.bounds_json ?? selectedDataset.bounds_json)}</p>
|
||||
<p>Aantal objecten: {selectedDatasetSummary?.feature_count ?? selectedDataset.feature_count ?? 'n.v.t.'}</p>
|
||||
<p>Ruimtelijke begrenzing: {formatBounds(selectedDatasetSummary?.bounds_json ?? selectedDataset.bounds_json)}</p>
|
||||
<details className="technical-inline-details">
|
||||
<summary>Technische bestandsgegevens</summary>
|
||||
<div className="entity-meta">
|
||||
<span>Dataset-ID: {selectedDataset.id}</span>
|
||||
<span>Oorspronkelijk bestand: {selectedDataset.original_filename ?? 'n.v.t.'}</span>
|
||||
<span>Bewaard bestand: {selectedDataset.stored_filename ?? 'n.v.t.'}</span>
|
||||
<span>Inhoudstype: {selectedDataset.content_type ?? 'n.v.t.'}</span>
|
||||
<span>Bestandsgrootte: {formatBytes(selectedDataset.size_bytes)}</span>
|
||||
<span>SHA-256: {selectedDataset.checksum_sha256 ?? 'n.v.t.'}</span>
|
||||
</div>
|
||||
</details>
|
||||
{selectedDataset.dataset_type === 'raster' ? (
|
||||
<RasterControls
|
||||
areas={areas}
|
||||
@@ -236,8 +242,9 @@ export function DatasetDetailPanel({
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<h3>Jobs</h3>
|
||||
{jobs.length === 0 ? <p>No jobs yet.</p> : null}
|
||||
<details className="technical-inline-details">
|
||||
<summary>Technische verwerking ({jobs.length})</summary>
|
||||
{jobs.length === 0 ? <p>Nog geen verwerkingen.</p> : null}
|
||||
<ul>
|
||||
{jobs.map((job) => (
|
||||
<li key={job.id}>
|
||||
@@ -247,19 +254,20 @@ export function DatasetDetailPanel({
|
||||
{job.result_json ? (
|
||||
<pre className="job-result">{JSON.stringify(job.result_json, null, 2)}</pre>
|
||||
) : null}
|
||||
{job.error_message ? <div className="error">error: {job.error_message}</div> : null}
|
||||
{job.error_message ? <div className="error">Fout: {job.error_message}</div> : null}
|
||||
{job.result_json?.output_dataset_id ? (
|
||||
<button type="button" onClick={() => onPickDerivedDataset(String(job.result_json?.output_dataset_id))}>
|
||||
open derived dataset
|
||||
Open afgeleide databron
|
||||
</button>
|
||||
) : null}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</details>
|
||||
</div>
|
||||
) : null}
|
||||
{loadingDatasetDetails ? <p>Loading dataset details...</p> : null}
|
||||
{datasetDetailError ? <p className="error">Dataset detail error: {datasetDetailError}</p> : null}
|
||||
{loadingDatasetDetails ? <p>Details van de databron laden...</p> : null}
|
||||
{datasetDetailError ? <p className="error">De details konden niet worden geladen: {datasetDetailError}</p> : null}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ interface DatasetPanelProps {
|
||||
|
||||
function formatBytes(value: number | null | undefined): string {
|
||||
if (!value && value !== 0) {
|
||||
return 'n/a'
|
||||
return 'n.v.t.'
|
||||
}
|
||||
const units = ['B', 'KB', 'MB', 'GB']
|
||||
let size = value
|
||||
@@ -46,11 +46,11 @@ function formatBytes(value: number | null | undefined): string {
|
||||
|
||||
function formatBounds(bounds: Record<string, number> | null | undefined): string {
|
||||
if (!bounds) {
|
||||
return 'n/a'
|
||||
return 'n.v.t.'
|
||||
}
|
||||
const keys = ['min_x', 'min_y', 'max_x', 'max_y']
|
||||
if (!keys.every((key) => key in bounds)) {
|
||||
return 'n/a'
|
||||
return 'n.v.t.'
|
||||
}
|
||||
return `${bounds.min_x?.toFixed(4)}, ${bounds.min_y?.toFixed(4)} -> ${bounds.max_x?.toFixed(4)}, ${bounds.max_y?.toFixed(4)}`
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ interface RasterControlsProps {
|
||||
|
||||
function formatRasterBounds(bounds: number[] | undefined | null): string {
|
||||
if (!bounds || bounds.length < 4) {
|
||||
return 'n/a'
|
||||
return 'n.v.t.'
|
||||
}
|
||||
const [minX, minY, maxX, maxY] = bounds
|
||||
return `${minX.toFixed(4)}, ${minY.toFixed(4)} -> ${maxX.toFixed(4)}, ${maxY.toFixed(4)}`
|
||||
@@ -101,57 +101,57 @@ export function RasterControls({
|
||||
onRunRasterNdwi,
|
||||
onRunRasterNdbi,
|
||||
}: RasterControlsProps) {
|
||||
const previewState = rasterPreview ? 'ready' : 'not generated'
|
||||
const previewState = rasterPreview ? 'gereed' : 'nog niet aangemaakt'
|
||||
const rasterReadinessItems = [
|
||||
{
|
||||
label: 'Metadata profile',
|
||||
state: selectedRasterMetadata ? 'ready' : 'inspect needed',
|
||||
label: 'Bestandsprofiel',
|
||||
state: selectedRasterMetadata ? 'gereed' : 'controle nodig',
|
||||
detail: selectedRasterMetadata
|
||||
? `${selectedRasterMetadata.driver} | ${selectedRasterMetadata.width} x ${selectedRasterMetadata.height} | ${selectedRasterMetadata.band_count} bands`
|
||||
: 'Run metadata inspection before derived raster operations.',
|
||||
? `${selectedRasterMetadata.driver} | ${selectedRasterMetadata.width} x ${selectedRasterMetadata.height} | ${selectedRasterMetadata.band_count} banden`
|
||||
: 'Controleer eerst de metadata voordat je afgeleide rasters maakt.',
|
||||
},
|
||||
{
|
||||
label: 'CRS readiness',
|
||||
state: selectedRasterMetadata?.crs ? 'ready' : 'missing',
|
||||
detail: selectedRasterMetadata?.crs ?? 'Raster CRS is required for safe map handoff and clipping.',
|
||||
label: 'Coördinatenstelsel',
|
||||
state: selectedRasterMetadata?.crs ? 'gereed' : 'ontbreekt',
|
||||
detail: selectedRasterMetadata?.crs ?? 'Een coördinatenstelsel is vereist om veilig te begrenzen en op de kaart te tonen.',
|
||||
},
|
||||
{
|
||||
label: 'Preview artifact',
|
||||
label: 'Voorbeeldweergave',
|
||||
state: previewState,
|
||||
detail: rasterPreview
|
||||
? `${rasterPreview.preview.path} (${rasterPreview.preview.width ?? 'n/a'} x ${rasterPreview.preview.height ?? 'n/a'})`
|
||||
: 'Generate a preview to confirm visual orientation before AI runs.',
|
||||
? `${rasterPreview.preview.width ?? 'n.v.t.'} x ${rasterPreview.preview.height ?? 'n.v.t.'} pixels`
|
||||
: 'Maak een voorbeeld om de oriëntatie te controleren vóór beeldanalyse.',
|
||||
},
|
||||
{
|
||||
label: 'Tile manifest handoff',
|
||||
state: isRasterTileInputValid ? 'input valid' : 'input blocked',
|
||||
label: 'Beeldtegels',
|
||||
state: isRasterTileInputValid ? 'instellingen geldig' : 'instellingen geblokkeerd',
|
||||
detail: isRasterTileInputValid
|
||||
? 'Tile generation will create the manifest path used by detection and segmentation requests.'
|
||||
: 'Tile size must be positive and overlap must stay below tile size.',
|
||||
? 'GeoIntel kan een manifest maken voor detectie en segmentatie.'
|
||||
: 'De tegelgrootte moet positief zijn en de overlap moet kleiner blijven.',
|
||||
},
|
||||
{
|
||||
label: 'Clip AOI',
|
||||
state: areas.length > 0 ? 'available' : 'missing',
|
||||
detail: areas.length > 0 ? `${areas.length} project area${areas.length === 1 ? '' : 's'} available.` : 'Create an area before clipping.',
|
||||
label: 'Werkgebied voor begrenzing',
|
||||
state: areas.length > 0 ? 'beschikbaar' : 'ontbreekt',
|
||||
detail: areas.length > 0 ? `${areas.length} ${areas.length === 1 ? 'gebied' : 'gebieden'} beschikbaar.` : 'Maak eerst een gebied aan.',
|
||||
},
|
||||
]
|
||||
const rasterGuardrailItems = [
|
||||
!selectedDatasetId ? 'Select a raster dataset before running raster operations.' : null,
|
||||
rasterUnavailableMessage ? `Raster unavailable: ${rasterUnavailableMessage}` : null,
|
||||
selectedDatasetId && !selectedRasterMetadata ? 'Inspect metadata before reprojecting, clipping, tiling or computing indices.' : null,
|
||||
selectedRasterMetadata && !selectedRasterMetadata?.crs ? 'CRS is missing; geospatial handoff should be fixed before downstream QA.' : null,
|
||||
!rasterPreview ? 'Preview is not generated yet; create it before visual review.' : null,
|
||||
!isRasterTileInputValid ? 'Tile settings are invalid; update tile size and overlap before generating a manifest.' : null,
|
||||
areas.length === 0 ? 'No project area exists yet, so raster clipping is disabled.' : null,
|
||||
!selectedDatasetId ? 'Kies eerst een rasterbestand.' : null,
|
||||
rasterUnavailableMessage ? `Raster niet beschikbaar: ${rasterUnavailableMessage}` : null,
|
||||
selectedDatasetId && !selectedRasterMetadata ? 'Controleer de metadata vóór herprojectie, begrenzing, tegels of indexberekening.' : null,
|
||||
selectedRasterMetadata && !selectedRasterMetadata?.crs ? 'Het coördinatenstelsel ontbreekt; herstel dit vóór verdere ruimtelijke analyse.' : null,
|
||||
!rasterPreview ? 'Er is nog geen voorbeeldweergave gemaakt.' : null,
|
||||
!isRasterTileInputValid ? 'De tegelinstellingen zijn ongeldig.' : null,
|
||||
areas.length === 0 ? 'Er bestaat nog geen werkgebied; begrenzen is daarom uitgeschakeld.' : null,
|
||||
].filter((item): item is string => Boolean(item))
|
||||
|
||||
return (
|
||||
<div className="dataset-tool-panel raster-tool-panel">
|
||||
<section className="raster-readiness-surface" aria-label="Raster pipeline readiness">
|
||||
<section className="raster-readiness-surface" aria-label="Gereedheid van rasterverwerking">
|
||||
<div className="panel-title-row">
|
||||
<div>
|
||||
<h3>Raster pipeline readiness</h3>
|
||||
<p>Operational state for metadata, preview, clipping and tile-manifest handoff.</p>
|
||||
<h3>Gereedheid van het raster</h3>
|
||||
<p>Status van metadata, voorbeeldweergave, begrenzing en beeldtegels.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="raster-readiness-grid">
|
||||
@@ -164,54 +164,54 @@ export function RasterControls({
|
||||
))}
|
||||
</div>
|
||||
<div className="raster-manifest-handoff">
|
||||
<span>Latest tile manifest</span>
|
||||
<span>Laatste beeldtegelmanifest</span>
|
||||
<p>
|
||||
{latestRasterTileManifestPath ||
|
||||
'No tile manifest generated yet. Generate tiles before handing this raster to Detection Lab.'}
|
||||
'Nog geen beeldtegels gemaakt. Maak beeldtegels voordat je dit raster gebruikt voor beeldanalyse.'}
|
||||
</p>
|
||||
{latestRasterTileManifest ? (
|
||||
<dl className="raster-manifest-details">
|
||||
<div>
|
||||
<dt>Tile count</dt>
|
||||
<dd>{latestRasterTileManifest.count ?? 'n/a'}</dd>
|
||||
<dt>Aantal tegels</dt>
|
||||
<dd>{latestRasterTileManifest.count ?? 'n.v.t.'}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Tile size</dt>
|
||||
<dd>{latestRasterTileManifest.tile_size ?? 'n/a'}</dd>
|
||||
<dt>Tegelgrootte</dt>
|
||||
<dd>{latestRasterTileManifest.tile_size ?? 'n.v.t.'}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Overlap</dt>
|
||||
<dd>{latestRasterTileManifest.overlap ?? 'n/a'}</dd>
|
||||
<dd>{latestRasterTileManifest.overlap ?? 'n.v.t.'}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Tile set</dt>
|
||||
<dd>{latestRasterTileManifest.tile_set_id ?? 'n/a'}</dd>
|
||||
<dt>Tegelset</dt>
|
||||
<dd>{latestRasterTileManifest.tile_set_id ?? 'n.v.t.'}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Use in Detection Lab with current manifest"
|
||||
aria-label="Gebruik huidig manifest voor gebouwdetectie"
|
||||
onClick={onUseTileManifestForDetection}
|
||||
disabled={!latestRasterTileManifestPath}
|
||||
>
|
||||
Use manifest in Detection Lab
|
||||
Gebruik voor gebouwdetectie
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Use in Segmentation Lab with current manifest"
|
||||
aria-label="Gebruik huidig manifest voor segmentatie"
|
||||
onClick={onUseTileManifestForSegmentation}
|
||||
disabled={!latestRasterTileManifestPath}
|
||||
>
|
||||
Use manifest in Segmentation Lab
|
||||
Gebruik voor segmentatie
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
<section className="raster-guardrail-surface" aria-label="Processing guardrails">
|
||||
<section className="raster-guardrail-surface" aria-label="Veiligheidscontroles">
|
||||
<div className="panel-title-row">
|
||||
<div>
|
||||
<h3>Processing guardrails</h3>
|
||||
<p>Checks that protect downstream GIS and AI operations from ambiguous raster state.</p>
|
||||
<h3>Veiligheidscontroles</h3>
|
||||
<p>Controles die onduidelijke of ruimtelijk onveilige verwerking voorkomen.</p>
|
||||
</div>
|
||||
</div>
|
||||
{rasterGuardrailItems.length > 0 ? (
|
||||
@@ -221,83 +221,83 @@ export function RasterControls({
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<p className="raster-readiness-state">Raster controls are ready for safe operation.</p>
|
||||
<p className="raster-readiness-state">Het raster is gereed voor veilige verwerking.</p>
|
||||
)}
|
||||
</section>
|
||||
<div className="dataset-tool-group">
|
||||
<h4 className="dataset-tool-heading">Raster metadata</h4>
|
||||
<p>Raster driver: {selectedRasterMetadata?.driver ?? 'n/a'}</p>
|
||||
<p>Raster size: {selectedRasterMetadata ? `${selectedRasterMetadata.width} x ${selectedRasterMetadata.height}` : 'n/a'}</p>
|
||||
<p>Raster checksum: {selectedRasterMetadata?.checksum_sha256 ?? 'n/a'}</p>
|
||||
<h4 className="dataset-tool-heading">Rastermetadata</h4>
|
||||
<p>Bestandsdriver: {selectedRasterMetadata?.driver ?? 'n.v.t.'}</p>
|
||||
<p>Afmetingen: {selectedRasterMetadata ? `${selectedRasterMetadata.width} x ${selectedRasterMetadata.height}` : 'n.v.t.'}</p>
|
||||
<p>Controlesom: {selectedRasterMetadata?.checksum_sha256 ?? 'n.v.t.'}</p>
|
||||
<p>
|
||||
Profile: CRS {selectedRasterMetadata?.crs ?? 'n/a'} | bands {selectedRasterMetadata?.band_count ?? 'n/a'} | dtype {
|
||||
(selectedRasterMetadata?.dtype as string[] | undefined)?.join(', ') ?? 'n/a'}
|
||||
Profiel: CRS {selectedRasterMetadata?.crs ?? 'n.v.t.'} | banden {selectedRasterMetadata?.band_count ?? 'n.v.t.'} | datatype {
|
||||
(selectedRasterMetadata?.dtype as string[] | undefined)?.join(', ') ?? 'n.v.t.'}
|
||||
</p>
|
||||
<p>Bounds: {formatRasterBounds(selectedRasterMetadata?.bounds)}</p>
|
||||
<p>Resolution: {selectedRasterMetadata?.resolution ? selectedRasterMetadata.resolution.join(', ') : 'n/a'}</p>
|
||||
{rasterUnavailableMessage ? <p className="error">Raster unavailable: {rasterUnavailableMessage}</p> : null}
|
||||
<p>Begrenzing: {formatRasterBounds(selectedRasterMetadata?.bounds)}</p>
|
||||
<p>Resolutie: {selectedRasterMetadata?.resolution ? selectedRasterMetadata.resolution.join(', ') : 'n.v.t.'}</p>
|
||||
{rasterUnavailableMessage ? <p className="error">Raster niet beschikbaar: {rasterUnavailableMessage}</p> : null}
|
||||
</div>
|
||||
<h3>Raster operations</h3>
|
||||
<p>Available operations: inspect, stats, reproject, preview, clip by selected area, tile generation.</p>
|
||||
<p>Preview: {rasterPreview?.preview.path ?? 'not generated'}</p>
|
||||
<p>Preview size: {rasterPreview?.preview.width ?? 'n/a'} x {rasterPreview?.preview.height ?? 'n/a'}</p>
|
||||
<h3>Rasterbewerkingen</h3>
|
||||
<p>Controleer metadata en statistieken, herprojecteer, begrens of maak beeldtegels.</p>
|
||||
<p>Voorbeeld: {rasterPreview ? 'aangemaakt' : 'nog niet aangemaakt'}</p>
|
||||
<p>Afmetingen voorbeeld: {rasterPreview?.preview.width ?? 'n.v.t.'} x {rasterPreview?.preview.height ?? 'n.v.t.'}</p>
|
||||
<button type="button" onClick={onRunRasterInspect}>
|
||||
Inspect raster metadata
|
||||
Metadata controleren
|
||||
</button>
|
||||
<button type="button" onClick={onRunRasterPreview} disabled={!selectedDatasetId}>
|
||||
Generate preview
|
||||
Voorbeeld maken
|
||||
</button>
|
||||
<button type="button" onClick={onRunRasterStats}>
|
||||
Compute band statistics
|
||||
Bandstatistieken berekenen
|
||||
</button>
|
||||
{selectedRasterStats ? (
|
||||
<div>
|
||||
<h4>Band statistics</h4>
|
||||
<p>Generated: {selectedRasterStats.generated_at ?? 'n/a'}</p>
|
||||
<h4>Bandstatistieken</h4>
|
||||
<p>Aangemaakt: {selectedRasterStats.generated_at ?? 'n.v.t.'}</p>
|
||||
<ul>
|
||||
{selectedRasterStats.bands.map((band) => (
|
||||
<li key={band.band_index}>
|
||||
Band {band.band_index}: min {band.min ?? 'n/a'}, max {band.max ?? 'n/a'}, mean {band.mean ?? 'n/a'}, std {band.std ?? 'n/a'},
|
||||
valid {band.valid_pixel_count}, nodata ratio {(band.nodata_ratio * 100).toFixed(2)}%, dtype {band.dtype ?? 'n/a'}
|
||||
Band {band.band_index}: minimum {band.min ?? 'n.v.t.'}, maximum {band.max ?? 'n.v.t.'}, gemiddelde {band.mean ?? 'n.v.t.'}, standaardafwijking {band.std ?? 'n.v.t.'},
|
||||
geldig {band.valid_pixel_count}, aandeel zonder data {(band.nodata_ratio * 100).toFixed(2)}%, datatype {band.dtype ?? 'n.v.t.'}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="dataset-tool-group">
|
||||
<h4 className="dataset-tool-heading">Reproject raster</h4>
|
||||
<p className="dataset-tool-helper">Create a derived raster in a target CRS with the selected resampling method.</p>
|
||||
<h4 className="dataset-tool-heading">Raster herprojecteren</h4>
|
||||
<p className="dataset-tool-helper">Maak een afgeleid raster in een ander coördinatenstelsel.</p>
|
||||
<div className="dataset-tool-grid">
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">Reproject CRS</span>
|
||||
<span className="dataset-tool-label">Doel-CRS</span>
|
||||
<input
|
||||
value={rasterReprojectCrs}
|
||||
onChange={(event) => onSetRasterReprojectCrs(event.target.value)}
|
||||
placeholder="EPSG:31370"
|
||||
/>
|
||||
<span className="dataset-tool-helper">Target CRS for the derived raster artifact.</span>
|
||||
<span className="dataset-tool-helper">Coördinatenstelsel van het afgeleide raster.</span>
|
||||
</label>
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">Resampling</span>
|
||||
<span className="dataset-tool-label">Herbemonstering</span>
|
||||
<select value={rasterReprojectResampling} onChange={(event) => onSetRasterReprojectResampling(event.target.value)}>
|
||||
<option value="nearest">nearest</option>
|
||||
<option value="bilinear">bilinear</option>
|
||||
<option value="cubic">cubic</option>
|
||||
</select>
|
||||
<span className="dataset-tool-helper">Nearest preserves classes; bilinear/cubic smooth continuous rasters.</span>
|
||||
<span className="dataset-tool-helper">Dichtstbijzijnd behoudt klassen; bilineair en kubisch verzachten continue rasters.</span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="dataset-tool-action-row">
|
||||
<button type="button" onClick={onRunRasterReproject}>
|
||||
Reproject raster
|
||||
Raster herprojecteren
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="dataset-tool-group">
|
||||
<h4 className="dataset-tool-heading">Clip raster</h4>
|
||||
<p className="dataset-tool-helper">Clip the selected raster to an existing project area.</p>
|
||||
<h4 className="dataset-tool-heading">Raster begrenzen</h4>
|
||||
<p className="dataset-tool-helper">Beperk het raster tot een bestaand werkgebied.</p>
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">Clip area</span>
|
||||
<span className="dataset-tool-label">Werkgebied</span>
|
||||
<select value={selectedClipAreaId} onChange={(event) => onSetSelectedClipAreaId(event.target.value)}>
|
||||
{areas.map((area) => (
|
||||
<option key={area.id} value={area.id}>
|
||||
@@ -308,24 +308,24 @@ export function RasterControls({
|
||||
</label>
|
||||
<div className="dataset-tool-action-row">
|
||||
<button type="button" onClick={onRunRasterClip} disabled={areas.length === 0}>
|
||||
Clip raster by area
|
||||
Raster begrenzen
|
||||
</button>
|
||||
</div>
|
||||
{areas.length === 0 ? <p className="dataset-tool-error">Create an area before raster clipping.</p> : null}
|
||||
{areas.length === 0 ? <p className="dataset-tool-error">Maak eerst een werkgebied aan.</p> : null}
|
||||
</div>
|
||||
<div className="dataset-tool-group">
|
||||
<h4 className="dataset-tool-heading">Generate tiles</h4>
|
||||
<p className="dataset-tool-helper">Create a tile manifest for downstream detection or segmentation runs.</p>
|
||||
<h4 className="dataset-tool-heading">Beeldtegels maken</h4>
|
||||
<p className="dataset-tool-helper">Maak beeldtegels voor detectie of segmentatie.</p>
|
||||
<div className="dataset-tool-grid">
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">Tile size</span>
|
||||
<span className="dataset-tool-label">Tegelgrootte</span>
|
||||
<input
|
||||
type="number"
|
||||
min={1}
|
||||
value={rasterTileSize}
|
||||
onChange={(event) => onSetRasterTileSize(Number(event.target.value))}
|
||||
/>
|
||||
<span className="dataset-tool-helper">{'Tile size must be > 0.'}</span>
|
||||
<span className="dataset-tool-helper">De tegelgrootte moet groter zijn dan nul.</span>
|
||||
</label>
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">Overlap</span>
|
||||
@@ -335,86 +335,86 @@ export function RasterControls({
|
||||
value={rasterTileOverlap}
|
||||
onChange={(event) => onSetRasterTileOverlap(Number(event.target.value))}
|
||||
/>
|
||||
<span className="dataset-tool-helper">Overlap must be smaller than tile size.</span>
|
||||
<span className="dataset-tool-helper">De overlap moet kleiner zijn dan de tegelgrootte.</span>
|
||||
</label>
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">Tile basename</span>
|
||||
<span className="dataset-tool-label">Bestandsnaamvoorvoegsel</span>
|
||||
<input
|
||||
value={rasterTileOutputName}
|
||||
onChange={(event) => onSetRasterTileOutputName(event.target.value)}
|
||||
placeholder="optional"
|
||||
placeholder="optioneel"
|
||||
/>
|
||||
<span className="dataset-tool-helper">Optional artifact name prefix for generated tiles.</span>
|
||||
<span className="dataset-tool-helper">Optioneel voorvoegsel voor de aangemaakte tegels.</span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="dataset-tool-action-row">
|
||||
<button type="button" onClick={onRunRasterTile} disabled={!isRasterTileInputValid}>
|
||||
Generate tiles
|
||||
Beeldtegels maken
|
||||
</button>
|
||||
</div>
|
||||
{!isRasterTileInputValid ? (
|
||||
<p className="dataset-tool-error">
|
||||
Tile size must be {'>'} 0 and overlap must be {'>='} 0 and smaller than tile size.
|
||||
De tegelgrootte moet groter zijn dan nul en de overlap moet positief en kleiner zijn dan de tegelgrootte.
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
<h4>Spectral indices</h4>
|
||||
<h4>Spectrale indexen</h4>
|
||||
<div>
|
||||
<p>Use available band indexes from the raster file (1-based).</p>
|
||||
<p>Gebruik de beschikbare bandnummers uit het rasterbestand, beginnend bij 1.</p>
|
||||
<div className="dataset-tool-group">
|
||||
<h4 className="dataset-tool-heading">NDVI</h4>
|
||||
<p className="dataset-tool-helper">Vegetation index from NIR and red bands.</p>
|
||||
<p className="dataset-tool-helper">Vegetatie-index op basis van nabij-infrarood en rood.</p>
|
||||
<div className="dataset-tool-grid">
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">NIR band</span>
|
||||
<span className="dataset-tool-label">NIR-band</span>
|
||||
<input type="number" min={1} value={ndviNirBand} onChange={(event) => onSetNdviNirBand(Number(event.target.value))} />
|
||||
</label>
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">Red band</span>
|
||||
<span className="dataset-tool-label">Rode band</span>
|
||||
<input type="number" min={1} value={ndviRedBand} onChange={(event) => onSetNdviRedBand(Number(event.target.value))} />
|
||||
</label>
|
||||
</div>
|
||||
<div className="dataset-tool-action-row">
|
||||
<button type="button" onClick={onRunRasterNdvi}>
|
||||
Compute NDVI
|
||||
NDVI berekenen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="dataset-tool-group">
|
||||
<h4 className="dataset-tool-heading">NDWI</h4>
|
||||
<p className="dataset-tool-helper">Water index from NIR and green bands.</p>
|
||||
<p className="dataset-tool-helper">Waterindex op basis van nabij-infrarood en groen.</p>
|
||||
<div className="dataset-tool-grid">
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">NIR band</span>
|
||||
<span className="dataset-tool-label">NIR-band</span>
|
||||
<input type="number" min={1} value={ndwiNirBand} onChange={(event) => onSetNdwiNirBand(Number(event.target.value))} />
|
||||
</label>
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">Green band</span>
|
||||
<span className="dataset-tool-label">Groene band</span>
|
||||
<input type="number" min={1} value={ndwiGreenBand} onChange={(event) => onSetNdwiGreenBand(Number(event.target.value))} />
|
||||
</label>
|
||||
</div>
|
||||
<div className="dataset-tool-action-row">
|
||||
<button type="button" onClick={onRunRasterNdwi}>
|
||||
Compute NDWI
|
||||
NDWI berekenen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="dataset-tool-group">
|
||||
<h4 className="dataset-tool-heading">NDBI</h4>
|
||||
<p className="dataset-tool-helper">Built-up index from SWIR and NIR bands.</p>
|
||||
<p className="dataset-tool-helper">Bebouwingsindex op basis van kortgolvig en nabij-infrarood.</p>
|
||||
<div className="dataset-tool-grid">
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">SWIR band</span>
|
||||
<span className="dataset-tool-label">SWIR-band</span>
|
||||
<input type="number" min={1} value={ndbiSwirBand} onChange={(event) => onSetNdbiSwirBand(Number(event.target.value))} />
|
||||
</label>
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">NIR band</span>
|
||||
<span className="dataset-tool-label">NIR-band</span>
|
||||
<input type="number" min={1} value={ndbiNirBand} onChange={(event) => onSetNdbiNirBand(Number(event.target.value))} />
|
||||
</label>
|
||||
</div>
|
||||
<div className="dataset-tool-action-row">
|
||||
<button type="button" onClick={onRunRasterNdbi}>
|
||||
Compute NDBI
|
||||
NDBI berekenen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,13 +25,13 @@ export function VectorControls({
|
||||
}: VectorControlsProps) {
|
||||
return (
|
||||
<div className="dataset-tool-panel vector-tool-panel">
|
||||
<h3>Vector operations</h3>
|
||||
<h3>Vectorbewerkingen</h3>
|
||||
<div className="dataset-tool-group">
|
||||
<h4 className="dataset-tool-heading">Clip vector</h4>
|
||||
<p className="dataset-tool-helper">Clip features to the selected project area.</p>
|
||||
<h4 className="dataset-tool-heading">Begrenzen tot gebied</h4>
|
||||
<p className="dataset-tool-helper">Beperk objecten tot het gekozen werkgebied.</p>
|
||||
<div className="dataset-tool-grid">
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">Clip area</span>
|
||||
<span className="dataset-tool-label">Werkgebied</span>
|
||||
<select value={selectedClipAreaId} onChange={(event) => onSetSelectedClipAreaId(event.target.value)}>
|
||||
{areas.map((area) => (
|
||||
<option key={area.id} value={area.id}>
|
||||
@@ -43,39 +43,39 @@ export function VectorControls({
|
||||
</div>
|
||||
<div className="dataset-tool-action-row">
|
||||
<button type="button" onClick={onRunVectorClip} disabled={areas.length === 0}>
|
||||
Run clip
|
||||
Begrenzen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="dataset-tool-group">
|
||||
<h4 className="dataset-tool-heading">Buffer vector</h4>
|
||||
<p className="dataset-tool-helper">Create a 25m buffer using the existing vector operation defaults.</p>
|
||||
<h4 className="dataset-tool-heading">Invloedszone</h4>
|
||||
<p className="dataset-tool-helper">Maak een zone van 25 meter rond ieder object.</p>
|
||||
<div className="dataset-tool-action-row">
|
||||
<button type="button" onClick={onRunVectorBuffer}>
|
||||
Run buffer (25m)
|
||||
Zone van 25 m maken
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="dataset-tool-group">
|
||||
<h4 className="dataset-tool-heading">Intersect vector</h4>
|
||||
<p className="dataset-tool-helper">Intersect with another persisted vector dataset.</p>
|
||||
<h4 className="dataset-tool-heading">Lagen doorsnijden</h4>
|
||||
<p className="dataset-tool-helper">Bereken de overlap met een andere bewaarde vectorlaag.</p>
|
||||
<div className="dataset-tool-grid">
|
||||
<label className="dataset-tool-field">
|
||||
<span className="dataset-tool-label">Intersect target</span>
|
||||
<span className="dataset-tool-label">Tweede kaartlaag</span>
|
||||
<select value={selectedIntersectTargetId} onChange={(event) => onSetSelectedIntersectTargetId(event.target.value)}>
|
||||
<option value="">auto first vector</option>
|
||||
<option value="">Automatisch de eerste geschikte laag</option>
|
||||
{availableVectorTargets.map((target) => (
|
||||
<option key={target.id} value={target.id}>
|
||||
{target.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<span className="dataset-tool-helper">Leave automatic to use the first available vector target.</span>
|
||||
<span className="dataset-tool-helper">Laat automatisch staan om de eerste beschikbare vectorlaag te gebruiken.</span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="dataset-tool-action-row">
|
||||
<button type="button" onClick={onRunVectorIntersect}>
|
||||
Run intersect
|
||||
Overlap berekenen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user