From b536a7cb7774bbd37d166929ab6cafb1d9480c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Mon, 6 Feb 2023 16:35:53 +0100 Subject: [PATCH] Extract component for supporting budget admin stats This is consistent with the component for balloting stats. We're about to change both components, and the changes are easier to follow if they're similar. We're also using consistent names in methods. --- .../budget_supporting_component.html.erb | 55 ++++++++++++++++++ .../stats/budget_supporting_component.rb | 36 ++++++++++++ app/controllers/admin/stats_controller.rb | 22 -------- .../admin/stats/budget_supporting.html.erb | 56 +------------------ .../stats/budget_supporting_component_spec.rb | 51 +++++++++++++++++ spec/system/admin/stats_spec.rb | 56 +------------------ 6 files changed, 146 insertions(+), 130 deletions(-) create mode 100644 app/components/admin/stats/budget_supporting_component.html.erb create mode 100644 app/components/admin/stats/budget_supporting_component.rb create mode 100644 spec/components/admin/stats/budget_supporting_component_spec.rb diff --git a/app/components/admin/stats/budget_supporting_component.html.erb b/app/components/admin/stats/budget_supporting_component.html.erb new file mode 100644 index 000000000..2d74625d9 --- /dev/null +++ b/app/components/admin/stats/budget_supporting_component.html.erb @@ -0,0 +1,55 @@ +<% content_for :head do %> + <%= javascript_include_tag "stat_graphs", "data-turbolinks-track" => "reload" %> +<% end %> + +<%= back_link_to budgets_admin_stats_path %> + +

<%= budget.name %> - <%= t("admin.stats.budget_supporting.title") %>

+ +
+
+
+ +
+ +
+

+ <%= t("admin.stats.budget_supporting.participant_count") %> +
+ + <%= user_count %> + +

+
+
+
+ +<%= render "admin/stats/graph", name: "user_supported_budgets", event: "", count: user_count %> + + + + + + + + + + + <% user_count_by_heading.each do |heading, count| %> + + + + + <% end %> + +
<%= t("admin.stats.budget_supporting.headings") %><%= t("admin.stats.budget_supporting.users") %>
+ <%= heading.name %> + + <%= number_with_delimiter count %> +
diff --git a/app/components/admin/stats/budget_supporting_component.rb b/app/components/admin/stats/budget_supporting_component.rb new file mode 100644 index 000000000..5dde0b4af --- /dev/null +++ b/app/components/admin/stats/budget_supporting_component.rb @@ -0,0 +1,36 @@ +class Admin::Stats::BudgetSupportingComponent < ApplicationComponent + attr_reader :budget + + def initialize(budget) + @budget = budget + end + + private + + def votes + Vote.where(votable_type: "Budget::Investment") + .includes(:budget_investment) + .where(budget_investments: { heading_id: budget.heading_ids }) + end + + def vote_count + votes.count + end + + def user_count + votes.select(:voter_id).distinct.count + end + + def user_count_by_heading + budget.headings.map do |heading| + [heading, voters_in_heading(heading)] + end + end + + def voters_in_heading(heading) + Vote.where(votable_type: "Budget::Investment") + .includes(:budget_investment) + .where(budget_investments: { heading_id: heading.id }) + .select("votes.voter_id").distinct.count + end +end diff --git a/app/controllers/admin/stats_controller.rb b/app/controllers/admin/stats_controller.rb index 8634788a8..fc4377a1d 100644 --- a/app/controllers/admin/stats_controller.rb +++ b/app/controllers/admin/stats_controller.rb @@ -56,19 +56,6 @@ class Admin::StatsController < Admin::BaseController def budget_supporting @budget = Budget.find(params[:budget_id]) - heading_ids = @budget.heading_ids - - votes = Vote.where(votable_type: "Budget::Investment"). - includes(:budget_investment). - where(budget_investments: { heading_id: heading_ids }) - - @vote_count = votes.count - @user_count = votes.select(:voter_id).distinct.count - - @voters_in_heading = {} - @budget.headings.each do |heading| - @voters_in_heading[heading] = voters_in_heading(heading) - end end def budget_balloting @@ -85,13 +72,4 @@ class Admin::StatsController < Admin::BaseController def sdg @goals = SDG::Goal.order(:code) end - - private - - def voters_in_heading(heading) - Vote.where(votable_type: "Budget::Investment"). - includes(:budget_investment). - where(budget_investments: { heading_id: heading.id }). - select("votes.voter_id").distinct.count - end end diff --git a/app/views/admin/stats/budget_supporting.html.erb b/app/views/admin/stats/budget_supporting.html.erb index 8affe4cd2..aa165ee19 100644 --- a/app/views/admin/stats/budget_supporting.html.erb +++ b/app/views/admin/stats/budget_supporting.html.erb @@ -1,55 +1 @@ -<% content_for :head do %> - <%= javascript_include_tag "stat_graphs", "data-turbolinks-track" => "reload" %> -<% end %> - -<%= back_link_to budgets_admin_stats_path %> - -

<%= @budget.name %> - <%= t("admin.stats.budget_supporting.title") %>

- -
-
-
- -
- -
-

- <%= t("admin.stats.budget_supporting.participant_count") %> -
- - <%= @user_count %> - -

