/** * MYP Platform - Erweiterte Optimierungs- und Batch-Funktionen * Implementiert Auto-Optimierung und Batch-Planung für 3D-Druckaufträge */ class OptimizationManager { constructor() { this.isAutoOptimizationEnabled = false; this.isBatchModeEnabled = false; this.selectedJobs = new Set(); this.optimizationSettings = { algorithm: 'round_robin', // 'round_robin', 'load_balance', 'priority_based' considerDistance: true, minimizeChangeover: true, maxBatchSize: 10, timeWindow: 24 // Stunden }; this.init(); } init() { this.setupEventListeners(); this.loadSavedSettings(); this.updateUI(); } setupEventListeners() { // Keyboard shortcuts document.addEventListener('keydown', (e) => { if (e.ctrlKey && e.altKey && e.key === 'O') { this.toggleAutoOptimization(); e.preventDefault(); } if (e.ctrlKey && e.altKey && e.key === 'B') { this.toggleBatchMode(); e.preventDefault(); } }); } /** * Auto-Optimierung ein-/ausschalten * Diese Funktion optimiert automatisch die Druckreihenfolge basierend auf verschiedenen Faktoren */ toggleAutoOptimization() { this.isAutoOptimizationEnabled = !this.isAutoOptimizationEnabled; const button = document.getElementById('auto-opt-toggle'); if (button) { this.updateAutoOptimizationButton(button); } // Settings speichern localStorage.setItem('myp-auto-optimization', this.isAutoOptimizationEnabled); // Notification anzeigen this.showOptimizationNotification( this.isAutoOptimizationEnabled ? 'aktiviert' : 'deaktiviert', 'auto-optimization' ); // Wenn aktiviert, sofortige Optimierung durchführen if (this.isAutoOptimizationEnabled) { this.performAutoOptimization(); } // UI aktualisieren this.updateUI(); } updateAutoOptimizationButton(button) { const span = button.querySelector('span'); const icon = button.querySelector('svg'); if (this.isAutoOptimizationEnabled) { button.classList.remove('btn-secondary'); button.classList.add('btn-primary'); span.textContent = 'Auto-Optimierung AN'; // Button-Animation button.style.transform = 'scale(1.05)'; setTimeout(() => { button.style.transform = ''; }, 200); // Icon-Animation icon.style.animation = 'spin 1s ease-in-out'; setTimeout(() => { icon.style.animation = ''; }, 1000); } else { button.classList.remove('btn-primary'); button.classList.add('btn-secondary'); span.textContent = 'Auto-Optimierung'; } } /** * Batch-Modus ein-/ausschalten * Ermöglicht die Auswahl mehrerer Jobs für Batch-Operationen */ toggleBatchMode() { this.isBatchModeEnabled = !this.isBatchModeEnabled; const button = document.getElementById('batch-toggle'); if (button) { this.updateBatchModeButton(button); } // Batch-Funktionalität aktivieren/deaktivieren this.toggleBatchSelection(); // Settings speichern localStorage.setItem('myp-batch-mode', this.isBatchModeEnabled); // Notification anzeigen this.showOptimizationNotification( this.isBatchModeEnabled ? 'aktiviert' : 'deaktiviert', 'batch-mode' ); // UI aktualisieren this.updateUI(); } updateBatchModeButton(button) { const span = button.querySelector('span'); if (this.isBatchModeEnabled) { button.classList.remove('btn-secondary'); button.classList.add('btn-warning'); span.textContent = `Batch-Modus (${this.selectedJobs.size})`; // Button-Animation button.style.transform = 'scale(1.05)'; setTimeout(() => { button.style.transform = ''; }, 200); } else { button.classList.remove('btn-warning'); button.classList.add('btn-secondary'); span.textContent = 'Mehrfachauswahl'; // Auswahl zurücksetzen this.selectedJobs.clear(); } } toggleBatchSelection() { const jobCards = document.querySelectorAll('.job-card, [data-job-id]'); jobCards.forEach(card => { if (this.isBatchModeEnabled) { this.enableBatchSelection(card); } else { this.disableBatchSelection(card); } }); } enableBatchSelection(card) { // Checkbox hinzufügen let checkbox = card.querySelector('.batch-checkbox'); if (!checkbox) { checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.className = 'batch-checkbox absolute top-3 left-3 w-5 h-5 rounded border-2 border-gray-300 text-blue-600 focus:ring-blue-500'; checkbox.style.zIndex = '10'; // Event Listener für Checkbox checkbox.addEventListener('change', (e) => { const jobId = card.dataset.jobId; if (e.target.checked) { this.selectedJobs.add(jobId); card.classList.add('selected-for-batch'); } else { this.selectedJobs.delete(jobId); card.classList.remove('selected-for-batch'); } this.updateBatchCounter(); }); // Checkbox in die Karte einfügen card.style.position = 'relative'; card.appendChild(checkbox); } checkbox.style.display = 'block'; card.classList.add('batch-selectable'); } disableBatchSelection(card) { const checkbox = card.querySelector('.batch-checkbox'); if (checkbox) { checkbox.style.display = 'none'; } card.classList.remove('batch-selectable', 'selected-for-batch'); } updateBatchCounter() { const button = document.getElementById('batch-toggle'); if (button && this.isBatchModeEnabled) { const span = button.querySelector('span'); span.textContent = `Batch-Modus (${this.selectedJobs.size})`; } } /** * Automatische Optimierung durchführen */ async performAutoOptimization() { try { const response = await fetch('/api/optimization/auto-optimize', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': this.getCSRFToken() }, body: JSON.stringify({ settings: this.optimizationSettings, enabled: this.isAutoOptimizationEnabled }) }); const data = await response.json(); if (data.success) { this.showSuccessMessage(`Optimierung erfolgreich: ${data.optimized_jobs} Jobs optimiert`); this.refreshCurrentView(); } else { this.showErrorMessage(`Optimierung fehlgeschlagen: ${data.error}`); } } catch (error) { console.error('Auto-Optimierung Fehler:', error); this.showErrorMessage('Netzwerkfehler bei der Auto-Optimierung'); } } /** * Batch-Operationen durchführen */ async performBatchOperation(operation) { if (this.selectedJobs.size === 0) { this.showWarningMessage('Keine Jobs für Batch-Operation ausgewählt'); return; } const jobIds = Array.from(this.selectedJobs); try { const response = await fetch('/api/jobs/batch-operation', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': this.getCSRFToken() }, body: JSON.stringify({ job_ids: jobIds, operation: operation }) }); const data = await response.json(); if (data.success) { this.showSuccessMessage(`Batch-Operation "${operation}" erfolgreich auf ${jobIds.length} Jobs angewendet`); this.selectedJobs.clear(); this.updateBatchCounter(); this.refreshCurrentView(); } else { this.showErrorMessage(`Batch-Operation fehlgeschlagen: ${data.error}`); } } catch (error) { console.error('Batch-Operation Fehler:', error); this.showErrorMessage('Netzwerkfehler bei der Batch-Operation'); } } /** * Optimierungs-Einstellungen konfigurieren */ showOptimizationSettings() { this.createOptimizationModal(); } createOptimizationModal() { const modal = document.createElement('div'); modal.id = 'optimization-settings-modal'; modal.className = 'fixed inset-0 bg-black/60 backdrop-blur-sm z-50 flex items-center justify-center p-4'; modal.innerHTML = `

Optimierungs-Einstellungen

Konfigurieren Sie die automatische Optimierung für maximale Effizienz

`; document.body.appendChild(modal); this.loadOptimizationSettingsInModal(); } loadOptimizationSettingsInModal() { document.getElementById('optimization-algorithm').value = this.optimizationSettings.algorithm; document.getElementById('consider-distance').checked = this.optimizationSettings.considerDistance; document.getElementById('minimize-changeover').checked = this.optimizationSettings.minimizeChangeover; document.getElementById('max-batch-size').value = this.optimizationSettings.maxBatchSize; document.getElementById('time-window').value = this.optimizationSettings.timeWindow; } saveOptimizationSettings() { this.optimizationSettings.algorithm = document.getElementById('optimization-algorithm').value; this.optimizationSettings.considerDistance = document.getElementById('consider-distance').checked; this.optimizationSettings.minimizeChangeover = document.getElementById('minimize-changeover').checked; this.optimizationSettings.maxBatchSize = parseInt(document.getElementById('max-batch-size').value); this.optimizationSettings.timeWindow = parseInt(document.getElementById('time-window').value); localStorage.setItem('myp-optimization-settings', JSON.stringify(this.optimizationSettings)); document.getElementById('optimization-settings-modal').remove(); this.showSuccessMessage('Optimierungs-Einstellungen gespeichert'); // Wenn Auto-Optimierung aktiv ist, neue Optimierung durchführen if (this.isAutoOptimizationEnabled) { this.performAutoOptimization(); } } loadSavedSettings() { // Auto-Optimierung Status laden const savedAutoOpt = localStorage.getItem('myp-auto-optimization'); if (savedAutoOpt !== null) { this.isAutoOptimizationEnabled = savedAutoOpt === 'true'; } // Batch-Modus Status laden const savedBatchMode = localStorage.getItem('myp-batch-mode'); if (savedBatchMode !== null) { this.isBatchModeEnabled = savedBatchMode === 'true'; } // Optimierungs-Einstellungen laden const savedSettings = localStorage.getItem('myp-optimization-settings'); if (savedSettings) { try { this.optimizationSettings = { ...this.optimizationSettings, ...JSON.parse(savedSettings) }; } catch (error) { console.error('Fehler beim Laden der Optimierungs-Einstellungen:', error); } } } updateUI() { // Buttons aktualisieren const autoOptButton = document.getElementById('auto-opt-toggle'); if (autoOptButton) { this.updateAutoOptimizationButton(autoOptButton); } const batchButton = document.getElementById('batch-toggle'); if (batchButton) { this.updateBatchModeButton(batchButton); } // Batch-Auswahl aktualisieren if (this.isBatchModeEnabled) { this.toggleBatchSelection(); } } // Utility-Funktionen getCSRFToken() { const token = document.querySelector('meta[name="csrf-token"]'); return token ? token.getAttribute('content') : ''; } refreshCurrentView() { // Je nach aktueller Seite entsprechende Refresh-Funktion aufrufen if (typeof refreshJobs === 'function') { refreshJobs(); } else if (typeof refreshCalendar === 'function') { refreshCalendar(); } else if (typeof refreshDashboard === 'function') { refreshDashboard(); } } showOptimizationNotification(status, type) { const messages = { 'auto-optimization': { 'aktiviert': '🚀 Auto-Optimierung aktiviert - Jobs werden automatisch optimiert', 'deaktiviert': '⏸️ Auto-Optimierung deaktiviert' }, 'batch-mode': { 'aktiviert': '📦 Batch-Modus aktiviert - Wählen Sie Jobs für Batch-Operationen aus', 'deaktiviert': '✅ Batch-Modus deaktiviert' } }; const message = messages[type]?.[status] || `${type} ${status}`; this.showSuccessMessage(message); } showSuccessMessage(message) { this.showToast(message, 'success'); } showErrorMessage(message) { this.showToast(message, 'error'); } showWarningMessage(message) { this.showToast(message, 'warning'); } showToast(message, type = 'info') { // Einfache Toast-Benachrichtigung const toast = document.createElement('div'); toast.className = `fixed top-4 right-4 z-50 p-4 rounded-lg shadow-lg transition-all duration-300 transform translate-x-full`; const colors = { success: 'bg-green-500 text-white', error: 'bg-red-500 text-white', warning: 'bg-yellow-500 text-black', info: 'bg-blue-500 text-white' }; toast.className += ` ${colors[type]}`; toast.textContent = message; document.body.appendChild(toast); // Animation einblenden setTimeout(() => { toast.classList.remove('translate-x-full'); }, 100); // Nach 5 Sekunden automatisch entfernen setTimeout(() => { toast.classList.add('translate-x-full'); setTimeout(() => { toast.remove(); }, 300); }, 5000); } } // Globale Funktionen für Template-Integration let optimizationManager; // Auto-Optimierung umschalten window.toggleAutoOptimization = function() { if (!optimizationManager) { optimizationManager = new OptimizationManager(); } optimizationManager.toggleAutoOptimization(); }; // Batch-Modus umschalten window.toggleBatchMode = function() { if (!optimizationManager) { optimizationManager = new OptimizationManager(); } optimizationManager.toggleBatchMode(); }; // Batch-Planung Modal öffnen window.openBatchPlanningModal = function() { if (!optimizationManager) { optimizationManager = new OptimizationManager(); } optimizationManager.showOptimizationSettings(); }; // Optimierungs-Einstellungen anzeigen window.showOptimizationSettings = function() { if (!optimizationManager) { optimizationManager = new OptimizationManager(); } optimizationManager.showOptimizationSettings(); }; // Initialisierung beim Laden der Seite document.addEventListener('DOMContentLoaded', function() { optimizationManager = new OptimizationManager(); console.log('🎯 Optimierungs-Manager initialisiert'); });