decidim-forms 0.27.6 → 0.28.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/cells/decidim/forms/answer_readonly/show.erb +1 -1
  4. data/app/cells/decidim/forms/matrix_readonly/show.erb +1 -1
  5. data/app/cells/decidim/forms/question_readonly/show.erb +8 -8
  6. data/app/cells/decidim/forms/question_readonly/title_and_description.erb +8 -0
  7. data/app/cells/decidim/forms/question_readonly_cell.rb +7 -0
  8. data/app/cells/decidim/forms/step_navigation/show.erb +13 -26
  9. data/app/cells/decidim/forms/step_navigation_cell.rb +7 -0
  10. data/app/commands/decidim/forms/answer_questionnaire.rb +31 -11
  11. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +4 -4
  12. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire_answers.rb +1 -1
  13. data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +3 -3
  14. data/app/forms/decidim/forms/answer_form.rb +7 -3
  15. data/app/forms/decidim/forms/questionnaire_form.rb +1 -1
  16. data/app/helpers/decidim/forms/admin/application_helper.rb +1 -1
  17. data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_url_helper.rb +2 -2
  18. data/app/models/decidim/forms/answer.rb +1 -1
  19. data/app/models/decidim/forms/display_condition.rb +2 -2
  20. data/app/models/decidim/forms/question.rb +0 -4
  21. data/app/models/decidim/forms/questionnaire.rb +1 -1
  22. data/app/packs/entrypoints/decidim_forms.js +4 -0
  23. data/app/packs/src/decidim/forms/admin/collapsible_questions.js +12 -6
  24. data/app/packs/src/decidim/forms/admin/forms.js +7 -7
  25. data/app/packs/src/decidim/forms/display_conditions.component.js +3 -3
  26. data/app/packs/src/decidim/forms/forms.js +15 -9
  27. data/app/packs/src/decidim/forms/option_attached_inputs.component.js +1 -1
  28. data/app/packs/stylesheets/decidim/forms/forms.scss +82 -52
  29. data/app/packs/stylesheets/decidim/forms/questionnaire-answers-pdf.scss +13 -13
  30. data/app/presenters/decidim/forms/admin/questionnaire_participant_presenter.rb +2 -2
  31. data/app/presenters/decidim/forms/admin_log/questionnaire_presenter.rb +2 -2
  32. data/app/presenters/decidim/forms/answer_option_presenter.rb +1 -1
  33. data/app/queries/decidim/forms/questionnaire_participants.rb +1 -1
  34. data/app/views/decidim/forms/admin/questionnaires/_answer_option.html.erb +1 -1
  35. data/app/views/decidim/forms/admin/questionnaires/_answer_option_template.html.erb +1 -1
  36. data/app/views/decidim/forms/admin/questionnaires/_display_condition.html.erb +2 -2
  37. data/app/views/decidim/forms/admin/questionnaires/_display_condition_template.html.erb +1 -1
  38. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +52 -74
  39. data/app/views/decidim/forms/admin/questionnaires/_matrix_row.html.erb +1 -1
  40. data/app/views/decidim/forms/admin/questionnaires/_matrix_row_template.html.erb +1 -1
  41. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +147 -135
  42. data/app/views/decidim/forms/admin/questionnaires/_separator.html.erb +15 -13
  43. data/app/views/decidim/forms/admin/questionnaires/_title_and_description.html.erb +69 -63
  44. data/app/views/decidim/forms/admin/questionnaires/answers/export/_answer.html.erb +4 -4
  45. data/app/views/decidim/forms/admin/questionnaires/answers/export/pdf.html.erb +1 -1
  46. data/app/views/decidim/forms/admin/questionnaires/answers/index.html.erb +41 -45
  47. data/app/views/decidim/forms/admin/questionnaires/answers/show.html.erb +13 -18
  48. data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +33 -6
  49. data/app/views/decidim/forms/questionnaires/_answer.html.erb +31 -27
  50. data/app/views/decidim/forms/questionnaires/_questionnaire.html.erb +78 -0
  51. data/app/views/decidim/forms/questionnaires/_questionnaire_readonly.html.erb +11 -0
  52. data/app/views/decidim/forms/questionnaires/answers/_files.html.erb +1 -1
  53. data/app/views/decidim/forms/questionnaires/answers/_long_answer.html.erb +3 -1
  54. data/app/views/decidim/forms/questionnaires/answers/_matrix_multiple.html.erb +44 -41
  55. data/app/views/decidim/forms/questionnaires/answers/_matrix_single.html.erb +44 -41
  56. data/app/views/decidim/forms/questionnaires/answers/_multiple_option.html.erb +7 -6
  57. data/app/views/decidim/forms/questionnaires/answers/_separator.html.erb +1 -1
  58. data/app/views/decidim/forms/questionnaires/answers/_short_answer.html.erb +3 -1
  59. data/app/views/decidim/forms/questionnaires/answers/_single_option.html.erb +13 -12
  60. data/app/views/decidim/forms/questionnaires/answers/_sorting.html.erb +9 -12
  61. data/app/views/decidim/forms/questionnaires/answers/_title_and_description.html.erb +1 -1
  62. data/app/views/decidim/forms/questionnaires/show.html.erb +35 -144
  63. data/config/initializers/wicked_pdf.rb +1 -1
  64. data/config/locales/ar.yml +0 -6
  65. data/config/locales/bg.yml +0 -11
  66. data/config/locales/ca.yml +7 -2
  67. data/config/locales/cs.yml +8 -3
  68. data/config/locales/de.yml +9 -4
  69. data/config/locales/el.yml +7 -2
  70. data/config/locales/en.yml +8 -3
  71. data/config/locales/es-MX.yml +7 -2
  72. data/config/locales/es-PY.yml +7 -2
  73. data/config/locales/es.yml +7 -2
  74. data/config/locales/eu.yml +8 -3
  75. data/config/locales/fi-plain.yml +7 -2
  76. data/config/locales/fi.yml +7 -2
  77. data/config/locales/fr-CA.yml +8 -3
  78. data/config/locales/fr.yml +8 -3
  79. data/config/locales/gl.yml +0 -4
  80. data/config/locales/hu.yml +3 -9
  81. data/config/locales/id-ID.yml +0 -4
  82. data/config/locales/it.yml +0 -6
  83. data/config/locales/ja.yml +6 -1
  84. data/config/locales/lb.yml +0 -6
  85. data/config/locales/lt.yml +7 -2
  86. data/config/locales/lv.yml +0 -6
  87. data/config/locales/nl.yml +0 -6
  88. data/config/locales/no.yml +0 -6
  89. data/config/locales/pl.yml +6 -8
  90. data/config/locales/pt-BR.yml +0 -25
  91. data/config/locales/pt.yml +0 -6
  92. data/config/locales/ro-RO.yml +19 -14
  93. data/config/locales/ru.yml +0 -3
  94. data/config/locales/sk.yml +0 -6
  95. data/config/locales/sv.yml +3 -6
  96. data/config/locales/tr-TR.yml +0 -6
  97. data/config/locales/zh-CN.yml +0 -6
  98. data/config/locales/zh-TW.yml +7 -2
  99. data/lib/decidim/forms/engine.rb +8 -0
  100. data/lib/decidim/forms/test/factories.rb +37 -51
  101. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +129 -239
  102. data/lib/decidim/forms/test/shared_examples/manage_questionnaire_answers.rb +18 -18
  103. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +14 -14
  104. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +60 -78
  105. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_display_conditions.rb +6 -6
  106. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +25 -25
  107. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +9 -9
  108. data/lib/decidim/forms/user_answers_serializer.rb +1 -1
  109. data/lib/decidim/forms/version.rb +1 -1
  110. metadata +26 -21
  111. data/app/packs/src/decidim/forms/autosortable_checkboxes.component.js +0 -83
  112. data/config/locales/he-IL.yml +0 -1
  113. data/decidim-forms.gemspec +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb8af1d2c76776bd4e799949d4723e998f57b4cc32ad3f021b1baff85fbd646b
