decidim-forms 0.29.6 → 0.30.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/forms/step_navigation_cell.rb +18 -5
  3. data/app/commands/decidim/forms/admin/update_questionnaire.rb +1 -82
  4. data/app/commands/decidim/forms/admin/update_questions.rb +109 -0
  5. data/app/commands/decidim/forms/answer_questionnaire.rb +10 -3
  6. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +39 -3
  7. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire_answers.rb +2 -2
  8. data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +12 -4
  9. data/app/forms/decidim/forms/admin/display_condition_form.rb +1 -1
  10. data/app/forms/decidim/forms/admin/questionnaire_form.rb +0 -9
  11. data/app/forms/decidim/forms/admin/questions_form.rb +18 -0
  12. data/app/forms/decidim/forms/answer_choice_form.rb +5 -0
  13. data/app/forms/decidim/forms/answer_form.rb +1 -0
  14. data/app/forms/decidim/forms/questionnaire_form.rb +7 -0
  15. data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_pagination_helper.rb +1 -1
  16. data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_url_helper.rb +5 -5
  17. data/app/jobs/decidim/forms/export_questionnaire_answers_job.rb +5 -1
  18. data/app/models/decidim/forms/answer_choice.rb +0 -2
  19. data/app/models/decidim/forms/answer_option.rb +1 -1
  20. data/app/models/decidim/forms/question.rb +10 -0
  21. data/app/packs/entrypoints/decidim_forms.js +0 -1
  22. data/app/packs/entrypoints/decidim_forms_admin.js +6 -0
  23. data/app/packs/src/decidim/forms/admin/publish_answers_buttons.js +72 -0
  24. data/app/packs/src/decidim/forms/forms.js +4 -25
  25. data/app/presenters/decidim/forms/admin/questionnaire_participant_presenter.rb +1 -1
  26. data/app/presenters/decidim/forms/admin_log/question_presenter.rb +31 -0
  27. data/app/queries/decidim/forms/questionnaire_user_answers.rb +1 -1
  28. data/app/views/decidim/forms/admin/questionnaires/_answer_option_template.html.erb +1 -1
  29. data/app/views/decidim/forms/admin/questionnaires/_display_condition_template.html.erb +1 -1
  30. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +0 -89
  31. data/app/views/decidim/forms/admin/questionnaires/_matrix_row_template.html.erb +1 -1
  32. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +14 -4
  33. data/app/views/decidim/forms/admin/questionnaires/_questions_form.html.erb +80 -0
  34. data/app/views/decidim/forms/admin/questionnaires/_separator.html.erb +10 -3
  35. data/app/views/decidim/forms/admin/questionnaires/_title_and_description.html.erb +11 -1
  36. data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +0 -20
  37. data/app/views/decidim/forms/admin/questionnaires/edit_questions.html.erb +47 -0
  38. data/app/views/decidim/forms/questionnaires/_answer.html.erb +1 -1
  39. data/app/views/decidim/forms/questionnaires/_questionnaire.html.erb +8 -1
  40. data/app/views/decidim/forms/questionnaires/answers/_files.html.erb +1 -1
  41. data/app/views/decidim/forms/questionnaires/answers/_long_answer.html.erb +1 -1
  42. data/app/views/decidim/forms/questionnaires/answers/_short_answer.html.erb +1 -1
  43. data/app/views/decidim/forms/questionnaires/answers/_sorting.html.erb +12 -6
  44. data/app/views/decidim/forms/questionnaires/edit.html.erb +47 -0
  45. data/app/views/decidim/forms/questionnaires/show.html.erb +13 -2
  46. data/config/assets.rb +1 -2
  47. data/config/locales/ar.yml +18 -1
  48. data/config/locales/bg.yml +42 -2
  49. data/config/locales/ca.yml +59 -13
  50. data/config/locales/cs.yml +54 -8
  51. data/config/locales/de.yml +56 -10
  52. data/config/locales/el.yml +41 -2
  53. data/config/locales/en.yml +51 -5
  54. data/config/locales/es-MX.yml +61 -15
  55. data/config/locales/es-PY.yml +61 -15
  56. data/config/locales/es.yml +60 -14
  57. data/config/locales/eu.yml +58 -12
  58. data/config/locales/fi-plain.yml +56 -10
  59. data/config/locales/fi.yml +56 -10
  60. data/config/locales/fr-CA.yml +51 -13
  61. data/config/locales/fr.yml +51 -13
  62. data/config/locales/ga-IE.yml +9 -0
  63. data/config/locales/gl.yml +11 -1
  64. data/config/locales/hu.yml +14 -1
  65. data/config/locales/id-ID.yml +9 -1
  66. data/config/locales/it.yml +31 -3
  67. data/config/locales/ja.yml +13 -12
  68. data/config/locales/lb.yml +32 -1
  69. data/config/locales/lt.yml +41 -2
  70. data/config/locales/lv.yml +15 -1
  71. data/config/locales/nl.yml +29 -0
  72. data/config/locales/no.yml +33 -0
  73. data/config/locales/pl.yml +43 -2
  74. data/config/locales/pt-BR.yml +35 -0
  75. data/config/locales/pt.yml +31 -0
  76. data/config/locales/ro-RO.yml +50 -17
  77. data/config/locales/ru.yml +3 -2
  78. data/config/locales/sk.yml +12 -1
  79. data/config/locales/sl.yml +7 -0
  80. data/config/locales/sv.yml +17 -15
  81. data/config/locales/tr-TR.yml +27 -0
  82. data/config/locales/val-ES.yml +2 -0
  83. data/config/locales/zh-CN.yml +27 -0
  84. data/config/locales/zh-TW.yml +41 -2
  85. data/db/migrate/20190315203056_add_session_token_to_decidim_forms_answers.rb +1 -1
  86. data/db/migrate/20241122142230_add_survey_answers_published_at_to_questions.rb +7 -0
  87. data/decidim-forms.gemspec +1 -2
  88. data/lib/decidim/api/answer_option_type.rb +1 -1
  89. data/lib/decidim/api/question_type.rb +4 -4
  90. data/lib/decidim/api/questionnaire_type.rb +4 -4
  91. data/lib/decidim/exporters/form_pdf.rb +114 -11
  92. data/lib/decidim/forms/download_your_data_user_answers_serializer.rb +0 -4
  93. data/lib/decidim/forms/test/factories.rb +2 -2
  94. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +46 -7
  95. data/lib/decidim/forms/test/shared_examples/manage_questionnaire_answers.rb +17 -17
  96. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +19 -21
  97. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +70 -94
  98. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_display_conditions.rb +15 -18
  99. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +115 -247
  100. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +3 -29
  101. data/lib/decidim/forms/version.rb +1 -1
  102. data/lib/decidim/forms.rb +0 -1
  103. metadata +18 -33
  104. data/app/packs/entrypoints/decidim_questionnaire_answers_pdf.js +0 -1
  105. data/app/packs/entrypoints/decidim_questionnaire_answers_pdf.scss +0 -1
  106. data/app/packs/stylesheets/decidim/forms/questionnaire-answers-pdf.scss +0 -69
  107. data/app/views/decidim/forms/admin/questionnaires/answers/export/_answer.html.erb +0 -31
  108. data/app/views/decidim/forms/admin/questionnaires/answers/export/pdf.html.erb +0 -13
  109. data/app/views/layouts/decidim/forms/admin/questionnaires/questionnaire_answers.html.erb +0 -12
  110. data/config/initializers/wicked_pdf.rb +0 -26
  111. data/config/locales/ca-IT.yml +0 -192
  112. data/lib/decidim/exporters/form_pdf_controller_helper.rb +0 -13
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Initializes event listeners for a button to toggle the publication status of question answers.
3
+ *
4
+ * The button's `data-publish-question-answer-action` attribute determines whether the action is
5
+ * to "publish" or "unpublish." Based on this attribute, the function makes an AJAX request using
6
+ * Rails' AJAX helper and updates the button's state and associated labels.
7
+ *
8
+ * @param {HTMLButtonElement} button - The button element that triggers the publication toggle action.
9
+ *
10
+ * @returns {void}
11
+ *
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.
15
+ *
16
+ * The DOM structure must include:
17
+ * - A parent element with the class `toggle__switch-toggle`.
18
+ * - A child element with the class `toggle__switch-trigger-text`.
19
+ * - Two labels within `toggle__switch-trigger-text`:
20
+ * - One with the class `label success` to indicate the "published" state.
21
+ * - One with the class `label success` to indicate the "unpublished" state.
22
+ *
23
+ * Example usage:
24
+ * ```html
25
+ * <label class="toggle__switch-toggle">
26
+ * <span class="toggle__switch-trigger-text">
27
+ * <span class="label success">Published</span>
28
+ * <span class="label alert hidden">Unpublished</span>
29
+ * <span>
30
+ * <input
31
+ * data-publish-question-answer-action="unpublish"
32
+ * data-publish-question-answer-question-url="/path/to/publish/or/unpublish">
33
+ * </span>
34
+ * </label>
35
+ * ```
36
+ */
37
+ export default function createPublicableQuestionAnswersButtons(button) {
38
+ button.addEventListener("click", () => {
39
+ const action = button.dataset.publishQuestionAnswerAction;
40
+ const url = button.dataset.publishQuestionAnswerQuestionUrl;
41
+ const buttonText = button.closest(".toggle__switch-toggle").querySelector(".toggle__switch-trigger-text");
42
+ const publishedLabel = buttonText.querySelector(".label.success");
43
+ const unpublishedLabel = buttonText.querySelector(".label.alert");
44
+
45
+ switch (action) {
46
+ case "publish":
47
+ Rails.ajax({
48
+ url: url,
49
+ type: "PUT",
50
+ success: function() {
51
+ button.setAttribute("data-publish-question-answer-action", "unpublish")
52
+ publishedLabel.classList.remove("hidden");
53
+ unpublishedLabel.classList.add("hidden");
54
+ }
55
+ });
56
+ break;
57
+ case "unpublish":
58
+ Rails.ajax({
59
+ url: url,
60
+ type: "DELETE",
61
+ success: function() {
62
+ button.setAttribute("data-publish-question-answer-action", "publish")
63
+ unpublishedLabel.classList.remove("hidden");
64
+ publishedLabel.classList.add("hidden");
65
+ }
66
+ });
67
+ break;
68
+ default:
69
+ console.log(`Publish questions answers: Unknown action ${action}`);
70
+ }
71
+ });
72
+ }
@@ -35,31 +35,10 @@ $(() => {
35
35
  }
36
36
  });
