Browse Source

Documented the "read/unread tracker" a bit better

sh4nks 11 years ago
parent
commit
f3bf6e0225
5 changed files with 64 additions and 22 deletions
  1. 1 1
      flaskbb/configs/default.py
  2. 0 1
      flaskbb/forum/__init__.py
  3. 28 13
      flaskbb/forum/models.py
  4. 10 2
      flaskbb/forum/views.py
  5. 25 5
      flaskbb/utils/helpers.py

+ 1 - 1
flaskbb/configs/default.py

@@ -98,4 +98,4 @@ class DefaultConfig(object):
 
     # The days for how long the forum should deal with unread topics
     # 0 - Disable it
-    TRACKER_LENGTH = 0
+    TRACKER_LENGTH = 7

+ 0 - 1
flaskbb/forum/__init__.py

@@ -1 +0,0 @@
-

+ 28 - 13
flaskbb/forum/models.py

@@ -261,11 +261,11 @@ class Topic(db.Model):
         Update the topics read status if the user hasn't read the latest
         post.
         """
-        # Don't do anything if the user is a guest
-        # or the the last post is is too old - can be specified in the
-        # config via `TRACKER_LENGTH`
         read_cutoff = datetime.utcnow() - timedelta(
             days=current_app.config['TRACKER_LENGTH'])
+
+        # Anonymous User or the post is too old for inserting it in the
+        # TopicsRead model
         if not user.is_authenticated() or \
                 read_cutoff > self.last_post.date_created:
             return
@@ -274,12 +274,14 @@ class Topic(db.Model):
             filter(TopicsRead.user_id == user.id,
                    TopicsRead.topic_id == self.id).first()
 
-        # If the user has visited this topic already but hasn't read
-        # it for a while, mark the topic as read
+        # A new post has been submitted that the user hasn't read.
+        # Updating...
         if topicread and (topicread.last_read < self.last_post.date_created):
             topicread.last_read = datetime.utcnow()
             topicread.save()
-        # If the user hasn't read the topic, add him to the topicsread model
+
+        # The user has not visited the topic before. Inserting him in
+        # the TopicsRead model.
         elif not topicread:
             topicread = TopicsRead()
             topicread.user_id = user.id
@@ -287,6 +289,8 @@ class Topic(db.Model):
             topicread.last_read = datetime.utcnow()
             topicread.save()
 
+        # else: no unread posts
+
         if forum:
             # fetch the unread posts in the forum
             unread_count = Topic.query.\
@@ -301,19 +305,29 @@ class Topic(db.Model):
                               TopicsRead.last_read < Topic.last_updated)).\
                 count()
 
-            # Mark it as read if no unread topics are found
+            #No unread topics available - trying to mark the forum as read
             if unread_count == 0:
                 forumread = ForumsRead.query.\
                     filter(ForumsRead.user_id == user.id,
                            ForumsRead.forum_id == forum.id).first()
 
-                # If the user has never visited a topic in this forum
-                # create a new entry
-                if not forumread:
-                    forumread = ForumsRead(user_id=user.id, forum_id=forum.id)
+                # ForumsRead is already up-to-date.
+                if forumread and forumread.last_read > topicread.last_read:
+                    return
+
+                # ForumRead Entry exists - Updating it because a new post
+                # has been submitted that the user hasn't read.
+                elif forumread:
+                    forumread.last_read = datetime.utcnow()
+                    forumread.save()
 
-                forumread.last_read = datetime.utcnow()
-                forumread.save()
+                # No ForumRead Entry existing - creating one.
+                else:
+                    forumread = ForumsRead()
+                    forumread.user_id = user.id
+                    forumread.forum_id = forum.id
+                    forumread.last_read = datetime.utcnow()
+                    forumread.save()
 
 
 class Forum(db.Model):
@@ -454,6 +468,7 @@ class ForumsRead(db.Model):
     forum_id = db.Column(db.Integer, db.ForeignKey("topics.id"),
                          primary_key=True)
     last_read = db.Column(db.DateTime, default=datetime.utcnow())
+    cleared = db.Column(db.DateTime)
 
     def save(self):
         db.session.add(self)

+ 10 - 2
flaskbb/forum/views.py

@@ -127,13 +127,21 @@ def markread(forum_id=None):
 
     # Mark all forums as read
     # TODO: Improve performance
+
+    forumsread = ForumsRead.query.filter_by(user_id=current_user.id).delete()
+    user = current_user
     forums = Forum.query.all()
     for forum in forums:
         if forum.is_category:
             continue
 
-        for topic in forum.topics:
-            topic.update_read(current_user, forum)
+        forumsread = ForumsRead()
+        forumsread.user_id = user.id
+        forumsread.forum_id = forum.id
+        forumsread.last_read = datetime.datetime.utcnow()
+        forumsread.cleared = datetime.datetime.utcnow()
+        db.session.add(forumsread)
+    db.session.commit()
 
     return redirect(url_for("forum.index"))
 

+ 25 - 5
flaskbb/utils/helpers.py

@@ -18,22 +18,42 @@ from flaskbb.extensions import redis
 from flaskbb.forum.models import ForumsRead, TopicsRead
 
 
-def is_unread(read_object, last_post, forum=None, topic=None):
+def is_unread(read_object, last_post, forum=None, topic=None, user=None):
     if not (isinstance(read_object, ForumsRead) or
             isinstance(read_object, TopicsRead) or not None):
         raise TypeError("Must be a ForumsRead or TopicsRead object")
 
+    # TODO: Do a check if the forums is marked as read
+
+    # By default, for all unregistered users the posts are marked as read
+    if user and not user.is_authenticated():
+        return False
+
     read_cutoff = datetime.utcnow() - timedelta(
         days=current_app.config['TRACKER_LENGTH'])
 
+    # Forum object passed but topic_count is 0 - mark the forum as read
     if forum and forum.topic_count == 0:
         return False
-    if topic and not read_object:
-        return read_cutoff > last_post.date_created
-    if read_object is None:
+
+    # Forum object passed but read_object is None.
+    # That means that there is atleast one post that the user hasn't read
+    if forum and not read_object:
         return True
-    if read_cutoff < last_post.date_created:
+
+    # Topic object passed but read_object is None.
+    # Checking if the topic is older as the read_cutoff
+    if topic and not read_object and last_post.date_created > read_cutoff:
+        return True
+
+    # Didn't match any of the above conditions, so we just have to look
+    # if the last_post is older as the read_cutoff.
+    if last_post.date_created > read_cutoff:
         return False
+
+    # read_object and last_post object available. Checking if the user
+    # hasn't read the last post --> the read_object needs to be smaller than
+    # the last post to mark it as unread
     return read_object.last_read < last_post.date_created