Actions from outdated tabs (survey deleted meanwhile, assignment revoked,
session expired) hit guard clauses that threw RuntimeException and produced
an HTTP 500 error page - seen 11x during the customer pretest on 2026-08-27
(duplicate on a deleted survey, edit link to a deleted survey). All frontend
guards now add a clear flash message and redirect to a freshly loaded view:
- list actions: distinct messages for deleted survey, revoked assignment,
expired session, unknown action
- editor: resolveSurvey redirects to the survey overview; editor POST with
invalid token redirects back to the editor
- reader/preview back button: reload the current question instead of failing
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every stale reset link produced a bare 'Ungültiges Token', which sent
users into a loop of requesting ever more e-mails. The overridden core
messages now explain that only the link from the newest e-mail counts,
the auth message template offers a direct 'Neuen Link anfordern' button,
and the change-password page asks for the 'Aktuelles Passwort' with a
hint covering freshly reset passwords.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Symfony's required default forced an answer to every question no matter
what the mandatory checkbox said. Optional choice questions now offer a
dedicated 'Keine Antwort' option, optional range and text questions a
'Keine Angaben machen' checkbox (preselected for ranges, because a slider
always submits a value); the side that is not chosen gets dimmed but stays
clickable. Mandatory ranges start their value display at '?' and reject
the submit until the slider was actually used, so the browser's midpoint
default no longer leaks into the results.
Empty answers are stored as a deliberate 'no answer', kept out of counts,
averages and charts, and reported separately on the results page and in
the PDF export. Also gives the reader textarea its full width and field
styling, adds grid overflow guards for unbreakable content and styles the
form error box.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Quill 2's getSemanticHTML() serializes every space as U+00A0, turning a
whole paragraph into one unbreakable word that stretched the survey cards
far past the viewport. Normalize to plain spaces when sanitizing (which
also heals existing records on every output) and when the editor writes
the serialized HTML back into the textarea.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ergänzt einen beforeunload-Handler im Frontend-Editor: Beim Verlassen der
Seite (Link, Zurück, Tab schließen) wird gewarnt, sobald mindestens ein
Editor-Formular ungespeicherte Änderungen hat. Der Handler koppelt an die
bestehende Dirty-Erkennung (data-survey-dirty-form) und wird nur
registriert, wenn solche Formulare existieren – also nur im Editor, nicht
in Liste/Reader/Ergebnissen.
Ein bewusstes Absenden (Speichern oder Aktion) setzt über einen globalen
submit-Listener ein Flag, sodass der normale Speicher-Flow nicht warnt.
Bewusst kein Auto-Save (getrennte Formulare mit eigenen CSRF-Tokens,
Struktur-Sperre nach Teilnahmen/Veröffentlichung); Dirty-Hinweis plus
beforeunload sind der risikoarme Kompromiss.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Zweite Runde Kundenrückmeldung:
- Range-Ergebnisse: Das Diagramm behält die komplette lineare Skala
(rangeMin..rangeMax), aber die Werte-Liste/Tabelle zeigt nur noch die
tatsächlich beantworteten Werte. Sonst würde eine große Skala (z. B. Alter
1-100, Schrittweite 1) die Ergebnisseite mit hunderten Nullzeilen fluten.
Neues Feld distributionRows für die Liste; distribution bleibt fürs Diagramm.
- Große Skalen: X-Achsenbeschriftung wird ausgedünnt (Chart.js autoSkip/
maxTicksLimit, SVG jede n-te Beschriftung), Punkt-Marker verkleinert bzw.
ab >40 Punkten weggelassen. Auch die Y-Ticks im PDF-SVG werden gedeckelt.
- PDF-Range-Tabelle ohne Farb-Swatch-Spalte (nur Wert/Anzahl/Anteil), da die
Kopplung an ein Vollskalen-Diagramm nicht mehr sinnvoll ist.
- Aktionslinks in der Frontend-Liste: Öffentliche Ansicht, Entwurfs-Ansicht
und Ergebnisse anzeigen öffnen wieder im neuen Fenster (target=_blank);
nur Bearbeiten bleibt im selben Tab.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Behebt die Fehler aus der Kunden-Testrunde (Praktikantin, Juli 2026):
- Ergebnisreihenfolge: Fragen werden vor dem Finalisieren nach _sorting
sortiert. finalizeQuestionResult entfernt _sorting, daher fiel die
bisherige Nachsortierung auf den alphabetischen Fallback zurück. Online,
PDF und Excel folgen jetzt derselben Frage-Sortierung.
- Excel-Export: Eigene Fragetext-Zeile über den Antwortspalten (je Frage
über die zugehörigen Spalten zusammengeführt). Zuvor fehlte der Fragetext.
- Range-Ergebnis: Verteilung deckt die komplette Skala rangeMin..rangeMax in
rangeStep-Schritten ab, damit die X-Achse linear und vollständig ist
(vorher nur tatsächlich vorkommende Werte in gleichen Abständen).
- Teilnahmen/Rücklauf pro Frage als absolute Zahlen ("X von Y beantwortet",
"Z übersprungen") statt reiner Prozent-Rücklaufquote.
- Freitextantworten gruppiert: jede Antwort einmal mit exakter Häufigkeit,
ohne Prozentangaben und ohne Doppel-Auflistung.
- Frontend-Liste: "Link kopieren"-Button (absolute Reader-URL) für
veröffentlichte Umfragen; Aktiv-Umschalter mit Textlabel statt nur Punkt;
Aktionslinks öffnen im selben Tab statt in neuen Tabs.
- Duplizieren: Titel-Kollisionsprüfung ohne Ausschluss der Quell-ID, damit
aus "... - Kopie" korrekt "... - Kopie 2" wird statt eines Dubletten-Titels.
Der internalNote-Fehler beim Anlegen/Duplizieren war ein fehlendes
DB-Schema-Update (Spalte tl_survey.internalNote) und wurde per
contao:migrate auf der Testumgebung nachgezogen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>