removing inline JS, adding more local caching

This commit is contained in:
Matt Claypotch 2010-06-18 19:17:56 -07:00
Родитель 3d1655e50e
Коммит cd9eb2faee
16 изменённых файлов: 518 добавлений и 523 удалений

Просмотреть файл

@ -1,49 +1,33 @@
{% extends "stats/stats.html" %}
{% block stats %}
{% block chart_config %}
data-series="applications|{ec8030f7-c20a-464f-9b0e-13a3a9e97384}|3.6.3,applications|{ec8030f7-c20a-464f-9b0e-13a3a9e97384}|3.6"
{% endblock %}
{% block csvtable %}
<div class="statbox">
<div class="tabular">
<table class="bar-table">
<table class="csv-table">
<thead>
<tr>
<th
data-field="date"
data-format="date">
{{_('Date')}}
</th>
<th
data-field="applications|{ec8030f7-c20a-464f-9b0e-13a3a9e97384}|3.6.3"
data-format="number">
{{_('Firefox 3.6.3')}}
</th>
<th
data-field="applications|{ec8030f7-c20a-464f-9b0e-13a3a9e97384}|3.6"
data-format="number">
{{_('Firefox 3.6')}}
</th>
</tr>
</thead>
</table>
</div>
</div>
{% endblock %}
{% block chartconfig %}
<script>
AMO.seriesList = {
metric: "apps",
fields: [
"applications|{ec8030f7-c20a-464f-9b0e-13a3a9e97384}|3.6.3",
"applications|{ec8030f7-c20a-464f-9b0e-13a3a9e97384}|3.6",
]
};
AMO.csvTableConfig = {
el: $("table.bar-table")[0],
report: "{{ report }}",
columns: [{
label: "{{_('Date')}}",
field: 'date',
format: function (value) {
return Highcharts.dateFormat('%a, %b %e, %Y', new Date(value));
}
},
{
label: "Firefox 3.6.3",
field: 'applications|{ec8030f7-c20a-464f-9b0e-13a3a9e97384}|3.6.3',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "Firefox 3.6",
field: 'applications|{ec8030f7-c20a-464f-9b0e-13a3a9e97384}|3.6',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
}
]
};
</script>
{% endblock %}

Просмотреть файл

@ -1,29 +1,36 @@
{% extends "stats/stats.html" %}
{% block chart_config %}
data-series="count"
{% endblock %}
{% block stats %}
<div class="featured">
<div class="featured-inner">
<div class="featured-body tabular">
<table class="stats-aggregate"><thead>
<tr><th>{{_('Category')}}</th><th>Last 7 Days</th><th>7-14 Days Ago</th><th>{{_('All Time')}}</th></tr>
<table class="stats-aggregate" data-field="count"><thead>
<tr><th>{{_('Category')}}</th><th class="range"></th><th class="prev_range"></th><th>{{_('All Time')}}</th></tr>
</thead>
<tbody>
<tr>
<td class="label">{{_('Total Downloads')}}</td>
<td class="value"><span class="value aggregate" id="sum_range"></span><span class="change" id="sum_diff"></span></td>
<td class="value"><span class="value aggregate" id="sum_prev_range"></span><span class="change" id="sum_prev_diff"></span></td>
<td class="value"><span class="value aggregate" id="sum_all_time"></span><span class="change">&nbsp;</span></td>
<td class="value"><span class="value aggregate" id="sum_all_time">{{ addon.total_downloads|numberfmt }}</span><span class="change">&nbsp;</span></td>
</tr>
<tr>
<td class="label">{{_('Average Downloads/Day')}}</td>
<td class="value"><span class="value aggregate" id="mean_range"></span><span class="change" id="mean_diff"></span></td>
<td class="value"><span class="value aggregate" id="mean_prev_range"></span><span class="change" id="mean_prev_diff"></span></td>
<td class="value"><span class="value aggregate" id="mean_all_time"></span><span class="change">&nbsp;</span></td>
<td class="value"><span class="value aggregate" id="mean_all_time">{{ addon.average_daily_downloads|numberfmt }}</span><span class="change">&nbsp;</span></td>
</tr>
</tbody></table>
</div>
</div>
</div>
{% endblock %}
{% block csvtable %}
<h3>{{_('Downloads by Date')}}</h3>
<div class="statbox">
<div class="tabular">
@ -43,6 +50,7 @@
{{_('Count')}}
</th>
</tr>
</thead>
</table>
</div>
</div>

Просмотреть файл

