/workspace/report.html. Fuehrt bewusst KEINE eigenen Eintraege, sondern fasst zusammen, was in Aufgaben, Bereichen, Terminen und Dateien schon steht: "Fortschritt wird nicht gefuehlt, sondern nachvollziehbar gemacht". Die vier Abschnitte sind woertlich die Fragen aus dem Deck, Seite 16: Was wurde erledigt? Was blockiert? Was hat funktioniert? Was kommt als Naechstes? Zwei Punkte daraus sind ernst genommen: 1. "Vorher / nachher" (Historie). Jede Zahl wird mit demselben, unmittelbar davorliegenden Zeitraum verglichen. Eine Zahl allein sagt wenig -- 3 erledigte Aufgaben sind gut oder schlecht, je nachdem ob es vorher 1 oder 9 waren. Bei Zahlen, wo mehr SCHLECHTER ist (offene Probleme), ist die Trendfarbe umgedreht. 2. "Jeder Review endet mit einer Entscheidung, nicht nur mit einer Zusammenfassung." Der Report legt deshalb direkt eine Aufgabe an -- ohne Seitenwechsel, mit hoher Prioritaet und optionaler Frist. Geprueft: Eintrag im Report -> Aufgabe erscheint im Brett. "Was blockiert?" zeigt zusaetzlich die drei am laengsten offenen Aufgaben mit Namen, nicht nur eine Zahl. Sichtbarkeit: - Scout: 404, sowohl Schnittstelle als auch Seite (leitet weg) - Creator: sieht nur sich. Geprueft -- Luna fordert ?creator=3 (Mika) an und bekommt einen Report ueber SICH, der Parameter wird fuer Nicht-Management ignoriert - Der Review-Termin aus dem Profil ist Steuerungswissen und wird einem Creator auch hier nicht mitgeschickt, genau wie im Profil selbst Damit ist Phase 2 aus dem Konzept vollstaendig.
129 lines
5.0 KiB
JavaScript
129 lines
5.0 KiB
JavaScript
/* ===================================================================
|
|
Startseite nach dem Anmelden.
|
|
Die Seite ist bereits serverseitig geschützt (workspace.js). Dieses
|
|
Skript holt nur noch, WER angemeldet ist, und regelt das Abmelden.
|
|
=================================================================== */
|
|
(() => {
|
|
'use strict';
|
|
|
|
const ROLLENTEXT = {
|
|
admin: 'Management · Gesamtübersicht und Freigaben',
|
|
creator: 'Creator · dein eigener Bereich',
|
|
scout: 'Scout · deine Pipeline und Kontakte',
|
|
};
|
|
|
|
/* Bereiche aus dem Konzept, mit der Phase aus dem Umsetzungsplan.
|
|
`rollen` steuert, wem ein Bereich überhaupt angezeigt wird - schon
|
|
jetzt, damit die Trennung von Anfang an sichtbar ist. */
|
|
const BEREICHE = [
|
|
{ name: 'Dashboard', phase: 1, rollen: ['admin', 'creator', 'scout'] },
|
|
{ name: 'Personen & Zugänge', phase: 1, rollen: ['admin'], ziel: 'personen.html' },
|
|
{ name: 'Creator-Profile', phase: 1, rollen: ['admin'], ziel: 'profil.html' },
|
|
{ name: 'Mein Profil', phase: 1, rollen: ['creator'], ziel: 'profil.html' },
|
|
{ name: 'Aufgaben', phase: 1, rollen: ['admin', 'creator', 'scout'], ziel: 'aufgaben.html' },
|
|
{ name: 'Kalender', phase: 1, rollen: ['admin', 'creator', 'scout'], ziel: 'kalender.html' },
|
|
{ name: 'Dateien', phase: 1, rollen: ['admin', 'creator', 'scout'], ziel: 'dateien.html' },
|
|
{ name: 'LIVE-Analyse', phase: 2, rollen: ['admin', 'creator'], ziel: 'bereich.html?b=live' },
|
|
{ name: 'Content-Planung', phase: 2, rollen: ['admin', 'creator'], ziel: 'bereich.html?b=content' },
|
|
{ name: 'Technik', phase: 2, rollen: ['admin', 'creator'], ziel: 'bereich.html?b=technik' },
|
|
{ name: 'Community', phase: 2, rollen: ['admin', 'creator'], ziel: 'bereich.html?b=community' },
|
|
{ name: 'Schutz & Regeln', phase: 2, rollen: ['admin', 'creator'], ziel: 'bereich.html?b=schutz' },
|
|
{ name: 'Reports & Review', phase: 2, rollen: ['admin', 'creator'], ziel: 'report.html' },
|
|
{ name: 'Calls', phase: 3, rollen: ['admin', 'creator', 'scout'] },
|
|
{ name: 'Scout-Pipeline', phase: 3, rollen: ['admin', 'scout'] },
|
|
{ name: 'Automationen', phase: 4, rollen: ['admin'] },
|
|
];
|
|
|
|
const $ = (id) => document.getElementById(id);
|
|
|
|
async function laden() {
|
|
let ich;
|
|
try {
|
|
const antwort = await fetch('/workspace/api/ich', { credentials: 'same-origin' });
|
|
if (!antwort.ok) { location.assign('/workspace/'); return; }
|
|
ich = await antwort.json();
|
|
} catch {
|
|
location.assign('/workspace/');
|
|
return;
|
|
}
|
|
|
|
$('wer').textContent = `${ich.name} · ${ich.rolle}`;
|
|
$('gruss').textContent = `Willkommen, ${ich.name}`;
|
|
$('rollentext').textContent = ROLLENTEXT[ich.rolle] || ich.rolle;
|
|
|
|
const liste = $('bereiche');
|
|
for (const b of BEREICHE.filter((b) => b.rollen.includes(ich.rolle))) {
|
|
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';
|
|
name.textContent = b.name;
|
|
|
|
const stand = document.createElement('span');
|
|
stand.className = 'bereich__stand';
|
|
stand.textContent = b.ziel ? 'öffnen' : (b.phase === 1 ? 'als Nächstes' : `Phase ${b.phase}`);
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
laden();
|
|
})();
|