Frontend tout en JS

This commit is contained in:
Evarin 2017-02-15 21:01:54 +01:00
parent 46f343b1ab
commit 0fcb29252b
7 changed files with 205 additions and 313 deletions

View file

@ -1,18 +1,166 @@
var STAT = {}; (function($){
window.StatsGroup = function (url, target) {
// context : array of objects {label, url}
// target : element of the DOM where to put the stats
var self = this;
var element = $(target);
var content = $("<div>");
var buttons;
jQuery(document).ready(function() { function dictToArray(dict, start) {
// FONCTIONS if (start === undefined) start = 0;
// Permet de raffraichir un champ, étant donné : // converts the dicts returned by JSONResponse to Arrays
// thing_url : l'url contenant le contenu // necessary because for..in does not guarantee the order
// thing_div : le div où le mettre var array = new Array();
// empty_... : le truc à dire si on a un contenu vide for (var k in dict) {
STAT.get_thing = function(thing_url, thing_div, empty_thing_message) { array[k] = dict[k];
$.get(thing_url, function(data) { }
if(jQuery.trim(data).length==0) { array.splice(0, start);
thing_div.html(empty_thing_message); return array;
} else { }
thing_div.html(data);
function handleTimeChart(dict) {
var data = dictToArray(dict, 0);
for (var i = 0; i < data.length; i++) {
var source = data[i];
data[i] = { x: new Date(source.at),
y: source.balance,
label: source.label }
}
return data;
}
this.showStats = function() {
buttons.find(".focus").removeClass("focus");
$(this).addClass("focus");
$.getJSON(this.stats_target_url + "?format=json",
self.displayStats);
}
this.displayStats = function(data) {
// create the chart
var canvas = $("<canvas>");
var chart_datasets = [];
var charts = dictToArray(data.charts);
var is_time_chart = data.is_time_chart || false;
for (var i = 0; i < charts.length; i++) {
var chart = charts[i];
chart_datasets.push(
{
label: chart.label,
borderColor: chart.color,
backgroundColor: chart.color,
fill: false,
lineTension: 0,
data: is_time_chart ? handleTimeChart(chart.values) : dictToArray(chart.values, 1),
});
}
var chart_options =
{
responsive: true,
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: false,
}
} }
}); if (is_time_chart) {
} chart_options['scales'] = {
}); xAxes: [{
type: "time",
display: true,
scaleLabel: {
display: false,
labelString: 'Date'
},
time: {
tooltipFormat: 'll HH:mm',
//min: new Date("{{ min_date }}"),
//max: new Date("{{ max_date }}"),
displayFormats: {
'millisecond': 'SSS [ms]',
'second': 'mm:ss a',
'minute': 'DD MMM',
'hour': 'ddd h[h]',
'day': 'DD MMM',
'week': 'DD MMM',
'month': 'MMM',
'quarter': 'MMM',
'year': 'YYYY',
}
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: false,
labelString: 'value'
}
}]
}
}
var chart_model =
{
type: 'line',
options: chart_options,
data: {
labels: dictToArray(data.labels, 1),
datasets: chart_datasets,
}
};
// display
var prev_chart = content.children();
content.append(canvas);
// create the chart
var chart = new Chart(canvas, chart_model);
// clean
prev_chart.remove();
}
// initialize the interface
this.initialize = function (data) {
buttons = $("<div>",
{class: "btn-group btn-group-justified",
role: "group",
"aria-label": "select-period"});
var to_click = undefined;
var context = dictToArray(data.stats);
for (var i = 0; i < context.length; i++) {
var btn_wrapper = $("<div>",
{class: "btn-group",
role:"group"});
var btn = $("<button>",
{class: "btn btn-primary",
type: "button"})
.text(context[i].label)
.prop("stats_target_url", context[i].url)
.on("click", self.showStats);
if (i == data.default_stat || i == 0)
to_click = btn;
btn_wrapper.append(btn);
buttons.append(btn_wrapper);
}
element.append(buttons);
element.append(content);
to_click.click();
};
(function () {
$.getJSON(url + "?format=json", self.initialize);
})();
};
})(jQuery);

View file

@ -14,14 +14,12 @@
<script type="text/javascript" src="{% static 'kfet/js/Chart.bundle.js' %}"></script> <script type="text/javascript" src="{% static 'kfet/js/Chart.bundle.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/statistic.js' %}"></script> <script type="text/javascript" src="{% static 'kfet/js/statistic.js' %}"></script>
<script> <script>
jQuery(document).ready(function() { jQuery(document).ready(function() {
var stat_last = $("#stat_last"); var stat_last = new StatsGroup("{% url 'kfet.account.stat.last' trigramme=account.trigramme %}",
var stat_balance = $("#stat_balance"); $("#stat_last"));
var stat_last_url = "{% url 'kfet.account.stat.last' trigramme=account.trigramme %}"; var stat_balance = new StatsGroup("{% url 'kfet.account.stat.balance' trigramme=account.trigramme %}",
var stat_balance_url = "{% url 'kfet.account.stat.balance' trigramme=account.trigramme %}"; $("#stat_balance"));
STAT.get_thing(stat_last_url, stat_last, "Stat non trouvées :("); });
STAT.get_thing(stat_balance_url, stat_balance, "Stat non trouvées :(");
});
</script> </script>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View file

@ -1,91 +0,0 @@
<!doctype html>
{% load dictionary_extras %}
<body>
<canvas id="{{ chart_id }}" height="100"></canvas>
{% comment %}
<ul>
{% for change in changes %}
<li>
{{ change | get_item:'label'}}
| {{ change | get_item:'at'}}
| ({{ change | get_item:'amount'}})
| balance {{ change | get_item:'balance'}}
</li>
{% endfor %}
</ul>
{% endcomment %}
<script>
jQuery(document).ready(function() {
var ctx1 = $({{ chart_id }});
var myChart = new Chart(ctx1, {
type: 'line',
data: {
datasets: [{
label: 'Balance',
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgba(255, 99, 132, 0.5)',
data: [
{% for change in changes %}
{
x: new Date("{{ change | get_item:'at'}}"),
y: {{ change | get_item:'balance'| stringformat:"f" }},
label: "{{change|get_item:'label'}}"
}{% if not forloop.last %}, {% endif %}
{% endfor %}
],
fill: true,
steppedLine: true,
lineTension: 0,
}]
},
options: {
responsive: true,
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: false,
},
scales: {
xAxes: [{
type: "time",
display: true,
scaleLabel: {
display: false,
labelString: 'Date'
},
time: {
tooltipFormat: 'll HH:mm',
min: new Date("{{ min_date }}"),
max: new Date("{{ max_date }}"),
displayFormats: {
'millisecond': 'SSS [ms]',
'second': 'mm:ss a',
'minute': 'DD MMM',
'hour': 'ddd h[h]',
'day': 'DD MMM',
'week': 'DD MMM',
'month': 'MMM',
'quarter': 'MMM',
'year': 'YYYY',
}
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: false,
labelString: 'value'
}
}]
}
}
});
});
</script>
</body>

View file

@ -1,52 +0,0 @@
<!doctype html>
<body>
<canvas id="{{ chart_id }}" height="100" ></canvas>
<script>
jQuery(document).ready(function() {
var ctx1 = $({{ chart_id }});
var myChart = new Chart(ctx1, {
type: 'line',
data: {
labels: [
{% for k,label in labels.items %}
{% if forloop.last %}
"{{ label }}"
{% else %}
"{{ label }}",
{% endif %}
{% endfor %}
],
datasets: [{
label: 'Nb items achetés',
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgb(255, 99, 132)',
data: [
{% for k,nb in nb_ventes.items %}
{% if forloop.last %}
"{{ nb }}"
{% else %}
"{{ nb }}",
{% endif %}
{% endfor %}
],
fill: false,
lineTension: 0,
}]
},
options: {
responsive: true,
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: false,
},
}
});
});
</script>
</body>

View file

@ -1,82 +0,0 @@
<!doctype html>
<body>
<canvas id="{{ chart_id }}" height="100" ></canvas>
<script>
jQuery(document).ready(function() {
var ctx1 = $({{ chart_id }});
var myChart = new Chart(ctx1, {
type: 'line',
data: {
labels: [
{% for k,label in labels.items %}
{% if forloop.last %}
"{{ label }}"
{% else %}
"{{ label }}",
{% endif %}
{% endfor %}
],
datasets: [{
label: 'Toutes consommations',
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgb(255, 99, 132)',
data: [
{% for k,nb in nb_ventes.items %}
{% if forloop.last %}
"{{ nb }}"
{% else %}
"{{ nb }}",
{% endif %}
{% endfor %}
],
fill: false,
lineTension: 0,
} , {
label: 'LIQ',
borderColor: 'rgb(54, 162, 235)',
backgroundColor: 'rgb(54, 162, 235)',
data: [
{% for k,nb in nb_liq.items %}
{% if forloop.last %}
"{{ nb }}"
{% else %}
"{{ nb }}",
{% endif %}
{% endfor %}
],
fill: false,
lineTension: 0,
} , {
label: 'Comptes K-Fêt',
borderColor: 'rgb(255, 205, 86)',
backgroundColor: 'rgb(255, 205, 86)',
data: [
{% for k,nb in nb_accounts.items %}
{% if forloop.last %}
"{{ nb }}"
{% else %}
"{{ nb }}",
{% endif %}
{% endfor %}
],
fill: false,
lineTension: 0,
}]
},
options: {
responsive: true,
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: false,
},
}
});
});
</script>
</body>

