decidim-budgets 0.27.9 → 0.28.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/stylesheets/decidim/budgets/budget/_budget-vote-button.scss +5 -5
  4. data/app/cells/decidim/budgets/base_cell.rb +1 -1
  5. data/app/cells/decidim/budgets/budget_cell.rb +6 -1
  6. data/app/cells/decidim/budgets/budget_information_modal/show.erb +14 -26
  7. data/app/cells/decidim/budgets/budget_list_item/projects_count.erb +6 -0
  8. data/app/cells/decidim/budgets/budget_list_item/show.erb +35 -30
  9. data/app/cells/decidim/budgets/budget_list_item/vote_action.erb +13 -0
  10. data/app/cells/decidim/budgets/budget_list_item_cell.rb +24 -1
  11. data/app/cells/decidim/budgets/budget_metadata_cell.rb +29 -0
  12. data/app/cells/decidim/budgets/budget_s_cell.rb +15 -0
  13. data/app/cells/decidim/budgets/budgets_header/show.erb +2 -6
  14. data/app/cells/decidim/budgets/budgets_list/card_list.erb +8 -13
  15. data/app/cells/decidim/budgets/budgets_list/main_list.erb +5 -0
  16. data/app/cells/decidim/budgets/budgets_list/show.erb +12 -16
  17. data/app/cells/decidim/budgets/budgets_list/voted.erb +8 -44
  18. data/app/cells/decidim/budgets/budgets_list_cell.rb +34 -0
  19. data/app/cells/decidim/budgets/limit_announcement/show.erb +3 -0
  20. data/app/cells/decidim/budgets/limit_announcement_cell.rb +2 -2
  21. data/app/cells/decidim/budgets/order_activity_cell.rb +1 -4
  22. data/app/cells/decidim/budgets/project_cell.rb +6 -1
  23. data/app/cells/decidim/budgets/project_l/extra_data.erb +6 -0
  24. data/app/cells/decidim/budgets/project_l/metadata.erb +4 -0
  25. data/app/cells/decidim/budgets/project_l_cell.rb +38 -0
  26. data/app/cells/decidim/budgets/project_metadata_cell.rb +78 -0
  27. data/app/cells/decidim/budgets/project_s_cell.rb +21 -0
  28. data/app/cells/decidim/budgets/project_tags/show.erb +1 -0
  29. data/app/cells/decidim/budgets/project_vote_button/show.erb +21 -15
  30. data/app/cells/decidim/budgets/project_vote_button_cell.rb +69 -1
  31. data/app/cells/decidim/budgets/project_voted_hint_cell.rb +1 -1
  32. data/app/cells/decidim/budgets/project_votes_count_cell.rb +9 -8
  33. data/app/commands/decidim/budgets/admin/create_project.rb +0 -1
  34. data/app/commands/decidim/budgets/admin/import_proposals_to_budgets.rb +1 -1
  35. data/app/commands/decidim/budgets/admin/update_project.rb +1 -2
  36. data/app/commands/decidim/budgets/admin/update_project_scope.rb +1 -1
  37. data/app/commands/decidim/budgets/admin/update_project_selection.rb +1 -1
  38. data/app/commands/decidim/budgets/admin/update_projects_budget.rb +57 -0
  39. data/app/controllers/concerns/decidim/budgets/admin/filterable.rb +1 -1
  40. data/app/controllers/concerns/decidim/budgets/needs_current_order.rb +2 -2
  41. data/app/controllers/decidim/budgets/admin/budgets_controller.rb +5 -5
  42. data/app/controllers/decidim/budgets/admin/projects_controller.rb +52 -10
  43. data/app/controllers/decidim/budgets/admin/proposals_imports_controller.rb +1 -1
  44. data/app/controllers/decidim/budgets/application_controller.rb +0 -4
  45. data/app/controllers/decidim/budgets/budgets_controller.rb +9 -0
  46. data/app/controllers/decidim/budgets/line_items_controller.rb +10 -16
  47. data/app/controllers/decidim/budgets/orders_controller.rb +7 -2
  48. data/app/controllers/decidim/budgets/projects_controller.rb +51 -4
  49. data/app/forms/decidim/budgets/admin/project_form.rb +1 -1
  50. data/app/helpers/decidim/budgets/application_helper.rb +4 -0
  51. data/app/helpers/decidim/budgets/projects_helper.rb +89 -33
  52. data/app/jobs/decidim/budgets/send_vote_reminder_job.rb +1 -1
  53. data/app/mailers/decidim/budgets/order_summary_mailer.rb +1 -1
  54. data/app/mailers/decidim/budgets/vote_reminder_mailer.rb +1 -1
  55. data/app/models/decidim/budgets/budget.rb +1 -0
  56. data/app/models/decidim/budgets/project.rb +17 -7
  57. data/app/packs/entrypoints/decidim_budgets.js +2 -0
  58. data/app/packs/src/decidim/budgets/exit_handler.js +11 -8
  59. data/app/packs/src/decidim/budgets/progressFixed.js +25 -11
  60. data/app/packs/src/decidim/budgets/projects.js +15 -10
  61. data/app/packs/stylesheets/budgets.scss +273 -0
  62. data/app/presenters/decidim/budgets/admin_log/budget_presenter.rb +2 -2
  63. data/app/presenters/decidim/budgets/admin_log/project_presenter.rb +2 -2
  64. data/app/services/decidim/budgets/order_reminder_generator.rb +4 -4
  65. data/app/views/decidim/budgets/admin/budgets/_form.html.erb +17 -12
  66. data/app/views/decidim/budgets/admin/budgets/edit.html.erb +16 -6
  67. data/app/views/decidim/budgets/admin/budgets/index.html.erb +58 -64
  68. data/app/views/decidim/budgets/admin/budgets/new.html.erb +16 -6
  69. data/app/views/decidim/budgets/admin/projects/_bulk-actions.html.erb +19 -10
  70. data/app/views/decidim/budgets/admin/projects/_form.html.erb +31 -35
  71. data/app/views/decidim/budgets/admin/projects/_project-tr.html.erb +15 -13
  72. data/app/views/decidim/budgets/admin/projects/bulk_actions/_budget-change.html.erb +22 -0
  73. data/app/views/decidim/budgets/admin/projects/bulk_actions/_change-selected.html.erb +3 -3
  74. data/app/views/decidim/budgets/admin/projects/bulk_actions/_dropdown.html.erb +8 -2
  75. data/app/views/decidim/budgets/admin/projects/bulk_actions/_recategorize.html.erb +3 -3
  76. data/app/views/decidim/budgets/admin/projects/bulk_actions/_scope-change.html.erb +5 -8
  77. data/app/views/decidim/budgets/admin/projects/edit.html.erb +16 -6
  78. data/app/views/decidim/budgets/admin/projects/index.html.erb +26 -31
  79. data/app/views/decidim/budgets/admin/projects/new.html.erb +16 -6
  80. data/app/views/decidim/budgets/admin/projects/update_attribute.js.erb +8 -4
  81. data/app/views/decidim/budgets/admin/proposals_imports/new.html.erb +40 -28
  82. data/app/views/decidim/budgets/budgets/index.html.erb +21 -3
  83. data/app/views/decidim/budgets/budgets/index.js.erb +6 -0
  84. data/app/views/decidim/budgets/line_items/update_budget.js.erb +21 -11
  85. data/app/views/decidim/budgets/projects/_addition_selector.html.erb +16 -0
  86. data/app/views/decidim/budgets/projects/_budget_confirm.html.erb +42 -31
  87. data/app/views/decidim/budgets/projects/_budget_excess.html.erb +12 -12
  88. data/app/views/decidim/budgets/projects/_budget_summary.html.erb +2 -75
  89. data/app/views/decidim/budgets/projects/_exit_modal.html.erb +15 -18
  90. data/app/views/decidim/budgets/projects/_linked_projects.html.erb +3 -12
  91. data/app/views/decidim/budgets/projects/_order.html.erb +1 -0
  92. data/app/views/decidim/budgets/projects/_order_progress_progressbar_marks_right.html.erb +10 -0
  93. data/app/views/decidim/budgets/projects/_order_progress_summary_content.html.erb +113 -0
  94. data/app/views/decidim/budgets/projects/_order_total_budget.html.erb +6 -7
  95. data/app/views/decidim/budgets/projects/_project.html.erb +2 -1
  96. data/app/views/decidim/budgets/projects/_project_budget_button.html.erb +11 -19
  97. data/app/views/decidim/budgets/projects/_projects.html.erb +8 -6
  98. data/app/views/decidim/budgets/projects/_projects_count.html.erb +5 -0
  99. data/app/views/decidim/budgets/projects/_projects_list.html.erb +3 -0
  100. data/app/views/decidim/budgets/projects/index.html.erb +58 -55
  101. data/app/views/decidim/budgets/projects/index.js.erb +5 -4
  102. data/app/views/decidim/budgets/projects/show.html.erb +78 -51
  103. data/config/assets.rb +0 -1
  104. data/config/locales/ar.yml +0 -50
  105. data/config/locales/bg.yml +0 -381
  106. data/config/locales/ca.yml +75 -84
  107. data/config/locales/cs.yml +73 -82
  108. data/config/locales/de.yml +76 -85
  109. data/config/locales/el.yml +34 -72
  110. data/config/locales/en.yml +79 -88
  111. data/config/locales/es-MX.yml +73 -82
  112. data/config/locales/es-PY.yml +73 -82
  113. data/config/locales/es.yml +75 -84
  114. data/config/locales/eu.yml +74 -86
  115. data/config/locales/fi-plain.yml +75 -84
  116. data/config/locales/fi.yml +79 -88
  117. data/config/locales/fr-CA.yml +74 -86
  118. data/config/locales/fr.yml +78 -90
  119. data/config/locales/ga-IE.yml +0 -12
  120. data/config/locales/gl.yml +0 -58
  121. data/config/locales/hu.yml +58 -81
  122. data/config/locales/id-ID.yml +0 -38
  123. data/config/locales/is-IS.yml +0 -22
  124. data/config/locales/it.yml +0 -84
  125. data/config/locales/ja.yml +69 -81
  126. data/config/locales/ko.yml +0 -54
  127. data/config/locales/lb.yml +0 -85
  128. data/config/locales/lt.yml +59 -82
  129. data/config/locales/lv.yml +0 -44
  130. data/config/locales/nl.yml +0 -96
  131. data/config/locales/no.yml +0 -84
  132. data/config/locales/pl.yml +0 -167
  133. data/config/locales/pt-BR.yml +9 -141
  134. data/config/locales/pt.yml +0 -85
  135. data/config/locales/ro-RO.yml +0 -95
  136. data/config/locales/ru.yml +0 -41
  137. data/config/locales/sk.yml +0 -44
  138. data/config/locales/sq-AL.yml +0 -52
  139. data/config/locales/sr-CS.yml +0 -4
  140. data/config/locales/sv.yml +42 -150
  141. data/config/locales/tr-TR.yml +2 -82
  142. data/config/locales/uk.yml +0 -41
  143. data/config/locales/zh-CN.yml +0 -65
  144. data/config/locales/zh-TW.yml +13 -59
  145. data/lib/decidim/budgets/admin_engine.rb +3 -2
  146. data/lib/decidim/budgets/component.rb +4 -90
  147. data/lib/decidim/budgets/engine.rb +30 -10
  148. data/lib/decidim/budgets/project_serializer.rb +3 -3
  149. data/lib/decidim/budgets/seeds.rb +69 -0
  150. data/lib/decidim/budgets/test/factories.rb +23 -37
  151. data/lib/decidim/budgets/version.rb +1 -1
  152. data/lib/decidim/budgets/workflows/base.rb +1 -1
  153. metadata +46 -42
  154. data/app/cells/decidim/budgets/budget_m/data.erb +0 -12
  155. data/app/cells/decidim/budgets/budget_m/footer.erb +0 -5
  156. data/app/cells/decidim/budgets/budget_m_cell.rb +0 -16
  157. data/app/cells/decidim/budgets/project_list_item/project_data.erb +0 -19
  158. data/app/cells/decidim/budgets/project_list_item/project_image.erb +0 -5
  159. data/app/cells/decidim/budgets/project_list_item/project_text.erb +0 -23
  160. data/app/cells/decidim/budgets/project_list_item/show.erb +0 -5
  161. data/app/cells/decidim/budgets/project_list_item_cell.rb +0 -70
  162. data/app/cells/decidim/budgets/project_m/data.erb +0 -12
  163. data/app/cells/decidim/budgets/project_m/footer.erb +0 -5
  164. data/app/cells/decidim/budgets/project_m_cell.rb +0 -22
  165. data/app/packs/stylesheets/decidim/budgets/_budgets.scss +0 -3
  166. data/app/packs/stylesheets/decidim/budgets/budget/_budget-list.scss +0 -198
  167. data/app/packs/stylesheets/decidim/budgets/budget/_budget-meter.scss +0 -83
  168. data/app/packs/stylesheets/decidim/budgets/budget/_progress.scss +0 -19
  169. data/app/views/decidim/budgets/admin/projects/proposals_picker.html.erb +0 -1
  170. data/app/views/decidim/budgets/projects/_filters.html.erb +0 -30
  171. data/app/views/decidim/budgets/projects/_filters_small_view.html.erb +0 -18
  172. data/app/views/decidim/budgets/projects/_order_progress.html.erb +0 -32
  173. data/app/views/decidim/budgets/projects/_order_selected_projects.html.erb +0 -27
  174. data/config/locales/he-IL.yml +0 -1
  175. data/decidim-budgets.gemspec +0 -34
  176. data/lib/decidim/budgets/seeds/city.jpeg +0 -0
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Budgets
5
+ # This cell renders metadata for an instance of a Project
6
+ class ProjectMetadataCell < Decidim::CardMetadataCell
7
+ include Decidim::Budgets::ProjectsHelper
8
+
9
+ delegate :selected?, to: :model
10
+
11
+ alias project model
12
+
13
+ def initialize(*)
14
+ super
15
+
16
+ @items.prepend(*project_items)
17
+ end
18
+
19
+ private
20
+
21
+ def project_items
22
+ [voted_item, category_item, scope_item, status_item]
23
+ end
24
+
25
+ def project_items_for_map
26
+ [voted_item_for_map, category_item, scope_item].compact_blank.map do |item|
27
+ {
28
+ text: item[:text].to_s.html_safe,
29
+ icon: item[:icon].present? ? icon(item[:icon]).html_safe : nil
30
+ }
31
+ end
32
+ end
33
+
34
+ def voted_item_for_map
35
+ {
36
+ text: "#{model.confirmed_orders_count} #{t("decidim.budgets.projects.project.votes", count: model.confirmed_orders_count)}",
37
+ icon: current_order_checked_out? && resource_added? ? "check-double-line" : "check-line"
38
+ }
39
+ end
40
+
41
+ def show_votes_count?
42
+ project.component.current_settings.show_votes?
43
+ end
44
+
45
+ def voted_item
46
+ return unless show_votes_count? && model.confirmed_orders_count.positive?
47
+
48
+ {
49
+ cell: "decidim/budgets/project_votes_count",
50
+ args: [model, { layout: :one_line }],
51
+ icon: current_order_checked_out? && resource_added? ? "check-double-line" : "check-line"
52
+ }
53
+ end
54
+
55
+ def status_item
56
+ return unless controller.try(:voting_finished?) && selected?
57
+
58
+ {
59
+ cell: "decidim/budgets/project_selected_status",
60
+ args: model,
61
+ icon: "question-line"
62
+ }
63
+ end
64
+
65
+ def current_order
66
+ @current_order ||= controller.try(:current_order)
67
+ end
68
+
69
+ def resource_added?
70
+ current_order && current_order.projects.include?(model)
71
+ end
72
+
73
+ def current_order_checked_out?
74
+ current_order&.checked_out?
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cell/partial"
4
+
5
+ module Decidim
6
+ module Budgets
7
+ # This cell renders the Search (:s) project card
8
+ # for an instance of a Project
9
+ class ProjectSCell < Decidim::CardSCell
10
+ private
11
+
12
+ def resource_path
13
+ resource_locator([model.budget, model]).path
14
+ end
15
+
16
+ def metadata_cell
17
+ "decidim/budgets/project_metadata"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,4 +1,5 @@
1
1
  <%= content_tag :ul, class: tags_classes do %>
