Fehler melden mit Screenshot und Markierung, Sammlung für Bearbeiter

Käfer-Button unten rechts: nimmt den sichtbaren Bildschirm mit html2canvas
(selbst gehostet) auf, Vorschau mit roten Rechtecken, Beschreibung, Name
optional, Senden ohne Anmeldung. Aus offenen Dialogen heraus wird der
Dialog selbst aufgenommen. Bearbeiter sehen die Meldungen unter „Fehler"
mit Zähler, kopieren einen fertigen Claude-Prompt und den Screenshot.

Serverseitig: Pfade nur in exakter Schreibweise, /api standardmäßig nur
für Bearbeiter mit ausdrücklicher Freigabeliste, Bremse zählt jeden
Versuch vor dem Lesen großer Bodies, X-Forwarded-For nur von vertrauten
Proxys, Nutzertext im Prompt eingezäunt. HTTP-Tests für die Sperren.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
ferdi2goandClaude Fable 5.1 committed 2026-10-15 08:19:46 +00:00
1 parent 6a3c68aaac
commit 4ec23ccd25
15 files changed
+877 -36

No files matched your search

+43 -6
View File
@@ -17,6 +17,7 @@
<a href="#personen" data-view="personen">Personen</a>
<a href="#abwesenheiten" data-view="abwesenheiten">Abwesenheiten</a>
<a href="#anfragen" data-view="anfragen">Anfragen <span id="requests-count" class="count" hidden></span></a>
<a href="#fehler" data-view="fehler">Fehler <span id="bugs-count" class="count" hidden></span></a>
<a href="#einstellungen" data-view="einstellungen">Einstellungen</a>
</nav>
<button type="button" id="auth-button" class="topbar-action" hidden>Anmelden</button>
@@ -157,6 +158,16 @@
<ul id="request-list-done" class="list" hidden></ul>
</section>
<!-- Fehlermeldungen (nur Bearbeiter) -->
<section id="view-fehler" class="view" hidden aria-labelledby="bugs-title">
<h2 id="bugs-title">Fehlermeldungen</h2>
<p class="hint">Gemeldet über den Käfer-Button unten rechts. „Prompt kopieren" legt eine fertige Anweisung für Claude in die Zwischenablage, „Screenshot kopieren" das Bild dazu. Beides zusammen in Claude Code einfügen, dann wird der Fehler direkt bearbeitet.</p>
<p class="hint" id="bugs-clipboard-hint" hidden>Diese Adresse ist nicht verschlüsselt (http). Bilder kann der Browser hier nicht direkt in die Zwischenablage legen: „Screenshot öffnen" nutzen und dort mit Rechtsklick „Bild kopieren" wählen. Über eine https-Adresse geht es mit einem Klick.</p>
<ul id="bug-list" class="list bug-list"></ul>
<label class="inline" id="bugs-toggle"><input type="checkbox" id="bugs-show-done"> Erledigte anzeigen</label>
<ul id="bug-list-done" class="list bug-list" hidden></ul>
</section>
<!-- Einstellungen -->
<section id="view-einstellungen" class="view" hidden aria-labelledby="settings-title">
<h2 id="settings-title">Einstellungen</h2>
@@ -167,6 +178,8 @@
<label>Fairness-Fenster in Tagen <input type="number" name="historyWindowDays" min="0" max="365"></label>
<label>Kalendername in Nextcloud <input name="calendarDisplayName" maxlength="60"></label>
<label class="inline wide"><input type="checkbox" name="inviteAttendees"> Moderatoren als Teilnehmer eintragen (E-Mail nötig; Nextcloud verschickt dann Einladungen)</label>
<label class="wide">Vorlage für den Fehler-Prompt <textarea name="bugPromptTemplate" rows="7" maxlength="4000"></textarea></label>
<p class="hint">Platzhalter: {text} Beschreibung, {reporter} Name, {date} Zeitpunkt, {page} Ansicht, {browser}, {viewport}, {version}, {url}. Leer lassen stellt die Vorlage wieder her.</p>
<div class="form-actions"><button type="submit" class="primary">Speichern</button></div>
</form>
@@ -192,7 +205,7 @@
<!-- Dialog: Tag bearbeiten -->
<dialog id="day-dialog">
<form method="dialog" class="dialog-form" id="day-form">
<h2 id="day-dialog-title">Tag</h2>
<div class="dialog-head"><h2 id="day-dialog-title">Tag</h2><button type="button" class="ghost icon-button dialog-bug" aria-label="Fehler in diesem Dialog melden" title="Fehler melden"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="6.5" r="2.5"/><path d="M7 14a5 5 0 0 1 10 0v2a5 5 0 0 1-10 0z"/><path d="M12 9v12"/><path d="M7 13H3.5"/><path d="M7 17H4l-1 2.5"/><path d="M17 13h3.5"/><path d="M17 17h3l1 2.5"/><path d="M8.5 9.5 5.5 7"/><path d="M15.5 9.5 18.5 7"/></svg></button></div>
<p id="day-dialog-info" class="hint"></p>
<label>Hauptmoderation <select name="main"></select></label>
<label>Nebenmoderation <select name="co"></select></label>
@@ -211,7 +224,7 @@
<!-- Dialog: Auslosen -->
<dialog id="plan-dialog">
<form method="dialog" class="dialog-form" id="plan-form">
<h2>Moderation auslosen</h2>
<div class="dialog-head"><h2>Moderation auslosen</h2><button type="button" class="ghost icon-button dialog-bug" aria-label="Fehler in diesem Dialog melden" title="Fehler melden"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="6.5" r="2.5"/><path d="M7 14a5 5 0 0 1 10 0v2a5 5 0 0 1-10 0z"/><path d="M12 9v12"/><path d="M7 13H3.5"/><path d="M7 17H4l-1 2.5"/><path d="M17 13h3.5"/><path d="M17 17h3l1 2.5"/><path d="M8.5 9.5 5.5 7"/><path d="M15.5 9.5 18.5 7"/></svg></button></div>
<label>Von Monat <input type="month" name="from" required></label>
<label>Bis Monat <input type="month" name="to" required></label>
<label class="inline"><input type="checkbox" name="overwrite"> Bereits ausgeloste, nicht fixierte Tage neu auslosen</label>
@@ -229,7 +242,7 @@
<!-- Dialog: Nextcloud -->
<dialog id="nextcloud-dialog">
<form method="dialog" class="dialog-form" id="nextcloud-form">
<h2>In Nextcloud schreiben</h2>
<div class="dialog-head"><h2>In Nextcloud schreiben</h2><button type="button" class="ghost icon-button dialog-bug" aria-label="Fehler in diesem Dialog melden" title="Fehler melden"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="6.5" r="2.5"/><path d="M7 14a5 5 0 0 1 10 0v2a5 5 0 0 1-10 0z"/><path d="M12 9v12"/><path d="M7 13H3.5"/><path d="M7 17H4l-1 2.5"/><path d="M17 13h3.5"/><path d="M17 17h3l1 2.5"/><path d="M8.5 9.5 5.5 7"/><path d="M15.5 9.5 18.5 7"/></svg></button></div>
<p id="nextcloud-info" class="hint"></p>
<label>Zielkalender
<select name="target"><option value="">– Kalender laden …</option></select>
@@ -251,7 +264,7 @@
<!-- Dialog: Kontakte importieren -->
<dialog id="contacts-dialog">
<form method="dialog" class="dialog-form" id="contacts-form">
<h2>Personen aus Nextcloud</h2>
<div class="dialog-head"><h2>Personen aus Nextcloud</h2><button type="button" class="ghost icon-button dialog-bug" aria-label="Fehler in diesem Dialog melden" title="Fehler melden"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="6.5" r="2.5"/><path d="M7 14a5 5 0 0 1 10 0v2a5 5 0 0 1-10 0z"/><path d="M12 9v12"/><path d="M7 13H3.5"/><path d="M7 17H4l-1 2.5"/><path d="M17 13h3.5"/><path d="M17 17h3l1 2.5"/><path d="M8.5 9.5 5.5 7"/><path d="M15.5 9.5 18.5 7"/></svg></button></div>
<label>Adressbuch <select name="addressbook"></select></label>
<p id="contacts-info" class="hint">Lade Kontakte …</p>
<div class="contacts-tools">
@@ -271,7 +284,7 @@
<!-- Dialog: Tausch anfragen (für alle) -->
<dialog id="request-dialog">
<form method="dialog" class="dialog-form" id="request-form">
<h2>Tausch anfragen</h2>
<div class="dialog-head"><h2>Tausch anfragen</h2><button type="button" class="ghost icon-button dialog-bug" aria-label="Fehler in diesem Dialog melden" title="Fehler melden"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="6.5" r="2.5"/><path d="M7 14a5 5 0 0 1 10 0v2a5 5 0 0 1-10 0z"/><path d="M12 9v12"/><path d="M7 13H3.5"/><path d="M7 17H4l-1 2.5"/><path d="M17 13h3.5"/><path d="M17 17h3l1 2.5"/><path d="M8.5 9.5 5.5 7"/><path d="M15.5 9.5 18.5 7"/></svg></button></div>
<p id="request-info" class="hint"></p>
<label>Ich bin <select name="personId" required></select></label>
<label>Tag, an dem ich nicht kann <input type="date" name="date" required></label>
@@ -290,7 +303,7 @@
<!-- Dialog: Anmelden zum Bearbeiten -->
<dialog id="login-dialog">
<form method="dialog" class="dialog-form" id="login-form">
<h2>Zum Bearbeiten anmelden</h2>
<div class="dialog-head"><h2>Zum Bearbeiten anmelden</h2><button type="button" class="ghost icon-button dialog-bug" aria-label="Fehler in diesem Dialog melden" title="Fehler melden"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="6.5" r="2.5"/><path d="M7 14a5 5 0 0 1 10 0v2a5 5 0 0 1-10 0z"/><path d="M12 9v12"/><path d="M7 13H3.5"/><path d="M7 17H4l-1 2.5"/><path d="M17 13h3.5"/><path d="M17 17h3l1 2.5"/><path d="M8.5 9.5 5.5 7"/><path d="M15.5 9.5 18.5 7"/></svg></button></div>
<p class="hint">Ansehen kann jeder. Auslosen, Personen, Abwesenheiten und Nextcloud erfordern das Bearbeitungspasswort.</p>
<label>Passwort <input type="password" name="password" id="login-password" autocomplete="current-password" required></label>
<p id="login-result" class="result error" hidden></p>
@@ -302,7 +315,31 @@
</form>
</dialog>
<!-- Fehler melden: Käfer-Button und Panel, für alle sichtbar -->
<div id="bug-widget">
<button type="button" id="bug-button" class="bug-button" aria-label="Fehler melden" title="Fehler melden" aria-expanded="false" aria-controls="bug-panel"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="6.5" r="2.5"/><path d="M7 14a5 5 0 0 1 10 0v2a5 5 0 0 1-10 0z"/><path d="M12 9v12"/><path d="M7 13H3.5"/><path d="M7 17H4l-1 2.5"/><path d="M17 13h3.5"/><path d="M17 17h3l1 2.5"/><path d="M8.5 9.5 5.5 7"/><path d="M15.5 9.5 18.5 7"/></svg></button>
<dialog id="bug-panel" class="bug-panel" aria-labelledby="bug-title">
<h2 id="bug-title">Fehler melden</h2>
<p id="bug-status" class="hint">Bildschirm wird aufgenommen …</p>
<div class="bug-shot" id="bug-shot" hidden>
<canvas id="bug-canvas" aria-label="Screenshot der Seite. Markiere die Stelle mit einem roten Rechteck."></canvas>
</div>
<p class="hint bug-shot-hint" id="bug-shot-hint" hidden>Ziehe ein rotes Rechteck auf, um die Stelle zu markieren. <button type="button" class="link" id="bug-clear-marks" hidden>Markierungen entfernen</button></p>
<form id="bug-form" class="bug-form" autocomplete="off">
<label>Was läuft falsch? <textarea name="text" id="bug-text" rows="3" maxlength="2000" required placeholder="z. B. Beim Klick auf Auslosen passiert nichts"></textarea></label>
<label>Dein Name (optional) <input name="reporter" id="bug-reporter" maxlength="80" autocomplete="name"></label>
<p id="bug-result" class="result" hidden></p>
<div class="form-actions">
<span class="spacer"></span>
<button type="button" class="ghost" id="bug-cancel">Abbrechen</button>
<button type="submit" class="primary" id="bug-submit">Senden</button>
</div>
</form>
</dialog>
</div>
<div id="toast" class="toast" role="status" aria-live="polite" hidden></div>
<script src="vendor/html2canvas.min.js" defer></script>
<script type="module" src="app.js"></script>
</body>
</html>