annotate gpp/forums/unread.py @ 133:c515b7401078

Use the new common way to apply markItUp to textareas and to get the smiley and markdown help dialogs for all the remaining apps except for forums and comments.
author Brian Neal <bgneal@gmail.com>
date Fri, 27 Nov 2009 00:21:47 +0000
parents 535d02d1c017
children 35a0e6345815
rev   line source
bgneal@113 1 """
bgneal@113 2 This file contains routines for implementing the "has unread" feature.
bgneal@113 3 Forums, topics, and posts are displayed with a visual indication if they have
bgneal@113 4 been read or not.
bgneal@113 5 """
bgneal@113 6 import datetime
bgneal@113 7
bgneal@113 8 from forums.models import ForumLastVisit, TopicLastVisit, Topic
bgneal@113 9
bgneal@113 10
bgneal@113 11 THRESHOLD = datetime.timedelta(days=7)
bgneal@113 12
bgneal@114 13 #######################################################################
bgneal@113 14
bgneal@113 15 def get_forum_unread_status(qs, user):
bgneal@113 16 if not user.is_authenticated():
bgneal@113 17 for forum in qs:
bgneal@113 18 forum.has_unread = False
bgneal@113 19 return
bgneal@113 20
bgneal@113 21 now = datetime.datetime.now()
bgneal@113 22 min_date = now - THRESHOLD
bgneal@113 23
bgneal@113 24 # retrieve ForumLastVisit records in one SQL query
bgneal@113 25 forum_ids = [forum.id for forum in qs]
bgneal@113 26 flvs = ForumLastVisit.objects.filter(user=user,
bgneal@113 27 forum__in=forum_ids).select_related()
bgneal@113 28 flvs = dict([(flv.forum.id, flv) for flv in flvs])
bgneal@113 29
bgneal@113 30 for forum in qs:
bgneal@113 31 # Edge case: forum has no posts
bgneal@113 32 if forum.last_post is None:
bgneal@113 33 forum.has_unread = False
bgneal@113 34 continue
bgneal@113 35
bgneal@113 36 # Get the ForumLastVisit record
bgneal@113 37 if forum.id in flvs:
bgneal@113 38 flv = flvs[forum.id]
bgneal@113 39 else:
bgneal@113 40 # One doesn't exist, create a default one for next time,
bgneal@113 41 # mark it as having no unread topics, and bail.
bgneal@113 42 flv = ForumLastVisit(user=user, forum=forum)
bgneal@113 43 flv.begin_date = now
bgneal@113 44 flv.end_date = now
bgneal@113 45 flv.save()
bgneal@113 46 forum.has_unread = False
bgneal@113 47 continue
bgneal@113 48
bgneal@113 49 # If the last visit record was too far in the past,
bgneal@113 50 # catch that user up and mark as no unreads.
bgneal@113 51 if now - flv.end_date > THRESHOLD:
bgneal@113 52 forum.catchup(user, flv)
bgneal@113 53 forum.has_unread = False
bgneal@113 54 continue
bgneal@113 55
bgneal@113 56 # Check the easy cases first. Check the last_post in the
bgneal@113 57 # forum. If created after the end_date in our window, there
bgneal@113 58 # are new posts. Likewise, if before the begin_date in our window,
bgneal@113 59 # there are no new posts.
bgneal@113 60 if forum.last_post.creation_date > flv.end_date:
bgneal@113 61 forum.has_unread = True
bgneal@113 62 elif forum.last_post.creation_date < flv.begin_date:
bgneal@113 63 if not flv.is_caught_up():
bgneal@113 64 forum.catchup(user, flv)
bgneal@113 65 forum.has_unread = False
bgneal@113 66 else:
bgneal@113 67 # Going to have to examine the topics in our window.
bgneal@113 68 # First adjust our window if it is too old.
bgneal@113 69 if now - flv.begin_date > THRESHOLD:
bgneal@113 70 flv.begin_date = min_date
bgneal@113 71 flv.save()
bgneal@113 72 TopicLastVisit.objects.filter(user=user, topic__forum=forum,
bgneal@113 73 last_visit__lt=min_date).delete()
bgneal@113 74
bgneal@113 75 topics = Topic.objects.filter(creation_date__gt=flv.begin_date)
bgneal@113 76 tracked_topics = TopicLastVisit.objects.filter(user=user,
bgneal@113 77 topic__forum=forum, last_visit__gt=flv.begin_date)
bgneal@113 78
bgneal@113 79 # If the number of topics created since our window was started
bgneal@113 80 # is greater than the tracked topic records, then there are new
bgneal@113 81 # posts.
bgneal@113 82 if topics.count() > tracked_topics.count():
bgneal@113 83 forum.has_unread = True
bgneal@113 84 continue
bgneal@113 85
bgneal@113 86 tracked_dict = dict([(t.id, t) for t in tracked_topics])
bgneal@113 87
bgneal@113 88 for topic in topics:
bgneal@113 89 if topic.id in tracked_dict:
bgneal@113 90 if topic.update_date > tracked_dict[topic.id].last_visit:
bgneal@113 91 forum.has_unread = True
bgneal@113 92 continue
bgneal@113 93 else:
bgneal@113 94 forum.has_unread = True
bgneal@113 95 continue
bgneal@113 96
bgneal@113 97 # If we made it through the above loop without continuing, then
bgneal@113 98 # we are all caught up.
bgneal@113 99 forum.catchup(user, flv)
bgneal@113 100 forum.has_unread = False
bgneal@114 101
bgneal@114 102 #######################################################################
bgneal@114 103
bgneal@114 104 def get_topic_unread_status(forum, topics, user):
bgneal@114 105
bgneal@114 106 # Edge case: no topics
bgneal@114 107 if forum.last_post is None:
bgneal@114 108 return
bgneal@114 109
bgneal@114 110 # This service isn't provided to unauthenticated users
bgneal@114 111 if not user.is_authenticated():
bgneal@114 112 for topic in topics:
bgneal@114 113 topic.has_unread = False
bgneal@114 114 return
bgneal@114 115
bgneal@114 116 now = datetime.datetime.now()
bgneal@114 117
bgneal@114 118 # Get the ForumLastVisit record
bgneal@114 119 try:
bgneal@114 120 flv = ForumLastVisit.objects.get(forum=forum, user=user)
bgneal@114 121 except ForumLastVisit.DoesNotExist:
bgneal@114 122 # One doesn't exist, create a default one for next time,
bgneal@114 123 # mark it as having no unread topics, and bail.
bgneal@114 124 flv = ForumLastVisit(user=user, forum=forum)
bgneal@114 125 flv.begin_date = now
bgneal@114 126 flv.end_date = now
bgneal@114 127 flv.save()
bgneal@114 128 for topic in topics:
bgneal@114 129 topic.has_unread = False
bgneal@114 130 return
bgneal@114 131
bgneal@114 132 # Are all the posts before our window? If so, all have been read.
bgneal@114 133 if forum.last_post.creation_date < flv.begin_date:
bgneal@114 134 for topic in topics:
bgneal@114 135 topic.has_unread = False
bgneal@114 136 return
bgneal@114 137
bgneal@114 138 topic_ids = [topic.id for topic in topics]
bgneal@114 139 tlvs = TopicLastVisit.objects.filter(user=user, topic__id__in=topic_ids)
bgneal@114 140 tlvs = dict([(tlv.topic.id, tlv) for tlv in tlvs])
bgneal@114 141
bgneal@114 142 # Otherwise we have to go through the topics one by one:
bgneal@114 143 for topic in topics:
bgneal@114 144 if topic.update_date < flv.begin_date:
bgneal@114 145 topic.has_unread = False
bgneal@114 146 elif topic.update_date > flv.end_date:
bgneal@114 147 topic.has_unread = True
bgneal@114 148 elif topic.id in tlvs:
bgneal@114 149 topic.has_unread = topic.update_date > tlvs[topic.id].last_visit
bgneal@114 150 else:
bgneal@114 151 topic.has_unread = True
bgneal@114 152
bgneal@114 153 #######################################################################
bgneal@114 154
bgneal@114 155 def get_post_unread_status(topic, posts, user):
bgneal@114 156 # This service isn't provided to unauthenticated users
bgneal@114 157 if not user.is_authenticated():
bgneal@114 158 for post in posts:
bgneal@114 159 post.unread = False
bgneal@114 160 return
bgneal@114 161
bgneal@114 162 # Get the ForumLastVisit record
bgneal@114 163 try:
bgneal@114 164 flv = ForumLastVisit.objects.get(forum=topic.forum, user=user)
bgneal@114 165 except ForumLastVisit.DoesNotExist:
bgneal@114 166 # One doesn't exist, all posts are old.
bgneal@114 167 for post in posts:
bgneal@114 168 post.unread = False
bgneal@114 169 return
bgneal@114 170
bgneal@114 171 # Are all the posts before our window? If so, all have been read.
bgneal@114 172 if topic.last_post.creation_date < flv.begin_date:
bgneal@114 173 for post in posts:
bgneal@114 174 post.unread = False
bgneal@114 175 return
bgneal@114 176
bgneal@114 177 # Do we have a topic last visit record for this topic?
bgneal@114 178
bgneal@114 179 try:
bgneal@114 180 tlv = TopicLastVisit.objects.get(user=user, topic=topic)
bgneal@114 181 except TopicLastVisit.DoesNotExist:
bgneal@114 182 # No we don't, we could be all caught up, or all are new
bgneal@114 183 for post in posts:
bgneal@114 184 post.unread = post.creation_date > flv.end_date
bgneal@114 185 else:
bgneal@114 186 for post in posts:
bgneal@114 187 post.unread = post.creation_date > tlv.last_visit