Files
survey-bundle/AI_HANDOVER.md
T
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

17 KiB

Survey Bundle AI Handover

Diese Datei beschreibt den aktuell gewünschten und umgesetzten Stand des Bundles. Ziel ist, dass ein KI-Modell oder ein neuer Bearbeiter die Logik, die Zustände und die wichtigsten Einstiegspunkte schnell versteht und darauf weiterarbeiten kann.

Zweck des Bundles

Das Bundle stellt ein Contao-Umfragesystem bereit mit:

  • Frontend-Liste für Redakteure
  • Frontend-Frageneditor
  • Öffentlicher Umfrageansicht über Alias-Link
  • Ergebnisseite im Frontend
  • Excel-Export der Ergebnisse
  • PDF-Export der Ergebnisse über Gotenberg
  • Backend-Verwaltung in Contao-DCA-Listen und Editmasken

Zentrale Zustandsfelder

Die Umfrage arbeitet mit drei relevanten Zuständen in tl_survey:

  • published

    • Fachlich: Die Umfrage wurde veröffentlicht.
    • Frontend: Ab Veröffentlichung darf der Redakteur im Frontend weder Fragen noch Metadaten bearbeiten.
    • Backend: Reversibel erlaubt. Der Admin darf den Status im Backend ändern.
  • isActive

    • Fachlich: Öffentliche Sichtbarkeit an/aus.
    • Gilt unabhängig vom Veröffentlichungsstatus als technischer Sichtbarkeitszustand.
    • Der öffentliche Reader liefert nur Umfragen aus, die published = 1 und isActive = 1 haben.
  • isLocked

    • Fachlich: Struktur wurde bereits benutzt oder veröffentlicht.
    • Wird automatisch gesetzt, wenn die erste Antwort gespeichert wird.
    • Wird beim Veröffentlichen ebenfalls gesetzt.
    • Im Backend gibt es bewusst keine harte Sperre mehr. Das Feld dient vor allem der internen Logik und Historie.

Gewollte Produktentscheidung

  • Frontend ist streng:

    • Keine Fragenbearbeitung nach Veröffentlichung
    • Keine Metadatenbearbeitung nach Veröffentlichung
    • Keine Fragenbearbeitung nach ersten Teilnahmen
  • Die Frontend-Sperre für veröffentlichte Umfragen soll bewusst nicht tief im System verankert sein.

    • Für Redakteure genügt das Ausblenden bzw. Deaktivieren der relevanten Buttons und Formulare im Frontend.
    • Es ist ausdrücklich keine zusätzliche harte Systembarriere gewünscht, solange die Redakteursoberfläche den Bearbeitungspfad sauber schließt.
  • Backend ist bewusst toleranter:

    • Ein einzelner Admin darf im Notfall weiter arbeiten
    • Statt harter Sperre gibt es nur einen Warnhinweis in der Liste bei veröffentlichten Umfragen
    • published ist im Backend editierbar
    • isActive ist im Backend per Contao-Toggle schaltbar
  • Bewusster Trade-off zwischen Frontend und Backend:

    • Ein veröffentlichter Survey soll für Frontend-Redakteure praktisch nicht mehr bearbeitbar sein.
    • Im Backend darf der Admin trotz Veröffentlichung weiterhin Änderungen vornehmen, zum Beispiel für Rechtschreibfehler oder kleine Korrekturen.
    • Dadurch bleibt bewusst das Risiko bestehen, dass der Admin auch Fragen oder Strukturen ändert, obwohl bereits Antworten vorliegen.
    • Mögliche Folgen sind verwässerte oder fachlich falsche Ergebnisseiten sowie Inkonsistenzen, wenn bestehende Antworten nicht mehr sauber zur später geänderten Struktur passen.
    • Dieses Risiko wird bewusst akzeptiert und organisatorisch über Briefing/Disziplin des Admins bzw. der zuständigen Redakteure abgefangen, nicht über eine harte technische Sperre im Backend.

Diese Entscheidung ist absichtlich so getroffen und kein Bug.

