decidim-forms 0.30.2 → 0.31.0.rc1

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.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -10
  3. data/app/cells/decidim/forms/matrix_readonly/show.erb +1 -1
  4. data/app/cells/decidim/forms/matrix_readonly_cell.rb +3 -3
  5. data/app/cells/decidim/forms/question_readonly/show.erb +5 -5
  6. data/app/cells/decidim/forms/question_readonly/title_and_description.erb +3 -3
  7. data/app/cells/decidim/forms/response_readonly_cell.rb +9 -0
  8. data/app/cells/decidim/forms/step_navigation/show.erb +3 -3
  9. data/app/cells/decidim/forms/step_navigation_cell.rb +3 -3
  10. data/app/commands/decidim/forms/admin/update_questions.rb +6 -6
  11. data/app/commands/decidim/forms/{answer_questionnaire.rb → response_questionnaire.rb} +35 -35
  12. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +12 -12
  13. data/app/controllers/decidim/forms/admin/concerns/{has_questionnaire_answers.rb → has_questionnaire_responses.rb} +23 -19
  14. data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +38 -33
  15. data/app/forms/decidim/forms/admin/display_condition_form.rb +14 -14
  16. data/app/forms/decidim/forms/admin/question_form.rb +3 -3
  17. data/app/forms/decidim/forms/admin/{answer_option_form.rb → response_option_form.rb} +3 -3
  18. data/app/forms/decidim/forms/questionnaire_form.rb +8 -9
  19. data/app/forms/decidim/forms/{answer_choice_form.rb → response_choice_form.rb} +5 -5
  20. data/app/forms/decidim/forms/{answer_form.rb → response_form.rb} +9 -9
  21. data/app/helpers/decidim/forms/admin/application_helper.rb +2 -2
  22. data/app/helpers/decidim/forms/admin/concerns/{has_questionnaire_answers_pagination_helper.rb → has_questionnaire_responses_pagination_helper.rb} +4 -4
  23. data/app/helpers/decidim/forms/admin/concerns/{has_questionnaire_answers_url_helper.rb → has_questionnaire_responses_url_helper.rb} +5 -5
  24. data/app/helpers/decidim/forms/admin/questionnaire_responses_helper.rb +32 -0
  25. data/app/helpers/decidim/forms/application_helper.rb +1 -2
  26. data/app/jobs/decidim/forms/{export_questionnaire_answers_job.rb → export_questionnaire_responses_job.rb} +5 -5
  27. data/app/models/decidim/forms/display_condition.rb +20 -20
  28. data/app/models/decidim/forms/question.rb +14 -13
  29. data/app/models/decidim/forms/question_matrix_row.rb +1 -1
  30. data/app/models/decidim/forms/questionnaire.rb +11 -6
  31. data/app/models/decidim/forms/{answer.rb → response.rb} +9 -9
  32. data/app/models/decidim/forms/response_choice.rb +22 -0
  33. data/app/models/decidim/forms/{answer_option.rb → response_option.rb} +5 -5
  34. data/app/packs/entrypoints/decidim_forms_admin.js +3 -3
  35. data/app/packs/src/decidim/forms/admin/collapsible_questions.js +12 -10
  36. data/app/packs/src/decidim/forms/admin/forms.js +35 -35
  37. data/app/packs/src/decidim/forms/admin/{publish_answers_buttons.js → publish_responses_buttons.js} +12 -12
  38. data/app/packs/src/decidim/forms/display_conditions.component.js +12 -12
  39. data/app/packs/src/decidim/forms/forms.js +4 -4
  40. data/app/packs/stylesheets/decidim/forms/forms.scss +2 -2
  41. data/app/presenters/decidim/forms/admin/questionnaire_participant_presenter.rb +13 -13
  42. data/app/presenters/decidim/forms/admin/{questionnaire_answer_presenter.rb → questionnaire_response_presenter.rb} +15 -15
  43. data/app/presenters/decidim/forms/admin_log/question_presenter.rb +3 -3
  44. data/app/presenters/decidim/forms/{answer_option_presenter.rb → response_option_presenter.rb} +2 -2
  45. data/app/queries/decidim/forms/questionnaire_participant.rb +5 -5
  46. data/app/queries/decidim/forms/questionnaire_participants.rb +6 -6
  47. data/app/queries/decidim/forms/questionnaire_user_responses.rb +32 -0
  48. data/app/views/decidim/forms/admin/questionnaires/_display_condition.html.erb +9 -9
  49. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +2 -2
  50. data/app/views/decidim/forms/admin/questionnaires/_matrix_row.html.erb +3 -3
  51. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +16 -16
  52. data/app/views/decidim/forms/admin/questionnaires/_questions_form.html.erb +11 -10
  53. data/app/views/decidim/forms/admin/questionnaires/{_answer_option.html.erb → _response_option.html.erb} +7 -7
  54. data/app/views/decidim/forms/admin/questionnaires/_response_option_template.html.erb +7 -0
  55. data/app/views/decidim/forms/admin/questionnaires/_separator.html.erb +10 -7
  56. data/app/views/decidim/forms/admin/questionnaires/_title_and_description.html.erb +7 -7
  57. data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +1 -1
  58. data/app/views/decidim/forms/admin/questionnaires/edit_questions.html.erb +8 -8
  59. data/app/views/decidim/forms/admin/questionnaires/responses/index.html.erb +80 -0
  60. data/app/views/decidim/forms/admin/questionnaires/responses/show.html.erb +43 -0
  61. data/app/views/decidim/forms/questionnaires/_questionnaire.html.erb +22 -26
  62. data/app/views/decidim/forms/questionnaires/_questionnaire_readonly.html.erb +8 -3
  63. data/app/views/decidim/forms/questionnaires/_response.html.erb +61 -0
  64. data/app/views/decidim/forms/questionnaires/edit.html.erb +2 -2
  65. data/app/views/decidim/forms/questionnaires/responses/_files.html.erb +1 -0
  66. data/app/views/decidim/forms/questionnaires/responses/_long_response.html.erb +3 -0
  67. data/app/views/decidim/forms/questionnaires/{answers → responses}/_matrix_multiple.html.erb +16 -15
  68. data/app/views/decidim/forms/questionnaires/{answers → responses}/_matrix_single.html.erb +17 -16
  69. data/app/views/decidim/forms/questionnaires/responses/_multiple_option.html.erb +26 -0
  70. data/app/views/decidim/forms/questionnaires/responses/_separator.html.erb +1 -0
  71. data/app/views/decidim/forms/questionnaires/responses/_short_response.html.erb +3 -0
  72. data/app/views/decidim/forms/questionnaires/responses/_single_option.html.erb +33 -0
  73. data/app/views/decidim/forms/questionnaires/responses/_sorting.html.erb +26 -0
  74. data/app/views/decidim/forms/questionnaires/responses/_title_and_description.html.erb +1 -0
  75. data/app/views/decidim/forms/questionnaires/show.html.erb +10 -10
  76. data/config/assets.rb +2 -2
  77. data/config/locales/ar.yml +0 -22
  78. data/config/locales/bg.yml +3 -36
  79. data/config/locales/ca-IT.yml +73 -73
  80. data/config/locales/ca.yml +73 -73
  81. data/config/locales/cs.yml +72 -75
  82. data/config/locales/de.yml +72 -72
  83. data/config/locales/el.yml +3 -36
  84. data/config/locales/en.yml +83 -83
  85. data/config/locales/es-MX.yml +75 -75
  86. data/config/locales/es-PY.yml +75 -75
  87. data/config/locales/es.yml +73 -73
  88. data/config/locales/eu.yml +71 -71
  89. data/config/locales/fi-plain.yml +71 -71
  90. data/config/locales/fi.yml +69 -69
  91. data/config/locales/fr-CA.yml +70 -67
  92. data/config/locales/fr.yml +70 -67
  93. data/config/locales/ga-IE.yml +0 -7
  94. data/config/locales/gl.yml +0 -22
  95. data/config/locales/hu.yml +0 -22
  96. data/config/locales/id-ID.yml +0 -22
  97. data/config/locales/it.yml +3 -40
  98. data/config/locales/ja.yml +80 -80
  99. data/config/locales/lb.yml +3 -36
  100. data/config/locales/lt.yml +3 -36
  101. data/config/locales/lv.yml +0 -22
  102. data/config/locales/nl.yml +3 -36
  103. data/config/locales/no.yml +3 -36
  104. data/config/locales/pl.yml +3 -36
  105. data/config/locales/pt-BR.yml +3 -36
  106. data/config/locales/pt.yml +3 -36
  107. data/config/locales/ro-RO.yml +22 -51
  108. data/config/locales/ru.yml +0 -9
  109. data/config/locales/sk.yml +0 -22
  110. data/config/locales/sl.yml +0 -5
  111. data/config/locales/sv.yml +82 -54
  112. data/config/locales/tr-TR.yml +3 -36
  113. data/config/locales/zh-CN.yml +3 -36
  114. data/config/locales/zh-TW.yml +3 -36
  115. data/db/migrate/20190315203056_add_session_token_to_decidim_forms_answers.rb +1 -1
  116. data/db/migrate/20250314150250_rename_answer_to_response_in_decidim_forms.rb +30 -0
  117. data/db/migrate/20250319130003_change_question_types_in_questions.rb +14 -0
  118. data/lib/decidim/api/question_matrix_row_type.rb +13 -0
  119. data/lib/decidim/api/question_type.rb +4 -3
  120. data/lib/decidim/api/questionnaire_type.rb +1 -0
  121. data/lib/decidim/api/response_option_type.rb +13 -0
  122. data/lib/decidim/exporters/form_pdf.rb +33 -33
  123. data/lib/decidim/forms/api.rb +2 -1
  124. data/lib/decidim/forms/{download_your_data_user_answers_serializer.rb → download_your_data_user_responses_serializer.rb} +3 -3
  125. data/lib/decidim/forms/engine.rb +2 -2
  126. data/lib/decidim/forms/test/factories.rb +24 -24
  127. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +176 -176
  128. data/lib/decidim/forms/test/shared_examples/manage_questionnaire_responses.rb +159 -0
  129. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +19 -19
  130. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +44 -44
  131. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_display_conditions.rb +10 -10
  132. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +18 -18
  133. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +4 -4
  134. data/lib/decidim/forms/test.rb +1 -1
  135. data/lib/decidim/forms/user_responses_serializer.rb +110 -0
  136. data/lib/decidim/forms/version.rb +1 -1
  137. data/lib/decidim/forms.rb +2 -2
  138. metadata +48 -45
  139. data/app/cells/decidim/forms/answer_readonly_cell.rb +0 -9
  140. data/app/helpers/decidim/forms/admin/questionnaire_answers_helper.rb +0 -30
  141. data/app/models/decidim/forms/answer_choice.rb +0 -22
  142. data/app/queries/decidim/forms/questionnaire_user_answers.rb +0 -32
  143. data/app/views/decidim/forms/admin/questionnaires/_answer_option_template.html.erb +0 -7
  144. data/app/views/decidim/forms/admin/questionnaires/answers/index.html.erb +0 -49
  145. data/app/views/decidim/forms/admin/questionnaires/answers/show.html.erb +0 -43
  146. data/app/views/decidim/forms/questionnaires/_answer.html.erb +0 -61
  147. data/app/views/decidim/forms/questionnaires/answers/_files.html.erb +0 -1
  148. data/app/views/decidim/forms/questionnaires/answers/_long_answer.html.erb +0 -3
  149. data/app/views/decidim/forms/questionnaires/answers/_multiple_option.html.erb +0 -25
  150. data/app/views/decidim/forms/questionnaires/answers/_separator.html.erb +0 -1
  151. data/app/views/decidim/forms/questionnaires/answers/_short_answer.html.erb +0 -3
  152. data/app/views/decidim/forms/questionnaires/answers/_single_option.html.erb +0 -32
  153. data/app/views/decidim/forms/questionnaires/answers/_sorting.html.erb +0 -26
  154. data/app/views/decidim/forms/questionnaires/answers/_title_and_description.html.erb +0 -1
  155. data/lib/decidim/api/answer_option_type.rb +0 -13
  156. data/lib/decidim/forms/test/shared_examples/manage_questionnaire_answers.rb +0 -149
  157. data/lib/decidim/forms/user_answers_serializer.rb +0 -105
  158. /data/app/cells/decidim/forms/{answer_readonly → response_readonly}/show.erb +0 -0
