Personen: eine Kategorie je Rolle, Reihenfolge wie auf der Zugangsseite

Wunsch Filipe: "ich will dass die auch immer die gleiche reihenfolge
haben, am besten sogar jeder seine eigene kategorie und die reihenfolge
genau wie in der zugangsseite."

Dabei kam ein echter Fehler ans Licht. Die Abfrage sortierte mit

    ORDER BY p.aktiv DESC, <Rolle>, p.name

Das "p.aktiv DESC" stand VOR der Rolle -- dadurch wanderte jede gesperrte
Person ans Ende der GESAMTEN Liste, quer durch alle Rollen. Im Bild vom
31.08.2026 stand der gesperrte Manager BanaStift deshalb ganz unten unter
den Creators. Die Reihenfolge DogFather-Manager-Scout-Creator, die
ueberall sonst gilt (ROLLEN_SORTIERUNG, CLAUDE.md), war ausgerechnet auf
der Personenseite aufgehoben -- und es sah nach Absicht aus.

Jetzt: Rolle zuerst, dann Gesperrtes ans Ende SEINER Rolle, dann Name.

Dazu vier Abschnitte mit Ueberschrift, Anzahl und demselben Zusatztext
wie auf der Zugangsseite ("Eigene Pipeline & Kontakte" usw.) -- wer sich
eben angemeldet hat, findet hier dieselbe Sprache wieder. Eine Rolle ohne
Personen wird weggelassen: Eine leere Ueberschrift ist kein
Ordnungsmerkmal, sondern eine Luecke.

Die Gruppen-Gestaltung kommt aus start.css und wird nur wiederverwendet
-- dieselbe Sprache wie auf der Startseite, kein zweiter Entwurf.

Nebenbei ein Eigentor: Der Kommentar zur Sortierung stand zuerst INNERHALB
der SQL-Zeichenkette und enthielt Rueckwaerts-Anfuehrungszeichen. Die
beenden ein Template-Literal -- der Server startete nicht mehr. Steht
jetzt darueber, mit einem Hinweis darauf.

