changeset 108:80ab249d1adc

Forums: quoting existing posts.
author Brian Neal <bgneal@gmail.com>
date Sat, 26 Sep 2009 03:55:50 +0000
parents e94398f5e027
children 07be3e39e639
files gpp/forums/forms.py gpp/forums/urls.py gpp/forums/views.py gpp/templates/forums/display_post.html gpp/templates/forums/new_post.html media/js/forums.js
diffstat 6 files changed, 123 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/gpp/forums/forms.py	Tue Sep 22 03:36:39 2009 +0000
+++ b/gpp/forums/forms.py	Sat Sep 26 03:55:50 2009 +0000
@@ -8,15 +8,6 @@
 from forums.models import Post
 
 
-def bump_post_count(user):
-    """
-    Increments the forum_post_count for the given user.
-    """
-    profile = user.get_profile()
-    profile.forum_post_count += 1
-    profile.save()
-
-
 class NewPostForm(forms.Form):
     """Form for creating a new post."""
     body = forms.CharField(label='', widget=forms.Textarea)
@@ -45,7 +36,6 @@
         post = Post(topic=self.topic, user=user, body=self.cleaned_data['body'],
                 user_ip=ip)
         post.save()
-        bump_post_count(user)
         return post
 
 
@@ -96,14 +86,12 @@
                 body=self.cleaned_data['body'],
                 user_ip=ip)
         post.save()
-
-        bump_post_count(self.user)
         return topic
 
 
 class PostForm(forms.ModelForm):
     """
-    Form for editing an existing post.
+    Form for editing an existing post or a new, non-quick post.
     """
     body = forms.CharField(label='', widget=forms.Textarea)
 
--- a/gpp/forums/urls.py	Tue Sep 22 03:36:39 2009 +0000
+++ b/gpp/forums/urls.py	Sat Sep 26 03:55:50 2009 +0000
@@ -13,6 +13,7 @@
     url(r'^forum/(?P<slug>[\w\d-]+)/$', 'forum_index', name='forums-forum_index'),
     url(r'^forum/(?P<slug>[\w\d-]+)/new-topic/$', 'new_topic', name='forums-new_topic'),
     url(r'^post/(\d+)/$', 'goto_post', name='forums-goto_post'),
+    url(r'^post/new/(?P<topic_id>\d+)/$', 'new_post', name='forums-new_post'),
     url(r'^quick-reply/$', 'quick_reply_ajax', name='forums-quick_reply'),
 )
 
--- a/gpp/forums/views.py	Tue Sep 22 03:36:39 2009 +0000
+++ b/gpp/forums/views.py	Sat Sep 26 03:55:50 2009 +0000
@@ -14,6 +14,7 @@
 from django.template.loader import render_to_string
 from django.template import RequestContext
 from django.views.decorators.http import require_POST
+from django.utils.text import wrap
 
 from core.paginator import DiggPaginator
 from core.functions import email_admins
@@ -145,6 +146,7 @@
         form = NewTopicForm(request.user, forum, request.POST)
         if form.is_valid():
             topic = form.save(request.META.get("REMOTE_ADDR"))
+            _bump_post_count(request.user)
             return HttpResponseRedirect(reverse('forums-new_topic_thanks',
                                             kwargs={'tid': topic.pk}))
     else:
@@ -179,20 +181,21 @@
     to the document.
     """
     if not request.user.is_authenticated():
-        return HttpResponseForbidden()
+        return HttpResponseForbidden('Please login or register to post.')
 
     form = NewPostForm(request.POST)
     if form.is_valid():
-        if form.topic.locked or not form.topic.forum.category.can_access(request.user):
-            return HttpResponseForbidden()
+        if not _can_post_in_topic(form.topic, request.user):
+            return HttpResponseForbidden("You don't have permission to post in this topic.")
 
-        post = form.save(request.user, request.META.get("REMOTE_ADDR"))
+        post = form.save(request.user, request.META.get("REMOTE_ADDR", ""))
+        _bump_post_count(request.user)
         return render_to_response('forums/display_post.html', {
             'post': post,
             },
             context_instance=RequestContext(request))
 
-    return HttpResponseBadRequest();
+    return HttpResponseBadRequest("Invalid post.");
 
 
 def goto_post(request, post_id):
@@ -244,9 +247,11 @@
     The superuser, forum moderators, and original author can edit posts.
     """
     post = get_object_or_404(Post.objects.select_related(), pk=id)
-    can_edit = request.user == post.user or \
-            request.user.is_superuser or \
-            request.user in post.topic.forum.moderators.all()
+
+    can_moderate = request.user.is_superuser or \
+        request.user in post.topic.forum.moderators.all()
+
+    can_edit = can_moderate or request.user == post.user
 
     if not can_edit:
         return HttpResponseForbidden("You don't have permission to edit that post.")
@@ -264,7 +269,7 @@
         'topic': post.topic,
         'post': post,
         'form': form,
-        'can_moderate': True,
+        'can_moderate': can_moderate,
         },
         context_instance=RequestContext(request))
 