@ -1,57 +1,39 @@
{% extends "stats/stats.html" %}
{% block stats %}
{% block chart_config %}
data-series="locales|en-US,locales|es-ES,locales|de"
{% endblock %}
{% block csvtable %}
<div class="statbox">
<div class="tabular">
<table class="bar-table">
<table class="csv-table">
<thead>
<tr>
<th
data-field="date"
data-format="date">
{{_('Date')}}
</th>
<th
data-field="locales|en-US"
data-format="number">
{{_('English (US)')}}
</th>
<th
data-field="locales|es-ES"
data-format="number">
{{_('Spanish')}}
</th>
<th
data-field="locales|de"
data-format="number">
{{_('German')}}
</th>
</tr>
</thead>
</table>
</div>
</div>
{% endblock %}
{% block chartconfig %}
<script>
AMO.seriesList = {
metric: "locales",
fields: [
"locales|en-US",
"locales|es-ES",
"locales|de"
]
};
AMO.csvTableConfig = {
el: $("table.bar-table")[0],
report: "{{ report }}",
columns: [{
label: "{{_('Date')}}",
field: 'date',
format: function (value) {
return Highcharts.dateFormat('%a, %b %e, %Y', new Date(value));
}
},
{
label: "{{_('English (US)')}}",
field: 'locales|en-US',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "{{_('Spanish')}}",
field: 'locales|es-ES',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "{{_('German')}}",
field: 'locales|de',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
}
]
};
</script>
{% endblock %}

Просмотреть файл

@ -1,57 +1,38 @@
{% extends "stats/stats.html" %}
{% block stats %}
{% block chart_config %}
data-series="oses|WINNT,oses|Darwin,oses|Linux"
{% endblock %}
{% block csvtable %}
<div class="statbox">
<div class="tabular">
<table class="bar-table">
<table class="csv-table">
<thead>
<tr>
<th
data-field="date"
data-format="date">
{{_('Date')}}
</th>
<th
data-field="oses|WINNT"
data-format="number">
{{_('Windows')}}
</th>
<th
data-field="oses|Darwin"
data-format="number">
{{_('Mac')}}
</th>
<th
data-field="oses|Linux"
data-format="number">
{{_('Linux')}}
</th>
</tr>
</thead>
</table>
</div>
</div>
{% endblock %}
{% block chartconfig %}
<script>
AMO.seriesList = {
metric: "os",
fields: [
"oses|WINNT",
"oses|Darwin",
"oses|Linux"
]
};
AMO.csvTableConfig = {
el: $("table.bar-table")[0],
report: "{{ report }}",
columns: [{
label: "{{_('Date')}}",
field: 'date',
format: function (value) {
return Highcharts.dateFormat('%a, %b %e, %Y', new Date(value));
}
},
{
label: "{{_('Windows')}}",
field: 'oses|WINNT',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "{{_('Mac')}}",
field: 'oses|Darwin',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "{{_('Linux')}}",
field: 'oses|Linux',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
}
]
};
</script>
{% endblock %}

Просмотреть файл

@ -1,10 +1,33 @@
{% extends "stats/stats.html" %}
{% block chart_config %}
data-series="count"
{% endblock %}
{% block chart_menu %}
<ul id='series-select'>
<li class="selected">
<a href="#"
data-report='downloads'
data-series='count'>
{{_('Downloads')}}
</a>
</li>
<li>
<a href="#"
data-report='usage'
data-series='count'>
{{_('Daily Users')}}
</a>
</li>
</ul>
{% endblock %}
{% block stats %}
<div class="featured">
<div class="featured-inner three-up">
<div><a href="#">850,749 Downloads</a><br/><small>16,534 in last 30 days</small></div>
<div><a href="#">672,501 Daily Users</a><br/><small>634,475 in last 30 days</small></div>
<div><a href="#">{{ addon.total_downloads|numberfmt }} Downloads</a><br/><small>16,534 in last 30 days</small></div>
<div><a href="#">{{ addon.average_daily_users|numberfmt }} Daily Users</a><br/><small>634,475 in last 30 days</small></div>
<div><a href="#">$956.00 Contributed</a><br/><small>$83.00 in last 30 days</small></div>
</div>
</div>

Просмотреть файл

@ -1,57 +1,38 @@
{% extends "stats/stats.html" %}
{% block stats %}
{% block chart_config %}
data-series="sources|api,sources|search,sources|collection"
{% endblock %}
{% block csvtable %}
<div class="statbox">
<div class="tabular">
<table class="bar-table">
<table class="csv-table">
<thead>
<tr>
<th
data-field="date"
data-format="date">
{{_('Date')}}
</th>
<th
data-field="sources|api"
data-format="number">
{{_('API')}}
</th>
<th
data-field="sources|search"
data-format="number">
{{_('Search')}}
</th>
<th
data-field="sources|collection"
data-format="number">
{{_('Collections')}}
</th>
</tr>
</thead>
</table>
</div>
</div>
{% endblock %}
{% block chartconfig %}
<script>
AMO.seriesList = {
metric: "sources",
fields: [
"sources|api",
"sources|search",
"sources|collection"
]
};
AMO.csvTableConfig = {
el: $("table.bar-table")[0],
report: "{{ report }}",
columns: [{
label: "{{_('Date')}}",
field: 'date',
format: function (value) {
return Highcharts.dateFormat('%a, %b %e, %Y', new Date(value));
}
},
{
label: "{{_('API')}}",
field: 'sources|api',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "{{_('Search')}}",
field: 'sources|search',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "{{_('Collection')}}",
field: 'sources|collection',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
}
]
};
</script>
{% endblock %}

