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
@@ -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,17 +24,39 @@ ja:
24
24
  missing: は完全ではありません
25
25
  too_many: 最大 %{count} 個まで選択できます。
26
26
  questionnaire:
27
- request_invalid: リクエストの処理中にエラーが発生しました。もう一度やり直してください。
27
+ request_invalid: リクエストの処理中に問題が発生しました。もう一度やり直してください。
28
28
  decidim:
29
+ download_your_data:
30
+ help:
31
+ answers:
32
+ answer: 質問への回答
33
+ id: 回答の固有ID
34
+ question: 回答された質問
35
+ questionnaire: 回答されたアンケート
36
+ user: アンケートに回答したユーザー
37
+ show:
38
+ answers: 回答のエクスポート
39
+ survey_user_answers: アンケートユーザーの回答
29
40
  forms:
30
41
  admin:
31
42
  models:
32
43
  components:
44
+ allow_answers: 回答を許可
45
+ allow_editing_answers: 登録ユーザーが自分のアンケート回答を編集できるようにする
46
+ allow_unregistered: 未登録ユーザーがアンケートに回答できるようにする
47
+ allow_unregistered_help: 有効な場合、ログインしていなくてもアンケートに回答できるようになります。 これは、収集されるデータが貧弱または信頼性が低下するおそれがあり、自動化された攻撃に対してより脆弱になります。 注意して使用してください。また、 異なるブラウザを使ったりまたはWebブラウザの「プライベートブラウジング」機能を使うことで、参加者が同じアンケートに複数回答えられることに注意してください。
48
+ announcement: お知らせ
49
+ clean_after_publish: アンケートを公開するときに回答を削除する
33
50
  description: 説明
51
+ ends_at: 回答受付の終了日時
52
+ ends_at_help: 特定の日付がない場合は空白のままにしてください
53
+ starts_at: 回答受付の開始日時
54
+ starts_at_help: 特定の日付がない場合は空白のままにしてください
34
55
  tos: 利用規約
35
56
  questionnaires:
36
57
  actions:
37
58
  back: 質問に戻る
59
+ publish_answers: 回答を公開
38
60
  show: 回答を表示
39
61
  answer_option:
40
62
  answer_option: 回答オプション
@@ -79,6 +101,12 @@ ja:
79
101
  edit:
80
102
  save: 保存
81
103
  title: アンケートを編集
104
+ edit_questions:
105
+ add_question: 質問を追加
106
+ add_separator: 区切り文字を追加
107
+ add_title_and_description: タイトルと説明を追加
108
+ save: 保存
109
+ title: 質問
82
110
  form:
83
111
  add_question: 質問を追加
84
112
  collapse: すべての質問を閉じる
@@ -103,6 +131,13 @@ ja:
103
131
  remove: 削除
104
132
  statement: ステートメント
105
133
  up: 上へ
134
+ questions_form:
135
+ already_answered_warning: このフォームはすでに回答しているユーザーがいるため、質問を修正することはできません。
136
+ collapse: すべての質問を閉じる
137
+ expand: すべての質問を展開
138
+ unpublished_warning: フォームは公開されていません。質問を修正することはできますが、そうすると現在の回答が削除されます。
139
+ update:
140
+ success: アンケートの質問を保存しました。
106
141
  separator:
107
142
  down: 下
108
143
  remove: 削除
@@ -121,6 +156,9 @@ ja:
121
156
  invalid: フォームの保存に失敗しました。
122
157
  success: フォームを保存しました。
123
158
  admin_log:
159
+ question:
160
+ publish_answers: "%{user_name} が %{resource_name} の質問の回答を %{space_name} スペースに公開しました"
161
+ unpublish_answers: "%{user_name} は %{resource_name} の質問の回答を %{space_name} スペースで非公開にしました"
124
162
  questionnaire:
125
163
  update: "%{user_name} が %{resource_name} アンケートを更新しました"
126
164
  errors:
@@ -163,6 +201,9 @@ ja:
163
201
  questionnaire_answered:
164
202
  body: このフォームには既に回答済みです。
165
203
  title: すでに回答済み
204
+ questionnaire_answered_edit:
205
+ body: すでにこのフォームに回答しています。 %{link}
206
+ edit: 回答を編集する
166
207
  questionnaire_closed:
167
208
  body: フォームが閉じられているため、回答できません。
168
209
  title: フォームを閉じました
