Browse Source

#630: events threads flags

Rafał Pitoń 8 years ago
parent
commit
a02606df5c

+ 6 - 5
misago/threads/events.py

@@ -3,10 +3,10 @@ from django.utils import timezone
 from .models import Post
 from .models import Post
 
 
 
 
-def record_event(request, thread, event, context=None, commit=True):
+def record_event(request, thread, event_type, context=None, commit=True):
     time_now = timezone.now()
     time_now = timezone.now()
 
 
-    event_post = Post.objects.create(
+    event = Post.objects.create(
         category=thread.category,
         category=thread.category,
         thread=thread,
         thread=thread,
         poster=request.user,
         poster=request.user,
@@ -17,11 +17,12 @@ def record_event(request, thread, event, context=None, commit=True):
         posted_on=time_now,
         posted_on=time_now,
         updated_on=time_now,
         updated_on=time_now,
         is_event=True,
         is_event=True,
-        event_type=event,
+        event_type=event_type,
         event_context=context,
         event_context=context,
     )
     )
 
 
-    thread.set_last_post(event_post)
+    thread.has_events = True
+    thread.set_last_post(event)
     if commit:
     if commit:
         thread.save()
         thread.save()
 
 
@@ -30,4 +31,4 @@ def record_event(request, thread, event, context=None, commit=True):
         if commit:
         if commit:
             thread.category.save()
             thread.category.save()
 
 
-    return event_post
+    return event

+ 2 - 0
misago/threads/migrations/0001_initial.py

@@ -76,6 +76,7 @@ class Migration(migrations.Migration):
                 ('title', models.CharField(max_length=255)),
                 ('title', models.CharField(max_length=255)),
                 ('slug', models.CharField(max_length=255)),
                 ('slug', models.CharField(max_length=255)),
                 ('replies', models.PositiveIntegerField(default=0, db_index=True)),
                 ('replies', models.PositiveIntegerField(default=0, db_index=True)),
+                ('has_events', models.BooleanField(default=False)),
                 ('has_reported_posts', models.BooleanField(default=False)),
                 ('has_reported_posts', models.BooleanField(default=False)),
                 ('has_open_reports', models.BooleanField(default=False)),
                 ('has_open_reports', models.BooleanField(default=False)),
                 ('has_unapproved_posts', models.BooleanField(default=False)),
                 ('has_unapproved_posts', models.BooleanField(default=False)),
@@ -83,6 +84,7 @@ class Migration(migrations.Migration):
                 ('started_on', models.DateTimeField(db_index=True)),
                 ('started_on', models.DateTimeField(db_index=True)),
                 ('starter_name', models.CharField(max_length=255)),
                 ('starter_name', models.CharField(max_length=255)),
                 ('starter_slug', models.CharField(max_length=255)),
                 ('starter_slug', models.CharField(max_length=255)),
+                ('last_post_is_event', models.BooleanField(default=False)),
                 ('last_post_on', models.DateTimeField(db_index=True)),
                 ('last_post_on', models.DateTimeField(db_index=True)),
                 ('last_poster_name', models.CharField(max_length=255, null=True, blank=True)),
                 ('last_poster_name', models.CharField(max_length=255, null=True, blank=True)),
                 ('last_poster_slug', models.CharField(max_length=255, null=True, blank=True)),
                 ('last_poster_slug', models.CharField(max_length=255, null=True, blank=True)),

+ 15 - 4
misago/threads/models/thread.py

@@ -34,6 +34,7 @@ class Thread(models.Model):
     slug = models.CharField(max_length=255)
     slug = models.CharField(max_length=255)
     replies = models.PositiveIntegerField(default=0, db_index=True)
     replies = models.PositiveIntegerField(default=0, db_index=True)
 
 
+    has_events = models.BooleanField(default=False)
     has_reported_posts = models.BooleanField(default=False)
     has_reported_posts = models.BooleanField(default=False)
     has_open_reports = models.BooleanField(default=False)
     has_open_reports = models.BooleanField(default=False)
     has_unapproved_posts = models.BooleanField(default=False)
     has_unapproved_posts = models.BooleanField(default=False)
@@ -65,6 +66,7 @@ class Thread(models.Model):
         blank=True,
         blank=True,
         on_delete=models.SET_NULL
         on_delete=models.SET_NULL
     )
     )
