Просмотр исходного кода

Topics read/unread feature. I still have a problem with read/unread forums - also subforums aren't counted in the parent forum

sh4nks 11 лет назад
Родитель
Сommit
4e3fc1f4fd

+ 77 - 10
flaskbb/forum/models.py

@@ -188,6 +188,52 @@ class Topic(db.Model):
 
         return self
 
+    def update_read(self, user):
+        """
+        Update the topics read status if the user hasn't read the latest
+        post.
+        """
+        # Don't do anything if the user is a guest
+        if not user.is_authenticated():
+            return
+
+        topicread = TopicsRead.query.\
+            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
+        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
+        elif not topicread:
+            topicread = TopicsRead()
+            topicread.user_id = user.id
+            topicread.topic_id = self.id
+            topicread.forum_id = self.forum_id
+            topicread.last_read = datetime.utcnow()
+            topicread.save()
+
+    def is_unread(self, user):
+        """
+        Returns True if the user hasn't read the topic
+        """
+        if not user.is_authenticated():
+            return True
+
+        topicread = TopicsRead.query.\
+            filter(TopicsRead.user_id == user.id,
+                   TopicsRead.topic_id == self.id).first()
+
+        # If no entry is found, the user hasn't read the topic
+        if not topicread:
+            return True
+        # If the entry is older than the last post, the user hasn't read it
+        if topicread.last_read < self.last_post.date_created:
+            return True
+        return False
+
     @cache.memoize(timeout=sys.maxint)
     def get_post_count(self):
         """
@@ -319,6 +365,27 @@ class Forum(db.Model):
         breadcrumbs.reverse()
         return breadcrumbs
 
+    def is_unread(self, user):
+        """
+        Returns True if the user has read the topic
+        """
+        if not user.is_authenticated():
+            return True
+
+        # make a count, and if the count is > 0, there are still unread topics
+        # in the forum
+        topicsread = TopicsRead.query.\
+            filter(TopicsRead.forum_id == self.id). \
+            filter(TopicsRead.last_read < self.last_post.date_created).\
+            count()
+
+        # If no entry is found, return true
+        if not topicsread:
+            return True
+        if topicsread > 0:
+            return True
+        return False
+
     @cache.memoize(timeout=sys.maxint)
     def get_post_count(self, include_children=True):
         """
@@ -397,25 +464,25 @@ class Forum(db.Model):
 
 
 """
-A topic can be tracked by many users
-and a user can track many topics.. so it's a many-to-many relationship
+This model stores the tracked topics for each user
 """
-topictracker = db.Table('topictracker',
+topictracker = db.Table(
+    'topictracker',
     db.Column('user_id', db.Integer(), db.ForeignKey('users.id')),
     db.Column('topic_id', db.Integer(), db.ForeignKey('topics.id')))
 
 
-class Tracking(db.Model):
+class TopicsRead(db.Model):
     """
     This model tracks the unread/read posts
-    Note: This functionality isn't implemented yet, but this will be the next
-    feature after the TopicTracker
     """
-    __tablename__ = "tracking"
+    __tablename__ = "topicsread"
 
-    id = db.Column(db.Integer, primary_key=True)
-    user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
-    topic_id = db.Column(db.Integer, db.ForeignKey("topics.id"))
+    user_id = db.Column(db.Integer, db.ForeignKey("users.id"), primary_key=True)
+    topic_id = db.Column(db.Integer, db.ForeignKey("topics.id"),
+                         primary_key=True)
+    forum_id = db.Column(db.Integer, db.ForeignKey("forums.id"),
+                         primary_key=True)
     last_read = db.Column(db.DateTime, default=datetime.utcnow())
 
     def __repr__(self):

+ 4 - 0
flaskbb/forum/views.py

@@ -45,6 +45,7 @@ def index():
                            online_users=len(get_online_users()),
                            online_guests=len(get_online_users(guest=True)))
 
+
 @forum.route("/forum/<int:forum_id>")
 def view_forum(forum_id):
     page = request.args.get('page', 1, type=int)
@@ -68,6 +69,9 @@ def view_topic(topic_id):
 
     # Count the topic views
     topic.views += 1
+
+    # Update the topicsread status if he hasn't read it
+    topic.update_read(current_user)
     topic.save()
 
     form = None

+ 5 - 1
flaskbb/templates/forum/category_layout.html

@@ -17,7 +17,11 @@
         {% for forum in category.children %}
         <tr>
             <td align="center" valign="center" width="1">
-                New </br> Posts
+            {% if forum.is_unread(current_user) %}
+                New posts
+            {% else %}
+                No new posts
+            {% endif %}
             </td>
 
             <td valign="top">

+ 12 - 2
flaskbb/templates/forum/forum.html

@@ -42,7 +42,11 @@
         {% for subforum in forum.children %}
         <tr>
             <td align="center" valign="center" width="1">
-                New </br> Posts
+            {% if subforum.is_unread(current_user) %}
+                New posts
+            {% else %}
+                No new posts
+            {% endif %}
             </td>
 
             <td valign="top">
@@ -111,7 +115,13 @@
 
         {% for topic in topics.items %}
         <tr>
-            <td width="4%"></td>
+            <td width="4%">
+            {% if topic.is_unread(current_user) %}
+                New
+            {% else %}
+                Read
+            {% endif %}
+            </td>
             <td>
                 <div>
                     <a href="{{ url_for('forum.view_topic', topic_id=topic.id) }}">{{ topic.title }}</a> <br />