Datenmodell und wichtige Tabellen

  • tl_survey
    • Umfrage-Stammdaten und Statusfelder
    • Enthält zusätzlich die backend-only gepflegte internalNote
  • tl_survey_content
    • Fragen der Umfrage
  • tl_survey_condition
    • Generische Sprungregeln
  • tl_survey_editor
    • Zugewiesene Frontend-Redakteure
  • tl_survey_submission
    • Umfrage-Durchläufe
  • tl_survey_answer
    • Gespeicherte Antworten inklusive Snapshot-Feldern zur Ergebnisstabilität

Wichtige Snapshot-Felder in tl_survey_answer:

  • questionType
  • questionLabel
  • questionDescription
  • questionSorting

Diese Felder sorgen dafür, dass Ergebnisse auch dann stabil bleiben, wenn Fragen später im Backend verändert oder gelöscht wurden.

Frontend-Module und Controller

1. Redakteursliste

Controller:

  • src/Controller/FrontendModule/MemberSurveyListController.php

Template:

  • contao/templates/frontend/member_survey_list.html.twig

Zweck:

  • Zeigt alle dem eingeloggten Frontend-Mitglied zugewiesenen Umfragen
  • Sortierung ist bewusst fest auf Titel ASC
  • Hier liegen die Redakteursaktionen zur Veröffentlichung und Aktivierung

Aktuelle Button- und Sichtbarkeitslogik pro Umfrage:

  • Bearbeiten
    • Nur klickbar, solange published = 0
    • Nach Veröffentlichung disabled
  • Öffentliche Ansicht
    • Nur sichtbar, wenn published = 1
  • Entwurfs-Ansicht
    • Nur sichtbar, wenn published = 0
  • Ergebnisse anzeigen
    • Immer verfügbar, sofern Results-Seite konfiguriert ist
  • Umfrage veröffentlichen
    • Eigene Aktion in der Liste
    • Nach Veröffentlichung disabled und textlich als veröffentlicht markiert
  • Duplizieren
    • Legt eine Kopie der Umfrage für den Redakteur an
    • Titelvergabe ist fortlaufend: Titel - Kopie, danach Titel - Kopie 2, Titel - Kopie 3 usw.
    • Bestehende - Kopie-Suffixe werden fachlich normalisiert, damit keine Titel wie ... - Kopie - Kopie mehr neu entstehen
  • Kreis grau/grün
    • Schaltet isActive
    • Ist bewusst kein Auge mehr

Wichtiger technischer Punkt:

  • Die Frontend-Listenaktionen arbeiten nur noch mit dem Contao-REQUEST_TOKEN plus Berechtigungsprüfung.
    • Die zusätzliche Symfony-Aktions-CSRF-Prüfung wurde bewusst entfernt, weil sie in diesem Frontend-Flow zu ungültigen Tokens führte.

2. Frontend-Editor

Controller:

  • src/Controller/FrontendModule/MemberSurveyEditController.php

Template:

  • contao/templates/frontend/member_survey_edit.html.twig

Zweck:

  • Anlegen neuer Umfragen
  • Bearbeiten der Metadaten vor Veröffentlichung
  • Bearbeiten der Fragenstruktur

Aktueller Aufbau:

  • Bei neuer Umfrage:
    • Titel und Beschreibung
  • Bei bestehender, nicht veröffentlichter Umfrage:
    • Metadatenformular oberhalb des Frageneditors
    • Frage-für-Frage-Editor im Akkordeon
    • Neue Frage anlegen
    • Sprungregelübersicht rechts/unten je nach Breakpoint
  • Bei veröffentlichter Umfrage oder bei isLocked = 1:
    • Fragen im Frontend nicht mehr änderbar
    • Metadaten im Frontend ebenfalls nicht mehr bearbeitbar

Wichtige Entscheidung:

  • Die Header-Badges im Fragen-Akkordeon wurden bewusst entfernt.

    • Typ, Pflicht usw. sollen nicht schon im Header gezeigt werden.
    • Die Details sieht man erst nach dem Aufklappen.
  • Die Sprungziel-Dropdowns im Frontend zeigen Positionsnummern der Umfrage (1. ..., 2. ...) statt globaler Datenbank-IDs.

    • Die aktuell bearbeitete Frage wird dort nicht als eigenes Sprungziel angeboten.

3. Öffentliche Umfrageansicht

