/**
* Mercedes-Benz MYP Admin Dashboard JavaScript
* Moderne Administration mit Echtzeit-Updates und eleganter UI
*/
// Globale Variablen
let statsUpdateInterval;
let systemStatusInterval;
let realTimeChart;
let csrfToken;
// Dynamische API-Base-URL-Erkennung
function detectApiBaseUrl() {
const currentHost = window.location.hostname;
const currentProtocol = window.location.protocol;
const currentPort = window.location.port;
console.log('đ Admin API URL Detection:', { currentHost, currentProtocol, currentPort });
// PrĂŒfe ob wir bereits auf dem richtigen Port sind
if (currentPort === '5000') {
console.log('â
Verwende relative URLs (bereits auf Port 5000)');
return '';
}
// FĂŒr Entwicklung: Verwende HTTP Port 5000
const devUrl = `http://${currentHost}:5000`;
console.log('đ Admin Fallback zu HTTP:5000:', devUrl);
return devUrl;
}
// Globale API-Base-URL
const API_BASE_URL = detectApiBaseUrl();
console.log('đ Admin API Base URL erkannt:', API_BASE_URL);
// Initialisierung beim Laden der Seite
document.addEventListener('DOMContentLoaded', function() {
// CSRF Token fĂŒr AJAX-Anfragen
csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
// Basis-Initialisierung
initProgressBars();
initConfirmDialogs();
initFlashMessages();
// Erweiterte Admin-FunktionalitÀten
initAdminButtons();
initRealTimeUpdates();
initSystemMonitoring();
initModernAnimations();
initSearchAndFilters();
initDataExport();
// Auto-Refresh fĂŒr Statistiken
startStatsUpdate();
console.log('đ Mercedes-Benz MYP Admin Dashboard loaded successfully');
});
/**
* Initialisiert alle Admin-Button-FunktionalitÀten
*/
function initAdminButtons() {
// Benutzer-Management Buttons
initUserManagement();
// Drucker-Management Buttons
initPrinterManagement();
// System-Management Buttons
initSystemManagement();
// Job-Management Buttons
initJobManagement();
}
/**
* Benutzer-Management FunktionalitÀten
*/
function initUserManagement() {
// Neuer Benutzer Button
const addUserBtn = document.getElementById('add-user-btn');
if (addUserBtn) {
addUserBtn.addEventListener('click', () => showUserModal());
}
// Benutzer bearbeiten Buttons
document.querySelectorAll('.edit-user-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const userId = e.target.closest('button').dataset.userId;
editUser(userId);
});
});
// Benutzer löschen Buttons
document.querySelectorAll('.delete-user-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const userId = e.target.closest('button').dataset.userId;
const userName = e.target.closest('button').dataset.userName;
deleteUser(userId, userName);
});
});
}
/**
* Drucker-Management FunktionalitÀten
*/
function initPrinterManagement() {
// Drucker hinzufĂŒgen Button
const addPrinterBtn = document.getElementById('add-printer-btn');
if (addPrinterBtn) {
addPrinterBtn.addEventListener('click', () => showPrinterModal());
}
// Drucker verwalten Buttons
document.querySelectorAll('.manage-printer-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const printerId = e.target.closest('button').dataset.printerId;
managePrinter(printerId);
});
});
// Drucker-Einstellungen Buttons
document.querySelectorAll('.settings-printer-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const printerId = e.target.closest('button').dataset.printerId;
showPrinterSettings(printerId);
});
});
}
/**
* System-Management FunktionalitÀten
*/
function initSystemManagement() {
// System Status Buttons
const systemStatusBtn = document.querySelector('button[onclick*="System Status"]');
if (systemStatusBtn) {
systemStatusBtn.onclick = null;
systemStatusBtn.addEventListener('click', () => showSystemStatus());
}
const analyticsBtn = document.querySelector('button[onclick*="Analytics"]');
if (analyticsBtn) {
analyticsBtn.onclick = null;
analyticsBtn.addEventListener('click', () => showAnalytics());
}
// Cache leeren
const clearCacheBtn = document.getElementById('clear-cache-btn');
if (clearCacheBtn) {
clearCacheBtn.addEventListener('click', () => clearSystemCache());
}
// Datenbank optimieren
const optimizeDbBtn = document.getElementById('optimize-db-btn');
if (optimizeDbBtn) {
optimizeDbBtn.addEventListener('click', () => optimizeDatabase());
}
// Backup erstellen
const createBackupBtn = document.getElementById('create-backup-btn');
if (createBackupBtn) {
createBackupBtn.addEventListener('click', () => createSystemBackup());
}
// Einstellungen bearbeiten
const editSettingsBtn = document.getElementById('edit-settings-btn');
if (editSettingsBtn) {
editSettingsBtn.addEventListener('click', () => showSystemSettings());
}
// Drucker aktualisieren
const updatePrintersBtn = document.getElementById('update-printers-btn');
if (updatePrintersBtn) {
updatePrintersBtn.addEventListener('click', () => updateAllPrinters());
}
// System neustarten
const restartSystemBtn = document.getElementById('restart-system-btn');
if (restartSystemBtn) {
restartSystemBtn.addEventListener('click', () => restartSystem());
}
// Drucker-Initialisierung erzwingen
const forceInitPrintersBtn = document.getElementById('force-init-printers-btn');
if (forceInitPrintersBtn) {
forceInitPrintersBtn.addEventListener('click', () => forceInitializePrinters());
}
}
/**
* Job-Management FunktionalitÀten
*/
function initJobManagement() {
// Job-Aktionen
document.querySelectorAll('.job-action-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const action = e.target.closest('button').dataset.action;
const jobId = e.target.closest('button').dataset.jobId;
handleJobAction(action, jobId);
});
});
}
/**
* Echtzeit-Updates fĂŒr Dashboard
*/
function initRealTimeUpdates() {
// Statistiken alle 30 Sekunden aktualisieren
statsUpdateInterval = setInterval(() => {
updateDashboardStats();
}, 30000);
// System-Status alle 10 Sekunden aktualisieren
systemStatusInterval = setInterval(() => {
updateSystemStatus();
}, 10000);
}
/**
* System-Monitoring initialisieren
*/
function initSystemMonitoring() {
// CPU/RAM Monitoring in Echtzeit
if (document.querySelector('.server-status')) {
monitorSystemResources();
}
}
/**
* Moderne Animationen initialisieren
*/
function initModernAnimations() {
// Animierte Counters fĂŒr Statistiken
animateCounters();
// Progress Bars mit Animation
animateProgressBars();
// Hover-Effekte
addHoverEffects();
}
/**
* Such- und Filter-FunktionalitÀten
*/
function initSearchAndFilters() {
// Benutzer-Suche
const userSearch = document.querySelector('#user-search');
if (userSearch) {
userSearch.addEventListener('input', (e) => {
filterUsers(e.target.value);
});
}
// Job-Filter
const jobFilter = document.querySelector('select[onchange*="filter"]');
if (jobFilter) {
jobFilter.onchange = null;
jobFilter.addEventListener('change', (e) => {
filterJobs(e.target.value);
});
}
}
/**
* Daten-Export FunktionalitÀten
*/
function initDataExport() {
// Export-Buttons
document.querySelectorAll('button[onclick*="export"]').forEach(btn => {
btn.onclick = null;
btn.addEventListener('click', (e) => {
const exportType = btn.textContent.includes('Export') ? 'csv' : 'json';
exportData(exportType);
});
});
}
/**
* Benutzer Modal anzeigen
*/
function showUserModal(userId = null) {
const modal = createModal('Benutzer ' + (userId ? 'bearbeiten' : 'hinzufĂŒgen'), `
`);
// Form-Handler mit preventDefault
const form = document.getElementById('user-form');
form.addEventListener('submit', (e) => {
e.preventDefault(); // Verhindert automatische Weiterleitung
const formData = new FormData(e.target);
if (userId) {
updateUser(userId, formData);
} else {
createUser(formData);
}
});
}
/**
* System Status anzeigen
*/
function showSystemStatus() {
showLoadingOverlay();
const url = `${API_BASE_URL}/api/admin/system/status`;
fetch(url)
.then(response => response.json())
.then(data => {
hideLoadingOverlay();
const modal = createModal('đ System Status - Live Monitoring', `
Server Resources
RAM:
${data.memory_usage || 0}%
Uptime:
${data.uptime || 'Unbekannt'}
Services
Database:
${data.database_status === 'connected' ? 'Connected' : 'Disconnected'}
Scheduler:
${data.scheduler_running ? 'Running' : 'Stopped'}
`);
})
.catch(error => {
hideLoadingOverlay();
showNotification('Fehler beim Laden des System Status', 'error');
console.error('System status error:', error);
});
}
/**
* Analytics anzeigen
*/
function showAnalytics() {
const modal = createModal('đ Live Analytics Dashboard', `
Drucker Auslastung
Erfolgsrate
`);
// Analytics-Daten laden und Charts initialisieren
loadAnalyticsData();
startLiveAnalytics();
}
/**
* System Cache leeren
*/
async function clearSystemCache() {
if (!confirm('đïž Möchten Sie wirklich den System-Cache leeren?')) return;
showLoadingOverlay();
try {
const url = `${API_BASE_URL}/api/admin/cache/clear`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
}
});
const data = await response.json();
hideLoadingOverlay();
if (data.success) {
showNotification('â
Cache erfolgreich geleert!', 'success');
// Seite nach 2 Sekunden neu laden
setTimeout(() => window.location.reload(), 2000);
} else {
showNotification('â Fehler beim Leeren des Cache: ' + data.message, 'error');
}
} catch (error) {
hideLoadingOverlay();
showNotification('â Netzwerkfehler beim Leeren des Cache', 'error');
console.error('Cache clear error:', error);
}
}
/**
* Datenbank optimieren
*/
async function optimizeDatabase() {
if (!confirm('đ§ Möchten Sie die Datenbank optimieren? Dies kann einige Minuten dauern.')) return;
showLoadingOverlay();
try {
const url = `${API_BASE_URL}/api/admin/database/optimize`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
}
});
const data = await response.json();
hideLoadingOverlay();
if (data.success) {
showNotification('â
Datenbank erfolgreich optimiert!', 'success');
} else {
showNotification('â Fehler bei der Datenbank-Optimierung: ' + data.message, 'error');
}
} catch (error) {
hideLoadingOverlay();
showNotification('â Netzwerkfehler bei der Datenbank-Optimierung', 'error');
console.error('Database optimization error:', error);
}
}
/**
* System Backup erstellen
*/
async function createSystemBackup() {
if (!confirm('đŸ Möchten Sie ein System-Backup erstellen?')) return;
showLoadingOverlay();
try {
const url = `${API_BASE_URL}/api/admin/backup/create`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
}
});
if (response.ok) {
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `myp-backup-${new Date().toISOString().split('T')[0]}.zip`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
hideLoadingOverlay();
showNotification('â
Backup erfolgreich erstellt und heruntergeladen!', 'success');
} else {
throw new Error('Backup failed');
}
} catch (error) {
hideLoadingOverlay();
showNotification('â Fehler beim Erstellen des Backups', 'error');
console.error('Backup error:', error);
}
}
/**
* Utility-Funktionen fĂŒr UI
*/
function createModal(title, content) {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-center justify-center p-4';
modal.innerHTML = `
`;
document.body.appendChild(modal);
// ESC-Key zum SchlieĂen
modal.addEventListener('keydown', (e) => {
if (e.key === 'Escape') closeModal();
});
return modal;
}
function closeModal() {
const modal = document.querySelector('.fixed.inset-0.bg-black\\/50');
if (modal) {
modal.remove();
}
}
function showLoadingOverlay() {
const overlay = document.getElementById('loading-overlay');
if (overlay) {
overlay.classList.remove('hidden');
}
}
function hideLoadingOverlay() {
const overlay = document.getElementById('loading-overlay');
if (overlay) {
overlay.classList.add('hidden');
}
}
function showNotification(message, type = 'info') {
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 px-6 py-4 rounded-xl shadow-2xl z-50 transform transition-all duration-500 translate-x-full ${
type === 'success' ? 'bg-green-500 text-white' :
type === 'error' ? 'bg-red-500 text-white' :
type === 'warning' ? 'bg-yellow-500 text-black' :
'bg-blue-500 text-white'
}`;
notification.innerHTML = `
${type === 'success' ? 'â
' :
type === 'error' ? 'â' :
type === 'warning' ? 'â ïž' : 'âčïž'}
${message}
`;
document.body.appendChild(notification);
// Animation einblenden
setTimeout(() => {
notification.classList.remove('translate-x-full');
}, 100);
// Nach 5 Sekunden entfernen
setTimeout(() => {
notification.classList.add('translate-x-full');
setTimeout(() => notification.remove(), 500);
}, 5000);
}
/**
* Original Basis-Funktionen (erweitert)
*/
function initProgressBars() {
const progressBars = document.querySelectorAll('.progress-bar-fill, [style*="width:"]');
progressBars.forEach((bar, index) => {
const width = bar.style.width || bar.getAttribute('data-width') || '0%';
bar.style.width = '0%';
// Animierte Progress Bars
setTimeout(() => {
bar.style.transition = 'width 1.5s cubic-bezier(0.4, 0, 0.2, 1)';
bar.style.width = width;
}, index * 200);
});
}
function initConfirmDialogs() {
// Erweiterte Confirm-Dialoge mit modernem Design
document.querySelectorAll('[data-confirm]').forEach(element => {
element.addEventListener('click', (e) => {
e.preventDefault();
const message = element.dataset.confirm;
if (confirm(message)) {
// UrsprĂŒngliche Aktion ausfĂŒhren
if (element.tagName === 'FORM') {
element.submit();
} else if (element.href) {
window.location.href = element.href;
}
}
});
});
}
function initFlashMessages() {
const flashMessages = document.querySelectorAll('.flash-messages .alert, [class*="alert"]');
flashMessages.forEach((message, index) => {
// Einblende-Animation
message.style.opacity = '0';
message.style.transform = 'translateY(-20px)';
setTimeout(() => {
message.style.transition = 'all 0.5s ease';
message.style.opacity = '1';
message.style.transform = 'translateY(0)';
}, index * 100);
// Auto-hide nach 7 Sekunden
setTimeout(() => {
message.style.transition = 'all 0.5s ease';
message.style.opacity = '0';
message.style.transform = 'translateY(-20px)';
setTimeout(() => message.remove(), 500);
}, 7000);
});
}
/**
* Dashboard-Updates
*/
function startStatsUpdate() {
updateDashboardStats();
setInterval(updateDashboardStats, 30000); // Alle 30 Sekunden
}
async function updateDashboardStats() {
try {
const url = `${API_BASE_URL}/api/admin/stats/live`;
const response = await fetch(url);
const data = await response.json();
// Stats animiert aktualisieren
updateAnimatedCounter('total-users', data.total_users);
updateAnimatedCounter('total-printers', data.total_printers);
updateAnimatedCounter('active-jobs', data.active_jobs);
updateAnimatedCounter('success-rate', data.success_rate);
} catch (error) {
console.error('Stats update error:', error);
}
}
function updateAnimatedCounter(elementId, newValue) {
const element = document.getElementById(elementId) ||
document.querySelector(`[data-stat="${elementId}"]`);
if (!element) return;
const currentValue = parseInt(element.textContent) || 0;
const difference = newValue - currentValue;
const steps = 20;
const stepValue = difference / steps;
let step = 0;
const interval = setInterval(() => {
step++;
const value = Math.round(currentValue + (stepValue * step));
element.textContent = value + (elementId === 'success-rate' ? '%' : '');
if (step >= steps) {
clearInterval(interval);
element.textContent = newValue + (elementId === 'success-rate' ? '%' : '');
}
}, 50);
}
// Global verfĂŒgbare Funktionen fĂŒr Modal-Callbacks
window.closeModal = closeModal;
window.refreshSystemStatus = () => {
closeModal();
showSystemStatus();
};
/**
* Animierte Counters fĂŒr Statistiken
*/
function animateCounters() {
const counters = document.querySelectorAll('.counter, .stat-number, [data-counter]');
counters.forEach(counter => {
const target = parseInt(counter.textContent.replace(/[^\d]/g, '')) || 0;
const duration = 2000; // 2 Sekunden
const increment = target / (duration / 16); // 60 FPS
let current = 0;
const updateCounter = () => {
if (current < target) {
current += increment;
counter.textContent = Math.floor(current).toLocaleString('de-DE');
requestAnimationFrame(updateCounter);
} else {
counter.textContent = target.toLocaleString('de-DE');
}
};
// Intersection Observer fĂŒr bessere Performance
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
updateCounter();
observer.unobserve(entry.target);
}
});
});
observer.observe(counter);
});
}
/**
* Progress Bars mit Animation
*/
function animateProgressBars() {
const progressBars = document.querySelectorAll('.progress-bar, [data-progress]');
progressBars.forEach(bar => {
const targetWidth = bar.dataset.progress || bar.style.width || '0%';
const targetValue = parseInt(targetWidth);
// Reset width
bar.style.width = '0%';
// Animate to target
setTimeout(() => {
bar.style.transition = 'width 1.5s ease-out';
bar.style.width = targetWidth;
}, 100);
});
}
/**
* Hover-Effekte hinzufĂŒgen
*/
function addHoverEffects() {
// Card hover effects
const cards = document.querySelectorAll('.card, .stat-card, .dashboard-card');
cards.forEach(card => {
card.addEventListener('mouseenter', () => {
card.style.transform = 'translateY(-2px)';
card.style.boxShadow = '0 10px 25px rgba(0,0,0,0.1)';
});
card.addEventListener('mouseleave', () => {
card.style.transform = 'translateY(0)';
card.style.boxShadow = '';
});
});
// Button hover effects
const buttons = document.querySelectorAll('.btn, button:not(.no-hover)');
buttons.forEach(button => {
button.addEventListener('mouseenter', () => {
button.style.transform = 'scale(1.02)';
});
button.addEventListener('mouseleave', () => {
button.style.transform = 'scale(1)';
});
});
}
/**
* Drucker Modal anzeigen
*/
function showPrinterModal(printerId = null) {
const modal = createModal('Drucker ' + (printerId ? 'bearbeiten' : 'hinzufĂŒgen'), `
`);
// Form-Handler mit preventDefault
const form = document.getElementById('printer-form');
form.addEventListener('submit', (e) => {
e.preventDefault(); // Verhindert automatische Weiterleitung
const formData = new FormData(e.target);
if (printerId) {
updatePrinter(printerId, formData);
} else {
createPrinter(formData);
}
});
// Wenn Drucker bearbeitet wird, Daten laden
if (printerId) {
loadPrinterData(printerId);
}
}
/**
* Drucker erstellen
*/
async function createPrinter(formData) {
try {
showLoadingOverlay();
const url = `${API_BASE_URL}/api/admin/printers/create`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken()
},
body: JSON.stringify({
name: formData.get('name'),
ip_address: formData.get('ip_address'),
location: formData.get('location'),
description: formData.get('description'),
printer_type: formData.get('printer_type'),
is_active: formData.get('is_active') === 'on'
})
});
const result = await response.json();
if (response.ok) {
showNotification('Drucker erfolgreich hinzugefĂŒgt', 'success');
closeModal();
location.reload(); // Seite neu laden um neue Daten anzuzeigen
} else {
showNotification(result.error || 'Fehler beim HinzufĂŒgen des Druckers', 'error');
}
} catch (error) {
console.error('Error creating printer:', error);
showNotification('Fehler beim HinzufĂŒgen des Druckers', 'error');
} finally {
hideLoadingOverlay();
}
}
/**
* Fehlende Admin-Funktionen
*/
// System-Einstellungen anzeigen
function showSystemSettings() {
const modal = createModal('âïž System-Einstellungen', `
`);
// Form-Handler
const form = document.getElementById('settings-form');
form.addEventListener('submit', async (e) => {
e.preventDefault();
await saveSystemSettings(new FormData(e.target));
});
}
// System-Einstellungen speichern
async function saveSystemSettings(formData) {
try {
showLoadingOverlay();
const settings = {
server: {
host: formData.get('host'),
port: parseInt(formData.get('port')),
ssl_enabled: formData.get('ssl_enabled') === 'on'
},
scheduler: {
interval_seconds: parseInt(formData.get('scheduler_interval')),
enabled: formData.get('scheduler_enabled') === 'on'
}
};
const url = `${API_BASE_URL}/api/admin/settings`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken()
},
body: JSON.stringify(settings)
});
const result = await response.json();
if (result.success) {
showNotification('â
Einstellungen erfolgreich gespeichert!', 'success');
closeModal();
} else {
showNotification('â Fehler beim Speichern: ' + result.message, 'error');
}
} catch (error) {
console.error('Settings save error:', error);
showNotification('â Fehler beim Speichern der Einstellungen', 'error');
} finally {
hideLoadingOverlay();
}
}
// Alle Drucker aktualisieren
async function updateAllPrinters() {
if (!confirm('đ Möchten Sie den Status aller Drucker aktualisieren?')) return;
showLoadingOverlay();
try {
const url = `${API_BASE_URL}/api/admin/printers/update-all`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken()
}
});
const result = await response.json();
if (result.success) {
showNotification(`â
${result.message}`, 'success');
// Seite nach 2 Sekunden neu laden
setTimeout(() => location.reload(), 2000);
} else {
showNotification('â Fehler beim Aktualisieren: ' + result.message, 'error');
}
} catch (error) {
console.error('Printer update error:', error);
showNotification('â Fehler beim Aktualisieren der Drucker', 'error');
} finally {
hideLoadingOverlay();
}
}
/**
* System neustarten
*/
async function restartSystem() {
if (!confirm('đ Möchten Sie das System wirklich neustarten?\n\nDies wird alle aktiven Verbindungen trennen.')) return;
showLoadingOverlay();
try {
const url = `${API_BASE_URL}/api/admin/system/restart`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
}
});
const data = await response.json();
hideLoadingOverlay();
if (data.success) {
showNotification('đ System wird neugestartet...', 'info');
// Nach 5 Sekunden zur Login-Seite weiterleiten
setTimeout(() => {
window.location.href = '/auth/login';
}, 5000);
} else {
showNotification('â Fehler beim Neustart: ' + data.message, 'error');
}
} catch (error) {
hideLoadingOverlay();
showNotification('â Netzwerkfehler beim Neustart', 'error');
console.error('System restart error:', error);
}
}
/**
* Robuste Drucker-Initialisierung erzwingen
*/
async function forceInitializePrinters() {
if (!confirm('đ Möchten Sie eine robuste Drucker-Initialisierung starten?\n\nDies ĂŒberprĂŒft alle Drucker um jeden Preis und markiert sie als online/offline.')) return;
showLoadingOverlay();
try {
const url = `${API_BASE_URL}/api/admin/printers/force-initialize`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken
}
});
const data = await response.json();
hideLoadingOverlay();
if (data.success) {
showNotification('đ Drucker-Initialisierung gestartet!', 'success');
showNotification('âčïž ' + data.info, 'info');
// Nach 3 Sekunden die Drucker-Statistiken aktualisieren
setTimeout(() => {
updateDashboardStats();
}, 3000);
// Nach 10 Sekunden eine weitere Aktualisierung fĂŒr vollstĂ€ndige Ergebnisse
setTimeout(() => {
updateDashboardStats();
showNotification('â
Drucker-Status wurde aktualisiert', 'success');
}, 10000);
} else {
showNotification('â Fehler bei der Drucker-Initialisierung: ' + data.message, 'error');
}
} catch (error) {
hideLoadingOverlay();
showNotification('â Netzwerkfehler bei der Drucker-Initialisierung', 'error');
console.error('Force printer initialization error:', error);
}
}
// Drucker verwalten
function managePrinter(printerId) {
window.location.href = `/admin/printers/${printerId}/manage`;
}
// Drucker-Einstellungen anzeigen
function showPrinterSettings(printerId) {
window.location.href = `/admin/printers/${printerId}/settings`;
}
// Benutzer bearbeiten
function editUser(userId) {
window.location.href = `/admin/users/${userId}/edit`;
}
// Benutzer löschen
async function deleteUser(userId, userName) {
if (!confirm(`â ïž Möchten Sie den Benutzer "${userName}" wirklich löschen? Diese Aktion kann nicht rĂŒckgĂ€ngig gemacht werden.`)) return;
showLoadingOverlay();
try {
const url = `${API_BASE_URL}/api/admin/users/${userId}`;
const response = await fetch(url, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken()
}
});
const result = await response.json();
if (response.ok) {
showNotification(`â
Benutzer "${userName}" erfolgreich gelöscht`, 'success');
// Seite nach 2 Sekunden neu laden
setTimeout(() => location.reload(), 2000);
} else {
showNotification('â Fehler beim Löschen: ' + result.error, 'error');
}
} catch (error) {
console.error('User delete error:', error);
showNotification('â Fehler beim Löschen des Benutzers', 'error');
} finally {
hideLoadingOverlay();
}
}
// Job-Aktionen verarbeiten
async function handleJobAction(action, jobId) {
let confirmMessage = '';
let url = '';
let method = 'POST';
switch (action) {
case 'cancel':
confirmMessage = 'Möchten Sie diesen Job wirklich abbrechen?';
url = `${API_BASE_URL}/api/jobs/${jobId}/cancel`;
break;
case 'delete':
confirmMessage = 'Möchten Sie diesen Job wirklich löschen?';
url = `${API_BASE_URL}/api/jobs/${jobId}`;
method = 'DELETE';
break;
case 'finish':
confirmMessage = 'Möchten Sie diesen Job als beendet markieren?';
url = `${API_BASE_URL}/api/jobs/${jobId}/finish`;
break;
default:
showNotification('â Unbekannte Aktion', 'error');
return;
}
if (!confirm(confirmMessage)) return;
showLoadingOverlay();
try {
const response = await fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken()
}
});
const result = await response.json();
if (response.ok) {
showNotification('â
Aktion erfolgreich ausgefĂŒhrt', 'success');
// Seite nach 2 Sekunden neu laden
setTimeout(() => location.reload(), 2000);
} else {
showNotification('â Fehler: ' + result.error, 'error');
}
} catch (error) {
console.error('Job action error:', error);
showNotification('â Fehler beim AusfĂŒhren der Aktion', 'error');
} finally {
hideLoadingOverlay();
}
}
// Such- und Filter-Funktionen
function filterUsers(searchTerm) {
const userRows = document.querySelectorAll('tbody tr');
userRows.forEach(row => {
const text = row.textContent.toLowerCase();
const matches = text.includes(searchTerm.toLowerCase());
row.style.display = matches ? '' : 'none';
});
}
function filterJobs(status) {
const jobRows = document.querySelectorAll('.job-row, [data-job-status]');
jobRows.forEach(row => {
if (status === 'all') {
row.style.display = '';
} else {
const jobStatus = row.dataset.jobStatus || row.querySelector('.status')?.textContent?.toLowerCase();
const matches = jobStatus === status.toLowerCase();
row.style.display = matches ? '' : 'none';
}
});
}
// Daten-Export
function exportData(type) {
const url = `${API_BASE_URL}/api/admin/export/${type}`;
window.open(url, '_blank');
}
// Analytics-Daten laden
async function loadAnalyticsData() {
try {
const response = await fetch(`${API_BASE_URL}/api/admin/stats/live`);
const data = await response.json();
// Charts mit Chart.js erstellen (falls verfĂŒgbar)
if (typeof Chart !== 'undefined') {
createPrinterUsageChart(data);
createSuccessRateChart(data);
}
} catch (error) {
console.error('Analytics data error:', error);
}
}
// Live-Analytics starten
function startLiveAnalytics() {
setInterval(async () => {
try {
const response = await fetch(`${API_BASE_URL}/api/admin/stats/live`);
const data = await response.json();
// Live-Werte aktualisieren
document.getElementById('live-jobs').textContent = data.jobs?.active || 0;
document.getElementById('live-printers').textContent = data.printers?.online || 0;
document.getElementById('live-queue').textContent = data.jobs?.queued || 0;
document.getElementById('live-success').textContent = (data.jobs?.success_rate || 0) + '%';
} catch (error) {
console.error('Live analytics error:', error);
}
}, 5000); // Alle 5 Sekunden
}
// System-Status aktualisieren
async function updateSystemStatus() {
try {
const response = await fetch(`${API_BASE_URL}/api/admin/system/status`);
const data = await response.json();
// Status-Indikatoren aktualisieren
const indicators = document.querySelectorAll('.status-indicator');
indicators.forEach(indicator => {
// Aktualisiere basierend auf data
});
} catch (error) {
console.error('System status update error:', error);
}
}
/**
* Drucker aktualisieren
*/
async function updatePrinter(printerId, formData) {
try {
showLoadingOverlay();
const url = `${API_BASE_URL}/api/admin/printers/${printerId}/edit`;
const response = await fetch(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken()
},
body: JSON.stringify({
name: formData.get('name'),
ip_address: formData.get('ip_address'),
location: formData.get('location'),
description: formData.get('description'),
printer_type: formData.get('printer_type'),
is_active: formData.get('is_active') === 'on'
})
});
const result = await response.json();
if (response.ok) {
showNotification('Drucker erfolgreich aktualisiert', 'success');
closeModal();
location.reload();
} else {
showNotification(result.error || 'Fehler beim Aktualisieren des Druckers', 'error');
}
} catch (error) {
console.error('Error updating printer:', error);
showNotification('Fehler beim Aktualisieren des Druckers', 'error');
} finally {
hideLoadingOverlay();
}
}
/**
* Drucker-Daten laden
*/
async function loadPrinterData(printerId) {
try {
const url = `${API_BASE_URL}/api/printers`;
const response = await fetch(url);
const printers = await response.json();
const printer = printers.find(p => p.id == printerId);
if (printer) {
const form = document.getElementById('printer-form');
form.name.value = printer.name || '';
form.ip_address.value = printer.ip_address || '';
form.location.value = printer.location || '';
form.description.value = printer.description || '';
form.printer_type.value = printer.printer_type || 'FDM';
form.is_active.checked = printer.is_active;
}
} catch (error) {
console.error('Error loading printer data:', error);
showNotification('Fehler beim Laden der Drucker-Daten', 'error');
}
}
/**
* CSRF Token abrufen
*/
function getCSRFToken() {
const token = document.querySelector('meta[name=csrf-token]');
return token ? token.getAttribute('content') : '';
}
/**
* Benutzer erstellen
*/
async function createUser(formData) {
try {
showLoadingOverlay();
const url = `${API_BASE_URL}/api/admin/users/create`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken()
},
body: JSON.stringify({
email: formData.get('email'),
name: formData.get('name'),
password: formData.get('password'),
role: formData.get('role'),
username: formData.get('email').split('@')[0] // Username aus E-Mail ableiten
})
});
const result = await response.json();
if (response.ok) {
showNotification('Benutzer erfolgreich erstellt', 'success');
closeModal();
location.reload(); // Seite neu laden um neue Daten anzuzeigen
} else {
showNotification(result.error || 'Fehler beim Erstellen des Benutzers', 'error');
}
} catch (error) {
console.error('Error creating user:', error);
showNotification('Fehler beim Erstellen des Benutzers', 'error');
} finally {
hideLoadingOverlay();
}
}
/**
* Benutzer aktualisieren
*/
async function updateUser(userId, formData) {
try {
showLoadingOverlay();
const url = `${API_BASE_URL}/api/admin/users/${userId}/edit`;
const response = await fetch(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken()
},
body: JSON.stringify({
email: formData.get('email'),
name: formData.get('name'),
password: formData.get('password'),
role: formData.get('role')
})
});
const result = await response.json();
if (response.ok) {
showNotification('Benutzer erfolgreich aktualisiert', 'success');
closeModal();
location.reload();
} else {
showNotification(result.error || 'Fehler beim Aktualisieren des Benutzers', 'error');
}
} catch (error) {
console.error('Error updating user:', error);
showNotification('Fehler beim Aktualisieren des Benutzers', 'error');
} finally {
hideLoadingOverlay();
}
}
console.log('đ Mercedes-Benz MYP Admin Dashboard JavaScript vollstĂ€ndig geladen!');