diff options
-rw-r--r-- | askbot/__init__.py | 2 | ||||
-rw-r--r-- | askbot/conf/site_settings.py | 9 | ||||
-rw-r--r-- | askbot/db | 0 | ||||
-rw-r--r-- | askbot/doc/source/changelog.rst | 11 | ||||
-rw-r--r-- | askbot/doc/source/contributors.rst | 8 | ||||
-rw-r--r-- | askbot/feed.py | 85 | ||||
-rw-r--r-- | askbot/middleware/anon_user.py | 25 | ||||
-rw-r--r-- | askbot/skins/default/media/style/style.css | 12 | ||||
-rw-r--r-- | askbot/skins/default/templates/macros.html | 6 | ||||
-rw-r--r-- | askbot/skins/default/templates/question.html | 22 | ||||
-rw-r--r-- | askbot/urls.py | 24 | ||||
-rw-r--r-- | askbot/views/writers.py | 2 |
12 files changed, 174 insertions, 32 deletions
diff --git a/askbot/__init__.py b/askbot/__init__.py index 5ced4ca1..b4889f92 100644 --- a/askbot/__init__.py +++ b/askbot/__init__.py @@ -9,7 +9,7 @@ import smtplib import sys import logging -VERSION = (0, 7, 23) +VERSION = (0, 7, 24) #necessary for interoperability of django and coffin try: diff --git a/askbot/conf/site_settings.py b/askbot/conf/site_settings.py index 0cab800b..e1f54d39 100644 --- a/askbot/conf/site_settings.py +++ b/askbot/conf/site_settings.py @@ -70,6 +70,15 @@ settings.register( ) settings.register( + livesettings.BooleanValue( + QA_SITE_SETTINGS, + 'ENABLE_GREETING_FOR_ANON_USER', + default = True, + description = _('Check to enable greeting for anonymous user') + ) +) + +settings.register( livesettings.StringValue( QA_SITE_SETTINGS, 'GREETING_FOR_ANONYMOUS_USER', diff --git a/askbot/db b/askbot/db new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/askbot/db diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst index 33a0199c..77ff4a45 100644 --- a/askbot/doc/source/changelog.rst +++ b/askbot/doc/source/changelog.rst @@ -1,13 +1,18 @@ Changes in Askbot ================= -Development version (not released yet) +Development version (Not yet released) -------------------------------------- +* RSS feed for individual question (Sayan Chowdhury) + +0.7.24 (Current Version) +------------------------ +* Made it possible to disable the anonymous user greeting alltogether (Raghu Udiyar) * Added annotations for the meanings of user levels on the "moderation" page. (Jishnu) * Auto-link patterns - e.g. to bug databases - are configurable from settings. (Arun SAG) -0.7.23 (Current Version) ------------------------- +0.7.23 +------ * Greeting for anonymuos users can be changed from live settings (Hrishi) * Greeting for anonymous users is shown only once (Rag Sagar) * Added support for Akismet spam detection service (Adolfo Fitoria) diff --git a/askbot/doc/source/contributors.rst b/askbot/doc/source/contributors.rst index fb8d9690..c372977d 100644 --- a/askbot/doc/source/contributors.rst +++ b/askbot/doc/source/contributors.rst @@ -11,19 +11,21 @@ Programming and documentation * Mike Chen & Sailing Cai - original authors of CNPROG forum * Evgeny Fadeev - founder of askbot * `Adolfo Fitoria <http://fitoria.net>`_ -* `Arun SAG <http://zer0c00l.in/>`_ +* `Sayan Chowdhury <http://fosswithme.wordpress.com>`_ * Andy Knotts * Benoit Lavine (with Windriver Software, Inc.) * Jeff Madynski * `Jishnu <http://thecodecracker.com/>`_ * `Hrishi <https://github.com/stultus>`_ * Andrei Mamoutkine -* Ramiro Morales (with Machinalis) +* `Ramiro Morales <http://rmorales.com.ar/>`_ (with Machinalis) * `NoahY <https://github.com/NoahY>`_ * `Gael Pasgrimaud <http://www.gawel.org/>`_ (bearstech) +* `Arun SAG <http://zer0c00l.in/>`_ * `Rag Sagar <https://github.com/ragsagar>`_ -* Alex Robbins (celery support) +* `Alex Robbins <https://github.com/alexrobbins>`_ * `Tomasz Szynalski <http://antimoon.com>`_ +* `Raghu Udiyar <http://raags.tumblr.com/>`_ Translations ------------ diff --git a/askbot/feed.py b/askbot/feed.py index 23416677..e0c69454 100644 --- a/askbot/feed.py +++ b/askbot/feed.py @@ -13,9 +13,87 @@ #!/usr/bin/env python #encoding:utf-8 from django.contrib.syndication.feeds import Feed +from django.contrib.contenttypes.models import ContentType from django.utils.translation import ugettext as _ -from askbot.models import Question +from django.core.exceptions import ObjectDoesNotExist +from askbot.models import Question, Answer, Comment from askbot.conf import settings as askbot_settings +import itertools + +class RssIndividualQuestionFeed(Feed): + """rss feed class for particular questions + """ + title = askbot_settings.APP_TITLE + _(' - ')+ _('Individual question feed') + link = askbot_settings.APP_URL + description = askbot_settings.APP_DESCRIPTION + copyright = askbot_settings.APP_COPYRIGHT + + def get_object(self, bits): + if len(bits) != 1: + raise ObjectDoesNotExist + return Question.objects.get(id__exact = bits[0]) + + def item_link(self, item): + """get full url to the item + """ + return self.link + item.get_absolute_url() + + def item_pubdate(self, item): + """get date of creation for the item + """ + return item.added_at + + def items(self, item): + """get content items for the feed + ordered as: question, question comments, + then for each answer - the answer itself, then + answer comments + """ + + chain_elements = list() + chain_elements.append([item,]) + chain_elements.append( + Comment.objects.filter( + object_id = item.id, + content_type = ContentType.objects.get_for_model(Question) + ) + ) + + answer_content_type = ContentType.objects.get_for_model(Answer) + answers = Answer.objects.filter(question = item.id) + for answer in answers: + chain_elements.append([answer,]) + chain_elements.append( + Comment.objects.filter( + object_id = answer.id, + content_type = answer_content_type + ) + ) + + return itertools.chain(*chain_elements) + + def item_title(self, item): + """returns the title for the item + """ + title = item + if item.post_type == "question": + self.title = item + elif item.post_type == "answer": + title = "Answer by %s for %s " % (item.author, self.title) + elif item.post_type == "comment": + title = "Comment by %s for %s" % (item.user, self.title) + return title + + def item_description(self, item): + """returns the description for the item + """ + if item.post_type == "question": + return item.text + if item.post_type == "answer": + return item.text + elif item.post_type == "comment": + return item.comment + class RssLastestQuestionsFeed(Feed): """rss feed class for the latest questions """ @@ -50,6 +128,11 @@ class RssLastestQuestionsFeed(Feed): because the slug can change """ return self.link + item.get_absolute_url(no_slug = True) + + def item_description(self, item): + """returns the desciption for the item + """ + return item.text def items(self, item): """get questions for the feed diff --git a/askbot/middleware/anon_user.py b/askbot/middleware/anon_user.py index d1e223b7..adaf6fd2 100644 --- a/askbot/middleware/anon_user.py +++ b/askbot/middleware/anon_user.py @@ -21,6 +21,8 @@ class AnonymousMessageManager(object): create_message(self.request, message) def get_and_delete(self): + """returns messages sent to the anonymous user + via session, and removes messages from the session""" messages = get_and_delete_messages(self.request) return messages @@ -31,9 +33,17 @@ def dummy_deepcopy(*arg): return None class ConnectToSessionMessagesMiddleware(object): - """middleware that attaches messages to anonymous users""" + """Middleware that attaches messages to anonymous users, and + makes sure that anonymous user greeting is shown just once. + Middleware does not do anything if the anonymous user greeting + is disabled. + """ def process_request(self, request): - if not request.user.is_authenticated(): + """Enables anonymous users to receive messages + the same way as authenticated users, and sets + the anonymous user greeting, if it should be shown""" + if request.user.is_anonymous(): + #1) Attach the ability to receive messages #plug on deepcopy which may be called by django db "driver" request.user.__deepcopy__ = dummy_deepcopy #here request is linked to anon user @@ -41,16 +51,18 @@ class ConnectToSessionMessagesMiddleware(object): request.user.get_and_delete_messages = \ request.user.message_set.get_and_delete - #also set the first greeting one time per session only + #2) set the first greeting one time per session only if 'greeting_set' not in request.session and \ - 'askbot_visitor' not in request.COOKIES: + 'askbot_visitor' not in request.COOKIES and \ + askbot_settings.ENABLE_GREETING_FOR_ANON_USER: request.session['greeting_set'] = True msg = askbot_settings.GREETING_FOR_ANONYMOUS_USER request.user.message_set.create(message=msg) def process_response(self, request, response): - """ Adds the ``'askbot_visitor'``key to cookie if user ever authenticates so - that the anonymous user message won't be shown. """ + """Adds the ``'askbot_visitor'``key to cookie if user ever + authenticates so that the anonymous user message won't + be shown after the user logs out""" if request.user.is_authenticated() and \ 'askbot_visitor' not in request.COOKIES : #import datetime @@ -61,4 +73,3 @@ class ConnectToSessionMessagesMiddleware(object): # "%a, %d-%b-%Y %H:%M:%S GMT") response.set_cookie('askbot_visitor', False) return response - diff --git a/askbot/skins/default/media/style/style.css b/askbot/skins/default/media/style/style.css index 983daf06..7dd8a056 100644 --- a/askbot/skins/default/media/style/style.css +++ b/askbot/skins/default/media/style/style.css @@ -898,6 +898,18 @@ p.rss a { background: url(../images/feed-icon-small.png) no-repeat; } +.question-page p.rss { + float:none; + clear:both; + padding: 3px 0 0 1px; + font-size: 14px; +} + +.question-page p.rss a { + padding-left: 18px; + vertical-align: top; +} + /* badges */ a.medal { font-size: 14px; diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html index afa7b264..c56d1cc4 100644 --- a/askbot/skins/default/templates/macros.html +++ b/askbot/skins/default/templates/macros.html @@ -282,11 +282,11 @@ poor design of the data or methods on data objects #} {% endif %} </div> {% elif contributor_type=="last_updater" %} - {% if post.post_type in ('Question', 'Answer') %} + {% if post.post_type in ('question', 'answer') %} {% set last_edited_at = post.last_edited_at %} {% set original_author = post.author %} {% set update_author = post.last_edited_by %} - {% elif post.post_type in ('QuestionRevision', 'AnswerRevision') %} + {% elif post.__class__.__name__ in ('QuestionRevision', 'AnswerRevision') %} {% set last_edited_at = post.revised_at %} {% set original_author = None %}{# fake value to force display widget in the revision views #} {% set update_author = post.author %} @@ -295,7 +295,7 @@ poor design of the data or methods on data objects #} <div class='post-update-info'> <p style="line-height:12px;"> <a - {% if post.post_type == 'Question' %} + {% if post.post_type == 'question' %} href="{% url question_revisions post.id %}" {% else %} href="{% url answer_revisions post.id %}" diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html index 06cd1332..91287bdb 100644 --- a/askbot/skins/default/templates/question.html +++ b/askbot/skins/default/templates/question.html @@ -406,14 +406,20 @@ {% trans count=follower_count %}{{count}} follower{% pluralize %}{{count}} followers{% endtrans %} {% endif %} </div> -<div class="notify-sidebar"> - {%if request.user.is_authenticated() %} - <input type="checkbox" id="question-subscribe-sidebar"/> - <label for="question-subscribe-sidebar">{% trans %}email the updates{% endtrans %}</label> - {%else%} - <input type="checkbox" id="question-subscribe-sidebar"/> - <label for="question-subscribe-sidebar">{% trans %}<strong>Here</strong> (once you log in) you will be able to sign up for the periodic email updates about this question.{% endtrans %}</label> - {%endif%} + <div class="notify-sidebar"> + {%if request.user.is_authenticated() %} + <input type="checkbox" id="question-subscribe-sidebar"/> + <label for="question-subscribe-sidebar">{% trans %}email the updates{% endtrans %}</label> + {%else%} + <input type="checkbox" id="question-subscribe-sidebar"/> + <label for="question-subscribe-sidebar">{% trans %}<strong>Here</strong> (once you log in) you will be able to sign up for the periodic email updates about this question.{% endtrans %}</label> + {%endif%} + <p class="rss"> + <a + href="{{settings.APP_URL}}/feeds/question/{{ question.id }}" + title="{% trans %}subscribe to this question rss feed{% endtrans %}" + >{% trans %}subsribe to rss feed{% endtrans %}</a> + </p> </div> </div> {% cache 0 "questions_tags" questions_tags question.id language_code %} diff --git a/askbot/urls.py b/askbot/urls.py index 54c50d96..c79f4f83 100644 --- a/askbot/urls.py +++ b/askbot/urls.py @@ -8,7 +8,7 @@ from django.conf.urls.defaults import handler500, handler404 from django.contrib import admin from django.utils.translation import ugettext as _ from askbot import views -from askbot.feed import RssLastestQuestionsFeed +from askbot.feed import RssLastestQuestionsFeed, RssIndividualQuestionFeed from askbot.sitemap import QuestionsSitemap from askbot.skins.utils import update_media_revision @@ -16,7 +16,8 @@ admin.autodiscover() update_media_revision()#needs to be run once, so put it here feeds = { - 'rss': RssLastestQuestionsFeed + 'rss': RssLastestQuestionsFeed, + 'question':RssIndividualQuestionFeed } sitemaps = { 'questions': QuestionsSitemap @@ -39,7 +40,12 @@ urlpatterns = patterns('', url( r'^%s(?P<path>.*)$' % settings.ASKBOT_UPLOADED_FILES_URL, 'django.views.static.serve', - {'document_root': os.path.join(settings.PROJECT_ROOT, 'askbot', 'upfiles').replace('\\','/')}, + {'document_root': os.path.join( + settings.PROJECT_ROOT, + 'askbot', + 'upfiles' + ).replace('\\','/') + }, name='uploaded_file', ), #no translation for this url!! @@ -298,8 +304,16 @@ if 'avatar' in settings.INSTALLED_APPS: #use jinja2 templates urlpatterns += ( url('^avatar/add/$', views.avatar_views.add, name='avatar_add'), - url('^avatar/change/$', views.avatar_views.change, name='avatar_change'), - url('^avatar/delete/$', views.avatar_views.delete, name='avatar_delete'), + url( + '^avatar/change/$', + views.avatar_views.change, + name='avatar_change' + ), + url( + '^avatar/delete/$', + views.avatar_views.delete, + name='avatar_delete' + ), url(#this urs we inherit from the original avatar app '^avatar/render_primary/(?P<user_id>[\+\d]+)/(?P<size>[\d]+)/$', views.avatar_views.render_primary, diff --git a/askbot/views/writers.py b/askbot/views/writers.py index fcc98761..d64c9c02 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -604,7 +604,7 @@ def post_comments(request):#generic ajax handler to load comments to an object raise Http404 @decorators.ajax_only -@decorators.check_spam('text') +@decorators.check_spam('comment') def edit_comment(request): if request.user.is_authenticated(): comment_id = int(request.POST['comment_id']) |