2
+ <%= icon "price-tag-3-line", class: "inline-block" %>
2
3
  <%= content_tag :li, link_to_category if category? %>
3
4
 
4
5
  <%= content_tag :li, link_to_scope if scope? %>
@@ -1,17 +1,23 @@
1
1
  <%= action_authorized_button_to "vote",
2
- budget_order_line_item_path(model.budget, project_id: model),
3
- method: vote_button_method,
4
- remote: true,
5
- class: "button tiny budget-list__action #{vote_button_class}",
6
- id: "project-vote-button-#{model.id}",
7
- data: {
8
- add: !resource_added?,
9
- disable: true,
10
- budget: model.budget_amount,
11
- allocation: resource_allocation,
12
- "redirect-url": resource_path
13
- },
14
- disabled: vote_button_disabled?,
15
- title: vote_button_label do %>
16
- <%= icon(resource_added? ? "x" : "check", class: "icon--small", aria_label: vote_button_label, role: "img") %>
2
+ budget_order_line_item_path(model.budget, project_id: model, show_only_added: options[:show_only_added]),
3
+ method: vote_button_method,
4
+ remote: true,
5
+ class: "button w-full #{vote_button_classes}",
6
+ id: "project-vote-button-#{model.id}",
7
+ data: {
8
+ add: !resource_added?,
9
+ disable: true,
10
+ budget: model.budget_amount,
11
+ allocation: resource_allocation,
12
+ "redirect-url": resource_path
13
+ },
14
+ disabled: vote_button_disabled?,
15
+ title: vote_button_label do %>
16
+ <% if resource_added? %>
17
+ <%= t("added", scope: "decidim.budgets.projects.project_budget_button") %>
18
+ <%= icon "checkbox-circle-line", class: "inline-block" %>
19
+ <% else %>
20
+ <%= t("add", scope: "decidim.budgets.projects.project_budget_button") %>
21
+ <%= icon "add-fill", class: "inline-block" %>
22
+ <% end %>
17
23
  <% end %>
