decidim-proposals 0.27.5 → 0.27.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/proposals/highlighted_proposals_for_component/show.erb +1 -1
  3. data/app/cells/decidim/proposals/participatory_text_proposal/buttons.erb +2 -2
  4. data/app/cells/decidim/proposals/proposal_tags/show.erb +2 -2
  5. data/app/controllers/decidim/proposals/widgets_controller.rb +11 -1
  6. data/app/helpers/decidim/proposals/application_helper.rb +1 -1
  7. data/app/models/decidim/proposals/proposal.rb +2 -14
  8. data/app/models/decidim/proposals/valuation_assignment.rb +2 -1
  9. data/app/packs/src/decidim/proposals/admin/proposals.js +7 -0
  10. data/app/permissions/decidim/proposals/permissions.rb +9 -0
  11. data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +1 -5
  12. data/app/presenters/decidim/proposals/admin_log/value_types/proposal_title_body_presenter.rb +1 -3
  13. data/app/presenters/decidim/proposals/log/valuation_assignment_presenter.rb +1 -1
  14. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +1 -1
  15. data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +1 -1
  16. data/app/views/decidim/proposals/admin/proposals/show.html.erb +1 -1
  17. data/app/views/decidim/proposals/admin/proposals/update_attribute.js.erb +2 -1
  18. data/app/views/decidim/proposals/proposals/show.html.erb +3 -1
  19. data/config/locales/ar.yml +2 -6
  20. data/config/locales/bg.yml +748 -1
  21. data/config/locales/ca.yml +35 -33
  22. data/config/locales/cs.yml +5 -4
  23. data/config/locales/de.yml +9 -7
  24. data/config/locales/el.yml +0 -4
  25. data/config/locales/en.yml +2 -0
  26. data/config/locales/es-MX.yml +9 -7
  27. data/config/locales/es-PY.yml +9 -7
  28. data/config/locales/es.yml +22 -20
  29. data/config/locales/eu.yml +6 -4
  30. data/config/locales/fi-plain.yml +7 -5
  31. data/config/locales/fi.yml +6 -4
  32. data/config/locales/fr-CA.yml +9 -7
  33. data/config/locales/fr.yml +9 -7
  34. data/config/locales/ga-IE.yml +13 -0
  35. data/config/locales/gl.yml +2 -5
  36. data/config/locales/he-IL.yml +1 -0
  37. data/config/locales/hu.yml +16 -11
  38. data/config/locales/id-ID.yml +1 -4
  39. data/config/locales/is-IS.yml +4 -5
  40. data/config/locales/it.yml +4 -7
  41. data/config/locales/ja.yml +19 -17
  42. data/config/locales/lt.yml +0 -4
  43. data/config/locales/lv.yml +1 -4
  44. data/config/locales/nl.yml +5 -8
  45. data/config/locales/no.yml +1 -4
  46. data/config/locales/pl.yml +91 -5
  47. data/config/locales/pt-BR.yml +34 -5
  48. data/config/locales/pt.yml +1 -4
  49. data/config/locales/ro-RO.yml +1 -3
  50. data/config/locales/ru.yml +7 -5
  51. data/config/locales/sk.yml +5 -8
  52. data/config/locales/sv.yml +3 -7
  53. data/config/locales/tr-TR.yml +9 -8
  54. data/config/locales/uk.yml +7 -5
  55. data/config/locales/zh-CN.yml +1 -4
  56. data/config/locales/zh-TW.yml +0 -4
  57. data/db/migrate/20240404202756_add_valuation_assignments_count_to_decidim_proposals_proposals.rb +16 -0
  58. data/decidim-proposals.gemspec +40 -0
  59. data/lib/decidim/proposals/proposal_serializer.rb +52 -0
  60. data/lib/decidim/proposals/test/factories.rb +76 -57
  61. data/lib/decidim/proposals/valuatable.rb +2 -1
  62. data/lib/decidim/proposals/version.rb +1 -1
  63. metadata +26 -25
  64. data/app/presenters/decidim/proposals/log/resource_presenter.rb +0 -22
  65. data/config/environment.rb +0 -3
@@ -171,7 +171,6 @@ sv:
171
171
  proposal_wizard_step_1_help_text: Hjälptext till steget "Skapa" i förslagsguiden
172
172
  proposal_wizard_step_2_help_text: Hjälptext till steget "Jämför" i förslagsguiden
173
173
  proposal_wizard_step_3_help_text: Hjälptext till steget "Komplettera" i förslagsguiden
174
- proposal_wizard_step_4_help_text: Förslagsguidens hjälptext för steg "Publicera"
175
174
  resources_permissions_enabled: Åtgärdsbehörigheter kan ställas in för varje förslag
176
175
  scope_id: Omfång
177
176
  scopes_enabled: Omfång aktiverade
@@ -257,7 +256,6 @@ sv:
257
256
  notification_title: Ditt förslag <a href="%{resource_path}">%{resource_title}</a> har accepterats.
258
257
  follower:
259
258
  email_intro: 'Förslaget "%{resource_title}" har accepterats. Läs svaret på den här sidan:'
