decidim-proposals 0.20.1 → 0.23.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (266) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/admin/decidim_proposals_manifest.js +1 -0
  3. data/app/assets/images/decidim/gamification/badges/accepted_proposals.svg +1 -234
  4. data/app/assets/images/decidim/gamification/badges/proposal_votes.svg +1 -95
  5. data/app/assets/images/decidim/gamification/badges/proposals.svg +1 -229
  6. data/app/assets/images/decidim/proposals/icon.svg +1 -3
  7. data/app/assets/javascripts/decidim/proposals/add_proposal.js.es6 +6 -0
  8. data/app/assets/javascripts/decidim/proposals/admin/proposals.es6 +24 -11
  9. data/app/assets/javascripts/decidim/proposals/admin/proposals_form.js.es6 +3 -5
  10. data/app/assets/javascripts/decidim/proposals/admin/proposals_picker.js.es6 +35 -0
  11. data/app/cells/decidim/proposals/collaborative_draft_cell.rb +1 -1
  12. data/app/cells/decidim/proposals/collaborative_draft_link_to_proposal_cell.rb +1 -1
  13. data/app/cells/decidim/proposals/collaborative_draft_m/footer.erb +1 -1
  14. data/app/cells/decidim/proposals/collaborative_draft_m_cell.rb +1 -1
  15. data/app/cells/decidim/proposals/cost_report/show.erb +35 -0
  16. data/app/cells/decidim/proposals/cost_report_cell.rb +42 -0
  17. data/app/cells/decidim/proposals/highlighted_proposals_for_component/show.erb +3 -3
  18. data/app/cells/decidim/proposals/highlighted_proposals_for_component_cell.rb +1 -1
  19. data/app/cells/decidim/proposals/irreversible_action_modal/show.erb +2 -2
  20. data/app/cells/decidim/proposals/irreversible_action_modal_cell.rb +1 -1
  21. data/app/cells/decidim/proposals/participatory_text_proposal/buttons.erb +3 -3
  22. data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +2 -2
  23. data/app/cells/decidim/proposals/proposal_cell.rb +1 -1
  24. data/app/cells/decidim/proposals/proposal_m/footer.erb +4 -1
  25. data/app/cells/decidim/proposals/proposal_m_cell.rb +37 -9
  26. data/app/cells/decidim/proposals/proposal_tags/show.erb +18 -10
  27. data/app/cells/decidim/proposals/proposal_tags_cell.rb +5 -0
  28. data/app/cells/decidim/proposals/proposals_picker/proposals.erb +12 -0
  29. data/app/cells/decidim/proposals/proposals_picker/show.erb +14 -0
  30. data/app/cells/decidim/proposals/proposals_picker_cell.rb +72 -0
  31. data/app/commands/decidim/proposals/admin/answer_proposal.rb +24 -46
  32. data/app/commands/decidim/proposals/admin/assign_proposals_to_valuator.rb +61 -0
  33. data/app/commands/decidim/proposals/admin/create_proposal.rb +10 -3
  34. data/app/commands/decidim/proposals/admin/create_proposal_note.rb +15 -0
  35. data/app/commands/decidim/proposals/admin/notify_proposal_answer.rb +85 -0
  36. data/app/commands/decidim/proposals/admin/publish_answers.rb +67 -0
  37. data/app/commands/decidim/proposals/admin/publish_participatory_text.rb +6 -1
  38. data/app/commands/decidim/proposals/admin/unassign_proposals_from_valuator.rb +62 -0
  39. data/app/commands/decidim/proposals/admin/update_participatory_text.rb +10 -2
  40. data/app/commands/decidim/proposals/admin/update_proposal.rb +5 -3
  41. data/app/commands/decidim/proposals/admin/update_proposal_scope.rb +75 -0
  42. data/app/commands/decidim/proposals/create_collaborative_draft.rb +1 -1
  43. data/app/commands/decidim/proposals/create_proposal.rb +7 -3
  44. data/app/commands/decidim/proposals/gallery_methods.rb +2 -51
  45. data/app/commands/decidim/proposals/publish_collaborative_draft.rb +2 -2
  46. data/app/commands/decidim/proposals/update_proposal.rb +25 -9
  47. data/app/controllers/concerns/decidim/proposals/admin/filterable.rb +82 -0
  48. data/app/controllers/concerns/decidim/proposals/admin/picker.rb +21 -0
  49. data/app/controllers/concerns/decidim/proposals/orderable.rb +1 -1
  50. data/app/controllers/decidim/proposals/admin/proposal_answers_controller.rb +16 -6
  51. data/app/controllers/decidim/proposals/admin/proposal_notes_controller.rb +8 -9
  52. data/app/controllers/decidim/proposals/admin/proposals_controller.rb +107 -31
  53. data/app/controllers/decidim/proposals/admin/valuation_assignments_controller.rb +58 -0
  54. data/app/controllers/decidim/proposals/collaborative_drafts_controller.rb +10 -3
  55. data/app/controllers/decidim/proposals/proposals_controller.rb +30 -10
  56. data/app/controllers/decidim/proposals/versions_controller.rb +9 -16
  57. data/app/controllers/decidim/proposals/{proposal_widgets_controller.rb → widgets_controller.rb} +2 -2
  58. data/app/events/decidim/proposals/admin/proposal_note_created_event.rb +27 -0
  59. data/app/events/decidim/proposals/admin/update_proposal_scope_event.rb +11 -0
  60. data/app/forms/decidim/proposals/admin/import_participatory_text_form.rb +3 -1
  61. data/app/forms/decidim/proposals/admin/participatory_text_proposal_form.rb +20 -0
  62. data/app/forms/decidim/proposals/admin/preview_participatory_text_form.rb +2 -2
  63. data/app/forms/decidim/proposals/admin/proposal_answer_form.rb +27 -2
  64. data/app/forms/decidim/proposals/admin/proposal_base_form.rb +136 -0
  65. data/app/forms/decidim/proposals/admin/proposal_form.rb +6 -117
  66. data/app/forms/decidim/proposals/admin/valuation_assignment_form.rb +37 -0
  67. data/app/forms/decidim/proposals/proposal_form.rb +25 -12
  68. data/app/forms/decidim/proposals/proposal_wizard_create_step_form.rb +13 -1
  69. data/app/helpers/decidim/proposals/admin/filterable_helper.rb +17 -0
  70. data/app/helpers/decidim/proposals/admin/proposal_bulk_actions_helper.rb +35 -0
  71. data/app/helpers/decidim/proposals/admin/proposal_rankings_helper.rb +63 -0
  72. data/app/helpers/decidim/proposals/admin/proposals_helper.rb +124 -0
  73. data/app/helpers/decidim/proposals/admin/proposals_picker_helper.rb +30 -0
  74. data/app/helpers/decidim/proposals/application_helper.rb +54 -38
  75. data/app/helpers/decidim/proposals/collaborative_draft_helper.rb +9 -9
  76. data/app/helpers/decidim/proposals/control_version_helper.rb +1 -37
  77. data/app/helpers/decidim/proposals/proposal_cells_helper.rb +1 -1
  78. data/app/helpers/decidim/proposals/proposal_endorsements_helper.rb +0 -145
  79. data/app/helpers/decidim/proposals/proposal_votes_helper.rb +2 -2
  80. data/app/helpers/decidim/proposals/proposal_wizard_helper.rb +24 -7
  81. data/app/helpers/decidim/proposals/proposals_helper.rb +24 -0
  82. data/app/models/decidim/proposals/collaborative_draft.rb +2 -2
  83. data/app/models/decidim/proposals/participatory_text.rb +3 -0
  84. data/app/models/decidim/proposals/proposal.rb +152 -42
  85. data/app/models/decidim/proposals/valuation_assignment.rb +24 -0
  86. data/app/permissions/decidim/proposals/admin/permissions.rb +77 -11
  87. data/app/permissions/decidim/proposals/permissions.rb +1 -22
  88. data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +1 -1
  89. data/app/presenters/decidim/proposals/admin_log/valuation_assignment_presenter.rb +51 -0
  90. data/app/presenters/decidim/proposals/admin_log/value_types/proposal_title_body_presenter.rb +6 -1
  91. data/app/presenters/decidim/proposals/admin_log/value_types/valuator_role_user_presenter.rb +19 -0
  92. data/app/presenters/decidim/proposals/collaborative_draft_presenter.rb +2 -28
  93. data/app/presenters/decidim/proposals/log/valuation_assignment_presenter.rb +22 -0
  94. data/app/presenters/decidim/proposals/official_author_presenter.rb +1 -29
  95. data/app/presenters/decidim/proposals/proposal_presenter.rb +79 -5
  96. data/app/queries/decidim/proposals/metrics/accepted_proposals_metric_manage.rb +1 -2
  97. data/app/queries/decidim/proposals/metrics/endorsements_metric_manage.rb +15 -12
  98. data/app/queries/decidim/proposals/metrics/proposal_participants_metric_measure.rb +5 -4
  99. data/app/queries/decidim/proposals/metrics/proposals_metric_manage.rb +2 -8
  100. data/app/queries/decidim/proposals/metrics/votes_metric_manage.rb +3 -9
  101. data/app/queries/decidim/proposals/similar_proposals.rb +4 -4
  102. data/app/services/decidim/proposals/collaborative_draft_search.rb +8 -10
  103. data/app/services/decidim/proposals/diff_renderer.rb +17 -5
  104. data/app/services/decidim/proposals/proposal_builder.rb +9 -3
  105. data/app/services/decidim/proposals/proposal_search.rb +11 -69
  106. data/app/types/decidim/proposals/proposal_input_filter.rb +29 -0
  107. data/app/types/decidim/proposals/proposal_input_sort.rb +22 -0
  108. data/app/types/decidim/proposals/proposal_type.rb +34 -13
  109. data/app/types/decidim/proposals/proposals_type.rb +22 -15
  110. data/app/validators/proposal_length_validator.rb +38 -0
  111. data/app/views/decidim/proposals/admin/participatory_texts/index.html.erb +9 -1
  112. data/app/views/decidim/proposals/admin/proposal_answers/_form.html.erb +35 -0
  113. data/app/views/decidim/proposals/admin/proposal_notes/_form.html.erb +1 -1
  114. data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes.html.erb +3 -3
  115. data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +8 -2
  116. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +8 -28
  117. data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +26 -27
  118. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_assign_to_valuator.html.erb +15 -0
  119. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_dropdown.html.erb +21 -1
  120. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_publish_answers.html.erb +14 -0
  121. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_scope-change.html.erb +25 -0
  122. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_unassign_from_valuator.html.erb +15 -0
  123. data/app/views/decidim/proposals/admin/proposals/index.html.erb +18 -9
  124. data/app/views/decidim/proposals/admin/proposals/publish_answers.js.erb +12 -0
  125. data/app/views/decidim/proposals/admin/proposals/show.html.erb +186 -0
  126. data/app/views/decidim/proposals/admin/proposals/update_category.js.erb +3 -2
  127. data/app/views/decidim/proposals/admin/proposals/update_scope.js.erb +27 -0
  128. data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +11 -9
  129. data/app/views/decidim/proposals/collaborative_drafts/_filters.html.erb +10 -8
  130. data/app/views/decidim/proposals/collaborative_drafts/_new_collaborative_draft_button.html.erb +4 -4
  131. data/app/views/decidim/proposals/collaborative_drafts/_reject_request_access_form.html.erb +1 -1
  132. data/app/views/decidim/proposals/collaborative_drafts/_wizard_aside.html.erb +4 -2
  133. data/app/views/decidim/proposals/collaborative_drafts/compare.html.erb +2 -0
  134. data/app/views/decidim/proposals/collaborative_drafts/complete.html.erb +2 -0
  135. data/app/views/decidim/proposals/collaborative_drafts/edit.html.erb +3 -1
  136. data/app/views/decidim/proposals/collaborative_drafts/index.html.erb +4 -2
  137. data/app/views/decidim/proposals/collaborative_drafts/new.html.erb +4 -0
  138. data/app/views/decidim/proposals/collaborative_drafts/show.html.erb +29 -30
  139. data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +52 -22
  140. data/app/views/decidim/proposals/proposals/_endorsements_card_row.html.erb +0 -16
  141. data/app/views/decidim/proposals/proposals/_filters.html.erb +18 -16
  142. data/app/views/decidim/proposals/proposals/_proposal_badge.html.erb +1 -4
  143. data/app/views/decidim/proposals/proposals/_proposal_preview.html.erb +1 -11
  144. data/app/views/decidim/proposals/proposals/_proposal_similar.html.erb +2 -2
  145. data/app/views/decidim/proposals/proposals/_proposals.html.erb +14 -0
  146. data/app/views/decidim/proposals/proposals/_vote_button.html.erb +14 -7
  147. data/app/views/decidim/proposals/proposals/_wizard_aside.html.erb +4 -2
  148. data/app/views/decidim/proposals/proposals/_wizard_header.html.erb +4 -3
  149. data/app/views/decidim/proposals/proposals/compare.html.erb +2 -0
  150. data/app/views/decidim/proposals/proposals/complete.html.erb +2 -0
  151. data/app/views/decidim/proposals/proposals/edit.html.erb +3 -1
  152. data/app/views/decidim/proposals/proposals/edit_draft.html.erb +2 -0
  153. data/app/views/decidim/proposals/proposals/index.html.erb +6 -13
  154. data/app/views/decidim/proposals/proposals/new.html.erb +6 -2
  155. data/app/views/decidim/proposals/proposals/participatory_texts/_index.html.erb +1 -1
  156. data/app/views/decidim/proposals/proposals/participatory_texts/_proposal_vote_button.html.erb +10 -3
  157. data/app/views/decidim/proposals/proposals/participatory_texts/_view_index.html.erb +1 -1
  158. data/app/views/decidim/proposals/proposals/preview.html.erb +7 -8
  159. data/app/views/decidim/proposals/proposals/show.html.erb +62 -50
  160. data/app/views/decidim/proposals/versions/index.html.erb +14 -32
  161. data/app/views/decidim/proposals/versions/show.html.erb +16 -34
  162. data/config/locales/am-ET.yml +1 -0
  163. data/config/locales/ar.yml +62 -66
  164. data/config/locales/bg-BG.yml +237 -0
  165. data/config/locales/bg.yml +237 -0
  166. data/config/locales/ca.yml +176 -66
  167. data/config/locales/cs.yml +188 -78
  168. data/config/locales/da-DK.yml +1 -0
  169. data/config/locales/da.yml +1 -0
  170. data/config/locales/de.yml +169 -62
  171. data/config/locales/el.yml +876 -0
  172. data/config/locales/en.yml +179 -69
  173. data/config/locales/eo.yml +1 -0
  174. data/config/locales/es-MX.yml +173 -63
  175. data/config/locales/es-PY.yml +173 -63
  176. data/config/locales/es.yml +179 -69
  177. data/config/locales/et-EE.yml +1 -0
  178. data/config/locales/et.yml +1 -0
  179. data/config/locales/eu.yml +28 -61
  180. data/config/locales/fi-plain.yml +174 -64
  181. data/config/locales/fi.yml +210 -100
  182. data/config/locales/fr-CA.yml +906 -0
  183. data/config/locales/fr.yml +184 -66
  184. data/config/locales/ga-IE.yml +1 -0
  185. data/config/locales/gl.yml +28 -61
  186. data/config/locales/hr-HR.yml +1 -0
  187. data/config/locales/hr.yml +1 -0
  188. data/config/locales/hu.yml +135 -63
  189. data/config/locales/id-ID.yml +28 -60
  190. data/config/locales/is-IS.yml +14 -30
  191. data/config/locales/is.yml +274 -0
  192. data/config/locales/it.yml +166 -80
  193. data/config/locales/ja-JP.yml +865 -0
  194. data/config/locales/ja.yml +889 -0
  195. data/config/locales/ko-KR.yml +1 -0
  196. data/config/locales/ko.yml +1 -0
  197. data/config/locales/lt-LT.yml +1 -0
  198. data/config/locales/lt.yml +1 -0
  199. data/config/locales/lv.yml +858 -0
  200. data/config/locales/mt-MT.yml +1 -0
  201. data/config/locales/mt.yml +1 -0
  202. data/config/locales/nl.yml +151 -63
  203. data/config/locales/no.yml +62 -67
  204. data/config/locales/om-ET.yml +1 -0
  205. data/config/locales/pl.yml +525 -392
  206. data/config/locales/pt-BR.yml +30 -66
  207. data/config/locales/pt.yml +439 -330
  208. data/config/locales/ro-RO.yml +841 -0
  209. data/config/locales/ru.yml +14 -45
  210. data/config/locales/sk-SK.yml +896 -0
  211. data/config/locales/sk.yml +869 -0
  212. data/config/locales/sl.yml +26 -0
  213. data/config/locales/so-SO.yml +1 -0
  214. data/config/locales/sr-CS.yml +126 -0
  215. data/config/locales/sv.yml +285 -169
  216. data/config/locales/ti-ER.yml +1 -0
  217. data/config/locales/tr-TR.yml +28 -61
  218. data/config/locales/uk.yml +14 -45
  219. data/config/locales/vi-VN.yml +1 -0
  220. data/config/locales/vi.yml +1 -0
  221. data/config/locales/zh-CN.yml +885 -0
  222. data/config/locales/zh-TW.yml +1 -0
  223. data/db/migrate/20181003074440_fix_user_groups_ids_in_proposals_endorsements.rb +4 -0
  224. data/db/migrate/20191206154128_add_endorsements_counter_cache_to_proposals.rb +7 -0
  225. data/db/migrate/20200120215928_move_proposal_endorsements_to_core_endorsements.rb +54 -0
  226. data/db/migrate/20200120230130_drop_proposal_endorsements.rb +8 -0
  227. data/db/migrate/20200203111239_add_proposal_valuation_assignments.rb +12 -0
  228. data/db/migrate/20200210135152_add_costs_to_proposals.rb +9 -0
  229. data/db/migrate/20200212120110_sync_proposals_state_with_amendments_state.rb +28 -0
  230. data/db/migrate/20200227175922_add_state_published_at_to_proposals.rb +7 -0
  231. data/db/migrate/20200306123652_publish_existing_proposals_state.rb +15 -0
  232. data/db/migrate/20200708091228_move_proposals_fields_to_i18n.rb +86 -0
  233. data/db/migrate/20200730131631_move_proposal_endorsed_event_notifications_to_resource_endorsed_event.rb +20 -0
  234. data/db/migrate/20200827154156_add_commentable_counter_cache_to_proposals.rb +12 -0
  235. data/db/migrate/20200915151348_fix_proposals_data_to_ensure_title_and_body_are_hashes.rb +37 -0
  236. data/db/migrate/20201002085508_fix_proposals_data.rb +37 -0
  237. data/lib/decidim/content_renderers/proposal_renderer.rb +3 -1
  238. data/lib/decidim/proposals.rb +1 -0
  239. data/lib/decidim/proposals/admin_engine.rb +7 -3
  240. data/lib/decidim/proposals/component.rb +55 -28
  241. data/lib/decidim/proposals/engine.rb +3 -7
  242. data/lib/decidim/proposals/markdown_to_proposals.rb +2 -2
  243. data/lib/decidim/proposals/proposal_serializer.rb +3 -3
  244. data/lib/decidim/proposals/test/capybara_proposals_picker.rb +49 -0
  245. data/lib/decidim/proposals/test/factories.rb +100 -28
  246. data/lib/decidim/proposals/valuatable.rb +21 -0
  247. data/lib/decidim/proposals/version.rb +1 -1
  248. metadata +117 -55
  249. data/app/assets/javascripts/decidim/proposals/identity_selector_dialog.js.es6 +0 -56
  250. data/app/cells/decidim/proposals/endorsers_list/show.erb +0 -17
  251. data/app/cells/decidim/proposals/endorsers_list_cell.rb +0 -31
  252. data/app/commands/decidim/proposals/attachment_methods.rb +0 -43
  253. data/app/commands/decidim/proposals/endorse_proposal.rb +0 -59
  254. data/app/commands/decidim/proposals/unendorse_proposal.rb +0 -40
  255. data/app/controllers/decidim/proposals/proposal_endorsements_controller.rb +0 -60
  256. data/app/models/decidim/proposals/proposal_endorsement.rb +0 -37
  257. data/app/views/decidim/proposals/admin/proposal_answers/edit.html.erb +0 -22
  258. data/app/views/decidim/proposals/admin/proposal_notes/index.html.erb +0 -3
  259. data/app/views/decidim/proposals/admin/shared/_info_proposal.html.erb +0 -20
  260. data/app/views/decidim/proposals/proposal_endorsements/_identity.html.erb +0 -9
  261. data/app/views/decidim/proposals/proposal_endorsements/identities.html.erb +0 -12
  262. data/app/views/decidim/proposals/proposal_endorsements/update_buttons_and_counters.js.erb +0 -20
  263. data/app/views/decidim/proposals/proposal_widgets/show.html.erb +0 -4
  264. data/app/views/decidim/proposals/proposals/_endorsement_button.html.erb +0 -11
  265. data/app/views/decidim/proposals/proposals/_endorsement_identities_cabin.html.erb +0 -13
  266. data/app/views/decidim/proposals/versions/_version.html.erb +0 -20
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Admin
6
+ # A command with all the business logic to publish many answers at once.
7
+ class PublishAnswers < Rectify::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # component - The component that contains the answers.
11
+ # user - the Decidim::User that is publishing the answers.
12
+ # proposal_ids - the identifiers of the proposals with the answers to be published.
13
+ def initialize(component, user, proposal_ids)
14
+ @component = component
15
+ @user = user
16
+ @proposal_ids = proposal_ids
17
+ end
18
+
19
+ # Executes the command. Broadcasts these events:
20
+ #
21
+ # - :ok when everything is valid.
22
+ # - :invalid if there are not proposals to publish.
23
+ #
24
+ # Returns nothing.
25
+ def call
26
+ return broadcast(:invalid) unless proposals.any?
27
+
28
+ proposals.each do |proposal|
29
+ transaction do
30
+ mark_proposal_as_answered(proposal)
31
+ notify_proposal_answer(proposal)
32
+ end
33
+ end
34
+
35
+ broadcast(:ok)
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :component, :user, :proposal_ids
41
+
42
+ def proposals
43
+ @proposals ||= Decidim::Proposals::Proposal
44
+ .published
45
+ .answered
46
+ .state_not_published
47
+ .where(component: component)
48
+ .where(id: proposal_ids)
49
+ end
50
+
51
+ def mark_proposal_as_answered(proposal)
52
+ Decidim.traceability.perform_action!(
53
+ "publish_answer",
54
+ proposal,
55
+ user
56
+ ) do
57
+ proposal.update!(state_published_at: Time.current)
58
+ end
59
+ end
60
+
61
+ def notify_proposal_answer(proposal)
62
+ NotifyProposalAnswer.call(proposal, nil)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -65,7 +65,12 @@ module Decidim
65
65
  body = proposal.body
