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
@@ -24,17 +24,31 @@ fr:
24
24
  missing: ne sont pas complets
25
25
  too_many: Vous pouvez choisir un maximum de %{count}.
26
26
  questionnaire:
27
- request_invalid: Une erreur s'est produite. Veuillez réessayer.
27
+ request_invalid: Une erreur s'est produite lors du traitement de la requête. Veuillez essayer à nouveau.
28
28
  decidim:
29
+ download_your_data:
30
+ show:
31
+ answers: Export des réponses
32
+ survey_user_answers: Réponses à l'enquête
29
33
  forms:
30
34
  admin:
31
35
  models:
32
36
  components:
37
+ allow_answers: Autoriser les réponses
38
+ allow_editing_answers: Autoriser les utilisateurs enregistrés à modifier leurs propres réponses à l'enquête
39
+ allow_unregistered: Autoriser les utilisateurs non enregistrés à répondre à l'enquête
40
+ announcement: Annonce
41
+ clean_after_publish: Supprimer les réponses lors de la publication de l’enquête
33
42
  description: La description
43
+ ends_at: Réponses acceptées jusqu'au
44
+ ends_at_help: Laisser vide si aucune date spécifique
45
+ starts_at: Réponses acceptées à partir du
46
+ starts_at_help: Laisser vide si aucune date spécifique
34
47
  tos: Conditions d'utilisation
35
48
  questionnaires:
36
49
  actions:
37
50
  back: Retour aux questions
51
+ publish_answers: Publier les réponses
38
52
  show: Afficher les réponses
39
53
  answer_option:
40
54
  answer_option: Option de réponse
@@ -79,16 +93,18 @@ fr:
79
93
  edit:
80
94
  save: sauvegarder
81
95
  title: Modifier le questionnaire
82
- form:
96
+ edit_questions:
83
97
  add_question: Ajouter une question
84
98
  add_separator: Ajouter un séparateur
85
99
  add_title_and_description: Ajouter un titre et une description
86
- already_answered_warning: Certains utilisateurs ont déjà répondu au formulaire, vous ne pouvez donc pas modifier ses questions.
100
+ save: Enregistrer
101
+ title: Questions
102
+ form:
103
+ add_question: Ajouter une question
87
104
  collapse: Réduire toutes les questions
88
105
  expand: Développer toutes les questions
89
106
  preview: Aperçu
90
107
  title: Modifier le questionnaire pour %{questionnaire_for}
91
- unpublished_warning: Le formulaire n'est pas publié. Vous pouvez modifier ses questions, mais cela supprimera les réponses actuelles.
92
108
  matrix_row:
93
109
  matrix_row: Ligne
94
110
  remove: Retirer
@@ -107,6 +123,13 @@ fr:
107
123
  remove: Retirer
108
124
  statement: Déclaration
109
125
  up: Monter
126
+ questions_form:
127
+ already_answered_warning: Certains utilisateurs ont déjà répondu au formulaire, vous ne pouvez donc pas modifier ses questions.
128
+ collapse: Replier toutes les questions
129
+ expand: Déplier toutes les questions
130
+ unpublished_warning: Le formulaire n'est pas publié. Vous pouvez modifier ses questions, mais cela supprimera les réponses actuelles.
131
+ update:
132
+ success: Les questions de l'enquête ont été sauvegardées avec succès.
110
133
  separator:
111
134
  down: Bas
112
135
  remove: Retirer
@@ -125,6 +148,9 @@ fr:
125
148
  invalid: Il y a eu des erreurs lors de la sauvegarde du questionnaire.
126
149
  success: Le questionnaire a bien été sauvegardé.
127
150
  admin_log:
151
+ question:
152
+ publish_answers: "%{user_name} a publié les réponses aux questions de %{resource_name} sur l'espace %{space_name}"
153
+ unpublish_answers: "%{user_name} a dépublié les réponses aux questions de %{resource_name} sur l'espace %{space_name}"
128
154
  questionnaire:
129
155
  update: "%{user_name} a modifié le questionnaire %{resource_name}"
130
156
  errors:
@@ -167,6 +193,9 @@ fr:
167
193
  questionnaire_answered:
168
194
  body: Vous avez déjà répondu à ce questionnaire.
169
195
  title: Déjà répondu
196
+ questionnaire_answered_edit:
197
+ body: Vous avez déjà répondu à ce formulaire. %{link}
198
+ edit: Modifier vos réponses
170
199
  questionnaire_closed:
