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
@@ -9,24 +9,18 @@ module Decidim
9
9
  helper_method :budget, :project
10
10
 
11
11
  def create
12
- enforce_permission_to :vote, :project, project: project, budget: budget, workflow: current_workflow
12
+ enforce_permission_to :vote, :project, project:, budget:, workflow: current_workflow
13
13
 
14
14
  respond_to do |format|
15
- # Note that the user-specific lock here is important in order to
16
- # prevent multiple simultaneous processes on different machines from
17
- # creating multiple orders for the same user in case the button is
18
- # pressed multiple times.
19
- current_user.with_lock do
20
- AddLineItem.call(persisted_current_order, project, current_user) do
21
- on(:ok) do |order|
22
- self.current_order = order
23
- format.html { redirect_back(fallback_location: budget_path(budget)) }
24
- format.js { render "update_budget" }
25
- end
26
-
27
- on(:invalid) do
28
- format.js { render "update_budget", status: :unprocessable_entity }
29
- end
15
+ AddLineItem.call(persisted_current_order, project, current_user) do
16
+ on(:ok) do |order|
17
+ self.current_order = order
18
+ format.html { redirect_back(fallback_location: budget_path(budget)) }
19
+ format.js { render "update_budget" }
20
+ end
21
+
22
+ on(:invalid) do
23
+ format.js { render "update_budget", status: :unprocessable_entity }
30
24
  end
31
25
  end
32
26
  end
@@ -7,11 +7,12 @@ module Decidim
7
7
  include NeedsCurrentOrder
8
8
 
9
9
  def checkout
10
- enforce_permission_to :vote, :project, order: current_order, budget: budget, workflow: current_workflow
10
+ enforce_permission_to :vote, :project, order: current_order, budget:, workflow: current_workflow
11
11
 
12
12
  Checkout.call(current_order) do
13
13
  on(:ok) do
14
- flash[:notice] = I18n.t("orders.checkout.success", scope: "decidim")
14
+ i18n_key = pending_to_vote_budgets.any? ? "success_html" : "success_no_left_budgets_html"
15
+ flash[:notice] = I18n.t(i18n_key, scope: "decidim.orders.checkout", rest_of_budgets_link: "#budgets")
15
16
  redirect_to budgets_path
16
17
  end
17
18
 
@@ -49,6 +50,10 @@ module Decidim
49
50
  budgets_path
50
51
  end
51
52
  end
53
+
54
+ def pending_to_vote_budgets
55
+ current_workflow.budgets - current_workflow.voted - [current_order.budget]
56
+ end
52
57
  end
53
58
  end
54
59
  end
@@ -7,8 +7,9 @@ module Decidim
7
7
  include FilterResource
8
8
  include NeedsCurrentOrder
9
9
  include Decidim::Budgets::Orderable
10
+ include Decidim::IconHelper
10
11
 
11
- helper_method :projects, :project, :budget, :all_geocoded_projects
12
+ helper_method :projects, :project, :budget, :all_geocoded_projects, :tabs, :panels
12
13
 
13
14
  def index
14
15
  raise ActionController::RoutingError, "Not Found" unless budget
@@ -41,15 +42,16 @@ module Decidim
41
42
  end
42
43
 
43
44
  def search_collection
44
- Project.where(budget: budget).includes([:scope, :component, :attachments, :category])
45
+ budget.projects.includes([:scope, :component, :attachments, :category]).with_order(filter_params[:addition_type] == "added" ? current_order : nil)
45
46
  end
46
47
 
47
48
  def default_filter_params
48
49
  {
49
50
  search_text_cont: "",
50
51
  with_any_status: default_filter_status_params,
51
- with_any_scope: default_filter_scope_params,
52
- with_any_category: default_filter_category_params
52
+ with_any_scope: nil,
53
+ with_any_category: nil,
54
+ addition_type: "all"
53
55
  }
54
56
  end
55
57
 
@@ -60,6 +62,51 @@ module Decidim
60
62
  def show_selected_budgets?
61
63
  voting_finished? && budget.projects.selected.any?
