decidim-forms 0.29.2 → 0.30.0.rc2

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 (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 +46 -1
  57. data/config/locales/lt.yml +0 -2
  58. data/config/locales/pl.yml +0 -2
  59. data/config/locales/ro-RO.yml +22 -17
  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