🐛 Backend Optimization: Enhanced database performance with new files (myp.db-shm, myp.db-wal) and CSS styling improvements in tailwind.min.css & printers.html 🖥️📊

This commit is contained in:
Till Tomczak 2025-06-01 17:51:10 +02:00
parent 345fc6cbb5
commit db4fd5b6c3
6 changed files with 13 additions and 602 deletions

View File

@ -2669,7 +2669,7 @@ def toggle_printer_power(printer_id):
# Standard-Zustand ermitteln (Toggle-Verhalten) # Standard-Zustand ermitteln (Toggle-Verhalten)
db_session = get_db_session() db_session = get_db_session()
printer = db_session.get(Printer, printer_id) printer = db_session.get(Printer, printer_id) # Modernized from query().get()
if not printer: if not printer:
db_session.close() db_session.close()
@ -2730,7 +2730,7 @@ def test_printer_tapo_connection(printer_id):
""" """
try: try:
db_session = get_db_session() db_session = get_db_session()
printer = db_session.get(Printer, printer_id) printer = db_session.query(Printer).get(printer_id)
if not printer: if not printer:
db_session.close() db_session.close()
@ -3963,7 +3963,7 @@ def create_job():
db_session = get_db_session() db_session = get_db_session()
# Prüfen, ob der Drucker existiert # Prüfen, ob der Drucker existiert
printer = db_session.get(Printer, printer_id) printer = db_session.query(Printer).get(printer_id)
if not printer: if not printer:
db_session.close() db_session.close()
return jsonify({"error": "Drucker nicht gefunden"}), 404 return jsonify({"error": "Drucker nicht gefunden"}), 404

Binary file not shown.

BIN
backend/database/myp.db-shm Normal file

Binary file not shown.

