decidim-proposals 0.29.2 → 0.30.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) 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/highlighted_proposals_for_component_cell.rb +1 -1
  4. data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +1 -1
  5. data/app/cells/decidim/proposals/proposal_g/show.erb +13 -0
  6. data/app/cells/decidim/proposals/proposal_g_cell.rb +13 -0
  7. data/app/cells/decidim/proposals/proposal_history_cell.rb +107 -0
  8. data/app/cells/decidim/proposals/proposal_l/show.erb +37 -0
  9. data/app/cells/decidim/proposals/proposal_l_cell.rb +9 -0
  10. data/app/cells/decidim/proposals/proposal_metadata_cell.rb +2 -2
  11. data/app/cells/decidim/proposals/proposal_vote/show.erb +75 -0
  12. data/app/cells/decidim/proposals/proposal_vote_cell.rb +43 -0
  13. data/app/commands/decidim/proposals/accept_coauthorship.rb +62 -0
  14. data/app/commands/decidim/proposals/admin/assign_proposals_to_valuator.rb +14 -0
  15. data/app/commands/decidim/proposals/admin/create_proposal.rb +6 -14
  16. data/app/commands/decidim/proposals/admin/create_proposal_note.rb +20 -11
  17. data/app/commands/decidim/proposals/admin/import_proposals.rb +0 -5
  18. data/app/commands/decidim/proposals/admin/merge_proposals.rb +2 -2
  19. data/app/commands/decidim/proposals/admin/proposal_notes_methods.rb +48 -0
  20. data/app/commands/decidim/proposals/admin/reply_proposal_note.rb +92 -0
  21. data/app/commands/decidim/proposals/admin/split_proposals.rb +2 -2
  22. data/app/commands/decidim/proposals/admin/update_proposal.rb +10 -16
  23. data/app/commands/decidim/proposals/admin/update_proposal_taxonomies.rb +34 -0
  24. data/app/commands/decidim/proposals/cancel_coauthorship.rb +32 -0
  25. data/app/commands/decidim/proposals/create_collaborative_draft.rb +1 -2
  26. data/app/commands/decidim/proposals/create_proposal.rb +1 -2
  27. data/app/commands/decidim/proposals/invite_coauthor.rb +45 -0
  28. data/app/commands/decidim/proposals/publish_collaborative_draft.rb +1 -2
  29. data/app/commands/decidim/proposals/reject_coauthorship.rb +54 -0
  30. data/app/commands/decidim/proposals/update_collaborative_draft.rb +1 -2
  31. data/app/commands/decidim/proposals/update_proposal.rb +1 -2
  32. data/app/controllers/concerns/decidim/proposals/admin/filterable.rb +5 -1
  33. data/app/controllers/concerns/decidim/proposals/admin/needs_interpolations.rb +40 -0
  34. data/app/controllers/decidim/proposals/admin/proposal_answers_controller.rb +50 -2
  35. data/app/controllers/decidim/proposals/admin/proposal_notes_controller.rb +18 -0
  36. data/app/controllers/decidim/proposals/admin/proposals_controller.rb +41 -85
  37. data/app/controllers/decidim/proposals/collaborative_drafts_controller.rb +2 -4
  38. data/app/controllers/decidim/proposals/invite_coauthors_controller.rb +87 -0
  39. data/app/controllers/decidim/proposals/proposals_controller.rb +7 -32
  40. data/app/events/decidim/proposals/accepted_coauthorship_event.rb +8 -0
  41. data/app/events/decidim/proposals/admin/proposal_assigned_to_valuator_event.rb +27 -0
  42. data/app/events/decidim/proposals/admin/proposal_note_created_event.rb +5 -0
  43. data/app/events/decidim/proposals/coauthor_accepted_invite_event.rb +49 -0
  44. data/app/events/decidim/proposals/coauthor_invited_event.rb +45 -0
  45. data/app/events/decidim/proposals/coauthor_rejected_invite_event.rb +8 -0
  46. data/app/events/decidim/proposals/rejected_coauthorship_event.rb +8 -0
  47. data/app/events/decidim/proposals/update_proposal_taxonomies_event.rb +9 -0
  48. data/app/forms/decidim/proposals/admin/proposal_answer_form.rb +1 -0
  49. data/app/forms/decidim/proposals/admin/proposal_base_form.rb +3 -31
  50. data/app/forms/decidim/proposals/admin/proposal_form.rb +11 -6
  51. data/app/forms/decidim/proposals/admin/proposals_import_form.rb +0 -5
  52. data/app/forms/decidim/proposals/collaborative_draft_form.rb +0 -8
  53. data/app/forms/decidim/proposals/proposal_form.rb +5 -32
  54. data/app/helpers/decidim/proposals/admin/proposal_bulk_actions_helper.rb +25 -0
  55. data/app/helpers/decidim/proposals/admin/proposals_helper.rb +0 -1
  56. data/app/helpers/decidim/proposals/application_helper.rb +23 -14
  57. data/app/helpers/decidim/proposals/collaborative_draft_helper.rb +7 -7
  58. data/app/helpers/decidim/proposals/map_helper.rb +0 -18
  59. data/app/helpers/decidim/proposals/proposal_votes_helper.rb +15 -2
  60. data/app/jobs/decidim/proposals/admin/proposal_answer_job.rb +20 -0
  61. data/app/models/decidim/proposals/collaborative_draft.rb +10 -1
  62. data/app/models/decidim/proposals/proposal.rb +66 -5
  63. data/app/models/decidim/proposals/proposal_note.rb +11 -0
  64. data/app/models/decidim/proposals/proposal_state.rb +1 -1
  65. data/app/packs/entrypoints/decidim_proposals.js +1 -0
  66. data/app/packs/entrypoints/decidim_proposals_geocoding.js +2 -0
  67. data/app/packs/src/decidim/proposals/admin/proposals.js +16 -1
  68. data/app/packs/src/decidim/proposals/exit_handler.js +73 -0
  69. data/app/packs/stylesheets/decidim/proposals/proposals.scss +248 -3
  70. data/app/permissions/decidim/proposals/admin/permissions.rb +2 -5
  71. data/app/permissions/decidim/proposals/permissions.rb +42 -0
  72. data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +1 -1
  73. data/app/presenters/decidim/proposals/proposal_presenter.rb +1 -1
  74. data/app/queries/decidim/proposals/filtered_proposals.rb +2 -2
  75. data/app/queries/decidim/proposals/metrics/accepted_proposals_metric_manage.rb +2 -2
  76. data/app/queries/decidim/proposals/metrics/endorsements_metric_manage.rb +10 -10
  77. data/app/queries/decidim/proposals/metrics/proposal_followers_metric_measure.rb +4 -4
  78. data/app/queries/decidim/proposals/metrics/proposal_participants_metric_measure.rb +6 -6
  79. data/app/queries/decidim/proposals/metrics/proposals_metric_manage.rb +6 -6
  80. data/app/queries/decidim/proposals/metrics/votes_metric_manage.rb +6 -6
  81. data/app/services/decidim/proposals/proposal_builder.rb +1 -1
  82. data/app/views/decidim/proposals/admin/proposal_notes/_form.html.erb +3 -3
  83. data/app/views/decidim/proposals/admin/proposal_notes/_proposal_note.html.erb +28 -0
  84. data/app/views/decidim/proposals/admin/proposal_notes/_proposal_note_reply.html.erb +9 -0
  85. data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes.html.erb +4 -28
  86. data/app/views/decidim/proposals/admin/proposal_states/_form.html.erb +1 -1
  87. data/app/views/decidim/proposals/admin/proposals/_actions.html.erb +21 -0
  88. data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +3 -2
  89. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +16 -23
  90. data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +12 -28
  91. data/app/views/decidim/proposals/admin/proposals/_proposals-thead.html.erb +45 -0
  92. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_apply_answer_template.html.erb +22 -0
  93. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_dropdown.html.erb +15 -11
  94. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_taxonomy_change.html.erb +23 -0
  95. data/app/views/decidim/proposals/admin/proposals/index.html.erb +17 -48
  96. data/app/views/decidim/proposals/admin/proposals/manage_trash.html.erb +18 -0
  97. data/app/views/decidim/proposals/admin/proposals/publish_answers.js.erb +1 -1
  98. data/app/views/decidim/proposals/admin/proposals/show.html.erb +10 -22
  99. data/app/views/decidim/proposals/admin/proposals/update_attribute.js.erb +1 -1
  100. data/app/views/decidim/proposals/admin/proposals_imports/new.html.erb +0 -3
  101. data/app/views/decidim/proposals/collaborative_drafts/_collaborative_actions.html.erb +9 -0
  102. data/app/views/decidim/proposals/collaborative_drafts/_collaborative_draft_aside.html.erb +0 -15
  103. data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +4 -6
  104. data/app/views/decidim/proposals/collaborative_drafts/index.html.erb +6 -2
  105. data/app/views/decidim/proposals/collaborative_drafts/show.html.erb +27 -11
  106. data/app/views/decidim/proposals/proposal_votes/update_buttons_and_counters.js.erb +29 -9
  107. data/app/views/decidim/proposals/proposals/_actions.html.erb +4 -7
  108. data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +17 -22
  109. data/app/views/decidim/proposals/proposals/_exit_modal.html.erb +17 -0
  110. data/app/views/decidim/proposals/proposals/_notification_alert_box.html.erb +1 -0
  111. data/app/views/decidim/proposals/proposals/_proposal_actions.html.erb +19 -0
  112. data/app/views/decidim/proposals/proposals/_proposal_aside.html.erb +9 -32
  113. data/app/views/decidim/proposals/proposals/_proposal_voting_rules.html.erb +33 -0
  114. data/app/views/decidim/proposals/proposals/_remaining_votes_count.html.erb +2 -2
  115. data/app/views/decidim/proposals/proposals/_remaining_votes_notification.html.erb +12 -0
  116. data/app/views/decidim/proposals/proposals/_update_proposal_voting_rules.html.erb +6 -0
  117. data/app/views/decidim/proposals/proposals/_vote_button.html.erb +12 -8
  118. data/app/views/decidim/proposals/proposals/_votes_count.html.erb +2 -1
  119. data/app/views/decidim/proposals/proposals/_voting_rules.html.erb +1 -7
  120. data/app/views/decidim/proposals/proposals/index.html.erb +10 -18
  121. data/app/views/decidim/proposals/proposals/index.js.erb +1 -1
  122. data/app/views/decidim/proposals/proposals/participatory_texts/_proposal_vote_button.html.erb +3 -1
  123. data/app/views/decidim/proposals/proposals/show.html.erb +35 -15
  124. data/config/locales/ar.yml +18 -72
  125. data/config/locales/bg.yml +7 -89
  126. data/config/locales/bs-BA.yml +0 -13
  127. data/config/locales/ca.yml +212 -72
  128. data/config/locales/cs.yml +213 -73
  129. data/config/locales/de.yml +214 -75
  130. data/config/locales/el.yml +8 -82
  131. data/config/locales/en.yml +209 -69
  132. data/config/locales/es-MX.yml +213 -73
  133. data/config/locales/es-PY.yml +213 -73
  134. data/config/locales/es.yml +215 -75
  135. data/config/locales/eu.yml +217 -78
  136. data/config/locales/fi-plain.yml +216 -75
  137. data/config/locales/fi.yml +216 -75
  138. data/config/locales/fr-CA.yml +118 -87
  139. data/config/locales/fr.yml +118 -87
  140. data/config/locales/ga-IE.yml +0 -19
  141. data/config/locales/gl.yml +8 -43
  142. data/config/locales/hu.yml +6 -66
  143. data/config/locales/id-ID.yml +8 -40
  144. data/config/locales/is-IS.yml +0 -14
  145. data/config/locales/it.yml +8 -53
  146. data/config/locales/ja.yml +162 -87
  147. data/config/locales/lt.yml +8 -83
  148. data/config/locales/lv.yml +8 -50
  149. data/config/locales/nl.yml +6 -55
  150. data/config/locales/no.yml +8 -42
  151. data/config/locales/pl.yml +6 -88
  152. data/config/locales/pt-BR.yml +6 -74
  153. data/config/locales/pt.yml +8 -54
  154. data/config/locales/ro-RO.yml +10 -54
  155. data/config/locales/ru.yml +0 -18
  156. data/config/locales/sk.yml +8 -50
  157. data/config/locales/sr-CS.yml +0 -14
  158. data/config/locales/sv.yml +128 -85
  159. data/config/locales/tr-TR.yml +8 -51
  160. data/config/locales/uk.yml +0 -18
  161. data/config/locales/zh-CN.yml +8 -51
  162. data/config/locales/zh-TW.yml +8 -84
  163. data/db/migrate/20171220084719_add_published_at_to_proposals.rb +1 -1
  164. data/db/migrate/20181016132225_add_organization_as_author.rb +1 -1
  165. data/db/migrate/20200120215928_move_proposal_endorsements_to_core_endorsements.rb +1 -1
  166. data/db/migrate/20200827154156_add_commentable_counter_cache_to_proposals.rb +3 -3
  167. data/db/migrate/20210310102839_add_followable_counter_cache_to_proposals.rb +1 -1
  168. data/db/migrate/20240110203504_create_default_proposal_states.rb +1 -1
  169. data/db/migrate/20240404202756_add_valuation_assignments_count_to_decidim_proposals_proposals.rb +1 -1
  170. data/db/migrate/20240617091140_add_email_on_assigned_proposals_to_users.rb +7 -0
  171. data/db/migrate/20240617170052_add_parent_relation_to_decidim_proposal_notes.rb +7 -0
  172. data/db/migrate/20240828103755_add_deleted_at_to_decidim_proposals_proposals.rb +8 -0
  173. data/decidim-proposals.gemspec +1 -1
  174. data/lib/decidim/api/functions/proposal_finder_helper.rb +12 -0
  175. data/lib/decidim/api/functions/proposal_list_helper.rb +12 -0
  176. data/lib/decidim/api/proposal_type.rb +17 -25
  177. data/lib/decidim/api/proposals_type.rb +4 -19
  178. data/lib/decidim/proposals/admin_engine.rb +12 -3
  179. data/lib/decidim/proposals/admin_filter.rb +3 -6
  180. data/lib/decidim/proposals/component.rb +4 -5
  181. data/lib/decidim/proposals/download_your_data_proposal_serializer.rb +15 -0
  182. data/lib/decidim/proposals/engine.rb +5 -0
  183. data/lib/decidim/proposals/import/proposal_creator.rb +4 -4
  184. data/lib/decidim/proposals/proposal_serializer.rb +12 -29
  185. data/lib/decidim/proposals/seeds.rb +21 -17
  186. data/lib/decidim/proposals/test/factories.rb +2 -1
  187. data/lib/decidim/proposals/version.rb +1 -1
  188. data/lib/decidim/proposals.rb +4 -0
  189. metadata +65 -29
  190. data/app/commands/decidim/proposals/admin/update_proposal_category.rb +0 -70
  191. data/app/commands/decidim/proposals/admin/update_proposal_scope.rb +0 -75
  192. data/app/events/decidim/proposals/admin/update_proposal_category_event.rb +0 -11
  193. data/app/events/decidim/proposals/admin/update_proposal_scope_event.rb +0 -11
  194. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_recategorize.html.erb +0 -15
  195. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_scope-change.html.erb +0 -21
  196. data/app/views/decidim/proposals/collaborative_drafts/_actions.html.erb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f0a793e0fdf54677810a839a8e177a8d3077aee2e25ff1618751d76f03f6401
