#1153: Few of the graphs converted to use Chartkick

This commit is contained in:
Jyri-Petteri Paloposki 2019-05-12 14:10:59 +03:00
parent b1fbc7202e
commit c9cae9421a
13 changed files with 185 additions and 192 deletions

View file

@ -88,3 +88,5 @@ group :test do
# get test coverage info on codeclimate
gem "codeclimate-test-reporter", "1.0.7", group: :test, require: nil
end
gem "chartkick"

View file

@ -66,6 +66,7 @@ GEM
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (11.0.1)
chartkick (3.0.2)
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
climate_control (0.2.0)
@ -284,6 +285,7 @@ DEPENDENCIES
bootstrap-sass (= 3.4.1)
bullet
byebug
chartkick
codeclimate-test-reporter (= 1.0.7)
coffee-rails (~> 4.2.0)
database_cleaner

View file

@ -36,3 +36,6 @@
//= require jquery.truncator
//= require superfish
//= require supersubs
//= require Chart.bundle
//= require chartkick

View file

@ -164,23 +164,6 @@ class StatsController < ApplicationController
render :layout => false
end
def actions_open_per_week_data
@actions_started = current_user.todos.created_after(@today-53.weeks).
select("todos.created_at, todos.completed_at").
reorder("todos.created_at DESC")
@max_weeks = difference_in_weeks(@today, @actions_started.last.created_at)
# cut off chart at 52 weeks = one year
@count = [52, @max_weeks].min
@actions_open_per_week_array = convert_to_weeks_running_from_today_array(@actions_started, @max_weeks+1)
@actions_open_per_week_array = cut_off_array(@actions_open_per_week_array, @count)
@max_actions = (@actions_open_per_week_array.max or 0)
render :layout => false
end
def context_total_actions_data
actions = Stats::TopContextsQuery.new(current_user).result
@ -196,75 +179,6 @@ class StatsController < ApplicationController
render :pie_chart_data, :layout => false
end
def actions_day_of_week_all_data
@actions_creation_day = current_user.todos.select("created_at")
@actions_completion_day = current_user.todos.completed.select("completed_at")
# convert to array and fill in non-existing days
@actions_creation_day_array = Array.new(7) { |i| 0}
@actions_creation_day.each { |t| @actions_creation_day_array[ t.created_at.wday ] += 1 }
@max = @actions_creation_day_array.max
# convert to array and fill in non-existing days
@actions_completion_day_array = Array.new(7) { |i| 0}
@actions_completion_day.each { |t| @actions_completion_day_array[ t.completed_at.wday ] += 1 }
@max = @actions_completion_day_array.max
render :layout => false
end
def actions_day_of_week_30days_data
@actions_creation_day = current_user.todos.created_after(@cut_off_month).select("created_at")
@actions_completion_day = current_user.todos.completed_after(@cut_off_month).select("completed_at")
# convert to hash to be able to fill in non-existing days
@max=0
@actions_creation_day_array = Array.new(7) { |i| 0}
@actions_creation_day.each { |r| @actions_creation_day_array[ r.created_at.wday ] += 1 }
# convert to hash to be able to fill in non-existing days
@actions_completion_day_array = Array.new(7) { |i| 0}
@actions_completion_day.each { |r| @actions_completion_day_array[r.completed_at.wday] += 1 }
@max = [@actions_creation_day_array.max, @actions_completion_day_array.max].max
render :layout => false
end
def actions_time_of_day_all_data
@actions_creation_hour = current_user.todos.select("created_at")
@actions_completion_hour = current_user.todos.completed.select("completed_at")
# convert to hash to be able to fill in non-existing days
@actions_creation_hour_array = Array.new(24) { |i| 0}
@actions_creation_hour.each{|r| @actions_creation_hour_array[r.created_at.hour] += 1 }
# convert to hash to be able to fill in non-existing days
@actions_completion_hour_array = Array.new(24) { |i| 0}
@actions_completion_hour.each{|r| @actions_completion_hour_array[r.completed_at.hour] += 1 }
@max = [@actions_creation_hour_array.max, @actions_completion_hour_array.max].max
render :layout => false
end
def actions_time_of_day_30days_data
@actions_creation_hour = current_user.todos.created_after(@cut_off_month).select("created_at")
@actions_completion_hour = current_user.todos.completed_after(@cut_off_month).select("completed_at")
# convert to hash to be able to fill in non-existing days
@actions_creation_hour_array = Array.new(24) { |i| 0}
@actions_creation_hour.each{|r| @actions_creation_hour_array[r.created_at.hour] += 1 }
# convert to hash to be able to fill in non-existing days
@actions_completion_hour_array = Array.new(24) { |i| 0}
@actions_completion_hour.each{|r| @actions_completion_hour_array[r.completed_at.hour] += 1 }
@max = [@actions_creation_hour_array.max, @max = @actions_completion_hour_array.max].max
render :layout => false
end
def show_selected_actions_from_chart
@page_title = t('stats.action_selection_title')
@count = 99

