308 lines
18 KiB
HTML
308 lines
18 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Admin-Bereich{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container mx-auto px-4 py-8">
|
|
<h1 class="text-3xl font-bold mb-8 text-gray-800 dark:text-white">Admin-Bereich</h1>
|
|
|
|
<!-- Tabs für verschiedene Bereiche -->
|
|
<div x-data="{ activeTab: 'users' }" class="mb-8">
|
|
<div class="flex space-x-2 mb-6 overflow-x-auto">
|
|
<button
|
|
@click="activeTab = 'users'"
|
|
:class="activeTab === 'users' ? 'bg-primary-600 text-white' : 'bg-white/10 text-gray-700 dark:text-gray-200'"
|
|
class="px-4 py-2 rounded-lg font-medium transition-all">
|
|
<i class="fas fa-users mr-2"></i> Benutzer
|
|
</button>
|
|
<button
|
|
@click="activeTab = 'nodes'"
|
|
:class="activeTab === 'nodes' ? 'bg-primary-600 text-white' : 'bg-white/10 text-gray-700 dark:text-gray-200'"
|
|
class="px-4 py-2 rounded-lg font-medium transition-all">
|
|
<i class="fas fa-project-diagram mr-2"></i> Mindmap-Knoten
|
|
</button>
|
|
<button
|
|
@click="activeTab = 'thoughts'"
|
|
:class="activeTab === 'thoughts' ? 'bg-primary-600 text-white' : 'bg-white/10 text-gray-700 dark:text-gray-200'"
|
|
class="px-4 py-2 rounded-lg font-medium transition-all">
|
|
<i class="fas fa-lightbulb mr-2"></i> Gedanken
|
|
</button>
|
|
<button
|
|
@click="activeTab = 'stats'"
|
|
:class="activeTab === 'stats' ? 'bg-primary-600 text-white' : 'bg-white/10 text-gray-700 dark:text-gray-200'"
|
|
class="px-4 py-2 rounded-lg font-medium transition-all">
|
|
<i class="fas fa-chart-bar mr-2"></i> Statistiken
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Benutzer-Tab -->
|
|
<div x-show="activeTab === 'users'" class="glass-morphism rounded-lg p-6">
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h2 class="text-xl font-bold text-gray-800 dark:text-white">Benutzerverwaltung</h2>
|
|
<button class="btn-outline">
|
|
<i class="fas fa-plus mr-2"></i> Neuer Benutzer
|
|
</button>
|
|
</div>
|
|
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead>
|
|
<tr class="text-left border-b border-gray-200 dark:border-gray-700">
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">ID</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Benutzername</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">E-Mail</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Admin</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Gedanken</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for user in users %}
|
|
<tr class="border-b border-gray-100 dark:border-gray-800 hover:bg-gray-50 dark:hover:bg-dark-700/30">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">{{ user.id }}</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">{{ user.username }}</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">{{ user.email }}</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">
|
|
{% if user.is_admin %}
|
|
<span class="bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300 px-2 py-1 rounded text-xs">Admin</span>
|
|
{% else %}
|
|
<span class="bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300 px-2 py-1 rounded text-xs">User</span>
|
|
{% endif %}
|
|
</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">{{ user.thoughts|length }}</td>
|
|
<td class="px-4 py-3 flex space-x-2">
|
|
<button class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300">
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<button class="text-red-600 hover:text-red-800 dark:text-red-400 dark:hover:text-red-300">
|
|
<i class="fas fa-trash-alt"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mindmap-Knoten-Tab -->
|
|
<div x-show="activeTab === 'nodes'" class="glass-morphism rounded-lg p-6">
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h2 class="text-xl font-bold text-gray-800 dark:text-white">Mindmap-Knoten Verwaltung</h2>
|
|
<button class="btn-outline">
|
|
<i class="fas fa-plus mr-2"></i> Neuer Knoten
|
|
</button>
|
|
</div>
|
|
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead>
|
|
<tr class="text-left border-b border-gray-200 dark:border-gray-700">
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">ID</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Name</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Elternknoten</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Gedanken</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for node in nodes %}
|
|
<tr class="border-b border-gray-100 dark:border-gray-800 hover:bg-gray-50 dark:hover:bg-dark-700/30">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">{{ node.id }}</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">{{ node.name }}</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">
|
|
{% if node.parent %}
|
|
{{ node.parent.name }}
|
|
{% else %}
|
|
<span class="text-gray-400 dark:text-gray-500">Wurzelknoten</span>
|
|
{% endif %}
|
|
</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">{{ node.thoughts|length }}</td>
|
|
<td class="px-4 py-3 flex space-x-2">
|
|
<button class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300">
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<button class="text-red-600 hover:text-red-800 dark:text-red-400 dark:hover:text-red-300">
|
|
<i class="fas fa-trash-alt"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Gedanken-Tab -->
|
|
<div x-show="activeTab === 'thoughts'" class="glass-morphism rounded-lg p-6">
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h2 class="text-xl font-bold text-gray-800 dark:text-white">Gedanken-Verwaltung</h2>
|
|
<div class="flex space-x-2">
|
|
<div class="relative">
|
|
<input type="text" placeholder="Suchen..." class="form-input pl-10 pr-4 py-2 rounded-lg bg-white/10 border border-gray-200/20 dark:border-gray-700/20 focus:outline-none focus:ring-2 focus:ring-primary-500 text-gray-700 dark:text-gray-200">
|
|
<div class="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">
|
|
<i class="fas fa-search"></i>
|
|
</div>
|
|
</div>
|
|
<button class="btn-outline">
|
|
<i class="fas fa-filter mr-2"></i> Filter
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead>
|
|
<tr class="text-left border-b border-gray-200 dark:border-gray-700">
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">ID</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Titel</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Autor</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Datum</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Bewertung</th>
|
|
<th class="px-4 py-2 text-gray-700 dark:text-gray-300">Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for thought in thoughts %}
|
|
<tr class="border-b border-gray-100 dark:border-gray-800 hover:bg-gray-50 dark:hover:bg-dark-700/30">
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">{{ thought.id }}</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300 font-medium">{{ thought.title }}</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">{{ thought.author.username }}</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">{{ thought.timestamp.strftime('%d.%m.%Y') }}</td>
|
|
<td class="px-4 py-3 text-gray-700 dark:text-gray-300">
|
|
<div class="flex items-center">
|
|
<span class="mr-2">{{ "%.1f"|format(thought.average_rating) }}</span>
|
|
<div class="flex">
|
|
{% for i in range(5) %}
|
|
{% if i < thought.average_rating|int %}
|
|
<i class="fas fa-star text-yellow-400"></i>
|
|
{% elif i < (thought.average_rating|int + 0.5) %}
|
|
<i class="fas fa-star-half-alt text-yellow-400"></i>
|
|
{% else %}
|
|
<i class="far fa-star text-yellow-400"></i>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td class="px-4 py-3 flex space-x-2">
|
|
<button class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300">
|
|
<i class="fas fa-eye"></i>
|
|
</button>
|
|
<button class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300">
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<button class="text-red-600 hover:text-red-800 dark:text-red-400 dark:hover:text-red-300">
|
|
<i class="fas fa-trash-alt"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Statistiken-Tab -->
|
|
<div x-show="activeTab === 'stats'" class="glass-morphism rounded-lg p-6">
|
|
<h2 class="text-xl font-bold mb-6 text-gray-800 dark:text-white">Systemstatistiken</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
|
<div class="glass-effect p-4 rounded-lg">
|
|
<div class="flex items-center mb-2">
|
|
<div class="bg-blue-500/20 p-3 rounded-lg mr-3">
|
|
<i class="fas fa-users text-blue-500"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="text-sm font-medium text-gray-600 dark:text-gray-300">Benutzer</h3>
|
|
<p class="text-2xl font-bold text-gray-800 dark:text-white">{{ users|length }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="glass-effect p-4 rounded-lg">
|
|
<div class="flex items-center mb-2">
|
|
<div class="bg-purple-500/20 p-3 rounded-lg mr-3">
|
|
<i class="fas fa-project-diagram text-purple-500"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="text-sm font-medium text-gray-600 dark:text-gray-300">Knoten</h3>
|
|
<p class="text-2xl font-bold text-gray-800 dark:text-white">{{ nodes|length }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="glass-effect p-4 rounded-lg">
|
|
<div class="flex items-center mb-2">
|
|
<div class="bg-green-500/20 p-3 rounded-lg mr-3">
|
|
<i class="fas fa-lightbulb text-green-500"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="text-sm font-medium text-gray-600 dark:text-gray-300">Gedanken</h3>
|
|
<p class="text-2xl font-bold text-gray-800 dark:text-white">{{ thoughts|length }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="glass-effect p-4 rounded-lg">
|
|
<div class="flex items-center mb-2">
|
|
<div class="bg-red-500/20 p-3 rounded-lg mr-3">
|
|
<i class="fas fa-comments text-red-500"></i>
|
|
</div>
|
|
<div>
|
|
<h3 class="text-sm font-medium text-gray-600 dark:text-gray-300">Kommentare</h3>
|
|
<p class="text-2xl font-bold text-gray-800 dark:text-white">
|
|
{% set comment_count = 0 %}
|
|
{% for thought in thoughts %}
|
|
{% set comment_count = comment_count + thought.comments|length %}
|
|
{% endfor %}
|
|
{{ comment_count }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div class="glass-effect p-4 rounded-lg">
|
|
<h3 class="text-lg font-bold mb-4 text-gray-800 dark:text-white">Aktive Benutzer</h3>
|
|
<div class="h-64 flex items-center justify-center bg-gray-100/20 dark:bg-dark-700/20 rounded">
|
|
<p class="text-gray-500 dark:text-gray-400">Hier würde ein Aktivitätsdiagramm angezeigt werden</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="glass-effect p-4 rounded-lg">
|
|
<h3 class="text-lg font-bold mb-4 text-gray-800 dark:text-white">Gedanken pro Kategorie</h3>
|
|
<div class="h-64 flex items-center justify-center bg-gray-100/20 dark:bg-dark-700/20 rounded">
|
|
<p class="text-gray-500 dark:text-gray-400">Hier würde eine Verteilungsstatistik angezeigt werden</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- System-Log (immer sichtbar) -->
|
|
<div class="mt-8">
|
|
<h2 class="text-xl font-bold mb-4 text-gray-800 dark:text-white">System-Log</h2>
|
|
<div class="glass-morphism rounded-lg p-4 h-32 overflow-y-auto font-mono text-sm text-gray-700 dark:text-gray-300">
|
|
<div class="text-green-500">[INFO] [{{ now.strftime('%Y-%m-%d %H:%M:%S') }}] System gestartet</div>
|
|
<div class="text-blue-500">[INFO] [{{ now.strftime('%Y-%m-%d %H:%M:%S') }}] Admin-Bereich aufgerufen von {{ current_user.username }}</div>
|
|
<div class="text-yellow-500">[WARN] [{{ now.strftime('%Y-%m-%d %H:%M:%S') }}] Hohe Serverauslastung erkannt</div>
|
|
<div class="text-gray-500">[INFO] [{{ now.strftime('%Y-%m-%d %H:%M:%S') }}] Backup erfolgreich erstellt</div>
|
|
<div class="text-red-500">[ERROR] [{{ now.strftime('%Y-%m-%d %H:%M:%S') }}] API-Zugriffsfehler (Timeout) bei externer Anfrage</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script>
|
|
// Admin-spezifische JavaScript-Funktionen
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
console.log('Admin-Bereich geladen');
|
|
|
|
// Beispiel für AJAX-Ladeverhalten von Daten
|
|
// Kann später durch echte API-Calls ersetzt werden
|
|
});
|
|
</script>
|
|
{% endblock %} |