Added weekly stats
This commit is contained in:
parent
e991a17151
commit
debb3bbee9
5 changed files with 141 additions and 0 deletions
55
counter/static/js/dateformat.js
Normal file
55
counter/static/js/dateformat.js
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
(function(globals) {
|
||||||
|
var replacements = {
|
||||||
|
'd': 'DD',
|
||||||
|
'D': 'ddd',
|
||||||
|
'j': 'D',
|
||||||
|
'l': 'dddd',
|
||||||
|
'N': 'E',
|
||||||
|
'S': 'o',
|
||||||
|
'w': 'e',
|
||||||
|
'z': 'DDD',
|
||||||
|
'W': 'W',
|
||||||
|
'F': 'MMMM',
|
||||||
|
'm': 'MM',
|
||||||
|
'M': 'MMM',
|
||||||
|
'n': 'M',
|
||||||
|
't': '', // no equivalent
|
||||||
|
'L': '', // no equivalent
|
||||||
|
'o': 'YYYY',
|
||||||
|
'Y': 'YYYY',
|
||||||
|
'y': 'YY',
|
||||||
|
'a': 'a',
|
||||||
|
'A': 'A',
|
||||||
|
'B': '', // no equivalent
|
||||||
|
'g': 'h',
|
||||||
|
'G': 'H',
|
||||||
|
'h': 'hh',
|
||||||
|
'H': 'HH',
|
||||||
|
'i': 'mm',
|
||||||
|
's': 'ss',
|
||||||
|
'u': 'SSS',
|
||||||
|
'e': 'zz', // deprecated since version 1.6.0 of moment.js
|
||||||
|
'I': '', // no equivalent
|
||||||
|
'O': '', // no equivalent
|
||||||
|
'P': '', // no equivalent
|
||||||
|
'T': '', // no equivalent
|
||||||
|
'Z': '', // no equivalent
|
||||||
|
'c': '', // no equivalent
|
||||||
|
'r': '', // no equivalent
|
||||||
|
'U': 'X',
|
||||||
|
};
|
||||||
|
|
||||||
|
globals.djangoToMomentFmt = function(djangoFormat) {
|
||||||
|
djangoFormat = djangoFormat.replace(/(\w+)/g, function (f) {
|
||||||
|
return '[' + f + ']';
|
||||||
|
});
|
||||||
|
Object.keys(replacements).forEach(function(key) {
|
||||||
|
djangoFormat = djangoFormat.replace("[" + key + "]", replacements[key])
|
||||||
|
});
|
||||||
|
return djangoFormat;
|
||||||
|
};
|
||||||
|
}(this));
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<li><a href="{% url "count_list" %}">Counts</a></li>
|
<li><a href="{% url "count_list" %}">Counts</a></li>
|
||||||
|
<li><a href="{% url "stats" %}">Weekly stats</a></li>
|
||||||
<li class="divider" tabindex="-1"></li>
|
<li class="divider" tabindex="-1"></li>
|
||||||
{% if user.is_superuser %}
|
{% if user.is_superuser %}
|
||||||
<li><a href="{% url "admin:index" %}">Admin</a></li>
|
<li><a href="{% url "admin:index" %}">Admin</a></li>
|
||||||
|
|
52
counter/templates/stats.html
Normal file
52
counter/templates/stats.html
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block title %}Weekly stats{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<script id="data" type="application/json">
|
||||||
|
{% autoescape off %}{{ weeklyArrows }}{% endautoescape %}
|
||||||
|
</script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
|
||||||
|
<script src="{% static 'js/dateformat.js' %}"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
var data = JSON.parse($('#data').text()),
|
||||||
|
format = djangoToMomentFmt(django.get_format('SHORT_DATE_FORMAT'));
|
||||||
|
console.log(format);
|
||||||
|
var labels = [], dataset = [];
|
||||||
|
data.forEach(function(d) {
|
||||||
|
labels.push(moment(d.weekStarts).format(format) + ' - ' +
|
||||||
|
moment(d.weekEnds).format(format));
|
||||||
|
dataset.push(d.sum_count);
|
||||||
|
});
|
||||||
|
console.log(data);
|
||||||
|
var myChart = new Chart($('#chart'), {
|
||||||
|
type: 'horizontalBar',
|
||||||
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [{
|
||||||
|
label: '# of Arrows',
|
||||||
|
data: dataset,
|
||||||
|
borderWidth: 1
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
scales: {
|
||||||
|
yAxes: [{
|
||||||
|
ticks: {
|
||||||
|
beginAtZero: true
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1 class="center">Weekly stats</h1>
|
||||||
|
<canvas id="chart"></canvas>
|
||||||
|
{% endblock %}
|
|
@ -4,6 +4,7 @@ from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', views.index, name='index'),
|
path('', views.index, name='index'),
|
||||||
|
path('stats', views.count_stats, name='stats'),
|
||||||
path('count/list', views.arrow_count_list, name='count_list'),
|
path('count/list', views.arrow_count_list, name='count_list'),
|
||||||
path('count/new', login_required(views.NewArrowCount.as_view()),
|
path('count/new', login_required(views.NewArrowCount.as_view()),
|
||||||
name='count_new'),
|
name='count_new'),
|
||||||
|
|
|
@ -9,11 +9,43 @@ from django.contrib.auth.decorators import login_required
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import SuspiciousOperation
|
from django.core.exceptions import SuspiciousOperation
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
from django.db.models.functions import Extract, ExtractWeek
|
||||||
|
from django.db.models import Sum
|
||||||
|
from datetime import datetime, timedelta, date
|
||||||
|
import json
|
||||||
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
|
|
||||||
|
# https://stackoverflow.com/questions/5882405
|
||||||
|
def tofirstdayinisoweek(year, week):
|
||||||
|
ret = datetime.strptime('%04d-%02d-1' % (year, week), '%Y-%W-%w')
|
||||||
|
if date(year, 1, 4).isoweekday() > 4:
|
||||||
|
ret -= timedelta(days=7)
|
||||||
|
return ret
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
template = loader.get_template('index.html')
|
template = loader.get_template('index.html')
|
||||||
return HttpResponse(template.render({}, request))
|
return HttpResponse(template.render({}, request))
|
||||||
|
|
||||||
|
def count_stats(request):
|
||||||
|
template = loader.get_template('stats.html')
|
||||||
|
|
||||||
|
# Group counts by week (extract isoyear works only on psql and DB2)
|
||||||
|
weeklyArrows = ArrowCount.objects \
|
||||||
|
.filter(user = request.user) \
|
||||||
|
.annotate(isoyear=Extract('date', lookup_name='isoyear')) \
|
||||||
|
.annotate(week=ExtractWeek('date')) \
|
||||||
|
.values('isoyear', 'week') \
|
||||||
|
.annotate(sum_count=Sum('count')) \
|
||||||
|
.order_by('-isoyear', '-week')
|
||||||
|
|
||||||
|
for w in weeklyArrows:
|
||||||
|
w['weekStarts'] = tofirstdayinisoweek(w['isoyear'], w['week'])
|
||||||
|
w['weekEnds'] = w['weekStarts'] + timedelta(days=6)
|
||||||
|
|
||||||
|
return HttpResponse(template.render({
|
||||||
|
'weeklyArrows': json.dumps(list(weeklyArrows), cls=DjangoJSONEncoder)
|
||||||
|
}, request))
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def arrow_count_list(request):
|
def arrow_count_list(request):
|
||||||
page = request.GET.get('page')
|
page = request.GET.get('page')
|
||||||
|
|
Loading…
Reference in a new issue