Controller:

  • src/Controller/FrontendModule/ShowSurveyController.php

Services:

  • src/Service/SurveyFlowService.php
  • src/Service/SurveySubmissionService.php

Zweck:

  • Öffentliche Teilnahme an Umfragen
  • Zusätzlich Entwurfsansicht per ?preview=1

Wichtige Regeln:

  • Öffentliche Ansicht findet eine Umfrage nur, wenn:
    • published = 1
    • isActive = 1
  • Entwurfsansicht arbeitet ohne Speicherung
  • Öffentliche Ansicht speichert Antworten und erstellt/führt Submission fort
  • Rückwärtsnavigation ist implementiert

4. Ergebnisseite

Controller:

  • src/Controller/FrontendModule/ShowSurveyResultsController.php

Service:

  • src/Service/SurveyResultsViewService.php

Template:

  • contao/templates/frontend/show_survey_results.html.twig

Zweck:

  • Aggregierte Auswertung pro Frage
  • Anzeige von Anzahl Teilnahmen, Rücklauf und Frageergebnissen

Aktuelle Ergebnislogik:

  • yes_no_maybe
    • Optionsstatistik plus Kreisdiagramm
  • choice
    • Optionsstatistik plus Kreisdiagramm
  • range
    • Minimum, Maximum, Durchschnitt plus Verteilung und Linienchart
  • text
    • Kein Pie-Chart
    • Stattdessen Response-Summary und Liste der Freitextantworten

Wichtig:

  • Die Ergebnisse werden aus den Antwort-Snapshots aufgebaut, nicht nur aus den aktuellen Fragen.
  • Dadurch bleiben historische Ergebnisse stabil.

Sprunglogik

Relevante Services/Repos:

  • src/Service/SurveyFlowService.php
  • src/Repository/SurveyConditionRepository.php
  • src/Controller/FrontendModule/MemberSurveyEditController.php

Reihenfolge der Navigation:

  1. Direkter Ja/Nein-Sprung über jumpOnYes / jumpOnNo
  2. Generische Bedingung aus tl_survey_condition
  3. Nächste Frage nach Sortierung

Wichtiger Detailpunkt:

  • In der Sprungregelübersicht im Frontend-Editor werden bewusst die Positionsnummern innerhalb der Umfrage angezeigt, nicht die globalen Datenbank-IDs der Fragen.
  • Gleiches gilt für die Sprungziel-Dropdowns in Backend und Frontend.

Wichtige technische Eigenschaft:

  • jumpOnYes, jumpOnNo und generische Bedingungen referenzieren Ziel-Fragen intern immer über die Frage-ID, nicht über die Position.
  • Dadurch bleiben Sprünge bei einer reinen Umordnung der Fragen fachlich stabil an dieselbe Frage gebunden.
  • Wenn eine Ziel-Frage an eine andere Position verschoben wird, zeigt die Oberfläche danach automatisch die neue Positionsnummer an.

Excel-Export

Controller:

  • src/Controller/SurveyResultsExportController.php

Service:

  • src/Service/SurveyResultsExportService.php

Bibliothek:

  • phpoffice/phpspreadsheet

Zweck:

  • Export aller abgeschlossenen Teilnahmen in eine XLSX-Datei

Aktuelle Spaltenlogik:

  • Ja/Nein/Vielleicht:
    • pro Antwortoption eigene Spalte
  • Choice:
    • pro Antwortoption eigene Spalte
  • Range:
    • eine Wertespalte
  • Text:
    • eine Textspalte

Wichtige Eigenschaft:

  • Die Spalten orientieren sich an den aktuell vorhandenen Fragen im Survey.
  • Die Zeilen enthalten nur abgeschlossene Submissions.

PDF-Export

Controller:

  • src/Controller/SurveyResultsExportController.php

Service:

  • src/Service/SurveyResultsPdfService.php

Template:

  • src/Resources/views/pdf/survey_results.html.twig

Externe Abhängigkeit:

  • Gotenberg über surveyGotenbergUrl in den Contao-Einstellungen

Zweck:

  • Serverseitiger PDF-Export der Ergebnisse