62
64
  end
65
+
66
+ def tabs
67
+ @tabs ||= items.map { |item| item.slice(:id, :text, :icon) }
68
+ end
69
+
70
+ def panels
71
+ @panels ||= items.map { |item| item.slice(:id, :method, :args) }
72
+ end
73
+
74
+ def items
75
+ @items ||= [
76
+ {
77
+ enabled: @project.linked_resources(:proposals, "included_proposals").present?,
78
+ id: "included_proposals",
79
+ text: t("decidim/proposals/proposal", scope: "activerecord.models", count: 2),
80
+ icon: resource_type_icon_key("Decidim::Budgets::Project"),
81
+ method: :cell,
82
+ args: ["decidim/linked_resources_for", @project, { type: :proposals, link_name: "included_proposals" }]
83
+ },
84
+ {
85
+ enabled: @project.linked_resources(:results, "included_projects").present?,
86
+ id: "included_results",
87
+ text: t("decidim/accountability/result", scope: "activerecord.models", count: 2),
88
+ icon: resource_type_icon_key("Decidim::Accountability::Result"),
89
+ method: :cell,
90
+ args: ["decidim/linked_resources_for", @project, { type: :results, link_name: "included_projects" }]
91
+ },
92
+ {
93
+ enabled: @project.photos.present?,
94
+ id: "images",
95
+ text: t("decidim.application.photos.photos"),
96
+ icon: resource_type_icon_key("images"),
97
+ method: :cell,
98
+ args: ["decidim/images_panel", @project]
99
+ },
100
+ {
101
+ enabled: @project.documents.present?,
102
+ id: "documents",
103
+ text: t("decidim.application.documents.documents"),
104
+ icon: resource_type_icon_key("documents"),
105
+ method: :cell,
106
+ args: ["decidim/documents_panel", @project]
107
+ }
108
+ ].select { |item| item[:enabled] }
109
+ end
63
110
  end
64
111
  end
65
112
  end
@@ -95,7 +95,7 @@ module Decidim
95
95
 
96
96
  private
97
97
 
98
- # This method will add an error to the `attachment` field only if there's
98
+ # This method will add an error to the `attachment` field only if there is
99
99
  # any error in any other field. This is needed because when the form has
100
100
  # an error, the attachment is lost, so we need a way to inform the user of
101
101
  # this problem.
@@ -19,6 +19,10 @@ module Decidim
19
19
  ]
20
20
  )
21
21
  end
22
+
23
+ def component_name
24
+ (defined?(current_component) && translated_attribute(current_component&.name).presence) || t("decidim.components.budgets.name")
25
+ end
22
26
  end
23
27
  end
24
28
  end
@@ -44,44 +44,61 @@ module Decidim
44
44
  current_order&.can_checkout?
45
45
  end
46
46
 
47
- def current_rule_explanation
48
- return unless current_order
47
+ # Returns false if the current order does not have a rule for minimum budget
48
+ # Returns false if the current order has not reached the minimum budget
49
+ # Otherwhise returns true
50
+ def current_order_minimum_reached?
51
+ return false if current_order.minimum_budget.zero?
49
52
 
50
- if current_order.projects_rule?
51
- if current_order.minimum_projects.positive? && current_order.minimum_projects < current_order.maximum_projects
52
- t(
53
- ".projects_rule.instruction",
54
- minimum_number: current_order.minimum_projects,
55
- maximum_number: current_order.maximum_projects
56
- )
57
- else
58
- t(".projects_rule_maximum_only.instruction", maximum_number: current_order.maximum_projects)
59
- end
60
- elsif current_order.minimum_projects_rule?
61
- t(".minimum_projects_rule.instruction", minimum_number: current_order.minimum_projects)
53
+ current_order.total > current_order.minimum_budget
54
+ end
55
+
56
+ def current_rule_call_for_action_text
57
+ return "" unless current_order
58
+
59
+ if current_order_minimum_reached?
60
+ t("minimum_reached", scope: "decidim.budgets.projects.order_progress.dynamic_help")
61
+ elsif current_order.projects.empty?
62
+ t("start_adding_projects", scope: "decidim.budgets.projects.order_progress.dynamic_help")
62
63
  else
