feat: simplify regional workbench language
This commit is contained in:
@@ -16,6 +16,13 @@ import { DETECTION_OPERATOR_PROFILES, type DetectionOperatorProfile } from './de
|
||||
const DETECTION_PAGE_SIZE_OPTIONS = [25, 50, 100] as const
|
||||
const DEFAULT_DETECTION_PAGE_SIZE = 50
|
||||
|
||||
function detectionModelLabel(model: DetectionModelCapability): string {
|
||||
if (model.model_id === 'yolo-configured') return 'Lokaal gebouwmodel'
|
||||
if (model.model_id === 'manual-fixture-detector') return 'Testmodel (alleen voor demo)'
|
||||
if (model.model_id === 'yolo-placeholder') return 'Gebouwmodel nog niet geconfigureerd'
|
||||
return model.display_name
|
||||
}
|
||||
|
||||
interface CalibrationRow {
|
||||
analysisRunId: string
|
||||
qualityCheckId: string
|
||||
@@ -272,7 +279,7 @@ export function DetectionLab({
|
||||
<ul className="model-list">
|
||||
{detectionModels.map((model) => (
|
||||
<li className={model.configured ? 'model-card model-card-ready' : 'model-card'} key={model.model_id}>
|
||||
<strong>{model.display_name}</strong>
|
||||
<strong>{detectionModelLabel(model)}</strong>
|
||||
<span className={model.configured ? 'status-badge status-badge-ready' : 'status-badge'}>{model.status}</span>
|
||||
<div className="entity-meta">
|
||||
<span>{model.model_id}</span>
|
||||
@@ -560,7 +567,7 @@ export function DetectionLab({
|
||||
<select value={selectedDetectionModelId} onChange={(event) => onSelectModel(event.target.value)}>
|
||||
{detectionModels.map((model) => (
|
||||
<option key={model.model_id} value={model.model_id}>
|
||||
{model.display_name}
|
||||
{detectionModelLabel(model)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -587,7 +594,7 @@ export function DetectionLab({
|
||||
Beeldtegelbestand
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Raster tile manifest path"
|
||||
placeholder="Pad naar de aangemaakte beeldtegels"
|
||||
value={detectionTileManifestPath}
|
||||
onChange={(event) => onSetTileManifestPath(event.target.value)}
|
||||
/>
|
||||
@@ -609,17 +616,17 @@ export function DetectionLab({
|
||||
<div className="ai-lab-state-stack">
|
||||
{detectionRunError ? (
|
||||
<div className="result-state result-state-error">
|
||||
<strong>Detection run failed.</strong>
|
||||
<strong>De beeldanalyse is mislukt.</strong>
|
||||
<p>{detectionRunError}</p>
|
||||
</div>
|
||||
) : null}
|
||||
{detectionRunResult ? (
|
||||
<div className="result-summary-card">
|
||||
<p>Status: {detectionRunResult.status}</p>
|
||||
<p>Message: {detectionRunResult.message}</p>
|
||||
<p>Analysis run: {detectionRunResult.analysis_run_id}</p>
|
||||
<p>Job: {detectionRunResult.job_id}</p>
|
||||
<p>Detections: {detectionRunResult.detection_count}</p>
|
||||
<p>Uitleg: {detectionRunResult.message}</p>
|
||||
<p>Analyse: {detectionRunResult.analysis_run_id}</p>
|
||||
<p>Verwerking: {detectionRunResult.job_id}</p>
|
||||
<p>Gevonden objecten: {detectionRunResult.detection_count}</p>
|
||||
{detectionRunResult.error_code ? <p className="error">Code: {detectionRunResult.error_code}</p> : null}
|
||||
</div>
|
||||
) : null}
|
||||
@@ -765,7 +772,7 @@ export function DetectionLab({
|
||||
<option value="">Kies een bewaarde analyse</option>
|
||||
{detectionRuns.map((run) => (
|
||||
<option key={run.id} value={run.id}>
|
||||
{run.model_name || 'detection'} - {run.status} - {run.id}
|
||||
{run.model_name || 'Gebouwdetectie'} · {run.status} · {run.id}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -774,7 +781,7 @@ export function DetectionLab({
|
||||
Type object
|
||||
<input
|
||||
type="text"
|
||||
placeholder="bijvoorbeeld building"
|
||||
placeholder="bijvoorbeeld gebouw"
|
||||
value={detectionClassFilter}
|
||||
onChange={(event) => onSetClassFilter(event.target.value)}
|
||||
/>
|
||||
@@ -811,10 +818,10 @@ export function DetectionLab({
|
||||
<div className="pagination-toolbar" aria-label="Detection result pagination">
|
||||
<p className="pagination-summary" aria-live="polite">
|
||||
<strong>{detectionPageStart + 1}-{detectionPageEnd}</strong>
|
||||
<span>of {detectionItems.length}</span>
|
||||
<span>van {detectionItems.length}</span>
|
||||
</p>
|
||||
<label className="pagination-page-size">
|
||||
Rows
|
||||
Rijen
|
||||
<select
|
||||
value={detectionPageSize}
|
||||
onChange={(event) => {
|
||||
@@ -831,19 +838,19 @@ export function DetectionLab({
|
||||
<button
|
||||
className="secondary-action pagination-button"
|
||||
type="button"
|
||||
aria-label="Previous detection results page"
|
||||
title="Previous page"
|
||||
aria-label="Vorige resultatenpagina"
|
||||
title="Vorige pagina"
|
||||
disabled={currentDetectionPage <= 1}
|
||||
onClick={() => setDetectionResultPage(currentDetectionPage - 1)}
|
||||
>
|
||||
{'<'}
|
||||
</button>
|
||||
<span>Page {currentDetectionPage} of {detectionPageCount}</span>
|
||||
<span>Pagina {currentDetectionPage} van {detectionPageCount}</span>
|
||||
<button
|
||||
className="secondary-action pagination-button"
|
||||
type="button"
|
||||
aria-label="Next detection results page"
|
||||
title="Next page"
|
||||
aria-label="Volgende resultatenpagina"
|
||||
title="Volgende pagina"
|
||||
disabled={currentDetectionPage >= detectionPageCount}
|
||||
onClick={() => setDetectionResultPage(currentDetectionPage + 1)}
|
||||
>
|
||||
@@ -855,10 +862,10 @@ export function DetectionLab({
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Class</th>
|
||||
<th>Confidence</th>
|
||||
<th>Type</th>
|
||||
<th>Zekerheid</th>
|
||||
<th>Model</th>
|
||||
<th>Source tile</th>
|
||||
<th>Beeldtegel</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -879,34 +886,40 @@ export function DetectionLab({
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="ai-lab-results-surface calibration-comparison-surface" aria-label="Detection calibration comparison">
|
||||
<details className="secondary-analysis-disclosure detection-technical-evaluation">
|
||||
<summary>
|
||||
<span>Technische modelevaluatie</span>
|
||||
<strong>{calibrationRows.length > 0 || detectionQaResult ? 'resultaten beschikbaar' : 'optioneel'}</strong>
|
||||
</summary>
|
||||
<div className="ai-lab-disclosure-body">
|
||||
<div className="ai-lab-results-surface calibration-comparison-surface" aria-label="Vergelijking modelkalibratie">
|
||||
<div className="panel-title-row">
|
||||
<div>
|
||||
<h3>Calibration comparison</h3>
|
||||
<p className="muted">Compare persisted detection runs by confidence threshold before promoting a model setting.</p>
|
||||
<h3>Kalibraties vergelijken</h3>
|
||||
<p className="muted">Vergelijk bewaarde analyseruns per zekerheidsdrempel voordat een modelinstelling wordt goedgekeurd.</p>
|
||||
</div>
|
||||
<span className="count-pill">{calibrationRows.length} rows</span>
|
||||
<span className="count-pill">{calibrationRows.length} resultaten</span>
|
||||
</div>
|
||||
{calibrationRows.length > 0 ? (
|
||||
<>
|
||||
<div className="calibration-summary-grid" aria-label="Calibration comparison winners">
|
||||
<CalibrationSummaryCard title="Best F1 candidate" row={bestF1Candidate} metric="f1" />
|
||||
<CalibrationSummaryCard title="Best precision candidate" row={bestPrecisionCandidate} metric="precision" />
|
||||
<CalibrationSummaryCard title="Lowest false-positive pressure" row={lowestFalsePositivePressureCandidate} metric="falsePositives" />
|
||||
<CalibrationSummaryCard title="Beste F1-score" row={bestF1Candidate} metric="f1" />
|
||||
<CalibrationSummaryCard title="Beste precisie" row={bestPrecisionCandidate} metric="precision" />
|
||||
<CalibrationSummaryCard title="Minste foutieve meldingen" row={lowestFalsePositivePressureCandidate} metric="falsePositives" />
|
||||
</div>
|
||||
<div className="table-scroll">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Threshold</th>
|
||||
<th>Drempel</th>
|
||||
<th>Model</th>
|
||||
<th>Detections</th>
|
||||
<th>Precision</th>
|
||||
<th>Objecten</th>
|
||||
<th>Precisie</th>
|
||||
<th>Recall</th>
|
||||
<th>F1</th>
|
||||
<th>False positives</th>
|
||||
<th>False negatives</th>
|
||||
<th>Quality check</th>
|
||||
<th>Fout positief</th>
|
||||
<th>Fout negatief</th>
|
||||
<th>Kwaliteitscontrole</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -915,7 +928,7 @@ export function DetectionLab({
|
||||
<td>{formatNullableNumber(row.threshold, 2)}</td>
|
||||
<td>
|
||||
<strong>{row.modelName}</strong>
|
||||
<span className="table-subtle">{row.modelAssetId ?? 'runtime configured path'}</span>
|
||||
<span className="table-subtle">{row.modelAssetId ?? 'geconfigureerd lokaal model'}</span>
|
||||
</td>
|
||||
<td>{row.detectionCount ?? 'n/a'}</td>
|
||||
<td>{formatNullableNumber(row.precision, 3)}</td>
|
||||
@@ -930,24 +943,24 @@ export function DetectionLab({
|
||||
</table>
|
||||
</div>
|
||||
<div className="lab-action-guardrail">
|
||||
<span>Promotion guardrail</span>
|
||||
<strong>Promote only after checking evidence across AOIs, false positives and false negatives.</strong>
|
||||
<span>Voorwaarde voor goedkeuring</span>
|
||||
<strong>Keur pas goed nadat meerdere gebieden en de foutieve positieve en negatieve resultaten zijn gecontroleerd.</strong>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="result-state result-state-empty">
|
||||
<strong>No calibration comparison available yet.</strong>
|
||||
<p>Run configured YOLO at multiple confidence thresholds, then compare each persisted detection run against the same reference dataset.</p>
|
||||
<strong>Nog geen kalibratievergelijking beschikbaar.</strong>
|
||||
<p>Voer het lokale model met meerdere zekerheidsdrempels uit en vergelijk de resultaten met dezelfde referentielaag.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="ai-lab-qa-surface" aria-label="Detection QA controls and results">
|
||||
<h3>Detection QA</h3>
|
||||
<div className="ai-lab-qa-surface" aria-label="Kwaliteitscontrole gebouwdetectie">
|
||||
<h3>Kwaliteitscontrole gebouwdetectie</h3>
|
||||
<label>
|
||||
Reference dataset
|
||||
Referentielaag
|
||||
<select value={detectionReferenceDatasetId} onChange={(event) => onSelectReferenceDataset(event.target.value)}>
|
||||
<option value="">Select reference dataset</option>
|
||||
<option value="">Kies een referentielaag</option>
|
||||
{referenceDatasets.map((dataset) => (
|
||||
<option key={dataset.id} value={dataset.id}>
|
||||
{dataset.name}
|
||||
@@ -956,24 +969,24 @@ export function DetectionLab({
|
||||
</select>
|
||||
</label>
|
||||
<button className="primary-action" type="button" onClick={onRunQa} disabled={runningDetectionQa || !selectedDetectionRunId || !detectionReferenceDatasetId}>
|
||||
Compare detections to reference
|
||||
Vergelijk met referentielaag
|
||||
</button>
|
||||
{detectionQaError ? (
|
||||
<div className="result-state result-state-error">
|
||||
<strong>Detection QA failed.</strong>
|
||||
<strong>De kwaliteitscontrole is mislukt.</strong>
|
||||
<p>{detectionQaError}</p>
|
||||
</div>
|
||||
) : null}
|
||||
{detectionQaResult ? (
|
||||
<div className="result-summary-card">
|
||||
<p>Status: {detectionQaResult.status}</p>
|
||||
<p>Quality check: {detectionQaResult.quality_check_id}</p>
|
||||
<p>Precision: {detectionQaResult.precision?.toFixed(3) ?? 'n/a'}</p>
|
||||
<p>Kwaliteitscontrole: {detectionQaResult.quality_check_id}</p>
|
||||
<p>Precisie: {detectionQaResult.precision?.toFixed(3) ?? 'n.v.t.'}</p>
|
||||
<p>Recall: {detectionQaResult.recall?.toFixed(3) ?? 'n/a'}</p>
|
||||
<p>F1: {detectionQaResult.f1_score?.toFixed(3) ?? 'n/a'}</p>
|
||||
<p>Mean IoU: {detectionQaResult.mean_iou?.toFixed(3) ?? 'n/a'}</p>
|
||||
<p>False positives: {detectionQaResult.false_positives}</p>
|
||||
<p>False negatives: {detectionQaResult.false_negatives}</p>
|
||||
<p>Gemiddelde overlap: {detectionQaResult.mean_iou?.toFixed(3) ?? 'n.v.t.'}</p>
|
||||
<p>Fout positief: {detectionQaResult.false_positives}</p>
|
||||
<p>Fout negatief: {detectionQaResult.false_negatives}</p>
|
||||
{detectionQaResult.coverage ? (
|
||||
<div className="detection-qa-diagnostic">
|
||||
<span>Inference coverage</span>
|
||||
@@ -1004,6 +1017,8 @@ export function DetectionLab({
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user