66
66
 
67
67
  PaperTrail.request(enabled: false) do
68
- proposal.update_columns(title: "", body: "") # rubocop:disable Rails/SkipsModelValidations
68
+ # rubocop:disable Rails/SkipsModelValidations
69
+ proposal.update_columns(
70
+ title: { I18n.locale => "" },
71
+ body: { I18n.locale => "" }
72
+ )
73
+ # rubocop:enable Rails/SkipsModelValidations
69
74
  end
70
75
 
71
76
  [title, body]
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Admin
6
+ # A command with all the business logic to unassign proposals from a given
7
+ # valuator.
8
+ class UnassignProposalsFromValuator < Rectify::Command
9
+ # Public: Initializes the command.
10
+ #
11
+ # form - A form object with the params.
12
+ def initialize(form)
13
+ @form = form
14
+ end
15
+
16
+ # Executes the command. Broadcasts these events:
17
+ #
18
+ # - :ok when everything is valid.
19
+ # - :invalid if the form wasn't valid and we couldn't proceed.
20
+ #
21
+ # Returns nothing.
22
+ def call
23
+ return broadcast(:invalid) unless form.valid?
24
+
25
+ unassign_proposals
26
+ broadcast(:ok)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :form
32
+
33
+ def unassign_proposals
34
+ transaction do
35
+ form.proposals.flat_map do |proposal|
36
+ assignment = find_assignment(proposal)
37
+ unassign(assignment) if assignment
38
+ end
39
+ end
40
+ end
41
+
42
+ def find_assignment(proposal)
43
+ Decidim::Proposals::ValuationAssignment.find_by(
44
+ proposal: proposal,
45
+ valuator_role: form.valuator_role
46
+ )
47
+ end
48
+
49
+ def unassign(assignment)
50
+ Decidim.traceability.perform_action!(
51
+ :delete,
52
+ assignment,
53
+ form.current_user,
54
+ proposal_title: assignment.proposal.title
55
+ ) do
56
+ assignment.destroy!
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -5,6 +5,8 @@ module Decidim
5
5
  module Admin
