58 Commits
Author SHA1 Message Date
admin.juergenandClaude Fable 5 fa0bbaa73c Default new questions to optional and add opt-in thumb icons for yes/no
Two customer decisions from the September feedback round:

- New questions are now optional by default; the mandatory checkbox is
  ticked deliberately (backend DCA default and frontend editor model).
  Existing questions, templates and duplication are unaffected.
- Yes/no/maybe questions get a per-question display option 'Antworten
  als Daumen darstellen' (showThumbs, e.g. for surveys with children):
  the reader renders thumb-up/down/sideways SVG icons above the answer
  labels. Purely presentational - answers are still stored, evaluated
  and exported as yes/no/maybe, and the 'Keine Antwort' card, jump
  hints and dim logic are unchanged. Icons are inline SVG in CI colors
  (no CDN). Requires contao:migrate for the new column.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v1.3.0
2026-09-11 11:38:55 +02:00
admin.juergenandClaude Fable 5 ab2dbfbc45 Add a restart button to the survey draft view
Pretesters had no way to leave or restart the draft view other than
clicking through every remaining question (customer pretest finding
no. 2). The preview keeps its state exclusively in hidden POST fields,
so a plain GET on the preview URL starts over at question 1 - the new
'Umfragenentwurf von vorn beginnen' button in the preview notice bar
links exactly there and is visible on every draft page including the
completion page. Jump marks remain deliberately unsupported so the
draft view keeps mirroring the real participation flow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v1.2.3
2026-09-08 15:28:00 +02:00
admin.juergenandClaude Fable 5 c885d2e4c4 Assign frontend duplicates to the duplicating member only
Duplicating a survey in the member area used to copy the source's full
editor-assignment list onto the copy. Because templates are assigned to
every member, every copy showed up in everyone's overview (customer
pretest finding no. 1, reconfirmed by Ms. Sturm on 2026-09-08 with a
template shared between two members).

A duplicate triggered from the member area (actor present) now belongs
exclusively to the member who created it and receives that member's
categories, mirroring createSurvey. Backend duplication (no actor) keeps
producing an exact 1:1 copy including all assigned members.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v1.2.2
2026-09-08 15:14:08 +02:00
admin.juergenandClaude Fable 5 965ce47d48 Redirect with a flash message instead of a 500 page on stale survey actions
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>
v1.2.1
2026-08-28 10:57:00 +02:00
admin.juergenandClaude Fable 5 024c97fce5 Clearer lost-password errors and a request-new-link action
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>
v1.2.0
2026-08-26 14:36:46 +02:00
admin.juergenandClaude Fable 5 6077832efc Honor the mandatory flag with explicit no-answer options
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>
2026-08-26 14:36:38 +02:00
admin.juergenandClaude Fable 5 1ceb0ad28e Normalize Quill's non-breaking spaces so rich-text descriptions wrap
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>
2026-08-26 14:36:28 +02:00
Claude Fable 5 a4ca026e82 Strip style/script/xml blocks and table structure before sanitizing pasted HTML
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v1.1.1
2026-08-22 13:16:11 +02:00
Claude Fable 5 d187f558b2 Name the survey list area 'Umfragen-Übersicht' and relabel back buttons
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v1.1.0
2026-08-22 12:47:40 +02:00
Claude Fable 5 f3f9dab184 Friendlier logged-out notice with session duration and login link
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 12:41:34 +02:00
Claude Fable 5 f181ab4f75 Mount rich-text editor outside the label to stop label clicks triggering the bold button
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 10:02:15 +02:00
Claude Fable 5 43e155bb72 Fix inherited bold weight in rich-text editor and entity display in backend list
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 09:57:03 +02:00
Claude Fable 5 a573321c1c Simplify reader header, fix bold/italic rendering, section title label in backend
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 09:25:24 +02:00
Claude Fable 5 833a8964cf Add topic sections, ordered inserts, rich-text descriptions and grouped results (Ausbaustufe 3)
- section content type with structure service, reader context and grouped results/PDF/Excel
- new questions append at the end (backend oncreate) and per-section add buttons
- rich-text descriptions: Quill 2 (frontend), reduced TinyMCE (backend), server-side whitelist sanitizer
- externalize inline assets, bundle Chart.js locally, harden debug access, validate range bounds

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 07:57:40 +02:00
Claude a9ffffbc78 Drop the confirmation field from the change password copy
The form asks for the new password once, not twice.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 20:50:14 +02:00
Claude 3a95ab9dcd Style the change password module
Add a template override for Contao's changePassword module with the
same card, explanatory copy and corporate design as the lost password
module.