@@ -4,7 +4,75 @@ module Decidim
4
4
  module Budgets
5
5
  # This cell renders an authorized_action button
6
6
  # to vote a given instance of a Project in a budget list
7
- class ProjectVoteButtonCell < ProjectListItemCell
7
+ class ProjectVoteButtonCell < Decidim::ViewModel
8
+ include Decidim::ActionAuthorizationHelper
9
+ include Decidim::Budgets::ProjectsHelper
10
+ include Decidim::Budgets::Engine.routes.url_helpers
11
+
12
+ delegate :current_user, :current_order, :current_component, :can_have_order?, to: :parent_controller
13
+
14
+ private
15
+
16
+ def project_item?
17
+ options[:project_item]
18
+ end
19
+
20
+ def resource_path
21
+ resource_locator([model.budget, model]).path
22
+ end
23
+
24
+ def resource_title
25
+ translated_attribute model.title
26
+ end
27
+
28
+ def resource_added?
29
+ current_order && current_order.projects.include?(model)
30
+ end
31
+
32
+ def resource_allocation
33
+ current_order.allocation_for(model)
34
+ end
35
+
36
+ def vote_button_disabled?
37
+ current_user && !can_have_order?
38
+ end
39
+
40
+ def vote_button_classes
41
+ classes = []
42
+
43
+ classes << if resource_added?
44
+ "success button__secondary budget-list__data--added"
45
+ else
46
+ "hollow button__transparent-secondary"
47
+ end
48
+
49
+ classes << if project_item?
50
+ "button__lg"
51
+ else
52
+ "button__sm"
53
+ end
54
+
55
+ classes << "budget-list__action" unless vote_button_disabled?
56
+
57
+ classes.join(" ")
58
+ end
59
+
60
+ def vote_button_method
61
+ return :delete if resource_added?
62
+
63
+ :post
64
+ end
65
+
66
+ def vote_button_label
67
+ if resource_added?
68
+ return t(
69
+ "decidim.budgets.projects.project.remove",
70
+ resource_name: resource_title
71
+ )
72
+ end
73
+
74
+ t("decidim.budgets.projects.project.add", resource_name: resource_title)
75
+ end
8
76
  end
