Revision: 531
Author: fragro
Date: Fri Jan 28 02:56:45 2011
Log: added notifications and made some small edits
http://code.google.com/p/pirate-politics/source/detail?r=531
Added:
/trunk/pirate-politics/new_templates/robots.txt
/trunk/pirate-politics/pirate_messages
/trunk/pirate-politics/pirate_messages/__init__.py
/trunk/pirate-politics/pirate_messages/models.py
/trunk/pirate-politics/pirate_messages/templatetags
/trunk/pirate-politics/pirate_messages/templatetags/__init__.py
/trunk/pirate-politics/pirate_messages/templatetags/notificationtags.py
/trunk/pirate-politics/pirate_messages/tests.py
/trunk/pirate-politics/pirate_messages/views.py
/trunk/pirate-politics/static/mail.png
/trunk/pirate-politics/static/no-mail.png
Modified:
/trunk/pirate-politics/ajaxapi/views.py
/trunk/pirate-politics/new_templates/base.html
/trunk/pirate-politics/new_templates/issue_detail.html
/trunk/pirate-politics/new_templates/solution_detail.html
/trunk/pirate-politics/new_templates/user_profile.html
/trunk/pirate-politics/pirate_comments/models.py
/trunk/pirate-politics/pirate_comments/templatetags/commenttags.py
/trunk/pirate-politics/pirate_core/middleware.py
/trunk/pirate-politics/pirate_core/templatetags/pp_url.py
/trunk/pirate-politics/pirate_deliberation/models.py
/trunk/pirate-politics/pirate_deliberation/templatetags/argumenttags.py
/trunk/pirate-politics/pirate_issues/templatetags/issuetags.py
/trunk/pirate-politics/pirate_issues/templatetags/solutiontags.py
/trunk/pirate-politics/pirate_signals/models.py
/trunk/pirate-politics/settings.py
/trunk/pirate-politics/static/favicon.ico
/trunk/pirate-politics/static/style.css
=======================================
--- /dev/null
+++ /trunk/pirate-politics/new_templates/robots.txt Fri Jan 28 02:56:45 2011
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:
=======================================
--- /dev/null
+++ /trunk/pirate-politics/pirate_messages/models.py Fri Jan 28 02:56:45
2011
@@ -0,0 +1,50 @@
+from django.db import models
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.contenttypes import generic
+import datetime
+import django.dispatch
+from django.contrib import admin
+from django.utils.translation import ugettext as _
+from django.contrib.auth.models import User
+from pirate_signals.models import notification_send
+
+# Create your models here.
+
+class Message(models.Model):
+
+ sender = models.ForeignKey(User, null=True,
related_name="message_sender")
+ receiver = models.ForeignKey(User, related_name="message_receiver")
+ text = models.TextField(max_length=1200)
+
+class Notification(models.Model):
+ receiver = models.ForeignKey(User,
related_name="notification_receiver")
+ sender = models.ForeignKey(User, related_name="notification_sender")
+ text = models.TextField(max_length=1200)
+ link = models.CharField(max_length=250)
+ content_type = models.ForeignKey(ContentType,
+ verbose_name=_('content type'),
+
related_name="content_type_set_for_%(class)s")
+ object_pk = models.IntegerField(_('object ID'))
+ content_object = generic.GenericForeignKey(ct_field="content_type",
fk_field="object_pk")
+ is_read = models.BooleanField()
+ submit_date = models.DateTimeField("date_sent")
+
+ def __unicode__(self):
+ return str(self.content_type) + ':' + str(self.object_pk)
+
+admin.site.register(Notification)
+
+#obj specifies the obj being replied to, new_obj specifies the new object
+def create_notification(obj,reply_to,**kwargs):
+ content_type = ContentType.objects.get_for_model(obj)
+ rep_type = ContentType.objects.get_for_model(reply_to)
+ if len(obj.text) > 30: tt = str(obj.text)[0:30] + "..."
+ else: tt = str(obj.text)
+ text = str(obj.user.username) + " replied to your " + str(rep_type)
+ ": " + tt + "..."
+ link = obj.get_absolute_url()
+ notif = Notification(receiver=obj.user,
sender=reply_to.user,text=text,link=link,content_type=rep_type,object_pk=
reply_to.pk,is_read=False,submit_date=datetime.datetime.now())
+ notif.save()
+
+notification_send.connect(create_notification)
+
+
=======================================
--- /dev/null
+++ /trunk/pirate-politics/pirate_messages/templatetags/notificationtags.py
Fri Jan 28 02:56:45 2011
@@ -0,0 +1,91 @@
+from django import template
+from django import forms
+from django.http import HttpResponse, HttpResponseRedirect
+from django.utils import simplejson
+from pirate_messages.models import Notification
+from django.db import transaction
+from django.middleware import csrf
+from django.contrib.contenttypes.models import ContentType
+from pirate_profile.models import Profile
+from django.utils.encoding import smart_str
+from ajaxapi.views import clean_html
+from pirate_core.views import template_for_model
+
+import datetime
+from pirate_signals.models import notification_send
+
+from django.shortcuts import get_object_or_404
+
+from pirate_core.views import HttpRedirectException, namespace_get
+
+from customtags.decorators import block_decorator
+register = template.Library()
+block = block_decorator(register)
+
+get_namespace = namespace_get('pp_messages')
+
+
+@block
+def pp_has_mail(context, nodelist, *args, **kwargs):
+ context.push()
+ namespace = get_namespace(context)
+
+ user = kwargs.get('user', None)
+
+ notes = Notification.objects.all()
+ notes = notes.filter(receiver=user,is_read=False)
+ count = len(list(notes))
+
+ if count == 0: has_mail = False
+ else: has_mail = True
+ namespace['has_mail'] = has_mail
+ namespace['count'] = count
+
+ output = nodelist.render(context)
+ context.pop()
+
+ return output
+
+
+@block
+def pp_notification_unread_list_get(context, nodelist, *args, **kwargs):
+ context.push()
+ namespace = get_namespace(context)
+
+ user = kwargs.get('user', None)
+
+ notes = Notification.objects.all()
+ notes = notes.filter(receiver=user,is_read=False)
+ notes = notes.order_by('-submit_date')
+ for i in notes:
+ i.is_read = True
+ i.save()
+
+ namespace['notifications'] = notes
+
+ output = nodelist.render(context)
+ context.pop()
+
+ return output
+
+
+@block
+def pp_notification_read_list_get(context, nodelist, *args, **kwargs):
+ context.push()
+ namespace = get_namespace(context)
+
+ user = kwargs.get('user', None)
+
+ notes = Notification.objects.all()
+ notes = notes.filter(receiver=user,is_read=True)
+ notes = notes.order_by('-submit_date')
+ for i in notes:
+ i.is_read = True
+ i.save()
+
+ namespace['notifications'] = notes
+
+ output = nodelist.render(context)
+ context.pop()
+
+ return output
=======================================
--- /dev/null
+++ /trunk/pirate-politics/pirate_messages/tests.py Fri Jan 28 02:56:45 2011
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
=======================================
--- /dev/null
+++ /trunk/pirate-politics/pirate_messages/views.py Fri Jan 28 02:56:45 2011
@@ -0,0 +1,1 @@
+# Create your views here.
=======================================
--- /dev/null
+++ /trunk/pirate-politics/static/mail.png Fri Jan 28 02:56:45 2011
@@ -0,0 +1,15 @@
+‰PNG
+
+
+IHDR óÿa sRGB ®Î
+é bKGD ÿ ÿ ÿ ½§“ pHYs šœ tIME Û
+
+6+»µj8 ÜIDAT8ËÕ“¿kSq Å?÷›÷#éKß³ ¦h)¥‹¸t©"(‚88¸HÛYg g[ ÿ té¢kÁE Etè"¥‹PwE¨” Lûò^ ûjšä}¯Cc ý zÇË9‡sîá© ðý¡êèØ¹EÔ‚ EkÝ0ï žª«@[µÛ4&ëˆé*J¯—ÓˆëO¬íÕ
+ E*®±³» äñ _{«7aª
+ã
+
+Èv`{ Ù|Y©Þ Ë¥ÅĘ ,G ˆÐl5ŸGŽ3‘ áÜ|ÖÚ r 5à¶ò6ªL F'÷ —úæ1ƒijiü"s
+ JÁÕ“Y á•mìõïñÎ ¨Š ˆ ú‹ò»fúþ›ãL<ðK—ŽÉCá̆S8ÿ±™¾ò!P@U p ¬µ€þóâ—œu×½|
ñ=¯h?ûîÌH·»[èƒ Ð>Þ cþÒ÷oWÇg'[éÖz /çj%íü.~ŠëË3 Ù×[#£sÀ¾ˆù¿F¯8|!
+Ëó¡ã N7~Æo Û›€wâ »~ql-ªLfð#Iâ5Ûël
+µ€ †á½$Ý{v6· ^›ÂTU ÷Ð@ k”úp®_š=½v&*?L’xíØAÁñªQ - Œ ª”À
+s ø¨ pˆv÷Ädm‘®ˆ IÒxª6¯ þ_â àˆÄJøcð IEND®B`‚
=======================================
--- /dev/null
+++ /trunk/pirate-politics/static/no-mail.png Fri Jan 28 02:56:45 2011
@@ -0,0 +1,17 @@
+‰PNG
+
+
+IHDR óÿa ÍIDATxÚÍ“?oÓ@ ÆïœÆ /vÓÄ I[$6
+²C‡¸ˆ o@Õ¡Tl°D
+ø3ò
+è ±Bb%3B*; m”ªÍù|§:*Äö
+wNZ2dëÒ»Å~õ>??zÞ× ÜñÀû 0{Ýoµ €à² Ë"ç¼l óg8o òæy b|ñžó|X tà 7
+´¾Œcò.MY¿T-ûš„¯ÖýÈEÖÁp4zVäÓï3€‰Bd ‘ šÅ 8aɸ¿Ì¬ßÚì >íp¡ RJ¾ ùßE€ ‚{ fë ´ø“QÜ_ 7üv Eö ã˽F3xÉ
+äÙŸ À°ÜÒA
+ {ê½¾æ¿Í²ü$½JJH½ÑîV`ÑÁøbOŰÖv M · ª
+]dJ îi• [‡yvýhr==6-Ä« ïæEñK öUÐÒÁnBÉ€ßd
+8¶
+1ÊzAûá!M. LÒ«#Û©½Ð fÉ`?ÙŽûÄqj
+<>ßW ’àÿ ݬ
+ž‹vªºå1%ž¤G˦ O òdˆ|$óZ pksã+IèG)þ¬BSW 9uiYÌw BMA¶W=ôúôì÷ó[@eE_÷<ïUE›‰Ô¼
+¸Y#PÖ wAv Bâ ‚ Ã{ò/Üåü Qùè öåà IEND®B`‚
=======================================
--- /trunk/pirate-politics/ajaxapi/views.py Fri Jan 21 16:05:49 2011
+++ /trunk/pirate-politics/ajaxapi/views.py Fri Jan 28 02:56:45 2011
@@ -12,6 +12,56 @@
from pirate_reputation.models import ReputationDimension
+from BeautifulSoup import BeautifulSoup
+
+acceptable_elements =
['a', 'abbr', 'acronym', 'address', 'area', 'b', 'big',
+ 'blockquote', 'br', 'button', 'caption', 'center', 'cite', 'code', 'col',
+ 'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt', 'em',
+ 'font', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img',
+ 'ins', 'kbd', 'label', 'legend', 'li', 'map', 'menu', 'ol',
+ 'p', 'pre', 'q', 's', 'samp', 'small', 'span', 'strike',
+ 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th',
+ 'thead', 'tr', 'tt', 'u', 'ul', 'var']
+
+acceptable_attributes = ['abbr', 'accept', 'accept-charset', 'accesskey',
+ 'action', 'align', 'alt', 'axis', 'border', 'cellpadding', 'cellspacing',
+ 'char', 'charoff', 'charset', 'checked', 'cite', 'clear', 'cols',
+ 'colspan', 'color', 'compact', 'coords', 'datetime', 'dir',
+ 'enctype', 'for', 'headers', 'height', 'href', 'hreflang', 'hspace',
+ 'id', 'ismap', 'label', 'lang', 'longdesc', 'maxlength', 'method',
+ 'multiple', 'name', 'nohref', 'noshade', 'nowrap', 'prompt',
+ 'rel', 'rev', 'rows', 'rowspan', 'rules', 'scope', 'shape', 'size',
+ 'span', 'src', 'start', 'summary', 'tabindex', 'target', 'title', 'type',
+ 'usemap', 'valign', 'value', 'vspace', 'width']
+
+
+"""This function cleans up user-generated text inputs so to disallow
dangerous
+ html such as <script></script> but still allow html modifications and
markdown"""
+def clean_html( fragment ):
+ while True:
+ soup = BeautifulSoup( fragment )
+ removed = False
+ for tag in soup.findAll(True): # find all tags
+ if
tag.name not in acceptable_elements:
+ tag.extract() # remove the bad ones
+ removed = True
+ else: # it might have bad attributes
+ # a better way to get all attributes?
+ for attr in tag._getAttrMap().keys():
+ if attr not in acceptable_attributes:
+ del tag[attr]
+
+ # turn it back to html
+ fragment = unicode(soup)
+
+ if removed:
+ # we removed tags and tricky can could exploit that!
+ # we need to reparse the html until it stops changing
+ continue # next round
+
+ return fragment
+
+#DELETE FUNCTIONS
def delete_source(request,object_id):
obj = get_object_or_404(URLSource,id=object_id)
obj.delete()
=======================================
--- /trunk/pirate-politics/new_templates/base.html Thu Jan 27 20:02:47 2011
+++ /trunk/pirate-politics/new_templates/base.html Fri Jan 28 02:56:45 2011
@@ -2,6 +2,7 @@
{% load topictags %}
{% load usertags %}
{% load reputationtags %}
+{% load notificationtags %}
<!DOCTYPE html
@@ -27,6 +28,22 @@
<script type="text/javascript"
src="/static/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
+
+
+ function ScrollToElement(theElement){
+
+ var selectedPosX = 0;
+ var selectedPosY = 0;
+
+ while(theElement != null){
+ selectedPosX += theElement.offsetLeft;
+ selectedPosY += theElement.offsetTop;
+ theElement = theElement.offsetParent;
+ }
+
+ window.scrollTo(selectedPosX,selectedPosY);
+
+ }
jQuery(document).ready(function(){
$('#collapsible_comments').collapsible();
@@ -79,9 +96,28 @@
{% endblock %}
{% block extra-head %}{% endblock %}
+
+ <script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-21028017-1']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type
= 'text/javascript'; ga.async = true;
+ ga.src = ('https:' ==
document.location.protocol ? '
https://ssl' : '
http://www')
+ '.
google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
+ })();
+
+ </script>
</head>
+{% if request.scroll_to %}
+<body onload="ScrollToElement({{request.scroll_to_div}})">
+{% else %}
<body>
+{% endif%}
+
<div id="header">
<div class="headtitle"><a STYLE="text-decoration:none" href="{% pp_url
template='issues.html' dimension='hot'%}">
egalit.ar</a></div>
<ul>
@@ -129,6 +165,13 @@
{% pp_get_reputation user=request.user %}
<ul>hello
<li><a href="{% pp_url template='user_profile.html'
object=request.user%}">{{request.user.username}}</a></li> |
+ {% pp_has_mail user=request.user %}
+ {% if pp_messages.has_mail %}
+ <li><a class="mailbutton" href="{% pp_url
template='user_profile.html' object=request.user%}" ></a> </li> |
+ {% else %}
+ <li><a class="nomailbutton" href="{% pp_url
template='user_profile.html' object=request.user%}" ></a> </li> |
+ {% endif %}
+ {% endpp_has_mail %}
<li>rep: {{ pp_reputation.reputation }}</li> |
<li><a STYLE="text-decoration:none" href="/logout/">logout</a></li>
{% endpp_get_reputation %}
@@ -152,8 +195,12 @@
{% endif %}
{% endblock %}
- {% block content %}
- These aren't the droids you are looking for.{% endblock %}
+ {% autoescape on %}
+ {% block content %}
+ These aren't the droids you are looking for.
+ {% endblock %}
+ {% endautoescape %}
+
</div>
</div>
<div id="footer">
=======================================
--- /trunk/pirate-politics/new_templates/issue_detail.html Wed Jan 26
22:18:11 2011
+++ /trunk/pirate-politics/new_templates/issue_detail.html Fri Jan 28
02:56:45 2011
@@ -81,7 +81,7 @@
</div>
<div class="details">
- {{pp_issue.issue.text|markdown}}
+ {{pp_issue.issue.text|markdown|escape }}
</div>
{% include "_sourcetags.html" %}
=======================================
--- /trunk/pirate-politics/new_templates/solution_detail.html Wed Jan 26
22:18:11 2011
+++ /trunk/pirate-politics/new_templates/solution_detail.html Fri Jan 28
02:56:45 2011
@@ -75,7 +75,10 @@
<div class="details">
- {{pp_solution.solution.text|markdown}}
+ {% autoescape on %}
+ {{pp_solution.solution.text|markdown }}
+ {% endautoescape %}
+
</div>
=======================================
--- /trunk/pirate-politics/new_templates/user_profile.html Thu Jan 27
20:02:47 2011
+++ /trunk/pirate-politics/new_templates/user_profile.html Fri Jan 28
02:56:45 2011
@@ -5,6 +5,7 @@
{% load profiletags %}
{% load topictags %}
{% load reputationtags %}
+{% load notificationtags %}
{% block css %}
@@ -72,6 +73,29 @@
{% endif %}
{% endifequal %}
{% endif %}
+
+ <hr>
+
+ <h3> Notifications </h3>
+
+ <h4> Unread Notifications: </h4>
+ {% pp_notification_unread_list_get user=request.user %}
+ <ul>
+ {% for note in pp_messages.notifications %}
+ <li><a href="{{note.link}}">{{ note.text }}</a></li>
+ {% empty %}None for the moment.
+ {% endfor %}
+ </ul>
+ {% endpp_notification_unread_list_get %}
+ <h4> Read Notifications: </h4>
+ {% pp_notification_read_list_get user=request.user %}
+ <ul>
+ {% for note in pp_messages.notifications %}
+ <li><a href="{{note.link}}">{{ note.text }}</a></li>
+ {% empty %}None for the moment.
+ {% endfor %}
+ </ul>
+ {% endpp_notification_read_list_get %}
{% if request.user.is_staff %}
<hr>
=======================================
--- /trunk/pirate-politics/pirate_comments/models.py Wed Jan 26 15:58:58
2011
+++ /trunk/pirate-politics/pirate_comments/models.py Fri Jan 28 02:56:45
2011
@@ -30,20 +30,10 @@
def __unicode__(self):
return self.user.username + ":" + str(self.submit_date)
- @models.permalink
- #This must be added to all classes that can be tagged
def get_absolute_url(self):
content_type = self.content_type
- path = template_for_model(str(content_type)) + "?_t=" +
str(
content_type.pk) + "&_o=" + str(self.object_pk)
+ path = template_for_model(str(content_type)) + "?_t=" +
str(
content_type.pk) + "&_o=" + str(self.object_pk) +"&_c=comment" +
str(
self.id)
return path
-
- def save(self, *args, **kwargs):
- new_comment = super(Comment, self).save(*args, **kwargs)
- try:
- new_comment.reply_to.is_leaf = False
- new_comment.reply_to.save()
- except: pass
- return new_comment
admin.site.register(Comment)
=======================================
--- /trunk/pirate-politics/pirate_comments/templatetags/commenttags.py Wed
Jan 26 15:58:58 2011
+++ /trunk/pirate-politics/pirate_comments/templatetags/commenttags.py Fri
Jan 28 02:56:45 2011
@@ -7,8 +7,12 @@
from django.middleware import csrf
from django.contrib.contenttypes.models import ContentType
from pirate_profile.models import Profile
+from django.utils.encoding import smart_str
+from ajaxapi.views import clean_html
+from pirate_core.views import template_for_model
import datetime
+from pirate_signals.models import notification_send
from django.shortcuts import get_object_or_404
@@ -98,6 +102,7 @@
return ret_html
+#TODO: FIX ME
def generate_time_string(then, now):
time_to = abs(now - then)
hours = time_to.seconds / 360
@@ -118,11 +123,12 @@
#ok this is as ugly as it gets, but there's little other ways to generate
this html that I am aware of
def render_comment(comment_obj, count, user, request):
content_type = ContentType.objects.get_for_model(comment_obj.user)
+ path = template_for_model(str(comment_obj.content_type)) + "?_t=" +
str(
comment_obj.content_type.pk) + "&_o=" + str(comment_obj.object_pk)
+"&_c=comment" + str(
comment_obj.id)
form =
ReplyForm(initial={'is_root':False,'is_leaf':True,'content_type':comment_obj.content_type,'object_pk':comment_obj.object_pk,'reply_to':comment_obj, 'submit_date':datetime.datetime.now(),'user':user})
if count == 0 or count > 1: plural = "s"
else: plural = ""
"""returns the relevant html for a single atomic comment given the
comment object"""
- return " <div class='comment_user'> <a href='/user_profile.html"
+ "?_t=" + str(
content_type.pk) + "&_o=" + str(
comment_obj.user.pk) + "'>"
+ str(comment_obj.user.username)+ "</a>" +
generate_time_string(comment_obj.submit_date, datetime.datetime.now())
+ ":</div><div>" + str(comment_obj.text) +"</div><div
class='comment_reply'>" + " <a href='javascript:;' onmousedown="
+ "'toggleSlide(" + '"add_reply' + str(
comment_obj.id) + '"'
+ ");'>reply</a><div id='add_reply" + str(
comment_obj.id) + "'
style='display:none; overflow:hidden; height:250px;'><form method='post'
action=''><div style='display:none'><input type='hidden'
name='csrfmiddlewaretoken' value='" + str(csrf.get_token(request)) + "'
/><input id='reply_to_object' type='hidden' name='reply_to_object' value='"
+ str(
comment_obj.id)+ "'/></div>" + str(form.as_p()) + "<input
type='submit' class='button green' value='Submit
Comment'></form></div></div>"
+ return "<div id='comment" + str(
comment_obj.id) + "'> <div
class='comment_user'> <a href='/user_profile.html" + "?_t=" +
str(
content_type.pk) + "&_o=" + str(
comment_obj.user.pk) + "'>" +
str(comment_obj.user.username)+ "</a>" +
generate_time_string(comment_obj.submit_date, datetime.datetime.now())
+ ":</div><div>" + smart_str(comment_obj.text, encoding='utf-8',
strings_only=False, errors='strict') +"</div><div class='comment_reply'>"
+ " <a href='javascript:;' onmousedown=" + "'toggleSlide(" + '"add_reply' +
str(
comment_obj.id) + '"' + ");'>reply</a> <a href='/" + path
+ "'>permalink</a><div id='add_reply" + str(
comment_obj.id) + "'
style='display:none; overflow:hidden; height:250px;'><form
id='add_reply_form" + str(
comment_obj.id) +"' method='post' action=''><div
style='display:none'><input type='hidden' name='csrfmiddlewaretoken'
value='" + str(csrf.get_token(request)) + "' /><input id='reply_to_object'
type='hidden' name='reply_to_object' value='" +
str(
comment_obj.id)+ "'/></div>" + str(form.as_p()) + "<input type='submit'
class='button green' value='Submit Comment'></form></div></div></div>"
def get_children(object_pk,cur_comment):
get_list = []
@@ -135,64 +141,6 @@
get_list.append(get_children(object_pk,c))
return [(cur_comment, len(comments)), get_list]
-@block
-def pp_comment_form2(context, nodelist, *args, **kwargs):
-
- context.push()
- namespace = get_namespace(context)
-
- POST = kwargs.get('POST', None)
- path = kwargs.get('path', None)
- obj = kwargs.get('object',None)
- comment = kwargs.get('edit',None)
- user = kwargs.get('user', None)
-
- if obj == None:
- raise ValueException("The designer must specify 'object' to the
form of type models.Model ")
- if user == None:
- raise ValueException("The designer must specify one of 'user',
generally request.user ")
-
- if isinstance(obj, Comment):
- root = obj
- else:
- root = None
-
- if POST and POST.get("form_id") == "pp_comment_form":
-
- form = CommentForm(POST) if comment is None else CommentForm(POST,
instance=comment)
-
- c_type = ContentType.objects.get_for_model(obj.__class__)
-
- if form.is_valid():
- if root == None:
- com = NSComment.add_root(
- user=user,
- text=form.cleaned_data['text'],
- created=datetime.datetime.now(),
- content_type=c_type,
- object_pk =
obj.pk)
- else:
- com = root.add_child(
- user=form.cleaned_data['user'],
- text=form.cleaned_data['text'],
- created=datetime.datetime.now(),
- content_type=c_type,
- object_pk =
obj.pk)
-
- if not root:
- root = com
-
- raise
HttpRedirectException(HttpResponseRedirect(obj.get_absolute_url()))
- else:
- form = CommentForm() if comment is None else
CommentForm(instance=comment)
-
- namespace['form'] = form
- output = nodelist.render(context)
- context.pop()
-
- return output
-
-
@block
def pp_comment_form(context, nodelist, *args, **kwargs):
@@ -229,13 +177,16 @@
newcomment.user = user
newcomment.content_type = c_type
newcomment.object_pk = object_pk
+ newcomment.text = clean_html(newcomment.text)
newcomment.reply_to = reply_to
newcomment.is_leaf = True
newcomment.submit_date = datetime.datetime.now()
if reply_to == None: newcomment.is_root = True #non-root
comments will use auto-generated reply form
else: newcomment.is_root = False
newcomment.save()
- raise
HttpRedirectException(HttpResponseRedirect(newcomment.content_object.get_absolute_url()))
+ if comment is None: #if comment is new and not editted
+
notification_send.send(sender=newcomment,obj=newcomment,reply_to=newcomment.content_object)
+ raise
HttpRedirectException(HttpResponseRedirect(newcomment.get_absolute_url()))
if POST and POST.get("form_id") == "pp_reply_form":
form = ReplyForm(POST) if comment is None else ReplyForm(POST,
instance=comment)
@@ -248,11 +199,14 @@
newcomment.reply_to = Comment.objects.get(pk=com_rep)
newcomment.reply_to.is_leaf = False
newcomment.reply_to.save()
+ newcomment.text = clean_html(newcomment.text)
newcomment.is_leaf = True
newcomment.is_root = False
newcomment.submit_date = datetime.datetime.now()
newcomment.save()
- raise
HttpRedirectException(HttpResponseRedirect(newcomment.content_object.get_absolute_url()))
+ if comment is None: #if comment is new and not editted
+
notification_send.send(sender=newcomment,obj=newcomment,reply_to=newcomment.reply_to)
+ raise
HttpRedirectException(HttpResponseRedirect(newcomment.get_absolute_url()))
else: form = CommentForm() if comment is None else
CommentForm(instance=comment)
=======================================
--- /trunk/pirate-politics/pirate_core/middleware.py Tue Jan 25 15:15:31
2011
+++ /trunk/pirate-politics/pirate_core/middleware.py Fri Jan 28 02:56:45
2011
@@ -6,6 +6,7 @@
START_KEY = "_s"
END_KEY = "_e"
DIM_KEY = "_d"
+SCROLL_KEY = "_c"
class UrlMiddleware(object):
"""
@@ -23,6 +24,7 @@
start = request.GET.get(START_KEY)
end = request.GET.get(END_KEY)
dim = request.GET.get(DIM_KEY)
+ scroll_to = request.GET.get(SCROLL_KEY)
if content_type_id is not None and obj_id is not None:
content_type = ContentType.objects.get(pk=content_type_id)
@@ -33,6 +35,10 @@
if dim is not None:
request.dimension = dim
+
+ if scroll_to:
+ request.scroll_to = True
+ request.scroll_to_div = scroll_to
request_path = request.get_full_path()
name = request_path
=======================================
--- /trunk/pirate-politics/pirate_core/templatetags/pp_url.py Fri Jan 21
16:05:49 2011
+++ /trunk/pirate-politics/pirate_core/templatetags/pp_url.py Fri Jan 28
02:56:45 2011
@@ -9,7 +9,7 @@
register = template.Library()
function = function_decorator(register)
-from pirate_core.middleware import TYPE_KEY, OBJ_KEY, START_KEY, END_KEY,
DIM_KEY
+from pirate_core.middleware import TYPE_KEY, OBJ_KEY, START_KEY, END_KEY,
DIM_KEY, SCROLL_KEY
'''
This file contains the tag responsible for creating useful urls within pp
templates.
@@ -67,6 +67,7 @@
start = kwargs.pop('start', None)
end = kwargs.pop('end', None)
dimension = kwargs.pop('dimension',None)
+ scroll_to = kwargs.pop('scroll_to',None) #argument for javascript
scroll_to function
pattern = kwargs.pop('view', 'pp-page')
@@ -84,6 +85,9 @@
raise ValueError("If 'object' argument is specified, it must
be of type "
"django.models.Model. Specified object is of
type '%s.'"
% obj.__class__.__name__)
+
+ if scroll_to is not None:
+ rev_kwargs['scroll_to'] = scroll_to
if start is not None and end is not None:
rev_kwargs['start'] = start
@@ -106,7 +110,7 @@
return output
-def get_reverse(pattern, kwargs, content_type_id=None, obj_id=None,
start=None, end=None,dimension=None):
+def get_reverse(pattern, kwargs, content_type_id=None, obj_id=None,
start=None, end=None,dimension=None,scroll_to=None):
url = reverse(pattern, kwargs=kwargs)
qs = []
if content_type_id is not None and obj_id is not None:
@@ -117,6 +121,8 @@
qs.append(END_KEY + "=" + str(end))
if dimension is not None:
qs.append(DIM_KEY + "=" + str(dimension))
+ if scroll_to is not None:
+ qs.append(SCROLL_KEY + "=" + str(scroll_to))
qs = "?" + "&".join(qs)
return url + qs
=======================================
--- /trunk/pirate-politics/pirate_deliberation/models.py Tue Jan 18
11:59:15 2011
+++ /trunk/pirate-politics/pirate_deliberation/models.py Fri Jan 28
02:56:45 2011
@@ -21,7 +21,7 @@
pub_date = models.DateTimeField('date_published', blank=True,null=True)
parent = models.ForeignKey(Solution) #Issue
user = models.ForeignKey(User, related_name='arg_author')
- text = models.CharField(max_length=1000)
+ text = models.TextField(max_length=1200)
arg_type = models.ForeignKey(Stance)
#comments = generic.GenericRelation(Comment)
=======================================
--- /trunk/pirate-politics/pirate_deliberation/templatetags/argumenttags.py
Tue Jan 25 15:15:31 2011
+++ /trunk/pirate-politics/pirate_deliberation/templatetags/argumenttags.py
Fri Jan 28 02:56:45 2011
@@ -2,16 +2,17 @@
from django import forms
from django.http import HttpResponseRedirect
import datetime
-from pirate_issues.models import Topic, Issue, Solution
+from pirate_issues.models import Topic, Issue, Solution
from django.contrib.contenttypes.models import ContentType
from pirate_deliberation.models import Argument, Stance
from pirate_consensus.models import Consensus, UpDownVote
from pirate_reputation.models import ReputationDimension
+from ajaxapi.views import clean_html
from pirate_core import HttpRedirectException, namespace_get, FormMixin
from pirate_issues.models import Topic, Issue
-from pirate_signals.models import aso_rep_event
+from pirate_signals.models import aso_rep_event,notification_send
from customtags.decorators import block_decorator
register = template.Library()
@@ -124,6 +125,8 @@
new_arg.pub_date = datetime.datetime.now()
new_arg.parent = solution
new_arg.user = request.user
+ new_arg.text = clean_html(new_arg.text)
+
new_arg.name = clean_html(
new_arg.name)
new_arg.arg_type = arg_type
new_arg.save()
contype = ContentType.objects.get_for_model(Argument)
@@ -133,6 +136,7 @@
if is_new: #if this is a new issue/consensus, send signal for
reputation
aso_rep_event.send(sender=new_arg,event_score=4,
user=new_arg.user,
dimension=ReputationDimension.objects.get('add_argument'))
+
notification_send.send(sender=new_arg.user,obj=new_arg,reply_to=new_arg.parent)
new_arg.parent.arguments += 1
new_arg.parent.issue.arguments +=1
new_arg.parent.issue.save()
=======================================
--- /trunk/pirate-politics/pirate_issues/templatetags/issuetags.py Wed Jan
26 15:29:32 2011
+++ /trunk/pirate-politics/pirate_issues/templatetags/issuetags.py Fri Jan
28 02:56:45 2011
@@ -10,6 +10,7 @@
from pirate_consensus.models import UpDownVote, Consensus
from django.utils.translation import ugettext as _
from pirate_reputation.models import ReputationDimension
+from ajaxapi.views import clean_html
from pirate_signals.models import aso_rep_event
@@ -275,6 +276,8 @@
issue.user = request.user
issue.solutions = 0
issue.arguments = 0
+
issue.name = clean_html(
issue.name)
+ issue.text = clean_html(issue.text)
if isinstance(topic, Topic):
issue.topic = topic
issue.save()
=======================================
--- /trunk/pirate-politics/pirate_issues/templatetags/solutiontags.py Tue
Jan 25 15:15:31 2011
+++ /trunk/pirate-politics/pirate_issues/templatetags/solutiontags.py Fri
Jan 28 02:56:45 2011
@@ -10,8 +10,9 @@
from pirate_consensus.models import UpDownVote, Consensus
from django.utils.translation import ugettext as _
from pirate_reputation.models import ReputationDimension
-
-from pirate_signals.models import aso_rep_event
+from ajaxapi.views import clean_html
+
+from pirate_signals.models import aso_rep_event, notification_send
from customtags.decorators import block_decorator
register = template.Library()
@@ -164,6 +165,8 @@
new_sol = form.save(commit=False)
new_sol.submit_date = datetime.datetime.now()
new_sol.issue = issue
+ new_sol.text = clean_html(new_sol.text)
+
new_sol.name = clean_html(
new_sol.name)
new_sol.comments = 0
new_sol.arguments = 0
new_sol.user = request.user
@@ -176,13 +179,12 @@
if is_new: #if this is a new issue/consensus, send signal for
reputation
aso_rep_event.send(sender=new_sol,event_score=5,
user=new_sol.user,
dimension=ReputationDimension.objects.get('add_solution'))
+
notification_send.send_robust(sender=new_sol.user,obj=new_sol,reply_to=new_sol.issue)
issue.solutions = issue.solutions+1
issue.save()
raise
HttpRedirectException(HttpResponseRedirect(new_sol.get_absolute_url()))
- load = "{% load pp_url %}"
- ts = "{% pp_url template='issue_detail.html' object=issue %}"
- path = template.Template(load +
ts).render(template.Context({'issue':issue}))
+ path = new_sol.get_absolute_url()
raise HttpRedirectException(HttpResponseRedirect(path))
else:
form = SolutionForm() if solution is None else
SolutionForm(instance=solution)
=======================================
--- /trunk/pirate-politics/pirate_signals/models.py Fri Jan 21 16:05:49 2011
+++ /trunk/pirate-politics/pirate_signals/models.py Fri Jan 28 02:56:45 2011
@@ -3,5 +3,6 @@
aso_rep_event =
django.dispatch.Signal(providing_args=["event_score", "user"])
aso_rep_delete =
django.dispatch.Signal(providing_args=["event_score", "user"])
+notification_send =
django.dispatch.Signal(providing_args=["obj","reply_to"])
=======================================
--- /trunk/pirate-politics/settings.py Tue Jan 25 15:15:31 2011
+++ /trunk/pirate-politics/settings.py Fri Jan 28 02:56:45 2011
@@ -24,6 +24,7 @@
'pirate_consensus',
'pirate_extensions',
'pirate_reputation',
+ 'pirate_messages',
'pirate_login',
'pirate_profile',
'pirate_sources',
=======================================
--- /trunk/pirate-politics/static/favicon.ico Thu Jan 27 01:48:18 2011
+++ /trunk/pirate-politics/static/favicon.ico Fri Jan 28 02:56:45 2011
Binary file, no diff available.
=======================================
--- /trunk/pirate-politics/static/style.css Thu Jan 27 20:02:47 2011
+++ /trunk/pirate-politics/static/style.css Fri Jan 28 02:56:45 2011
@@ -584,6 +584,7 @@
font-size:75%;
position:absolute;
right:1%;
+ top:-30%;
padding:0px 0px 0px 0px;
}
@@ -738,6 +739,20 @@
list-style-type:none;
}
/* BUTTONS */
+
+
+.mailbutton {
+ padding: 1px 8px;
+ margin-right:4px;
+ background: url(mail.png) repeat-x bottom;
+ }
+
+
+.nomailbutton {
+ padding: 1px 8px;
+ margin-right:4px;
+ background: url(no-mail.png) repeat-x bottom;
+ }
.button {
padding: 5px 10px;