Extract component for balloting budget admin stats

We're also moving the tests, but we're keeping one system test in order
to test the controller and the navigation to get to this page.

Note we're slightly changing the order of the methods in the component;
the order of the instance variables was `user_`, `vote_`, `vote_`,
`user_`, which was hard to follow.
This commit is contained in:
Javi Martín
2023-02-02 19:49:52 +01:00
parent 915999db4a
commit 76b08398cf
6 changed files with 111 additions and 78 deletions

View File

@@ -0,0 +1,57 @@
<%= back_link_to budgets_admin_stats_path %>
<h2><%= budget.name %> - <%= t("admin.stats.budget_balloting.title") %></h2>
<div class="stats">
<div class="row stats-numbers">
<div class="small-12 medium-3 column">
<p class="featured">
<%= t("admin.stats.budget_balloting.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_balloting.participant_count") %>
<br>
<span id="total_participants_count" class="number">
<%= user_count %>
</span>
</p>
</div>
</div>
</div>
<table class="investment-projects-summary">
<th colspan="2"><%= t("admin.stats.budget_balloting.votes_per_heading") %></th>
<% vote_count_by_heading.each do |heading_name, count| %>
<tr id="vote_count_<%= heading_name.parameterize %>">
<td class="name">
<%= heading_name %>
</td>
<td class="name">
<%= number_with_delimiter count %>
</td>
</tr>
<% end %>
</table>
<table class="investment-projects-summary">
<th colspan="2"><%= t("admin.stats.budget_balloting.participants_per_district") %></th>
<% user_count_by_district.each do |heading_name, count| %>
<tr id="user_count_<%= heading_name.parameterize %>">
<td class="name">
<%= heading_name %>
</td>
<td class="name">
<%= number_with_delimiter count %>
</td>
</tr>
<% end %>
</table>

View File

@@ -0,0 +1,25 @@
class Admin::Stats::BudgetBallotingComponent < ApplicationComponent
attr_reader :budget
def initialize(budget)
@budget = budget
end
private
def vote_count
budget.lines.count
end
def user_count
budget.ballots.select { |ballot| ballot.lines.any? }.count
end
def vote_count_by_heading
budget.lines.group(:heading_id).count.map { |k, v| [Budget::Heading.find(k).name, v] }.sort
end
def user_count_by_district
User.where.not(balloted_heading_id: nil).group(:balloted_heading_id).count.map { |k, v| [Budget::Heading.find(k).name, v] }.sort
end
end

View File

@@ -75,14 +75,6 @@ class Admin::StatsController < Admin::BaseController
@budget = Budget.find(params[:budget_id])
authorize! :read_admin_stats, @budget, message: t("admin.stats.budgets.no_data_before_balloting_phase")
@user_count = @budget.ballots.select { |ballot| ballot.lines.any? }.count
@vote_count = @budget.lines.count
@vote_count_by_heading = @budget.lines.group(:heading_id).count.map { |k, v| [Budget::Heading.find(k).name, v] }.sort
@user_count_by_district = User.where.not(balloted_heading_id: nil).group(:balloted_heading_id).count.map { |k, v| [Budget::Heading.find(k).name, v] }.sort
end
def polls

View File

@@ -1,57 +1 @@
<%= back_link_to budgets_admin_stats_path %>
<h2><%= @budget.name %> - <%= t("admin.stats.budget_balloting.title") %></h2>
<div class="stats">
<div class="row stats-numbers">
<div class="small-12 medium-3 column">
<p class="featured">
<%= t("admin.stats.budget_balloting.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_balloting.participant_count") %>
<br>
<span id="total_participants_count" class="number">
<%= @user_count %>
</span>
</p>
</div>
</div>
</div>
<table class="investment-projects-summary">
<th colspan="2"><%= t("admin.stats.budget_balloting.votes_per_heading") %></th>
<% @vote_count_by_heading.each do |heading_name, count| %>
<tr id="vote_count_<%= heading_name.parameterize %>">
<td class="name">
<%= heading_name %>
</td>
<td class="name">
<%= number_with_delimiter count %>
</td>
</tr>
<% end %>
</table>
<table class="investment-projects-summary">
<th colspan="2"><%= t("admin.stats.budget_balloting.participants_per_district") %></th>
<% @user_count_by_district.each do |heading_name, count| %>
<tr id="user_count_<%= heading_name.parameterize %>">
<td class="name">
<%= heading_name %>
</td>
<td class="name">
<%= number_with_delimiter count %>
</td>
</tr>
<% end %>
</table>
<%= render Admin::Stats::BudgetBallotingComponent.new(@budget) %>

View File

@@ -0,0 +1,28 @@
require "rails_helper"
describe Admin::Stats::BudgetBallotingComponent do
let(:budget) { create(:budget, :balloting) }
let(:heading) { create(:budget_heading, budget: budget) }
let(:investment) { create(:budget_investment, :feasible, :selected, heading: heading) }
it "shows the number of votes in investment projects" do
investment_2 = create(:budget_investment, :feasible, :selected, budget: budget)
create(:user, ballot_lines: [investment, investment_2])
create(:user, ballot_lines: [investment_2])
render_inline Admin::Stats::BudgetBallotingComponent.new(budget)
expect(page).to have_css "p", exact_text: "Votes 3", normalize_ws: true
end
it "shows the number of users that have voted a investment project" do
create(:user, ballot_lines: [investment])
create(:user, ballot_lines: [investment])
create(:user)
render_inline Admin::Stats::BudgetBallotingComponent.new(budget)
expect(page).to have_css "p", exact_text: "Participants 2", normalize_ws: true
end
end

View File

@@ -195,19 +195,6 @@ describe "Stats", :admin do
end
expect(page).to have_content "VOTES\n3"
end
scenario "Number of users that have voted a investment project" do
create(:user, ballot_lines: [investment])
create(:user, ballot_lines: [investment])
create(:user)
visit admin_stats_path
click_link "Participatory Budgets"
within("#budget_#{budget.id}") do
click_link "Final voting"
end
expect(page).to have_content "PARTICIPANTS\n2"
end
end