decidim-forms 0.29.2 → 0.30.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) 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 +22 -18
  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 +3 -3
  33. data/app/views/decidim/forms/admin/questionnaires/_questions_form.html.erb +80 -0
  34. data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +0 -20
  35. data/app/views/decidim/forms/admin/questionnaires/edit_questions.html.erb +47 -0
  36. data/app/views/decidim/forms/questionnaires/_questionnaire.html.erb +8 -1
  37. data/app/views/decidim/forms/questionnaires/answers/_files.html.erb +1 -1
  38. data/app/views/decidim/forms/questionnaires/answers/_sorting.html.erb +12 -6
  39. data/app/views/decidim/forms/questionnaires/edit.html.erb +47 -0
  40. data/app/views/decidim/forms/questionnaires/show.html.erb +13 -2
  41. data/config/assets.rb +1 -2
  42. data/config/locales/bg.yml +0 -2
  43. data/config/locales/ca.yml +46 -6
  44. data/config/locales/cs.yml +45 -5
  45. data/config/locales/de.yml +45 -5
  46. data/config/locales/el.yml +0 -2
  47. data/config/locales/en.yml +45 -5
  48. data/config/locales/es-MX.yml +45 -5
  49. data/config/locales/es-PY.yml +45 -5
  50. data/config/locales/es.yml +45 -5
  51. data/config/locales/eu.yml +45 -5
  52. data/config/locales/fi-plain.yml +45 -5
  53. data/config/locales/fi.yml +45 -5
  54. data/config/locales/fr-CA.yml +37 -5
  55. data/config/locales/fr.yml +37 -5
  56. data/config/locales/ja.yml +1 -1
  57. data/config/locales/lt.yml +0 -2
  58. data/config/locales/pl.yml +0 -2
  59. data/config/locales/ro-RO.yml +8 -3
  60. data/config/locales/zh-TW.yml +0 -2
  61. data/db/migrate/20190315203056_add_session_token_to_decidim_forms_answers.rb +1 -1
  62. data/db/migrate/20241122142230_add_survey_answers_published_at_to_questions.rb +7 -0
  63. data/decidim-forms.gemspec +1 -2
  64. data/lib/decidim/api/answer_option_type.rb +1 -1
  65. data/lib/decidim/api/question_type.rb +4 -4
  66. data/lib/decidim/api/questionnaire_type.rb +4 -4
  67. data/lib/decidim/exporters/form_pdf.rb +114 -11
  68. data/lib/decidim/forms/download_your_data_user_answers_serializer.rb +0 -4
  69. data/lib/decidim/forms/test/factories.rb +2 -2
  70. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +44 -4
  71. data/lib/decidim/forms/test/shared_examples/manage_questionnaire_answers.rb +17 -17
  72. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +19 -21
  73. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +70 -94
  74. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_display_conditions.rb +15 -18
  75. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +90 -125
  76. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +4 -25
  77. data/lib/decidim/forms/version.rb +1 -1
  78. data/lib/decidim/forms.rb +0 -1
  79. metadata +18 -32
  80. data/app/packs/entrypoints/decidim_questionnaire_answers_pdf.js +0 -1
  81. data/app/packs/entrypoints/decidim_questionnaire_answers_pdf.scss +0 -1
  82. data/app/packs/stylesheets/decidim/forms/questionnaire-answers-pdf.scss +0 -69
  83. data/app/views/decidim/forms/admin/questionnaires/answers/export/_answer.html.erb +0 -31
  84. data/app/views/decidim/forms/admin/questionnaires/answers/export/pdf.html.erb +0 -13
  85. data/app/views/layouts/decidim/forms/admin/questionnaires/questionnaire_answers.html.erb +0 -12
  86. data/config/initializers/wicked_pdf.rb +0 -26
  87. 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
+ }
@@ -11,6 +11,7 @@ import "dragula/dist/dragula.css";
11
11
  import createOptionAttachedInputs from "src/decidim/forms/option_attached_inputs.component"
12
12
  import createDisplayConditions from "src/decidim/forms/display_conditions.component"
13
13
  import createMaxChoicesAlertComponent from "src/decidim/forms/max_choices_alert.component"
