Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

global stats dashboard (bug 697358)

  • Loading branch information...
commit 333b68f360d8d1b78324395afb783cebdc4ea2f8 1 parent f9e2c5f
Potch potch authored

Showing 24 changed files with 228 additions and 27 deletions. Show diff stats Hide diff stats

  1. +1 0  apps/stats/templates/stats/dashboard.html
  2. +36 0 apps/stats/templates/stats/global_report_menu.html
  3. +5 0 apps/stats/templates/stats/reports/addons_created.html
  4. +5 0 apps/stats/templates/stats/reports/addons_downloaded.html
  5. +5 0 apps/stats/templates/stats/reports/addons_downloads.html
  6. +5 0 apps/stats/templates/stats/reports/addons_in_use.html
  7. +5 0 apps/stats/templates/stats/reports/addons_updated.html
  8. 0  apps/stats/templates/stats/{ → reports}/apps.html
  9. +5 0 apps/stats/templates/stats/reports/collections_created.html
  10. 0  apps/stats/templates/stats/{ → reports}/downloads.html
  11. 0  apps/stats/templates/stats/{ → reports}/locales.html
  12. 0  apps/stats/templates/stats/{ → reports}/os.html
  13. 0  apps/stats/templates/stats/{ → reports}/overview.html
  14. +5 0 apps/stats/templates/stats/reports/reviews_created.html
  15. 0  apps/stats/templates/stats/{ → reports}/sources.html
  16. 0  apps/stats/templates/stats/{ → reports}/statuses.html
  17. 0  apps/stats/templates/stats/{ → reports}/usage.html
  18. +5 0 apps/stats/templates/stats/reports/users_created.html
  19. 0  apps/stats/templates/stats/{ → reports}/versions.html
  20. +34 2 apps/stats/urls.py
  21. +45 15 apps/stats/views.py
  22. +28 9 media/js/impala/stats/chart.js
  23. +42 0 media/js/impala/stats/csv_keys.js
  24. +2 1  media/js/impala/stats/stats.js
1  apps/stats/templates/stats/dashboard.html
... ... @@ -0,0 +1 @@
  1 +{% extends "stats/stats.html" %}
36 apps/stats/templates/stats/global_report_menu.html
... ... @@ -0,0 +1,36 @@
  1 +<nav id="side-nav">
  2 + <ul>
  3 + <li>
  4 + <a href="{{ url('stats.dashboard') }}">
  5 + {{ _('Dashboard') }}</a>
  6 + </li>
  7 + <li>
  8 + <a href="{{ url('stats.addons_in_use') }}">
  9 + {{ _('Add-ons in Use') }}</a>
  10 + </li>
  11 + <li>
  12 + <a href="{{ url('stats.addons_created') }}">
  13 + {{ _('Add-ons Created') }}</a>
  14 + </li>
  15 + <li>
  16 + <a href="{{ url('stats.addons_downloaded') }}">
  17 + {{ _('Add-ons Downloaded') }}</a>
  18 + </li>
  19 + <li>
  20 + <a href="{{ url('stats.addons_updated') }}">
  21 + {{ _('Add-ons Updated') }}</a>
  22 + </li>
  23 + <li>
  24 + <a href="{{ url('stats.collections_created') }}">
  25 + {{ _('Collections Created') }}</a>
  26 + </li>
  27 + <li>
  28 + <a href="{{ url('stats.reviews_created') }}">
  29 + {{ _('Reviews Written') }}</a>
  30 + </li>
  31 + <li>
  32 + <a href="{{ url('stats.users_created') }}">
  33 + {{ _('User Signups') }}</a>
  34 + </li>
  35 + </ul>
  36 +</nav>
5 apps/stats/templates/stats/reports/addons_created.html
... ... @@ -0,0 +1,5 @@
  1 +{% extends "stats/stats.html" %}
  2 +
  3 +{% block csvtitle %}
  4 +<h2>{{_('Add-ons Created by Date')}}<a id="export_data" href=''>{{_('Export as CSV')}}</a></h2>
  5 +{% endblock %}
