From 586eb51504df91beb9157716835425161eb324c8 Mon Sep 17 00:00:00 2001 From: Dogfather Date: Sun, 20 Sep 2026 19:07:06 +0200 Subject: [PATCH] Profilfotos im Chat, rechte Hand zuerst, Karten lesbar ---- SCREEN 9: DIE FOTOS ------------------------------------------- Filipe: "da soll man im chat auch die profilfotos von den leuten sehen wenn die schon eins drin haben." ZWEI Luecken, beide an Stellen, wo ein Feld weggeworfen wurde: 1. Die GESPRAECHSLISTE bekam kein Bild. `teilnehmerVon` liest es aus der Datenbank, die Detailansicht nimmt es mit -- die Zeile fuer die Liste warf es weg. Folge: im offenen Gespraech ein Gesicht, in der Liste daneben ein Buchstabe. Vom selben Menschen. 2. Eine FRISCH GESENDETE Nachricht trug kein Bild. Der Verlauf beim Laden schon. Folge: Wer gerade zusieht, bekommt einen Buchstaben; wer neu laedt, ein Gesicht -- der Unterschied haengt nur daran, wann man geschaut hat. Der Buchstabe bleibt als Unterlage LIEGEN und wird nicht ersetzt: Laedt das Bild nicht, steht dort weiterhin etwas Sinnvolles statt eines kaputten Bildsymbols. Vier Stellen, ein Verhalten. ---- SCREEN 3: REIHENFOLGE UND AUSSEHEN ---------------------------- Filipe: "ich will dass hier wie ueberall die reihenfolge immer rechte hand und dan erst die modis." Die Abfrage sortierte nach `aktiv DESC, name` -- die ROLLE wurde nicht einmal mitgelesen. Die Seite konnte gar nicht wissen, wer rechte Hand ist; sie sortierte alphabetisch, und damit stand Diene vor Funny, weil D vor F kommt. Jetzt mit ROLLEN_SORTIERUNG -- derselben Regel, die auch Personenliste, Chat und Rechtetafel benutzen. "die kiste von rechte hand soll auch noch vieeeeeel krasser und spezieller aussehen ... der hintergrund von den kacheln soll auch viel krasser und geiler sein und so dass man texte und so besser erkennt. weil gerade ist es schwer lesbar." ZUERST DAS LESEN: Der Grund fuer die schlechte Lesbarkeit war der durchscheinende Untergrund -- die Karten lagen auf dem Buehnenbild, und ein Foto wird stellenweise hell. Sie bekommen jetzt eine DECKENDE Unterlage und erst darueber die Verlaeufe. Die Verlaeufe sieht man weiterhin, nur nicht mehr das Bild dahinter. DANN DAS BESONDERE: Die rechte Hand bekommt einen goldenen Ton, eine deutlich hellere Kante und eine schmale Leiste an der linken Seite -- man sieht den Rang aus zwei Metern, ohne ein Wort zu lesen. KEIN zweiter Bauplan: dieselbe Karte, dieselben Felder, nur ein Merkmal am Element. Zwei Karten zu bauen hiesse, jede kuenftige Aenderung zweimal zu machen. ---- EINE PRUEFUNG, DIE EINE POSITION FESTNAGELTE ------------------ `ok(leute[0]?.id === idMarina, "die Aktiven stehen oben")` wurde rot, sobald die rechte Hand nach vorn sortierte. Richtig wurde sie dadurch nicht: Die Aussage "die Aktiven stehen oben" hat mit Marinas Platz nichts zu tun. Jetzt prueft sie die EIGENSCHAFT (keine Pause vor einer Aktiven) -- eine Pruefung, die eine Position festnagelt, verbietet jede Umsortierung, auch die gewollte. GEPRUEFT: pruef-team-stufen 28/0 (zwei Aussagen mehr), pruef-erwaehnung 69/0 (zwei mehr: das Bild kommt in der Liste an, und wer keines hat, bekommt auch keines vorgegaukelt), pruef-css-klassen. Co-Authored-By: Claude Opus 5 --- server/pruef-erwaehnung.mjs | 30 +++++++++++ server/pruef-team-stufen.mjs | 29 ++++++++++- server/workspace-chat.js | 34 ++++++++++++- server/workspace-teamlage.js | 24 ++++++++- workspace/anruf-probe.html | 8 +-- workspace/app.webmanifest | 8 +-- workspace/assets/css/module.css | 90 +++++++++++++++++++++++++++++++++ workspace/assets/js/chat.js | 20 ++++++++ workspace/assets/js/teamlage.js | 15 ++++++ workspace/aufgaben.html | 30 +++++------ workspace/automation.html | 30 +++++------ workspace/befinden.html | 28 +++++----- workspace/bereich.html | 38 +++++++------- workspace/bewerben.html | 34 ++++++------- workspace/bewerbungen.html | 32 ++++++------ workspace/calls.html | 32 ++++++------ workspace/chat.html | 34 ++++++------- workspace/content.html | 32 ++++++------ workspace/crew-index.html | 10 ++-- workspace/crew.webmanifest | 8 +-- workspace/dateien.html | 32 ++++++------ workspace/entwicklung.html | 28 +++++----- workspace/hilfe.html | 26 +++++----- workspace/index.html | 8 +-- workspace/kalender.html | 32 ++++++------ workspace/leistung.html | 30 +++++------ workspace/personen.html | 30 +++++------ workspace/profil.html | 34 ++++++------- workspace/rechte.html | 28 +++++----- workspace/report.html | 32 ++++++------ workspace/scouting.html | 30 +++++------ workspace/start.html | 28 +++++----- workspace/startcheck.html | 32 ++++++------ workspace/steckbrief.html | 34 ++++++------- workspace/talente.html | 30 +++++------ workspace/team.html | 28 +++++----- workspace/teamlage.html | 28 +++++----- workspace/teilen.html | 26 +++++----- workspace/treff-moderation.html | 28 +++++----- workspace/treff-regeln.html | 28 +++++----- workspace/uebersicht.html | 30 +++++------ workspace/unsere-seiten.html | 24 ++++----- workspace/werdegang.html | 28 +++++----- workspace/wissen.html | 32 ++++++------ 44 files changed, 742 insertions(+), 510 deletions(-) diff --git a/server/pruef-erwaehnung.mjs b/server/pruef-erwaehnung.mjs index e71109d0..c4464a1f 100644 --- a/server/pruef-erwaehnung.mjs +++ b/server/pruef-erwaehnung.mjs @@ -242,6 +242,36 @@ ok(Number.isInteger(raumId), `eine Gruppe mit drei Leuten steht (Raum ${raumId}) `die Raumliste bringt die Teilnehmer schon mit (${r?.teilnehmer?.length})`); ok(r?.teilnehmer?.every((t) => t.id && t.name), " mit Nummer und Namen — mehr braucht die Auswahl nicht"); + + /* ---- UND MIT DEM PROFILBILD (20.09.2026) --------------------------- + + Filipe: "da soll man im chat auch die profilfotos von den leuten + sehen wenn die schon eins drin haben." + + Es fehlte in GENAU DIESER Abbildung: `teilnehmerVon` liest das Bild + aus der Datenbank, und die Zeile in der Raumliste warf es weg. Die + Detailansicht nahm es mit. Folge: im offenen Gespraech ein Gesicht, + in der Liste daneben ein Buchstabe -- vom selben Menschen. + + Geprueft wird mit einem eingetragenen Dateinamen; ob die Datei + existiert, ist eine andere Frage und gehoert zum Steckbrief. Hier + geht es darum, dass der WEG ueberhaupt ankommt. */ + { + const d = new DatabaseSync(process.env.WORKSPACE_DB); + d.prepare("UPDATE personen SET bild = ? WHERE id = ?").run("probe.webp", idVan); + d.close(); + const l2 = json(await ruf("/workspace/api/chat/raeume", aDogi.keks)); + const r2 = (l2.raeume || []).find((x) => x.id === raumId); + const van = r2?.teilnehmer?.find((t) => t.id === idVan); + ok(typeof van?.bild === "string" && van.bild.includes("probe.webp"), + `das Profilbild kommt in der Gespraechsliste an (${van?.bild})`); + const ohne = r2?.teilnehmer?.find((t) => t.id === idFunny); + ok(ohne && !ohne.bild, + "Gegenprobe: wer keines hinterlegt hat, bekommt auch keines vorgegaukelt"); + const d2 = new DatabaseSync(process.env.WORKSPACE_DB); + d2.prepare("UPDATE personen SET bild = NULL WHERE id = ?").run(idVan); + d2.close(); + } } /* Jetzt die eigentliche Nachricht. */ diff --git a/server/pruef-team-stufen.mjs b/server/pruef-team-stufen.mjs index 84650311..3596c68f 100644 --- a/server/pruef-team-stufen.mjs +++ b/server/pruef-team-stufen.mjs @@ -143,8 +143,33 @@ ok(!!marina && !!kim, "beide sind namentlich wiederzufinden"); ok(marina?.aktiv === true && kim?.aktiv === false, `Status stimmt (Marina aktiv: ${marina?.aktiv}, Kim aktiv: ${kim?.aktiv})`); -/* AKTIVE ZUERST -- wer pausiert ist, steht unten und nicht mittendrin. */ -ok(leute[0]?.id === idMarina, "die Aktiven stehen oben"); +/* AKTIVE ZUERST -- wer pausiert ist, steht unten und nicht mittendrin. + + GEPRUEFT WIRD DIE EIGENSCHAFT, NICHT DIE POSITION (berichtigt + 20.09.2026). Hier stand `leute[0]?.id === idMarina` -- und das wurde + rot, sobald die rechte Hand nach vorn sortiert wurde. Richtig wurde + es dadurch nicht: Die Aussage "die Aktiven stehen oben" hat mit + Marinas Platz nichts zu tun. Eine Pruefung, die eine Position + festnagelt, verbietet jede Umsortierung -- auch die gewollte. */ +const letzteAktive = leute.map((m) => m.aktiv).lastIndexOf(true); +const ersteInPause = leute.map((m) => m.aktiv).indexOf(false); +ok(ersteInPause === -1 || letzteAktive < ersteInPause, + `die Aktiven stehen oben (letzte aktive Stelle ${letzteAktive}, erste Pause ${ersteInPause})`); + +/* ==== UND DIE RECHTE HAND VOR DEN MODIS (20.09.2026) ================ + + Filipe: "ich will dass hier wie ueberall die reihenfolge immer + rechte hand und dan erst die modis." + + Vorher sortierte die Abfrage nur nach Namen -- die Rolle wurde nicht + einmal mitgelesen. Damit stand die Reihenfolge im Alphabet, und das + ist keine. */ +const platzHand = leute.findIndex((m) => m.id === idHand); +const ersterModi = leute.findIndex((m) => m.id !== idHand && m.aktiv); +ok(platzHand >= 0 && (ersterModi === -1 || platzHand < ersterModi), + `die rechte Hand steht vor den Modis (Platz ${platzHand} vor ${ersterModi})`); +ok(leute.every((m) => typeof m.rolle === "string" && m.rolle), + "und jede Karte weiss, welche Rolle sie hat — sonst kann die Seite sie nicht unterscheiden"); ok(typeof marina?.seit === "string" && marina.seit.startsWith(vor40Tagen.slice(0, 10)), `"dabei seit" kommt mit (${(marina?.seit || "").slice(0, 10)})`); diff --git a/server/workspace-chat.js b/server/workspace-chat.js index f920f08b..0f7abf9b 100644 --- a/server/workspace-chat.js +++ b/server/workspace-chat.js @@ -160,6 +160,20 @@ function istDrin(raumId, person) { wurde damit zu Programmtext, und die Datei liess sich nicht mehr lesen. Ein Kommentar, der die Zeichenkette schliesst, in der er steht. */ +/** Der Weg zum Profilbild dieser Person -- oder null. + * + * ALS EIGENE FUNKTION, weil die Zeile + * `bild ? "/workspace/api/steckbrief/bild/" + bild : null` + * sonst an drei Stellen steht. Die dritte Abschrift ist die, die + * den Pfad falsch schreibt, und ein kaputter Bildpfad sieht aus wie + * "die Person hat halt kein Bild". */ +function bildWegFuer(personId) { + try { + const z = db().prepare("SELECT bild FROM personen WHERE id = ?").get(personId); + return z?.bild ? `/workspace/api/steckbrief/bild/${z.bild}` : null; + } catch { return null; } +} + function teilnehmerVon(raumId) { return db().prepare(` SELECT t.person_id AS id, p.name, p.rolle, p.bild, t.leitung, t.gelesen_bis @@ -545,7 +559,18 @@ chatRouter.get("/workspace/api/chat/raeume", (req, res) => { Stellen steht; genau daran ist es beim ersten Anlauf gescheitert. */ darf_aufloesen: darfAufloesen(r, req.person), - teilnehmer: leute.map((t) => ({ id: t.id, name: t.name, rolle: t.rolle })), + /* DAS BILD GEHOERT DAZU (20.09.2026). + + Filipe: "da soll man im chat auch die profilfotos von den + leuten sehen wenn die schon eins drin haben." + + Es fehlte genau hier: `teilnehmerVon` liest das Bild aus der + Datenbank, und diese Zeile warf es weg. Die Detailansicht + weiter unten nimmt es mit -- die LISTE nicht. Deshalb stand + im offenen Gespraech ein Gesicht und in der Liste daneben ein + Buchstabe, vom selben Menschen. */ + teilnehmer: leute.map((t) => ({ id: t.id, name: t.name, rolle: t.rolle, + bild: t.bild })), letzte: letzte ? { /* Ein Anhang ohne Begleittext hätte hier eine leere Zeile hinterlassen. "Foto"/"PDF" ist die Vorschau, die man in @@ -1061,6 +1086,13 @@ chatRouter.post("/workspace/api/chat/raeume/:id/nachrichten", gleicheHerkunft, const nachricht = { id, raum_id: raumId, von_id: req.person.id, von: req.person.name, + /* DAS BILD MUSS MIT (20.09.2026). Der Verlauf beim Laden bringt + `von_bild` mit -- diese Nachricht hier nicht, und sie ist die, + die per Ereignisstrom bei allen anderen ankommt. Folge: Wer + gerade zusieht, bekommt einen Buchstaben; wer die Seite neu + laedt, ein Gesicht. Derselbe Mensch, zwei Darstellungen, und + der Unterschied haengt nur daran, wann man geschaut hat. */ + von_bild: bildWegFuer(req.person.id), rolle: req.person.rolle, text, erstellt: n, zurueckgenommen: false, antwort: zitat ? { id: antwortAuf, von: zitat.von || "Gelöscht", diff --git a/server/workspace-teamlage.js b/server/workspace-teamlage.js index df99ce9a..b8073658 100644 --- a/server/workspace-teamlage.js +++ b/server/workspace-teamlage.js @@ -34,6 +34,7 @@ import express from "express"; import { db, sitzungLesen, istDogFather, fuehrtTeamDogi, heuteLokal, protokolliere, echteIp, + ROLLEN_SORTIERUNG, } from "./workspace.js"; import { MODI_PUNKTE } from "./workspace-modi-punkte.js"; import { checklistenTabellen } from "./workspace-checkliste.js"; @@ -171,10 +172,24 @@ teamlageRouter.get("/workspace/api/teamlage", (req, res) => { verhindern soll. Der Riegel eine Zeile hoeher (`darfEingang`) bleibt beim Angemeldeten: Das ist ein Recht, keine Anzeige. */ const zeigt = req.sicht || person; + /* ==== DIE RECHTE HAND STEHT ZUERST (20.09.2026) ============== + + Filipe: "ich will dass hier wie ueberall die reihenfolge immer + rechte hand und dan erst die modis." + + Hier stand `ORDER BY aktiv DESC, name` -- die Rolle wurde nicht + einmal MITGELESEN. Die Seite konnte also gar nicht wissen, wer + rechte Hand ist und wer Modi; sie sortierte alphabetisch, und + damit stand Diene vor Funny, weil D vor F kommt. + + Sortiert wird jetzt mit ROLLEN_SORTIERUNG -- derselben Regel, die + auch die Personenliste, der Chat und die Rechtetafel benutzen. + Eine eigene Reihenfolge hier waere die zweite Wahrheit, und die + zweite ist die, die beim naechsten Rollenwechsel abweicht. */ const modis = db().prepare( - `SELECT id, name, bild, letzter_login, aktiv, erstellt, stufe FROM personen + `SELECT id, name, rolle, bild, letzter_login, aktiv, erstellt, stufe FROM personen WHERE rolle IN ('hand','modi') AND id <> ? - ORDER BY aktiv DESC, name`).all(zeigt.id); + ORDER BY aktiv DESC, ` + ROLLEN_SORTIERUNG + `, name`).all(zeigt.id); if (!modis.length) { /* `eingang` auch hier -- die Oberflaeche darf nicht raten @@ -374,6 +389,11 @@ teamlageRouter.get("/workspace/api/teamlage", (req, res) => { return { id: m.id, name: m.name, + /* DIE ROLLE GEHT MIT (20.09.2026). Ohne sie kann die Seite + die rechte Hand nicht von einem Modi unterscheiden -- und + genau das soll sie: andere Reihenfolge, anderes Aussehen. + Sie stand bisher nicht einmal in der Abfrage. */ + rolle: m.rolle, bild: m.bild ? `/workspace/api/steckbrief/bild/${m.bild}` : null, letzter_login: m.letzter_login, /* Die drei Felder aus Kapitel 4: Status, "dabei seit", Stufe. */ diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 1a95cc5c..95e1a868 100644 --- a/workspace/anruf-probe.html +++ b/workspace/anruf-probe.html @@ -16,15 +16,15 @@ verdeckt. Gefunden hat es pruef-struktur. Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. --> - - + + - +