b2af866cf0
Add persistent German/English switching, translated UI messages and English 12-hour times. Align desktop event actions while preserving mobile layouts and record bilingual project guidance. Include pending diary deletion exclusions. Validate both languages with nine tests.
58 lines
4.0 KiB
HTML
58 lines
4.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="{{ language() }}">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{{ _('Benutzerverwaltung · MetalCircle') }}</title>
|
|
<link rel="icon" type="image/png" href="/static/images/metalcircle-circle.png">
|
|
<link rel="stylesheet" href="/static/css/style.css">
|
|
<style>
|
|
.invite-link { display: block; margin-top: 14px; padding: 12px; overflow-wrap: anywhere; background: #0f1420; border: 1px solid var(--border); border-radius: 9px; color: #c4b5fd; }
|
|
.user-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; gap: 12px; align-items: center; }
|
|
.user-row form { margin: 0; }
|
|
.role-form { display: flex; gap: 8px; }
|
|
.role-form label { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
|
|
.role-form label input { width: auto; margin: 0; }
|
|
.founder-lock { color: #fbbf24; font-weight: 700; white-space: nowrap; }
|
|
@media (max-width: 700px) { .user-row { grid-template-columns: 1fr; } }
|
|
</style>
|
|
<link rel="stylesheet" href="/static/css/language.css">
|
|
</head>
|
|
<body>
|
|
<header><div class="header-inner"><a href="/" class="logo"><img class="brand-logo" src="/static/images/metalcircle-full.png" alt="MetalCircle"></a>{% include '_user_menu.html' %}</div> {% include '_language_switch.html' %}
|
|
</header>
|
|
<main>
|
|
<div class="page-title"><h1>{{ _('⚙️ Verwaltung') }}</h1><p>{{ _('Benutzerkonten und Einladungen verwalten.') }}</p></div>
|
|
{% set admin_section = 'users' %}{% include '_admin_nav.html' %}
|
|
<section class="admin-section">
|
|
<h2>{{ _('Einladung erstellen') }}</h2>
|
|
<p>{{ _('Der Link kann einmalig verwendet werden.') }}</p>
|
|
<form method="post" action="/admin/invites"><button class="button" type="submit">{{ _('+ Einladungslink erzeugen') }}</button></form>
|
|
{% if invite_url %}<label class="invite-link">{{ invite_url }}</label>{% endif %}
|
|
</section>
|
|
<section class="admin-section">
|
|
<h2>{{ _('Benutzer') }}</h2>
|
|
<div class="admin-list">
|
|
{% for managed_user in users %}
|
|
<div class="admin-row user-row">
|
|
<div><strong>{% if managed_user.username|lower == 'kai' %}🏴☠️ {% endif %}{{ managed_user.display_name }}</strong><div class="admin-meta">@{{ managed_user.username }} · {{ managed_user.email }} {{ _('· seit') }} {{ managed_user.created_at }}</div></div>
|
|
{% if managed_user.username|lower == 'kai' %}
|
|
<span class="founder-lock">{{ _('🏴\u200d☠️ Gründer · Admin (fest)') }}</span>
|
|
{% else %}
|
|
<form class="role-form" method="post" action="/admin/users/{{ managed_user.id }}">
|
|
<select name="role" aria-label="{{ _('Rolle für') }} {{ managed_user.username }}"><option value="user" {% if not managed_user.is_admin %}selected{% endif %}>{{ _('Benutzer') }}</option><option value="admin" {% if managed_user.is_admin %}selected{% endif %}>🏴☠️ Admin</option></select>
|
|
<button class="button" type="submit">{{ _('Speichern') }}</button>
|
|
</form>
|
|
{% endif %}
|
|
<div class="role-form">
|
|
<form method="post" action="/admin/users/{{ managed_user.id }}/account-link"><input type="hidden" name="purpose" value="password_reset"><button class="button button-secondary" type="submit">{{ _('Passwort-Reset') }}</button></form>
|
|
</div>
|
|
{% if managed_user.id != user.id and managed_user.username|lower != 'kai' %}<form method="post" action="/admin/users/{{ managed_user.id }}/delete" onsubmit="return confirm({{ _('Diesen Benutzer wirklich löschen?') | tojson | forceescape }});"><button class="admin-danger" type="submit">{{ _('Löschen') }}</button></form>{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</body>
|
|
</html>
|