-
-
-
- -<%= render "graph", name: "user_supported_budgets", event: "", count: @user_count %> - - - - - - - - - - - <% @voters_in_heading.each do |heading, count| %> - - - - - <% end %> - -
<%= t("admin.stats.budget_supporting.headings") %><%= t("admin.stats.budget_supporting.users") %>
- <%= heading.name %> - - <%= number_with_delimiter count %> -
+<%= render Admin::Stats::BudgetSupportingComponent.new(@budget) %> diff --git a/spec/components/admin/stats/budget_supporting_component_spec.rb b/spec/components/admin/stats/budget_supporting_component_spec.rb new file mode 100644 index 000000000..0fefa4f98 --- /dev/null +++ b/spec/components/admin/stats/budget_supporting_component_spec.rb @@ -0,0 +1,51 @@ +require "rails_helper" + +describe Admin::Stats::BudgetSupportingComponent do + let(:budget) { create(:budget, :balloting) } + let(:heading) { create(:budget_heading, budget: budget, name: "Main heading") } + let(:investment) { create(:budget_investment, :feasible, :selected, heading: heading) } + + it "shows the number of supports in investment projects" do + another_heading = create(:budget_heading, budget: budget) + another_investment = create(:budget_investment, heading: another_heading) + + create(:user, :level_two, votables: [investment, another_investment]) + create(:user, :level_two, votables: [investment]) + create(:user, :level_two) + + render_inline Admin::Stats::BudgetSupportingComponent.new(budget) + + expect(page).to have_css "p", exact_text: "Votes 3", normalize_ws: true + end + + it "shows the number of users that have supported an investment project" do + another_heading = create(:budget_heading, budget: budget) + another_investment = create(:budget_investment, heading: another_heading) + + create(:user, :level_two, votables: [investment, another_investment]) + create(:user, :level_two, votables: [investment]) + create(:user, :level_two) + + render_inline Admin::Stats::BudgetSupportingComponent.new(budget) + + expect(page).to have_css "p", exact_text: "Participants 2", normalize_ws: true + end + + it "shows the number of users that have supported investments projects per heading" do + group_districts = create(:budget_group, budget: budget) + north_district = create(:budget_heading, group: group_districts, name: "North district") + create(:budget_heading, group: group_districts, name: "South district") + + create(:budget_investment, heading: heading, voters: [create(:user)]) + create(:budget_investment, heading: north_district, voters: [create(:user)]) + create(:budget_investment, heading: north_district, voters: [create(:user)]) + + render_inline Admin::Stats::BudgetSupportingComponent.new(budget) + + page.find ".user-count-by-heading tbody" do |table_body| + expect(table_body).to have_css "tr", exact_text: "Main heading 1", normalize_ws: true + expect(table_body).to have_css "tr", exact_text: "North district 2", normalize_ws: true + expect(table_body).to have_css "tr", exact_text: "South district 0", normalize_ws: true + end + end +end diff --git a/spec/system/admin/stats_spec.rb b/spec/system/admin/stats_spec.rb index 62f11d3a2..5bde3e8c0 100644 --- a/spec/system/admin/stats_spec.rb +++ b/spec/system/admin/stats_spec.rb @@ -91,23 +91,7 @@ describe "Stats", :admin do let(:budget) { create(:budget) } let(:heading_all_city) { create(:budget_heading, budget: budget) } - scenario "Number of supports in investment projects" do - group_2 = create(:budget_group, budget: budget) - - create(:budget_investment, heading: create(:budget_heading, group: group_2), voters: [create(:user)]) - create(:budget_investment, heading: heading_all_city, voters: [create(:user), create(:user)]) - - visit admin_stats_path - click_link "Participatory Budgets" - within("#budget_#{budget.id}") do - click_link "Supporting phase" - end - - expect(page).to have_content "VOTES\n3" - expect(page).to have_link "Go back", count: 1 - end - - scenario "Number of users that have supported an investment project" do + scenario "Number of users and supports in investment projects" do group_2 = create(:budget_group, budget: budget) investment1 = create(:budget_investment, heading: create(:budget_heading, group: group_2)) investment2 = create(:budget_investment, heading: heading_all_city) @@ -122,43 +106,9 @@ describe "Stats", :admin do click_link "Supporting phase" end + expect(page).to have_content "VOTES\n3" expect(page).to have_content "PARTICIPANTS\n2" - end - - scenario "Number of users that have supported investments projects per geozone" do - budget = create(:budget) - - group_all_city = create(:budget_group, budget: budget) - group_districts = create(:budget_group, budget: budget) - - all_city = create(:budget_heading, group: group_all_city) - carabanchel = create(:budget_heading, group: group_districts) - barajas = create(:budget_heading, group: group_districts) - - create(:budget_investment, heading: all_city, voters: [create(:user)]) - create(:budget_investment, heading: carabanchel, voters: [create(:user)]) - create(:budget_investment, heading: carabanchel, voters: [create(:user)]) - - visit admin_stats_path - click_link "Participatory Budgets" - within("#budget_#{budget.id}") do - click_link "Supporting phase" - end - - within("#budget_heading_#{all_city.id}") do - expect(page).to have_content all_city.name - expect(page).to have_content 1 - end - - within("#budget_heading_#{carabanchel.id}") do - expect(page).to have_content carabanchel.name - expect(page).to have_content 2 - end - - within("#budget_heading_#{barajas.id}") do - expect(page).to have_content barajas.name - expect(page).to have_content 0 - end + expect(page).to have_link "Go back", count: 1 end scenario "hide final voting link" do