View file

@ -6,6 +6,12 @@ module Stats
attr_reader :user
def initialize(user)
@user = user
@today = Time.zone.now.utc.beginning_of_day
@cut_off_year = 12.months.ago.beginning_of_day
@cut_off_year_plus3 = 15.months.ago.beginning_of_day
@cut_off_month = 1.month.ago.beginning_of_day
@cut_off_30days = 30.days.ago.beginning_of_day
end
def ttc
@ -42,16 +48,121 @@ module Stats
@timing_charts ||= %w{
actions_visible_running_time_data
actions_running_time_data
actions_open_per_week_data
actions_day_of_week_all_data
actions_day_of_week_30days_data
actions_time_of_day_all_data
actions_time_of_day_30days_data
}.map do |action|
Stats::Chart.new(action)
end
end
def running_time_data
@actions_running_time = @user.todos.not_completed.select("created_at").reorder("created_at DESC")
# convert to array and fill in non-existing weeks with 0
@max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at)
@actions_running_per_week_array = convert_to_weeks_from_today_array(@actions_running_time, @max_weeks+1, :created_at)
# cut off chart at 52 weeks = one year
@count = [52, @max_weeks].min
# convert to new array to hold max @cut_off elems + 1 for sum of actions after @cut_off
@actions_running_time_array = cut_off_array_with_sum(@actions_running_per_week_array, @count)
@max_actions = @actions_running_time_array.max
# get percentage done cumulative
@cum_percent_done = convert_to_cumulative_array(@actions_running_time_array, @actions_running_time.count )
end
def open_per_week_data
@actions_started = @user.todos.created_after(@today-53.weeks).
select("todos.created_at, todos.completed_at").
reorder("todos.created_at DESC")
@max_weeks = difference_in_weeks(@today, @actions_started.last.created_at)
# cut off chart at 52 weeks = one year
@count = [52, @max_weeks].min
@actions_open_per_week_array = convert_to_weeks_running_from_today_array(@actions_started, @max_weeks+1)
@actions_open_per_week_array = cut_off_array(@actions_open_per_week_array, @count)
return @actions_open_per_week_array.each_with_index.map { |total, week| [week, total] }
end
def day_of_week_all_data
@actions_creation_day = @user.todos.select("created_at")
@actions_completion_day = @user.todos.completed.select("completed_at")
# convert to array and fill in non-existing days
@actions_creation_day_array = Array.new(7) { |i| 0}
@actions_creation_day.each { |t| @actions_creation_day_array[ t.created_at.wday ] += 1 }
@max = @actions_creation_day_array.max
# convert to array and fill in non-existing days
@actions_completion_day_array = Array.new(7) { |i| 0}
@actions_completion_day.each { |t| @actions_completion_day_array[ t.completed_at.wday ] += 1 }
# FIXME: Day of week as string instead of number
return [
{name: "Created", data: @actions_creation_day_array.each_with_index.map { |total, day| [day, total] } },
{name: "Completed", data: @actions_completion_day_array.each_with_index.map { |total, day| [day, total] } }
]
end
def day_of_week_30days_data
@actions_creation_day = @user.todos.created_after(@cut_off_month).select("created_at")
@actions_completion_day = @user.todos.completed_after(@cut_off_month).select("completed_at")
# convert to hash to be able to fill in non-existing days
@max=0
@actions_creation_day_array = Array.new(7) { |i| 0}
@actions_creation_day.each { |r| @actions_creation_day_array[ r.created_at.wday ] += 1 }
# convert to hash to be able to fill in non-existing days
@actions_completion_day_array = Array.new(7) { |i| 0}
@actions_completion_day.each { |r| @actions_completion_day_array[r.completed_at.wday] += 1 }
# FIXME: Day of week as string instead of number
return [
{name: "Created", data: @actions_creation_day_array.each_with_index.map { |total, day| [day, total] } },
{name: "Completed", data: @actions_completion_day_array.each_with_index.map { |total, day| [day, total] } }
]
end
def time_of_day_all_data
@actions_creation_hour = @user.todos.select("created_at")
@actions_completion_hour = @user.todos.completed.select("completed_at")
# convert to hash to be able to fill in non-existing days
@actions_creation_hour_array = Array.new(24) { |i| 0}
@actions_creation_hour.each{|r| @actions_creation_hour_array[r.created_at.hour] += 1 }
# convert to hash to be able to fill in non-existing days
@actions_completion_hour_array = Array.new(24) { |i| 0}
@actions_completion_hour.each{|r| @actions_completion_hour_array[r.completed_at.hour] += 1 }
return [
{name: "Created", data: @actions_creation_hour_array.each_with_index.map { |total, hour| [hour, total] } },
{name: "Completed", data: @actions_completion_hour_array.each_with_index.map { |total, hour| [hour, total] } }
]
end
def time_of_day_30days_data
@actions_creation_hour = @user.todos.created_after(@cut_off_month).select("created_at")
@actions_completion_hour = @user.todos.completed_after(@cut_off_month).select("completed_at")
# convert to hash to be able to fill in non-existing days
@actions_creation_hour_array = Array.new(24) { |i| 0}
@actions_creation_hour.each{|r| @actions_creation_hour_array[r.created_at.hour] += 1 }
# convert to hash to be able to fill in non-existing days
@actions_completion_hour_array = Array.new(24) { |i| 0}
@actions_completion_hour.each{|r| @actions_completion_hour_array[r.completed_at.hour] += 1 }
return [
{name: "Created", data: @actions_creation_hour_array.each_with_index.map { |total, hour| [hour, total] } },
{name: "Completed", data: @actions_completion_hour_array.each_with_index.map { |total, hour| [hour, total] } }
]
end
private
def one_year
@ -73,5 +184,39 @@ module Stats
def completed
@completed ||= user.todos.completed.select("completed_at, created_at")
end
# assumes date1 > date2
def difference_in_days(date1, date2)
return ((date1.utc.at_midnight-date2.utc.at_midnight)/SECONDS_PER_DAY).to_i
end
# assumes date1 > date2
def difference_in_weeks(date1, date2)
return difference_in_days(date1, date2) / 7
end
# uses the supplied block to determine array of indexes in hash
# the block should return an array of indexes each is added to the hash and summed
def convert_to_array(records, upper_bound)
a = Array.new(upper_bound, 0)
records.each { |r| (yield r).each { |i| a[i] += 1 if a[i] } }
a
end
def convert_to_weeks_running_from_today_array(records, array_size)
return convert_to_array(records, array_size) { |r| week_indexes_of(r) }
end
def cut_off_array(array, cut_off)
return Array.new(cut_off){|i| array[i]||0}
end
def week_indexes_of(record)
a = []
start_week = difference_in_weeks(@today, record.created_at)
end_week = record.completed_at ? difference_in_weeks(@today, record.completed_at) : 0
end_week.upto(start_week) { |i| a << i };
return a
end
end
end