5 apps/stats/templates/stats/reports/addons_downloaded.html
... ... @@ -0,0 +1,5 @@
  1 +{% extends "stats/stats.html" %}
  2 +
  3 +{% block csvtitle %}
  4 +<h2>{{_('Add-ons Downloaded by Date')}}<a id="export_data" href=''>{{_('Export as CSV')}}</a></h2>
  5 +{% endblock %}
5 apps/stats/templates/stats/reports/addons_downloads.html
... ... @@ -0,0 +1,5 @@
  1 +{% extends "stats/stats.html" %}
  2 +
  3 +{% block csvtitle %}
  4 +<h2>{{_('Add-ons in Use by Date')}}<a id="export_data" href=''>{{_('Export as CSV')}}</a></h2>
  5 +{% endblock %}
5 apps/stats/templates/stats/reports/addons_in_use.html
... ... @@ -0,0 +1,5 @@
  1 +{% extends "stats/stats.html" %}
  2 +
  3 +{% block csvtitle %}
  4 +<h2>{{_('Add-ons in Use by Date')}}<a id="export_data" href=''>{{_('Export as CSV')}}</a></h2>
  5 +{% endblock %}
5 apps/stats/templates/stats/reports/addons_updated.html
... ... @@ -0,0 +1,5 @@
  1 +{% extends "stats/stats.html" %}
  2 +
  3 +{% block csvtitle %}
  4 +<h2>{{_('Add-ons Updated by Date')}}<a id="export_data" href=''>{{_('Export as CSV')}}</a></h2>
  5 +{% endblock %}
0  apps/stats/templates/stats/apps.html → apps/stats/templates/stats/reports/apps.html
File renamed without changes
5 apps/stats/templates/stats/reports/collections_created.html
... ... @@ -0,0 +1,5 @@
  1 +{% extends "stats/stats.html" %}
  2 +
  3 +{% block csvtitle %}
  4 +<h2>{{_('Collections Created by Date')}}<a id="export_data" href=''>{{_('Export as CSV')}}</a></h2>
  5 +{% endblock %}
0  apps/stats/templates/stats/downloads.html → apps/stats/templates/stats/reports/downloads.html
File renamed without changes
0  apps/stats/templates/stats/locales.html → apps/stats/templates/stats/reports/locales.html
File renamed without changes
0  apps/stats/templates/stats/os.html → apps/stats/templates/stats/reports/os.html
File renamed without changes
0  apps/stats/templates/stats/overview.html → apps/stats/templates/stats/reports/overview.html
File renamed without changes
5 apps/stats/templates/stats/reports/reviews_created.html
... ... @@ -0,0 +1,5 @@
  1 +{% extends "stats/stats.html" %}
  2 +
  3 +{% block csvtitle %}
  4 +<h2>{{_('Reviews Created by Date')}}<a id="export_data" href=''>{{_('Export as CSV')}}</a></h2>
  5 +{% endblock %}
0  apps/stats/templates/stats/sources.html → apps/stats/templates/stats/reports/sources.html
File renamed without changes
0  apps/stats/templates/stats/statuses.html → apps/stats/templates/stats/reports/statuses.html
File renamed without changes
0  apps/stats/templates/stats/usage.html → apps/stats/templates/stats/reports/usage.html
File renamed without changes
5 apps/stats/templates/stats/reports/users_created.html
... ... @@ -0,0 +1,5 @@
  1 +{% extends "stats/stats.html" %}
  2 +
  3 +{% block csvtitle %}
  4 +<h2>{{_('User Signups by Date')}}<a id="export_data" href=''>{{_('Export as CSV')}}</a></h2>
  5 +{% endblock %}
