decidim-forms 0.29.2 → 0.30.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/cells/decidim/forms/step_navigation_cell.rb +18 -5
- data/app/commands/decidim/forms/admin/update_questionnaire.rb +1 -82
- data/app/commands/decidim/forms/admin/update_questions.rb +109 -0
- data/app/commands/decidim/forms/answer_questionnaire.rb +10 -3
- data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +39 -3
- data/app/controllers/decidim/forms/admin/concerns/has_questionnaire_answers.rb +2 -2
- data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +12 -4
- data/app/forms/decidim/forms/admin/display_condition_form.rb +1 -1
- data/app/forms/decidim/forms/admin/questionnaire_form.rb +0 -9
- data/app/forms/decidim/forms/admin/questions_form.rb +18 -0
- data/app/forms/decidim/forms/answer_choice_form.rb +5 -0
- data/app/forms/decidim/forms/answer_form.rb +1 -0
- data/app/forms/decidim/forms/questionnaire_form.rb +7 -0
- data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_pagination_helper.rb +1 -1
- data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_url_helper.rb +5 -5
- data/app/jobs/decidim/forms/export_questionnaire_answers_job.rb +5 -1
- data/app/models/decidim/forms/answer_choice.rb +0 -2
- data/app/models/decidim/forms/answer_option.rb +1 -1
- data/app/models/decidim/forms/question.rb +10 -0
- data/app/packs/entrypoints/decidim_forms.js +0 -1
- data/app/packs/entrypoints/decidim_forms_admin.js +6 -0
- data/app/packs/src/decidim/forms/admin/publish_answers_buttons.js +72 -0
- data/app/packs/src/decidim/forms/forms.js +22 -18
- data/app/presenters/decidim/forms/admin/questionnaire_participant_presenter.rb +1 -1
- data/app/presenters/decidim/forms/admin_log/question_presenter.rb +31 -0
- data/app/queries/decidim/forms/questionnaire_user_answers.rb +1 -1
- data/app/views/decidim/forms/admin/questionnaires/_answer_option_template.html.erb +1 -1
- data/app/views/decidim/forms/admin/questionnaires/_display_condition_template.html.erb +1 -1
- data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +0 -89
- data/app/views/decidim/forms/admin/questionnaires/_matrix_row_template.html.erb +1 -1
- data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +3 -3
- data/app/views/decidim/forms/admin/questionnaires/_questions_form.html.erb +80 -0
- data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +0 -20
- data/app/views/decidim/forms/admin/questionnaires/edit_questions.html.erb +47 -0
- data/app/views/decidim/forms/questionnaires/_questionnaire.html.erb +8 -1
- data/app/views/decidim/forms/questionnaires/answers/_files.html.erb +1 -1
- data/app/views/decidim/forms/questionnaires/answers/_sorting.html.erb +12 -6
- data/app/views/decidim/forms/questionnaires/edit.html.erb +47 -0
- data/app/views/decidim/forms/questionnaires/show.html.erb +13 -2
- data/config/assets.rb +1 -2
- data/config/locales/bg.yml +0 -2
- data/config/locales/ca.yml +46 -6
- data/config/locales/cs.yml +45 -5
- data/config/locales/de.yml +45 -5
- data/config/locales/el.yml +0 -2
- data/config/locales/en.yml +45 -5
- data/config/locales/es-MX.yml +45 -5
- data/config/locales/es-PY.yml +45 -5
- data/config/locales/es.yml +45 -5
- data/config/locales/eu.yml +45 -5
- data/config/locales/fi-plain.yml +45 -5
- data/config/locales/fi.yml +45 -5
- data/config/locales/fr-CA.yml +37 -5
- data/config/locales/fr.yml +37 -5
- data/config/locales/ja.yml +46 -1
- data/config/locales/lt.yml +0 -2
- data/config/locales/pl.yml +0 -2
- data/config/locales/ro-RO.yml +22 -17
- data/config/locales/zh-TW.yml +0 -2
- data/db/migrate/20190315203056_add_session_token_to_decidim_forms_answers.rb +1 -1
- data/db/migrate/20241122142230_add_survey_answers_published_at_to_questions.rb +7 -0
- data/decidim-forms.gemspec +1 -2
- data/lib/decidim/api/answer_option_type.rb +1 -1
- data/lib/decidim/api/question_type.rb +4 -4
- data/lib/decidim/api/questionnaire_type.rb +4 -4
- data/lib/decidim/exporters/form_pdf.rb +114 -11
- data/lib/decidim/forms/download_your_data_user_answers_serializer.rb +0 -4
- data/lib/decidim/forms/test/factories.rb +2 -2
- data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +44 -4
- data/lib/decidim/forms/test/shared_examples/manage_questionnaire_answers.rb +17 -17
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +19 -21
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +70 -94
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_display_conditions.rb +15 -18
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +90 -125
- data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +4 -25
- data/lib/decidim/forms/version.rb +1 -1
- data/lib/decidim/forms.rb +0 -1
- metadata +18 -32
- data/app/packs/entrypoints/decidim_questionnaire_answers_pdf.js +0 -1
- data/app/packs/entrypoints/decidim_questionnaire_answers_pdf.scss +0 -1
- data/app/packs/stylesheets/decidim/forms/questionnaire-answers-pdf.scss +0 -69
- data/app/views/decidim/forms/admin/questionnaires/answers/export/_answer.html.erb +0 -31
- data/app/views/decidim/forms/admin/questionnaires/answers/export/pdf.html.erb +0 -13
- data/app/views/layouts/decidim/forms/admin/questionnaires/questionnaire_answers.html.erb +0 -12
- data/config/initializers/wicked_pdf.rb +0 -26
- data/lib/decidim/exporters/form_pdf_controller_helper.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4c080cf4b74aa801c82210112648094d7f7f8c938c0343e8cffa97087ffe372
|
4
|
+
data.tar.gz: af06a9fd9157416757f30ea10d4e736ed8b0c10a9bda17644aa9aba2095d08c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da06fab2cc22f16184e8929dc1509693656b5704956b0f76e2d2d17f758df17fb7495f7e2633bde2d597d48d90a8dc6817867d91443e8cb78dd7cd12fc9bee10
|
7
|
+
data.tar.gz: f85cd3907a641d5b5b5d20cebac78ae7dd6139d6e9bb7a97e2a1eb4918242922dad588d023740ad95f13ca06582efef6dba0553b96c942fef6319df9b3b5d987
|
@@ -40,12 +40,25 @@ module Decidim
|
|
40
40
|
"step-#{current_step_index}"
|
41
41
|
end
|
42
42
|
|
43
|
+
def allow_editing_answers?
|
44
|
+
options[:allow_editing_answers]
|
45
|
+
end
|
46
|
+
|
43
47
|
def confirm_data
|
44
|
-
{
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
{
|
49
|
+
data: {
|
50
|
+
confirm:,
|
51
|
+
disable: true,
|
52
|
+
data: "survey-buttons"
|
53
|
+
}
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def confirm
|
58
|
+
return t("decidim.forms.step_navigation.show.are_you_sure_no_edit") unless allow_editing_answers?
|
59
|
+
return t("decidim.forms.step_navigation.show.are_you_sure_edit_guest") unless current_user
|
60
|
+
|
61
|
+
t("decidim.forms.step_navigation.show.are_you_sure_edit")
|
49
62
|
end
|
50
63
|
end
|
51
64
|
end
|
@@ -25,14 +25,7 @@ module Decidim
|
|
25
25
|
Decidim.traceability.perform_action!("update",
|
26
26
|
@questionnaire,
|
27
27
|
@user) do
|
28
|
-
|
29
|
-
if @questionnaire.questions_editable?
|
30
|
-
update_questionnaire_questions
|
31
|
-
delete_answers unless @questionnaire.published?
|
32
|
-
end
|
33
|
-
|
34
|
-
update_questionnaire
|
35
|
-
end
|
28
|
+
update_questionnaire
|
36
29
|
end
|
37
30
|
|
38
31
|
broadcast(:ok)
|
@@ -40,85 +33,11 @@ module Decidim
|
|
40
33
|
|
41
34
|
private
|
42
35
|
|
43
|
-
def update_questionnaire_questions
|
44
|
-
@form.questions.each do |form_question|
|
45
|
-
update_questionnaire_question(form_question)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def update_questionnaire_question(form_question)
|
50
|
-
question_attributes = {
|
51
|
-
body: form_question.body,
|
52
|
-
description: form_question.description,
|
53
|
-
position: form_question.position,
|
54
|
-
mandatory: form_question.mandatory,
|
55
|
-
question_type: form_question.question_type,
|
56
|
-
max_choices: form_question.max_choices,
|
57
|
-
max_characters: form_question.max_characters
|
58
|
-
}
|
59
|
-
|
60
|
-
update_nested_model(form_question, question_attributes, @questionnaire.questions) do |question|
|
61
|
-
form_question.answer_options.each do |form_answer_option|
|
62
|
-
answer_option_attributes = {
|
63
|
-
body: form_answer_option.body,
|
64
|
-
free_text: form_answer_option.free_text
|
65
|
-
}
|
66
|
-
|
67
|
-
update_nested_model(form_answer_option, answer_option_attributes, question.answer_options)
|
68
|
-
end
|
69
|
-
|
70
|
-
form_question.display_conditions.each do |form_display_condition|
|
71
|
-
type = form_display_condition.condition_type
|
72
|
-
|
73
|
-
display_condition_attributes = {
|
74
|
-
condition_question: form_display_condition.condition_question,
|
75
|
-
condition_type: form_display_condition.condition_type,
|
76
|
-
condition_value: type == "match" ? form_display_condition.condition_value : nil,
|
77
|
-
answer_option: %w(equal not_equal).include?(type) ? form_display_condition.answer_option : nil,
|
78
|
-
mandatory: form_display_condition.mandatory
|
79
|
-
}
|
80
|
-
|
81
|
-
next if form_display_condition.deleted? && form_display_condition.id.blank?
|
82
|
-
|
83
|
-
update_nested_model(form_display_condition, display_condition_attributes, question.display_conditions)
|
84
|
-
end
|
85
|
-
|
86
|
-
form_question.matrix_rows_by_position.each_with_index do |form_matrix_row, idx|
|
87
|
-
matrix_row_attributes = {
|
88
|
-
body: form_matrix_row.body,
|
89
|
-
position: form_matrix_row.position || idx
|
90
|
-
}
|
91
|
-
|
92
|
-
update_nested_model(form_matrix_row, matrix_row_attributes, question.matrix_rows)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def update_nested_model(form, attributes, parent_association)
|
98
|
-
record = parent_association.find_by(id: form.id) || parent_association.build(attributes)
|
99
|
-
|
100
|
-
yield record if block_given?
|
101
|
-
|
102
|
-
if record.persisted?
|
103
|
-
if form.deleted?
|
104
|
-
record.destroy!
|
105
|
-
else
|
106
|
-
record.update!(attributes)
|
107
|
-
end
|
108
|
-
else
|
109
|
-
record.save!
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
36
|
def update_questionnaire
|
114
37
|
@questionnaire.update!(title: @form.title,
|
115
38
|
description: @form.description,
|
116
39
|
tos: @form.tos)
|
117
40
|
end
|
118
|
-
|
119
|
-
def delete_answers
|
120
|
-
@questionnaire.answers.destroy_all
|
121
|
-
end
|
122
41
|
end
|
123
42
|
end
|
124
43
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Forms
|
5
|
+
module Admin
|
6
|
+
# This command is executed when the user changes a Questionnaire questions from the admin
|
7
|
+
# panel.
|
8
|
+
class UpdateQuestions < Decidim::Command
|
9
|
+
# Initializes a UpdateQuestions Command.
|
10
|
+
#
|
11
|
+
# form - The form from which to get the data.
|
12
|
+
# questionnaire - The current instance of the questionnaire questions to be updated.
|
13
|
+
def initialize(form, questionnaire)
|
14
|
+
@form = form
|
15
|
+
@questionnaire = questionnaire
|
16
|
+
end
|
17
|
+
|
18
|
+
# Updates the questionnaire if valid.
|
19
|
+
#
|
20
|
+
# Broadcasts :ok if successful, :invalid otherwise.
|
21
|
+
def call
|
22
|
+
return broadcast(:invalid) if @form.invalid?
|
23
|
+
|
24
|
+
Decidim.traceability.perform_action!("update",
|
25
|
+
@questionnaire,
|
26
|
+
@form.current_user) do
|
27
|
+
Decidim::Forms::Questionnaire.transaction do
|
28
|
+
update_questionnaire_questions if @questionnaire.questions_editable?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
broadcast(:ok)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def update_questionnaire_questions
|
38
|
+
@form.questions.each do |form_question|
|
39
|
+
update_questionnaire_question(form_question)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def update_questionnaire_question(form_question)
|
44
|
+
question_attributes = {
|
45
|
+
body: form_question.body,
|
46
|
+
description: form_question.description,
|
47
|
+
position: form_question.position,
|
48
|
+
mandatory: form_question.mandatory,
|
49
|
+
question_type: form_question.question_type,
|
50
|
+
max_choices: form_question.max_choices,
|
51
|
+
max_characters: form_question.max_characters
|
52
|
+
}
|
53
|
+
|
54
|
+
update_nested_model(form_question, question_attributes, @questionnaire.questions) do |question|
|
55
|
+
form_question.answer_options.each do |form_answer_option|
|
56
|
+
answer_option_attributes = {
|
57
|
+
body: form_answer_option.body,
|
58
|
+
free_text: form_answer_option.free_text
|
59
|
+
}
|
60
|
+
|
61
|
+
update_nested_model(form_answer_option, answer_option_attributes, question.answer_options)
|
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_by_position.each_with_index do |form_matrix_row, idx|
|
81
|
+
matrix_row_attributes = {
|
82
|
+
body: form_matrix_row.body,
|
83
|
+
position: form_matrix_row.position || idx
|
84
|
+
}
|
85
|
+
|
86
|
+
update_nested_model(form_matrix_row, matrix_row_attributes, question.matrix_rows)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def update_nested_model(form, attributes, parent_association)
|
92
|
+
record = parent_association.find_by(id: form.id) || parent_association.build(attributes)
|
93
|
+
|
94
|
+
yield record if block_given?
|
95
|
+
|
96
|
+
if record.persisted?
|
97
|
+
if form.deleted?
|
98
|
+
record.destroy!
|
99
|
+
else
|
100
|
+
record.update!(attributes)
|
101
|
+
end
|
102
|
+
else
|
103
|
+
record.save!
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -11,18 +11,21 @@ module Decidim
|
|
11
11
|
#
|
12
12
|
# form - The form from which to get the data.
|
13
13
|
# questionnaire - The current instance of the questionnaire to be answered.
|
14
|
-
|
14
|
+
# allow_editing_answers - Flag that ensures a form can or cannot be editable after the questionnaire's answers have been provided.
|
15
|
+
def initialize(form, questionnaire, allow_editing_answers: false)
|
15
16
|
@form = form
|
16
17
|
@questionnaire = questionnaire
|
18
|
+
@allow_editing_answers = allow_editing_answers
|
17
19
|
end
|
18
20
|
|
19
21
|
# Answers a questionnaire if it is valid
|
20
22
|
#
|
21
23
|
# Broadcasts :ok if successful, :invalid otherwise.
|
22
24
|
def call
|
23
|
-
return broadcast(:invalid) if @form.invalid? || user_already_answered?
|
25
|
+
return broadcast(:invalid) if @form.invalid? || (user_already_answered? && !allow_editing_answers)
|
24
26
|
|
25
27
|
with_events do
|
28
|
+
clear_answers! if allow_editing_answers
|
26
29
|
answer_questionnaire
|
27
30
|
end
|
28
31
|
|
@@ -34,7 +37,7 @@ module Decidim
|
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
37
|
-
attr_reader :form, :questionnaire
|
40
|
+
attr_reader :form, :questionnaire, :allow_editing_answers
|
38
41
|
|
39
42
|
private
|
40
43
|
|
@@ -75,6 +78,10 @@ module Decidim
|
|
75
78
|
end
|
76
79
|
end
|
77
80
|
|
81
|
+
def clear_answers!
|
82
|
+
Answer.where(questionnaire: questionnaire, user: current_user, session_token: form.context.session_token, ip_hash: form.context.ip_hash).destroy_all
|
83
|
+
end
|
84
|
+
|
78
85
|
def answer_questionnaire
|
79
86
|
@main_form = @form
|
80
87
|
@errors = nil
|
@@ -38,13 +38,12 @@ module Decidim
|
|
38
38
|
|
39
39
|
@form = form(Admin::QuestionnaireForm).from_model(questionnaire)
|
40
40
|
|
41
|
-
render template:
|
41
|
+
render template: edit_template
|
42
42
|
end
|
43
43
|
|
44
44
|
def update
|
45
45
|
enforce_permission_to(:update, :questionnaire, questionnaire:)
|
46
46
|
|
47
|
-
params["published_at"] = Time.current if params.has_key? "save_and_publish"
|
48
47
|
@form = form(Admin::QuestionnaireForm).from_params(params)
|
49
48
|
|
50
49
|
Admin::UpdateQuestionnaire.call(@form, questionnaire, current_user) do
|
@@ -57,7 +56,30 @@ module Decidim
|
|
57
56
|
on(:invalid) do
|
58
57
|
# i18n-tasks-use t("decidim.forms.admin.questionnaires.update.invalid")
|
59
58
|
flash.now[:alert] = I18n.t("update.invalid", scope: i18n_flashes_scope)
|
60
|
-
render template:
|
59
|
+
render template: edit_template
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def edit_questions
|
65
|
+
@form = form(Admin::QuestionsForm).from_model(questionnaire)
|
66
|
+
|
67
|
+
render template: edit_questions_template
|
68
|
+
end
|
69
|
+
|
70
|
+
# i18n-tasks-use t("decidim.forms.admin.questionnaires.questions_form.update.success")
|
71
|
+
# i18n-tasks-use t("decidim.forms.admin.questionnaires.update.invalid")
|
72
|
+
def update_questions
|
73
|
+
@form = form(Admin::QuestionsForm).from_params(params)
|
74
|
+
Admin::UpdateQuestions.call(@form, questionnaire) do
|
75
|
+
on(:ok) do
|
76
|
+
flash[:notice] = I18n.t("update.success", scope: i18n_questions_flashes_scope)
|
77
|
+
redirect_to after_update_url
|
78
|
+
end
|
79
|
+
|
80
|
+
on(:invalid) do
|
81
|
+
flash.now[:alert] = I18n.t("update.invalid", scope: i18n_flashes_scope)
|
82
|
+
render template: edit_questions_template
|
61
83
|
end
|
62
84
|
end
|
63
85
|
end
|
@@ -96,6 +118,12 @@ module Decidim
|
|
96
118
|
raise "#{self.class.name} is expected to implement #public_url"
|
97
119
|
end
|
98
120
|
|
121
|
+
# Implement this method in your controller to set the URL
|
122
|
+
# where the user will be render while editing the questionnaire questions
|
123
|
+
def edit_questions_template
|
124
|
+
"decidim/forms/admin/questionnaires/edit_questions"
|
125
|
+
end
|
126
|
+
|
99
127
|
# Returns the url to get the answer options json (for the display conditions form)
|
100
128
|
# for the question with id = params[:id]
|
101
129
|
def answer_options_url(params)
|
@@ -110,10 +138,18 @@ module Decidim
|
|
110
138
|
|
111
139
|
private
|
112
140
|
|
141
|
+
def edit_template
|
142
|
+
"decidim/forms/admin/questionnaires/edit"
|
143
|
+
end
|
144
|
+
|
113
145
|
def i18n_flashes_scope
|
114
146
|
"decidim.forms.admin.questionnaires"
|
115
147
|
end
|
116
148
|
|
149
|
+
def i18n_questions_flashes_scope
|
150
|
+
"decidim.forms.admin.questionnaires.questions_form"
|
151
|
+
end
|
152
|
+
|
117
153
|
def questionnaire
|
118
154
|
@questionnaire ||= Questionnaire.find_by(questionnaire_for:)
|
119
155
|
end
|
@@ -37,7 +37,7 @@ module Decidim
|
|
37
37
|
def show
|
38
38
|
enforce_permission_to :show, :questionnaire_answers
|
39
39
|
|
40
|
-
@participant = participant(participants_query.participant(params[:
|
40
|
+
@participant = participant(participants_query.participant(params[:id]))
|
41
41
|
|
42
42
|
render template: "decidim/forms/admin/questionnaires/answers/show"
|
43
43
|
end
|
@@ -45,7 +45,7 @@ module Decidim
|
|
45
45
|
def export_response
|
46
46
|
enforce_permission_to :export_response, :questionnaire_answers
|
47
47
|
|
48
|
-
session_token = params[:
|
48
|
+
session_token = params[:id]
|
49
49
|
answers = QuestionnaireUserAnswers.for(questionnaire)
|
50
50
|
|
51
51
|
# i18n-tasks-use t("decidim.forms.admin.questionnaires.answers.export_response.title")
|
@@ -16,7 +16,7 @@ module Decidim
|
|
16
16
|
helper Decidim::Forms::ApplicationHelper
|
17
17
|
include FormFactory
|
18
18
|
|
19
|
-
helper_method :questionnaire_for, :questionnaire, :allow_answers?, :visitor_can_answer?, :visitor_already_answered?, :update_url, :form_path
|
19
|
+
helper_method :questionnaire_for, :questionnaire, :allow_answers?, :visitor_can_answer?, :visitor_already_answered?, :update_url, :visitor_can_edit_answers?, :form_path
|
20
20
|
|
21
21
|
invisible_captcha on_spam: :spam_detected
|
22
22
|
|
@@ -25,20 +25,20 @@ module Decidim
|
|
25
25
|
render template: "decidim/forms/questionnaires/show"
|
26
26
|
end
|
27
27
|
|
28
|
+
# i18n-tasks-use t("decidim.forms.questionnaires.answer.success")
|
29
|
+
# i18n-tasks-use t("decidim.forms.questionnaires.answer.invalid")
|
28
30
|
def answer
|
29
31
|
enforce_permission_to_answer_questionnaire
|
30
32
|
|
31
33
|
@form = form(Decidim::Forms::QuestionnaireForm).from_params(params, session_token:, ip_hash:)
|
32
34
|
|
33
|
-
Decidim::Forms::AnswerQuestionnaire.call(@form, questionnaire) do
|
35
|
+
Decidim::Forms::AnswerQuestionnaire.call(@form, questionnaire, allow_editing_answers: allow_editing_answers?) do
|
34
36
|
on(:ok) do
|
35
|
-
# i18n-tasks-use t("decidim.forms.questionnaires.answer.success")
|
36
37
|
flash[:notice] = I18n.t("answer.success", scope: i18n_flashes_scope)
|
37
38
|
redirect_to after_answer_path
|
38
39
|
end
|
39
40
|
|
40
41
|
on(:invalid) do
|
41
|
-
# i18n-tasks-use t("decidim.forms.questionnaires.answer.invalid")
|
42
42
|
flash.now[:alert] = I18n.t("answer.invalid", scope: i18n_flashes_scope)
|
43
43
|
render template: "decidim/forms/questionnaires/show"
|
44
44
|
end
|
@@ -98,6 +98,14 @@ module Decidim
|
|
98
98
|
|
99
99
|
private
|
100
100
|
|
101
|
+
def allow_editing_answers?
|
102
|
+
false
|
103
|
+
end
|
104
|
+
|
105
|
+
def visitor_can_edit_answers?
|
106
|
+
current_user.present? && questionnaire_for.try(:allow_editing_answers?)
|
107
|
+
end
|
108
|
+
|
101
109
|
def i18n_flashes_scope
|
102
110
|
"decidim.forms.questionnaires"
|
103
111
|
end
|
@@ -44,7 +44,7 @@ module Decidim
|
|
44
44
|
question.translated_body,
|
45
45
|
question.id,
|
46
46
|
{
|
47
|
-
"disabled" =>
|
47
|
+
"disabled" => question.question_type == "sorting" || question.id == id,
|
48
48
|
"data-type" => question.question_type
|
49
49
|
}
|
50
50
|
]
|
@@ -11,16 +11,7 @@ module Decidim
|
|
11
11
|
translatable_attribute :description, Decidim::Attributes::RichText
|
12
12
|
translatable_attribute :tos, Decidim::Attributes::RichText
|
13
13
|
|
14
|
-
attribute :published_at, Decidim::Attributes::TimeWithZone
|
15
|
-
attribute :questions, Array[QuestionForm]
|
16
|
-
|
17
14
|
validates :title, :tos, translatable_presence: true
|
18
|
-
|
19
|
-
def map_model(model)
|
20
|
-
self.questions = model.questions.map do |question|
|
21
|
-
QuestionForm.from_model(question)
|
22
|
-
end
|
23
|
-
end
|
24
15
|
end
|
25
16
|
end
|
26
17
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Forms
|
5
|
+
module Admin
|
6
|
+
# This class holds a Form to update questionnaires questions from Decidim's admin panel.
|
7
|
+
class QuestionsForm < Decidim::Form
|
8
|
+
attribute :questions, Array[QuestionForm]
|
9
|
+
|
10
|
+
def map_model(model)
|
11
|
+
self.questions = model.questions.map do |question|
|
12
|
+
QuestionForm.from_model(question)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -11,6 +11,11 @@ module Decidim
|
|
11
11
|
attribute :matrix_row_id, Integer
|
12
12
|
|
13
13
|
validates :answer_option_id, presence: true
|
14
|
+
|
15
|
+
def map_model(model)
|
16
|
+
self.answer_option_id = model.decidim_answer_option_id
|
17
|
+
self.matrix_row_id = model.decidim_question_matrix_row_id
|
18
|
+
end
|
14
19
|
end
|
15
20
|
end
|
16
21
|
end
|
@@ -13,6 +13,7 @@ module Decidim
|
|
13
13
|
attribute :public_participation, Boolean, default: false
|
14
14
|
|
15
15
|
attribute :tos_agreement, Boolean
|
16
|
+
attribute :allow_editing_answers, Boolean, default: false
|
16
17
|
|
17
18
|
before_validation :before_validation
|
18
19
|
|
@@ -28,6 +29,12 @@ module Decidim
|
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
32
|
+
def add_answers!(questionnaire:, session_token:, ip_hash:)
|
33
|
+
self.responses = questionnaire.questions.map do |question|
|
34
|
+
AnswerForm.from_model(Decidim::Forms::Answer.where(question:, user: current_user, session_token:, ip_hash:).first_or_initialize)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
31
38
|
# Add other responses to the context so AnswerForm can validate conditional questions
|
32
39
|
def before_validation
|
33
40
|
context.responses = attributes[:responses]
|
@@ -21,17 +21,17 @@ module Decidim
|
|
21
21
|
# You can implement this method in your controller to change the URL
|
22
22
|
# where the questionnaire participants' info will be shown.
|
23
23
|
def questionnaire_participants_url
|
24
|
-
url_for([
|
24
|
+
url_for([questionnaire.questionnaire_for, { format: nil }])
|
25
25
|
end
|
26
26
|
|
27
27
|
# You can implement this method in your controller to change the URL
|
28
28
|
# where the user's questionnaire answers will be shown.
|
29
|
-
def questionnaire_participant_answers_url(
|
30
|
-
url_for([
|
29
|
+
def questionnaire_participant_answers_url(id)
|
30
|
+
url_for([questionnaire.questionnaire_for, { id: }])
|
31
31
|
end
|
32
32
|
|
33
|
-
def questionnaire_export_response_url(
|
34
|
-
url_for([
|
33
|
+
def questionnaire_export_response_url(id)
|
34
|
+
url_for([questionnaire.questionnaire_for, { id:, format: "pdf" }])
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module Decidim
|
4
4
|
module Forms
|
5
5
|
class ExportQuestionnaireAnswersJob < ApplicationJob
|
6
|
+
include Decidim::PrivateDownloadHelper
|
7
|
+
|
6
8
|
queue_as :exports
|
7
9
|
|
8
10
|
def perform(user, title, answers)
|
@@ -12,7 +14,9 @@ module Decidim
|
|
12
14
|
serializer = Decidim::Forms::UserAnswersSerializer
|
13
15
|
export_data = Decidim::Exporters::FormPDF.new(answers, serializer).export
|
14
16
|
|
15
|
-
|
17
|
+
private_export = attach_archive(export_data, title, user)
|
18
|
+
|
19
|
+
ExportMailer.export(user, private_export).deliver_later
|
16
20
|
end
|
17
21
|
end
|
18
22
|
end
|
@@ -17,8 +17,6 @@ module Decidim
|
|
17
17
|
optional: true
|
18
18
|
|
19
19
|
validates :matrix_row, presence: true, if: -> { answer.question.matrix? }
|
20
|
-
|
21
|
-
default_scope { left_outer_joins(:matrix_row).order(arel_table[:position].asc, Decidim::Forms::QuestionMatrixRow.arel_table[:position].asc, arel_table[:id].asc) }
|
22
20
|
end
|
23
21
|
end
|
24
22
|
end
|
@@ -9,7 +9,7 @@ module Decidim
|
|
9
9
|
|
10
10
|
translatable_fields :body
|
11
11
|
|
12
|
-
belongs_to :question, class_name: "Question", foreign_key: "decidim_question_id", counter_cache:
|
12
|
+
belongs_to :question, class_name: "Question", foreign_key: "decidim_question_id", counter_cache: :answer_options_count
|
13
13
|
|
14
14
|
has_many :display_conditions,
|
15
15
|
class_name: "DisplayCondition",
|
@@ -47,6 +47,12 @@ module Decidim
|
|
47
47
|
foreign_key: "decidim_condition_question_id",
|
48
48
|
class_name: "Question"
|
49
49
|
|
50
|
+
has_many :answers,
|
51
|
+
class_name: "Answer",
|
52
|
+
foreign_key: "decidim_question_id",
|
53
|
+
dependent: :destroy,
|
54
|
+
inverse_of: :question
|
55
|
+
|
50
56
|
validates :question_type, inclusion: { in: TYPES }
|
51
57
|
|
52
58
|
scope :not_separator, -> { where.not(question_type: SEPARATOR_TYPE) }
|
@@ -97,6 +103,10 @@ module Decidim
|
|
97
103
|
def answers_count
|
98
104
|
questionnaire.answers.where(question: self).count
|
99
105
|
end
|
106
|
+
|
107
|
+
def self.log_presenter_class_for(_log)
|
108
|
+
Decidim::Forms::AdminLog::QuestionPresenter
|
109
|
+
end
|
100
110
|
end
|
101
111
|
end
|
102
112
|
end
|
@@ -1,4 +1,10 @@
|
|
1
1
|
import "src/decidim/forms/admin/collapsible_questions"
|
2
2
|
|
3
3
|
import createEditableForm from "src/decidim/forms/admin/forms"
|
4
|
+
import createPublicableQuestionAnswersButtons from "src/decidim/forms/admin/publish_answers_buttons"
|
5
|
+
|
4
6
|
window.Decidim.createEditableForm = createEditableForm
|
7
|
+
|
8
|
+
document.addEventListener("DOMContentLoaded", function() {
|
9
|
+
document.querySelectorAll("[data-publish-question-answer-action]").forEach((el) => createPublicableQuestionAnswersButtons(el));
|
10
|
+
});
|