4
- data.tar.gz: 65f42cfd48b2b6e175dcba554014b97533a25c7b92eac8e2144d165f5bf86a42
3
+ metadata.gz: dd5dd73bd692f7b3831ddd2c681e809f57d93e837cf954805175a62f828d346e
4
+ data.tar.gz: ddd68c6abf91ff0844f9564b9d2416316be51e68ff63f897418764756d9a2145
5
5
  SHA512:
6
- metadata.gz: b8a5638134be13bb12df3bc391fe1cff12314030215dde44c52ea87889946efdf7673f602ade25b7e8d87b0f973fc164649a46a97286547d754d469835891e08
7
- data.tar.gz: 4e1eaebf065003acc37cd0bcb26e5549f6b32202d2edb9d96e748c32a8caf70a7b26eceda53fe447160880d1e4525038ec572b54766a52bae2e26eb20b2b15f7
6
+ metadata.gz: 7112f8af0871a617187b9a0de640ccc12afa2c8d1bec3548dc437a9da246509648d0e453683e008b17cdea12545c0b056cf0b4f5efdf2a3639bf8fe23067ee2a
7
+ data.tar.gz: 3f428f34a2676141b67a7bfa0b5838e5f6bb5c949b20f0815cac3f3e472e73b8467b74fb0d67e8d11f71f45b34a07920795784ced44e792c305d2fc39e289bb2
data/README.md CHANGED
@@ -12,7 +12,7 @@ A `Decidim::Forms::Question` must be of one of the types:
12
12
 
