workon on notifications: user home, user notifications page, triggers in signals
authordurandn
Thu, 04 Aug 2016 15:01:27 +0200
changeset 98 2b738b88d483
parent 97 f747c112e8f4
child 99 21ed0482625b
workon on notifications: user home, user notifications page, triggers in signals
src/iconolab/models.py
src/iconolab/signals/handlers.py
src/iconolab/static/iconolab/css/iconolab.css
src/iconolab/templates/iconolab/user_home.html
src/iconolab/templates/iconolab/user_notifications.html
src/iconolab/templates/iconolab_base.html
src/iconolab/templates/partials/header.html
src/iconolab/urls.py
src/iconolab/views/iconolab.py
--- a/src/iconolab/models.py	Wed Aug 03 15:47:03 2016 +0200
+++ b/src/iconolab/models.py	Thu Aug 04 15:01:27 2016 +0200
@@ -230,7 +230,8 @@
         if revision_to_reject.state == AnnotationRevision.AWAITING:
             revision_to_reject.state = AnnotationRevision.REJECTED
             revision_to_reject.save()
-        
+            iconolab_signals.revision_rejected.send(sender=AnnotationRevision, instance=revision_to_reject)
+    
     # Call when we're validating an awaiting revision whose parent isn't the current revision OR IF IT WAS CHANGED BY THE ANNOTATION AUTHOR
     @transaction.atomic
     def merge_existing_revision(self, title, description, fragment, tags, revision_to_merge):
@@ -313,13 +314,16 @@
             sparql_template = 'select distinct * where { <<%uri%>> rdfs:label ?l FILTER( langMatches( lang(?l), "<%lang%>" ) ) }' 
             sparql_query = re.sub("<%uri%>", uri, re.sub("<%lang%>", lang, sparql_template))
             sparql_query_url = source+'sparql'
-            dbpedia_resp = requests.get(
-                sparql_query_url, 
-                params={
-                        "query": sparql_query,
-                        "format": "json"
-                }
-            )
+            try:
+                dbpedia_resp = requests.get(
+                    sparql_query_url, 
+                    params={
+                            "query": sparql_query,
+                            "format": "json"
+                    }
+                )
+            except:
+                pass
             try:
                 results = json.loads(dbpedia_resp.text).get("results", {})
             except:
--- a/src/iconolab/signals/handlers.py	Wed Aug 03 15:47:03 2016 +0200
+++ b/src/iconolab/signals/handlers.py	Thu Aug 04 15:01:27 2016 +0200
@@ -2,10 +2,10 @@
 from django.db.models.signals import post_save
 from django.dispatch import Signal, receiver
 from notifications.signals import notify
-from django_comments.signals import comment_was_posted
 
 # Signal sent during method Annotation.validate_existing_revision to update stats
 revision_accepted = Signal(providing_args=['instance'])
+revision_rejected = Signal(providing_args=['instance'])
 revision_created = Signal(providing_args=['instance'])
 
 
@@ -17,6 +17,8 @@
         annotation.stats.submitted_revisions_count += 1
         if instance.state in [AnnotationRevision.ACCEPTED, AnnotationRevision.STUDIED]:
             annotation.stats.accepted_revisions_count += 1
+        if instance.state == AnnotationRevision.ACCEPTED and instance.merge_parent_revision.state == AnnotationRevision.STUDIED:
+            annotation.stats.awaiting_revisions_count -= 1
         if instance.state in [AnnotationRevision.AWAITING]:
             annotation.stats.awaiting_revisions_count += 1
         annotation.stats.set_tags_stats()
@@ -28,7 +30,7 @@
         image.stats.save()
         
     
-def increment_stats_on_new_comments(sender, instance, created, **kwargs):
+def increment_stats_on_new_comment(sender, instance, created, **kwargs):
     from iconolab.models import IconolabComment
     if created and sender == IconolabComment:
         model = apps.get_model(instance.content_type.app_label,instance.content_type.model)
@@ -40,11 +42,19 @@
         annotation.image.stats.save()
 
 
