decidim-proposals 0.25.0.rc4 → 0.26.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/proposals/collaborative_draft_m_cell.rb +1 -1
  3. data/app/cells/decidim/proposals/cost_report_cell.rb +3 -3
  4. data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +1 -1
  5. data/app/cells/decidim/proposals/proposal_m_cell.rb +4 -5
  6. data/app/cells/decidim/proposals/proposals_picker_cell.rb +7 -5
  7. data/app/commands/decidim/proposals/update_proposal.rb +3 -2
  8. data/app/controllers/concerns/decidim/proposals/orderable.rb +21 -8
  9. data/app/controllers/decidim/proposals/admin/proposals_merges_controller.rb +4 -1
  10. data/app/controllers/decidim/proposals/admin/proposals_splits_controller.rb +4 -1
  11. data/app/controllers/decidim/proposals/proposals_controller.rb +6 -3
  12. data/app/events/decidim/proposals/proposal_mentioned_event.rb +8 -0
  13. data/app/events/decidim/proposals/publish_proposal_event.rb +26 -0
  14. data/app/forms/decidim/proposals/admin/proposals_file_import_form.rb +31 -0
  15. data/app/forms/decidim/proposals/admin/proposals_fork_form.rb +8 -3
  16. data/app/helpers/decidim/proposals/application_helper.rb +1 -6
  17. data/app/helpers/decidim/proposals/map_helper.rb +1 -1
  18. data/app/helpers/decidim/proposals/proposals_helper.rb +1 -1
  19. data/app/models/decidim/proposals/proposal.rb +4 -3
  20. data/app/packs/src/decidim/proposals/add_proposal.js +8 -2
  21. data/app/packs/src/decidim/proposals/admin/proposals_picker.js +15 -0
  22. data/app/presenters/decidim/proposals/proposal_presenter.rb +2 -48
  23. data/app/queries/decidim/proposals/similar_proposals.rb +20 -5
  24. data/app/services/decidim/proposals/proposal_search.rb +9 -4
  25. data/app/views/decidim/proposals/admin/imports/_proposals_fields.html.erb +11 -0
  26. data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +7 -2
  27. data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +1 -1
  28. data/app/views/decidim/proposals/collaborative_drafts/_filters_small_view.html.erb +3 -3
  29. data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +2 -2
  30. data/app/views/decidim/proposals/proposals/_filters.html.erb +2 -0
  31. data/app/views/decidim/proposals/proposals/_filters_small_view.html.erb +3 -3
  32. data/app/views/decidim/proposals/proposals/_proposals.html.erb +18 -0
  33. data/app/views/decidim/proposals/proposals/index.html.erb +0 -5
  34. data/app/views/decidim/proposals/proposals/participatory_texts/_index.html.erb +2 -2
  35. data/config/brakeman.ignore +88 -0
  36. data/config/locales/ar.yml +0 -5
  37. data/config/locales/bg.yml +0 -2
  38. data/config/locales/ca.yml +4 -5
  39. data/config/locales/cs.yml +60 -5
  40. data/config/locales/de.yml +0 -5
  41. data/config/locales/el.yml +0 -5
  42. data/config/locales/en.yml +57 -6
  43. data/config/locales/es-MX.yml +3 -5
  44. data/config/locales/es-PY.yml +3 -5
  45. data/config/locales/es.yml +59 -5
  46. data/config/locales/eu.yml +230 -8
  47. data/config/locales/fi-plain.yml +54 -5
  48. data/config/locales/fi.yml +56 -5
  49. data/config/locales/fr-CA.yml +63 -5
  50. data/config/locales/fr.yml +64 -6
  51. data/config/locales/ga-IE.yml +274 -0
  52. data/config/locales/gl.yml +55 -6
  53. data/config/locales/hu.yml +0 -5
  54. data/config/locales/id-ID.yml +0 -4
  55. data/config/locales/is-IS.yml +0 -2
  56. data/config/locales/it.yml +13 -5
  57. data/config/locales/ja.yml +78 -30
  58. data/config/locales/lb.yml +40 -0
  59. data/config/locales/lv.yml +0 -5
  60. data/config/locales/nl.yml +57 -5
  61. data/config/locales/no.yml +0 -5
  62. data/config/locales/pl.yml +7 -12
  63. data/config/locales/pt-BR.yml +1 -6
  64. data/config/locales/pt.yml +96 -5
  65. data/config/locales/ro-RO.yml +467 -382
  66. data/config/locales/ru.yml +0 -2
  67. data/config/locales/sk.yml +0 -5
  68. data/config/locales/sr-CS.yml +0 -1
  69. data/config/locales/sv.yml +54 -5
  70. data/config/locales/tr-TR.yml +0 -5
  71. data/config/locales/uk.yml +0 -2
  72. data/config/locales/val-ES.yml +1 -0
  73. data/config/locales/zh-CN.yml +0 -5
  74. data/lib/decidim/proposals/component.rb +37 -4
  75. data/lib/decidim/proposals/engine.rb +4 -0
  76. data/lib/decidim/proposals/import/proposal_answer_creator.rb +95 -0
  77. data/lib/decidim/proposals/import/proposal_creator.rb +124 -0
  78. data/lib/decidim/proposals/import/proposals_answers_verifier.rb +29 -0
  79. data/lib/decidim/proposals/import/proposals_verifier.rb +16 -0
  80. data/lib/decidim/proposals/import.rb +12 -0
  81. data/lib/decidim/proposals/proposal_serializer.rb +6 -3
  82. data/lib/decidim/proposals/test/factories.rb +1 -9
  83. data/lib/decidim/proposals/version.rb +1 -1
  84. data/lib/decidim/proposals.rb +1 -1
  85. metadata +34 -25
  86. data/lib/decidim/proposals/proposal_creator.rb +0 -98
