changeset 13:777451a98f9d

Shoutbox work: shouts now have absolute URLs. Shouts can now be flagged as abuse. Minor tweak to breadcrumbs css. Added flag date to comments admin.
author Brian Neal <bgneal@gmail.com>
date Thu, 16 Apr 2009 02:00:17 +0000
parents f408971657b9
children 7b6540b185d9
files gpp/comments/admin.py gpp/shoutbox/admin.py gpp/shoutbox/models.py gpp/shoutbox/urls.py gpp/shoutbox/views.py gpp/templates/shoutbox/missing_shout.html gpp/templates/shoutbox/shout_detail.html gpp/templates/shoutbox/shoutbox.html gpp/templates/shoutbox/view.html gpp/templates/shoutbox/view_shout.html media/css/base.css media/js/shoutbox_app.js
diffstat 12 files changed, 160 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/gpp/comments/admin.py	Wed Apr 15 01:13:17 2009 +0000
+++ b/gpp/comments/admin.py	Thu Apr 16 02:00:17 2009 +0000
@@ -25,7 +25,7 @@
     raw_id_fields = ('user', 'content_type')
 
 class CommentFlagAdmin(admin.ModelAdmin):
-    list_display = ('__unicode__', 'get_comment_url')
+    list_display = ('__unicode__', 'flag_date', 'get_comment_url')
 
 admin.site.register(Comment, CommentAdmin)
 admin.site.register(CommentFlag, CommentFlagAdmin)
