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.
This commit is contained in:
Javi Martín
2023-02-06 16:35:53 +01:00
parent dd28163be7
commit b536a7cb77
6 changed files with 146 additions and 130 deletions

View File

@@ -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 %>
<h2><%= budget.name %> - <%= t("admin.stats.budget_supporting.title") %></h2>
<div class="stats">
<div class="row stats-numbers">
<div class="small-12 medium-3 column">
<p class="featured">
<%= t("admin.stats.budget_supporting.vote_count") %>
<br>
<span id="total_votes_count" class="number">
<%= vote_count %>
</span>
</p>
</div>
<div class="small-12 medium-6 column end">
<p>
<%= t("admin.stats.budget_supporting.participant_count") %>
<br>
<span id="total_participants_count" class="number">
<%= user_count %>
</span>
</p>
</div>
</div>
</div>
<%= render "admin/stats/graph", name: "user_supported_budgets", event: "", count: user_count %>
<table class="investment-projects-summary user-count-by-heading">
<thead>
<tr>
<th><%= t("admin.stats.budget_supporting.headings") %></th>
<th><%= t("admin.stats.budget_supporting.users") %></th>
</tr>
</thead>
<tbody>
<% user_count_by_heading.each do |heading, count| %>
<tr id="<%= dom_id(heading) %>">
<td class="name">
<%= heading.name %>
</td>
<td class="name">
<%= number_with_delimiter count %>
</td>
</tr>
<% end %>
</tbody>
</table>

View File

@@ -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

View File

@@ -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

View File

@@ -1,55 +1 @@
<% content_for :head do %>
<%= javascript_include_tag "stat_graphs", "data-turbolinks-track" => "reload" %>
<% end %>
<%= back_link_to budgets_admin_stats_path %>
<h2><%= @budget.name %> - <%= t("admin.stats.budget_supporting.title") %></h2>
<div class="stats">
<div class="row stats-numbers">
<div class="small-12 medium-3 column">
<p class="featured">
<%= t("admin.stats.budget_supporting.vote_count") %>
<br>
<span id="total_votes_count" class="number">
<%= @vote_count %>
</span>
</p>
</div>
<div class="small-12 medium-6 column end">
<p>
<%= t("admin.stats.budget_supporting.participant_count") %>
<br>
<span id="total_participants_count" class="number">
<%= @user_count %>
</span>
</p>
</div>
</div>
</div>
<%= render "graph", name: "user_supported_budgets", event: "", count: @user_count %>
<table class="investment-projects-summary">
<thead>
<tr>
<th><%= t("admin.stats.budget_supporting.headings") %></th>
<th><%= t("admin.stats.budget_supporting.users") %></th>
</tr>
</thead>
<tbody>
<% @voters_in_heading.each do |heading, count| %>
<tr id="<%= dom_id(heading) %>">
<td class="name">
<%= heading.name %>
</td>
<td class="name">
<%= number_with_delimiter count %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= render Admin::Stats::BudgetSupportingComponent.new(@budget) %>

View File

@@ -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

View File

@@ -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