/** * MYP Platform Job Manager * Verwaltung und Steuerung von 3D-Druckaufträgen * Version: 1.0.0 */ (function() { 'use strict'; /** * Job Manager Klasse für 3D-Druckaufträge */ class JobManager { constructor() { this.jobs = []; this.currentPage = 1; this.totalPages = 1; this.isLoading = false; this.refreshInterval = null; this.autoRefreshEnabled = false; console.log('🔧 JobManager wird initialisiert...'); } /** * JobManager initialisieren */ async init() { try { console.log('🚀 JobManager-Initialisierung gestartet'); // Event-Listener einrichten this.setupEventListeners(); // Formular-Handler einrichten this.setupFormHandlers(); // Anfängliche Jobs laden await this.loadJobs(); // Auto-Refresh starten falls aktiviert if (this.autoRefreshEnabled) { this.startAutoRefresh(); } console.log('✅ JobManager erfolgreich initialisiert'); } catch (error) { console.error('❌ Fehler bei JobManager-Initialisierung:', error); this.showToast('Fehler beim Initialisieren des Job-Managers', 'error'); } } /** * Event-Listener für Job-Aktionen einrichten */ setupEventListeners() { console.log('📡 Event-Listener werden eingerichtet...'); // Job-Aktionen über data-Attribute document.addEventListener('click', (e) => { const target = e.target.closest('[data-job-action]'); if (!target) return; const action = target.getAttribute('data-job-action'); const jobId = target.getAttribute('data-job-id'); if (!jobId) { console.warn('⚠️ Job-ID fehlt für Aktion:', action); return; } switch (action) { case 'start': this.startJob(jobId); break; case 'pause': this.pauseJob(jobId); break; case 'resume': this.resumeJob(jobId); break; case 'stop': this.stopJob(jobId); break; case 'delete': this.deleteJob(jobId); break; case 'details': this.openJobDetails(jobId); break; default: console.warn('⚠️ Unbekannte Job-Aktion:', action); } }); // Refresh-Button const refreshBtn = document.getElementById('refresh-jobs'); if (refreshBtn) { refreshBtn.addEventListener('click', () => this.loadJobs()); } // Auto-Refresh Toggle const autoRefreshToggle = document.getElementById('auto-refresh-toggle'); if (autoRefreshToggle) { autoRefreshToggle.addEventListener('change', (e) => { this.autoRefreshEnabled = e.target.checked; if (this.autoRefreshEnabled) { this.startAutoRefresh(); } else { this.stopAutoRefresh(); } }); } console.log('✅ Event-Listener erfolgreich eingerichtet'); } /** * Formular-Handler für Job-Erstellung einrichten */ setupFormHandlers() { console.log('📝 Formular-Handler werden eingerichtet...'); const newJobForm = document.getElementById('new-job-form'); if (newJobForm) { newJobForm.addEventListener('submit', async (e) => { e.preventDefault(); await this.createNewJob(new FormData(newJobForm)); }); } const editJobForm = document.getElementById('edit-job-form'); if (editJobForm) { editJobForm.addEventListener('submit', async (e) => { e.preventDefault(); const jobId = editJobForm.getAttribute('data-job-id'); await this.updateJob(jobId, new FormData(editJobForm)); }); } console.log('✅ Formular-Handler erfolgreich eingerichtet'); } /** * Jobs von Server laden */ async loadJobs(page = 1) { if (this.isLoading) { console.log('⚠️ Jobs werden bereits geladen...'); return; } this.isLoading = true; this.showLoadingState(true); try { console.log(`📥 Lade Jobs (Seite ${page})...`); const response = await fetch(`/api/jobs?page=${page}`, { headers: { 'X-CSRFToken': this.getCSRFToken(), 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); // VERBESSERTE NULL-CHECKS für jobs-Daten if (data && typeof data === 'object') { // Sicherstellen, dass jobs immer ein Array ist this.jobs = Array.isArray(data.jobs) ? data.jobs : []; this.currentPage = Number(data.current_page) || 1; this.totalPages = Number(data.total_pages) || 1; console.log(`✅ ${this.jobs.length} Jobs erfolgreich geladen`, this.jobs); } else { console.warn('⚠️ Unerwartete API-Response-Struktur:', data); this.jobs = []; this.currentPage = 1; this.totalPages = 1; } // Sichere Rendering-Aufrufe this.renderJobs(); this.updatePagination(); console.log(`✅ ${this.jobs.length} Jobs erfolgreich geladen und gerendert`); } catch (error) { console.error('❌ Fehler beim Laden der Jobs:', error); this.showToast('Fehler beim Laden der Jobs', 'error'); // Fallback: Leere Jobs-Liste anzeigen this.jobs = []; this.currentPage = 1; this.totalPages = 1; this.renderJobs(); } finally { this.isLoading = false; this.showLoadingState(false); } } /** * Job starten */ async startJob(jobId) { try { console.log(`▶️ Starte Job ${jobId}...`); const response = await fetch(`/api/jobs/${jobId}/start`, { method: 'POST', headers: { 'X-CSRFToken': this.getCSRFToken(), 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } this.showToast('Job erfolgreich gestartet', 'success'); await this.loadJobs(); } catch (error) { console.error('❌ Fehler beim Starten des Jobs:', error); this.showToast('Fehler beim Starten des Jobs', 'error'); } } /** * Job pausieren */ async pauseJob(jobId) { try { console.log(`⏸️ Pausiere Job ${jobId}...`); const response = await fetch(`/api/jobs/${jobId}/pause`, { method: 'POST', headers: { 'X-CSRFToken': this.getCSRFToken(), 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } this.showToast('Job erfolgreich pausiert', 'success'); await this.loadJobs(); } catch (error) { console.error('❌ Fehler beim Pausieren des Jobs:', error); this.showToast('Fehler beim Pausieren des Jobs', 'error'); } } /** * Job fortsetzen */ async resumeJob(jobId) { try { console.log(`▶️ Setze Job ${jobId} fort...`); const response = await fetch(`/api/jobs/${jobId}/resume`, { method: 'POST', headers: { 'X-CSRFToken': this.getCSRFToken(), 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } this.showToast('Job erfolgreich fortgesetzt', 'success'); await this.loadJobs(); } catch (error) { console.error('❌ Fehler beim Fortsetzen des Jobs:', error); this.showToast('Fehler beim Fortsetzen des Jobs', 'error'); } } /** * Job stoppen */ async stopJob(jobId) { if (!confirm('Möchten Sie diesen Job wirklich stoppen?')) { return; } try { console.log(`⏹️ Stoppe Job ${jobId}...`); const response = await fetch(`/api/jobs/${jobId}/stop`, { method: 'POST', headers: { 'X-CSRFToken': this.getCSRFToken(), 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } this.showToast('Job erfolgreich gestoppt', 'success'); await this.loadJobs(); } catch (error) { console.error('❌ Fehler beim Stoppen des Jobs:', error); this.showToast('Fehler beim Stoppen des Jobs', 'error'); } } /** * Job löschen */ async deleteJob(jobId) { if (!confirm('Möchten Sie diesen Job wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden.')) { return; } try { console.log(`🗑️ Lösche Job ${jobId}...`); const response = await fetch(`/api/jobs/${jobId}`, { method: 'DELETE', headers: { 'X-CSRFToken': this.getCSRFToken(), 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } this.showToast('Job erfolgreich gelöscht', 'success'); await this.loadJobs(); } catch (error) { console.error('❌ Fehler beim Löschen des Jobs:', error); this.showToast('Fehler beim Löschen des Jobs', 'error'); } } /** * Job-Details öffnen */ openJobDetails(jobId) { console.log(`📄 Öffne Details für Job ${jobId}...`); // Modal für Job-Details öffnen oder zu Detail-Seite navigieren const detailsUrl = `/jobs/${jobId}`; // Prüfen ob Modal verfügbar ist const detailsModal = document.getElementById(`job-details-${jobId}`); if (detailsModal && typeof window.MYP !== 'undefined' && window.MYP.UI && window.MYP.UI.modal) { window.MYP.UI.modal.open(`job-details-${jobId}`); } else { // Fallback: Zur Detail-Seite navigieren window.location.href = detailsUrl; } } /** * Jobs in der UI rendern */ renderJobs() { const jobsList = document.getElementById('jobs-list'); if (!jobsList) { console.warn('⚠️ Jobs-Liste Element nicht gefunden'); return; } // VERBESSERTE SICHERHEITSCHECKS if (!Array.isArray(this.jobs)) { console.warn('⚠️ this.jobs ist kein Array:', this.jobs); this.jobs = []; } if (this.jobs.length === 0) { jobsList.innerHTML = `
Es wurden noch keine Druckaufträge erstellt.
Es gab einen Fehler beim Darstellen der Jobs.