-def increment_accepted_revisions(sender, instance, **kwargs):
+def increment_stats_on_accepted_revision(sender, instance, **kwargs):
     from iconolab.models import AnnotationRevision
     if sender == AnnotationRevision:
         annotation = instance.annotation
         annotation.stats.accepted_revisions_count += 1
+        annotation.stats.awaiting_revisions_count -= 1
+        annotation.stats.save()
+
+def increment_stats_on_rejected_revision(sender, instance, **kwargs):
+    from iconolab.models import AnnotationRevision
+    if sender == AnnotationRevision:
+        annotation = instance.annotation
+        annotation.stats.awaiting_revisions_count -= 1
         annotation.stats.save()
 
 def increment_annotations_count(sender, instance, created, **kwargs):
@@ -57,18 +67,18 @@
         image.stats.save()
 
 
-def notify_users_on_new_comment(sender, comment, **kwargs):
+def notify_users_on_new_comment(sender, instance, **kwargs):
     from iconolab.models import IconolabComment, Annotation, MetaCategory
+    print(sender)
     if sender == IconolabComment and instance.content_type.app_label == 'iconolab' and instance.content_type.model == 'annotation':
         comment_annotation = Annotation.objects.get(id=instance.object_pk)
         # Notifying new user comment
         if instance.user != comment_annotation.author:
             notify.send(instance.user, recipient=comment_annotation.author, verb='a écrit un commentaire sur votre annotation', action_object=instance, target=comment_annotation)
-        print(instance.parent_id)
-        print(instance.id)
-        if instance.level > 0:
+        if instance.parent_id and instance.level > 0: # We check parent_id as django comment xtd saves comments in two steps and only set the information we need in the second step
             parent_comment = IconolabComment.objects.get(id=instance.parent_id)
             notify.send(instance.user, recipient=parent_comment.user, verb='a répondu à votre commentaire', action_object=instance, target=comment_annotation)
+
         for metacategory in instance.metacategories.all():
             if metacategory.triggers_notifications == MetaCategory.COMMENTERS:
                 for commenter in comment_annotation.stats.commenters.exclude(id=instance.user.id).all():
@@ -95,11 +105,12 @@
 
 # Stats handlers connect
 post_save.connect(increment_annotations_count)
-post_save.connect(increment_stats_on_new_comments)
+post_save.connect(increment_stats_on_new_comment)
 revision_created.connect(increment_stats_on_new_revision)
-revision_accepted.connect(increment_accepted_revisions)
+revision_accepted.connect(increment_stats_on_accepted_revision)
+revision_rejected.connect(increment_stats_on_rejected_revision)
 # Notifications handlers connect
-comment_was_posted.connect(notify_users_on_new_comment)
+post_save.connect(notify_users_on_new_comment)
 revision_created.connect(notify_users_on_new_revision)
 revision_accepted.connect(notify_users_on_accepted_revision)
         
\ No newline at end of file
--- a/src/iconolab/static/iconolab/css/iconolab.css	Wed Aug 03 15:47:03 2016 +0200
+++ b/src/iconolab/static/iconolab/css/iconolab.css	Thu Aug 04 15:01:27 2016 +0200
@@ -103,4 +103,7 @@
 
 .notif-badge{
   margin-bottom: 5px;
+}
+.show-all-notifications{
+  cursor: pointer;
 }
\ No newline at end of file
--- a/src/iconolab/templates/iconolab/user_home.html	Wed Aug 03 15:47:03 2016 +0200
+++ b/src/iconolab/templates/iconolab/user_home.html	Thu Aug 04 15:01:27 2016 +0200
@@ -5,6 +5,7 @@
 {% load thumbnail %}
 
 {% load iconolab_tags %}
+
 {% load notifications_tags %}
 
 {% block content %}
@@ -14,8 +15,9 @@
       <h3>{% if profile_user == request.user %}Mon espace:{% else %}Profil: {% endif %} {{profile_user.username}}</h3>
       <div class="panel panel-default" style="padding-left: 10px; padding-right: 10px;">
         {% if profile_user == request.user %}
-        <h4><span class="badge notif-badge {% if notifications.unread %}badge-error{% endif %}">{{notifications.unread.count}}</span> Notifications non lues 
-          <a href=# class="btn btn-default btn-xs">Voir toutes mes notifications</a>
+        {% notifications_unread as unread_count %}
+        <h4><span class="badge notif-badge {% if unread_count %}badge-error{% endif %}">{{unread_count}}</span> Notifications non lues 
+          <a href="{% url 'user_notifications' %}" class="btn btn-default btn-xs">Voir toutes mes notifications</a>
           <a href=# class="btn btn-default btn-xs">Tout marquer comme lu</a>
         </h4>
         <div class="row">
@@ -26,7 +28,7 @@
                 <a  
                   {% if notification.target and notification.action_object %}
                     {% with notification.target as annotation %}
-                      class="list-group-item"
+                      class="list-group-item list-group-item-info {% if forloop.counter > 5 %}hide-on-load{% endif %}"
                       {% if notification.action_object.get_comment_page %}
                       href="{% url 'annotation_detail' annotation.image.item.collection.name annotation.image.image_guid annotation.annotation_guid %}?page={{notification.action_object.get_comment_page}}#c{{notification.action_object.id}}"
                       {% else %}
@@ -34,10 +36,13 @@
                       {% endif %}
                     {% endwith %}
                   {% else %}
-                    class="list-group-item disabled"
+                    class="list-group-item disabled {% if forloop.counter > 5 %}hide-on-load{% endif %}"
                   {% endif %}>
                   <b>{{notification.actor.username}}</b> {{notification.verb}} <small> - {{notification.timesince}}</small>
                 </a>
+                {% if forloop.counter == 5 %}
+                  <a class="list-group-item show-all-notifications" title="Montrer autres notifications"> ... </a>
+                {% endif %}
               {% endfor %}
               </ul>
             {% endif %}
@@ -70,7 +75,7 @@
                       <dt>Commentaires: </dt>
                       <dd><span class="badge">{{annotation.stats.comments_count}}</span></dd>
                       <dt>Révisions en attente:</dt>
-                      <dd><span class="badge {% if annotation.awaiting_revisions_count > 0 %}badge-warning{% endif %}">{{annotation.awaiting_revisions_count}}</span></dd>
+                      <dd><span class="badge {% if annotation.stats.awaiting_revisions_count > 0 %}badge-warning{% endif %}">{{annotation.stats.awaiting_revisions_count}}</span></dd>
                     </dl>
                   </div>
               </div>
@@ -103,4 +108,14 @@
       </div>
     </div>
   </div>