6
6
  # A command with all the business logic when an admin updates participatory text proposals.
7
7
  class UpdateParticipatoryText < Rectify::Command
8
+ include Decidim::TranslatableAttributes
9
+
8
10
  # Public: Initializes the command.
9
11
  #
10
12
  # form - A PreviewParticipatoryTextForm form object with the params.
@@ -40,10 +42,16 @@ module Decidim
40
42
  def update_contents_and_resort_proposals(form)
41
43
  PaperTrail.request(enabled: false) do
42
44
  form.proposals.each do |prop_form|
45
+ add_failure(prop_form) if prop_form.invalid?
46
+
43
47
  proposal = Proposal.where(component: form.current_component).find(prop_form.id)
44
48
  proposal.set_list_position(prop_form.position) if proposal.position != prop_form.position
45
- proposal.title = prop_form.title
46
- proposal.body = prop_form.body if proposal.participatory_text_level == ParticipatoryTextSection::LEVELS[:article]
49
+ proposal.title = { I18n.locale => translated_attribute(prop_form.title) }
50
+ proposal.body = if proposal.participatory_text_level == ParticipatoryTextSection::LEVELS[:article]
51
+ { I18n.locale => translated_attribute(prop_form.body) }
52
+ else
53
+ { I18n.locale => "" }
54
+ end
47
55
 
