Show charts using c3.js
This commit is contained in:
11
app/assets/javascripts/stats.js.coffee
Normal file
11
app/assets/javascripts/stats.js.coffee
Normal file
@@ -0,0 +1,11 @@
|
||||
# Helper for generate C3.js graphs
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
buildGraph = (el) ->
|
||||
url = $(el).data 'graph'
|
||||
conf = bindto: el, data: {x: 'x', url: url, mimeType: 'json'}, axis: { x: {type: 'timeseries',tick: { format: '%Y-%m-%d' } }}
|
||||
graph = c3.generate conf
|
||||
|
||||
App.Stats =
|
||||
initialize: ->
|
||||
buildGraph(g) for g in $("[data-graph]")
|
||||
@@ -1,10 +1,22 @@
|
||||
class Api::StatsController < Api::ApiController
|
||||
def show
|
||||
event_type = params[:event]
|
||||
unless event_type.present?
|
||||
unless params[:events].present? || params[:visits].present?
|
||||
return render json: {}, status: :bad_request
|
||||
end
|
||||
|
||||
render json: Ahoy::Event.where(name: event_type).group_by_day(:time).count
|
||||
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
|
||||
end
|
||||
|
||||
if params[:visits].present?
|
||||
ds.add "Visits", Visit.group_by_day(:started_at).count
|
||||
end
|
||||
|
||||
render json: ds.build
|
||||
end
|
||||
end
|
||||
|
||||
16
app/helpers/stats_helper.rb
Normal file
16
app/helpers/stats_helper.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
module StatsHelper
|
||||
def events_chart_tag(events, opt={})
|
||||
events = events.join(',') if events.is_a? Array
|
||||
opt[:data] ||= {}
|
||||
opt[:data][:graph] = api_stats_path(events: events)
|
||||
content_tag :div, "", opt
|
||||
end
|
||||
|
||||
def visits_chart_tag(opt={})
|
||||
events = events.join(',') if events.is_a? Array
|
||||
opt[:data] ||= {}
|
||||
opt[:data][:graph] = api_stats_path(visits: true)
|
||||
content_tag :div, "", opt
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,9 +1,13 @@
|
||||
<h1>Stats</h1>
|
||||
|
||||
<h3>Visits</h3>
|
||||
<%= line_chart Visit.group_by_day(:started_at).count %>
|
||||
<%= visits_chart_tag id: "visits" %>
|
||||
|
||||
<h3>Combined</h3>
|
||||
<%= events_chart_tag @event_types, id: 'combined' %>
|
||||
|
||||
|
||||
<% @event_types.each do |event_type| %>
|
||||
<h3><%= event_type.titleize %></h3>
|
||||
<%= line_chart api_stats_path(event: event_type) %>
|
||||
<%= events_chart_tag event_type %>
|
||||
<% end %>
|
||||
|
||||
@@ -8,36 +8,89 @@ describe Api::StatsController do
|
||||
describe 'GET index' do
|
||||
let(:user) { create :user }
|
||||
|
||||
context 'event not present' do
|
||||
context 'events or visits not present' do
|
||||
it 'should respond with bad_request' do
|
||||
sign_in user
|
||||
get :show
|
||||
expect(response).to_not be_ok
|
||||
expect(response.status).to eq 400
|
||||
end
|
||||
end
|
||||
|
||||
context 'event present' do
|
||||
it 'should return event counts' do
|
||||
time_1 = DateTime.yesterday.to_datetime
|
||||
time_2 = DateTime.now
|
||||
context 'events present' do
|
||||
before :each do
|
||||
time_1 = DateTime.parse("2015-01-01")
|
||||
time_2 = DateTime.parse("2015-01-02")
|
||||
time_3 = DateTime.parse("2015-01-03")
|
||||
|
||||
event_1 = create :ahoy_event, name: 'foo', time: time_1
|
||||
event_2 = create :ahoy_event, name: 'foo', time: time_1
|
||||
event_3 = create :ahoy_event, name: 'foo', time: time_2
|
||||
event_4 = create :ahoy_event, name: 'bar'
|
||||
create :ahoy_event, name: 'foo', time: time_1
|
||||
create :ahoy_event, name: 'foo', time: time_1
|
||||
create :ahoy_event, name: 'foo', time: time_2
|
||||
create :ahoy_event, name: 'bar', time: time_1
|
||||
create :ahoy_event, name: 'bar', time: time_3
|
||||
create :ahoy_event, name: 'bar', time: time_3
|
||||
end
|
||||
|
||||
it 'should return single events formated for working with c3.js' do
|
||||
sign_in user
|
||||
get :show, event: 'foo'
|
||||
get :show, events: 'foo'
|
||||
|
||||
expect(response).to be_ok
|
||||
|
||||
data = JSON.parse(response.body)
|
||||
dates = data.keys
|
||||
expect(data).to eq "x"=>["2015-01-01", "2015-01-02"], "Foo"=>[2, 1]
|
||||
end
|
||||
|
||||
expect(DateTime.parse dates.first).to eq time_1.utc.beginning_of_day
|
||||
expect(DateTime.parse dates.last).to eq time_2.utc.beginning_of_day
|
||||
expect(data[dates.first]).to eq 2
|
||||
expect(data[dates.last]).to eq 1
|
||||
it 'should return combined comma separated events formated for working with c3.js' do
|
||||
sign_in user
|
||||
get :show, events: 'foo,bar'
|
||||
|
||||
expect(response).to be_ok
|
||||
|
||||
data = JSON.parse(response.body)
|
||||
expect(data).to eq "x"=>["2015-01-01", "2015-01-02", "2015-01-03"], "Foo"=>[2, 1, 0], "Bar"=>[1, 0, 2]
|
||||
end
|
||||
end
|
||||
|
||||
context 'visits present' do
|
||||
it 'should return visits formated for working with c3.js' do
|
||||
time_1 = DateTime.parse("2015-01-01")
|
||||
time_2 = DateTime.parse("2015-01-02")
|
||||
|
||||
create :visit, started_at: time_1
|
||||
create :visit, started_at: time_1
|
||||
create :visit, started_at: time_2
|
||||
|
||||
sign_in user
|
||||
get :show, visits: true
|
||||
|
||||
expect(response).to be_ok
|
||||
|
||||
data = JSON.parse(response.body)
|
||||
expect(data).to eq "x"=>["2015-01-01", "2015-01-02"], "Visits"=>[2, 1]
|
||||
end
|
||||
end
|
||||
|
||||
context 'visits and events present' do
|
||||
it 'should return combined events and visits formated for working with c3.js' do
|
||||
time_1 = DateTime.parse("2015-01-01")
|
||||
time_2 = DateTime.parse("2015-01-02")
|
||||
|
||||
create :ahoy_event, name: 'foo', time: time_1
|
||||
create :ahoy_event, name: 'foo', time: time_2
|
||||
create :ahoy_event, name: 'foo', time: time_2
|
||||
|
||||
create :visit, started_at: time_1
|
||||
create :visit, started_at: time_1
|
||||
create :visit, started_at: time_2
|
||||
|
||||
sign_in user
|
||||
get :show, events: 'foo', visits: true
|
||||
|
||||
expect(response).to be_ok
|
||||
|
||||
data = JSON.parse(response.body)
|
||||
expect(data).to eq "x"=>["2015-01-01", "2015-01-02"], "Foo"=>[1, 2], "Visits"=>[2, 1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -36,4 +36,9 @@ FactoryGirl.define do
|
||||
time DateTime.now
|
||||
sequence(:name) {|n| "Event #{n} type"}
|
||||
end
|
||||
|
||||
factory :visit do
|
||||
id { SecureRandom.uuid }
|
||||
started_at DateTime.now
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user