@@ -82,7 +82,6 @@ ru:
82
82
  step:
83
83
  announcement: Объявление
84
84
  comments_blocked: Комментарии отключены
85
- creation_enabled: Включена возможность создания предложений
86
85
  endorsements_blocked: Возможность выразить поддержку отключена
87
86
  endorsements_enabled: Возможность выразить поддержку включена
88
87
  proposal_answering_enabled: Включена возможность отвечать на предложения
@@ -122,7 +121,6 @@ ru:
122
121
  proposal_published_for_space:
123
122
  email_intro: В "%{participatory_space_title}", за которым вы следите, добавлено предложение "%{resource_title}".
124
123
  email_outro: Вы получили это уведомление, потому что вы следите за «%{participatory_space_title}». Вы можете перестать за ним следить, перейдя по приведенной выше ссылке.
125
- notification_title: В %{participatory_space_title} было добавлено предложение <a href="%{resource_path}">%{resource_title}</a>
126
124
  proposal_rejected:
127
125
  follower:
128
126
  email_intro: 'Предложение "%{resource_title}" было отклонено. Вы можете прочитать ответ на странице:'
@@ -106,7 +106,6 @@ sk:
106
106
  name: Návrhy
107
107
  settings:
108
108
  global:
109
- allow_card_image: Povoliť kartové obrázky
110
109
  amendments_enabled: Pozmeňujúce návrhy povolené
111
110
  amendments_enabled_help: Ak je aktívne, nastavte funkcie Pozmeňujúcich návrhov pre každý krok.
112
111
  amendments_wizard_help_text: Sprievodca Pozmeňujúcimi návrhmi
@@ -147,7 +146,6 @@ sk:
147
146
  answers_with_costs: Povoliť náklady v rámci odpovedí na návrhy
148
147
  automatic_hashtags: Do všetkých návrhov boli pridané značky hashtags
149
148
  comments_blocked: Komentáre boli blokované
150
- creation_enabled: Vytváranie návrhu je povolené
151
149
  endorsements_blocked: Schvaľovanie blokované
152
150
  endorsements_enabled: Schvaľovanie povolené
153
151
  proposal_answering_enabled: Odpovedanie na návrh je povolené
@@ -234,7 +232,6 @@ sk:
234
232
  email_intro: Návrh "%{resource_title}" bol pridaný k "%{participatory_space_title}", ktorý sledujete.
235
233
  email_outro: Toto oznámenie ste dostali, pretože sledujete "%{participatory_space_title}". Môžete ho odhlásiť od predchádzajúceho odkazu.
236
234
  email_subject: Nový návrh "%{resource_title}" bol pridaný k%{participatory_space_title}
237
- notification_title: Návrh <a href="%{resource_path}">%{resource_title} </a> bol pridaný do%{participatory_space_title}
238
235
  proposal_rejected:
239
236
  affected_user:
240
237
  email_intro: 'Váš návrh "%{resource_title}" bol zamietnutý. Odpoveď môžete čítať na tejto stránke: '
@@ -471,11 +468,9 @@ sk:
471
468
  select_states: Skontrolujte stav návrhov, ktoré chcete importovať