13
13
  Here are the relations between the classes of a `Decidim::Questionnaire`:
14
14
 
15
- ```
15
+ ```plantuml
16
16
  1..* +----------+ 1..* +--------------+
17
17
  +------------->| Question |------------->| AnswerOption |
18
18
  | +-----+----+ +------+-------+
@@ -1,3 +1,3 @@
1
- <li class="questionnaire-question_readonly-answer">
1
+ <li>
2
2
  <%= translated_attribute(model.body) %>
3
3
  </li>
@@ -1,4 +1,4 @@
1
- <li class="questionnaire-question_readonly-answer">
1
+ <li>
2
2
  <%= translated_attribute(model.body) %>
3
3
 
4
4
  (<%= answer_options %>)
@@ -1,14 +1,14 @@
1
- <li class="questionnaire-question_readonly">
2
- <p>
3
- <%= decidim_escape_translated(model.body) %>
4
- <br>
5
- <em>
6
- (<%= t(model.question_type, scope: "decidim.forms.question_types") %>)
7
- </em>
1
+ <li class="answer-questionnaire__question" data-question-readonly>
2
+ <p class="answer-questionnaire__question-label" data-answer-idx="<%= position %>">
3
+ <%= translated_attribute(model.body) %>
4
+ </p>
5
+
6
+ <p class="answer-questionnaire__question-description">
7
+ <em><%= t(model.question_type, scope: "decidim.forms.question_types") %></em>
8
8
  </p>
9
9
 
10
10
  <% if model.multiple_choice? %>
11
- <ul class="questionnaire-question_readonly-answers <%= model.question_type %>">
11
+ <ul class="answer-questionnaire__question-description space-y-4">
12
12
  <% if model.matrix? %>
13
13
  <%= cell("decidim/forms/matrix_readonly", collection: model.matrix_rows) %>
14
14
  <% else %>
@@ -0,0 +1,8 @@
1
+ <li class="answer-questionnaire__question" data-question-readonly>
2
+ <div class="answer-questionnaire__step-heading">
3
+ <h3 class="h3"><%= translated_attribute(model.body) %></h3>
4
+ <p class="answer-questionnaire__question-description">
5
+ <em><%= t(model.question_type, scope: "decidim.forms.question_types") %></em>
6
+ </p>
7
+ </div>
8
+ </li>
@@ -4,11 +4,18 @@ module Decidim
4
4
  module Forms
5
5
  # This cell renders a question (readonly) of a questionnaire
6
6
  class QuestionReadonlyCell < Decidim::ViewModel
7
+ include Decidim::SanitizeHelper
8
+
7
9
  def show
8
10
  return if model.separator?
11
+ return render :title_and_description if model.title_and_description?
9
12
 
