c7439e4822
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>
146 lines
9.9 KiB
Twig
146 lines
9.9 KiB
Twig
{% trans_default_domain 'messages' %}
|
|
|
|
{% include '@Survey/frontend/_survey_assets.html.twig' %}
|
|
{% if not templatesOnly|default(false) %}
|
|
{% include '@Survey/frontend/_survey_branding.html.twig' %}
|
|
{% endif %}
|
|
|
|
{% set moduleHeadline = (headline is iterable ? headline.text|default('') : headline|default(''))|striptags|trim %}
|
|
{% set templatesOnly = templatesOnly|default(false) %}
|
|
|
|
<section class="survey-shell survey-grid{{ templatesOnly ? ' survey-shell--template' : '' }}">
|
|
{% for message in app.flashes('success') %}
|
|
<div class="survey-alert success">{{ message }}</div>
|
|
{% endfor %}
|
|
|
|
{% for message in app.flashes('error') %}
|
|
<div class="survey-alert error">{{ message }}</div>
|
|
{% endfor %}
|
|
|
|
{% if moduleHeadline %}
|
|
<header>
|
|
<h2>{{ moduleHeadline }}</h2>
|
|
</header>
|
|
{% endif %}
|
|
|
|
{% if loginRequired %}
|
|
<div class="survey-alert warning">{{ 'survey.list.login_required'|trans }}</div>
|
|
{% else %}
|
|
<div class="survey-button-row">
|
|
{% if createUrl %}
|
|
<a class="survey-button primary" href="{{ createUrl }}">{{ 'survey.list.create'|trans }}</a>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="survey-grid survey-list-grid">
|
|
{% for survey in surveys %}
|
|
<article class="survey-card survey-list-card">
|
|
<div class="survey-list-card__head{{ templatesOnly ? ' survey-list-card__head--template' : '' }}">
|
|
<div class="survey-list-card__headline{{ templatesOnly ? ' survey-list-card__headline--template' : '' }}">
|
|
<div class="survey-list-card__title-wrap">
|
|
<h3>{{ survey.title|striptags|trim }}</h3>
|
|
</div>
|
|
<div class="survey-list-card__stats">
|
|
<span class="survey-list-stat">{{ 'survey.list.questions'|trans({'%count%': survey.questionCount}) }}</span>
|
|
{% if not templatesOnly %}
|
|
<span class="survey-list-stat">{{ 'survey.list.participations'|trans({'%count%': survey.participationCount}) }}</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% if templatesOnly %}
|
|
<div class="survey-list-card__head-actions survey-list-card__head-actions--template">
|
|
<form method="post" class="survey-question-action-form">
|
|
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
|
|
<input type="hidden" name="_token" value="{{ csrf_token('duplicate-survey-' ~ survey.id) }}">
|
|
<input type="hidden" name="_survey_action" value="duplicate-survey">
|
|
<input type="hidden" name="item_id" value="{{ survey.id }}">
|
|
<button class="survey-button secondary" onclick="return confirm('{{ 'survey.list.duplicate_confirm'|trans({'%title%': survey.title|striptags|trim})|e('js') }}');">{{ 'survey.list.duplicate'|trans }}</button>
|
|
</form>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% if not templatesOnly %}
|
|
<div class="survey-list-card__footer">
|
|
<div class="survey-button-row survey-list-card__actions">
|
|
{% if survey.editUrl %}
|
|
{% if survey.published %}
|
|
<span class="survey-button primary is-disabled" aria-disabled="true">{{ 'survey.list.edit'|trans }}</span>
|
|
{% else %}
|
|
<a class="survey-button primary" href="{{ survey.editUrl }}">{{ 'survey.list.edit'|trans }}</a>
|
|
{% endif %}
|
|
{% endif %}
|
|
{% if survey.publicUrl and survey.published %}
|
|
<a class="survey-button secondary" href="{{ survey.publicUrl }}">{{ 'survey.list.public_view'|trans }}</a>
|
|
{% endif %}
|
|
{% if survey.copyUrl and survey.published %}
|
|
<button
|
|
type="button"
|
|
class="survey-button secondary"
|
|
data-copy-text="{{ survey.copyUrl }}"
|
|
data-copy-label="{{ 'survey.list.copy_link'|trans }}"
|
|
data-copy-success="{{ 'survey.list.copy_link_done'|trans }}"
|
|
>{{ 'survey.list.copy_link'|trans }}</button>
|
|
{% endif %}
|
|
{% if survey.draftUrl and not survey.published %}
|
|
<a class="survey-button secondary" href="{{ survey.draftUrl }}">{{ 'survey.list.draft_view'|trans }}</a>
|
|
{% endif %}
|
|
{% if survey.resultsUrl %}
|
|
<a class="survey-button secondary" href="{{ survey.resultsUrl }}">{{ 'survey.list.show_results'|trans }}</a>
|
|
{% endif %}
|
|
<form method="post" class="survey-question-action-form">
|
|
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
|
|
<input type="hidden" name="_token" value="{{ csrf_token('duplicate-survey-' ~ survey.id) }}">
|
|
<input type="hidden" name="_survey_action" value="duplicate-survey">
|
|
<input type="hidden" name="item_id" value="{{ survey.id }}">
|
|
<button class="survey-button secondary" onclick="return confirm('{{ 'survey.list.duplicate_confirm'|trans({'%title%': survey.title|striptags|trim})|e('js') }}');">{{ 'survey.list.duplicate'|trans }}</button>
|
|
</form>
|
|
<form method="post" class="survey-question-action-form">
|
|
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
|
|
<input type="hidden" name="_token" value="{{ csrf_token('delete-survey-' ~ survey.id) }}">
|
|
<input type="hidden" name="_survey_action" value="delete-survey">
|
|
<input type="hidden" name="item_id" value="{{ survey.id }}">
|
|
<button class="survey-button danger" onclick="return confirm('{{ 'survey.list.delete_confirm'|trans|e('js') }}') && confirm('{{ 'survey.list.delete_confirm_second'|trans|e('js') }}');">{{ 'survey.list.delete'|trans }}</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="survey-list-card__head-actions">
|
|
<form method="post" class="survey-list-publish-form">
|
|
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
|
|
<input type="hidden" name="_token" value="{{ csrf_token('publish-survey-' ~ survey.id) }}">
|
|
<input type="hidden" name="_survey_action" value="publish-survey">
|
|
<input type="hidden" name="item_id" value="{{ survey.id }}">
|
|
<button
|
|
type="submit"
|
|
class="survey-button primary survey-list-publish-button"
|
|
{% if survey.published %}disabled{% endif %}
|
|
{% if not survey.published %}onclick="return confirm('{{ 'survey.edit.publish_confirm'|trans|e('js') }}');"{% endif %}
|
|
>
|
|
{{ survey.published ? 'survey.list.publish_done'|trans : 'survey.list.publish'|trans }}
|
|
</button>
|
|
{% if not survey.published %}
|
|
<span class="survey-list-publish-help">{{ 'survey.list.publish_help'|trans }}</span>
|
|
{% endif %}
|
|
</form>
|
|
|
|
<form method="post" class="survey-list-eye-form">
|
|
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
|
|
<input type="hidden" name="_token" value="{{ csrf_token('toggle-active-' ~ survey.id) }}">
|
|
<input type="hidden" name="_survey_action" value="toggle-active">
|
|
<input type="hidden" name="item_id" value="{{ survey.id }}">
|
|
<button type="submit" class="survey-visibility-toggle{{ survey.isActive ? ' is-on' : '' }}" title="{{ survey.isActive ? 'survey.edit.deactivate_survey'|trans : 'survey.edit.activate_survey'|trans }}" aria-label="{{ survey.isActive ? 'survey.edit.deactivate_survey'|trans : 'survey.edit.activate_survey'|trans }}">
|
|
<span class="survey-visibility-dot{{ survey.isActive ? ' is-on' : '' }}" aria-hidden="true"></span>
|
|
<span class="survey-visibility-label">{{ survey.isActive ? 'survey.list.active_state'|trans : 'survey.list.inactive_state'|trans }}</span>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</article>
|
|
{% else %}
|
|
{% if not templatesOnly %}
|
|
<div class="survey-card">{{ 'survey.list.empty'|trans }}</div>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
</section> |