472
469
  proposals_merges:
473
470
  create:
474
- invalid: Pri prepojení vybraných návrhov došlo k chybe.
475
471
  success: Projekty boli úspešne zlúčené do novej.
476
472
  proposals_splits:
477
473
  create:
478
- invalid: Pri výbere vybraných návrhov došlo k chybe.
479
474
  success: Úspešne rozdelil návrhy na nové.
480
475
  valuation_assignments:
481
476
  create:
@@ -24,7 +24,6 @@ sr:
24
24
  proposals:
25
25
  settings:
26
26
  global:
27
- allow_card_image: Dozvoli sliku kartice
28
27
  new_proposal_body_template: Novi predlog šablona glavnog teksta
29
28
  new_proposal_body_template_help: Možete da definišete tekst koji će se pojavljivati pri kreiranju novog predloga
30
29
  step:
@@ -57,6 +57,16 @@ sv:
57
57
  identical: OCH titeln kan inte vara identisk
58
58
  title:
59
59
  identical: OCH innehållet kan inte vara identiskt
60
+ proposals_merge:
61
+ attributes:
62
+ base:
63
+ not_official: Är inte officiella
64
+ supported: Har fått stöd eller instämmande
65
+ proposals_split:
66
+ attributes:
67
+ base:
68
+ not_official: Är inte officiella
69
+ supported: Har fått stöd eller instämmande
60
70
  models:
61
71
  decidim/proposals/accepted_proposal_event: Förslag accepterat
62
72
  decidim/proposals/admin/update_proposal_category_event: Förslagskategori ändrad
@@ -125,7 +135,6 @@ sv:
125
135
  name: Förslag
126
136
  settings:
127
137
  global:
128
- allow_card_image: Tillåt kortbild
129
138
  amendments_enabled: Ändringar möjliga
130
139
  amendments_enabled_help: Om aktivt, konfigurera ändringsfunktioner till varje steg.
131
140
  amendments_wizard_help_text: Hjälptext för guiden för ändringsförslag
@@ -135,6 +144,17 @@ sv:
135
144
  collaborative_drafts_enabled: Samarbetsutkast aktiverat
136
145
  comments_enabled: Kommentarer aktiverade
137
146
  comments_max_length: Maximal längd för kommentarer (Lämna 0 för standardvärde)
147
+ default_sort_order: Förvald produkt sortering
148
+ default_sort_order_help: Förinställt innebär att om stödet är aktiverat kommer förslagen sorteras slumpmässigt, och om stöden är blockerade kommer de att sorteras efter mest stödda.
149
+ default_sort_order_options:
150
+ default: Förinställt
151
+ most_commented: Mest kommenterade
152
+ most_endorsed: Mest instämda i
153
+ most_followed: Mest följda
154
+ most_voted: Mest stödda
155
+ random: Slumpmässigt
156
+ recent: Senaste
157
+ with_more_authors: Med fler författare
138
158
  geocoding_enabled: Geokodning aktiverad
139
159
  minimum_votes_per_user: Minsta antal stöd per användare
140
160
  new_proposal_body_template: Innehållsmall för nytt förslag
@@ -176,7 +196,17 @@ sv:
176
196
  answers_with_costs: Tillåt kostnader i svar på förslag
177
197
  automatic_hashtags: Hashtags läggs till i alla förslag
178
198
  comments_blocked: Kommentarer blockerade
179
- creation_enabled: Skapande av förslag aktiverat
199
+ default_sort_order: Förvald produkt sortering
200
+ default_sort_order_help: Förinställt innebär att om stödet är aktiverat kommer förslagen sorteras slumpmässigt, och om stöden är blockerade kommer de att sorteras efter mest stödda.
201
+ default_sort_order_options:
202
+ default: Förinställt
203
+ most_commented: Mest kommenterade
204
+ most_endorsed: Mest instämda i
205
+ most_followed: Mest följda
206
+ most_voted: Mest stödda
207
+ random: Slumpmässigt
208
+ recent: Senaste
209
+ with_more_authors: Med fler författare
180
210
  endorsements_blocked: Instämmanden är blockerade
181
211
  endorsements_enabled: Instämmanden aktiverade
182
212
  proposal_answering_enabled: Svar på förslag aktiverat
@@ -269,7 +299,6 @@ sv:
269
299
  email_intro: Förslaget "%{resource_title}" har lagts till i "%{participatory_space_title}" som du följer.