48
56
  add_failure(proposal) unless proposal.save
49
57
  end
@@ -5,7 +5,7 @@ module Decidim
5
5
  module Admin
6
6
  # A command with all the business logic when a user updates a proposal.
7
7
  class UpdateProposal < Rectify::Command
8
- include AttachmentMethods
8
+ include ::Decidim::AttachmentMethods
9
9
  include GalleryMethods
10
10
  include HashtagsMethods
11
11
 
@@ -56,11 +56,13 @@ module Decidim
56
56
  attr_reader :form, :proposal, :attachment, :gallery
57
57
 
58
58
  def update_proposal
59
+ parsed_title = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.title, current_organization: form.current_organization).rewrite
60
+ parsed_body = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.body, current_organization: form.current_organization).rewrite
59
61
  Decidim.traceability.update!(
60
62
  proposal,
61
63
  form.current_user,
62
- title: title_with_hashtags,
63
- body: body_with_hashtags,
64
+ title: parsed_title,
65
+ body: parsed_body,
64
66
  category: form.category,
65
67
  scope: form.scope,
66
68
  address: form.address,
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Admin
6
+ # A command with all the business logic when an admin batch updates proposals scope.
7
+ class UpdateProposalScope < Rectify::Command
8
+ include TranslatableAttributes
9
+ # Public: Initializes the command.
10
+ #
11
+ # scope_id - the scope id to update
12
+ # proposal_ids - the proposals ids to update.
13
+ def initialize(scope_id, proposal_ids)
14
+ @scope = Decidim::Scope.find_by id: scope_id
15
+ @proposal_ids = proposal_ids
16
+ @response = { scope_name: "", successful: [], errored: [] }
17
+ end
18
+
19
+ # Executes the command. Broadcasts these events:
20
+ #
21
+ # - :update_proposals_scope - when everything is ok, returns @response.
22
+ # - :invalid_scope - if the scope is blank.
23
+ # - :invalid_proposal_ids - if the proposal_ids is blank.
24
+ #
25
+ # Returns @response hash:
26
+ #
27
+ # - :scope_name - the translated_name of the scope assigned
28
+ # - :successful - Array of names of the updated proposals
29
+ # - :errored - Array of names of the proposals not updated because they already had the scope assigned
30
+ def call
31
+ return broadcast(:invalid_scope) if @scope.blank?
32
+ return broadcast(:invalid_proposal_ids) if @proposal_ids.blank?
33
+
34
+ update_proposals_scope
35
+
36
+ broadcast(:update_proposals_scope, @response)
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :scope, :proposal_ids
42
+
43
+ def update_proposals_scope
44
+ @response[:scope_name] = translated_attribute(scope.name, scope.organization)
45
+ Proposal.where(id: proposal_ids).find_each do |proposal|
46
+ if scope == proposal.scope
47
+ @response[:errored] << proposal.title
48
+ else
49
+ transaction do
50
+ update_proposal_scope proposal
51
+ notify_author proposal if proposal.coauthorships.any?
52
+ end
53
+ @response[:successful] << proposal.title
54
+ end
55
+ end
56
+ end
57
+
58
+ def update_proposal_scope(proposal)
59
+ proposal.update!(
60
+ scope: scope
61
+ )
62
+ end
63
+
64
+ def notify_author(proposal)
65
+ Decidim::EventsManager.publish(
66
+ event: "decidim.events.proposals.proposal_update_scope",
67
+ event_class: Decidim::Proposals::Admin::UpdateProposalScopeEvent,
68
+ resource: proposal,
69
+ affected_users: proposal.notifiable_identities
70
+ )
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -4,7 +4,7 @@ module Decidim
4
4
  module Proposals
5
5
  # A command with all the business logic when a user creates a new collaborative draft.
6
6
  class CreateCollaborativeDraft < Rectify::Command
7
- include AttachmentMethods
7
+ include ::Decidim::AttachmentMethods
8
8
  include HashtagsMethods
9
9
 
10
10
  # Public: Initializes the command.
@@ -4,7 +4,7 @@ module Decidim
4
4
  module Proposals
5
5
  # A command with all the business logic when a user creates a new proposal.
6
6
  class CreateProposal < Rectify::Command
7
- include AttachmentMethods
7
+ include ::Decidim::AttachmentMethods
8
8
  include HashtagsMethods
9
9
 
10
10
  # Public: Initializes the command.
@@ -57,8 +57,12 @@ module Decidim
57
57
  visibility: "public-only"
58
58
  ) do