Aktuelle Logik:

  • HTML wird serverseitig mit Twig gerendert
  • Diagramme werden als SVG/Data-URI vorbereitet
  • Gotenberg rendert daraus das PDF
  • Ist keine Gotenberg-URL gesetzt, wird im Frontend kein PDF-Download angeboten

Backend-Aufbau

tl_survey

Dateien:

  • contao/dca/tl_survey.php
  • contao/languages/de/tl_survey.php
  • contao/languages/en/tl_survey.php

Wichtige Listenoperationen:

  • Fragen bearbeiten
  • Umfrage bearbeiten
  • isActive als Contao-Toggle
  • Warnsymbol bei veröffentlichten Umfragen
  • Link kopieren
  • Ergebnisse anzeigen

Aktuelle Listen- und Filterlogik:

  • Die mehrspaltige Umfragenliste zeigt aktuell:
    • Titel
    • Zugewiesene Benutzer
    • Vorlage
    • Interne Notiz
  • Kategorien wurden bewusst aus der mehrspaltigen Liste und aus der rechten Filterspalte entfernt.
  • Die Spalte Zugewiesene Benutzer wird in der Listenmetadatenlogik gekürzt:
    • maximal 3 Namen direkt sichtbar
    • danach Zusatz wie ... und X weitere
  • internalNote
    • backend-only Feld in tl_survey
    • nur im Backend bearbeitbar
    • in der mehrspaltigen Liste sichtbar
    • bei Duplikaten wird der Wert mitkopiert
  • In der rechten Suchspalte ist Interne Notiz suchbar.
  • ID wurde für die Umfragenliste bewusst aus dem Suchfeld entfernt.
    • Das geschieht über einen kleinen backend-spezifischen JS-Workaround, weil Contao id im Core für DC_Table hart ergänzt.

Aktuelle Backend-Entscheidung:

  • Das Warnsymbol genügt als Hinweis bei veröffentlichten Umfragen
  • Es gibt bewusst keine harte Sperre für Fragen im Backend

Child-Tabellen

  • tl_survey_content
  • tl_survey_condition
  • tl_survey_editor

Hinweis:

  • isLocked wird in den Child-Headerfeldern nicht mehr angezeigt, weil der Backend-Lock bewusst keine führende Benutzerfunktion mehr ist.
  • In tl_survey_content ist der Fragenlisten-Header zusätzlich reduziert:
    • nur noch Titel und Veröffentlicht
    • kein öffentlicher Link-Schlüssel mehr
    • die rechte Header-Leiste mit Aktionen ist im Normalzustand ausgeblendet
    • im aktiven Verschiebe-/Clipboard-Modus wird sie wieder eingeblendet, damit Neu oben bzw. die Einfügepositionen erreichbar bleiben

Fragenliste tl_survey_content:

  • Direkt sichtbare Primäraktion pro Frage:
    • Bearbeiten-Stift
  • Verschieben:
    • erfolgt im Backend über den normalen Contao-Paste-/Move-Flow
    • die Aktion Verschieben liegt bewusst nur unter den drei Punkten
    • dort wird der Contao-Pfeil mover.svg verwendet, nicht die blaue Schere
    • nach Aktivierung des Clipboard-Zustands erscheinen die üblichen Einfügeziele wie Nach dem Element ... einfügen

Systemeinstellungen

Datei:

  • contao/dca/tl_settings.php

Wichtige Settings:

  • surveyReaderPage
  • surveyResultsPage
  • surveyGotenbergUrl

Aktuelle Produktregeln in Kurzform

  • Frontend-Liste:
    • Titel alphabetisch
    • Veröffentlichung und Aktivierung in der Liste
  • Frontend-Editor:
    • Metadaten nur vor Veröffentlichung
    • Fragenbearbeitung nur solange nicht veröffentlicht und keine Teilnahmen vorliegen
  • Öffentliche Ansicht:
    • Nur published = 1 und isActive = 1
  • Backend:
    • published reversibel erlaubt
    • isActive per Standard-Contao-Toggle
    • nur Warnsymbol statt Backend-Sperre
    • Admin darf Fragen auch nach Veröffentlichung oder nach vorhandenen Antworten umsortieren

Wichtige Dateien nach Themengebiet