270
300
  email_outro: Du har fått det här meddelandet eftersom du följer "%{participatory_space_title}". Du kan sluta att ta emot meddelanden genom att följa föregående länk.
271
301
  email_subject: Nytt förslag "%{resource_title}" lades till %{participatory_space_title}
272
- notification_title: Förslaget <a href="%{resource_path}">%{resource_title}</a> har lagts till %{participatory_space_title}
273
302
  proposal_rejected:
274
303
  affected_user:
275
304
  email_intro: 'Ditt förslag "%{resource_title}" har avslagits. Du kan läsa svaret på den här sidan:'
@@ -366,6 +395,23 @@ sv:
366
395
  exports:
367
396
  proposal_comments: Kommentarer
368
397
  proposals: Förslag
398
+ imports:
399
+ help:
400
+ answers: 'Importdokumentet ska innehålla följande kolumner: id, state (accepterat, utvärderat, avvisat), answer/sv, answer/en (och andra språk aktiverade för organisationen).'
401
+ proposals: Filen måste ha kolumnnamn title/sv och body/sv (eller ett annat språk som du föredrar t. ex.. title/en och body/en). Även scope/id och category/id kolumner stöds.
402
+ label:
403
+ answers: Importera svar från en fil
404
+ proposals: Importerar förslag från en fil
405
+ resources:
406
+ answers:
407
+ one: svar till förslaget
408
+ other: svar till förslaget
409
+ proposals:
410
+ one: förslag
411
+ other: förslag
412
+ title:
413
+ answers: Importera svar till förslag
414
+ proposals: Importera förslag
369
415
  models:
370
416
  proposal:
371
417
  name: Förslag
@@ -509,11 +555,11 @@ sv:
509
555
  title: Importera förslag
510
556
  proposals_merges:
511
557
  create:
512
- invalid: Det gick inte att slå samman de valda förslagen.
558
+ invalid: 'Det gick inte att slå samman de valda förslagen på grund av vissa av dem:'
513
559
  success: Förslagen har sammanfogats till ett nytt förslag.
514
560
  proposals_splits:
515
561
  create:
516
- invalid: Det gick inte att dela upp de valda förslagen.
562
+ invalid: 'Det gick inte att dela upp de valda förslagen på grund av vissa av dem:'
517
563
  success: Förslagen har delats upp till nya förslag.
518
564
  valuation_assignments:
519
565
  create:
@@ -753,9 +799,12 @@ sv:
753
799
  filter_by: Filtrera efter
754
800
  unfold: Veckla ut
755
801
  index:
802
+ click_here: Se alla förslag
756
803
  collaborative_drafts_list: Visa gemensamma utkast
757
804
  new_proposal: Nytt förslag
805
+ see_all: Se alla förslag
758
806
  see_all_withdrawn: Se alla tillbakadragna förslag
807
+ text_banner: Du tittar på listan över förslag som dragits tillbaka av deras författare. %{go_back_link}.
759
808
  view_proposal: Visa förslag
760
809
  linked_proposals:
761
810
  proposal_votes:
@@ -122,7 +122,6 @@ tr:
122
122
  name: Teklifler
123
123
  settings:
124
124
  global:
125
- allow_card_image: Kart resmine izin ver
126
125
  amendments_enabled: Değişiklikler etkinleştirildi
127
126
  amendments_enabled_help: Etkinse, her adım için Değişiklik özelliklerini yapılandırın.
128
127
  amendments_wizard_help_text: Değişiklik Sihirbazı yardım metni
@@ -169,7 +168,6 @@ tr:
169
168
  answers_with_costs: Teklif yanıtlarında maliyetleri etkinleştirin
170
169
  automatic_hashtags: Tüm tekliflere etiketler eklendi
171
170
  comments_blocked: Yorumlar engellendi
172
- creation_enabled: Teklif oluşturma etkin
173
171
  endorsements_blocked: Onaylar engellendi
174
172
  endorsements_enabled: Onaylar etkin
175
173
  proposal_answering_enabled: Teklif yanıtlama etkin
@@ -262,7 +260,6 @@ tr:
262
260
  email_intro: '"%{resource_title}" teklifi takip ettiğiniz "%{participatory_space_title}" listesine eklendi.'
263
261
  email_outro: Bu bildirimi, "%{participatory_space_title}" takip ettiğiniz için aldınız. Bir önceki bağlantıdan takip etmeyi bırakabilirsiniz.