9
77
  end
10
78
  end
@@ -18,7 +18,7 @@ module Decidim
18
18
 
19
19
  def hint
20
20
  contents = []
21
- contents << icon("check", role: "img", "aria-hidden": true)
21
+ contents << icon("check-line", role: "img", "aria-hidden": true)
22
22
  contents << " "
23
23
  contents << t("decidim.budgets.projects.project.you_voted")
24
24
  end
@@ -6,7 +6,6 @@ module Decidim
6
6
  # Two possible layouts: One or two lines
7
7
  class ProjectVotesCountCell < Decidim::ViewModel
8
8
  include Decidim::IconHelper
9
- delegate :show_votes_count?, to: :controller
10
9
 
11
10
  def show
12
11
  return unless show_votes_count?
@@ -16,22 +15,24 @@ module Decidim
16
15
 
17
16
  private
18
17
 
18
+ def show_votes_count?
19
+ model.component.current_settings.show_votes?
20
+ end
21
+
19
22
  def content
20
23
  if options[:layout] == :one_line
21
- safe_join([model.confirmed_orders_count, " ", label(t("decidim.budgets.projects.project.votes",
22
- count: model.confirmed_orders_count))])
24
+ safe_join([model.confirmed_orders_count, " ", count_label])
23
25
  else