4
- data.tar.gz: 90b7698d7c3560677628165a4ce38c5fdf78b3d1dc5cb00671967a83a9af0d72
3
+ metadata.gz: df9005202c6078251b19d437ce9dad80b29d44bd6bec63b9d64e5fd89009f385
4
+ data.tar.gz: 02a8ec7149f40e004177f0fb8fc25e223f7c482f81c666ccedb8a9292d284f61
5
5
  SHA512:
6
- metadata.gz: fd2a28b72d4d22a47f40a4ccbd000421d19c0e014f0788a6888ce36f6665660c5d2d3c862b034280cc4798da73d1137fe4815e773ac48113a89a1baeacee9d2e
7
- data.tar.gz: 499ac55e1d39ae1b19c105f69187ef399ee5bb97d110ea7ab6f15cef2aaa08c30456c12dbb45a85ff72041aaf0d38df9fca5b202e895286a7e2731e450eca263
6
+ metadata.gz: 274abec4fe629268688e921100ffde55cdf4b6184a21bb47c6101fab45a697741ffe77937848b04637f427af7a8e14b222e52f990fd2e516e458fffcf7375e77
7
+ data.tar.gz: 67248a8cbd8d13029e82780ad4a6e10780567c92dbb7e94da8d8c752cb6e549ca7602fd40b2ed9539cb68ede4e7ac130e2633b5bc364cd119d665f8f41d31999
@@ -25,7 +25,7 @@
25
25
  <div class="flex items-start justify-between">