264
262
  email_subject: Yeni teklif "%{resource_title}" %{participatory_space_title} eklendi
265
- notification_title: <a href="%{resource_path}">%{resource_title}</a> önerisi %{participatory_space_title} alanına eklendi
266
263
  proposal_rejected:
267
264
  affected_user:
268
265
  email_intro: 'Teklifiniz "%{resource_title}" reddedildi. Cevabı bu sayfada okuyabilirsiniz:'
@@ -501,11 +498,9 @@ tr:
501
498
  title: Teklifleri içe aktar
502
499
  proposals_merges:
503
500
  create:
504
- invalid: Seçilen teklifler birleştirilirken bir hata oluştu.
505
501
  success: Teklifler, yeni bir taneyle başarılı bir şekilde birleştirildi.
506
502
  proposals_splits:
507
503
  create:
508
- invalid: Seçilen teklifleri bölerken bir sorun vardı.
509
504
  success: Teklifleri başarılı bir şekilde yenilere ayırdı.
510
505
  valuation_assignments:
511
506
  create:
@@ -82,7 +82,6 @@ uk:
82
82
  step:
83
83
  announcement: Оголошення
84
84
  comments_blocked: Коментарі вимкнено
85
- creation_enabled: Внесення пропозицій увімкнено
86
85
  endorsements_blocked: Надання підтримки вимкнене
87
86
  endorsements_enabled: Надання підтримки увімкнено
88
87
  proposal_answering_enabled: Відповіді на пропозиції увімкнено
@@ -122,7 +121,6 @@ uk:
122
121
  proposal_published_for_space:
123
122
  email_intro: До "%{participatory_space_title}", за яким ви стежите, була додана пропозиція "%{resource_title}".
124
123
  email_outro: Ви отримали це сповіщення, тому що ви стежите за "%{participatory_space_title}". Ви можете припинити стежити за ним, перейшовши за наведеним вище посиланням.
125
- notification_title: До %{participatory_space_title} було додано пропозицію <a href="%{resource_path}">%{resource_title}</a>
126
124
  proposal_rejected:
127
125
  follower:
128
126
  email_intro: 'Пропозиція "%{resource_title}" була відхилена. Ви можете прочитати відповідь на сторінці:'
@@ -0,0 +1 @@
1
+ val:
@@ -115,7 +115,6 @@ zh-CN:
115
115
  name: 建议
116
116
  settings:
117
117
  global:
118
- allow_card_image: 允许卡片图像
119
118
  amendments_enabled: 修改已启用
120
119
  amendments_enabled_help: 如果激活,配置每一步的修正功能。
121
120
  amendments_wizard_help_text: 修正向导帮助文本
@@ -162,7 +161,6 @@ zh-CN:
162
161
  answers_with_costs: 启用建议答案的成本
163
162
  automatic_hashtags: 添加到所有建议的标签
164
163
  comments_blocked: 评论已阻止
165
- creation_enabled: 建议创建已启用
166
164
  endorsements_blocked: 已阻止授权
167
165
  endorsements_enabled: 授权已启用
168
166
  proposal_answering_enabled: 建议答案已启用
@@ -248,7 +246,6 @@ zh-CN:
248
246
  email_intro: 提议 "%{resource_title}" 已被添加到"%{participatory_space_title}",您正在关注它。
249
247
  email_outro: 您收到此通知是因为您正在关注 "%{participatory_space_title}"。您可以停止收到跟随上一个链接的通知。
250
248
  email_subject: 新提议 "%{resource_title}" 已添加到 %{participatory_space_title}
251
- notification_title: 提议 <a href="%{resource_path}">%{resource_title}</a> 已被添加到 %{participatory_space_title}
252
249
  proposal_rejected:
253
250
  affected_user:
254
251
  email_intro: '您的提议 "%{resource_title}" 已被拒绝。您可以在此页中读取答案:'
@@ -480,11 +477,9 @@ zh-CN:
480
477
  select_states: 检查要导入的建议的状态
481
478
  proposals_merges:
482
479
  create:
483
- invalid: 合并选定的建议时出现问题。
484
480
  success: 成功地将提案合并为一个新提案。
485
481
  proposals_splits:
486
482
  create:
487
- invalid: 在分割选定的建议时遇到问题。
488
483
  success: 成功地将建议分成新的建议。
489
484
  valuation_assignments:
490
485
  create:
@@ -22,6 +22,8 @@ Decidim.register_component(:proposals) do |component|
22
22
 