--- a/gpp/shoutbox/admin.py	Wed Apr 15 01:13:17 2009 +0000
+++ b/gpp/shoutbox/admin.py	Thu Apr 16 02:00:17 2009 +0000
@@ -3,9 +3,17 @@
 """
 from django.contrib import admin
 from shoutbox.models import Shout
+from shoutbox.models import ShoutFlag
 
 class ShoutAdmin(admin.ModelAdmin):
-   list_display = ('shout_date', '__unicode__')
-   raw_id_fields = ('user', )
+    list_display = ('shout_date', '__unicode__')
+    raw_id_fields = ('user', )
+
+class ShoutFlagAdmin(admin.ModelAdmin):
+    list_display = ('__unicode__', 'flag_date', 'get_shout_url')
+
 
 admin.site.register(Shout, ShoutAdmin)
+admin.site.register(ShoutFlag, ShoutFlagAdmin)
+
+# vim: ts=4 sw=4
--- a/gpp/shoutbox/models.py	Wed Apr 15 01:13:17 2009 +0000
+++ b/gpp/shoutbox/models.py	Thu Apr 16 02:00:17 2009 +0000
@@ -4,14 +4,38 @@
 from django.db import models
 from django.contrib.auth.models import User
 
+
 class Shout(models.Model):
-   user = models.ForeignKey(User)
-   shout_date = models.DateTimeField(auto_now_add=True)
-   shout = models.TextField()
+    user = models.ForeignKey(User)
+    shout_date = models.DateTimeField(auto_now_add=True)
+    shout = models.TextField()
 
-   def __unicode__(self):
-      shout = self.shout[:60]
-      return u'Shout from %s: %s' % (self.user.username, shout)
+    @models.permalink
+    def get_absolute_url(self):
+        return ('shoutbox-view', [str(self.id)])
 
-   class Meta:
-      ordering = ('-shout_date', )
+    def __unicode__(self):
+        shout = self.shout[:60]
+        return u'Shout from %s: %s' % (self.user.username, shout)
+
+    class Meta:
+        ordering = ('-shout_date', )
+
+
+class ShoutFlag(models.Model):
+    """This model represents a user flagging a shout as inappropriate."""
+    user = models.ForeignKey(User)
+    shout = models.ForeignKey(Shout)
+    flag_date = models.DateTimeField(auto_now_add=True)
+
+    def __unicode__(self):
+        return u'Shout ID %s flagged by %s' % (self.shout_id, self.user.username)
+
+    class Meta:
+        ordering = ('flag_date', )
+
+    def get_shout_url(self):
+        return '<a href="/admin/shoutbox/shout/%s">Shout</a>' % self.shout.id
+    get_shout_url.allow_tags = True
+
+# vim: ts=4 sw=4
--- a/gpp/shoutbox/urls.py	Wed Apr 15 01:13:17 2009 +0000
+++ b/gpp/shoutbox/urls.py	Thu Apr 16 02:00:17 2009 +0000
@@ -7,7 +7,11 @@
 urlpatterns = patterns('shoutbox.views',
     url(r'^delete/$', 'delete', name='shoutbox-delete'),
     url(r'^edit/$', 'edit', name='shoutbox-edit'),
+    url(r'^flag/$', 'flag', name='shoutbox-flag'),
     url(r'^shout/$', 'shout', name='shoutbox-shout'),
     url(r'^text/$', 'text', name='shoutbox-text'),
-    url(r'^view/(?P<page>\d+)/$', 'view', name='shoutbox-view'),
+    url(r'^view/(\d+)/$', 'view_shout', name='shoutbox-view'),
+    url(r'^view/history/(?P<page>\d+)/$', 'view_history', name='shoutbox-history'),
 )
+
+# vim: ts=4 sw=4
--- a/gpp/shoutbox/views.py	Wed Apr 15 01:13:17 2009 +0000
+++ b/gpp/shoutbox/views.py	Thu Apr 16 02:00:17 2009 +0000
@@ -13,8 +13,10 @@
 from django.views.decorators.http import require_POST
 
 from core.paginator import DiggPaginator
+from core.functions import email_admins
 from shoutbox.forms import ShoutBoxForm
 from shoutbox.models import Shout
+from shoutbox.models import ShoutFlag
 
 SHOUTS_PER_PAGE = 10
 
@@ -33,7 +35,21 @@
        context_instance = RequestContext(request))
 
 
-def view(request, page=1):
+def view_shout(request, id):
+    """This view is for viewing an individual shout."""
+    try:
+        shout = Shout.objects.get(pk=id)
+    except Shout.DoesNotExist:
+        return render_to_response('shoutbox/missing_shout.html', {},
+           context_instance = RequestContext(request))
+
+    return render_to_response('shoutbox/view_shout.html', {
+       'shout': shout,
+       },
+       context_instance = RequestContext(request))
+
+
+def view_history(request, page=1):
     """This view allows one to view the shoutbox history."""
     paginator = DiggPaginator(Shout.objects.all(), SHOUTS_PER_PAGE, body=5, tail=3, margin=3, padding=2)
     try:
@@ -107,4 +123,32 @@
 
     return HttpResponseForbidden()
 
+
+@require_POST
+def flag(request):
+    """
+    This function handles the flagging of shouts by users. This function should
+    be the target of an AJAX post.
+    """
+    if not request.user.is_authenticated():
+        return HttpResponse('Please login or register to flag a shout.')
+
+    id = request.POST.get('id', None)
+    if id is None:
+        return HttpResponseBadRequest('No id')
+
+    try:
+        shout = Shout.objects.get(pk=id)
+    except Shout.DoesNotExist:
+        return HttpResponseBadRequest('No shout with id %s' % id)
+
+    flag = ShoutFlag(user=request.user, shout=shout)
+    flag.save()
+    email_admins('A Shout Has Been Flagged', """Hello,
+
+A user has flagged a shout for review.
+""")
+    return HttpResponse('The shout was flagged. A moderator will review the shout shortly. ' \
+            'Thanks for helping to improve the quality of this site.')
+
 # vim: ts=4 sw=4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/templates/shoutbox/missing_shout.html	Thu Apr 16 02:00:17 2009 +0000
@@ -0,0 +1,7 @@
+{% extends 'base.html' %}
+{% block title %}Shout Not Found{% endblock %}
+{% block content %}
+<div class="breadcrumbs"><a href="{% url shoutbox-history page=1 %}">Shoutbox History</a> &raquo; Shout Not Found</div>
+<h2>Shout Not Found</h2>
+<p>We're sorry, it looks like that shout no longer exists.</p>
+{% endblock %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/templates/shoutbox/shout_detail.html	Thu Apr 16 02:00:17 2009 +0000
@@ -0,0 +1,21 @@
+{% load avatar_tags %}
+{% load smiley_tags %}
+<tr>
+<th>
+<a href="{% url bio-view_profile username=shout.user.username %}">{% avatar shout.user %}</a>
+<a href="{% url bio-view_profile username=shout.user.username %}">{{ shout.user.username }}</a>
+</th>
+<td>
+<div {% ifequal user shout.user %}class="edit" id="shout-{{ shout.id }}"{% endifequal %}>{{ shout.shout|smilify|urlize }}</div>
+</div>
+<br />
+<span class="date">{{ shout.shout_date|date:"D M d Y H:i:s" }}</span><br />
+<a href="{% url shoutbox-view shout.id %}"><img src="{{ MEDIA_URL }}icons/link.png" alt="Permalink" title="Permalink" /></a>
+<a href="#" class="shout-flag" id="shout-flag-{{ shout.id }}"><img src="{{ MEDIA_URL }}icons/flag_red.png" alt="Flag"
+   title="Flag this shout as offensive" /></a>
+{% ifequal user shout.user %}
+<a href="#" class="shout-del" id="shout-del-{{ shout.id }}"><img src="{{ MEDIA_URL }}icons/cross.png" alt="Delete"
+   title="Delete this shout" /></a>
+{% endifequal %}
+</td>
+</tr>
--- a/gpp/templates/shoutbox/shoutbox.html	Wed Apr 15 01:13:17 2009 +0000
+++ b/gpp/templates/shoutbox/shoutbox.html	Thu Apr 16 02:00:17 2009 +0000
@@ -11,7 +11,7 @@
       </p>
    {% endfor %}
 </div>
-<center><a href="{% url shoutbox-view page=1 %}">Shout History</a></center>
+<center><a href="{% url shoutbox-history page=1 %}">Shout History</a></center>
 {% if user.is_authenticated %}
 <center>
 <form action="{% url shoutbox-shout %}" method="post">
--- a/gpp/templates/shoutbox/view.html	Wed Apr 15 01:13:17 2009 +0000
+++ b/gpp/templates/shoutbox/view.html	Thu Apr 16 02:00:17 2009 +0000
@@ -19,21 +19,7 @@
 <div class="shoutbox-history">
 <table>
 {% for shout in page.object_list %}
-    <tr>
-    <th>
-    <a href="{% url bio-view_profile username=shout.user.username %}">{% avatar shout.user %}</a>
-    <a href="{% url bio-view_profile username=shout.user.username %}">{{ shout.user.username }}</a>
-    </th>
-    <td>
-<div {% ifequal user shout.user %}class="edit" id="shout-{{ shout.id }}"{% endifequal %}>{{ shout.shout|smilify|urlize }}</div>
-    </div>
-    <br />
-    <span class="date">{{ shout.shout_date|date:"D M d Y H:i:s" }}</span>
-    {% ifequal user shout.user %}
-        | <a href="#" class="shout-del" id="shout-del-{{ shout.id }}">Delete</a>
-    {% endifequal %}
-    </td>
-    </tr>
+{% include "shoutbox/shout_detail.html" %}
 {% endfor %}
 </table>
 </div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpp/templates/shoutbox/view_shout.html	Thu Apr 16 02:00:17 2009 +0000
@@ -0,0 +1,19 @@
+{% extends 'base.html' %}
+{% load script_tags %}
+{% block custom_css %}
+<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}css/shoutbox_app.css" />
+{% endblock %}
+{% block custom_js %}
+{% script_tags "jquery-jeditable" %}
+<script type="text/javascript" src="{{ MEDIA_URL }}js/shoutbox_app.js"></script>
+{% endblock %}
+{% block title %}Shout #{{ shout.id }}{% endblock %}
+{% block content %}
+<div class="breadcrumbs"><a href="{% url shoutbox-history page=1 %}">Shoutbox History</a> &raquo; Shout #{{ shout.id }}</div>
+<h2>Shout #{{ shout.id }}</h2>
+<div class="shoutbox-history">
+<table>
+{% include "shoutbox/shout_detail.html" %}
+</table>
+</div>
+{% endblock %}
--- a/media/css/base.css	Wed Apr 15 01:13:17 2009 +0000
+++ b/media/css/base.css	Thu Apr 16 02:00:17 2009 +0000
@@ -97,6 +97,7 @@
 }
 .breadcrumbs {
    font-size: x-small;
+   padding-bottom: 0.5em;
 }
 table {
    width: auto;
--- a/media/js/shoutbox_app.js	Wed Apr 15 01:13:17 2009 +0000
+++ b/media/js/shoutbox_app.js	Thu Apr 16 02:00:17 2009 +0000
@@ -7,10 +7,10 @@
          submit : 'OK',
          cancel : 'Cancel'
      });
-     $('.shout-del').click(function () {
+     $('a.shout-del').click(function () {
          if (confirm('Really delete this shout?')) {
              var id = this.id;
-             if (id.match(/shout-del-(\d+)/)) {
+             if (id.match(/^shout-del-(\d+)/)) {
                 $.post('/shout/delete/', { id : RegExp.$1 }, function (id) {
                     var id = '#shout-del-' + id;
                     $(id).parents('tr').fadeOut(1500, function () {
@@ -22,4 +22,19 @@
          }
          return false;
      });
+     $('.shout-flag').click(function () {
+         var id = this.id;
+         if (id.match(/^shout-flag-(\d+)/)) {
+            id = RegExp.$1;
+            if (confirm('Only flag a shout if you feel it is spam, abuse, violates site rules, ' +
+                    'or is not appropriate. ' +
+                    'A moderator will be notified and will review the shout. ' +
+                    'Are you sure you want to flag this shout?')) {
+                $.post('/shout/flag/', { id : id }, function(response) {
+                    alert(response);
+                    }, 'text');
+             }            
+         }
+         return false;
+     });
  });