@@ -177,8 +218,12 @@ ja:
177
218
  tos_agreement: 参加することにより、利用規約に同意します。
178
219
  step_navigation:
179
220
  show:
221
+ are_you_sure_edit: 回答を編集することができます。よろしいですか?
222
+ are_you_sure_edit_guest: 回答を後で編集できるようにしたい場合は、ログインまたはアカウントを作成する必要があります。
223
+ are_you_sure_no_edit: この操作は元に戻すことができず、回答を編集することはできません。よろしいですか?
180
224
  back: 戻る
181
225
  continue: 続ける
226
+ disallowed: 回答を編集する権限がありません。
182
227
  submit: 送信
183
228
  user_answers_serializer:
184
229
  body: 回答
@@ -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:
@@ -11,7 +11,7 @@ ro:
11
11
  question_type: Tip
12
12
  questionnaire_question:
13
13
  mandatory: Obligatoriu
14
- max_characters: Limita de caractere (lăsați la 0 dacă nu este nicio limită)
14
+ max_characters: Limita de caractere (lăsați 0 dacă nu este nicio limită)
15
15
  errors:
16
16
  models:
17
17
  answer:
@@ -21,20 +21,19 @@ ro:
21
21
  body:
22
22
  too_long: este prea lung
23
23
  choices:
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.
24
+ missing: nu sunt complete
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
- tos: Condiţii de utilizare
32
+ tos: Termenii serviciului
34
33
  questionnaires:
35
34
  actions:
36
35
  back: Înapoi la întrebări
37
- show: Afișează răspunsurile
36
+ show: Afișați răspunsurile
38
37
  answer_option:
39
38
  answer_option: Opțiune de răspuns
40
39
  free_text: Text liber
@@ -43,10 +42,10 @@ ro:
43
42
  answers:
44
43
  actions:
45
44
  back: Înapoi la răspunsuri
46
- export: Exportă
45
+ export: Exportați
47
46
  next: Următoarea ›
48
47
  previous: "‹ Anterioara"
49
- show: Afişează răspunsurile
48
+ show: Afișați răspunsurile
50
49
  empty: Niciun răspuns încă
51
50
  export:
52
51
  answer:
@@ -63,7 +62,7 @@ ro:
63
62
  condition_type: Condiție
64
63
  condition_types:
65
64
  answered: Răspunse
66
- equal: Egal cu
65
+ equal: Egal
67
66
  match: Include textul
68
67
  not_answered: Fără răspuns
69
68
  not_equal: Nu este egal cu
@@ -77,16 +76,16 @@ ro:
77
76
  select_condition_type: Selectați un tip de condiție
78
77
  edit:
79
78
  save: Salvează
80
- title: Editare chestionar
79
+ title: Modificați chestionar
81
80
  form:
82
81
  add_question: Adaugă întrebare
83
- collapse: Restrânge toate întrebările
82
+ collapse: Restrângeți toate întrebările
84
83
  expand: Extinde toate întrebările
85
84
  preview: Previzualizează
86
- title: Actualizați chestionarul pentru %{questionnaire_for}
85
+ title: Modificați chestionarul pentru %{questionnaire_for}
87
86
  matrix_row:
88
87
  matrix_row: Rând
89
- remove: Elimină
88
+ remove: Eliminați
90
89
  statement: Declarație
91
90
  question:
92
91
  add_answer_option: Adaugă opțiune de răspuns
@@ -108,10 +107,10 @@ ro:
108
107
  separator: Separator
109
108
  up: Mergi în sus
110
109
  title_and_description:
111
- collapse: Restrânge
110
+ collapse: Restrângeți
112
111
  description: Descriere
113
112
  down: Mergi în jos
114
- expand: Extinde
113
+ expand: Extindeți
115
114
  remove: Șterge
116
115
  title: Titlu
117
116
  title_and_description: Titlu și descriere
@@ -154,13 +153,16 @@ ro:
154
153
  already_have_an_account?: Ai deja un cont?
155
154
  are_you_new?: Utilizator nou?
156
155
  sign_up_description: Creați un cont de participant pentru a participa la sondaj
157
- title: Completează chestionarul
156
+ title: Completați formularul
158
157
  current_step: Pasul %{step}
159
158
  empty: Nicio întrebare configurată pentru acest formular încă.
160
159
  of_total_steps: din %{total_steps}
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