@@ -16,74 +16,79 @@ 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, :visitor_can_edit_answers?, :form_path
19
+ helper_method :questionnaire_for, :questionnaire, :allow_responses?, :visitor_can_respond?, :visitor_already_responded?, :update_url, :visitor_can_edit_responses?,
20
+ :form_path
20
21
 
21
22
  invisible_captcha on_spam: :spam_detected
22
23
 
23
24
  def show
24
25
  @form = form(Decidim::Forms::QuestionnaireForm).from_model(questionnaire)
25
- render template: "decidim/forms/questionnaires/show"
26
+ render template:
26
27
  end
27
28
 
28
- # i18n-tasks-use t("decidim.forms.questionnaires.answer.success")
29
- # i18n-tasks-use t("decidim.forms.questionnaires.answer.invalid")
30
- def answer
31
- enforce_permission_to_answer_questionnaire
29
+ # i18n-tasks-use t("decidim.forms.questionnaires.response.success")
30
+ # i18n-tasks-use t("decidim.forms.questionnaires.response.invalid")
31
+ def respond
32
+ enforce_permission_to_respond_questionnaire
32
33
 
33
34
  @form = form(Decidim::Forms::QuestionnaireForm).from_params(params, session_token:, ip_hash:)
34
35
 
35
- Decidim::Forms::AnswerQuestionnaire.call(@form, questionnaire, allow_editing_answers: allow_editing_answers?) do
36
+ Decidim::Forms::ResponseQuestionnaire.call(@form, questionnaire, allow_editing_responses: allow_editing_responses?) do
36
37
  on(:ok) do
37
- flash[:notice] = I18n.t("answer.success", scope: i18n_flashes_scope)
38
- redirect_to after_answer_path
38
+ flash[:notice] = I18n.t("response.success", scope: i18n_flashes_scope)
39
+ redirect_to after_response_path
39
40
  end
40
41
 
41
42
  on(:invalid) do
42
- flash.now[:alert] = I18n.t("answer.invalid", scope: i18n_flashes_scope)
43
- render template: "decidim/forms/questionnaires/show"
43
+ flash.now[:alert] = I18n.t("response.invalid", scope: i18n_flashes_scope)
44
+ render template:, status: :unprocessable_entity
44
45
  end
45
46
  end
46
47
  end
47
48
 
49
+ def template
50
+ "decidim/forms/questionnaires/show"
51
+ end
52
+
48
53
  # Public: Method to be implemented at the controller. You need to
49
- # return true if the questionnaire can receive answers
50
- def allow_answers?
51
- raise "#{self.class.name} is expected to implement #allow_answers?"
54
+ # return true if the questionnaire can receive responses
55
+ def allow_responses?
56
+ raise "#{self.class.name} is expected to implement #allow_responses?"
52
57
  end
53
58
 
54
59
  # Public: Method to be implemented at the controller if needed. You need to
55
- # return true if the questionnaire can receive answers by unregistered users
60
+ # return true if the questionnaire can receive responses by unregistered users
56
61
  def allow_unregistered?
57
62
  false
58
63
  end
59
64
 
60
- # Public: return true if the current user (if logged) can answer the questionnaire
61
- def visitor_can_answer?
65
+ # Public: return true if the current user (if logged) can response the questionnaire
66
+ def visitor_can_respond?
62
67
  current_user || allow_unregistered?
63
68
  end
64
69
 
65
- # Public: return true if the current user (or session visitor) can answer the questionnaire
66
- def visitor_already_answered?
67
- questionnaire.answered_by?(current_user || tokenize(session[:session_id]))
70
+ # Public: return true if the current user (or session visitor) can respond the questionnaire
71
+ def visitor_already_responded?
72
+ questionnaire.responded_by?(current_user || tokenize(session[:session_id]))
68
73
  end
69
74
 
70
75
  # Public: Returns a String or Object that will be passed to `redirect_to` after
71
- # answering the questionnaire. By default it redirects to the questionnaire_for.
76
+ # responding the questionnaire. By default it redirects to the questionnaire_for.
72
77
  #
73
78
  # It can be redefined at controller level if you need to redirect elsewhere.
74
- def after_answer_path
79
+ def after_response_path
75
80
  questionnaire_for
76
81
  end
77
82
 
78
83
  # You can implement this method in your controller to change the URL
79
84
  # where the questionnaire will be submitted.
80
85
  def update_url
81
- url_for([questionnaire_for, { action: :answer }])
86
+ url_for([questionnaire_for, { action: :respond }])
82
87
  end
83
88
 
84
89
  # Points to the shortest path accessing the current form. This will be
85
90
  # used to detect whether a user is leaving the form with some partial
86
- # answers, so that we can warn them.
91
+ # responses, so that we can warn them.
87
92
  #
88
93
  # Overwrite this method at the controller.
89
94
  def form_path
@@ -98,12 +103,12 @@ module Decidim
98
103
 
99
104
  private
100
105
 
101
- def allow_editing_answers?
106
+ def allow_editing_responses?
102
107
  false
103
108
  end
104
109
 
105
- def visitor_can_edit_answers?
106
- current_user.present? && questionnaire_for.try(:allow_editing_answers?)
110
+ def visitor_can_edit_responses?
111
+ current_user.present? && questionnaire_for.try(:allow_editing_responses?)
107
112
  end
108
113
 
109
114
  def i18n_flashes_scope
@@ -111,22 +116,22 @@ module Decidim
111
116
  end
112
117
 
113
118
  def questionnaire
114
- @questionnaire ||= Questionnaire.includes(questions: :answer_options).find_by(questionnaire_for:)
119
+ @questionnaire ||= Questionnaire.includes(questions: :response_options).find_by(questionnaire_for:)
115
120
  end
116
121
 
117
122
  def spam_detected
118
- enforce_permission_to_answer_questionnaire
123
+ enforce_permission_to_respond_questionnaire
119
124
 
120
125
  @form = form(Decidim::Forms::QuestionnaireForm).from_params(params)
121
126
 
122
- flash.now[:alert] = I18n.t("answer.spam_detected", scope: i18n_flashes_scope)
123
- render template: "decidim/forms/questionnaires/show"
127
+ flash.now[:alert] = I18n.t("response.spam_detected", scope: i18n_flashes_scope)
128
+ render template:
124
129
  end
125
130
 
126
131
  # You can implement this method in your controller to change the
127
132
  # enforce_permission_to arguments.
128
- def enforce_permission_to_answer_questionnaire
129
- enforce_permission_to :answer, :questionnaire
133
+ def enforce_permission_to_respond_questionnaire
134
+ enforce_permission_to :respond, :questionnaire
130
135
  end
131
136
 
132
137
  def ip_hash
@@ -9,7 +9,7 @@ module Decidim
9
9
 
10
10
  attribute :decidim_question_id, Integer
11
11
  attribute :decidim_condition_question_id, Integer
12
- attribute :decidim_answer_option_id, Integer
12
+ attribute :decidim_response_option_id, Integer
13
13
  attribute :condition_type, String
14
14
  attribute :mandatory, Boolean, default: false
15
15
  attribute :deleted, Boolean, default: false
@@ -18,13 +18,13 @@ module Decidim
18
18
 
19
19
  validates :question, presence: true, unless: :deleted
20
20
  validates :condition_question, presence: true, unless: :deleted
21
- validates :answer_option, presence: true, if: :answer_option_mandatory?
21
+ validates :response_option, presence: true, if: :response_option_mandatory?
22
22
 
23
23
  validates :condition_value, translatable_presence: true, if: :condition_value_mandatory?
24
24
  validates :condition_type, presence: true, unless: :deleted
25
25
 
26
26
  validate :condition_question_position, unless: :deleted
27
- validate :valid_answer_option?, unless: :deleted
27
+ validate :valid_response_option?, unless: :deleted
28
28
 
29
29
  def to_param
30
30
  return id if id.present?
@@ -32,10 +32,10 @@ module Decidim
32
32
  "questionnaire-display-condition-id"
33
33
  end
34
34
 
35
- def answer_options
35
+ def response_options
36
36
  return [] if condition_question.blank?
37
37
 
38
- condition_question.answer_options
38
+ condition_question.response_options
39
39
  end
40
40
 
41
41
  def questions_for_select(questionnaire, id)
@@ -65,11 +65,11 @@ module Decidim
65
65
  @condition_question ||= Question.find_by(id: decidim_condition_question_id)
66
66
  end
67
67
 
68
- # Finds the Answer Option from the given decidim_answer_option_id
68
+ # Finds the Response Option from the given decidim_response_option_id
69
69
  #
70
- # Returns a Decidim::Forms::AnswerOption
71
- def answer_option
72
- @answer_option ||= AnswerOption.find_by(id: decidim_answer_option_id)
70
+ # Returns a Decidim::Forms::ResponseOption
71
+ def response_option
72
+ @response_option ||= ResponseOption.find_by(id: decidim_response_option_id)
73
73
  end
74
74
 
75
75
  private
@@ -78,15 +78,15 @@ module Decidim
78
78
  !deleted && condition_type == "match"
79
79
  end
80
80
 
81
- def answer_option_mandatory?
81
+ def response_option_mandatory?
82
82
  !deleted && %w(equal not_equal).include?(condition_type)
83
83
  end
84
84
 
85
- def valid_answer_option?
86
- return unless answer_option_mandatory?
87
- return if answer_option.blank?
85
+ def valid_response_option?
86
+ return unless response_option_mandatory?
87
+ return if response_option.blank?
88
88
 
89
- errors.add(:decidim_answer_option_id, :invalid) if answer_option.question.id != decidim_condition_question_id
89
+ errors.add(:decidim_response_option_id, :invalid) if response_option.question.id != decidim_condition_question_id
90
90
  end
91
91
 
92
92
  def condition_question_position
@@ -10,7 +10,7 @@ module Decidim
10
10
  attribute :position, Integer
11
11
  attribute :mandatory, Boolean, default: false
12
12
  attribute :question_type, String
13
- attribute :answer_options, Array[AnswerOptionForm]
13
+ attribute :response_options, Array[ResponseOptionForm]
14
14
  attribute :display_conditions, Array[DisplayConditionForm]
15
15
  attribute :matrix_rows, Array[QuestionMatrixRowForm]
16
16
  attribute :max_choices, Integer
@@ -26,7 +26,7 @@ module Decidim
26
26
  validates :max_characters, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
27
27
  validates :body, translatable_presence: true, if: :requires_body?
28
28
  validates :matrix_rows, presence: true, if: :matrix?
29
- validates :answer_options, presence: true, if: :matrix?
29
+ validates :response_options, presence: true, if: :matrix?
30
30
 
31
31
  def to_param
32
32
  return id if id.present?
@@ -35,7 +35,7 @@ module Decidim
35
35
  end
36
36
 
37
37
  def number_of_options
38
- answer_options.size
38
+ response_options.size
39
39
  end
40
40
 
41
41
  def separator?
@@ -3,8 +3,8 @@
3
3
  module Decidim
4
4
  module Forms
5
5
  module Admin
6
- # This class holds a Form to update answer options
7
- class AnswerOptionForm < Decidim::Form
6
+ # This class holds a Form to update response options
7
+ class ResponseOptionForm < Decidim::Form
8
8
  include TranslatableAttributes
9
9
 
10
10
  attribute :deleted, Boolean, default: false
@@ -17,7 +17,7 @@ module Decidim
17
17
  def to_param
18
18
  return id if id.present?
19
19
 
20
- "questionnaire-question-answer-option-id"
20
+ "questionnaire-question-response-option-id"
21
21
  end
22
22
  end
23
23
  end
@@ -2,18 +2,17 @@
2
2
 
3
3
  module Decidim
4
4
  module Forms
5
- # This class holds a Form to answer a questionnaire from Decidim's public page.
5
+ # This class holds a Form to response a questionnaire from Decidim's public page.
6
6
  class QuestionnaireForm < Decidim::Form
7
7
  include ActiveModel::Validations::Callbacks
8
8
 
9
- # as questionnaire uses "answers" for the database relationships is
9
+ # as questionnaire uses "responses" for the database relationships is
10
10
  # important not to use the same word here to avoid querying all the entries, resulting in a high performance penalty
11
- attribute :responses, Array[AnswerForm]
12
- attribute :user_group_id, Integer
11
+ attribute :responses, Array[ResponseForm]
13
12
  attribute :public_participation, Boolean, default: false
14
13
 
15
14
  attribute :tos_agreement, Boolean
16
- attribute :allow_editing_answers, Boolean, default: false
15
+ attribute :allow_editing_responses, Boolean, default: false
17
16
 
18
17
  before_validation :before_validation
19
18
 
@@ -25,17 +24,17 @@ module Decidim
25
24
  # Returns nothing.
26
25
  def map_model(model)
27
26
  self.responses = model.questions.map do |question|
28
- AnswerForm.from_model(Decidim::Forms::Answer.new(question:))
27
+ ResponseForm.from_model(Decidim::Forms::Response.new(question:))
29
28
  end
30
29
  end
31
30
 
32
- def add_answers!(questionnaire:, session_token:, ip_hash:)
31
+ def add_responses!(questionnaire:, session_token:, ip_hash:)
33
32
  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)
33
+ ResponseForm.from_model(Decidim::Forms::Response.where(question:, user: current_user, session_token:, ip_hash:).first_or_initialize)
35
34
  end
36
35
  end
37
36
 
38
- # Add other responses to the context so AnswerForm can validate conditional questions
37
+ # Add other responses to the context so ResponseForm can validate conditional questions
39
38
  def before_validation
40
39
  context.responses = attributes[:responses]
41
40
  end
@@ -2,18 +2,18 @@
2
2
 
3
3
  module Decidim
4
4
  module Forms
5
- # This class holds a Form to save the chosen option for an answer
6
- class AnswerChoiceForm < Decidim::Form
5
+ # This class holds a Form to save the chosen option for an response
6
+ class ResponseChoiceForm < Decidim::Form
7
7
  attribute :body, String
8
8
  attribute :custom_body, String
9
9
  attribute :position, Integer
10
- attribute :answer_option_id, Integer
10
+ attribute :response_option_id, Integer
11
11
  attribute :matrix_row_id, Integer
12
12
 
13
- validates :answer_option_id, presence: true
13
+ validates :response_option_id, presence: true
14
14
 
15
15
  def map_model(model)
16
- self.answer_option_id = model.decidim_answer_option_id
16
+ self.response_option_id = model.decidim_response_option_id
17
17
  self.matrix_row_id = model.decidim_question_matrix_row_id
18
18
  end
19
19
  end
@@ -2,15 +2,15 @@
2
2
 
3
3
  module Decidim
4
4
  module Forms
5
- # This class holds a Form to save the questionnaire answers from Decidim's public page
6
- class AnswerForm < Decidim::Form
5
+ # This class holds a Form to save the questionnaire responses from Decidim's public page
6
+ class ResponseForm < Decidim::Form
7
7
  include Decidim::TranslationsHelper
8
8
  include Decidim::AttachmentAttributes
9
9
 
10
10
  attribute :question_id, String
11
11
  attribute :body, String
12
- attribute :choices, Array[AnswerChoiceForm]
13
- attribute :matrix_choices, Array[AnswerChoiceForm]
12
+ attribute :choices, Array[ResponseChoiceForm]
13
+ attribute :matrix_choices, Array[ResponseChoiceForm]
14
14
 
15
15
  attachments_attribute :documents
16
16
 
@@ -47,7 +47,7 @@ module Decidim
47
47
  self.documents = model.attachments
48
48
 
49
49
  self.choices = model.choices.map do |choice|
50
- AnswerChoiceForm.from_model(choice)
50
+ ResponseChoiceForm.from_model(choice)
51
51
  end
52
52
  end
53
53
 
@@ -67,8 +67,8 @@ module Decidim
67
67
 
68
68
  def mandatory_conditions_fulfilled?
69
69
  question.display_conditions.where(mandatory: true).all? do |condition|
70
- answer = context.responses&.find { |r| r.question_id&.to_i == condition.condition_question.id }
71
- condition.fulfilled?(answer)
70
+ response = context.responses&.find { |r| r.question_id&.to_i == condition.condition_question.id }
71
+ condition.fulfilled?(response)
72
72
  end
73
73
  end
74
74
 
@@ -76,8 +76,8 @@ module Decidim
76
76
  return true unless question.display_conditions.where(mandatory: false).any?
77
77
 
78
78
  question.display_conditions.where(mandatory: false).any? do |condition|
79
- answer = context.responses&.find { |r| r.question_id&.to_i == condition.condition_question.id }
80
- condition.fulfilled?(answer)
79
+ response = context.responses&.find { |r| r.question_id&.to_i == condition.condition_question.id }
80
+ condition.fulfilled?(response)
81
81
  end
82
82
  end
83
83
 
@@ -12,8 +12,8 @@ module Decidim
12
12
  "questionnaire_question_#{question.to_param}"
13
13
  end
14
14
 
15
- def tabs_id_for_question_answer_option(question, answer_option)
16
- "questionnaire_question_#{question.to_param}_answer_option_#{answer_option.to_param}"
15
+ def tabs_id_for_question_response_option(question, response_option)
16
+ "questionnaire_question_#{question.to_param}_response_option_#{response_option.to_param}"
17
17
  end
18
18
 
19
19
  def tabs_id_for_question_display_condition(question, display_condition)
@@ -4,9 +4,9 @@ module Decidim
4
4
  module Forms
5
5
  module Admin
6
6
  module Concerns
7
- # Pagination helper for HasQuestionnaireAnswers controller concern
7
+ # Pagination helper for HasQuestionnaireResponses controller concern
8
8
  #
9
- module HasQuestionnaireAnswersPaginationHelper
9
+ module HasQuestionnaireResponsesPaginationHelper
10
10
  def self.included(base)
11
11
  base.helper_method :prev_url, :next_url, :first?, :last?, :current_idx
12
12
  end
@@ -15,14 +15,14 @@ module Decidim
15
15
  return if first?
16
16
 
17
17
  token = participant_ids[current_idx - 1]
18
- questionnaire_participant_answers_url(token)
18
+ questionnaire_participant_responses_url(token)
19
19
  end
20
20
 
21
21
  def next_url
22
22
  return if last?
23
23
 
24
24
  token = participant_ids[current_idx + 1]
25
- questionnaire_participant_answers_url(token)
25
+ questionnaire_participant_responses_url(token)
26
26
  end
27
27
 
28
28
  def first?
@@ -4,12 +4,12 @@ module Decidim
4
4
  module Forms
5
5
  module Admin
6
6
  module Concerns
7
- # Url helper for HasQuestionnaireAnswers controller concern
7
+ # Url helper for HasQuestionnaireResponses controller concern
8
8
  #
9
- module HasQuestionnaireAnswersUrlHelper
9
+ module HasQuestionnaireResponsesUrlHelper
10
10
  def self.included(base)
11
11
  base.helper_method :questionnaire_url, :questionnaire_participants_url,
12
- :questionnaire_participant_answers_url, :questionnaire_export_response_url
12
+ :questionnaire_participant_responses_url, :questionnaire_export_response_url
13
13
  end
14
14
 
15
15
  # You can implement this method in your controller to change the URL
@@ -25,8 +25,8 @@ module Decidim
25
25
  end
26
26
 
27
27
  # You can implement this method in your controller to change the URL
28
- # where the user's questionnaire answers will be shown.
29
- def questionnaire_participant_answers_url(id)
28
+ # where the user's questionnaire responses will be shown.
29
+ def questionnaire_participant_responses_url(id)
30
30
  url_for([questionnaire.questionnaire_for, { id: }])
31
31
  end
32
32
 
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Forms
5
+ module Admin
6
+ # Custom helpers for questionnaire responses
7
+ #
8
+ module QuestionnaireResponsesHelper
9
+ def first_table_th(response)
10
+ return nil if response.nil?
11
+
12
+ if response.first_short_response
13
+ @first_short_response = response.first_short_response
14
+ return translated_attribute @first_short_response.question.body
15
+ end
16
+
17
+ t("session_token", scope: "decidim.forms.user_responses_serializer")
18
+ end
19
+
20
+ def first_table_td(response)
21
+ return response.first_short_response&.body if @first_short_response
22
+
23
+ response.session_token
24
+ end
25
+
26
+ def display_percentage(number)
27
+ number_to_percentage(number, precision: 0, strip_insignificant_zeros: true, locale: I18n.locale)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -5,12 +5,11 @@ module Decidim
5
5
  # Custom helpers, scoped to the forms engine.
6
6
  module ApplicationHelper
7
7
  # Show cell for selected models
8
- def show_represent_user_group?
8
+ def show_public_participation?
9
9
  model_name = questionnaire_for.model_name.element
10
10
 
11
11
  permitted_models.include?(model_name)
12
12
  end
13
- alias show_public_participation? show_represent_user_group?
14
13
 
15
14
  def permitted_models
16
15
  %(meeting)
@@ -2,17 +2,17 @@
2
2
 
3
3
  module Decidim
4
4
  module Forms
5
- class ExportQuestionnaireAnswersJob < ApplicationJob
5
+ class ExportQuestionnaireResponsesJob < ApplicationJob
6
6
  include Decidim::PrivateDownloadHelper
7
7
 
8
8
  queue_as :exports
9
9
 
10
- def perform(user, file_name, answers, export_type = nil)
10
+ def perform(user, file_name, responses, export_type = nil)
11
11
  return if user&.email.blank?
12
- return if answers.blank?
12
+ return if responses.blank?
13
13
 
14
- serializer = Decidim::Forms::UserAnswersSerializer
15
- export_data = Decidim::Exporters::FormPDF.new(answers, serializer).export
14
+ serializer = Decidim::Forms::UserResponsesSerializer
15
+ export_data = Decidim::Exporters::FormPDF.new(responses, serializer).export
16
16
 
17
17
  private_export = attach_archive(export_data, file_name, user, export_type)
18
18
 
@@ -5,12 +5,12 @@ module Decidim
5
5
  # The data store for a DisplayCondition in the Decidim::Forms component.
6
6
  # A display condition is associated to two questions. :question is the question
7
7
  # that we want to display or hide based on some conditions, and :condition_question
8
- # is the question the answers of which are checked against the conditions.
9
- # Conditions can be whether the question is answered ("answered") or it is not ("not_answered"),
10
- # if the selected answer option is ("equal") or is not ("not_equal") a given one, or whether
11
- # the text value of the answer matches a string ("match").
8
+ # is the question the responses of which are checked against the conditions.
9
+ # Conditions can be whether the question is responded ("responded") or it is not ("not_responded"),
10
+ # if the selected response option is ("equal") or is not ("not_equal") a given one, or whether
11
+ # the text value of the response matches a string ("match").
12
12
  class DisplayCondition < Forms::ApplicationRecord
13
- enum condition_type: [:answered, :not_answered, :equal, :not_equal, :match], _prefix: true
13
+ enum :condition_type, [:responded, :not_responded, :equal, :not_equal, :match], prefix: true
14
14
 
15
15
  # Question which will be displayed or hidden
16
16
  belongs_to :question,
@@ -19,29 +19,29 @@ module Decidim
19
19
  inverse_of: :display_conditions,
20
20
  counter_cache: :display_conditions_count
21
21
 
22
- # Question the answers of which are checked against conditions
22
+ # Question the responses of which are checked against conditions
23
23
  belongs_to :condition_question,
24
24
  class_name: "Question",
25
25
  foreign_key: "decidim_condition_question_id",
26
26
  inverse_of: :display_conditions_for_other_questions,
27
27
  counter_cache: :display_conditions_for_other_questions_count
28
28
 
29
- # Answer option provided to check for "equal" or "not_equal" (optional)
30
- belongs_to :answer_option, class_name: "AnswerOption", foreign_key: "decidim_answer_option_id", optional: true
29
+ # Response option provided to check for "equal" or "not_equal" (optional)
30
+ belongs_to :response_option, class_name: "ResponseOption", foreign_key: "decidim_response_option_id", optional: true
31
31
 
32
- def fulfilled?(answer_form)
33
- return answer_form.present? if condition_type == "answered"
34
- return answer_form.blank? if condition_type == "not_answered"
32
+ def fulfilled?(response_form)
33
+ return response_form.present? if condition_type == "responded"
34
+ return response_form.blank? if condition_type == "not_responded"
35
35
  # rest of options require presence
36
- return if answer_form.blank?
36
+ return if response_form.blank?
37
37
 
38
38
  case condition_type
39
39
  when "equal"
40
- answer_form.choices.pluck(:answer_option_id).include?(answer_option.id)
40
+ response_form.choices.pluck(:response_option_id).include?(response_option.id)
41
41
  when "not_equal"
42
- answer_form.choices.pluck(:answer_option_id).exclude?(answer_option.id)
42
+ response_form.choices.pluck(:response_option_id).exclude?(response_option.id)
43
43
  when "match"
44
- condition_value.values.compact_blank.any? { |value| answer_form_matches?(answer_form, value) }
44
+ condition_value.values.compact_blank.any? { |value| response_form_matches?(response_form, value) }
45
45
  end
46
46
  end
47
47
 
@@ -50,7 +50,7 @@ module Decidim
50
50
  id:,
51
51
  type: condition_type,
52
52
  condition: decidim_condition_question_id,
53
- option: decidim_answer_option_id,
53
+ option: decidim_response_option_id,
54
54
  mandatory:,
55
55
  value: condition_value&.dig(I18n.locale.to_s)
56
56
  }.compact
@@ -58,12 +58,12 @@ module Decidim
58
58
 
59
59
  private
60
60
 
61
- def answer_form_matches?(answer_form, value)
61
+ def response_form_matches?(response_form, value)
62
62
  search = Regexp.new(value, Regexp::IGNORECASE)
63
- if answer_form.body
64
- answer_form.body.match?(search)
63
+ if response_form.body
64
+ response_form.body.match?(search)
65
65
  else
66
- answer_form.choices.any? do |choice_value|
66
+ response_form.choices.any? do |choice_value|
67
67
  choice_value.body&.match?(search) || choice_value.custom_body&.match?(search)
68
68
  end
69
69
  end