Skip to content

Commit

Permalink
Merge pull request #3499 from consul/backport-admin_stats
Browse files Browse the repository at this point in the history
Add admin budget stats
  • Loading branch information
javierm committed May 16, 2019
2 parents c39a3d7 + d5c7858 commit 668b6cf
Show file tree
Hide file tree
Showing 20 changed files with 450 additions and 86 deletions.
15 changes: 8 additions & 7 deletions app/controllers/admin/api/stats_controller.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
class Admin::Api::StatsController < Admin::Api::BaseController

def show
unless params[:events].present? ||
unless params[:event].present? ||
params[:visits].present? ||
params[:spending_proposals].present? ||
params[:budget_investments].present?
params[:budget_investments].present? ||
params[:user_supported_budgets].present?
return render json: {}, status: :bad_request
end

ds = Ahoy::DataSource.new

if params[:events].present?
event_types = params[:events].split ","
event_types.each do |event|
ds.add event.titleize, Ahoy::Event.where(name: event).group_by_day(:time).count
end
if params[:event].present?
ds.add params[:event].titleize, Ahoy::Event.where(name: params[:event]).group_by_day(:time).count
end

if params[:visits].present?
Expand All @@ -29,6 +27,9 @@ def show
ds.add "Budget Investments", Budget::Investment.group_by_day(:created_at).count
end

if params[:user_supported_budgets].present?
ds.add "User supported budgets", Vote.where(votable_type: "Budget::Investment").group_by_day(:updated_at).count
end
render json: ds.build
end
end
54 changes: 53 additions & 1 deletion app/controllers/admin/stats_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class Admin::StatsController < Admin::BaseController

def show
@event_types = Ahoy::Event.group(:name).count
@event_types = Ahoy::Event.pluck(:name).uniq.sort

@visits = Visit.count
@debates = Debate.with_hidden.count
Expand Down Expand Up @@ -31,6 +31,17 @@ def show
@investments = Budget::Investment.where(budget_id: budgets_ids).count
end

def graph
@name = params[:id]
@event = params[:event]

if params[:event]
@count = Ahoy::Event.where(name: params[:event]).count
else
@count = params[:count]
end
end

def proposal_notifications
@proposal_notifications = ProposalNotification.all
@proposals_with_notifications = @proposal_notifications.select(:proposal_id).distinct.count
Expand All @@ -41,9 +52,50 @@ def direct_messages
@users_who_have_sent_message = DirectMessage.select(:sender_id).distinct.count
end