24
- safe_join([number, label(t("decidim.budgets.projects.project.votes",
25
- count: model.confirmed_orders_count))])
26
+ safe_join([number, count_label])
26
27
  end
27
28
  end
28
29
 
29
30
  def number
30
- content_tag :div, model.confirmed_orders_count, class: "text-large"
31
+ content_tag :div, model.confirmed_orders_count
31
32
  end
32
33
 
33
- def label(i18n_string)
34
- content_tag :span, i18n_string, class: "text-uppercase text-small"
34
+ def count_label
35
+ content_tag(:span, t("decidim.budgets.projects.project.votes", count: model.confirmed_orders_count))
35
36
  end
36
37
 
37
38
  def css_class
@@ -6,7 +6,6 @@ module Decidim
6
6
  # This command is executed when the user creates a Project from the admin
7
7
  # panel.
8
8
  class CreateProject < Decidim::Command
9
- include ::Decidim::AttachmentMethods
10
9
  include ::Decidim::GalleryMethods
11
10
 
12
11
  def initialize(form)
@@ -16,7 +16,7 @@ module Decidim
16
16
  # Executes the command. Broadcasts these events:
17
17
  #
18
18
  # - :ok when everything is valid.
19
- # - :invalid if the form wasn't valid and we couldn't proceed.
19
+ # - :invalid if the form was not valid and we could not proceed.
20
20
  #
