Commander: „wenn man auf rippen starten klickt passiert irgendwas, was das
Programm nicht mag. Der Hintergrund ist einfach leer und er startet nix. Es
gibt auch keine fehlermeldung."
Nachgestellt: Dienst lokal gestartet, Disc-Karte geoeffnet, „Rippen starten"
geklickt. Browser-Konsole:
TypeError: Cannot read properties of undefined (reading 'toUpperCase')
## Er startet sehr wohl — man sieht es nur nie
Waehrend die Seite leer war, lief der Job (per API gemessen: status
`processing`, progress 12). Das „er startet nix" ist also der zweite Teil
desselben Fehlers: Die Oberflaeche war weg, bevor sie ihn zeigen konnte.
## Die Ursache
`_job_kurz` in `bus/waechter.py` trug nur `status`, `progress`, `title` und
`error` — **keinen `type`**. Das UI fuegt aus `job.created` einen halben Job
in seine Liste ein, `LiveLogSection` liest `job.type.toUpperCase()`, und React
baut bei einem Fehler im Zeichnen den GESAMTEN Baum ab. Es gab in diesem
Projekt keine einzige Fehlergrenze — also blieb ein leerer Bildschirm ohne
jede Meldung.
## Drei Reparaturen, weil es drei Fehler waren
1. **Das Ereignis traegt den Job.** `type`, `device` und `startTime` fahren
mit. Sie aendern sich ueber die Lebenszeit eines Jobs nie, kosten also kein
zusaetzliches Ereignis — und ohne `startTime` stand in der Jobliste
sekundenlang „Invalid Date".
2. **Das UI vertraegt sein Fehlen.** `LiveLogSection` und `TypeBadge` nahmen
einen vollstaendigen Job an. Zeile 108 derselben Datei hatte das
Fragezeichen laengst, Zeile 48 nicht.
3. **Eine Fehlergrenze.** Ein Fehler in einer Karte darf nicht den ganzen
Bildschirm mitnehmen — und schon gar nicht schweigend. Jetzt steht da, was
los ist, die Navigation bleibt bedienbar, und der Hinweis sagt das
Wichtigste: laufende Rips gehen weiter.
## Warum es niemand gefunden hat
`unterschiede()` bekommt die Kurzform schon fertig, und alle Tests reichen
ihre eigenen Woerterbuecher herein. **`_job_kurz` selbst war nie geprueft.**
Jetzt bewacht `UI_PFLICHTFELDER` den Vertrag mechanisch — es gibt kein
gemeinsames Typsystem zwischen Python und dem UI.
Gegengeprueft im Browser: derselbe Klick, keine Konsolenfehler, Job erscheint
als „Alle (1)".
833 Tests gruen, ruff sauber.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
import { Disc } from 'lucide-react'
|
|
import { STATUS_STYLES, DISC_TYPE_STYLES } from '../../lib/design'
|
|
|
|
interface StatusBadgeProps {
|
|
status: string
|
|
className?: string
|
|
}
|
|
|
|
export function StatusBadge({ status, className = '' }: StatusBadgeProps) {
|
|
const config = STATUS_STYLES[status as keyof typeof STATUS_STYLES] || {
|
|
badge: 'bg-slate-500/15 text-slate-400 border-slate-500/30',
|
|
label: status,
|
|
}
|
|
|
|
return (
|
|
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium border ${config.badge} ${className}`}>
|
|
{config.label}
|
|
</span>
|
|
)
|
|
}
|
|
|
|
interface TypeBadgeProps {
|
|
type: string
|
|
className?: string
|
|
}
|
|
|
|
export function TypeBadge({ type, className = '' }: TypeBadgeProps) {
|
|
// Ein fehlender Typ darf kein Absturz sein. Am 29.08.2026 hat genau diese
|
|
// Annahme (an anderer Stelle) die ganze Oberflaeche geleert: Ein frisch
|
|
// angelegter Job kommt ueber den Ereignisstrom ohne `type` an.
|
|
const config = DISC_TYPE_STYLES[type as keyof typeof DISC_TYPE_STYLES] || {
|
|
badge: 'bg-slate-500/15 text-slate-400 border-slate-500/30',
|
|
label: type ? type.toUpperCase() : 'DISC',
|
|
}
|
|
|
|
return (
|
|
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md text-xs font-medium border ${config.badge} ${className}`}>
|
|
<Disc size={13} />
|
|
{config.label}
|
|
</span>
|
|
)
|
|
}
|