decidim-forms 0.19.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/config/admin/decidim_forms_manifest.js +1 -0
  4. data/app/assets/images/decidim/surveys/icon.svg +1 -19
  5. data/app/assets/javascripts/decidim/forms/admin/collapsible_questions.js.es6 +13 -0
  6. data/app/assets/javascripts/decidim/forms/admin/forms.js.es6 +95 -7
  7. data/app/assets/javascripts/decidim/forms/admin/live_text_update.component.js.es6 +52 -0
  8. data/app/assets/javascripts/decidim/forms/forms.js.es6 +42 -1
  9. data/app/assets/javascripts/decidim/forms/max_choices_alert.component.js.es6 +44 -0
  10. data/app/assets/stylesheets/decidim/forms/forms.scss +39 -0
  11. data/app/cells/decidim/forms/matrix_readonly/show.erb +5 -0
  12. data/app/cells/decidim/forms/matrix_readonly_cell.rb +12 -0
  13. data/app/cells/decidim/forms/question_readonly/show.erb +5 -1
  14. data/app/cells/decidim/forms/question_readonly_cell.rb +5 -0
  15. data/app/cells/decidim/forms/step_navigation/show.erb +35 -0
  16. data/app/cells/decidim/forms/step_navigation_cell.rb +46 -0
  17. data/app/commands/decidim/forms/admin/update_questionnaire.rb +8 -0
  18. data/app/commands/decidim/forms/answer_questionnaire.rb +7 -2
  19. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +6 -2
  20. data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +58 -2
  21. data/app/forms/decidim/forms/admin/question_form.rb +20 -1
  22. data/app/forms/decidim/forms/admin/question_matrix_row_form.rb +26 -0
  23. data/app/forms/decidim/forms/answer_choice_form.rb +1 -0
  24. data/app/forms/decidim/forms/answer_form.rb +16 -2
  25. data/app/forms/decidim/forms/questionnaire_form.rb +33 -3
  26. data/app/helpers/decidim/forms/admin/application_helper.rb +16 -0
  27. data/app/models/decidim/forms/answer.rb +2 -2
  28. data/app/models/decidim/forms/answer_choice.rb +7 -0
  29. data/app/models/decidim/forms/question.rb +18 -2
  30. data/app/models/decidim/forms/question_matrix_row.rb +12 -0
  31. data/app/models/decidim/forms/questionnaire.rb +2 -1
  32. data/app/queries/decidim/forms/questionnaire_user_answers.rb +1 -1
  33. data/app/types/decidim/forms/answer_option_type.rb +14 -0
  34. data/app/types/decidim/forms/question_type.rb +23 -0
  35. data/app/types/decidim/forms/questionnaire_type.rb +22 -0
  36. data/app/views/decidim/forms/admin/questionnaires/_answer_option_template.html.erb +1 -1
  37. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +37 -4
  38. data/app/views/decidim/forms/admin/questionnaires/_matrix_row.html.erb +34 -0
  39. data/app/views/decidim/forms/admin/questionnaires/_matrix_row_template.html.erb +7 -0
  40. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +29 -6
  41. data/app/views/decidim/forms/admin/questionnaires/_separator.html.erb +41 -0
  42. data/app/views/decidim/forms/questionnaires/_answer.html.erb +21 -92
  43. data/app/views/decidim/forms/questionnaires/answers/_long_answer.html.erb +1 -0
  44. data/app/views/decidim/forms/questionnaires/answers/_matrix_multiple.html.erb +43 -0
  45. data/app/views/decidim/forms/questionnaires/answers/_matrix_single.html.erb +43 -0
  46. data/app/views/decidim/forms/questionnaires/answers/_multiple_option.html.erb +23 -0
  47. data/app/views/decidim/forms/questionnaires/answers/_separator.html.erb +1 -0
  48. data/app/views/decidim/forms/questionnaires/answers/_short_answer.html.erb +1 -0
  49. data/app/views/decidim/forms/questionnaires/answers/_single_option.html.erb +30 -0
  50. data/app/views/decidim/forms/questionnaires/answers/_sorting.html.erb +23 -0
  51. data/app/views/decidim/forms/questionnaires/show.html.erb +60 -27
  52. data/config/locales/ar.yml +12 -3
  53. data/config/locales/bg-BG.yml +16 -0
  54. data/config/locales/ca.yml +45 -7
  55. data/config/locales/cs.yml +41 -3
  56. data/config/locales/da-DK.yml +1 -0
  57. data/config/locales/de.yml +41 -3
  58. data/config/locales/el-GR.yml +1 -0
  59. data/config/locales/el.yml +120 -0
  60. data/config/locales/en.yml +41 -3
  61. data/config/locales/es-MX.yml +41 -3
  62. data/config/locales/es-PY.yml +41 -3
  63. data/config/locales/es.yml +41 -3
  64. data/config/locales/et-EE.yml +1 -0
  65. data/config/locales/eu.yml +7 -3
  66. data/config/locales/fi-plain.yml +41 -3
  67. data/config/locales/fi.yml +42 -4
  68. data/config/locales/fr-CA.yml +120 -0
  69. data/config/locales/fr.yml +41 -3
  70. data/config/locales/ga-IE.yml +1 -0
  71. data/config/locales/gl.yml +7 -3
  72. data/config/locales/hr-HR.yml +1 -0
  73. data/config/locales/hu.yml +18 -4
  74. data/config/locales/id-ID.yml +7 -3
  75. data/config/locales/is-IS.yml +1 -0
  76. data/config/locales/it.yml +42 -4
  77. data/config/locales/ja-JP.yml +120 -0
  78. data/config/locales/lt-LT.yml +1 -0
  79. data/config/locales/lv-LV.yml +119 -0
  80. data/config/locales/mt-MT.yml +1 -0
  81. data/config/locales/nl.yml +41 -3
  82. data/config/locales/no.yml +86 -1
  83. data/config/locales/pl.yml +63 -25
  84. data/config/locales/pt-BR.yml +8 -4
  85. data/config/locales/pt.yml +62 -24
  86. data/config/locales/ro-RO.yml +118 -0
  87. data/config/locales/ru.yml +47 -0
  88. data/config/locales/sk-SK.yml +88 -0
  89. data/config/locales/sk.yml +92 -0
  90. data/config/locales/sl.yml +5 -0
  91. data/config/locales/sr-CS.yml +1 -0
  92. data/config/locales/sv.yml +41 -3
  93. data/config/locales/tr-TR.yml +7 -3
  94. data/db/migrate/20190315203056_add_session_token_to_decidim_forms_answers.rb +17 -0
  95. data/db/migrate/20190930094710_add_ip_hash_to_decidim_form_answers.rb +12 -0
  96. data/db/migrate/20200225123810_create_decidim_forms_question_matrix_rows.rb +11 -0
  97. data/db/migrate/20200304152939_add_matrix_row_id_to_decidim_forms_answer_choices.rb +11 -0
  98. data/lib/decidim/api/questionnaire_entity_interface.rb +18 -0
  99. data/lib/decidim/forms.rb +1 -0
  100. data/lib/decidim/forms/api.rb +7 -0
  101. data/lib/decidim/forms/test/factories.rb +55 -11
  102. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +320 -43
  103. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +347 -16
  104. data/lib/decidim/forms/user_answers_serializer.rb +23 -4
  105. data/lib/decidim/forms/version.rb +1 -1
  106. metadata +56 -9
