decidim-forms 0.21.0 → 0.23.2
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.css +3 -0
- data/app/assets/config/admin/decidim_forms_manifest.js +1 -0
- data/app/assets/config/decidim_forms_manifest.css +1 -0
- data/app/assets/images/decidim/surveys/icon.svg +1 -19
- data/app/assets/javascripts/decidim/forms/admin/auto_select_options_from_url.component.js.es6 +40 -0
- data/app/assets/javascripts/decidim/forms/admin/collapsible_questions.js.es6 +13 -0
- data/app/assets/javascripts/decidim/forms/admin/forms.js.es6 +260 -16
- data/app/assets/javascripts/decidim/forms/admin/live_text_update.component.js.es6 +52 -0
- data/app/assets/javascripts/decidim/forms/autosortable_checkboxes.component.js.es6 +54 -34
- data/app/assets/javascripts/decidim/forms/display_conditions.component.js.es6 +203 -0
- data/app/assets/javascripts/decidim/forms/forms.js.es6 +49 -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/assets/stylesheets/decidim/forms/questionnaire-answers-pdf.scss +69 -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 +33 -1
- data/app/commands/decidim/forms/answer_questionnaire.rb +2 -1
- data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +52 -2
- data/app/controllers/decidim/forms/admin/concerns/has_questionnaire_answers.rb +97 -0
- data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +14 -4
- data/app/forms/decidim/forms/admin/display_condition_form.rb +100 -0
- data/app/forms/decidim/forms/admin/question_form.rb +21 -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 +31 -2
- data/app/forms/decidim/forms/questionnaire_form.rb +30 -3
- data/app/helpers/decidim/forms/admin/application_helper.rb +37 -0
- data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_pagination_helper.rb +49 -0
- data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_url_helper.rb +40 -0
- data/app/helpers/decidim/forms/admin/questionnaire_answers_helper.rb +30 -0
- data/app/jobs/decidim/forms/export_questionnaire_answers_job.rb +19 -0
- data/app/models/decidim/forms/answer.rb +0 -3
- data/app/models/decidim/forms/answer_choice.rb +7 -0
- data/app/models/decidim/forms/answer_option.rb +14 -0
- data/app/models/decidim/forms/display_condition.rb +65 -0
- data/app/models/decidim/forms/question.rb +52 -2
- data/app/models/decidim/forms/question_matrix_row.rb +15 -0
- data/app/models/decidim/forms/questionnaire.rb +20 -1
- data/app/presenters/decidim/forms/admin/questionnaire_answer_presenter.rb +43 -0
- data/app/presenters/decidim/forms/admin/questionnaire_participant_presenter.rb +60 -0
- data/app/presenters/decidim/forms/answer_option_presenter.rb +20 -0
- data/app/presenters/decidim/forms/question_presenter.rb +16 -0
- data/app/queries/decidim/forms/questionnaire_participant.rb +35 -0
- data/app/queries/decidim/forms/questionnaire_participants.rb +43 -0
- data/app/views/decidim/forms/admin/questionnaires/_answer_option_template.html.erb +1 -1
- data/app/views/decidim/forms/admin/questionnaires/_display_condition.html.erb +88 -0
- data/app/views/decidim/forms/admin/questionnaires/_display_condition_template.html.erb +7 -0
- data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +67 -8
- 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 +45 -6
- data/app/views/decidim/forms/admin/questionnaires/_separator.html.erb +41 -0
- data/app/views/decidim/forms/admin/questionnaires/answers/export/_answer.html.erb +31 -0
- data/app/views/decidim/forms/admin/questionnaires/answers/export/pdf.html.erb +13 -0
- data/app/views/decidim/forms/admin/questionnaires/answers/index.html.erb +53 -0
- data/app/views/decidim/forms/admin/questionnaires/answers/show.html.erb +48 -0
- data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +9 -5
- data/app/views/decidim/forms/questionnaires/_answer.html.erb +28 -99
- 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 +78 -26
- data/app/views/layouts/decidim/forms/admin/questionnaires/questionnaire_answers.html.erb +12 -0
- data/config/initializers/wicked_pdf.rb +25 -0
- data/config/locales/am-ET.yml +1 -0
- data/config/locales/ar.yml +7 -4
- data/config/locales/bg-BG.yml +14 -0
- data/config/locales/bg.yml +14 -0
- data/config/locales/ca.yml +89 -5
- data/config/locales/cs.yml +90 -6
- data/config/locales/da-DK.yml +1 -0
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +94 -4
- data/config/locales/el.yml +117 -0
- data/config/locales/en.yml +89 -5
- data/config/locales/eo.yml +1 -0
- data/config/locales/es-MX.yml +88 -4
- data/config/locales/es-PY.yml +88 -4
- data/config/locales/es.yml +88 -4
- data/config/locales/et-EE.yml +1 -0
- data/config/locales/et.yml +1 -0
- data/config/locales/eu.yml +7 -4
- data/config/locales/fi-plain.yml +88 -4
- data/config/locales/fi.yml +88 -4
- data/config/locales/fr-CA.yml +172 -0
- data/config/locales/fr.yml +89 -5
- data/config/locales/ga-IE.yml +1 -0
- data/config/locales/gl.yml +8 -4
- data/config/locales/hr-HR.yml +1 -0
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +11 -5
- data/config/locales/id-ID.yml +7 -4
- data/config/locales/is.yml +1 -0
- data/config/locales/it.yml +89 -5
- data/config/locales/ja-JP.yml +170 -0
- data/config/locales/ja.yml +170 -0
- data/config/locales/ko-KR.yml +1 -0
- data/config/locales/ko.yml +1 -0
- data/config/locales/lt-LT.yml +1 -0
- data/config/locales/lt.yml +1 -0
- data/config/locales/lv.yml +118 -0
- data/config/locales/mt-MT.yml +1 -0
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +92 -8
- data/config/locales/no.yml +55 -5
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +113 -26
- data/config/locales/pt-BR.yml +8 -5
- data/config/locales/pt.yml +111 -24
- data/config/locales/ro-RO.yml +167 -0
- data/config/locales/ru.yml +4 -2
- data/config/locales/si-LK.yml +1 -0
- data/config/locales/sk-SK.yml +88 -0
- data/config/locales/sk.yml +90 -0
- data/config/locales/sl.yml +12 -0
- data/config/locales/so-SO.yml +1 -0
- data/config/locales/sr-CS.yml +1 -0
- data/config/locales/sv.yml +88 -7
- data/config/locales/sw-KE.yml +1 -0
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/tr-TR.yml +95 -5
- data/config/locales/vi-VN.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +172 -0
- data/config/locales/zh-TW.yml +1 -0
- data/db/migrate/20200130194123_create_decidim_forms_display_conditions.rb +20 -0
- 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/db/migrate/20201110152921_add_salt_to_decidim_forms_questionnaires.rb +16 -0
- data/lib/decidim/exporters/form_pdf.rb +33 -0
- data/lib/decidim/exporters/form_pdf_controller_helper.rb +11 -0
- data/lib/decidim/forms.rb +5 -0
- data/lib/decidim/forms/admin_engine.rb +1 -1
- data/lib/decidim/forms/test.rb +6 -0
- data/lib/decidim/forms/test/factories.rb +51 -0
- data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +918 -60
- data/lib/decidim/forms/test/shared_examples/manage_questionnaire_answers.rb +108 -0
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +33 -575
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +179 -0
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +463 -0
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_display_conditions.rb +93 -0
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +461 -0
- data/lib/decidim/forms/user_answers_serializer.rb +22 -5
- data/lib/decidim/forms/version.rb +1 -1
- metadata +133 -13
@@ -35,3 +35,42 @@
|
|
35
35
|
.questionnaire-question_readonly-answer{
|
36
36
|
font-weight: normal;
|
37
37
|
}
|
38
|
+
|
39
|
+
.questionnaire-question-matrix{
|
40
|
+
.collection-input{
|
41
|
+
display: flex;
|
42
|
+
align-items: center;
|
43
|
+
justify-content: center;
|
44
|
+
flex-grow: 1;
|
45
|
+
flex-basis: 0;
|
46
|
+
|
47
|
+
input[type="text"]{
|
48
|
+
margin-top: auto;
|
49
|
+
margin-bottom: auto;
|
50
|
+
}
|
51
|
+
|
52
|
+
input[type="checkbox"],
|
53
|
+
input[type="radio"]{
|
54
|
+
margin-bottom: 0;
|
55
|
+
|
56
|
+
& ~ input[type="text"]{
|
57
|
+
margin-left: .5rem;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
tr,
|
63
|
+
tr:nth-child(2n){
|
64
|
+
background: initial;
|
65
|
+
border-bottom: 1px solid #f0f0f0;
|
66
|
+
}
|
67
|
+
|
68
|
+
thead td{
|
69
|
+
text-align: center;
|
70
|
+
}
|
71
|
+
|
72
|
+
td{
|
73
|
+
min-width: 100px;
|
74
|
+
border-right: 1px solid #f0f0f0;
|
75
|
+
}
|
76
|
+
}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
.questionnaire-answers{
|
2
|
+
.header{
|
3
|
+
h1{
|
4
|
+
margin: 0;
|
5
|
+
padding: 25px;
|
6
|
+
background: rgb(59, 69, 87);
|
7
|
+
color: white;
|
8
|
+
border-radius: 4px 4px 0 0;
|
9
|
+
}
|
10
|
+
|
11
|
+
.description{
|
12
|
+
margin: 0;
|
13
|
+
padding: 25px;
|
14
|
+
background: #f6f6f6;
|
15
|
+
color: #202751;
|
16
|
+
border-radius: 0 0 4px 4px;
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
.answer{
|
21
|
+
margin-top: 25px;
|
22
|
+
background: #f6f6f6;
|
23
|
+
border-radius: 0 0 4px 4px;
|
24
|
+
|
25
|
+
.title{
|
26
|
+
page-break-inside: avoid;
|
27
|
+
border-radius: 4px 4px 0 0;
|
28
|
+
padding: 10px 25px;
|
29
|
+
background: rgb(59, 69, 87);
|
30
|
+
color: white;
|
31
|
+
}
|
32
|
+
|
33
|
+
.participant-info{
|
34
|
+
margin-top: 0;
|
35
|
+
padding: 10px 25px;
|
36
|
+
width: 100%;
|
37
|
+
text-align: center;
|
38
|
+
background: #eee;
|
39
|
+
color: #202751;
|
40
|
+
page-break-inside: avoid;
|
41
|
+
|
42
|
+
th:first-child{
|
43
|
+
text-align: left;
|
44
|
+
}
|
45
|
+
|
46
|
+
td:first-child{
|
47
|
+
text-align: left;
|
48
|
+
}
|
49
|
+
|
50
|
+
th:last-child{
|
51
|
+
text-align: right;
|
52
|
+
}
|
53
|
+
|
54
|
+
td:last-child{
|
55
|
+
text-align: right;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
.answers{
|
60
|
+
padding: 25px;
|
61
|
+
|
62
|
+
.question{
|
63
|
+
page-break-inside: avoid;
|
64
|
+
font-size: inherit;
|
65
|
+
color: #202751;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Forms
|
5
|
+
# This cell renders a possible matrix answer of a question (readonly)
|
6
|
+
class MatrixReadonlyCell < Decidim::ViewModel
|
7
|
+
def answer_options
|
8
|
+
model.question.answer_options.map { |option| translated_attribute(option.body) }.join(" / ")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -9,7 +9,11 @@
|
|
9
9
|
|
10
10
|
<% if model.multiple_choice? %>
|
11
11
|
<ul class="questionnaire-question_readonly-answers <%= model.question_type %>">
|
12
|
-
|
12
|
+
<% if model.matrix? %>
|
13
|
+
<%= cell("decidim/forms/matrix_readonly", collection: model.matrix_rows) %>
|
14
|
+
<% else %>
|
15
|
+
<%= cell("decidim/forms/answer_readonly", collection: model.answer_options) %>
|
16
|
+
<% end %>
|
13
17
|
</ul>
|
14
18
|
<% end %>
|
15
19
|
</li>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<div class="button--double form-general-submit answer-questionnaire__submit">
|
2
|
+
<% if first_step? %>
|
3
|
+
<a></a>
|
4
|
+
<% else %>
|
5
|
+
<%= link_to(
|
6
|
+
icon("caret-left", class: "icon--small", role: "img") + " " + t("decidim.forms.step_navigation.show.back"),
|
7
|
+
"#",
|
8
|
+
class: "hollow secondary",
|
9
|
+
data: {
|
10
|
+
toggle: [previous_step_dom_id, current_step_dom_id].join(" ")
|
11
|
+
}
|
12
|
+
) %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% if last_step? %>
|
16
|
+
<%= form.submit(
|
17
|
+
t("decidim.forms.step_navigation.show.submit"),
|
18
|
+
class: "button button--sc",
|
19
|
+
disabled: button_disabled?,
|
20
|
+
data: {
|
21
|
+
confirm: t("decidim.forms.step_navigation.show.are_you_sure"),
|
22
|
+
disable: true
|
23
|
+
}
|
24
|
+
) %>
|
25
|
+
<% else %>
|
26
|
+
<%= link_to(
|
27
|
+
t("decidim.forms.step_navigation.show.continue"),
|
28
|
+
"#",
|
29
|
+
class: "button button--sc",
|
30
|
+
data: {
|
31
|
+
toggle: [next_step_dom_id, current_step_dom_id].join(" ")
|
32
|
+
}
|
33
|
+
) %>
|
34
|
+
<% end %>
|
35
|
+
</div>
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Forms
|
5
|
+
# This cell renders the navigation of a questionnaire step.
|
6
|
+
class StepNavigationCell < Decidim::ViewModel
|
7
|
+
include Decidim::LayoutHelper
|
8
|
+
|
9
|
+
def current_step_index
|
10
|
+
model
|
11
|
+
end
|
12
|
+
|
13
|
+
def first_step?
|
14
|
+
current_step_index.zero?
|
15
|
+
end
|
16
|
+
|
17
|
+
def last_step?
|
18
|
+
current_step_index + 1 == total_steps
|
19
|
+
end
|
20
|
+
|
21
|
+
def total_steps
|
22
|
+
options[:total_steps]
|
23
|
+
end
|
24
|
+
|
25
|
+
def form
|
26
|
+
options[:form]
|
27
|
+
end
|
28
|
+
|
29
|
+
def button_disabled?
|
30
|
+
options[:button_disabled]
|
31
|
+
end
|
32
|
+
|
33
|
+
def previous_step_dom_id
|
34
|
+
"step-#{current_step_index - 1}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def next_step_dom_id
|
38
|
+
"step-#{current_step_index + 1}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def current_step_dom_id
|
42
|
+
"step-#{current_step_index}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -22,7 +22,11 @@ module Decidim
|
|
22
22
|
return broadcast(:invalid) if @form.invalid?
|
23
23
|
|
24
24
|
Decidim::Forms::Questionnaire.transaction do
|
25
|
-
|
25
|
+
if @questionnaire.questions_editable?
|
26
|
+
update_questionnaire_questions
|
27
|
+
delete_answers unless @questionnaire.published?
|
28
|
+
end
|
29
|
+
|
26
30
|
update_questionnaire
|
27
31
|
end
|
28
32
|
|
@@ -56,6 +60,30 @@ module Decidim
|
|
56
60
|
|
57
61
|
update_nested_model(form_answer_option, answer_option_attributes, question.answer_options)
|
58
62
|
end
|
63
|
+
|
64
|
+
form_question.display_conditions.each do |form_display_condition|
|
65
|
+
type = form_display_condition.condition_type
|
66
|
+
|
67
|
+
display_condition_attributes = {
|
68
|
+
condition_question: form_display_condition.condition_question,
|
69
|
+
condition_type: form_display_condition.condition_type,
|
70
|
+
condition_value: type == "match" ? form_display_condition.condition_value : nil,
|
71
|
+
answer_option: %w(equal not_equal).include?(type) ? form_display_condition.answer_option : nil,
|
72
|
+
mandatory: form_display_condition.mandatory
|
73
|
+
}
|
74
|
+
|
75
|
+
next if form_display_condition.deleted? && form_display_condition.id.blank?
|
76
|
+
|
77
|
+
update_nested_model(form_display_condition, display_condition_attributes, question.display_conditions)
|
78
|
+
end
|
79
|
+
|
80
|
+
form_question.matrix_rows.each do |form_matrix_row|
|
81
|
+
matrix_row_attributes = {
|
82
|
+
body: form_matrix_row.body
|
83
|
+
}
|
84
|
+
|
85
|
+
update_nested_model(form_matrix_row, matrix_row_attributes, question.matrix_rows)
|
86
|
+
end
|
59
87
|
end
|
60
88
|
end
|
61
89
|
|
@@ -80,6 +108,10 @@ module Decidim
|
|
80
108
|
description: @form.description,
|
81
109
|
tos: @form.tos)
|
82
110
|
end
|
111
|
+
|
112
|
+
def delete_answers
|
113
|
+
@questionnaire.answers.destroy_all
|
114
|
+
end
|
83
115
|
end
|
84
116
|
end
|
85
117
|
end
|
@@ -30,7 +30,7 @@ module Decidim
|
|
30
30
|
|
31
31
|
def answer_questionnaire
|
32
32
|
Answer.transaction do
|
33
|
-
form.
|
33
|
+
form.responses_by_step.flatten.select(&:display_conditions_fulfilled?).each do |form_answer|
|
34
34
|
answer = Answer.new(
|
35
35
|
user: @current_user,
|
36
36
|
questionnaire: @questionnaire,
|
@@ -45,6 +45,7 @@ module Decidim
|
|
45
45
|
body: choice.body,
|
46
46
|
custom_body: choice.custom_body,
|
47
47
|
decidim_answer_option_id: choice.answer_option_id,
|
48
|
+
decidim_question_matrix_row_id: choice.matrix_row_id,
|
48
49
|
position: choice.position
|
49
50
|
)
|
50
51
|
end
|
@@ -15,7 +15,21 @@ module Decidim
|
|
15
15
|
|
16
16
|
included do
|
17
17
|
helper Decidim::Forms::Admin::ApplicationHelper
|
18
|
-
helper_method :questionnaire_for, :questionnaire, :blank_question, :blank_answer_option, :
|
18
|
+
helper_method :questionnaire_for, :questionnaire, :blank_question, :blank_answer_option, :blank_matrix_row,
|
19
|
+
:blank_display_condition, :question_types, :display_condition_types, :update_url, :public_url, :answer_options_url
|
20
|
+
|
21
|
+
if defined? Decidim::Templates::Admin
|
22
|
+
include Decidim::Templates::Admin::Concerns::Templatable
|
23
|
+
helper Decidim::Templates::Admin::TemplatesHelper
|
24
|
+
|
25
|
+
def templatable_type
|
26
|
+
"Decidim::Forms::Questionnaire"
|
27
|
+
end
|
28
|
+
|
29
|
+
def templatable
|
30
|
+
questionnaire
|
31
|
+
end
|
32
|
+
end
|
19
33
|
|
20
34
|
def edit
|
21
35
|
enforce_permission_to :update, :questionnaire, questionnaire: questionnaire
|
@@ -46,6 +60,16 @@ module Decidim
|
|
46
60
|
end
|
47
61
|
end
|
48
62
|
|
63
|
+
def answer_options
|
64
|
+
respond_to do |format|
|
65
|
+
format.json do
|
66
|
+
question_id = params["id"]
|
67
|
+
question = Question.find_by(id: question_id)
|
68
|
+
render json: question.answer_options.map { |answer_option| AnswerOptionPresenter.new(answer_option).as_json } if question.present?
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
49
73
|
# Public: The only method to be implemented at the controller. You need to
|
50
74
|
# return the object that will hold the questionnaire.
|
51
75
|
def questionnaire_for
|
@@ -64,6 +88,18 @@ module Decidim
|
|
64
88
|
url_for(questionnaire.questionnaire_for)
|
65
89
|
end
|
66
90
|
|
91
|
+
# Implement this method in your controller to set the URL
|
92
|
+
# where the questionnaire can be answered.
|
93
|
+
def public_url
|
94
|
+
raise "#{self.class.name} is expected to implement #public_url"
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns the url to get the answer options json (for the display conditions form)
|
98
|
+
# for the question with id = params[:id]
|
99
|
+
def answer_options_url(params)
|
100
|
+
url_for([questionnaire.questionnaire_for, action: :answer_options, format: :json, **params])
|
101
|
+
end
|
102
|
+
|
67
103
|
private
|
68
104
|
|
69
105
|
def i18n_flashes_scope
|
@@ -82,11 +118,25 @@ module Decidim
|
|
82
118
|
@blank_answer_option ||= Admin::AnswerOptionForm.new
|
83
119
|
end
|
84
120
|
|
121
|
+
def blank_display_condition
|
122
|
+
@blank_display_condition ||= Admin::DisplayConditionForm.new
|
123
|
+
end
|
124
|
+
|
125
|
+
def blank_matrix_row
|
126
|
+
@blank_matrix_row ||= Admin::QuestionMatrixRowForm.new
|
127
|
+
end
|
128
|
+
|
85
129
|
def question_types
|
86
|
-
@question_types ||= Question::
|
130
|
+
@question_types ||= Question::QUESTION_TYPES.map do |question_type|
|
87
131
|
[question_type, I18n.t("decidim.forms.question_types.#{question_type}")]
|
88
132
|
end
|
89
133
|
end
|
134
|
+
|
135
|
+
def display_condition_types
|
136
|
+
@display_condition_types ||= DisplayCondition.condition_types.keys.map do |condition_type|
|
137
|
+
[condition_type, I18n.t("decidim.forms.admin.questionnaires.display_condition.condition_types.#{condition_type}")]
|
138
|
+
end
|
139
|
+
end
|
90
140
|
end
|
91
141
|
end
|
92
142
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Forms
|
5
|
+
module Admin
|
6
|
+
module Concerns
|
7
|
+
# Questionnaires can be related to any class in Decidim. In order to
|
8
|
+
# manage the questionnaires answers for a given type, you should create a new
|
9
|
+
# controller and include the HasQuestionnaire concern as well as this one.
|
10
|
+
#
|
11
|
+
# In the controller that includes this concern, you should define a
|
12
|
+
# `questionnaire_for` method that returns an instance of the model that the
|
13
|
+
# questionnaire belongs to. You should also define the routes for:
|
14
|
+
# `index_<model>_url` and `export_<model>_url` as well as
|
15
|
+
# `show_<model>_url` and `export_response_<model>_url` (which are passed
|
16
|
+
# a `:session_token` parameter)
|
17
|
+
module HasQuestionnaireAnswers
|
18
|
+
extend ActiveSupport::Concern
|
19
|
+
|
20
|
+
included do
|
21
|
+
include Decidim::Paginable
|
22
|
+
include Decidim::Forms::Admin::Concerns::HasQuestionnaireAnswersUrlHelper
|
23
|
+
include Decidim::Forms::Admin::Concerns::HasQuestionnaireAnswersPaginationHelper
|
24
|
+
|
25
|
+
helper Decidim::Forms::Admin::QuestionnaireAnswersHelper
|
26
|
+
|
27
|
+
def index
|
28
|
+
enforce_permission_to :index, :questionnaire_answers
|
29
|
+
|
30
|
+
@query = paginate(collection)
|
31
|
+
@participants = participants(@query)
|
32
|
+
@total = participants_query.count_participants
|
33
|
+
|
34
|
+
render template: "decidim/forms/admin/questionnaires/answers/index"
|
35
|
+
end
|
36
|
+
|
37
|
+
def show
|
38
|
+
enforce_permission_to :show, :questionnaire_answers
|
39
|
+
|
40
|
+
@participant = participant(participants_query.participant(params[:session_token]))
|
41
|
+
|
42
|
+
render template: "decidim/forms/admin/questionnaires/answers/show"
|
43
|
+
end
|
44
|
+
|
45
|
+
def export_response
|
46
|
+
enforce_permission_to :export_response, :questionnaire_answers
|
47
|
+
|
48
|
+
session_token = params[:session_token]
|
49
|
+
answers = QuestionnaireUserAnswers.for(questionnaire)
|
50
|
+
|
51
|
+
# i18n-tasks-use t("decidim.forms.admin.questionnaires.answers.export_response.title")
|
52
|
+
title = t("export_response.title", scope: i18n_scope, token: session_token)
|
53
|
+
|
54
|
+
Decidim::Forms::ExportQuestionnaireAnswersJob.perform_later(current_user, title, answers.select { |a| a.first.session_token == session_token })
|
55
|
+
|
56
|
+
flash[:notice] = t("decidim.admin.exports.notice")
|
57
|
+
|
58
|
+
redirect_back(fallback_location: questionnaire_participant_answers_url(session_token))
|
59
|
+
end
|
60
|
+
|
61
|
+
# Public: The only method to be implemented at the controller. You need to
|
62
|
+
# return the object that will hold the questionnaire.
|
63
|
+
def questionnaire_for
|
64
|
+
raise "#{self.class.name} is expected to implement #questionnaire_for"
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def i18n_scope
|
70
|
+
"decidim.forms.admin.questionnaires.answers"
|
71
|
+
end
|
72
|
+
|
73
|
+
def questionnaire
|
74
|
+
@questionnaire ||= Questionnaire.find_by(questionnaire_for: questionnaire_for)
|
75
|
+
end
|
76
|
+
|
77
|
+
def participants_query
|
78
|
+
QuestionnaireParticipants.new(questionnaire)
|
79
|
+
end
|
80
|
+
|
81
|
+
def collection
|
82
|
+
@collection ||= participants_query.participants
|
83
|
+
end
|
84
|
+
|
85
|
+
def participant(answer)
|
86
|
+
Decidim::Forms::Admin::QuestionnaireParticipantPresenter.new(participant: answer)
|
87
|
+
end
|
88
|
+
|
89
|
+
def participants(query)
|
90
|
+
query.map { |answer| participant(answer) }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|