Files
tesm-license/apps/tesm-license/src/tesm_license/templates/license/tickets.html
T
alientimandClaude Opus 5 ab5fda658e Umlaute in der Oberflaeche, Sitzungskopplung, Statusanzeigen
Echte Umlaute in allen Texten der Oberflaeche und in den Markdown-Dateien.
Die Einbindung von Dateifreigaben haengt jetzt an der Sitzung: wird sie
widerrufen oder laeuft sie ab, verschwinden die Freigaben mit ihr. Neu
einstellbar ist die automatische Abmeldung bei Leerlauf (Vorgabe 30 Minuten).
Ein Geraet, das nicht antwortet, bietet nur noch "Einschalten (PoE)" an --
Neustart ueber SSH oder RPC braucht ein erreichbares Geraet. Der Zeitgeber der
naechsten Pruefung und die Restlaufzeit der Lizenz stehen jetzt oben in der
Kopfzeile; der doppelte Knopf darunter ist weg. Millisekunden werden ab einer
Sekunde als Sekunden und ab einer Minute als m:ss dargestellt.

Ausserdem: Release-Tarball nicht mehr im Repository -- er haengt am Release.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 23:54:35 +02:00

92 lines
3.7 KiB
HTML

{% extends "tesm_core/base.html" %}
{% from "tesm_core/macros.html" import pill, search_box, empty_state, alert %}
{% block page_title %}Tickets{% endblock %}
{% block page_sub %}
{{ tickets | length }} Tickets &middot; ein Ticket ist der dauerhafte Anspruch auf eine Lizenz
{% endblock %}
{% block topbar_extra %}
{{ search_box('tickets-table', 'Kunde, Typ, ID ...') }}
{% if current_user.has('tickets.create') %}
<a class="btn btn--primary btn--sm" href="{{ url_for('tickets.new') }}">
{{ icon('plus', size=15) }} Ticket anlegen
</a>
{% endif %}
{% endblock %}
{% block content %}
{% if endpoint_missing %}
{{ alert(endpoint_missing, 'danger', 'Keine Ausstellung möglich') }}
{% endif %}
{{ alert('Ein Ticket beschreibt den Anspruch (Typ, Module, Laufzeit); die Lizenz ist die daraus
erzeugte, signierte Datei. Änderungen am Ticket wirken auf die nächste
Ausstellung -- bereits ausgestellte Lizenzen bleiben unverändert.', 'info') }}
<section class="card">
<div class="table-wrap">
<table class="table" id="tickets-table" data-behavior="sortable">
<thead>
<tr>
<th class="sortable">Kunde</th>
<th class="sortable">Ticket</th>
<th class="sortable">Typ</th>
<th>Module</th>
<th class="sortable">Laufzeit</th>
<th class="sortable">Zustand</th>
<th>Offene Lizenz</th>
</tr>
</thead>
<tbody>
{% for ticket in tickets %}
<tr data-filter-text="{{ ticket.customer_name }} {{ ticket.type }} {{ ticket.id }} {{ ticket.role }}">
<td>
<a class="fw-600" href="{{ url_for('customers.detail', customer_id=ticket.customer_id) }}">
{{ ticket.customer_name }}
</a>
{% if ticket.role != 'customer' %}
{{ pill(role_labels.get(ticket.role, ticket.role), 'accent') }}
{% endif %}
</td>
<td class="mono fs-sm">
<a href="{{ url_for('tickets.detail', ticket_id=ticket.id) }}">{{ ticket.id[:12] }}&hellip;</a>
</td>
<td class="fs-sm">{{ type_labels.get(ticket.type, ticket.type) }}</td>
<td class="fs-xs">
{% set mods = ticket.modules | from_json %}
{% if mods %}{{ mods | map('replace', '_', ' ') | join(', ') }}
{% else %}<span class="faint">keine</span>{% endif %}
</td>
<td class="fs-sm">
{% if ticket.lifetime %}{{ pill('unbefristet', 'online') }}
{% else %}{{ ticket.valid_days }} Tage{% endif %}
</td>
<td>
{% if ticket.status == 'blocked' %}{{ pill('gesperrt', 'danger') }}
{% else %}{{ pill('offen', 'online') }}{% endif %}
</td>
<td class="fs-sm">
{% set entry = open_licenses.get(ticket.id) %}
{% if entry %}
<a href="{{ url_for('licenses.detail', license_id=entry.license_id) }}">
{{ entry.status }}
</a>
{% if entry.lifetime %}{{ pill('unbefristet', 'online') }}
{% elif entry.color == 'red' %}{{ pill(entry.days_left ~ ' Tage', 'danger') }}
{% elif entry.color == 'orange' %}{{ pill(entry.days_left ~ ' Tage', 'warning') }}
{% else %}{{ pill(entry.days_left ~ ' Tage', 'online') }}{% endif %}
{% else %}
<span class="faint">keine</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if not tickets %}
{{ empty_state('Keine Tickets', 'Legen Sie das erste Ticket für einen Kunden an.', 'ticket') }}
{% endif %}
</section>
{% endblock %}