10
13
  render :show
11
14
  end
15
+
16
+ def position
17
+ options[:indexed_items].index(model.id) + 1
18
+ end
12
19
  end
13
20
  end
14
21
  end
@@ -1,35 +1,22 @@
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", "aria-hidden": true) + " " + 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
- ) %>
1
+ <div class="form-general-submit answer-questionnaire__submit">
2
+ <% if !first_step? %>
3
+ <button type="button" class="button button__sm button__text-secondary" data-toggle="<%= [previous_step_dom_id, current_step_dom_id].join(" ") %>">
4
+ <%= icon "arrow-left-line", class: "fill-current" %>
5
+ <%= t("decidim.forms.step_navigation.show.back") %>
6
+ </button>
13
7
  <% end %>
14
8
 
15
9
  <% if last_step? %>
16
10
  <%= form.submit(
17
- t("decidim.forms.step_navigation.show.submit"),
18
- class: "button button--sc",
11
+ "#{t("decidim.forms.step_navigation.show.submit")}#{icon "mail-send-line", class: "fill-current"}".html_safe,
12
+ class: "button button__sm button__secondary",
19
13
  disabled: button_disabled?,
20
- data: {
21
- confirm: t("decidim.forms.step_navigation.show.are_you_sure"),
22
- disable: true
23
- }
14
+ **confirm_data
24
15
  ) %>
25
16
  <% 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
- ) %>
17
+ <button type="button" class="button button__sm button__secondary" data-toggle="<%= [next_step_dom_id, current_step_dom_id].join(" ") %>">
18
+ <%= t("decidim.forms.step_navigation.show.continue") %>
19
+ <%= icon "arrow-right-line", class: "fill-current" %>
20
+ </button>
34
21
  <% end %>
35
22
  </div>
@@ -41,6 +41,13 @@ module Decidim
41
41
  def current_step_dom_id
42
42
  "step-#{current_step_index}"
43
43
  end
44
+
45
+ def confirm_data
46
+ { data: {
47
+ confirm: t("decidim.forms.step_navigation.show.are_you_sure"),
48
+ disable: true
49
+ } }
50
+ end
44
51
  end
45
52
  end
46
53
  end
@@ -22,7 +22,9 @@ module Decidim
22
22
  def call
23
23
  return broadcast(:invalid) if @form.invalid? || user_already_answered?
24
24
 
25
- answer_questionnaire
25
+ with_events do
26
+ answer_questionnaire
27
+ end
26
28
 
27
29
  if @errors
28
30
  reset_form_attachments
@@ -36,7 +38,18 @@ module Decidim
36
38
 
37
39
  private
38
40
 
39
- # This method will add an error to the `add_documents` field only if there's
41
+ def event_arguments
42
+ {
43
+ resource: questionnaire,
44
+ extra: {
45
+ session_token: form.context.session_token,
46
+ questionnaire:,
47
+ event_author: current_user
48
+ }
49
+ }
50
+ end
51
+
52
+ # This method will add an error to the `add_documents` field only if there is
40
53
  # any error in any other field or an error in another answer in the
41
54
  # questionnaire. This is needed because when the form has
42
55
  # an error, the attachments are lost, so we need a way to inform the user
@@ -47,6 +60,21 @@ module Decidim
47
60
  end
48
61
  end
49
62
 
63
+ def build_choices(answer, form_answer)
64
+ use_position = form_answer.sorting?
65
+
66
+ form_answer.selected_choices.each_with_index do |choice, idx|
67
+ choice_position = use_position ? choice.position.presence || idx : choice.position
68
+ answer.choices.build(
69
+ body: choice.body,
70
+ custom_body: choice.custom_body,
71
+ decidim_answer_option_id: choice.answer_option_id,
72
+ decidim_question_matrix_row_id: choice.matrix_row_id,
73
+ position: choice_position
74
+ )
75
+ end
76
+ end
77
+
50
78
  def answer_questionnaire
51
79
  @main_form = @form
52
80
  @errors = nil
@@ -62,15 +90,7 @@ module Decidim
62
90
  ip_hash: form.context.ip_hash
