Files
tesm/srv/poe_manager/templates/groups.html
T
alientimandClaude Sonnet 5 08d8d1f738 Dashboard-Kacheln, Ansichtsrechte, Standardgruppe, Countdown-Fix, Deploy-Pfad
- Dashboard zeigt jetzt in beiden Zustaenden (mit/ohne Login) Kacheln statt
  Tabelle; ohne Login nur aktive Geraete + Online/Offline/Gesamt, eingeloggt
  alle Geraete + zusaetzliche Deaktiviert-Kachel
- Sortierung ueberall: erst alle Nicht-Online-Geraete, dann Online, jeweils
  alphabetisch
- Neue Rechte devices.view / switches.view; Standardgruppe 'Benutzer' wird
  automatisch angelegt (alle Ansichtsrechte) und jedem neuen Benutzer
  zugeordnet; bestehende Benutzer ohne Gruppe werden migriert
- Gruppen-Seite zeigt zusaetzlich virtuelle 'Admin'-Karte (informativ) und
  markiert die Standardgruppe (nicht loeschbar)
- 'Naechste Pruefung'-Countdown wird serverseitig aus dem tatsaechlichen
  letzten Log-Eintrag geseedet statt bei jedem Reload neu zu starten
- Deployment-Doku korrigiert: Checkout getrennt von /srv/poe_manager, damit
  kein verschachteltes srv/poe_manager/srv/poe_manager entsteht

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 12:41:21 +02:00

158 lines
6.6 KiB
HTML

{% extends "base.html" %}
{% set active_page = "groups" %}
{% block page_title %}Gruppen{% endblock %}
{% block page_sub %}<div class="topbar-sub">{{ groups|length + 1 }} Gruppen · Rechteverwaltung</div>{% endblock %}
{% block topbar_right %}
<button type="button" class="btn btn-primary" data-open-modal="addGroupModal">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>
Neue Gruppe
</button>
{% endblock %}
{% block content %}
<p class="text-faint" style="font-size:12.5px; margin-bottom:18px; max-width:720px;">
Admins dürfen immer alles. Über Gruppen lassen sich einzelne Verwaltungsrechte für
Devices und Switches gezielt an normale Benutzer vergeben, ohne sie zu Admins zu machen.
Ein Benutzer kann mehreren Gruppen angehören — die Rechte addieren sich.
</p>
{# Virtuelle Admin-"Gruppe": rein informativ, kein Formular — Admin-Status
wird ausschließlich über den is_admin-Schalter auf der Users-Seite gesetzt. #}
<div class="card card-pad" style="margin-bottom:16px; opacity:0.85;">
<div class="section-head">
<div class="flex gap-2" style="align-items:center;">
<h3 style="font-size:16px;">Admin</h3>
<span class="pill admin">Systemrolle</span>
</div>
</div>
<p class="text-faint" style="font-size:12px; margin:-8px 0 14px;">
Admins dürfen immer alles — Rolle wird über <a href="{{ url_for('users') }}" style="color:var(--accent-strong); font-weight:600;">Users</a> vergeben, nicht hier.
</p>
<div style="display:grid; grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); gap:24px;">
{% for cat_key, cat in permission_catalog.items() %}
<div>
<div class="permission-group-title">{{ cat['label'] }}</div>
<div class="check-list">
{% for key, label in cat['items'].items() %}
<label class="check-row" style="cursor:default; color:var(--text-faint);">
<input type="checkbox" checked disabled>
{{ label }}
</label>
{% endfor %}
</div>
</div>
{% endfor %}
<div>
<div class="permission-group-title">Mitglieder</div>
<p class="text-dim" style="font-size:13px;">
{% if admin_virtual_group.member_names %}{{ admin_virtual_group.member_names|join(', ') }}{% else %}Keine Admins vorhanden.{% endif %}
</p>
</div>
</div>
</div>
{% if groups %}
<div style="display:flex; flex-direction:column; gap:16px;">
{% for g in groups %}
<div class="card card-pad">
<form method="post">
<input type="hidden" name="save_group" value="1">
<input type="hidden" name="group_id" value="{{ g.id }}">
<div class="section-head">
<div class="field" style="margin-bottom:0; max-width:280px; flex:1;">
<label>Gruppenname</label>
<div class="flex gap-2" style="align-items:center;">
<input type="text" name="name" value="{{ g.name }}" required>
{% if g.is_default %}<span class="pill user" style="white-space:nowrap;">Standard</span>{% endif %}
</div>
</div>
<button type="submit" class="btn btn-primary">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg>
Speichern
</button>
</div>
{% if g.is_default %}
<p class="text-faint" style="font-size:11.5px; margin:-8px 0 8px;">
Standardgruppe — jeder neu angelegte Benutzer wird ihr automatisch zugeordnet. Kann nicht gelöscht werden.
</p>
{% endif %}
<div style="display:grid; grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); gap:24px; margin-top:8px;">
{% for cat_key, cat in permission_catalog.items() %}
<div>
<div class="permission-group-title">{{ cat['label'] }}</div>
<div class="check-list">
{% for key, label in cat['items'].items() %}
<label class="check-row">
<input type="checkbox" name="permissions" value="{{ key }}" {% if key in g.permissions %}checked{% endif %}>
{{ label }}
</label>
{% endfor %}
</div>
</div>
{% endfor %}
<div>
<div class="permission-group-title">Mitglieder</div>
<div class="check-list" style="max-height:180px; overflow-y:auto; padding-right:4px;">
{% for u in all_users %}
<label class="check-row">
<input type="checkbox" name="members" value="{{ u['id'] }}" {% if u['id'] in g.members %}checked{% endif %}>
{{ u['username'] }}
</label>
{% else %}
<p class="text-faint" style="font-size:12px;">Keine Nicht-Admin-Benutzer vorhanden.</p>
{% endfor %}
</div>
</div>
</div>
</form>
<div class="flex" style="justify-content:space-between; align-items:center; margin-top:16px; padding-top:14px; border-top:1px solid var(--border-soft);">
<span class="text-faint" style="font-size:12px;">
{% if g.member_names %}Mitglieder: {{ g.member_names|join(', ') }}{% else %}Keine Mitglieder{% endif %}
</span>
{% if not g.is_default %}
<form method="post" data-confirm="Gruppe „{{ g.name }}“ wirklich löschen? Mitglieder verlieren die zugehörigen Rechte.">
<input type="hidden" name="delete_group" value="{{ g.id }}">
<button type="submit" class="btn btn-sm btn-danger">Gruppe löschen</button>
</form>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="card card-pad" style="text-align:center; color:var(--text-faint);">
Noch keine Gruppen angelegt.
</div>
{% endif %}
<!-- Modal: Neue Gruppe -->
<div class="modal-overlay" id="addGroupModal">
<div class="modal" style="max-width:380px;">
<form method="post">
<div class="modal-header">
<h3>Neue Gruppe</h3>
<button type="button" class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<input type="hidden" name="add_group" value="1">
<div class="field">
<label>Name</label>
<input type="text" name="name" required placeholder="z.B. Facility-Team">
<div class="field-hint">Rechte und Mitglieder werden danach auf der Gruppenkarte eingestellt.</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" class="btn btn-primary">Anlegen</button>
</div>
</form>
</div>
</div>
{% endblock %}