26
26
  <div class="grow space-y-6">
27
27
  <% proposals_to_render.each do |p| %>
28
- <%= card_for p, link_whole_card: true, title_tag: :h3, **options.slice(:show_space) %>
28
+ <%= card_for p, link_whole_card: true, hide_voting: true, title_tag: :h3, **options.slice(:show_space) %>
29
29
  <% end %>
30
30
  </div>
31
31
  </div>
@@ -49,7 +49,7 @@ module Decidim
49
49
  end
50
50
 
51
51
  def proposals_to_render
52
- @proposals_to_render ||= proposals.includes([:amendable, :category, :component, :scope]).limit(Decidim::Proposals.config.participatory_space_highlighted_proposals_limit)
52
+ @proposals_to_render ||= proposals.includes([:amendable, :component, :taxonomies]).limit(Decidim::Proposals.config.participatory_space_highlighted_proposals_limit)
53
53
  end
54
54
 
55
55
  def cache_hash
@@ -69,7 +69,7 @@ module Decidim
69
69
  end
70
70
 
71
71
  def amendment_creation_enabled?
72
- (current_component.settings.amendments_enabled? && current_settings.amendment_creation_enabled?)
72
+ current_component.settings.amendments_enabled? && current_settings.amendment_creation_enabled?
73
73
  end