def budgets
@budgets = Budget.all
end

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
@budget = Budget.find(params[:budget_id])
@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.collect {|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.collect {|k,v| [Budget::Heading.find(k).name, v]}.sort
end

def polls
@polls = ::Poll.current
@participants = ::Poll::Voter.where(poll: @polls)
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
4 changes: 0 additions & 4 deletions app/helpers/budgets_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ def namespaced_budget_investment_vote_path(investment, options = {})
end
end

def display_budget_countdown?(budget)
budget.balloting?
end

def css_for_ballot_heading(heading)
return "" if current_ballot.blank? || @current_filter == "unfeasible"
current_ballot.has_lines_in_heading?(heading) ? "is-active" : ""
Expand Down
29 changes: 16 additions & 13 deletions app/helpers/stats_helper.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
module StatsHelper

def events_chart_tag(events, opt = {})
events = events.join(",") if events.is_a? Array
def chart_tag(opt = {})
opt[:data] ||= {}
opt[:data][:graph] = admin_api_stats_path(events: events)
opt[:data][:graph] = admin_api_stats_path(chart_data(opt))
content_tag :div, "", opt
end

def visits_chart_tag(opt = {})
events = events.join(",") if events.is_a? Array
opt[:data] ||= {}
opt[:data][:graph] = admin_api_stats_path(visits: true)
content_tag :div, "", opt
def chart_data(opt = {})
data = nil
if opt[:id].present?
data = { opt[:id] => true }
elsif opt[:event].present?
data = { event: opt[:event] }
end
data
end

def spending_proposals_chart_tag(opt = {})
events = events.join(",") if events.is_a? Array
opt[:data] ||= {}
opt[:data][:graph] = admin_api_stats_path(spending_proposals: true)
content_tag :div, "", opt
def graph_link_text(event)
text = t("admin.stats.graph.#{event}")
if text.to_s.match(/translation missing/)
text = event
end
text
end

def budget_investments_chart_tag(opt = {})
Expand Down
1 change: 1 addition & 0 deletions app/models/budget.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def name_uniqueness_by_budget
has_many :ballots, dependent: :destroy
has_many :groups, dependent: :destroy
has_many :headings, through: :groups
has_many :lines, through: :ballots, class_name: "Budget::Ballot::Line"
has_many :phases, class_name: Budget::Phase

has_one :poll
Expand Down
6 changes: 6 additions & 0 deletions app/views/admin/stats/_graph.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<%= back_link_to %>

<div id="graph" class="small-12 column">
<h2><%= t "admin.stats.graph.#{name || event}" %> (<%= count %>)</h2>
<%= chart_tag id: name, event: event %>
</div>
57 changes: 57 additions & 0 deletions app/views/admin/stats/budget_balloting.html.erb
Original file line number Diff line number Diff line change
@@ -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>
49 changes: 49 additions & 0 deletions app/views/admin/stats/budget_supporting.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<% content_for :head do %>
<%= javascript_include_tag "stat_graphs", "data-turbolinks-track" => true %>
<% 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">
<th><%= t("admin.stats.budget_supporting.headings") %></th>
<th><%= t("admin.stats.budget_supporting.users") %></th>

<% @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 %>
</table>
17 changes: 17 additions & 0 deletions app/views/admin/stats/budgets.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<%= back_link_to admin_stats_path %>

<h2><%= t("admin.stats.budgets.title") %></h2>

<% @budgets.each do |budget| %>
<table>
<tr id="<%= dom_id(budget) %>">
<td>
<strong><%= budget.name %></strong>
</td>
<td>
<%= link_to t("admin.stats.budgets.supporting_phase"), budget_supporting_admin_stats_path(budget_id: budget.id), class: "button hollow" %>
<%= link_to t("admin.stats.budgets.balloting_phase"), budget_balloting_admin_stats_path(budget_id: budget.id), class: "button hollow" %>
</td>
</tr>
</table>
<% end %>
5 changes: 5 additions & 0 deletions app/views/admin/stats/graph.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<% content_for :head do %>
<%= javascript_include_tag "stat_graphs", 'data-turbolinks-track' => true %>
<% end %>
<%= render 'graph', name: @name, event: @event, count: @count %>
30 changes: 10 additions & 20 deletions app/views/admin/stats/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
<% content_for :head do %>
<%= javascript_include_tag "stat_graphs", "data-turbolinks-track" => true %>
<% end %>
<div class="stats">
<div id="stats" class="stats">
<div class="row">
<div class="small-12 column">
<h1 class="inline-block"><%= t "admin.stats.show.stats_title" %></h1>

<div class="float-right clear">
<%= link_to t("admin.stats.show.polls"),
polls_admin_stats_path, class: "button hollow" %>
<%= link_to t("admin.stats.show.participatory_budgets"),
budgets_admin_stats_path, class: "button hollow" %>
<%= link_to t("admin.stats.show.direct_messages"),
direct_messages_admin_stats_path, class: "button hollow" %>
<%= link_to t("admin.stats.show.proposal_notifications"),
Expand All @@ -22,7 +21,8 @@
<div class="row stats-numbers">
<div class="small-12 medium-3 column">
<p class="featured">
<%= t "admin.stats.show.summary.visits" %> <br>
<%= link_to t("admin.stats.show.summary.visits"),
graph_admin_stats_path(id: "visits", count: @visits) %> <br>
<span class="number"><%= number_with_delimiter(@visits) %></span>
</p>

Expand Down Expand Up @@ -119,24 +119,14 @@
</div>

<div class="small-12 column">
<h2><%= t "admin.stats.show.visits_title" %></h2>
<%= visits_chart_tag id: "visits" %>
</div>

<div class="small-12 column">
<% @event_types.each do |event, count| %>
<h2><%= event.titleize %> (<%= count %>)</h2>
<%= events_chart_tag event %>
<% @event_types.each do |event| %>
<h3>
<%= link_to graph_link_text(event),
graph_admin_stats_path(event: event) %>
</h3>
<% end %>
</div>

<% if feature?(:spending_proposals) %>
<div class="small-12 column">
<h2><%= t "admin.stats.show.spending_proposals_title" %></h2>
<%= spending_proposals_chart_tag id: "spending_proposals" %>
</div>
<% end %>
<% if feature?(:budgets) %>
<div class="small-12 column">
<h2><%= t "admin.stats.show.budgets_title" %></h2>
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/admin.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

<div class="admin-content small-12 medium-9 column" data-equalizer-watch>
<%= render "layouts/flash" %>
<%= render "layouts/officing_booth" %>
<%= render "layouts/officing_booth" if controller.class.parent == Officing && session[:booth_id].present? %>
<%= yield %>
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions config/initializers/ahoy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ def track_event(name, properties, options)
event.ip = request.ip
end
end

def exclude?
false
end
end
1 change: 1 addition & 0 deletions config/initializers/vote_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
include Graphqlable

belongs_to :signature
belongs_to :budget_investment, foreign_key: "votable_id", class_name: "Budget::Investment"

scope :public_for_api, -> do
where(%{(votes.votable_type = 'Debate' and votes.votable_id in (?)) or
Expand Down

0 comments on commit 668b6cf

Please sign in to comment.