260
- email_outro: Du har fått det här meddelandet eftersom du följer "%{resource_title}". Du kan sluta att följa det via föregående länk.
261
259
  email_subject: Ett förslag som du följer har accepterats
262
260
  notification_title: Förslaget <a href="%{resource_path}">%{resource_title}</a> har accepterats.
263
261
  proposal_evaluating:
@@ -268,7 +266,6 @@ sv:
268
266
  notification_title: Ditt förslag <a href="%{resource_path}">%{resource_title}</a> utvärderas.
269
267
  follower:
270
268
  email_intro: 'Förslaget "%{resource_title}" utvärderas för närvarande. Du kan söka efter ett svar på den här sidan:'
271
- email_outro: Du har fått det här meddelandet eftersom du följer "%{resource_title}". Du kan sluta att följa det via föregående länk.
272
269
  email_subject: Ett förslag som du följer utvärderas
273
270
  notification_title: Förslaget <a href="%{resource_path}">%{resource_title}</a> utvärderas.
274
271
  proposal_mentioned:
@@ -293,7 +290,6 @@ sv:
293
290
  notification_title: Ditt förslag <a href="%{resource_path}">%{resource_title}</a> har avslagits.
294
291
  follower:
295
292
  email_intro: 'Förslaget "%{resource_title}" har avslagits. Du kan läsa svaret på den här sidan:'
296
- email_outro: Du har fått det här meddelandet eftersom du följer "%{resource_title}". Du kan sluta att följa det via föregående länk.
297
293
  email_subject: Ett förslag som du följer har avslagits
298
294
  notification_title: Förslaget <a href="%{resource_path}">%{resource_title}</a> har avslagits.
299
295
  proposal_update_category:
@@ -436,7 +432,7 @@ sv:
436
432
  accepted: Accepterat
437
433
  answer_proposal: Svara
438
434
  evaluating: Utvärderas
439
- not_answered: Ej besvarade
435
+ not_answered: Ej besvarat
440
436
  rejected: Avvisat
441
437
  title: Svar på förslaget %{title}
442
438
  proposal_notes:
@@ -581,11 +577,11 @@ sv:
581
577
  filter_scope_values:
582
578
  all: Alla
583
579
  filter_state_values:
584
- accepted: Accepterade
580
+ accepted: Accepterat
585
581
  all: Alla
586
582
  evaluating: Utvärderas
587
583
  not_answered: Ej besvarade
588
- rejected: Avvisade
584
+ rejected: Avvisat
589
585
  filter_type_values:
590
586
  all: Alla
591
587
  amendments: Ändringsförslag
@@ -143,7 +143,7 @@ tr:
143
143
  proposal_wizard_step_1_help_text: Teklif sihirbazı "Oluştur" adımı yardım metni
144
144
  proposal_wizard_step_2_help_text: Teklif sihirbazı "Karşılaştır" adımı yardım metni
145
145
  proposal_wizard_step_3_help_text: Teklif sihirbazı "Tamamlandı" adımı yardım metni
146
- proposal_wizard_step_4_help_text: Teklif sihirbazı "Yayınla" adımı yardım metni
146
+ proposal_wizard_step_4_help_text: Teklif "Yayınlama" sihirbazı yardım metni
147
147
  resources_permissions_enabled: Her teklif için işlem izinleri ayarlanabilir
148
148
  scope_id: Kapsam
149
149
  scopes_enabled: Kapsamlar etkinleştirildi
@@ -217,7 +217,7 @@ tr:
217
217
  notification_title: Teklifiniz <a href="%{resource_path}">%{resource_title}</a> kabul edildi.
218
218
  follower:
219
219
  email_intro: '"%{resource_title}" teklifi kabul edildi. Cevabı bu sayfada okuyabilirsiniz:'
220
- email_outro: Bu bildirimi, "%{resource_title}" takip ettiğiniz için aldınız. Bir önceki bağlantıdan takip etmeyi bırakabilirsiniz.
220
+ email_outro: Bu bildirimi "%{resource_title}" adresini takip ettiğiniz için aldınız. Önceki bağlantıdan takibi bırakabilirsiniz.
221
221
  email_subject: Takip ettiğiniz bir teklif kabul edildi
222
222
  notification_title: <a href="%{resource_path}">%{resource_title}</a> teklif kabul edildi.
223
223
  proposal_evaluating:
@@ -228,7 +228,7 @@ tr:
228
228
  notification_title: Teklifiniz <a href="%{resource_path}">%{resource_title}</a> değerlendiriliyor.
229
229
  follower:
230
230
  email_intro: 'Şu anda "%{resource_title}" teklifi değerlendiriliyor. Bu sayfadaki cevabı kontrol edebilirsiniz:'
231
- email_outro: Bu bildirimi, "%{resource_title}" takip ettiğiniz için aldınız. Bir önceki bağlantıdan takip etmeyi bırakabilirsiniz.
231
+ email_outro: Bu bildirimi "%{resource_title}" adresini takip ettiğiniz için aldınız. Önceki bağlantıdan takibi bırakabilirsiniz.
232
232
  email_subject: Takip ettiğiniz bir teklif değerlendiriliyor
233
233
  notification_title: <a href="%{resource_path}">%{resource_title}</a> teklifi değerlendiriliyor.
