Refine survey editor workflow and publication handling

This commit is contained in:
Jürgen Mummert
2026-05-29 10:19:19 +02:00
parent 6bbded4181
commit 1174410c1b
40 changed files with 1121 additions and 335 deletions
+47 -6
View File
@@ -22,6 +22,8 @@ $GLOBALS['TL_DCA']['tl_survey'] = [
'id' => 'primary',
'alias' => 'unique',
'published' => 'index',
'isActive' => 'index',
'isTemplate' => 'index',
],
],
],
@@ -33,7 +35,7 @@ $GLOBALS['TL_DCA']['tl_survey'] = [
'panelLayout' => 'filter;sort,search,limit',
],
'label' => [
'fields' => ['title', 'categorySummary', 'assignedMembersSummary'],
'fields' => ['title', 'categorySummary', 'assignedMembersSummary', 'templateSummary'],
'showColumns' => true,
],
'global_operations' => [
@@ -52,10 +54,22 @@ $GLOBALS['TL_DCA']['tl_survey'] = [
'href' => 'act=edit',
'icon' => 'header.svg',
],
'publishSurvey' => [
'label' => &$GLOBALS['TL_LANG']['tl_survey']['publishSurvey'],
'href' => 'act=toggle&field=published',
'icon' => 'visible.svg',
'button_callback' => [SurveyDcaListener::class, 'generatePublishSurveyButton'],
],
'toggleActive' => [
'label' => &$GLOBALS['TL_LANG']['tl_survey']['toggleActive'],
'href' => 'act=toggle&field=isActive',
'icon' => 'visible.svg',
'button_callback' => [SurveyDcaListener::class, 'generateToggleActiveButton'],
],
'delete' => [
'href' => 'act=delete',
'icon' => 'delete.svg',
'attributes' => 'onclick="if(!confirm(\'Eintrag wirklich loeschen?\'))return false;Backend.getScrollOffset()"',
'attributes' => 'onclick="if(!confirm(\'Eintrag wirklich löschen?\'))return false;Backend.getScrollOffset()"',
],
'show' => [
'href' => 'act=show',
@@ -74,7 +88,7 @@ $GLOBALS['TL_DCA']['tl_survey'] = [
],
],
'palettes' => [
'default' => '{title_legend},title,category,description;{assignment_legend},assignedMembers;{publishing_legend},published,isLocked;{meta_legend},createdAt,updatedAt',
'default' => '{title_legend},title,category,description;{assignment_legend},assignedMembers;{publishing_legend},isTemplate;{meta_legend},createdAt,updatedAt',
],
'fields' => [
'id' => [
@@ -105,6 +119,7 @@ $GLOBALS['TL_DCA']['tl_survey'] = [
],
'category' => [
'label' => &$GLOBALS['TL_LANG']['tl_survey']['category'],
'filter' => true,
'inputType' => 'select',
'foreignKey' => 'tl_survey_category.title',
'eval' => ['multiple' => true, 'chosen' => true, 'tl_class' => 'clr'],
@@ -113,9 +128,8 @@ $GLOBALS['TL_DCA']['tl_survey'] = [
],
'categoryFilter' => [
'label' => &$GLOBALS['TL_LANG']['tl_survey']['categoryFilter'],
'filter' => true,
'inputType' => 'select',
'options_callback' => [SurveyDcaListener::class, 'getCategoryOptions'],
'options_callback' => [SurveyDcaListener::class, 'getUsedCategoryFilterOptions'],
'eval' => ['includeBlankOption' => true, 'chosen' => true, 'findInSet' => true],
'sql' => "varchar(255) NOT NULL default ''",
],
@@ -127,8 +141,33 @@ $GLOBALS['TL_DCA']['tl_survey'] = [
'label' => &$GLOBALS['TL_LANG']['tl_survey']['published'],
'inputType' => 'checkbox',
'eval' => ['tl_class' => 'w50 m12'],
'save_callback' => [[SurveyDcaListener::class, 'savePublishedState']],
'sql' => "char(1) NOT NULL default ''",
],
'isActive' => [
'label' => &$GLOBALS['TL_LANG']['tl_survey']['isActive'],
'inputType' => 'checkbox',
'save_callback' => [[SurveyDcaListener::class, 'saveActiveState']],
'sql' => "char(1) NOT NULL default ''",
],
'isTemplate' => [
'label' => &$GLOBALS['TL_LANG']['tl_survey']['isTemplate'],
'inputType' => 'checkbox',
'eval' => ['tl_class' => 'w50 m12'],
'sql' => "char(1) NOT NULL default ''",
],
'templateFilter' => [
'label' => &$GLOBALS['TL_LANG']['tl_survey']['templateFilter'],
'filter' => true,
'inputType' => 'select',
'options_callback' => [SurveyDcaListener::class, 'getTemplateFilterOptions'],
'eval' => ['includeBlankOption' => true, 'chosen' => true],
'sql' => "char(1) NOT NULL default ''",
],
'templateSummary' => [
'label' => &$GLOBALS['TL_LANG']['tl_survey']['templateSummary'],
'sql' => "varchar(16) NOT NULL default ''",
],
'isLocked' => [
'label' => &$GLOBALS['TL_LANG']['tl_survey']['isLocked'],
'inputType' => 'checkbox',
@@ -192,7 +231,7 @@ if ('cli' !== PHP_SAPI) {
System::getContainer()->get('database_connection')->fetchFirstColumn('SHOW COLUMNS FROM tl_survey'),
);
$hasListMetadataColumns = !array_diff(
['categoryfilter', 'categorysummary', 'assignedmembersfilter', 'assignedmemberssummary'],
['categoryfilter', 'categorysummary', 'templatefilter', 'templatesummary', 'assignedmembersfilter', 'assignedmemberssummary'],
$columnNames,
);
} catch (\Throwable) {
@@ -205,6 +244,8 @@ if ('cli' !== PHP_SAPI) {
unset(
$GLOBALS['TL_DCA']['tl_survey']['fields']['categoryFilter'],
$GLOBALS['TL_DCA']['tl_survey']['fields']['categorySummary'],
$GLOBALS['TL_DCA']['tl_survey']['fields']['templateFilter'],
$GLOBALS['TL_DCA']['tl_survey']['fields']['templateSummary'],
$GLOBALS['TL_DCA']['tl_survey']['fields']['assignedMembersFilter'],
$GLOBALS['TL_DCA']['tl_survey']['fields']['assignedMembersSummary'],
);
+9
View File
@@ -52,6 +52,15 @@ $GLOBALS['TL_DCA']['tl_survey_answer'] = [
'label' => &$GLOBALS['TL_LANG']['tl_survey_answer']['questionType'],
'sql' => "varchar(32) NOT NULL default ''",
],
'questionLabel' => [
'sql' => "varchar(255) NOT NULL default ''",
],
'questionDescription' => [
'sql' => 'text NULL',
],
'questionSorting' => [
'sql' => 'int(10) unsigned NOT NULL default 0',
],
'value' => [
'label' => &$GLOBALS['TL_LANG']['tl_survey_answer']['value'],
'sql' => 'text NULL',
+1 -1
View File
@@ -34,7 +34,7 @@ $GLOBALS['TL_DCA']['tl_survey_category'] = [
'delete' => [
'href' => 'act=delete',
'icon' => 'delete.svg',
'attributes' => 'onclick="if(!confirm(\'Eintrag wirklich loeschen?\'))return false;Backend.getScrollOffset()"',
'attributes' => 'onclick="if(!confirm(\'Eintrag wirklich löschen?\'))return false;Backend.getScrollOffset()"',
],
'show' => [
'href' => 'act=show',
+4 -1
View File
@@ -12,6 +12,9 @@ $GLOBALS['TL_DCA']['tl_survey_condition'] = [
'dataContainer' => DC_Table::class,
'ptable' => 'tl_survey',
'enableVersioning' => true,
'onload_callback' => [
[SurveyDcaListener::class, 'restrictSurveyConditionEditing'],
],
'onsubmit_callback' => [
[SurveyDcaListener::class, 'touchSurveyConditionParent'],
],
@@ -51,7 +54,7 @@ $GLOBALS['TL_DCA']['tl_survey_condition'] = [
'delete' => [
'href' => 'act=delete',
'icon' => 'delete.svg',
'attributes' => 'onclick="if(!confirm(\'Eintrag wirklich loeschen?\'))return false;Backend.getScrollOffset()"',
'attributes' => 'onclick="if(!confirm(\'Eintrag wirklich löschen?\'))return false;Backend.getScrollOffset()"',
],
'show' => [
'href' => 'act=show',
+4 -1
View File
@@ -12,6 +12,9 @@ $GLOBALS['TL_DCA']['tl_survey_content'] = [
'dataContainer' => DC_Table::class,
'ptable' => 'tl_survey',
'enableVersioning' => true,
'onload_callback' => [
[SurveyDcaListener::class, 'restrictSurveyContentEditing'],
],
'onsubmit_callback' => [
[SurveyDcaListener::class, 'touchSurveyContentParent'],
],
@@ -55,7 +58,7 @@ $GLOBALS['TL_DCA']['tl_survey_content'] = [
'delete' => [
'href' => 'act=delete',
'icon' => 'delete.svg',
'attributes' => 'onclick="if(!confirm(\'Eintrag wirklich loeschen?\'))return false;Backend.getScrollOffset()"',
'attributes' => 'onclick="if(!confirm(\'Eintrag wirklich löschen?\'))return false;Backend.getScrollOffset()"',
],
'show' => [
'href' => 'act=show',
+1 -1
View File
@@ -47,7 +47,7 @@ $GLOBALS['TL_DCA']['tl_survey_editor'] = [
'delete' => [
'href' => 'act=delete',
'icon' => 'delete.svg',
'attributes' => 'onclick="if(!confirm(\'Eintrag wirklich loeschen?\'))return false;Backend.getScrollOffset()"',
'attributes' => 'onclick="if(!confirm(\'Eintrag wirklich löschen?\'))return false;Backend.getScrollOffset()"',
],
'show' => [
'href' => 'act=show',
+4 -4
View File
@@ -1,10 +1,10 @@
<?php
$GLOBALS['TL_LANG']['MOD']['survey_bundle_surveys'] = ['Umfragen', 'Umfragen, Fragen, Bedingungen und anonyme Antworten verwalten.'];
$GLOBALS['TL_LANG']['MOD']['survey_bundle_categories'] = ['Umfrage-Kategorien', 'Kategorien fuer Umfragen pflegen.'];
$GLOBALS['TL_LANG']['MOD']['survey_bundle_categories'] = ['Umfrage-Kategorien', 'Kategorien für Umfragen pflegen.'];
$GLOBALS['TL_LANG']['FMD']['survey'] = 'Umfragen';
$GLOBALS['TL_LANG']['FMD']['member_survey_list'] = ['Meine Umfragen', 'Zeigt alle dem Mitglied zugewiesenen Umfragen an.'];
$GLOBALS['TL_LANG']['FMD']['member_survey_edit'] = ['Umfrage bearbeiten', 'Bearbeitungsbereich fuer zugewiesene Umfragen im Frontend.'];
$GLOBALS['TL_LANG']['FMD']['show_survey'] = ['Umfrage ausfuellen', 'Oeffentliche Umfrageansicht ueber den oeffentlichen Link.'];
$GLOBALS['TL_LANG']['FMD']['survey_results'] = ['Ergebnisse', 'Zeigt die Ergebnisse einer Umfrage ueber den konfigurierten Ergebnis-Link an.'];
$GLOBALS['TL_LANG']['FMD']['member_survey_edit'] = ['Umfrage bearbeiten', 'Bearbeitungsbereich für zugewiesene Umfragen im Frontend.'];
$GLOBALS['TL_LANG']['FMD']['show_survey'] = ['Umfrage ausfüllen', 'Öffentliche Umfrageansicht über den öffentlichen Link.'];
$GLOBALS['TL_LANG']['FMD']['survey_results'] = ['Ergebnisse', 'Zeigt die Ergebnisse einer Umfrage über den konfigurierten Ergebnis-Link an.'];
+1 -1
View File
@@ -2,4 +2,4 @@
$GLOBALS['TL_LANG']['tl_member']['survey_legend'] = 'Umfrage-Zuordnung';
$GLOBALS['TL_LANG']['tl_member']['surveyCategories'] = ['Umfrage-Kategorien', 'Diese Kategorien werden neuen und bereits zugewiesenen Umfragen dieses Mitglieds automatisch zugeordnet.'];
$GLOBALS['TL_LANG']['tl_member']['assignedSurveys'] = ['Zugewiesene Umfragen', 'Waehlen Sie die Umfragen aus, die dieses Mitglied bearbeiten darf. Das Suchfeld in der Auswahl hilft bei vielen Eintraegen.'];
$GLOBALS['TL_LANG']['tl_member']['assignedSurveys'] = ['Zugewiesene Umfragen', 'Wählen Sie die Umfragen aus, die dieses Mitglied bearbeiten darf. Das Suchfeld in der Auswahl hilft bei vielen Einträgen.'];
+3 -3
View File
@@ -1,6 +1,6 @@
<?php
$GLOBALS['TL_LANG']['tl_module']['survey_navigation_legend'] = 'Verknuepfte Seiten';
$GLOBALS['TL_LANG']['tl_module']['survey_navigation_legend'] = 'Verknüpfte Seiten';
$GLOBALS['TL_LANG']['tl_module']['surveyEditPage'] = ['Bearbeitungsseite', 'Seite mit dem Frontendmodul zur Bearbeitung von Umfragen.'];
$GLOBALS['TL_LANG']['tl_module']['surveyListPage'] = ['Uebersichtsseite', 'Seite mit der Uebersicht der Umfragen.'];
$GLOBALS['TL_LANG']['tl_module']['surveyReaderPage'] = ['Anzeigeseite', 'Oeffentliche Seite zum Aufrufen einer Umfrage ueber den oeffentlichen Link.'];
$GLOBALS['TL_LANG']['tl_module']['surveyListPage'] = ['Übersichtsseite', 'Seite mit der Übersicht der Umfragen.'];
$GLOBALS['TL_LANG']['tl_module']['surveyReaderPage'] = ['Anzeigeseite', 'Öffentliche Seite zum Aufrufen einer Umfrage über den öffentlichen Link.'];
+3 -3
View File
@@ -1,6 +1,6 @@
<?php
$GLOBALS['TL_LANG']['tl_settings']['survey_settings_legend'] = 'Umfrage-Einstellungen';
$GLOBALS['TL_LANG']['tl_settings']['surveyReaderPage'] = ['Reader-Seite', 'Diese Seite wird global fuer den oeffentlichen Umfrage-Link verwendet.'];
$GLOBALS['TL_LANG']['tl_settings']['surveyResultsPage'] = ['Ergebnisseite', 'Diese Seite wird global fuer die Anzeige der Umfrage-Ergebnisse verwendet.'];
$GLOBALS['TL_LANG']['tl_settings']['surveyGotenbergUrl'] = ['Gotenberg-URL', 'Basis-URL der Gotenberg-Instanz fuer den serverseitigen PDF-Export, z. B. https://gotenberg.mummert.media'];
$GLOBALS['TL_LANG']['tl_settings']['surveyReaderPage'] = ['Reader-Seite', 'Diese Seite wird global für den öffentlichen Umfrage-Link verwendet.'];
$GLOBALS['TL_LANG']['tl_settings']['surveyResultsPage'] = ['Ergebnisseite', 'Diese Seite wird global für die Anzeige der Umfrage-Ergebnisse verwendet.'];
$GLOBALS['TL_LANG']['tl_settings']['surveyGotenbergUrl'] = ['Gotenberg-URL', 'Basis-URL der Gotenberg-Instanz für den serverseitigen PDF-Export, z. B. https://gotenberg.mummert.media'];
+13 -5
View File
@@ -1,21 +1,29 @@
<?php
$GLOBALS['TL_LANG']['tl_survey']['title'] = ['Titel', 'Titel der Umfrage.'];
$GLOBALS['TL_LANG']['tl_survey']['alias'] = ['Oeffentlicher Link-Schluessel', 'Wird automatisch als 20-stelliger Link-Schluessel erzeugt.'];
$GLOBALS['TL_LANG']['tl_survey']['alias'] = ['Öffentlicher Link-Schlüssel', 'Wird automatisch als 20-stelliger Link-Schlüssel erzeugt.'];
$GLOBALS['TL_LANG']['tl_survey']['category'] = ['Kategorien', 'Ordnet die Umfrage einer oder mehreren Kategorien zu.'];
$GLOBALS['TL_LANG']['tl_survey']['categoryFilter'] = ['Kategorien', 'Filtert die Liste nach einer Umfrage-Kategorie.'];
$GLOBALS['TL_LANG']['tl_survey']['categorySummary'] = ['Kategorien', 'Zugeordnete Kategorien der Umfrage.'];
$GLOBALS['TL_LANG']['tl_survey']['description'] = ['Beschreibung', 'Einleitung fuer den Editor und das Frontend.'];
$GLOBALS['TL_LANG']['tl_survey']['isTemplate'] = ['Umfrage ist eine Vorlage', 'Wird den zugewiesenen Nutzern als Vorlage angezeigt.'];
$GLOBALS['TL_LANG']['tl_survey']['templateFilter'] = ['Vorlage', 'Filtert die Liste nach Vorlagenstatus.'];
$GLOBALS['TL_LANG']['tl_survey']['templateSummary'] = ['Vorlage', 'Zeigt an, ob die Umfrage als Vorlage markiert ist.'];
$GLOBALS['TL_LANG']['tl_survey']['template_yes'] = 'Ja';
$GLOBALS['TL_LANG']['tl_survey']['template_no'] = 'Nein';
$GLOBALS['TL_LANG']['tl_survey']['description'] = ['Beschreibung', 'Einleitung für den Editor und das Frontend.'];
$GLOBALS['TL_LANG']['tl_survey']['title_legend'] = 'Grunddaten';
$GLOBALS['TL_LANG']['tl_survey']['assignment_legend'] = 'Bearbeitende Mitglieder';
$GLOBALS['TL_LANG']['tl_survey']['publishing_legend'] = 'Sichtbarkeit';
$GLOBALS['TL_LANG']['tl_survey']['meta_legend'] = 'Verwaltungsdaten';
$GLOBALS['TL_LANG']['tl_survey']['published'] = ['Veroeffentlicht', 'Die Umfrage oeffentlich freischalten.'];
$GLOBALS['TL_LANG']['tl_survey']['published'] = ['Veröffentlicht', 'Die Umfrage öffentlich freischalten.'];
$GLOBALS['TL_LANG']['tl_survey']['isActive'] = ['Vorübergehend aktiv', 'Schaltet eine bereits veröffentlichte Umfrage öffentlich an oder aus.'];
$GLOBALS['TL_LANG']['tl_survey']['isLocked'] = ['Gesperrt', 'Struktur ist wegen vorhandener Antworten gesperrt.'];
$GLOBALS['TL_LANG']['tl_survey']['assignedMembers'] = ['Zugewiesene Mitglieder', 'Waehlen Sie die Mitglieder aus, die diese Umfrage bearbeiten duerfen.'];
$GLOBALS['TL_LANG']['tl_survey']['publishSurvey'] = ['Umfrage veröffentlichen', 'Veröffentlicht die Umfrage endgültig.'];
$GLOBALS['TL_LANG']['tl_survey']['toggleActive'] = ['Sichtbarkeit umschalten', 'Schaltet die veröffentlichte Umfrage vorübergehend an oder aus.'];
$GLOBALS['TL_LANG']['tl_survey']['assignedMembers'] = ['Zugewiesene Mitglieder', 'Wählen Sie die Mitglieder aus, die diese Umfrage bearbeiten dürfen.'];
$GLOBALS['TL_LANG']['tl_survey']['assignedMembersFilter'] = ['Zugewiesene Benutzer', 'Filtert die Liste nach einem zugewiesenen Benutzer.'];
$GLOBALS['TL_LANG']['tl_survey']['assignedMembersSummary'] = ['Zugewiesene Benutzer', 'Kommagetrennte Liste der zugewiesenen Benutzer.'];
$GLOBALS['TL_LANG']['tl_survey']['copyPublicLink'] = ['Link kopieren', 'Den oeffentlichen Link in die Zwischenablage kopieren'];
$GLOBALS['TL_LANG']['tl_survey']['copyPublicLink'] = ['Link kopieren', 'Den öffentlichen Link in die Zwischenablage kopieren'];
$GLOBALS['TL_LANG']['tl_survey']['showResults'] = ['Ergebnisse anzeigen', 'Die Ergebnisse dieser Umfrage im Frontend anzeigen'];
$GLOBALS['TL_LANG']['tl_survey']['createdBy'] = ['Angelegt von', 'ID des erstellenden Mitglieds.'];
$GLOBALS['TL_LANG']['tl_survey']['updatedBy'] = ['Aktualisiert von', 'ID des zuletzt bearbeitenden Mitglieds.'];
+1 -1
View File
@@ -3,4 +3,4 @@
$GLOBALS['TL_LANG']['tl_survey_category']['title'] = ['Titel', 'Titel der Kategorie.'];
$GLOBALS['TL_LANG']['tl_survey_category']['alias'] = ['Alias', 'Optionaler Alias.'];
$GLOBALS['TL_LANG']['tl_survey_category']['title_legend'] = 'Grunddaten';
$GLOBALS['TL_LANG']['tl_survey_category']['sorting'] = ['Sortierung', 'Sortierwert fuer die Backend-Liste.'];
$GLOBALS['TL_LANG']['tl_survey_category']['sorting'] = ['Sortierung', 'Sortierwert für die Backend-Liste.'];
+1 -1
View File
@@ -3,4 +3,4 @@
$GLOBALS['TL_LANG']['tl_survey_condition']['logic_legend'] = 'Sprungregel';
$GLOBALS['TL_LANG']['tl_survey_condition']['sourceQuestion'] = ['Ausgangsfrage', 'Frage, deren Antwort ausgewertet wird.'];
$GLOBALS['TL_LANG']['tl_survey_condition']['answerValue'] = ['Antwort', 'Antwortwert, bei dem zu einer anderen Frage gesprungen wird.'];
$GLOBALS['TL_LANG']['tl_survey_condition']['targetQuestion'] = ['Naechste Frage', 'Zu dieser Frage wird bei passender Antwort gewechselt.'];
$GLOBALS['TL_LANG']['tl_survey_condition']['targetQuestion'] = ['Nächste Frage', 'Zu dieser Frage wird bei passender Antwort gewechselt.'];
+13 -13
View File
@@ -13,20 +13,20 @@ $GLOBALS['TL_LANG']['tl_survey_content']['question_legend'] = 'Frage';
$GLOBALS['TL_LANG']['tl_survey_content']['settings_legend'] = 'Einstellungen';
$GLOBALS['TL_LANG']['tl_survey_content']['mandatory'] = ['Pflichtfrage', 'Diese Frage muss beantwortet werden.'];
$GLOBALS['TL_LANG']['tl_survey_content']['published'] = ['Aktiv', 'Die Frage wird in der Umfrage angezeigt.'];
$GLOBALS['TL_LANG']['tl_survey_content']['allowMaybe'] = ['Vielleicht anbieten', 'Ergaenzt die Ja-Nein-Frage um die Antwortmoeglichkeit Vielleicht.'];
$GLOBALS['TL_LANG']['tl_survey_content']['allowMaybe'] = ['Vielleicht anbieten', 'Ergänzt die Ja-Nein-Frage um die Antwortmöglichkeit Vielleicht.'];
$GLOBALS['TL_LANG']['tl_survey_content']['jumpOnYes'] = ['Zur Frage springen bei Auswahl ja', 'Springt bei der Antwort Ja direkt zu dieser Frage.'];
$GLOBALS['TL_LANG']['tl_survey_content']['jumpOnNo'] = ['Zur Frage springen bei Auswahl nein', 'Springt bei der Antwort Nein direkt zu dieser Frage.'];
$GLOBALS['TL_LANG']['tl_survey_content']['allowMultiple'] = ['Multiple-Choice aktivieren', 'Erlaubt mehrere Antworten statt einer einzelnen Auswahl.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption1'] = ['Antwort 1', 'Erste moegliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption2'] = ['Antwort 2', 'Zweite moegliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption3'] = ['Antwort 3', 'Dritte moegliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption4'] = ['Antwort 4', 'Vierte moegliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption5'] = ['Antwort 5', 'Fuenfte moegliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption6'] = ['Antwort 6', 'Sechste moegliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption7'] = ['Antwort 7', 'Siebte moegliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption8'] = ['Antwort 8', 'Achte moegliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption9'] = ['Antwort 9', 'Neunte moegliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption10'] = ['Antwort 10', 'Zehnte moegliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption1'] = ['Antwort 1', 'Erste mögliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption2'] = ['Antwort 2', 'Zweite mögliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption3'] = ['Antwort 3', 'Dritte mögliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption4'] = ['Antwort 4', 'Vierte mögliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption5'] = ['Antwort 5', 'Fünfte mögliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption6'] = ['Antwort 6', 'Sechste mögliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption7'] = ['Antwort 7', 'Siebte mögliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption8'] = ['Antwort 8', 'Achte mögliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption9'] = ['Antwort 9', 'Neunte mögliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['answerOption10'] = ['Antwort 10', 'Zehnte mögliche Antwort.'];
$GLOBALS['TL_LANG']['tl_survey_content']['rangeMin'] = ['Kleinster Wert', 'Kleinster Wert des Schiebereglers.'];
$GLOBALS['TL_LANG']['tl_survey_content']['rangeMax'] = ['Groesster Wert', 'Groesster Wert des Schiebereglers.'];
$GLOBALS['TL_LANG']['tl_survey_content']['rangeStep'] = ['Schrittweite', 'Abstand zwischen den moeglichen Werten des Schiebereglers.'];
$GLOBALS['TL_LANG']['tl_survey_content']['rangeMax'] = ['Größter Wert', 'Größter Wert des Schiebereglers.'];
$GLOBALS['TL_LANG']['tl_survey_content']['rangeStep'] = ['Schrittweite', 'Abstand zwischen den möglichen Werten des Schiebereglers.'];
+1 -1
View File
@@ -4,4 +4,4 @@ $GLOBALS['TL_LANG']['tl_survey_submission']['token'] = ['Teilnahme-Code', 'Anony
$GLOBALS['TL_LANG']['tl_survey_submission']['startedAt'] = ['Begonnen am', 'Zeitpunkt, an dem die Umfrage begonnen wurde.'];
$GLOBALS['TL_LANG']['tl_survey_submission']['completedAt'] = ['Beendet am', 'Zeitpunkt, an dem die Umfrage abgeschlossen wurde.'];
$GLOBALS['TL_LANG']['tl_survey_submission']['currentQuestion'] = ['Aktuelle Frage', 'Interne Kennung der aktuell offenen Frage.'];
$GLOBALS['TL_LANG']['tl_survey_submission']['isFinished'] = ['Abgeschlossen', 'Kennzeichnet abgeschlossene Umfrage-Durchlaeufe.'];
$GLOBALS['TL_LANG']['tl_survey_submission']['isFinished'] = ['Abgeschlossen', 'Kennzeichnet abgeschlossene Umfrage-Durchläufe.'];
+8
View File
@@ -5,13 +5,21 @@ $GLOBALS['TL_LANG']['tl_survey']['alias'] = ['Public link key', 'Automatically g
$GLOBALS['TL_LANG']['tl_survey']['category'] = ['Categories', 'Assigns the survey to one or more categories.'];
$GLOBALS['TL_LANG']['tl_survey']['categoryFilter'] = ['Categories', 'Filters the list by a survey category.'];
$GLOBALS['TL_LANG']['tl_survey']['categorySummary'] = ['Categories', 'Assigned categories of the survey.'];
$GLOBALS['TL_LANG']['tl_survey']['isTemplate'] = ['Survey is a template', 'Shown to assigned users as a template.'];
$GLOBALS['TL_LANG']['tl_survey']['templateFilter'] = ['Template', 'Filters the list by template status.'];
$GLOBALS['TL_LANG']['tl_survey']['templateSummary'] = ['Template', 'Shows whether the survey is marked as a template.'];
$GLOBALS['TL_LANG']['tl_survey']['template_yes'] = 'Yes';
$GLOBALS['TL_LANG']['tl_survey']['template_no'] = 'No';
$GLOBALS['TL_LANG']['tl_survey']['description'] = ['Description', 'Introduction for the editor and the frontend.'];
$GLOBALS['TL_LANG']['tl_survey']['title_legend'] = 'Basic data';
$GLOBALS['TL_LANG']['tl_survey']['assignment_legend'] = 'Editing members';
$GLOBALS['TL_LANG']['tl_survey']['publishing_legend'] = 'Visibility';
$GLOBALS['TL_LANG']['tl_survey']['meta_legend'] = 'Administrative data';
$GLOBALS['TL_LANG']['tl_survey']['published'] = ['Published', 'Make the survey publicly accessible.'];
$GLOBALS['TL_LANG']['tl_survey']['isActive'] = ['Temporarily active', 'Turns an already published survey on or off publicly.'];
$GLOBALS['TL_LANG']['tl_survey']['isLocked'] = ['Locked', 'Structure is locked because answers already exist.'];
$GLOBALS['TL_LANG']['tl_survey']['publishSurvey'] = ['Publish survey', 'Publishes the survey permanently.'];
$GLOBALS['TL_LANG']['tl_survey']['toggleActive'] = ['Toggle visibility', 'Temporarily switches the published survey on or off.'];
$GLOBALS['TL_LANG']['tl_survey']['assignedMembers'] = ['Assigned members', 'Choose the members who are allowed to edit this survey.'];
$GLOBALS['TL_LANG']['tl_survey']['assignedMembersFilter'] = ['Assigned users', 'Filters the list by an assigned user.'];
$GLOBALS['TL_LANG']['tl_survey']['assignedMembersSummary'] = ['Assigned users', 'Comma-separated list of assigned users.'];
@@ -189,12 +189,50 @@
padding-right: 0.25rem;
}
.survey-text-summary-grid {
display: grid;
gap: 0.9rem;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
.survey-text-summary-card {
display: grid;
gap: 0.6rem;
padding: 1rem;
border-radius: 1.2rem;
background: rgba(255, 255, 255, 0.78);
border: 1px solid rgba(162, 168, 180, 0.24);
}
.survey-text-response-grid {
display: grid;
gap: 0.9rem;
}
.survey-response-card {
display: grid;
gap: 0.7rem;
margin: 0;
font-style: normal;
background: rgba(255, 255, 255, 0.72);
}
.survey-response-card blockquote {
margin: 0;
}
.survey-response-card__index {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2rem;
height: 2rem;
border-radius: 999px;
background: rgba(0, 100, 173, 0.1);
color: var(--survey-blue);
font-weight: 700;
}
.survey-metric-grid {
display: grid;
gap: 0.85rem;
@@ -338,6 +376,18 @@
align-items: center;
}
.survey-action-stack {
display: grid;
gap: 0.35rem;
}
.survey-action-help {
color: var(--survey-gray-dark);
font-size: 0.92rem;
line-height: 1.35;
max-width: 28rem;
}
.survey-publish-toggle-form {
margin: 0;
}
@@ -427,6 +477,12 @@
.survey-button.primary { background: var(--survey-blue); color: #fff; }
.survey-button.secondary { background: rgba(255,255,255,0.86); color: var(--survey-blue); border-color: rgba(0,100,173,0.18); }
.survey-button.danger { background: rgba(157, 82, 118, 0.12); color: var(--survey-purple); border-color: rgba(157, 82, 118, 0.22); }
.survey-button.is-disabled,
.survey-button[disabled] {
opacity: 0.45;
cursor: not-allowed;
pointer-events: none;
}
.survey-button-compact {
padding: 0.65rem 0.9rem;
@@ -46,41 +46,32 @@
{{ form_end(surveyForm, {render_rest: false}) }}
</div>
{% else %}
{% set locked = survey.isLocked == '1' %}
<div class="survey-button-row survey-button-row--editor-actions">
{% if backUrl %}<a class="survey-button secondary" href="{{ backUrl }}">{{ 'survey.edit.back_to_list'|trans }}</a>{% endif %}
{% if publicUrl %}<a class="survey-button primary" href="{{ publicUrl }}" target="_blank" rel="noreferrer">{{ 'survey.edit.public_view_open'|trans }}</a>{% endif %}
{% if publicUrl %}
<button
type="button"
class="survey-button secondary"
data-copy-text="{{ publicUrl|e('html_attr') }}"
data-copy-label="{{ 'survey.edit.copy_public_link'|trans|e('html_attr') }}"
data-copy-success="{{ 'survey.edit.copy_public_link_success'|trans|e('html_attr') }}"
>{{ 'survey.edit.copy_public_link'|trans }}</button>
{% endif %}
<form method="post" class="survey-publish-toggle-form">
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
<input type="hidden" name="_survey_action" value="toggle-published">
<input type="hidden" name="item_id" value="{{ survey.id }}">
<input type="hidden" name="_token" value="{{ csrf_token('toggle-published-' ~ survey.id) }}">
<button
type="submit"
class="survey-publish-toggle{{ survey.published ? ' is-on' : '' }}"
aria-pressed="{{ survey.published ? 'true' : 'false' }}"
>
<span class="survey-publish-toggle__track" aria-hidden="true">
<span class="survey-publish-toggle__thumb"></span>
</span>
<span class="survey-publish-toggle__copy">
<span class="survey-publish-toggle__label">{{ 'survey.edit.status'|trans }}</span>
<span class="survey-publish-toggle__value">{{ survey.published ? 'survey.edit.published'|trans : 'survey.edit.draft'|trans }}</span>
</span>
</button>
</form>
<div class="survey-action-stack">
{% if not survey.published %}
<form method="post" class="survey-action-form">
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
<input type="hidden" name="_survey_action" value="publish-survey">
<input type="hidden" name="item_id" value="{{ survey.id }}">
<input type="hidden" name="_token" value="{{ csrf_token('publish-survey-' ~ survey.id) }}">
<button class="survey-button primary" onclick="return confirm('{{ 'survey.edit.publish_confirm'|trans|e('js') }}');">{{ 'survey.edit.publish_survey'|trans }}</button>
</form>
<div class="survey-action-help">{{ 'survey.edit.publish_help'|trans }}</div>
{% else %}
<form method="post" class="survey-action-form">
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
<input type="hidden" name="_survey_action" value="toggle-active">
<input type="hidden" name="item_id" value="{{ survey.id }}">
<input type="hidden" name="_token" value="{{ csrf_token('toggle-active-' ~ survey.id) }}">
<button class="survey-button secondary">{{ survey.isActive ? 'survey.edit.deactivate_survey'|trans : 'survey.edit.activate_survey'|trans }}</button>
</form>
<div class="survey-action-help">{{ survey.isActive ? 'survey.edit.deactivate_help'|trans : 'survey.edit.activate_help'|trans }}</div>
{% endif %}
</div>
</div>
{% if locked %}
{% if structureLocked|default(false) %}
<div class="survey-alert warning">{{ 'survey.edit.structure_locked'|trans }}</div>
{% endif %}
@@ -147,7 +138,15 @@
</h4>
<div class="survey-accordion-panel handorgel__content">
<div class="handorgel__content__inner" data-survey-question-editor>
{% if questionItemForm %}
{% if structureLocked|default(false) %}
<div class="survey-grid">
<div class="survey-meta">
<span class="survey-badge neutral">{{ ('survey.survey.question_type_' ~ question.type)|trans }}</span>
{% if question.mandatory %}<span class="survey-badge warning">{{ 'survey.edit.mandatory_badge'|trans }}</span>{% endif %}
</div>
{% if question.description|striptags|trim %}<p>{{ question.description|striptags|trim }}</p>{% endif %}
</div>
{% elseif questionItemForm %}
{% set questionType = questionItemForm.type.vars.value ?: question.type ?: 'yes_no_maybe' %}
{{ form_start(questionItemForm, {attr: {class: 'survey-form-grid', id: questionFormId, 'data-survey-dirty-form': '1'}}) }}
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
@@ -186,15 +185,13 @@
<div class="survey-button-row survey-button-row--form-actions survey-button-row--question-actions">
<button class="survey-button primary" type="submit" form="{{ questionFormId }}">{{ 'survey.edit.save_this_question'|trans }}</button>
{% if not locked %}
<form method="post" class="survey-question-action-form">
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
<input type="hidden" name="_survey_action" value="delete-question">
<input type="hidden" name="item_id" value="{{ question.id }}">
<input type="hidden" name="_token" value="{{ csrf_token('delete-question-' ~ question.id) }}">
<button class="survey-button danger" onclick="return confirm('{{ 'survey.edit.delete_question_confirm'|trans|e('js') }}');">{{ 'survey.edit.delete'|trans }}</button>
</form>
{% endif %}
<form method="post" class="survey-question-action-form">
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
<input type="hidden" name="_survey_action" value="delete-question">
<input type="hidden" name="item_id" value="{{ question.id }}">
<input type="hidden" name="_token" value="{{ csrf_token('delete-question-' ~ question.id) }}">
<button class="survey-button danger" onclick="return confirm('{{ 'survey.edit.delete_question_confirm'|trans|e('js') }}');">{{ 'survey.edit.delete'|trans }}</button>
</form>
<div class="survey-dirty-hint" data-survey-dirty-hint-for="{{ questionFormId }}" hidden>{{ 'survey.edit.dirty_question'|trans }}</div>
</div>
{% endif %}
@@ -205,7 +202,7 @@
<div>{{ 'survey.edit.no_questions'|trans }}</div>
{% endfor %}
{% if not locked %}
{% if not (structureLocked|default(false)) %}
<article id="survey-question-new" class="survey-accordion-item">
<h4 class="survey-accordion-header handorgel__header">
<button
@@ -266,7 +263,7 @@
</div>
</div>
</article>
{% endif %}
{% endif %}
</div>
</div>
@@ -35,31 +35,15 @@
<div class="survey-list-card__head">
<div class="survey-list-card__title-wrap">
<h3>{{ survey.title|striptags|trim }}</h3>
{% if survey.isLocked %}
<div class="survey-meta">
<div class="survey-meta">
<span class="survey-badge {{ survey.published ? 'success' : 'warning' }}">{{ survey.published ? 'survey.list.published'|trans : 'survey.list.draft'|trans }}</span>
{% if survey.published %}
<span class="survey-badge {{ survey.isActive ? 'success' : 'warning' }}">{{ survey.isActive ? 'survey.list.active'|trans : 'survey.list.inactive'|trans }}</span>
{% elseif survey.isLocked %}
<span class="survey-badge warning">{{ 'survey.list.locked'|trans }}</span>
</div>
{% endif %}
{% endif %}
</div>
</div>
<form method="post" class="survey-publish-toggle-form survey-list-card__toggle-form">
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
<input type="hidden" name="_survey_action" value="toggle-published">
<input type="hidden" name="item_id" value="{{ survey.id }}">
<input type="hidden" name="_token" value="{{ csrf_token('toggle-published-' ~ survey.id) }}">
<button
type="submit"
class="survey-publish-toggle survey-publish-toggle--compact{{ survey.published ? ' is-on' : '' }}"
aria-pressed="{{ survey.published ? 'true' : 'false' }}"
>
<span class="survey-publish-toggle__track" aria-hidden="true">
<span class="survey-publish-toggle__thumb"></span>
</span>
<span class="survey-publish-toggle__copy">
<span class="survey-publish-toggle__label">{{ 'survey.edit.status'|trans }}</span>
<span class="survey-publish-toggle__value">{{ survey.published ? 'survey.list.published'|trans : 'survey.list.draft'|trans }}</span>
</span>
</button>
</form>
</div>
<div class="survey-meta survey-list-card__stats">
<span class="survey-badge neutral">{{ 'survey.list.questions'|trans({'%count%': survey.questionCount}) }}</span>
@@ -69,8 +53,13 @@
{% if survey.editUrl %}
<a class="survey-button primary" href="{{ survey.editUrl }}">{{ 'survey.list.edit'|trans }}</a>
{% endif %}
{% if survey.publicUrl %}
{% if survey.publicUrl and survey.published and survey.isActive %}
<a class="survey-button secondary" href="{{ survey.publicUrl }}" target="_blank" rel="noreferrer">{{ 'survey.list.public_view'|trans }}</a>
{% elseif survey.publicUrl %}
<span class="survey-button secondary is-disabled" aria-disabled="true">{{ 'survey.list.public_view'|trans }}</span>
{% endif %}
{% if survey.draftUrl and not survey.published %}
<a class="survey-button secondary" href="{{ survey.draftUrl }}" target="_blank" rel="noreferrer">{{ 'survey.list.draft_view'|trans }}</a>
{% endif %}
{% if survey.resultsUrl %}
<a class="survey-button secondary" href="{{ survey.resultsUrl }}" target="_blank" rel="noreferrer">{{ 'survey.list.show_results'|trans }}</a>
@@ -16,10 +16,15 @@
<article class="survey-card">
<div class="survey-meta">
<h3>{{ survey.title|striptags|trim }}</h3>
{% if isPreview %}<span class="survey-badge warning">{{ 'survey.survey.preview_badge'|trans }}</span>{% endif %}
{% if progress.total > 0 %}<span class="survey-badge neutral">{{ progress.current }}/{{ progress.total }}</span>{% endif %}
</div>
<p>{{ (survey.description|striptags|trim) ?: 'survey.survey.default_description'|trans }}</p>
{% if isPreview %}
<div class="survey-alert warning">{{ 'survey.survey.preview_notice'|trans }}</div>
{% endif %}
{% if progress.total > 0 %}
<div class="survey-progress"><span style="width: {{ progress.percentage }}%"></span></div>
{% endif %}
@@ -28,7 +33,7 @@
{% if isComplete %}
<article class="survey-card">
<h3>{{ 'survey.survey.thanks_title'|trans }}</h3>
<p>{{ 'survey.survey.thanks_text'|trans }}</p>
<p>{{ isPreview ? 'survey.survey.preview_thanks_text'|trans : 'survey.survey.thanks_text'|trans }}</p>
{% if answers %}
<div class="survey-grid">
{% for answer in answers %}
@@ -47,8 +52,25 @@
<h3>{{ question.question|striptags|trim }}</h3>
{% if question.description|striptags|trim %}<p>{{ question.description|striptags|trim }}</p>{% endif %}
{% if canGoBack %}
<form method="post" class="survey-button-row survey-button-row--navigation">
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
<input type="hidden" name="_survey_navigation" value="back">
<input type="hidden" name="_navigation_token" value="{{ csrf_token((isPreview ? 'survey-preview-back-' : 'survey-back-') ~ survey.id) }}">
{% if isPreview %}
<input type="hidden" name="preview_question" value="{{ question.id }}">
<input type="hidden" name="preview_history" value="{{ historyState }}">
{% endif %}
<button type="submit" class="survey-button secondary">{{ 'survey.survey.back'|trans }}</button>
</form>
{% endif %}
{{ form_start(surveyForm, {attr: {class: 'survey-form-grid'}}) }}
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
{% if isPreview %}
<input type="hidden" name="preview_question" value="{{ question.id }}">
<input type="hidden" name="preview_history" value="{{ historyState }}">
{% endif %}
{% if question.type == 'yes_no_maybe' %}
<div class="survey-grid" style="grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));">
{% for child in surveyForm.answer %}
@@ -108,25 +108,25 @@
</div>
{% else %}
{% if question.responseSummary is defined and question.responseSummary %}
<div class="survey-results-list">
<div class="survey-text-summary-grid">
{% for option in question.responseSummary %}
<div class="survey-results-row">
<article class="survey-text-summary-card">
<strong>{{ option.label|striptags|trim }}</strong>
<div class="survey-meta">
<strong>{{ option.label|striptags|trim }}</strong>
<span class="survey-badge neutral">{{ option.count }}</span>
<span class="survey-badge neutral">{{ option.percentage }}%</span>
</div>
<div class="survey-progress">
<span class="survey-progress-bar" style="width: {{ option.percentage }}%"></span>
</div>
</div>
</article>
{% endfor %}
</div>
{% endif %}
<div class="survey-results-list survey-results-responses">
<div class="survey-text-response-grid survey-results-responses">
{% for response in question.responses %}
<blockquote class="survey-card survey-response-card">{{ response|striptags|trim|nl2br }}</blockquote>
<article class="survey-card survey-response-card">
<span class="survey-response-card__index">{{ loop.index }}</span>
<blockquote>{{ response|striptags|trim|nl2br }}</blockquote>
</article>
{% else %}
<p>{{ 'survey.results.no_text_responses'|trans }}</p>
{% endfor %}