59
59
  proposal = Proposal.new(
60
- title: title_with_hashtags,
61
- body: body_with_hashtags,
60
+ title: {
61
+ I18n.locale => title_with_hashtags
62
+ },
63
+ body: {
64
+ I18n.locale => body_with_hashtags
65
+ },
62
66
  component: form.component
63
67
  )
64
68
  proposal.add_coauthor(@current_user, user_group: user_group)
@@ -6,62 +6,13 @@ module Decidim
6
6
  # and collaborative draft commands.
7
7
  # Allows to create several image attachments at once
8
8
  module GalleryMethods
9
- private
10
-
11
- def build_gallery
12
- @gallery = []
13
- @form.add_photos.each do |photo|
14
- next unless image? photo
15
-
16
- @gallery << Attachment.new(
17
- title: photo.original_filename,
18
- file: photo,
19
- attached_to: @attached_to
20
- )
21
- end
22
- end
9
+ include ::Decidim::GalleryMethods
23
10
 
24
- def image?(image)
25
- return unless image.respond_to? :content_type
26
-
27
- image.content_type.start_with? "image"
28
- end
29
-
30
- def gallery_invalid?
31
- gallery.each do |photo|
32
- if photo.invalid? && photo.errors.has_key?(:file)
33
- @form.errors.add(:add_photos, photo.errors[:file])
34
- return true
35
- end
36
- end
37
- false
38
- end
39
-
40
- def create_gallery
41
- @gallery.map! do |photo|
42
- photo.attached_to = @attached_to
43
- photo.save!
44
- @form.photos << photo.id.to_s
45
- end
46
- end
47
-
48
- def photo_cleanup!
49
- @attached_to.photos.each do |photo|
50
- photo.destroy! if @form.photos.exclude? photo.id.to_s
51
- end
52
- # manually reset cached photos
53
- @attached_to.reload
54
- @attached_to.instance_variable_set(:@photos, nil)
55
- end
11
+ private
56
12
 