234
234
  proposal_mentioned:
@@ -252,7 +252,7 @@ tr:
252
252
  notification_title: Teklifiniz <a href="%{resource_path}">%{resource_title}</a> reddedildi.
253
253
  follower:
254
254
  email_intro: '"%{resource_title}" teklifi reddedildi. Cevabı bu sayfada okuyabilirsiniz:'
255
- email_outro: Bu bildirimi, "%{resource_title}" takip ettiğiniz için aldınız. Bir önceki bağlantıdan takip etmeyi bırakabilirsiniz.
255
+ email_outro: Bu bildirimi "%{resource_title}" adresini takip ettiğiniz için aldınız. Önceki bağlantıdan takibi bırakabilirsiniz.
256
256
  email_subject: Takip ettiğiniz bir teklif reddedildi
257
257
  notification_title: <a href="%{resource_path}">%{resource_title}</a> teklifi reddedildi.
258
258
  proposal_update_category:
@@ -381,10 +381,11 @@ tr:
381
381
  success: Katılımcı metin başarıyla güncellendi.
382
382
  proposal_answers:
383
383
  form:
384
- accepted: Kabul edilmiş
384
+ accepted: Kabul Edildi
385
385
  answer_proposal: Cevap
386
- evaluating: değerlendirilmesi
387
- rejected: Reddedilen
386
+ evaluating: Değerlendiriliyor
387
+ not_answered: Cevaplanmadı
388
+ rejected: Reddedildi
388
389
  title: Teklifin cevabı %{title}
389
390
  proposal_notes:
390
391
  create:
@@ -817,7 +818,7 @@ tr:
817
818
  wizard_aside:
818
819
  back: Geri
819
820
  back_from_step_1: Teklifte geri dön
820
- back_from_step_2: Tekliflere geri dön
821
+ back_from_step_2: Teklifte geri dön
821
822
  back_from_step_3: Teklifleri karşılaştırmaya geri dön
822
823
  back_from_step_4: Taslağı düzenlemeye dön
823
824
  info: <strong>teklif</strong>.
@@ -8,6 +8,7 @@ uk:
8
8
  body: Основний текст
9
9
  category_id: Категорія
10
10
  has_address: Має адресу
11
+ scope_id: Обсяг
11
12
  state: Стан
12
13
  title: Назва
13
14
  user_group_id: Створити пропозицію як
@@ -82,7 +83,6 @@ uk:
82
83
  proposal_wizard_step_1_help_text: Довідка майстра пропозицій щодо кроку "Створити"
83
84
  proposal_wizard_step_2_help_text: Довідка майстра пропозицій щодо кроку "Порівняти"
84
85
  proposal_wizard_step_3_help_text: Довідка майстра пропозицій щодо кроку "Завершити"
85
- proposal_wizard_step_4_help_text: Довідка майстра пропозицій щодо кроку "Оприлюднити"
86
86
  resources_permissions_enabled: Для кожної пропозиції можна встановити ті чи інші дозволи на дії
87
87
  threshold_per_proposal: Поріг на кожну пропозицію
88
88
  vote_limit: Гранична кількість голосів від одного учасника
@@ -110,13 +110,11 @@ uk:
110
110
  proposal_accepted:
111
111
  follower:
112
112
  email_intro: 'Пропозиція "%{resource_title}" була прийнята. Ви можете прочитати відповідь на сторінці:'
113
- email_outro: Ви отримали це сповіщення, тому що ви стежите за "%{resource_title}". Ви можете припинити стежити за ним, перейшовши за наведеним вище посиланням.
114
113
  email_subject: Пропозиція, за якою ви стежите, була прийнята
115
114
  notification_title: Пропозицію <a href="%{resource_path}">%{resource_title}</a> було прийнято.
116
115
  proposal_evaluating:
117
116
  follower:
118
117
  email_intro: 'Пропозиція "%{resource_title}" зараз розглядається. Ви можете перевірити наявність відповіді на сторінці:'
119
- email_outro: Ви отримали це сповіщення, тому що ви стежите за "%{resource_title}". Ви можете припинити стежити за ним, перейшовши за наведеним вище посиланням.
120
118
  email_subject: Пропозиція, за якою ви стежите, зараз розглядається
121
119
  notification_title: Пропозиція <a href="%{resource_path}">%{resource_title}</a> розглядається.
122
120
  proposal_mentioned:
@@ -131,7 +129,6 @@ uk:
131
129
  proposal_rejected:
132
130
  follower:
133
131
  email_intro: 'Пропозиція "%{resource_title}" була відхилена. Ви можете прочитати відповідь на сторінці:'
134
- email_outro: Ви отримали це сповіщення, тому що ви стежите за "%{resource_title}". Ви можете припинити стежити за ним, перейшовши за наведеним вище посиланням.
135
132
  email_subject: Пропозиція, за якою ви стежите, була відхилена
136
133
  notification_title: Пропозицію <a href="%{resource_path}">%{resource_title}</a> було відхилено.
137
134
  proposal_update_category:
@@ -164,6 +161,7 @@ uk:
164
161
  accepted: Прийнято
165
162
  answer_proposal: Відповісти