View file

@ -1,35 +0,0 @@
<!doctype html>
{% load staticfiles %}
{% load dictionary_extras %}
<body>
<div class="btn-group btn-group-justified" role="group" aria-label="select-period">
{% for k,stat in stats.items %}
<div class="btn-group" role="group">
<button id="{{ stat | get_item:'btn' }}" type="button" class="btn btn-primary {{ id_prefix }}-btn {%if k == default_stat%} focus{%endif%}">{{ stat | get_item:'label' }}</button>
</div>
{% endfor %}
</div><!-- /boutons -->
<div id="{{ content_id}}">
</div>
<script>
jQuery(document).ready(function() {
// VARIABLES
{{id_prefix}}_content_id = $("#{{content_id}}");
{{id_prefix}}_btns = $(".{{id_prefix}}-btn");
{% for k,stat in stats.items %}
{% if k == default_stat %}
{{id_prefix}}_default_url = "{{ stat | get_item:'url' }}";
{% endif %}
{% endfor %}
// INIT
STAT.get_thing({{id_prefix}}_default_url, {{id_prefix}}_content_id, "Ouppss ?");
{% for k,stat in stats.items %}
$("#{{stat|get_item:'btn'}}").on('click', function() {
STAT.get_thing("{{stat|get_item:'url'}}", {{id_prefix}}_content_id, "Ouuups ?");
{{id_prefix}}_btns.removeClass("focus");
$("#{{stat|get_item:'btn'}}").addClass("focus");
});
{% endfor %}
});
</script>
</body>

View file

