216 lines
8.6 KiB
JavaScript
216 lines
8.6 KiB
JavaScript
// -----------------------------
|
||
// Projektübersicht — Show Mode
|
||
// -----------------------------
|
||
// Präsentationsmodus für die Hauptseite (nur von Test.html geladen, nach
|
||
// js/gantt.js, vor js/tabs-auth.js). Er durchläuft automatisch die in
|
||
// SHOW_MODE_SEQUENCE hinterlegten Abteilungs-/Ansichts-Kombinationen (Board
|
||
// und Auslastung) und zeigt sie in einem Vollbild-Overlay. Genutzt werden
|
||
// showTab() aus js/tabs-auth.js, switchDepartment() aus js/store.js,
|
||
// setHeaderCollapsed() aus js/ui.js sowie renderBoard()/renderLoad() aus
|
||
// js/board/board.js/js/load/load.js. Der gesamte Lauf-Zustand liegt in den
|
||
// Modulvariablen am Dateikopf.
|
||
|
||
// showModeActive: true, solange der Show Mode läuft
|
||
let showModeActive = false;
|
||
// showModeTimer: Timer-Handle für den Wechsel zur nächsten Folie
|
||
let showModeTimer = null;
|
||
// showModeResumeTimer: Timer-Handle für die automatische Fortsetzung nach einer Pause
|
||
let showModeResumeTimer = null;
|
||
// showModePaused: true, wenn der Durchlauf gerade pausiert ist
|
||
let showModePaused = false;
|
||
// showModePollTimer: Timer-Handle des Poll-Intervalls in waitForLoadThenRender
|
||
// (wird in stopShowMode mit aufgeräumt, sonst rendert es nach dem Beenden weiter)
|
||
let showModePollTimer = null;
|
||
// showModeOriginal: Abteilung und Tab vor dem Start, wird beim Beenden wiederhergestellt
|
||
let showModeOriginal = { department: DEFAULT_DEPARTMENT, tab: DEFAULT_TAB };
|
||
const SHOW_MODE_SLIDE_DURATION = 10000; // 10 Sekunden pro Slide
|
||
const SHOW_MODE_PAUSE_DURATION = 60000; // 1 Minute Pause
|
||
// SHOW_MODE_SEQUENCE: Reihenfolge der Slides (Abteilung + Ansicht), die
|
||
// zyklisch durchlaufen wird
|
||
const SHOW_MODE_SEQUENCE = [
|
||
{ dept: 'ELT', view: 'board' },
|
||
{ dept: 'ELT', view: 'load' },
|
||
{ dept: 'HLS', view: 'board' },
|
||
{ dept: 'HLS', view: 'load' },
|
||
{ dept: 'ARCH', view: 'board' },
|
||
{ dept: 'ARCH', view: 'load' }
|
||
];
|
||
// showModeIndex: Position innerhalb der SHOW_MODE_SEQUENCE
|
||
let showModeIndex = 0;
|
||
|
||
// startShowMode: startet den Präsentationsmodus (falls nicht schon aktiv):
|
||
// merkt sich Abteilung/Tab, zeigt das Overlay, kollabiert das Menü und beginnt
|
||
// den Slide-Durchlauf. Kein Rückgabewert.
|
||
function startShowMode(){
|
||
if(showModeActive) return;
|
||
showModeActive = true;
|
||
showModePaused = false;
|
||
showModeOriginal = { department: currentDepartment, tab: currentTab };
|
||
showModeIndex = 0;
|
||
|
||
const overlay = document.getElementById('showModeOverlay');
|
||
if(overlay) overlay.style.display = 'flex';
|
||
|
||
// Menü schließen, falls offen
|
||
setHeaderCollapsed(true, false);
|
||
|
||
showModeNextSlide();
|
||
}
|
||
|
||
// stopShowMode: beendet den Präsentationsmodus: stoppt alle Timer, verbirgt
|
||
// das Overlay und stellt Abteilung und Tab des ursprünglichen Zustands wieder
|
||
// her (renderAll danach). Kein Rückgabewert.
|
||
function stopShowMode(){
|
||
showModeActive = false;
|
||
showModePaused = false;
|
||
clearTimeout(showModeTimer);
|
||
clearTimeout(showModeResumeTimer);
|
||
if(showModePollTimer){ clearInterval(showModePollTimer); showModePollTimer = null; }
|
||
|
||
const overlay = document.getElementById('showModeOverlay');
|
||
if(overlay) overlay.style.display = 'none';
|
||
|
||
// Ursprünglichen Zustand wiederherstellen. Geschützte Tabs ('projects'/
|
||
// 'people') werden nur ohne Passwort angezeigt, wenn bereits authentifiziert –
|
||
// sonst öffnet showTab (ohne skipAuth) das Passwort-Modal.
|
||
currentTab = showModeOriginal.tab;
|
||
if(currentDepartment !== showModeOriginal.department){
|
||
switchDepartment(showModeOriginal.department);
|
||
} else {
|
||
showTab(currentTab, isAuthenticated);
|
||
renderAll();
|
||
}
|
||
}
|
||
|
||
// pauseShowMode: pausiert den Durchlauf (Anzeige "Pausiert") und startet die
|
||
// automatische Fortsetzung nach SHOW_MODE_PAUSE_DURATION; bei erneutem Aufruf
|
||
// im pausierten Zustand wird sofort fortgesetzt. Kein Rückgabewert.
|
||
function pauseShowMode(){
|
||
if(!showModeActive) return;
|
||
if(showModePaused){
|
||
// bereits pausiert -> sofort fortsetzen
|
||
resumeShowMode();
|
||
return;
|
||
}
|
||
showModePaused = true;
|
||
clearTimeout(showModeTimer);
|
||
clearTimeout(showModeResumeTimer);
|
||
const pausedEl = document.getElementById('showModePaused');
|
||
if(pausedEl) pausedEl.style.display = 'block';
|
||
showModeResumeTimer = setTimeout(() => {
|
||
if(showModeActive && showModePaused) resumeShowMode();
|
||
}, SHOW_MODE_PAUSE_DURATION);
|
||
}
|
||
|
||
// resumeShowMode: setzt einen pausierten Durchlauf fort (Timer aufräumen,
|
||
// Hinweis ausblenden) und zeigt die nächste Folie. Kein Rückgabewert.
|
||
function resumeShowMode(){
|
||
if(!showModeActive) return;
|
||
showModePaused = false;
|
||
clearTimeout(showModeResumeTimer);
|
||
const pausedEl = document.getElementById('showModePaused');
|
||
if(pausedEl) pausedEl.style.display = 'none';
|
||
showModeNextSlide();
|
||
}
|
||
|
||
// showModeNextSlide: stellt die nächste Folie der SHOW_MODE_SEQUENCE dar:
|
||
// setzt Titel und Ladehinweis, wechselt ggf. per switchDepartment die Abteilung
|
||
// (mit waitForLoadThenRender) und kopiert danach die aktuelle Ansicht ins
|
||
// Overlay. Kein Rückgabewert.
|
||
function showModeNextSlide(){
|
||
if(!showModeActive || showModePaused) return;
|
||
|
||
const slide = SHOW_MODE_SEQUENCE[showModeIndex % SHOW_MODE_SEQUENCE.length];
|
||
showModeIndex++;
|
||
|
||
const titleEl = document.getElementById('showModeTitle');
|
||
if(titleEl){
|
||
const deptLabel = DEPARTMENTS[slide.dept] ? DEPARTMENTS[slide.dept].label : slide.dept;
|
||
titleEl.textContent = `${deptLabel} – ${slide.view === 'load' ? 'Auslastung' : 'Projektboard'}`;
|
||
}
|
||
|
||
// Ladehinweis anzeigen, damit der alte Inhalt nicht kurz sichtbar flackert
|
||
const content = document.getElementById('showModeContent');
|
||
if(content){
|
||
content.innerHTML = '<div class="show-mode-loading">Lädt…</div>';
|
||
}
|
||
|
||
// Wechsle Department und View in der Hauptansicht, dann kopiere ins Overlay.
|
||
// Da switchDepartment asynchron lädt, müssen wir auf den Abschluss warten.
|
||
if(currentDepartment !== slide.dept){
|
||
// Temporär currentTab setzen, damit nach dem Laden der richtige Tab aktiv ist.
|
||
currentTab = slide.view;
|
||
switchDepartment(slide.dept);
|
||
// Warte bis Daten geladen sind, dann rendern und kopieren
|
||
waitForLoadThenRender(slide.view);
|
||
} else {
|
||
showTab(slide.view, true);
|
||
renderAll();
|
||
requestAnimationFrame(() => {
|
||
requestAnimationFrame(() => {
|
||
copyCurrentViewToShowMode();
|
||
scheduleNextShowModeSlide();
|
||
});
|
||
});
|
||
}
|
||
}
|
||
|
||
// waitForLoadThenRender: wartet nach dem asynchronen Abteilungswechsel, bis
|
||
// Wochen geladen sind (Polling alle 200 ms, Abbruch nach 30 Versuchen), und
|
||
// rendert dann die gewünschte Ansicht, kopiert sie ins Show-Mode-Overlay und
|
||
// plant die nächste Folie. Parameter: view = 'board' oder 'load'.
|
||
function waitForLoadThenRender(view){
|
||
let attempts = 0;
|
||
showModePollTimer = setInterval(() => {
|
||
attempts++;
|
||
// Poll nur fortsetzen, solange der Show Mode noch läuft (sonst würde nach
|
||
// stopShowMode der gerade wiederhergestellte Zustand überschrieben).
|
||
if(!showModeActive && showModePollTimer){ clearInterval(showModePollTimer); showModePollTimer = null; return; }
|
||
// Wenn Wochen geladen sind oder nach Seed gefallen ist
|
||
if((db.weeks.length > 0 || attempts > 30) && showModeActive){
|
||
if(showModePollTimer){ clearInterval(showModePollTimer); showModePollTimer = null; }
|
||
showTab(view, true);
|
||
renderAll();
|
||
// Kurze Verzögerung, damit das DOM aktualisiert ist, bevor kopiert wird
|
||
requestAnimationFrame(() => {
|
||
requestAnimationFrame(() => {
|
||
copyCurrentViewToShowMode();
|
||
scheduleNextShowModeSlide();
|
||
});
|
||
});
|
||
}
|
||
}, 200);
|
||
}
|
||
|
||
// scheduleNextShowModeSlide: plant den Wechsel zur nächsten Folie nach
|
||
// SHOW_MODE_SLIDE_DURATION (außer im pausierten/inaktiven Zustand).
|
||
function scheduleNextShowModeSlide(){
|
||
if(!showModeActive || showModePaused) return;
|
||
clearTimeout(showModeTimer);
|
||
showModeTimer = setTimeout(() => {
|
||
showModeNextSlide();
|
||
}, SHOW_MODE_SLIDE_DURATION);
|
||
}
|
||
|
||
// copyCurrentViewToShowMode: kopiert das gerenderte HTML des aktuellen Tabs
|
||
// (Board oder Auslastung) in das Show-Mode-Overlay; in der Auslastungs-Ansicht
|
||
// werden dabei Titel und Toolbar ausgeblendet. Kein Rückgabewert.
|
||
function copyCurrentViewToShowMode(){
|
||
const content = document.getElementById('showModeContent');
|
||
const sourceId = currentTab === 'load' ? 'load' : 'board';
|
||
const source = document.getElementById(sourceId);
|
||
if(content && source){
|
||
content.innerHTML = source.innerHTML;
|
||
// Im Show Mode sollen in der Auslastung Überschrift und Steuerelemente ausgeblendet werden
|
||
if(currentTab === 'load'){
|
||
content.querySelectorAll('.section-title, .toolbar').forEach(el => el.remove());
|
||
}
|
||
}
|
||
}
|
||
|
||
// ESC-Taste beendet den Show Mode (globaler Keydown-Listener).
|
||
document.addEventListener('keydown', function(e){
|
||
if(showModeActive && e.key === 'Escape'){
|
||
stopShowMode();
|
||
}
|
||
}); |