@@ -13,6 +13,22 @@ module Decidim
13
13
  def tabs_id_for_question_answer_option(question, answer_option)
14
14
  "questionnaire_question_#{question.to_param}_answer_option_#{answer_option.to_param}"
15
15
  end
16
+
17
+ def tabs_id_for_question_matrix_row(question, matrix_row)
18
+ "questionnaire_question_#{question.to_param}_matrix_row_#{matrix_row.to_param}"
19
+ end
20
+
21
+ def dynamic_title(title, **options)
22
+ data = {
23
+ "max-length" => options[:max_length],
24
+ "omission" => options[:omission],
25
+ "placeholder" => options[:placeholder],
26
+ "locale" => I18n.locale
27
+ }
28
+ content_tag :span, class: options[:class], data: data do
29
+ truncate translated_attribute(title), length: options[:max_length], omission: options[:omission]
30
+ end
31
+ end
16
32
  end
17
33
  end
18
34
  end
@@ -7,7 +7,7 @@ module Decidim
7
7
  include Decidim::DataPortability
8
8
  include Decidim::NewsletterParticipant
9
9
 
10
- belongs_to :user, class_name: "Decidim::User", foreign_key: "decidim_user_id"
10
+ belongs_to :user, class_name: "Decidim::User", foreign_key: "decidim_user_id", optional: true
11
11
  belongs_to :questionnaire, class_name: "Questionnaire", foreign_key: "decidim_questionnaire_id"
