summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2011-06-22 22:47:44 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2011-06-22 22:47:44 -0400
commite29674c17e846b227d44d62b64f3f2c47c81c488 (patch)
tree79b3fea20c52a103f25621afc6b848b8c8e942fb
parentf0bb55bec42b03b2a8720e04bf72c6b1ef99984c (diff)
downloadaskbot-e29674c17e846b227d44d62b64f3f2c47c81c488.tar.gz
askbot-e29674c17e846b227d44d62b64f3f2c47c81c488.tar.bz2
askbot-e29674c17e846b227d44d62b64f3f2c47c81c488.zip
voting for comments works
-rw-r--r--askbot/models/__init__.py7
-rw-r--r--askbot/skins/default/media/js/post.js93
-rwxr-xr-xaskbot/skins/default/media/style/style.css25
-rw-r--r--askbot/skins/default/templates/macros.html8
-rw-r--r--askbot/tests/db_api_tests.py42
-rw-r--r--askbot/views/commands.py9
-rw-r--r--askbot/views/writers.py7
7 files changed, 100 insertions, 91 deletions
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index 4cf713b2..66992dad 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -336,7 +336,12 @@ def user_assert_can_vote_for_post(
:param:post can be instance of question or answer
"""
- if self == post.author:
+ #todo: after unifying models this if else will go away
+ if isinstance(post, Comment):
+ post_author = post.user
+ else:
+ post_author = post.author
+ if self == post_author:
raise django_exceptions.PermissionDenied(_('cannot vote for own posts'))
blocked_error_message = _(
diff --git a/askbot/skins/default/media/js/post.js b/askbot/skins/default/media/js/post.js
index e836ac32..5fbf0ad8 100644
--- a/askbot/skins/default/media/js/post.js
+++ b/askbot/skins/default/media/js/post.js
@@ -142,22 +142,17 @@ var CPValidator = function(){
}();
/**
- * @enum {number}
- */
-var VoteType = {
- UP: 0,
- DOWN: 1,
-};
-
-/**
* @constructor
* @extends {SimpleControl}
- * @param {VoteType} vote_type
- * @param {string} vote_url
+ * @param {Comment} comment to upvote
*/
-var CommentVoteButton = function(vote_type, vote_url){
+var CommentVoteButton = function(comment){
SimpleControl.call(this);
/**
+ * @param {Comment}
+ */
+ this._comment = comment;
+ /**
* @type {boolean}
*/
this._voted = false;
@@ -165,33 +160,9 @@ var CommentVoteButton = function(vote_type, vote_url){
* @type {number}
*/
this._score = 0;
- /**
- * @type {VoteType}
- */
- this._vote_type = vote_type;
- /**
- * @type {string}
- */
- this._vote_url = vote_url;
- /**
- * @type {?number}
- */
- this._post_id;
};
inherits(CommentVoteButton, SimpleControl);
/**
- * @param {number}
- */
-CommentVoteButton.prototype.setCommentId = function(post_id){
- this._post_id = post_id;
-};
-/**
- * a hack. this method is to be called before CommentVoteButton.getElement()
- */
-CommentVoteButton.prototype.setCommentElement = function(celem){
- this._comment_element = celem;
-};
-/**
* @param {number} score
*/
CommentVoteButton.prototype.setScore = function(score){
@@ -205,14 +176,17 @@ CommentVoteButton.prototype.setScore = function(score){
*/
CommentVoteButton.prototype.setVoted = function(voted){
this._voted = voted;
+ if (this._element){
+ this._element.addClass('upvoted');
+ }
};
CommentVoteButton.prototype.getVoteHandler = function(){
var me = this;
+ var comment = this._comment;
return function(){
var voted = me._voted;
- var post_id = me._post_id;
- var url = me._vote_url;
+ var post_id = me._comment.getId();
var data = {
cancel_vote: voted ? true:false,
post_id: post_id
@@ -221,14 +195,14 @@ CommentVoteButton.prototype.getVoteHandler = function(){
type: 'POST',
data: data,
dataType: 'json',
- url: url,
+ url: askbot['urls']['upvote_comment'],
cache: false,
success: function(data){
me.setScore(data['score']);
me.setVoted(true);
},
error: function(xhr, textStatus, exception) {
- showMessage(me.getElement(), xhr.responseText, 'after');
+ showMessage(comment.getElement(), xhr.responseText, 'after');
}
});
};
@@ -236,33 +210,34 @@ CommentVoteButton.prototype.getVoteHandler = function(){
CommentVoteButton.prototype.decorate = function(element){
this._element = element;
-
this.setHandler(this.getVoteHandler());
- var comment_vote = this._element.find('.upvote');
- if (this._element.parent()){
- var height = this._element.parent().height();
- this._element.height(height);
- }
var element = this._element;
- this._comment_element.mouseenter(function(){
- elment.addClass('hover');
+ var comment = this._comment;
+ /* can't call comment.getElement() here due
+ * an issue in the getElement() of comment
+ * so use an "illegal" access to comment._element here
+ */
+ comment._element.mouseenter(function(){
+ //outside height may not be known
+ var height = comment.getElement().height();
+ element.height(height);
+ element.addClass('hover');
});
- this._comment_element.mouseleave(function(){
+ comment._element.mouseleave(function(){
element.removeClass('hover');
});
};
CommentVoteButton.prototype.createDom = function(){
- this._element = this.makeElement('span');
- if (this._vote_type === VoteType.UP){
- this._element.addClass('upvote');
- } else if (this._vote_type === VoteType.DOWN){
- this._element.addClass('downvote');
+ this._element = this.makeElement('div');
+ if (this._score > 0){
+ this._element.html(this._score);
}
+ this._element.addClass('upvote');
if (this._voted){
- this._element.addClass('voted');
+ this._element.addClass('upvoted');
}
this.decorate(this._element);
};
@@ -1188,10 +1163,7 @@ Comment.prototype.decorate = function(element){
this._edit_link.decorate(edit_link);
}
- var url = askbot['urls']['upvote_comment'];
- var vote = new CommentVoteButton(VoteType.UP, url);
- vote.setCommentId(comment_id);
- vote.setCommentElement(this._element);
+ var vote = new CommentVoteButton(this);
vote.decorate(this._element.find('.comment-votes .upvote'));
this._blank = false;
@@ -1235,14 +1207,11 @@ Comment.prototype.setContent = function(data){
var votes = this.makeElement('div');
votes.addClass('comment-votes');
- var vote_url = askbot['urls']['upvote_comment'];
- var vote = new CommentVoteButton(VoteType.UP, vote_url);
+ var vote = new CommentVoteButton(this);
if (this._data['upvoted_by_user']){
vote.setVoted(true);
}
vote.setScore(this._data['score']);
- vote.setCommentId(this._data['id']);
- vote.setCommentElement(this._element);
votes.append(vote.getElement());
this._element.append(votes);
diff --git a/askbot/skins/default/media/style/style.css b/askbot/skins/default/media/style/style.css
index c1474432..85bc8801 100755
--- a/askbot/skins/default/media/style/style.css
+++ b/askbot/skins/default/media/style/style.css
@@ -968,20 +968,29 @@ a:hover.medal {
}
div.comment .comment-votes {
- position:absolute;
+ position: absolute;
width: 20px;
- height: 25px;
- margin-left: -20px;
+ margin: -2px 0 0 -20px;
}
-div.comment .comment-votes .upvote.hover {
+div.comment .upvote {
+ width: 20px;
+ height: 20px;
+ padding: 3px 0 0 3px;
+ font-weight: bold;
+ color: #777;
+}
+
+div.comment .upvote.upvoted {
+ color: #d64000;
+}
+
+div.comment .upvote.hover {
background: url(../images/go-up-grey.png) no-repeat;
- padding-left: 16px;
}
-div.comment .comment-votes .upvote:hover {
+div.comment .upvote:hover {
background: url(../images/go-up-orange.png) no-repeat;
- padding-left: 16px;
}
.comments div.controls {
@@ -1807,7 +1816,7 @@ button::-moz-focus-inner {
border-top: 1px dotted #ccccce;
margin: 0;
color: #444;
- padding: 2px 3px 5px 3px;
+ padding: 5px 3px 5px 3px;
overflow: auto;
}
diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html
index 5e401cb8..23177c0b 100644
--- a/askbot/skins/default/templates/macros.html
+++ b/askbot/skins/default/templates/macros.html
@@ -453,12 +453,12 @@ poor design of the data or methods on data objects #}
{%- macro comment_votes(comment = None) -%}
<div class="comment-votes">
{% if comment.score > 0 %}
- <span class="upvote{% if comment.voted_by_user %} upvoted{% endif %}">
+ <div class="upvote{% if comment.upvoted_by_user %} upvoted{% endif %}">
{{comment.score}}
- </span>
+ </div>
{% else %}
- <span class="upvote">
- </span>
+ <div class="upvote">
+ </div>
{% endif %}
</div>
{%- endmacro -%}
diff --git a/askbot/tests/db_api_tests.py b/askbot/tests/db_api_tests.py
index 2bb39084..18fc174b 100644
--- a/askbot/tests/db_api_tests.py
+++ b/askbot/tests/db_api_tests.py
@@ -3,6 +3,7 @@ functions that happen on behalf of users
e.g. ``some_user.do_something(...)``
"""
+from django.core import exceptions
from askbot.tests.utils import AskbotTestCase
from askbot import models
from askbot import const
@@ -38,16 +39,6 @@ class DBApiTests(AskbotTestCase):
self.assertTrue(post.deleted_by == None)
self.assertTrue(post.deleted_at == None)
- def test_get_question_comments(self):
- comment = self.user.post_comment(
- parent_post = self.question,
- body_text = 'lalalalalalalalal hahahah'
- )
- self.other_user.upvote(comment)
- comments = self.question.get_comments(visitor = self.other_user)
- self.assertEquals(len(comments), 1)
- self.assertEquals(comments[0].upvoted_by_user, True)
-
def test_flag_question(self):
self.user.set_status('m')
self.user.flag_post(self.question)
@@ -355,3 +346,34 @@ class GlobalTagSubscriberGetterTests(AskbotTestCase):
expected_subscribers = set([self.u2,]),
reason = 'bad'
)
+
+class CommentTests(AskbotTestCase):
+ """unfortunately, not very useful tests,
+ as assertions of type "user can" are not inside
+ the User.upvote() function
+ todo: refactor vote processing code
+ """
+ def setUp(self):
+ self.create_user()
+ self.create_user(username = 'other_user')
+ self.question = self.post_question()
+ self.now = datetime.datetime.now()
+ self.comment = self.user.post_comment(
+ parent_post = self.question,
+ body_text = 'lalalalalalalalal hahahah'
+ )
+
+ def test_other_user_can_upvote_comment(self):
+ self.other_user.upvote(self.comment)
+ comments = self.question.get_comments(visitor = self.other_user)
+ self.assertEquals(len(comments), 1)
+ self.assertEquals(comments[0].upvoted_by_user, True)
+
+
+ def test_other_user_can_cancel_upvote(self):
+ self.test_other_user_can_upvote_comment()
+ comment = models.Comment.objects.get(id = self.comment.id)
+ self.assertEquals(comment.score, 1)
+ self.other_user.upvote(comment, cancel = True)
+ comment = models.Comment.objects.get(id = self.comment.id)
+ self.assertEquals(comment.score, 0)
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index d6fe4759..04d4ef1b 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -35,7 +35,6 @@ def process_vote(user = None, vote_direction = None, post = None):
also in the future make keys in response data be more meaningful
right now they are kind of cryptic - "status", "count"
"""
-
if user.is_anonymous():
raise exceptions.PermissionDenied(_('anonymous users cannot vote'))
@@ -539,8 +538,6 @@ def swap_question_with_answer(request):
@decorators.ajax_only
@decorators.post_only
def upvote_comment(request):
- import pdb
- pdb.set_trace()
if request.user.is_anonymous():
raise exceptions.PermissionDenied(_('Please sign in to vote'))
form = forms.VoteForm(request.POST)
@@ -548,7 +545,11 @@ def upvote_comment(request):
comment_id = form.cleaned_data['post_id']
cancel_vote = form.cleaned_data['cancel_vote']
comment = models.Comment.objects.get(id = comment_id)
- request.user.upvote(comment, cancel = cancel_vote)
+ process_vote(
+ post = comment,
+ vote_direction = 'up',
+ user = request.user
+ )
else:
raise ValueError
return {'score': comment.score}
diff --git a/askbot/views/writers.py b/askbot/views/writers.py
index 8ec85bad..c5a69c1d 100644
--- a/askbot/views/writers.py
+++ b/askbot/views/writers.py
@@ -529,7 +529,7 @@ def __generate_comments_json(obj, user):#non-view generates json data for the po
comment_owner = comment.get_owner()
- json_comments.append({'id' : comment.id,
+ comment_data = {'id' : comment.id,
'object_id': obj.id,
'comment_age': diff_date(comment.added_at),
'html': comment.html,
@@ -538,7 +538,10 @@ def __generate_comments_json(obj, user):#non-view generates json data for the po
'user_id': comment_owner.id,
'is_deletable': is_deletable,
'is_editable': is_editable,
- })
+ 'score': comment.score,
+ 'upvoted_by_user': getattr(comment, 'upvoted_by_user', False)
+ }
+ json_comments.append(comment_data)
data = simplejson.dumps(json_comments)
return HttpResponse(data, mimetype="application/json")