63
91
  )
64
92
 
65
- form_answer.selected_choices.each do |choice|
66
- answer.choices.build(
67
- body: choice.body,
68
- custom_body: choice.custom_body,
69
- decidim_answer_option_id: choice.answer_option_id,
70
- decidim_question_matrix_row_id: choice.matrix_row_id,
71
- position: choice.position
72
- )
73
- end
93
+ build_choices(answer, form_answer)
74
94
 
75
95
  answer.save!
76
96
 
@@ -20,7 +20,7 @@ module Decidim
20
20
  helper_method :questionnaire_for, :questionnaire, :blank_question, :blank_answer_option, :blank_matrix_row,
21
21
  :blank_display_condition, :question_types, :display_condition_types, :update_url, :public_url, :answer_options_url, :edit_questionnaire_title
22
22
 
23
- if defined?(Decidim::Templates::Admin::Concerns::Templatable)
23
+ if defined? Decidim::Templates::Admin
24
24
  include Decidim::Templates::Admin::Concerns::Templatable
25
25
  helper Decidim::DatalistSelectHelper
26
26
 
@@ -34,7 +34,7 @@ module Decidim
34
34
  end
35
35
 
36
36
  def edit
37
- enforce_permission_to :update, :questionnaire, questionnaire: questionnaire
37
+ enforce_permission_to(:update, :questionnaire, questionnaire:)
38
38
 
39
39
  @form = form(Admin::QuestionnaireForm).from_model(questionnaire)
40
40
 
@@ -42,7 +42,7 @@ module Decidim
42
42
  end
43
43
 
44
44
  def update
45
- enforce_permission_to :update, :questionnaire, questionnaire: questionnaire
45
+ enforce_permission_to(:update, :questionnaire, questionnaire:)
46
46
 
47
47
  params["published_at"] = Time.current if params.has_key? "save_and_publish"
48
48
  @form = form(Admin::QuestionnaireForm).from_params(params)
@@ -115,7 +115,7 @@ module Decidim
115
115
  end
116
116
 
117
117
  def questionnaire
118
- @questionnaire ||= Questionnaire.find_by(questionnaire_for: questionnaire_for)
118
+ @questionnaire ||= Questionnaire.find_by(questionnaire_for:)
119
119
  end
120
120
 
121
121
  def blank_question
@@ -71,7 +71,7 @@ module Decidim
71
71
  end
72
72
 
73
73
  def questionnaire
74
- @questionnaire ||= Questionnaire.find_by(questionnaire_for: questionnaire_for)
74
+ @questionnaire ||= Questionnaire.find_by(questionnaire_for:)
75
75
  end
76
76
 
77
77
  def participants_query
@@ -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, ip_hash: ip_hash)
31
+ @form = form(Decidim::Forms::QuestionnaireForm).from_params(params, session_token:, ip_hash:)
32
32
 
33
33
  Decidim::Forms::AnswerQuestionnaire.call(@form, current_user, questionnaire) do
34
34
  on(:ok) do
@@ -103,7 +103,7 @@ module Decidim
103
103
  end
104
104
 
105
105
  def questionnaire
106
- @questionnaire ||= Questionnaire.includes(questions: :answer_options).find_by(questionnaire_for: questionnaire_for)
106
+ @questionnaire ||= Questionnaire.includes(questions: :answer_options).find_by(questionnaire_for:)
107
107
  end
108
108
 
109
109
  def spam_detected
@@ -138,7 +138,7 @@ module Decidim
138
138
  end
139
139
 
140
140
  def tokenize(id, length: 10)
141
- tokenizer = Decidim::Tokenizer.new(salt: questionnaire.salt || questionnaire.id, length: length)
141
+ tokenizer = Decidim::Tokenizer.new(salt: questionnaire.salt || questionnaire.id, length:)
142
142
  tokenizer.int_digest(id).to_s
143
143
  end
144
144
  end
@@ -18,7 +18,7 @@ module Decidim
18
18
  validates :selected_choices, presence: true, if: :mandatory_choices?
19
19
 
20
20
  validate :max_choices, if: -> { question.max_choices }
