decidim-proposals 0.29.2 → 0.30.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +55 -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 +24 -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 +17 -24
  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 +14 -26
  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 +215 -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: 57ef0ea1b3c03d7770041d74f7f95183817088ae774fcfe6c1b3ffdb5be89569
4
+ data.tar.gz: d289bc845f005d511a24cc72e7051b65a30d3756165b431c7b9bc6e140bcc702
5
5
  SHA512:
6
- metadata.gz: fd2a28b72d4d22a47f40a4ccbd000421d19c0e014f0788a6888ce36f6665660c5d2d3c862b034280cc4798da73d1137fe4815e773ac48113a89a1baeacee9d2e
7
- data.tar.gz: 499ac55e1d39ae1b19c105f69187ef399ee5bb97d110ea7ab6f15cef2aaa08c30456c12dbb45a85ff72041aaf0d38df9fca5b202e895286a7e2731e450eca263
6
+ metadata.gz: 9a7c6d25457ecc074a0bc261a4155c6d8040cc8ec3b39e444369ff52b48711bfb6e66a49fd970d23dfd6515556448ac7cc5b1befc8e1fef65369fd900df2cb98
7
+ data.tar.gz: 1defeac441eec1dae4c002710b4c51efbb70d40b1e4a4e6edba3cd4151cb05ebd81c4c4a2e5344d39159f9c763dfcddcd5df320e3ccaac4356a37103d9379fd9
@@ -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