0  apps/stats/templates/stats/versions.html → apps/stats/templates/stats/reports/versions.html
File renamed without changes
36 apps/stats/urls.py
@@ -10,13 +10,45 @@
10 10 series = dict((type, '%s-%s' % (type, series_re)) for type in views.SERIES)
11 11
12 12 urlpatterns = patterns('',
13   - # url('^$', views.dashboard, name='stats.dashboard'),
  13 + url('^$', views.dashboard, name='stats.dashboard'),
14 14 url('^site%s/%s$' % (format_re, group_date_re),
15 15 views.site, name='stats.site'),
16 16 url('^site-%s' % series_re, views.site, name='stats.site.new'),
17 17 url('^fake-%s' % series_re, views.fake_collection_stats),
18 18 url('^collection/(?P<uuid>[\w-]+).%s$' % (format_re),
19   - views.collection, name='stats.collection')
  19 + views.collection, name='stats.collection'),
  20 +
  21 + # global series urls.
  22 + url(series['addons_in_use'], views.site_series,
  23 + kwargs={'field': 'addons_in_use'}),
  24 + url(series['addons_updated'], views.site_series,
  25 + kwargs={'field': 'addons_updated'}),
  26 + url(series['addons_downloaded'], views.site_series,
  27 + kwargs={'field': 'addons_downloaded'}),
  28 + url(series['addons_created'], views.site_series,
  29 + kwargs={'field': 'addons_created'}),
  30 + url(series['reviews_created'], views.site_series,
  31 + kwargs={'field': 'reviews_created'}),
  32 + url(series['collections_created'], views.site_series,
  33 + kwargs={'field': 'collections_created'}),
  34 + url(series['users_created'], views.site_series,
  35 + kwargs={'field': 'users_created'}),
  36 +
  37 + # global series urls.
  38 + url('^addons_in_use/$', views.site_stats_report,
  39 + kwargs={'report': 'addons_in_use'}, name='stats.addons_in_use'),
  40 + url('^addons_updated/$', views.site_stats_report,
  41 + kwargs={'report': 'addons_updated'}, name='stats.addons_updated'),
  42 + url('^addons_downloaded/$', views.site_stats_report,
  43 + kwargs={'report': 'addons_downloaded'}, name='stats.addons_downloaded'),
  44 + url('^addons_created/$', views.site_stats_report,
  45 + kwargs={'report': 'addons_created'}, name='stats.addons_created'),
  46 + url('^reviews_created/$', views.site_stats_report,
  47 + kwargs={'report': 'reviews_created'}, name='stats.reviews_created'),
  48 + url('^collections_created/$', views.site_stats_report,
  49 + kwargs={'report': 'collections_created'}, name='stats.collections_created'),
  50 + url('^users_created/$', views.site_stats_report,
  51 + kwargs={'report': 'users_created'}, name='stats.users_created'),
20 52 )
21 53
22 54 # Addon specific stats.
60 apps/stats/views.py
@@ -35,8 +35,20 @@
35 35 SERIES_GROUPS = ('day', 'week', 'month')
36 36 SERIES_GROUPS_DATE = ('date', 'week', 'month') # Backwards compat.
37 37 SERIES_FORMATS = ('json', 'csv')
38   -SERIES = ('downloads', 'usage', 'contributions', 'overview',
39   - 'sources', 'os', 'locales', 'statuses', 'versions', 'apps')
  38 +SERIES = ('downloads', 'usage', 'contributions', 'overview', 'global',
  39 + 'sources', 'os', 'locales', 'statuses', 'versions', 'apps',
  40 + 'addons_in_use', 'addons_updated', 'addons_downloaded',
  41 + 'collections_created', 'reviews_created', 'addons_created',
  42 + 'users_created')
  43 +
  44 +
  45 +def dashboard(request):
  46 + stats_base_url = reverse('stats.dashboard')
  47 + view = get_report_view(request)
  48 + return jingo.render(request, 'stats/dashboard.html',
  49 + {'report': 'site',
  50 + 'view': view,
  51 + 'stats_base_url': stats_base_url})
