From d13ee8aa889304ca95cbd8cc777ab5e957fbed54 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Wed, 6 Mar 2013 20:50:21 -0300 Subject: added function to repost answer as comment under the latest previously posted answer --- askbot/doc/source/changelog.rst | 1 + askbot/media/images/delete.png | Bin 434 -> 431 bytes askbot/media/images/edit2.png | Bin 498 -> 571 bytes askbot/media/images/flag.png | Bin 515 -> 519 bytes askbot/media/images/link.png | Bin 601 -> 513 bytes askbot/media/images/sprites.png | Bin 15025 -> 18549 bytes askbot/media/style/style.less | 53 ++++++++++--- askbot/models/post.py | 30 +++++++- askbot/models/question.py | 7 ++ askbot/templates/question.html | 92 +++++++++++++++++------ askbot/templates/question/answer_controls.html | 92 ++++++++++++++--------- askbot/templates/question/javascript.html | 1 - askbot/templates/question/question_controls.html | 28 +++---- askbot/urls.py | 15 +++- askbot/views/readers.py | 1 + askbot/views/writers.py | 27 ++++++- 16 files changed, 257 insertions(+), 90 deletions(-) diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst index 031a3e64..888ad286 100644 --- a/askbot/doc/source/changelog.rst +++ b/askbot/doc/source/changelog.rst @@ -7,6 +7,7 @@ Development version Danish, Dutch, English, Finnish, French, German, Hungarian, Italian, Japanese (requires package textsearch_ja), Norwegian, Portugese, Romanian, Russian, Spanish, Swedish, Turkish. +* repost answer as a comment under the previous (older) answer 0.7.48 (Jan 28, 2013) diff --git a/askbot/media/images/delete.png b/askbot/media/images/delete.png index 9263eae3..90349e69 100644 Binary files a/askbot/media/images/delete.png and b/askbot/media/images/delete.png differ diff --git a/askbot/media/images/edit2.png b/askbot/media/images/edit2.png index f142a68c..e683fddf 100644 Binary files a/askbot/media/images/edit2.png and b/askbot/media/images/edit2.png differ diff --git a/askbot/media/images/flag.png b/askbot/media/images/flag.png index fc302335..f9d8f0c0 100644 Binary files a/askbot/media/images/flag.png and b/askbot/media/images/flag.png differ diff --git a/askbot/media/images/link.png b/askbot/media/images/link.png index 6ad60f5e..7dd90f10 100644 Binary files a/askbot/media/images/link.png and b/askbot/media/images/link.png differ diff --git a/askbot/media/images/sprites.png b/askbot/media/images/sprites.png index 78eea747..4f23e088 100644 Binary files a/askbot/media/images/sprites.png and b/askbot/media/images/sprites.png differ diff --git a/askbot/media/style/style.less b/askbot/media/style/style.less index a0813f1a..0ce1b849 100644 --- a/askbot/media/style/style.less +++ b/askbot/media/style/style.less @@ -2086,7 +2086,8 @@ ul#related-tags li { margin-top:10px; margin-bottom:8px; - a { + a, + span.dropdown-toggle { color: #777; padding: 0px 7px 3px 18px; cursor: pointer; @@ -2095,17 +2096,51 @@ ul#related-tags li { font-family:@body-font; text-decoration: none; height:18px; - display:block; - float:right; line-height:18px; margin-top:-2px; margin-left:4px; } - a:hover { + a:hover, + span.dropdown-toggle:hover { background-color: #f5f0c9; + } + span.dropdown-toggle { + background: url(../images/sprites.png) no-repeat -7px -242px; .rounded-corners(3px); - + position: relative; + } + span.dropdown-toggle:hover { + padding-right: 0; + background: url(../images/sprites.png) no-repeat -7px -274px; + form { + margin: 0; + } + input { + display: block !important; + height: 20px !important; + line-height: 20px !important; + margin: 0; + padding: 0 5px; + .rounded-corners(0); + width: 100% !important; + } + .dropdown-menu { + display: block; + padding: 5px 0; + right: -5px !important; + left: auto; + li, + li:hover { + display: block !important; + margin: 0; + padding: 0; + width: 100% !important; + } + li:hover { + background-color: #f5f0c9; + } + } } .sep { color: #ccc; @@ -2116,11 +2151,11 @@ ul#related-tags li { } .post-controls, .answer-controls{ .question-delete{ - background: url(../images/delete.png) no-repeat left 2px; + background: url(../images/delete.png) no-repeat left -1px; padding-left:11px; } .question-flag{ - background: url(../images/flag.png) no-repeat center left; + background: url(../images/flag.png) no-repeat 2px 0; } .answer-publish{ background: url(../images/publish.png) no-repeat center left; @@ -2129,7 +2164,7 @@ ul#related-tags li { background: url(../images/unpublish.png) no-repeat 2px center; } .question-edit{ - background: url(../images/edit2.png) no-repeat 2px center; + background: url(../images/edit2.png) no-repeat 3px 1px; } .question-retag{ background: url(../images/retag.png) no-repeat center left; @@ -2138,7 +2173,7 @@ ul#related-tags li { background: url(../images/close.png) no-repeat center left; } .permant-link{ - background: url(../images/link.png) no-repeat center left; + background: url(../images/link.png) no-repeat 2px 1px; } .answer-convert{ diff --git a/askbot/models/post.py b/askbot/models/post.py index 66004ce4..322a3759 100644 --- a/askbot/models/post.py +++ b/askbot/models/post.py @@ -581,6 +581,11 @@ class Post(models.Model): def is_reject_reason(self): return self.post_type == 'reject_reason' + def get_last_edited_date(self): + """returns date of last edit or date of creation + if there were no edits""" + return self.last_edited_at or self.added_at + def get_moderators(self): """returns query set of users who are site administrators and moderators""" @@ -589,10 +594,27 @@ class Post(models.Model): user_filter = user_filter & models.Q(groups__in=self.groups.all()) return User.objects.filter(user_filter) - def get_last_edited_date(self): - """returns date of last edit or date of creation - if there were no edits""" - return self.last_edited_at or self.added_at + def get_previous_answer(self, user=None): + """returns a previous answer to a given answer; + only works on the "answer" post types""" + assert(self.post_type == 'answer') + all_answers = self.thread.get_answers(user=user) + + matching_answers = all_answers.filter( + added_at__lt=self.added_at, + ).order_by('-added_at') + + if len(matching_answers) == 0: + return None + + answer = matching_answers[0] + + if answer.id == self.id: + return None + if answer.added_at > self.added_at: + return None + + return answer def has_group(self, group): """true if post belongs to the group""" diff --git a/askbot/models/question.py b/askbot/models/question.py index 2d282fbc..d1fa7cae 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -600,6 +600,13 @@ class Thread(models.Model): else: return self.get_answers(user).count() + def get_oldest_answer_id(self, user=None): + """give oldest visible answer id for the user""" + answers = self.get_answers(user=user).order_by('added_at') + if len(answers) > 0: + return answers[0].id + return None + def get_sharing_info(self, visitor=None): """returns a dictionary with abbreviated thread sharing info: * users - up to a certain number of users, excluding the visitor diff --git a/askbot/templates/question.html b/askbot/templates/question.html index e2e6f394..5fcea3a9 100644 --- a/askbot/templates/question.html +++ b/askbot/templates/question.html @@ -15,7 +15,43 @@ /* - askbot['data']['maxCommentLength'] - ){ - convert_answer.parentNode.removeChild(convert_answer); + var answerBody = findChildrenByClassName(answer_container, 'answer-body')[0]; + //todo: this is not reliable + var answerBodyNodes = answerBody.childNodes; + var answerElement = answerBodyNodes[answerBodyNodes.length - 1]; + if (trim(answerElement.textContent).length > askbot['data']['maxCommentLength']) { + repostAsQuestionComment.parentNode.removeChild(repostAsQuestionComment); + repostAsPrevAnsComment.parentNode.removeChild(repostAsPrevAnsComment); + } else if (parseInt(post_id) === data['oldestAnswerId']) { + repostAsPrevAnsComment.parentNode.removeChild(repostAsPrevAnsComment); } } else{ - convert_answer.parentNode.removeChild(convert_answer); + repostAsQuestionComment.parentNode.removeChild(repostAsQuestionComment); + repostAsPrevAnsComment.parentNode.removeChild(repostAsPrevAnsComment); + } + + if (extraOptsList.getElementsByTagName('li').length === 0) { + extraOpts.parentNode.removeChild(extraOpts); } } @@ -87,21 +135,21 @@ if (data['userIsAdminOrMod']){ return;//all remaining functions stay on } - if (data['user_posts'] === undefined) { - return; - } - if (post_id in data['user_posts']){ + if (data['user_posts'] && post_id in data['user_posts']){ //todo: remove edit button from older comments - return;//same here + return; } + var deleteBtn = document.getElementById('post-' + post_id + '-delete'); + var controls = deleteBtn.parentNode; if (//maybe remove "delete" button data['userReputation'] < {{settings.MIN_REP_TO_DELETE_OTHERS_COMMENTS}} ) { - var delete_btn = document.getElementById( - 'post-' + post_id + '-delete' - ); - delete_btn.parentNode.removeChild(delete_btn); + removeNode(deleteBtn); + } + var flags = findChildrenByClassName(controls, 'question-flag'); + if (flags.length > 0) { + removeNode(flags[0]); } if (//maybe remove "edit" button data['userReputation'] < @@ -116,8 +164,10 @@ data['userReputation'] < {{settings.MIN_REP_TO_RETAG_OTHERS_QUESTIONS}} ){ - var retag_btn = document.getElementById('retag'); - retag_btn.parentNode.removeChild(retag_btn); + var retagBtn = document.getElementById('retag'); + if (retagBtn) { + retagBtn.parentNode.removeChild(retagBtn); + } } } function render_add_comment_button(post_id, extra_comment_count){ @@ -188,7 +238,7 @@ function hide_convert_links(){ if (!askbot['data']['userIsAdminOrMod']){ - var links = document.getElementsByClassName('convert-comment'); + var links = findChildrenByClassName(document, 'convert-comment'); for (i=0; i {% trans %}swap with question{% endtrans %} uncomment if needed#} - - - {% trans %}link{% endtrans %} - - - - {% if answer.id in published_answer_ids %} - {% trans %}unpublish{% endtrans %} - {% else %} - {% trans %}publish{% endtrans %} - {% endif %} - - - {% if answer.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %} + + {% trans %}edit{% endtrans %} {% if answer.offensive_flag_count > 0 %} {% trans %}flag offensive{% endtrans %} {% endif %} - - {% trans %}edit{% endtrans %} + + {% if answer.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %} + + + {% if answer.id in published_answer_ids %} + {% trans %}unpublish{% endtrans %} + {% else %} + {% trans %}publish{% endtrans %} + {% endif %} + + + + {% trans %}link{% endtrans %} + - -
- {% csrf_token %} - - -
+{% trans %}more{% endtrans %} + +{% trans %}retag{% endtrans %} {% if question.offensive_flag_count > 0 %} {% trans %}flag offensive{% endtrans %} {% endif %} - -{% trans %}retag{% endtrans %} -{% trans %}edit{% endtrans %} +{% if thread.closed %} + {% trans %}reopen{% endtrans %} +{% else %} + {% trans %}close{% endtrans %} +{% endif %} +{% if question.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %} diff --git a/askbot/urls.py b/askbot/urls.py index a82b4694..551b9ecd 100644 --- a/askbot/urls.py +++ b/askbot/urls.py @@ -194,15 +194,22 @@ urlpatterns = patterns('', views.readers.get_comment, name='get_comment' ), - url(#post only + url( r'^comment/convert/$', views.writers.comment_to_answer, name='comment_to_answer' ), + url( + r'^answer/repost-as-comment-under-question/$', + views.writers.repost_answer_as_comment, + kwargs={'destination': 'comment_under_question'}, + name='repost_answer_as_comment_under_question' + ), url(#post only - r'^answer/convert/$', - views.writers.answer_to_comment, - name='answer_to_comment' + '^answer/repost-as-comment-under-previous-answer/$', + views.writers.repost_answer_as_comment, + kwargs={'destination': 'comment_under_previous_answer'}, + name='repost_answer_as_comment_under_previous_answer' ), url(#post only r'^answer/publish/$', diff --git a/askbot/views/readers.py b/askbot/views/readers.py index 7fbcf6d0..51a4da8e 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -598,6 +598,7 @@ def question(request, id):#refactor - long subroutine. display question body, an 'user_post_id_list': user_post_id_list, 'user_can_post_comment': user_can_post_comment,#in general 'user_already_gave_answer': user_already_gave_answer, + 'oldest_answer_id': thread.get_oldest_answer_id(request.user), 'previous_answer': previous_answer, 'tab_id' : answer_sort_method, 'favorited' : favorited, diff --git a/askbot/views/writers.py b/askbot/views/writers.py index b581036c..8c421fb7 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -771,22 +771,43 @@ def comment_to_answer(request): @decorators.admins_only @decorators.post_only -def answer_to_comment(request): +#todo: change the urls config for this +def repost_answer_as_comment(request, destination=None): + assert( + destination in ( + 'comment_under_question', + 'comment_under_previous_answer' + ) + ) answer_id = request.POST.get('answer_id') if answer_id: answer_id = int(answer_id) answer = get_object_or_404(models.Post, post_type = 'answer', id=answer_id) + + if destination == 'comment_under_question': + destination_post = answer.thread._question_post() + else: + #comment_under_previous_answer + destination_post = answer.get_previous_answer(user=request.user) + #todo: implement for comment under other answer + + if destination_post is None: + message = _('Error - could not find the destination post') + request.user.message_set.create(message=message) + return HttpResponseRedirect(answer.get_absolute_url()) + if len(answer.text) <= askbot_settings.MAX_COMMENT_LENGTH: answer.post_type = 'comment' - answer.parent = answer.thread._question_post() + answer.parent = destination_post #can we trust this? old_comment_count = answer.comment_count answer.comment_count = 0 answer_comments = models.Post.objects.get_comments().filter(parent=answer) - answer_comments.update(parent=answer.parent) + answer_comments.update(parent=destination_post) + #why this and not just "save"? answer.parse_and_save(author=answer.author) answer.thread.update_answer_count() -- cgit v1.2.3-1-g7c22