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
@@ -6,7 +6,7 @@ module Decidim
6
6
  class Question < Forms::ApplicationRecord
7
7
  include Decidim::TranslatableResource
8
8
 
9
- QUESTION_TYPES = %w(short_answer long_answer single_option multiple_option sorting files matrix_single matrix_multiple).freeze
9
+ QUESTION_TYPES = %w(short_response long_response single_option multiple_option sorting files matrix_single matrix_multiple).freeze
10
10
  SEPARATOR_TYPE = "separator"
11
11
  TITLE_AND_DESCRIPTION_TYPE = "title_and_description"
12
12
  TYPES = (QUESTION_TYPES + [SEPARATOR_TYPE, TITLE_AND_DESCRIPTION_TYPE]).freeze
@@ -21,8 +21,8 @@ module Decidim
21
21
  dependent: :destroy,
22
22
  inverse_of: :question
23
23
 
24
- has_many :answer_options,
25
- class_name: "AnswerOption",
24
+ has_many :response_options,
25
+ class_name: "ResponseOption",
26
26
  foreign_key: "decidim_question_id",
27
27
  dependent: :destroy,
28
28
  inverse_of: :question
@@ -34,21 +34,22 @@ module Decidim
34
34
  dependent: :destroy,
35
35
  inverse_of: :question
36
36
 
37
- # Conditions to display other questions based on the value of this question's answer
37
+ # Conditions to display other questions based on the value of this question's response
38
38
  has_many :display_conditions_for_other_questions,
39
39
  class_name: "DisplayCondition",
40
40
  foreign_key: "decidim_condition_question_id",
41
41
  dependent: :destroy,
42
- inverse_of: :question
42
+ inverse_of: :question,
43
+ counter_cache: :display_conditions_for_other_questions_count
43
44
 
44
- # Questions which have display conditions based on the value of this question's answer
45
+ # Questions which have display conditions based on the value of this question's response
45
46
  has_many :conditioned_questions,
46
47
  through: :display_conditions_for_other_questions,
47
48
  foreign_key: "decidim_condition_question_id",
48
49
  class_name: "Question"
49
50
 
50
- has_many :answers,
51
- class_name: "Answer",
51
+ has_many :responses,
52
+ class_name: "Response",
52
53
  foreign_key: "decidim_question_id",
53
54
  dependent: :destroy,
54
55
  inverse_of: :question
@@ -58,8 +59,8 @@ module Decidim
58
59
  scope :not_separator, -> { where.not(question_type: SEPARATOR_TYPE) }
59
60
  scope :not_title_and_description, -> { where.not(question_type: TITLE_AND_DESCRIPTION_TYPE) }
60
61
 
61
- scope :with_body, -> { where(question_type: %w(short_answer long_answer)) }
62
- scope :with_choices, -> { where.not(question_type: %w(short_answer long_answer)) }
62
+ scope :with_body, -> { where(question_type: %w(short_response long_response)) }
63
+ scope :with_choices, -> { where.not(question_type: %w(short_response long_response)) }
63
64
 
64
65
  scope :conditioned, -> { includes(:display_conditions).where.not(decidim_forms_display_conditions: { id: nil }) }
65
66
  scope :not_conditioned, -> { includes(:display_conditions).where(decidim_forms_display_conditions: { id: nil }) }
@@ -81,7 +82,7 @@ module Decidim
81
82
  end
82
83
 
83
84
  def number_of_options
84
- answer_options.size
85
+ response_options.size
85
86
  end
86
87
 
87
88
  def translated_body
@@ -100,8 +101,8 @@ module Decidim
100
101
  question_type.to_s == "files"
101
102
  end
102
103
 
103
- def answers_count
104
- questionnaire.answers.where(question: self).count
104
+ def responses_count
105
+ questionnaire.responses.where(question: self).count
105
106
  end
106
107
 
107
108
  def self.log_presenter_class_for(_log)
@@ -9,7 +9,7 @@ module Decidim
9
9
  translatable_fields :body
10
10
  belongs_to :question, class_name: "Question", foreign_key: "decidim_question_id", counter_cache: :matrix_rows_count
11
11
 
12
- delegate :answer_options, :mandatory, :max_choices, to: :question
12
+ delegate :response_options, :mandatory, :max_choices, to: :question
13
13
 
14
14
  scope :by_position, -> { order(:position) }
15
15
  default_scope { by_position }
@@ -13,22 +13,27 @@ module Decidim
13
13
  belongs_to :questionnaire_for, polymorphic: true
14
14
 
15
15
  has_many :questions, -> { order(:position) }, class_name: "Question", foreign_key: "decidim_questionnaire_id", dependent: :destroy
16
- has_many :answers, class_name: "Answer", foreign_key: "decidim_questionnaire_id", dependent: :destroy
16
+ has_many :responses, class_name: "Response", foreign_key: "decidim_questionnaire_id", dependent: :destroy
17
17
 
18
18
  after_initialize :set_default_salt
19
19
 
20
20
  attr_accessor :questionnaire_template_id
21
+ attr_reader :override_edit
21
22
 
22
23
  # Public: returns whether the questionnaire questions can be modified or not.
23
24
  def questions_editable?
24
25
  has_component = questionnaire_for.respond_to? :component
25
- (has_component && !questionnaire_for.component.published?) || answers.empty?
26
+ (has_component && !questionnaire_for.component.published?) || override_edit.presence || responses.empty?
26
27
  end
27
28
 
28
- # Public: returns whether the questionnaire is answered by the user or not.
29
- def answered_by?(user)
29
+ def override_edit!
30
+ @override_edit = true
31
+ end
32
+
33
+ # Public: returns whether the questionnaire is responded by the user or not.
34
+ def responded_by?(user)
30
35
  query = user.is_a?(String) ? { session_token: user } : { user: }
31
- answers.where(query).any? if questions.present?
36
+ responses.where(query).any? if questions.present?
32
37
  end
33
38
 
34
39
  def pristine?
@@ -45,7 +50,7 @@ module Decidim
45
50
 
46
51
  private
47
52
 
48
- # salt is used to generate secure hash in anonymous answers
53
+ # salt is used to generate secure hash in anonymous responses
49
54
  def set_default_salt
50
55
  return unless defined?(salt)
51
56
 
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Decidim
4
4
  module Forms
5
- # The data store for an Answer in the Decidim::Forms
6
- class Answer < Forms::ApplicationRecord
5
+ # The data store for an Response in the Decidim::Forms
6
+ class Response < Forms::ApplicationRecord
7
7
  include Decidim::DownloadYourData
8
8
  include Decidim::NewsletterParticipant
9
9
  include Decidim::HasAttachments
@@ -13,10 +13,10 @@ module Decidim
13
13
  belongs_to :question, class_name: "Question", foreign_key: "decidim_question_id"
14
14
 
15
15
  has_many :choices,
16
- class_name: "AnswerChoice",
17
- foreign_key: "decidim_answer_id",
16
+ class_name: "ResponseChoice",
17
+ foreign_key: "decidim_response_id",
18
18
  dependent: :destroy,
19
- inverse_of: :answer
19
+ inverse_of: :response
20
20
 
21
21
  validate :user_questionnaire_same_organization
22
22
  validate :question_belongs_to_questionnaire
@@ -29,7 +29,7 @@ module Decidim
29
29
  end
30
30
 
31
31
  def self.export_serializer
32
- Decidim::Forms::DownloadYourDataUserAnswersSerializer
32
+ Decidim::Forms::DownloadYourDataUserResponsesSerializer
33
33
  end
34
34
 
35
35
  def self.newsletter_participant_ids(component)
@@ -37,10 +37,10 @@ module Decidim
37
37
  questionnaires = Decidim::Forms::Questionnaire.includes(:questionnaire_for)
38
38
  .where(questionnaire_for_type: Decidim::Surveys::Survey.name, questionnaire_for_id: surveys.pluck(:id))
39
39
 
40
- answers = Decidim::Forms::Answer.joins(:questionnaire)
41
- .where(questionnaire: questionnaires)
40
+ responses = Decidim::Forms::Response.joins(:questionnaire)
41
+ .where(questionnaire: questionnaires)
42
42
 
43
- answers.pluck(:decidim_user_id).flatten.compact.uniq
43
+ responses.pluck(:decidim_user_id).flatten.compact.uniq
44
44
  end
45
45
 
46
46
  def organization
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Forms
5
+ class ResponseChoice < Forms::ApplicationRecord
6
+ belongs_to :response,
7
+ class_name: "Response",
8
+ foreign_key: "decidim_response_id"
9
+
10
+ belongs_to :response_option,
11
+ class_name: "ResponseOption",
12
+ foreign_key: "decidim_response_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: -> { response.question.matrix? }
20
+ end
21
+ end
22
+ end
@@ -2,23 +2,23 @@
2
2
 
3
3
  module Decidim
4
4
  module Forms
5
- class AnswerOption < Forms::ApplicationRecord
5
+ class ResponseOption < Forms::ApplicationRecord
6
6
  include Decidim::TranslatableResource
7
7
 
8
8
  default_scope { order(arel_table[:id].asc) }
9
9
 
10
10
  translatable_fields :body
11
11
 
12
- belongs_to :question, class_name: "Question", foreign_key: "decidim_question_id", counter_cache: :answer_options_count
12
+ belongs_to :question, class_name: "Question", foreign_key: "decidim_question_id", counter_cache: :response_options_count
13
13
 
14
14
  has_many :display_conditions,
15
15
  class_name: "DisplayCondition",
16
- foreign_key: "decidim_answer_option_id",
16
+ foreign_key: "decidim_response_option_id",
17
17
  dependent: :nullify,
18
- inverse_of: :answer_option
18
+ inverse_of: :response_option
19
19
 
20
20
  def translated_body
21
- Decidim::Forms::AnswerOptionPresenter.new(self).translated_body
21
+ Decidim::Forms::ResponseOptionPresenter.new(self).translated_body
22
22
  end
23
23
  end
24
24
  end
@@ -1,10 +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"
4
+ import createPublicableQuestionResponsesButtons from "src/decidim/forms/admin/publish_responses_buttons"
5
5
 
6
6
  window.Decidim.createEditableForm = createEditableForm
7
7
 
8
- document.addEventListener("DOMContentLoaded", function() {
9
- document.querySelectorAll("[data-publish-question-answer-action]").forEach((el) => createPublicableQuestionAnswersButtons(el));
8
+ document.addEventListener("turbo:load", () => {
9
+ document.querySelectorAll("[data-publish-question-response-action]").forEach((el) => createPublicableQuestionResponsesButtons(el));
10
10
  });
@@ -1,19 +1,21 @@
1
- (() => {
1
+ document.addEventListener("turbo:load", () => {
2
2
  const getButtons = document.querySelectorAll("button.question--collapse");
3
3
 
4
4
  setTimeout(() => {
5
- [...getButtons].forEach((button) => {
5
+ getButtons.forEach((button) => {
6
6
  if (button.classList.contains("question-error")) {
7
- button.click()
7
+ button.click();
8
8
  }
9
- })
10
- }, 100)
9
+ });
10
+ }, 100);
11
11
 
12
- $("button.collapse-all").on("click", () => {
13
- $("[id$=field]").find("button.question--collapse[aria-expanded='true']").click()
12
+ document.querySelector("button.collapse-all")?.addEventListener("click", () => {
13
+ document.querySelectorAll("[id$=field] button.question--collapse[aria-expanded='true']").
14
+ forEach((button) => button.click());
14
15
  });
15
16
 
16
- $("button.expand-all").on("click", () => {
17
- $("[id$=field]").find("button.question--collapse[aria-expanded='false']").click()
17
+ document.querySelector("button.expand-all")?.addEventListener("click", () => {
18
+ document.querySelectorAll("[id$=field] button.question--collapse[aria-expanded='false']").
19
+ forEach((button) => button.click());
18
20
  });
19
- })(window);
21
+ });
@@ -16,9 +16,9 @@ export default function createEditableForm() {
16
16
  const wrapperSelector = ".questionnaire-questions";
17
17
  const fieldSelector = ".questionnaire-question";
18
18
  const questionTypeSelector = "select[name$=\\[question_type\\]]";
19
- const answerOptionFieldSelector = ".questionnaire-question-answer-option";
20
- const answerOptionsWrapperSelector = ".questionnaire-question-answer-options";
21
- const answerOptionRemoveFieldButtonSelector = ".remove-answer-option";
19
+ const responseOptionFieldSelector = ".questionnaire-question-response-option";
20
+ const responseOptionsWrapperSelector = ".questionnaire-question-response-options";
21
+ const responseOptionRemoveFieldButtonSelector = ".remove-response-option";
22
22
  const matrixRowFieldSelector = ".questionnaire-question-matrix-row";
23
23
  const matrixRowsWrapperSelector = ".questionnaire-question-matrix-rows";
24
24
  const matrixRowRemoveFieldButtonSelector = ".remove-matrix-row";
@@ -30,12 +30,12 @@ export default function createEditableForm() {
30
30
  const displayConditionRemoveFieldButtonSelector = ".remove-display-condition";
31
31
 
32
32
  const displayConditionQuestionSelector = "select[name$=\\[decidim_condition_question_id\\]]";
33
- const displayConditionAnswerOptionSelector = "select[name$=\\[decidim_answer_option_id\\]]";
33
+ const displayConditionResponseOptionSelector = "select[name$=\\[decidim_response_option_id\\]]";
34
34
  const displayConditionTypeSelector = "select[name$=\\[condition_type\\]]";
35
35
  const deletedInputSelector = "input[name$=\\[deleted\\]]";
36
36
 
37
37
  const displayConditionValueWrapperSelector = ".questionnaire-question-display-condition-value";
38
- const displayconditionAnswerOptionWrapperSelector = ".questionnaire-question-display-condition-answer-option";
38
+ const displayconditionResponseOptionWrapperSelector = ".questionnaire-question-display-condition-response-option";
39
39
 
40
40
  const addDisplayConditionButtonSelector = ".add-display-condition";
41
41
 
@@ -74,27 +74,27 @@ export default function createEditableForm() {
74
74
  const MULTIPLE_CHOICE_VALUES = ["single_option", "multiple_option", "sorting", "matrix_single", "matrix_multiple"];
75
75
  const MATRIX_VALUES = ["matrix_single", "matrix_multiple"];
76
76
 
77
- const createAutoMaxChoicesByNumberOfAnswerOptions = (fieldId) => {
77
+ const createAutoMaxChoicesByNumberOfResponseOptions = (fieldId) => {
78
78
  return new AutoSelectOptionsByTotalItemsComponent({
79
79
  wrapperSelector: fieldSelector,
80
80
  selectSelector: `${maxChoicesWrapperSelector} select`,
81
- listSelector: `#${fieldId} ${answerOptionsWrapperSelector} .questionnaire-question-answer-option:not(.hidden)`
81
+ listSelector: `#${fieldId} ${responseOptionsWrapperSelector} .questionnaire-question-response-option:not(.hidden)`
82
82
  })
83
83
  };
84
84
 
85
- const createAutoButtonsByMinItemsForAnswerOptions = (fieldId) => {
85
+ const createAutoButtonsByMinItemsForResponseOptions = (fieldId) => {
86
86
  return new AutoButtonsByMinItemsComponent({
87
87
  wrapperSelector: fieldSelector,
88
- listSelector: `#${fieldId} ${answerOptionsWrapperSelector} .questionnaire-question-answer-option:not(.hidden)`,
88
+ listSelector: `#${fieldId} ${responseOptionsWrapperSelector} .questionnaire-question-response-option:not(.hidden)`,
89
89
  minItems: 2,
90
- hideOnMinItemsOrLessSelector: answerOptionRemoveFieldButtonSelector
90
+ hideOnMinItemsOrLessSelector: responseOptionRemoveFieldButtonSelector
91
91
  })
92
92
  };
93
93
 
94
94
  const createAutoSelectOptionsFromUrl = ($field) => {
95
95
  return new AutoSelectOptionsFromUrl({
96
96
  source: $field.find(displayConditionQuestionSelector),
97
- select: $field.find(displayConditionAnswerOptionSelector),
97
+ select: $field.find(displayConditionResponseOptionSelector),
98
98
  sourceToParams: ($element) => { return { id: $element.val() } }
99
99
  })
100
100
  };
@@ -138,18 +138,18 @@ export default function createEditableForm() {
138
138
  }
139
139
  };
140
140
 
141
- const createDynamicFieldsForAnswerOptions = (fieldId) => {
142
- const autoButtons = createAutoButtonsByMinItemsForAnswerOptions(fieldId);
143
- const autoSelectOptions = createAutoMaxChoicesByNumberOfAnswerOptions(fieldId);
141
+ const createDynamicFieldsForResponseOptions = (fieldId) => {
142
+ const autoButtons = createAutoButtonsByMinItemsForResponseOptions(fieldId);
143
+ const autoSelectOptions = createAutoMaxChoicesByNumberOfResponseOptions(fieldId);
144
144
 
145
145
  return createDynamicFields({
146
- placeholderId: "questionnaire-question-answer-option-id",
147
- wrapperSelector: `#${fieldId} ${answerOptionsWrapperSelector}`,
148
- containerSelector: ".questionnaire-question-answer-options-list",
149
- fieldSelector: answerOptionFieldSelector,
150
- addFieldButtonSelector: ".add-answer-option",
151
- fieldTemplateSelector: ".decidim-answer-option-template",
152
- removeFieldButtonSelector: answerOptionRemoveFieldButtonSelector,
146
+ placeholderId: "questionnaire-question-response-option-id",
147
+ wrapperSelector: `#${fieldId} ${responseOptionsWrapperSelector}`,
148
+ containerSelector: ".questionnaire-question-response-options-list",
149
+ fieldSelector: responseOptionFieldSelector,
150
+ addFieldButtonSelector: ".add-response-option",
151
+ fieldTemplateSelector: ".decidim-response-option-template",
152
+ removeFieldButtonSelector: responseOptionRemoveFieldButtonSelector,
153
153
  onAddField: () => {
154
154
  autoButtons.run();
155
155
  autoSelectOptions.run();
@@ -161,7 +161,7 @@ export default function createEditableForm() {
161
161
  });
162
162
  };
163
163
 
164
- const dynamicFieldsForAnswerOptions = {};
164
+ const dynamicFieldsForResponseOptions = {};
165
165
 
166
166
  const createDynamicFieldsForMatrixRows = (fieldId) => {
167
167
  return createDynamicFields({
@@ -200,7 +200,7 @@ export default function createEditableForm() {
200
200
 
201
201
  const isMultiple = isMultipleChoiceOption(selectedQuestionType);
202
202
 
203
- let conditionTypes = ["answered", "not_answered"];
203
+ let conditionTypes = ["responded", "not_responded"];
204
204
 
205
205
  if (isMultiple) {
206
206
  conditionTypes.push("equal");
@@ -236,7 +236,7 @@ export default function createEditableForm() {
236
236
  const onDisplayConditionTypeChange = ($field) => {
237
237
  const value = $field.find(displayConditionTypeSelector).val();
238
238
  const $valueWrapper = $field.find(displayConditionValueWrapperSelector);
239
- const $answerOptionWrapper = $field.find(displayconditionAnswerOptionWrapperSelector);
239
+ const $responseOptionWrapper = $field.find(displayconditionResponseOptionWrapperSelector);
240
240
 
241
241
  const $questionSelector = $field.find(displayConditionQuestionSelector);
242
242
  const selectedQuestionType = getSelectedQuestionType($questionSelector[0]);
@@ -251,10 +251,10 @@ export default function createEditableForm() {
251
251
  }
252
252
 
253
253
  if (isMultiple && (value === "not_equal" || value === "equal")) {
254
- $answerOptionWrapper.show();
254
+ $responseOptionWrapper.show();
255
255
  }
256
256
  else {
257
- $answerOptionWrapper.hide();
257
+ $responseOptionWrapper.hide();
258
258
  }
259
259
  };
260
260
 
@@ -302,8 +302,8 @@ export default function createEditableForm() {
302
302
  createFieldDependentInputs({
303
303
  controllerField: $fieldQuestionTypeSelect,
304
304
  wrapperSelector: fieldSelector,
305
- dependentFieldsSelector: answerOptionsWrapperSelector,
306
- dependentInputSelector: `${answerOptionFieldSelector} input`,
305
+ dependentFieldsSelector: responseOptionsWrapperSelector,
306
+ dependentInputSelector: `${responseOptionFieldSelector} input`,
307
307
  enablingCondition: ($field) => {
308
308
  return isMultipleChoiceOption($field.val());
309
309
  }
@@ -329,20 +329,20 @@ export default function createEditableForm() {
329
329
  }
330
330
  });
331
331
 
332
- dynamicFieldsForAnswerOptions[fieldId] = createDynamicFieldsForAnswerOptions(fieldId);
332
+ dynamicFieldsForResponseOptions[fieldId] = createDynamicFieldsForResponseOptions(fieldId);
333
333
  dynamicFieldsForMatrixRows[fieldId] = createDynamicFieldsForMatrixRows(fieldId);
334
334
  dynamicFieldsForDisplayConditions[fieldId] = createDynamicFieldsForDisplayConditions(fieldId);
335
335
 
336
- const dynamicFieldsAnswerOptions = dynamicFieldsForAnswerOptions[fieldId];
336
+ const dynamicFieldsResponseOptions = dynamicFieldsForResponseOptions[fieldId];
337
337
  const dynamicFieldsMatrixRows = dynamicFieldsForMatrixRows[fieldId];
338
338
 
339
339
  const onQuestionTypeChange = () => {
340
340
  if (isMultipleChoiceOption($fieldQuestionTypeSelect.val())) {
341
- const nOptions = $fieldQuestionTypeSelect.parents(fieldSelector).find(answerOptionFieldSelector).length;
341
+ const nOptions = $fieldQuestionTypeSelect.parents(fieldSelector).find(responseOptionFieldSelector).length;
342
342
 
343
343
  if (nOptions === 0) {
344
- dynamicFieldsAnswerOptions._addField();
345
- dynamicFieldsAnswerOptions._addField();
344
+ dynamicFieldsResponseOptions._addField();
345
+ dynamicFieldsResponseOptions._addField();
346
346
  }
347
347
  }
348
348
 
@@ -400,8 +400,8 @@ export default function createEditableForm() {
400
400
  autoLabelByPosition.run();
401
401
  autoButtonsByPosition.run();
402
402
 
403
- $field.find(answerOptionRemoveFieldButtonSelector).each((idx, el) => {
404
- dynamicFieldsForAnswerOptions[$field.attr("id")]._removeField(el);
403
+ $field.find(responseOptionRemoveFieldButtonSelector).each((idx, el) => {
404
+ dynamicFieldsForResponseOptions[$field.attr("id")]._removeField(el);
405
405
  });
406
406
 
407
407
  $field.find(matrixRowRemoveFieldButtonSelector).each((idx, el) => {
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Initializes event listeners for a button to toggle the publication status of question answers.
2
+ * Initializes event listeners for a button to toggle the publication status of question responses.
3
3
  *
4
- * The button's `data-publish-question-answer-action` attribute determines whether the action is
4
+ * The button's `data-publish-question-response-action` attribute determines whether the action is
5
5
  * to "publish" or "unpublish." Based on this attribute, the function makes an AJAX request using
6
6
  * Rails' AJAX helper and updates the button's state and associated labels.
7
7
  *
@@ -10,8 +10,8 @@
10
10
  * @returns {void}
11
11
  *
12
12
  * Button element must have the following data attributes:
13
- * - `data-publish-question-answer-action`: Specifies the current action ("publish" or "unpublish").
14
- * - `data-publish-question-answer-question-url`: Specifies the endpoint URL for the AJAX request.
13
+ * - `data-publish-question-response-action`: Specifies the current action ("publish" or "unpublish").
14
+ * - `data-publish-question-response-question-url`: Specifies the endpoint URL for the AJAX request.
15
15
  *
16
16
  * The DOM structure must include:
17
17
  * - A parent element with the class `toggle__switch-toggle`.
@@ -28,16 +28,16 @@
28
28
  * <span class="label alert hidden">Unpublished</span>
29
29
  * <span>
30
30
  * <input
31
- * data-publish-question-answer-action="unpublish"
32
- * data-publish-question-answer-question-url="/path/to/publish/or/unpublish">
31
+ * data-publish-question-response-action="unpublish"
32
+ * data-publish-question-response-question-url="/path/to/publish/or/unpublish">
33
33
  * </span>
34
34
  * </label>
35
35
  * ```
36
36
  */
37
- export default function createPublicableQuestionAnswersButtons(button) {
37
+ export default function createPublicableQuestionResponsesButtons(button) {
38
38
  button.addEventListener("click", () => {
39
- const action = button.dataset.publishQuestionAnswerAction;
40
- const url = button.dataset.publishQuestionAnswerQuestionUrl;
39
+ const action = button.dataset.publishQuestionResponseAction;
40
+ const url = button.dataset.publishQuestionResponseQuestionUrl;
41
41
  const buttonText = button.closest(".toggle__switch-toggle").querySelector(".toggle__switch-trigger-text");
42
42
  const publishedLabel = buttonText.querySelector(".label.success");
43
43
  const unpublishedLabel = buttonText.querySelector(".label.alert");
@@ -48,7 +48,7 @@ export default function createPublicableQuestionAnswersButtons(button) {
48
48
  url: url,
49
49
  type: "PUT",
50
50
  success: function() {
51
- button.setAttribute("data-publish-question-answer-action", "unpublish")
51
+ button.setAttribute("data-publish-question-response-action", "unpublish")
52
52
  publishedLabel.classList.remove("hidden");
53
53
  unpublishedLabel.classList.add("hidden");
54
54
  }
@@ -59,14 +59,14 @@ export default function createPublicableQuestionAnswersButtons(button) {
59
59
  url: url,
60
60
  type: "DELETE",
61
61
  success: function() {
62
- button.setAttribute("data-publish-question-answer-action", "publish")
62
+ button.setAttribute("data-publish-question-response-action", "publish")
63
63
  unpublishedLabel.classList.remove("hidden");
64
64
  publishedLabel.classList.add("hidden");
65
65
  }
66
66
  });
67
67
  break;
68
68
  default:
69
- console.log(`Publish questions answers: Unknown action ${action}`);
69
+ console.log(`Publish questions responses: Unknown action ${action}`);
70
70
  }
71
71
  });
72
72
  }
@@ -5,7 +5,7 @@ class DisplayCondition {
5
5
  this.wrapperField = options.wrapperField;
6
6
  this.type = options.type;
7
7
  this.conditionQuestion = options.conditionQuestion;
8
- this.answerOption = options.answerOption;
8
+ this.responseOption = options.responseOption;
9
9
  this.mandatory = options.mandatory;
10
10
  this.value = options.value;
11
11
  this.onFulfilled = options.onFulfilled;
@@ -34,7 +34,7 @@ class DisplayCondition {
34
34
  if (checked) {
35
35
  const text = $(el).find("input[name$=\\[custom_body\\]]").val();
36
36
  const value = $input.val();
37
- const id = $(el).find("input[name$=\\[answer_option_id\\]]").val();
37
+ const id = $(el).find("input[name$=\\[response_option_id\\]]").val();
38
38
 
39
39
  multipleInput.push({ id, value, text });
40
40
  }
@@ -54,7 +54,7 @@ class DisplayCondition {
54
54
  return $conditionWrapperField.find(".js-collection-input").find("input:not([type='hidden'])");
55
55
  }
56
56
 
57
- checkAnsweredCondition(value) {
57
+ checkRespondedCondition(value) {
58
58
  if (typeof (value) !== "object") {
59
59
  return Boolean(value);
60
60
  }
@@ -62,20 +62,20 @@ class DisplayCondition {
62
62
  return Boolean(value.some((it) => it.value));
63
63
  }
64
64
 
65
- checkNotAnsweredCondition(value) {
66
- return !this.checkAnsweredCondition(value);
65
+ checkNotRespondedCondition(value) {
66
+ return !this.checkRespondedCondition(value);
67
67
  }
68
68
 
69
69
  checkEqualCondition(value) {
70
70
  if (value.length) {
71
- return value.some((it) => it.id === this.answerOption.toString());
71
+ return value.some((it) => it.id === this.responseOption.toString());
72
72
  }
73
73
  return false;
74
74
  }
75
75
 
76
76
  checkNotEqualCondition(value) {
77
77
  if (value.length) {
78
- return value.every((it) => it.id !== this.answerOption.toString());
78
+ return value.every((it) => it.id !== this.responseOption.toString());
79
79
  }
80
80
  return false;
81
81
  }
@@ -99,11 +99,11 @@ class DisplayCondition {
99
99
  let fulfilled = false;
100
100
 
101
101
  switch (this.type) {
102
- case "answered":
103
- fulfilled = this.checkAnsweredCondition(value);
102
+ case "responded":
103
+ fulfilled = this.checkRespondedCondition(value);
104
104
  break;
105
- case "not_answered":
106
- fulfilled = this.checkNotAnsweredCondition(value);
105
+ case "not_responded":
106
+ fulfilled = this.checkNotRespondedCondition(value);
107
107
  break;
108
108
  case "equal":
109
109
  fulfilled = this.checkEqualCondition(value);
@@ -143,7 +143,7 @@ class DisplayConditionsComponent {
143
143
  wrapperField: this.wrapperField,
144
144
  type: $condition.data("type"),
145
145
  conditionQuestion: $condition.data("condition"),
146
- answerOption: $condition.data("option"),
146
+ responseOption: $condition.data("option"),
147
147
  mandatory: $condition.data("mandatory"),
148
148
  value: $condition.data("value"),
149
149
  onFulfilled: (fulfilled) => {
@@ -13,7 +13,7 @@ import createDisplayConditions from "src/decidim/forms/display_conditions.compon
13
13
  import createMaxChoicesAlertComponent from "src/decidim/forms/max_choices_alert.component"
14
14
  import { preventUnload } from "src/decidim/utilities/dom"
15
15
 
16
- $(() => {
16
+ document.addEventListener("turbo:load", () => {
17
17
  $(".js-radio-button-collection, .js-check-box-collection").each((idx, el) => {
18
18
  createOptionAttachedInputs({
19
19
  wrapperField: $(el),
@@ -22,7 +22,7 @@ $(() => {
22
22
  });
23
23
  });
24
24
 
25
- $.unique($(".js-check-box-collection").parents(".answer")).each((idx, el) => {
25
+ $.unique($(".js-check-box-collection").parents(".response")).each((idx, el) => {
26
26
  const maxChoices = $(el).data("max-choices");
27
27
  if (maxChoices) {
28
28
  createMaxChoicesAlertComponent({
@@ -40,13 +40,13 @@ $(() => {
40
40
  item: ".js-collection-input"
41
41
  }));
42
42
 
43
- $(".answer-questionnaire .question[data-conditioned='true']").each((idx, el) => {
43
+ $(".response-questionnaire .question[data-conditioned='true']").each((idx, el) => {
44
44
  createDisplayConditions({
45
45
  wrapperField: $(el)
46
46
  });
47
47
  });
48
48
 
49
- const form = document.querySelector("form.answer-questionnaire");
49
+ const form = document.querySelector("form.response-questionnaire");
50
50
  if (form) {
51
51
  const safePath = form.dataset.safePath.split("?")[0];
52
52
  let exitUrl = "";
@@ -1,4 +1,4 @@
1
- .answer-questionnaire {
1
+ .response-questionnaire {
2
2
  @apply border-t-2 border-background pt-8;
3
3
 
4
4
  &__step {
@@ -22,7 +22,7 @@
22
22
  }
23
23
 
24
24
  &__question-label {
25
- @apply text-black text-xl font-semibold relative before:content-[attr(data-answer-idx)] before:w-6 before:h-6 md:before:absolute md:before:-left-4 md:before:-translate-x-full before:inline-flex before:justify-center before:rounded-full before:bg-background before:text-lg before:text-gray-2 before:font-semibold;
25
+ @apply text-black text-xl font-semibold relative before:content-[attr(data-response-idx)] before:w-6 before:h-6 md:before:absolute md:before:-left-4 md:before:-translate-x-full before:inline-flex before:justify-center before:rounded-full before:bg-background before:text-lg before:text-gray-2 before:font-semibold;
26
26
  }
27
27
 
28
28
  &__question-description {