63
- t(".vote_threshold_percent_rule.instruction", minimum_budget: budget_to_currency(current_order.minimum_budget))
64
+ t("keep_adding_projects", scope: "decidim.budgets.projects.order_progress.dynamic_help")
64
65
  end
65
66
  end
66
67
 
67
68
  def current_rule_description
68
69
  return unless current_order
69
70
 
70
- if current_order.projects_rule?
71
- if current_order.minimum_projects.positive? && current_order.minimum_projects < current_order.maximum_projects
72
- t(
73
- ".projects_rule.description",
74
- minimum_number: current_order.minimum_projects,
75
- maximum_number: current_order.maximum_projects
76
- )
77
- else
78
- t(".projects_rule_maximum_only.description", maximum_number: current_order.maximum_projects)
79
- end
80
- elsif current_order.minimum_projects_rule?
81
- t(".minimum_projects_rule.description", minimum_number: current_order.minimum_projects)
82
- else
83
- t(".vote_threshold_percent_rule.description", minimum_budget: budget_to_currency(current_order.minimum_budget))
84
- end
71
+ rule_text = if current_order_minimum_reached?
72
+ ""
73
+ elsif current_order.projects_rule?
74
+ if current_order.minimum_projects.positive? && current_order.minimum_projects < current_order.maximum_projects
75
+ t(
76
+ "projects_rule.description",
77
+ scope: "decidim.budgets.projects.order_progress",
78
+ minimum_number: current_order.minimum_projects,
79
+ maximum_number: current_order.maximum_projects
80
+ )
81
+ else
82
+ t(
83
+ "projects_rule_maximum_only.description",
84
+ scope: "decidim.budgets.projects.order_progress",
85
+ maximum_number: current_order.maximum_projects
86
+ )
87
+ end
88
+ elsif current_order.minimum_projects_rule?
89
+ t(
90
+ "minimum_projects_rule.description",
91
+ scope: "decidim.budgets.projects.order_progress",
92
+ minimum_number: current_order.minimum_projects
93
+ )
94
+ else
95
+ t(
96
+ "vote_threshold_percent_rule.description",
97
+ scope: "decidim.budgets.projects.order_progress",
98
+ minimum_budget: budget_to_currency(current_order.minimum_budget)
99
+ )
100
+ end
101
+ %(<strong>#{current_rule_call_for_action_text}</strong>. #{rule_text}).html_safe
85
102
  end
86
103
 
87
104
  # Serialize a collection of geocoded projects to be used by the dynamic map component
@@ -98,9 +115,8 @@ module Decidim
98
115
  .slice(:latitude, :longitude, :address)
99
116
  .merge(
100
117
  title: decidim_html_escape(translated_attribute(project.title)),
101
- description: html_truncate(decidim_sanitize_editor(translated_attribute(project.description)), length: 100),
102
- icon: icon("project", width: 40, height: 70, remove_icon_class: true),
103
- link: ::Decidim::ResourceLocatorPresenter.new([project.budget, project]).path
118
+ link: ::Decidim::ResourceLocatorPresenter.new([project.budget, project]).path,
119
+ items: cell("decidim/budgets/project_metadata", project).send(:project_items_for_map).to_json
104
120
  )
105
121
  end
106
122
 
@@ -109,6 +125,46 @@ module Decidim
109
125
 
110
126
  project.latitude.present? && project.longitude.present?
111
127
  end
128
+
129
+ def filter_addition_type_values(added_count:)
130
+ return [] if voting_finished?
131
+
132
+ [
133
+ ["all", { text: t("all", scope: "decidim.budgets.projects.project_filter"), count: nil }],
134
+ ["added", { text: t("added", scope: "decidim.budgets.projects.project_filter"), count: added_count }]
135
+ ]
136
+ end
137
+
138
+ def filter_sections
139
+ @filter_sections ||= begin
140
+ items = []
141
+ items.append(method: :with_any_status, collection: filter_status_values, label_scope: "decidim.budgets.projects.filters", id: "status") if voting_finished?
142
+ if current_component.has_subscopes?
143
+ items.append(method: :with_any_scope, collection: resource_filter_scope_values(budget.scope), label_scope: "decidim.budgets.projects.filters", id: "scope")
144
+ end
145
+ if current_participatory_space.categories.any?
146
+ items.append(method: :with_any_category, collection: filter_categories_values, label_scope: "decidim.budgets.projects.filters", id: "category")
147
+ end
148
+ end
149
+
150
+ items.reject { |item| item[:collection].blank? }
151
+ end
152
+
153
+ def budgets_select_tag(name, options: {})
154
+ select_tag(
155
+ name,
156
+ options_for_select(reference_budgets_for_select),
157
+ options.merge(include_blank: I18n.t("decidim.budgets.prompt"))
158
+ )
159
+ end
160
+
161
+ def reference_budgets_for_select
162
+ references = Budget.joins(:component)
163
+ .where(component: { participatory_space: current_participatory_space }).order(weight: :asc)
164
+ references.map do |budget|
165
+ ["#{"&nbsp;" * 4} #{translated_attribute(budget.title)}".html_safe, budget.id]
166
+ end
167
+ end
112
168
  end
113
169
  end
114
170
  end
@@ -8,7 +8,7 @@ module Decidim
8
8
  def perform(reminder)
9
9
  return if reminder.records.active.blank?
10
10
 
11
- ::Decidim::ReminderDelivery.create(reminder: reminder)
11
+ ::Decidim::ReminderDelivery.create(reminder:)
12
12
  ::Decidim::Budgets::VoteReminderMailer.vote_reminder(reminder).deliver_now
13
13
  end
14
14
  end
@@ -28,7 +28,7 @@ module Decidim
28
28
  budget_name: translated_attribute(@budget.title),
29
29
  space_name: translated_attribute(@space.title)
30
30
  )