The card rules keyed off .mod_lostPassword.block, which does not scale
to a third auth module. Move them to a .survey-auth-module class that
the overrides put on the wrapper themselves, so another auth module
needs one line and no new CSS.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 20:45:50 +02:00
Claude b339f73bbc Document password validation fork and PHP 8.4 requirement
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 19:01:39 +02:00
Claude d8891315f9 Style password reset flow and send corporate design mails
Give the lost password module the same centred card as the login,
right-align the reset link, add explanatory copy and a way back to
the login from every dead end Contao routes through mod_message.

Contao only sets a text body on the opt-in mail, so a MessageEvent
listener adds an HTML alternative in the corporate design. It reads
the locale from the fallback root page because mails can go out from
a CLI worker, where kernel.default_locale is "en".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 16:08:58 +02:00
admin.juergenandClaude Opus 4.8 4fe142422a Warn on leaving the editor with unsaved changes
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>
2026-07-05 20:24:09 +02:00
admin.juergenandClaude Opus 4.8 954a5102ac Refine range results and restore new-tab view links
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>
2026-07-05 20:15:05 +02:00
admin.juergenandClaude Opus 4.8 c7439e4822 Fix customer-reported survey results and list issues
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>
2026-07-05 19:30:34 +02:00
Jürgen MummertandClaude Opus 4.8 788f5ccde0 Widen assigned-members checkbox wizard to 6 columns
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 22:36:07 +02:00
Jürgen MummertandClaude Opus 4.8 5f9a77d5bd Set tstamp on record inserts/updates
Questions, editor assignments and conditions were inserted without tstamp,
so Contao rendered them with tstamp=0 -> the backend "draft" styling
(opacity .5), making question rows look greyed out despite being published.

- SurveyQuestionRepository::insert()/update() (covers create, edit, duplicate)
- SurveyEditorRepository::insert()
- SurveyConditionRepository::insert()
SurveyRepository already set tstamp. Also widened the assigned-members
checkbox-wizard columns at smaller breakpoints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v1.0.0
2026-06-14 22:31:25 +02:00
Jürgen MummertandClaude Opus 4.8 d6227d9f4e Remove dead condition-editing code
The frontend condition create/edit path was never wired (no caller, no UI).
Conditions stay live where used: the SurveyFlowService reads tl_survey_condition
for jumps, the editor shows the read-only overview, and delete still works.

Removed:
- SurveyConditionEditorType (zero references)
- SurveyEditorService::saveCondition() + its SurveyConditionData import
- SurveyConditionData form model
- SurveyConditionRepository::update() (only caller was saveCondition)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 13:23:11 +02:00
Jürgen MummertandClaude Opus 4.8 db7094fd1e Fix frontend CSRF, clean reader URLs, and review findings
CSRF / actions:
- List action forms now send both REQUEST_TOKEN (Contao gate) and _token
  (Symfony, validated via isCsrfTokenValid) — mirrors the editor; fixes
  the 400/500 "Ungültiger CSRF-Token" on publish/toggle/duplicate/delete

Public reader / URLs:
- Reader & results read auto_item via Input::get (marks the route param used)
  so clean path URLs /<page>/<alias> no longer 404
- List controller generates path URLs via ['parameters' => '/'.$alias]
- Allow re-participation in the same session after a 60s cooldown

Review fixes:
- Results: merge answer snapshots by questionId+type (no more split cards on
  label edits); seed "Vielleicht" when allowMaybe so screen matches Excel
