UI fixes
This commit is contained in:
parent
b1618fd218
commit
b6ad070ee4
@ -536,7 +536,7 @@ func trainingRunJob(root string, count int) {
|
||||
detectorScript,
|
||||
"--root", root,
|
||||
"--base", "yolo11n.pt",
|
||||
"--epochs", "80",
|
||||
"--epochs", "20",
|
||||
"--imgsz", "640",
|
||||
)
|
||||
|
||||
|
||||
@ -213,6 +213,37 @@ function sortTrainingLabels(input: Partial<TrainingLabels> | null | undefined):
|
||||
}
|
||||
}
|
||||
|
||||
function TrainingOverlay(props: { step: string; progress: number }) {
|
||||
return (
|
||||
<div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-black/45 text-center text-white backdrop-blur-[1px]">
|
||||
<LoadingSpinner
|
||||
size="lg"
|
||||
className="text-white"
|
||||
srLabel="Training läuft…"
|
||||
/>
|
||||
|
||||
<div className="mt-3 text-sm font-semibold">
|
||||
Training läuft…
|
||||
</div>
|
||||
|
||||
<div className="mt-1 max-w-[260px] px-4 text-xs text-white/80">
|
||||
{props.step || 'Bitte warten. Die Oberfläche ist währenddessen gesperrt.'}
|
||||
</div>
|
||||
|
||||
<div className="mt-3 h-2 w-48 overflow-hidden rounded-full bg-white/20">
|
||||
<div
|
||||
className="h-full rounded-full bg-emerald-400 transition-all duration-500"
|
||||
style={{ width: `${clampPercent(props.progress)}%` }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-1 text-[11px] text-white/70">
|
||||
{Math.round(props.progress)}%
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function TrainingTab() {
|
||||
const [labels, setLabels] = useState<TrainingLabels>(emptyLabels)
|
||||
const [sample, setSample] = useState<TrainingSample | null>(null)
|
||||
@ -353,12 +384,9 @@ export default function TrainingTab() {
|
||||
|
||||
if (cancelled) return
|
||||
|
||||
const res = await fetch('/api/training/status', { cache: 'no-store' })
|
||||
const data = await res.json().catch(() => null)
|
||||
|
||||
if (!cancelled && !data?.training?.running) {
|
||||
await loadNext()
|
||||
}
|
||||
// Wichtig: Auch während laufendem Training wieder das aktuelle offene Sample laden,
|
||||
// damit nicht "Kein Frame geladen" angezeigt wird.
|
||||
await loadNext()
|
||||
}
|
||||
|
||||
void init()
|
||||
@ -819,22 +847,6 @@ export default function TrainingTab() {
|
||||
{trainingRunning ? 'Training läuft…' : 'Training starten'}
|
||||
</Button>
|
||||
|
||||
{trainingRunning ? (
|
||||
<div className="rounded-lg bg-gray-50 p-2 text-xs ring-1 ring-black/5 dark:bg-white/5 dark:ring-white/10">
|
||||
<div className="flex items-center justify-between gap-2 text-[11px] text-gray-600 dark:text-gray-300">
|
||||
<span>{shownTrainingStep || 'Training läuft…'}</span>
|
||||
<span>{Math.round(shownTrainingProgress)}%</span>
|
||||
</div>
|
||||
|
||||
<div className="mt-2 h-2 overflow-hidden rounded-full bg-gray-200 dark:bg-white/10">
|
||||
<div
|
||||
className="h-full rounded-full bg-emerald-500 transition-all duration-500"
|
||||
style={{ width: `${clampPercent(shownTrainingProgress)}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className="text-[11px] leading-relaxed text-gray-500 dark:text-gray-400">
|
||||
{canStartTraining ? (
|
||||
<>
|
||||
@ -865,14 +877,7 @@ export default function TrainingTab() {
|
||||
{/* Mitte */}
|
||||
<section className="min-w-0 rounded-xl border border-gray-200 bg-white p-3 shadow-sm dark:border-white/10 dark:bg-gray-900/60">
|
||||
<div className="relative flex min-h-[360px] flex-1 items-center justify-center overflow-hidden rounded-lg bg-black">
|
||||
{loading ? (
|
||||
<LoadingSpinner
|
||||
size="lg"
|
||||
center
|
||||
className="text-white/80"
|
||||
srLabel="Frame wird geladen…"
|
||||
/>
|
||||
) : imageSrc ? (
|
||||
{imageSrc ? (
|
||||
<div className="relative flex h-full w-full items-center justify-center">
|
||||
<div
|
||||
ref={imageBoxRef}
|
||||
@ -926,7 +931,7 @@ export default function TrainingTab() {
|
||||
? 'cursor-default bg-amber-400'
|
||||
: 'cursor-pointer bg-emerald-400 hover:bg-red-400',
|
||||
].join(' ')}
|
||||
disabled={Boolean(isDraft)}
|
||||
disabled={Boolean(isDraft) || uiLocked}
|
||||
title={isDraft ? box.label : `${box.label} löschen`}
|
||||
onPointerDown={(e) => {
|
||||
e.preventDefault()
|
||||
@ -935,7 +940,7 @@ export default function TrainingTab() {
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if (!isDraft) removeBox(index)
|
||||
if (!isDraft && !uiLocked) removeBox(index)
|
||||
}}
|
||||
>
|
||||
<span>{box.label}</span>
|
||||
@ -951,35 +956,26 @@ export default function TrainingTab() {
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{trainingRunning ? (
|
||||
<div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-black/45 text-center text-white backdrop-blur-[1px]">
|
||||
<LoadingSpinner
|
||||
size="lg"
|
||||
className="text-white"
|
||||
srLabel="Training läuft…"
|
||||
/>
|
||||
|
||||
<div className="mt-3 text-sm font-semibold">
|
||||
Training läuft…
|
||||
</div>
|
||||
|
||||
<div className="mt-1 max-w-[260px] px-4 text-xs text-white/80">
|
||||
{shownTrainingStep || 'Bitte warten. Die Oberfläche ist währenddessen gesperrt.'}
|
||||
</div>
|
||||
|
||||
<div className="mt-3 h-2 w-48 overflow-hidden rounded-full bg-white/20">
|
||||
<div
|
||||
className="h-full rounded-full bg-emerald-400 transition-all duration-500"
|
||||
style={{ width: `${clampPercent(shownTrainingProgress)}%` }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-1 text-[11px] text-white/70">
|
||||
{Math.round(shownTrainingProgress)}%
|
||||
</div>
|
||||
</div>
|
||||
<TrainingOverlay
|
||||
step={shownTrainingStep}
|
||||
progress={shownTrainingProgress}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
) : trainingRunning ? (
|
||||
<TrainingOverlay
|
||||
step={shownTrainingStep || 'Aktuelles Bild wird geladen…'}
|
||||
progress={shownTrainingProgress}
|
||||
/>
|
||||
) : loading ? (
|
||||
<LoadingSpinner
|
||||
size="lg"
|
||||
center
|
||||
className="text-white/80"
|
||||
srLabel="Frame wird geladen…"
|
||||
/>
|
||||
) : (
|
||||
<div className="text-sm text-white/80">Kein Frame geladen</div>
|
||||
)}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user