23
23
  component.permissions_class_name = "Decidim::Proposals::Permissions"
24
24
 
25
+ POSSIBLE_SORT_ORDERS = %w(default random recent most_endorsed most_voted most_commented most_followed with_more_authors).freeze
26
+
25
27
  component.settings(:global) do |settings|
26
28
  settings.attribute :scopes_enabled, type: :boolean, default: false
27
29
  settings.attribute :scope_id, type: :scope
@@ -34,12 +36,12 @@ Decidim.register_component(:proposals) do |component|
34
36
  settings.attribute :threshold_per_proposal, type: :integer, default: 0
35
37
  settings.attribute :can_accumulate_supports_beyond_threshold, type: :boolean, default: false
36
38
  settings.attribute :proposal_answering_enabled, type: :boolean, default: true
39
+ settings.attribute :default_sort_order, type: :select, default: "default", choices: -> { POSSIBLE_SORT_ORDERS }
37
40
  settings.attribute :official_proposals_enabled, type: :boolean, default: true
38
41
  settings.attribute :comments_enabled, type: :boolean, default: true
39
42
  settings.attribute :comments_max_length, type: :integer, required: false
40
43
  settings.attribute :geocoding_enabled, type: :boolean, default: false
41
44
  settings.attribute :attachments_allowed, type: :boolean, default: false
42
- settings.attribute :allow_card_image, type: :boolean, default: false
43
45
  settings.attribute :resources_permissions_enabled, type: :boolean, default: true
44
46
  settings.attribute :collaborative_drafts_enabled, type: :boolean, default: false
45
47
  settings.attribute :participatory_texts_enabled,
@@ -65,6 +67,7 @@ Decidim.register_component(:proposals) do |component|
65
67
  settings.attribute :comments_blocked, type: :boolean, default: false
66
68
  settings.attribute :creation_enabled, type: :boolean
67
69
  settings.attribute :proposal_answering_enabled, type: :boolean, default: true
70
+ settings.attribute :default_sort_order, type: :select, include_blank: true, choices: -> { POSSIBLE_SORT_ORDERS }
68
71
  settings.attribute :publish_answers_immediately, type: :boolean, default: true
69
72
  settings.attribute :answers_with_costs, type: :boolean, default: false
70
73
  settings.attribute :amendment_creation_enabled, type: :boolean, default: true
@@ -128,7 +131,7 @@ Decidim.register_component(:proposals) do |component|
128
131
  collection = Decidim::Proposals::Proposal
129
132
  .published
130
133
  .where(component: component_instance)
131
- .includes(:category, :component)
134
+ .includes(:scope, :category, :component)
132
135
 
133
136
  if space.user_roles(:valuator).where(user: user).any?
134
137
  collection.with_valuation_assigned_to(user, space)
@@ -146,7 +149,7 @@ Decidim.register_component(:proposals) do |component|
146
149
  exports.collection do |component_instance|
147
150
  Decidim::Comments::Export.comments_for_resource(
148
151
  Decidim::Proposals::Proposal, component_instance
149
- )
152
+ ).includes(:author, :user_group, root_commentable: { component: { participatory_space: :organization } })
150
153
  end
151
154
 
152
155
  exports.include_in_open_data = true
@@ -155,7 +158,37 @@ Decidim.register_component(:proposals) do |component|
155
158
  end
156
159
 
157
160
  component.imports :proposals do |imports|
158
- imports.creator Decidim::Proposals::ProposalCreator
161
+ imports.form_view = "decidim/proposals/admin/imports/proposals_fields"
162
+ imports.form_class_name = "Decidim::Proposals::Admin::ProposalsFileImportForm"
163
+
164
+ imports.messages do |msg|
165
+ msg.set(:resource_name) { |count: 1| I18n.t("decidim.proposals.admin.imports.resources.proposals", count: count) }
166
+ msg.set(:title) { I18n.t("decidim.proposals.admin.imports.title.proposals") }
167
+ msg.set(:label) { I18n.t("decidim.proposals.admin.imports.label.proposals") }
168
+ msg.set(:help) { I18n.t("decidim.proposals.admin.imports.help.proposals") }
169
+ end
170
+
171
+ imports.creator Decidim::Proposals::Import::ProposalCreator
172
+ end
173
+
174
+ component.imports :answers do |imports|
175
+ imports.messages do |msg|
176
+ msg.set(:resource_name) { |count: 1| I18n.t("decidim.proposals.admin.imports.resources.answers", count: count) }
177
+ msg.set(:title) { I18n.t("decidim.proposals.admin.imports.title.answers") }
178
+ msg.set(:label) { I18n.t("decidim.proposals.admin.imports.label.answers") }
179
+ msg.set(:help) { I18n.t("decidim.proposals.admin.imports.help.answers") }
180
+ end
181
+
182
+ imports.creator Decidim::Proposals::Import::ProposalAnswerCreator
183
+ imports.example do |import_component|
184
+ organization = import_component.organization
185
+ [
186
+ %w(id state) + organization.available_locales.map { |l| "answer/#{l}" },
187
+ [1, "accepted"] + organization.available_locales.map { "Example answer" },
188
+ [2, "rejected"] + organization.available_locales.map { "Example answer" },
189
+ [3, "evaluating"] + organization.available_locales.map { "Example answer" }
190
+ ]
191
+ end
159
192
  end