+    last_post_is_event = models.BooleanField(default=False)
     last_poster = models.ForeignKey(
     last_poster = models.ForeignKey(
         settings.AUTH_USER_MODEL,
         settings.AUTH_USER_MODEL,
         related_name='last_poster_set',
         related_name='last_poster_set',
@@ -141,16 +143,24 @@ class Thread(models.Model):
         hidden_post_qs = self.post_set.filter(is_hidden=True)[:1]
         hidden_post_qs = self.post_set.filter(is_hidden=True)[:1]
         self.has_hidden_posts = hidden_post_qs.exists()
         self.has_hidden_posts = hidden_post_qs.exists()
 
 
-        first_post = self.post_set.order_by('id')[:1][0]
+        posts = self.post_set.order_by('id')
+
+        first_post = posts.first()
         self.set_first_post(first_post)
         self.set_first_post(first_post)
 
 
-        last_post_qs = self.post_set.filter(is_unapproved=False).order_by('-id')
-        last_post = last_post_qs[:1]
+        last_post = posts.filter(is_unapproved=False).last()
         if last_post:
         if last_post:
-            self.set_last_post(last_post[0])
+            self.set_last_post(last_post)
         else:
         else:
             self.set_last_post(first_post)
             self.set_last_post(first_post)
 
 
+        self.has_events = False
+        if last_post:
+            if last_post.is_event:
+                self.has_events = True
+            else:
+                self.has_events = self.post_set.filter(is_event=True).exists()
+
     @property
     @property
     def thread_type(self):
     def thread_type(self):
         return self.category.thread_type
         return self.category.thread_type
@@ -210,6 +220,7 @@ class Thread(models.Model):
 
 
     def set_last_post(self, post):
     def set_last_post(self, post):
         self.last_post_on = post.posted_on
         self.last_post_on = post.posted_on
+        self.last_post_is_event = post.is_event
         self.last_post = post
         self.last_post = post
         self.last_poster = post.poster
         self.last_poster = post.poster
         self.last_poster_name = post.poster_name
         self.last_poster_name = post.poster_name

+ 3 - 0
misago/threads/serializers/thread.py

@@ -39,6 +39,7 @@ class ThreadSerializer(serializers.ModelSerializer):
             'has_unapproved_posts',
             'has_unapproved_posts',
             'started_on',
             'started_on',
             'last_post_on',
             'last_post_on',
+            'last_post_is_event',
             'last_post',
             'last_post',
             'last_poster_name',
             'last_poster_name',
             'is_unapproved',
             'is_unapproved',
@@ -133,6 +134,7 @@ class PrivateThreadSerializer(ThreadSerializer):
             'has_unapproved_posts',
             'has_unapproved_posts',
             'started_on',
             'started_on',
             'last_post_on',
             'last_post_on',
+            'last_post_is_event',
             'last_post',
             'last_post',
             'last_poster_name',
             'last_poster_name',
             'is_unapproved',
             'is_unapproved',
@@ -172,6 +174,7 @@ class ThreadsListSerializer(ThreadSerializer):
             'has_unapproved_posts',
             'has_unapproved_posts',
             'started_on',
             'started_on',
             'last_post_on',
             'last_post_on',
+            'last_post_is_event',
             'last_post',
             'last_post',
             'last_poster_name',
             'last_poster_name',
             'weight',
             'weight',

+ 3 - 1
misago/threads/tests/test_events.py

@@ -50,7 +50,9 @@ class EventsAPITests(TestCase):
         event = record_event(request, self.thread, 'announcement', context)
         event = record_event(request, self.thread, 'announcement', context)
 
 
         event_post = self.thread.post_set.order_by('-id')[:1][0]
         event_post = self.thread.post_set.order_by('-id')[:1][0]
-        self.assertTrue(self.thread.last_post, event_post)
+        self.assertEqual(self.thread.last_post, event_post)
+        self.assertTrue(self.thread.has_events)
+        self.assertTrue(self.thread.last_post_is_event)
 
 
         self.assertEqual(event.pk, event_post.pk)
         self.assertEqual(event.pk, event_post.pk)
         self.assertTrue(event_post.is_event)
         self.assertTrue(event_post.is_event)

+ 31 - 4
misago/threads/tests/test_thread_model.py

@@ -162,7 +162,7 @@ class ThreadModelTests(TestCase):
         self.assertEqual(self.thread.replies, 3)
         self.assertEqual(self.thread.replies, 3)
 
 
          # add event post
          # add event post
-        hidden_post = Post.objects.create(
+        event = Post.objects.create(
             category=self.category,
             category=self.category,
             thread=self.thread,
             thread=self.thread,
             poster=user,
             poster=user,
@@ -176,18 +176,45 @@ class ThreadModelTests(TestCase):
             is_event=True
             is_event=True
         )
         )
 
 
-        # events don't count to reply count
         self.thread.synchronize()
         self.thread.synchronize()
-        self.assertEqual(self.thread.last_post, hidden_post)
-        self.assertEqual(self.thread.last_post_on, hidden_post.posted_on)
+        self.assertEqual(self.thread.last_post, event)
+        self.assertEqual(self.thread.last_post_on, event.posted_on)
         self.assertEqual(self.thread.last_poster, user)
         self.assertEqual(self.thread.last_poster, user)
         self.assertEqual(self.thread.last_poster_name, user.username)
         self.assertEqual(self.thread.last_poster_name, user.username)
         self.assertEqual(self.thread.last_poster_slug, user.slug)
         self.assertEqual(self.thread.last_poster_slug, user.slug)
+        self.assertTrue(self.thread.last_post_is_event)
+        self.assertTrue(self.thread.has_events)
         self.assertFalse(self.thread.has_reported_posts)
         self.assertFalse(self.thread.has_reported_posts)
         self.assertFalse(self.thread.has_unapproved_posts)
         self.assertFalse(self.thread.has_unapproved_posts)
         self.assertFalse(self.thread.has_hidden_posts)
         self.assertFalse(self.thread.has_hidden_posts)
+        # events don't count to reply count
         self.assertEqual(self.thread.replies, 3)
         self.assertEqual(self.thread.replies, 3)
 
 
+        # create another post to provoke other has_events resolution path
+        Post.objects.create(
+            category=self.category,
+            thread=self.thread,
+            poster=user,
+            poster_name=user.username,
+            poster_ip='127.0.0.1',
+            original="Hello! I am test message!",
+            parsed="<p>Hello! I am test message!</p>",
+            checksum="nope",
+            posted_on=datetime,
+            updated_on=datetime
+        )
+
+        self.thread.synchronize()
+        self.assertFalse(self.thread.last_post_is_event)
+        self.assertTrue(self.thread.has_events)
+
+        # remove event
+        event.delete()
+
+        self.thread.synchronize()
+        self.assertFalse(self.thread.last_post_is_event)
+        self.assertFalse(self.thread.has_events)
+
     def test_set_first_post(self):
     def test_set_first_post(self):
         """set_first_post sets first post and poster data on thread"""
         """set_first_post sets first post and poster data on thread"""
         User = get_user_model()
         User = get_user_model()