Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add admin budget stats #3499

Merged
merged 15 commits into from
May 16, 2019
Merged
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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metrics/LineLength: Line is too long. [103/100] (https://github.com/bbatsov/ruby-style-guide#80-character-limits)

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metrics/LineLength: Line is too long. [117/100] (https://github.com/bbatsov/ruby-style-guide#80-character-limits)

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metrics/LineLength: Line is too long. [122/100] (https://github.com/bbatsov/ruby-style-guide#80-character-limits)


@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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metrics/LineLength: Line is too long. [159/100] (https://github.com/bbatsov/ruby-style-guide#80-character-limits)

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