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>
This commit is contained in:
1 parent
ab2dbfbc45
commit
fa0bbaa73c
12 files changed
+50
-3
No files matched your search
@@ -73,7 +73,7 @@ $GLOBALS['TL_DCA']['tl_survey_content'] = [
|
||||
],
|
||||
'palettes' => [
|
||||
'default' => '{question_legend},type,question,description;{settings_legend},mandatory,published',
|
||||
'yes_no_maybe' => '{question_legend},type,question,description;{settings_legend},mandatory,published,allowMaybe,jumpOnYes,jumpOnNo',
|
||||
'yes_no_maybe' => '{question_legend},type,question,description;{settings_legend},mandatory,published,allowMaybe,showThumbs,jumpOnYes,jumpOnNo',
|
||||
'text' => '{question_legend},type,question,description;{settings_legend},mandatory,published',
|
||||
'range' => '{question_legend},type,question,description;{settings_legend},mandatory,published,rangeMin,rangeMax,rangeStep',
|
||||
'choice' => '{question_legend},type,question,description;{settings_legend},mandatory,published,allowMultiple,answerOption1,answerOption2,answerOption3,answerOption4,answerOption5,answerOption6,answerOption7,answerOption8,answerOption9,answerOption10',
|
||||
@@ -111,7 +111,8 @@ $GLOBALS['TL_DCA']['tl_survey_content'] = [
|
||||
'mandatory' => [
|
||||
'label' => &$GLOBALS['TL_LANG']['tl_survey_content']['mandatory'],
|
||||
'inputType' => 'checkbox',
|
||||
'default' => '1',
|
||||
// Neue Fragen sind bewusst freiwillig; Pflicht wird aktiv angehakt
|
||||
// (Kundenentscheidung 09/2026, Pretest-Punkt 3).
|
||||
'eval' => ['tl_class' => 'w50 m12'],
|
||||
'sql' => "char(1) NOT NULL default ''",
|
||||
],
|
||||
@@ -128,6 +129,12 @@ $GLOBALS['TL_DCA']['tl_survey_content'] = [
|
||||
'eval' => ['tl_class' => 'w50 m12 clr'],
|
||||
'sql' => "char(1) NOT NULL default ''",
|
||||
],
|
||||
'showThumbs' => [
|
||||
'label' => &$GLOBALS['TL_LANG']['tl_survey_content']['showThumbs'],
|
||||
'inputType' => 'checkbox',
|
||||
'eval' => ['tl_class' => 'w50 m12'],
|
||||
'sql' => "char(1) NOT NULL default ''",
|
||||
],
|
||||
'jumpOnYes' => [
|
||||
'label' => &$GLOBALS['TL_LANG']['tl_survey_content']['jumpOnYes'],
|
||||
'inputType' => 'select',
|
||||
|
||||
@@ -15,6 +15,7 @@ $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', 'Ergänzt die Ja-Nein-Frage um die Antwortmöglichkeit Vielleicht.'];
|
||||
$GLOBALS['TL_LANG']['tl_survey_content']['showThumbs'] = ['Antworten als Daumen darstellen', 'Zeigt bei Ja/Nein/Vielleicht zusätzlich Daumen-Symbole an (z. B. für Befragungen mit Kindern). Gespeichert und ausgewertet werden weiterhin die Antworten Ja, Nein und 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.'];
|
||||
|
||||
@@ -15,6 +15,7 @@ $GLOBALS['TL_LANG']['tl_survey_content']['settings_legend'] = 'Settings';
|
||||
$GLOBALS['TL_LANG']['tl_survey_content']['mandatory'] = ['Required question', 'This question must be answered.'];
|
||||
$GLOBALS['TL_LANG']['tl_survey_content']['published'] = ['Active', 'The question is shown in the survey.'];
|
||||
$GLOBALS['TL_LANG']['tl_survey_content']['allowMaybe'] = ['Offer maybe', 'Adds the Maybe answer option to the yes-no question.'];
|
||||
$GLOBALS['TL_LANG']['tl_survey_content']['showThumbs'] = ['Show thumb icons', 'Displays thumb icons for yes/no/maybe answers (e.g. for surveys with children). Answers are still stored and evaluated as yes, no and maybe.'];
|
||||
$GLOBALS['TL_LANG']['tl_survey_content']['jumpOnYes'] = ['Jump to question on yes', 'Jumps directly to this question when the answer is Yes.'];
|
||||
$GLOBALS['TL_LANG']['tl_survey_content']['jumpOnNo'] = ['Jump to question on no', 'Jumps directly to this question when the answer is No.'];
|
||||
$GLOBALS['TL_LANG']['tl_survey_content']['allowMultiple'] = ['Enable multiple choice', 'Allows multiple answers instead of a single selection.'];
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
<label class="survey-inline-check">{{ form_widget(form.mandatory) }}<span>{{ 'survey.edit.mandatory'|trans }}</span></label>
|
||||
<label class="survey-inline-check">{{ form_widget(form.published) }}<span>{{ 'survey.edit.active'|trans }}</span></label>
|
||||
<label class="survey-inline-check yes-no-config-field"{% if questionType != 'yes_no_maybe' %} style="display:none"{% endif %}>{{ form_widget(form.allowMaybe) }}<span>{{ 'survey.edit.allow_maybe'|trans }}</span></label>
|
||||
<label class="survey-inline-check yes-no-config-field"{% if questionType != 'yes_no_maybe' %} style="display:none"{% endif %}>{{ form_widget(form.showThumbs) }}<span>{{ 'survey.edit.show_thumbs'|trans }}</span></label>
|
||||
<label class="survey-inline-check choice-config-field"{% if questionType != 'choice' %} style="display:none"{% endif %}>{{ form_widget(form.allowMultiple) }}<span>{{ 'survey.edit.allow_multiple'|trans }}</span></label>
|
||||
</div>
|
||||
<div class="yes-no-config-field survey-grid-columns" style="grid-template-columns: repeat(2, minmax(0, 1fr));{% if questionType != 'yes_no_maybe' %}display:none;{% endif %}">
|
||||
|
||||
@@ -79,9 +79,16 @@
|
||||
{% set answerChildren = surveyForm.answer is defined ? surveyForm.answer|filter(child => child.vars.value is not defined or child.vars.value != '__no_answer__') : [] %}
|
||||
{% set noAnswerChildren = surveyForm.answer is defined ? surveyForm.answer|filter(child => child.vars.value is defined and child.vars.value == '__no_answer__') : [] %}
|
||||
{% if question.type == 'yes_no_maybe' %}
|
||||
{# Reine Darstellungsoption: gespeichert wird weiterhin yes/no/maybe. #}
|
||||
{% set showThumbIcons = '1' == question.showThumbs %}
|
||||
<div class="survey-grid" style="grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));" data-survey-answer-zone>
|
||||
{% for child in answerChildren %}
|
||||
<label class="survey-card" style="cursor: pointer;">
|
||||
{% if showThumbIcons and child.vars.value in ['yes', 'no', 'maybe'] %}
|
||||
<span class="survey-thumb survey-thumb--{{ child.vars.value }}" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" focusable="false"><path fill="currentColor" d="M2 20h2c.55 0 1-.45 1-1v-9c0-.55-.45-1-1-1H2v11zm19.83-7.12c.11-.25.17-.52.17-.8V11c0-1.1-.9-2-2-2h-5.5l.92-4.65c.05-.22.02-.46-.08-.66-.23-.45-.52-.86-.88-1.22L14 2 7.59 8.41C7.21 8.79 7 9.3 7 9.83v7.84C7 18.95 8.05 20 9.34 20h8.11c.7 0 1.36-.37 1.72-.97l2.66-6.15z"/></svg>
|
||||
</span>
|
||||
{% endif %}
|
||||
<div class="survey-meta"><strong>{{ child.vars.label|striptags|trim }}</strong>{{ form_widget(child) }}</div>
|
||||
{% set jumpHint = jumpHints|default({})[child.vars.value]|default(null) %}
|
||||
{% if jumpHint %}
|
||||
|
||||
@@ -735,6 +735,21 @@
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* Optionale Daumen-Darstellung bei Ja/Nein/Vielleicht (z. B. Kinderbefragungen).
|
||||
Reine Anzeige – gespeichert wird weiterhin yes/no/maybe. */
|
||||
.survey-thumb {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 0.2rem auto 0.55rem;
|
||||
}
|
||||
|
||||
.survey-thumb svg { width: 46px; height: 46px; }
|
||||
.survey-thumb--yes { color: var(--survey-green); }
|
||||
.survey-thumb--no { color: var(--survey-orange); }
|
||||
.survey-thumb--maybe { color: var(--survey-gray-dark); }
|
||||
.survey-thumb--no svg { transform: rotate(180deg); }
|
||||
.survey-thumb--maybe svg { transform: rotate(90deg); }
|
||||
|
||||
.survey-preview-bar .survey-preview-restart {
|
||||
flex-shrink: 0;
|
||||
padding: 0.45rem 0.95rem;
|
||||
|
||||
@@ -11,9 +11,12 @@ final class SurveyQuestionData
|
||||
public string $type = 'yes_no_maybe';
|
||||
public string $question = '';
|
||||
public ?string $description = '';
|
||||
public bool $mandatory = true;
|
||||
// Neue Fragen sind bewusst freiwillig; Pflicht wird aktiv angehakt
|
||||
// (Kundenentscheidung 09/2026, Pretest-Punkt 3).
|
||||
public bool $mandatory = false;
|
||||
public bool $published = true;
|
||||
public bool $allowMaybe = false;
|
||||
public bool $showThumbs = false;
|
||||
public bool $allowMultiple = false;
|
||||
public ?int $jumpOnYes = 0;
|
||||
public ?int $jumpOnNo = 0;
|
||||
@@ -46,6 +49,7 @@ final class SurveyQuestionData
|
||||
$data->mandatory = '1' === (string) $question->mandatory;
|
||||
$data->published = '1' === (string) $question->published;
|
||||
$data->allowMaybe = '1' === (string) $question->allowMaybe;
|
||||
$data->showThumbs = '1' === (string) $question->showThumbs;
|
||||
$data->allowMultiple = '1' === (string) $question->allowMultiple;
|
||||
$data->jumpOnYes = (int) $question->jumpOnYes;
|
||||
$data->jumpOnNo = (int) $question->jumpOnNo;
|
||||
@@ -74,6 +78,7 @@ final class SurveyQuestionData
|
||||
'mandatory' => $this->mandatory,
|
||||
'published' => $this->published,
|
||||
'allowMaybe' => $this->allowMaybe,
|
||||
'showThumbs' => $this->showThumbs,
|
||||
'allowMultiple' => $this->allowMultiple,
|
||||
'jumpOnYes' => max(0, (int) ($this->jumpOnYes ?? 0)),
|
||||
'jumpOnNo' => max(0, (int) ($this->jumpOnNo ?? 0)),
|
||||
|
||||
@@ -71,6 +71,11 @@ final class SurveyQuestionEditorType extends AbstractType
|
||||
'required' => false,
|
||||
'attr' => ['data-question-editor-target' => 'yesNoMaybeField'],
|
||||
])
|
||||
->add('showThumbs', CheckboxType::class, [
|
||||
'label' => 'Antworten als Daumen darstellen',
|
||||
'required' => false,
|
||||
'attr' => ['data-question-editor-target' => 'yesNoMaybeField'],
|
||||
])
|
||||
->add('jumpOnYes', ChoiceType::class, [
|
||||
'label' => 'Zur Frage springen bei Auswahl ja',
|
||||
'required' => false,
|
||||
|
||||
@@ -298,6 +298,7 @@ final class SurveyQuestionRepository
|
||||
'mandatory' => !$isSection && !empty($data['mandatory']) ? '1' : '',
|
||||
'published' => $isSection || !empty($data['published']) ? '1' : '',
|
||||
'allowMaybe' => $isYesNo && !empty($data['allowMaybe']) ? '1' : '',
|
||||
'showThumbs' => $isYesNo && !empty($data['showThumbs']) ? '1' : '',
|
||||
'jumpOnYes' => $isYesNo ? max(0, (int) ($data['jumpOnYes'] ?? $existing?->jumpOnYes ?? 0)) : 0,
|
||||
'jumpOnNo' => $isYesNo ? max(0, (int) ($data['jumpOnNo'] ?? $existing?->jumpOnNo ?? 0)) : 0,
|
||||
'allowMultiple' => $isChoice && !empty($data['allowMultiple']) ? '1' : '',
|
||||
|
||||
@@ -153,6 +153,7 @@ final class SurveyEditorService
|
||||
'mandatory' => '1' === (string) $sourceQuestion->mandatory,
|
||||
'published' => '1' === (string) $sourceQuestion->published,
|
||||
'allowMaybe' => '1' === (string) ($sourceQuestion->allowMaybe ?? ''),
|
||||
'showThumbs' => '1' === (string) ($sourceQuestion->showThumbs ?? ''),
|
||||
'allowMultiple' => '1' === (string) ($sourceQuestion->allowMultiple ?? ''),
|
||||
'answerOption1' => (string) ($sourceQuestion->answerOption1 ?? ''),
|
||||
'answerOption2' => (string) ($sourceQuestion->answerOption2 ?? ''),
|
||||
@@ -191,6 +192,7 @@ final class SurveyEditorService
|
||||
'mandatory' => '1' === (string) $sourceQuestion->mandatory,
|
||||
'published' => '1' === (string) $sourceQuestion->published,
|
||||
'allowMaybe' => '1' === (string) ($sourceQuestion->allowMaybe ?? ''),
|
||||
'showThumbs' => '1' === (string) ($sourceQuestion->showThumbs ?? ''),
|
||||
'allowMultiple' => '1' === (string) ($sourceQuestion->allowMultiple ?? ''),
|
||||
'answerOption1' => (string) ($sourceQuestion->answerOption1 ?? ''),
|
||||
'answerOption2' => (string) ($sourceQuestion->answerOption2 ?? ''),
|
||||
|
||||
@@ -88,6 +88,7 @@ survey:
|
||||
mandatory: "Pflichtfrage"
|
||||
active: "Aktiv"
|
||||
allow_maybe: "Vielleicht anbieten"
|
||||
show_thumbs: "Antworten als Daumen darstellen"
|
||||
jump_yes: "Zur Frage springen bei Auswahl ja"
|
||||
jump_no: "Zur Frage springen bei Auswahl nein"
|
||||
allow_multiple: "Multiple-Choice aktivieren"
|
||||
|
||||
@@ -88,6 +88,7 @@ survey:
|
||||
mandatory: "Required question"
|
||||
active: "Active"
|
||||
allow_maybe: "Offer maybe"
|
||||
show_thumbs: "Show thumb icons"
|
||||
jump_yes: "Jump to question on yes"
|
||||
jump_no: "Jump to question on no"
|
||||
allow_multiple: "Enable multiple choice"
|
||||
|
||||
Reference in new issue
Block a user