21
- validate :all_choices, if: -> { question.sorting? && question.mandatory? }
21
+ validate :all_choices, if: :sorting?
22
22
  validate :min_choices, if: -> { question.matrix? && question.mandatory? }
23
23
  validate :documents_present, if: -> { question.question_type == "files" && question.mandatory? }
24
24
  validate :max_characters, if: -> { question.max_characters.positive? }
@@ -31,8 +31,8 @@ module Decidim
31
31
  @question ||= Decidim::Forms::Question.find(question_id)
32
32
  end
33
33
 
34
- def label(idx)
35
- base = "#{idx + 1}. #{translated_attribute(question.body)}"
34
+ def label
35
+ base = translated_attribute(question.body)
36
36
  base += " #{mandatory_label}" if question.mandatory?
37
37
  base += " (#{max_choices_label})" if question.max_choices
38
38
  base
@@ -88,6 +88,10 @@ module Decidim
88
88
  errors[:add_documents].present?
89
89
  end
90
90
 
91
+ def sorting?
92
+ question.question_type == "sorting"
93
+ end
94
+
91
95
  private
92
96
 
93
97
  def mandatory_body?
@@ -24,7 +24,7 @@ module Decidim
24
24
  # Returns nothing.
25
25
  def map_model(model)
26
26
  self.responses = model.questions.map do |question|
27
- AnswerForm.from_model(Decidim::Forms::Answer.new(question: question))
27
+ AnswerForm.from_model(Decidim::Forms::Answer.new(question:))
28
28
  end
29
29
  end
30
30
 
@@ -31,7 +31,7 @@ module Decidim
31
31
  "placeholder" => options[:placeholder],
32
32
  "locale" => I18n.locale
33
33
  }
34
- tag.span(class: options[:class], data: data) do
34
+ tag.span(class: options[:class], data:) do
35
35
  truncate translated_attribute(title), length: options[:max_length], omission: options[:omission]
36
36
  end
37
37
  end
@@ -27,11 +27,11 @@ module Decidim
27
27
  # You can implement this method in your controller to change the URL
28
28
  # where the user's questionnaire answers will be shown.
29
29
  def questionnaire_participant_answers_url(session_token)
30
- url_for([:show, questionnaire.questionnaire_for, { session_token: session_token }])
30
+ url_for([:show, questionnaire.questionnaire_for, { session_token: }])
31
31
  end
32
32
 
33
33
  def questionnaire_export_response_url(session_token)
34
- url_for([:export_response, questionnaire.questionnaire_for, { session_token: session_token, format: "pdf" }])
34
+ url_for([:export_response, questionnaire.questionnaire_for, { session_token:, format: "pdf" }])
35
35
  end
36
36
  end
37
37
  end
@@ -33,7 +33,7 @@ module Decidim
33
33
  end
34
34
 
35
35
  def self.newsletter_participant_ids(component)
36
- surveys = Decidim::Surveys::Survey.joins(:component, :questionnaire).where(component: component)
36
+ surveys = Decidim::Surveys::Survey.joins(:component, :questionnaire).where(component:)
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
 
@@ -39,11 +39,11 @@ module Decidim
39
39
 
40
40
  def to_html_data
41
41
  {
42
- id: id,
42
+ id:,
43
43
  type: condition_type,
44
44
  condition: decidim_condition_question_id,
45
45
  option: decidim_answer_option_id,
46
- mandatory: mandatory,
46
+ mandatory:,
47
47
  value: condition_value&.dig(I18n.locale.to_s)
48
48
  }.compact
49
49
  end
@@ -70,10 +70,6 @@ module Decidim
70
70
  mandatory? && !multiple_choice? && !has_attachments?
71
71
  end
72
72
 
73
- def sorting?
74
- question_type == "sorting"
75
- end
76
-
77
73
  def mandatory_choices?
78
74
  mandatory? && multiple_choice? && !has_attachments?
79
75
  end
@@ -27,7 +27,7 @@ module Decidim
27
27
 
28
28
  # Public: returns whether the questionnaire is answered by the user or not.
29
29
  def answered_by?(user)