Просмотреть файл

@ -48,6 +48,7 @@
<div class="primary statistics"
data-report="{{ report }}"
data-addon_id="{{ addon.id }}"
data-base_url="{{ stats_base_url }}"
>
{% if true %}
<div class="custom criteria hidden">
@ -64,31 +65,32 @@
</select>
<button id="date-range-submit" type="submit">Update</button>
</form>
<!-- <ul><li>From</li><li class="selected"><a>Control 1</a></li></ul> -->
</div>
{% endif %}
<div class="featured">
<div class="featured-inner chart">
<div class="listing-header"><ul><li class="selected">&nbsp;</li></ul></div>
<div class="featured-body" id="head-chart" style="background:#fff;height:256px"></div>
<div class="listing-header">
{% block chart_menu %}
<ul><li class="selected">&nbsp;</li></ul>
{% endblock %}
</div>
<div class="featured-body" id="head-chart" style="background:#fff;height:256px"
{% block chart_config %}
data-series="{{ series_fields }}"
{% endblock %}
>
</div>
</div>
</div>
{% block stats %}
{% endblock %}
{% block csvtable %}
{% endblock %}
</div>
{% endblock %}
{% block js %}
<script>
(function () {
var stats_base_url = '{{ stats_base_url }}/';
AMO.getStatsBaseURL = function () { return stats_base_url };
})();
</script>
{% block chartconfig %}
{% endblock %}
<script src="{{ MEDIA_URL }}js/zamboni/jquery-datepicker.js"></script>
<script src="{{ MEDIA_URL }}js/zamboni/highcharts.src.js"></script>
<!--[if IE]>

Просмотреть файл

@ -1,66 +1,44 @@
{% extends "stats/stats.html" %}
{% block chart_config %}
data-series="statuses|userEnabled,statuses|userDisabled"
{% endblock %}
{% block stats %}
<h3>{{_('Add-on Status by Date')}}</h3>
<div class="statbox">
<div class="tabular">
<table class="bar-table">
<table class="csv-table">
<thead>
<tr>
<th
data-field="date"
data-format="date">
{{_('Date')}}
</th>
<th
data-field="statuses|userEnabled"
data-format="number">
{{_('Enabled')}}
</th>
<th
data-field="statuses|userDisabled"
data-format="number">
{{_('Disabled')}}
</th>
<th
data-field="userEnabled,incompatible"
data-format="number">
{{_('Enabled (incompatible)')}}
</th>
<th
data-field="userDisabled,incompatible"
data-format="number">
{{_('Disabled (incompatible)')}}
</th>
</tr>
</thead>
</table>
</div>
</div>
{% endblock %}
{% block chartconfig %}
<script>
AMO.seriesList = {
metric: "statuses",
fields: [
"statuses|userEnabled",
"statuses|userDisabled",
"statuses|userEnabled,incompatible"
]
};
AMO.csvTableConfig = {
el: $("table.bar-table")[0],
report: "{{ report }}",
columns: [{
label: "{{_('Date')}}",
field: 'date',
format: function (value) {
return Highcharts.dateFormat('%a, %b %e, %Y', new Date(value));
}
},
{
label: "{{_('Enabled')}}",
field: 'statuses|userEnabled',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "{{_('Disabled')}}",
field: 'statuses|userDisabled',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "{{_('Enabled (Incompatible)')}}",
field: 'statuses|userEnabled,incompatible',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "{{_('Disabled (Incompatible)')}}",
field: 'statuses|userDisabled,incompatible',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
}
]
};
</script>
{% endblock %}

Просмотреть файл

