WINDOWS #36, Aufgabe 2/3: handleSubmit und fetchUsers verschluckten
abgewiesene Antworten und Verbindungsfehler ebenso wie der Loeschweg aus
Aufgabe 1. formError zeigt jetzt den Servertext oder eine Ersatzmeldung
im offenen Formulardialog; loadError verhindert die irrefuehrende
Meldung "Keine Benutzer gefunden", wenn das Laden selbst gescheitert
ist. Beide Zustaende werden beim Oeffnen eines neuen Dialogs
zurueckgesetzt, damit eine alte Meldung nicht in den naechsten Aufruf
hinueberwandert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
WINDOWS #36, Aufgabe 1/3: handleDelete verschluckte einen 403 bisher
komplett (nur res.ok geprueft, Fang-Zweig ohne Wirkung). readApiMessage
liest jetzt gezielt das Feld message aus dem Antwortrumpf; der
Loeschdialog zeigt den Servertext, eine uebersetzte Ersatzmeldung ohne
verwertbaren Rumpf oder bei Verbindungsfehler — und bleibt in allen drei
Faellen offen. Neue Texte unter admin.users.errors in de.json/en.json,
Umlaut-Waechter gruen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
- admin/ldap/page.tsx: SyncResult um emailConflicts/skippedNoLogin/
entryFailures erweitert; drei neue Berichtsabschnitte (Bernstein fuer
Kollisionen, neutral fuer fehlenden Anmeldenamen, destruktiv fuer
unerwartete Fehler) — kein englischer Techniktext, kein roher
Datenbank-Wortlaut mehr im Bericht
- GroupMembersModal.tsx: TenantUser.email optional, Suchvergleich gegen
leere Adresse abgesichert (WINDOWS #15) — die Mitgliedersuche stuerzt
nicht mehr ab, sobald ein Konto ohne Adresse existiert
- users/page.tsx: User.email optional, Formular faellt auf leere
Zeichenkette zurueck, Tabellenzelle zeigt einen Gedankenstrich;
UserFormData.email bleibt bei Handanlage Pflicht
- Neue Sprachschluessel unter admin.ldap.sync in de.json/en.json,
Umlaut- und Sprachschluessel-Gate bestaetigt gruen (kein neues
Allowlist-Wort noetig)
- Neuer Testfall in groups-page.test.tsx vorab gegen den unveraenderten
Bestand rot gelaufen; Abweichung von der Plan-Fixture dokumentiert
(Kurzfassung: ein einzelnes Konto mit passendem Benutzernamen loest die
Kollision wegen OR-Kurzschlussauswertung nie aus, ein zweites,
nicht-treffendes Konto ohne Adresse schon — Vollfassung im SUMMARY)
- 651/651 API- und 233/233 Web-Tests gruen, beide Typpruefungen sauber
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYZcd3SSmo14QTqWx2KKzU
- Reuses admin.groups.members.sourceManual/.sourceLdap -- no new i18n key
- Badge markup copied verbatim from GroupMembersModal.tsx (blue for LDAP,
neutral gray otherwise), same visual language on both surfaces
- Chips come from the response's groups (actual GroupMembership rows),
not the union of row.viaGroups -- closes the reproduced defect where
revoking a group's last grant hid an otherwise-unchanged membership
- React key is the group id, not the name
- Test file: moved the LDAP/MANUAL badge assertion out of this commit,
it belongs to Task 2 which reuses admin.groups.members
- Neue UserAccessModal.tsx: laedt einmal GET /module-grants/users/:userId
und rendert daraus zwei Abschnitte -- Gruppenmitgliedschaften (read-only
Chip-Liste, dedupliziert aus allen viaGroups-Namen; Bearbeitung bleibt
ausschliesslich unter /admin/groups, D-16) und Modul-Zugriff (Modul |
erbende Gruppen als Chips oder "–" | Direkt-Checkbox)
- Direkt-Checkbox verhaelt sich identisch zur Matrix-Zelle: optimistisches
Toggle via POST/DELETE /module-grants mit moduleId+userId, Rollback samt
sichtbarer Fehlermeldung bei Fehlschlag (T-15-25), aria-label pro Zeile
aus admin.users.grants.directCheckboxLabel
- admin/users/page.tsx: vierter Aktionsbutton "Details" je Zeile oeffnet
das Modal
- user-access-modal.test.tsx: 5 Tests (Chip-Liste + Leerzustand, Modultabelle
mit geerbtem/nicht-geerbtem Modul, Rollback bei Fehler, Hinweistext ohne
aktive Module, aria-label je Checkbox)