Przeglądaj źródła

Functionnal timeline and prettified graph display

Denis Merigoux 9 lat temu
rodzic
commit
fe5279150e

+ 1 - 1
counter/models.py

19
     counter = models.ForeignKey('Counter')
19
     counter = models.ForeignKey('Counter')
20
 
20
 
21
     def __str__(self):
21
     def __str__(self):
22
-        return "%s : %s" % (self.counter,format_timedelta(datetime.now()-self.timestamp.replace(tzinfo=None),locale='fr'))
22
+        return "%s : %s (%s)" % (self.counter,format_timedelta(datetime.now()-self.timestamp.replace(tzinfo=None),locale='fr'),self.reason)
23
 
23
 
24
     class Meta:
24
     class Meta:
25
         verbose_name = "Remise à zéro"
25
         verbose_name = "Remise à zéro"

+ 14 - 1
counter/templates/baseTemplate.html

12
 	{# Load the tag library #} {% load bootstrap3 %} {# Load CSS and JavaScript #} {% bootstrap_css %} {% bootstrap_javascript %} {# Display django.contrib.messages as Bootstrap alerts #} {% bootstrap_messages %}
12
 	{# Load the tag library #} {% load bootstrap3 %} {# Load CSS and JavaScript #} {% bootstrap_css %} {% bootstrap_javascript %} {# Display django.contrib.messages as Bootstrap alerts #} {% bootstrap_messages %}
13
 
13
 
14
 	<style>
14
 	<style>
15
+		body {
16
+			background-color: #EEEEEE
17
+		}
18
+
15
 		.seum-counter {
19
 		.seum-counter {
16
 			height: 125px;
20
 			height: 125px;
17
 			overflow: auto;
21
 			overflow: auto;
18
-			margin-bottom: 15px;
22
+		}
23
+
24
+		.timeline {
25
+			height: 125px;
26
+			overflow-y: hidden;
19
 		}
27
 		}
20
 
28
 
21
 		.graphs > div {
29
 		.graphs > div {
22
 			display: block;
30
 			display: block;
23
 			margin: 0 auto;
31
 			margin: 0 auto;
24
 		}
32
 		}
33
+
34
+		.counter-link, .counter-link:hover {
35
+  	color: inherit; /* blue colors for links too */
36
+  	text-decoration: inherit; /* no underline */
37
+		}
25
 	</style>
38
 	</style>
26
 
39
 
27
 	<script type="text/javascript" src="https://www.google.com/jsapi"></script>
40
 	<script type="text/javascript" src="https://www.google.com/jsapi"></script>

+ 11 - 7
counter/templates/counterTemplate.html

1
-{% extends 'baseTemplate.html' %} {% block title %}Compteurs{% endblock %} {% block content %}
1
+{% extends 'baseTemplate.html' %} {% block title %}{{counter.trigramme}}{% endblock %} {% block content %}
2
 <div class="text-center">
2
 <div class="text-center">
3
-  <h1>{{counter.trigramme}}</h1>
3
+  <h1>{{counter.trigramme}} <small>{{ counter.name }}</small></h1>
4
 </div>
4
 </div>
5
 <div class="container-fluid">
5
 <div class="container-fluid">
6
   <div class="row">
6
   <div class="row">
7
-    <div class="col-md-4 col-sm-6 col-lg-3">
7
+    <div class="col-md-3">
8
       <div class="panel panel-primary">
8
       <div class="panel panel-primary">
9
         <div class="panel-heading">
9
         <div class="panel-heading">
10
-          <h2 class="panel-title">{{ counter.name }}</h2>
10
+          <h2 class="panel-title">Dernier seum</h2>
11
         </div>
11
         </div>
12
         <div class="seum-counter panel-body">
12
         <div class="seum-counter panel-body">
13
           {% if counter.lastReset.noSeum %}
13
           {% if counter.lastReset.noSeum %}
27
               <textarea class="form-control" name="reason"></textarea>
27
               <textarea class="form-control" name="reason"></textarea>
28
             </div>
28
             </div>
29
             <input type="hidden" name="counter" value="{{counter.id}}"></input>
29
             <input type="hidden" name="counter" value="{{counter.id}}"></input>
30
+            <input type="hidden" name="redirect" value="counter/{{counter.id}}"></input>
30
             <div class="text-center">
31
             <div class="text-center">
31
               <button type="submit" class="btn btn-default btn-success">Foutre le seum</button>
32
               <button type="submit" class="btn btn-default btn-success">Foutre le seum</button>
32
             </div>
33
             </div>
34
         </div>
35
         </div>
35
       </div>
36
       </div>
36
     </div>
37
     </div>
37
-    <div class="col-md-8 col-sm-6 col-lg-9">
38
+    <div class="col-md-9">
38
       <div class="panel panel-default">
39
       <div class="panel panel-default">
39
         <div class="panel-heading">
40
         <div class="panel-heading">
40
           <h2 class="panel-title">Timeline du seum</h2>
41
           <h2 class="panel-title">Timeline du seum</h2>
41
         </div>
42
         </div>
42
-        <div class="seum-counter panel-body">
43
-          Salut !
43
+        <div class="graphs timeline panel-body">
44
+          {{chart.as_html}}
44
         </div>
45
         </div>
45
       </div>
46
       </div>
46
     </div>
47
     </div>
47
   </div>
48
   </div>
49
+  <div class="text-center">
50
+    <a class="btn btn-success" href="{% url 'counter.views.home' %}">Retour à la liste des compteurs</a>
51
+  </div>
48
 </div>
52
 </div>
49
 {% endblock %}
53
 {% endblock %}

+ 2 - 1
counter/templates/homeTemplate.html

8
 		<div class="col-md-4 col-sm-6 col-lg-3">
8
 		<div class="col-md-4 col-sm-6 col-lg-3">
9
 			<div class="panel panel-primary">
9
 			<div class="panel panel-primary">
10
 				<div class="panel-heading">
10
 				<div class="panel-heading">
11
-					<h2 class="panel-title">{{ counter.trigramme }} <small>{{ counter.name }}</small></h2>
11
+					<a class="counter-link" href="{% url 'counter.views.counter' id_counter=counter.id %}"><h2 class="panel-title">{{ counter.trigramme }} <small>{{ counter.name }}</small></h2></a>
12
 				</div>
12
 				</div>
13
 				<div class="seum-counter panel-body">
13
 				<div class="seum-counter panel-body">
14
 					{% if counter.lastReset.noSeum %}
14
 					{% if counter.lastReset.noSeum %}
28
 							<textarea class="form-control" name="reason"></textarea>
28
 							<textarea class="form-control" name="reason"></textarea>
29
 						</div>
29
 						</div>
30
 						<input type="hidden" name="counter" value="{{counter.id}}"></input>
30
 						<input type="hidden" name="counter" value="{{counter.id}}"></input>
31
+						<input type="hidden" name="redirect" value="home"></input>
31
 						<div class="text-center">
32
 						<div class="text-center">
32
 							<button type="submit" class="btn btn-default btn-success">Foutre le seum</button>
33
 							<button type="submit" class="btn btn-default btn-success">Foutre le seum</button>
33
 						</div>
34
 						</div>

+ 4 - 3
counter/urls.py

3
 from . import views
3
 from . import views
4
 
4
 
5
 urlpatterns = [
5
 urlpatterns = [
6
-    url(r'^$', views.home,name='home'),
7
-    url(r'^reset-counter/',views.resetCounter,name='reset-counter'),
8
-    url(r'^counter/(?P<id_counter>\d+)$', views.counter, name='counter'),
6
+    url(r'^$', views.home),
7
+    url(r'^seum/', views.home),
8
+    url(r'^reset-counter/',views.resetCounter),
9
+    url(r'^counter/(?P<id_counter>\d+)$', views.counter),
9
 ]
10
 ]

+ 28 - 5
counter/views.py

7
 from django.core import serializers
7
 from django.core import serializers
8
 from graphos.renderers import gchart
8
 from graphos.renderers import gchart
9
 from graphos.sources.simple import SimpleDataSource
9
 from graphos.sources.simple import SimpleDataSource
10
+from graphos.sources.model import ModelDataSource
11
+import random
10
 
12
 
11
 class resetCounterForm(forms.ModelForm):
13
 class resetCounterForm(forms.ModelForm):
12
     class Meta:
14
     class Meta:
31
             counter.lastReset = lastReset[0]
33
             counter.lastReset = lastReset[0]
32
             counter.lastReset.noSeum = False
34
             counter.lastReset.noSeum = False
33
             counter.lastReset.delta = datetime.now()-counter.lastReset.timestamp.replace(tzinfo=None)
35
             counter.lastReset.delta = datetime.now()-counter.lastReset.timestamp.replace(tzinfo=None)
34
-            lastResets.append([counter.trigramme,(counter.lastReset.delta.total_seconds())/(24*3600)])
36
+            lastResets.append([counter.trigramme,{'v' : (counter.lastReset.delta.total_seconds())/(24*3600), 'f' : str(round((counter.lastReset.delta.total_seconds())/(24*3600),1))} ])
35
             if (counter.lastReset.delta.total_seconds())/(24*3600) > maxJSS:
37
             if (counter.lastReset.delta.total_seconds())/(24*3600) > maxJSS:
36
                 maxJSS = (counter.lastReset.delta.total_seconds())/(24*3600)
38
                 maxJSS = (counter.lastReset.delta.total_seconds())/(24*3600)
37
             counter.lastReset.formatted_delta = format_timedelta(counter.lastReset.delta,locale='fr',threshold=1)
39
             counter.lastReset.formatted_delta = format_timedelta(counter.lastReset.delta,locale='fr',threshold=1)
38
         counter.isHidden = "hidden"
40
         counter.isHidden = "hidden"
39
     counters = sorted(counters,key=lambda t: -t.lastReset.delta)
41
     counters = sorted(counters,key=lambda t: -t.lastReset.delta)
40
     #Generate graph
42
     #Generate graph
41
-    lastResets.sort(key=lambda x: (x[1],x[0]))
43
+    lastResets.sort(key=lambda x: x[1]['v'])
42
     lastResets.insert(0,['Trigramme','Jours sans seum'])
44
     lastResets.insert(0,['Trigramme','Jours sans seum'])
43
     data = SimpleDataSource(lastResets)
45
     data = SimpleDataSource(lastResets)
44
     chart = gchart.ColumnChart(data,options={'title' : '', 'legend' : 'none','vAxis' : { 'viewWindow' : { 'max' : max(maxJSS,1) , 'min' : 0} , 'ticks' : [1,2,3,4,5,6,7,8,9,10,11,12,13,14],'title' : 'Jours sans seum' }, 'hAxis' : {'title' : 'Trigramme' }})
46
     chart = gchart.ColumnChart(data,options={'title' : '', 'legend' : 'none','vAxis' : { 'viewWindow' : { 'max' : max(maxJSS,1) , 'min' : 0} , 'ticks' : [1,2,3,4,5,6,7,8,9,10,11,12,13,14],'title' : 'Jours sans seum' }, 'hAxis' : {'title' : 'Trigramme' }})
56
         reset.timestamp = datetime.now()
58
         reset.timestamp = datetime.now()
57
         reset.save()
59
         reset.save()
58
         # check whether it's valid
60
         # check whether it's valid
59
-    return HttpResponseRedirect('/')
61
+    return HttpResponseRedirect('/'+data['redirect'][0])
60
 
62
 
61
 def counter(request, id_counter):
63
 def counter(request, id_counter):
64
+
62
     counter = Counter.objects.get(pk=id_counter)
65
     counter = Counter.objects.get(pk=id_counter)
63
-    lastReset = Reset.objects.filter(counter=counter).order_by('-timestamp')
66
+    resets = Reset.objects.filter(counter=counter)
67
+    lastReset = resets.order_by('-timestamp')
68
+    #Display
64
     if (lastReset.count() == 0):
69
     if (lastReset.count() == 0):
65
         counter.lastReset = Reset()
70
         counter.lastReset = Reset()
66
         counter.lastReset.delta = timezero
71
         counter.lastReset.delta = timezero
69
         counter.lastReset = lastReset[0]
74
         counter.lastReset = lastReset[0]
70
         counter.lastReset.noSeum = False
75
         counter.lastReset.noSeum = False
71
         counter.lastReset.delta = datetime.now()-counter.lastReset.timestamp.replace(tzinfo=None)
76
         counter.lastReset.delta = datetime.now()-counter.lastReset.timestamp.replace(tzinfo=None)
77
+        counter.lastReset.formatted_delta = format_timedelta(counter.lastReset.delta,locale='fr',threshold=1)
78
+
79
+    ###Timeline graph
80
+    #Data pre-processing
81
+    for reset in resets:
82
+        reset.timestamp={'v' : reset.timestamp.timestamp(), 'f' : "Il y a "+format_timedelta(datetime.now()-reset.timestamp.replace(tzinfo=None),locale='fr',threshold=1) }
83
+        reset.Seum={'v' : 0, 'f' : reset.reason}
84
+    #Drawing the graph
85
+    data = ModelDataSource(resets,fields=['timestamp','Seum'])
86
+    chart = gchart.LineChart(data, options={
87
+        'lineWidth' : 0,
88
+        'pointSize' : 10,
89
+        'title' : '',
90
+        'vAxis' : { 'ticks' : []},
91
+        'hAxis' : {'ticks' : [{'v' : datetime(2016,3,9,23,0,0,0).timestamp(), 'f' : 'ADD des X2013' }, { 'v' :datetime.now().timestamp(), 'f' : 'Présent'}]},
92
+        'legend' : 'none',
93
+        'height' : 90
94
+    })
72
 
95
 
73
-    return render(request,'counterTemplate.html', { 'counter' : counter})
96
+    return render(request,'counterTemplate.html', { 'counter' : counter, 'chart' : chart})