Workspace: Aufgabenbrett und Dashboard-Zahlen

Erster echter Arbeitsbereich aus dem Konzept. Kanban mit offen / in
Arbeit / Review / erledigt, dazu Prioritaet, Frist, Verantwortlicher und
Zuordnung zu einem Creator-Bereich.

Kern ist die Datentrennung, und die sitzt AUSSCHLIESSLICH im Server --
in jeder einzelnen Abfrage, an einer Stelle definiert (sichtbar()):
  admin   sieht alles
  creator sieht seinen Bereich und was ihm zugewiesen ist
  scout   sieht nur, was ihm zugewiesen ist

Geprueft mit vier Testkonten:
- Chef sieht 4, Luna 2, Mika 1, Sam 1 Aufgaben
- Luna auf Mikas Aufgabe: 404 (nicht 403 -- sonst liesse sich durch
  Ausprobieren herausfinden, welche Nummern es gibt)
- Luna legt Aufgabe mit creator_id=Mika an: wird still auf ihren eigenen
  Bereich umgebogen, Mika sieht sie nicht
- Anfrage mit fremdem Origin: 403
- ohne Anmeldung: 401, ungueltiger Status/leerer Titel: 400
- Scout bekommt in der Personenliste nur sich selbst
- Dashboard-Zahlen je Rolle korrekt eingegrenzt

Weitere Punkte:
- Texte werden im Browser nur ueber textContent gesetzt, nie innerHTML --
  ein Aufgabentitel darf keine Auszeichnung einschleusen
- ueberfaellig = Frist vorbei UND nicht erledigt; die Kachel faerbt sich
  nur, wenn wirklich etwas ansteht
- erledigt_am wird gesetzt bzw. wieder geleert, wenn eine Aufgabe
  zurueckgeholt wird
- Erledigtes verschwindet nicht, wie im Konzept gefordert
This commit is contained in:
2026-08-27 23:00:17 +02:00
parent 6d9bad880c
commit 2eecb40537
9 changed files with 833 additions and 10 deletions
+56 -3
View File
@@ -19,7 +19,7 @@
{ name: 'Dashboard', phase: 1, rollen: ['admin', 'creator', 'scout'] },
{ name: 'Creator-Profile', phase: 1, rollen: ['admin'] },
{ name: 'Mein Profil', phase: 1, rollen: ['creator'] },
{ name: 'Aufgaben', phase: 1, rollen: ['admin', 'creator'] },
{ name: 'Aufgaben', phase: 1, rollen: ['admin', 'creator', 'scout'], ziel: 'aufgaben.html' },
{ name: 'Kalender', phase: 1, rollen: ['admin', 'creator', 'scout'] },
{ name: 'Dateien', phase: 1, rollen: ['admin', 'creator'] },
{ name: 'LIVE-Analyse', phase: 2, rollen: ['admin', 'creator'] },
@@ -55,6 +55,7 @@
const li = document.createElement('li');
li.className = 'bereich';
li.dataset.phase = String(b.phase);
if (b.ziel) li.dataset.fertig = 'ja';
const name = document.createElement('span');
name.className = 'bereich__name';
@@ -62,9 +63,61 @@
const stand = document.createElement('span');
stand.className = 'bereich__stand';
stand.textContent = b.phase === 1 ? 'als Nächstes' : `Phase ${b.phase}`;
stand.textContent = b.ziel ? 'öffnen' : (b.phase === 1 ? 'als Nächstes' : `Phase ${b.phase}`);
li.append(name, stand);
if (b.ziel) {
/* Fertige Bereiche sind echte Verweise -- Tastatur und
Rechtsklick funktionieren damit wie gewohnt. */
const a = document.createElement('a');
a.className = 'bereich__link';
a.href = b.ziel;
a.append(name, stand);
li.append(a);
} else {
li.append(name, stand);
}
liste.append(li);
}
await zahlenLaden();
}
/* Die Zahlen kommen aus derselben Quelle wie das Brett und sind bereits
serverseitig auf die eigene Rolle eingegrenzt. */
const ZAHLEN = [
{ schluessel: 'ueberfaellig', name: 'Überfällig', warn: true },
{ schluessel: 'heute', name: 'Heute fällig' },
{ schluessel: 'offen', name: 'Offen' },
{ schluessel: 'arbeit', name: 'In Arbeit' },
{ schluessel: 'review', name: 'Review' },
{ schluessel: 'erledigt', name: 'Erledigt' },
];
async function zahlenLaden() {
let daten;
try {
const antwort = await fetch('/workspace/api/uebersicht', { credentials: 'same-origin' });
if (!antwort.ok) return;
daten = await antwort.json();
} catch { return; }
const liste = $('zahlen');
liste.textContent = '';
for (const z of ZAHLEN) {
const wert = daten[z.schluessel] ?? 0;
const li = document.createElement('li');
li.className = 'zahl';
if (z.warn && wert > 0) li.dataset.warn = 'ja';
const n = document.createElement('span');
n.className = 'zahl__wert';
n.textContent = String(wert);
const t = document.createElement('span');
t.className = 'zahl__name';
t.textContent = z.name;
li.append(n, t);
liste.append(li);
}
}