30
- query = user.is_a?(String) ? { session_token: user } : { user: user }
30
+ query = user.is_a?(String) ? { session_token: user } : { user: }
31
31
  answers.where(query).any? if questions.present?
32
32
  end
33
33
 
@@ -1,4 +1,8 @@
1
1
  import "src/decidim/forms/forms"
2
2
 
3
+ // CSS
4
+ import "stylesheets/decidim/forms/forms.scss"
5
+ import "stylesheets/decidim/forms/questionnaire-answers-pdf.scss"
6
+
3
7
  // Images
4
8
  require.context("../images", true)
@@ -1,13 +1,19 @@
1
1
  (() => {
2
+ const getButtons = document.querySelectorAll("button.question--collapse");
3
+
4
+ setTimeout(() => {
5
+ [...getButtons].forEach((button) => {
6
+ if (button.classList.contains("question-error")) {
7
+ button.click()
8
+ }
9
+ })
10
+ }, 100)
11
+
2
12
  $("button.collapse-all").on("click", () => {
3
- $(".collapsible").addClass("hide");
4
- $(".question--collapse .icon-expand").removeClass("hide");
5
- $(".question--collapse .icon-collapse").addClass("hide");
13
+ $("[id$=field]").find("button.question--collapse[aria-expanded='true']").click()
6
14
  });
7
15
 
8
16
  $("button.expand-all").on("click", () => {
9
- $(".collapsible").removeClass("hide");
10
- $(".question--collapse .icon-expand").addClass("hide");
11
- $(".question--collapse .icon-collapse").removeClass("hide");
17
+ $("[id$=field]").find("button.question--collapse[aria-expanded='false']").click()
12
18
  });
13
19
  })(window);
@@ -10,7 +10,6 @@ import AutoLabelByPositionComponent from "src/decidim/admin/auto_label_by_positi
10
10
  import createSortList from "src/decidim/admin/sort_list.component"
11
11
  import createDynamicFields from "src/decidim/admin/dynamic_fields.component"
12
12
  import createFieldDependentInputs from "src/decidim/admin/field_dependent_inputs.component"
13
- import createQuillEditor from "src/decidim/editor"
14
13
  import initLanguageChangeSelect from "src/decidim/admin/choose_language"
15
14
 