View file

@ -13,15 +13,5 @@ module Stats
def running_actions
@running_actions ||= Stats::TopContextsQuery.new(user, :limit => 5, :running => true).result
end
def charts
@charts = %w{
context_total_actions_data
context_running_actions_data
}.map do |action|
Stats::Chart.new(action, :height => 325)
end
end
end
end

View file

@ -15,3 +15,21 @@
render :partial => 'chart', :locals => {:chart => chart}
-%><% end %>
<h2>Current running time of all incomplete actions</h2>
<%= column_chart actions.running_time_data %>
<h2>Active (visible and hidden) next actions per week</h2>
<%= column_chart actions.open_per_week_data, xtitle: "Weeks ago" %>
<h2>Day of week (all actions)</h2>
<%= column_chart actions.day_of_week_all_data %>
<h2>Day of week (past 30 days)</h2>
<%= column_chart actions.day_of_week_30days_data %>
<h2>Time of day (all actions)</h2>
<%= column_chart actions.time_of_day_all_data %>
<h2>Time of day (last 30 days)</h2>
<%= column_chart actions.time_of_day_30days_data %>

View file

@ -1,9 +1,15 @@
<% contexts.charts.each do |chart| %><%=
render :partial => 'chart', :locals => {:chart => chart}
-%><% end %>
<br style="clear:both">
<h2>Spread of actions for all contexts</h2>
<%= pie_chart Stats::TopContextsQuery.new(current_user).result.map { |context|
[context.name, context.total]
} %>
<h2>Spread of actions for visible contexts</h2>
<%= pie_chart Stats::TopContextsQuery.new(current_user, :running => true).result.map { |context|
[context.name, context.total]
} %>
<%= render :partial => 'contexts_list', :locals => {:contexts => contexts.actions, :key => 'contexts'} -%>
<%= render :partial => 'contexts_list', :locals => {:contexts => contexts.running_actions, :key => 'visible_contexts_with_incomplete_actions'} -%>

View file