166
163
  evaluating: Розглядається
164
+ not_answered: Без відповідей
167
165
  rejected: Відхилено
168
166
  title: Відповідь на пропозицію %{title}
169
167
  proposal_notes:
@@ -230,7 +228,10 @@ uk:
230
228
  filter_origin_values:
231
229
  official: Службове
232
230
  filter_state_values:
231
+ accepted: Прийнято
232
+ evaluating: Розглядається
233
233
  not_answered: Без відповідей
234
+ rejected: Відхилено
234
235
  content_blocks:
235
236
  highlighted_proposals:
236
237
  proposals: Пропозиції
@@ -269,7 +270,6 @@ uk:
269
270
  no_similars_found: Гарна робота! Не знайдено схожий пропозицій
270
271
  title: Подібні пропозиції
271
272
  complete:
272
- send: Надіслати
273
273
  title: Завершіть свою пропозицію
274
274
  edit:
275
275
  attachment_legend: "(Необов'язково) Додати вкладений файл"
@@ -283,6 +283,7 @@ uk:
283
283
  send: Попередній перегляд
284
284
  title: Редагувати чернетку пропозиції
285
285
  filters:
286
+ all: Усі
286
287
  category: Категорія
287
288
  origin: Джерело
288
289
  related_to: Пов'язане з
@@ -355,6 +356,7 @@ uk:
355
356
  vote_limit:
356
357
  description: Ви можете проголосувати до %{limit} пропозицій.
357
358
  left: Залишилось
359
+ votes: Голоси
358
360
  wizard_aside:
359
361
  back: Повернутись
360
362
  info: Ви вносите <strong>пропозицію</strong>.
@@ -136,7 +136,6 @@ zh-CN:
136
136
  proposal_wizard_step_1_help_text: 建议向导“创建”步骤帮助文本
137
137
  proposal_wizard_step_2_help_text: 建议向导“Compare”步骤帮助文本
138
138
  proposal_wizard_step_3_help_text: 建议向导“完成”步骤帮助文本
139
- proposal_wizard_step_4_help_text: 建议向导"发布"步骤帮助文本
140
139
  resources_permissions_enabled: 每个提案都可以设置动作权限
141
140
  scope_id: 范围
142
141
  scopes_enabled: 范围已启用
@@ -206,7 +205,6 @@ zh-CN:
206
205
  notification_title: 您的提议 <a href="%{resource_path}">%{resource_title}</a> 已被接受。
207
206
  follower:
208
207
  email_intro: '提议 "%{resource_title}" 已被接受。您可以在此页面中阅读答案:'
209
- email_outro: 您收到此通知是因为您正在关注 "%{resource_title}"。您可以从上一个链接取消关注它。
210
208
  email_subject: 您关注的建议已被接受
211
209
  notification_title: <a href="%{resource_path}">%{resource_title}</a> 提议已被接受。
212
210
  proposal_evaluating:
@@ -217,7 +215,6 @@ zh-CN:
217
215
  notification_title: 您的提议 <a href="%{resource_path}">%{resource_title}</a> 正在评估中。
218
216
  follower:
219
217
  email_intro: '提议 "%{resource_title}" 目前正在评估。您可以在这个页面检查答案:'
220
- email_outro: 您收到此通知是因为您正在关注 "%{resource_title}"。您可以从上一个链接取消关注它。
221
218
  email_subject: 正在评估您关注的建议
222
219
  notification_title: <a href="%{resource_path}">%{resource_title}</a> 提议正在评估中。
223
220
  proposal_mentioned:
@@ -239,7 +236,6 @@ zh-CN:
239
236
  notification_title: 您的提议 <a href="%{resource_path}">%{resource_title}</a> 已被拒绝
240
237
  follower:
241
238
  email_intro: '提议 "%{resource_title}" 已被拒绝。您可以在此页中读取答案:'
242
- email_outro: 您收到此通知是因为您正在关注 "%{resource_title}"。您可以从上一个链接取消关注它。
243
239
  email_subject: 您关注的建议已被拒绝
244
240
  notification_title: <a href="%{resource_path}">%{resource_title}</a> 提议已被拒绝。
245
241
  proposal_update_category:
@@ -366,6 +362,7 @@ zh-CN:
366
362
  accepted: 已接受
367
363
  answer_proposal: 答案
368
364
  evaluating: 评价
365
+ not_answered: 未回答
369
366
  rejected: 已拒绝
370
367
  title: 对提议 %{title} 的答案
371
368
  proposal_notes:
@@ -171,7 +171,6 @@ zh-TW:
171
171
  proposal_wizard_step_1_help_text: 提案向導「創建」步驟說明文字
172
172
  proposal_wizard_step_2_help_text: 提案向導「比較」步驟說明文字
173
173
  proposal_wizard_step_3_help_text: 提案向導「完成」步驟說明文字
174
- proposal_wizard_step_4_help_text: 提案向導「發佈」步驟說明文字
175
174
  resources_permissions_enabled: 每個提案都可以設定行動權限
176
175
  scope_id: 範圍
177
176
  scopes_enabled: 啟用範圍
