🎉 Improved logging system & documentation updates 🎉
This commit is contained in:
@ -357,155 +357,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Timer Management Section -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<!-- Session Timer -->
|
||||
<div class="dashboard-card p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="section-title mb-0">Session-Timer</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="mb-status-indicator mb-status-idle" id="session-timer-status"></div>
|
||||
<span class="text-sm text-slate-500 dark:text-slate-400">Gestoppt</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Timer Container -->
|
||||
<div id="session-countdown-timer" class="mb-6"></div>
|
||||
|
||||
<!-- Timer Configuration -->
|
||||
<div class="bg-gray-50 dark:bg-slate-700/30 rounded-lg p-4 mb-4">
|
||||
<h4 class="text-sm font-medium text-slate-900 dark:text-white mb-3">Timer-Einstellungen</h4>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-xs text-slate-500 dark:text-slate-400 mb-1">Dauer (Minuten)</label>
|
||||
<select id="session-duration" class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-slate-600 rounded-md bg-white dark:bg-slate-800 text-slate-900 dark:text-white">
|
||||
<option value="30">30 Minuten</option>
|
||||
<option value="60">1 Stunde</option>
|
||||
<option value="120" selected>2 Stunden</option>
|
||||
<option value="240">4 Stunden</option>
|
||||
<option value="480">8 Stunden</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-slate-500 dark:text-slate-400 mb-1">Force-Quit Aktion</label>
|
||||
<select id="session-force-quit" class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-slate-600 rounded-md bg-white dark:bg-slate-800 text-slate-900 dark:text-white">
|
||||
<option value="logout" selected>Automatisch abmelden</option>
|
||||
<option value="warning">Nur warnen</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<label class="block text-xs text-slate-500 dark:text-slate-400 mb-1">Warnung (Sekunden vor Ablauf)</label>
|
||||
<input type="number" id="session-warning" value="60" min="10" max="300" class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-slate-600 rounded-md bg-white dark:bg-slate-800 text-slate-900 dark:text-white">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions -->
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<button id="create-session-timer" class="btn-primary text-sm px-4 py-2">
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
|
||||
</svg>
|
||||
Timer erstellen
|
||||
</button>
|
||||
<button id="extend-session-5min" class="btn-secondary text-sm px-4 py-2">
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
+5 Min
|
||||
</button>
|
||||
<button id="extend-session-15min" class="btn-secondary text-sm px-4 py-2">
|
||||
+15 Min
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Kiosk Timer (Admin Only) -->
|
||||
{% if current_user.is_admin %}
|
||||
<div class="dashboard-card p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="section-title mb-0">Kiosk-Timer</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="mb-status-indicator mb-status-idle" id="kiosk-timer-status"></div>
|
||||
<span class="text-sm text-slate-500 dark:text-slate-400">Inaktiv</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Timer Container -->
|
||||
<div id="kiosk-countdown-timer" class="mb-6"></div>
|
||||
|
||||
<!-- Admin Configuration -->
|
||||
<div class="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-4 mb-4">
|
||||
<div class="flex items-center mb-3">
|
||||
<svg class="w-5 h-5 text-amber-600 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" />
|
||||
</svg>
|
||||
<h4 class="text-sm font-medium text-amber-800 dark:text-amber-200">Administrator-Funktion</h4>
|
||||
</div>
|
||||
<p class="text-xs text-amber-700 dark:text-amber-300 mb-3">Kiosk-Timer gelten systemweit für alle Benutzer und führen bei Ablauf automatische Aktionen aus.</p>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-xs text-amber-700 dark:text-amber-300 mb-1">Dauer (Minuten)</label>
|
||||
<select id="kiosk-duration" class="w-full px-3 py-2 text-sm border border-amber-300 dark:border-amber-700 rounded-md bg-white dark:bg-slate-800 text-slate-900 dark:text-white">
|
||||
<option value="15">15 Minuten</option>
|
||||
<option value="30" selected>30 Minuten</option>
|
||||
<option value="60">1 Stunde</option>
|
||||
<option value="120">2 Stunden</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs text-amber-700 dark:text-amber-300 mb-1">System-Aktion</label>
|
||||
<select id="kiosk-action" class="w-full px-3 py-2 text-sm border border-amber-300 dark:border-amber-700 rounded-md bg-white dark:bg-slate-800 text-slate-900 dark:text-white">
|
||||
<option value="logout" selected>Alle Benutzer abmelden</option>
|
||||
<option value="restart">System neustarten</option>
|
||||
<option value="shutdown">System herunterfahren</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Admin Actions -->
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<button id="create-kiosk-timer" class="btn-warning text-sm px-4 py-2">
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
||||
</svg>
|
||||
Kiosk-Timer starten
|
||||
</button>
|
||||
<button id="stop-kiosk-timer" class="btn-danger text-sm px-4 py-2">
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 10a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z" />
|
||||
</svg>
|
||||
Stoppen
|
||||
</button>
|
||||
<button id="force-quit-now" class="btn-danger text-sm px-4 py-2">
|
||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" />
|
||||
</svg>
|
||||
Force-Quit jetzt
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<!-- Timer Overview for Non-Admin -->
|
||||
<div class="dashboard-card p-6">
|
||||
<h2 class="section-title">Timer-Übersicht</h2>
|
||||
<div id="timer-overview" class="space-y-4">
|
||||
<!-- Dynamic timer list will be populated here -->
|
||||
<div class="text-center py-8">
|
||||
<svg class="w-12 h-12 mx-auto mb-3 text-slate-400 dark:text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<p class="text-slate-700 dark:text-slate-300 font-medium mb-1">Keine aktiven Timer</p>
|
||||
<p class="text-slate-500 dark:text-slate-400 text-sm">Erstellen Sie einen Session-Timer für automatische Verwaltung.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Active Jobs Section -->
|
||||
<div class="dashboard-card p-6">
|
||||
<h2 class="section-title">Aktuelle Druckaufträge</h2>
|
||||
@ -647,7 +498,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script src="{{ url_for('static', filename='js/countdown-timer.js') }}"></script>
|
||||
<script>
|
||||
class DashboardManager {
|
||||
constructor() {
|
||||
@ -1091,512 +941,12 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.dashboardManager = new DashboardManager();
|
||||
|
||||
// Timer-Funktionalität initialisieren
|
||||
initializeTimerControls();
|
||||
|
||||
// Cleanup beim Verlassen
|
||||
window.addEventListener('beforeunload', () => {
|
||||
if (window.dashboardManager) {
|
||||
window.dashboardManager.cleanup();
|
||||
}
|
||||
// Timer cleanup
|
||||
if (window.TimerManager) {
|
||||
window.TimerManager.destroyAll();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Initialisiert die Timer-Steuerung im Dashboard
|
||||
*/
|
||||
function initializeTimerControls() {
|
||||
console.log('🕒 Timer-Steuerung wird initialisiert...');
|
||||
|
||||
// Session-Timer Ereignisse
|
||||
setupSessionTimerEvents();
|
||||
|
||||
// Kiosk-Timer Ereignisse (nur für Admins)
|
||||
if (document.getElementById('create-kiosk-timer')) {
|
||||
setupKioskTimerEvents();
|
||||
}
|
||||
|
||||
// Bestehende Timer laden
|
||||
loadExistingTimers();
|
||||
|
||||
// Timer-Status regelmäßig aktualisieren
|
||||
setInterval(updateTimerStatus, 5000);
|
||||
|
||||
console.log('✅ Timer-Steuerung erfolgreich initialisiert');
|
||||
}
|
||||
|
||||
/**
|
||||
* Konfiguriert Session-Timer Ereignisse
|
||||
*/
|
||||
function setupSessionTimerEvents() {
|
||||
// Timer erstellen
|
||||
const createBtn = document.getElementById('create-session-timer');
|
||||
if (createBtn) {
|
||||
createBtn.addEventListener('click', async function() {
|
||||
const duration = parseInt(document.getElementById('session-duration').value);
|
||||
const forceQuitAction = document.getElementById('session-force-quit').value;
|
||||
const warningThreshold = parseInt(document.getElementById('session-warning').value);
|
||||
|
||||
await createSessionTimer(duration, forceQuitAction, warningThreshold);
|
||||
});
|
||||
}
|
||||
|
||||
// Timer verlängern - 5 Minuten
|
||||
const extend5Btn = document.getElementById('extend-session-5min');
|
||||
if (extend5Btn) {
|
||||
extend5Btn.addEventListener('click', async function() {
|
||||
await extendSessionTimer(300); // 5 Minuten = 300 Sekunden
|
||||
});
|
||||
}
|
||||
|
||||
// Timer verlängern - 15 Minuten
|
||||
const extend15Btn = document.getElementById('extend-session-15min');
|
||||
if (extend15Btn) {
|
||||
extend15Btn.addEventListener('click', async function() {
|
||||
await extendSessionTimer(900); // 15 Minuten = 900 Sekunden
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Konfiguriert Kiosk-Timer Ereignisse (Admin)
|
||||
*/
|
||||
function setupKioskTimerEvents() {
|
||||
// Kiosk-Timer erstellen
|
||||
const createKioskBtn = document.getElementById('create-kiosk-timer');
|
||||
if (createKioskBtn) {
|
||||
createKioskBtn.addEventListener('click', async function() {
|
||||
const duration = parseInt(document.getElementById('kiosk-duration').value);
|
||||
const action = document.getElementById('kiosk-action').value;
|
||||
|
||||
await createKioskTimer(duration, action);
|
||||
});
|
||||
}
|
||||
|
||||
// Kiosk-Timer stoppen
|
||||
const stopKioskBtn = document.getElementById('stop-kiosk-timer');
|
||||
if (stopKioskBtn) {
|
||||
stopKioskBtn.addEventListener('click', async function() {
|
||||
await stopKioskTimer();
|
||||
});
|
||||
}
|
||||
|
||||
// Force-Quit sofort ausführen
|
||||
const forceQuitBtn = document.getElementById('force-quit-now');
|
||||
if (forceQuitBtn) {
|
||||
forceQuitBtn.addEventListener('click', async function() {
|
||||
if (confirm('⚠️ Force-Quit wird sofort ausgeführt. Alle Benutzer werden abgemeldet. Fortfahren?')) {
|
||||
await executeForceQuitNow();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt einen Session-Timer
|
||||
*/
|
||||
async function createSessionTimer(durationMinutes, forceQuitAction, warningThreshold) {
|
||||
try {
|
||||
showTimerLoading('session');
|
||||
|
||||
// API-Aufruf zur Timer-Erstellung
|
||||
const response = await fetch('/api/timers/session/create', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': getCSRFToken()
|
||||
},
|
||||
body: JSON.stringify({
|
||||
duration_minutes: durationMinutes
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
// Timer-UI erstellen
|
||||
const timer = window.TimerManager.create('session_timer', {
|
||||
container: 'session-countdown-timer',
|
||||
duration: durationMinutes * 60,
|
||||
forceQuitAction: forceQuitAction,
|
||||
warningThreshold: warningThreshold,
|
||||
syncWithServer: true,
|
||||
apiBase: '/api/timers/session_timer_' + getCurrentUserId(),
|
||||
size: 'medium',
|
||||
theme: 'primary',
|
||||
warningMessage: 'Ihre Session läuft ab! Speichern Sie Ihre Arbeit.',
|
||||
autoStart: true,
|
||||
|
||||
// Callbacks
|
||||
onTick: (remaining, total) => {
|
||||
updateTimerStatusIndicator('session', 'running');
|
||||
},
|
||||
onWarning: (remaining) => {
|
||||
showTimerWarning('Session läuft in ' + Math.floor(remaining / 60) + ' Minuten ab!');
|
||||
updateTimerStatusIndicator('session', 'warning');
|
||||
},
|
||||
onExpired: () => {
|
||||
updateTimerStatusIndicator('session', 'expired');
|
||||
if (forceQuitAction === 'logout') {
|
||||
showLogoutWarning();
|
||||
}
|
||||
},
|
||||
onForceQuit: () => {
|
||||
handleSessionForceQuit(forceQuitAction);
|
||||
}
|
||||
});
|
||||
|
||||
showTimerSuccess('Session-Timer erfolgreich erstellt und gestartet');
|
||||
updateSessionTimerControls(true);
|
||||
|
||||
} else {
|
||||
throw new Error(result.error || 'Timer konnte nicht erstellt werden');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen des Session-Timers:', error);
|
||||
showTimerError('Session-Timer konnte nicht erstellt werden: ' + error.message);
|
||||
} finally {
|
||||
hideTimerLoading('session');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt einen Kiosk-Timer (Admin)
|
||||
*/
|
||||
async function createKioskTimer(durationMinutes, action) {
|
||||
try {
|
||||
showTimerLoading('kiosk');
|
||||
|
||||
const response = await fetch('/api/timers/kiosk/create', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': getCSRFToken()
|
||||
},
|
||||
body: JSON.stringify({
|
||||
duration_minutes: durationMinutes,
|
||||
auto_start: true
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
// Kiosk-Timer UI erstellen
|
||||
const timer = window.TimerManager.create('kiosk_timer', {
|
||||
container: 'kiosk-countdown-timer',
|
||||
duration: durationMinutes * 60,
|
||||
forceQuitAction: action,
|
||||
warningThreshold: 30,
|
||||
syncWithServer: true,
|
||||
apiBase: '/api/timers/kiosk_session',
|
||||
size: 'medium',
|
||||
theme: 'warning',
|
||||
warningMessage: '⚠️ Kiosk-Session läuft ab! System wird automatisch ' + getActionText(action) + '.',
|
||||
autoStart: true,
|
||||
showControls: true,
|
||||
|
||||
onTick: (remaining, total) => {
|
||||
updateTimerStatusIndicator('kiosk', 'running');
|
||||
broadcastKioskTimerUpdate(remaining, total);
|
||||
},
|
||||
onWarning: (remaining) => {
|
||||
showKioskWarning('Kiosk-Timer läuft in ' + Math.floor(remaining / 60) + ' Minuten ab!');
|
||||
updateTimerStatusIndicator('kiosk', 'warning');
|
||||
},
|
||||
onExpired: () => {
|
||||
updateTimerStatusIndicator('kiosk', 'expired');
|
||||
executeKioskAction(action);
|
||||
}
|
||||
});
|
||||
|
||||
showTimerSuccess('Kiosk-Timer erfolgreich gestartet');
|
||||
updateKioskTimerControls(true);
|
||||
|
||||
} else {
|
||||
throw new Error(result.error || 'Kiosk-Timer konnte nicht erstellt werden');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Erstellen des Kiosk-Timers:', error);
|
||||
showTimerError('Kiosk-Timer konnte nicht erstellt werden: ' + error.message);
|
||||
} finally {
|
||||
hideTimerLoading('kiosk');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verlängert Session-Timer
|
||||
*/
|
||||
async function extendSessionTimer(additionalSeconds) {
|
||||
try {
|
||||
const timer = window.TimerManager.get('session_timer');
|
||||
if (!timer) {
|
||||
showTimerError('Kein aktiver Session-Timer gefunden');
|
||||
return;
|
||||
}
|
||||
|
||||
const success = await timer.extend(additionalSeconds);
|
||||
if (success) {
|
||||
const minutes = Math.floor(additionalSeconds / 60);
|
||||
showTimerSuccess(`Session-Timer um ${minutes} Minuten verlängert`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Verlängern des Session-Timers:', error);
|
||||
showTimerError('Timer konnte nicht verlängert werden');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stoppt Kiosk-Timer
|
||||
*/
|
||||
async function stopKioskTimer() {
|
||||
try {
|
||||
const timer = window.TimerManager.get('kiosk_timer');
|
||||
if (!timer) {
|
||||
showTimerError('Kein aktiver Kiosk-Timer gefunden');
|
||||
return;
|
||||
}
|
||||
|
||||
const success = await timer.stop();
|
||||
if (success) {
|
||||
showTimerSuccess('Kiosk-Timer gestoppt');
|
||||
updateKioskTimerControls(false);
|
||||
updateTimerStatusIndicator('kiosk', 'stopped');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Stoppen des Kiosk-Timers:', error);
|
||||
showTimerError('Kiosk-Timer konnte nicht gestoppt werden');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Führt Force-Quit sofort aus
|
||||
*/
|
||||
async function executeForceQuitNow() {
|
||||
try {
|
||||
const response = await fetch('/api/timers/kiosk_session/force-quit', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': getCSRFToken()
|
||||
}
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success) {
|
||||
showTimerSuccess('Force-Quit wird ausgeführt...');
|
||||
|
||||
// Je nach Aktion unterschiedlich behandeln
|
||||
if (result.action === 'logout') {
|
||||
setTimeout(() => {
|
||||
window.location.href = result.redirect_url || '/login';
|
||||
}, 2000);
|
||||
} else {
|
||||
showTimerSuccess('Force-Quit-Aktion ausgeführt: ' + result.action);
|
||||
}
|
||||
} else {
|
||||
throw new Error(result.error || 'Force-Quit fehlgeschlagen');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Force-Quit:', error);
|
||||
showTimerError('Force-Quit konnte nicht ausgeführt werden');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt bestehende Timer beim Seitenaufruf
|
||||
*/
|
||||
async function loadExistingTimers() {
|
||||
try {
|
||||
const response = await fetch('/api/timers');
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success && result.data) {
|
||||
result.data.forEach(timerData => {
|
||||
if (timerData.status === 'running') {
|
||||
recreateTimerFromData(timerData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden bestehender Timer:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreiert Timer aus Server-Daten
|
||||
*/
|
||||
function recreateTimerFromData(timerData) {
|
||||
const isSessionTimer = timerData.timer_type === 'session';
|
||||
const isKioskTimer = timerData.timer_type === 'kiosk';
|
||||
|
||||
if (isSessionTimer && timerData.context_id === getCurrentUserId()) {
|
||||
// Session-Timer für aktuellen Benutzer recreieren
|
||||
const timer = window.TimerManager.create('session_timer', {
|
||||
container: 'session-countdown-timer',
|
||||
duration: timerData.duration_seconds,
|
||||
remaining: timerData.remaining_seconds,
|
||||
forceQuitAction: timerData.force_quit_action,
|
||||
warningThreshold: timerData.force_quit_warning_seconds,
|
||||
syncWithServer: true,
|
||||
autoStart: false, // Läuft bereits
|
||||
size: 'medium',
|
||||
theme: 'primary'
|
||||
});
|
||||
|
||||
updateTimerStatusIndicator('session', 'running');
|
||||
updateSessionTimerControls(true);
|
||||
|
||||
} else if (isKioskTimer && isCurrentUserAdmin()) {
|
||||
// Kiosk-Timer für Admin recreieren
|
||||
const timer = window.TimerManager.create('kiosk_timer', {
|
||||
container: 'kiosk-countdown-timer',
|
||||
duration: timerData.duration_seconds,
|
||||
remaining: timerData.remaining_seconds,
|
||||
forceQuitAction: timerData.force_quit_action,
|
||||
warningThreshold: timerData.force_quit_warning_seconds,
|
||||
syncWithServer: true,
|
||||
autoStart: false, // Läuft bereits
|
||||
size: 'medium',
|
||||
theme: 'warning'
|
||||
});
|
||||
|
||||
updateTimerStatusIndicator('kiosk', 'running');
|
||||
updateKioskTimerControls(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert Timer-Status regelmäßig
|
||||
*/
|
||||
async function updateTimerStatus() {
|
||||
// Implementierung für regelmäßige Status-Updates
|
||||
const sessionTimer = window.TimerManager.get('session_timer');
|
||||
const kioskTimer = window.TimerManager.get('kiosk_timer');
|
||||
|
||||
if (sessionTimer && sessionTimer.config.syncWithServer) {
|
||||
sessionTimer.syncWithServer();
|
||||
}
|
||||
|
||||
if (kioskTimer && kioskTimer.config.syncWithServer) {
|
||||
kioskTimer.syncWithServer();
|
||||
}
|
||||
}
|
||||
|
||||
// Hilfsfunktionen
|
||||
function updateTimerStatusIndicator(timerType, status) {
|
||||
const indicator = document.getElementById(`${timerType}-timer-status`);
|
||||
const statusText = indicator?.nextElementSibling;
|
||||
|
||||
if (indicator) {
|
||||
indicator.className = `mb-status-indicator ${getTimerStatusClass(status)}`;
|
||||
}
|
||||
|
||||
if (statusText) {
|
||||
statusText.textContent = getTimerStatusText(status);
|
||||
}
|
||||
}
|
||||
|
||||
function getTimerStatusClass(status) {
|
||||
const classes = {
|
||||
'running': 'mb-status-busy',
|
||||
'stopped': 'mb-status-idle',
|
||||
'warning': 'mb-status-busy',
|
||||
'expired': 'mb-status-offline'
|
||||
};
|
||||
return classes[status] || 'mb-status-idle';
|
||||
}
|
||||
|
||||
function getTimerStatusText(status) {
|
||||
const texts = {
|
||||
'running': 'Läuft',
|
||||
'stopped': 'Gestoppt',
|
||||
'warning': 'Warnung',
|
||||
'expired': 'Abgelaufen'
|
||||
};
|
||||
return texts[status] || 'Unbekannt';
|
||||
}
|
||||
|
||||
function updateSessionTimerControls(active) {
|
||||
const createBtn = document.getElementById('create-session-timer');
|
||||
const extendBtns = [
|
||||
document.getElementById('extend-session-5min'),
|
||||
document.getElementById('extend-session-15min')
|
||||
];
|
||||
|
||||
if (createBtn) createBtn.disabled = active;
|
||||
extendBtns.forEach(btn => {
|
||||
if (btn) btn.disabled = !active;
|
||||
});
|
||||
}
|
||||
|
||||
function updateKioskTimerControls(active) {
|
||||
const createBtn = document.getElementById('create-kiosk-timer');
|
||||
const stopBtn = document.getElementById('stop-kiosk-timer');
|
||||
const forceQuitBtn = document.getElementById('force-quit-now');
|
||||
|
||||
if (createBtn) createBtn.disabled = active;
|
||||
if (stopBtn) stopBtn.disabled = !active;
|
||||
if (forceQuitBtn) forceQuitBtn.disabled = !active;
|
||||
}
|
||||
|
||||
function showTimerLoading(timerType) {
|
||||
// Implementierung für Loading-Anzeige
|
||||
}
|
||||
|
||||
function hideTimerLoading(timerType) {
|
||||
// Implementierung für Loading-Anzeige ausblenden
|
||||
}
|
||||
|
||||
function showTimerSuccess(message) {
|
||||
if (window.dashboardManager) {
|
||||
window.dashboardManager.showToast(message, 'success');
|
||||
}
|
||||
}
|
||||
|
||||
function showTimerError(message) {
|
||||
if (window.dashboardManager) {
|
||||
window.dashboardManager.showToast(message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function showTimerWarning(message) {
|
||||
if (window.dashboardManager) {
|
||||
window.dashboardManager.showToast(message, 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
function getActionText(action) {
|
||||
const actions = {
|
||||
'logout': 'abgemeldet',
|
||||
'restart': 'neugestartet',
|
||||
'shutdown': 'heruntergefahren'
|
||||
};
|
||||
return actions[action] || action;
|
||||
}
|
||||
|
||||
function getCurrentUserId() {
|
||||
return {{ current_user.id }};
|
||||
}
|
||||
|
||||
function isCurrentUserAdmin() {
|
||||
return {{ 'true' if current_user.is_admin else 'false' }};
|
||||
}
|
||||
|
||||
function getCSRFToken() {
|
||||
const token = document.querySelector('meta[name="csrf-token"]');
|
||||
return token ? token.getAttribute('content') : '';
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
Reference in New Issue
Block a user