+{% endblock %}
+
+{% block footer_js %}
+  <script>
+  	$(".hide-on-load").hide()
+  	$(".show-all-notifications").click(function(){
+  	  	$(".show-all-notifications").hide();
+  	    $(".hide-on-load").slideDown();
+  	})
+  </script>
 {% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/templates/iconolab/user_notifications.html	Thu Aug 04 15:01:27 2016 +0200
@@ -0,0 +1,40 @@
+{% extends 'iconolab_base.html' %}
+
+{% load staticfiles %}
+
+{% load thumbnail %}
+
+{% load iconolab_tags %}
+
+{% load notifications_tags %}
+
+{% block content %}
+  <div id="user-profile-block" class="row" style="border: 1px solid gray; padding-top:15px;">
+    <div class="col-md-12">
+      <div class="panel panel-default" style="padding-bottom: 10px; padding-left:10px; padding-right: 10px;">
+          <h3>Mes notifications: </h3>
+          {% if notifications %}
+            <ul class="list-group">
+            {% for notification in notifications %}
+              <a  
+                {% if notification.target and notification.action_object %}
+                  {% with notification.target as annotation %}
+                    class="list-group-item {% if notification.id in notifications_unread_ids %}list-group-item-info{% endif %}"
+                    {% if notification.action_object.get_comment_page %}
+                    href="{% url 'annotation_detail' annotation.image.item.collection.name annotation.image.image_guid annotation.annotation_guid %}?page={{notification.action_object.get_comment_page}}#c{{notification.action_object.id}}"
+                    {% else %}
+                    href="{% url 'revision_detail' annotation.image.item.collection.name annotation.image.image_guid annotation.annotation_guid notification.action_object.revision_guid %}"
+                    {% endif %}
+                  {% endwith %}
+                {% else %}
+                  class="list-group-item disabled {% if forloop.counter > 5 %}hide-on-load{% endif %}"
+                {% endif %}>
+                <b>{{notification.actor.username}}</b> {{notification.verb}} <small> - {{notification.timesince}}</small>
+              </a>
+            {% endfor %}
+            </ul>
+          {% endif %}
+      </div>
+    </div>
+  </div>
+{% endblock %}
\ No newline at end of file
--- a/src/iconolab/templates/iconolab_base.html	Wed Aug 03 15:47:03 2016 +0200
+++ b/src/iconolab/templates/iconolab_base.html	Thu Aug 04 15:01:27 2016 +0200
@@ -1,4 +1,7 @@
 {% load staticfiles %}
+
+{% load notifications_tags %}
+
 <!DOCTYPE html>
 <html>
 
--- a/src/iconolab/templates/partials/header.html	Wed Aug 03 15:47:03 2016 +0200
+++ b/src/iconolab/templates/partials/header.html	Thu Aug 04 15:01:27 2016 +0200
@@ -1,3 +1,4 @@
+{% load notifications_tags %}
 <nav class="navbar navbar-default" style="">
   <div class="container-fluid">
     <div class="navbar-header">
@@ -25,7 +26,8 @@
 
       <ul class="nav navbar-nav navbar-right">
         {% if request.user.is_authenticated %}
-          <li><a href="{% url 'user_home' request.user.id %}">{{user.username}}: Mon espace</a></li>
+          {% notifications_unread as unread_count %}
+          <li><a href="{% url 'user_home' request.user.id %}">{{user.username}}: Mon espace <span class="badge {% if unread_count %}badge-error{% endif %}">{{ unread_count }}</span></a></li>
           <li><a href="{% url 'account:logout' %}">Se déconnecter</a></li>
         {% else %}
           <li><a href="{% url 'account:register' %}">Créer un compte</a></li>
--- a/src/iconolab/urls.py	Wed Aug 03 15:47:03 2016 +0200
+++ b/src/iconolab/urls.py	Thu Aug 04 15:01:27 2016 +0200
@@ -36,7 +36,8 @@
     url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/edit$', login_required(views.iconolab.EditAnnotationView.as_view()), name='annotation_edit'),
     url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/revisions/(?P<revision_guid>[^/]+)/detail', views.iconolab.ShowRevisionView.as_view(), name='revision_detail'),
     url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/revisions/(?P<revision_guid>[^/]+)/merge$', login_required(views.iconolab.MergeProposalView.as_view()), name='annotation_merge'),
-    url(r'^user/(?P<slug>[a-z0-9\-]+)/home/', views.iconolab.UserHomeView.as_view(), name="user_home"),
+    url(r'^user/(?P<slug>[a-z0-9\-]+)/home/?$', views.iconolab.UserHomeView.as_view(), name="user_home"),
+    url(r'^user/notifications/all/?$', login_required(views.iconolab.UserNotificationsView.as_view()), name="user_notifications"),
     url(r'^errors/404', views.iconolab.NotFoundErrorView.as_view(), name="404error"),
     url(r'^rest', include('restapi.urls')),
     url(r'^account/', include('iconolab.auth.urls', namespace='account')),
--- a/src/iconolab/views/iconolab.py	Wed Aug 03 15:47:03 2016 +0200
+++ b/src/iconolab/views/iconolab.py	Thu Aug 04 15:01:27 2016 +0200
@@ -56,6 +56,17 @@
             context["notifications"] = Notification.objects.filter(recipient=request.user)
         return render(request, 'iconolab/user_home.html', context)
 
+class UserNotificationsView(View):
+    
+    def get(self, request, *args, **kwargs):
+        print("WHATTHEFUCK")
+        context = {}
+        notifications = Notification.objects.filter(recipient=request.user)
+        context["notifications_unread_ids"] = notifications.unread().values_list("id", flat=True)
+        #notifications.mark_all_as_read()
+        context["notifications"] = notifications
+        return render(request, 'iconolab/user_notifications.html', context)
+
 
 class CollectionHomepageView(View, ContextMixin):
     def check_kwargs(self, kwargs):