@ -7,7 +7,7 @@ from django.views.generic import ListView, DetailView
from django.views.generic.list import BaseListView, MultipleObjectTemplateResponseMixin from django.views.generic.list import BaseListView, MultipleObjectTemplateResponseMixin
from django.views.generic.detail import BaseDetailView, SingleObjectTemplateResponseMixin from django.views.generic.detail import BaseDetailView, SingleObjectTemplateResponseMixin
from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse, reverse_lazy
from django.contrib import messages from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login
@ -1983,6 +1983,14 @@ class JSONResponseMixin(object):
return context return context
class JSONDetailView(JSONResponseMixin,
BaseDetailView):
"""
Returns a DetailView that renders a JSON
"""
def render_to_response(self, context):
return self.render_to_json_response(context)
class HybridDetailView(JSONResponseMixin, class HybridDetailView(JSONResponseMixin,
SingleObjectTemplateResponseMixin, SingleObjectTemplateResponseMixin,
BaseDetailView): BaseDetailView):
@ -2013,12 +2021,11 @@ class HybridListView(JSONResponseMixin,
return super(HybridListView, self).render_to_response(context) return super(HybridListView, self).render_to_response(context)
class ObjectResumeStat(DetailView): class ObjectResumeStat(JSONDetailView):
""" """
Summarize all the stats of an object Summarize all the stats of an object
DOES NOT RETURN A JSON RESPONSE Handles JSONResponse
""" """
template_name = 'kfet/object_stat_resume.html'
context_object_name = '' context_object_name = ''
id_prefix = '' id_prefix = ''
# nombre de vues à résumer # nombre de vues à résumer
@ -2049,7 +2056,7 @@ class ObjectResumeStat(DetailView):
'btn': "btn_%s_%d_%d" % (self.id_prefix, 'btn': "btn_%s_%d_%d" % (self.id_prefix,
object_id, object_id,
i), i),
'url': reverse_lazy(self.stat_urls[i], 'url': reverse(self.stat_urls[i],
kwargs=dict( kwargs=dict(
self.get_object_url_kwargs(), self.get_object_url_kwargs(),
**url_kwargs[i] **url_kwargs[i]
@ -2072,7 +2079,7 @@ ID_PREFIX_ACC_BALANCE = "balance_acc"
# Un résumé de toutes les vues ArticleStatBalance # Un résumé de toutes les vues ArticleStatBalance
# NE REND PAS DE JSON # REND DU JSON
class AccountStatBalanceAll(ObjectResumeStat): class AccountStatBalanceAll(ObjectResumeStat):
model = Account model = Account
context_object_name = 'account' context_object_name = 'account'
@ -2105,9 +2112,9 @@ class AccountStatBalanceAll(ObjectResumeStat):
return super(AccountStatBalanceAll, self).dispatch(*args, **kwargs) return super(AccountStatBalanceAll, self).dispatch(*args, **kwargs)
class AccountStatBalance(HybridDetailView): class AccountStatBalance(JSONDetailView):
""" """
Returns a graph (or a JSON Response) of the evolution a the personnal Returns a JSON containing the evolution a the personnal
balance of a trigramme between timezone.now() and `nb_days` balance of a trigramme between timezone.now() and `nb_days`
ago (specified to the view as an argument) ago (specified to the view as an argument)
takes into account the Operations and the Transfers takes into account the Operations and the Transfers
@ -2116,7 +2123,6 @@ class AccountStatBalance(HybridDetailView):
model = Account model = Account
trigramme_url_kwarg = 'trigramme' trigramme_url_kwarg = 'trigramme'
nb_date_url_kwargs = 'nb_date' nb_date_url_kwargs = 'nb_date'
template_name = 'kfet/account_stat_balance.html'
context_object_name = 'account' context_object_name = 'account'
id_prefix = "" id_prefix = ""
@ -2223,10 +2229,10 @@ class AccountStatBalance(HybridDetailView):
nb_days_string = 'anytime' nb_days_string = 'anytime'
else: else:
nb_days_string = str(int(nb_days)) nb_days_string = str(int(nb_days))
context['changes'] = changes context['charts'] = [ { "color": "rgb(255, 99, 132)",
context['chart_id'] = "%s_%s_%s_days" % (self.id_prefix, "label": "Balance",
self.object.id, "values": changes } ]
nb_days_string) context['is_time_chart'] = True
context['min_date'] = changes[len(changes)-1]['at'] context['min_date'] = changes[len(changes)-1]['at']
context['max_date'] = changes[0]['at'] context['max_date'] = changes[0]['at']
# TODO: offset # TODO: offset
@ -2272,14 +2278,13 @@ class AccountStatLastAll(ObjectResumeStat):
return super(AccountStatLastAll, self).dispatch(*args, **kwargs) return super(AccountStatLastAll, self).dispatch(*args, **kwargs)
class AccountStatLast(HybridDetailView): class AccountStatLast(JSONDetailView):
""" """
Returns a graph (or a JSON Response) of the evolution a the personnal Returns a JSON containing the evolution a the personnal
consommation of a trigramme at the diffent dates specified consommation of a trigramme at the diffent dates specified
""" """
model = Account model = Account
trigramme_url_kwarg = 'trigramme' trigramme_url_kwarg = 'trigramme'
template_name = 'kfet/account_stat_last.html'
context_object_name = 'account' context_object_name = 'account'
end_date = timezone.now() end_date = timezone.now()
id_prefix = "" id_prefix = ""
@ -2331,10 +2336,9 @@ class AccountStatLast(HybridDetailView):
operations = self.sort_operations() operations = self.sort_operations()
for i in operations: for i in operations:
nb_ventes[i] = tot_ventes(operations[i]) nb_ventes[i] = tot_ventes(operations[i])
context['nb_ventes'] = nb_ventes context['charts'] = [ { "color": "rgb(255, 99, 132)",
# ID unique "label": "NB items achetés",
context['chart_id'] = "%s_%d" % (self.id_prefix, "values": nb_ventes } ]
self.object.id)
return context return context
@method_decorator(login_required) @method_decorator(login_required)
@ -2411,13 +2415,12 @@ class ArticleStatLastAll(ObjectResumeStat):
return super(ArticleStatLastAll, self).dispatch(*args, **kwargs) return super(ArticleStatLastAll, self).dispatch(*args, **kwargs)
class ArticleStatLast(HybridDetailView): class ArticleStatLast(JSONDetailView):
""" """
Returns a graph (or a JSON Response) of the consommation Returns a JSON containing the consommation
of an article at the diffent dates precised of an article at the diffent dates precised
""" """
model = Article model = Article
template_name = 'kfet/article_stat_last.html'
context_object_name = 'article' context_object_name = 'article'
end_date = timezone.now() end_date = timezone.now()
id_prefix = "" id_prefix = ""
@ -2478,12 +2481,15 @@ class ArticleStatLast(HybridDetailView):
operations[i] operations[i]
.exclude(group__on_acc__trigramme='LIQ') .exclude(group__on_acc__trigramme='LIQ')
) )
context['nb_ventes'] = nb_ventes context['charts'] = [ { "color": "rgb(255, 99, 132)",
context['nb_accounts'] = nb_accounts "label": "Toutes consommations",
context['nb_liq'] = nb_liq "values": nb_ventes },
# ID unique { "color": "rgb(54, 162, 235)",
context['chart_id'] = "%s_%d" % (self.id_prefix, "label": "LIQ",
self.object.id) "values": nb_liq },
{ "color": "rgb(255, 205, 86)",
"label": "Comptes K-Fêt",
"values": nb_accounts } ]
return context return context
@method_decorator(login_required) @method_decorator(login_required)