"feat: Update job templates in frontend"
This commit is contained in:
parent
4f7602b047
commit
89b085dec9
@ -1,40 +1,23 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import atexit
|
||||||
import time
|
|
||||||
import subprocess
|
|
||||||
import socket
|
|
||||||
import json
|
|
||||||
import secrets
|
|
||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from functools import wraps
|
from flask import Flask, render_template, request, jsonify, redirect, url_for, flash, send_file, abort, session
|
||||||
from typing import Optional, Dict, List, Tuple, Any, Union
|
from flask_login import LoginManager, login_user, logout_user, login_required, current_user
|
||||||
|
|
||||||
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify, session, send_file, Response, make_response
|
|
||||||
from flask_login import LoginManager, login_user, logout_user, login_required, current_user, UserMixin
|
|
||||||
from werkzeug.security import check_password_hash, generate_password_hash
|
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
import sqlalchemy.exc
|
from sqlalchemy.orm import sessionmaker, joinedload
|
||||||
import sqlalchemy
|
|
||||||
from sqlalchemy.orm import joinedload
|
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
from PyP100 import PyP110
|
|
||||||
from flask_wtf.csrf import CSRFProtect
|
|
||||||
from flask_wtf.csrf import CSRFError
|
|
||||||
|
|
||||||
from config.settings import (
|
# Lokale Imports
|
||||||
SECRET_KEY, TAPO_USERNAME, TAPO_PASSWORD, PRINTERS,
|
from models import init_database, create_initial_admin, User, Printer, Job, Stats, SystemLog, get_db_session, GuestRequest, UserPermission, Notification
|
||||||
FLASK_HOST, FLASK_PORT, FLASK_DEBUG, SESSION_LIFETIME,
|
from utils.logging_config import setup_logging, get_logger
|
||||||
SCHEDULER_INTERVAL, SCHEDULER_ENABLED, get_ssl_context, FLASK_FALLBACK_PORT,
|
from utils.printer_status import check_printer_status, check_multiple_printers_status
|
||||||
SSL_ENABLED, SSL_CERT_PATH, SSL_KEY_PATH
|
from utils.decorators import measure_execution_time
|
||||||
)
|
from utils.file_manager import FileManager
|
||||||
from utils.logging_config import setup_logging, get_logger, log_startup_info, debug_request, debug_response, measure_execution_time
|
from utils.job_scheduler import JobScheduler, get_job_scheduler
|
||||||
from models import User, Printer, Job, Stats, GuestRequest, UserPermission, Notification, get_db_session, init_database, create_initial_admin
|
from utils.queue_manager import start_queue_manager, stop_queue_manager, get_queue_manager
|
||||||
from utils.job_scheduler import scheduler
|
from config.settings import SECRET_KEY, UPLOAD_FOLDER, ALLOWED_EXTENSIONS, ENVIRONMENT
|
||||||
from utils.template_helpers import register_template_helpers
|
|
||||||
from utils.database_utils import backup_manager, database_monitor, maintenance_scheduler
|
|
||||||
|
|
||||||
# Blueprints importieren
|
# Blueprints importieren
|
||||||
from blueprints.guest import guest_blueprint
|
from blueprints.guest import guest_blueprint
|
||||||
@ -4067,6 +4050,45 @@ def mark_all_notifications_read():
|
|||||||
|
|
||||||
# ===== ENDE BENACHRICHTIGUNGS-API-ENDPUNKTE =====
|
# ===== ENDE BENACHRICHTIGUNGS-API-ENDPUNKTE =====
|
||||||
|
|
||||||
|
# ===== QUEUE-MANAGER-API-ENDPUNKTE =====
|
||||||
|
|
||||||
|
@app.route('/api/queue/status', methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
def get_queue_status():
|
||||||
|
"""Gibt den aktuellen Status der Drucker-Warteschlangen zurück."""
|
||||||
|
try:
|
||||||
|
queue_manager = get_queue_manager()
|
||||||
|
status = queue_manager.get_queue_status()
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"success": True,
|
||||||
|
"queue_status": status
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
app_logger.error(f"Fehler beim Abrufen des Queue-Status: {str(e)}")
|
||||||
|
return jsonify({
|
||||||
|
"success": False,
|
||||||
|
"message": f"Fehler beim Abrufen des Queue-Status: {str(e)}"
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
@app.route('/api/queue/check-now', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def trigger_queue_check():
|
||||||
|
"""Triggert eine sofortige Überprüfung der Warteschlangen."""
|
||||||
|
try:
|
||||||
|
# Bestehende check_waiting_jobs API verwenden
|
||||||
|
return check_waiting_jobs()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
app_logger.error(f"Fehler beim manuellen Queue-Check: {str(e)}")
|
||||||
|
return jsonify({
|
||||||
|
"success": False,
|
||||||
|
"message": f"Fehler beim manuellen Queue-Check: {str(e)}"
|
||||||
|
}), 500
|
||||||
|
|
||||||
|
# ===== ENDE QUEUE-MANAGER-API-ENDPUNKTE =====
|
||||||
|
|
||||||
# ===== STARTUP UND MAIN =====
|
# ===== STARTUP UND MAIN =====
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
@ -4082,6 +4104,21 @@ if __name__ == "__main__":
|
|||||||
# Template-Hilfsfunktionen registrieren
|
# Template-Hilfsfunktionen registrieren
|
||||||
register_template_helpers(app)
|
register_template_helpers(app)
|
||||||
|
|
||||||
|
# Queue-Manager für automatische Drucker-Überwachung starten
|
||||||
|
try:
|
||||||
|
queue_manager = start_queue_manager()
|
||||||
|
app_logger.info("✅ Printer Queue Manager erfolgreich gestartet")
|
||||||
|
|
||||||
|
# Shutdown-Handler registrieren
|
||||||
|
def cleanup_queue_manager():
|
||||||
|
app_logger.info("🔄 Beende Queue Manager...")
|
||||||
|
stop_queue_manager()
|
||||||
|
|
||||||
|
atexit.register(cleanup_queue_manager)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
app_logger.error(f"❌ Fehler beim Starten des Queue-Managers: {str(e)}")
|
||||||
|
|
||||||
# Scheduler starten (falls aktiviert)
|
# Scheduler starten (falls aktiviert)
|
||||||
if SCHEDULER_ENABLED:
|
if SCHEDULER_ENABLED:
|
||||||
try:
|
try:
|
||||||
|
@ -26,6 +26,9 @@
|
|||||||
<div class="relative overflow-hidden rounded-2xl p-6 bg-white/70 dark:bg-slate-800/70 backdrop-blur-lg border border-gray-200/80 dark:border-slate-700/30 shadow-xl transition-all duration-300">
|
<div class="relative overflow-hidden rounded-2xl p-6 bg-white/70 dark:bg-slate-800/70 backdrop-blur-lg border border-gray-200/80 dark:border-slate-700/30 shadow-xl transition-all duration-300">
|
||||||
<h2 class="text-xl font-semibold mb-6 text-slate-900 dark:text-white">Neue Reservierung anlegen</h2>
|
<h2 class="text-xl font-semibold mb-6 text-slate-900 dark:text-white">Neue Reservierung anlegen</h2>
|
||||||
|
|
||||||
|
<!-- Queue-Status-Anzeige -->
|
||||||
|
<div id="queue-status-info"></div>
|
||||||
|
|
||||||
<form id="newJobForm" class="space-y-6">
|
<form id="newJobForm" class="space-y-6">
|
||||||
<div class="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
<div class="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
||||||
<!-- Drucker auswählen -->
|
<!-- Drucker auswählen -->
|
||||||
@ -569,6 +572,119 @@ function checkWaitingJobs() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Queue-Status anzeigen (neue Funktion)
|
||||||
|
function loadQueueStatus() {
|
||||||
|
fetch('/api/queue/status')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success && data.queue_status) {
|
||||||
|
updateQueueStatusDisplay(data.queue_status);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Fehler beim Laden des Queue-Status:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue-Status-Anzeige aktualisieren (neue Funktion)
|
||||||
|
function updateQueueStatusDisplay(queueStatus) {
|
||||||
|
const statusContainer = document.getElementById('queue-status-info');
|
||||||
|
if (!statusContainer) return;
|
||||||
|
|
||||||
|
const { waiting_jobs, online_printers, total_printers, queue_manager_running } = queueStatus;
|
||||||
|
|
||||||
|
let statusHtml = '';
|
||||||
|
|
||||||
|
if (waiting_jobs > 0) {
|
||||||
|
statusHtml = `
|
||||||
|
<div class="bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-800 rounded-lg p-3 mb-4">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex-shrink-0 w-8 h-8 mr-3 flex items-center justify-center rounded-full bg-orange-100 dark:bg-orange-800">
|
||||||
|
<svg class="w-5 h-5 text-orange-600 dark:text-orange-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<h4 class="text-sm font-semibold text-orange-800 dark:text-orange-200">
|
||||||
|
🔄 WARTESCHLANGEN-MODUS AKTIV
|
||||||
|
</h4>
|
||||||
|
<p class="text-xs text-orange-700 dark:text-orange-300 mt-1">
|
||||||
|
<span class="font-medium">${waiting_jobs}</span> Job${waiting_jobs === 1 ? '' : 's'} warten auf offline Drucker
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-orange-600 dark:text-orange-400 mt-1">
|
||||||
|
🟢 ${online_printers} von ${total_printers} Druckern online |
|
||||||
|
⏰ System prüft alle 2 Minuten automatisch
|
||||||
|
</p>
|
||||||
|
${queue_manager_running ?
|
||||||
|
'<span class="inline-flex items-center px-2 py-1 rounded-full text-xs bg-green-100 text-green-800 dark:bg-green-800 dark:text-green-200 mt-2"><span class="w-2 h-2 bg-green-500 rounded-full mr-1 animate-pulse"></span>Überwachung aktiv</span>' :
|
||||||
|
'<span class="inline-flex items-center px-2 py-1 rounded-full text-xs bg-red-100 text-red-800 dark:bg-red-800 dark:text-red-200 mt-2"><span class="w-2 h-2 bg-red-500 rounded-full mr-1"></span>Überwachung inaktiv</span>'
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<button onclick="triggerQueueCheck()" class="ml-3 px-3 py-1 bg-orange-100 hover:bg-orange-200 text-orange-800 rounded-lg text-xs font-medium transition-colors">
|
||||||
|
Jetzt prüfen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else if (online_printers === total_printers && total_printers > 0) {
|
||||||
|
statusHtml = `
|
||||||
|
<div class="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-3 mb-4">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex-shrink-0 w-8 h-8 mr-3 flex items-center justify-center rounded-full bg-green-100 dark:bg-green-800">
|
||||||
|
<svg class="w-5 h-5 text-green-600 dark:text-green-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<h4 class="text-sm font-semibold text-green-800 dark:text-green-200">
|
||||||
|
✅ ALLE DRUCKER ONLINE
|
||||||
|
</h4>
|
||||||
|
<p class="text-xs text-green-700 dark:text-green-300 mt-1">
|
||||||
|
Alle ${total_printers} Drucker sind verfügbar - Jobs starten sofort
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
statusContainer.innerHTML = statusHtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manuelle Queue-Überprüfung triggern (neue Funktion)
|
||||||
|
function triggerQueueCheck() {
|
||||||
|
const button = event.target;
|
||||||
|
const originalText = button.textContent;
|
||||||
|
|
||||||
|
button.disabled = true;
|
||||||
|
button.textContent = 'Prüfe...';
|
||||||
|
|
||||||
|
fetch('/api/queue/check-now', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.updated_jobs && data.updated_jobs.length > 0) {
|
||||||
|
showNotification(`🎉 ${data.updated_jobs.length} Job(s) aktiviert!`, 'success');
|
||||||
|
loadActiveJobs();
|
||||||
|
} else {
|
||||||
|
showNotification('✓ Queue-Check abgeschlossen - keine neuen Updates', 'info');
|
||||||
|
}
|
||||||
|
loadQueueStatus(); // Status neu laden
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Fehler beim manuellen Queue-Check:', error);
|
||||||
|
showNotification('Fehler beim Queue-Check', 'error');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
button.disabled = false;
|
||||||
|
button.textContent = originalText;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Initialisierung des Formulars für neue Jobs
|
// Initialisierung des Formulars für neue Jobs
|
||||||
function initNewJobForm() {
|
function initNewJobForm() {
|
||||||
const form = document.getElementById('newJobForm');
|
const form = document.getElementById('newJobForm');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user