@@ -271,7 +270,6 @@ zh-TW:
271
270
  notification_title: 您的提案 <a href="%{resource_path}">%{resource_title}</a> 已被接受。
272
271
  follower:
273
272
  email_intro: '該提案「%{resource_title}」已被接受。您可以在此頁面上閱讀回應:'
274
- email_outro: 您收到了此通知,是因為您正在關注 "%{resource_title}"。您可以通過前面的鏈接取消關注它。
275
273
  email_subject: 您追蹤的提案已被接受
276
274
  notification_title: <a href="%{resource_path}">%{resource_title}</a>" 提案已經被接受。
277
275
  proposal_evaluating:
@@ -282,7 +280,6 @@ zh-TW:
282
280
  notification_title: 您的提案<a href="%{resource_path}">%{resource_title}</a>正在評估中。
283
281
  follower:
284
282
  email_intro: '該提案“%{resource_title}”正在進行評估。您可以在此頁面上查看答案:'
285
- email_outro: 您收到了此通知,是因為您正在關注 "%{resource_title}"。您可以通過前面的鏈接取消關注它。
286
283
  email_subject: 你追蹤的提案正在評估中
287
284
  notification_title: <a href="%{resource_path}">%{resource_title}</a> 提案正在評估中。
288
285
  proposal_mentioned:
@@ -309,7 +306,6 @@ zh-TW:
309
306
  notification_title: 您的提案<a href="%{resource_path}">%{resource_title}</a>已被拒絕。
310
307
  follower:
311
308
  email_intro: '該提案「%{resource_title}」已被駁回。您可以在此頁面中閱讀回覆:'
312
- email_outro: 您收到了此通知,是因為您正在關注 "%{resource_title}"。您可以通過前面的鏈接取消關注它。
313
309
  email_subject: 您追蹤的提案已被拒絕
314
310
  notification_title: <a href="%{resource_path}">%{resource_title}</a>" 提案已經被拒絕。
315
311
  proposal_update_category:
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddValuationAssignmentsCountToDecidimProposalsProposals < ActiveRecord::Migration[6.1]
4
+ def change
5
+ add_column :decidim_proposals_proposals, :valuation_assignments_count, :integer, default: 0
6
+
7
+ reversible do |dir|
8
+ dir.up do
9
+ Decidim::Proposals::Proposal.reset_column_information
10
+ Decidim::Proposals::Proposal.find_each do |record|
11
+ Decidim::Proposals::Proposal.reset_counters(record.id, :valuation_assignments)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.push File.expand_path("lib", __dir__)
4
+
5
+ # Maintain your gem's version:
6
+ require "decidim/proposals/version"
7
+
8
+ # Describe your gem and declare its dependencies:
9
+ Gem::Specification.new do |s|
10
+ s.version = Decidim::Proposals.version
11
+ s.authors = ["Josep Jaume Rey Peroy", "Marc Riera Casals", "Oriol Gual Oliva"]
12
+ s.email = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com"]
13
+ s.license = "AGPL-3.0"
14
+ s.homepage = "https://github.com/decidim/decidim"
15
+ s.required_ruby_version = "~> 3.0.0"
16
+
17
+ s.name = "decidim-proposals"
18
+ s.summary = "Decidim proposals module"
19
+ s.description = "A proposals component for decidim's participatory spaces."
20
+
21
+ s.files = Dir.chdir(__dir__) do
22
+ `git ls-files -z`.split("\x0").select do |f|
23
+ (File.expand_path(f) == __FILE__) ||
24
+ f.start_with?(*%w(app/ config/ db/ lib/ Rakefile README.md))
25
+ end
26
+ end
27
+
28
+ s.add_dependency "decidim-comments", Decidim::Proposals.version
29
+ s.add_dependency "decidim-core", Decidim::Proposals.version
30
+ s.add_dependency "doc2text", "~> 0.4.5"
31
+ s.add_dependency "redcarpet", "~> 3.5", ">= 3.5.1"
32
+
33
+ s.add_development_dependency "decidim-admin", Decidim::Proposals.version
34
+ s.add_development_dependency "decidim-assemblies", Decidim::Proposals.version
35
+ s.add_development_dependency "decidim-budgets", Decidim::Proposals.version
36
+ s.add_development_dependency "decidim-conference", Decidim::Proposals.version
37
+ s.add_development_dependency "decidim-dev", Decidim::Proposals.version
38
+ s.add_development_dependency "decidim-meetings", Decidim::Proposals.version
39
+ s.add_development_dependency "decidim-participatory_processes", Decidim::Proposals.version
40
+ end
@@ -19,6 +19,9 @@ module Decidim
19
19
  def serialize