Frontend-Liste:

  • src/Controller/FrontendModule/MemberSurveyListController.php
  • contao/templates/frontend/member_survey_list.html.twig

Frontend-Editor:

  • src/Controller/FrontendModule/MemberSurveyEditController.php
  • contao/templates/frontend/member_survey_edit.html.twig

Öffentliche Umfrage:

  • src/Controller/FrontendModule/ShowSurveyController.php
  • src/Service/SurveyFlowService.php
  • src/Service/SurveySubmissionService.php

Ergebnisse:

  • src/Controller/FrontendModule/ShowSurveyResultsController.php
  • src/Service/SurveyResultsViewService.php
  • contao/templates/frontend/show_survey_results.html.twig

Exporte:

  • src/Controller/SurveyResultsExportController.php
  • src/Service/SurveyResultsExportService.php
  • src/Service/SurveyResultsPdfService.php

Backend:

  • contao/dca/tl_survey.php
  • src/EventListener/SurveyDcaListener.php

Technische Validierung, die in diesem Projekt gut funktioniert

  • php -l auf die geänderten PHP-Dateien
  • ddev exec php bin/console lint:yaml ...
  • ddev exec php bin/console cache:clear

Offene technische Punkte / Deployment-Hinweise

  • Neue DB-Spalte in tl_survey:

    • internalNote
    • Typ aktuell: varchar(255) NOT NULL default ''
    • Für andere Umgebungen muss diese Spalte per Migration/SQL vorhanden sein, sonst fehlen Backend-Feld, Listenanzeige und Suchfunktion fachlich bzw. führen zu Inkonsistenzen.
  • Nach Änderungen an DCA, Backend-CSS oder Backend-JS ist in dieser Installation typischerweise nötig:

    • php vendor/bin/contao-console assets:install public --symlink --relative
    • php vendor/bin/contao-console cache:clear --env=prod
  • Es gibt aktuell zwei bewusst eingebaute backend-spezifische UI-Workarounds über Bundle-Assets:

    • In der Umfragenliste wird ID aus dem Suchfeld per JS entfernt, weil Contao das Feld im Core von DC_Table hart ergänzt.
    • In der Fragenliste (table=tl_survey_content) wird die rechte Parent-Header-Leiste per CSS/JS im Normalzustand ausgeblendet und nur im aktiven Clipboard-/Verschiebe-Modus wieder eingeblendet.
  • Lokale DDEV-Besonderheit, die bei Fehleranalyse relevant sein kann:

    • Das Bundle läuft hier als Path-Repository/Symlink.
    • Wenn Backend-Übersetzungen oder Assets trotz korrektem Code unerwartet fehlen, zuerst Bundle-Pfad, veröffentlichte Assets und Prod-Cache prüfen.

Bekannte bewusste Trade-offs

  • Backend kann veröffentlichte Umfragen technisch weiterhin verändern.
    • Das ist bewusst akzeptiert, weil nur ein Admin arbeitet.
  • isLocked bleibt als internes Logikfeld bestehen, obwohl der Backend-Lock nicht mehr durchgesetzt wird.
  • PDF-Export hängt von Gotenberg ab und ist absichtlich optional.
  • Eine reine Umordnung von Fragen ist für Sprungziele logisch unkritisch, weil Sprünge an Frage-IDs hängen.
  • Ergebnisse vorhandener, weiterhin existierender Fragen folgen bei der Anzeige jedoch der aktuellen Sortierung der Frage.
    • Historische Antwort-Snapshots speichern zwar questionSorting, die Ergebnisansicht sortiert vorhandene Fragen aber primär nach der aktuellen Frage-Sortierung.
    • Das ist im toleranten Backend-Modell ein bewusst akzeptierter Side-Effect.

Empfohlene Einstiegspunkte für künftige Änderungen

  • Status-/Sichtbarkeitslogik: SurveyRepository, SurveyEditorService, MemberSurveyListController
  • Fragerouting: SurveyFlowService, SurveyConditionRepository
  • Ergebnisdarstellung: SurveyResultsViewService
  • Exportlogik: SurveyResultsExportService, SurveyResultsPdfService
  • Backend-Operationen und DCA-Verhalten: tl_survey.php, SurveyDcaListener