31
- mail(to: user.email, subject: subject)
31
+ mail(to: user.email, subject:)
32
32
  end
33
33
  end
34
34
  end
@@ -25,7 +25,7 @@ module Decidim
25
25
  count: @orders.count
26
26
  )
27
27
 
28
- mail(to: @user.email, subject: subject)
28
+ mail(to: @user.email, subject:)
29
29
  end
30
30
  end
31
31
 
@@ -8,6 +8,7 @@ module Decidim
8
8
  include Decidim::ScopableResource
9
9
  include Decidim::HasComponent
10
10
  include Decidim::Searchable
11
+ include Decidim::Randomable
11
12
  include Traceable
12
13
  include Loggable
13
14
 
@@ -28,9 +28,17 @@ module Decidim
28
28
  has_many :orders, through: :line_items, foreign_key: "decidim_project_id", class_name: "Decidim::Budgets::Order"
29
29
 
30
30
  delegate :organization, :participatory_space, :can_participate_in_space?, to: :component
31
+ delegate :visible?, to: :budget
31
32
 
32
33
  alias can_participate? can_participate_in_space?
33
34
 
35
+ scope :with_order, lambda { |order|
36
+ if order.present?
37
+ joins(:orders).where(decidim_budgets_orders: { id: order.id })
38
+ else
39
+ all
40
+ end
41
+ }
34
42
  scope :selected, -> { where.not(selected_at: nil) }
35
43
  scope :not_selected, -> { where(selected_at: nil) }
36
44
 
@@ -38,13 +46,15 @@ module Decidim
38
46
 
39
47
  scope_search_multi :with_any_status, [:selected, :not_selected]
40
48
 
41
- searchable_fields(
42
- scope_id: :decidim_scope_id,
43
- participatory_space: { component: :participatory_space },
44
- A: :title,
45
- D: :description,
46
- datetime: :created_at
47
- )
49
+ searchable_fields({
50
+ scope_id: :decidim_scope_id,
51
+ participatory_space: { component: :participatory_space },
52
+ A: :title,
53
+ D: :description,
54
+ datetime: :created_at
55
+ },
56
+ index_on_create: ->(project) { project.visible? },
57
+ index_on_update: ->(project) { project.visible? })
48
58
 
