376 lines
15 KiB
HTML
376 lines
15 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Admin-Einstellungen - Mercedes-Benz MYP Platform{% endblock %}
|
||
|
||
{% block head %}
|
||
{{ super() }}
|
||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50 dark:from-slate-900 dark:via-slate-800 dark:to-slate-900">
|
||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||
|
||
<!-- Header -->
|
||
<div class="mb-8">
|
||
<div class="flex items-center justify-between">
|
||
<div>
|
||
<h1 class="text-3xl font-bold text-slate-900 dark:text-white">Admin-Einstellungen</h1>
|
||
<p class="text-slate-600 dark:text-slate-400 mt-2">Systemkonfiguration und Verwaltungsoptionen</p>
|
||
</div>
|
||
<a href="{{ url_for('admin_page') }}" class="inline-flex items-center px-4 py-2 bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-300 rounded-xl hover:bg-slate-300 dark:hover:bg-slate-600 transition-all duration-300">
|
||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
||
</svg>
|
||
Zurück zum Dashboard
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||
<!-- System-Wartung -->
|
||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white mb-4">System-Wartung</h3>
|
||
<div class="space-y-4">
|
||
<button onclick="clearCache()"
|
||
class="w-full px-4 py-3 bg-blue-500 text-white rounded-xl hover:bg-blue-600 transition-all duration-300">
|
||
Cache leeren
|
||
</button>
|
||
<button onclick="optimizeDatabase()"
|
||
class="w-full px-4 py-3 bg-green-500 text-white rounded-xl hover:bg-green-600 transition-all duration-300">
|
||
Datenbank optimieren
|
||
</button>
|
||
<button onclick="createBackup()"
|
||
class="w-full px-4 py-3 bg-purple-500 text-white rounded-xl hover:bg-purple-600 transition-all duration-300">
|
||
Backup erstellen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Drucker-Verwaltung -->
|
||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white mb-4">Drucker-Verwaltung</h3>
|
||
<div class="space-y-4">
|
||
<button onclick="updatePrinters()"
|
||
class="w-full px-4 py-3 bg-orange-500 text-white rounded-xl hover:bg-orange-600 transition-all duration-300">
|
||
Drucker-Status aktualisieren
|
||
</button>
|
||
<button onclick="testAllPrinters()"
|
||
class="w-full px-4 py-3 bg-teal-500 text-white rounded-xl hover:bg-teal-600 transition-all duration-300">
|
||
Alle Drucker testen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- System-Informationen -->
|
||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white mb-4">System-Informationen</h3>
|
||
<div class="space-y-3" id="system-info">
|
||
<div class="flex items-center justify-between">
|
||
<span class="text-slate-600 dark:text-slate-400">Server-Status:</span>
|
||
<span class="text-slate-900 dark:text-white font-semibold" id="server-status">Lade...</span>
|
||
</div>
|
||
<div class="flex items-center justify-between">
|
||
<span class="text-slate-600 dark:text-slate-400">Datenbank:</span>
|
||
<span class="text-slate-900 dark:text-white font-semibold" id="db-status">Lade...</span>
|
||
</div>
|
||
<div class="flex items-center justify-between">
|
||
<span class="text-slate-600 dark:text-slate-400">Uptime:</span>
|
||
<span class="text-slate-900 dark:text-white font-semibold" id="uptime">Lade...</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Logs und Überwachung -->
|
||
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white mb-4">Logs und Überwachung</h3>
|
||
<div class="space-y-4">
|
||
<button onclick="downloadLogs()"
|
||
class="w-full px-4 py-3 bg-slate-500 text-white rounded-xl hover:bg-slate-600 transition-all duration-300">
|
||
Logs herunterladen
|
||
</button>
|
||
<button onclick="runMaintenance()"
|
||
class="w-full px-4 py-3 bg-indigo-500 text-white rounded-xl hover:bg-indigo-600 transition-all duration-300">
|
||
Wartung ausführen
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Erweiterte Einstellungen -->
|
||
<div class="mt-8 bg-white dark:bg-slate-800 rounded-2xl shadow-xl p-6">
|
||
<h3 class="text-lg font-semibold text-slate-900 dark:text-white mb-4">Erweiterte Einstellungen</h3>
|
||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||
<div>
|
||
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
|
||
Automatische Backup-Intervall (Stunden)
|
||
</label>
|
||
<input type="number" id="backup-interval" min="1" max="168" value="24"
|
||
class="w-full px-4 py-3 border border-slate-300 dark:border-slate-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-slate-700 dark:text-white">
|
||
</div>
|
||
<div>
|
||
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
|
||
Maximale Job-Laufzeit (Stunden)
|
||
</label>
|
||
<input type="number" id="max-job-time" min="1" max="72" value="12"
|
||
class="w-full px-4 py-3 border border-slate-300 dark:border-slate-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-slate-700 dark:text-white">
|
||
</div>
|
||
</div>
|
||
<div class="mt-6 flex justify-end">
|
||
<button onclick="saveSettings()"
|
||
class="px-6 py-3 bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-xl hover:from-blue-600 hover:to-blue-700 transition-all duration-300 shadow-lg">
|
||
Einstellungen speichern
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// CSRF Token
|
||
function getCsrfToken() {
|
||
const token = document.querySelector('meta[name="csrf-token"]');
|
||
return token ? token.getAttribute('content') : '';
|
||
}
|
||
|
||
// Notification anzeigen
|
||
function showNotification(message, type = 'info') {
|
||
if (type === 'success') {
|
||
alert('✓ ' + message);
|
||
} else if (type === 'error') {
|
||
alert('✗ ' + message);
|
||
} else {
|
||
alert('ℹ ' + message);
|
||
}
|
||
}
|
||
|
||
// Cache leeren
|
||
async function clearCache() {
|
||
if (!confirm('Möchten Sie den Cache wirklich leeren?')) return;
|
||
|
||
try {
|
||
const response = await fetch('/api/admin/cache/clear', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': getCsrfToken()
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result.success) {
|
||
showNotification('Cache erfolgreich geleert', 'success');
|
||
} else {
|
||
showNotification(result.error || 'Fehler beim Leeren des Cache', 'error');
|
||
}
|
||
} catch (error) {
|
||
showNotification('Netzwerkfehler: ' + error.message, 'error');
|
||
}
|
||
}
|
||
|
||
// Datenbank optimieren
|
||
async function optimizeDatabase() {
|
||
if (!confirm('Möchten Sie die Datenbank optimieren? Dies kann einige Minuten dauern.')) return;
|
||
|
||
try {
|
||
const response = await fetch('/api/admin/database/optimize', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': getCsrfToken()
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result.success) {
|
||
showNotification('Datenbank erfolgreich optimiert', 'success');
|
||
} else {
|
||
showNotification(result.error || 'Fehler bei der Datenbankoptimierung', 'error');
|
||
}
|
||
} catch (error) {
|
||
showNotification('Netzwerkfehler: ' + error.message, 'error');
|
||
}
|
||
}
|
||
|
||
// Backup erstellen
|
||
async function createBackup() {
|
||
if (!confirm('Möchten Sie ein Backup erstellen?')) return;
|
||
|
||
try {
|
||
const response = await fetch('/api/admin/backup/create', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': getCsrfToken()
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result.success) {
|
||
showNotification('Backup erfolgreich erstellt', 'success');
|
||
} else {
|
||
showNotification(result.error || 'Fehler beim Erstellen des Backups', 'error');
|
||
}
|
||
} catch (error) {
|
||
showNotification('Netzwerkfehler: ' + error.message, 'error');
|
||
}
|
||
}
|
||
|
||
// Drucker aktualisieren
|
||
async function updatePrinters() {
|
||
try {
|
||
const response = await fetch('/api/admin/printers/update', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': getCsrfToken()
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result.success) {
|
||
showNotification('Drucker-Status erfolgreich aktualisiert', 'success');
|
||
} else {
|
||
showNotification(result.error || 'Fehler beim Aktualisieren der Drucker', 'error');
|
||
}
|
||
} catch (error) {
|
||
showNotification('Netzwerkfehler: ' + error.message, 'error');
|
||
}
|
||
}
|
||
|
||
// Alle Drucker testen
|
||
async function testAllPrinters() {
|
||
try {
|
||
const response = await fetch('/api/printers/status');
|
||
const printers = await response.json();
|
||
|
||
if (response.ok) {
|
||
const onlineCount = printers.filter(p => p.status === 'available').length;
|
||
showNotification(`${onlineCount} von ${printers.length} Druckern sind online`, 'info');
|
||
} else {
|
||
showNotification('Fehler beim Testen der Drucker', 'error');
|
||
}
|
||
} catch (error) {
|
||
showNotification('Netzwerkfehler: ' + error.message, 'error');
|
||
}
|
||
}
|
||
|
||
// Logs herunterladen
|
||
async function downloadLogs() {
|
||
try {
|
||
const response = await fetch('/api/admin/logs/download');
|
||
|
||
if (response.ok) {
|
||
const blob = await response.blob();
|
||
const url = window.URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = 'myp-logs.zip';
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
window.URL.revokeObjectURL(url);
|
||
document.body.removeChild(a);
|
||
showNotification('Logs werden heruntergeladen', 'success');
|
||
} else {
|
||
showNotification('Fehler beim Herunterladen der Logs', 'error');
|
||
}
|
||
} catch (error) {
|
||
showNotification('Netzwerkfehler: ' + error.message, 'error');
|
||
}
|
||
}
|
||
|
||
// Wartung ausführen
|
||
async function runMaintenance() {
|
||
if (!confirm('Möchten Sie die Systemwartung ausführen?')) return;
|
||
|
||
try {
|
||
const response = await fetch('/api/admin/maintenance/run', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': getCsrfToken()
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result.success) {
|
||
showNotification('Wartung erfolgreich ausgeführt', 'success');
|
||
} else {
|
||
showNotification(result.error || 'Fehler bei der Wartung', 'error');
|
||
}
|
||
} catch (error) {
|
||
showNotification('Netzwerkfehler: ' + error.message, 'error');
|
||
}
|
||
}
|
||
|
||
// Einstellungen speichern
|
||
async function saveSettings() {
|
||
const backupInterval = document.getElementById('backup-interval').value;
|
||
const maxJobTime = document.getElementById('max-job-time').value;
|
||
|
||
try {
|
||
const response = await fetch('/api/admin/settings', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRFToken': getCsrfToken()
|
||
},
|
||
body: JSON.stringify({
|
||
backup_interval: parseInt(backupInterval),
|
||
max_job_time: parseInt(maxJobTime)
|
||
})
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result.success) {
|
||
showNotification('Einstellungen erfolgreich gespeichert', 'success');
|
||
} else {
|
||
showNotification(result.error || 'Fehler beim Speichern der Einstellungen', 'error');
|
||
}
|
||
} catch (error) {
|
||
showNotification('Netzwerkfehler: ' + error.message, 'error');
|
||
}
|
||
}
|
||
|
||
// System-Informationen laden
|
||
async function loadSystemInfo() {
|
||
try {
|
||
const [systemResponse, dbResponse] = await Promise.all([
|
||
fetch('/api/admin/system/status'),
|
||
fetch('/api/admin/database/status')
|
||
]);
|
||
|
||
const systemData = await systemResponse.json();
|
||
const dbData = await dbResponse.json();
|
||
|
||
if (systemResponse.ok) {
|
||
document.getElementById('server-status').textContent = systemData.status || 'Online';
|
||
document.getElementById('uptime').textContent = systemData.uptime || 'Unbekannt';
|
||
}
|
||
|
||
if (dbResponse.ok) {
|
||
document.getElementById('db-status').textContent = dbData.connected ? 'Verbunden' : 'Getrennt';
|
||
}
|
||
} catch (error) {
|
||
console.error('Fehler beim Laden der System-Informationen:', error);
|
||
document.getElementById('server-status').textContent = 'Fehler';
|
||
document.getElementById('db-status').textContent = 'Fehler';
|
||
document.getElementById('uptime').textContent = 'Fehler';
|
||
}
|
||
}
|
||
|
||
// Beim Laden der Seite
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
loadSystemInfo();
|
||
|
||
// Alle 30 Sekunden aktualisieren
|
||
setInterval(loadSystemInfo, 30000);
|
||
});
|
||
</script>
|
||
{% endblock %} |