14
+ import { preventUnload } from "src/decidim/utilities/dom"
14
15
 
15
16
  $(() => {
16
17
  $(".js-radio-button-collection, .js-check-box-collection").each((idx, el) => {
@@ -45,30 +46,33 @@ $(() => {
45
46
  });
46
47
  });
47
48
 
48
- const $form = $("form.answer-questionnaire");
49
- if ($form.length > 0) {
50
- $form.find("input, textarea, select").on("change", () => {
51
- $form.data("changed", true);
49
+ const form = document.querySelector("form.answer-questionnaire");
50
+ if (form) {
51
+ const safePath = form.dataset.safePath.split("?")[0];
52
+ let exitUrl = "";
53
+ document.addEventListener("click", (event) => {
54
+ const link = event.target?.closest("a");
55
+ if (link) {
56
+ exitUrl = link.href;
57
+ }
52
58
  });
53
59
 
54
- const safePath = $form.data("safe-path").split("?")[0];
55
- $(document).on("click", "a", (event) => {
56
- window.exitUrl = event.currentTarget.href;
57
- });
60
+ // The submit listener has to be registered through jQuery because the
61
+ // custom confirm dialog does not dispatch the "submit" event normally.
58
62
  $(document).on("submit", "form", (event) => {
59
- window.exitUrl = event.currentTarget.action;
63
+ exitUrl = event.currentTarget.action;
60
64
  });
61
65
 
62
- window.addEventListener("beforeunload", (event) => {
63
- const exitUrl = window.exitUrl;
64
- const hasChanged = $form.data("changed");
65
- window.exitUrl = null;
66
+ let hasChanged = false;
67
+ const controls = form.querySelectorAll("input, textarea, select");
68
+ const changeListener = () => {
69
+ if (!hasChanged) {
70
+ hasChanged = true;
71
+ controls.forEach((control) => control.removeEventListener("change", changeListener));
66
72
 
67
- if (!hasChanged || (exitUrl && exitUrl.includes(safePath))) {
68
- return;
73
+ preventUnload(() => !exitUrl.includes(safePath));
69
74
  }
70
-
71
- event.returnValue = true;
72
- });
75
+ };
76
+ controls.forEach((control) => control.addEventListener("change", changeListener));
73
77
  }
74
78
  })
@@ -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>
@@ -111,7 +111,7 @@
111
111
  <div class="questionnaire-question-matrix-rows" data-template="<%= matrix_row_template_selector %>">
112
112
  <div class="questionnaire-question-matrix-rows-list">
113
113
  <% question.matrix_rows_by_position.each do |matrix_row| %>
114
- <%= 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| %>
115
115
  <%= render "decidim/forms/admin/questionnaires/matrix_row", form: matrix_row_form, question:, editable: %>
116
116
  <% end %>
117
117
  <% end %>
@@ -126,7 +126,7 @@
126
126
  <div class="questionnaire-question-answer-options" data-template="<%= answer_option_template_selector %>">
127
127
  <div class="questionnaire-question-answer-options-list">
128
128
  <% question.answer_options.each do |answer_option| %>
129
- <%= 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| %>
130
130
  <%= render "decidim/forms/admin/questionnaires/answer_option", form: answer_option_form, question:, editable: %>
131
131
  <% end %>
132
132
  <% end %>
@@ -153,7 +153,7 @@
153
153
  <div class="questionnaire-question-display-conditions" data-template="<%= display_condition_template_selector %>">
154
154
  <div class="questionnaire-question-display-conditions-list">
155
155
  <% question.display_conditions.each do |display_condition| %>
156
- <%= 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| %>
157
157
  <%= render "decidim/forms/admin/questionnaires/display_condition", form: display_condition_form, question:, editable: %>
158
158
  <% end %>
159
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 %>
@@ -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 %>
@@ -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,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" %>
@@ -0,0 +1,47 @@
1
+ <% add_decidim_meta_tags({
2
+ title: translated_attribute(questionnaire.title),
3
+ description: translated_attribute(questionnaire.description)
4
+ }) %>
5
+
6
+ <%= append_stylesheet_pack_tag "decidim_forms" %>
7
+ <%= append_javascript_pack_tag "decidim_forms" %>
8
+
9
+ <%= render layout: "layouts/decidim/shared/layout_center" do %>
10
+
11
+ <div class="text-center py-10">
12
+ <% if questionnaire.title.present? %>
13
+ <h1 class="title-decorator inline-block text-left mb-12">
14
+ <%= translated_attribute questionnaire.title %>
15
+ </h1>
16
+ <% end %>
17
+
18
+ <% if questionnaire.description.present? %>
19
+ <div class="text-left editor-content">
20
+ <%= decidim_sanitize_editor_admin translated_attribute questionnaire.description %>
21
+ </div>
22
+ <% end %>
23
+ </div>
24
+
25
+ <%= render partial: "decidim/shared/component_announcement" if current_component.manifest_name == "surveys" %>
26
+
27
+ <% unless questionnaire_for.try(:component)&.try(:published?) %>
28
+ <%= cell("decidim/announcement", t("decidim.forms.questionnaires.show.questionnaire_not_published.body"), callout_class: "warning") %>
29
+ <% end %>
30
+
31
+ <section>
32
+ <% if allow_answers? %>
33
+ <% if visitor_can_answer? %>
34
+ <% if @form.responses_by_step.flatten.empty? %>
35
+ <%= cell("decidim/announcement", t("decidim.forms.questionnaires.show.empty")) %>
36
+ <% else %>
37
+ <%= render partial: "decidim/forms/questionnaires/questionnaire" %>
38
+ <% end %>
39
+ <% else %>
40
+ <%= render partial: "decidim/forms/questionnaires/questionnaire_readonly" %>
41
+ <% end %>
42
+ <% else %>
43
+ <%= cell("decidim/announcement", { title: t("decidim.forms.questionnaires.show.questionnaire_closed.title"), body: t("decidim.forms.questionnaires.show.questionnaire_closed.body") }, callout_class: "warning") %>
44
+ <% end %>
45
+ </section>
46
+
47
+ <% end %>
@@ -32,7 +32,14 @@
32
32
  <% if allow_answers? %>
33
33
  <% if visitor_can_answer? %>
34
34
  <% if visitor_already_answered? %>
35
- <%= cell("decidim/announcement", { title: t("decidim.forms.questionnaires.show.questionnaire_answered.title"), body: t("decidim.forms.questionnaires.show.questionnaire_answered.body") }) %>
35
+ <% if visitor_can_edit_answers? && current_component.manifest_name == "surveys" %>
36
+ <% body = t("decidim.forms.questionnaires.show.questionnaire_answered_edit.body",
37
+ link: link_to(t("decidim.forms.questionnaires.show.questionnaire_answered_edit.edit"), edit_survey_path(questionnaire_for))
38
+ ) %>
39
+ <% else %>
40
+ <% body = t("decidim.forms.questionnaires.show.questionnaire_answered.body") %>
41
+ <% end %>
42
+ <%= cell("decidim/announcement", { title: t("decidim.forms.questionnaires.show.questionnaire_answered.title"), body: body }) %>
36
43
  <% else %>
37
44
  <% if @form.responses_by_step.flatten.empty? %>
38
45
  <%= cell("decidim/announcement", t("decidim.forms.questionnaires.show.empty")) %>
@@ -44,7 +51,11 @@
44
51
  <%= render partial: "decidim/forms/questionnaires/questionnaire_readonly" %>
45
52
  <% end %>
46
53
  <% else %>
47
- <%= cell("decidim/announcement", { title: t("decidim.forms.questionnaires.show.questionnaire_closed.title"), body: t("decidim.forms.questionnaires.show.questionnaire_closed.body") }, callout_class: "warning") %>
54
+ <% if questionnaire_for.class.name == "Decidim::Surveys::Survey" && show_published_questions_answers? %>
55
+ <%= render partial: "decidim/surveys/surveys/published_questions_answers" %>
56
+ <% else %>
57
+ <%= cell("decidim/announcement", { title: t("decidim.forms.questionnaires.show.questionnaire_closed.title"), body: t("decidim.forms.questionnaires.show.questionnaire_closed.body") }, callout_class: "warning") %>
58
+ <% end %>
48
59
  <% end %>
49
60
  </section>
50
61