171
200
  body: Le questionnaire est fermé et vous ne pouvez pas y répondre.
172
201
  title: Questionnaire fermé
@@ -181,9 +210,12 @@ fr:
181
210
  tos_agreement: En participant, vous acceptez ces conditions d'utilisation
182
211
  step_navigation:
183
212
  show:
184
- are_you_sure: Cette action ne peut pas être annulée et vous ne pourrez pas modifier vos réponses. Êtes-vous sûr(e) ?
213
+ are_you_sure_edit: Vous serez en mesure de modifier vos réponses. Êtes-vous sûr(e)?
214
+ are_you_sure_edit_guest: Si vous voulez pouvoir modifier vos réponses par la suite, vous devez vous connecter ou créer un compte.
215
+ are_you_sure_no_edit: Cette action ne peut pas être annulée et vous ne pourrez pas modifier vos réponses. Êtes-vous sûr(e) ?
185
216
  back: Revenir en arrière
186
217
  continue: Continuer
218
+ disallowed: Vous n'êtes pas autorisé(e) à modifier vos réponses.
187
219
  submit: Soumettre
188
220
  user_answers_serializer:
189
221
  body: Répondre
@@ -24,7 +24,7 @@ ja:
24
24
  missing: は完全ではありません
25
25
  too_many: 最大 %{count} 個まで選択できます。
26
26
  questionnaire:
27
- request_invalid: リクエストの処理中にエラーが発生しました。もう一度やり直してください。
27
+ request_invalid: リクエストの処理中に問題が発生しました。もう一度やり直してください。
28
28
  decidim:
29
29
  forms:
30
30
  admin:
@@ -22,8 +22,6 @@ lt:
22
22
  too_long: per ilgas
23
23
  choices:
24
24
  missing: nepilnas - trūksta elementų
25
- questionnaire:
26
- request_invalid: Tvarkant prašymą įvyko klaida. Bandykite dar kartą.
27
25
  decidim:
28
26
  forms:
29
27
  admin:
@@ -23,8 +23,6 @@ pl:
23
23
  choices:
24
24
  missing: nie są kompletne
25
25
  too_many: Możesz wybrać maksymalnie %{count}.
26
- questionnaire:
27
- request_invalid: Wystąpił błąd podczas obsługi żądania. Spróbuj ponownie.
28
26
  decidim:
29
27
  forms:
30
28
  admin:
@@ -22,13 +22,12 @@ ro:
22
22
  too_long: este prea lung
23
23
  choices:
24
24
  missing: nu sunt completate
25
- questionnaire:
26
- request_invalid: A apărut o eroare la procesarea cererii. Te rugăm să încerci din nou.
27
25
  decidim:
28
26
  forms:
29
27
  admin:
30
28
  models:
31
29
  components:
30
+ allow_editing_answers: Permiteți utilizatorilor înregistrați să modifice propriile răspunsuri la sondaj
32
31
  description: Descriere
33
32
  tos: Condiţii de utilizare
34
33
  questionnaires:
@@ -161,6 +160,9 @@ ro:
161
160
  questionnaire_answered:
162
161
  body: Ai completat deja la acest chestionar.
163
162
  title: Un răspuns a fost deja trimis
163
+ questionnaire_answered_edit:
164
+ body: Ați răspuns deja la acest sondaj. %{link}
165
+ edit: Modificați răspunsurile
164
166
  questionnaire_closed:
165
167
  body: Chestionarul este închis și nu mai poate fi completat.
166
168
  title: Formular închis
@@ -175,9 +177,12 @@ ro:
175
177
  tos_agreement: Prin participare accepți Termenii și condițiile sale de utilizare
176
178
  step_navigation:
177
179
  show:
178
- are_you_sure: Această acțiune nu poate fi anulată și nu veți putea să modificați răspunsurile. Sunteți sigur?
180
+ are_you_sure_edit: Veți putea să modificați răspunsurile. Sunteți sigur?
181
+ are_you_sure_edit_guest: Dacă doriți să modificați răspunsurile după ce veți răspunde, atunci trebuie să vă autentificați sau să creați un cont.
182
+ are_you_sure_no_edit: Această acțiune nu poate fi anulată și nu veți putea să vă modificați răspunsurile. Sunteți sigur?
179
183
  back: Înapoi
180
184
  continue: Continuă
185
+ disallowed: Nu aveți permisiunea să vă modificați răspunsurile.
181
186
  submit: Trimite
182
187
  user_answers_serializer:
183
188
  body: Răspuns