12
12
  belongs_to :question, class_name: "Question", foreign_key: "decidim_question_id"
13
13
 
@@ -45,7 +45,7 @@ module Decidim
45
45
  private
46
46
 
47
47
  def user_questionnaire_same_organization
48
- return if user&.organization == questionnaire.questionnaire_for&.organization
48
+ return if user.nil? || user&.organization == questionnaire.questionnaire_for&.organization
49
49
 
50
50
  errors.add(:user, :invalid)
51
51
  end
@@ -10,6 +10,13 @@ module Decidim
10
10
  belongs_to :answer_option,
11
11
  class_name: "AnswerOption",
12
12
  foreign_key: "decidim_answer_option_id"
13
+
14
+ belongs_to :matrix_row,
15
+ class_name: "QuestionMatrixRow",
16
+ foreign_key: "decidim_question_matrix_row_id",
17
+ optional: true
18
+
19
+ validates :matrix_row, presence: true, if: -> { answer.question.matrix? }
13
20
  end
14
21
  end
15
22
  end
@@ -4,10 +4,18 @@ module Decidim
4
4
  module Forms
5
5
  # The data store for a Question in the Decidim::Forms component.
6
6
  class Question < Forms::ApplicationRecord
7
- TYPES = %w(short_answer long_answer single_option multiple_option sorting).freeze
7
+ QUESTION_TYPES = %w(short_answer long_answer single_option multiple_option sorting matrix_single matrix_multiple).freeze
8
+ SEPARATOR_TYPE = "separator"
9
+ TYPES = (QUESTION_TYPES + [SEPARATOR_TYPE]).freeze
8
10
 
9
11
  belongs_to :questionnaire, class_name: "Questionnaire", foreign_key: "decidim_questionnaire_id"
10
12
 
13
+ has_many :matrix_rows,
14
+ class_name: "QuestionMatrixRow",
15
+ foreign_key: "decidim_question_id",
16
+ dependent: :destroy,
17
+ inverse_of: :question
18
+
11
19
  has_many :answer_options,
12
20
  class_name: "AnswerOption",
13
21
  foreign_key: "decidim_question_id",
@@ -16,8 +24,12 @@ module Decidim
16
24
 
17
25
  validates :question_type, inclusion: { in: TYPES }
18
26
 
27
+ def matrix?
28
+ %w(matrix_single matrix_multiple).include?(question_type)
29
+ end
30
+
19
31
  def multiple_choice?
20
- %w(single_option multiple_option sorting).include?(question_type)
32
+ %w(single_option multiple_option sorting matrix_single matrix_multiple).include?(question_type)
21
33
  end
22
34
 
23
35
  def mandatory_body?
@@ -31,6 +43,10 @@ module Decidim
31
43
  def number_of_options
32
44
  answer_options.size
33
45
  end
46
+
47
+ def separator?
48
+ question_type.to_s == SEPARATOR_TYPE
49
+ end
34
50
  end
35
51
  end
36
52
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Forms
5
+ # The data store for a QuestionMatrix in the Decidim::Forms component.
6
+ class QuestionMatrixRow < Forms::ApplicationRecord
7
+ belongs_to :question, class_name: "Question", foreign_key: "decidim_question_id"
8
+
9
+ delegate :answer_options, :mandatory, :max_choices, to: :question
10
+ end
11
+ end
12
+ end
@@ -16,7 +16,8 @@ module Decidim
16
16
 