@ -1,24 +1,28 @@
{% extends "stats/stats.html" %}
{% block chart_config %}
data-series="count"
{% endblock %}
{% block stats %}
<div class="featured">
<div class="featured-inner">
<div class="featured-body tabular">
<table class="stats-overview"><thead>
<table class="stats-aggregate" data-field="count"><thead>
<tr><th>{{_('Category')}}</th><th>Last 7 Days</th><th>7-14 Days Ago</th><th>{{_('All Time')}}</th></tr>
</thead>
<tbody>
<tr>
<td class="label">{{_('Average Daily Users')}}</td>
<td class="value"><span class="value" id="sum_range"></span><span class="change" id="sum_diff"></span></td>
<td class="value"><span class="value" id="sum_prev_range"></span><span class="change" id="sum_prev_diff"></span></td>
<td class="value"><span class="value" id="sum_all_time"></span><span class="change">&nbsp;</span></td>
<td class="value"><span class="value aggregate" id="mean_range"></span><span class="change" id="mean_diff"></span></td>
<td class="value"><span class="value aggregate" id="mean_prev_range"></span><span class="change" id="mean_prev_diff"></span></td>
<td class="value"><span class="value aggregate" id="mean_all_time">{{ addon.average_daily_users|numberfmt }}</span><span class="change">&nbsp;</span></td>
</tr>
<tr>
<td class="label">{{_('Max. Daily Users')}}</td>
<td class="value"><span class="value" id="mean_range"></span><span class="change" id="mean_diff"></span></td>
<td class="value"><span class="value" id="mean_prev_range"></span><span class="change" id="mean_prev_diff"></span></td>
<td class="value"><span class="value" id="mean_all_time"></span><span class="change">&nbsp;</span></td>
<td class="value"><span class="value aggregate" id="max_range"></span><span class="change" id="max_diff"></span></td>
<td class="value"><span class="value aggregate" id="max_prev_range"></span><span class="change" id="max_prev_diff"></span></td>
<td class="value"><span class="value aggregate" id="max_all_time"></span><span class="change">&nbsp;</span></td>
</tr>
</tbody></table>
</div>
@ -30,41 +34,24 @@
<h3>{{_('Daily Users by Date')}}</h3>
<div class="statbox">
<div class="tabular">
<table class="bar-table">
<table class="csv-table">
<thead>
<tr>
<th
data-field="date"
data-format="date">
{{_('Date')}}
</th>
<th
data-field="count"
data-format="number"
data-bar_column="true"
data-bar_width="65%">
{{_('Count')}}
</th>
</tr>
</thead>
</table>
</div>
</div>
{% endblock %}
{% block chartconfig %}
<script>
AMO.csvTableConfig = {
el: $("table.bar-table")[0],
report: "{{ report }}",
columns: [{
label: "{{_('Date')}}",
field: 'date',
format: function (value) {
return Highcharts.dateFormat('%a, %b %e, %Y', new Date(value));
}
},
{
label: "{{_('Count')}}",
field: 'count',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
}],
barColumns: [{
valueColumn: 2,
barColor: '#26a2ce',
className: 'bar',
width: "65%"
}]
};
AMO.aggregate_stats_field = {
metric: "usage",
name: "count"
};
</script>
{% endblock %}

Просмотреть файл

@ -1,57 +1,38 @@
{% extends "stats/stats.html" %}
{% block stats %}
{% block chart_config %}
data-series="versions|1.2,versions|1.1,versions|1.0"
{% endblock %}
{% block csvtable %}
<div class="statbox">
<div class="tabular">
<table class="bar-table">
<table class="csv-table">
<thead>
<tr>
<th
data-field="date"
data-format="date">
{{_('Date')}}
</th>
<th
data-field="versions|1.2"
data-format="number">
{{_('1.2')}}
</th>
<th
data-field="versions|1.1"
data-format="number">
{{_('1.1')}}
</th>
<th
data-field="versions|1.0"
data-format="number">
{{_('1.0')}}
</th>
</tr>
</thead>
</table>
</div>
</div>
{% endblock %}
{% block chartconfig %}
<script>
AMO.seriesList = {
metric: "versions",
fields: [
"versions|1.2",
"versions|1.1",
"versions|1.0"
]
};
AMO.csvTableConfig = {
el: $("table.bar-table")[0],
report: "{{ report }}",
columns: [{
label: "{{_('Date')}}",
field: 'date',
format: function (value) {
return Highcharts.dateFormat('%a, %b %e, %Y', new Date(value));
}
},
{
label: "1.2",
field: 'versions|1.2',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "1.1",
field: 'versions|1.1',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
},
{
label: "1.0",
field: 'versions|1.0',
format: function (value) {
return Highcharts.numberFormat(value, 0);
}
}
]
};
</script>
{% endblock %}
{% endblock %}3

Просмотреть файл

