From ed6e6b81ebbb5bd052b56c1e3eb8c2016165e8a8 Mon Sep 17 00:00:00 2001 From: Florian Wilde Date: Fri, 25 Sep 2026 18:55:29 +0200 Subject: [PATCH] feat(laeufe): Service, Abarbeitung, Kommentare und Archivschutz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ein Lauf wird vorbereitet, abgearbeitet, abgeschlossen und archiviert. Der Archiv-Schreibschutz sitzt in genau einer Funktion und wird vor jeder Aenderung an Kopfdaten, Schrittergebnis und Kommentar gerufen; abgeschlossen bleibt aenderbar, archiviert nicht. Die Abarbeitungsansicht speichert jeden Schritt einzeln, frischt sich alle zehn Sekunden auf und pausiert im Hintergrund. Sie traegt in der Polling-Antwort keine Befehle und laedt sich auch nicht von selbst neu, solange ein generiertes Passwort auf der Seite steht: beides tauschte es dem Techniker zwischen Lesen und Einfuegen aus. Der unabhaengige Review fand zwei Blocker: ein Befehl konnte zwei verschiedene Passwoerter tragen (Konto bekommt A, Benutzer erfaehrt B), und „nicht zutreffend“ liess sich nicht zuruecknehmen, waehrend die Oberflaeche behauptete, nichts sei gewaehlt. Beides behoben und in Tests festgehalten. Closes #13 Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 43 + docs/architektur.md | 24 + docs/devlog.md | 65 +- docs/issues/013-laeufe-abarbeitung.md | 103 +- docs/issues/README.md | 4 +- docs/screenshots/m8/laeufe-liste-desktop.png | Bin 0 -> 158565 bytes docs/screenshots/m8/laeufe-liste-handy.png | Bin 0 -> 115769 bytes .../m8/lauf-abarbeiten-desktop.png | Bin 0 -> 365447 bytes docs/screenshots/m8/lauf-abarbeiten-handy.png | Bin 0 -> 118520 bytes .../m8/lauf-befehlsschritt-desktop.png | Bin 0 -> 42086 bytes .../m8/lauf-befehlsschritt-handy.png | Bin 0 -> 42498 bytes docs/screenshots/m8/lauf-starten-desktop.png | Bin 0 -> 165963 bytes docs/screenshots/m8/lauf-starten-handy.png | Bin 0 -> 116318 bytes package.json | 1 + scripts/beispiel-lauf.ts | 132 ++ scripts/screenshots.ts | 44 +- src/app/(app)/laeufe/[id]/page.tsx | 406 ++++++ src/app/(app)/laeufe/page.tsx | 210 ++++ src/app/(app)/laeufe/starten/page.tsx | 74 ++ src/app/api/laeufe/[id]/zustand/route.ts | 49 + src/components/laeufe/abschnitt-huelle.tsx | 70 ++ src/components/laeufe/befehlsblock.tsx | 96 ++ src/components/laeufe/lauf-aktionen.tsx | 309 +++++ src/components/laeufe/lauf-aktualisierung.tsx | 130 ++ src/components/laeufe/lauf-starten.tsx | 366 ++++++ src/components/laeufe/schritt-wert.tsx | 139 ++ src/components/laeufe/schritt-zustand.tsx | 210 ++++ src/lib/navigation.ts | 2 +- src/lib/platzhalter-werte.ts | 17 +- src/proxy.ts | 11 + src/server/actions/laeufe.ts | 421 +++++++ src/server/queries/laeufe.ts | 729 +++++++++++ src/server/services/befehle.ts | 42 +- src/server/services/kommentare.ts | 80 ++ src/server/services/laeufe.ts | 1114 +++++++++++++++++ src/server/services/schrittergebnisse.ts | 314 +++++ tests/e2e/laeufe.spec.ts | 367 ++++++ tests/e2e/vorlagen-editor.spec.ts | 2 +- tests/kommentare.test.ts | 194 +++ tests/laeufe.test.ts | 888 +++++++++++++ tests/markdown.test.tsx | 4 +- tests/platzhalter-werte.test.ts | 33 +- tests/schrittergebnisse.test.ts | 553 ++++++++ tests/zustand-route.test.ts | 255 ++++ 44 files changed, 7440 insertions(+), 61 deletions(-) create mode 100644 docs/screenshots/m8/laeufe-liste-desktop.png create mode 100644 docs/screenshots/m8/laeufe-liste-handy.png create mode 100644 docs/screenshots/m8/lauf-abarbeiten-desktop.png create mode 100644 docs/screenshots/m8/lauf-abarbeiten-handy.png create mode 100644 docs/screenshots/m8/lauf-befehlsschritt-desktop.png create mode 100644 docs/screenshots/m8/lauf-befehlsschritt-handy.png create mode 100644 docs/screenshots/m8/lauf-starten-desktop.png create mode 100644 docs/screenshots/m8/lauf-starten-handy.png create mode 100644 scripts/beispiel-lauf.ts create mode 100644 src/app/(app)/laeufe/[id]/page.tsx create mode 100644 src/app/(app)/laeufe/page.tsx create mode 100644 src/app/(app)/laeufe/starten/page.tsx create mode 100644 src/app/api/laeufe/[id]/zustand/route.ts create mode 100644 src/components/laeufe/abschnitt-huelle.tsx create mode 100644 src/components/laeufe/befehlsblock.tsx create mode 100644 src/components/laeufe/lauf-aktionen.tsx create mode 100644 src/components/laeufe/lauf-aktualisierung.tsx create mode 100644 src/components/laeufe/lauf-starten.tsx create mode 100644 src/components/laeufe/schritt-wert.tsx create mode 100644 src/components/laeufe/schritt-zustand.tsx create mode 100644 src/server/actions/laeufe.ts create mode 100644 src/server/queries/laeufe.ts create mode 100644 src/server/services/kommentare.ts create mode 100644 src/server/services/laeufe.ts create mode 100644 src/server/services/schrittergebnisse.ts create mode 100644 tests/e2e/laeufe.spec.ts create mode 100644 tests/kommentare.test.ts create mode 100644 tests/laeufe.test.ts create mode 100644 tests/schrittergebnisse.test.ts create mode 100644 tests/zustand-route.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 0addc2f..9a37d9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,6 +94,28 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). (#012) - „Alle Befehle als Skript kopieren“ je Abschnitt: die Befehle in Reihenfolge, je mit einer Kommentarzeile darüber und dem Zeilenumbruch der jeweiligen Shell (#012) +- Läufe: anlegen — auch als `offen` ohne Start, das ist die Zuweisung —, abarbeiten, abschließen + und archivieren. Ein Lauf wird erst `in Arbeit`, wenn ihn jemand wirklich öffnet (#013) +- Abarbeitungsansicht: nummerierte Abschnitte, Fortschrittsbalken, je Schritt Zustand, Wert, + Notiz, Kommentare und „wer wann“; jeder Schritt speichert einzeln, damit ein verlorener Klick + nicht zwei Stunden Arbeit kostet (#013) +- Die Ansicht frischt sich alle zehn Sekunden auf und pausiert, solange der Tab im Hintergrund + liegt — zwei Techniker an einem Onboarding sehen die Arbeit des anderen (#013) +- Umschalter „Kompakt / Ausführlich“: beim ersten Mal sind die Hilfetexte der eigentliche Wert, + beim dritten Mal stehen sie im Weg (#013) +- Befehlsschritte zeigen den fertigen Befehl mit eingesetzten Werten und einem Kopier-Knopf; ein + unaufgelöster Platzhalter wird angezeigt, statt stillschweigend mitkopiert zu werden (#013) +- „Abschnitt trifft nicht zu“ setzt alle Schritte eines Abschnitts mit einer Begründung auf + `nicht zutreffend` — für die Konto-Abschnitte eines Onboardings ohne eigenes AD (#013) +- Kommentare am Lauf und am einzelnen Schritt (#013) +- Ein Lauf mit Freitextnamen lässt sich nachträglich mit einem Konto aus dem Verzeichnis + verknüpfen: beim Onboarding gibt es die Person dort noch nicht (#013) +- Start-Dialog mit Vorbelegung aus der Adresse, Laufliste mit Suche nach Titel, Ticket, Hostname + und Person sowie Filter nach Status und eigener Zuweisung (#013) +- Der Start-Dialog schlägt `upn`, `sam` und `mail` nach den Namensregeln vor, sobald die Vorlage + solche Variablen hat; ausgefüllte Felder bleiben stehen (#013) +- Abschnitte klappen zu, sobald in ihnen nichts mehr zu tun ist — wer einen wieder aufklappt, + behält ihn offen, auch über das Speichern hinweg (#013) ### Sicherheit @@ -159,3 +181,24 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). `[Passwort – nicht gespeichert]` (#012) - Ein eingesetzter Wert wird nicht doppelt maskiert: React maskiert Textknoten selbst, und ein Test am gerenderten HTML hält fest, dass ein `