Selaa lähdekoodia

Added badge for number of seums for each counter, beautified code

Denis Merigoux 9 vuotta sitten
vanhempi
commit
6c99685c18
3 muutettua tiedostoa jossa 149 lisäystä ja 97 poistoa
  1. 4 2
      counter/templates/counterTemplate.html
  2. 7 7
      counter/templates/homeTemplate.html
  3. 138 88
      counter/views.py

+ 4 - 2
counter/templates/counterTemplate.html

@@ -1,13 +1,15 @@
1 1
 {% extends 'baseTemplate.html' %} {% block title %}{{counter.trigramme}}{% endblock %} {% block content %}
2 2
 <div class="text-center">
3
-  <h1>{{counter.trigramme}} <small>{{ counter.name }}</small></h1>
3
+  <h1>
4
+      {{counter.trigramme}} <small>{{ counter.name }}</small>
5
+  </h1>
4 6
 </div>
5 7
 <div class="container-fluid">
6 8
   <div class="row">
7 9
     <div class="col-md-3">
8 10
       <div class="panel panel-primary">
9 11
         <div class="panel-heading">
10
-          <h2 class="panel-title">Dernier seum</h2>
12
+          <h2 class="panel-title">Dernier seum {% if not counter.lastReset.noSeum %}<span class="badge pull-right">{{ counter.seumCount }}</span>{% endif %}</h2>
11 13
         </div>
12 14
         <div class="seum-counter panel-body">
13 15
           {% if counter.lastReset.noSeum %}

+ 7 - 7
counter/templates/homeTemplate.html

@@ -8,7 +8,11 @@
8 8
 		<div class="col-md-4 col-sm-6 col-lg-3">
9 9
 			<div class="panel panel-{{counter.CSSclass}}" style="opacity:{{counter.opacity}}">
10 10
 				<div class="panel-heading">
11
-					<a class="counter-link" href="{% url 'counter' id_counter=counter.id %}"><h2 class="panel-title">{{ counter.trigramme }} <small>{{ counter.name }}</small></h2></a>
11
+					<a class="counter-link" href="{% url 'counter' id_counter=counter.id %}">
12
+						<h2 class="panel-title">{{ counter.trigramme }} <small>{{ counter.name }}</small>
13
+							{% if not counter.lastReset.noSeum %}<span class="pull-right badge">{{ counter.seumCount }}</span>{% endif %}
14
+						</h2>
15
+					</a>
12 16
 				</div>
13 17
 				<div class="seum-counter panel-body">
14 18
 					{% if counter.lastReset.noSeum %}
@@ -49,9 +53,7 @@
49 53
 					<div class="text-center text-muted">
50 54
 						<p>Personne n'a le seum...</p>
51 55
 					</div>
52
-					{% else %}
53
-					{{ col_chart.as_html }}
54
-					{% endif %}
56
+					{% else %} {{ col_chart.as_html }} {% endif %}
55 57
 				</div>
56 58
 			</div>
57 59
 		</div>
@@ -67,9 +69,7 @@
67 69
 					<div class="text-center text-muted">
68 70
 						<p>Pas de seum dans les dernières 24 heures...</p>
69 71
 					</div>
70
-					{% else %}
71
-					{{ line_chart.as_html }}
72
-					{% endif %}
72
+					{% else %} {{ line_chart.as_html }} {% endif %}
73 73
 				</div>
74 74
 			</div>
75 75
 		</div>

+ 138 - 88
counter/views.py

@@ -1,7 +1,7 @@
1 1
 from django.shortcuts import render
2
-from counter.models import Counter,Reset
2
+from counter.models import Counter, Reset
3 3
 from babel.dates import format_timedelta, format_datetime
4
-from datetime import datetime,timedelta
4
+from datetime import datetime, timedelta
5 5
 from django import forms
6 6
 from django.http import HttpResponseRedirect
7 7
 from django.core import serializers
@@ -13,23 +13,28 @@ import random
13 13
 import math
14 14
 from django.utils import timezone
15 15
 
16
+
16 17
 class resetCounterForm(forms.ModelForm):
18
+
17 19
     class Meta:
18 20
         model = Reset
19
-        fields = ['reason','counter']
21
+        fields = ['reason', 'counter']
22
+
20 23
 
21 24
 def home(request):
22
-    #JSS above this limit will not be displayed on the col graph
25
+    # JSS above this limit will not be displayed on the col graph
23 26
     JSS_limit = 7
24
-    #Display counters
27
+    # Display counters
25 28
     counters = Counter.objects.all()
26 29
     lastResets = []
27
-    #Calculates infos for each counter
30
+    # Calculates infos for each counter
28 31
     maxJSS = 0
29 32
     timezero = timedelta(0)
30 33
     for counter in counters:
31
-        lastReset = Reset.objects.filter(counter=counter).order_by('-timestamp')
34
+        lastReset = Reset.objects.filter(
35
+            counter=counter).order_by('-timestamp')
32 36
         if (lastReset.count() == 0):
37
+            # This person never had the seum
33 38
             counter.lastReset = Reset()
34 39
             counter.lastReset.delta = timezero
35 40
             counter.lastReset.noSeum = True
@@ -37,111 +42,139 @@ def home(request):
37 42
         else:
38 43
             counter.lastReset = lastReset[0]
39 44
             counter.lastReset.noSeum = False
40
-            counter.lastReset.delta = datetime.now()-counter.lastReset.timestamp.replace(tzinfo=None)
41
-            if ((counter.lastReset.delta.total_seconds())/(24*3600)<JSS_limit):
42
-                #If more thant 7 JSS do not display on graph
43
-                lastResets.append([counter.trigramme,{'v' : (counter.lastReset.delta.total_seconds())/(24*3600), 'f' : str(round((counter.lastReset.delta.total_seconds())/(24*3600),1))} ])
44
-                counter.CSSclass = "primary"
45
-                if (counter.lastReset.delta.total_seconds())/(24*3600) > maxJSS:
46
-                    maxJSS = (counter.lastReset.delta.total_seconds())/(24*3600)
47
-            else:
48
-                counter.CSSclass = "primary"
49
-            counter.opacity = 0.3 + 0.7*math.exp(-(counter.lastReset.delta.total_seconds())/(7*24*3600))
50
-        counter.lastReset.formatted_delta = format_timedelta(counter.lastReset.delta,locale='fr',threshold=1)
45
+            counter.lastReset.delta = datetime.now(
46
+            ) - counter.lastReset.timestamp.replace(tzinfo=None)
47
+            if ((counter.lastReset.delta.total_seconds()) / (24 * 3600) <
48
+                    JSS_limit):
49
+                # Less than 7 JSS -> display on graph
50
+                lastResets.append(
51
+                    [counter.trigramme,
52
+                     {'v': (counter.lastReset.delta.total_seconds()) /
53
+                      (24 * 3600),
54
+                      'f': str(round(
55
+                          (counter.lastReset.delta.total_seconds()) /
56
+                          (24 * 3600), 1))}])
57
+                # Updating the max JSS displayed on the graph to compute scale
58
+                if (counter.lastReset.delta.total_seconds() / (24 * 3600) >
59
+                        maxJSS):
60
+                    maxJSS = (counter.lastReset.delta.total_seconds() /
61
+                              (24 * 3600))
62
+            # Defining CSS attributes for the counter
63
+            counter.CSSclass = "primary"
64
+            counter.opacity = 0.3 + 0.7 * \
65
+                math.exp(-(counter.lastReset.delta.total_seconds()) /
66
+                         (7 * 24 * 3600))
67
+            # Computing the total number of resets for this counter
68
+            counter.seumCount = Reset.objects.filter(
69
+                counter=counter).count()
70
+        counter.lastReset.formatted_delta = format_timedelta(
71
+            counter.lastReset.delta, locale='fr', threshold=1)
51 72
         counter.isHidden = "hidden"
52
-    counters = sorted(counters,key=lambda t: t.lastReset.delta)
53
-    #Column graph
54
-    if (len(lastResets) ==0):
73
+    counters = sorted(counters, key=lambda t: t.lastReset.delta)
74
+    # Column graph
75
+    if (len(lastResets) == 0):
55 76
         noGraph = True
56 77
         col_chart = None
57 78
     else:
58 79
         noGraph = False
59 80
         lastResets.sort(key=lambda x: x[1]['v'])
60
-        lastResets.insert(0,['Trigramme','Jours sans seum'])
81
+        lastResets.insert(0, ['Trigramme', 'Jours sans seum'])
61 82
         col_data = SimpleDataSource(lastResets)
62
-        col_chart = gchart.ColumnChart(col_data,options={
63
-            'title' : '',
64
-            'legend' : 'none',
65
-            'vAxis' : {
66
-                'viewWindow' : {
67
-                    'max' : max(maxJSS,1) ,
68
-                    'min' : 0
69
-                    },
70
-                'ticks' : [1,2,3,4,5,6,7],
71
-                'title' : 'Jours sans seum'
83
+        col_chart = gchart.ColumnChart(col_data, options={
84
+            'title': '',
85
+            'legend': 'none',
86
+            'vAxis': {
87
+                'viewWindow': {
88
+                    'max': max(maxJSS, 1),
89
+                    'min': 0
72 90
                 },
73
-            'hAxis' : {'title' : 'Trigramme' },
91
+                'ticks': [1, 2, 3, 4, 5, 6, 7],
92
+                'title': 'Jours sans seum'
93
+            },
94
+            'hAxis': {'title': 'Trigramme'},
74 95
         })
75 96
 
76
-    ###Timeline graph
77
-    #Data pre-processing
78
-    resets = Reset.objects.filter(timestamp__gte=timezone.now() - timedelta(days=1))
97
+    # Timeline graph
98
+    # Data pre-processing
99
+    resets = Reset.objects.filter(
100
+        timestamp__gte=timezone.now() - timedelta(days=1))
79 101
     if (resets.count() == 0):
80 102
         noTimeline = True
81 103
         line_chart = None
82 104
     else:
83 105
         noTimeline = False
84 106
         for reset in resets:
85
-            reset.timestamp={
86
-                'v' : reset.timestamp.timestamp(),
87
-                'f' : "Il y a "+format_timedelta(datetime.now()-reset.timestamp.replace(tzinfo=None),locale='fr',threshold=1)
88
-                }
89
-            reset.Seum={'v' : 0, 'f' : reset.counter.trigramme+" : "+reset.reason}
90
-            #Drawing the graph
91
-        line_data = ModelDataSource(resets,fields=['timestamp','Seum'])
107
+            reset.timestamp = {
108
+                'v': reset.timestamp.timestamp(),
109
+                'f': "Il y a " + format_timedelta(datetime.now() -
110
+                                                  reset.timestamp.replace(
111
+                                                      tzinfo=None),
112
+                                                  locale='fr', threshold=1)
113
+            }
114
+            reset.Seum = {
115
+                'v': 0, 'f': reset.counter.trigramme + " : " + reset.reason}
116
+        # Drawing the graph
117
+        line_data = ModelDataSource(resets, fields=['timestamp', 'Seum'])
92 118
         line_chart = gchart.LineChart(line_data, options={
93
-            'lineWidth' : 0,
94
-            'pointSize' : 10,
95
-            'title' : '',
96
-            'vAxis' : { 'ticks' : []},
97
-            'hAxis' : {
98
-                'ticks' : [
99
-                        {'v' : (datetime.now() - timedelta(days=1)).timestamp(), 'f' : 'Il y a 24 h' },
100
-                        { 'v' :datetime.now().timestamp(), 'f' : 'Présent'}
101
-                    ]
102
-                },
103
-            'legend' : 'none',
104
-            'height' : 90
105
-            })
106
-
107
-    return render(request,'homeTemplate.html', {
108
-        'counters' : counters,
109
-        'col_chart' : col_chart,
110
-        'line_chart' : line_chart,
111
-        'noTimeline' : noTimeline,
112
-        'noGraph' : noGraph
119
+            'lineWidth': 0,
120
+            'pointSize': 10,
121
+            'title': '',
122
+            'vAxis': {'ticks': []},
123
+            'hAxis': {
124
+                'ticks': [
125
+                    {'v': (datetime.now() - timedelta(days=1)
126
+                           ).timestamp(), 'f': 'Il y a 24 h'},
127
+                    {'v': datetime.now().timestamp(), 'f': 'Présent'}
128
+                ]
129
+            },
130
+            'legend': 'none',
131
+            'height': 90
113 132
         })
114 133
 
134
+    return render(request, 'homeTemplate.html', {
135
+        'counters': counters,
136
+        'col_chart': col_chart,
137
+        'line_chart': line_chart,
138
+        'noTimeline': noTimeline,
139
+        'noGraph': noGraph
140
+    })
141
+
142
+
115 143
 def resetCounter(request):
116
-    #Update Form counter
144
+    # Update Form counter
117 145
     if (request.method == 'POST'):
118 146
         # create a form instance and populate it with data from the request:
119 147
         data = dict(request.POST)
120
-        counter =  Counter.objects.get(pk=int(data['counter'][0]))
148
+        counter = Counter.objects.get(pk=int(data['counter'][0]))
121 149
         reset = Reset()
122 150
         reset.counter = counter
123 151
         reset.reason = data['reason'][0]
124 152
         reset.timestamp = datetime.now()
125 153
         reset.save()
126
-        emails = [u[0] for u in Counter.objects.all().values_list('email') if u[0] != 'null@localhost']
127
-        #Now send emails to everyone
128
-        email_to_send = EmailMessage( counter.name+' a le seum', data['reason'][0]+'''
154
+        # We send the emails only to those who have an email address
155
+        emails = [u[0] for u in Counter.objects.all().values_list('email')
156
+                  if u[0] != 'null@localhost']
157
+        # Now send emails to everyone
158
+        email_to_send = EmailMessage(counter.name + ' a le seum',
159
+                                     data['reason'][0] + '''
129 160
 
130 161
 --
131 162
 SeumBook™ - http://seum.merigoux.ovh
132 163
 
133 164
 P.S. : Pour ne plus recevoir ces messages, envoie un mail à denis.merigoux@gmail.com''',
134
-        'SeumMan <seum@merigoux.ovh>', emails,[],reply_to=emails)
165
+                                     'SeumMan <seum@merigoux.ovh>', emails, [],
166
+                                     reply_to=emails)
135 167
     email_to_send.send()
136 168
 
137 169
     return HttpResponseRedirect(data['redirect'][0])
138 170
 
171
+
139 172
 def counter(request, id_counter):
140 173
 
141 174
     counter = Counter.objects.get(pk=id_counter)
142 175
     resets = Reset.objects.filter(counter=counter).order_by('-timestamp')
143 176
     timezero = timedelta(0)
144
-    #Display
177
+    # Display
145 178
     if (resets.count() == 0):
146 179
         counter.lastReset = Reset()
147 180
         counter.lastReset.delta = timezero
@@ -149,27 +182,44 @@ def counter(request, id_counter):
149 182
     else:
150 183
         counter.lastReset = resets[0]
151 184
         counter.lastReset.noSeum = False
152
-        counter.lastReset.delta = datetime.now()-counter.lastReset.timestamp.replace(tzinfo=None)
153
-        counter.lastReset.formatted_delta = format_timedelta(counter.lastReset.delta,locale='fr',threshold=1)
185
+        counter.lastReset.delta = datetime.now(
186
+        ) - counter.lastReset.timestamp.replace(tzinfo=None)
187
+        counter.lastReset.formatted_delta = format_timedelta(
188
+            counter.lastReset.delta, locale='fr', threshold=1)
189
+        counter.seumCount = Reset.objects.filter(
190
+            counter=counter).count()
154 191
 
155 192
     for reset in resets:
156
-        reset.date = format_datetime(reset.timestamp,locale='fr',format="EEEE dd MMMM Y 'à' HH:mm:ss").capitalize()
157
-    ###Timeline graph
158
-    #Data pre-processing
159
-    resets_graph=resets
193
+        reset.date = format_datetime(
194
+            reset.timestamp, locale='fr',
195
+            format="EEEE dd MMMM Y 'à' HH:mm:ss").capitalize()
196
+    # Timeline graph
197
+    # Data pre-processing
198
+    resets_graph = resets
160 199
     for reset in resets_graph:
161
-        reset.timestamp={'v' : reset.timestamp.timestamp(), 'f' : "Il y a "+format_timedelta(datetime.now()-reset.timestamp.replace(tzinfo=None),locale='fr',threshold=1) }
162
-        reset.Seum={'v' : 0, 'f' : reset.reason}
163
-    #Drawing the graph
164
-    data = ModelDataSource(resets,fields=['timestamp','Seum'])
200
+        reset.timestamp = {
201
+            'v': reset.timestamp.timestamp(),
202
+            'f': "Il y a " + format_timedelta(
203
+                datetime.now() - reset.timestamp.replace(tzinfo=None),
204
+                locale='fr', threshold=1)
205
+        }
206
+        reset.Seum = {'v': 0, 'f': reset.reason}
207
+    # Drawing the graph
208
+    data = ModelDataSource(resets, fields=['timestamp', 'Seum'])
165 209
     chart = gchart.LineChart(data, options={
166
-        'lineWidth' : 0,
167
-        'pointSize' : 10,
168
-        'title' : '',
169
-        'vAxis' : { 'ticks' : []},
170
-        'hAxis' : {'ticks' : [{'v' : datetime(2016,3,9,23,0,0,0).timestamp(), 'f' : 'ADD des X2013' }, { 'v' :datetime.now().timestamp(), 'f' : 'Présent'}]},
171
-        'legend' : 'none',
172
-        'height' : 90
210
+        'lineWidth': 0,
211
+        'pointSize': 10,
212
+        'title': '',
213
+        'vAxis': {'ticks': []},
214
+        'hAxis': {'ticks': [{
215
+            'v': datetime(2016, 3, 9, 23, 0, 0, 0).timestamp(),
216
+            'f': 'ADD des X2013'
217
+        }, {
218
+            'v': datetime.now().timestamp(),
219
+            'f': 'Présent'}
220
+        ]},
221
+        'legend': 'none',
222
+        'height': 90
173 223
     })
174 224
 
175
-    return render(request,'counterTemplate.html', { 'counter' : counter, 'chart' : chart, 'resets' : resets })
225
+    return render(request, 'counterTemplate.html', {'counter': counter, 'chart': chart, 'resets': resets})