@ -32,8 +32,7 @@ urlpatterns = patterns('',
url('^contributions/$', views.stats_report, name='stats.contributions',
kwargs={'report': 'contributions'}),
# url('^downloads/sources/$', views.download, name='stats.download_sources'),
# url('^usage/$', views.download, name='stats.usage'),
# time series URLs following this pattern:
# /addon/{addon_id}/statistics/{series}-{group}-{start}-{end}.{format}
@ -56,7 +55,9 @@ urlpatterns = patterns('',
url(series['apps'], views.usage_breakdown_series,
name='stats.apps_series', kwargs={'field': 'applications'}),
# special case time series
url('^contributions-detail-%s\.%s$' % (range_re, format_re),
views.contributions_detail, name='stats.contributions_detail'),
)

Просмотреть файл

@ -13,6 +13,7 @@ import jingo
from access import acl
from addons.models import Addon
from amo.urlresolvers import reverse
from amo.helpers import locale_url
from .db import DayAvg, Avg
@ -144,7 +145,7 @@ def usage_breakdown_series(request, addon_id, group,
qs = UpdateCount.stats.filter(addon=addon_id,
date__range=(start_date, end_date))
gen = qs.period_summary(group, **dict(fields))
if format == 'csv':
gen, headings = csv_dynamic_prep(gen, qs, fields,
'count', field)
@ -181,7 +182,7 @@ def check_stats_permission(request, addon, for_contributions=False):
def stats_report(request, addon_id, report):
addon = get_object_or_404(Addon.objects.valid(), id=addon_id)
stats_base_url = locale_url('/addon/%d/statistics' % (addon.id))
stats_base_url = reverse('stats.overview', args=[addon.id]);
return jingo.render(request, 'stats/%s.html' % report,
{'addon': addon,
'report': report,

Просмотреть файл

@ -1,16 +1,28 @@
$(document).ready(function () {
var csvTable;
jQuery.fn.getData = function(name) {
return this.attr("data-" + name);
};
var addon_id = $(".primary").getData("addon_id");
var reportName = $(".primary").getData("report");
AMO.getAddonId = function () { return addon_id };
AMO.getReportName = function () { return reportName };
page_state.addon_id = $(".primary").getData("addon_id");
page_state.report_name = $(".primary").getData("report");
page_state.data_range = "30 days";
page_state.chart_fields = $("#head-chart").getData("series").split(',') || ["count"];
var stats_base_url = $(".primary").getData("base_url");
AMO.aggregate_stats_field = $(".stats-aggregate").getData("field");
AMO.getAddonId = function () { return page_state.addon_id };
AMO.getReportName = function () { return page_state.report_name };
AMO.getSeriesList = function () {
return AMO.seriesList || {"metric" : reportName, fields : ["count"]};
return {
"metric": page_state.report_name,
"fields": page_state.chart_fields
}
};
AMO.getStatsBaseURL = function () { return stats_base_url };
t.go();
@ -39,8 +51,13 @@ $(document).ready(function () {
if (newRange == "custom") {
$customRangeForm.removeClass("hidden").slideDown('fast');
} else {
page_state.data_range = newRange;
$customRangeForm.slideUp('fast');
AMO.StatsManager.getSeries(AMO.getSeriesList(), newRange, updateSeries);
AMO.StatsManager.getSeries(AMO.getSeriesList(), page_state.data_range, updateSeries);
if (AMO.aggregate_stats_field) {
show_aggregate_stats(AMO.aggregate_stats_field, page_state.data_range);
}
}
}
e.preventDefault();
@ -50,24 +67,53 @@ $(document).ready(function () {
var start = new Date($("#date-range-start").val());
var end = new Date($("#date-range-end").val());
range = {
page_state.data_range = {
custom: true,
start: start,
end: end
};
generateSeries(report, range, updateSeries);
generateSeries(report, page_state.data_range, updateSeries);
});
t.lap("events init");
var csv_table_el = $(".csv-table");
if (csv_table_el.length) {
csvTable = new PageTable(csv_table_el[0]);
}
if (report == "overview") {
page_state.report_name = 'downloads';
var series_menu = $("#series-select");
t.lap("csvtable init");
series_menu.click(function(e) {
var $target = $(e.target);
var new_report = $target.getData("report");
var new_series = $target.getData("series");
if (new_series && new_report != AMO.getReportName()) {
series_menu.children("li.selected").removeClass("selected");
$target.parent().addClass("selected");
page_state.report_name = new_report;
page_state.data_fields = new_series;
AMO.StatsManager.getSeries(AMO.getSeriesList(), page_state.data_range, initCharts);
}
e.preventDefault();
});
// generate_top_charts();
initTopCharts();
} else {
var csv_table_el = $(".csv-table");
if (csv_table_el.length) {
csvTable = new PageTable(csv_table_el[0]);
}
t.lap("csvtable init");
}
LoadBar.on("Loading the latest data&hellip;");
//Get initial dataset
@ -76,16 +122,21 @@ $(document).ready(function () {
} else {
var fetchStart = ago("30 days");
}
AMO.StatsManager._fetchData(report, fetchStart, today(), function () {
t.go("fetching data")
AMO.StatsManager.getDataRange(AMO.getReportName(), fetchStart, today(), function () {
t.lap("building aggregate stats")
if (AMO.aggregate_stats_field) {
show_aggregate_stats(AMO.aggregate_stats_field, 30);
show_aggregate_stats(AMO.aggregate_stats_field, page_state.data_range);
}
t.lap("building initial chart stuff")
AMO.StatsManager.getSeries(AMO.getSeriesList(), "30 days", initCharts);
LoadBar.off();
csvTable.gotoPage(1);
});
//initTopCharts();
if (csvTable) {
csvTable.gotoPage(1);
}
}, {force: true});
});
@ -123,14 +174,17 @@ $(document).ready(function () {
var t = new Timer();
function dbg() {
if(window.console && console.log) {
console.log(Array.prototype.slice.apply(arguments));
if(window.console && window.console.log) {
window.console.log(Array.prototype.slice.apply(arguments));
}
}
function updateSeries(cfg) {
for (var i=0; i<cfg.length; i++) {
mainChart.get(cfg[i].id).setData(cfg[i].data);
var series = mainChart.get(cfg[i].id);
if (series) {
series.setData(cfg[i].data);
}
}
}
@ -149,7 +203,9 @@ $(document).ready(function () {
function initCharts(cfg) {
t.lap("pre-charts");
if (mainChart) {
mainChart.destroy();
}
mainChart = new Highcharts.Chart({
chart: {
renderTo: 'head-chart',
@ -205,7 +261,6 @@ $(document).ready(function () {
series: cfg
});
t.lap("charts init");
}
@ -285,10 +340,17 @@ function initTopCharts() {
});
}
function show_aggregate_stats (field, size) {
AMO.StatsManager.getSum(field, ago((size * 3) + ' days'), ago((size * 2 - 1) + ' days'), function(sum_3x_range) {
AMO.StatsManager.getSum(field, ago((size * 2) + ' days'), ago((size - 1) + ' days'), function(sum_prev_range) {
AMO.StatsManager.getSum(field, ago(size + ' days'), today(), function(sum_range) {
function show_aggregate_stats (_field, range) {
field = {
metric: AMO.getReportName(),
name: _field
}
$(".stats-aggregate .range").text("Last " + range);
$(".stats-aggregate .prev_range").text("Prior " + range);
AMO.StatsManager.getSum(field, ago(range, 3), ago(range, 2) + millis("1 day"), function(sum_3x_range) {
AMO.StatsManager.getSum(field, ago(range, 2), ago(range) + millis("1 day"), function(sum_prev_range) {
AMO.StatsManager.getSum(field, ago(range), today(), function(sum_range) {
$("#sum_range").text(Highcharts.numberFormat(sum_range, 0));
$("#sum_prev_range").text(Highcharts.numberFormat(sum_prev_range, 0));
@ -297,9 +359,9 @@ function show_aggregate_stats (field, size) {
draw_diff($("#sum_prev_diff"), sum_prev_range, sum_3x_range);
AMO.StatsManager.getMean(field, ago((size * 3) + ' days'), ago((size * 2 - 1) + ' days'), function(mean_3x_range) {
AMO.StatsManager.getMean(field, ago((size * 2) + ' days'), ago((size - 1) + ' days'), function(mean_prev_range) {
AMO.StatsManager.getMean(field, ago(size + ' days'), today(), function(mean_range) {
AMO.StatsManager.getMean(field, ago(range, 3), ago(range, 2) + millis("1 day"), function(mean_3x_range) {
AMO.StatsManager.getMean(field, ago(range, 2), ago(range) + millis("1 day"), function(mean_prev_range) {
AMO.StatsManager.getMean(field, ago(range), today(), function(mean_range) {
$("#mean_range").text(Highcharts.numberFormat(mean_range, 0));
$("#mean_prev_range").text(Highcharts.numberFormat(mean_prev_range, 0));
@ -314,5 +376,4 @@ function show_aggregate_stats (field, size) {
});
});
}
}

Просмотреть файл

@ -1,7 +1,7 @@
// (function () {
// Versioning for offline storage
var version = "1";
var version = "2";
// where all the time-series data for the page is kept
var datastore = {};
@ -13,8 +13,17 @@
maxdate: today()
};
var writeInterval = false;
var page_state = {
}
var capabilities = {
localStorage : ('localStorage' in window) && window['localStorage'] !== null,
JSON : window.JSON && typeof JSON.parse == 'function'
};
var writeInterval = false;
LoadBar = {
bar : $("#lm"),
msg : $("#lm span"),
@ -29,14 +38,14 @@
LoadBar.bar.removeClass("on");
}
};
// date management helpers
var _millis = {
"day" : 1000 * 60 * 60 * 24,
"week" : 1000 * 60 * 60 * 24 * 7
};
function millis(str) {
var tokens = str.split(/\s+/);
n = parseInt(tokens[0]);
@ -54,65 +63,74 @@
return Date.parse([d.getFullYear(), pad2(d.getMonth()+1), pad2(d.getDate()+1)].join('-'));
}
function ago (str) {
return today() - millis(str);
function ago (str, times) {
times = (times !== undefined) ? times : 1;
return today() - millis(str) * times;
}
function chunkfor(start, end, step, chunk_size, inner, callback, ctx) {
var position = start;
/* cfg takes:
* start: the initial value
* end: the (non-inclusive) max value
* step: value to iterate by
* chunk-size: how many iterations before setTimeout
* inner: function to perform each iteration
* callback: function to perform when finished
* ctx: context from which to run all functions
*/
function chunkfor(cfg) {
var position = cfg.start;
function nextchunk() {
if (position < end) {
if (position < cfg.end) {
for (var iterator = position;
iterator < position+(chunk_size*step) && iterator < end;
iterator += step) {
inner.call(ctx, iterator);
iterator < position+(cfg.chunk_size*cfg.step) && iterator < cfg.end;
iterator += cfg.step) {
cfg.inner.call(cfg.ctx, iterator);
}
position += chunk_size * step;
position += cfg.chunk_size * cfg.step;
setTimeout( function () {
nextchunk.call(this);
}, 0);
} else {
callback.call(ctx);
cfg.callback.call(cfg.ctx);
}
}
nextchunk();
}
document.onbeforeunload = function () {
AMO.StatsManager.write_local();
}
AMO.StatsManager = {
init: function () {
if (window.globalStorage) {
var host = location.hostname;
var local_store = globalStorage[host];
if (capabilities.localStorage) {
var local_store = localStorage;
dbg("looking for local data");
if (local_store.getItem("statscache") && AMO.StatsManager.verify_local()) {
var cacheObject = local_store.getItem("statscache");
dbg("found local data, loading...");
datastore = JSON.parse(cacheObject);
dbg(datastore);
}
} else {
dbg("no local storage");
}
},
write_local: function () {
dbg("saving local data");
if (window.globalStorage) {
if (capabilities.localStorage) {
dbg("user has local storage");
var host = location.hostname;
var local_store = globalStorage[host];
var local_store = localStorage;
local_store.setItem("statscache", JSON.stringify(datastore));
local_store.setItem("stats_version", version);
dbg("saved local data");
} else {
dbg("no local storage");
@ -120,19 +138,17 @@
},
clear_local: function () {
if (globalStorage) {
var host = location.hostname;
var local_store = globalStorage[host];
if (capabilities.localStorage) {
var local_store = localStorage;
local_store.removeItem("statscache");
dbg("cleared local data");
}
},
verify_local: function () {
if (window.globalStorage) {
var host = location.hostname;
var local_store = globalStorage[host];
if (local_store.getItem("stats_version") == version) {
if (capabilities.localStorage) {
var local_store = localStorage;
if (local_store.getItem("stats_version") === version) {
return true;
} else {
dbg("wrong offline data verion");
@ -141,23 +157,26 @@
}
return false;
},
_fetchData: function (metric, start, end, callback) {
var seriesStart = start;
var seriesEnd = end;
var seriesURLStart = Highcharts.dateFormat('%Y%m%d', seriesStart);
var seriesURLEnd = Highcharts.dateFormat('%Y%m%d', seriesEnd);
var seriesURL = AMO.getStatsBaseURL() + ([metric,"day",seriesURLStart,seriesURLEnd]).join("-") + ".json";
var seriesURLStart = Highcharts.dateFormat('%Y%m%d', seriesStart),
seriesURLEnd = Highcharts.dateFormat('%Y%m%d', seriesEnd),
seriesURL = AMO.getStatsBaseURL() + ([metric,"day",seriesURLStart,seriesURLEnd]).join("-") + ".json";
$.get(seriesURL, function(data, status, xhr) {
$.ajax({ url: seriesURL,
dataType: 'text',
success: function(raw_data, status, xhr) {
var maxdate = 0,
mindate = today();
if (xhr.status == 200) {
if (!datastore[metric]) {
datastore[metric] = {};
datastore[metric].mindate = today();
@ -165,59 +184,75 @@
}
var ds = datastore[metric];
// process the Data. We want to directly use the native JSON
// without jQuery's costly regexes if we can.
if (capabilities.JSON) {
dbg("native JSON");
var data = JSON.parse(raw_data);
} else {
dbg("jQuery JSON");
var data = $.parseJSON(raw_data);
}
chunkfor(0, data.length, 1, 10,
function (i) {
var datekey = Date.parse(data[i].date);
maxdate = Math.max(datekey, ds.maxdate);
mindate = Math.min(datekey, ds.mindate);
chunkfor({
start: 0,
end: data.length,
step: 1,
chunk_size: 10,
inner: function (i) {
var datekey = parseInt(Date.parse(data[i].date));
maxdate = Math.max(datekey, maxdate);
mindate = Math.min(datekey, mindate);
ds[datekey] = data[i];
},
function () {
ds.maxdate = Math.max(maxdate, ds.maxdate);
ds.mindate = Math.min(mindate, ds.mindate);
callback: function () {
ds.maxdate = Math.max(parseInt(maxdate), parseInt(ds.maxdate));
ds.mindate = Math.min(parseInt(mindate), parseInt(ds.mindate));
callback.call(this, true);
clearTimeout(writeInterval);
writeInterval = setTimeout(AMO.StatsManager.write_local, 2000);
}, this
);
},
ctx: this
});
} else if (xhr.status == 202) {
var retry_delay = 30000;
if (xhr.getResponseHeader("Retry-After")) {
retry_delay = parseInt(xhr.getResponseHeader("Retry-After")) * 1000;
}
setTimeout(function () {
AMO.StatsManager._fetchData(metric, start, end, callback);
}, retry_delay);
}
});
}});
},
/*
* getDataRange: ensures we have all the data from the server we need,
* and queues up requests to the server if the requested data is outside
* the range currently stored locally. Once all server requests return,
* we move on.
*/
getDataRange: function (metric, start, end, callback, quiet) {
var needed = 0;
getDataRange: function (metric, start, end, callback, opts) {
var needed = 0,
opts = opts || {};
quiet = opts.quiet || false,
force = opts.force || false;
end = Math.min(end, range_limits.maxdate);
function finished() {
needed--;
if (datastore[metric].maxdate < end) {
if (datastore[metric] && datastore[metric].maxdate < end) {
dbg("truncating fetchable range");
range_limits.maxdate = datastore[metric].maxdate;
}
@ -228,8 +263,8 @@
if (!quiet) LoadBar.on("Loading&hellip;");
}
}
if (datastore[metric]) {
if (datastore[metric] && !force) {
ds = datastore[metric];
if (ds.maxdate < end) {
needed++;
@ -243,10 +278,10 @@
needed++;
AMO.StatsManager._fetchData(metric, start, end, finished);
}
finished();
},
getSeries: function (seriesList, time, callback) {
metric = seriesList.metric;
if (typeof time == "string") {
@ -270,30 +305,31 @@
} else {
AMO.StatsManager.getDataRange(metric, seriesStart, seriesEnd, function() {
var out = {};
var fields = seriesList.fields;
var data = datastore[metric];
for (var j=0; j<fields.length; j++) {
out[fields[j]] = [];
}
chunkfor(seriesStart, seriesEnd, millis("1 day"), 10,
function (i) {
chunkfor({
start: seriesStart,
end: seriesEnd,
step: millis("1 day"),
chunk_size: 10,
inner: function (i) {
for (var j=0; j<fields.length; j++) {
var val = data[i] ? AMO.StatsManager.getField(data[i], fields[j]) : null;
var point = {
x : i,
y : data[i] ? parseFloat(AMO.StatsManager.getField(data[i], fields[j])) : null
y : val ? parseFloat(val) : null
};
out[fields[j]].push(point);
}
},
function () {
callback: function () {
var ret = [];
for (var j=0; j<fields.length; j++) {
ret.push({
type: 'line',
@ -301,34 +337,27 @@
data: out[fields[j]]
});
}
seriesCache[cacheKey] = ret;
callback.call(this, ret);
}
);
},
ctx: this
});
});
}
},
getPage: function(metric, num, callback, size) {
size = size || 14;
var cacheKey = metric + "_page_" + num + "_by_" + size;
if (seriesCache[cacheKey]) {
if (!seriesCache[cacheKey].nodata) {
callback.call(this, seriesCache[cacheKey]);
}
} else {
var ds = datastore[metric];
var seriesEnd = ds.maxdate - size * (num - 1) * millis("1 day");
@ -337,15 +366,15 @@
var dataStart = seriesStart - size * millis("1 day");
AMO.StatsManager.getDataRange(metric, dataStart, seriesEnd, function() {
var ret = [];
ret.page = num;
for (var i=seriesEnd; i>seriesStart; i-= millis("1 day")) {
if (ds[i] !== undefined) ret.push(ds[i]);
}
if (ret.length) {
seriesCache[cacheKey] = ret;
@ -353,35 +382,35 @@
} else {
seriesCache[cacheKey] = {nodata:true};
}
});
}
},
getNumPages: function(metric, size) {
size = size || 14;
var ds = datastore[metric];
return Math.ceil((ds.maxdate - ds.mindate) / millis("1 day") / size);
},
getSum: function(field, start, end, callback, name) {
var metric = field.metric;
var cacheKey = name || (metric + field.name + "_sum_" + start + "_" + end);
if (seriesCache[cacheKey]) {
callback.call(this, seriesCache[cacheKey]);
} else {
AMO.StatsManager.getDataRange(metric, start, end, function () {
var ds = datastore[metric];
var sum = 0;
var nodata = true;
for (var i=start; i<end; i+= millis("1 day")) {
if (ds[i] !== undefined) {
var datum = AMO.StatsManager.getField(ds[i], field.name);
@ -391,24 +420,24 @@
}
}
}
if (nodata) {
var ret = {nodata: true};
} else {
var ret = sum;
}
seriesCache[cacheKey] = ret;
callback.call(this, ret);
});
}
},
getMean: function(field, start, end, callback) {
var metric = field.metric;
AMO.StatsManager.getSum(field, start, end, function (sum) {
if (sum.nodata) {
callback.call(this, sum);
@ -417,26 +446,29 @@
callback.call(this, mean);
}
});
},
getStat: function(name) {
return seriesCache[name] || {nodata: true};
},
getField: function(record, field) {
var parts = field.split('|');
var val = record;
for (var i=0; i<parts.length; i++) {
val = val[parts[i]];
if (!val) {
return null;
}
}
return val;
}
};
// })();

Просмотреть файл

@ -73,8 +73,6 @@ function PageTable(_el) {
//Set up a BarTable if needed
dbg(barColumns);
if (barColumns.length) {
this.barTable = new BarTable({
el: this.tableEl,
@ -149,8 +147,6 @@ PageTable.prototype.addPage = function (data) {
t.lap('done page');
console.log(page.html());
this.pages[data.page] = page;
this.tableEl.append(page);
if (this.barTable) {

Просмотреть файл

@ -38,9 +38,6 @@ urlpatterns = patterns('',
# Search
('^search/', include('search.urls')),
# Stats
('^stats/', include('stats.urls')),
# Global stats dashboard.
url('^statistics/', lambda r: redirect('/'), name='statistics.dashboard'),