74
74
 
75
75
  def amend_button_disabled?
@@ -1,3 +1,4 @@
1
+ <div class="card__proposals-item">
1
2
  <%= link_to resource_path, class: classes[:default], id: resource_id do %>
2
3
  <div class="<%= classes[:img] %>">
3
4
  <% if has_image? %>
@@ -21,3 +22,15 @@
21
22
  <% end %>
22
23
  </div>
23
24
  <% end %>
25
+ <% if has_actions? %>
26
+ <% if current_settings.votes_hidden? %>
27
+ <div class="card__proposals-votes-hidden">
28
+ <%= cell proposal_vote_cell, resource, **options %>
29
+ </div>
30
+ <% else %>
31
+ <div class="card__proposals-votes">
32
+ <%= cell proposal_vote_cell, resource, **options %>
33
+ </div>
34
+ <% end %>
35
+ <% end %>
36
+ </div>
@@ -24,6 +24,18 @@ module Decidim
24
24
  "decidim/proposals/proposal_metadata"
25
25
  end
26
26
 
27
+ def proposal_vote_cell
28
+ "decidim/proposals/proposal_vote"
29
+ end
30
+
31
+ def has_actions?
32
+ model.component.current_settings.votes_enabled? && !model.draft? && !model.withdrawn? && !model.rejected?
33
+ end
34
+
35
+ def proposal_votes_count
36
+ model.proposal_votes_count || 0
37
+ end
38
+
27
39
  def metadata_cell_instance
28
40
  @metadata_cell_instance ||= cell("decidim/proposals/proposal_metadata", model)
29
41
  end
@@ -41,6 +53,7 @@ module Decidim
41
53
  hash << self.class.name.demodulize.underscore
42
54
  hash << model.cache_key_with_version
43
55
  hash << model.proposal_votes_count
56
+ hash << options[:hide_voting] ? 1 : 0
44
57
  hash << model.endorsements_count
45
58
  hash << model.comments_count