17
17
  # Public: returns whether the questionnaire is answered by the user or not.
18
18
  def answered_by?(user)
19
- answers.where(user: user).any? if questions.present?
19
+ query = user.is_a?(String) ? { session_token: user } : { user: user }
20
+ answers.where(query).any? if questions.present?
20
21
  end
21
22
  end
22
23
  end
@@ -21,7 +21,7 @@ module Decidim
21
21
  # Finds and group answers by user for each questionnaire's question.
22
22
  def query
23
23
  answers = Answer.where(questionnaire: @questionnaire)
24
- answers.sort_by { |answer| answer.question.position }.group_by(&:user).values
24
+ answers.sort_by { |answer| answer.question.position }.group_by { |a| a.user || a.session_token }.values
25
25
  end
26
26
  end
27
27
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Forms
5
+ AnswerOptionType = GraphQL::ObjectType.define do
6
+ name "AnswerOption"
7
+ description "An answer option for a multi-choice question in a questionnaire"
8
+
9
+ field :id, !types.ID, "ID of this answer option"
10
+ field :body, !Decidim::Core::TranslatedFieldType, "The text answer response option."
11
+ field :freeText, !types.Boolean, "Whether if this answer accepts any free text from the user.", property: :free_text
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Forms
5
+ QuestionType = GraphQL::ObjectType.define do
6
+ name "Question"
7
+ description "A question in a questionnaire"
8
+
9
+ interfaces [
10
+ -> { Decidim::Core::TimestampsInterface }
11
+ ]
12
+
13
+ field :id, !types.ID, "ID of this question"
14
+ field :body, !Decidim::Core::TranslatedFieldType, "What is being asked in this question."
15
+ field :description, Decidim::Core::TranslatedFieldType, "The description of this question."
16
+ field :mandatory, !types.Boolean, "Whether if this question is mandatory."
17
+ field :position, types.Int, "Order position of the question in the questionnaire"
18
+ field :maxChoices, types.Int, "On questions with answer options, maximum number of choices the user has", property: :max_choices
19
+ field :questionType, types.String, "Type of question.", property: :question_type
20
+ field :answerOptions, !types[AnswerOptionType], "List of answer options in multi-choice questions.", property: :answer_options
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Forms
5
+ QuestionnaireType = GraphQL::ObjectType.define do
6
+ name "Questionnaire"
7
+ description "A questionnaire"
8
+
9
+ interfaces [
10
+ -> { Decidim::Core::TimestampsInterface }
11
+ ]
12
+
13
+ field :id, !types.ID, "ID of this questionnaire"
14
+ field :title, !Decidim::Core::TranslatedFieldType, "The title of this questionnaire."
15
+ field :description, Decidim::Core::TranslatedFieldType, "The description of this questionnaire."
16
+ field :tos, Decidim::Core::TranslatedFieldType, "The Terms of Service for this questionnaire."
17
+ field :forType, types.String, "Type of entity using this questionnaire.", property: :questionnaire_for_type
18
+ field :forEntity, QuestionnaireEntityInterface, "Entity using this questionnaire.", property: :questionnaire_for
19
+ field :questions, !types[QuestionType], "Questions in this questionnaire."
20
+ end
21
+ end
22
+ end
@@ -1,6 +1,6 @@
1
1
  <% question = form.object %>
2
2
 
3
- <script type="text/template" class="decidim-template" id="<%= template_id %>">
3
+ <script type="text/template" class="decidim-answer-option-template decidim-template" id="<%= template_id %>">
4
4
  <%= fields_for "questionnaire[questions][#{question.to_param}][answer_options][]", blank_answer_option do |answer_option_form| %>
5
5
  <%= render "decidim/forms/admin/questionnaires/answer_option", form: answer_option_form, question: question, editable: editable %>
6
6
  <% end %>
@@ -21,12 +21,29 @@
21
21
  </div>
22
22
 
23
23
  <div class="questionnaire-questions">
24
+ <div class="row column text-center">
25
+ <button type="button" class="button collapse-all"><%= t(".collapse") %></button>
26
+ <button type="button" class="button expand-all"><%= t(".expand") %></button>
27
+ </div>
28
+
24
29
  <% if questionnaire.questions_editable? %>
