summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-09-22 00:45:40 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-09-22 00:45:40 -0400
commit4b343ee9542435008543b7a2f63cd0550fb2575a (patch)
treec8f09b93b85fa9b19991e79c568684943594921d
parent3cf76880c1dfb6032613b68832a7bee38be6d694 (diff)
downloadaskbot-4b343ee9542435008543b7a2f63cd0550fb2575a.tar.gz
askbot-4b343ee9542435008543b7a2f63cd0550fb2575a.tar.bz2
askbot-4b343ee9542435008543b7a2f63cd0550fb2575a.zip
hopefully fixed format of instant emails, made feedback to be sent to moderators and admins, changed comment rendering into div and a small fix to livesearch.js
-rw-r--r--askbot/__init__.py29
-rw-r--r--askbot/conf/email.py9
-rw-r--r--askbot/models/__init__.py16
-rw-r--r--askbot/models/content.py23
-rw-r--r--askbot/models/meta.py8
-rw-r--r--askbot/models/question.py6
-rwxr-xr-xaskbot/skins/default/media/js/com.cnprog.post.js4
-rw-r--r--askbot/skins/default/media/js/live_search.js6
-rwxr-xr-xaskbot/skins/default/media/style/style.css2
-rw-r--r--askbot/skins/default/templates/instant_notification.html7
-rw-r--r--askbot/skins/default/templates/question.html13
-rw-r--r--askbot/skins/default/templates/questions.html8
-rw-r--r--askbot/startup_tests.py4
-rw-r--r--askbot/tests/email_alert_tests.py34
-rw-r--r--askbot/views/meta.py4
-rw-r--r--askbot/views/readers.py14
16 files changed, 143 insertions, 44 deletions
diff --git a/askbot/__init__.py b/askbot/__init__.py
index 0b7e61bb..6c3fac23 100644
--- a/askbot/__init__.py
+++ b/askbot/__init__.py
@@ -24,6 +24,8 @@ def get_version():
"""
return '0.6.11'
+#todo: maybe send_mail functions belong to models
+#or the future API
def send_mail(
subject_line = None,
body_text = None,
@@ -44,9 +46,11 @@ def send_mail(
if raise_on_failure is True, exceptions.EmailNotSent is raised
"""
- #print subject_line
- #print body_text
+ from askbot.conf import settings as askbot_settings
+ prefix = askbot_settings.EMAIL_SUBJECT_PREFIX.strip() + ' '
try:
+ assert(subject_line is not None)
+ subject_line = prefix + subject_line
msg = mail.EmailMessage(
subject_line,
body_text,
@@ -62,3 +66,24 @@ def send_mail(
logging.critical(unicode(e))
if raise_on_failure == True:
raise exceptions.EmailNotSent(unicode(e))
+
+def mail_moderators(subject_line, body_text):
+ """sends email to forum moderators and admins
+ """
+ from django.db.models import Q
+ from askbot.models import User
+ recipient_list = User.objects.filter(
+ Q(status='m') | Q(is_superuser=True)
+ ).values_list('email', flat=True)
+ recipient_list = set(recipient_list)
+
+ from_email = ''
+ if hasattr(django_settings, 'DEFAULT_FROM_EMAIL'):
+ from_email = django_settings.DEFAULT_FROM_EMAIL
+
+ try:
+ mail.send_mail(subject_line, body_text, from_email, recipient_list)
+ except smtplib.SMPTException, e:
+ logging.critical(unicode(e))
+ if raise_on_failure == True:
+ raise exceptions.EmailNotSent(unicode(e))
diff --git a/askbot/conf/email.py b/askbot/conf/email.py
index dd3e5bdc..77407d70 100644
--- a/askbot/conf/email.py
+++ b/askbot/conf/email.py
@@ -67,3 +67,12 @@ settings.register(
help_text=_('Use this setting to control gravatar for email-less user')
)
)
+
+settings.register(
+ StringValue(
+ EMAIL,
+ 'EMAIL_SUBJECT_PREFIX',
+ default='',
+ description=_('Prefix for the email subject line'),
+ )
+)
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index e99672d2..69129813 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -1434,33 +1434,33 @@ def format_instant_notification_email(
assert(isinstance(post, Comment))
assert(isinstance(post.content_object, Question))
subject_line = _(
- 'new question comment about: "%(title)s"'
+ 'Re: "%(title)s"'
) % {'title': origin_post.title}
elif update_type == 'answer_comment':
assert(isinstance(post, Comment))
assert(isinstance(post.content_object, Answer))
subject_line = _(
- 'new answer comment about: "%(title)s"'
+ 'Re: "%(title)s"'
) % {'title': origin_post.title}
elif update_type == 'answer_update':
assert(isinstance(post, Answer))
subject_line = _(
- 'answer modified for: "%(title)s"'
+ 'Re: "%(title)s"'
) % {'title': origin_post.title}
elif update_type == 'new_answer':
assert(isinstance(post, Answer))
subject_line = _(
- 'new answer for: "%(title)s"'
+ 'Re: "%(title)s"'
) % {'title': origin_post.title}
elif update_type == 'question_update':
assert(isinstance(post, Question))
subject_line = _(
- 'question modified: "%(title)s"'
+ 'Question: "%(title)s"'
) % {'title': origin_post.title}
elif update_type == 'new_question':
assert(isinstance(post, Question))
subject_line = _(
- 'new question: "%(title)s"'
+ 'Question: "%(title)s"'
) % {'title': origin_post.title}
else:
raise ValueError('unexpected update_type %s' % update_type)
@@ -1468,6 +1468,7 @@ def format_instant_notification_email(
update_data = {
'update_author_name': from_user.username,
'receiving_user_name': to_user.username,
+ 'content_preview': post.get_snippet(),
'update_type': update_type,
'post_url': site_url + post.get_absolute_url(),
'origin_post_title': origin_post.title,
@@ -1500,6 +1501,7 @@ def send_instant_notifications_about_activity_in_post(
update_type_map = const.RESPONSE_ACTIVITY_TYPE_MAP_FOR_TEMPLATES
update_type = update_type_map[update_activity.activity_type]
+ origin_post = post.get_origin_post()
for user in receiving_users:
subject_line, body_text = format_instant_notification_email(
@@ -1515,7 +1517,7 @@ def send_instant_notifications_about_activity_in_post(
subject_line = subject_line,
body_text = body_text,
recipient_list = [user.email],
- related_object = post.get_origin_post(),
+ related_object = origin_post,
activity_type = const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT
)
diff --git a/askbot/models/content.py b/askbot/models/content.py
index eaba4fd6..636b093e 100644
--- a/askbot/models/content.py
+++ b/askbot/models/content.py
@@ -6,6 +6,7 @@ from django.contrib.sitemaps import ping_google
from django.db import models
from askbot.models.meta import Comment, Vote, FlaggedItem
from askbot.models.user import EmailFeedSetting
+from django.utils import html as html_utils
class Content(models.Model):
"""
@@ -52,6 +53,11 @@ class Content(models.Model):
def get_text(self):
return self.text
+ def get_snippet(self):
+ """returns an abbreviated snippet of the content
+ """
+ return html_utils.strip_tags(self.html)[:120] + ' ...'
+
def add_comment(self, comment=None, user=None, added_at=None):
if added_at is None:
added_at = datetime.datetime.now()
@@ -68,6 +74,23 @@ class Content(models.Model):
comment.parse_and_save(author = user)
self.comment_count = self.comment_count + 1
self.save()
+
+ #tried to add this to bump updated question
+ #in most active list, but it did not work
+ #becase delayed email updates would be triggered
+ #for cases where user did not subscribe for them
+ #
+ #need to redo the delayed alert sender
+ #
+ #origin_post = self.get_origin_post()
+ #if origin_post == self:
+ # self.last_activity_at = added_at
+ # self.last_activity_by = user
+ #else:
+ # origin_post.last_activity_at = added_at
+ # origin_post.last_activity_by = user
+ # origin_post.save()
+
return comment
def get_instant_notification_subscribers(
diff --git a/askbot/models/meta.py b/askbot/models/meta.py
index 0da701bc..9aa372cc 100644
--- a/askbot/models/meta.py
+++ b/askbot/models/meta.py
@@ -1,6 +1,7 @@
import datetime
from django.contrib.contenttypes.models import ContentType
from django.db import models
+from django.utils import html as html_utils
from askbot import const
from askbot.models import base
from askbot.models.user import EmailFeedSetting
@@ -99,6 +100,7 @@ class FlaggedItem(base.MetaContent, base.UserContent):
def __unicode__(self):
return '[%s] flagged at %s' %(self.user, self.flagged_at)
+#todo: move this class to content
class Comment(base.MetaContent, base.UserContent):
comment = models.CharField(max_length = const.COMMENT_HARD_MAX_LENGTH)
added_at = models.DateTimeField(default = datetime.datetime.now)
@@ -125,6 +127,12 @@ class Comment(base.MetaContent, base.UserContent):
def set_text(self, text):
self.comment = text
+ def get_snippet(self):
+ """returns an abbreviated snippet of the content
+ todo: remove this if comment model unites with Q&A
+ """
+ return html_utils.strip_tags(self.html)[:120] + ' ...'
+
def get_owner(self):
return self.user
diff --git a/askbot/models/question.py b/askbot/models/question.py
index a740aac2..c450eed9 100644
--- a/askbot/models/question.py
+++ b/askbot/models/question.py
@@ -287,8 +287,10 @@ class Question(content.Content, DeletableContent):
similar_questions = self.__class__.objects.filter(
tags__in = self.tags.all()
).exclude(
- id = self.id
- )[:100]
+ id = self.id,
+ ).exclude(
+ deleted = True
+ ).distinct()[:100]
similar_questions = list(similar_questions)
output = list()
for question in similar_questions:
diff --git a/askbot/skins/default/media/js/com.cnprog.post.js b/askbot/skins/default/media/js/com.cnprog.post.js
index ae4e5d50..e03053ab 100755
--- a/askbot/skins/default/media/js/com.cnprog.post.js
+++ b/askbot/skins/default/media/js/com.cnprog.post.js
@@ -593,7 +593,7 @@ function createComments(type) {
// {"Id":6,"PostId":38589,"CreationDate":"an hour ago","Text":"hello there!","UserDisplayName":"Jarrod Dixon","UserUrl":"/users/3/jarrod-dixon","DeleteUrl":null}
var renderComment = function(jDiv, json) {
- var html = '<p id="comment-' + json.id + '" class="comment" style="display:none">' + json.text;
+ var html = '<div id="comment-' + json.id + '" class="comment" style="display:none">' + json.text;
html += json.user_url ? ' - <a href="' + json.user_url + '"' : '<span';
html += ' class="comment-user">' + json.user_display_name + (json.user_url ? '</a>' : '</span>');
html += ' (' + json.comment_age + ')';
@@ -605,7 +605,7 @@ function createComments(type) {
if (json.delete_url) {
}
- html += '</p>';
+ html += '</div>';
jDiv.append(html);
};
diff --git a/askbot/skins/default/media/js/live_search.js b/askbot/skins/default/media/js/live_search.js
index ea429ddd..ec18bb6c 100644
--- a/askbot/skins/default/media/js/live_search.js
+++ b/askbot/skins/default/media/js/live_search.js
@@ -250,10 +250,10 @@ $(document).ready(function(){
new_list.attr('id', q_list_sel);
render_paginator(data['paginator']);
set_question_count(data['question_counter']);
+ render_faces(data['faces']);
+ render_related_tags(data['related_tags']);
+ query.focus();
}
- render_faces(data['faces']);
- render_related_tags(data['related_tags']);
- query.focus();
//show new div
}
diff --git a/askbot/skins/default/media/style/style.css b/askbot/skins/default/media/style/style.css
index 71cec370..cbdceba9 100755
--- a/askbot/skins/default/media/style/style.css
+++ b/askbot/skins/default/media/style/style.css
@@ -2362,7 +2362,7 @@ p.space-above {
vertical-align: top;
}
-p.comment {
+.comment {
border-top: 1px dotted #ccccce;
margin: 0;
font-size: 11px;
diff --git a/askbot/skins/default/templates/instant_notification.html b/askbot/skins/default/templates/instant_notification.html
index c958c41b..86556fda 100644
--- a/askbot/skins/default/templates/instant_notification.html
+++ b/askbot/skins/default/templates/instant_notification.html
@@ -3,14 +3,12 @@
{% blocktrans %}<p>Dear {{receiving_user_name}},</p>{% endblocktrans %}
{% if update_type == 'question_comment' %}
{% blocktrans %}
-<p>{{update_author_name}} left a <a href="%{{post_url}}">new comment</a>
-for question "{{origin_post_title}}"</p>
+<p>{{update_author_name}} left a <a href="{{post_url}}">new comment</a>:</p>
{% endblocktrans %}
{% endif %}
{% if update_type == 'answer_comment' %}
{% blocktrans %}
-<p>{{update_author_name}} left a <a href="{{post_url}}">new comment</a>
- for an answer to question "{{origin_post_title}}"</p>
+<p>{{update_author_name}} left a <a href="{{post_url}}">new comment</a></p>
{% endblocktrans %}
{% endif %}
{% if update_type == 'new_answer' %}
@@ -39,6 +37,7 @@ for question "{{origin_post_title}}"</p>
{% endif %}
<p></p>
{% blocktrans %}
+<div>{{content_preview}}</div>
<p>Please note - you can easily <a href="{{user_subscriptions_url}}">change</a>
how often you receive these notifications or unsubscribe. Thank you for your interest in our forum!</p>
{% endblocktrans %}
diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html
index d7bc42fb..73a43d14 100644
--- a/askbot/skins/default/templates/question.html
+++ b/askbot/skins/default/templates/question.html
@@ -187,9 +187,10 @@
{% post_contributor_info question "original_author" %}
{% post_contributor_info question "last_updater" %}
</div>
+ {% spaceless %}
<div class="comments-container" id="comments-container-question-{{question.id}}">
{% for comment in question.get_comments|slice:":5" %}
- <p class="comment" id="comment-{{comment.id}}">
+ <div class="comment" id="comment-{{comment.id}}">
{{comment.html|safe}}
- <a class="comment-user" href="{{comment.user.get_profile_url}}">{{comment.user}}</a>
{% spaceless %}
@@ -200,9 +201,10 @@
title="{% trans "delete this comment" %}"/>
{% endif %}
{% endspaceless %}
- </p>
+ </div>
{% endfor %}
</div>
+ {% endspaceless %}
<div class="post-comments" style="margin-bottom:20px">
<input id="can-post-comments-question-{{question.id}}" type="hidden" value="{{ request.user|can_post_comment:question }}"/>
{% if request.user|can_post_comment:question or question.comment_count > 5 %}
@@ -329,9 +331,10 @@
{% post_contributor_info answer "original_author" %}
{% post_contributor_info answer "last_updater" %}
</div>
+ {% spaceless %}
<div class="comments-container" id="comments-container-answer-{{answer.id}}">
{% for comment in answer.get_comments|slice:":5" %}
- <p id="comment-{{comment.id}}" class="comment">
+ <div id="comment-{{comment.id}}" class="comment">
{{comment.html|safe}}
- <a class="comment-user" href="{{comment.user.get_profile_url}}">{{comment.user}}</a>
{% spaceless %}
@@ -342,9 +345,10 @@
title="{% trans "delete this comment" %}"/>
{% endif %}
{% endspaceless %}
- </p>
+ </div>
{% endfor %}
</div>
+ {% endspaceless %}
<div class="post-comments" style="margin-bottom:20px">
<input id="can-post-comments-answer-{{answer.id}}" type="hidden" value="{{ request.user|can_post_comment:answer}}"/>
{% if request.user|can_post_comment:answer or answer.comment_count > 5 %}
@@ -501,7 +505,6 @@
<div class="boxC">
<h3 class="subtitle">{% trans "Related questions" %}</h3>
<div class="questions-related">
-
{% for question in similar_questions.data %}
<p>
<a href="{{ question.get_absolute_url }}">{{ question.get_question_title }}</a>
diff --git a/askbot/skins/default/templates/questions.html b/askbot/skins/default/templates/questions.html
index 36a15ae1..d35336aa 100644
--- a/askbot/skins/default/templates/questions.html
+++ b/askbot/skins/default/templates/questions.html
@@ -302,9 +302,11 @@
{% cache 600 contributors search_tags scope sort query context.page context.page_size LANGUAGE_CODE %}
<div id="contrib-users" class="boxC">
<h3 class="subtitle">{% trans "Contributors" %}</h3>
- {% for person in contributors %}
- {% gravatar person 48 %}
- {% endfor %}
+ {% spaceless %}
+ {% for person in contributors %}
+ {% gravatar person 48 %}
+ {% endfor %}
+ {% endspaceless %}
</div>
{% endcache %}
{% endif %}
diff --git a/askbot/startup_tests.py b/askbot/startup_tests.py
index 6a238965..c6d000a1 100644
--- a/askbot/startup_tests.py
+++ b/askbot/startup_tests.py
@@ -8,6 +8,10 @@ the main function is run_startup_tests
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
+#todo:
+#
+# *validate emails in settings.py
+
def run_startup_tests():
"""main function that runs
all startup tests
diff --git a/askbot/tests/email_alert_tests.py b/askbot/tests/email_alert_tests.py
index 3ce4fc6b..c54f8ad2 100644
--- a/askbot/tests/email_alert_tests.py
+++ b/askbot/tests/email_alert_tests.py
@@ -4,7 +4,9 @@ import copy
from django.conf import settings as django_settings
from django.core import management
import django.core.mail
+from django.core.urlresolvers import reverse
from django.test import TestCase
+from django.test.client import Client
from askbot.tests import utils
from askbot import models
@@ -680,3 +682,35 @@ class DelayedAlertSubjectLineTests(TestCase):
order,
sorted(order)
)
+
+class FeedbackTests(utils.AskbotTestCase):
+ def setUp(self):
+ self.create_user(username = 'user1', status='m')
+ self.create_user(username = 'user2', status='m')
+ u3 = self.create_user(username = 'user3')
+ u3.is_superuser = True
+ u3.save()
+
+ def assert_feedback_works(self):
+ outbox = django.core.mail.outbox
+ self.assertEqual(len(outbox), 1)
+ self.assertEqual(len(outbox[0].recipients()), 3)
+
+ def test_feedback_post_form(self):
+ client = Client()
+ data = {
+ 'email': 'evgeny.fadeev@gmail.com',
+ 'text': 'hi this is a test case',
+ 'subject': 'subject line'
+ }
+ response = client.post(reverse('feedback'), data)
+ self.assertEquals(response.status_code, 200)
+ self.assertEquals(response.template[0].name, 'feedback.html')
+
+ def test_mail_moderators(self):
+ """tests askbot.mail_moderators()
+ """
+ import askbot
+ askbot.mail_moderators('subject', 'text')
+ self.assert_feedback_works()
+
diff --git a/askbot/views/meta.py b/askbot/views/meta.py
index b4a22932..88d9bac7 100644
--- a/askbot/views/meta.py
+++ b/askbot/views/meta.py
@@ -9,10 +9,10 @@ from django.template import RequestContext
from django.http import HttpResponseRedirect, HttpResponse
from askbot.forms import FeedbackForm
from django.core.urlresolvers import reverse
-from django.core.mail import mail_admins
from django.utils.translation import ugettext as _
from askbot.utils.forms import get_next_url
from askbot.models import Badge, Award
+import askbot
def about(request):
return render_to_response('about.html', context_instance=RequestContext(request))
@@ -37,7 +37,7 @@ def feedback(request):
data['message'] = form.cleaned_data['message']
data['name'] = form.cleaned_data.get('name',None)
message = render_to_response('feedback_email.txt',data,context_instance=RequestContext(request))
- mail_admins(_('Q&A forum feedback'), message)
+ askbot.mail_moderators(_('Q&A forum feedback'), message)
msg = _('Thanks for the feedback!')
request.user.message_set.create(message=msg)
return HttpResponseRedirect(get_next_url(request))
diff --git a/askbot/views/readers.py b/askbot/views/readers.py
index 1281918c..6c4e6cce 100644
--- a/askbot/views/readers.py
+++ b/askbot/views/readers.py
@@ -25,7 +25,6 @@ from django.views.decorators.cache import cache_page
from django.core import exceptions as django_exceptions
from django.contrib.humanize.templatetags import humanize
-from askbot.utils.slug import slugify
from askbot.utils.html import sanitize_html
#from lxml.html.diff import htmldiff
from askbot.utils.diff import textDiff as htmldiff
@@ -433,18 +432,7 @@ def question(request, id):#refactor - long subroutine. display question body, an
question = get_object_or_404(Question, id=id)
try:
- path_prefix = r'/%s%s%d/' % (
- settings.ASKBOT_URL,
- _('question/'),
- question.id
- )
- if not request.path.startswith(path_prefix):
- logging.critical('bad request path %s' % request.path)
- raise Http404
- slug = request.path.replace(path_prefix, '', 1)
- logging.debug('have slug %s' % slug)
- logging.debug('requestion path is %s' % request.path)
- assert(slug == slugify(question.title))
+ assert(request.path == question.get_absolute_url())
except AssertionError:
logging.debug('no slug match!')
return HttpResponseRedirect(question.get_absolute_url())