decidim-forms 0.21.0 → 0.22.0
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/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
|
@@ -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
|
|
@@ -56,6 +56,14 @@ module Decidim
|
|
|
56
56
|
|
|
57
57
|
update_nested_model(form_answer_option, answer_option_attributes, question.answer_options)
|
|
58
58
|
end
|
|
59
|
+
|
|
60
|
+
form_question.matrix_rows.each do |form_matrix_row|
|
|
61
|
+
matrix_row_attributes = {
|
|
62
|
+
body: form_matrix_row.body
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
update_nested_model(form_matrix_row, matrix_row_attributes, question.matrix_rows)
|
|
66
|
+
end
|
|
59
67
|
end
|
|
60
68
|
end
|
|
61
69
|
|
|
@@ -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.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,7 @@ 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, :question_types, :update_url
|
|
18
|
+
helper_method :questionnaire_for, :questionnaire, :blank_question, :blank_answer_option, :blank_matrix_row, :question_types, :update_url
|
|
19
19
|
|
|
20
20
|
def edit
|
|
21
21
|
enforce_permission_to :update, :questionnaire, questionnaire: questionnaire
|
|
@@ -82,8 +82,12 @@ module Decidim
|
|
|
82
82
|
@blank_answer_option ||= Admin::AnswerOptionForm.new
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
+
def blank_matrix_row
|
|
86
|
+
@blank_matrix_row ||= Admin::QuestionMatrixRowForm.new
|
|
87
|
+
end
|
|
88
|
+
|
|
85
89
|
def question_types
|
|
86
|
-
@question_types ||= Question::
|
|
90
|
+
@question_types ||= Question::QUESTION_TYPES.map do |question_type|
|
|
87
91
|
[question_type, I18n.t("decidim.forms.question_types.#{question_type}")]
|
|
88
92
|
end
|
|
89
93
|
end
|
|
@@ -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
|
|
19
|
+
helper_method :questionnaire_for, :questionnaire, :allow_answers?, :visitor_can_answer?, :visitor_already_answered?, :update_url, :form_path
|
|
20
20
|
|
|
21
21
|
invisible_captcha on_spam: :spam_detected
|
|
22
22
|
|
|
@@ -28,7 +28,7 @@ module Decidim
|
|
|
28
28
|
def answer
|
|
29
29
|
enforce_permission_to :answer, :questionnaire
|
|
30
30
|
|
|
31
|
-
@form = form(Decidim::Forms::QuestionnaireForm).from_params(params, session_token: session_token)
|
|
31
|
+
@form = form(Decidim::Forms::QuestionnaireForm).from_params(params, session_token: session_token, ip_hash: ip_hash)
|
|
32
32
|
|
|
33
33
|
Decidim::Forms::AnswerQuestionnaire.call(@form, current_user, questionnaire) do
|
|
34
34
|
on(:ok) do
|
|
@@ -81,6 +81,15 @@ module Decidim
|
|
|
81
81
|
url_for([questionnaire_for, action: :answer])
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
# Points to the shortest path accessing the current form. This will be
|
|
85
|
+
# used to detect whether a user is leaving the form with some partial
|
|
86
|
+
# answers, so that we can warn them.
|
|
87
|
+
#
|
|
88
|
+
# Overwrite this method at the controller.
|
|
89
|
+
def form_path
|
|
90
|
+
url_for([questionnaire_for, only_path: true])
|
|
91
|
+
end
|
|
92
|
+
|
|
84
93
|
# Public: Method to be implemented at the controller. You need to
|
|
85
94
|
# return the object that will hold the questionnaire.
|
|
86
95
|
def questionnaire_for
|
|
@@ -11,6 +11,7 @@ module Decidim
|
|
|
11
11
|
attribute :mandatory, Boolean, default: false
|
|
12
12
|
attribute :question_type, String
|
|
13
13
|
attribute :answer_options, Array[AnswerOptionForm]
|
|
14
|
+
attribute :matrix_rows, Array[QuestionMatrixRowForm]
|
|
14
15
|
attribute :max_choices, Integer
|
|
15
16
|
attribute :deleted, Boolean, default: false
|
|
16
17
|
|
|
@@ -20,7 +21,9 @@ module Decidim
|
|
|
20
21
|
validates :position, numericality: { greater_than_or_equal_to: 0 }
|
|
21
22
|
validates :question_type, inclusion: { in: Decidim::Forms::Question::TYPES }
|
|
22
23
|
validates :max_choices, numericality: { only_integer: true, greater_than: 1, less_than_or_equal_to: ->(form) { form.number_of_options } }, allow_blank: true
|
|
23
|
-
validates :body, translatable_presence: true,
|
|
24
|
+
validates :body, translatable_presence: true, if: :requires_body?
|
|
25
|
+
validates :matrix_rows, presence: true, if: :matrix?
|
|
26
|
+
validates :answer_options, presence: true, if: :matrix?
|
|
24
27
|
|
|
25
28
|
def to_param
|
|
26
29
|
return id if id.present?
|
|
@@ -31,6 +34,22 @@ module Decidim
|
|
|
31
34
|
def number_of_options
|
|
32
35
|
answer_options.size
|
|
33
36
|
end
|
|
37
|
+
|
|
38
|
+
def separator?
|
|
39
|
+
question_type == Decidim::Forms::Question::SEPARATOR_TYPE
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def matrix?
|
|
45
|
+
question_type == "matrix_single" || question_type == "matrix_multiple"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def requires_body?
|
|
49
|
+
return false if separator?
|
|
50
|
+
|
|
51
|
+
!deleted
|
|
52
|
+
end
|
|
34
53
|
end
|
|
35
54
|
end
|
|
36
55
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Forms
|
|
5
|
+
module Admin
|
|
6
|
+
# This class holds a Form to update questionnaire question matrixes from Decidim's admin panel.
|
|
7
|
+
class QuestionMatrixRowForm < Decidim::Form
|
|
8
|
+
include TranslatableAttributes
|
|
9
|
+
|
|
10
|
+
attribute :position, Integer, default: 0
|
|
11
|
+
attribute :deleted, Boolean, default: false
|
|
12
|
+
|
|
13
|
+
translatable_attribute :body, String
|
|
14
|
+
|
|
15
|
+
validates :position, numericality: { greater_than_or_equal_to: 0 }
|
|
16
|
+
validates :body, translatable_presence: true, unless: :deleted
|
|
17
|
+
|
|
18
|
+
def to_param
|
|
19
|
+
return id if id.present?
|
|
20
|
+
|
|
21
|
+
"questionnaire-question-matrix-row-id"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -9,14 +9,16 @@ module Decidim
|
|
|
9
9
|
attribute :question_id, String
|
|
10
10
|
attribute :body, String
|
|
11
11
|
attribute :choices, Array[AnswerChoiceForm]
|
|
12
|
+
attribute :matrix_choices, Array[AnswerChoiceForm]
|
|
12
13
|
|
|
13
14
|
validates :body, presence: true, if: :mandatory_body?
|
|
14
15
|
validates :selected_choices, presence: true, if: :mandatory_choices?
|
|
15
16
|
|
|
16
17
|
validate :max_choices, if: -> { question.max_choices }
|
|
17
18
|
validate :all_choices, if: -> { question.question_type == "sorting" }
|
|
19
|
+
validate :min_choices, if: -> { question.matrix? && question.mandatory? }
|
|
18
20
|
|
|
19
|
-
delegate :mandatory_body?, :mandatory_choices?, to: :question
|
|
21
|
+
delegate :mandatory_body?, :mandatory_choices?, :matrix?, to: :question
|
|
20
22
|
|
|
21
23
|
attr_writer :question
|
|
22
24
|
|
|
@@ -49,8 +51,20 @@ module Decidim
|
|
|
49
51
|
|
|
50
52
|
private
|
|
51
53
|
|
|
54
|
+
def grouped_choices
|
|
55
|
+
selected_choices.group_by(&:matrix_row_id).values
|
|
56
|
+
end
|
|
57
|
+
|
|
52
58
|
def max_choices
|
|
53
|
-
|
|
59
|
+
if matrix?
|
|
60
|
+
errors.add(:choices, :too_many) if grouped_choices.any? { |choices| choices.count > question.max_choices }
|
|
61
|
+
elsif selected_choices.size > question.max_choices
|
|
62
|
+
errors.add(:choices, :too_many)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def min_choices
|
|
67
|
+
errors.add(:choices, :missing) if grouped_choices.count != question.matrix_rows.count
|
|
54
68
|
end
|
|
55
69
|
|
|
56
70
|
def all_choices
|
|
@@ -4,7 +4,9 @@ module Decidim
|
|
|
4
4
|
module Forms
|
|
5
5
|
# This class holds a Form to answer a questionnaire from Decidim's public page.
|
|
6
6
|
class QuestionnaireForm < Decidim::Form
|
|
7
|
-
|
|
7
|
+
# as questionnaire uses "answers" for the database relationships is
|
|
8
|
+
# important not to use the same word here to avoid querying all the entries, resulting in a high performance penalty
|
|
9
|
+
attribute :responses, Array[AnswerForm]
|
|
8
10
|
attribute :user_group_id, Integer
|
|
9
11
|
|
|
10
12
|
attribute :tos_agreement, Boolean
|
|
@@ -12,15 +14,35 @@ module Decidim
|
|
|
12
14
|
validates :tos_agreement, allow_nil: false, acceptance: true
|
|
13
15
|
validate :session_token_in_context
|
|
14
16
|
|
|
15
|
-
# Private: Create the
|
|
17
|
+
# Private: Create the responses from the questionnaire questions
|
|
16
18
|
#
|
|
17
19
|
# Returns nothing.
|
|
18
20
|
def map_model(model)
|
|
19
|
-
self.
|
|
21
|
+
self.responses = model.questions.map do |question|
|
|
20
22
|
AnswerForm.from_model(Decidim::Forms::Answer.new(question: question))
|
|
21
23
|
end
|
|
22
24
|
end
|
|
23
25
|
|
|
26
|
+
# Public: Splits reponses by step, keeping the separator.
|
|
27
|
+
#
|
|
28
|
+
# Returns an array of steps. Each step is a list of the questions in that
|
|
29
|
+
# step, including the separator.
|
|
30
|
+
def responses_by_step
|
|
31
|
+
@responses_by_step ||=
|
|
32
|
+
begin
|
|
33
|
+
steps = responses.chunk_while do |a, b|
|
|
34
|
+
!a.question.separator? || b.question.separator?
|
|
35
|
+
end.to_a
|
|
36
|
+
|
|
37
|
+
steps = [[]] if steps == []
|
|
38
|
+
steps
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def total_steps
|
|
43
|
+
responses_by_step.count
|
|
44
|
+
end
|
|
45
|
+
|
|
24
46
|
def session_token_in_context
|
|
25
47
|
return if context&.session_token
|
|
26
48
|
|
|
@@ -13,6 +13,22 @@ module Decidim
|
|
|
13
13
|
def tabs_id_for_question_answer_option(question, answer_option)
|
|
14
14
|
"questionnaire_question_#{question.to_param}_answer_option_#{answer_option.to_param}"
|
|
15
15
|
end
|
|
16
|
+
|
|
17
|
+
def tabs_id_for_question_matrix_row(question, matrix_row)
|
|
18
|
+
"questionnaire_question_#{question.to_param}_matrix_row_#{matrix_row.to_param}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def dynamic_title(title, **options)
|
|
22
|
+
data = {
|
|
23
|
+
"max-length" => options[:max_length],
|
|
24
|
+
"omission" => options[:omission],
|
|
25
|
+
"placeholder" => options[:placeholder],
|
|
26
|
+
"locale" => I18n.locale
|
|
27
|
+
}
|
|
28
|
+
content_tag :span, class: options[:class], data: data do
|
|
29
|
+
truncate translated_attribute(title), length: options[:max_length], omission: options[:omission]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
16
32
|
end
|
|
17
33
|
end
|
|
18
34
|
end
|
|
@@ -10,6 +10,13 @@ module Decidim
|
|
|
10
10
|
belongs_to :answer_option,
|
|
11
11
|
class_name: "AnswerOption",
|
|
12
12
|
foreign_key: "decidim_answer_option_id"
|
|
13
|
+
|
|
14
|
+
belongs_to :matrix_row,
|
|
15
|
+
class_name: "QuestionMatrixRow",
|
|
16
|
+
foreign_key: "decidim_question_matrix_row_id",
|
|
17
|
+
optional: true
|
|
18
|
+
|
|
19
|
+
validates :matrix_row, presence: true, if: -> { answer.question.matrix? }
|
|
13
20
|
end
|
|
14
21
|
end
|
|
15
22
|
end
|
|
@@ -4,10 +4,18 @@ module Decidim
|
|
|
4
4
|
module Forms
|
|
5
5
|
# The data store for a Question in the Decidim::Forms component.
|
|
6
6
|
class Question < Forms::ApplicationRecord
|
|
7
|
-
|
|
7
|
+
QUESTION_TYPES = %w(short_answer long_answer single_option multiple_option sorting matrix_single matrix_multiple).freeze
|
|
8
|
+
SEPARATOR_TYPE = "separator"
|
|
9
|
+
TYPES = (QUESTION_TYPES + [SEPARATOR_TYPE]).freeze
|
|
8
10
|
|
|
9
11
|
belongs_to :questionnaire, class_name: "Questionnaire", foreign_key: "decidim_questionnaire_id"
|
|
10
12
|
|
|
13
|
+
has_many :matrix_rows,
|
|
14
|
+
class_name: "QuestionMatrixRow",
|
|
15
|
+
foreign_key: "decidim_question_id",
|
|
16
|
+
dependent: :destroy,
|
|
17
|
+
inverse_of: :question
|
|
18
|
+
|
|
11
19
|
has_many :answer_options,
|
|
12
20
|
class_name: "AnswerOption",
|
|
13
21
|
foreign_key: "decidim_question_id",
|
|
@@ -16,8 +24,12 @@ module Decidim
|
|
|
16
24
|
|
|
17
25
|
validates :question_type, inclusion: { in: TYPES }
|
|
18
26
|
|
|
27
|
+
def matrix?
|
|
28
|
+
%w(matrix_single matrix_multiple).include?(question_type)
|
|
29
|
+
end
|
|
30
|
+
|
|
19
31
|
def multiple_choice?
|
|
20
|
-
%w(single_option multiple_option sorting).include?(question_type)
|
|
32
|
+
%w(single_option multiple_option sorting matrix_single matrix_multiple).include?(question_type)
|
|
21
33
|
end
|
|
22
34
|
|
|
23
35
|
def mandatory_body?
|
|
@@ -31,6 +43,10 @@ module Decidim
|
|
|
31
43
|
def number_of_options
|
|
32
44
|
answer_options.size
|
|
33
45
|
end
|
|
46
|
+
|
|
47
|
+
def separator?
|
|
48
|
+
question_type.to_s == SEPARATOR_TYPE
|
|
49
|
+
end
|
|
34
50
|
end
|
|
35
51
|
end
|
|
36
52
|
end
|