AstraOS Ver. 1.17:
- Comments entfernt
This commit is contained in:
parent
fd707cd0b7
commit
f4bfa163a7
|
|
@ -11,7 +11,6 @@
|
|||
</header>
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<!-- Verification Form -->
|
||||
<div class="bg-black/40 p-6 rounded-xl backdrop-blur border {% if maintenance_active %}border-yellow-500/30{% else %}border-purple-500/20{% endif %}">
|
||||
<h3 class="text-2xl font-semibold mb-4">Neue Überprüfung</h3>
|
||||
<form method="POST" class="space-y-4">
|
||||
|
|
@ -61,7 +60,6 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- User Search -->
|
||||
<div class="bg-black/40 p-6 rounded-xl backdrop-blur border {% if maintenance_active %}border-yellow-500/30{% else %}border-purple-500/20{% endif %}">
|
||||
<h3 class="text-2xl font-semibold mb-4">Benutzer suchen</h3>
|
||||
<form method="GET" class="flex gap-2 mb-4">
|
||||
|
|
@ -97,9 +95,8 @@
|
|||
function copyToClipboard(elementId) {
|
||||
const input = document.getElementById(elementId);
|
||||
input.select();
|
||||
input.setSelectionRange(0, 99999); // For mobile devices
|
||||
input.setSelectionRange(0, 99999);
|
||||
document.execCommand('copy');
|
||||
// Optional: Visuelles Feedback geben
|
||||
const originalButtonText = event.target.innerText;
|
||||
event.target.innerText = 'Kopiert!';
|
||||
setTimeout(() => {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- HEADER -->
|
||||
<header class="flex justify-between items-center mb-6">
|
||||
<div>
|
||||
<a href="{{ url_for('discord_bots') }}" class="text-sm {% if maintenance_active %}text-yellow-400 hover:text-yellow-300{% else %}text-purple-400 hover:text-purple-300{% endif %}">‹ Zurück zur Übersicht</a>
|
||||
|
|
@ -50,7 +49,6 @@
|
|||
</div>
|
||||
</header>
|
||||
|
||||
<!-- CONSOLE -->
|
||||
<div id="console-output">
|
||||
<div class="log-line log-system">Initialisiere Konsolenverbindung...</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
box-shadow: 0 0 20px rgba(192,132,252,0.3);
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
/* Schriftgröße für Systemstatus-Text im Wartungsmodus noch kleiner und mittig */
|
||||
#system-status-text.small {
|
||||
font-size: 2rem;
|
||||
text-align: center;
|
||||
|
|
@ -45,7 +44,6 @@
|
|||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
<!-- Aktive Benutzer -->
|
||||
<div class="glow-card opacity-0 translate-y-8 bg-black/40 rounded-xl p-6 backdrop-blur
|
||||
{% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<h3 class="text-xl font-semibold mb-2 {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Aktive Benutzer</h3>
|
||||
|
|
@ -60,14 +58,12 @@
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Server-Auslastung -->
|
||||
<div id="server-load-card" class="glow-card opacity-0 translate-y-8 bg-black/40 border border-red-500/40 rounded-xl p-6 backdrop-blur">
|
||||
<h3 class="text-xl font-semibold mb-2 {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Server-Auslastung</h3>
|
||||
<p class="text-4xl font-bold" id="server-load">{{ stats.server_load.percent }}%</p>
|
||||
<p class="text-red-400 text-sm mt-1" id="server-load-status">{{ stats.server_load.status }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Offene Tickets -->
|
||||
<div class="glow-card opacity-0 translate-y-8 bg-black/40 rounded-xl p-6 backdrop-blur
|
||||
{% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<h3 class="text-xl font-semibold mb-2 {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Offene Tickets</h3>
|
||||
|
|
@ -75,7 +71,6 @@
|
|||
<p class="text-gray-400 text-sm mt-1">Keine offenen Anfragen</p>
|
||||
</div>
|
||||
|
||||
<!-- Systemstatus -->
|
||||
<div id="system-status-card" class="glow-card opacity-0 translate-y-8 bg-black/40 border border-green-500/40 rounded-xl p-6 backdrop-blur">
|
||||
<h3 class="text-xl font-semibold mb-2 {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Systemstatus</h3>
|
||||
{% set status = stats.system_status.status %}
|
||||
|
|
@ -97,7 +92,6 @@
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Geplante Wartung -->
|
||||
<div class="glow-card opacity-0 translate-y-8 bg-black/40 rounded-xl p-6 backdrop-blur
|
||||
{% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<h3 class="text-xl font-semibold mb-2 {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Geplante Wartung</h3>
|
||||
|
|
@ -114,7 +108,6 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Letzte Benutzererstellung -->
|
||||
<div class="glow-card opacity-0 translate-y-8 bg-black/40 rounded-xl p-6 backdrop-blur
|
||||
{% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<h3 class="text-xl font-semibold mb-2 {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Letzte Benutzererstellung</h3>
|
||||
|
|
@ -126,15 +119,11 @@
|
|||
<script>
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
// Lade-Timeline
|
||||
setTimeout(() => {
|
||||
// Timeline für Header + Cards
|
||||
const tl = gsap.timeline({ defaults: { duration: 0.4, ease: "power3.out" } });
|
||||
|
||||
// Header
|
||||
tl.to("header", { opacity: 1, y: 0 });
|
||||
|
||||
// Cards schnell einblenden
|
||||
tl.to(".glow-card", { opacity: 1, y: 0, stagger: 0.08 });
|
||||
|
||||
// Header Parallax
|
||||
|
|
@ -149,7 +138,6 @@ setTimeout(() => {
|
|||
});
|
||||
}, 800);
|
||||
|
||||
// Hover Glow
|
||||
document.querySelectorAll(".glow-card").forEach(card => {
|
||||
card.addEventListener("mouseenter", () => {
|
||||
gsap.to(card, { boxShadow: "0 0 30px rgba(192,132,252,0.4)", duration: 0.2 });
|
||||
|
|
@ -159,7 +147,6 @@ document.querySelectorAll(".glow-card").forEach(card => {
|
|||
});
|
||||
});
|
||||
|
||||
// Server-Auslastung alle 5 Sekunden aktualisieren
|
||||
function updateServerLoad() {
|
||||
fetch('/api/server_load')
|
||||
.then(res => res.json())
|
||||
|
|
@ -194,7 +181,6 @@ function updateServerLoad() {
|
|||
setInterval(updateServerLoad, 5000);
|
||||
updateServerLoad();
|
||||
|
||||
// Systemstatus dynamisch Randfarbe anpassen
|
||||
function updateSystemStatusCard() {
|
||||
const card = document.getElementById('system-status-card');
|
||||
const statusText = document.getElementById('system-status-text');
|
||||
|
|
@ -211,8 +197,7 @@ function updateSystemStatusCard() {
|
|||
card.classList.add('border-red-500/40');
|
||||
}
|
||||
}
|
||||
setTimeout(updateSystemStatusCard, 100); // initial nach Render
|
||||
// Optional: falls Systemstatus dynamisch per AJAX kommt, hier regelmäßig prüfen
|
||||
setTimeout(updateSystemStatusCard, 100);
|
||||
setInterval(updateSystemStatusCard, 2000);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
{% block head %}
|
||||
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
|
||||
<style>
|
||||
/* Toggle Switch */
|
||||
.switch { position: relative; display: inline-block; width: 50px; height: 28px; }
|
||||
.switch input { opacity: 0; width: 0; height: 0; }
|
||||
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #4a5568; transition: .4s; border-radius: 28px; }
|
||||
|
|
@ -17,7 +16,6 @@
|
|||
|
||||
{% block content %}
|
||||
<div x-data="{ showUploadModal: false, showDeleteModal: false, botToDelete: null }">
|
||||
<!-- HEADER -->
|
||||
<header class="flex justify-between items-center mb-10">
|
||||
<h2 class="text-4xl font-bold tracking-wide {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Discord Bot Management</h2>
|
||||
<button @click="showUploadModal = true" class="font-bold py-2 px-4 rounded-lg transition text-white
|
||||
|
|
@ -26,7 +24,6 @@
|
|||
</button>
|
||||
</header>
|
||||
|
||||
<!-- BOT LIST -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{% for bot in bots %}
|
||||
<div class="bg-black/40 rounded-xl backdrop-blur-lg p-6 flex flex-col justify-between
|
||||
|
|
@ -62,7 +59,6 @@
|
|||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- UPLOAD BOT MODAL -->
|
||||
<div x-show="showUploadModal" @keydown.escape.window="showUploadModal = false" class="fixed inset-0 bg-black/70 backdrop-blur-sm flex items-center justify-center z-50" style="display: none;">
|
||||
<div @click.away="showUploadModal = false" class="bg-gray-900 rounded-xl shadow-2xl p-8 w-full max-w-md
|
||||
{% if maintenance_active %}border border-yellow-500/50{% else %}border border-purple-500/50{% endif %}">
|
||||
|
|
@ -86,7 +82,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DELETE CONFIRMATION MODAL -->
|
||||
<div x-show="showDeleteModal" @keydown.escape.window="showDeleteModal = false" class="fixed inset-0 bg-black/70 backdrop-blur-sm flex items-center justify-center z-50" style="display: none;">
|
||||
<div @click.away="showDeleteModal = false" class="bg-gray-900 border border-red-500/50 rounded-xl shadow-2xl p-8 w-full max-w-md">
|
||||
<h3 class="text-2xl font-bold text-red-400 mb-4">Bot löschen</h3>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
{% block head %}
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<style>
|
||||
/* Toggle Switch Styles */
|
||||
.switch { position: relative; display: inline-block; width: 50px; height: 28px; }
|
||||
.switch input { opacity: 0; width: 0; height: 0; }
|
||||
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #4a5568; transition: .4s; border-radius: 28px; }
|
||||
|
|
@ -17,12 +16,10 @@
|
|||
|
||||
{% block content %}
|
||||
<div x-data="{ isCheater: false }" class="space-y-10">
|
||||
<!-- HEADER -->
|
||||
<header class="flex justify-between items-center">
|
||||
<h2 class="text-4xl font-bold tracking-wide {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">IP Analyzer</h2>
|
||||
</header>
|
||||
|
||||
<!-- INPUT FORM -->
|
||||
<div class="bg-black/40 rounded-xl backdrop-blur-lg p-8 {% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<form action="{{ url_for('ip_analyzer') }}" method="POST" class="space-y-6">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
|
|
@ -58,7 +55,6 @@
|
|||
</form>
|
||||
</div>
|
||||
|
||||
<!-- RESULTS -->
|
||||
{% if error %}
|
||||
<div class="bg-red-500/20 border border-red-500/30 text-red-300 p-4 rounded-lg">{{ error }}</div>
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -5,29 +5,22 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AstraOS — Login</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='media/AstraOS_Logo.ico') }}" type="image/x-icon">
|
||||
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/TextPlugin.min.js"></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: radial-gradient(circle at top, #1b1b26, #0a0a0f 70%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="text-white">
|
||||
|
||||
<div id="startup" class="fixed inset-0 bg-black flex flex-col items-center justify-center z-50">
|
||||
|
||||
<div id="star" class="w-16 h-16 relative">
|
||||
<div class="absolute inset-0 rounded-full blur-2xl opacity-70"
|
||||
style="background: rgba(192, 132, 252, 0.7)"></div>
|
||||
|
||||
<svg class="relative z-10" viewBox="0 0 100 100">
|
||||
|
||||
<path
|
||||
d="M50 5
|
||||
L63 40
|
||||
|
|
@ -40,7 +33,6 @@
|
|||
Z"
|
||||
fill="#c084fc"
|
||||
/>
|
||||
|
||||
<path
|
||||
d="M50 28
|
||||
L58 45
|
||||
|
|
@ -54,20 +46,14 @@
|
|||
fill="#ffffff"
|
||||
opacity="0.9"
|
||||
/>
|
||||
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<p class="mt-4 text-xl tracking-wide opacity-80">AstraOS</p>
|
||||
</div>
|
||||
|
||||
<div id="loginContent" class="min-h-screen flex items-center justify-center px-4">
|
||||
|
||||
<div id="loginBox" class="w-full max-w-md bg-black/40 border border-purple-500/20 rounded-2xl p-8 backdrop-blur-lg shadow-xl opacity-0">
|
||||
|
||||
<h1 id="loginTitle" class="text-3xl font-bold text-center mb-6 tracking-wider text-purple-300">
|
||||
</h1>
|
||||
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
|
|
@ -77,7 +63,6 @@
|
|||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<form id="loginForm" action="/login" method="POST" class="flex flex-col gap-5 opacity-0">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div>
|
||||
|
|
@ -86,7 +71,6 @@
|
|||
class="mt-1 w-full px-4 py-2 rounded-lg bg-gray-800/60 text-white
|
||||
focus:outline-none focus:ring-2 focus:ring-purple-600">
|
||||
</div>
|
||||
|
||||
<div x-data="{ showPassword: false }">
|
||||
<label class="text-gray-300 text-sm">Passwort</label>
|
||||
<div class="relative">
|
||||
|
|
@ -104,31 +88,24 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit"
|
||||
class="mt-2 bg-purple-600 hover:bg-purple-700 text-white py-2 rounded-lg
|
||||
font-semibold transition">
|
||||
Login
|
||||
</button>
|
||||
|
||||
<div class="flex items-center my-1">
|
||||
<div class="flex-grow border-t border-gray-600"></div>
|
||||
<span class="flex-shrink mx-4 text-gray-400 text-sm">oder</span>
|
||||
<div class="flex-grow border-t border-gray-600"></div>
|
||||
</div>
|
||||
|
||||
<a href="{{ url_for('login_discord') }}"
|
||||
class="flex items-center justify-center bg-[#5865F2] hover:bg-[#4752C4] text-white py-2 rounded-lg font-semibold transition">
|
||||
<svg class="w-6 h-6 mr-2" aria-hidden="true" role="img" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M20.317 4.36981C18.2767 3.20426 16.1224 2.27659 13.8468 1.61774C13.679 1.57584 13.5041 1.68116 13.4343 1.84475C12.8151 3.24952 12.3413 4.96228 12.0009 6.53635C10.6866 6.37181 9.36521 6.37181 8.01525 6.53635C7.67488 4.96228 7.20103 3.24952 6.58181 1.84475C6.51205 1.68116 6.33712 1.57584 6.16931 1.61774C3.89372 2.27659 1.73942 3.20426 -0.300884 4.36981C-0.535332 4.49339 -0.620213 4.7833 -0.499842 5.01329C0.0107496 5.92333 0.406433 6.97593 0.683583 8.0343C0.715011 8.14443 0.801901 8.23132 0.912038 8.26275C2.43731 8.73725 3.93953 9.1111 5.42371 9.34818C5.60563 9.3789 5.75754 9.24538 5.71964 9.06346C5.54471 8.25822 5.3928 7.43716 5.24089 6.62322C5.22194 6.52066 5.28274 6.4181 5.3853 6.39233C9.41501 5.69637 14.5858 5.69637 18.6155 6.39233C18.7181 6.4181 18.7789 6.52066 18.7599 6.62322C18.608 7.43716 18.4561 8.25822 18.2812 9.06346C18.2433 9.24538 18.3952 9.3789 18.5771 9.34818C20.0613 9.1111 21.5635 8.73725 23.0888 8.26275C23.1989 8.23132 23.2858 8.14443 23.3172 8.0343C23.5944 6.97593 23.9901 5.92333 24.4998 5.01329C24.6202 4.7833 24.5353 4.49339 24.3009 4.36981L20.317 4.36981Z"></path><path fill="currentColor" d="M12.0009 16.4373C14.2131 16.4373 16.0013 14.834 16.0013 12.8337C16.0013 10.8334 14.2202 9.23004 12.0009 9.23004C9.78161 9.23004 8.00049 10.8334 8.00049 12.8337C8.00049 14.834 9.78161 16.4373 12.0009 16.4373ZM18.0016 16.4373C20.2138 16.4373 22.002 14.834 22.002 12.8337C22.002 10.8334 20.2209 9.23004 18.0016 9.23004C15.7823 9.23004 14.0012 10.8334 14.0012 12.8337C14.0012 14.834 15.7823 16.4373 18.0016 16.4373Z"></path></svg>
|
||||
Mit Discord anmelden
|
||||
</a>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
gsap.to("#star", {
|
||||
rotation: 360,
|
||||
|
|
@ -136,7 +113,6 @@
|
|||
ease: "power1.inOut",
|
||||
repeat: -1
|
||||
});
|
||||
|
||||
gsap.to("#star", {
|
||||
scale: 1.22,
|
||||
duration: 1,
|
||||
|
|
@ -144,20 +120,15 @@
|
|||
repeat: -1,
|
||||
ease: "power1.inOut"
|
||||
});
|
||||
|
||||
gsap.registerPlugin(TextPlugin);
|
||||
|
||||
{% if not get_flashed_messages() %}
|
||||
// Nur Animation abspielen, wenn keine Nachrichten vorhanden sind (erster Besuch)
|
||||
setTimeout(() => {
|
||||
gsap.to("#startup", {
|
||||
opacity: 0,
|
||||
duration: 0.5,
|
||||
onComplete: () => {
|
||||
document.getElementById("startup").style.display = "none";
|
||||
|
||||
const tl = gsap.timeline();
|
||||
|
||||
tl.fromTo("#loginBox",
|
||||
{ opacity: 0, scale: 0.8 },
|
||||
{
|
||||
|
|
@ -167,13 +138,11 @@
|
|||
ease: "power2.out"
|
||||
}
|
||||
);
|
||||
|
||||
tl.to("#loginTitle", {
|
||||
duration: 0.8,
|
||||
text: "AstraOS Login",
|
||||
ease: "none"
|
||||
}, "-=0.2");
|
||||
|
||||
tl.to("#loginForm", {
|
||||
opacity: 1,
|
||||
duration: 0.4
|
||||
|
|
@ -182,13 +151,11 @@
|
|||
});
|
||||
}, 800);
|
||||
{% else %}
|
||||
// Wenn Nachrichten vorhanden sind, Animation überspringen
|
||||
document.getElementById("startup").style.display = "none";
|
||||
document.getElementById("loginBox").style.opacity = 1;
|
||||
document.getElementById("loginForm").style.opacity = 1;
|
||||
document.getElementById("loginTitle").textContent = "AstraOS Login";
|
||||
{% endif %}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PAGINATION -->
|
||||
{% if total_pages > 1 %}
|
||||
<nav class="mt-6 flex items-center justify-between">
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
</style>
|
||||
</head>
|
||||
<body class="text-white">
|
||||
|
||||
<div class="min-h-screen flex flex-col items-center justify-center text-center px-4">
|
||||
<div id="star" class="w-16 h-16 relative mb-6">
|
||||
<div class="absolute inset-0 rounded-full blur-2xl opacity-70" style="background: rgba(243, 156, 18, 0.7)"></div>
|
||||
|
|
@ -22,7 +21,6 @@
|
|||
<path stroke-linecap="round" stroke-linejoin="round" d="M11.42 15.17L17.25 21A2.652 2.652 0 0021 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.73-.664 1.203-.832l3.528-1.604a2.652 2.652 0 10-3.528-3.528l-1.604 3.528c-.168.473-.448.886-.832 1.203l-3.03 2.496m0 0l-5.877-5.877A2.652 2.652 0 003 9.02l5.877 5.877m0 0l-2.496 3.03c-.317.384-.73.664-1.203.832L3 21a2.652 2.652 0 003.528 3.528l1.604-3.528c.168-.473.448-.886.832-1.203l3.03-2.496m0 0l5.877 5.877a2.652 2.652 0 003.528-3.528l-5.877-5.877m0 0L9.02 3a2.652 2.652 0 00-3.528 3.528L9.02 9.02" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h1 class="text-4xl md:text-5xl font-bold text-yellow-400 tracking-wide mb-4">Wartungsarbeiten</h1>
|
||||
<p class="text-lg text-gray-300 max-w-2xl mb-2">
|
||||
{{ maint_info.status if maint_info and maint_info.status else 'Wir führen zurzeit planmäßige Wartungsarbeiten durch, um unsere Dienste zu verbessern.' }}
|
||||
|
|
@ -30,7 +28,6 @@
|
|||
<p class="text-lg text-gray-300 max-w-2xl">
|
||||
Wir sind bald wieder für Sie da.
|
||||
</p>
|
||||
|
||||
{% if maint_info and maint_info.time %}
|
||||
<div class="mt-8 bg-black/30 border border-yellow-500/30 rounded-lg p-4">
|
||||
<p class="text-gray-400">Voraussichtliches Ende:</p>
|
||||
|
|
@ -38,14 +35,12 @@
|
|||
<p class="text-xl font-semibold text-yellow-300">{{ end_time.strftime('%d. %B %Y, %H:%M Uhr') }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="absolute bottom-10">
|
||||
<a href="{{ url_for('maintenance_login') }}" class="px-5 py-2 border border-yellow-500/40 text-yellow-300 rounded-lg hover:bg-yellow-500/10 transition-colors text-sm">
|
||||
Wartungsarbeiten Login
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
gsap.to("#star", {
|
||||
rotation: 360,
|
||||
|
|
@ -54,6 +49,5 @@
|
|||
repeat: -1
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -5,21 +5,17 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AstraOS — Maintenance Login</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='media/AstraOS_Logo.ico') }}" type="image/x-icon">
|
||||
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/TextPlugin.min.js"></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: radial-gradient(circle at top, #2c2315, #0a0a0f 70%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="text-white">
|
||||
|
||||
<div id="startup" class="fixed inset-0 bg-black flex flex-col items-center justify-center z-50">
|
||||
<div id="star" class="w-16 h-16 relative">
|
||||
<div class="absolute inset-0 rounded-full blur-2xl opacity-70" style="background: rgba(243, 156, 18, 0.7)"></div>
|
||||
|
|
@ -29,20 +25,14 @@
|
|||
</div>
|
||||
<p class="mt-4 text-xl tracking-wide opacity-80">AstraOS Maintenance</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="loginContent" class="min-h-screen flex items-center justify-center px-4">
|
||||
|
||||
<div id="loginBox" class="w-full max-w-md bg-black/40 border border-yellow-500/20 rounded-2xl p-8 backdrop-blur-lg shadow-xl opacity-0">
|
||||
|
||||
<div class="flex justify-center items-center gap-4 mb-6">
|
||||
<svg class="w-8 h-8 text-yellow-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" />
|
||||
</svg>
|
||||
<h1 id="loginTitle" class="text-3xl font-bold text-center tracking-wider text-yellow-300"></h1>
|
||||
</div>
|
||||
|
||||
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
|
|
@ -52,7 +42,6 @@
|
|||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<form id="loginForm" action="{{ url_for('maintenance_login') }}" method="POST" class="flex flex-col gap-5 opacity-0">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
<div>
|
||||
|
|
@ -61,7 +50,6 @@
|
|||
class="mt-1 w-full px-4 py-2 rounded-lg bg-gray-800/60 text-white
|
||||
focus:outline-none focus:ring-2 focus:ring-yellow-500">
|
||||
</div>
|
||||
|
||||
<div x-data="{ showPassword: false }">
|
||||
<label class="text-gray-300 text-sm">Passwort</label>
|
||||
<div class="relative">
|
||||
|
|
@ -79,19 +67,14 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit"
|
||||
class="mt-2 bg-yellow-600 hover:bg-yellow-700 text-white py-2 rounded-lg
|
||||
font-semibold transition">
|
||||
Bypass Login
|
||||
</button>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
gsap.to("#star", {
|
||||
rotation: 360,
|
||||
|
|
@ -99,20 +82,15 @@
|
|||
ease: "none",
|
||||
repeat: -1
|
||||
});
|
||||
|
||||
gsap.registerPlugin(TextPlugin);
|
||||
|
||||
{% if not get_flashed_messages() %}
|
||||
// Nur Animation abspielen, wenn keine Nachrichten vorhanden sind
|
||||
setTimeout(() => {
|
||||
gsap.to("#startup", {
|
||||
opacity: 0,
|
||||
duration: 0.5,
|
||||
onComplete: () => {
|
||||
document.getElementById("startup").style.display = "none";
|
||||
|
||||
const tl = gsap.timeline();
|
||||
|
||||
tl.fromTo("#loginBox",
|
||||
{ opacity: 0, scale: 0.8 },
|
||||
{
|
||||
|
|
@ -122,13 +100,11 @@
|
|||
ease: "power2.out"
|
||||
}
|
||||
);
|
||||
|
||||
tl.to("#loginTitle", {
|
||||
duration: 0.8,
|
||||
text: "Maintenance Login",
|
||||
ease: "none"
|
||||
}, "-=0.2");
|
||||
|
||||
tl.to("#loginForm", {
|
||||
opacity: 1,
|
||||
duration: 0.4
|
||||
|
|
@ -137,7 +113,6 @@
|
|||
});
|
||||
}, 800);
|
||||
{% else %}
|
||||
// Wenn Nachrichten vorhanden sind, Animation überspringen
|
||||
document.getElementById("startup").style.display = "none";
|
||||
document.getElementById("loginBox").style.opacity = 1;
|
||||
document.getElementById("loginForm").style.opacity = 1;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
{% block head %}
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<style>
|
||||
/* Toggle Switch Styles */
|
||||
.switch { position: relative; display: inline-block; width: 60px; height: 34px; }
|
||||
.switch input { opacity: 0; width: 0; height: 0; }
|
||||
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #4a5568; transition: .4s; border-radius: 34px; }
|
||||
|
|
@ -17,18 +16,15 @@
|
|||
|
||||
{% block content %}
|
||||
<main class="flex-1 p-8 space-y-10" id="mainContent">
|
||||
<!-- HEADER -->
|
||||
<header class="flex justify-between items-center mb-10">
|
||||
<h2 class="text-4xl font-bold tracking-wide {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Maintenance Management</h2>
|
||||
</header>
|
||||
|
||||
<!-- SETTINGS FORM -->
|
||||
<div class="bg-black/40 rounded-xl backdrop-blur-lg p-8
|
||||
{% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<form action="{{ url_for('update_maintenance') }}" method="POST" class="space-y-8">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
||||
|
||||
<!-- Maintenance Mode Toggle -->
|
||||
<div class="flex items-center justify-between p-4 bg-gray-900/50 rounded-lg">
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Wartungsmodus</h3>
|
||||
|
|
@ -40,7 +36,6 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Discord Bots Wartungsmodus Toggle -->
|
||||
<div class="flex items-center justify-between p-4 bg-gray-900/50 rounded-lg">
|
||||
<div>
|
||||
<h3 class="text-xl font-semibold {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Discord Bots Wartungsmodus</h3>
|
||||
|
|
@ -52,7 +47,6 @@
|
|||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Maintenance Details -->
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<label for="status_message" class="block text-sm font-medium text-gray-300">Wartungsnachricht</label>
|
||||
|
|
@ -79,7 +73,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<div class="flex justify-end pt-4">
|
||||
<button type="submit" class="px-6 py-2 text-white font-semibold rounded-lg transition
|
||||
{% if maintenance_active %}bg-yellow-600 hover:bg-yellow-700{% else %}bg-purple-600 hover:bg-purple-700{% endif %}">
|
||||
|
|
@ -89,4 +82,4 @@
|
|||
</form>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
{% block content %}
|
||||
<div x-data="{ showAddRoleModal: false, showDeleteModal: false, roleToDelete: null, roleToEdit: null }">
|
||||
<!-- HEADER -->
|
||||
<header class="flex justify-between items-center mb-10">
|
||||
<h2 class="text-4xl font-bold tracking-wide {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Rollen verwalten</h2>
|
||||
<button @click="showAddRoleModal = true" class="font-bold py-2 px-4 rounded-lg transition text-white
|
||||
|
|
@ -15,7 +14,6 @@
|
|||
+ Neue Rolle hinzufügen
|
||||
</button>
|
||||
</header>
|
||||
<!-- ROLE TABLE -->
|
||||
<div class="bg-black/40 rounded-xl backdrop-blur-lg overflow-hidden
|
||||
{% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<table class="min-w-full divide-y {% if maintenance_active %}divide-yellow-500/30{% else %}divide-purple-500/20{% endif %}">
|
||||
|
|
@ -55,7 +53,6 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<!-- ADD/EDIT ROLE MODAL -->
|
||||
<div x-show="showAddRoleModal" @keydown.escape.window="showAddRoleModal = false" class="fixed inset-0 bg-black/70 backdrop-blur-sm flex items-center justify-center z-50" style="display: none;">
|
||||
<div @click.away="showAddRoleModal = false" class="bg-gray-900 rounded-xl shadow-2xl p-8 w-full max-w-lg
|
||||
{% if maintenance_active %}border border-yellow-500/50{% else %}border border-purple-500/50{% endif %}">
|
||||
|
|
@ -94,7 +91,6 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- DELETE CONFIRMATION MODAL -->
|
||||
<div x-show="showDeleteModal" @keydown.escape.window="showDeleteModal = false" class="fixed inset-0 bg-black/70 backdrop-blur-sm flex items-center justify-center z-50" style="display: none;">
|
||||
<div @click.away="showDeleteModal = false" class="bg-gray-900 border border-red-500/50 rounded-xl shadow-2xl p-8 w-full max-w-md">
|
||||
<h3 class="text-2xl font-bold text-red-400 mb-4">Rolle löschen</h3>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
<h2 class="text-4xl font-bold tracking-wide {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Einstellungen</h2>
|
||||
</header>
|
||||
|
||||
<!-- ACCOUNT-INFORMATIONEN -->
|
||||
<div class="bg-black/40 rounded-xl backdrop-blur-lg p-8 {% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<h3 class="text-2xl font-semibold mb-6 {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Account-Informationen</h3>
|
||||
<div class="space-y-4">
|
||||
|
|
@ -23,7 +22,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PASSWORT ÄNDERN -->
|
||||
<div class="bg-black/40 rounded-xl backdrop-blur-lg p-8 {% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<h3 class="text-2xl font-semibold mb-6 {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Passwort ändern</h3>
|
||||
<form action="{{ url_for('update_password') }}" method="POST" class="space-y-4 max-w-md">
|
||||
|
|
@ -48,7 +46,6 @@
|
|||
</form>
|
||||
</div>
|
||||
|
||||
<!-- DISCORD-VERKNÜPFUNG -->
|
||||
<div class="bg-black/40 rounded-xl backdrop-blur-lg p-8 {% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<h3 class="text-2xl font-semibold mb-6 {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">Discord-Verknüpfung</h3>
|
||||
{% if user.discord_id %}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,11 @@
|
|||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
||||
<style>
|
||||
/* Custom scrollbar */
|
||||
::-webkit-scrollbar { width: 8px; height: 8px; }
|
||||
::-webkit-scrollbar-track { background: #0a0a0f; }
|
||||
::-webkit-scrollbar-thumb { background-color: #4b5563; border-radius: 4px; }
|
||||
::-webkit-scrollbar-thumb:hover { background-color: #6b7280; }
|
||||
|
||||
/* Hintergrund / global (vereinheitlicht mit Referenz) */
|
||||
body {
|
||||
background: radial-gradient(circle at top, #1b1b26, #0a0a0f 70%);
|
||||
overflow-x: hidden;
|
||||
|
|
@ -40,18 +38,18 @@
|
|||
justify-content: center;
|
||||
transition: background-color 0.2s, border-color 0.2s;
|
||||
margin-right: 0.75rem;
|
||||
border-color: #8b5cf6; /* purple-500 */
|
||||
border-color: #8b5cf6;
|
||||
}
|
||||
.custom-checkbox-label.maintenance .custom-checkbox-box {
|
||||
border-color: #f59e0b; /* yellow-600 */
|
||||
border-color: #f59e0b;
|
||||
}
|
||||
input[type="checkbox"]:checked + .custom-checkbox-box {
|
||||
background-color: #8b5cf6; /* purple-500 */
|
||||
border-color: #8b5cf6; /* purple-500 */
|
||||
background-color: #8b5cf6;
|
||||
border-color: #8b5cf6;
|
||||
}
|
||||
.custom-checkbox-label.maintenance input[type="checkbox"]:checked + .custom-checkbox-box {
|
||||
background-color: #f59e0b; /* yellow-600 */
|
||||
border-color: #f59e0b; /* yellow-600 */
|
||||
background-color: #f59e0b;
|
||||
border-color: #f59e0b;
|
||||
}
|
||||
input[type="checkbox"]:checked + .custom-checkbox-box svg {
|
||||
display: block;
|
||||
|
|
@ -122,7 +120,6 @@
|
|||
0% { transform: translateY(100vh) scale(1); }
|
||||
100% { transform: translateY(-10vh) scale(1.5); }
|
||||
}
|
||||
/* Benachrichtigungen: normale (schmale) Breite + Slide/Fade */
|
||||
.toast-container {
|
||||
position: fixed;
|
||||
top: 1.25rem;
|
||||
|
|
@ -135,30 +132,25 @@
|
|||
pointer-events: none;
|
||||
max-width: calc(100% - 3rem);
|
||||
}
|
||||
/* Einzelne Toasts: normale Desktop-Breite (~28rem), mobil volle Breite */
|
||||
.toast {
|
||||
pointer-events: auto;
|
||||
width: 100%;
|
||||
max-width: 28rem; /* <- hier die "normale" Breite einstellen */
|
||||
max-width: 28rem;
|
||||
box-sizing: border-box;
|
||||
word-break: break-word;
|
||||
background: rgba(8,10,12,0.95);
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid rgba(255,255,255,0.04);
|
||||
padding: 0.75rem 1rem;
|
||||
/* Slide + Fade (zusätzlich zu Alpine/Tailwind x-transition) */
|
||||
transition: transform 0.32s cubic-bezier(.2,.9,.2,1), opacity 0.32s ease;
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
/* Wenn ein Toast noch im "enter-start" Zustand ist (Tailwind-Klassen verwenden translate-x-8 / opacity-0),
|
||||
sorgt die transition-Einstellung oben für sanftes Rein-/Rausrutschen. */
|
||||
</style>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
<body class="text-white flex flex-col min-h-screen font-sans antialiased">
|
||||
<!-- Loading Screen überall (vereinheitlicht) -->
|
||||
<div id="startup">
|
||||
<div id="star">
|
||||
<div class="blur"></div>
|
||||
|
|
@ -170,11 +162,9 @@
|
|||
<p>AstraOS</p>
|
||||
</div>
|
||||
|
||||
<!-- Animierter Hintergrund überall -->
|
||||
<div class="animated-bg"></div>
|
||||
<div class="flex h-screen"> <!-- overflow-hidden entfernt, damit die Seite scrollen kann -->
|
||||
<div class="flex h-screen">
|
||||
|
||||
<!-- Sidebar -->
|
||||
<aside class="fixed top-0 left-0 w-64 h-screen bg-black/40 border-r p-6 backdrop-blur-lg flex flex-col flex-shrink-0 z-20
|
||||
{% if maintenance_active %}border-yellow-500/30{% else %}border-purple-500/20{% endif %}">
|
||||
<h1 class="text-3xl font-bold mb-8 tracking-wide
|
||||
|
|
@ -307,7 +297,6 @@
|
|||
</aside>
|
||||
|
||||
<div class="ml-64 flex-1 flex flex-col min-h-screen">
|
||||
<!-- FLASH MESSAGES (zentral, breit, non-overlap) -->
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<div class="toast-container" x-data>
|
||||
|
|
@ -347,7 +336,6 @@
|
|||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
<!-- LOGOUT BUTTON -->
|
||||
<a href="{{ url_for('logout') }}" class="fixed bottom-6 left-6 text-white font-bold py-3 px-5 rounded-full shadow-lg transition-all backdrop-blur-sm flex items-center gap-2 z-30
|
||||
{% if maintenance_active %}
|
||||
bg-yellow-600/50 hover:bg-yellow-500/80 hover:shadow-yellow-500/40 border border-yellow-500/20
|
||||
|
|
@ -360,14 +348,12 @@
|
|||
<span>Logout</span>
|
||||
</a>
|
||||
|
||||
|
||||
<script src="{{ url_for('static', filename='JAVASCRIPT/main.js') }}"></script>
|
||||
{% if maintenance_active %}
|
||||
<script>document.body.classList.add('maintenance-active');</script>
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
// GSAP Animationen und Ladebildschirm-Logik
|
||||
gsap.to("#star", {
|
||||
rotation: 360,
|
||||
duration: 1.2,
|
||||
|
|
@ -393,7 +379,6 @@
|
|||
});
|
||||
}, 400);
|
||||
|
||||
// Animierter Hintergrund
|
||||
const bg = document.querySelector('.animated-bg');
|
||||
if (bg) {
|
||||
for (let i = 0; i < 50; i++) {
|
||||
|
|
@ -410,4 +395,4 @@
|
|||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
@ -30,11 +30,10 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- HEADER -->
|
||||
<header class="flex justify-between items-center mb-10">
|
||||
<h2 class="text-4xl font-bold tracking-wide {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">System Status</h2>
|
||||
</header>
|
||||
<!-- STATUS LIST -->
|
||||
|
||||
<div class="space-y-4" id="status-list">
|
||||
<div class="bg-black/40 rounded-xl p-6 backdrop-blur-lg flex justify-between items-center
|
||||
{% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
|
|
@ -69,12 +68,12 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function updateStatusPage() {
|
||||
fetch('/api/system_status')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
// Helper
|
||||
function setStatus(id, status) {
|
||||
let text = "";
|
||||
let indicator = "";
|
||||
|
|
@ -105,4 +104,4 @@ function updateStatusPage() {
|
|||
setInterval(updateStatusPage, 5000);
|
||||
updateStatusPage();
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
@ -21,7 +21,6 @@
|
|||
}
|
||||
}">
|
||||
<div class="space-y-10">
|
||||
<!-- HEADER -->
|
||||
<header class="flex justify-between items-center">
|
||||
<h2 class="text-4xl font-bold tracking-wide {% if maintenance_active %}text-yellow-300{% else %}text-purple-300{% endif %}">User Management</h2>
|
||||
<button @click="userToEdit = null; showAddUserModal = true" class="font-bold py-2 px-4 rounded-lg transition text-white
|
||||
|
|
@ -30,7 +29,6 @@
|
|||
</button>
|
||||
</header>
|
||||
|
||||
<!-- USER TABLE -->
|
||||
<div class="bg-black/40 rounded-xl backdrop-blur-lg overflow-hidden
|
||||
{% if maintenance_active %}border border-yellow-500/30{% else %}border border-purple-500/20{% endif %}">
|
||||
<table class="min-w-full divide-y {% if maintenance_active %}divide-yellow-500/30{% else %}divide-purple-500/20{% endif %}">
|
||||
|
|
@ -69,7 +67,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ADD/EDIT USER MODAL -->
|
||||
<div x-show="showAddUserModal" @keydown.escape.window="showAddUserModal = false" class="fixed inset-0 bg-black/70 backdrop-blur-sm flex items-center justify-center z-50" style="display: none;">
|
||||
<div @click.away="showAddUserModal = false" class="bg-gray-900 rounded-xl shadow-2xl p-8 w-full max-w-md
|
||||
{% if maintenance_active %}border border-yellow-500/50{% else %}border border-purple-500/50{% endif %}">
|
||||
|
|
@ -125,7 +122,6 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- DELETE CONFIRMATION MODAL -->
|
||||
<div x-show="showDeleteModal" @keydown.escape.window="showDeleteModal = false" class="fixed inset-0 bg-black/70 backdrop-blur-sm flex items-center justify-center z-50" style="display: none;">
|
||||
<div @click.away="showDeleteModal = false" class="bg-gray-900 border border-red-500/50 rounded-xl shadow-2xl p-8 w-full max-w-md">
|
||||
<h3 class="text-2xl font-bold text-red-400 mb-4">Benutzer löschen</h3>
|
||||
|
|
@ -138,7 +134,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Daten für Alpine.js bereitstellen -->
|
||||
<script id="users-data" type="application/json">
|
||||
{{ users_for_modal | tojson | safe }}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- DELETE CONFIRMATION MODAL -->
|
||||
<div x-show="showDeleteModal" @keydown.escape.window="showDeleteModal = false" class="fixed inset-0 bg-black/70 backdrop-blur-sm flex items-center justify-center z-50" style="display: none;">
|
||||
<div @click.away="showDeleteModal = false" class="bg-gray-900 border border-red-500/50 rounded-xl shadow-2xl p-8 w-full max-w-md">
|
||||
<h3 class="text-2xl font-bold text-red-400 mb-4">Eintrag löschen</h3>
|
||||
|
|
@ -86,9 +85,8 @@
|
|||
function copyToClipboard(elementId) {
|
||||
const input = document.getElementById(elementId);
|
||||
input.select();
|
||||
input.setSelectionRange(0, 99999); // For mobile devices
|
||||
input.setSelectionRange(0, 99999);
|
||||
document.execCommand('copy');
|
||||
// Optional: Visuelles Feedback geben
|
||||
const originalButtonText = event.target.innerText;
|
||||
event.target.innerText = 'Kopiert!';
|
||||
setTimeout(() => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
// --- Initial Load: Set correct open/closed state ---
|
||||
document.querySelectorAll('.collapsible').forEach(button => {
|
||||
const content = button.nextElementSibling;
|
||||
const chevron = button.querySelector('svg');
|
||||
|
|
@ -19,15 +18,12 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
// --- Accordion Click Behavior ---
|
||||
document.querySelectorAll('.collapsible').forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
|
||||
const content = button.nextElementSibling;
|
||||
const chevron = button.querySelector('svg');
|
||||
|
||||
// First close all others
|
||||
document.querySelectorAll('.collapsible').forEach(other => {
|
||||
if (other !== button) {
|
||||
const otherContent = other.nextElementSibling;
|
||||
|
|
@ -48,7 +44,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
}
|
||||
});
|
||||
|
||||
// Toggle current
|
||||
if (content.classList.contains('hidden')) {
|
||||
content.classList.remove('hidden');
|
||||
gsap.fromTo(content,
|
||||
|
|
@ -72,4 +67,4 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue