Denis Merigoux лет назад: 9
Родитель
Сommit
c4e0a876af
5 измененных файлов с 105 добавлено и 29 удалено
  1. 5 1
      counter/models.py
  2. 27 1
      counter/templates/counterTemplate.html
  3. 30 8
      counter/templates/homeTemplate.html
  4. 13 12
      counter/urls.py
  5. 30 7
      counter/views.py

+ 5 - 1
counter/models.py

42
                                          locale='fr'), self.reason)
42
                                          locale='fr'), self.reason)
43
         else:
43
         else:
44
             return '%s à %s : %s (%s)' % (self.who, self.counter,
44
             return '%s à %s : %s (%s)' % (self.who, self.counter,
45
-                                           format_timedelta(
45
+                                          format_timedelta(
46
                                               datetime.now() -
46
                                               datetime.now() -
47
                                               self.timestamp.replace(
47
                                               self.timestamp.replace(
48
                                                   tzinfo=None),
48
                                                   tzinfo=None),
61
     class Meta:
61
     class Meta:
62
         verbose_name = 'like'
62
         verbose_name = 'like'
63
         verbose_name_plural = 'likes'
63
         verbose_name_plural = 'likes'
64
+        unique_together = ('liker', 'reset')
65
+
66
+    def __str__(self):
67
+        return '%s aime %s' % (self.liker, self.reset)

+ 27 - 1
counter/templates/counterTemplate.html

9
     <div class="col-md-3">
9
     <div class="col-md-3">
10
       <div class="panel panel-primary">
10
       <div class="panel panel-primary">
11
         <div class="panel-heading">
11
         <div class="panel-heading">
12
-          <h2 class="panel-title">Dernier seum {% if not counter.lastReset.noSeum %}<span class="badge pull-right">{{ counter.seumCount }}</span>{% endif %}</h2>
12
+            <form action="{% url 'like' %}" method="POST" name="like{{counter.id}}">
13
+                {% csrf_token %}
14
+                <input type="hidden" name="liker" value="{{myCounter.id}}" />
15
+                <input type="hidden" name="reset" value="{{counter.lastReset.id}}" <h2 class="panel-title" />
16
+                <input type="hidden" name="redirect" value="{% url 'counter' id_counter=counter.id %}" />
17
+                <a class="counter-link" href="{% url 'counter' id_counter=counter.id %}">
18
+                    <b>{{ counter.trigramme }}</b> <small>{{ counter.name }}</small>
19
+                </a>
20
+                {% if not counter.lastReset.noSeum %}
21
+                {% if counter.alreadyLiked %}
22
+                <span class="pull-right badge">
23
+                    <span class="glyphicon glyphicon-ok" />&nbsp;{{ counter.likeCount }}
24
+                </span>
25
+                {% elif counter.id == myCounter.id %}
26
+                <span class="pull-right badge">
27
+                    <span class="glyphicon glyphicon-fire" />&nbsp;{{ counter.likeCount }}
28
+                </span>
29
+                {% else %}
30
+                <a class="pull-right badge" onclick="document.forms['like{{counter.id}}'].submit();">
31
+                    <span class="glyphicon glyphicon-fire" />&nbsp;{{ counter.likeCount }}
32
+                </a>
33
+                {% endif %}
34
+                {% endif %}
35
+                </h2>
36
+            </form>
13
         </div>
37
         </div>
14
         <div class="seum-counter panel-body" style="height:125px" id="container{{counter.id}}">
38
         <div class="seum-counter panel-body" style="height:125px" id="container{{counter.id}}">
15
           {% if counter.lastReset.noSeum %}
39
           {% if counter.lastReset.noSeum %}
74
                 <th>Date</th>
98
                 <th>Date</th>
75
                 <th>Motif</th>
99
                 <th>Motif</th>
76
                 <th>Fouteur de seum</th>
100
                 <th>Fouteur de seum</th>
101
+                <th>Nombre de likes</th>
77
               </tr>
102
               </tr>
78
             </thead>
103
             </thead>
79
             <tbody>
104
             <tbody>
86
                     {{ reset.who.trigramme }}
111
                     {{ reset.who.trigramme }}
87
                 {% endif %}
112
                 {% endif %}
88
                 </td>
113
                 </td>
114
+                <td>{{ reset.likeCount }}</td>
89
               </tr>
115
               </tr>
90
               {% endfor %}
116
               {% endfor %}
91
             </tbody>
117
             </tbody>

+ 30 - 8
counter/templates/homeTemplate.html

7
 		<div class="col-sm-6">
7
 		<div class="col-sm-6">
8
 			<div class="panel panel-primary">
8
 			<div class="panel panel-primary">
9
 				<div class="panel-heading">
9
 				<div class="panel-heading">
10
-					<a class="counter-link" href="{% url 'counter' id_counter=myCounter.id %}">
11
-						<h2 class="panel-title"><b>{{ myCounter.trigramme }}</b> <small>{{ myCounter.name }}</small>
12
-							{% if not myCounter.lastReset.noSeum %}<span class="pull-right badge">{{ myCounter.seumCount }}</span>{% endif %}
10
+					<h2 class="panel-title">
11
+						<a class="counter-link panel-title" href="{% url 'counter' id_counter=myCounter.id %}">
12
+							<b>{{ myCounter.trigramme }}</b> <small>{{ myCounter.name }}</small>
13
+						</a>
14
+						{% if not myCounter.lastReset.noSeum %}
15
+							<span class="pull-right badge">
16
+								<span class="glyphicon glyphicon-fire" />&nbsp;{{ myCounter.likeCount }}
17
+							</span>
18
+						{% endif %}
13
 						</h2>
19
 						</h2>
14
-					</a>
15
 				</div>
20
 				</div>
16
 				<div class="primary-counter panel-body" id="container{{myCounter.id}}">
21
 				<div class="primary-counter panel-body" id="container{{myCounter.id}}">
17
 					<div style="width:100%;">
22
 					<div style="width:100%;">
85
 		<div class="col-md-3 col-sm-4 col-lg-2">
90
 		<div class="col-md-3 col-sm-4 col-lg-2">
86
 			<div class="panel panel-{{counter.CSSclass}}" style="opacity:{{counter.opacity}}">
91
 			<div class="panel panel-{{counter.CSSclass}}" style="opacity:{{counter.opacity}}">
87
 				<div class="panel-heading">
92
 				<div class="panel-heading">
88
-					<a class="counter-link" href="{% url 'counter' id_counter=counter.id %}">
89
-						<h2 class="panel-title"><b>{{ counter.trigramme }}</b> <small>{{ counter.name }}</small>
90
-							{% if not counter.lastReset.noSeum %}<span class="pull-right badge">{{ counter.seumCount }}</span>{% endif %}
93
+					<form action="{% url 'like' %}" method="POST" name="like{{counter.id}}">
94
+						{% csrf_token %}
95
+						<input type="hidden" name="liker" value="{{myCounter.id}}" />
96
+						<input type="hidden" name="redirect" value="{% url 'counter' id_counter=counter.id %}" />
97
+						<input type="hidden" name="reset" value="{{counter.lastReset.id}}" />
98
+						<h2 class="panel-title">
99
+							<a class="counter-link" href="{% url 'counter' id_counter=counter.id %}">
100
+								<b>{{ counter.trigramme }}</b> <small>{{ counter.name }}</small>
101
+							</a>
102
+							{% if not counter.lastReset.noSeum %}
103
+							{% if counter.alreadyLiked %}
104
+							<span class="pull-right badge">
105
+								<span class="glyphicon glyphicon-ok" />&nbsp;{{ counter.likeCount }}
106
+							</span>
107
+							{% else %}
108
+							<a class="pull-right badge" onclick="document.forms['like{{counter.id}}'].submit();">
109
+								<span class="glyphicon glyphicon-fire" />&nbsp;{{ counter.likeCount }}
110
+							</a>
111
+							{% endif %}
112
+							{% endif %}
91
 						</h2>
113
 						</h2>
92
-					</a>
114
+					</form>
93
 				</div>
115
 				</div>
94
 				<div class="seum-counter panel-body">
116
 				<div class="seum-counter panel-body">
95
 					{% if counter.lastReset.noSeum %}
117
 					{% if counter.lastReset.noSeum %}

+ 13 - 12
counter/urls.py

6
 from . import views
6
 from . import views
7
 
7
 
8
 urlpatterns = [
8
 urlpatterns = [
9
-    url(r'^$', views.home, name="home"),
10
-    url(r'^reset-counter/$', views.resetCounter, name="reset-counter"),
11
-    url(r'^counter/(?P<id_counter>\d+)/$', views.counter, name="counter"),
9
+    url(r'^$', views.home, name='home'),
10
+    url(r'^reset-counter/$', views.resetCounter, name='reset-counter'),
11
+    url(r'^counter/(?P<id_counter>\d+)/$', views.counter, name='counter'),
12
     url(r'^rss/$', SeumFeed()),
12
     url(r'^rss/$', SeumFeed()),
13
-    url(r'^create_user/$', views.createUser, name="create_user"),
13
+    url(r'^create_user/$', views.createUser, name='create_user'),
14
+    url(r'^like/$', views.like, name='like'),
14
     url(r'^toggle-notif/$', views.toggleEmailNotifications,
15
     url(r'^toggle-notif/$', views.toggleEmailNotifications,
15
-        name="toggle_email_notifications"),
16
+        name='toggle_email_notifications'),
16
     url(r'^login/$', auth_views.login,
17
     url(r'^login/$', auth_views.login,
17
         {'template_name': 'login.html'},
18
         {'template_name': 'login.html'},
18
-        name="login"),
19
+        name='login'),
19
     url(r'^logout/$', auth_views.logout_then_login,
20
     url(r'^logout/$', auth_views.logout_then_login,
20
         name='logout'),
21
         name='logout'),
21
     url(r'^password/change/$', auth_views.password_change,
22
     url(r'^password/change/$', auth_views.password_change,
22
         {'template_name': 'passwordChange.html'},
23
         {'template_name': 'passwordChange.html'},
23
-        name="password_change"),
24
+        name='password_change'),
24
     url(r'^password/change/done∕$', auth_views.password_change_done,
25
     url(r'^password/change/done∕$', auth_views.password_change_done,
25
         {'template_name': 'passwordChangeDone.html'},
26
         {'template_name': 'passwordChangeDone.html'},
26
-        name="password_change_done"),
27
+        name='password_change_done'),
27
     url(r'^password/reset/$', auth_views.password_reset,
28
     url(r'^password/reset/$', auth_views.password_reset,
28
         {'template_name': 'passwordReset.html',
29
         {'template_name': 'passwordReset.html',
29
          'email_template_name': 'resetEmail.txt',
30
          'email_template_name': 'resetEmail.txt',
30
          'subject_template_name': 'subjectEmail.txt'},
31
          'subject_template_name': 'subjectEmail.txt'},
31
-        name="password_reset"),
32
+        name='password_reset'),
32
     url(r'^password/reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
33
     url(r'^password/reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
33
         auth_views.password_reset_confirm,
34
         auth_views.password_reset_confirm,
34
         {'template_name': 'passwordResetConfirm.html'},
35
         {'template_name': 'passwordResetConfirm.html'},
35
-        name="password_reset_confirm"),
36
+        name='password_reset_confirm'),
36
     url(r'^password/reset/complete/$',
37
     url(r'^password/reset/complete/$',
37
         auth_views.password_reset_complete,
38
         auth_views.password_reset_complete,
38
         {'template_name': 'passwordResetComplete.html'},
39
         {'template_name': 'passwordResetComplete.html'},
39
-        name="password_reset_complete"),
40
+        name='password_reset_complete'),
40
     url(r'^password/reset/done/$',
41
     url(r'^password/reset/done/$',
41
         auth_views.password_reset_done,
42
         auth_views.password_reset_done,
42
         {'template_name': 'passwordResetDone.html'},
43
         {'template_name': 'passwordResetDone.html'},
43
-        name="password_reset_done"),
44
+        name='password_reset_done'),
44
     url(r'^', RedirectView.as_view(pattern_name='home')),
45
     url(r'^', RedirectView.as_view(pattern_name='home')),
45
 ]
46
 ]

+ 30 - 7
counter/views.py

1
 from django.shortcuts import render
1
 from django.shortcuts import render
2
-from counter.models import Counter, Reset
2
+from counter.models import Counter, Reset, Like
3
 from django.contrib.auth.models import User
3
 from django.contrib.auth.models import User
4
 from babel.dates import format_timedelta, format_datetime
4
 from babel.dates import format_timedelta, format_datetime
5
 from datetime import datetime, timedelta
5
 from datetime import datetime, timedelta
51
                 myCounter.lastReset.selfSeum = False
51
                 myCounter.lastReset.selfSeum = False
52
             myCounter.lastReset.delta = datetime.now(
52
             myCounter.lastReset.delta = datetime.now(
53
             ) - myCounter.lastReset.timestamp.replace(tzinfo=None)
53
             ) - myCounter.lastReset.timestamp.replace(tzinfo=None)
54
-            myCounter.seumCount = Reset.objects.filter(
55
-                counter=myCounter).count()
54
+            myCounter.likeCount = Like.objects.filter(
55
+                reset=myCounter.lastReset).count()
56
         myCounter.lastReset.formatted_delta = format_timedelta(
56
         myCounter.lastReset.formatted_delta = format_timedelta(
57
             myCounter.lastReset.delta, locale='fr', threshold=1)
57
             myCounter.lastReset.delta, locale='fr', threshold=1)
58
     except Counter.DoesNotExist:
58
     except Counter.DoesNotExist:
61
     # Building data for counters display
61
     # Building data for counters display
62
     counters = Counter.objects.all()
62
     counters = Counter.objects.all()
63
     for counter in counters:
63
     for counter in counters:
64
-        #Only the last reset is displayed
64
+        # Only the last reset is displayed
65
         lastReset = Reset.objects.filter(
65
         lastReset = Reset.objects.filter(
66
             counter=counter).order_by('-timestamp')
66
             counter=counter).order_by('-timestamp')
67
         if (lastReset.count() == 0):  # This person never had the seum
67
         if (lastReset.count() == 0):  # This person never had the seum
101
             counter.opacity = 0.4 + 0.6 * \
101
             counter.opacity = 0.4 + 0.6 * \
102
                 math.exp(-(counter.lastReset.delta.total_seconds()) /
102
                 math.exp(-(counter.lastReset.delta.total_seconds()) /
103
                          (7 * 24 * 3600))
103
                          (7 * 24 * 3600))
104
-            # Computing the total number of resets for this counter
105
-            counter.seumCount = Reset.objects.filter(
106
-                counter=counter).count()
104
+            # Computing the total number of likes for this counter
105
+            counter.likeCount = Like.objects.filter(
106
+                reset=counter.lastReset).count()
107
+            counter.alreadyLiked = (Like.objects.filter(
108
+                reset=counter.lastReset, liker=myCounter).exists())
109
+
107
         counter.lastReset.formatted_delta = format_timedelta(
110
         counter.lastReset.formatted_delta = format_timedelta(
108
             counter.lastReset.delta, locale='fr', threshold=1)
111
             counter.lastReset.delta, locale='fr', threshold=1)
109
         counter.isHidden = "hidden"
112
         counter.isHidden = "hidden"
327
         seumFrequency = format_timedelta((
330
         seumFrequency = format_timedelta((
328
             datetime.now() - firstReset.timestamp.replace(tzinfo=None)) /
331
             datetime.now() - firstReset.timestamp.replace(tzinfo=None)) /
329
             counter.seumCount, locale='fr', threshold=1)
332
             counter.seumCount, locale='fr', threshold=1)
333
+        counter.alreadyLiked = (Like.objects.filter(
334
+            reset=counter.lastReset, liker=myCounter).exists())
335
+        counter.likeCount = Like.objects.filter(
336
+            reset=counter.lastReset).count()
330
 
337
 
331
     for reset in resets:
338
     for reset in resets:
332
         if (reset.who is None or
339
         if (reset.who is None or
337
         reset.date = format_datetime(
344
         reset.date = format_datetime(
338
             reset.timestamp, locale='fr',
345
             reset.timestamp, locale='fr',
339
             format="dd/MM/Y HH:mm")
346
             format="dd/MM/Y HH:mm")
347
+        reset.likeCount = Like.objects.filter(reset=reset).count()
348
+
340
     # Timeline graph
349
     # Timeline graph
341
     # Data pre-processing
350
     # Data pre-processing
342
     if not counter.lastReset.noSeum:
351
     if not counter.lastReset.noSeum:
429
     counter.email_notifications = not counter.email_notifications
438
     counter.email_notifications = not counter.email_notifications
430
     counter.save()
439
     counter.save()
431
     return HttpResponseRedirect(reverse('home'))
440
     return HttpResponseRedirect(reverse('home'))
441
+
442
+
443
+@login_required
444
+def like(request):
445
+    if (request.method == 'POST'):
446
+        # create a form instance and populate it with data from the request:
447
+        data = dict(request.POST)
448
+        liker = Counter.objects.get(pk=data['liker'][0])
449
+        reset = Reset.objects.get(pk=data['reset'][0])
450
+        like = Like()
451
+        like.liker = liker
452
+        like.reset = reset
453
+        like.save()
454
+    return HttpResponseRedirect(data['redirect'][0])