160
193
 
161
194
  component.seeds do |participatory_space|
@@ -198,6 +198,10 @@ module Decidim
198
198
  metric_operation.manager_class = "Decidim::Proposals::Metrics::ProposalFollowersMetricMeasure"
199
199
  end
200
200
  end
201
+
202
+ initializer "decidim_proposals.webpacker.assets_path" do
203
+ Decidim.register_assets_path File.expand_path("app/packs", root)
204
+ end
201
205
  end
202
206
  end
203
207
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Import
6
+ # This class is responsible for creating the imported proposal answers
7
+ # and must be included in proposals component's import manifest.
8
+ class ProposalAnswerCreator < Decidim::Admin::Import::Creator
9
+ POSSIBLE_ANSWER_STATES = %w(evaluating accepted rejected).freeze
10
+
11
+ # Retuns the resource class to be created with the provided data.
12
+ def self.resource_klass
13
+ Decidim::Proposals::Proposal
14
+ end
15
+
16
+ # Returns a verifier class to be used to verify the correctness of the
17
+ # import data.
18
+ def self.verifier_klass
19
+ Decidim::Proposals::Import::ProposalsAnswersVerifier
20
+ end
21
+
22
+ # Add answer to proposal
23
+ #
24
+ # Returns a proposal
25
+ def produce
26
+ resource
27
+ end
28
+
29
+ def finish!
30
+ Decidim.traceability.perform_action!(
31
+ "answer",
32
+ resource,
33
+ current_user
34
+ ) do
35
+ resource.save!
36
+ end
37
+ notify(resource)
38
+ end
39
+
40
+ private
41
+
42
+ def resource
43
+ @resource ||= begin
44
+ proposal = Decidim::Proposals::Proposal.find_by(id: id)
45
+ return nil unless proposal
46
+ return nil if proposal.emendation?
47
+
48
+ if proposal.component != component
49
+ proposal.errors.add(:component, :invalid)
50
+ return proposal
51
+ end
52
+
53
+ proposal.answer = answer
54
+ proposal.answered_at = Time.current
55
+ if POSSIBLE_ANSWER_STATES.include?(state)
56
+ proposal.state = state
57
+ proposal.state_published_at = Time.current if component.current_settings.publish_answers_immediately?
58
+ else
59
+ proposal.errors.add(:state, :invalid)
60
+ end
61
+ proposal
62
+ end
63
+ end
64
+
65
+ def id
66
+ data[:id].to_i
67
+ end
68
+
69
+ def state
70
+ data[:state]
71
+ end
72
+
73
+ def answer
74
+ locale_hasher("answer", available_locales)
75
+ end
76
+
77
+ def available_locales
78
+ @available_locales ||= component.participatory_space.organization.available_locales
79
+ end
80
+
81
+ def component
82
+ context[:current_component]
83
+ end
84
+
85
+ def current_user
86
+ context[:current_user]
87
+ end
88
+
89
+ def notify(proposal)
90
+ ::Decidim::Proposals::Admin::NotifyProposalAnswer.call(proposal, proposal.state)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Import
6
+ # This class is responsible for creating the imported proposals
7
+ # and must be included in proposals component's import manifest.
8
+ class ProposalCreator < Decidim::Admin::Import::Creator
9
+ # Retuns the resource class to be created with the provided data.
10
+ def self.resource_klass
11
+ Decidim::Proposals::Proposal
12
+ end
13
+
14
+ # Returns a verifier class to be used to verify the correctness of the
15
+ # import data.
16
+ def self.verifier_klass
17
+ Decidim::Proposals::Import::ProposalsVerifier
18
+ end
19
+
20
+ def initialize(data, context = nil)
21
+ @data = data.except(:id, "id")
22
+ @context = context
23
+ end
24
+
25
+ # Produces a proposal from parsed data
26
+ #
27
+ # Returns a proposal
28
+ def produce
29
+ resource.add_coauthor(context[:current_user], user_group: context[:user_group])
30
+
31
+ resource
32
+ end
33
+
34
+ # Saves the proposal
35
+ def finish!
36
+ super # resource.save!
37
+ notify(resource)
38
+ publish(resource)
39
+ end
40
+
41
+ private
42
+
43
+ def resource
44
+ @resource ||= Decidim::Proposals::Proposal.new(
45
+ category: category,
46
+ scope: scope,
47
+ title: title,
48
+ body: body,
49
+ address: address,
50
+ latitude: latitude,
51
+ longitude: longitude,
52
+ component: component,
53
+ published_at: Time.current
54
+ )
55
+ end
56
+
57
+ def category
58
+ id = data.has_key?(:category) ? data[:category]["id"] : data[:"category/id"].to_i
59
+ Decidim::Category.find_by(id: id)
60
+ end
61
+
62
+ def scope
63
+ id = data.has_key?(:scope) ? data[:scope]["id"] : data[:"scope/id"].to_i
64
+ Decidim::Scope.find_by(id: id)
65
+ end
66
+
67
+ def title
68
+ locale_hasher("title", available_locales)
69
+ end
70
+
71
+ def body
72
+ locale_hasher("body", available_locales)
73
+ end
74
+
75
+ def address
76
+ data.has_key?(:address) ? data[:address] : nil
77
+ end
78
+
79
+ def latitude
80
+ data.has_key?(:latitude) ? data[:latitude] : nil
81
+ end
82
+
83
+ def longitude
84
+ data.has_key?(:longitude) ? data[:longitude] : nil
85
+ end
86
+
87
+ def available_locales
88
+ @available_locales ||= component.participatory_space.organization.available_locales
89
+ end
90
+
91
+ def component
92
+ context[:current_component]
93
+ end
94
+
95
+ def notify(proposal)
96
+ return if proposal.coauthorships.empty?
97
+
98
+ Decidim::EventsManager.publish(
99
+ event: "decidim.events.proposals.proposal_published",
100
+ event_class: Decidim::Proposals::PublishProposalEvent,
101
+ resource: proposal,
102
+ followers: coauthors_followers(proposal)
103
+ )
104
+ end
105
+
106
+ def publish(proposal)
107
+ Decidim::EventsManager.publish(
108
+ event: "decidim.events.proposals.proposal_published",
109
+ event_class: Decidim::Proposals::PublishProposalEvent,
110
+ resource: proposal,
111
+ followers: proposal.participatory_space.followers - coauthors_followers(proposal),
112
+ extra: {
113
+ participatory_space: true
114
+ }
115
+ )
116
+ end
117
+
118
+ def coauthors_followers(proposal)
119
+ @coauthors_followers ||= proposal.authors.flat_map(&:followers)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Import
6
+ # This class is responsible for verifying the data for proposal answers
7
+ # import.
8
+ class ProposalsAnswersVerifier < Decidim::Admin::Import::Verifier
9
+ protected
10
+
11
+ def required_headers
12
+ %w(id state) + required_localized_headers("answer")
13
+ end
14
+
15
+ # Check if prepared resource is valid
16
+ #
17
+ # record - Decidim::Proposals::Proposal
18
+ #
19
+ # Returns true if record is valid
20
+ def valid_record?(record)
21
+ return false if record.nil?
22
+ return false if record.errors.any?
23
+
24
+ record.valid?
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Import
6
+ # This class is responsible for verifying the data for proposals import.
7
+ class ProposalsVerifier < Decidim::Admin::Import::Verifier
8
+ protected
9
+
10
+ def required_headers
11
+ required_localized_headers("title") + required_localized_headers("body")
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Import
6
+ autoload :ProposalAnswerCreator, "decidim/proposals/import/proposal_answer_creator"
7
+ autoload :ProposalCreator, "decidim/proposals/import/proposal_creator"
8
+ autoload :ProposalsAnswersVerifier, "decidim/proposals/import/proposals_answers_verifier"
9
+ autoload :ProposalsVerifier, "decidim/proposals/import/proposals_verifier"
10
+ end
11
+ end
12
+ end