49
59
  def self.ordered_ids(ids)
50
60
  # Make sure each ID in the matching text has a "," character as their
@@ -4,3 +4,5 @@ import "src/decidim/budgets/exit_handler"
4
4
 
5
5
  // Images
6
6
  require.context("../images", true)
7
+
8
+ import "stylesheets/budgets.scss"
@@ -9,7 +9,7 @@ const isSafeUrl = (exitUrl) => {
9
9
  }
10
10
 
11
11
  const safeUrls = [
12
- $(".budget-summary").attr("data-safe-url").split("?")[0],
12
+ $(".budget-summary").attr("data-safe-url").replace(location.origin, ""),
13
13
  `${location.pathname}#`,
14
14
  `${location.href}#`,
15
15
  "#"
@@ -18,7 +18,7 @@ const isSafeUrl = (exitUrl) => {
18
18
  let safe = false;
19
19
  safeUrls.forEach((url) => {
20
20
  if (exitUrl.startsWith(url)) {
21
- safe = true
21
+ safe = true
22
22
  }
23
23
  });
24
24
 
@@ -36,10 +36,12 @@ const allowExitFrom = ($el) => {
36
36
  return true;
37
37
  } else if ($el.attr("id") === "exit-notification-link") {
38
38
  return true;
39
- } else if ($el.parents(".voting-wrapper").length > 0) {
39
+ } else if ($el.parents("main").length > 0) {
40
40
  return true;
41
41
  } else if (isSafeUrl($el.attr("href"))) {
42
42
  return true
43
+ } else if (document.querySelector(".panel-container") && document.querySelector(".panel-container").contains($el[0])) {
44
+ return true
43
45
  }
44
46
 
45
47
  return false;
@@ -50,6 +52,7 @@ $(() => {
50
52
  const $exitLink = $("#exit-notification-link");
51
53
  const defaultExitUrl = $exitLink.attr("href");
52
54
  const defaultExitLinkText = $exitLink.text();
55
+ const signOutPath = window.Decidim.config.get("sign_out_path");
53
56
  let exitLinkText = defaultExitLinkText;
54
57
 
55
58
  if ($exitNotification.length < 1) {
@@ -65,8 +68,8 @@ $(() => {
65
68
  }
66
69
 
67
70
  $exitLink.attr("href", url);
68
- $exitLink.text(exitLinkText);
69
- $exitNotification.foundation("open");
71
+ $exitLink.html(exitLinkText);
72
+ window.Decidim.currentDialogs["exit-notification"].open();
70
73
  };
71
74
 
72
75
  $(document).on("click", "a", (event) => {
@@ -78,11 +81,11 @@ $(() => {
78
81
  openExitNotification($link.attr("href"), $link.data("method"));
79
82
  }
80
83
  });
81
- // Custom handling for the header sign out so that it won't trigger the
84
+ // Custom handling for the header sign out so that it will not trigger the
82
85
  // logout form submit and so that it changes the exit link text. This does
83
86
  // not trigger the document link click listener because it has the
84
87
  // data-method attribute to trigger a form submit event.
85
- $(".header a.sign-out-link").on("click", (event) => {
88
+ $(`[href='${signOutPath}']`).on("click", (event) => {
86
89
  event.preventDefault();
87
90
  event.stopPropagation();
88
91
 
@@ -93,7 +96,7 @@ $(() => {
93
96
  // Custom handling for the exit link which needs to change the exit link
94
97
  // text to the default text as this is not handled by the document click
95
98
  // listener.
96
- $("a[data-open='exit-notification']").on("click", () => {
99
+ $("a[data-dialog-open='exit-notification']").on("click", () => {
97
100
  exitLinkText = defaultExitLinkText;
98
101
  openExitNotification(defaultExitUrl);
99
102
  });
@@ -1,18 +1,32 @@
1
1
  $(() => {
2
2
  const checkProgressPosition = () => {
3
- let progressFix = document.querySelector("[data-progressbox-fixed]"),
4
- progressRef = document.querySelector("[data-progress-reference]"),
5
- progressVisibleClass = "is-progressbox-visible";
6
3
 
7
- if (!progressRef) {
8
- return;
9
- }
4
+ const progressRef = document.querySelectorAll("[data-progress-reference]");
5
+ if (progressRef.length) {
6
+ const progressFix = document.querySelectorAll("[data-progressbox-fixed]");
7
+
8
+ let selectedProgressRef = "";
9
+ let selectedProgressFix = "";
10
+ const progressVisibleClass = "is-progressbox-visible";
11
+
12
+ if (window.matchMedia("(min-width: 768px)").matches) {
13
+ selectedProgressRef = progressRef[1];
14
+ selectedProgressFix = progressFix[1];
15
+ } else {
16
+ selectedProgressRef = progressRef[0];
17
+ selectedProgressFix = progressFix[0];
18
+ }
19
+
20
+ if (!progressRef) {
21
+ return;
22
+ }
10
23
 
11
- let progressPosition = progressRef.getBoundingClientRect().bottom;
12
- if (progressPosition > 0) {
13
- progressFix.classList.remove(progressVisibleClass);
14
- } else {
15
- progressFix.classList.add(progressVisibleClass);
24
+ let progressPosition = selectedProgressRef.getBoundingClientRect().bottom;
25
+ if (progressPosition > 0) {
26
+ selectedProgressFix.classList.remove(progressVisibleClass);
27
+ } else {
28
+ selectedProgressFix.classList.add(progressVisibleClass);
29
+ }
16
30
  }
17
31
  }
18
32
 
@@ -1,13 +1,13 @@
1
1
  $(() => {
2
- const $projects = $("#projects, #project");
3
- const $budgetSummaryTotal = $(".budget-summary__total");
4
- const $budgetExceedModal = $("#budget-excess");
2
+ const $projects = $("#projects, #project-item");
3
+ const $budgetSummaryTotal = $(".budget-summary__progressbar-marks_right");
4
+ const selectBudgetSummaryTotal = $budgetSummaryTotal.data("totalAllocation");
5
5
  const $budgetSummary = $(".budget-summary__progressbox");
6
6
  const $voteButton = $(".budget-vote-button");
7
- const totalAllocation = parseInt($budgetSummaryTotal.attr("data-total-allocation"), 10);
7
+ const totalAllocation = parseInt(selectBudgetSummaryTotal, 10);
8
+ const additionSelectorButtons = document.querySelectorAll(".budget__list--header .button__pill")
8
9
 
9
10
  const cancelEvent = (event) => {
10
- $(event.currentTarget).removeClass("loading-spinner");
11
11
  event.stopPropagation();
12
12
  event.preventDefault();
13
13
  };
@@ -21,15 +21,20 @@ $(() => {
21
21
  const $currentTarget = $(event.currentTarget);
22
22
  const projectAllocation = parseInt($currentTarget.attr("data-allocation"), 10);
23
23
 
24
- if (!$currentTarget.attr("data-open")) {
25
- $currentTarget.addClass("loading-spinner");
26
- }
27
-
28
24
  if ($currentTarget.attr("disabled")) {
29
25
  cancelEvent(event);
30
26
  } else if (($currentTarget.attr("data-add") === "true") && ((currentAllocation + projectAllocation) > totalAllocation)) {
31
- $budgetExceedModal.foundation("toggle");
27
+ window.Decidim.currentDialogs["budget-excess"].toggle()
32
28
  cancelEvent(event);
33
29
  }
34
30
  });
31
+
32
+ additionSelectorButtons.forEach(function(button) {
33
+ button.addEventListener("click", function(event) {
34
+ additionSelectorButtons.forEach(function(element) {
35
+ element.classList.remove("button__pill--active")
36
+ })
37
+ event.currentTarget.classList.add("button__pill--active")
38
+ })
39
+ });
35
40
  });