BIN
backend/database/myp.db-wal Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1288,233 +1288,15 @@ let printerManager;
// Enhanced Printer Management System // Enhanced Printer Management System
class PrinterManager { class PrinterManager {
constructor() { constructor() {
this.printers = []; this.init();
this.lastUpdateTime = null; this.setupEventListeners();
this.autoRefreshInterval = null; this.startAutoRefresh();
this.isPerformanceMonitoringEnabled = false;
} }
async init() { async init() {
try { await this.loadPrinters();
await this.loadPrinters(); this.populateFilterDropdowns(); // setupFilters() existiert nicht - verwende populateFilterDropdowns()
this.initializeEventListeners(); this.initializePerformanceMonitoring();
this.initializePerformanceMonitoring();
this.startAutoRefresh();
console.log('✅ PrinterManager erfolgreich initialisiert');
} catch (error) {
console.error('❌ Fehler bei PrinterManager-Initialisierung:', error);
}
}
initializePerformanceMonitoring() {
try {
// Performance Monitoring initialisieren
this.isPerformanceMonitoringEnabled = true;
console.log('✅ Performance Monitoring aktiviert');
} catch (error) {
console.error('⚠️ Performance Monitoring konnte nicht initialisiert werden:', error);
this.isPerformanceMonitoringEnabled = false;
}
}
async testPrint(printerId) {
try {
console.log(`🖨️ Testdruck für Drucker ${printerId} wird gestartet...`);
// Toggle-Button für Testdruck
const response = await fetch(`/api/admin/printers/${printerId}/toggle`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': this.getCSRFToken()
},
body: JSON.stringify({ state: true })
});
const result = await response.json();
if (response.ok && result.success) {
this.showSuccess(`Testdruck für Drucker ${printerId} gestartet`);
// Drucker-Status aktualisieren
setTimeout(() => this.loadPrinters(), 1000);
} else {
this.showError(`Testdruck fehlgeschlagen: ${result.error || 'Unbekannter Fehler'}`);
}
} catch (error) {
console.error('Fehler beim Testdruck:', error);
this.showError('Netzwerkfehler beim Starten des Testdrucks');
}
}
async pausePrint(printerId) {
try {
console.log(`⏸️ Pausiere Druck für Drucker ${printerId}...`);
const response = await fetch(`/api/admin/printers/${printerId}/toggle`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': this.getCSRFToken()
},
body: JSON.stringify({ state: false })
});
const result = await response.json();
if (response.ok && result.success) {
this.showSuccess(`Druck für Drucker ${printerId} pausiert`);
setTimeout(() => this.loadPrinters(), 1000);
} else {
this.showError(`Pausieren fehlgeschlagen: ${result.error || 'Unbekannter Fehler'}`);
}
} catch (error) {
console.error('Fehler beim Pausieren:', error);
this.showError('Netzwerkfehler beim Pausieren des Drucks');
}
}
async resetPrinter(printerId) {
try {
console.log(`🔄 Reset für Drucker ${printerId}...`);
const response = await fetch(`/api/admin/printers/${printerId}/toggle`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': this.getCSRFToken()
},
body: JSON.stringify({ state: false })
});
const result = await response.json();
if (response.ok && result.success) {
this.showSuccess(`Drucker ${printerId} wurde zurückgesetzt`);
setTimeout(() => this.loadPrinters(), 1000);
} else {
this.showError(`Reset fehlgeschlagen: ${result.error || 'Unbekannter Fehler'}`);
}
} catch (error) {
console.error('Fehler beim Reset:', error);
this.showError('Netzwerkfehler beim Zurücksetzen des Druckers');
}
}
async connectPrinter(printerId) {
try {
console.log(`🔗 Verbinde zu Drucker ${printerId}...`);
const response = await fetch(`/api/admin/printers/${printerId}/toggle`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': this.getCSRFToken()
},
body: JSON.stringify({ state: true })
});
const result = await response.json();
if (response.ok && result.success) {
this.showSuccess(`Verbindung zu Drucker ${printerId} hergestellt`);
setTimeout(() => this.loadPrinters(), 1000);
} else {
this.showError(`Verbindung fehlgeschlagen: ${result.error || 'Unbekannter Fehler'}`);
}
} catch (error) {
console.error('Fehler bei Verbindung:', error);
this.showError('Netzwerkfehler beim Verbinden mit dem Drucker');
}
}
initializeEventListeners() {
// Search input
const searchInput = document.getElementById('search-input');
if (searchInput) {
searchInput.addEventListener('input', this.debounce(() => this.applyFilters(), 300));
}
// Filter dropdowns
['filterStatus', 'filterLocation', 'filterModel', 'sort-by'].forEach(id => {
const element = document.getElementById(id);
if (element) {
element.addEventListener('change', () => this.applyFilters());
}
});
// Filter checkboxes
['show-offline', 'show-maintenance', 'only-available'].forEach(id => {
const element = document.getElementById(id);
if (element) {
element.addEventListener('change', () => this.applyFilters());
}
});
// Modal close handlers
document.addEventListener('click', (e) => {
if (e.target.classList.contains('modal-overlay')) {
this.closeAllModals();
}
});
// Keyboard shortcuts
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.closeAllModals();
}
});
console.log('✅ Event Listeners initialisiert');
}
showSuccess(message) {
console.log('✅ Erfolg:', message);
// Toast-Benachrichtigung hier implementieren
this.showToast(message, 'success');
}
showError(message) {
console.error('❌ Fehler:', message);
// Toast-Benachrichtigung hier implementieren
this.showToast(message, 'error');
}
showToast(message, type = 'info') {
// Einfache Toast-Implementation
const toast = document.createElement('div');
toast.className = `fixed top-4 right-4 p-4 rounded-lg shadow-lg z-50 ${
type === 'success' ? 'bg-green-500 text-white' :
type === 'error' ? 'bg-red-500 text-white' :
'bg-blue-500 text-white'
}`;
toast.textContent = message;
document.body.appendChild(toast);
// Animation
setTimeout(() => toast.classList.add('animate-fade-in'), 10);
// Auto-remove
setTimeout(() => {
toast.classList.add('animate-fade-out');
setTimeout(() => document.body.removeChild(toast), 300);
}, 3000);
}
getCSRFToken() {
const metaTag = document.querySelector('meta[name="csrf-token"]');
if (metaTag) {
return metaTag.getAttribute('content');
}
// Fallback: Suche nach CSRFToken in versteckten Input-Feldern
const csrfInput = document.querySelector('input[name="csrf_token"]');
if (csrfInput) {
return csrfInput.value;
}
console.warn('⚠️ CSRF-Token nicht gefunden');
return '';
} }
setupEventListeners() { setupEventListeners() {
@ -2257,302 +2039,15 @@ class PrinterManager {
} }
} }
async loadPrinterDetails(printer) { loadPrinterDetails(printer) {
// Hier würden die Detail-Informationen geladen werden
console.log('Lade Details für Drucker:', printer); console.log('Lade Details für Drucker:', printer);
// TODO: Implementiere Detail-Ansicht
try {
// Update basic info
document.getElementById('printer-name-display').textContent = printer.name;
document.getElementById('printer-model-display').textContent = printer.model || 'Unbekanntes Modell';
document.getElementById('ip-address').textContent = printer.ip_address || printer.plug_ip || 'Keine IP';
// Update status
this.updatePrinterStatusDisplay(printer);
// Load extended data from API
const response = await fetch(`/api/printers/${printer.id}/details`);
if (response.ok) {
const detailData = await response.json();
if (detailData.success) {
this.populateDetailedPrinterInfo(detailData.data);
} else {
console.warn('Fehler beim Laden der erweiterten Druckerdetails:', detailData.message);
this.populateMockPrinterInfo(printer);
}
} else {
console.warn('API-Endpunkt nicht verfügbar, verwende Mock-Daten');
this.populateMockPrinterInfo(printer);
}
} catch (error) {
console.error('Fehler beim Laden der Druckerdetails:', error);
this.populateMockPrinterInfo(printer);
}
}
updatePrinterStatusDisplay(printer) {
const statusIcon = document.getElementById('printer-status-icon');
const statusBadge = document.getElementById('printer-status-badge');
const powerBtn = document.getElementById('power-toggle-btn');
// Status Icon und Badge aktualisieren
const statusClasses = this.getStatusClasses(printer.status);
statusIcon.className = `w-12 h-12 ${statusClasses.iconBg} rounded-xl flex items-center justify-center`;
statusIcon.innerHTML = this.getStatusIcon(printer.status);
statusBadge.className = `inline-flex items-center px-3 py-1 rounded-full text-sm font-medium ${statusClasses.badge}`;
statusBadge.innerHTML = `
<div class="w-2 h-2 ${printer.status === 'online' ? 'bg-green-500' : printer.status === 'offline' ? 'bg-red-500' : 'bg-yellow-500'} rounded-full mr-2 ${printer.status === 'printing' ? 'animate-pulse' : ''}"></div>
${this.getStatusText(printer.status)}
`;
// Power Button aktualisieren
if (printer.status === 'offline') {
powerBtn.innerHTML = `
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
</svg>
<span>Steckdose einschalten</span>
`;
powerBtn.className = 'w-full px-4 py-3 bg-green-500 hover:bg-green-600 text-white rounded-lg transition-colors flex items-center justify-center space-x-2';
} else {
powerBtn.innerHTML = `
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728L5.636 5.636m12.728 12.728L18.364 5.636M5.636 18.364l12.728-12.728"/>
</svg>
<span>Steckdose ausschalten</span>
`;
powerBtn.className = 'w-full px-4 py-3 bg-red-500 hover:bg-red-600 text-white rounded-lg transition-colors flex items-center justify-center space-x-2';
}
}
populateDetailedPrinterInfo(data) {
// Netzwerkstatus
document.getElementById('network-status').textContent = data.network?.connected ? 'Verbunden' : 'Getrennt';
document.getElementById('last-activity').textContent = this.formatTimeAgo(data.last_activity);
document.getElementById('printer-uptime').textContent = `Uptime: ${this.formatUptime(data.uptime)}`;
// Temperaturen
if (data.temperatures) {
this.updateTemperatureDisplays(data.temperatures);
}
// Aktueller Job
if (data.current_job) {
this.displayCurrentJob(data.current_job);
} else {
this.showNoJobMessage();
}
// Aktivitätsverlauf
if (data.activity_log) {
this.displayActivityLog(data.activity_log);
}
// Statistiken
if (data.statistics) {
this.displayStatistics(data.statistics);
}
}
populateMockPrinterInfo(printer) {
// Mock-Informationen für Drucker-Details
const detailsContainer = document.getElementById('printer-details-content');
if (detailsContainer) {
detailsContainer.innerHTML = `
<div class="space-y-4">
<div>
<h4 class="font-medium">Grundinformationen</h4>
<p>Modell: ${printer.model || 'Unbekannt'}</p>
<p>Standort: ${printer.location || 'Unbekannt'}</p>
<p>IP-Adresse: ${printer.ip_address || printer.plug_ip || 'Unbekannt'}</p>
</div>
</div>
`;
}
}
updateTemperatureDisplays(temperatures) {
if (temperatures.extruder) {
document.getElementById('extruder-temp').textContent = `${temperatures.extruder.current}°C`;
const extruderPercent = (temperatures.extruder.current / temperatures.extruder.max) * 100;
document.getElementById('extruder-temp-bar').style.width = `${extruderPercent}%`;
}
if (temperatures.bed) {
document.getElementById('bed-temp').textContent = `${temperatures.bed.current}°C`;
const bedPercent = (temperatures.bed.current / temperatures.bed.max) * 100;
document.getElementById('bed-temp-bar').style.width = `${bedPercent}%`;
}
if (temperatures.ambient) {
document.getElementById('ambient-temp').textContent = `${temperatures.ambient.current}°C`;
}
}
displayCurrentJob(job) {
document.getElementById('no-job-message').classList.add('hidden');
document.getElementById('active-job-display').classList.remove('hidden');
document.getElementById('job-title').textContent = job.title;
document.getElementById('job-details').textContent = `Gestartet vor ${this.formatDuration(job.time_elapsed)}`;
document.getElementById('job-progress-text').textContent = `${job.progress}%`;
document.getElementById('job-progress-bar').style.width = `${job.progress}%`;
document.getElementById('time-elapsed').textContent = `Vergangen: ${this.formatDuration(job.time_elapsed)}`;
document.getElementById('time-remaining').textContent = `Verbleibend: ~${this.formatDuration(job.time_remaining)}`;
document.getElementById('current-layer').textContent = `${job.current_layer}/${job.total_layers}`;
document.getElementById('print-quality').textContent = job.quality;
document.getElementById('print-material').textContent = job.material;
// Priority Badge
const priorityBadge = document.getElementById('job-priority');
priorityBadge.textContent = job.priority === 'high' ? 'Hoch' : job.priority === 'low' ? 'Niedrig' : 'Normal';
priorityBadge.className = job.priority === 'high' ?
'px-3 py-1 bg-orange-100 dark:bg-orange-900/30 text-orange-800 dark:text-orange-300 rounded-full text-sm font-medium' :
'px-3 py-1 bg-blue-100 dark:bg-blue-900/30 text-blue-800 dark:text-blue-300 rounded-full text-sm font-medium';
// Show job control buttons
document.getElementById('pause-resume-btn').classList.remove('hidden');
document.getElementById('stop-print-btn').classList.remove('hidden');
}
showNoJobMessage() {
document.getElementById('no-job-message').classList.remove('hidden');
document.getElementById('active-job-display').classList.add('hidden');
document.getElementById('pause-resume-btn').classList.add('hidden');
document.getElementById('stop-print-btn').classList.add('hidden');
}
displayActivityLog(activities) {
const container = document.getElementById('recent-activity-info');
container.innerHTML = activities.map(activity => `
<div class="flex items-center space-x-3 p-3 bg-gray-50 dark:bg-slate-700/50 rounded-lg">
<div class="flex-shrink-0">
<div class="w-2 h-2 ${activity.type === 'success' ? 'bg-green-500' : activity.type === 'error' ? 'bg-red-500' : 'bg-blue-500'} rounded-full"></div>
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium text-mercedes-black dark:text-white">${activity.action}</p>
<p class="text-xs text-mercedes-gray dark:text-slate-400">${this.formatTimeAgo(activity.time)}</p>
</div>
</div>
`).join('');
}
displayStatistics(stats) {
// Heutige Statistiken
document.getElementById('jobs-today').textContent = stats.today.jobs;
document.getElementById('success-rate').textContent = `${stats.today.success_rate}%`;
document.getElementById('print-time-today').textContent = `${stats.today.print_time}h`;
document.getElementById('material-used').textContent = `${stats.today.material_used}g`;
// Wöchentliche Statistiken
document.getElementById('weekly-jobs').textContent = stats.weekly.jobs;
document.getElementById('weekly-success').textContent = stats.weekly.successful;
document.getElementById('weekly-failed').textContent = stats.weekly.failed;
document.getElementById('weekly-material').textContent = `${(stats.weekly.material_used / 1000).toFixed(1)}kg`;
}
formatTimeAgo(dateString) {
const now = new Date();
const date = new Date(dateString);
const diffInMinutes = Math.floor((now - date) / (1000 * 60));
if (diffInMinutes < 1) return 'Gerade eben';
if (diffInMinutes < 60) return `Vor ${diffInMinutes} Min`;
if (diffInMinutes < 1440) return `Vor ${Math.floor(diffInMinutes / 60)} Std`;
return `Vor ${Math.floor(diffInMinutes / 1440)} Tagen`;
}
renderSmartPlugControls(printer) {
// Nur für Admins sichtbar
if (!this.isCurrentUserAdmin()) {
return '';
}
const isOnline = ['online', 'printing', 'idle'].includes(printer.status);
const buttonClass = isOnline ? 'bg-red-500 hover:bg-red-600' : 'bg-green-500 hover:bg-green-600';
const buttonText = isOnline ? 'AUS' : 'EIN';
const buttonIcon = isOnline ?
`<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>` :
`<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
</svg>`;
return `
<div class="smart-plug-control p-3 bg-gray-50 dark:bg-gray-800 rounded-lg">
<h4 class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
🔌 Smart-Plug Steuerung
</h4>
<div class="flex items-center justify-between">
<div class="text-xs text-gray-500">
Steckdose: ${printer.plug_ip || 'Nicht konfiguriert'}
</div>
<button
onclick="printerManager.toggleSmartPlug(${printer.id}, ${!isOnline})"
class="smart-plug-btn flex items-center space-x-1 px-3 py-1 rounded text-white text-sm font-medium ${buttonClass} transition-colors duration-200"
${!printer.plug_ip ? 'disabled' : ''}
>
${buttonIcon}
<span>${buttonText}</span>
</button>
</div>
<div class="mt-2 text-xs text-gray-500">
Status: <span class="font-medium">${this.getStatusText(printer.status)}</span>
</div>
</div>
`;
}
async toggleSmartPlug(printerId, turnOn) {
try {
const action = turnOn ? 'einschalten' : 'ausschalten';
console.log(`🔌 Smart-Plug für Drucker ${printerId} wird ${action}...`);
// Visuelles Feedback
const button = document.querySelector(`button[onclick*="toggleSmartPlug(${printerId}"]`);
if (button) {
button.disabled = true;
button.innerHTML = '<svg class="w-4 h-4 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path></svg> <span>Wird geschaltet...</span>';
}
const response = await fetch(`/api/admin/printers/${printerId}/toggle`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': this.getCSRFToken()
},
body: JSON.stringify({ state: turnOn })
});
const result = await response.json();
if (response.ok && result.success) {
this.showSuccess(`Smart-Plug erfolgreich ${action}: ${result.printer_name}`);
// Sofortige UI-Aktualisierung
setTimeout(() => this.loadPrinters(), 500);
} else {
this.showError(`Smart-Plug ${action} fehlgeschlagen: ${result.error || 'Unbekannter Fehler'}`);
}
} catch (error) {
console.error('Fehler beim Smart-Plug Toggle:', error);
this.showError(`Netzwerkfehler beim ${turnOn ? 'Einschalten' : 'Ausschalten'} der Smart-Plug`);
} finally {
// Button wieder aktivieren
setTimeout(() => this.loadPrinters(), 1000);
}
}
isCurrentUserAdmin() {
// Prüfe ob der aktuelle Benutzer Admin-Rechte hat
const userRole = document.querySelector('meta[name="user-role"]')?.getAttribute('content');
return userRole === 'admin';
} }
} }
// Initialize Printer Manager // Initialize Printer Manager
printerManager = new PrinterManager(); printerManager = new PrinterManager();
printerManager.init();
// Global functions for UI interactions // Global functions for UI interactions
function refreshPrinters() { function refreshPrinters() {
@ -2725,89 +2220,5 @@ function getStatusSummary() {
return summary; return summary;
} }
// Neue globale Funktionen für Printer Details Modal Schnellaktionen
function refreshPrinterDetails() {
const currentPrinter = printerManager.getCurrentDetailsPrinter();
if (currentPrinter) {
printerManager.loadPrinterDetails(currentPrinter);
}
}
function togglePrinterPower() {
const currentPrinter = printerManager.getCurrentDetailsPrinter();
if (currentPrinter) {
const isOnline = ['online', 'printing', 'idle'].includes(currentPrinter.status);
printerManager.toggleSmartPlug(currentPrinter.id, !isOnline);
}
}
function pauseResumePrint() {
const currentPrinter = printerManager.getCurrentDetailsPrinter();
if (currentPrinter && currentPrinter.status === 'printing') {
// TODO: Implementiere Pause/Resume Funktionalität
console.log('Pausiere/Fortsetze Druck für Drucker:', currentPrinter.id);
printerManager.showSuccess('Pause/Resume Funktionalität wird implementiert');
}
}
function stopPrint() {
const currentPrinter = printerManager.getCurrentDetailsPrinter();
if (currentPrinter && currentPrinter.status === 'printing') {
if (confirm('Möchten Sie den aktuellen Druckauftrag wirklich abbrechen?')) {
// TODO: Implementiere Stop Print Funktionalität
console.log('Stoppe Druck für Drucker:', currentPrinter.id);
printerManager.showSuccess('Stop Print Funktionalität wird implementiert');
}
}
}
function sendToMaintenance() {
const currentPrinter = printerManager.getCurrentDetailsPrinter();
if (currentPrinter) {
if (confirm(`Möchten Sie ${currentPrinter.name} in den Wartungsmodus versetzen?`)) {
// TODO: Implementiere Wartungsmodus
console.log('Wartungsmodus für Drucker:', currentPrinter.id);
printerManager.showSuccess('Wartungsmodus Funktionalität wird implementiert');
}
}
}
function testPrinterConnection() {
const currentPrinter = printerManager.getCurrentDetailsPrinter();
if (currentPrinter) {
console.log('Teste Verbindung für Drucker:', currentPrinter.id);
printerManager.showSuccess('Verbindungstest wird durchgeführt...');
// Simulate connection test
setTimeout(() => {
printerManager.showSuccess('Verbindung erfolgreich getestet');
}, 2000);
}
}
function openFileManager() {
const currentPrinter = printerManager.getCurrentDetailsPrinter();
if (currentPrinter) {
console.log('Öffne Datei-Manager für Drucker:', currentPrinter.id);
printerManager.showSuccess('Datei-Manager wird geöffnet...');
// TODO: Implementiere Datei-Manager Modal
}
}
function uploadFile() {
const currentPrinter = printerManager.getCurrentDetailsPrinter();
if (currentPrinter) {
console.log('Datei-Upload für Drucker:', currentPrinter.id);
printerManager.showSuccess('Datei-Upload wird geöffnet...');
// TODO: Implementiere Datei-Upload Modal
}
}
</script>
{% endblock %}
});
return summary;
}
</script> </script>
{% endblock %} {% endblock %}