"feat: Update WARTESCHLANGEN System Documentation and related files"
This commit is contained in:
1
backend/app/WARTESCHLANGEN_SYSTEM_DOKUMENTATION.md
Normal file
1
backend/app/WARTESCHLANGEN_SYSTEM_DOKUMENTATION.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
@@ -12,7 +12,6 @@ from sqlalchemy import func
|
|||||||
# Lokale Imports
|
# Lokale Imports
|
||||||
from models import init_database, create_initial_admin, User, Printer, Job, Stats, SystemLog, get_db_session, GuestRequest, UserPermission, Notification
|
from models import init_database, create_initial_admin, User, Printer, Job, Stats, SystemLog, get_db_session, GuestRequest, UserPermission, Notification
|
||||||
from utils.logging_config import setup_logging, get_logger
|
from utils.logging_config import setup_logging, get_logger
|
||||||
from utils.printer_status import check_printer_status, check_multiple_printers_status
|
|
||||||
from utils.decorators import measure_execution_time
|
from utils.decorators import measure_execution_time
|
||||||
from utils.file_manager import FileManager
|
from utils.file_manager import FileManager
|
||||||
from utils.job_scheduler import JobScheduler, get_job_scheduler
|
from utils.job_scheduler import JobScheduler, get_job_scheduler
|
||||||
|
2
backend/app/static/css/tailwind.min.css
vendored
2
backend/app/static/css/tailwind.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -215,87 +215,34 @@ window.isAdmin = {% if current_user.is_admin %}true{% else %}false{% endif %};
|
|||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// File upload preview
|
console.log('🔄 Jobs-Seite initialisiert');
|
||||||
const fileInput = document.getElementById('stl_file');
|
|
||||||
const fileNameDisplay = document.getElementById('file-name');
|
|
||||||
|
|
||||||
if (fileInput) {
|
// Zuerst Formular-Defaults initialisieren
|
||||||
fileInput.addEventListener('change', function() {
|
initFormDefaults();
|
||||||
if (this.files && this.files.length > 0) {
|
|
||||||
fileNameDisplay.textContent = 'Ausgewählte Datei: ' + this.files[0].name;
|
|
||||||
fileNameDisplay.classList.remove('hidden');
|
|
||||||
} else {
|
|
||||||
fileNameDisplay.classList.add('hidden');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zeige die aktuelle Zeit als Standardwert für Startzeit
|
// Erst aktuell warten Jobs prüfen
|
||||||
const startTimeInput = document.getElementById('start_time');
|
checkWaitingJobs();
|
||||||
if (startTimeInput) {
|
|
||||||
const now = new Date();
|
|
||||||
now.setMinutes(now.getMinutes() + 30); // Default: 30 Minuten in der Zukunft
|
|
||||||
startTimeInput.value = formatDateTimeForInput(now);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drucker-Liste laden und Formular initialisieren
|
// Dann alles laden
|
||||||
loadPrinters();
|
loadPrinters();
|
||||||
loadActiveJobs();
|
loadActiveJobs();
|
||||||
|
loadQueueStatus(); // Neu: Queue-Status laden
|
||||||
// Event-Listener für Drucker-Auswahl (Status-Anzeige)
|
|
||||||
const printerSelect = document.getElementById('printer_id');
|
|
||||||
const statusWarning = document.getElementById('printer-status-warning');
|
|
||||||
const statusInfo = document.getElementById('printer-status-info');
|
|
||||||
|
|
||||||
if (printerSelect && statusWarning && statusInfo) {
|
|
||||||
printerSelect.addEventListener('change', function() {
|
|
||||||
const selectedOption = this.options[this.selectedIndex];
|
|
||||||
|
|
||||||
if (!selectedOption || selectedOption.value === "") {
|
|
||||||
// Keine Auswahl
|
|
||||||
statusWarning.classList.add('hidden');
|
|
||||||
statusInfo.innerHTML = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status des ausgewählten Druckers bestimmen
|
|
||||||
const isOffline = selectedOption.getAttribute('data-offline') === 'true';
|
|
||||||
const printerName = selectedOption.textContent.split('(')[0].trim().replace(/🟢|🔴/g, '').trim();
|
|
||||||
|
|
||||||
if (isOffline) {
|
|
||||||
// Offline-Drucker: Deutliche Warnung anzeigen
|
|
||||||
statusWarning.classList.remove('hidden');
|
|
||||||
statusInfo.innerHTML = `
|
|
||||||
<div class="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-red-100 text-red-800 border border-red-200">
|
|
||||||
<span class="w-2 h-2 mr-1 bg-red-500 rounded-full"></span>
|
|
||||||
${printerName} ist OFFLINE
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
} else {
|
|
||||||
// Online-Drucker: Positive Statusmeldung
|
|
||||||
statusWarning.classList.add('hidden');
|
|
||||||
statusInfo.innerHTML = `
|
|
||||||
<div class="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800 border border-green-200">
|
|
||||||
<span class="w-2 h-2 mr-1 bg-green-500 rounded-full animate-pulse"></span>
|
|
||||||
${printerName} ist ONLINE und bereit
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initial auslösen, um den Status der Vorauswahl anzuzeigen
|
|
||||||
printerSelect.dispatchEvent(new Event('change'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Formulare initialisieren
|
// Formulare initialisieren
|
||||||
initNewJobForm();
|
initNewJobForm();
|
||||||
initExtendJobForm();
|
initExtendJobForm();
|
||||||
|
|
||||||
// Timer für automatische Aktualisierung der Jobs (alle 60 Sekunden)
|
// Statuswarnung für Drucker-Auswahl konfigurieren
|
||||||
setInterval(loadActiveJobs, 60000);
|
setupPrinterStatusWarning();
|
||||||
|
|
||||||
// Timer für Überprüfung wartender Jobs (alle 30 Sekunden)
|
// Automatic Updates aktivieren
|
||||||
setInterval(checkWaitingJobs, 30000);
|
setInterval(() => {
|
||||||
|
loadActiveJobs();
|
||||||
|
checkWaitingJobs();
|
||||||
|
loadQueueStatus(); // Neu: Queue-Status regelmäßig aktualisieren
|
||||||
|
}, 30000); // 30 Sekunden
|
||||||
|
|
||||||
|
console.log('✅ Jobs-Seite vollständig initialisiert');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Hilfsfunktion zum Formatieren des Datums für Datetime-Input
|
// Hilfsfunktion zum Formatieren des Datums für Datetime-Input
|
||||||
@@ -1391,5 +1338,78 @@ function loadPrintersBasic() {
|
|||||||
showNotification('Fehler beim Laden der Drucker', 'error');
|
showNotification('Fehler beim Laden der Drucker', 'error');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup für Drucker-Status-Warnung
|
||||||
|
function setupPrinterStatusWarning() {
|
||||||
|
const printerSelect = document.getElementById('printer_id');
|
||||||
|
const statusWarning = document.getElementById('printer-status-warning');
|
||||||
|
const statusInfo = document.getElementById('printer-status-info');
|
||||||
|
|
||||||
|
if (printerSelect && statusWarning && statusInfo) {
|
||||||
|
printerSelect.addEventListener('change', function() {
|
||||||
|
const selectedOption = this.options[this.selectedIndex];
|
||||||
|
|
||||||
|
if (!selectedOption || selectedOption.value === "") {
|
||||||
|
// Keine Auswahl
|
||||||
|
statusWarning.classList.add('hidden');
|
||||||
|
statusInfo.innerHTML = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status des ausgewählten Druckers bestimmen
|
||||||
|
const isOffline = selectedOption.getAttribute('data-offline') === 'true';
|
||||||
|
const printerName = selectedOption.textContent.split('(')[0].trim().replace(/🟢|🔴/g, '').trim();
|
||||||
|
|
||||||
|
if (isOffline) {
|
||||||
|
// Offline-Drucker: Deutliche Warnung anzeigen
|
||||||
|
statusWarning.classList.remove('hidden');
|
||||||
|
statusInfo.innerHTML = `
|
||||||
|
<div class="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-red-100 text-red-800 border border-red-200">
|
||||||
|
<span class="w-2 h-2 mr-1 bg-red-500 rounded-full"></span>
|
||||||
|
${printerName} ist OFFLINE
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// Online-Drucker: Positive Statusmeldung
|
||||||
|
statusWarning.classList.add('hidden');
|
||||||
|
statusInfo.innerHTML = `
|
||||||
|
<div class="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800 border border-green-200">
|
||||||
|
<span class="w-2 h-2 mr-1 bg-green-500 rounded-full animate-pulse"></span>
|
||||||
|
${printerName} ist ONLINE und bereit
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initial auslösen, um den Status der Vorauswahl anzuzeigen
|
||||||
|
printerSelect.dispatchEvent(new Event('change'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formular-Initialisierungen
|
||||||
|
function initFormDefaults() {
|
||||||
|
// File upload preview
|
||||||
|
const fileInput = document.getElementById('stl_file');
|
||||||
|
const fileNameDisplay = document.getElementById('file-name');
|
||||||
|
|
||||||
|
if (fileInput) {
|
||||||
|
fileInput.addEventListener('change', function() {
|
||||||
|
if (this.files && this.files.length > 0) {
|
||||||
|
fileNameDisplay.textContent = 'Ausgewählte Datei: ' + this.files[0].name;
|
||||||
|
fileNameDisplay.classList.remove('hidden');
|
||||||
|
} else {
|
||||||
|
fileNameDisplay.classList.add('hidden');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zeige die aktuelle Zeit als Standardwert für Startzeit
|
||||||
|
const startTimeInput = document.getElementById('start_time');
|
||||||
|
if (startTimeInput) {
|
||||||
|
const now = new Date();
|
||||||
|
now.setMinutes(now.getMinutes() + 30); // Default: 30 Minuten in der Zukunft
|
||||||
|
startTimeInput.value = formatDateTimeForInput(now);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -187,13 +187,13 @@
|
|||||||
// Load available printers
|
// Load available printers
|
||||||
async function loadPrinters() {
|
async function loadPrinters() {
|
||||||
try {
|
try {
|
||||||
// Versuche zuerst Status-Check API für bessere Verfügbarkeitsprüfung
|
// Lade ALLE Drucker mit Live-Status-Check (nicht nur verfügbare)
|
||||||
let response;
|
let response;
|
||||||
try {
|
try {
|
||||||
response = await apiCall('/api/printers/status');
|
response = await apiCall('/api/printers/status/live');
|
||||||
printers = Array.isArray(response) ? response : (response.printers || []);
|
printers = Array.isArray(response) ? response : (response.printers || []);
|
||||||
} catch (statusError) {
|
} catch (statusError) {
|
||||||
console.log('Status-API fehlgeschlagen, verwende normale API:', statusError);
|
console.log('Live-Status-API fehlgeschlagen, verwende normale API:', statusError);
|
||||||
response = await apiCall('/api/printers');
|
response = await apiCall('/api/printers');
|
||||||
printers = response.printers || [];
|
printers = response.printers || [];
|
||||||
}
|
}
|
||||||
@@ -203,43 +203,85 @@
|
|||||||
|
|
||||||
console.log('Geladene Drucker:', printers);
|
console.log('Geladene Drucker:', printers);
|
||||||
|
|
||||||
// Filtere verfügbare Drucker (status: 'available' oder active: true)
|
if (printers.length === 0) {
|
||||||
const availablePrinters = printers.filter(p => {
|
select.innerHTML = '<option value="">Keine Drucker in der Datenbank</option>';
|
||||||
return p.status === 'available' || p.active === true;
|
select.disabled = true;
|
||||||
});
|
showFlashMessage('Keine Drucker in der Datenbank gefunden', 'error');
|
||||||
|
|
||||||
console.log('Verfügbare Drucker:', availablePrinters);
|
|
||||||
|
|
||||||
if (availablePrinters.length === 0) {
|
|
||||||
// Zeige alle Drucker an, falls keine als verfügbar markiert sind
|
|
||||||
if (printers.length > 0) {
|
|
||||||
printers.forEach(printer => {
|
|
||||||
const option = document.createElement('option');
|
|
||||||
option.value = printer.id;
|
|
||||||
option.textContent = `${printer.name} (${printer.location || printer.model || 'Unbekanntes Modell'}) - Status unbekannt`;
|
|
||||||
select.appendChild(option);
|
|
||||||
});
|
|
||||||
showFlashMessage(`${printers.length} Drucker geladen (Status unbekannt)`, 'warning');
|
|
||||||
} else {
|
|
||||||
select.innerHTML = '<option value="">Keine Drucker verfügbar</option>';
|
|
||||||
select.disabled = true;
|
|
||||||
showFlashMessage('Keine Drucker in der Datenbank gefunden', 'error');
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
availablePrinters.forEach(printer => {
|
// Sortiere Drucker: Online zuerst, dann nach Name
|
||||||
|
const sortedPrinters = printers.sort((a, b) => {
|
||||||
|
const aOnline = a.status === 'available' || a.is_online || a.active;
|
||||||
|
const bOnline = b.status === 'available' || b.is_online || b.active;
|
||||||
|
|
||||||
|
if (aOnline && !bOnline) return -1;
|
||||||
|
if (!aOnline && bOnline) return 1;
|
||||||
|
|
||||||
|
return a.name.localeCompare(b.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Zähler für Online- und Offline-Drucker
|
||||||
|
let onlineCount = 0;
|
||||||
|
let offlineCount = 0;
|
||||||
|
|
||||||
|
// Alle Drucker anzeigen (online und offline)
|
||||||
|
sortedPrinters.forEach(printer => {
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
option.value = printer.id;
|
option.value = printer.id;
|
||||||
|
|
||||||
// Status-Indikator hinzufügen
|
// Status-Indikator bestimmen
|
||||||
const statusText = printer.status === 'available' ? '✅ Verfügbar' : '⚠️ Status unbekannt';
|
const isOnline = printer.status === 'available' || printer.is_online || printer.active;
|
||||||
|
let statusIcon, statusText;
|
||||||
|
|
||||||
|
if (isOnline) {
|
||||||
|
statusIcon = '✅';
|
||||||
|
statusText = 'ONLINE - Sofortiger Start';
|
||||||
|
option.style.backgroundColor = 'rgba(4, 120, 87, 0.1)';
|
||||||
|
option.style.color = '#047857';
|
||||||
|
option.style.fontWeight = '500';
|
||||||
|
onlineCount++;
|
||||||
|
} else {
|
||||||
|
statusIcon = '🔄';
|
||||||
|
statusText = 'OFFLINE - Warteschlange';
|
||||||
|
option.style.backgroundColor = 'rgba(245, 158, 11, 0.1)';
|
||||||
|
option.style.color = '#d97706';
|
||||||
|
option.style.fontWeight = '400';
|
||||||
|
option.setAttribute('data-offline', 'true');
|
||||||
|
offlineCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Letzter Check-Zeitstempel
|
||||||
|
let lastChecked = '';
|
||||||
|
if (printer.last_checked) {
|
||||||
|
const checkTime = new Date(printer.last_checked);
|
||||||
|
const now = new Date();
|
||||||
|
const diffMinutes = Math.floor((now - checkTime) / 60000);
|
||||||
|
|
||||||
|
if (diffMinutes < 1) {
|
||||||
|
lastChecked = ' (gerade geprüft)';
|
||||||
|
} else if (diffMinutes < 60) {
|
||||||
|
lastChecked = ` (vor ${diffMinutes} Min)`;
|
||||||
|
} else {
|
||||||
|
lastChecked = ` (vor ${Math.floor(diffMinutes / 60)} Std)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const location = printer.location || printer.model || 'Unbekanntes Modell';
|
const location = printer.location || printer.model || 'Unbekanntes Modell';
|
||||||
option.textContent = `${printer.name} (${location}) - ${statusText}`;
|
option.textContent = `${statusIcon} ${printer.name} (${location}) - ${statusText}${lastChecked}`;
|
||||||
select.appendChild(option);
|
select.appendChild(option);
|
||||||
});
|
});
|
||||||
|
|
||||||
showFlashMessage(`${availablePrinters.length} verfügbare Drucker geladen`, 'success');
|
// Status-Nachricht anzeigen
|
||||||
|
if (onlineCount > 0) {
|
||||||
|
if (onlineCount === sortedPrinters.length) {
|
||||||
|
showFlashMessage(`✅ OPTIMAL: Alle ${sortedPrinters.length} Drucker sind ONLINE und bereit`, 'success');
|
||||||
|
} else {
|
||||||
|
showFlashMessage(`🔄 ${onlineCount} von ${sortedPrinters.length} Drucker ONLINE | ${offlineCount} Drucker in Warteschlange verfügbar`, 'success');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showFlashMessage(`🔄 WARTESCHLANGEN-MODUS: Alle ${sortedPrinters.length} Drucker sind OFFLINE - Jobs werden automatisch gestartet, wenn Drucker verfügbar werden`, 'warning');
|
||||||
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading printers:', error);
|
console.error('Error loading printers:', error);
|
||||||
|
Reference in New Issue
Block a user