21
21
  # Returns nothing.
22
22
  def call
@@ -6,7 +6,6 @@ module Decidim
6
6
  # This command is executed when the user changes a Project from the admin
7
7
  # panel.
8
8
  class UpdateProject < Decidim::Command
9
- include ::Decidim::AttachmentMethods
10
9
  include ::Decidim::GalleryMethods
11
10
 
12
11
  # Initializes an UpdateProject Command.
@@ -53,7 +52,7 @@ module Decidim
53
52
  title: form.title,
54
53
  description: form.description,
55
54
  budget_amount: form.budget_amount,
56
- selected_at: selected_at,
55
+ selected_at:,
57
56
  address: form.address,
58
57
  latitude: form.latitude,
59
58
  longitude: form.longitude
@@ -45,7 +45,7 @@ module Decidim
45
45
 
46
46
  def update_project_scope(project)
47
47
  project.update!(
48
- scope: scope
48
+ scope:
49
49
  )
50
50
  end
51
51
  end
@@ -47,7 +47,7 @@ module Decidim
47
47
  def update_project_selection(project)
48
48
  selected_at = selection ? Time.current : nil
49
49
  project.update!(
50
- selected_at: selected_at
50
+ selected_at:
51
51
  )
52
52
  end
53
53
  end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Budgets
5
+ module Admin
6
+ class UpdateProjectsBudget < Decidim::Command
7
+ include TranslatableAttributes
8
+
9
+ # Public: Initializes the command.
10
+ #
11
+ # destination_budget - the destination budget for which the projects should update to.
12
+ # project_ids - the project ids to update.
13
+ def initialize(destination_budget, project_ids)
14
+ @destination_budget = destination_budget
15
+ @project_ids = project_ids
16
+ @response = { selection_name: "", successful: [], errored: [], failed_ids: [] }
17
+ end
18
+
19
+ def call
20
+ return broadcast(:invalid_project_ids) if @project_ids.blank?
21
+ return broadcast(:invalid_project_ids) if @destination_budget.blank?
22
+
23
+ update_projects_budget
24
+
25
+ broadcast(:update_projects_budget, @response)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :selection, :project_ids
31
+
32
+ def update_projects_budget
33
+ ::Decidim::Budgets::Project.includes(:budget, budget: { component: :participatory_space }).where(id: project_ids).find_each do |project|
34
+ if update_allowed?(project)
35
+ transaction do
36
+ project.update!(
37
+ decidim_budgets_budget_id: @destination_budget.id
38
+ )
39
+ end
40
+ @response[:successful] << translated_attribute(project.title)
41
+ else
42
+ @response[:errored] << translated_attribute(project.title)
43
+ @response[:failed_ids] << project.id
44
+ end
45
+ end
46
+ end
47
+
48
+ def update_allowed?(project)
49
+ origin_budget = project.budget
50
+ return false if origin_budget == @destination_budget
51
+
52
+ origin_budget.participatory_space == @destination_budget.participatory_space
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -39,7 +39,7 @@ module Decidim
39
39
  }
40
40
  end
41
41
 
42
- # Can't user `super` here, because it does not belong to a superclass
42
+ # Cannot user `super` here, because it does not belong to a superclass
43
43
  # but to a concern.
44
44
  def dynamically_translated_filters
45
45
  [:scope_id_eq, :category_id_eq]
@@ -15,7 +15,7 @@ module Decidim
15
15
  #
16
16
  # Returns an Order.
17
17
  def current_order
18
- @current_order ||= Order.includes(:projects).find_or_initialize_by(user: current_user, budget: budget)
18
+ @current_order ||= Order.includes(:projects).find_or_initialize_by(user: current_user, budget:)
19
19
  end
20
20
 
21
21
  def current_order=(order)
@@ -30,7 +30,7 @@ module Decidim
30
30
  current_user.present? &&
31
31
  voting_open? &&
32
32
  current_participatory_space.can_participate?(current_user) &&
33
- allowed_to?(:create, :order, budget: budget, workflow: current_workflow)
33
+ allowed_to?(:create, :order, budget:, workflow: current_workflow)
34
34
  end
35
35
 
36
36
  # Return true if the user has voted the project
@@ -15,7 +15,7 @@ module Decidim
15
15
 
