776deaec97
- Added a quick admin link section in the admin dashboard for managing team cards. - Updated the admin licenses template to correct German language spelling. - Improved the appointments template with conditional rendering for test package options. - Enhanced the base template with a logo image and adjusted brand styling. - Updated the license management template for consistent German language usage. - Removed the tutorial template and replaced it with a new admin team management template. - Introduced a new admin team management page allowing for the addition, editing, and deletion of team members.
268 lines
7.4 KiB
HTML
268 lines
7.4 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Admin | Lizenz-Key Verwaltung{% endblock %}
|
|
|
|
{% block head %}
|
|
{{ super() }}
|
|
<style>
|
|
.key-header {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.key-header p {
|
|
margin-top: 0.4rem;
|
|
max-width: 70ch;
|
|
}
|
|
|
|
.key-layout {
|
|
display: grid;
|
|
grid-template-columns: 360px 1fr;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.key-card {
|
|
background: #ffffff;
|
|
border: 1px solid #d4e0e9;
|
|
border-radius: 14px;
|
|
padding: 1rem;
|
|
box-shadow: 0 10px 28px rgba(20, 40, 55, 0.05);
|
|
}
|
|
|
|
.key-card h3 {
|
|
font-size: 1.02rem;
|
|
color: #143a55;
|
|
margin-bottom: 0.65rem;
|
|
}
|
|
|
|
.key-form {
|
|
display: grid;
|
|
gap: 0.55rem;
|
|
}
|
|
|
|
.key-form label {
|
|
font-size: 0.86rem;
|
|
font-weight: 700;
|
|
color: #3f5f74;
|
|
}
|
|
|
|
.key-form select,
|
|
.key-form input,
|
|
.key-form button {
|
|
width: 100%;
|
|
font: inherit;
|
|
border-radius: 10px;
|
|
padding: 0.52rem 0.62rem;
|
|
}
|
|
|
|
.key-form select,
|
|
.key-form input {
|
|
border: 1px solid #c7d7e2;
|
|
background: #ffffff;
|
|
color: #17394f;
|
|
}
|
|
|
|
.btn-main,
|
|
.btn-alt,
|
|
.btn-danger {
|
|
border: none;
|
|
cursor: pointer;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.btn-main {
|
|
color: #ffffff;
|
|
background: linear-gradient(120deg, #0b5b89 0%, #0b4262 100%);
|
|
}
|
|
|
|
.btn-alt {
|
|
color: #0f3d59;
|
|
border: 1px solid #bfd2df;
|
|
background: #f8fbfd;
|
|
}
|
|
|
|
.btn-danger {
|
|
color: #7e2d2d;
|
|
border: 1px solid #e8b8b8;
|
|
background: #fff3f3;
|
|
}
|
|
|
|
.key-actions {
|
|
display: grid;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.key-actions a {
|
|
text-align: center;
|
|
}
|
|
|
|
.key-table-wrap {
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.key-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.key-table th,
|
|
.key-table td {
|
|
border-bottom: 1px solid #e0e8ef;
|
|
text-align: left;
|
|
padding: 0.68rem 0.5rem;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.key-table th {
|
|
font-size: 0.82rem;
|
|
color: #4b697d;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
|
|
.key-table td {
|
|
color: #17384f;
|
|
font-size: 0.95rem;
|
|
}
|
|
|
|
.code {
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
font-size: 0.85rem;
|
|
background: #f2f6fa;
|
|
border: 1px solid #d9e4ed;
|
|
border-radius: 8px;
|
|
padding: 0.2rem 0.35rem;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.badge {
|
|
display: inline-block;
|
|
border-radius: 999px;
|
|
padding: 0.2rem 0.5rem;
|
|
font-size: 0.78rem;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.badge.assigned {
|
|
border: 1px solid #9fd2bf;
|
|
color: #14684a;
|
|
background: #edfaf4;
|
|
}
|
|
|
|
.badge.unassigned {
|
|
border: 1px solid #ebd08c;
|
|
color: #8a6113;
|
|
background: #fff8e8;
|
|
}
|
|
|
|
.remove-form {
|
|
display: inline;
|
|
}
|
|
|
|
@media (max-width: 1024px) {
|
|
.key-layout {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<section class="key-header">
|
|
<h1>Lizenz-Key Verwaltung</h1>
|
|
<p>Generieren, zuweisen und sichern Sie Lizenz-Keys im gleichen Stil wie der restliche Admin-Bereich.</p>
|
|
</section>
|
|
|
|
<section class="key-layout">
|
|
<aside class="key-card">
|
|
<h3>Key erstellen</h3>
|
|
<form method="POST" action="{{ url_for('generate_new') }}" class="key-form">
|
|
<button type="submit" class="btn-main">Neuen Key generieren</button>
|
|
</form>
|
|
|
|
<h3 style="margin-top: 1rem;">Key zuweisen</h3>
|
|
<form method="POST" action="{{ url_for('allocate_key') }}" class="key-form">
|
|
<label for="alloc_user">Benutzer</label>
|
|
<select id="alloc_user" name="username" required>
|
|
<option value="">Benutzer auswählen</option>
|
|
{% for user in users %}
|
|
<option value="{{ user.username }}">{{ user.username }} ({{ user.display_name }})</option>
|
|
{% endfor %}
|
|
</select>
|
|
|
|
<label for="alloc_key">Lizenz-Key</label>
|
|
<select id="alloc_key" name="license_key" required>
|
|
<option value="">Key auswählen</option>
|
|
{% for item in keys %}
|
|
<option value="{{ item.license_key }}">{{ item.user_id or '----' }} | {{ item.license_key[:22] }}{% if item.license_key|length > 22 %}...{% endif %}</option>
|
|
{% endfor %}
|
|
</select>
|
|
|
|
<button type="submit" class="btn-main">Key zuweisen</button>
|
|
</form>
|
|
|
|
<h3 style="margin-top: 1rem;">Backup</h3>
|
|
<div class="key-actions">
|
|
<a href="{{ url_for('download_backup') }}" class="btn-alt">Backup herunterladen</a>
|
|
<form method="POST" action="{{ url_for('upload_backup') }}" enctype="multipart/form-data" class="key-form">
|
|
<input type="file" name="file" accept=".json" required>
|
|
<button type="submit" class="btn-danger" onclick="return confirm('Backup wirklich einspielen? Aktuelle Keys werden ersetzt.');">Backup einspielen</button>
|
|
</form>
|
|
</div>
|
|
</aside>
|
|
|
|
<article class="key-card">
|
|
<h3>Alle Keys</h3>
|
|
<div class="key-table-wrap">
|
|
<table class="key-table">
|
|
<thead>
|
|
<tr>
|
|
<th>User ID</th>
|
|
<th>Lizenz-Key</th>
|
|
<th>Benutzer</th>
|
|
<th>HWID</th>
|
|
<th>Status</th>
|
|
<th>Aktion</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for item in keys %}
|
|
<tr>
|
|
<td>{{ item.user_id or '-' }}</td>
|
|
<td><span class="code">{{ item.license_key }}</span></td>
|
|
<td>{{ item.username or '-' }}</td>
|
|
<td>
|
|
{% if item.hwid_uuid %}
|
|
<span class="code">{{ item.hwid_uuid }}</span>
|
|
{% else %}
|
|
-
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if item.username %}
|
|
<span class="badge assigned">Zugewiesen</span>
|
|
{% else %}
|
|
<span class="badge unassigned">Nicht zugewiesen</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if item.user_id %}
|
|
<form method="POST" action="{{ url_for('remove_key', user_id=item.user_id) }}" class="remove-form" onsubmit="return confirm('Key für User {{ item.user_id }} wirklich löschen?');">
|
|
<button type="submit" class="btn-danger">Entfernen</button>
|
|
</form>
|
|
{% else %}
|
|
-
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% else %}
|
|
<tr>
|
|
<td colspan="6">Keine Lizenz-Keys gefunden.</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</article>
|
|
</section>
|
|
|
|
{% endblock %} |