25
30
  <%= fields_for "questionnaire[questions][#{blank_question.to_param}]", blank_question do |question_form| %>
26
- <script type="text/template" class="decidim-template">
27
- <%= render "decidim/forms/admin/questionnaires/question", form: question_form, id: tabs_id_for_question(blank_question), editable: questionnaire.questions_editable?, child_template_selector: "#answer-option-template-dummy" %>
31
+ <script type="text/template" class="decidim-question-template decidim-template" id="question-template">
32
+ <%= render "decidim/forms/admin/questionnaires/question",
33
+ form: question_form,
34
+ id: tabs_id_for_question(blank_question),
35
+ editable: questionnaire.questions_editable?,
36
+ answer_option_template_selector: "#answer-option-template-dummy",
37
+ matrix_row_template_selector: "#matrix-row-template-dummy" %>
38
+ </script>
39
+ <script type="text/template" class="decidim-separator-template decidim-template" id="separator-template">
40
+ <%= render "decidim/forms/admin/questionnaires/separator",
41
+ form: question_form,
42
+ id: tabs_id_for_question(blank_question),
43
+ editable: questionnaire.questions_editable? %>
28
44
  </script>
29
45
  <%= render "decidim/forms/admin/questionnaires/answer_option_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "answer-option-template-dummy" %>
46
+ <%= render "decidim/forms/admin/questionnaires/matrix_row_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "matrix-row-template-dummy" %>
30
47
  <% end %>
31
48
  <% else %>
32
49
  <div class="callout warning">
@@ -37,17 +54,33 @@
37
54
  <div class="questionnaire-questions-list">
38
55
  <% @form.questions.each_with_index do |question, index| %>
39
56
  <%= fields_for "questionnaire[questions][]", question do |question_form| %>
40
- <%= render "decidim/forms/admin/questionnaires/question", form: question_form, id: tabs_id_for_question(question), editable: questionnaire.questions_editable?, child_template_selector: "#answer-option-template-#{index}" %>
41
- <%= render "decidim/forms/admin/questionnaires/answer_option_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "answer-option-template-#{index}" %>
57
+ <% if question.separator? %>
58
+ <%= render "decidim/forms/admin/questionnaires/separator",
59
+ form: question_form,
60
+ id: tabs_id_for_question(question),
61
+ editable: questionnaire.questions_editable? %>
62
+ <% else %>
63
+ <%= render "decidim/forms/admin/questionnaires/question",
64
+ form: question_form,
65
+ id: tabs_id_for_question(question),
66
+ editable: questionnaire.questions_editable?,
67
+ answer_option_template_selector: "#answer-option-template-#{index}",
68
+ matrix_row_template_selector: "#matrix-row-template-#{index}" %>
69
+ <%= render "decidim/forms/admin/questionnaires/answer_option_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "answer-option-template-#{index}" %>
70
+ <%= render "decidim/forms/admin/questionnaires/matrix_row_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "matrix-row-template-#{index}" %>
71
+ <% end %>
42
72
  <% end %>
43
73
  <% end %>
44
74
  </div>
45
75
 
46
76
  <% if questionnaire.questions_editable? %>
47
77
  <button class="button add-question"><%= t(".add_question") %></button>
78
+ <button class="button add-separator"><%= t(".add_separator") %></button>
48
79
  <% end %>
49
80
  </div>
50
81
 
51
82
  <% if questionnaire.questions_editable? %>
52
83
  <%= javascript_include_tag "decidim/forms/admin/forms" %>
53
84
  <% end %>