@@ -22,8 +22,6 @@ zh-TW:
22
22
  too_long: 太長
23
23
  choices:
24
24
  missing: 尚未完成
25
- questionnaire:
26
- request_invalid: 處理請求時發生錯誤。請再試一次。
27
25
  decidim:
28
26
  forms:
29
27
  admin:
@@ -10,7 +10,7 @@ class AddSessionTokenToDecidimFormsAnswers < ActiveRecord::Migration[5.2]
10
10
  add_index :decidim_forms_answers, :session_token
11
11
 
12
12
  Answer.find_each do |answer|
13
- answer.session_token = Digest::MD5.hexdigest("#{answer.decidim_user_id}-#{Rails.application.secrets.secret_key_base}")
13
+ answer.session_token = Digest::MD5.hexdigest("#{answer.decidim_user_id}-#{Rails.application.secret_key_base}")
14
14
  answer.save!
15
15
  end
16
16
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddSurveyAnswersPublishedAtToQuestions < ActiveRecord::Migration[7.0]
4
+ def change
5
+ add_column :decidim_forms_questions, :survey_answers_published_at, :datetime, index: true
6
+ end
7
+ end
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  "homepage_uri" => "https://decidim.org",
20
20
  "source_code_uri" => "https://github.com/decidim/decidim"
21
21
  }
22
- s.required_ruby_version = "~> 3.2.0"
22
+ s.required_ruby_version = "~> 3.3.0"
23
23
 
24
24
  s.name = "decidim-forms"
25
25
  s.summary = "Decidim forms"
@@ -33,7 +33,6 @@ Gem::Specification.new do |s|
33
33
  end
34
34
 
35
35
  s.add_dependency "decidim-core", Decidim::Forms.version
36
- s.add_dependency "wicked_pdf", "~> 2.1"
37
36
 
38
37
  s.add_development_dependency "decidim-admin", Decidim::Forms.version
39
38
  s.add_development_dependency "decidim-dev", Decidim::Forms.version
@@ -5,9 +5,9 @@ module Decidim
5
5
  class AnswerOptionType < Decidim::Api::Types::BaseObject
6
6
  description "An answer option for a multi-choice question in a questionnaire"
7
7
 
8
- field :id, GraphQL::Types::ID, "ID of this answer option", null: false
9
8
  field :body, Decidim::Core::TranslatedFieldType, "The text answer response option.", null: false
10
9
  field :free_text, GraphQL::Types::Boolean, "Whether if this answer accepts any free text from the user.", null: false
10
+ field :id, GraphQL::Types::ID, "ID of this answer option", null: false
11
11
  end
12
12
  end
13
13
  end
@@ -7,15 +7,15 @@ module Decidim
7
7
 
8
8
  implements Decidim::Core::TimestampsInterface
9
9
 
10
- field :id, GraphQL::Types::ID, "ID of this question", null: false
10
+ field :answer_options, [AnswerOptionType, { null: true }], "List of answer options in multi-choice questions.", null: false
11
11
  field :body, Decidim::Core::TranslatedFieldType, "What is being asked in this question.", null: false
12
12
  field :description, Decidim::Core::TranslatedFieldType, "The description of this question.", null: true
13
+ field :id, GraphQL::Types::ID, "ID of this question", null: false
13
14
  field :mandatory, GraphQL::Types::Boolean, "Whether if this question is mandatory.", null: false
14
- field :position, GraphQL::Types::Int, "Order position of the question in the questionnaire", null: true
15
- field :max_choices, GraphQL::Types::Int, "On questions with answer options, maximum number of choices the user has", null: true
16
15
  field :max_characters, GraphQL::Types::Int, "On questions with free text answers, maximum number of characters the answer can have (0 if no limit)", null: false
16
+ field :max_choices, GraphQL::Types::Int, "On questions with answer options, maximum number of choices the user has", null: true
17
+ field :position, GraphQL::Types::Int, "Order position of the question in the questionnaire", null: true
17
18
  field :question_type, GraphQL::Types::String, "Type of question.", null: true
18
- field :answer_options, [AnswerOptionType, { null: true }], "List of answer options in multi-choice questions.", null: false
19
19
  end
20
20
  end
21
21
  end
@@ -7,13 +7,13 @@ module Decidim
7
7
 
8
8
  implements Decidim::Core::TimestampsInterface
9
9
 