20
20
  {
21
21
  id: proposal.id,
22
+ author: {
23
+ **author_fields
24
+ },
22
25
  category: {
23
26
  id: proposal.category.try(:id),
24
27
  name: proposal.category.try(:name) || empty_translatable
@@ -40,6 +43,7 @@ module Decidim
40
43
  state: proposal.state.to_s,
41
44
  reference: proposal.reference,
42
45
  answer: ensure_translatable(proposal.answer),
46
+ answered_at: proposal.answered_at,
43
47
  supports: proposal.proposal_votes_count,
44
48
  endorsements: {
45
49
  total_count: proposal.endorsements.size,
@@ -101,6 +105,54 @@ module Decidim
101
105
 
102
106
  convert_to_text(value)
103
107
  end
108
+
109
+ def author_fields
110
+ is_author_user_group = resource.coauthorships.map(&:decidim_user_group_id).any?
111
+
112
+ {
113
+ id: resource.authors.map(&:id),
114
+ name: resource.authors.map do |author|
115
+ author_name(is_author_user_group ? resource.coauthorships.first.user_group : author)
116
+ end,
117
+ url: resource.authors.map do |author|
118
+ author_url(is_author_user_group ? resource.coauthorships.first.user_group : author)
119
+ end
120
+ }
121
+ end
122
+
123
+ def author_name(author)
124
+ if author.respond_to?(:name)
125
+ translated_attribute(author.name) # is a Decidim::User or Decidim::Organization or Decidim::UserGroup
126
+ elsif author.respond_to?(:title)
127
+ translated_attribute(author.title) # is a Decidim::Meetings::Meeting
128
+ end
129
+ end
130
+
131
+ def author_url(author)
132
+ if author.respond_to?(:nickname)
133
+ profile_url(author.nickname) # is a Decidim::User or Decidim::UserGroup
134
+ elsif author.respond_to?(:title)
135
+ meeting_url(author) # is a Decidim::Meetings::Meeting
136
+ else
137
+ root_url # is a Decidim::Organization
138
+ end
139
+ end
140
+
141
+ def profile_url(nickname)
142
+ Decidim::Core::Engine.routes.url_helpers.profile_url(nickname, host: host)
143
+ end
144
+
145
+ def meeting_url(meeting)
146
+ Decidim::EngineRouter.main_proxy(meeting.component).meeting_url(id: meeting.id, host: host)
147
+ end
148
+
149
+ def root_url
150
+ Decidim::Core::Engine.routes.url_helpers.root_url(host: host)
151
+ end
152
+
153
+ def host
154
+ resource.organization.host
155
+ end
104
156
  end
105
157
  end
106
158
  end
@@ -6,10 +6,12 @@ require "decidim/meetings/test/factories"
6
6
 
7
7
  FactoryBot.define do
8
8
  factory :proposal_component, parent: :component do
9
- name { Decidim::Components::Namer.new(participatory_space.organization.available_locales, :proposals).i18n_name }
9
+ transient do
10
+ skip_injection { false }
11
+ end
12
+ name { generate_component_name(participatory_space.organization.available_locales, :proposals) }
10
13
  manifest_name { :proposals }
11
- participatory_space { create(:participatory_process, :with_steps, organization: organization) }
12
-
14
+ participatory_space { create(:participatory_process, :with_steps, organization: organization, skip_injection: skip_injection) }
13
15
  trait :with_endorsements_enabled do
14
16
  step_settings do
15
17
  {
@@ -250,28 +252,16 @@ FactoryBot.define do
250
252
  skip_injection { false }
251
253
  end
252
254
 
253
- title do
254
- if skip_injection
255
- Decidim::Faker::Localized.localized { generate(:title) }
256
- else
257
- Decidim::Faker::Localized.localized { "<script>alert(\"TITLE\");</script> #{generate(:title)}" }
258
- end
259
- end
260
- body do
261
- if skip_injection
262
- Decidim::Faker::Localized.localized { Faker::Lorem.sentences(number: 3).join("\n") }
263
- else
264
- Decidim::Faker::Localized.localized { "<script>alert(\"TITLE\");</script> #{Faker::Lorem.sentences(number: 3).join("\n")}" }
265
- end
266
- end
267
- component { create(:proposal_component) }
255
+ title { generate_localized_title(:proposal_title, skip_injection: skip_injection) }
256
+ body { generate_localized_description(:proposal_body, skip_injection: skip_injection) }
257
+ component { create(:proposal_component, skip_injection: skip_injection) }
268
258
  published_at { Time.current }
269
259
  address { "#{Faker::Address.street_name}, #{Faker::Address.city}" }
270
260
  latitude { Faker::Address.latitude }
271
261
  longitude { Faker::Address.longitude }
272
262
  cost { 20_000 }
273
- cost_report { { en: "My cost report" } }
274
- execution_period { { en: "My execution period" } }
263
+ cost_report { generate_localized_title(:proposal_cost_report, skip_injection: skip_injection) }
264
+ execution_period { generate_localized_title(:proposal_execution_period, skip_injection: skip_injection) }
275
265
 
276
266
  after(:build) do |proposal, evaluator|
277
267
  proposal.title = if evaluator.title.is_a?(String)
@@ -289,7 +279,7 @@ FactoryBot.define do
289
279
  proposal.body = Decidim::ContentProcessor.parse_with_processor(:hashtag, proposal.body, current_organization: proposal.organization).rewrite
290
280
 
291
281
  if proposal.component
292
- users = evaluator.users || [create(:user, :confirmed, organization: proposal.component.participatory_space.organization)]
282
+ users = evaluator.users || [create(:user, :confirmed, organization: proposal.component.participatory_space.organization, skip_injection: evaluator.skip_injection)]
293
283
  users.each_with_index do |user, idx|
294
284
  user_group = evaluator.user_groups[idx]
295
285
  proposal.coauthorships.build(author: user, user_group: user_group)
@@ -306,18 +296,18 @@ FactoryBot.define do
306
296
  end
307
297
 
308
298
  trait :participant_author do
309
- after :build do |proposal|
299
+ after :build do |proposal, evaluator|
310
300
  proposal.coauthorships.clear
311
- user = build(:user, organization: proposal.component.participatory_space.organization)
301
+ user = build(:user, organization: proposal.component.participatory_space.organization, skip_injection: evaluator.skip_injection)
312
302
  proposal.coauthorships.build(author: user)
313
303
  end
314
304
  end
315
305
 
316
306
  trait :user_group_author do
317
- after :build do |proposal|
307
+ after :build do |proposal, evaluator|
318
308
  proposal.coauthorships.clear
319
- user = create(:user, organization: proposal.component.participatory_space.organization)
320
- user_group = create(:user_group, :verified, organization: user.organization, users: [user])
309
+ user = create(:user, organization: proposal.component.participatory_space.organization, skip_injection: evaluator.skip_injection)
310
+ user_group = create(:user_group, :verified, organization: user.organization, users: [user], skip_injection: evaluator.skip_injection)
321
311
  proposal.coauthorships.build(author: user, user_group: user_group)
322
312
  end
323
313
  end
@@ -330,10 +320,10 @@ FactoryBot.define do
330
320
  end
331
321
 
332
322
  trait :official_meeting do
333
- after :build do |proposal|
323
+ after :build do |proposal, evaluator|
334
324
  proposal.coauthorships.clear
335
- component = build(:meeting_component, participatory_space: proposal.component.participatory_space)
336
- proposal.coauthorships.build(author: build(:meeting, component: component))
325
+ component = build(:meeting_component, participatory_space: proposal.component.participatory_space, skip_injection: evaluator.skip_injection)
326
+ proposal.coauthorships.build(author: build(:meeting, component: component, skip_injection: evaluator.skip_injection))
337
327
  end
338
328
  end
339
329
 
@@ -382,78 +372,101 @@ FactoryBot.define do
382
372
  end
383
373
 
384
374
  trait :hidden do
385
- after :create do |proposal|
386
- create(:moderation, hidden_at: Time.current, reportable: proposal)
375
+ after :create do |proposal, evaluator|
376
+ create(:moderation, hidden_at: Time.current, reportable: proposal, skip_injection: evaluator.skip_injection)
387
377
  end
388
378
  end
389
379
 
390
380
  trait :with_votes do
391
- after :create do |proposal|
392
- create_list(:proposal_vote, 5, proposal: proposal)
381
+ after :create do |proposal, evaluator|
382
+ create_list(:proposal_vote, 5, proposal: proposal, skip_injection: evaluator.skip_injection)
393
383
  end
394
384
  end
395
385
 
396
386
  trait :with_endorsements do
397
- after :create do |proposal|
387
+ after :create do |proposal, evaluator|
398
388
  5.times.collect do
399
- create(:endorsement, resource: proposal, author: build(:user, organization: proposal.participatory_space.organization))
389
+ create(:endorsement, resource: proposal, skip_injection: evaluator.skip_injection,
390
+ author: build(:user, organization: proposal.participatory_space.organization, skip_injection: evaluator.skip_injection))
400
391
  end
401
392
  end
402
393
  end
403
394
 
404
395
  trait :with_amendments do
405
- after :create do |proposal|
406
- create_list(:proposal_amendment, 5, amendable: proposal)
396
+ after :create do |proposal, evaluator|
397
+ create_list(:proposal_amendment, 5, amendable: proposal, skip_injection: evaluator.skip_injection)
407
398
  end
408
399
  end
409
400
 
410
401
  trait :with_photo do
411
- after :create do |proposal|
412
- proposal.attachments << create(:attachment, :with_image, attached_to: proposal)
402
+ after :create do |proposal, evaluator|
403
+ proposal.attachments << create(:attachment, :with_image, attached_to: proposal, skip_injection: evaluator.skip_injection)
413
404
  end
414
405
  end
415
406
 
416
407
  trait :with_document do
417
- after :create do |proposal|
418
- proposal.attachments << create(:attachment, :with_pdf, attached_to: proposal)
408
+ after :create do |proposal, evaluator|
409
+ proposal.attachments << create(:attachment, :with_pdf, attached_to: proposal, skip_injection: evaluator.skip_injection)
410
+ end
411
+ end
412
+
413
+ trait :moderated do
414
+ after(:create) do |proposal, evaluator|
415
+ create(:moderation, reportable: proposal, hidden_at: 2.days.ago, skip_injection: evaluator.skip_injection)
419
416
  end
420
417
  end
421
418
  end
422
419
 
423
420
  factory :proposal_vote, class: "Decidim::Proposals::ProposalVote" do
424
- proposal { build(:proposal) }
425
- author { build(:user, organization: proposal.organization) }
421
+ transient do
422
+ skip_injection { false }
423
+ end
424
+ proposal { build(:proposal, skip_injection: skip_injection) }
425
+ author { build(:user, organization: proposal.organization, skip_injection: skip_injection) }
426
426
  end
427
427
 
428
428
  factory :proposal_amendment, class: "Decidim::Amendment" do
429
- amendable { build(:proposal) }
430
- emendation { build(:proposal, component: amendable.component) }
431
- amender { build(:user, organization: amendable.component.participatory_space.organization) }
429
+ transient do
430
+ skip_injection { false }
431
+ end
432
+ amendable { build(:proposal, skip_injection: skip_injection) }
433
+ emendation { build(:proposal, component: amendable.component, skip_injection: skip_injection) }
434
+ amender { build(:user, organization: amendable.component.participatory_space.organization, skip_injection: skip_injection) }
432
435
  state { Decidim::Amendment::STATES.sample }
433
436
  end
434
437
 
435
438
  factory :proposal_note, class: "Decidim::Proposals::ProposalNote" do
436
- body { Faker::Lorem.sentences(number: 3).join("\n") }
437
- proposal { build(:proposal) }
438
- author { build(:user, organization: proposal.organization) }
439
+ transient do
440
+ skip_injection { false }
441
+ end
442
+ body do
443
+ if skip_injection
444
+ generate(:title)
445
+ else
446
+ "<script>alert(\"proposal_note_body\");</script> #{generate(:title)}"
447
+ end
448
+ end
449
+ proposal { build(:proposal, skip_injection: skip_injection) }
450
+ author { build(:user, organization: proposal.organization, skip_injection: skip_injection) }
439
451
  end
440
452
 
441
453
  factory :collaborative_draft, class: "Decidim::Proposals::CollaborativeDraft" do
442
454
  transient do
443
455
  users { nil }
456
+ skip_injection { false }
444
457
  # user_groups correspondence to users is by sorting order
445
458
  user_groups { [] }
446
459
  end
447
460
 
448
- title { "<script>alert(\"TITLE\");</script> #{generate(:title)}" }
449
- body { "<script>alert(\"BODY\");</script>\n#{Faker::Lorem.sentences(number: 3).join("\n")}" }
450
- component { create(:proposal_component) }
461
+ title { generate_localized_title(:collaborative_draft_title, skip_injection: skip_injection)["en"] }
462
+ body { generate_localized_description(:collaborative_draft_body, skip_injection: skip_injection)["en"] }
463
+ component { create(:proposal_component, skip_injection: skip_injection) }
451
464
  address { "#{Faker::Address.street_name}, #{Faker::Address.city}" }
452
465
  state { "open" }
453
466
 
454
467
  after(:build) do |collaborative_draft, evaluator|
455
468
  if collaborative_draft.component
456
- users = evaluator.users || [create(:user, organization: collaborative_draft.component.participatory_space.organization)]
469
+ users = evaluator.users || [create(:user, organization: collaborative_draft.component.participatory_space.organization, skip_injection: evaluator.skip_injection)]
457
470
  users.each_with_index do |user, idx|
458
471
  user_group = evaluator.user_groups[idx]
459
472
  collaborative_draft.coauthorships.build(author: user, user_group: user_group)
@@ -476,17 +489,23 @@ FactoryBot.define do
476
489
  end
477
490
 
478
491
  factory :participatory_text, class: "Decidim::Proposals::ParticipatoryText" do
479
- title { { en: "<script>alert(\"TITLE\");</script> #{generate(:title)}" } }
480
- description { { en: "<script>alert(\"DESCRIPTION\");</script>\n#{Faker::Lorem.sentences(number: 3).join("\n")}" } }
481
- component { create(:proposal_component) }
492
+ transient do
493
+ skip_injection { false }
494
+ end
495
+ title { generate_localized_title(:participatory_text_title, skip_injection: skip_injection) }
496
+ description { generate_localized_description(:participatory_text_description, skip_injection: skip_injection) }
497
+ component { create(:proposal_component, skip_injection: skip_injection) }
482
498
  end
483
499
 
484
500
  factory :valuation_assignment, class: "Decidim::Proposals::ValuationAssignment" do
501
+ transient do
502
+ skip_injection { false }
503
+ end
485
504
  proposal
486
505
  valuator_role do
487
506
  space = proposal.component.participatory_space
488
507
  organization = space.organization
489
- build :participatory_process_user_role, role: :valuator, user: build(:user, organization: organization)
508
+ build :participatory_process_user_role, role: :valuator, skip_injection: skip_injection, user: build(:user, organization: organization, skip_injection: skip_injection)
490
509
  end
491
510
  end
492
511
  end
@@ -8,7 +8,8 @@ module Decidim
8
8
  include Decidim::Comments::Commentable
9
9
 
10
10
  included do
11
- has_many :valuation_assignments, foreign_key: "decidim_proposal_id", dependent: :destroy
11
+ has_many :valuation_assignments, foreign_key: "decidim_proposal_id", dependent: :destroy,
12
+ counter_cache: :valuation_assignments_count, class_name: "Decidim::Proposals::ValuationAssignment"
12
13
 
13
14
  def valuators
14
15
  valuator_role_ids = valuation_assignments.where(proposal: self).pluck(:valuator_role_id)