Kund:innen können jetzt eigene Gruppen selbst verwalten (/gruppen) statt nur intern über /admin/kunden - reiner Kundenplattform-Zusatz, keine Backend-Änderung nötig (anode-API war bereits organisationsgebunden und generisch aufgebaut, siehe ADR-0012). Admin-Zugang bleibt zusätzlich bestehen (Support/Onboarding), beide teilen sich dieselbe anode-API. Neuer Router routers/gruppen.py (eng an struktur.py angelehnt, gleiches Besitz-Validierungsmuster), Templates gruppen_liste/gruppe_detail (Merkmale-Tristate-Editor + Geräte-Mitgliedschaft, wie admin/gruppe_detail.html)/gruppe_umbenennen/gruppe_loeschen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
92 lines
3.8 KiB
HTML
92 lines
3.8 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Gruppe {{ gruppe.name }} — Tuxflotte{% endblock %}
|
|
{% block content %}
|
|
<p><a href="/gruppen">← Gruppen</a></p>
|
|
<h2>Gruppe: {{ gruppe.name }}</h2>
|
|
|
|
<section>
|
|
<h3>Merkmale</h3>
|
|
<p><small>"Nicht festgelegt" überlässt die Entscheidung der OE-Kette bzw. dem Workspace-Standard des Geräts. Gehört ein Gerät mehreren Gruppen mit widersprüchlicher Einstellung an, gewinnt "aktiv".</small></p>
|
|
{% if not kategorien %}
|
|
<p>Keine katalogfähigen Merkmale vorhanden.</p>
|
|
{% else %}
|
|
{% for kategorie_name, eintraege in kategorien.items() %}
|
|
<h4>{{ kategorie_name }}</h4>
|
|
<figure>
|
|
<table>
|
|
<tbody>
|
|
{% for eintrag in eintraege %}
|
|
<tr>
|
|
<td>
|
|
<strong>{{ eintrag.name }}</strong>
|
|
{% if eintrag.description %}<br><small>{{ eintrag.description }}</small>{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if eintrag.aktiv is none %}
|
|
<span class="state-absent">nicht festgelegt</span>
|
|
{% elif eintrag.aktiv %}
|
|
<span class="state-present">aktiv</span>
|
|
{% else %}
|
|
<span class="state-absent">inaktiv</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if eintrag.aktiv != true %}
|
|
<form method="post" action="/gruppen/{{ gruppe.id }}/merkmale/{{ eintrag.merkmal }}/select">
|
|
<button type="submit">Aktiv setzen</button>
|
|
</form>
|
|
{% endif %}
|
|
{% if eintrag.aktiv != false %}
|
|
<form method="post" action="/gruppen/{{ gruppe.id }}/merkmale/{{ eintrag.merkmal }}/deselect">
|
|
<button type="submit" class="secondary">Inaktiv setzen</button>
|
|
</form>
|
|
{% endif %}
|
|
{% if eintrag.aktiv is not none %}
|
|
<form method="post" action="/gruppen/{{ gruppe.id }}/merkmale/{{ eintrag.merkmal }}/unset">
|
|
<button type="submit" class="outline">Zurücksetzen</button>
|
|
</form>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</figure>
|
|
{% endfor %}
|
|
{% endif %}
|
|
</section>
|
|
|
|
<section>
|
|
<h3>Geräte in dieser Gruppe</h3>
|
|
{% if not devices %}
|
|
<p>Keine Geräte vorhanden.</p>
|
|
{% else %}
|
|
<figure>
|
|
<table>
|
|
<thead><tr><th>Hostname</th><th>Kennung</th><th>Mitglied</th><th></th></tr></thead>
|
|
<tbody>
|
|
{% for device in devices %}
|
|
<tr>
|
|
<td>{{ device.hostname or "—" }}</td>
|
|
<td><code>{{ device.device_fingerprint }}</code></td>
|
|
<td>{{ "ja" if device.id in mitglied_ids else "nein" }}</td>
|
|
<td>
|
|
{% if device.id in mitglied_ids %}
|
|
<form method="post" action="/gruppen/{{ gruppe.id }}/geraete/{{ device.id }}/entfernen">
|
|
<button type="submit" class="outline secondary">Entfernen</button>
|
|
</form>
|
|
{% else %}
|
|
<form method="post" action="/gruppen/{{ gruppe.id }}/geraete/{{ device.id }}/hinzufuegen">
|
|
<button type="submit" class="outline">Hinzufügen</button>
|
|
</form>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</figure>
|
|
{% endif %}
|
|
</section>
|
|
{% endblock %}
|