10
- field :id, GraphQL::Types::ID, "ID of this questionnaire", null: false
11
- field :title, Decidim::Core::TranslatedFieldType, "The title of this questionnaire.", null: false
12
10
  field :description, Decidim::Core::TranslatedFieldType, "The description of this questionnaire.", null: true
13
- field :tos, Decidim::Core::TranslatedFieldType, "The Terms of Service for this questionnaire.", null: true
14
- field :for_type, GraphQL::Types::String, "Type of entity using this questionnaire.", method: :questionnaire_for_type, null: true
15
11
  field :for_entity, QuestionnaireEntityInterface, "Entity using this questionnaire.", method: :questionnaire_for, null: true
12
+ field :for_type, GraphQL::Types::String, "Type of entity using this questionnaire.", method: :questionnaire_for_type, null: true
13
+ field :id, GraphQL::Types::ID, "ID of this questionnaire", null: false
16
14
  field :questions, [Decidim::Forms::QuestionType, { null: true }], "Questions in this questionnaire.", null: false
15
+ field :title, Decidim::Core::TranslatedFieldType, "The title of this questionnaire.", null: false
16
+ field :tos, Decidim::Core::TranslatedFieldType, "The Terms of Service for this questionnaire.", null: true
17
17
  end
18
18
  end
19
19
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "wicked_pdf"
4
-
5
3
  module Decidim
6
4
  module Exporters
7
5
  # Inherits from abstract PDF exporter. This class is used to set
@@ -9,25 +7,130 @@ module Decidim
9
7
  #
10
8
  class FormPDF < PDF
11
9
  # i18n-tasks-use t('decidim.admin.exports.formats.FormPDF')
10
+ include ActionView::Helpers::NumberHelper
11
+ include Decidim::Forms::Admin::QuestionnaireAnswersHelper
12
+
13
+ class QuestionnaireAnswerPresenter < Decidim::Forms::Admin::QuestionnaireAnswerPresenter
14
+ def choice(choice_hash)
15
+ render_body_for choice_hash
16
+ end
17
+
18
+ delegate :attachments, to: :answer
19
+
20
+ def body
21
+ return { string: answer.body } if answer.body.present?
22
+ return { attachments: answer.attachments } if answer.attachments.any?
23
+ return { string: "-" } if answer.choices.empty?
24
+
25
+ choices = answer.choices.map do |choice|
26
+ {
27
+ answer_option_body: choice.try(:answer_option).try(:translated_body),
28
+ choice_body: body_or_custom_body(choice)
29
+ }
30
+ end
31
+
32
+ return { single_option: choice(choices.first) } if answer.question.question_type == "single_option"
12
33
 
13
- def controller
14
- @controller ||= FormPDFControllerHelper.new
34
+ { multiple_option: choices.map { |c| choice(c) } }
35
+ end
15
36
  end
16
37
 
17
- def template
18
- "decidim/forms/admin/questionnaires/answers/export/pdf"
38
+ class ParticipantPresenter < Decidim::Forms::Admin::QuestionnaireParticipantPresenter
39
+ def answers
40
+ siblings.map { |answer| QuestionnaireAnswerPresenter.new(answer:) }
41
+ end
19
42
  end
20
43
 
21
- def layout
22
- "decidim/forms/admin/questionnaires/questionnaire_answers"
44
+ protected
45
+
46
+ def add_data!
47
+ composer.text(decidim_sanitize(translated_attribute(questionnaire.title), strip_tags: true), style: :h1)
48
+ composer.text(decidim_sanitize(translated_attribute(questionnaire.description), strip_tags: true), style: :description)
49
+ composer.text(I18n.t("title", scope: "decidim.forms.admin.questionnaires.answers.index", total: collection.count), style: :section_title)
50
+
51
+ local_collection = collection.map { |answer| ParticipantPresenter.new(participant: answer.first) }
52
+
53
+ local_collection.each_with_index do |record, index|
54
+ add_response_box(record, index)
55
+ end
23
56
  end
24
57
 
25
- def locals
58
+ def questionnaire = collection.first.first.questionnaire
59
+
60
+ def styles
26
61
  {
27
- questionnaire: collection.first.first.questionnaire,
28
- collection: collection.map { |answer| Decidim::Forms::Admin::QuestionnaireParticipantPresenter.new(participant: answer.first) }
62
+ h1: { font: bold_font, font_size: 18, margin: [0, 0, 10, 0] },
63
+ th: { font: bold_font, font_size: 10, margin: [0, 0, 10, 0] },
64
+ td: { font:, font_size: 10, margin: [0, 0, 10, 0] },
65
+ description: { font:, margin: [0, 0, 10, 0], font_size: 10 },
66
+ section_title: { font: bold_font, margin: [15, 0, 15, 0], font_size: 16 },
67
+ question_title: { font: bold_font, margin: [10, 0, 10, 0], font_size: 12 },
68
+ question_answer: { font:, margin: [10, 0, 10, 0], font_size: 10 },
69
+ file_info: { font:, margin: [10, 0, 10, 0], font_size: 8 },
70
+ link: { font:, margin: [10, 0, 10, 0], font_size: 10, underline: true }
29
71
  }
