Der Modi bekommt seine eigene Seite -- und sein Brett zurueck

DER WICHTIGSTE FUND, und er kam nicht aus dem Nachdenken: Ein Modi sah
auf dem Aufgabenbrett GAR NICHTS -- nicht einmal seine eigenen Aufgaben.
sichtbar() endet mit `default: 0=1`, und 'modi' stand nicht darin.

Genau dieser Fehler ist am 01.09.2026 schon dem Manager passiert; der
Kommentar zwei Zeilen darueber warnt woertlich davor ("Ein leeres Brett
sieht aus wie 'nichts zu tun', nicht wie ein Fehler; deshalb ist das
vermutlich lange niemandem aufgefallen"). Der Rollen-Rundgang meldete
fuer den Modi trotzdem brav "aufgaben.html ok" -- die Seite laedt ja,
sie war nur leer. Gefunden hat es erst eine Pruefung, die eine Aufgabe
ANLEGT und sie danach wiederzufinden versucht.

Ein Modi sieht jetzt die Aufgaben des ganzen Modi-Teams (Filipes
Entscheidung "sie sind untereinander ein Team"), aendern darf er
weiterhin nur seine eigenen. Die Nummern werden bei jeder Abfrage frisch
gelesen -- eine beim Serverstart gebaute Liste waere ab dem naechsten
neuen Modi falsch, und niemand wuesste warum.

DIE STARTSEITE. Ein Modi hatte keine einzige Kachel: Jede traegt eine
feste Rollenliste, und 'modi' darf dort nicht stehen -- bereiche.js
bekommt jeder ausgeliefert, der die Seite oeffnet. Die Kacheln kommen
deshalb vom Server (MODI_BEREICHE), samt Beschriftung. Nur die Ziele zu
schicken haette nicht gereicht: Unter "Dashboard" stuende sonst "Alle
Creator auf einen Blick" -- fuer jemanden ohne Creator. Die Worte
gehoeren zum Empfaenger, nicht zum Ziel.

Neun Kacheln in drei Gruppen: Aufgaben, Chat, Kalender, Dateien /
Live-Ablauf, Community, Technik / Profil, Wissen. Nichts aus der
Agentur -- diese Seiten drehen sich um betreute Creator oder um Rechte.

`null` heisst "nimm deine eigene Liste", eine LEERE Liste hiesse "keine
Kacheln". Verwechselte man die beiden, haetten die fuenf bekannten
Rollen ab sofort eine leere Startseite.

ZWEI DINGE HAT DAS BILDSCHIRMFOTO GEZEIGT, NICHT DER CODE:

  * Ueber der Modi-Startseite stand "Spicy Media" -- die Marke einer
    Agentur, mit der er nichts zu tun hat. Jetzt "Team Dogi", wie auf
    der oeffentlichen Seite. Ersetzt wird nur der Textknoten: In dem
    Element sitzen zwei Zierrauten, ein textContent haette sie lautlos
    geloescht.
  * Auf seinem Aufgabenbrett stand das Creator-Vorlagenbrett, 80
    Aufgaben fuer den Aufbau eines Kanals. Fuer einen Moderator ist
    davon nichts gedacht. Ausgeblendet, bis sein Katalog aus Teil 2 des
    Anforderungsdokuments da ist -- nichts ist ehrlicher als etwas
    Fremdes.

Dazu: "0 betreut" stand dauerhaft auf seiner Startseite, eine Zahl, die
nie etwas anderes sagen kann. Jetzt zaehlt sie, wie viele im Modi-Team
sind. Und der Satz unter der Begruessung war nur das Wort "Modi", neben
fuenf Rollen mit einem ganzen Satz -- das sah nicht verborgen aus,
sondern unfertig.

KATEGORIEN (Kapitel 6.1), nach Filipes Entscheidung nur bei den Modis.
Acht Stueck; hier steht, wohin die dreizehn aus Teil 2 fallen
(Branding/Team/Kommunikation -> Planung, Wachstum -> Community).

Der heikelste Fall ist nicht das Setzen, sondern das SCHICKEN durch
jemanden, der es nicht darf: Eine Absage ("Unbekannte Kategorie") waere
die Auskunft, dass es das Feld gibt. Also faellt der Wert lautlos weg
und die Aufgabe entsteht ganz normal. Wer die Kategorien benutzen darf,
bekommt bei einem Tippfehler dagegen sehr wohl eine Absage.

Das Feld erscheint nur, wenn die Aufgabe wirklich zu einem Modi gehoert
-- bei DogFather also erst, wenn er einen als Person auswaehlt. Sonst
stuende es auch an jeder Creator-Aufgabe. Verborgen heisst dabei auch
"nichts mitschicken": Ein Wert in einem unsichtbaren Feld wandert sonst
beim naechsten Speichern mit.

KEINE NEUE CSS-KLASSE fuer die Kategorie auf der Karte. Sie muesste in
sieben gleichlautenden Kopien der Modulliste gepflegt werden -- sieben
Gelegenheiten fuer einen Unterschied, fuer eine Zeile Text.

AUSSERDEM BERICHTIGT, UND ES WAR SCHON VORHER ROT: pruef-start-ansicht
erwartete drei Kachelgruppen. Seit b45de94 gibt es vier ("Rund um das
Team"). Bevor ich die Zahl angefasst habe, habe ich meine Aenderungen
beiseitegelegt und den Lauf wiederholt -- schon auf dem unveraenderten
Stand rot, also nicht von mir. Geprueft werden jetzt die NAMEN: Vier
Gruppen koennten auch drei richtige und eine doppelte sein.

GEPRUEFT: pruef-modi-verborgen (57), pruef-modi-kategorien (22, neu),
pruef-rollen (113 statt 97 -- der Modi laeuft jetzt ueber jede der 16
Seiten), pruef-start-ansicht, pruef-aufgabenbrett, pruef-sicht,
pruef-verborgen, pruef-personen-formular (24), pruef-personen-liste,
pruef-css-klassen, pruef-spicy (60).

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-10 00:52:06 +02:00
co-authored by Claude Opus 5
parent 7be488e0ca
commit 114a00eed5
30 changed files with 1196 additions and 268 deletions
+195
View File
@@ -186,6 +186,173 @@ export const ROLLEN_NAME = {
modi: "Modi",
};
/* =====================================================================
DIE KACHELN EINES MODIS (10.09.2026)
Wo die anderen fuenf Rollen ihre Kacheln aus assets/js/bereiche.js
bekommen, kommen sie fuer einen Modi von hier. Der Grund ist derselbe
wie beim Anzeigenamen und bei der Rollenauswahl: bereiche.js wird an
JEDEN ausgeliefert, der die Seite oeffnet. Stuende dort auch nur
`rollen: [... , 'modi']`, waere die Rolle mit einem Blick in den
Quelltext gefunden -- und damit alles verraten.
NICHT NUR EINE LISTE VON ZIELEN, sondern die ganze Kachel. Wer nur
die Ziele schickte und die Beschriftung aus bereiche.js nehmen liesse,
bekaeme unter "Dashboard" den Untertitel "Alle Creator auf einen
Blick" -- fuer jemanden, der keine Creator betreut. Die Worte gehoeren
zum Empfaenger, nicht zum Ziel.
ZEICHEN, TON UND SZENE SIND SCHLUESSEL AUS bereiche.js, keine neuen.
Sie sagen nichts ueber Modis aus (jede andere Kachel benutzt dieselben)
und muessen deshalb nicht verborgen werden. Neue zu erfinden waere
genau falsch herum: Sie muessten in bereiche.js stehen, und dort
faellt jede unbenutzte Zeile irgendwann jemandem auf. Die Toene sind
dieselben wie an den entsprechenden Kacheln der anderen Rollen -- ein
Ton kennzeichnet die Kachel, nicht ihren Platz.
WAS NICHT DABEI IST, und warum: Uebersicht, Calls, Content, Reports,
Scouting, Personen und Automationen. Sie drehen sich um betreute
Creator, um die Agentur oder um Rechte -- fuer einen Modi waeren sie
leer oder nicht seine Sache. Der Rollen-Rundgang (pruef-rollen) zeigt,
dass sie ihn nicht abstuerzen lassen; das ist der Grund, sie
wegzulassen, und nicht der Grund, sie mitzunehmen.
ES IST EINE ROLLENFRAGE, KEINE PERSONENFRAGE: Alle Modis bekommen
dasselbe. Sollte das je auseinandergehen, gehoert die Auswahl an die
Person und nicht hierher -- dann aber bewusst und mit einer Stelle,
an der sie gepflegt wird.
===================================================================== */
const MODI_BEREICHE = [
{ gruppe: "Täglich", gruppeUnter: "Was du sowieso jeden Tag aufmachst",
name: "Aufgaben", unter: "Offen, in Arbeit, Review", zeichen: "aufgaben",
ton: 13, gross: true, ziel: "aufgaben.html", szene: "garage" },
{ gruppe: "Täglich", gruppeUnter: "Was du sowieso jeden Tag aufmachst",
name: "Chat", unter: "Nachrichten mit dem Team", zeichen: "chat",
ton: 4, ziel: "chat.html", szene: "lounge" },
{ gruppe: "Täglich", gruppeUnter: "Was du sowieso jeden Tag aufmachst",
name: "Kalender", unter: "Live-Zeiten und Termine", zeichen: "kalender",
ton: 8, ziel: "kalender.html", szene: "skyline" },
{ gruppe: "Täglich", gruppeUnter: "Was du sowieso jeden Tag aufmachst",
name: "Dateien", unter: "Ablage und Freigaben", zeichen: "dateien",
ton: 19, ziel: "dateien.html", szene: "arena" },
{ gruppe: "Rund ums Live", gruppeUnter: "Vor, während und nach der Sendung",
name: "Live-Ablauf", unter: "Checkliste für vorher, mittendrin und danach",
zeichen: "live", ton: 3, ziel: "bereich.html?b=live", szene: "portal" },
{ gruppe: "Rund ums Live", gruppeUnter: "Vor, während und nach der Sendung",
name: "Community", unter: "Begrüßen, vermitteln, wiedererkennen",
zeichen: "community", ton: 6, ziel: "bereich.html?b=community", szene: "lounge" },
{ gruppe: "Rund ums Live", gruppeUnter: "Vor, während und nach der Sendung",
name: "Technik", unter: "Ton, Bild, Verbindung", zeichen: "technik",
ton: 14, ziel: "bereich.html?b=technik", szene: "garage" },
{ gruppe: "Für dich", gruppeUnter: "Deine Seite im Team",
name: "Mein Profil", unter: "Deine Angaben und dein Bild", zeichen: "profil",
ton: 20, ziel: "profil.html", szene: "halle" },
{ gruppe: "Für dich", gruppeUnter: "Deine Seite im Team",
name: "Wissen", unter: "Nachschlagen statt nachfragen", zeichen: "wissen",
ton: 9, ziel: "wissen.html", szene: "arena" },
];
/**
* Die Kacheln dieser Person -- oder `null`, wenn sie aus bereiche.js
* kommen sollen.
*
* `null` und nicht eine leere Liste: Die Oberflaeche unterscheidet
* "nimm deine eigene Liste" von "du bekommst keine Kacheln". Eine leere
* Liste hiesse das Zweite, und die fuenf bekannten Rollen haetten ab
* sofort eine leere Startseite.
*/
export function bereicheFuer(person) {
return person?.rolle === "modi" ? MODI_BEREICHE : null;
}
/* Der Satz unter der Begruessung. Die fuenf bekannten Rollen haben ihn
in assets/js/start.js stehen ("Creator · dein eigener Bereich"); fuer
einen Modi darf er dort nicht stehen und kommt deshalb von hier.
OHNE IHN STAND DA NUR DAS WORT "Modi" -- neben fuenf Rollen, die einen
ganzen Satz bekommen. Das sieht nicht verborgen aus, sondern
unfertig, und Filipe haette zu Recht gefragt, warum seine Seite
halbfertig wirkt. Gefunden hat das die Browserpruefung, nicht das
Nachdenken.
AUF AUGENHOEHE FORMULIERT: "dein Bereich im Team", nicht "dein
Bereich unter DogFather". Ein Modi ist Teil des Teams, kein
Untergebener -- das gilt fuer jeden Text im Haus. */
const MODI_ROLLENTEXT = "Modi · dein Bereich im Team";
/* DIE ZIERZEILE UEBER "DIE ZENTRALE".
Sie nennt den BETRIEB, unter dem gearbeitet wird -- seit dem
08.09.2026 auf Filipes Wunsch "Spicy Media" statt "Dogfather
Universe". Das steht fest in start.html, und fuer die fuenf bekannten
Rollen stimmt es auch.
FUER EINEN MODI STIMMT ES NICHT. Ein Modi gehoert nicht zur Agentur,
er moderiert die Lives -- "Team Dogi" heisst diese Runde auch auf der
oeffentlichen Seite (team-modis.html). Bis hierher stand ueber seiner
Startseite die Marke eines Betriebs, mit dem er nichts zu tun hat.
Aufgefallen ist das nicht beim Nachdenken, sondern auf dem
Bildschirmfoto der Browserpruefung.
Wie ueberall kommt der Text vom Server: Ein zweiter Markenname in
start.html waere zwar kein Verrat (er sagt nichts ueber Modis), aber
eine Zeile, die fuer fast jeden Leser tot dasteht -- und tote Zeilen
werden irgendwann falsch erklaert. */
const MODI_MARKE = "Team Dogi";
/* =====================================================================
DIE KATEGORIEN EINER MODI-AUFGABE (10.09.2026)
Kapitel 6.1 des Anforderungsdokuments nennt sechs Beispiele, der
Aufgabenkatalog in Teil 2 benutzt dreizehn. Dreizehn Knoepfe in einer
Filterleiste sind auf einem Handy unbedienbar -- deshalb diese acht,
und hier steht, wohin die uebrigen fallen:
Branding, Team, Kommunikation -> Planung & Organisation
Wachstum -> Community & Events
Das ist eine Entscheidung und keine Uebersetzung. Wer sie spaeter
anders will, aendert sie hier, an einer Stelle.
SIE STEHEN AUF DEM SERVER, nicht in assets/js/aufgaben.js. Nicht weil
die Woerter etwas verraten wuerden -- "Clipping" sagt nichts ueber
Modis --, sondern weil eine Liste, die im Browser jedes Menschen
liegt und nur bei einem einzigen benutzt wird, die Frage aufwirft,
fuer wen sie da ist. Genau diese Frage soll niemand stellen. */
export const MODI_KATEGORIEN = [
{ wert: "chat", name: "Chat-Moderation" },
{ wert: "clipping", name: "Clipping & Schnitt" },
{ wert: "social", name: "Social Media" },
{ wert: "community", name: "Community & Events" },
{ wert: "technik", name: "Technik" },
{ wert: "planung", name: "Planung & Organisation" },
{ wert: "analyse", name: "Analyse & Zahlen" },
{ wert: "sonstiges", name: "Sonstiges" },
];
/**
* Darf diese Person mit Kategorien arbeiten?
*
* Ein Modi (es sind seine Aufgaben) und die DogFather-Rolle (sie sieht
* seine Aufgaben und legt ihm welche an). Sonst niemand -- und "sonst
* niemand" heisst hier: Die Liste kommt gar nicht erst mit, statt
* mitzukommen und ausgeblendet zu werden.
*/
export function kategorienFuer(person) {
if (!person) return [];
return person.rolle === "modi" || person.rolle === "admin" ? MODI_KATEGORIEN : [];
}
export function rollentextFuer(person) {
return person?.rolle === "modi" ? MODI_ROLLENTEXT : null;
}
export function markeFuer(person) {
return person?.rolle === "modi" ? MODI_MARKE : null;
}
/* scrypt-Parameter. N=2^15 braucht auf diesem Server rund 150 ms — spürbar
genug, um Rateversuche auszubremsen, und unauffällig für einen echten
Anmeldevorgang. Die Werte werden je Datensatz mitgespeichert, damit sie
@@ -614,6 +781,20 @@ function umstellungen(d) {
nur, WEN man pruefen soll; ob der Code stimmt, sagt weiterhin
allein scrypt. Ein Treffer hier allein laesst niemanden herein. */
["personen", "code_kennung", "TEXT"],
/* DIE KATEGORIE EINER AUFGABE (10.09.2026).
Kapitel 6.1 des Anforderungsdokuments verlangt sie an jeder
Aufgabe. Filipes Entscheidung dazu: nur bei den Modis -- fuer
Creator, Scouts und Manager bleibt das Formular, wie es war.
KEIN CHECK IN DER SPALTE, obwohl die Werte fest sind. Ein CHECK
laesst sich in SQLite nicht aendern; die Liste um eine Kategorie
zu erweitern hiesse jedes Mal, die ganze Tabelle neu zu bauen.
Geprueft wird stattdessen beim Schreiben (siehe KATEGORIEN in
workspace-aufgaben.js) -- an EINER Stelle, durch die alle
Schreibwege laufen. */
["aufgaben", "kategorie", "TEXT"],
]) {
try {
const vorhanden = d.prepare(`PRAGMA table_info(${tabelle})`).all().map((s) => s.name);
@@ -2439,6 +2620,20 @@ workspaceRouter.get("/workspace/api/ich", (req, res) => {
rolle_name: ROLLEN_NAME[person.rolle] ?? person.rolle,
sicht,
bild,
/* DIE KACHELN, WENN SIE NICHT IM BROWSER STEHEN DUERFEN.
Fuer die fuenf bekannten Rollen steht hier `null`, und die
Oberflaeche nimmt wie bisher ihre eigene Liste -- der Ablauf
aendert sich fuer sie also nicht.
NACH DER ANGESEHENEN PERSON, nicht nach der eigenen: Sieht sich
DogFather den Arbeitsplatz eines Modis an, soll er DESSEN Kacheln
sehen. Genau daran war beim Sicht-Umschalter schon einmal zu
erkennen, dass er nicht greift ("ich seh immer noch die Seite
genau wie meine"). */
bereiche: bereicheFuer(angesehen || person),
rolle_text: rollentextFuer(angesehen || person),
marke: markeFuer(angesehen || person),
});
});