37
37
 
38
- document.querySelectorAll(".js-sortable-check-box-collection").forEach((el) => {
39
-
40
- /**
41
- * Due to a bug reported in https://github.com/decidim/decidim/issues/15191
42
- * we have to listen to the `drag` event and prevent the scrolling
43
- * and enabling it back again after it.
44
- */
45
-
46
- let preventScroll = function(event) {
47
- event.preventDefault();
48
- }
49
-
50
- el.addEventListener("touchmove", (event) => {
51
- preventScroll(event);
52
- }, { passive: false });
53
-
54
- el.addEventListener("touchend", () => {
55
- el.removeEventListener("touchmove", preventScroll)
56
- });
57
-
58
- return new DragonDrop(el, {
59
- handle: false,
60
- item: ".js-collection-input"
61
- });
62
- });
38
+ document.querySelectorAll(".js-sortable-check-box-collection").forEach((el) => new DragonDrop(el, {
39
+ handle: false,
40
+ item: ".js-collection-input"
41
+ }));
63
42
 
64
43
  $(".answer-questionnaire .question[data-conditioned='true']").each((idx, el) => {
65
44
  createDisplayConditions({
@@ -45,7 +45,7 @@ module Decidim
45
45
  def completion
46
46
  with_body = siblings.where(decidim_forms_questions: { question_type: %w(short_answer long_answer) })
47
47
  .where.not(body: "").count
48
- with_choices = siblings.where.not("decidim_forms_questions.question_type in (?)", %w(short_answer long_answer))
48
+ with_choices = siblings.where.not(decidim_forms_questions: { question_type: %w(short_answer long_answer) })
49
49
  .where("decidim_forms_answers.id IN (SELECT decidim_answer_id FROM decidim_forms_answer_choices)").count
50
50
 
51
51
  (with_body + with_choices).to_f / questionnaire.questions.not_separator.not_title_and_description.count * 100
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Forms
5
+ module AdminLog
6
+ # This class holds the logic to present a `Decidim::Forms::Question`
7
+ # for the `AdminLog` log.
8
+ #
9
+ # Usage should be automatic and you should not need to call this class
10
+ # directly, but here is an example:
11
+ #
12
+ # action_log = Decidim::ActionLog.last
13
+ # view_helpers # => this comes from the views
14
+ # QuestionPresenter.new(action_log, view_helpers).present
15
+ class QuestionPresenter < Decidim::Log::BasePresenter
16
+ private
17
+
18
+ # i18n-tasks-use t("decidim.forms.admin_log.question.publish_answers")
19
+ # i18n-tasks-use t("decidim.forms.admin_log.question.unpublish_answers")
20
+ def action_string
21
+ case action
22
+ when "publish_answers", "unpublish_answers"
23
+ "decidim.forms.admin_log.question.#{action}"
24
+ else
25
+ super
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -25,7 +25,7 @@ module Decidim
25
25
  .joins(:question)
26
26
  .where(questionnaire: @questionnaire)
27
27
 
28
- answers.sort_by { |answer| answer.question.position }.group_by { |a| a.user || a.session_token }.values
28
+ answers.sort_by { |answer| answer.question.position.to_i }.group_by { |a| a.user || a.session_token }.values
29
29
  end
30
30
  end
31
31
  end
@@ -1,7 +1,7 @@
1
1
  <% question = form.object %>
2
2
 
3
3
  <script type="text/template" class="decidim-answer-option-template decidim-template" id="<%= template_id %>">
4
- <%= fields_for "questionnaire[questions][#{question.to_param}][answer_options][]", blank_answer_option do |answer_option_form| %>
4
+ <%= fields_for "questions[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:, editable: %>
6
6
  <% end %>
7
7
  </script>
@@ -1,7 +1,7 @@
1
1
  <% question = form.object %>
2
2
 
3
3
  <script type="text/template" class="decidim-template" id="<%= template_id %>">
4
- <%= fields_for "questionnaire[questions][#{question.to_param}][display_conditions][]", blank_display_condition do |display_condition_form| %>
4
+ <%= fields_for "questions[questions][#{question.to_param}][display_conditions][]", blank_display_condition do |display_condition_form| %>
5
5
  <%= render "decidim/forms/admin/questionnaires/display_condition", form: display_condition_form, question:, editable: %>
6
6
  <% end %>
7
7
  </script>
@@ -13,92 +13,3 @@
13
13
  </div>
14
14
  </div>
15
15
  </div>
16
-
17
- <div class="questionnaire-questions form__wrapper">
18
- <div class="row column text-center my-4">
19
- <button type="button" class="button button__sm button__secondary collapse-all"><%= t(".collapse") %></button>
20
- <button type="button" class="button button__sm button__secondary expand-all"><%= t(".expand") %></button>
21
- </div>
22
-
23
- <% if questionnaire.questions_editable? %>
24
- <% if questionnaire.answers.any? && !questionnaire.published? %>
25
- <%= cell("decidim/announcement", t(".unpublished_warning"), callout_class: "warning" ) %>
26
- <% end %>
27
-
28
- <%= fields_for "questionnaire[questions][#{blank_question.to_param}]", blank_question do |question_form| %>
29
- <script type="text/template" class="decidim-question-template decidim-template" id="question-template">
30
- <%= render "decidim/forms/admin/questionnaires/question",
31
- form: question_form,
32
- id: tabs_id_for_question(blank_question),
33
- editable: questionnaire.questions_editable?,
34
- answer_option_template_selector: "#answer-option-template-dummy",
35
- display_condition_template_selector: "#display-condition-template-dummy",
36
- matrix_row_template_selector: "#matrix-row-template-dummy" %>
37
- </script>
38
- <script type="text/template" class="decidim-separator-template decidim-template" id="separator-template">
39
- <%= render "decidim/forms/admin/questionnaires/separator",
40
- form: question_form,
41
- id: tabs_id_for_question(blank_question),
42
- editable: questionnaire.questions_editable? %>
43
- </script>
44
- <script type="text/template" class="decidim-title-and-description-template decidim-template" id="title-and-description-template">
45
- <%= render "decidim/forms/admin/questionnaires/title_and_description",
46
- form: question_form,
47
- id: tabs_id_for_question(blank_question),
48
- editable: questionnaire.questions_editable? %>
49
- </script>
50
- <%= render "decidim/forms/admin/questionnaires/answer_option_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "answer-option-template-dummy" %>
51
- <%= render "decidim/forms/admin/questionnaires/display_condition_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "display-condition-template-dummy" %>
52
- <%= render "decidim/forms/admin/questionnaires/matrix_row_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "matrix-row-template-dummy" %>
53
- <% end %>
54
- <% else %>
55
- <%= cell("decidim/announcement", t(".already_answered_warning"), callout_class: "warning" ) %>
56
- <% end %>
57
-
58
- <div class="questionnaire-questions-list flex flex-col py-6 gap-6 last:pb-0">
59
- <% @form.questions.each_with_index do |question, index| %>
60
- <%= fields_for "questionnaire[questions][]", question do |question_form| %>
61
- <% if question.separator? %>
62
- <%= render "decidim/forms/admin/questionnaires/separator",
63
- form: question_form,
64
- id: tabs_id_for_question(question),
65
- editable: questionnaire.questions_editable? %>
66
- <% elsif question.title_and_description? %>
67
- <%= render "decidim/forms/admin/questionnaires/title_and_description",
68
- form: question_form,
69
- id: tabs_id_for_question(question),
70
- editable: questionnaire.questions_editable? %>
71
- <% else %>
72
- <%= render "decidim/forms/admin/questionnaires/question",
73
- form: question_form,
74
- id: tabs_id_for_question(question),
75
- editable: questionnaire.questions_editable?,
76
- display_condition_template_selector: "#display-condition-template-#{index}",
77
- answer_option_template_selector: "#answer-option-template-#{index}",
78
- matrix_row_template_selector: "#matrix-row-template-#{index}" %>
79
- <%= render "decidim/forms/admin/questionnaires/display_condition_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "display-condition-template-#{index}" %>
80
- <%= render "decidim/forms/admin/questionnaires/answer_option_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "answer-option-template-#{index}" %>
81
- <%= render "decidim/forms/admin/questionnaires/matrix_row_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "matrix-row-template-#{index}" %>
82
- <% end %>
83
- <% end %>
84
- <% end %>
85
- </div>
86
-
87
- <% if questionnaire.questions_editable? %>
88
- <div class="mt-4">
89
- <button class="button button__sm button__secondary add-question"><%= t(".add_question") %></button>
90
- <button class="button button__sm button__secondary add-separator"><%= t(".add_separator") %></button>
91
- <button class="button button__sm button__secondary add-title-and-description"><%= t(".add_title_and_description") %></button>
92
- </div>
93
- <% end %>
94
- </div>
95
-
96
- <%= append_javascript_pack_tag "decidim_forms_admin" %>
97
-
98
- <% if questionnaire.questions_editable? %>
99
- <script>
100
- document.addEventListener("DOMContentLoaded", function () {
101
- window.Decidim.createEditableForm();
102
- });
103
- </script>
104
- <% end %>
@@ -1,7 +1,7 @@
1
1
  <% question = form.object %>
2
2
 
3
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| %>
4
+ <%= fields_for "questions[questions][#{question.to_param}][matrix_rows][]", blank_matrix_row do |matrix_row_form| %>
5
5
  <%= render "decidim/forms/admin/questionnaires/matrix_row", form: matrix_row_form, question:, editable: %>
6
6
  <% end %>
7
7
  </script>
@@ -23,7 +23,17 @@
23
23
  </button>
24
24
 
25
25
  <% if editable %>
26
- <button class="button button__xs button__transparent-secondary small alert remove-question button--title">
26
+ <button class="button button__sm button__transparent-secondary small alert move-up-question button--title">
27
+ <%= icon("arrow-up-line") %>
28
+ <%= t(".up") %>
29
+ </button>
30
+
31
+ <button class="button button__sm button__transparent-secondary small alert move-down-question button--title">
32
+ <%= icon("arrow-down-line") %>
33
+ <%= t(".down") %>
34
+ </button>
35
+
36
+ <button class="button button__sm button__transparent-secondary small alert remove-question button--title">
27
37
  <%= icon("delete-bin-line") %>
28
38
  <%= t(".remove") %>
29
39
  </button>
@@ -101,7 +111,7 @@
101
111
  <div class="questionnaire-question-matrix-rows" data-template="<%= matrix_row_template_selector %>">
102
112
  <div class="questionnaire-question-matrix-rows-list">
103
113
  <% question.matrix_rows_by_position.each do |matrix_row| %>
104
- <%= fields_for "questionnaire[questions][#{question.to_param}][matrix_rows][]", matrix_row do |matrix_row_form| %>
114
+ <%= fields_for "questions[questions][#{question.to_param}][matrix_rows][]", matrix_row do |matrix_row_form| %>
105
115
  <%= render "decidim/forms/admin/questionnaires/matrix_row", form: matrix_row_form, question:, editable: %>
106
116
  <% end %>
107
117
  <% end %>
@@ -116,7 +126,7 @@
116
126
  <div class="questionnaire-question-answer-options" data-template="<%= answer_option_template_selector %>">
117
127
  <div class="questionnaire-question-answer-options-list">
118
128
  <% question.answer_options.each do |answer_option| %>
119
- <%= fields_for "questionnaire[questions][#{question.to_param}][answer_options][]", answer_option do |answer_option_form| %>
129
+ <%= fields_for "questions[questions][#{question.to_param}][answer_options][]", answer_option do |answer_option_form| %>
120
130
  <%= render "decidim/forms/admin/questionnaires/answer_option", form: answer_option_form, question:, editable: %>
121
131
  <% end %>
122
132
  <% end %>
@@ -143,7 +153,7 @@
143
153
  <div class="questionnaire-question-display-conditions" data-template="<%= display_condition_template_selector %>">
144
154
  <div class="questionnaire-question-display-conditions-list">
145
155
  <% question.display_conditions.each do |display_condition| %>
146
- <%= fields_for "questionnaire[questions][#{question.to_param}][display_conditions][]", display_condition do |display_condition_form| %>
156
+ <%= fields_for "questions[questions][#{question.to_param}][display_conditions][]", display_condition do |display_condition_form| %>
147
157
  <%= render "decidim/forms/admin/questionnaires/display_condition", form: display_condition_form, question:, editable: %>
148
158
  <% end %>
149
159
  <% end %>
@@ -0,0 +1,80 @@
1
+ <div class="questionnaire-questions form__wrapper">
2
+ <div class="row column text-center my-4">
3
+ <button type="button" class="button button__sm button__secondary collapse-all"><%= t(".collapse") %></button>
4
+ <button type="button" class="button button__sm button__secondary expand-all"><%= t(".expand") %></button>
5
+ </div>
6
+
7
+ <% if questionnaire.questions_editable? %>
8
+ <% if questionnaire.answers.any? && !questionnaire.published? %>
9
+ <%= cell("decidim/announcement", t(".unpublished_warning"), callout_class: "warning" ) %>
10
+ <% end %>
11
+
12
+ <%= fields_for "questions[questions][#{blank_question.to_param}]", blank_question do |question_form| %>
13
+ <script type="text/template" class="decidim-question-template decidim-template" id="question-template">
14
+ <%= render "decidim/forms/admin/questionnaires/question",
15
+ form: question_form,
16
+ id: tabs_id_for_question(blank_question),
17
+ editable: questionnaire.questions_editable?,
18
+ answer_option_template_selector: "#answer-option-template-dummy",
19
+ display_condition_template_selector: "#display-condition-template-dummy",
20
+ matrix_row_template_selector: "#matrix-row-template-dummy" %>
21
+ </script>
22
+ <script type="text/template" class="decidim-separator-template decidim-template" id="separator-template">
23
+ <%= render "decidim/forms/admin/questionnaires/separator",
24
+ form: question_form,
25
+ id: tabs_id_for_question(blank_question),
26
+ editable: questionnaire.questions_editable? %>
27
+ </script>
28
+ <script type="text/template" class="decidim-title-and-description-template decidim-template" id="title-and-description-template">
29
+ <%= render "decidim/forms/admin/questionnaires/title_and_description",
30
+ form: question_form,
31
+ id: tabs_id_for_question(blank_question),
32
+ editable: questionnaire.questions_editable? %>
33
+ </script>
34
+ <%= render "decidim/forms/admin/questionnaires/answer_option_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "answer-option-template-dummy" %>
35
+ <%= render "decidim/forms/admin/questionnaires/display_condition_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "display-condition-template-dummy" %>
36
+ <%= render "decidim/forms/admin/questionnaires/matrix_row_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "matrix-row-template-dummy" %>
37
+ <% end %>
38
+ <% else %>
39
+ <%= cell("decidim/announcement", t(".already_answered_warning"), callout_class: "warning" ) %>
40
+ <% end %>
41
+
42
+ <div class="questionnaire-questions-list flex flex-col py-6 gap-6 last:pb-0">
43
+ <% @form.questions.each_with_index do |question, index| %>
44
+ <%= fields_for "questions[questions][]", question do |question_form| %>
45
+ <% if question.separator? %>
46
+ <%= render "decidim/forms/admin/questionnaires/separator",
47
+ form: question_form,
48
+ id: tabs_id_for_question(question),
49
+ editable: questionnaire.questions_editable? %>
50
+ <% elsif question.title_and_description? %>
51
+ <%= render "decidim/forms/admin/questionnaires/title_and_description",
52
+ form: question_form,
53
+ id: tabs_id_for_question(question),
54
+ editable: questionnaire.questions_editable? %>
55
+ <% else %>
56
+ <%= render "decidim/forms/admin/questionnaires/question",
57
+ form: question_form,
58
+ id: tabs_id_for_question(question),
59
+ editable: questionnaire.questions_editable?,
60
+ display_condition_template_selector: "#display-condition-template-#{index}",
61
+ answer_option_template_selector: "#answer-option-template-#{index}",
62
+ matrix_row_template_selector: "#matrix-row-template-#{index}" %>
63
+ <%= render "decidim/forms/admin/questionnaires/display_condition_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "display-condition-template-#{index}" %>
64
+ <%= render "decidim/forms/admin/questionnaires/answer_option_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "answer-option-template-#{index}" %>
65
+ <%= render "decidim/forms/admin/questionnaires/matrix_row_template", form: question_form, editable: questionnaire.questions_editable?, template_id: "matrix-row-template-#{index}" %>
66
+ <% end %>
67
+ <% end %>
68
+ <% end %>
69
+ </div>
70
+ </div>
71
+
72
+ <%= append_javascript_pack_tag "decidim_forms_admin" %>
73
+
74
+ <% if questionnaire.questions_editable? %>
75
+ <script>
76
+ document.addEventListener("DOMContentLoaded", function () {
77
+ window.Decidim.createEditableForm();
78
+ });
79
+ </script>
80
+ <% end %>
@@ -12,9 +12,16 @@
12
12
 
13
13
  <div class="flex items-center gap-x-4 ml-auto">
14
14
  <% if editable %>
15
- <button class="button button__xs button__transparent button__transparent-secondary small alert remove-question button--title">
16
- <%= icon("delete-bin-line") %>
17
- <span class="hidden md:block"><%= t(".remove") %></span>
15
+ <button class="button button__sm button__transparent button__transparent-secondary small alert move-up-question button--title">
16
+ <%== "#{icon("arrow-up-line")} #{t(".up")}" %>
17
+ </button>
18
+
19
+ <button class="button button__sm button__transparent button__transparent-secondary small alert move-down-question button--title">
20
+ <%== "#{icon("arrow-down-line")} #{t(".down")}" %>
21
+ </button>
22
+
23
+ <button class="button button__sm button__transparent button__transparent-secondary small alert remove-question button--title">
24
+ <%= t(".remove") %>
18
25
  </button>
19
26
  <% end %>
20
27
  </div>
@@ -23,7 +23,17 @@
23
23
  </button>
24
24
 
25
25
  <% if editable %>
26
- <button class="button button__xs button__transparent button__transparent-secondary small alert remove-question button--title">
26
+ <button class="button button__sm button__transparent button__transparent-secondary small alert move-up-question button--title">
27
+ <%= icon("arrow-up-line") %>
28
+ <%= t(".up") %>
29
+ </button>
30
+
31
+ <button class="button button__sm button__transparent button__transparent-secondary small alert move-down-question button--title">
32
+ <%= icon("arrow-down-line") %>
33
+ <%= t(".down") %>
34
+ </button>
35
+
36
+ <button class="button button__sm button__transparent button__transparent-secondary small alert remove-question button--title">
27
37
  <%= icon("delete-bin-line") %>
28
38
  <%= t(".remove") %>
29
39
  </button>
@@ -4,26 +4,6 @@
4
4
  <%= render partial: "decidim/templates/admin/questionnaire_templates/choose", locals: { target: questionnaire, form_title: t("decidim.forms.admin.questionnaires.edit.title") } %>
5
5
  <% else %>
6
6
 
7
- <div class="item_show__header">
8
- <h1 class="item_show__header-title">
9
- <%= edit_questionnaire_title %>
10
-
11
- <% unless template? questionnaire.questionnaire_for %>
12
- <% if allowed_to? :preview, :questionnaire %>
13
- <%= link_to t("preview", scope: "decidim.forms.admin.questionnaires.form"), public_url, class: "button button__sm button__secondary", target: :_blank, data: { "external-link": false } %>
14
- <% end %>
15
- <% if questionnaire.answers.any? %>
16
- <%= export_dropdown(current_component, questionnaire.id) if allowed_to? :export_answers, :questionnaire %>
17
- <% if allowed_to? :show, :questionnaire_answers %>
18
- <%= link_to t("actions.show", scope: "decidim.forms.admin.questionnaires"), questionnaire_participants_url, class: "button button__sm button__secondary new whitespace-nowrap" %>
19
- <% end %>
20
- <% else %>
21
- <button class="button button__sm button__secondary whitespace-nowrap" disabled><%= t("empty", scope: "decidim.forms.admin.questionnaires.answers") %></button>
22
- <% end %>
23
- <% end %>
24
- </h1>
25
- </div>
26
-
27
7
  <div class="item__edit item__edit-1col">
28
8
  <div class="item__edit-form">
29
9
  <%= decidim_form_for(@form, url: update_url, method: :put, html: { class: "form-defaults form edit_questionnaire" }) do |form| %>
@@ -0,0 +1,47 @@
1
+ <% add_decidim_page_title(t("decidim.forms.admin.questionnaires.edit.title")) %>
2
+
3
+ <% if templates_defined? && choose_template? %>
4
+ <%= render partial: "decidim/templates/admin/questionnaire_templates/choose", locals: { target: questionnaire, form_title: t("decidim.forms.admin.questionnaires.edit.title") } %>
5
+ <% else %>
6
+
7
+ <div class="questionnaire-questions">
8
+ <div class="item_show__header">
9
+ <h1 class="item_show__header-title">
10
+ <%= t("decidim.forms.admin.questionnaires.edit_questions.title") %>
11
+
12
+ <% unless template? questionnaire.questionnaire_for %>
13
+ <% if questionnaire.questions_editable? %>
14
+ <button class="button button__sm button__secondary add-question"><%= t(".add_question") %></button>
15
+ <button class="button button__sm button__secondary add-separator"><%= t(".add_separator") %></button>
16
+ <button class="button button__sm button__secondary add-title-and-description"><%= t(".add_title_and_description") %></button>
17
+ <% end %>
18
+ <% if allowed_to? :preview, :questionnaire %>
19
+ <%= link_to t("preview", scope: "decidim.forms.admin.questionnaires.form"), public_url, class: "button button__sm button__transparent-secondary", target: :_blank, data: { "external-link": false } %>
20
+ <% end %>
21
+ <% if questionnaire.answers.any? %>
22
+ <%= export_dropdown(current_component, questionnaire.id) if allowed_to? :export_answers, :questionnaire %>
23
+ <% if allowed_to? :show, :questionnaire_answers %>
24
+ <%= link_to t("actions.show", scope: "decidim.forms.admin.questionnaires"), questionnaire_participants_url, class: "button button__sm button__secondary new whitespace-nowrap" %>
25
+ <% end %>
26
+ <% else %>
27
+ <button class="button button__sm button__secondary whitespace-nowrap" disabled><%= t("empty", scope: "decidim.forms.admin.questionnaires.answers") %></button>
28
+ <% end %>
29
+ <% end %>
30
+ </h1>
31
+ </div>
32
+ </div>
33
+
34
+ <div class="item__edit item__edit-1col">
35
+ <div class="item__edit-form">
36
+ <%= decidim_form_for(@form, url: update_url, method: :put, html: { class: "form-defaults form edit_questionnaire" }) do |form| %>
37
+ <%= render partial: "decidim/forms/admin/questionnaires/questions_form", object: form %>
38
+ <div class="item__edit-sticky">
39
+ <div class="item__edit-sticky-container">
40
+ <%= form.submit t(".save"), class: "button button__sm button__secondary" %>
41
+ </div>
42
+ </div>
43
+ <% end %>
44
+ </div>
45
+ </div>
46
+
47
+ <% end %>
@@ -50,7 +50,7 @@
50
50
  <small class="form-error max-choices-alert"><%= t(".max_choices_alert") %></small>
51
51
  <% end %>
52
52
 
53
- <% %w(short_answer long_answer).exclude?(answer&.question&.question_type) && answer.errors.full_messages.each do |msg| %>
53
+ <% answer.errors.full_messages.each do |msg| %>
54
54
  <small class="form-error is-visible"><%= msg %></small>
55
55
  <% end %>
56
56
 
@@ -6,9 +6,15 @@
6
6
  <%= cell("decidim/announcement", { title: t("decidim.forms.questionnaires.show.questionnaire_for_private_users.title"), body: t("decidim.forms.questionnaires.show.questionnaire_for_private_users.body") }, callout_class: "alert") %>
7
7
  <% end %>
8
8
 
9
+ <% if questionnaire_for.respond_to?(:announcement) and questionnaire_for.announcement.present? %>
10
+ <%= cell("decidim/announcement", translated_attribute(questionnaire_for.announcement), callout_class: "warning") %>
11
+ <% end %>
12
+
9
13
  <%= decidim_form_for(@form, url: update_url, method: :post, html: { multipart: true, class: "form answer-questionnaire" }, data: { "safe-path" => form_path }) do |form| %>
10
14
  <%= form_required_explanation %>
11
15
 
16
+ <%= form.hidden_field :allow_editing_answers %>
17
+
12
18
  <%= invisible_captcha %>
13
19
  <% answer_idx = 0 %>
14
20
  <% cleaned_answer_idx = 1 %>
@@ -70,7 +76,8 @@
70
76
  step_index,
71
77
  total_steps: @form.total_steps,
72
78
  button_disabled: !current_participatory_space.can_participate?(current_user),
73
- form:
79
+ form:,
80
+ allow_editing_answers: questionnaire_for.try(:allow_editing_answers?)
74
81
  ) %>
75
82
  </div>
76
83
  </div>
@@ -1 +1 @@
1
- <%= answer_form.upload :add_documents, label: false, multiple: true, id: field_id, disabled:, button_class: "button button__lg button__transparent-secondary w-full" %>
1
+ <%= answer_form.upload :add_documents, attachments: answer.documents, label: false, multiple: true, id: field_id, disabled:, button_class: "button button__lg button__transparent-secondary w-full" %>
@@ -1,3 +1,3 @@
1
1
  <div>
2
- <%= answer_form.text_area :body, label: false, id: field_id, rows: 10, disabled:, maxlength:, class: "w-full", required: false %>
2
+ <%= answer_form.text_area :body, label: false, id: field_id, rows: 10, disabled:, maxlength:, class: "w-full" %>
3
3
  </div>
@@ -1,3 +1,3 @@
1
1
  <div>
2
- <%= answer_form.text_field :body, label: false, id: field_id, disabled:, maxlength:, class: "w-full", required: false %>
2
+ <%= answer_form.text_field :body, label: false, id: field_id, disabled:, maxlength:, class: "w-full" %>
3
3
  </div>
@@ -1,13 +1,19 @@
1
1
  <div class="answer-questionnaire__sorting-container js-sortable-check-box-collection">
2
- <% answer.question.answer_options.each_with_index do |answer_option, idx| %>
3
- <% choice = answer.selected_choices.find { |choice| choice.answer_option_id == answer_option.id } %>
2
+ <%
3
+ # This is a block that aims to identify the order to the answer questions, and if there is an user answer, use that
4
+ # to order the date that needs to be displayed. It is done like this to help with edit user answer form
5
+ %>
6
+ <% ordering = answer.question.answer_options.pluck(:id) %>
7
+ <% if answer.selected_choices.present? %>
8
+ <% ordering = answer.selected_choices.map(&:answer_option_id) %>
9
+ <% end %>
4
10
 
5
- <div class="answer-questionnaire__sorting js-collection-input" role="button">
11
+ <% ids_for_order = ordering.map.with_index { |id, index| "#{id}=#{index + 1}" }.join(", ") %>
6
12
 
7
- <%#= check_box_tag "questionnaire[responses][#{answer_idx}][choices][#{idx}][body]",
8
- translated_attribute(answer_option.body),
9
- choice.present?, disabled: disabled %>
13
+ <% answer.question.reload.answer_options.reorder(Arel.sql("POSITION(id::text in '#{ids_for_order}')")).each_with_index do |answer_option, idx| %>
14
+ <% choice = answer.selected_choices.find { |choice| choice.answer_option_id == answer_option.id } %>
10
15
 
16
+ <div class="answer-questionnaire__sorting js-collection-input" role="button">
11
17
  <%= translated_attribute(answer_option.body) %>
12
18
 
13
19
  <%= icon "drag-move-2-line" %>