decidim-forms 0.21.0 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/config/admin/decidim_forms_manifest.js +1 -0
- data/app/assets/images/decidim/surveys/icon.svg +1 -19
- data/app/assets/javascripts/decidim/forms/admin/collapsible_questions.js.es6 +13 -0
- data/app/assets/javascripts/decidim/forms/admin/forms.js.es6 +95 -7
- data/app/assets/javascripts/decidim/forms/admin/live_text_update.component.js.es6 +52 -0
- data/app/assets/javascripts/decidim/forms/forms.js.es6 +42 -1
- data/app/assets/javascripts/decidim/forms/max_choices_alert.component.js.es6 +44 -0
- data/app/assets/stylesheets/decidim/forms/forms.scss +39 -0
- data/app/cells/decidim/forms/matrix_readonly/show.erb +5 -0
- data/app/cells/decidim/forms/matrix_readonly_cell.rb +12 -0
- data/app/cells/decidim/forms/question_readonly/show.erb +5 -1
- data/app/cells/decidim/forms/question_readonly_cell.rb +5 -0
- data/app/cells/decidim/forms/step_navigation/show.erb +35 -0
- data/app/cells/decidim/forms/step_navigation_cell.rb +46 -0
- data/app/commands/decidim/forms/admin/update_questionnaire.rb +8 -0
- data/app/commands/decidim/forms/answer_questionnaire.rb +2 -1
- data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +6 -2
- data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +11 -2
- data/app/forms/decidim/forms/admin/question_form.rb +20 -1
- data/app/forms/decidim/forms/admin/question_matrix_row_form.rb +26 -0
- data/app/forms/decidim/forms/answer_choice_form.rb +1 -0
- data/app/forms/decidim/forms/answer_form.rb +16 -2
- data/app/forms/decidim/forms/questionnaire_form.rb +25 -3
- data/app/helpers/decidim/forms/admin/application_helper.rb +16 -0
- data/app/models/decidim/forms/answer_choice.rb +7 -0
- data/app/models/decidim/forms/question.rb +18 -2
- data/app/models/decidim/forms/question_matrix_row.rb +12 -0
- data/app/views/decidim/forms/admin/questionnaires/_answer_option_template.html.erb +1 -1
- data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +37 -4
- data/app/views/decidim/forms/admin/questionnaires/_matrix_row.html.erb +34 -0
- data/app/views/decidim/forms/admin/questionnaires/_matrix_row_template.html.erb +7 -0
- data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +29 -6
- data/app/views/decidim/forms/admin/questionnaires/_separator.html.erb +41 -0
- data/app/views/decidim/forms/questionnaires/_answer.html.erb +21 -92
- data/app/views/decidim/forms/questionnaires/answers/_long_answer.html.erb +1 -0
- data/app/views/decidim/forms/questionnaires/answers/_matrix_multiple.html.erb +43 -0
- data/app/views/decidim/forms/questionnaires/answers/_matrix_single.html.erb +43 -0
- data/app/views/decidim/forms/questionnaires/answers/_multiple_option.html.erb +23 -0
- data/app/views/decidim/forms/questionnaires/answers/_separator.html.erb +1 -0
- data/app/views/decidim/forms/questionnaires/answers/_short_answer.html.erb +1 -0
- data/app/views/decidim/forms/questionnaires/answers/_single_option.html.erb +30 -0
- data/app/views/decidim/forms/questionnaires/answers/_sorting.html.erb +23 -0
- data/app/views/decidim/forms/questionnaires/show.html.erb +57 -25
- data/config/locales/ar.yml +7 -3
- data/config/locales/bg-BG.yml +16 -0
- data/config/locales/ca.yml +35 -3
- data/config/locales/cs.yml +35 -3
- data/config/locales/da-DK.yml +1 -0
- data/config/locales/de.yml +41 -3
- data/config/locales/el.yml +119 -0
- data/config/locales/en.yml +35 -3
- data/config/locales/es-MX.yml +35 -3
- data/config/locales/es-PY.yml +35 -3
- data/config/locales/es.yml +35 -3
- data/config/locales/et-EE.yml +1 -0
- data/config/locales/eu.yml +7 -3
- data/config/locales/fi-plain.yml +35 -3
- data/config/locales/fi.yml +36 -4
- data/config/locales/fr-CA.yml +120 -0
- data/config/locales/fr.yml +36 -4
- data/config/locales/ga-IE.yml +1 -0
- data/config/locales/gl.yml +7 -3
- data/config/locales/hr-HR.yml +1 -0
- data/config/locales/hu.yml +11 -3
- data/config/locales/id-ID.yml +7 -3
- data/config/locales/it.yml +36 -4
- data/config/locales/ja-JP.yml +120 -0
- data/config/locales/lt-LT.yml +1 -0
- data/config/locales/lv-LV.yml +119 -0
- data/config/locales/mt-MT.yml +1 -0
- data/config/locales/nl.yml +35 -3
- data/config/locales/no.yml +7 -3
- data/config/locales/pl.yml +63 -25
- data/config/locales/pt-BR.yml +8 -4
- data/config/locales/pt.yml +62 -24
- data/config/locales/ro-RO.yml +118 -0
- data/config/locales/ru.yml +4 -1
- data/config/locales/sk-SK.yml +88 -0
- data/config/locales/sk.yml +92 -0
- data/config/locales/sl.yml +5 -0
- data/config/locales/sr-CS.yml +1 -0
- data/config/locales/sv.yml +38 -6
- data/config/locales/tr-TR.yml +7 -3
- data/db/migrate/20200225123810_create_decidim_forms_question_matrix_rows.rb +11 -0
- data/db/migrate/20200304152939_add_matrix_row_id_to_decidim_forms_answer_choices.rb +11 -0
- data/lib/decidim/forms/test/factories.rb +20 -0
- data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +313 -36
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +346 -15
- data/lib/decidim/forms/user_answers_serializer.rb +21 -4
- data/lib/decidim/forms/version.rb +1 -1
- metadata +45 -8
data/config/locales/ru.yml
CHANGED
@@ -13,9 +13,10 @@ ru:
|
|
13
13
|
remove: Удалить
|
14
14
|
edit:
|
15
15
|
save: Сохранить
|
16
|
-
title: Заголовок
|
17
16
|
form:
|
18
17
|
add_question: Добавить вопрос
|
18
|
+
matrix_row:
|
19
|
+
remove: Удалить
|
19
20
|
question:
|
20
21
|
add_answer_option: Добавить вариант ответа
|
21
22
|
any: Любые
|
@@ -42,4 +43,6 @@ ru:
|
|
42
43
|
questionnaire_for_private_users:
|
43
44
|
body: Форма доступна только для частных пользователей
|
44
45
|
title: Форма закрыта
|
46
|
+
step_navigation:
|
47
|
+
show:
|
45
48
|
submit: Отправить
|
@@ -0,0 +1,88 @@
|
|
1
|
+
sk:
|
2
|
+
activemodel:
|
3
|
+
attributes:
|
4
|
+
answer:
|
5
|
+
body: Odpoveď
|
6
|
+
question:
|
7
|
+
max_choices: Maximálny počet možností
|
8
|
+
question_type: Typ
|
9
|
+
questionnaire_question:
|
10
|
+
mandatory: Povinné
|
11
|
+
errors:
|
12
|
+
models:
|
13
|
+
answer:
|
14
|
+
attributes:
|
15
|
+
choices:
|
16
|
+
missing: nie je kompletné
|
17
|
+
too_many: je príliš veľa
|
18
|
+
questionnaire:
|
19
|
+
request_invalid: Počas požiadavku sa vyskytla chyba, skúste to znova.
|
20
|
+
decidim:
|
21
|
+
forms:
|
22
|
+
admin:
|
23
|
+
models:
|
24
|
+
components:
|
25
|
+
description: Popis
|
26
|
+
tos: Podmienky použitia
|
27
|
+
questionnaires:
|
28
|
+
answer_option:
|
29
|
+
answer_option: Možnosť odpovede
|
30
|
+
free_text: Voľný text
|
31
|
+
remove: Odstrániť
|
32
|
+
statement: Prehlásenie
|
33
|
+
edit:
|
34
|
+
save: Uložiť
|
35
|
+
title: Názov
|
36
|
+
form:
|
37
|
+
add_question: Pridať otázku
|
38
|
+
already_answered_warning: Na formulár už niekto odpovedal, takže nemôžete meniť jeho otázky.
|
39
|
+
question:
|
40
|
+
add_answer_option: Pridať možnosť odpovede
|
41
|
+
any: Akékoľvek
|
42
|
+
description: Popis
|
43
|
+
down: Nadol
|
44
|
+
question: Otázka
|
45
|
+
remove: Odstrániť
|
46
|
+
statement: Prehlásenie
|
47
|
+
up: Hore
|
48
|
+
update:
|
49
|
+
invalid: Vyskytol sa problém s ukladaním formulára.
|
50
|
+
success: Formulár úspešne uložený.
|
51
|
+
errors:
|
52
|
+
answer:
|
53
|
+
body: Telo nemôže byť prázdne
|
54
|
+
question_types:
|
55
|
+
long_answer: Dlhá odpoveď
|
56
|
+
multiple_option: Viacero možností
|
57
|
+
short_answer: Krátka odpoveď
|
58
|
+
single_option: Jedna možnosť
|
59
|
+
sorting: Zoradenie
|
60
|
+
questionnaires:
|
61
|
+
answer:
|
62
|
+
invalid: Vyskytol sa problém s odpovedaním na formulár.
|
63
|
+
success: Formulár úspešne zodpovedaný.
|
64
|
+
question:
|
65
|
+
max_choices: 'Maximum možností: %{n}'
|
66
|
+
show:
|
67
|
+
answer_questionnaire:
|
68
|
+
anonymous_user_message: <a href="%{sign_in_link}">Prihláste sa so svojím účtom</a> alebo <a href="%{sign_up_link}"> sa zaregistrujte</a>, aby ste mohli odpovedať.
|
69
|
+
title: Odpovedať na formulár
|
70
|
+
are_you_sure: Táto akcia sa nedá vrátiť späť, a nebudete môcť upraviť svoje odpovede. Ste si istí?
|
71
|
+
questionnaire_answered:
|
72
|
+
body: Na tento formulár už ste dopovedali.
|
73
|
+
title: Už ste odpovedali
|
74
|
+
questionnaire_closed:
|
75
|
+
body: Tento formulár je už uzavretý a nedá sa naň odpovedať.
|
76
|
+
title: Formulár je uzavretý.
|
77
|
+
questionnaire_for_private_users:
|
78
|
+
body: Formulár je otvorený len pre súkromných používateľov
|
79
|
+
title: Formulár je uzavretý
|
80
|
+
submit: Poslať
|
81
|
+
tos_agreement: Účasťou súhlasíte s našimi Podmienkami použitia
|
82
|
+
user_answers_serializer:
|
83
|
+
created_at: Odpovedané na
|
84
|
+
id: ID odpovede
|
85
|
+
ip_hash: IP Hash
|
86
|
+
registered: Registrovaný
|
87
|
+
unregistered: Neregistrovaný
|
88
|
+
user_status: Status Užívateľa
|
@@ -0,0 +1,92 @@
|
|
1
|
+
sk:
|
2
|
+
activemodel:
|
3
|
+
attributes:
|
4
|
+
answer:
|
5
|
+
body: Odpoveď
|
6
|
+
question:
|
7
|
+
max_choices: Maximálny počet možností
|
8
|
+
question_type: Typ
|
9
|
+
questionnaire_question:
|
10
|
+
mandatory: Povinné
|
11
|
+
errors:
|
12
|
+
models:
|
13
|
+
answer:
|
14
|
+
attributes:
|
15
|
+
choices:
|
16
|
+
missing: nie je kompletné
|
17
|
+
too_many: je príliš veľa
|
18
|
+
questionnaire:
|
19
|
+
request_invalid: Počas požiadavku sa vyskytla chyba, skúste to znova.
|
20
|
+
decidim:
|
21
|
+
forms:
|
22
|
+
admin:
|
23
|
+
models:
|
24
|
+
components:
|
25
|
+
description: Popis
|
26
|
+
tos: Podmienky použitia
|
27
|
+
questionnaires:
|
28
|
+
answer_option:
|
29
|
+
answer_option: Možnosť odpovede
|
30
|
+
free_text: Voľný text
|
31
|
+
remove: Odstrániť
|
32
|
+
statement: Prehlásenie
|
33
|
+
edit:
|
34
|
+
save: Uložiť
|
35
|
+
form:
|
36
|
+
add_question: Pridať otázku
|
37
|
+
already_answered_warning: Na formulár už niekto odpovedal, takže nemôžete meniť jeho otázky.
|
38
|
+
matrix_row:
|
39
|
+
remove: Odstrániť
|
40
|
+
statement: Prehlásenie
|
41
|
+
question:
|
42
|
+
add_answer_option: Pridať možnosť odpovede
|
43
|
+
any: Akékoľvek
|
44
|
+
description: Popis
|
45
|
+
down: Nadol
|
46
|
+
question: Otázka
|
47
|
+
remove: Odstrániť
|
48
|
+
statement: Prehlásenie
|
49
|
+
up: Hore
|
50
|
+
update:
|
51
|
+
invalid: Vyskytol sa problém s ukladaním formulára.
|
52
|
+
success: Formulár úspešne uložený.
|
53
|
+
errors:
|
54
|
+
answer:
|
55
|
+
body: Telo nemôže byť prázdne
|
56
|
+
question_types:
|
57
|
+
long_answer: Dlhá odpoveď
|
58
|
+
multiple_option: Viacero možností
|
59
|
+
short_answer: Krátka odpoveď
|
60
|
+
single_option: Jedna možnosť
|
61
|
+
sorting: Zoradenie
|
62
|
+
questionnaires:
|
63
|
+
answer:
|
64
|
+
invalid: Vyskytol sa problém s odpovedaním na formulár.
|
65
|
+
success: Formulár úspešne zodpovedaný.
|
66
|
+
question:
|
67
|
+
max_choices: 'Maximum možností: %{n}'
|
68
|
+
show:
|
69
|
+
answer_questionnaire:
|
70
|
+
anonymous_user_message: <a href="%{sign_in_link}">Prihláste sa so svojím účtom</a> alebo <a href="%{sign_up_link}"> sa zaregistrujte</a>, aby ste mohli odpovedať.
|
71
|
+
title: Odpovedať na formulár
|
72
|
+
questionnaire_answered:
|
73
|
+
body: Na tento formulár už ste dopovedali.
|
74
|
+
title: Už ste odpovedali
|
75
|
+
questionnaire_closed:
|
76
|
+
body: Tento formulár je už uzavretý a nedá sa naň odpovedať.
|
77
|
+
title: Formulár je uzavretý.
|
78
|
+
questionnaire_for_private_users:
|
79
|
+
body: Formulár je otvorený len pre súkromných používateľov
|
80
|
+
title: Formulár je uzavretý
|
81
|
+
tos_agreement: Účasťou súhlasíte s našimi Podmienkami použitia
|
82
|
+
step_navigation:
|
83
|
+
show:
|
84
|
+
are_you_sure: Táto akcia sa nedá vrátiť späť, a nebudete môcť upraviť svoje odpovede. Ste si istí?
|
85
|
+
submit: Poslať
|
86
|
+
user_answers_serializer:
|
87
|
+
created_at: Odpovedané na
|
88
|
+
id: ID odpovede
|
89
|
+
ip_hash: IP Hash
|
90
|
+
registered: Registrovaný
|
91
|
+
unregistered: Neregistrovaný
|
92
|
+
user_status: Status Užívateľa
|
@@ -0,0 +1 @@
|
|
1
|
+
sr:
|
data/config/locales/sv.yml
CHANGED
@@ -16,7 +16,7 @@ sv:
|
|
16
16
|
missing: är inte fullständiga
|
17
17
|
too_many: är för många
|
18
18
|
questionnaire:
|
19
|
-
request_invalid: Ett fel uppstod när begäran skulle hanteras.
|
19
|
+
request_invalid: Ett fel uppstod när begäran skulle hanteras. Försök igen
|
20
20
|
decidim:
|
21
21
|
forms:
|
22
22
|
admin:
|
@@ -32,27 +32,52 @@ sv:
|
|
32
32
|
statement: Påstående
|
33
33
|
edit:
|
34
34
|
save: Spara
|
35
|
-
title:
|
35
|
+
title: Redigera frågeformulär
|
36
36
|
form:
|
37
37
|
add_question: Lägg till fråga
|
38
|
+
add_separator: Lägg till separator
|
38
39
|
already_answered_warning: Frågeformuläret har redan besvarats av vissa användare så du inte kan ändra dess frågor.
|
40
|
+
collapse: Komprimera alla frågor
|
41
|
+
expand: Expandera alla frågor
|
42
|
+
matrix_row:
|
43
|
+
matrix_row: Rad
|
44
|
+
remove: Ta bort
|
45
|
+
statement: Påstående
|
39
46
|
question:
|
40
47
|
add_answer_option: Lägg till svarsalternativ
|
48
|
+
add_matrix_row: Lägg till rad
|
41
49
|
any: Någon
|
50
|
+
collapse: Komprimera
|
42
51
|
description: Beskrivning
|
43
52
|
down: Ned
|
53
|
+
expand: Expandera
|
44
54
|
question: Fråga
|
45
55
|
remove: Ta bort
|
46
56
|
statement: Påstående
|
47
57
|
up: Upp
|
58
|
+
separator:
|
59
|
+
down: Ner
|
60
|
+
remove: Radera
|
61
|
+
separator: Avgränsare
|
62
|
+
up: Upp
|
48
63
|
update:
|
49
64
|
invalid: Det gick inte att spara formuläret.
|
50
65
|
success: Formuläret har sparats.
|
51
66
|
errors:
|
52
67
|
answer:
|
53
68
|
body: Kroppen kan inte vara to
|
69
|
+
files:
|
70
|
+
extension_whitelist: 'Godkända format:'
|
71
|
+
images:
|
72
|
+
dimensions: "%{width} x %{height} px"
|
73
|
+
dimensions_info: 'Denna bild kommer att vara:'
|
74
|
+
processors:
|
75
|
+
resize_and_pad: Anpassad och vadderad till
|
76
|
+
resize_to_fit: Anpassad för att passa
|
54
77
|
question_types:
|
55
78
|
long_answer: Långt svar
|
79
|
+
matrix_multiple: Matris (flera alternativ)
|
80
|
+
matrix_single: Matris (Single alternativ)
|
56
81
|
multiple_option: Flera alternativ
|
57
82
|
short_answer: Kort svar
|
58
83
|
single_option: Ett alternativ
|
@@ -60,6 +85,7 @@ sv:
|
|
60
85
|
questionnaires:
|
61
86
|
answer:
|
62
87
|
invalid: Det gick inte att besvara formuläret.
|
88
|
+
max_choices_alert: Det finns för många val valda
|
63
89
|
success: Formuläret har besvarats.
|
64
90
|
question:
|
65
91
|
max_choices: 'Högst antal val: %{n}'
|
@@ -67,7 +93,8 @@ sv:
|
|
67
93
|
answer_questionnaire:
|
68
94
|
anonymous_user_message: <a href="%{sign_in_link}">Logga in med ditt konto</a> eller <a href="%{sign_up_link}">registrera dig</a> om du vill svara på formuläret.
|
69
95
|
title: Besvara formuläret
|
70
|
-
|
96
|
+
current_step: Steg %{step}
|
97
|
+
of_total_steps: av %{total_steps}
|
71
98
|
questionnaire_answered:
|
72
99
|
body: Du har redan besvarat det här formuläret.
|
73
100
|
title: Redan svarat
|
@@ -77,12 +104,17 @@ sv:
|
|
77
104
|
questionnaire_for_private_users:
|
78
105
|
body: Formuläret är endast tillgängligt för privata användare
|
79
106
|
title: Formuläret är stängt
|
80
|
-
submit: Skicka in
|
81
107
|
tos_agreement: Genom att delta godkänner du användarvillkoren
|
108
|
+
step_navigation:
|
109
|
+
show:
|
110
|
+
are_you_sure: Den här åtgärden kan inte ångras och du kommer inte att kunna redigera dina svar. Är du säker?
|
111
|
+
back: Tillbaka
|
112
|
+
continue: Fortsätt
|
113
|
+
submit: Skicka in
|
82
114
|
user_answers_serializer:
|
83
115
|
created_at: Besvarad
|
84
116
|
id: Svars-ID
|
85
|
-
ip_hash: Ip
|
117
|
+
ip_hash: Ip-hash
|
86
118
|
registered: Registrerad
|
87
|
-
unregistered:
|
119
|
+
unregistered: Ej registrerad
|
88
120
|
user_status: Användarstatus
|
data/config/locales/tr-TR.yml
CHANGED
@@ -30,10 +30,12 @@ tr:
|
|
30
30
|
statement: Beyan
|
31
31
|
edit:
|
32
32
|
save: Kayıt etmek
|
33
|
-
title: Başlık
|
34
33
|
form:
|
35
34
|
add_question: Soru ekle
|
36
35
|
already_answered_warning: Form, bazı kullanıcılar tarafından zaten yanıtlandı, bu nedenle sorularını değiştiremezsiniz.
|
36
|
+
matrix_row:
|
37
|
+
remove: Kaldır
|
38
|
+
statement: Beyan
|
37
39
|
question:
|
38
40
|
add_answer_option: Cevap seçeneği ekle
|
39
41
|
any: herhangi
|
@@ -65,7 +67,6 @@ tr:
|
|
65
67
|
answer_questionnaire:
|
66
68
|
anonymous_user_message: <a href="%{sign_in_link}">Formu yanıtlamak için</a> veya <a href="%{sign_up_link}">hesabınızla giriş yapın</a>.
|
67
69
|
title: Formu cevapla
|
68
|
-
are_you_sure: Bu işlem geri alınamaz ve cevaplarınızı düzenleyemezsiniz. Emin misiniz?
|
69
70
|
questionnaire_answered:
|
70
71
|
body: Bu formu zaten cevapladınız.
|
71
72
|
title: Zaten cevaplandı
|
@@ -75,8 +76,11 @@ tr:
|
|
75
76
|
questionnaire_for_private_users:
|
76
77
|
body: Form yalnızca özel kullanıcılar tarafından kullanılabilir
|
77
78
|
title: Form kapatıldı
|
78
|
-
submit: Gönder
|
79
79
|
tos_agreement: Katılarak Hizmet Şartlarını kabul etmiş olursunuz.
|
80
|
+
step_navigation:
|
81
|
+
show:
|
82
|
+
are_you_sure: Bu işlem geri alınamaz ve cevaplarınızı düzenleyemezsiniz. Emin misiniz?
|
83
|
+
submit: Gönder
|
80
84
|
user_answers_serializer:
|
81
85
|
created_at: Yanıtlandı
|
82
86
|
id: Cevap kimliği
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateDecidimFormsQuestionMatrixRows < ActiveRecord::Migration[5.2]
|
4
|
+
def change
|
5
|
+
create_table :decidim_forms_question_matrix_rows do |t|
|
6
|
+
t.references :decidim_question, index: { name: "index_decidim_forms_question_matrix_questionnaire_id" }
|
7
|
+
t.integer :position, index: true
|
8
|
+
t.jsonb :body
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AddMatrixRowIdToDecidimFormsAnswerChoices < ActiveRecord::Migration[5.2]
|
4
|
+
class AnswerChoice < ApplicationRecord
|
5
|
+
self.table_name = :decidim_forms_answer_choices
|
6
|
+
end
|
7
|
+
|
8
|
+
def change
|
9
|
+
add_column :decidim_forms_answer_choices, :decidim_question_matrix_row_id, :integer
|
10
|
+
end
|
11
|
+
end
|
@@ -28,6 +28,7 @@ FactoryBot.define do
|
|
28
28
|
factory :questionnaire_question, class: "Decidim::Forms::Question" do
|
29
29
|
transient do
|
30
30
|
options { [] }
|
31
|
+
rows { [] }
|
31
32
|
end
|
32
33
|
|
33
34
|
body { generate_localized_title }
|
@@ -50,6 +51,14 @@ FactoryBot.define do
|
|
50
51
|
)
|
51
52
|
end
|
52
53
|
end
|
54
|
+
|
55
|
+
if question.matrix_rows.empty?
|
56
|
+
evaluator.rows.each do |row|
|
57
|
+
question.matrix_rows.build(
|
58
|
+
body: row["body"]
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
53
62
|
end
|
54
63
|
|
55
64
|
trait :with_answer_options do
|
@@ -57,6 +66,10 @@ FactoryBot.define do
|
|
57
66
|
Array.new(3).collect { build(:answer_option) }
|
58
67
|
end
|
59
68
|
end
|
69
|
+
|
70
|
+
trait :separator do
|
71
|
+
question_type { :separator }
|
72
|
+
end
|
60
73
|
end
|
61
74
|
|
62
75
|
factory :answer, class: "Decidim::Forms::Answer" do
|
@@ -75,5 +88,12 @@ FactoryBot.define do
|
|
75
88
|
factory :answer_choice, class: "Decidim::Forms::AnswerChoice" do
|
76
89
|
answer
|
77
90
|
answer_option { create(:answer_option, question: answer.question) }
|
91
|
+
matrix_row { create(:question_matrix_row, question: answer.question) }
|
92
|
+
end
|
93
|
+
|
94
|
+
factory :question_matrix_row, class: "Decidim::Forms::QuestionMatrixRow" do
|
95
|
+
question { create(:questionnaire_question) }
|
96
|
+
body { generate_localized_title }
|
97
|
+
position { 0 }
|
78
98
|
end
|
79
99
|
end
|
@@ -35,7 +35,9 @@ shared_examples_for "has questionnaire" do
|
|
35
35
|
|
36
36
|
check "questionnaire_tos_agreement"
|
37
37
|
|
38
|
-
accept_confirm
|
38
|
+
accept_confirm do
|
39
|
+
click_button "Submit"
|
40
|
+
end
|
39
41
|
|
40
42
|
within ".success.flash" do
|
41
43
|
expect(page).to have_content("successfully")
|
@@ -47,6 +49,73 @@ shared_examples_for "has questionnaire" do
|
|
47
49
|
expect(page).to have_no_i18n_content(question.body)
|
48
50
|
end
|
49
51
|
|
52
|
+
context "with multiple steps" do
|
53
|
+
let!(:separator) { create(:questionnaire_question, questionnaire: questionnaire, position: 1, question_type: :separator) }
|
54
|
+
let!(:question2) { create(:questionnaire_question, questionnaire: questionnaire, position: 2) }
|
55
|
+
|
56
|
+
before do
|
57
|
+
visit questionnaire_public_path
|
58
|
+
end
|
59
|
+
|
60
|
+
it "allows answering the first questionnaire" do
|
61
|
+
expect(page).to have_content("STEP 1 OF 2")
|
62
|
+
|
63
|
+
within ".answer-questionnaire__submit" do
|
64
|
+
expect(page).to have_no_content("Back")
|
65
|
+
end
|
66
|
+
|
67
|
+
answer_first_questionnaire
|
68
|
+
|
69
|
+
expect(page).to have_no_selector(".success.flash")
|
70
|
+
end
|
71
|
+
|
72
|
+
it "allows revisiting previously-answered questionnaires with my answers" do
|
73
|
+
answer_first_questionnaire
|
74
|
+
|
75
|
+
click_link "Back"
|
76
|
+
|
77
|
+
expect(page).to have_content("STEP 1 OF 2")
|
78
|
+
expect(page).to have_field("questionnaire_answers_0", with: "My first answer")
|
79
|
+
end
|
80
|
+
|
81
|
+
it "finishes the submission when answering the last questionnaire" do
|
82
|
+
answer_first_questionnaire
|
83
|
+
|
84
|
+
check "questionnaire_tos_agreement"
|
85
|
+
accept_confirm { click_button "Submit" }
|
86
|
+
|
87
|
+
within ".success.flash" do
|
88
|
+
expect(page).to have_content("successfully")
|
89
|
+
end
|
90
|
+
|
91
|
+
visit questionnaire_public_path
|
92
|
+
|
93
|
+
expect(page).to have_content("You have already answered this form.")
|
94
|
+
end
|
95
|
+
|
96
|
+
def answer_first_questionnaire
|
97
|
+
expect(page).to have_no_selector("#questionnaire_tos_agreement")
|
98
|
+
|
99
|
+
fill_in question.body["en"], with: "My first answer"
|
100
|
+
within ".answer-questionnaire__submit" do
|
101
|
+
click_link "Continue"
|
102
|
+
end
|
103
|
+
expect(page).to have_content("STEP 2 OF 2")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
it "requires confirmation when exiting mid-answering" do
|
108
|
+
visit questionnaire_public_path
|
109
|
+
|
110
|
+
fill_in question.body["en"], with: "My first answer"
|
111
|
+
|
112
|
+
dismiss_page_unload do
|
113
|
+
page.find(".logo-wrapper a").click
|
114
|
+
end
|
115
|
+
|
116
|
+
expect(page).to have_current_path questionnaire_public_path
|
117
|
+
end
|
118
|
+
|
50
119
|
context "when the questionnaire has already been answered by someone else" do
|
51
120
|
let!(:question) do
|
52
121
|
create(
|
@@ -205,6 +274,7 @@ shared_examples_for "has questionnaire" do
|
|
205
274
|
:questionnaire_question,
|
206
275
|
questionnaire: questionnaire,
|
207
276
|
question_type: question_type,
|
277
|
+
position: 1,
|
208
278
|
options: [
|
209
279
|
{ "body" => answer_option_bodies[0] },
|
210
280
|
{ "body" => answer_option_bodies[1] },
|
@@ -219,6 +289,7 @@ shared_examples_for "has questionnaire" do
|
|
219
289
|
questionnaire: questionnaire,
|
220
290
|
question_type: "multiple_option",
|
221
291
|
max_choices: 2,
|
292
|
+
position: 2,
|
222
293
|
options: [
|
223
294
|
{ "body" => Decidim::Faker::Localized.sentence },
|
224
295
|
{ "body" => Decidim::Faker::Localized.sentence },
|
@@ -283,16 +354,16 @@ shared_examples_for "has questionnaire" do
|
|
283
354
|
it "renders them as check boxes with attached text fields disabled by default" do
|
284
355
|
expect(page.first(".check-box-collection")).to have_selector("input[type=checkbox]", count: 3)
|
285
356
|
|
286
|
-
expect(page).to have_field("
|
357
|
+
expect(page).to have_field("questionnaire_responses_0_choices_2_custom_body", disabled: true, count: 1)
|
287
358
|
|
288
359
|
check answer_option_bodies[2]["en"]
|
289
360
|
|
290
|
-
expect(page).to have_field("
|
361
|
+
expect(page).to have_field("questionnaire_responses_0_choices_2_custom_body", disabled: false, count: 1)
|
291
362
|
end
|
292
363
|
|
293
364
|
it "saves the free text in a separate field if submission correct" do
|
294
365
|
check answer_option_bodies[2]["en"]
|
295
|
-
fill_in "
|
366
|
+
fill_in "questionnaire_responses_0_choices_2_custom_body", with: "Cacatua"
|
296
367
|
|
297
368
|
check "questionnaire_tos_agreement"
|
298
369
|
accept_confirm { click_button "Submit" }
|
@@ -305,12 +376,12 @@ shared_examples_for "has questionnaire" do
|
|
305
376
|
end
|
306
377
|
|
307
378
|
it "preserves the previous custom body if submission not correct" do
|
308
|
-
check "
|
309
|
-
check "
|
310
|
-
check "
|
379
|
+
check "questionnaire_responses_1_choices_0_body"
|
380
|
+
check "questionnaire_responses_1_choices_1_body"
|
381
|
+
check "questionnaire_responses_1_choices_2_body"
|
311
382
|
|
312
383
|
check answer_option_bodies[2]["en"]
|
313
|
-
fill_in "
|
384
|
+
fill_in "questionnaire_responses_0_choices_2_custom_body", with: "Cacatua"
|
314
385
|
|
315
386
|
check "questionnaire_tos_agreement"
|
316
387
|
accept_confirm { click_button "Submit" }
|
@@ -319,7 +390,7 @@ shared_examples_for "has questionnaire" do
|
|
319
390
|
expect(page).to have_content("There was a problem answering")
|
320
391
|
end
|
321
392
|
|
322
|
-
expect(page).to have_field("
|
393
|
+
expect(page).to have_field("questionnaire_responses_0_choices_2_custom_body", with: "Cacatua")
|
323
394
|
end
|
324
395
|
end
|
325
396
|
end
|
@@ -409,6 +480,8 @@ shared_examples_for "has questionnaire" do
|
|
409
480
|
check answer_options[1]["body"][:en]
|
410
481
|
check answer_options[2]["body"][:en]
|
411
482
|
|
483
|
+
expect(page).to have_content("too many choices")
|
484
|
+
|
412
485
|
check "questionnaire_tos_agreement"
|
413
486
|
|
414
487
|
accept_confirm { click_button "Submit" }
|
@@ -429,33 +502,6 @@ shared_examples_for "has questionnaire" do
|
|
429
502
|
end
|
430
503
|
end
|
431
504
|
|
432
|
-
context "when question type is multiple option" do
|
433
|
-
let(:answer_options) { Array.new(2) { { "body" => Decidim::Faker::Localized.sentence } } }
|
434
|
-
let!(:question) { create(:questionnaire_question, questionnaire: questionnaire, question_type: "multiple_option", options: answer_options) }
|
435
|
-
|
436
|
-
it "renders the question answers as a collection of radio buttons" do
|
437
|
-
visit questionnaire_public_path
|
438
|
-
|
439
|
-
expect(page).to have_selector(".check-box-collection input[type=checkbox]", count: 2)
|
440
|
-
|
441
|
-
check answer_options[0]["body"][:en]
|
442
|
-
check answer_options[1]["body"][:en]
|
443
|
-
|
444
|
-
check "questionnaire_tos_agreement"
|
445
|
-
|
446
|
-
accept_confirm { click_button "Submit" }
|
447
|
-
|
448
|
-
within ".success.flash" do
|
449
|
-
expect(page).to have_content("successfully")
|
450
|
-
end
|
451
|
-
|
452
|
-
visit questionnaire_public_path
|
453
|
-
|
454
|
-
expect(page).to have_content("You have already answered this form.")
|
455
|
-
expect(page).to have_no_i18n_content(question.body)
|
456
|
-
end
|
457
|
-
end
|
458
|
-
|
459
505
|
context "when question type is sorting" do
|
460
506
|
let!(:question) do
|
461
507
|
create(
|
@@ -524,5 +570,236 @@ shared_examples_for "has questionnaire" do
|
|
524
570
|
expect(page).to have_content("are not complete")
|
525
571
|
end
|
526
572
|
end
|
573
|
+
|
574
|
+
context "when question type is matrix_single" do
|
575
|
+
let(:matrix_rows) { Array.new(2) { { "body" => Decidim::Faker::Localized.sentence } } }
|
576
|
+
let(:answer_options) { Array.new(2) { { "body" => Decidim::Faker::Localized.sentence } } }
|
577
|
+
let(:mandatory) { false }
|
578
|
+
|
579
|
+
let!(:question) do
|
580
|
+
create(
|
581
|
+
:questionnaire_question,
|
582
|
+
questionnaire: questionnaire,
|
583
|
+
question_type: "matrix_single",
|
584
|
+
rows: matrix_rows,
|
585
|
+
options: answer_options,
|
586
|
+
mandatory: mandatory
|
587
|
+
)
|
588
|
+
end
|
589
|
+
|
590
|
+
it "renders the question answers as a collection of radio buttons" do
|
591
|
+
visit questionnaire_public_path
|
592
|
+
|
593
|
+
expect(page).to have_selector(".radio-button-collection input[type=radio]", count: 4)
|
594
|
+
|
595
|
+
expect(page).to have_content(matrix_rows.map { |row| row["body"]["en"] }.join("\n"))
|
596
|
+
expect(page).to have_content(answer_options.map { |option| option["body"]["en"] }.join(" "))
|
597
|
+
|
598
|
+
radio_buttons = page.all(".radio-button-collection input[type=radio]")
|
599
|
+
|
600
|
+
choose radio_buttons.first[:id]
|
601
|
+
choose radio_buttons.last[:id]
|
602
|
+
|
603
|
+
check "questionnaire_tos_agreement"
|
604
|
+
|
605
|
+
accept_confirm { click_button "Submit" }
|
606
|
+
|
607
|
+
within ".success.flash" do
|
608
|
+
expect(page).to have_content("successfully")
|
609
|
+
end
|
610
|
+
|
611
|
+
visit questionnaire_public_path
|
612
|
+
|
613
|
+
expect(page).to have_content("You have already answered this form.")
|
614
|
+
expect(page).to have_no_i18n_content(question.body)
|
615
|
+
|
616
|
+
first_choice, last_choice = Decidim::Forms::Answer.last.choices.pluck(:decidim_answer_option_id, :decidim_question_matrix_row_id)
|
617
|
+
|
618
|
+
expect(first_choice).to eq([question.answer_options.first.id, question.matrix_rows.first.id])
|
619
|
+
expect(last_choice).to eq([question.answer_options.last.id, question.matrix_rows.last.id])
|
620
|
+
end
|
621
|
+
|
622
|
+
it "preserves the chosen answers if submission not correct" do
|
623
|
+
visit questionnaire_public_path
|
624
|
+
|
625
|
+
radio_buttons = page.all(".radio-button-collection input[type=radio]")
|
626
|
+
choose radio_buttons[1][:id]
|
627
|
+
|
628
|
+
accept_confirm { click_button "Submit" }
|
629
|
+
|
630
|
+
within ".alert.flash" do
|
631
|
+
expect(page).to have_content("There was a problem answering")
|
632
|
+
end
|
633
|
+
|
634
|
+
radio_buttons = page.all(".radio-button-collection input[type=radio]")
|
635
|
+
expect(radio_buttons.map { |b| b[:checked] }).to eq([nil, "true", nil, nil])
|
636
|
+
end
|
637
|
+
|
638
|
+
context "when the question is mandatory and the answer is not complete" do
|
639
|
+
let!(:mandatory) { true }
|
640
|
+
|
641
|
+
it "shows an error if the question is mandatory and the answer is not complete" do
|
642
|
+
visit questionnaire_public_path
|
643
|
+
|
644
|
+
radio_buttons = page.all(".radio-button-collection input[type=radio]")
|
645
|
+
choose radio_buttons[0][:id]
|
646
|
+
|
647
|
+
check "questionnaire_tos_agreement"
|
648
|
+
accept_confirm { click_button "Submit" }
|
649
|
+
|
650
|
+
within ".alert.flash" do
|
651
|
+
expect(page).to have_content("There was a problem answering")
|
652
|
+
end
|
653
|
+
|
654
|
+
expect(page).to have_content("Choices are not complete")
|
655
|
+
end
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
context "when question type is matrix_multiple" do
|
660
|
+
let(:matrix_rows) { Array.new(2) { { "body" => Decidim::Faker::Localized.sentence } } }
|
661
|
+
let(:answer_options) { Array.new(3) { { "body" => Decidim::Faker::Localized.sentence } } }
|
662
|
+
let(:max_choices) { nil }
|
663
|
+
let(:mandatory) { false }
|
664
|
+
|
665
|
+
let!(:question) do
|
666
|
+
create(
|
667
|
+
:questionnaire_question,
|
668
|
+
questionnaire: questionnaire,
|
669
|
+
question_type: "matrix_multiple",
|
670
|
+
rows: matrix_rows,
|
671
|
+
options: answer_options,
|
672
|
+
max_choices: max_choices,
|
673
|
+
mandatory: mandatory
|
674
|
+
)
|
675
|
+
end
|
676
|
+
|
677
|
+
it "renders the question answers as a collection of check boxes" do
|
678
|
+
visit questionnaire_public_path
|
679
|
+
|
680
|
+
expect(page).to have_selector(".check-box-collection input[type=checkbox]", count: 6)
|
681
|
+
|
682
|
+
expect(page).to have_content(matrix_rows.map { |row| row["body"]["en"] }.join("\n"))
|
683
|
+
expect(page).to have_content(answer_options.map { |option| option["body"]["en"] }.join(" "))
|
684
|
+
|
685
|
+
checkboxes = page.all(".check-box-collection input[type=checkbox]")
|
686
|
+
|
687
|
+
check checkboxes[0][:id]
|
688
|
+
check checkboxes[1][:id]
|
689
|
+
check checkboxes[3][:id]
|
690
|
+
|
691
|
+
check "questionnaire_tos_agreement"
|
692
|
+
|
693
|
+
accept_confirm { click_button "Submit" }
|
694
|
+
|
695
|
+
within ".success.flash" do
|
696
|
+
expect(page).to have_content("successfully")
|
697
|
+
end
|
698
|
+
|
699
|
+
visit questionnaire_public_path
|
700
|
+
|
701
|
+
expect(page).to have_content("You have already answered this form.")
|
702
|
+
expect(page).to have_no_i18n_content(question.body)
|
703
|
+
|
704
|
+
first_choice, second_choice, third_choice = Decidim::Forms::Answer.last.choices.pluck(:decidim_answer_option_id, :decidim_question_matrix_row_id)
|
705
|
+
|
706
|
+
expect(first_choice).to eq([question.answer_options.first.id, question.matrix_rows.first.id])
|
707
|
+
expect(second_choice).to eq([question.answer_options.second.id, question.matrix_rows.first.id])
|
708
|
+
expect(third_choice).to eq([question.answer_options.first.id, question.matrix_rows.last.id])
|
709
|
+
end
|
710
|
+
|
711
|
+
context "when the question hax max_choices defined" do
|
712
|
+
let!(:max_choices) { 2 }
|
713
|
+
|
714
|
+
it "respects the max number of choices" do
|
715
|
+
visit questionnaire_public_path
|
716
|
+
|
717
|
+
expect(page).to have_content("Max choices: 2")
|
718
|
+
|
719
|
+
checkboxes = page.all(".check-box-collection input[type=checkbox]")
|
720
|
+
|
721
|
+
check checkboxes[0][:id]
|
722
|
+
check checkboxes[1][:id]
|
723
|
+
check checkboxes[2][:id]
|
724
|
+
|
725
|
+
expect(page).to have_content("too many choices")
|
726
|
+
|
727
|
+
check checkboxes[3][:id]
|
728
|
+
check checkboxes[4][:id]
|
729
|
+
|
730
|
+
expect(page).to have_content("too many choices")
|
731
|
+
|
732
|
+
check checkboxes[5][:id]
|
733
|
+
|
734
|
+
uncheck checkboxes[0][:id]
|
735
|
+
|
736
|
+
expect(page).to have_content("too many choices")
|
737
|
+
|
738
|
+
check "questionnaire_tos_agreement"
|
739
|
+
|
740
|
+
accept_confirm { click_button "Submit" }
|
741
|
+
|
742
|
+
within ".alert.flash" do
|
743
|
+
expect(page).to have_content("There was a problem answering")
|
744
|
+
end
|
745
|
+
|
746
|
+
expect(page).to have_content("are too many")
|
747
|
+
|
748
|
+
checkboxes = page.all(".check-box-collection input[type=checkbox]")
|
749
|
+
|
750
|
+
uncheck checkboxes[5][:id]
|
751
|
+
|
752
|
+
accept_confirm { click_button "Submit" }
|
753
|
+
|
754
|
+
within ".success.flash" do
|
755
|
+
expect(page).to have_content("successfully")
|
756
|
+
end
|
757
|
+
end
|
758
|
+
end
|
759
|
+
|
760
|
+
context "when the submission is not correct" do
|
761
|
+
let!(:max_choices) { 2 }
|
762
|
+
|
763
|
+
it "preserves the chosen answers" do
|
764
|
+
visit questionnaire_public_path
|
765
|
+
|
766
|
+
checkboxes = page.all(".check-box-collection input[type=checkbox]")
|
767
|
+
check checkboxes[0][:id]
|
768
|
+
check checkboxes[1][:id]
|
769
|
+
check checkboxes[2][:id]
|
770
|
+
check checkboxes[5][:id]
|
771
|
+
|
772
|
+
check "questionnaire_tos_agreement"
|
773
|
+
accept_confirm { click_button "Submit" }
|
774
|
+
|
775
|
+
within ".alert.flash" do
|
776
|
+
expect(page).to have_content("There was a problem answering")
|
777
|
+
end
|
778
|
+
|
779
|
+
checkboxes = page.all(".check-box-collection input[type=checkbox]")
|
780
|
+
expect(checkboxes.map { |c| c[:checked] }).to eq(["true", "true", "true", nil, nil, "true"])
|
781
|
+
end
|
782
|
+
end
|
783
|
+
|
784
|
+
context "when the question is mandatory and the answer is not complete" do
|
785
|
+
let!(:mandatory) { true }
|
786
|
+
|
787
|
+
it "shows an error" do
|
788
|
+
visit questionnaire_public_path
|
789
|
+
|
790
|
+
checkboxes = page.all(".check-box-collection input[type=checkbox]")
|
791
|
+
check checkboxes[0][:id]
|
792
|
+
|
793
|
+
check "questionnaire_tos_agreement"
|
794
|
+
accept_confirm { click_button "Submit" }
|
795
|
+
|
796
|
+
within ".alert.flash" do
|
797
|
+
expect(page).to have_content("There was a problem answering")
|
798
|
+
end
|
799
|
+
|
800
|
+
expect(page).to have_content("Choices are not complete")
|
801
|
+
end
|
802
|
+
end
|
803
|
+
end
|
527
804
|
end
|
528
805
|
end
|