57
- # maybe a custom settings options would be nice
58
13
  def gallery_allowed?
59
14
  @form.current_component.settings.attachments_allowed?
60
15
  end
61
-
62
- def process_gallery?
63
- gallery_allowed? && @form.add_photos.any?
64
- end
65
16
  end
66
17
  end
67
18
  end
@@ -59,8 +59,8 @@ module Decidim
59
59
  parsed_title = Decidim::ContentProcessor.parse_with_processor(:hashtag, @collaborative_draft.title, current_organization: @collaborative_draft.organization).rewrite
60
60
  parsed_body = Decidim::ContentProcessor.parse_with_processor(:hashtag, @collaborative_draft.body, current_organization: @collaborative_draft.organization).rewrite
61
61
 
62
- fields[:title] = parsed_title
63
- fields[:body] = parsed_body
62
+ fields[:title] = { I18n.locale => parsed_title }
63
+ fields[:body] = { I18n.locale => parsed_body }
64
64
  fields[:component] = @collaborative_draft.component
65
65
  fields[:scope] = @collaborative_draft.scope
66
66
  fields[:address] = @collaborative_draft.address
@@ -4,7 +4,8 @@ module Decidim
4
4
  module Proposals
5
5
  # A command with all the business logic when a user updates a proposal.
6
6
  class UpdateProposal < Rectify::Command
