changeset 114:535d02d1c017

Forums: Implemented unread status for topics and posts.
author Brian Neal <bgneal@gmail.com>
date Sun, 11 Oct 2009 20:27:07 +0000
parents d97ceb95ce02
children 0ce0104c7df3
files gpp/forums/unread.py gpp/forums/views.py gpp/templates/forums/display_post.html gpp/templates/forums/forum_index.html
diffstat 4 files changed, 99 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/gpp/forums/unread.py	Sun Oct 11 19:10:54 2009 +0000
+++ b/gpp/forums/unread.py	Sun Oct 11 20:27:07 2009 +0000
@@ -10,6 +10,7 @@
 
 THRESHOLD = datetime.timedelta(days=7)
 
+#######################################################################
 
 def get_forum_unread_status(qs, user):
     if not user.is_authenticated():
@@ -97,3 +98,90 @@
             # we are all caught up.
             forum.catchup(user, flv)
             forum.has_unread = False
+
+#######################################################################
+
+def get_topic_unread_status(forum, topics, user):
+
+    # Edge case: no topics 
+    if forum.last_post is None:
+        return
+
+    # This service isn't provided to unauthenticated users
+    if not user.is_authenticated():
+        for topic in topics:
+            topic.has_unread = False
+        return
+
+    now = datetime.datetime.now()
+
+    # Get the ForumLastVisit record
+    try:
+        flv = ForumLastVisit.objects.get(forum=forum, user=user)
+    except ForumLastVisit.DoesNotExist:
+        # One doesn't exist, create a default one for next time,
+        # mark it as having no unread topics, and bail.
+        flv = ForumLastVisit(user=user, forum=forum)
+        flv.begin_date = now
+        flv.end_date = now
+        flv.save()
+        for topic in topics:
+            topic.has_unread = False
+        return
+
+    # Are all the posts before our window? If so, all have been read.
+    if forum.last_post.creation_date < flv.begin_date:
+        for topic in topics:
+            topic.has_unread = False
+        return
+
+    topic_ids = [topic.id for topic in topics]
+    tlvs = TopicLastVisit.objects.filter(user=user, topic__id__in=topic_ids)
+    tlvs = dict([(tlv.topic.id, tlv) for tlv in tlvs])
+
+    # Otherwise we have to go through the topics one by one:
+    for topic in topics:
+        if topic.update_date < flv.begin_date:
+            topic.has_unread = False
+        elif topic.update_date > flv.end_date:
+            topic.has_unread = True
+        elif topic.id in tlvs:
+            topic.has_unread = topic.update_date > tlvs[topic.id].last_visit
+        else:
+            topic.has_unread = True
+
+#######################################################################
+
+def get_post_unread_status(topic, posts, user):
+    # This service isn't provided to unauthenticated users
+    if not user.is_authenticated():
+        for post in posts:
+            post.unread = False
+        return
+
+    # Get the ForumLastVisit record
+    try:
+        flv = ForumLastVisit.objects.get(forum=topic.forum, user=user)
+    except ForumLastVisit.DoesNotExist:
+        # One doesn't exist, all posts are old.
+        for post in posts:
+            post.unread = False
+        return
+
+    # Are all the posts before our window? If so, all have been read.
+    if topic.last_post.creation_date < flv.begin_date:
+        for post in posts:
+            post.unread = False
+        return
+
+    # Do we have a topic last visit record for this topic?
+
+    try:
+        tlv = TopicLastVisit.objects.get(user=user, topic=topic)
+    except TopicLastVisit.DoesNotExist:
+        # No we don't, we could be all caught up, or all are new
+        for post in posts:
+            post.unread = post.creation_date > flv.end_date
+    else:
+        for post in posts:
+            post.unread = post.creation_date > tlv.last_visit
--- a/gpp/forums/views.py	Sun Oct 11 19:10:54 2009 +0000
+++ b/gpp/forums/views.py	Sun Oct 11 20:27:07 2009 +0000
@@ -23,7 +23,8 @@
 from forums.models import Forum, Topic, Post, FlaggedPost, TopicLastVisit, \
         ForumLastVisit
 from forums.forms import NewTopicForm, NewPostForm, PostForm, MoveTopicForm
-from forums.unread import get_forum_unread_status
+from forums.unread import get_forum_unread_status, get_topic_unread_status, \
+        get_post_unread_status
 
 #######################################################################
 
@@ -71,6 +72,8 @@
         return HttpResponseForbidden()
 
     topics = forum.topics.select_related('user', 'last_post', 'last_post__user')
+    get_topic_unread_status(forum, topics, request.user)
+
     paginator = create_topic_paginator(topics)
     page_num = int(request.GET.get('page', 1))
     try:
@@ -105,6 +108,8 @@
     topic.save()
 
     posts = topic.posts.select_related()
+    get_post_unread_status(topic, posts, request.user)
+
     paginator = create_post_paginator(posts)
     page_num = int(request.GET.get('page', 1))
     try:
@@ -195,6 +200,7 @@
             return HttpResponseForbidden("You don't have permission to post in this topic.")
 
         post = form.save(request.user, request.META.get("REMOTE_ADDR", ""))
+        post.unread = True
         _bump_post_count(request.user)
         _update_last_visit(request.user, form.topic)
         return render_to_response('forums/display_post.html', {
--- a/gpp/templates/forums/display_post.html	Sun Oct 11 19:10:54 2009 +0000
+++ b/gpp/templates/forums/display_post.html	Sun Oct 11 20:27:07 2009 +0000
@@ -11,6 +11,7 @@
    </td>
    <td class="forum-post-body">
       <div class="forum-post-info quiet">
+      {% if post.unread %}<img src="{{ MEDIA_URL }}icons/new.png" alt="New" title="New" />{% endif %}
       <a href="{{ post.get_absolute_url }}"><img src="{{ MEDIA_URL }}icons/link.png" alt="Link" title="Link to this post" /></a>
          Posted on {{ post.creation_date|date:"M d, Y H:i" }}
          {% if can_moderate %}from IP: {{ post.user_ip }}{% endif %}
--- a/gpp/templates/forums/forum_index.html	Sun Oct 11 19:10:54 2009 +0000
+++ b/gpp/templates/forums/forum_index.html	Sun Oct 11 20:27:07 2009 +0000
@@ -30,7 +30,9 @@
    <tbody>
    {% for topic in page.object_list %}
       <tr class="{% cycle 'odd' 'even' %}">
-         <td>{% if topic.sticky %}<img src="{{ MEDIA_URL }}icons/asterisk_orange.png" alt="Sticky" title="Sticky" class="forums-topic-icon" />{% endif %}
+         <td>
+            {% if topic.has_unread %}<img src="{{ MEDIA_URL }}icons/new.png" alt="New Posts" title="New Posts" class="forums-topic-icon" />{% endif %}
+            {% if topic.sticky %}<img src="{{ MEDIA_URL }}icons/asterisk_orange.png" alt="Sticky" title="Sticky" class="forums-topic-icon" />{% endif %}
             {% if topic.locked %}<img src="{{ MEDIA_URL }}icons/lock.png" alt="Locked" title="Locked"
             class="forums-topic-icon" />{% endif %}
          <h4><a href="{{ topic.get_absolute_url }}">{{ topic.name }}</a></h4></td>