@ -1,16 +0,0 @@
&title=<%= t('stats.actions_dow_30days_title') %>,{font-size:16},&
&y_legend=<%= t('stats.actions_dow_30days_legend.number_of_actions') %>,10,0x736AFF&
&x_legend=<%= t('stats.actions_dow_30days_legend.day_of_week') %>,10,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0,<%= t('stats.labels.created') %>,8&
&filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,8&
&values=<%= @actions_creation_day_array.join(",") %>&
&values_2=<%= @actions_completion_day_array.join(",") %>&
&x_labels=<%= t('date.day_names').join(",") %>&
&y_min=0&
<%
# add one to @max for people who have no actions completed yet.
# OpenFlashChart cannot handle y_max=0
-%>
&y_max=<%=@max+1 -%>&
&x_label_style=9,,2,1&

View file

@ -1,16 +0,0 @@
&title=<%= t('stats.actions_day_of_week_title') %>,{font-size:16},&
&y_legend=<%= t('stats.actions_day_of_week_legend.number_of_actions') %>,10,0x736AFF&
&x_legend=<%= t('stats.actions_day_of_week_legend.day_of_week') %>,10,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0,<%= t('stats.labels.created') %>,8&
&filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,8&
&values=<%= @actions_creation_day_array.join(",") %>&
&values_2=<%= @actions_completion_day_array.join(",") %>&
&x_labels=<%= t('date.day_names').join(",") %>&
&y_min=0&
<%
# add one to @max for people who have no actions completed yet.
# OpenFlashChart cannot handle y_max=0
-%>
&y_max=<%=@max+1 -%>&
&x_label_style=9,,2,1&

View file

@ -1,23 +0,0 @@
&title=<%= t('stats.tod30') %>,{font-size:16},&
&y_legend=<%= t('stats.tod30_legend.number_of_actions') %>,12,0x736AFF&
&x_legend=<%= t('stats.tod30_legend.time_of_day') %>,12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0,<%= t('stats.labels.created') %>,8&
&filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,8&
&values=<%
0.upto 22 do |i| -%>
<%=@actions_creation_hour_array[i] -%>,
<% end -%><%=@actions_creation_hour_array[23]%>&
&values_2=<%
0.upto 22 do |i| -%>
<%=@actions_completion_hour_array[i] -%>,
<% end -%><%=@actions_completion_hour_array[23]%>&
&x_labels= <%
0.upto 22 do |i| -%>
<%=i-%>,
<% end -%>23&
&y_min=0&
<% # add one to @max for people who have no actions completed yet.
# OpenFlashChart cannot handle y_max=0 -%>
&y_max=<%=@max+1 -%>&
&x_label_style=9,,1,1&

View file

@ -1,23 +0,0 @@
&title=<%= t('stats.time_of_day') %>,{font-size:16},&
&y_legend=<%= t('stats.time_of_day_legend.number_of_actions') %>,12,0x736AFF&
&x_legend=<%= t('stats.time_of_day_legend.time_of_day') %>,12,0x736AFF&
&y_ticks=5,10,5&
&filled_bar=50,0x9933CC,0x8010A0,<%= t('stats.labels.created') %>,8&
&filled_bar_2=50,0x0066CC,0x0066CC,<%= t('stats.labels.completed') %>,8&
&values=<%
0.upto 22 do |i| -%>
<%=@actions_creation_hour_array[i] -%>,
<% end -%><%=@actions_creation_hour_array[23]%>&
&values_2=<%
0.upto 22 do |i| -%>
<%=@actions_completion_hour_array[i] -%>,
<% end -%><%=@actions_completion_hour_array[23]%>&
&x_labels= <%
0.upto 22 do |i| -%>
<%=i-%>,
<% end -%>23&
&y_min=0&
<% # add one to @max for people who have no actions completed yet.
# OpenFlashChart cannot handle y_max=0 -%>
&y_max=<%=@max+1 -%>&
&x_label_style=9,,1,1&

View file

@ -1,9 +0,0 @@
&title=<%= @data.title %>,{font-size:16}&
&pie=<%= @data.alpha %>,#505050,{font-size: 12px; color: #404040;}&
&x_axis_steps=1& &y_ticks=5,10,5& &line=3,#87421F& &y_min=0& &y_max=20&
&values=<%= @data.values.join(",") %>&
&pie_labels=<%= @data.labels.join(",") %>&
&links=<%= @data.ids.map{|id| context_path(id)}.join(",") %>&
&colours=#d01f3c,#356aa0,#C79810,#c61fd0,#1fc6d0,#1fd076,#72d01f,#c6d01f,#d0941f,#40941f&
&tool_tip=#x_label#: #val#%25&
&x_label_style=9,,2,1&