- Termin aus Mail: Mailtext oder .eml per Drag & Drop/Strg+V auf Terminplan oder Aufgaben, KI schlägt Aufgaben vor, Prüfung im Aufgaben-Panel; neues Notizfeld je Aufgabe (plan_todos.notiz) - Terminplan: Meilensteine ohne Aufgabenbezug je in eigener Zeile, "+ Neu"-Menü klappt neben schmaler Seitenleiste nach rechts, Leistungsphasen - Rollen & Rechte, Abwesenheiten-Seite, Benachrichtigungen, Rundgang - Glas-Darstellung, Logo als Favicon - Pi-Betrieb: PDF-Arbeit im Kindprozess, Wächter, Einrichtungs- und Prüfskript inkl. WLAN-Wächter Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
114 lines
5.9 KiB
JavaScript
114 lines
5.9 KiB
JavaScript
// -----------------------------
|
|
// Projektübersicht — Tabs (Navigation)
|
|
// -----------------------------
|
|
// Modul für die Tab-Navigation der Hauptseite (nur von App.html geladen, nach
|
|
// js/wand/wand.js, vor js/pdf.js). showTab() wechselt zwischen Board,
|
|
// Wochenbericht, Auslastung, Projekte, Projektbeteiligte, Planung, Plan
|
|
// Checker, Meine Aufgaben, Wandtafel, Einstellungen, Admin und dem
|
|
// Projektbereich eines einzelnen Projekts ('plan', siehe TAB_PANELS).
|
|
// Einstellungen und Admin sind keine eigenen Tabs mehr, sondern aufklappbare
|
|
// Bereiche direkt in der Seitenleiste (siehe toggleSidebarAccordion() in
|
|
// js/ui.js). Gerendert werden beim Tab-Wechsel renderBoard()/
|
|
// renderWochenbericht()/renderLoad()/renderProjects()/renderPeople()/
|
|
// renderDashboard()/renderWandboard() aus js/board/board.js,
|
|
// js/wochenbericht/wochenbericht.js, js/load/load.js, js/projects/projects.js,
|
|
// js/people/people.js, js/dashboard/dashboard.js, js/wand/wand.js. Der
|
|
// frühere clientseitige Passwortschutz für die Tabs 'projects'/'people' wurde
|
|
// entfernt — der Zugriffsschutz läuft jetzt serverseitig über die Session
|
|
// (siehe js/auth.js, server.js).
|
|
//
|
|
// TAB_PANELS: alle Bereiche der Hauptseite. 'plan' ist der Projektbereich
|
|
// EINES Projekts (#plan) — früher die eigenständige Seite project-plan.html,
|
|
// die in einem eigenen Dokument geöffnet wurde. Seit dem Umbau ist er ein
|
|
// Bereich wie jeder andere: Menüband und Seitenleiste bleiben stehen, der
|
|
// Wechsel dorthin läuft über denselben showTab()-Weg wie der Wechsel vom
|
|
// Dashboard ins Projektboard.
|
|
const TAB_PANELS = ['board','wochenbericht','load','abwesenheit','people','planung','planchecker','dashboard','wand','settings','admin','plan'];
|
|
|
|
function showTab(t){
|
|
// Weichen nach Rollen & Rechte (UI-Gate, die Routen dahinter prüft der
|
|
// Server mit requireRecht()): „Admin“ nur mit einem Admin-Recht, die
|
|
// Wandtafel nur mit „Wandtafel anzeigen“, und eine Rolle ohne „Anwendung
|
|
// nutzen“ (früher das Kiosk-Konto) landet immer auf der Wandtafel.
|
|
if(currentUser && !hatRecht('app') && hatRecht('wand')) t = 'wand';
|
|
if(t === 'admin' && !hatAdminRecht()) t = DEFAULT_TAB;
|
|
if(t === 'abwesenheit' && currentUser && !darfIrgendeineAbwesenheit()) t = DEFAULT_TAB;
|
|
if(t === 'wand' && currentUser && !hatRecht('wand')) t = DEFAULT_TAB;
|
|
if(t !== currentTab) previousTab = currentTab;
|
|
currentTab = t;
|
|
saveUiState();
|
|
updateRouteUrl(t);
|
|
|
|
TAB_PANELS.forEach(x=>{
|
|
const el = document.getElementById(x);
|
|
if(el) el.style.display=(x===t?'block':'none');
|
|
});
|
|
// Der Projektbereich steht als einziger Bereich AUSSERHALB von .container
|
|
// (er bringt eigene Kopfzeile und Innenabstände mit). Der leere Container
|
|
// hinterließe sonst seinen Innenabstand als blinden Streifen über der
|
|
// Kopfzeile des Projektbereichs.
|
|
const containerEl = document.querySelector('.app-main > .container');
|
|
if(containerEl) containerEl.style.display = (t === 'plan') ? 'none' : '';
|
|
// Wandtafel: Seitenleiste und Kopfzeile ausblenden (body.wandtafel-aktiv,
|
|
// styles.css) — das Kiosk-Konto hat echte Schreibrechte, eine zufällige
|
|
// Berührung der Navigation soll nicht in einen bearbeitbaren Bereich
|
|
// führen. startWandboard()/stopWandboard() (js/wand/wand.js) starten bzw.
|
|
// beenden dabei die Hintergrund-Aktualisierung und die Kachel-Rotation.
|
|
document.body.classList.toggle('wandtafel-aktiv', t === 'wand');
|
|
if(t === 'wand') startWandboard(); else stopWandboard();
|
|
document.querySelectorAll('.tab').forEach(el=>el.classList.toggle('active',el.dataset.tab===t));
|
|
if(t==='board' && currentWeek()) renderBoard();
|
|
if(t==='wochenbericht') renderWochenbericht();
|
|
if(t==='load') renderLoad();
|
|
if(t==='abwesenheit'){ abwBeimOeffnen(); renderAbwesenheiten(); }
|
|
if(t==='people') renderPeople();
|
|
if(t==='planung') renderPlanung();
|
|
if(t==='planchecker') renderPlanChecker();
|
|
if(t==='dashboard') renderDashboard();
|
|
if(t==='wand') renderWandboard();
|
|
if(t==='settings') renderSettings();
|
|
if(t==='admin') renderAdminArea();
|
|
syncAdminNavState(t);
|
|
// Der Projektbereich wird erst NACH dem Einblenden gerendert: das GANTT
|
|
// rechnet mit der Containerbreite, die in einem ausgeblendeten Bereich 0
|
|
// wäre. Das Ziel (Sitzung + Projekt) steht vorher über setPlanTarget().
|
|
if(t==='plan') openPlanView();
|
|
syncPlanNavItem();
|
|
}
|
|
|
|
// syncAdminNavState: „Admin" ist in der Seitenleiste kein .tab-Knopf,
|
|
// sondern der Kopf einer aufklappbaren Gruppe — die allgemeine
|
|
// .tab-Hervorhebung oben greift dort also nicht. Diese Funktion markiert ihn
|
|
// stattdessen, solange der Bereich offen ist, und klappt die Gruppe dabei
|
|
// auf, damit der gewählte Abschnitt sichtbar wird.
|
|
// Parameter: t (aktiver Bereich). Keine Rückgabe.
|
|
function syncAdminNavState(t){
|
|
const toggle = document.getElementById('adminAccordionToggle');
|
|
const subnav = document.getElementById('adminSubnav');
|
|
if(!toggle || !subnav) return;
|
|
const aktiv = (t === 'admin');
|
|
toggle.classList.toggle('active', aktiv);
|
|
if(aktiv && !subnav.classList.contains('open')){
|
|
subnav.classList.add('open');
|
|
toggle.classList.add('expanded');
|
|
toggle.setAttribute('aria-expanded', 'true');
|
|
}
|
|
}
|
|
|
|
// syncPlanNavItem: hält den Eintrag des Projektbereichs in der Seitenleiste
|
|
// aktuell. Er ist der einzige Navigationspunkt, der nicht immer da ist — er
|
|
// erscheint erst, wenn ein Projekt geöffnet wurde, und trägt dann dessen
|
|
// Bezeichnung. Damit zeigt die Seitenleiste auch im Projektbereich, wo man
|
|
// gerade ist, statt (wie es ohne ihn wäre) gar keinen Punkt hervorzuheben.
|
|
// Keine Parameter, keine Rückgabe.
|
|
function syncPlanNavItem(){
|
|
const item = document.getElementById('planNavItem');
|
|
if(!item) return;
|
|
const app = window.PlanApp;
|
|
const name = app && app.projName ? app.projName : '';
|
|
item.style.display = name ? '' : 'none';
|
|
const label = document.getElementById('planNavItemLabel');
|
|
if(label) label.textContent = name || 'Projektbereich';
|
|
item.title = name ? ('Projektbereich: ' + name) : 'Projektbereich';
|
|
}
|