30
72
  end
73
+
74
+ def header
75
+ [
76
+ layout.text(I18n.t("session_token", scope: "decidim.forms.user_answers_serializer"), style: :th),
77
+ layout.text(I18n.t("user_status", scope: "decidim.forms.user_answers_serializer"), style: :th),
78
+ layout.text(I18n.t("ip_hash", scope: "decidim.forms.user_answers_serializer"), style: :th),
79
+ layout.text(I18n.t("completion", scope: "decidim.forms.user_answers_serializer"), style: :th),
80
+ layout.text(I18n.t("created_at", scope: "decidim.forms.user_answers_serializer"), style: :th)
81
+ ]
82
+ end
83
+
84
+ def add_user_data(record)
85
+ cells = [
86
+ layout.text(record.session_token, style: :td),
87
+ layout.text(record.status, style: :td),
88
+ layout.text(record.ip_hash, style: :td),
89
+ layout.text(display_percentage(record.completion), style: :td),
90
+ layout.text(I18n.l(record.answered_at, format: :short), style: :td)
91
+ ]
92
+ composer.table([cells], header: ->(_table) { [header] }, cell_style: { border: { width: 0 } })
93
+ end
94
+
95
+ def add_response_box(record, index)
96
+ composer.text(I18n.t("title", number: index + 1, scope: "decidim.forms.admin.questionnaires.answers.export.answer"), style: :section_title)
97
+ add_user_data(record)
98
+
99
+ record.answers.each do |answer|
100
+ composer.text(answer.question, style: :question_title)
101
+ add_answer_body(answer)
102
+ end
103
+ end
104
+
105
+ def add_answer_body(answer)
106
+ return composer.text(answer.body[:string], style: :question_answer) if answer.body.has_key?(:string)
107
+
108
+ if answer.attachments.any?
109
+ composer.list(marker_type: :disc) do |sub_list|
110
+ answer.attachments.each do |attachment|
111
+ sub_list.formatted_text(
112
+ [{ link: attachment.url,
113
+ text: translated_attribute(attachment.title).presence ||
114
+ I18n.t("download_attachment", scope: "decidim.forms.questionnaire_answer_presenter"),
115
+ style: :link },
116
+ " (#{attachment.file_type} #{number_to_human_size(attachment.file_size)})"],
117
+ style: :file_info
118
+ )
119
+ end
120
+ end
121
+ return
122
+ end
123
+
124
+ if answer.body.has_key?(:single_option)
125
+ composer.list(marker_type: :disc) do |sub_list|
126
+ sub_list.text(answer.body[:single_option], style: :question_answer)
127
+ end
128
+ else
129
+ composer.list(marker_type: :disc) do |sub_list|
130
+ answer.body[:multiple_option].map { |choice| sub_list.text(choice, style: :question_answer) }
131
+ end
132
+ end
133
+ end
31
134
  end
32
135
  end
33
136
  end
@@ -8,10 +8,6 @@ module Decidim
8
8
  def serialize
9
9
  {
10
10
  id: resource.id,
11
- user: {
12
- name: resource.user.name,
13
- email: resource.user.email
14
- },
15
11
  questionnaire: {
16
12
  id: resource.question.questionnaire.id,
17
13
  title: translated_attribute(resource.question.questionnaire.title),
@@ -149,8 +149,8 @@ FactoryBot.define do
149
149
 
150
150
  trait :with_attachments do
151
151
  after(:create) do |answer, evaluator|
152
- create :attachment, :with_image, attached_to: answer, skip_injection: evaluator.skip_injection
153
- create :attachment, :with_pdf, attached_to: answer, skip_injection: evaluator.skip_injection
152
+ create(:attachment, :with_image, attached_to: answer, skip_injection: evaluator.skip_injection)
153
+ create(:attachment, :with_pdf, attached_to: answer, skip_injection: evaluator.skip_injection)
154
154
  end
155
155
  end
156
156
  end