Add ticket status setter and prevent draft text loss

- Set ticket state (Offen / In Bearbeitung / Warten auf Schließen /
  Geschlossen) from the ticket detail page via a live PUT to Zammad;
  pending-close gets a default pending time and the change is synced back
  so it isn't flagged as an external change
- Replace the disruptive meta-refresh with a JS auto-refresh that pauses
  while a text field has unsent content or focus
- Persist reply/new-ticket drafts to localStorage and restore them after
  a reload or accidental navigation

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 11:15:30 +02:00
co-authored by Claude Opus 4.8
parent 1041f283a4
commit 1107a912bc
7 changed files with 141 additions and 11 deletions
+1 -1
View File
@@ -5,7 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}EPI-Support{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<meta http-equiv="refresh" content="120">
</head>
<body>
<header class="topbar">
@@ -32,6 +31,7 @@
<footer>
EPI-Support-Monitor · liest <code>{{ zammad_url }}</code> · Seite aktualisiert sich automatisch
</footer>
<script src="{{ url_for('static', filename='app.js') }}"></script>
{% block scripts %}{% endblock %}
</body>
</html>
+2 -2
View File
@@ -9,7 +9,7 @@
<form method="post" action="{{ url_for('new_ticket_preview') }}"
class="form attach-form" enctype="multipart/form-data">
<label>Titel / Betreff
<input type="text" name="title" required maxlength="200"
<input type="text" name="title" required maxlength="200" data-draft
placeholder="Kurze Zusammenfassung des Anliegens">
</label>
<label>Gruppe
@@ -20,7 +20,7 @@
</select>
</label>
<label>Nachricht
<textarea name="body" rows="10" required
<textarea name="body" rows="10" required data-draft
placeholder="Beschreibe dein Anliegen… (Screenshot mit Strg+V einfügen)"></textarea>
</label>
{% include "_attach.html" %}
+11 -1
View File
@@ -20,6 +20,16 @@
<div><dt>zuletzt geändert</dt><dd>{{ ticket.zammad_updated_at|dt }}</dd></div>
<div><dt>geschlossen</dt><dd>{{ ticket.last_close_at|dt }}</dd></div>
</dl>
<form method="post" action="{{ url_for('set_state', ticket_id=ticket.id) }}" class="state-form">
<label for="state_id">Status ändern:</label>
<select id="state_id" name="state_id">
{% for s in settable_states %}
<option value="{{ s.id }}" {{ 'selected' if s.id == ticket.state_id }}>{{ s.label }}</option>
{% endfor %}
</select>
<button class="btn-sm" type="submit">setzen</button>
<span class="hint-inline">wirkt live in Zammad</span>
</form>
</section>
<section class="panel">
@@ -75,7 +85,7 @@
{% if ticket.state != 'closed' %}
<form method="post" action="{{ url_for('reply_preview', ticket_id=ticket.id) }}"
class="reply-form attach-form" enctype="multipart/form-data">
<textarea name="body" rows="4" required
<textarea name="body" rows="4" required data-draft
placeholder="Antwort an den EPI-Support verfassen… (Screenshot mit Strg+V einfügen)"></textarea>
{% include "_attach.html" %}
<div class="form-actions">