85
+
86
+ <%= javascript_include_tag "decidim/forms/admin/collapsible_questions" %>
@@ -0,0 +1,34 @@
1
+ <% matrix_row = form.object %>
2
+
3
+ <div class="card questionnaire-question-matrix-row">
4
+ <div class="card-divider">
5
+ <h2 class="card-title">
6
+ <span><%= t(".matrix_row") %></span>
7
+ <% if editable %>
8
+ <button class="button small alert hollow remove-matrix-row button--title">
9
+ <%= t(".remove") %>
10
+ </button>
11
+ <% end %>
12
+ </h2>
13
+ </div>
14
+
15
+ <div class="card-section">
16
+ <div class="row column">
17
+ <%=
18
+ form.translated(
19
+ :text_field,
20
+ :body,
21
+ tabs_id: tabs_id_for_question_matrix_row(question, matrix_row),
22
+ label: t(".statement"),
23
+ disabled: !editable
24
+ )
25
+ %>
26
+ </div>
27
+ </div>
28
+
29
+ <% if matrix_row.persisted? %>
30
+ <%= form.hidden_field :id, disabled: !editable %>
31
+ <% end %>
32
+
33
+ <%= form.hidden_field :deleted, disabled: !editable %>
34
+ </div>
@@ -0,0 +1,7 @@
1
+ <% question = form.object %>
2
+
3
+ <script type="text/template" class="decidim-matrix-row-template decidim-template" id="<%= template_id %>">
4
+ <%= fields_for "questionnaire[questions][#{question.to_param}][matrix_rows][]", blank_matrix_row do |matrix_row_form| %>
5
+ <%= render "decidim/forms/admin/questionnaires/matrix_row", form: matrix_row_form, question: question, editable: editable %>
6
+ <% end %>
7
+ </script>
@@ -5,12 +5,21 @@
5
5
  <h2 class="card-title">
6
6
  <span>
7
7
  <% if editable %>
8
- <%== "#{icon("move")} #{t(".question")}" %>
9
- <% else %>
10
- <%= t(".question") %>
8
+ <%== icon("move") %>
11
9
  <% end %>
10
+ <%= dynamic_title(translated_attribute(question.body), class: "question-title-statement", max_length: 50, omission: "...", placeholder: t(".question")) %>
12
11
  </span>
13
12
 
13
+ <button type="button" class="button small secondary button--title question--collapse" data-toggle="<%= id %>-question-card button--collapse-question-<%= id %> button--expand-question-<%= id %>">
14
+ <span id="button--collapse-question-<%= id %>" data-toggler=".hide" class="icon-collapse hide">
15
+ <%== icon("caret-top", aria_label: t(".collapse"), role: "img") %>
16
+ </span>
17
+
18
+ <span id="button--expand-question-<%= id %>" data-toggler=".hide" class="icon-expand">
19
+ <%== icon("caret-bottom", aria_label: t(".expand"), role: "img") %>
20
+ </span>
21
+ </button>
22
+
14
23
  <% if editable %>
15
24
  <button class="button small alert hollow move-up-question button--title">
16
25
  <%== "#{icon("arrow-top")} #{t(".up")}" %>
@@ -27,7 +36,7 @@
27
36
  </h2>
28
37
  </div>
29
38
 
30
- <div class="card-section">
39
+ <div class="card-section collapsible hide" data-toggler=".hide" id="<%= id %>-question-card">
31
40
  <div class="row column">
32
41
  <%=