46
59
  hash << Digest::MD5.hexdigest(model.component.cache_key_with_version)
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ # This cell is used to render the proposal history panel of a resource
6
+ # inside a tab of a show view
7
+ #
8
+ # The `model` must be a proposal resource to get the history from.
9
+ #
10
+ # Example:
11
+ #
12
+ # cell(
13
+ # "decidim/proposal_history",
14
+ # proposal
15
+ # )
16
+ class ProposalHistoryCell < Decidim::ResourceHistoryCell
17
+ include Decidim::Proposals::ApplicationHelper
18
+
19
+ private
20
+
21
+ def linked_resources_items
22
+ # linked resources generate from this proposal
23
+ [
24
+ {
25
+ resources: @model.linked_resources_from(:proposals, "copied_from_component"),
26
+ link_name: "copied_from_component",
27
+ text_key: "decidim.proposals.proposal.import_from_proposal_text",
28
+ icon_key: "Decidim::Proposals::Proposal"
29
+ },
30
+ {
31
+ resources: @model.linked_resources_from(:proposals, "splitted_from_component"),
32
+ link_name: "splitted_from_component",
33
+ text_key: "decidim.proposals.proposal.split_from_proposal_text",
34
+ icon_key: "Decidim::Proposals::Proposal"
35
+ },
36
+ {
37
+ resources: @model.linked_resources_from(:proposals, "merged_from_component"),
38
+ link_name: "merged_from_component",
39
+ text_key: "decidim.proposals.proposal.merge_from_proposal_text",
40
+ icon_key: "Decidim::Proposals::Proposal"
41
+ },
42
+ {
43
+
44
+ resources: @model.linked_resources(:projects, "included_proposals"),
45
+ link_name: "included_proposals",
46
+ text_key: "decidim.budgets.project.text",
47
+ icon_key: "Decidim::Budgets::Project"
48
+ },
49
+ {
50
+ resources: @model.linked_resources(:results, "included_proposals"),
51
+ link_name: "included_proposals",
52
+ text_key: "decidim.accountability.result.text",
53
+ icon_key: "Decidim::Accountability::Result"
54
+ },
55
+ {
56
+ resources: @model.linked_resources(:meetings, "proposals_from_meeting"),
57
+ link_name: "proposals_from_meeting",
58
+ text_key: "decidim.meetings.meeting.text",
59
+ icon_key: "Decidim::Meetings::Meeting"
60
+ },
61
+ {
62
+
63
+ # linked resource generate to this proposal
64
+ resources: @model.linked_resources_to(:proposals, "copied_from_component"),
65
+ link_name: "copied_to_component",
66
+ text_key: "decidim.proposals.proposal.import_to_proposal_text",
67
+ icon_key: "Decidim::Proposals::Proposal"
68
+ },
69
+ {
70
+ resources: @model.linked_resources_to(:proposals, "splitted_from_component"),
71
+ link_name: "splitted_to_component",
72
+ text_key: "decidim.proposals.proposal.split_to_proposal_text",
73
+ icon_key: "Decidim::Proposals::Proposal"
74
+ },
75
+ {
76
+ resources: @model.linked_resources_to(:proposals, "merged_from_component"),
77
+ link_name: "merged_to_component",
78
+ text_key: "decidim.proposals.proposal.merge_to_proposal_text",
79
+ icon_key: "Decidim::Proposals::Proposal"
80
+ }
81
+ ]
82
+ end
83
+
84
+ def creation_item
85
+ creation_text = if history_items_contains?(:merged_to_component)
86
+ t("decidim.proposals.creation.merged_text")
87
+ elsif history_items_contains?(:splitted_to_component)
88
+ t("decidim.proposals.creation.splitted_text")
89
+ elsif history_items_contains?(:copied_to_component)
90
+ t("decidim.proposals.creation.imported_text")
91
+ else
92
+ t("decidim.proposals.creation.text")
93
+ end
94
+ {
95
+ id: "proposal_creation",
96
+ date: @model.created_at,
97
+ text: creation_text,
98
+ icon: resource_type_icon_key("Decidim::Proposals::Proposal")
99
+ }
100
+ end
101
+
102
+ def history_cell_id
103
+ "proposal"
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,37 @@
1
+ <% if has_link_to_resource? && link_whole_card? %>
2
+ <div class="card__proposals-item">
3
+ <%= link_to resource_path, class: item_list_class, id: resource_id, **html_options do %>
4
+ <%= render :content %>
5
+ <%= render :extra_data if render_extra_data? %>
6
+ <% end %>
7
+ <% if has_actions? && options.fetch(:hide_voting, false) == false %>
8
+ <% if current_settings.votes_hidden? %>
9
+ <div class="card__proposals-votes-hidden">
10
+ <%= cell proposal_vote_cell, resource, **options %>
11
+ </div>
12
+ <% else %>
13
+ <div class="card__proposals-votes">
14
+ <%= cell proposal_vote_cell, resource, **options %>
15
+ </div>
16
+ <% end %>
17
+ <% end %>
18
+ </div>
19
+ <% else %>
20
+ <%= content_tag :div, class: wrapper_class, id: resource_id do %>
21
+ <%= content_tag :div, class: item_list_class do %>
22
+ <%= render :content %>
23
+ <% end %>
24
+ <%= render :extra_data if render_extra_data? %>
25
+ <% if has_actions? %>
26
+ <% if current_settings.votes_hidden? %>
27
+ <div class="card__proposals-votes-hidden">
28
+ <%= cell proposal_vote_cell, resource, **options %>
29
+ </div>
30
+ <% else %>
31
+ <div class="card__proposals-votes">
32
+ <%= cell proposal_vote_cell, resource, **options %>
33
+ </div>
34
+ <% end %>
35
+ <% end %>
36
+ <% end %>
37
+ <% end %>
@@ -19,6 +19,14 @@ module Decidim
19
19
  "decidim/proposals/proposal_metadata"
20
20
  end
21
21
 
22
+ def has_actions?
23
+ model.component.current_settings.votes_enabled? && !model.draft? && !model.withdrawn? && !model.rejected?
24
+ end
25
+
26
+ def proposal_vote_cell
27
+ "decidim/proposals/proposal_vote"
28
+ end
29
+
22
30
  def cache_hash
23
31
  @cache_hash ||= begin
24
32
  hash = []
@@ -26,6 +34,7 @@ module Decidim
26
34
  hash << self.class.name.demodulize.underscore
