summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2011-06-17 04:01:58 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2011-06-17 04:01:58 -0400
commitd3c84e5fe9751434f4d3ad4afb0eace8d9219a44 (patch)
tree5d873babc6cd80a68c154e19cfe29bba84ac2801
parenta199515ba60f8a74faabff5753714d211a7a13b0 (diff)
downloadaskbot-d3c84e5fe9751434f4d3ad4afb0eace8d9219a44.tar.gz
askbot-d3c84e5fe9751434f4d3ad4afb0eace8d9219a44.tar.bz2
askbot-d3c84e5fe9751434f4d3ad4afb0eace8d9219a44.zip
added swap answer with question feature
-rw-r--r--askbot/conf/forum_data_rules.py2
-rw-r--r--askbot/models/answer.py46
-rw-r--r--askbot/models/question.py36
-rw-r--r--askbot/skins/default/media/js/post.js51
-rw-r--r--askbot/skins/default/templates/question.html6
-rw-r--r--askbot/urls.py5
-rw-r--r--askbot/views/commands.py20
7 files changed, 160 insertions, 6 deletions
diff --git a/askbot/conf/forum_data_rules.py b/askbot/conf/forum_data_rules.py
index 6ce169fa..dc801d41 100644
--- a/askbot/conf/forum_data_rules.py
+++ b/askbot/conf/forum_data_rules.py
@@ -66,7 +66,7 @@ settings.register(
settings.register(
livesettings.BooleanValue(
FORUM_DATA_RULES,
- 'ALLOW_SWAPPING_ANSWER_WITH_QUESTION',
+ 'ALLOW_SWAPPING_QUESTION_WITH_ANSWER',
default = False,
description = _('Allow swapping answer with question'),
help_text = _(
diff --git a/askbot/models/answer.py b/askbot/models/answer.py
index c268551d..09b5a444 100644
--- a/askbot/models/answer.py
+++ b/askbot/models/answer.py
@@ -161,6 +161,52 @@ class Answer(content.Content, DeletableContent):
self.question.last_activity_by = edited_by
self.question.save()
+ def repost_as_question(self, new_title = None):
+ """posts answer as question, together with all the comments
+ while preserving time stamps and authors
+ does not delete the answer itself though
+ """
+ revisions = self.revisions.all().order_by('revised_at')
+ rev0 = revisions[0]
+ new_question = rev0.author.post_question(
+ title = new_title,
+ body_text = rev0.text,
+ tags = self.question.tagnames,
+ wiki = self.question.wiki,
+ is_anonymous = self.question.is_anonymous,
+ timestamp = rev0.revised_at
+ )
+ if len(revisions) > 1:
+ for rev in revisions[1:]:
+ rev.author.edit_question(
+ question = new_question,
+ body_text = rev.text,
+ revision_comment = rev.summary,
+ timestamp = rev.revised_at
+ )
+ for comment in self.comments.all():
+ comment.content_object = new_question
+ comment.save()
+ return new_question
+
+ def swap_with_question(self, new_title = None):
+ """swaps answer with the question it belongs to and
+ sets the title of question to ``new_title``
+ """
+ #1) make new question by using new title, tags of old question
+ # and the answer body, as well as the authors of all revisions
+ # and repost all the comments
+ new_question = self.repost_as_question(new_title = new_title)
+
+ #2) post question (all revisions and comments) as answer
+ new_answer = self.question.repost_as_answer(question = new_question)
+
+ #3) assign all remaining answers to the new question
+ self.question.answers.update(question = new_question)
+ self.question.delete()
+ self.delete()
+ return new_question
+
def add_revision(self, author=None, revised_at=None, text=None, comment=None):
#todo: this may be identical to Question.add_revision
if None in (author, revised_at, text):
diff --git a/askbot/models/question.py b/askbot/models/question.py
index 41579c11..7a2be48c 100644
--- a/askbot/models/question.py
+++ b/askbot/models/question.py
@@ -457,15 +457,13 @@ class Question(content.Content, DeletableContent):
self.save()
def update_favorite_count(self):
- """
- update favourite_count for given question
+ """update favourite_count for given question
"""
self.favourite_count = FavoriteQuestion.objects.filter(
question=self
).count()
self.save()
-
def get_similar_questions(self):
"""
Get 10 similar questions for given one.
@@ -602,6 +600,31 @@ class Question(content.Content, DeletableContent):
return False
+ def repost_as_answer(self, question = None):
+ """posts question as answer to another question,
+ but does not delete the question,
+ but moves all the comments to the new answer"""
+ revisions = self.revisions.all().order_by('revised_at')
+ rev0 = revisions[0]
+ new_answer = rev0.author.post_answer(
+ question = question,
+ body_text = rev0.text,
+ wiki = self.wiki,
+ timestamp = rev0.revised_at
+ )
+ if len(revisions) > 1:
+ for rev in revisions:
+ rev.author.edit_answer(
+ answer = new_answer,
+ body_text = rev.text,
+ revision_comment = rev.summary,
+ timestamp = rev.revised_at
+ )
+ for comment in self.comments.all():
+ comment.content_object = new_answer
+ comment.save()
+ return new_answer
+
def delete(self):
super(Question, self).delete()
try:
@@ -782,7 +805,12 @@ class Question(content.Content, DeletableContent):
if no_slug == True:
return url
else:
- return url + django_urlquote(slugify(self.title))
+ return url + django_urlquote(self.slug)
+
+ def _get_slug(self):
+ return slugify(self.title)
+
+ slug = property(_get_slug)
def has_favorite_by_user(self, user):
if not user.is_authenticated():
diff --git a/askbot/skins/default/media/js/post.js b/askbot/skins/default/media/js/post.js
index 0d84508e..a228e9ce 100644
--- a/askbot/skins/default/media/js/post.js
+++ b/askbot/skins/default/media/js/post.js
@@ -1394,11 +1394,62 @@ var socialSharing = function(){
}
}();
+/**
+ * @constructor
+ * @extends {SimpleControl}
+ */
+var QASwapper = function(){
+ SimpleControl.call(this);
+ this._ans_id = null;
+};
+inherits(QASwapper, SimpleControl);
+
+QASwapper.prototype.decorate = function(element){
+ this._element = element;
+ this._ans_id = parseInt(element.attr('id').split('-').pop());
+ var me = this;
+ this.setHandler(function(){
+ me.startSwapping();
+ });
+};
+
+QASwapper.prototype.startSwapping = function(){
+ while (true){
+ var title = prompt(gettext('Please enter question title (>10 characters)'));
+ if (title.length >= 10){
+ var data = {new_title: title, answer_id: this._ans_id};
+ $.ajax({
+ type: "POST",
+ cache: false,
+ dataType: "json",
+ url: askbot['urls']['swap_question_with_answer'],
+ data: data,
+ success: function(data){
+ var url_template = askbot['urls']['question_url_template'];
+ new_question_url = url_template.replace(
+ '{{QuestionID}}',
+ data['id']
+ ).replace(
+ '{{questionSlug}}',
+ data['slug']
+ );
+ window.location.href = new_question_url;
+ }
+ });
+ break;
+ }
+ }
+};
+
$(document).ready(function() {
$('[id^="comments-for-"]').each(function(index, element){
var comments = new PostCommentsWidget();
comments.decorate(element);
});
+ $('[id^="swap-question-with-answer-"]').each(function(idx, element){
+ var swapper = new QASwapper();
+ swapper.decorate($(element));
+ });
questionRetagger.init();
socialSharing.init();
});
diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html
index 6b51c756..b9f3edc5 100644
--- a/askbot/skins/default/templates/question.html
+++ b/askbot/skins/default/templates/question.html
@@ -264,6 +264,11 @@
</span>
{% endspaceless %}
{% endif %}
+ {% if settings.ALLOW_SWAPPING_QUESTION_WITH_ANSWER %}{{ pipe() }}
+ <span class="action-link">
+ <a id="swap-question-with-answer-{{answer.id}}">{% trans %}swap with question{% endtrans %}</a>
+ </span>
+ {% endif %}
</div>
<div class="post-update-info-container">
{{
@@ -441,6 +446,7 @@
askbot['urls']['question_url_template'] = scriptUrl + '{% trans %}question/{% endtrans %}{{ "{{QuestionID}}/{{questionSlug}}" }}';{# yes it needs to be that whacky #}
askbot['urls']['user_signin'] = '{{ settings.LOGIN_URL }}';
askbot['urls']['vote_url_template'] = scriptUrl + '{% trans %}questions/{% endtrans %}{{ "{{QuestionID}}/" }}{% trans %}vote/{% endtrans %}';
+ askbot['urls']['swap_question_with_answer'] = '{% url swap_question_with_answer %}';
askbot['messages']['addComment'] = '{% trans %}add comment{% endtrans %}';
{% if settings.SAVE_COMMENT_ON_ENTER %}
askbot['settings']['saveCommentOnEnter'] = true;
diff --git a/askbot/urls.py b/askbot/urls.py
index 99ff6300..714ce4ca 100644
--- a/askbot/urls.py
+++ b/askbot/urls.py
@@ -171,6 +171,11 @@ urlpatterns = patterns('',
name = 'get_tag_list'
),
url(
+ r'^swap-question-with-answer/',
+ views.commands.swap_question_with_answer,
+ name = 'swap_question_with_answer'
+ ),
+ url(
r'^%s$' % _('subscribe-for-tags/'),
views.commands.subscribe_for_tags,
name = 'subscribe_for_tags'
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index 9b9e7af5..5b7e8f18 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -9,7 +9,7 @@ from django.conf import settings as django_settings
from django.core import exceptions
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
-from django.http import HttpResponse, HttpResponseRedirect
+from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.forms import ValidationError
from django.shortcuts import get_object_or_404
from django.views.decorators import csrf
@@ -518,6 +518,24 @@ def reopen(request, id):#re-open question
request.user.message_set.create(message = unicode(e))
return HttpResponseRedirect(question.get_absolute_url())
+
+@decorators.ajax_only
+def swap_question_with_answer(request):
+ """receives two json parameters - answer id
+ and new question title
+ the view is made to be used only by the site administrator
+ or moderators
+ """
+ if request.user.is_authenticated():
+ if request.user.is_administrator() or request.user.is_moderator():
+ answer = models.Answer.objects.get(id = request.POST['answer_id'])
+ new_question = answer.swap_with_question(new_title = request.POST['new_title'])
+ return {
+ 'id': new_question.id,
+ 'slug': new_question.slug
+ }
+ raise Http404
+
#askbot-user communication system
def read_message(request):#marks message a read
if request.method == "POST":