first commit

This commit is contained in:
2026-06-29 09:52:02 +02:00
commit da2f7c3c86
31 changed files with 2306 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
{% extends "base.html" %}
{% block title %}Auswertung · EPI-Support{% endblock %}
{% block content %}
{% macro bars(items) %}
{% set top = (items|map(attribute=1)|max) if items else 1 %}
<div class="barlist">
{% for label, cnt in items %}
<div class="barrow">
<span class="barlabel" title="{{ label }}">{{ label }}</span>
<span class="bartrack"><span class="barfill" style="width: {{ (cnt / top * 100) if top else 0 }}%"></span></span>
<span class="barval">{{ cnt }}</span>
</div>
{% else %}
<p class="muted">Keine Daten.</p>
{% endfor %}
</div>
{% endmacro %}
<div class="toolbar">
<div class="chips">
{% for val, label in periods %}
<a class="chip {{ 'on' if active_period == val }}"
href="{{ url_for('analytics_view', period=val) }}">{{ label }}</a>
{% endfor %}
</div>
<a class="btn-sm" href="{{ url_for('export_xlsx', period=active_period) }}">⬇ Excel-Export</a>
</div>
<section class="cards cards-6">
<div class="card"><span class="num">{{ m.total }}</span><span class="lbl">Tickets im Zeitraum</span></div>
<div class="card"><span class="num">{{ m.open }}</span><span class="lbl">offen</span></div>
<div class="card"><span class="num">{{ m.closed }}</span><span class="lbl">geschlossen</span></div>
<div class="card {{ 'alert' if m.escalated }}"><span class="num">{{ m.escalated }}</span><span class="lbl">eskaliert</span></div>
<div class="card"><span class="num">{{ h(m.response.median) }}</span><span class="lbl">Median Reaktionszeit</span></div>
<div class="card"><span class="num">{{ h(m.resolution.median) }}</span><span class="lbl">Median Lösungszeit</span></div>
</section>
<section class="panel">
<div class="panel-head"><h2>Ticket-Aufkommen pro Monat</h2></div>
<div class="chart-wrap">{{ chart_svg|safe }}</div>
</section>
<div class="grid-2">
<section class="panel">
<div class="panel-head"><h2>Reaktions- & Lösungszeiten</h2></div>
<table class="kv">
<tr><th></th><th>Median</th><th>Ø</th><th>P90</th><th>n</th></tr>
<tr><td>Reaktionszeit</td>
<td>{{ h(m.response.median) }}</td><td>{{ h(m.response.avg) }}</td>
<td>{{ h(m.response.p90) }}</td><td>{{ m.response.n }}</td></tr>
<tr><td>Lösungszeit</td>
<td>{{ h(m.resolution.median) }}</td><td>{{ h(m.resolution.avg) }}</td>
<td>{{ h(m.resolution.p90) }}</td><td>{{ m.resolution.n }}</td></tr>
</table>
{% if m.oldest_open %}
<p class="hint">Ältestes offenes Ticket:
<a href="{{ url_for('ticket_detail', ticket_id=m.oldest_open.id) }}">#{{ m.oldest_open.number }}</a>
{{ m.oldest_open.title }} seit <b>{{ m.oldest_open.age|round(0)|int }} Tagen</b>
{% if m.open_age_avg_days %}(Ø offen: {{ m.open_age_avg_days|round(1) }} Tage){% endif %}
</p>
{% endif %}
</section>
<section class="panel">
<div class="panel-head"><h2>Nach Priorität</h2></div>
{{ bars(m.by_priority) }}
</section>
</div>
<div class="grid-2">
<section class="panel">
<div class="panel-head"><h2>Nach Status</h2></div>
{{ bars(m.by_state) }}
</section>
<section class="panel">
<div class="panel-head"><h2>Nach Gruppe</h2></div>
{{ bars(m.by_group) }}
</section>
</div>
<section class="panel">
<div class="panel-head"><h2>Nach Bearbeiter (Agent)</h2></div>
{{ bars(m.by_owner) }}
</section>
{% endblock %}