27
35
  hash << model.cache_key_with_version
28
36
  hash << model.proposal_votes_count
37
+ hash << options[:hide_voting] ? 1 : 0
29
38
  hash << model.endorsements_count
30
39
  hash << model.comments_count
31
40
  hash << Digest::MD5.hexdigest(model.component.cache_key_with_version)
@@ -44,10 +44,10 @@ module Decidim
44
44
  private
45
45
 
46
46
  def proposal_items
47
- [coauthors_item, comments_count_item, endorsements_count_item, state_item, emendation_item]
47
+ [coauthors_item] + taxonomy_items + [comments_count_item, endorsements_count_item, state_item, emendation_item]
48
48
  end
49
49
 
50
- def proposal_items_for_map
50
+ def items_for_map
51
51
  [coauthors_item_for_map, comments_count_item, endorsements_count_item, state_item, emendation_item].compact_blank.map do |item|
52
52
  {
53
53
  text: item[:text].to_s.html_safe,
@@ -0,0 +1,75 @@
1
+ <% if !current_settings.votes_hidden? && current_component.participatory_space.can_participate?(current_user) %>
2
+ <% if component_settings.participatory_texts_enabled? && from_proposals_list %>
3
+ <%= render partial: "decidim/proposals/proposals/participatory_texts/proposal_votes_count", locals: { proposal: resource, from_proposals_list: true } %>
4
+ <% else %>
5
+ <% progress ||= resource.proposal_votes_count || 0 %>
6
+ <% total ||= resource.maximum_votes || 0 %>
7
+ <%= cell(
8
+ "decidim/progress_bar",
9
+ progress,
10
+ total:,
11
+ units_name: "decidim.proposals.proposals.votes_count.count",
12
+ element_id: "proposal-#{resource.id}-votes-count",
13
+ class: total.positive? ? "card__proposals-votes-limited" : "card__proposals-votes-unlimited"
14
+ ) %>
15
+ <% end %>
16
+ <% end %>
17
+
18
+ <% button_classes = "button button__lg button__secondary w-full" %>
19
+
20
+ <% unless resource.rejected? || resource.withdrawn? %>
21
+ <% if component_settings.participatory_texts_enabled? && from_proposals_list %>
22
+ <%= render partial: "decidim/proposals/proposals/participatory_texts/proposal_vote_button", locals: { resource:, from_proposals_list: true } %>
23
+ <% else %>
24
+ <div id="proposal-<%= resource.id %>-vote-button" class="card__proposals-votes-container">
25
+ <% if !current_user %>
26
+ <% if current_settings.votes_blocked? %>
27
+ <%= action_authorized_button_to :vote, t("decidim.proposals.proposals.vote_button.votes_blocked"), proposal_proposal_vote_path(proposal_id: resource, from_proposals_list:), resource: , class: button_classes, disabled: true %>
28
+ <% else %>
29
+ <%= action_authorized_button_to :vote, proposal_proposal_vote_path(proposal_id: resource, from_proposals_list:), resource: , class: button_classes, data: { "proposal-vote-button": true, disable: true, "redirect-url": proposal_path(resource) } do %>
30
+ <%= t("decidim.proposals.proposals.vote_button.vote") %>
31
+ <span class="sr-only"><%= decidim_html_escape(present(resource).title) %></span>
32
+ <% end %>
33
+ <% end %>
34
+ <% else %>
35
+ <% if @voted_proposals ? @voted_proposals.include?(resource.id) : resource.voted_by?(current_user) %>
36
+ <%= action_authorized_button_to(
37
+ :vote,
38
+ proposal_proposal_vote_path(proposal_id: resource, from_proposals_list:),
39
+ resource:,
40
+ method: :delete,
41
+ remote: true,
42
+ data: {
43
+ disable: true,
44
+ original: t("decidim.proposals.proposals.vote_button.already_voted"),
45
+ replace: t("decidim.proposals.proposals.vote_button.already_voted_hover"),
46
+ "redirect-url": proposal_path(resource)
47
+ },
48
+ disabled: current_settings.votes_blocked?,
49
+ class: "#{button_classes}",
50
+ id: "vote_button-#{resource.id}"
51
+ ) do %>
52
+ <%= t("decidim.proposals.proposals.vote_button.already_voted") %>
53
+ <%= icon "check-line", class: "already-voted-icon" %>
54
+ <span class="sr-only"><%= decidim_html_escape(present(resource).title) %></span>
55
+ <% end %>
56
+ <% else %>
57
+ <% if resource.maximum_votes_reached? && !resource.can_accumulate_votes_beyond_threshold && current_component.participatory_space.can_participate?(current_user) %>
58
+ <%= content_tag :button, t("decidim.proposals.proposals.vote_button.maximum_votes_reached"), class: button_classes, disabled: true %>
59
+ <% else %>
60
+ <% if vote_limit_enabled? && remaining_votes_count_for(current_user) == 0 %>
61
+ <%= content_tag :button, t("decidim.proposals.proposals.vote_button.no_votes_remaining"), class: button_classes, disabled: true %>
62
+ <% elsif current_settings.votes_blocked? || !current_component.participatory_space.can_participate?(current_user) %>
63
+ <%= content_tag :button, t("decidim.proposals.proposals.vote_button.votes_blocked"), class: button_classes, disabled: true %>
64
+ <% else %>
65
+ <%= action_authorized_button_to :vote, proposal_proposal_vote_path(proposal_id: resource, from_proposals_list:), resource: , remote: true, data: { disable: true, "redirect-url": proposal_path(resource) }, class: button_classes do %>
66
+ <%= t("decidim.proposals.proposals.vote_button.vote") %>
67
+ <span class="sr-only"><%= decidim_html_escape(present(resource).title) %></span>
68
+ <% end %>
69
+ <% end %>
70
+ <% end %>
71
+ <% end %>
72
+ <% end %>
73
+ </div>
74
+ <% end %>
75
+ <% end %>
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This cell is used to display votes inside a card
5
+ module Proposals
6
+ class ProposalVoteCell < Decidim::ViewModel
7
+ include Decidim::DateRangeHelper
8
+ include Cell::ViewModel::Partial
9
+ include Decidim::ViewHooksHelper
10
+
11
+ alias resource model
12
+
13
+ def show
14
+ return if @items.blank?
15
+
16
+ render
17
+ end
18
+
19
+ def initialize(*)
20
+ super
21
+
22
+ @items ||= []
23
+ @items << votes_count_item
24
+ end
25
+
26
+ private
27
+
28
+ def from_proposals_list
29
+ true
30
+ end
31
+
32
+ def votes_count_item
33
+ return unless resource.respond_to?(:proposal_votes_count)
34
+
35
+ {
36
+ text: resource.proposal_votes_count,
37
+ icon: resource_type_icon_key(:like),
38
+ data_attributes: { votes_count: "" }
39
+ }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ # A command with all the business logic when a user accepts an invitation to be a coauthor of a proposal.
6
+ class AcceptCoauthorship < Decidim::Command
7
+ # Public: Initializes the command.
8
+ #
9
+ # proposal - The proposal to add a coauthor to.
10
+ # coauthor - The user to invite as coauthor.
11
+ def initialize(proposal, coauthor)
12
+ @proposal = proposal
13
+ @coauthor = coauthor
14
+ end
15
+
16
+ # Executes the command. Broadcasts these events:
17
+ #
18
+ # - :ok when everything is valid, together with the proposal.
19
+ # - :invalid if the coauthor is not valid.
20
+ #
21
+ # Returns nothing.
22
+ def call
23
+ return broadcast(:invalid) unless @coauthor
24
+ return broadcast(:invalid) if @proposal.authors.include?(@coauthor)
25
+
26
+ begin
27
+ transaction do
28
+ @proposal.add_coauthor(@coauthor)
29
+ @proposal.coauthor_invitations_for(@coauthor).destroy_all
30
+ end
31
+
32
+ generate_notifications
33
+ rescue ActiveRecord::RecordInvalid
34
+ return broadcast(:invalid)
35
+ end
36
+
37
+ broadcast(:ok)
38
+ end
39
+
40
+ private
41
+
42
+ def generate_notifications
43
+ # notify the author that the co-author has accepted the invitation
44
+ Decidim::EventsManager.publish(
45
+ event: "decidim.events.proposals.coauthor_accepted_invite",
46
+ event_class: Decidim::Proposals::CoauthorAcceptedInviteEvent,
47
+ resource: @proposal,
48
+ affected_users: @proposal.authors.reject { |author| author == @coauthor },
49
+ extra: { coauthor_id: @coauthor.id }
50
+ )
51
+
52
+ # notify the co-author of the new co-authorship
53
+ Decidim::EventsManager.publish(
54
+ event: "decidim.events.proposals.accepted_coauthorship",
55
+ event_class: Decidim::Proposals::AcceptedCoauthorshipEvent,
56
+ resource: @proposal,
57
+ affected_users: [@coauthor]
58
+ )
59
+ end
60
+ end
61
+ end
62
+ end
@@ -37,6 +37,7 @@ module Decidim
37
37
  form.proposals.flat_map do |proposal|
38
38
  form.valuator_roles.each do |valuator_role|
39
39
  find_assignment(proposal, valuator_role) || assign_proposal(proposal, valuator_role)
40
+ notify_valuator(proposal, valuator_role)
40
41
  end
41
42
  end
42
43
  end
@@ -57,6 +58,19 @@ module Decidim
57
58
  valuator_role:
58
59
  )
59
60
  end
61
+
62
+ def notify_valuator(proposal, valuator_role)
63
+ return unless valuator_role.user.email_on_assigned_proposals?
64
+
65
+ data = {
66
+ event: "decidim.events.proposals.admin.proposal_assigned_to_valuator",
67
+ event_class: Decidim::Proposals::Admin::ProposalAssignedToValuatorEvent,
68
+ resource: proposal,
69
+ affected_users: [valuator_role.user]
70
+ }
71
+
72
+ Decidim::EventsManager.publish(**data)
73
+ end
60
74
  end
61
75
  end
62
76
  end
@@ -5,8 +5,7 @@ module Decidim
5
5
  module Admin
6
6
  # A command with all the business logic when a user creates a new proposal.
7
7
  class CreateProposal < Decidim::Command
8
- include ::Decidim::AttachmentMethods
9
- include GalleryMethods
8
+ include ::Decidim::MultipleAttachmentsMethods
10
9
  include HashtagsMethods
11
10
 
12
11
  # Public: Initializes the command.
@@ -26,19 +25,13 @@ module Decidim
26
25
  return broadcast(:invalid) if form.invalid?
27
26
 
28
27
  if process_attachments?
29
- build_attachment
30
- return broadcast(:invalid) if attachment_invalid?
31
- end
32
-
33
- if process_gallery?
34
- build_gallery
35
- return broadcast(:invalid) if gallery_invalid?
28
+ build_attachments
29
+ return broadcast(:invalid) if attachments_invalid?
36
30
  end