7
- include AttachmentMethods
7
+ include ::Decidim::MultipleAttachmentsMethods
8
+ include GalleryMethods
8
9
  include HashtagsMethods
9
10
 
10
11
  # Public: Initializes the command.
@@ -26,15 +27,18 @@ module Decidim
26
27
  #
27
28
  # Returns nothing.
28
29
  def call
29
- return broadcast(:invalid) if form.invalid?
30
- return broadcast(:invalid) unless proposal.editable_by?(current_user)
31
- return broadcast(:invalid) if proposal_limit_reached?
30
+ return broadcast(:invalid) if invalid?
32
31
 
33
32
  if process_attachments?
34
33
  @proposal.attachments.destroy_all
35
34
 
36
- build_attachment
37
- return broadcast(:invalid) if attachment_invalid?
35
+ build_attachments
36
+ return broadcast(:invalid) if attachments_invalid?
37
+ end
38
+
39
+ if process_gallery?
40
+ build_gallery
41
+ return broadcast(:invalid) if gallery_invalid?
38
42
  end
39
43
 
40
44
  transaction do
@@ -43,7 +47,11 @@ module Decidim
43
47
  else
44
48
  update_proposal
45
49
  end
46
- create_attachment if process_attachments?
50
+ create_gallery if process_gallery?
51
+ create_attachments if process_attachments?
52
+
53
+ photo_cleanup!
54
+ document_cleanup!
47
55
  end
48
56
 
49
57
  broadcast(:ok, proposal)
@@ -53,6 +61,10 @@ module Decidim
53
61
 
54
62
  attr_reader :form, :proposal, :current_user, :attachment
55
63
 
64
+ def invalid?
65
+ form.invalid? || !proposal.editable_by?(current_user) || proposal_limit_reached?
66
+ end
67
+
56
68
  # Prevent PaperTrail from creating an additional version
57
69
  # in the proposal multi-step creation process (step 3: complete)
58
70
  #
@@ -79,8 +91,12 @@ module Decidim
79
91
 
80
92
  def attributes
81
93
  {
82
- title: title_with_hashtags,
83
- body: body_with_hashtags,
94
+ title: {
95
+ I18n.locale => title_with_hashtags
96
+ },
97
+ body: {
98
+ I18n.locale => body_with_hashtags
99
+ },
84
100
  category: form.category,
85
101
  scope: form.scope,
86
102
  address: form.address,