30 Pruefungen. Neu darunter: dass die vier Abschnitte in genau dieser
Reihenfolge stehen, dass der gesperrte Manager bei den Managern steht und
nicht bei den Creators, und dass zugeklappt nur der DogFather-Abschnitt
da ist.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-08-31 23:05:04 +02:00
co-authored by Claude Opus 5
parent 099d9a7693
commit 2dbf9fb57a
21 changed files with 203 additions and 107 deletions
+32
View File
@@ -72,6 +72,14 @@ async function seiteFuer(kontext) {
const lesen = (seite) => seite.evaluate(() => ({
namen: [...document.querySelectorAll(".person__name")].map((n) => n.textContent.replace(" (du)", "")),
/* Die Abschnitte in der Reihenfolge, in der sie tatsächlich stehen --
nicht in der, in der sie gemeint waren. */
abschnitte: [...document.querySelectorAll(".gruppe")].map((g) => ({
name: g.querySelector(".gruppe__name")?.textContent,
zahl: g.querySelector(".gruppe__zahl")?.textContent,
unter: g.querySelector(".gruppe__unter")?.textContent,
personen: [...g.querySelectorAll(".person__name")].map((n) => n.textContent.replace(" (du)", "")),
})),
knopfDa: !document.getElementById("rest-schalter")?.hidden,
knopfText: document.getElementById("rest-schalter-text")?.textContent,
auf: document.getElementById("rest-schalter")?.getAttribute("aria-expanded"),
@@ -90,6 +98,8 @@ console.log("\n1) Standardmäßig nur DogFather");
console.log(" sichtbar:", r.namen.join(", "));
console.log(" Knopf: ", r.knopfText);
ok(r.namen.length === 2, `zwei Personen sichtbar (${r.namen.length})`);
ok(r.abschnitte.length === 1 && r.abschnitte[0].name === "DogFather",
`zugeklappt steht nur der DogFather-Abschnitt da (${r.abschnitte.map((a) => a.name).join(", ") || "keiner"})`);
ok(r.namen.includes("Dogfather") && r.namen.includes("VanVan"),
`Dogfather und VanVan (${r.namen.join(", ")})`);
ok(!r.namen.includes("Tili"), "kein Creator");
@@ -113,6 +123,28 @@ console.log("\n2) Auf Knopfdruck kommen alle dazu");
ok(/Nur DogFather zeigen/.test(r.knopfText || ""), `Knopf bietet das Zuklappen an (${r.knopfText})`);
ok(r.auf === "true", `aria-expanded=true (${r.auf})`);
ok(r.ueber <= 0, `nichts steht über (${r.ueber}px)`);
console.log(" Abschnitte:", r.abschnitte.map((a) => `${a.name}(${a.zahl})`).join(" → "));
ok(r.abschnitte.length === 4, `vier Abschnitte (${r.abschnitte.length})`);
ok(r.abschnitte.map((a) => a.name).join(",") === "DogFather,Manager,Scout,Creator",
`Reihenfolge wie auf der Zugangsseite (${r.abschnitte.map((a) => a.name).join(", ")})`);
ok(r.abschnitte.map((a) => a.zahl).join(",") === "2,1,2,2",
`Anzahl je Rolle (${r.abschnitte.map((a) => a.zahl).join(", ")})`);
/* Der eigentliche Fehler von vorher: Der GESPERRTE Manager stand ganz
unten unter den Creators, weil "aktiv" vor der Rolle sortierte. */
const manager = r.abschnitte.find((a) => a.name === "Manager");
ok(manager?.personen.includes("BanaStift"),
`der gesperrte Manager steht bei den Managern (${manager?.personen.join(", ")})`);
const creator = r.abschnitte.find((a) => a.name === "Creator");
ok(!creator?.personen.includes("BanaStift"), "und nicht mehr bei den Creators");
ok(creator?.personen.join(",") === "SpongBobSchwammKopf,Tili",
`innerhalb der Rolle nach Namen (${creator?.personen.join(", ")})`);
/* Dieselben Zusatztexte wie auf der Zugangsseite -- wer sich eben
angemeldet hat, findet hier dieselbe Sprache wieder. */
ok(r.abschnitte[2]?.unter === "Eigene Pipeline & Kontakte",
`Zusatztext wörtlich von der Zugangsseite ("${r.abschnitte[2]?.unter}")`);
}
console.log("\n3) Der Zustand überlebt das Neuladen");
+14 -1
View File
@@ -73,6 +73,19 @@ function nurDogFatherBeiLeitung(req, res, next) {
/* ---------- Übersicht --------------------------------------------------- */
/* Sortierung: Die ROLLE zuerst, dann erst der Zustand.
Vorher stand "p.aktiv DESC" ganz vorn -- dadurch wanderte jede
gesperrte Person ans Ende der GESAMTEN Liste, quer durch alle Rollen.
Ein gesperrter Manager stand also unter den Creators, und die
Reihenfolge DogFather-Manager-Scout-Creator, die ueberall sonst gilt,
war ausgerechnet auf der Personenseite aufgehoben.
Jetzt: Rolle, dann Gesperrtes ans Ende SEINER Rolle, dann Name.
(Der Kommentar steht bewusst hier und nicht in der Abfrage: Er enthaelt
Rueckwaerts-Anfuehrungszeichen, und die beenden mitten in einer
Zeichenkette genau diese -- der Server startete danach nicht mehr.) */
personenRouter.get("/workspace/api/verwaltung/personen", (req, res) => {
try {
res.json({
@@ -87,7 +100,7 @@ personenRouter.get("/workspace/api/verwaltung/personen", (req, res) => {
(SELECT COUNT(*) FROM betreuung y WHERE y.betreuer_id = p.id) AS betreut_anzahl
FROM personen p
LEFT JOIN betreuung b ON b.creator_id = p.id
ORDER BY p.aktiv DESC, ${ROLLEN_SORTIERUNG.replace("rolle", "p.rolle")}, p.name`).all(),
ORDER BY ${ROLLEN_SORTIERUNG.replace("rolle", "p.rolle")}, p.aktiv DESC, p.name`).all(),
/* Wer ueberhaupt als zustaendig eingetragen werden kann. */
betreuer: db().prepare(
"SELECT id, name FROM personen WHERE rolle = 'scout' AND aktiv = 1 ORDER BY name").all(),