40 52
41 53
42 54 def get_series(model, extra_field=None, **filters):
@@ -279,11 +291,20 @@ def stats_report(request, addon, report):
279 291 for_contributions=(report == 'contributions'))
280 292 stats_base_url = reverse('stats.overview', args=[addon.slug])
281 293 view = get_report_view(request)
282   - return jingo.render(request, 'stats/%s.html' % report,
  294 + return jingo.render(request, 'stats/reports/%s.html' % report,
283 295 {'addon': addon,
284   - 'report': report,
285   - 'view': view,
286   - 'stats_base_url': stats_base_url})
  296 + 'report': report,
  297 + 'view': view,
  298 + 'stats_base_url': stats_base_url})
  299 +
  300 +
  301 +def site_stats_report(request, report):
  302 + stats_base_url = reverse('stats.dashboard')
  303 + view = get_report_view(request)
  304 + return jingo.render(request, 'stats/reports/%s.html' % report,
  305 + {'report': report, 'view': view,
  306 + 'stats_base_url': stats_base_url})
  307 +
287 308
288 309
289 310 def get_report_view(request):
@@ -449,7 +470,7 @@ def _site_query(period, start, end):
449 470 assert period in SERIES_GROUPS_DATE, '%s period is not valid.'
450 471 sql = ("SELECT name, MIN(date), SUM(count) "
451 472 "FROM global_stats "
452   - "WHERE date > %%s AND date < %%s "
  473 + "WHERE date >= %%s AND date <= %%s "
453 474 "AND name IN (%s) "
454 475 "GROUP BY %s(date), name "
455 476 "ORDER BY %s(date) DESC;"
@@ -464,7 +485,8 @@ def _site_query(period, start, end):
464 485 if date not in result:
465 486 result[date] = default.copy()
466 487 result[date]['date'] = date
467   - result[date][keys[name]] = count
  488 + result[date]['data'] = {}
  489 + result[date]['data'][keys[name]] = count
468 490
469 491 return result.values(), sorted(keys.values())
470 492
@@ -487,13 +509,21 @@ def site(request, format, group, start=None, end=None):
487 509 return render_json(request, None, series)
488 510
489 511
490   -def collection_stats(request, username, slug):
491   - c = {'name': 'Sample Collection'}
492   - view = get_report_view(request)
493   - return jingo.render(request, 'stats/collections.html',
494   - {'collection': c,
495   - 'view': view,
496   - })
  512 +def site_series(request, format, group, start, end, field):
  513 + """Pull a single field from the site_query data"""
  514 + start, end = get_daterange_or_404(start, end)
  515 + group = 'date' if group == 'day' else group
  516 + print format, group, start, end, field
  517 + series = []
  518 + full_series, keys = _site_query(group, start, end)
  519 + for row in full_series:
  520 + if field in row['data']:
  521 + series.append({
  522 + 'date': row['date'],
  523 + 'count': row['data'][field],
  524 + })
  525 + print series
  526 + return render_json(request, None, series)
497 527
498 528
499 529 def collection(request, uuid, format):
37 media/js/impala/stats/chart.js
@@ -62,15 +62,22 @@
62 62 var chart;
63 63 // which unit do we use for a given metric?
64 64 var metricTypes = {
65   - "usage" : "users",
66   - "apps" : "users",
67   - "locales" : "users",
68   - "os" : "users",
69   - "versions" : "users",
70   - "statuses" : "users",
71   - "downloads" : "downloads",
72   - "sources" : "downloads",
73   - "contributions" : "currency"
  65 + "usage" : "users",
  66 + "apps" : "users",
  67 + "locales" : "users",
  68 + "os" : "users",
  69 + "versions" : "users",
  70 + "statuses" : "users",
  71 + "users_created" : "users",
  72 + "downloads" : "downloads",
  73 + "sources" : "downloads",
  74 + "contributions" : "currency",
  75 + "reviews_created" : "reviews",
  76 + "addons_in_use" : "addons",
  77 + "addons_created" : "addons",
  78 + "addons_updated" : "addons",
  79 + "addons_downloaded" : "addons",
  80 + "colletions_created" : "collections"
74 81 };
75 82
76 83 var acceptedGroups = {
@@ -159,6 +166,9 @@
159 166 function monthFormatter(d) { return Highcharts.dateFormat('%B %Y', new Date(d)); }
160 167 function downloadFormatter(n) { return Highcharts.numberFormat(n, 0) + ' downloads'; }
161 168 function userFormatter(n) { return Highcharts.numberFormat(n, 0) + ' users'; }
  169 + function addonsFormatter(n) { return Highcharts.numberFormat(n, 0) + ' addons'; }
  170 + function collecitonsFormatter(n) { return Highcharts.numberFormat(n, 0) + ' collections'; }
  171 + function reviewsFormatter(n) { return Highcharts.numberFormat(n, 0) + ' reviews'; }
162 172 function currencyFormatter(n) { return '$' + Highcharts.numberFormat(n, 2); }
163 173 function addEventData(s, date) {
164 174 var e = events[date];
@@ -215,6 +225,15 @@
215 225 case "currency":
216 226 yFormatter = currencyFormatter;
217 227 break;
  228 + case "collections":
  229 + yFormatter = collectionsFormatter;
  230 + break;
  231 + case "reviews":
  232 + yFormatter = reviewsFormatter;
  233 + break;
  234 + case "addons":
  235 + yFormatter = addonsFormatter;
  236 + break;
218 237 }
219 238 return function() {
220 239 var ret = "<b>" + this.series.name + "</b><br>" +
42 media/js/impala/stats/csv_keys.js
@@ -147,6 +147,48 @@ var csv_keys = {
147 147 "fake" : [
148 148 "Fake data last {0} days",
149 149 "Fake data from {0} to {1}"
  150 + ],
  151 + "addons_in_use" : [
  152 + // L10n: {0} is an integer.
  153 + gettext("Add-ons in Use, last {0} days"),
  154 + // L10n: both {0} and {1} are dates in YYYY-MM-DD format.
  155 + gettext("Add-ons in Use from {0} to {1}")
  156 + ],
  157 + "addons_downloaded" : [
  158 + // L10n: {0} is an integer.
  159 + gettext("Add-ons Downloaded, last {0} days"),
  160 + // L10n: both {0} and {1} are dates in YYYY-MM-DD format.
  161 + gettext("Add-ons Downloaded from {0} to {1}")
  162 + ],
  163 + "addons_created" : [
  164 + // L10n: {0} is an integer.
  165 + gettext("Add-ons Created, last {0} days"),
  166 + // L10n: both {0} and {1} are dates in YYYY-MM-DD format.
  167 + gettext("Add-ons Created from {0} to {1}")
  168 + ],
  169 + "addons_updated" : [
  170 + // L10n: {0} is an integer.
  171 + gettext("Add-ons Updated, last {0} days"),
  172 + // L10n: both {0} and {1} are dates in YYYY-MM-DD format.
  173 + gettext("Add-ons Updated from {0} to {1}")
  174 + ],
  175 + "reviews_created" : [
  176 + // L10n: {0} is an integer.
  177 + gettext("Reviews Written, last {0} days"),
  178 + // L10n: both {0} and {1} are dates in YYYY-MM-DD format.
  179 + gettext("Reviews Written from {0} to {1}")
  180 + ],
  181 + "users_created" : [
  182 + // L10n: {0} is an integer.
  183 + gettext("User Signups, last {0} days"),
  184 + // L10n: both {0} and {1} are dates in YYYY-MM-DD format.
  185 + gettext("User Signups from {0} to {1}")
  186 + ],
  187 + "collections_created" : [
  188 + // L10n: {0} is an integer.
  189 + gettext("Collections Created, last {0} days"),
  190 + // L10n: both {0} and {1} are dates in YYYY-MM-DD format.
  191 + gettext("Collections Created from {0} to {1}")
150 192 ]
151 193 },
152 194 aggregateLabel: {
3  media/js/impala/stats/stats.js
@@ -72,9 +72,10 @@
72 72 $exceptionModal.render();
73 73 });
74 74
  75 + $('.csv-table').csvTable();
  76 +
75 77 // Trigger the initial data load.
76 78 $(window).trigger('changeview', initView);
77 79 });
78 80
79   - $('.csv-table').csvTable();
80 81 })();

0 comments on commit 333b68f

Please sign in to comment.
Something went wrong with that request. Please try again.