16
16
  def create
17
17
  enforce_permission_to :create, :budget
18
- @form = form(BudgetForm).from_params(params, current_component: current_component)
18
+ @form = form(BudgetForm).from_params(params, current_component:)
19
19
 
20
20
  CreateBudget.call(@form) do
21
21
  on(:ok) do
@@ -31,13 +31,13 @@ module Decidim
31
31
  end
32
32
 
33
33
  def edit
34
- enforce_permission_to :update, :budget, budget: budget
34
+ enforce_permission_to(:update, :budget, budget:)
35
35
  @form = form(BudgetForm).from_model(budget)
36
36
  end
37
37
 
38
38
  def update
39
- enforce_permission_to :update, :budget, budget: budget
40
- @form = form(BudgetForm).from_params(params, current_component: current_component)
39
+ enforce_permission_to(:update, :budget, budget:)
40
+ @form = form(BudgetForm).from_params(params, current_component:)
41
41
 
42
42
  UpdateBudget.call(@form, budget) do
43
43
  on(:ok) do
@@ -53,7 +53,7 @@ module Decidim
53
53
  end
54
54
 
55
55
  def destroy
56
- enforce_permission_to :delete, :budget, budget: budget
56
+ enforce_permission_to(:delete, :budget, budget:)
57
57
 
58
58
  DestroyBudget.call(budget, current_user) do
59
59
  on(:ok) do
@@ -6,9 +6,9 @@ module Decidim
6
6
  # This controller allows an admin to manage projects from a Participatory Process
7
7
  class ProjectsController < Admin::ApplicationController
8
8
  include Decidim::ApplicationHelper
9
- include Decidim::Proposals::Admin::Picker if Decidim::Budgets.enable_proposal_linking
10
9
  include Decidim::Budgets::Admin::Filterable
11
10
  helper Decidim::Budgets::Admin::ProjectBulkActionsHelper
11
+ helper Decidim::Budgets::ProjectsHelper
12
12
 
13
13
  helper_method :projects, :finished_orders, :pending_orders, :present, :project_ids
14
14
 
@@ -19,15 +19,14 @@ module Decidim
19
19
  def new
20
20
  enforce_permission_to :create, :project
21
21
  @form = form(ProjectForm).from_params(
22
- { attachment: form(AttachmentForm).instance },
23
- budget: budget
22
+ attachment: form(AttachmentForm).instance
24
23
  )
25
24
  end
26
25
 
27
26
  def create
28
27
  enforce_permission_to :create, :project
29
28
 
30
- @form = form(ProjectForm).from_params(params, budget: budget)
29
+ @form = form(ProjectForm).from_params(params, budget:)
31
30
 
32
31
  CreateProject.call(@form) do
33
32
  on(:ok) do
@@ -43,14 +42,14 @@ module Decidim
43
42
  end
44
43
 
45
44
  def edit
46
- enforce_permission_to :update, :project, project: project
47
- @form = form(ProjectForm).from_model(project, budget: budget)
45
+ enforce_permission_to(:update, :project, project:)
46
+ @form = form(ProjectForm).from_model(project)
48
47
  @form.attachment = form(AttachmentForm).instance
49
48
  end
50
49
 
51
50
  def update
52
- enforce_permission_to :update, :project, project: project
53
- @form = form(ProjectForm).from_params(params, budget: budget)
51
+ enforce_permission_to(:update, :project, project:)
52
+ @form = form(ProjectForm).from_params(params, budget:)
54
53
 
55
54
  UpdateProject.call(@form, project) do
56
55
  on(:ok) do
@@ -66,7 +65,7 @@ module Decidim
66
65
  end
67
66
 
68
67
  def destroy
69
- enforce_permission_to :destroy, :project, project: project
68
+ enforce_permission_to(:destroy, :project, project:)
70
69
 
71
70
  DestroyProject.call(project, current_user) do
72
71
  on(:ok) do
@@ -163,6 +162,25 @@ module Decidim
163
162
  end
164
163
  end
165
164
 
165
+ def update_budget
166
+ enforce_permission_to :update, :project, project: sample_project
167
+ ::Decidim::Budgets::Admin::UpdateProjectsBudget.call(reference_budget, project_ids) do
168
+ on(:invalid_project_ids) do
169
+ flash.now[:alert] = t("projects.update_budget.select_a_project", scope: "decidim.budgets.admin")
170
+ end
171
+
172
+ on(:update_projects_budget) do
173
+ moved_items(@response)
174
+ flash.now[:notice] = update_projects_bulk_response_successful(@response, :budget)
175
+ flash.now[:alert] = update_projects_bulk_response_errored(@response, :budget)
176
+ end
177
+ end
178
+
179
+ respond_to do |format|
180
+ format.js { render :update_attribute, locals: { form_selector: "#js-form-budget-change-projects", attribute_selector: "#selected_value", moved_items: } }
181
+ end
182
+ end
183
+
166
184
  private