@@ -343,3 +348,74 @@
     # It should be safe to just delete the topic now. This will
     # automatically delete all posts in the topic.
     topic.delete()
+
+
+@login_required
+def new_post(request, topic_id):
+    """
+    This function is the view for creating a normal, non-quick reply
+    to a topic.
+    """
+    topic = get_object_or_404(Topic.objects.select_related(), pk=topic_id)
+    can_post = _can_post_in_topic(topic, request.user)
+
+    if can_post:
+        if request.method == 'POST':
+            form = PostForm(request.POST)
+            if form.is_valid():
+                post = form.save(commit=False)
+                post.topic = topic
+                post.user = request.user
+                post.user_ip = request.META.get("REMOTE_ADDR", "")
+                post.save()
+                _bump_post_count(request.user)
+                return HttpResponseRedirect(post.get_absolute_url())
+        else:
+            quote_id = request.GET.get('quote')
+            if quote_id:
+                quote_post = get_object_or_404(Post.objects.select_related(),
+                        pk=quote_id)
+                form = PostForm(initial={'body': _quote_message(quote_post.user.username,
+                    quote_post.body)})
+            else:
+                form = PostForm()
+    else:
+        form = None
+
+    return render_to_response('forums/new_post.html', {
+        'forum': topic.forum,
+        'topic': topic,
+        'form': form,
+        'can_post': can_post,
+        },
+        context_instance=RequestContext(request))
+
+
+def _can_post_in_topic(topic, user):
+    """
+    This function returns true if the given user can post in the given topic
+    and false otherwise.
+    """
+    return (not topic.locked and topic.forum.category.can_access(user)) or \
+            (user.is_superuser or user in topic.forum.moderators.all())
+
+
+def _bump_post_count(user):
+    """
+    Increments the forum_post_count for the given user.
+    """
+    profile = user.get_profile()
+    profile.forum_post_count += 1
+    profile.save()
+
+
+def _quote_message(who, message):
+   """
+   Builds a message reply by quoting the existing message in a
+   typical email-like fashion. The quoting is compatible with Markdown.
+   """
+   header = '*%s wrote:*\n\n' % (who, )
+   lines = wrap(message, 55).split('\n')
+   for i, line in enumerate(lines):
+      lines[i] = '> ' + line
+   return header + '\n'.join(lines)
--- a/gpp/templates/forums/display_post.html	Tue Sep 22 03:36:39 2009 +0000
+++ b/gpp/templates/forums/display_post.html	Sat Sep 26 03:55:50 2009 +0000
@@ -22,7 +22,9 @@
          {% endifnotequal %}
       </div>
       <div class="forum-post-info-tools">
-      <a href=""><img src="{{ MEDIA_URL }}icons/comment.png" alt="Reply with quote" title="Reply with quote" /></a>
+      {% if can_reply %}
+         <a href="{% url forums-new_post topic_id=post.topic.id %}?quote={{ post.id }}"><img src="{{ MEDIA_URL }}icons/comment.png" alt="Reply with quote" title="Reply with quote" /></a>
+      {% endif %}
       {% post_edit_button post user can_moderate MEDIA_URL %}
       <a href="#" class="post-flag" id="fp-{{ post.id }}" 
          title="Flag this post as spam, abuse, or a violation of site rules.">
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/templates/forums/new_post.html	Sat Sep 26 03:55:50 2009 +0000
@@ -0,0 +1,31 @@
+{% extends 'base.html' %}
+{% block title %}Forums: New Post{% endblock %}
+{% block custom_js %}{{ form.media }}{% endblock %}
+{% block content %}
+<h2>Forums: New Post</h2>
+
+<h3>
+   <a href="{% url forums-index %}">SurfGuitar101 Forum Index</a> &raquo;
+   <a href="{% url forums-forum_index slug=forum.slug %}">{{ forum.name }}</a> &raquo;
+   <a href="{% url forums-topic_index id=topic.id %}">{{ topic.name }}</a>
+</h3>
+
+{% if can_post %}
+<div class="forum-block">
+<a name="forum-reply-form"></a>
+<form action="." method="post" id="forums-reply">
+<fieldset>
+<legend>New Post</legend>
+{{ form.as_p }}
+<input type="submit" value="Submit Post" id="forums-new-post" />
+</fieldset>
+</form>
+</div>
+{% else %}
+   {% if topic.locked %}
+   <p>This topic is locked.</p>
+   {% else %}
+   <p>You don't have permission to post to this topic.</p>
+   {% endif %}
+{% endif %}
+{% endblock %}
--- a/media/js/forums.js	Tue Sep 22 03:36:39 2009 +0000
+++ b/media/js/forums.js	Sat Sep 26 03:55:50 2009 +0000
@@ -25,7 +25,8 @@
             postButton.removeAttr('disabled').val('Submit Reply');
          },
          error: function (xhr, textStatus, ex) {
-            alert('Oops, an error occurred. Please reload the page and try again.');
+            alert('Oops, an error occurred. ' + xhr.statusText + ' - ' + 
+               xhr.responseText);
             postButton.removeAttr('disabled').val('Submit Reply');
          }
          });