33
42
  form.translated(
@@ -81,7 +90,21 @@
81
90
  <%= form.hidden_field :position, value: question.position || 0, disabled: !editable %>
82
91
  <%= form.hidden_field :deleted, disabled: !editable %>
83
92
 
84
- <div class="questionnaire-question-answer-options" data-template="<%= child_template_selector %>">
93
+ <div class="questionnaire-question-matrix-rows" data-template="<%= matrix_row_template_selector %>">
94
+ <div class="questionnaire-question-matrix-rows-list">
95
+ <% question.matrix_rows.each do |matrix_row| %>
96
+ <%= fields_for "questionnaire[questions][#{question.to_param}][matrix_rows][]", matrix_row do |matrix_row_form| %>
97
+ <%= render "decidim/forms/admin/questionnaires/matrix_row", form: matrix_row_form, question: question, editable: editable %>
98
+ <% end %>
99
+ <% end %>
100
+ </div>
101
+
102
+ <% if editable %>
103
+ <button class="button add-matrix-row"><%= t(".add_matrix_row") %></button>
104
+ <% end %>
105
+ </div>
106
+
107
+ <div class="questionnaire-question-answer-options" data-template="<%= answer_option_template_selector %>">
85
108
  <div class="questionnaire-question-answer-options-list">
86
109
  <% question.answer_options.each do |answer_option| %>
87
110
  <%= fields_for "questionnaire[questions][#{question.to_param}][answer_options][]", answer_option do |answer_option_form| %>
@@ -100,7 +123,7 @@
100
123
  form.select(
101
124
  :max_choices,
102
125
  (2..question.number_of_options),
103
- { prompt: t(".any") },
126
+ { include_blank: t(".any") },
104
127
  disabled: !editable
105
128
  )
106
129
  %>
@@ -0,0 +1,41 @@
1
+ <% question = form.object %>
2
+
3
+ <div class="card questionnaire-question" id="<%= id %>-field">
4
+ <div class="card-divider question-divider">
5
+ <h2 class="card-title">
6
+ <span>
7
+ <% if editable %>
8
+ <%== icon("move") %>
9
+ <% end %>
10
+ <%= dynamic_title(t(".separator"), class: "question-title-statement", max_length: 50, omission: "...", placeholder: t(".separator")) %>
11
+ </span>
12
+
13
+ <% if editable %>
14
+ <button class="button small alert hollow move-up-question button--title">
15
+ <%== "#{icon("arrow-top")} #{t(".up")}" %>
16
+ </button>
17
+
18
+ <button class="button small alert hollow move-down-question button--title">
19
+ <%== "#{icon("arrow-bottom")} #{t(".down")}" %>
20
+ </button>
21
+
22
+ <button class="button small alert hollow remove-question button--title">
23
+ <%= t(".remove") %>
24
+ </button>
25
+ <% end %>
26
+ </h2>
27
+
28
+ <%=
29
+ form.hidden_field(
30
+ :question_type,
31
+ value: :separator
32
+ )
33
+ %>
34
+ <% if question.persisted? %>
35
+ <%= form.hidden_field :id, disabled: !editable %>
36
+ <% end %>
37
+
38
+ <%= form.hidden_field :position, value: question.position || 0, disabled: !editable %>
39
+ <%= form.hidden_field :deleted, disabled: !editable %>
40
+ </div>
41
+ </div>
@@ -1,100 +1,29 @@
1
1
  <% field_id = "questionnaire_answers_#{answer_idx}" %>
2
- <%= label_tag field_id, answer.label(answer_idx), class: "questionnaire-question" %>
3
2
 
4
- <% if translated_attribute(answer.question.description).present? %>
5
- <div class="help-text">
6
- <%= decidim_sanitize translated_attribute(answer.question.description) %>
7
- </div>
8
- <% end %>
9
-
10
- <% case answer.question.question_type %>
11
- <% when "short_answer" %>
12
- <%= answer_form.text_field :body, label: false, id: field_id, disabled: disabled %>
13
- <% when "long_answer" %>
14
- <%= answer_form.text_area :body, label: false, id: field_id, rows: 10, disabled: disabled %>
15
- <% when "single_option" %>
16
- <div class="radio-button-collection">
17
- <% choice = answer.choices.first %>
18
-
19
- <% answer.question.answer_options.each_with_index do |answer_option, idx| %>
20
- <% choice_id = "#{field_id}_choices_#{idx}" %>
21
-
22
- <div class="collection-input">
23
- <%= label_tag "#{choice_id}_body" do %>
24
- <%= radio_button_tag "questionnaire[answers][#{answer_idx}][choices][][body]",
25
- translated_attribute(answer_option.body),
26
- answer_option.id == choice.try(:answer_option_id),
27
- id: "#{choice_id}_body", disabled: disabled %>
28
-
29
- <%= translated_attribute(answer_option.body) %>
30
-
31
- <%= hidden_field_tag "questionnaire[answers][#{answer_idx}][choices][][answer_option_id]",
32
- answer_option.id,
33
- id: "#{choice_id}_answer_option",
34
- disabled: true %>
35
- <% end %>
36
-
37
- <% if answer_option.free_text %>
38
- <%= text_field_tag "questionnaire[answers][#{answer_idx}][choices][][custom_body]",
39
- choice.try(:custom_body),
40
- id: "#{choice_id}_custom_body",
41
- disabled: true %>
42
- <% end %>
43
- </div>
44
- <% end %>
45
- </div>
46
- <% when "multiple_option" %>
47
- <div class="check-box-collection">
48
- <% answer.question.answer_options.each_with_index do |answer_option, idx| %>
49
- <% choice = answer.selected_choices.find { |choice| choice.answer_option_id == answer_option.id } %>
3
+ <% if answer.question.separator? %>
4
+ <%= render partial: "decidim/forms/questionnaires/answers/#{answer.question.question_type}", locals: { answer: answer, answer_form: answer_form, answer_idx: answer_idx, field_id: field_id, disabled: disabled } %>
5
+ <%= answer_form.hidden_field :question_id %>
6
+ <% else %>
7
+ <% case answer.question.question_type %>
8
+ <% when "single_option", "multiple_option", "sorting" %>
9
+ <label class="questionnaire-question"><%= answer.label(cleaned_answer_idx) %></label>
10
+ <% else %>
11
+ <%= label_tag field_id, answer.label(cleaned_answer_idx), class: "questionnaire-question" %>
12
+ <% end %>
50
13
 
51
- <div class="collection-input">
52
- <%= label_tag do %>
53
- <%= check_box_tag "questionnaire[answers][#{answer_idx}][choices][#{idx}][body]",
54
- translated_attribute(answer_option.body),
55
- choice.present?, disabled: disabled %>
14
+ <% if translated_attribute(answer.question.description).present? %>
15
+ <div class="help-text">
16
+ <%= decidim_sanitize translated_attribute(answer.question.description) %>
17
+ </div>
18
+ <% end %>
56
19
 
57
- <%= translated_attribute(answer_option.body) %>
20
+ <%= render partial: "decidim/forms/questionnaires/answers/#{answer.question.question_type}", locals: { answer: answer, answer_form: answer_form, answer_idx: answer_idx, field_id: field_id, disabled: disabled } %>
58
21
 
59
- <%= hidden_field_tag "questionnaire[answers][#{answer_idx}][choices][#{idx}][answer_option_id]", answer_option.id %>
60
- <% end %>
61
-
62
- <% if answer_option.free_text %>
63
- <%= text_field_tag "questionnaire[answers][#{answer_idx}][choices][#{idx}][custom_body]",
64
- choice.try(:custom_body),
65
- disabled: true %>
66
- <% end %>
67
- </div>
68
- <% end %>
69
- </div>
70
- <% when "sorting" %>
71
- <div class="sortable-check-box-collection">
72
- <% answer.question.answer_options.each_with_index do |answer_option, idx| %>
73
- <% choice = answer.selected_choices.find { |choice| choice.answer_option_id == answer_option.id } %>
74
-
75
- <div class="collection-input">
76
- <%= label_tag do %>
77
- <%= check_box_tag "questionnaire[answers][#{answer_idx}][choices][#{idx}][body]",
78
- translated_attribute(answer_option.body),
79
- choice.present?, disabled: disabled %>
80
-
81
- <span class="position"><%= choice.try(:position) %></span>
82
-
83
- <%= translated_attribute(answer_option.body) %>
84
-
85
- <%= hidden_field_tag "questionnaire[answers][#{answer_idx}][choices][#{idx}][position]",
86
- choice.try(:position),
87
- disabled: true %>
88
-
89
- <%= hidden_field_tag "questionnaire[answers][#{answer_idx}][choices][#{idx}][answer_option_id]", answer_option.id %>
90
- <% end %>
91
- </div>
92
- <% end %>
93
- </div>
94
- <% end %>
22
+ <%= answer_form.hidden_field :question_id %>
95
23
 
96
- <%= answer_form.hidden_field :question_id %>
24
+ <small class="form-error max-choices-alert"><%= t(".max_choices_alert") %></small>
97
25
 
98
- <% answer.errors.full_messages.each do |msg| %>
99
- <small class="form-error is-visible"><%= msg %></small>
26
+ <% answer.errors.full_messages.each do |msg| %>
27
+ <small class="form-error is-visible"><%= msg %></small>
28
+ <% end %>
100
29
  <% end %>