167
185
 
168
186
  def projects
@@ -170,13 +188,19 @@ module Decidim
170
188
  end
171
189
 
172
190
  def orders
173
- @orders ||= Order.where(budget: budget)
191
+ @orders ||= Order.where(budget:)
174
192
  end
175
193
 
176
194
  def project_ids
177
195
  @project_ids ||= params[:project_ids]
178
196
  end
179
197
 
198
+ def reference_budget
199
+ return unless params[:reference_id]
200
+
201
+ Budget.find(params[:reference_id])
202
+ end
203
+
180
204
  def pending_orders
181
205
  orders.pending
182
206
  end
@@ -185,6 +209,12 @@ module Decidim
185
209
  orders.finished
186
210
  end
187
211
 
212
+ def sample_project
213
+ return if project_ids.empty?
214
+
215
+ Decidim::Budgets::Project.find(project_ids.first)
216
+ end
217
+
188
218
  def project
189
219
  @project ||= projects.find(params[:id])
190
220
  end
@@ -202,6 +232,8 @@ module Decidim
202
232
  t("projects.update_category.success", scope: "decidim.budgets.admin", **interpolations)
203
233
  when :scope
204
234
  t("projects.update_scope.success", scope: "decidim.budgets.admin", **interpolations)
235
+ when :budget
236
+ t("projects.update_budget.success", scope: "decidim.budgets.admin", **interpolations)
205
237
  when :selected
206
238
  if extra[:selection]
207
239
  t("projects.update_selected.success.selected", scope: "decidim.budgets.admin", **interpolations)
@@ -224,6 +256,8 @@ module Decidim
224
256
  t("projects.update_category.invalid", scope: "decidim.budgets.admin", **interpolations)
225
257
  when :scope
226
258
  t("projects.update_scope.invalid", scope: "decidim.budgets.admin", **interpolations)
259
+ when :budget
260
+ t("projects.update_budget.invalid", scope: "decidim.budgets.admin", **interpolations)
227
261
  when :selected
228
262
  if extra[:selection]
229
263
  t("projects.update_selected.invalid.selected", scope: "decidim.budgets.admin", **interpolations)
@@ -232,6 +266,14 @@ module Decidim
232
266
  end
233
267
  end
234
268
  end
269
+
270
+ def moved_items(response = nil)
271
+ @moved_items ||= if response
272
+ @project_ids - response[:failed_ids]
273
+ else
274
+ @project_ids
275
+ end
276
+ end
235
277
  end
236
278
  end
237
279
  end
@@ -15,7 +15,7 @@ module Decidim
15
15
  def create
16
16
  enforce_permission_to :import_proposals, :projects
17
17
 
18
- @form = form(Admin::ProjectImportProposalsForm).from_params(params, budget: budget)
18
+ @form = form(Admin::ProjectImportProposalsForm).from_params(params, budget:)
19
19
  Admin::ImportProposalsToBudgets.call(@form) do
20
20
  on(:ok) do |projects|
21
21
  flash[:notice] = I18n.t("proposals_imports.create.success", scope: "decidim.budgets.admin", number: projects.length)
@@ -22,10 +22,6 @@ module Decidim
22
22
  current_settings.votes == "finished"
23
23
  end
24
24
 
25
- def show_votes_count?
26
- current_settings.show_votes?
27
- end
28
-
29
25
  private
30
26
 
31
27
  def workflow_name
@@ -4,6 +4,11 @@ module Decidim
4
4
  module Budgets
5
5
  # Exposes the budget resources so users can participate on them
6
6
  class BudgetsController < Decidim::Budgets::ApplicationController
7
+ helper_method :announcement_body
8
+
9
+ include Decidim::Budgets::Orderable
10
+ include Decidim::TranslatableAttributes
11
+
7
12
  def index
8
13
  redirect_to budget_projects_path(current_workflow.single) if current_workflow.single?
9
14
  end
@@ -16,6 +21,10 @@ module Decidim
16
21
 
17
22
  private
18
23
 
24
+ def announcement_body
25
+ @announcement_body ||= [translated_attribute(current_settings.announcement), translated_attribute(component_settings.announcement)].find(&:present?)&.html_safe
26
+ end
27
+
19
28
  def budget
20
29
  @budget ||= Budget.where(component: current_component).includes(:projects).find_by(id: params[:id])
21
30
  end