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>
92 lines
3.7 KiB
HTML
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 · 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] }}…</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 %}
|