- Reader: replace generic answer hint with per-option "weiter zu Frage X"
  only when a jump is configured; strip HTML tags from survey description
- PDF: render free-text frequency summary; drop duplicate "Minimum" label
- Drag-sort: bundle SortableJS locally, drop the duplicated inline sort CSS/JS
  from _survey_assets, throttle the backend MutationObserver
- Backend: move hardcoded tl_survey operation labels to TL_LANG (de+en)
- Remove dead code: SurveyEditorVoter, SurveyPermissionService,
  categoryFilter/categorySummary + helpers, orphaned publishSurvey lang key

Reader layout:
- max-width 1000px (other views keep 1400px); back/next buttons fill the
  width as equal, card-sized halves; sort handle icon offset tweak

Docs: update AI_HANDOVER (dual-token CSRF, clean URLs) and README

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 13:00:05 +02:00
Jürgen Mummert 1b16675ae9 Add survey question drag-sort and backend assets
- Frontend editor: drag-to-sort questions with dedicated sort assets/JS
- Backend list/search refinements for tl_survey and tl_survey_content
- Repository helpers for survey/question/editor queries
- Translations and AI handover notes update
2026-06-14 09:13:07 +02:00
Jürgen Mummert 79c4402aee Fix survey reader back flow 2026-06-08 20:14:57 +02:00
Jürgen Mummert e3553e1108 Differentiate survey template shell 2026-06-08 20:05:58 +02:00
Jürgen Mummert 99caf51af9 Refine survey template module layout 2026-06-08 20:01:08 +02:00
Jürgen Mummert 7843fca003 Add survey template list module 2026-06-08 19:45:20 +02:00
Jürgen Mummert 9cc2f98456 Adjust survey action alignment 2026-06-08 19:23:14 +02:00
Jürgen Mummert d44f3be571 Add survey duplication actions 2026-06-08 14:06:32 +02:00
Jürgen Mummert 97a302a985 Document frontend/backend publication trade-off 2026-06-07 22:32:48 +02:00
Jürgen Mummert 809c30e5b5 Add AI handover documentation survey-freeze-2026-06-07 2026-06-07 22:26:47 +02:00
Jürgen Mummert b7bcdd8372 Clean up obsolete survey editor and DCA code 2026-06-07 22:16:37 +02:00
Jürgen Mummert 497b4f962d Fix backend survey action labels 2026-06-07 21:45:42 +02:00
Jürgen Mummert 4b82d70117 Restore backend survey publish and active controls 2026-06-07 21:29:04 +02:00
Jürgen Mummert 4f3fc0e697 Restore backend active toggle field 2026-06-07 21:21:38 +02:00
Jürgen Mummert 132ca6b80a Polish survey list actions and backend toggle 2026-06-07 21:09:36 +02:00
Jürgen Mummert fb9a5b9ee6 Refine survey list layout and backend active toggle 2026-06-07 20:52:57 +02:00
Jürgen Mummert 59514c6911 Separate survey list controls from editor view 2026-06-07 20:31:31 +02:00
Jürgen Mummert 1174410c1b Refine survey editor workflow and publication handling 2026-05-29 10:19:19 +02:00
Jürgen Mummert 6bbded4181 Adjust fixed logout navigation styling 2026-05-25 16:09:12 +02:00
Jürgen Mummert a893078945 Refine survey editor flow and auth styling 2026-05-25 16:02:47 +02:00
Jürgen Mummert e204da60b6 Add German and English survey translations 2026-05-24 21:24:53 +02:00
Jürgen Mummert 6eec9ec537 Sanitize survey frontend and PDF output 2026-05-24 17:53:53 +02:00
Jürgen Mummert 64fc578d4c Adjust survey typography 2026-05-24 17:01:43 +02:00
Jürgen Mummert 003508a841 Increase survey spacing 2026-05-24 16:56:47 +02:00
Jürgen Mummert 26e2df1425 Fix Firefox survey overflow 2026-05-24 16:52:57 +02:00
Jürgen Mummert 0be3f3b59c Refine survey page gutters 2026-05-24 16:49:44 +02:00