changeset 102:e67c4dd98db5

Forums: new topic form sprouts boolean fields for sticky and locking if the user has rights. Implemented the locked logic. Fixed a bug where topics where getting out of order (the view_count was bumping the update_date because of auto_now).
author Brian Neal <bgneal@gmail.com>
date Wed, 16 Sep 2009 02:01:57 +0000
parents 4bbb6a9aa317
children bb3f0d315c5f
files gpp/forums/admin.py gpp/forums/forms.py gpp/forums/models.py gpp/forums/views.py gpp/templates/forums/forum_index.html gpp/templates/forums/topic.html media/css/base.css media/icons/lock.png
diffstat 8 files changed, 57 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/gpp/forums/admin.py	Wed Sep 16 00:39:27 2009 +0000
+++ b/gpp/forums/admin.py	Wed Sep 16 02:01:57 2009 +0000
@@ -24,7 +24,7 @@
 
 
 class TopicAdmin(admin.ModelAdmin):
-    list_display = ('name', 'forum', 'creation_date', 'user', 'sticky', 'locked',
+    list_display = ('name', 'forum', 'creation_date', 'update_date', 'user', 'sticky', 'locked',
             'post_count')
     raw_id_fields = ('user', 'last_post', )
     search_fields = ('name', )
--- a/gpp/forums/forms.py	Wed Sep 16 00:39:27 2009 +0000
+++ b/gpp/forums/forms.py	Wed Sep 16 02:01:57 2009 +0000
@@ -33,7 +33,7 @@
     def clean_topic_id(self):
         id = self.cleaned_data['topic_id']
         try:
-            self.topic = Topic.objects.get(pk=id)
+            self.topic = Topic.objects.select_related().get(pk=id)
         except Topic.DoesNotExist:
             raise forms.ValidationError('invalid topic')
         return id 
@@ -50,10 +50,17 @@
 
 
 class NewTopicForm(forms.Form):
-    """Form for creating a new topic and 1st post to that topic."""
+    """
+    Form for creating a new topic and 1st post to that topic.
+    Superusers and moderators can also create the topic as a sticky or initially
+    locked.
+    """
     name = forms.CharField(label='Subject', max_length=255,
             widget=forms.TextInput(attrs={'size': 64}))
     body = forms.CharField(label='', widget=forms.Textarea)
+    user = None
+    forum = None
+    has_mod_fields = False
 
     class Media:
         css = {
@@ -62,21 +69,33 @@
         js = settings.GPP_THIRD_PARTY_JS['markitup'] + \
             ('js/forums.js', )
 
-    def save(self, forum, user, ip=None):
+    def __init__(self, user, forum, *args, **kwargs):
+        super(NewTopicForm, self).__init__(*args, **kwargs)
+        self.user = user
+        self.forum = forum
+
+        if user.is_superuser or user in forum.moderators.all():
+            self.fields['sticky'] = forms.BooleanField(required=False)
+            self.fields['locked'] = forms.BooleanField(required=False)
+            self.has_mod_fields = True
+
+    def save(self, ip=None):
         """
         Creates the new Topic and first Post from the form data and supplied
         arguments.
         """
-        topic = Topic(forum=forum,
+        topic = Topic(forum=self.forum,
                 name=self.cleaned_data['name'],
-                user=user)
+                user=self.user,
+                sticky=self.has_mod_fields and self.cleaned_data['sticky'],
+                locked=self.has_mod_fields and self.cleaned_data['locked'])
         topic.save()
 
         post = Post(topic=topic,
-                user=user,
+                user=self.user,
                 body=self.cleaned_data['body'],
                 user_ip=ip)
         post.save()
 
-        bump_post_count(user)
+        bump_post_count(self.user)
         return topic
--- a/gpp/forums/models.py	Wed Sep 16 00:39:27 2009 +0000
+++ b/gpp/forums/models.py	Wed Sep 16 02:01:57 2009 +0000
@@ -1,6 +1,8 @@
 """
 Models for the forums application.
 """
+import datetime
+
 from django.db import models
 from django.db.models import Q
 from django.contrib.auth.models import User, Group
@@ -121,7 +123,7 @@
 
     # denormalized fields to reduce database hits
     post_count = models.IntegerField(blank=True, default=0)
-    update_date = models.DateTimeField(auto_now=True)
+    update_date = models.DateTimeField()
     last_post = models.OneToOneField('Post', blank=True, null=True,
         related_name='parent_topic')
 
@@ -158,6 +160,14 @@
             return self.post_count - 1
         return 0
 
+    def save(self, *args, **kwargs):
+        if not self.id:
+            now = datetime.datetime.now()
+            self.creation_date = now
+            self.update_date = now
+
+        super(Topic, self).save(*args, **kwargs)
+
 
 class Post(models.Model):
     """
--- a/gpp/forums/views.py	Wed Sep 16 00:39:27 2009 +0000
+++ b/gpp/forums/views.py	Wed Sep 16 02:01:57 2009 +0000
@@ -134,13 +134,13 @@
         return HttpResponseForbidden()
 
     if request.method == 'POST':
-        form = NewTopicForm(request.POST)
+        form = NewTopicForm(request.user, forum, request.POST)
         if form.is_valid():
-            topic = form.save(forum, request.user, request.META.get("REMOTE_ADDR"))
+            topic = form.save(request.META.get("REMOTE_ADDR"))
             return HttpResponseRedirect(reverse('forums-new_topic_thanks',
                                             kwargs={'tid': topic.pk}))
     else:
-        form = NewTopicForm()
+        form = NewTopicForm(request.user, forum)
     
     return render_to_response('forums/new_topic.html', {
         'forum': forum,
@@ -175,7 +175,7 @@
 
     form = PostForm(request.POST)
     if form.is_valid():
-        if not form.topic.forum.category.can_access(request.user):
+        if form.topic.locked or not form.topic.forum.category.can_access(request.user):
             return HttpResponseForbidden()
 
         post = form.save(request.user, request.META.get("REMOTE_ADDR"))
--- a/gpp/templates/forums/forum_index.html	Wed Sep 16 00:39:27 2009 +0000
+++ b/gpp/templates/forums/forum_index.html	Wed Sep 16 02:01:57 2009 +0000
@@ -25,7 +25,9 @@
    <tbody>
    {% for topic in page.object_list %}
       <tr class="{% cycle 'odd' 'even' %}">
-         <td><h4><a href="{{ topic.get_absolute_url }}">{{ topic.name }}</a></h4></td>
+         <td>{% 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>
          <td class="forum-index_replies">{{ topic.reply_count }}</td>
          <td class="forum-index_author"><a href="{% url bio-view_profile username=topic.user.username %}" title="View profile for {{ topic.user.username }}">{{ topic.user.username }}</a></td>
          <td class="forum-index_views">{{ topic.view_count }}</td>
--- a/gpp/templates/forums/topic.html	Wed Sep 16 00:39:27 2009 +0000
+++ b/gpp/templates/forums/topic.html	Wed Sep 16 02:01:57 2009 +0000
@@ -11,12 +11,16 @@
 </h3>
 
 <div class="forum-block">
+{% if topic.locked %}
+<img src="{{ MEDIA_URL }}/icons/lock.png" alt="Lock" title="This topic is locked" />
+{% else %}
 {% if last_page %}
-<a href="#forum-reply-form">New Reply</a> &bull;
+<a href="#forum-reply-form">New Reply</a>
 {% else %}
-<a href="./?page={{ page.paginator.num_pages }}#forum-reply-form">New Reply</a> &bull;
+<a href="./?page={{ page.paginator.num_pages }}#forum-reply-form">New Reply</a>
 {% endif %}
-<a href="{% url forums-new_topic slug=forum.slug %}">New Topic</a>
+{% endif %}
+&bull; <a href="{% url forums-new_topic slug=forum.slug %}">New Topic</a>
 {{ page_nav }}
 
 <table class="forum-topic" id="forum-topic">
@@ -26,7 +30,7 @@
 </table>
 {{ page_nav }}
 
-{% if last_page and user.is_authenticated %}
+{% if last_page and user.is_authenticated and not topic.locked %}
 <a name="forum-reply-form"></a>
 <form action="" method="post" id="forums-quick-reply">
 <fieldset>
--- a/media/css/base.css	Wed Sep 16 00:39:27 2009 +0000
+++ b/media/css/base.css	Wed Sep 16 02:01:57 2009 +0000
@@ -235,3 +235,7 @@
 #forums-quick-reply {
    margin-top: 1.5em;
 }
+img.forums-topic-icon {
+   float: left;
+   margin-right: 3px;
+}
Binary file media/icons/lock.png has changed