37
31
 
38
32
  transaction do
39
33
  create_proposal
40
- create_gallery if process_gallery?
41
- create_attachment(weight: first_attachment_weight) if process_attachments?
34
+ create_attachments(first_weight: first_attachment_weight) if process_attachments?
42
35
  link_author_meeting if form.created_in_meeting?
43
36
  end
44
37
 
@@ -49,7 +42,7 @@ module Decidim
49
42
 
50
43
  private
51
44
 
52
- attr_reader :form, :proposal, :attachment, :gallery
45
+ attr_reader :form, :proposal, :attachment
53
46
 
54
47
  def create_proposal
55
48
  @proposal = Decidim::Proposals::ProposalBuilder.create(
@@ -69,8 +62,7 @@ module Decidim
69
62
  {
70
63
  title: parsed_title,
71
64
  body: parsed_body,
72
- category: form.category,
73
- scope: form.scope,
65
+ taxonomizations: form.taxonomizations,
74
66
  component: form.component,
75
67
  address: form.address,
76
68
  latitude: form.latitude,
@@ -5,6 +5,8 @@ module Decidim
5
5
  module Admin
6
6
  # A command with all the business logic when an admin creates a private note proposal.
7
7
  class CreateProposalNote < Decidim::Command
8
+ include ProposalNotesMethods
9
+
8
10
  # Public: Initializes the command.
9
11
  #
10
12
  # form - A form object with the params.
@@ -24,7 +26,8 @@ module Decidim
24
26
  return broadcast(:invalid) if form.invalid?
25
27
 
26
28
  create_proposal_note
27
- notify_admins_and_valuators
29
+ notify_mentioned
30
+ notify_not_mentioned_valuators
28
31
 
29
32
  broadcast(:ok, proposal_note)
30
33
  end
@@ -38,7 +41,7 @@ module Decidim
38
41
  ProposalNote,
39
42
  form.current_user,
40
43
  {
41
- body: form.body,
44
+ body: rewritten_body,
42
45
  proposal:,
43
46
  author: form.current_user
44
47
  },
@@ -48,18 +51,24 @@ module Decidim
48
51
  )
49
52
  end
50
53
 
51
- def notify_admins_and_valuators
52
- affected_users = Decidim::User.org_admins_except_me(form.current_user).all
53
- affected_users += Decidim::Proposals::ValuationAssignment.includes(valuator_role: :user).where.not(id: form.current_user.id).where(proposal:).map(&:valuator)
54
+ def notify_mentioned
55
+ notify_creation(mentioned_admins_or_valuators, "decidim.events.proposals.admin.proposal_note_mentioned")
56
+ end
57
+
58
+ def notify_not_mentioned_valuators
59
+ notify_creation(proposal_valuators - mentioned_admins_or_valuators, "decidim.events.proposals.admin.proposal_note_created")
60
+ end
54
61
 
55
- data = {
56
- event: "decidim.events.proposals.admin.proposal_note_created",
62
+ def notify_creation(affected_users, event)
63
+ return if affected_users.blank?
64
+
65
+ Decidim::EventsManager.publish(
66
+ event:,
57
67
  event_class: Decidim::Proposals::Admin::ProposalNoteCreatedEvent,
58
68
  resource: proposal,
59
- affected_users:
60
- }
61
-
62
- Decidim::EventsManager.publish(**data)
69
+ affected_users:,
70
+ extra: { note_author_id: form.current_user.id }
71
+ )
63
72
  end
64
73
  end
65
74
  end
@@ -47,7 +47,6 @@ module Decidim
47
47
  def proposals
48
48
  @proposals = Decidim::Proposals::Proposal
49
49
  .where(component: origin_component)
50
- @proposals = @proposals.where(scope: proposal_scopes) unless proposal_scopes.empty?
51
50
 
52
51
  @proposals = if @form.states.include?("not_answered")
53
52
  @proposals.not_answered.or(@proposals.where(id: @proposals.only_status(@form.states).pluck(:id)))
@@ -58,10 +57,6 @@ module Decidim
58
57
  @proposals
59
58
  end
60
59
 
61
- def proposal_scopes
62
- @form.scopes
63
- end
64
-
65
60
  def origin_component
66
61
  @form.origin_component
67
62
  end
@@ -32,7 +32,7 @@ module Decidim
32
32
  def merge_proposals
33
33
  transaction do
34
34
  merged_proposal = create_new_proposal
35
- merged_proposal.link_resources(proposals_to_link, "copied_from_component")
35
+ merged_proposal.link_resources(proposals_to_link, "merged_from_component")
36
36
  form.proposals.each(&:destroy!) if form.same_component?
37
37
  merged_proposal
38
38
  end
@@ -46,7 +46,7 @@ module Decidim
46
46
 
47
47
  def previous_links
48
48
  @previous_links ||= form.proposals.flat_map do |proposal|
49
- proposal.linked_resources(:proposals, "copied_from_component")
49
+ proposal.linked_resources(:proposals, "merged_from_component")
50
50
  end
51
51
  end
52
52