16
15
  export default function createEditableForm() {
@@ -132,8 +131,10 @@ export default function createEditableForm() {
132
131
  const $collapsible = $target.find(".collapsible");
133
132
  if ($collapsible.length > 0) {
134
133
  const collapsibleId = $collapsible.attr("id").replace("-question-card", "");
135
- const toggleAttr = `${collapsibleId}-question-card button--collapse-question-${collapsibleId} button--expand-question-${collapsibleId}`;
136
- $target.find(".question--collapse").data("toggle", toggleAttr);
134
+ const toggleAttr = `${collapsibleId}-question-card`;
135
+
136
+ // we need to update the DOM, not just the dataset
137
+ $target.find(".question--collapse").attr("data-controls", toggleAttr);
137
138
  }
138
139
  };
139
140
 
@@ -387,14 +388,13 @@ export default function createEditableForm() {
387
388
  setupInitialQuestionAttributes($field);
388
389
  createSortableList();
389
390
 
390
- $field.find(".editor-container").each((idx, el) => {
391
- createQuillEditor(el);
392
- });
393
-
394
391
  autoLabelByPosition.run();
395
392
  autoButtonsByPosition.run();
396
393
 
397
394
  initLanguageChangeSelect($field.find("select.language-change").toArray());
395
+
396
+ // instead of initialize specific stuff, we send an event, with the DOM fragment we wanna update/refresh/bind
397
+ document.dispatchEvent(new CustomEvent("ajax:loaded", { detail: $field[0] }));
398
398
  },
399
399
  onRemoveField: ($field) => {
400
400
  autoLabelByPosition.run();
@@ -1,4 +1,4 @@
1
- /* eslint-disable no-ternary, no-plusplus, require-jsdoc */
1
+ /* eslint-disable no-plusplus, require-jsdoc */
2
2
 
3
3
  class DisplayCondition {
4
4
  constructor(options = {}) {
@@ -27,7 +27,7 @@ class DisplayCondition {
27
27
 
28
28
  let multipleInput = [];
29
29
 
30
- $conditionWrapperField.find(".radio-button-collection, .check-box-collection").find(".collection-input").each((idx, el) => {
30
+ $conditionWrapperField.find(".js-radio-button-collection, .js-check-box-collection").find(".js-collection-input").each((idx, el) => {
31
31
  const $input = $(el).find("input[name$=\\[body\\]]");
32
32
  const checked = $input.is(":checked");
33
33
 
@@ -51,7 +51,7 @@ class DisplayCondition {
51
51
  return $textInput;
52
52
  }
53
53
 
54
- return $conditionWrapperField.find(".collection-input").find("input:not([type='hidden'])");
54
+ return $conditionWrapperField.find(".js-collection-input").find("input:not([type='hidden'])");
55
55
  }
56
56
 
57
57
  checkAnsweredCondition(value) {
@@ -1,12 +1,19 @@
1
1
  /* eslint-disable require-jsdoc */
2
2
 
3
+ /**
4
+ * Since the ["drag-on-drop"](https://github.com/schne324/dragon-drop) dependency is just an A11Y wrapper,
5
+ * its core is actually using the ["dragula"](https://github.com/bevacqua/dragula) resource,
6
+ * therefore the styles must be imported from the original library.
7
+ */
8
+ import DragonDrop from "drag-on-drop";
9
+ import "dragula/dist/dragula.css";
10
+
3
11
  import createOptionAttachedInputs from "src/decidim/forms/option_attached_inputs.component"
4
- import createAutosortableCheckboxes from "src/decidim/forms/autosortable_checkboxes.component"
5
12
  import createDisplayConditions from "src/decidim/forms/display_conditions.component"
6
13
  import createMaxChoicesAlertComponent from "src/decidim/forms/max_choices_alert.component"
7
14
 
8
15
  $(() => {
9
- $(".radio-button-collection, .check-box-collection").each((idx, el) => {
16
+ $(".js-radio-button-collection, .js-check-box-collection").each((idx, el) => {
10
17
  createOptionAttachedInputs({
11
18
  wrapperField: $(el),
12
19
  controllerFieldSelector: "input[type=radio], input[type=checkbox]",
@@ -14,24 +21,23 @@ $(() => {
14
21
  });
15
22
  });
16
23
 
17
- $.unique($(".check-box-collection").parents(".answer")).each((idx, el) => {
24
+ $.unique($(".js-check-box-collection").parents(".answer")).each((idx, el) => {
18
25
  const maxChoices = $(el).data("max-choices");
19
26
  if (maxChoices) {
20
27
  createMaxChoicesAlertComponent({
21
28
  wrapperField: $(el),
22
29
  controllerFieldSelector: "input[type=checkbox]",
23
- controllerCollectionSelector: ".check-box-collection",
30
+ controllerCollectionSelector: ".js-check-box-collection",
24
31
  alertElement: $(el).find(".max-choices-alert"),
25
32
  maxChoices: maxChoices
26
33
  });
27
34
  }
28
35
  });
29
36
 
30
- $(".sortable-check-box-collection").each((idx, el) => {
31
- createAutosortableCheckboxes({
32
- wrapperField: $(el)
33
- })
34
- });
37
+ document.querySelectorAll(".js-sortable-check-box-collection").forEach((el) => new DragonDrop(el, {
38
+ handle: false,
39
+ item: ".js-collection-input"
40
+ }));
35
41
 
36
42
  $(".answer-questionnaire .question[data-conditioned='true']").each((idx, el) => {
37
43
  createDisplayConditions({
@@ -15,7 +15,7 @@ class OptionAttachedInputsComponent {
15
15
  const $field = $(el);
16
16
  const enabled = $field.is(":checked");
17
17
 
18
- $field.parents("div.collection-input").find(this.dependentInputSelector).prop("disabled", !enabled);
18
+ $field.parents("div.js-collection-input").find(this.dependentInputSelector).prop("disabled", !enabled);
19
19
  });
20
20
  }
21
21