mirror of
https://github.com/TracksApp/tracks.git
synced 2025-09-22 05:50:47 +02:00
#1153: Use translations properly, add missing labels, fix bugs and add links to charts
This commit is contained in:
parent
0a106aac5e
commit
0b326e17d8
4 changed files with 160 additions and 75 deletions
|
@ -44,13 +44,6 @@ class StatsController < ApplicationController
|
|||
render :layout => false
|
||||
end
|
||||
|
||||
def context_running_actions_data
|
||||
actions = Stats::TopContextsQuery.new(current_user, :running => true).result
|
||||
@data = Stats::PieChartData.new(actions, t('stats.spread_of_running_actions_for_visible_contexts'), 60)
|
||||
|
||||
render :pie_chart_data, :layout => false
|
||||
end
|
||||
|
||||
def show_selected_actions_from_chart
|
||||
@page_title = t('stats.action_selection_title')
|
||||
@count = 99
|
||||
|
@ -170,4 +163,14 @@ class StatsController < ApplicationController
|
|||
def put_events_into_month_buckets(records, array_size, date_method_on_todo)
|
||||
convert_to_array(records.select { |x| x.send(date_method_on_todo) }, array_size) { |r| [difference_in_months(@today, r.send(date_method_on_todo))]}
|
||||
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
|
||||
end
|
||||
|
|
|
@ -54,6 +54,7 @@ module Stats
|
|||
@actions_created_avg_last12months_array = compute_running_avg_array(created_in_last_15_months, 13)
|
||||
|
||||
# interpolate avg for current month.
|
||||
# FIXME: These should also be used.
|
||||
@interpolated_actions_created_this_month = interpolate_avg_for_current_month(@actions_created_last12months_array)
|
||||
@interpolated_actions_done_this_month = interpolate_avg_for_current_month(@actions_done_last12months_array)
|
||||
|
||||
|
@ -62,14 +63,14 @@ module Stats
|
|||
|
||||
return {
|
||||
datasets: [
|
||||
{label: "Avg created", data: @created_count_array.map { |total| [total] }, type: "line"},
|
||||
{label: "Avg completed", data: @done_count_array.map { |total| [total] }, type: "line"},
|
||||
{label: "3 months avg completed", data: @actions_done_avg_last12months_array.map { |total| [total] }, type: "line"},
|
||||
{label: "3 months avg created", data: @actions_created_avg_last12months_array.map { |total| [total] }, type: "line"},
|
||||
{label: "Created", data: @actions_created_last12months_array.map { |total| [total] } },
|
||||
{label: "Completed", data: @actions_done_last12months_array.map { |total| [total] } }
|
||||
{label: I18n.t('stats.labels.avg_created'), data: @created_count_array.map { |total| [total] }, type: "line"},
|
||||
{label: I18n.t('stats.labels.avg_completed'), data: @done_count_array.map { |total| [total] }, type: "line"},
|
||||
{label: I18n.t('stats.labels.month_avg_completed', :months => 3), data: @actions_done_avg_last12months_array.map { |total| [total] }, type: "line"},
|
||||
{label: I18n.t('stats.labels.month_avg_created', :months => 3), data: @actions_created_avg_last12months_array.map { |total| [total] }, type: "line"},
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_created_last12months_array.map { |total| [total] } },
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_done_last12months_array.map { |total| [total] } },
|
||||
],
|
||||
labels: @actions_done_avg_last12months_array.each_with_index.map { |total, month| [month] }
|
||||
labels: array_of_month_labels(@done_count_array.size),
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -88,18 +89,16 @@ module Stats
|
|||
created_count_array = Array.new(30){ |i| @actions_created_last30days.size/30.0 }
|
||||
done_count_array = Array.new(30){ |i| @actions_done_last30days.size/30.0 }
|
||||
# TODO: make the strftime i18n proof
|
||||
# TODO: Fix this, broke during transition from Flash-based stats.
|
||||
# time_labels = Array.new(30){ |i| l(Time.zone.now-i.days, :format => :stats) }
|
||||
time_labels = Array.new(30){ |i| I18n.l(Time.zone.now-i.days, :format => :stats) }
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: "Avg created", data: created_count_array.map { |total| [total] }, type: "line"},
|
||||
{label: "Avg completed", data: done_count_array.map { |total| [total] }, type: "line"},
|
||||
{label: "Created", data: @actions_created_last30days_array.map { |total| [total] } },
|
||||
{label: "Completed", data: @actions_done_last30days_array.map { |total| [total] } }
|
||||
{label: I18n.t('stats.labels.avg_created'), data: created_count_array.map { |total| [total] }, type: "line"},
|
||||
{label: I18n.t('stats.labels.completed'), data: done_count_array.map { |total| [total] }, type: "line"},
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_created_last30days_array.map { |total| [total] } },
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_done_last30days_array.map { |total| [total] } },
|
||||
],
|
||||
# labels: time_labels
|
||||
labels: @actions_done_last30days_array.each_with_index.map { |total, days| [days] }
|
||||
labels: time_labels,
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -122,10 +121,10 @@ module Stats
|
|||
|
||||
return {
|
||||
datasets: [
|
||||
{label: "Percentage", data: @cum_percent_done.map { |total| [total] }, type: "line"},
|
||||
{label: "Actions", data: @actions_completion_time_array.map { |total| [total] } }
|
||||
{label: I18n.t('stats.legend.percentage'), data: @cum_percent_done.map { |total| [total] }, type: "line"},
|
||||
{label: I18n.t('stats.legend.actions'), data: @actions_completion_time_array.map { |total| [total] } },
|
||||
],
|
||||
labels: @actions_completion_time_array.each_with_index.map { |total, week| [week] }
|
||||
labels: @actions_completion_time_array.each_with_index.map { |total, week| [week] },
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -148,10 +147,10 @@ module Stats
|
|||
|
||||
return {
|
||||
datasets: [
|
||||
{label: "Percentage", data: @cum_percent_done.map { |total| [total] }, type: "line"},
|
||||
{label: "Actions", data: @actions_running_time_array.map { |total| [total] } }
|
||||
{label: I18n.t('stats.running_time_all_legend.percentage'), data: @cum_percent_done.map { |total| [total] }, type: "line"},
|
||||
{label: I18n.t('stats.running_time_all_legend.actions'), data: @actions_running_time_array.map { |total| [total] } },
|
||||
],
|
||||
labels: @actions_running_time_array.each_with_index.map { |total, week| [week] }
|
||||
labels: @actions_running_time_array.each_with_index.map { |total, week| [week] },
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -183,10 +182,10 @@ module Stats
|
|||
|
||||
return {
|
||||
datasets: [
|
||||
{label: "Percentage", data: @cum_percent_done.map { |total| [total] }, type: "line"},
|
||||
{label: "Actions", data: @actions_running_time_array.map { |total| [total] } }
|
||||
{label: I18n.t('stats.running_time_legend.percentage'), data: @cum_percent_done.map { |total| [total] }, type: "line"},
|
||||
{label: I18n.t('stats.running_time_legend.actions'), data: @actions_running_time_array.map { |total| [total] } },
|
||||
],
|
||||
labels: @actions_running_time_array.each_with_index.map { |total, week| [week] }
|
||||
labels: @actions_running_time_array.each_with_index.map { |total, week| [week] },
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -205,9 +204,9 @@ module Stats
|
|||
|
||||
return {
|
||||
datasets: [
|
||||
{label: "Actions", data: @actions_open_per_week_array.map { |total| [total] } }
|
||||
{label: I18n.t('stats.open_per_week_legend.actions'), data: @actions_open_per_week_array.map { |total| [total] } },
|
||||
],
|
||||
labels: @actions_open_per_week_array.each_with_index.map { |total, week| [week] }
|
||||
labels: @actions_open_per_week_array.each_with_index.map { |total, week| [week] },
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -224,13 +223,12 @@ module Stats
|
|||
@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 {
|
||||
datasets: [
|
||||
{label: "Created", data: @actions_creation_day_array.map { |total| [total] } },
|
||||
{label: "Completed", data: @actions_completion_day_array.map { |total| [total] } }
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_creation_day_array.map { |total| [total] } },
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_completion_day_array.map { |total| [total] } },
|
||||
],
|
||||
labels: @actions_creation_day_array.each_with_index.map { |total, day| [day] }
|
||||
labels: I18n.t('date.day_names'),
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -247,13 +245,12 @@ module Stats
|
|||
@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 {
|
||||
datasets: [
|
||||
{label: "Created", data: @actions_creation_day_array.map { |total| [total] } },
|
||||
{label: "Completed", data: @actions_completion_day_array.map { |total| [total] } }
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_creation_day_array.map { |total| [total] } },
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_completion_day_array.map { |total| [total] } },
|
||||
],
|
||||
labels: @actions_creation_day_array.each_with_index.map { |total, day| [day] }
|
||||
labels: I18n.t('date.day_names'),
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -271,10 +268,10 @@ module Stats
|
|||
|
||||
return {
|
||||
datasets: [
|
||||
{label: "Created", data: @actions_creation_hour_array.map { |total| [total] } },
|
||||
{label: "Completed", data: @actions_completion_hour_array.map { |total| [total] } }
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_creation_hour_array.map { |total| [total] } },
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_completion_hour_array.map { |total| [total] } },
|
||||
],
|
||||
labels: @actions_creation_hour_array.each_with_index.map { |total, hour| [hour] }
|
||||
labels: @actions_creation_hour_array.each_with_index.map { |total, hour| [hour] },
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -292,10 +289,10 @@ module Stats
|
|||
|
||||
return {
|
||||
datasets: [
|
||||
{label: "Created", data: @actions_creation_hour_array.map { |total| [total] } },
|
||||
{label: "Completed", data: @actions_completion_hour_array.map { |total| [total] } }
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_creation_hour_array.map { |total| [total] } },
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_completion_hour_array.map { |total| [total] } },
|
||||
],
|
||||
labels: @actions_creation_hour_array.each_with_index.map { |total, hour| [hour] }
|
||||
labels: @actions_creation_hour_array.each_with_index.map { |total, hour| [hour] },
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -414,5 +411,13 @@ module Stats
|
|||
result[0] = "null"
|
||||
result
|
||||
end # unsolved, not triggered, edge case for set.length == upper_bound + 1
|
||||
|
||||
def month_label(i)
|
||||
I18n.t('date.month_names')[ (Time.zone.now.mon - i -1 ) % 12 + 1 ]
|
||||
end
|
||||
|
||||
def array_of_month_labels(count)
|
||||
Array.new(count) { |i| month_label(i) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,9 +7,9 @@ options = {
|
|||
responsive: false,
|
||||
plugins: {
|
||||
colorschemes: {
|
||||
scheme: 'brewer.Paired12'
|
||||
}
|
||||
}
|
||||
scheme: 'brewer.Paired12',
|
||||
},
|
||||
},
|
||||
}
|
||||
%>
|
||||
<p><%= t('stats.actions_actions_avg_created_30days', :count => (actions.created_last30days*10.0/30.0).round/10.0 )%>
|
||||
|
@ -17,31 +17,98 @@ options = {
|
|||
<%= t('stats.actions_avg_created', :count => (actions.created_last12months*10.0/12.0).round/10.0 )%>
|
||||
<%= t('stats.actions_avg_completed', :count => (actions.done_last12months*10.0/12.0).round/10.0 )%></p>
|
||||
|
||||
<%= bar_chart actions.done_last30days_data, options.merge({'title': {'display': true, 'text': 'Actions in the last 30 days'}}) %>
|
||||
<%= bar_chart actions.done_last30days_data, options.merge({
|
||||
scales: {
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.number_of_days')}}],
|
||||
yAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.number_of_actions')}}],
|
||||
},
|
||||
'title': {'display': true, 'text': t('stats.actions_30days_title')},
|
||||
}) %>
|
||||
|
||||
<%= bar_chart actions.done_last12months_data, options.merge({'title': {'display': true, 'text': 'Actions in the last 12 months'}}) %>
|
||||
<%
|
||||
# TODO: Missing the first 3 month avg values because they're null?
|
||||
%>
|
||||
<%= bar_chart actions.done_last12months_data, options.merge({
|
||||
scales: {
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.months_ago')}}],
|
||||
yAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.number_of_actions')}}],
|
||||
},
|
||||
'title': {'display': true, 'text': t('stats.actions_lastyear_title')},
|
||||
'onClick': 'function() { window.location.href = "' + url_for(:controller => 'stats', :action => 'actions_done_last_years') + '"; }',
|
||||
}) %>
|
||||
|
||||
<%= bar_chart actions.completion_time_data, options.merge({'title': {'display': true, 'text': 'Completion time (all completed actions)'}}) %>
|
||||
<%
|
||||
# TODO: There should be separate scales for percentage and amount of tasks so that the max of both is in the top of the chart, ie. the left y-axis should be "Percentage".
|
||||
%>
|
||||
<%= bar_chart actions.completion_time_data, options.merge({
|
||||
scales: {
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.running_time')}}],
|
||||
yAxes: [{ scaleLabel: { display: true, labelString: t('stats.legend.actions')}}],
|
||||
},
|
||||
'title': {'display': true, 'text': t('stats.action_completion_time_title')}}) %>
|
||||
|
||||
<br style="clear:both">
|
||||
|
||||
<%
|
||||
# TODO: There should be separate scales for percentage and amount of tasks so that the max of both is in the top of the chart.
|
||||
# TODO: There should be separate scales for percentage and amount of tasks so that the max of both is in the top of the chart, ie. the left y-axis should be "Percentage".
|
||||
%>
|
||||
<%= bar_chart actions.visible_running_time_data, options.merge({'title': {'display': true, 'text': 'Current running time of incomplete visible actions'}}) %>
|
||||
<%= bar_chart actions.visible_running_time_data, options.merge({
|
||||
scales: {
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: t('stats.running_time_legend.weeks')}}],
|
||||
yAxes: [{ scaleLabel: { display: true, labelString: t('stats.running_time_legend.actions')}}],
|
||||
},
|
||||
'title': {'display': true, 'text': t('stats.current_running_time_of_incomplete_visible_actions')},
|
||||
'onClick': 'function(event, array) { window.location.href = "' + url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :id => "art") + '?index=" + array[0]._index; }',
|
||||
}) %>
|
||||
|
||||
<%= bar_chart actions.running_time_data, options.merge({'title': {'display': true, 'text': 'Current running time of all incomplete actions'}}) %>
|
||||
|
||||
<br style="clear:both">
|
||||
<%= bar_chart actions.open_per_week_data, options.merge({scales: {yAxes: [{ scaleLabel: { display: true, labelString: 'Weeks ago'}}]}, 'title': {'display': true, 'text': 'Active (visible and hidden) next actions per week'}}) %>
|
||||
|
||||
<%= bar_chart actions.day_of_week_all_data, options.merge({'title': {'display': true, 'text': 'Day of week (all actions)'}}) %>
|
||||
|
||||
<%= bar_chart actions.day_of_week_30days_data, options.merge({'title': {'display': true, 'text': 'Day of week (past 30 days)'}}) %>
|
||||
<%
|
||||
# TODO: There should be separate scales for percentage and amount of tasks so that the max of both is in the top of the chart, ie. the left y-axis should be "Percentage".
|
||||
%>
|
||||
<%= bar_chart actions.running_time_data, options.merge({
|
||||
scales: {
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: t('stats.running_time_all_legend.running_time')}}],
|
||||
yAxes: [{ scaleLabel: { display: true, labelString: t('stats.running_time_legend.actions')}}],
|
||||
},
|
||||
'title': {'display': true, 'text': t('stats.running_time_all')},
|
||||
'onClick': 'function(event, array) { window.location.href = "' + url_for(:controller => 'stats', :action => 'show_selected_actions_from_chart', :id => "avrt") + '?index=" + array[0]._index; }',
|
||||
}) %>
|
||||
|
||||
<br style="clear:both">
|
||||
|
||||
<%= bar_chart actions.time_of_day_all_data, options.merge({'title': {'display': true, 'text': 'Time of day (all actions)'}}) %>
|
||||
<%= bar_chart actions.open_per_week_data, options.merge({
|
||||
scales: {
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: t('stats.open_per_week_legend.weeks')}}],
|
||||
yAxes: [{ scaleLabel: { display: true, labelString: t('stats.open_per_week_legend.actions')}}],
|
||||
},
|
||||
'title': {'display': true, 'text': t('stats.open_per_week')}}) %>
|
||||
|
||||
<%= bar_chart actions.time_of_day_30days_data, options.merge({'title': {'display': true, 'text': 'Time of day (last 30 days)'}}) %>
|
||||
<%= bar_chart actions.day_of_week_all_data, options.merge({
|
||||
scales: {
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: t('stats.actions_day_of_week_legend.day_of_week')}}],
|
||||
yAxes: [{ scaleLabel: { display: true, labelString: t('stats.actions_day_of_week_legend.number_of_actions')}}],
|
||||
},
|
||||
'title': {'display': true, 'text': t('stats.actions_day_of_week_title')}}) %>
|
||||
|
||||
<%= bar_chart actions.day_of_week_30days_data, options.merge({
|
||||
scales: {
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: t('stats.actions_dow_30days_legend.day_of_week')}}],
|
||||
yAxes: [{ scaleLabel: { display: true, labelString: t('stats.actions_dow_30days_legend.number_of_actions')}}],
|
||||
},
|
||||
'title': {'display': true, 'text': t('stats.actions_dow_30days_title')}}) %>
|
||||
|
||||
<br style="clear:both">
|
||||
|
||||
<%= bar_chart actions.time_of_day_all_data, options.merge({
|
||||
scales: {
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: t('stats.time_of_day_legend.time_of_day')}}],
|
||||
yAxes: [{ scaleLabel: { display: true, labelString: t('stats.time_of_day_legend.number_of_actions')}}],
|
||||
},
|
||||
'title': {'display': true, 'text': t('stats.time_of_day')}}) %>
|
||||
|
||||
<%= bar_chart actions.time_of_day_30days_data, options.merge({
|
||||
scales: {
|
||||
xAxes: [{ scaleLabel: { display: true, labelString: t('stats.tod30_legend.time_of_day')}}],
|
||||
yAxes: [{ scaleLabel: { display: true, labelString: t('stats.tod30_legend.number_of_actions')}}],
|
||||
},
|
||||
'title': {'display': true, 'text': t('stats.tod30')}}) %>
|
||||
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
<% data = {
|
||||
datasets: [{
|
||||
data: Array.new
|
||||
data: Array.new,
|
||||
}],
|
||||
labels: Array.new
|
||||
labels: Array.new,
|
||||
ids: Array.new,
|
||||
}
|
||||
Stats::TopContextsQuery.new(current_user).result.map { |context|
|
||||
data[:datasets][0][:data].append(context.total)
|
||||
data[:labels].append(context.name)
|
||||
data[:ids].append(context.id)
|
||||
}
|
||||
options = {
|
||||
width: "400px",
|
||||
|
@ -17,25 +19,33 @@ options = {
|
|||
responsive: false,
|
||||
plugins: {
|
||||
colorschemes: {
|
||||
scheme: 'brewer.Paired12'
|
||||
}
|
||||
}
|
||||
scheme: 'brewer.Paired12',
|
||||
},
|
||||
},
|
||||
}
|
||||
%>
|
||||
<%= pie_chart data, options.merge({'title': {'display': true, 'text': 'Spread of actions for all contexts'}}) %>
|
||||
<% #TODO: Move data handling to model. Show value as percentage %>
|
||||
<%= pie_chart data, options.merge({
|
||||
'title': {'display': true, 'text': t('stats.spread_of_actions_for_all_context')},
|
||||
'onClick': 'function(event, array) { console.log(array); window.location.href = "' + url_for(:controller => 'contexts', :action => 'show', :id => -1).gsub('-1', '') + '" + array[0]._chart.chart.data.ids[array[0]._index]; }'
|
||||
}) %>
|
||||
|
||||
<% data = {
|
||||
datasets: [{
|
||||
data: Array.new
|
||||
data: Array.new,
|
||||
}],
|
||||
labels: Array.new
|
||||
}
|
||||
labels: Array.new,
|
||||
ids: Array.new,
|
||||
}
|
||||
Stats::TopContextsQuery.new(current_user, :running => true).result.map { |context|
|
||||
data[:datasets][0][:data].append(context.total)
|
||||
data[:labels].append(context.name)
|
||||
data[:ids].append(context.id)
|
||||
}
|
||||
%>
|
||||
<%= pie_chart data, options.merge({'title': {'display': true, 'text': 'Spread of actions for visible contexts'}}) %>
|
||||
<%= pie_chart data, options.merge({
|
||||
'onClick': 'function(event, array) { console.log(array); window.location.href = "' + url_for(:controller => 'contexts', :action => 'show', :id => -1).gsub('-1', '') + '" + array[0]._chart.chart.data.ids[array[0]._index]; }',
|
||||
'title': {'display': true, 'text': t('stats.spread_of_running_actions_for_visible_contexts')}}) %>
|
||||
|
||||
<br style="clear:both">
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue