let dashboardData={};let updateInterval;const elements={activeJobs:null,scheduledJobs:null,availablePrinters:null,totalPrintTime:null,schedulerStatus:null,recentJobsList:null,recentActivitiesList:null,refreshBtn:null,schedulerToggleBtn:null};document.addEventListener('DOMContentLoaded',function(){initializeDashboard();});function initializeDashboard(){elements.activeJobs=document.getElementById('active-jobs');elements.scheduledJobs=document.getElementById('scheduled-jobs');elements.availablePrinters=document.getElementById('available-printers');elements.totalPrintTime=document.getElementById('total-print-time');elements.schedulerStatus=document.getElementById('scheduler-status');elements.recentJobsList=document.getElementById('recent-jobs-list');elements.recentActivitiesList=document.getElementById('recent-activities-list');elements.refreshBtn=document.getElementById('refresh-btn');elements.schedulerToggleBtn=document.getElementById('scheduler-toggle-btn');if(elements.refreshBtn){elements.refreshBtn.addEventListener('click',refreshDashboard);} if(elements.schedulerToggleBtn){elements.schedulerToggleBtn.addEventListener('click',toggleScheduler);} loadDashboardData();loadRecentJobs();loadRecentActivities();loadSchedulerStatus();updateInterval=setInterval(function(){loadDashboardData();loadRecentJobs();loadRecentActivities();loadSchedulerStatus();},30000);} async function loadDashboardData(){try{const response=await fetch('/api/dashboard');if(!response.ok){throw new Error(`HTTP ${response.status}:${response.statusText}`);} dashboardData=await response.json();updateDashboardUI();}catch(error){console.error('Fehler beim Laden der Dashboard-Daten:',error);showError('Fehler beim Laden der Dashboard-Daten');}} function updateDashboardUI(){if(elements.activeJobs){elements.activeJobs.textContent=dashboardData.active_jobs||0;} if(elements.scheduledJobs){elements.scheduledJobs.textContent=dashboardData.scheduled_jobs||0;} if(elements.availablePrinters){elements.availablePrinters.textContent=dashboardData.available_printers||0;} if(elements.totalPrintTime){const hours=Math.floor((dashboardData.total_print_time||0)/3600);const minutes=Math.floor(((dashboardData.total_print_time||0)%3600)/60);elements.totalPrintTime.textContent=`${hours}h ${minutes}m`;}} async function loadRecentJobs(){try{const response=await fetch('/api/jobs/recent');if(!response.ok){throw new Error(`HTTP ${response.status}:${response.statusText}`);} const data=await response.json();updateRecentJobsList(data.jobs);}catch(error){console.error('Fehler beim Laden der aktuellen Jobs:',error);if(elements.recentJobsList){elements.recentJobsList.innerHTML='
  • Fehler beim Laden
  • ';}}} function updateRecentJobsList(jobs){if(!elements.recentJobsList)return;if(!jobs||jobs.length===0){elements.recentJobsList.innerHTML='
  • Keine aktuellen Jobs
  • ';return;} const jobsHtml=jobs.map(job=>{const statusClass=getStatusClass(job.status);const timeAgo=formatTimeAgo(job.created_at);return`
  • ${escapeHtml(job.name)}
    ${escapeHtml(job.printer_name)}• ${timeAgo}
    ${getStatusText(job.status)}
  • `;}).join('');elements.recentJobsList.innerHTML=jobsHtml;} async function loadRecentActivities(){try{const response=await fetch('/api/activity/recent');if(!response.ok){throw new Error(`HTTP ${response.status}:${response.statusText}`);} const data=await response.json();updateRecentActivitiesList(data.activities);}catch(error){console.error('Fehler beim Laden der Aktivitäten:',error);if(elements.recentActivitiesList){elements.recentActivitiesList.innerHTML='
  • Fehler beim Laden
  • ';}}} function updateRecentActivitiesList(activities){if(!elements.recentActivitiesList)return;if(!activities||activities.length===0){elements.recentActivitiesList.innerHTML='
  • Keine aktuellen Aktivitäten
  • ';return;} const activitiesHtml=activities.map(activity=>{const timeAgo=formatTimeAgo(activity.timestamp);return`
  • ${escapeHtml(activity.description)}
    ${timeAgo}
  • `;}).join('');elements.recentActivitiesList.innerHTML=activitiesHtml;} async function loadSchedulerStatus(){try{const response=await fetch('/api/scheduler/status');if(!response.ok){throw new Error(`HTTP ${response.status}:${response.statusText}`);} const data=await response.json();updateSchedulerStatus(data.running);}catch(error){console.error('Fehler beim Laden des Scheduler-Status:',error);if(elements.schedulerStatus){elements.schedulerStatus.innerHTML='Unbekannt';}}} function updateSchedulerStatus(isRunning){if(!elements.schedulerStatus)return;const statusClass=isRunning?'bg-success':'bg-danger';const statusText=isRunning?'Aktiv':'Gestoppt';elements.schedulerStatus.innerHTML=`${statusText}`;if(elements.schedulerToggleBtn){elements.schedulerToggleBtn.textContent=isRunning?'Scheduler stoppen':'Scheduler starten';elements.schedulerToggleBtn.className=isRunning?'btn btn-danger btn-sm':'btn btn-success btn-sm';}} async function toggleScheduler(){try{const isRunning=dashboardData.scheduler_running;const endpoint=isRunning?'/api/scheduler/stop':'/api/scheduler/start';const response=await fetch(endpoint,{method:'POST',headers:{'Content-Type':'application/json'}});if(!response.ok){throw new Error(`HTTP ${response.status}:${response.statusText}`);} const result=await response.json();if(result.success){showSuccess(result.message);setTimeout(loadSchedulerStatus,1000);}else{showError(result.error||'Unbekannter Fehler');}}catch(error){console.error('Fehler beim Umschalten des Schedulers:',error);showError('Fehler beim Umschalten des Schedulers');}} function refreshDashboard(){if(elements.refreshBtn){elements.refreshBtn.disabled=true;elements.refreshBtn.innerHTML=' Aktualisiere...';} Promise.all([loadDashboardData(),loadRecentJobs(),loadRecentActivities(),loadSchedulerStatus()]).finally(()=>{if(elements.refreshBtn){elements.refreshBtn.disabled=false;elements.refreshBtn.innerHTML=' Aktualisieren';}});} function getStatusClass(status){const statusClasses={'pending':'bg-warning','printing':'bg-primary','completed':'bg-success','failed':'bg-danger','cancelled':'bg-secondary','scheduled':'bg-info'};return statusClasses[status]||'bg-secondary';} function getStatusText(status){const statusTexts={'pending':'Wartend','printing':'Druckt','completed':'Abgeschlossen','failed':'Fehlgeschlagen','cancelled':'Abgebrochen','scheduled':'Geplant'};return statusTexts[status]||status;} function formatTimeAgo(timestamp){const now=new Date();const time=new Date(timestamp);const diffMs=now-time;const diffMins=Math.floor(diffMs/60000);const diffHours=Math.floor(diffMins/60);const diffDays=Math.floor(diffHours/24);if(diffMins<1)return'Gerade eben';if(diffMins<60)return`vor ${diffMins}Min`;if(diffHours<24)return`vor ${diffHours}Std`;return`vor ${diffDays}Tag${diffDays>1?'en':''}`;} function escapeHtml(text){const div=document.createElement('div');div.textContent=text;return div.innerHTML;} function showSuccess(message){showNotification(message,'success');} function showError(message){showNotification(message,'danger');} function showNotification(message,type){const alertDiv=document.createElement('div');alertDiv.className=`alert alert-${type}alert-dismissible fade show position-fixed`;alertDiv.style.top='20px';alertDiv.style.right='20px';alertDiv.style.zIndex='9999';alertDiv.innerHTML=`${escapeHtml(message)}`;document.body.appendChild(alertDiv);setTimeout(()=>{if(alertDiv.parentNode){alertDiv.parentNode.removeChild(alertDiv);}},5000);} window.addEventListener('beforeunload',function(){if(updateInterval){clearInterval(updateInterval);}});