upvoting / downvoting complete

v1.18.x
psychobunny 11 years ago
parent af805d3ca4
commit 25a6302c01

@ -44,7 +44,7 @@
"vote.not_logged_in.title": "Not Logged In", "vote.not_logged_in.title": "Not Logged In",
"vote.not_logged_in.message": "Please log in in order to vote", "vote.not_logged_in.message": "Please log in in order to vote",
"vote.cant_vote_self.title": "Invalid Vote", "vote.cant_vote_self.title": "Invalid Vote",
"vote.not_logged_in.message": "You cannot vote for your own post", "vote.cant_vote_self.message": "You cannot vote for your own post",
"loading_more_posts": "Loading More Posts", "loading_more_posts": "Loading More Posts",
"move_topic": "Move Topic", "move_topic": "Move Topic",

@ -445,9 +445,9 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
$('#post-container').on('click', '.upvote', function() { $('#post-container').on('click', '.upvote', function() {
var post = $(this).parents('.post-row'), var post = $(this).parents('.post-row'),
pid = post.attr('data-pid'), pid = post.attr('data-pid'),
upvoted = post.find('.votes').attr('data-vote-status') === 'upvoted'; upvoted = post.find('.upvoted').length;
if (upvoted === true) { if (upvoted) {
socket.emit('posts.unvote', { socket.emit('posts.unvote', {
pid: pid, pid: pid,
room_id: app.currentRoom room_id: app.currentRoom
@ -465,9 +465,9 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
$('#post-container').on('click', '.downvote', function() { $('#post-container').on('click', '.downvote', function() {
var post = $(this).parents('.post-row'), var post = $(this).parents('.post-row'),
pid = post.attr('data-pid'), pid = post.attr('data-pid'),
downvoted = post.find('.votes').attr('data-vote-status') === 'downvoted'; downvoted = post.find('.downvoted').length;
if (downvoted === true) { if (downvoted) {
socket.emit('posts.unvote', { socket.emit('posts.unvote', {
pid: pid, pid: pid,
room_id: app.currentRoom room_id: app.currentRoom
@ -802,29 +802,18 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
socket.on('posts.upvote', function(data) { socket.on('posts.upvote', function(data) {
if (data && data.pid) { if (data && data.pid) {
var post = $('li[data-pid="' + data.pid + '"]'), var post = $('li[data-pid="' + data.pid + '"]'),
upvote = post.find('.upvote'), upvote = post.find('.upvote');
downvote = post.find('.downvote'),
votes = post.find('.votes');
upvote.addClass('btn-primary'); upvote.addClass('btn-primary upvoted');
downvote.removeClass('btn-primary');
votes.attr('data-vote-status', 'upvoted');
} }
}); });
socket.on('posts.downvote', function(data) { socket.on('posts.downvote', function(data) {
if (data && data.pid) { if (data && data.pid) {
var post = $('li[data-pid="' + data.pid + '"]'), var post = $('li[data-pid="' + data.pid + '"]'),
upvote = post.find('.upvote'), downvote = post.find('.downvote');
downvote = post.find('.downvote'),
votes = post.find('.votes'), downvote.addClass('btn-primary downvoted');
currentVotes = parseInt(votes.attr('data-votes'), 10) - 1;
downvote.addClass('btn-primary');
upvote.removeClass('btn-primary');
votes.html(currentVotes)
.attr('data-votes', currentVotes)
.attr('data-vote-status', 'downvoted');
} }
}); });
@ -832,22 +821,10 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
if (data && data.pid) { if (data && data.pid) {
var post = $('li[data-pid="' + data.pid + '"]'), var post = $('li[data-pid="' + data.pid + '"]'),
upvote = post.find('.upvote'), upvote = post.find('.upvote'),
downvote = post.find('.downvote'), downvote = post.find('.downvote');
votes = post.find('.votes'),
status = votes.attr('data-vote-status'),
currentVotes = parseInt(votes.attr('data-votes'), 10);
if (status === 'upvoted') {
currentVotes --;
upvote.removeClass('btn-primary');
} else if (status === 'downvoted') {
currentVotes ++;
downvote.removeClass('btn-primary');
}
votes.html(currentVotes) upvote.removeClass('btn-primary upvoted');
.attr('data-votes', currentVotes) downvote.removeClass('btn-primary downvoted');
.attr('data-vote-status', '');
} }
}); });
@ -903,8 +880,8 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
currentVotes += value; currentVotes += value;
reputation += value; reputation += value;
reputationElements.html(currentVotes).attr('data-votes', currentVotes); votes.html(currentVotes).attr('data-votes', currentVotes);
reputationElements.html(reputation); reputationElements.html(reputation).attr('data-reputation', reputation);
} }
function set_locked_state(locked, alert) { function set_locked_state(locked, alert) {

@ -72,7 +72,7 @@
<button class="btn btn-sm btn-default flag" type="button" title="[[topic:flag_title]]"><i class="fa fa-flag-o"></i></button> <button class="btn btn-sm btn-default flag" type="button" title="[[topic:flag_title]]"><i class="fa fa-flag-o"></i></button>
<button data-favourited="{posts.favourited}" class="favourite favourite-tooltip btn btn-sm btn-default <!-- IF posts.favourited --> btn-warning <!-- ENDIF posts.favourited -->" type="button"> <button data-favourited="{posts.favourited}" class="favourite favourite-tooltip btn btn-sm btn-default <!-- IF posts.favourited --> btn-warning <!-- ENDIF posts.favourited -->" type="button">
<span class="favourite-text">[[topic:favourite]]</span> <span class="favourite-text">[[topic:favourite]]</span>
<span class="post_rep_{posts.pid}">{posts.favourited} </span> <span class="post_rep_{posts.pid}">{posts.reputation} </span>
<!-- IF posts.favourited --> <!-- IF posts.favourited -->
<i class="fa fa-star"></i> <i class="fa fa-star"></i>
<!-- ELSE --> <!-- ELSE -->
@ -82,9 +82,9 @@
</div> </div>
<div class="btn-group"> <div class="btn-group">
<button class="upvote btn btn-sm btn-default"><i class="fa fa-chevron-up"></i></button> <button class="upvote btn btn-sm btn-default <!-- IF posts.upvoted --> upvoted btn-primary <!-- ENDIF posts.upvoted -->"><i class="fa fa-chevron-up"></i></button>
<button class="votes btn btn-sm btn-default" data-vote-status="" data-votes="1" disabled>1</button> <button class="votes btn btn-sm btn-default" data-votes="{posts.votes}" disabled>{posts.votes}</button>
<button class="downvote btn btn-sm btn-default"><i class="fa fa-chevron-down"></i></button> <button class="downvote btn btn-sm btn-default <!-- IF posts.downvoted --> downvoted btn-primary <!-- ENDIF posts.downvoted -->"><i class="fa fa-chevron-down"></i></button>
</div> </div>
<!-- IF privileges.write --> <!-- IF privileges.write -->

@ -8,74 +8,109 @@ var async = require('async'),
(function (Favourites) { (function (Favourites) {
"use strict"; "use strict";
function vote(type, postData, pid, room_id, uid, socket) { function vote(type, unvote, pid, room_id, uid, socket, callback) {
var websockets = require('./socket.io'); var websockets = require('./socket.io');
if (uid === 0) { if (uid === 0) {
return socket.emit('event:alert', { return socket.emit('event:alert', {
alert_id: 'post_vote', alert_id: 'post_vote',
title: '[[vote.not_logged_in.title]]', title: '[[topic:vote.not_logged_in.title]]',
message: '[[vote.not_logged_in.message]]', message: '[[topic:vote.not_logged_in.message]]',
type: 'danger',
timeout: 5000
});
} else if (uid === postData.uid) {
return socket.emit('event:alert', {
alert_id: 'post_vote',
title: '[[vote.cant_vote_self.title]]',
message: '[[vote.cant_vote_self.message]]',
type: 'danger', type: 'danger',
timeout: 5000 timeout: 5000
}); });
} }
//Favourites.hasVoted(type, pid, uid, function (err, hasVoted) { posts.getPostFields(pid, ['uid', 'timestamp'], function (err, postData) {
// if (!hasVoted) { if (uid === parseInt(postData.uid, 10)) {
var notType = (type === 'upvote' ? 'downvote' : 'upvote'); socket.emit('event:alert', {
alert_id: 'post_vote',
title: '[[topic:vote.cant_vote_self.title]]',
message: '[[topic:vote.cant_vote_self.message]]',
type: 'danger',
timeout: 5000
});
db[type === 'upvote' ? 'sortedSetAdd' : 'sortedSetRemove']('uid:' + uid + ':upvote', postData.timestamp, pid); if (callback) {
db[type === 'upvote' ? 'sortedSetRemove' : 'sortedSetAdd']('uid:' + uid + ':downvote', postData.timestamp, pid); callback(false);
}
return false;
}
user[type === 'upvote' ? 'incrementUserFieldBy' : 'decrementUserFieldBy'](postData.uid, 'reputation', 1, function (err, newreputation) { db[type === 'upvote' || !unvote ? 'sortedSetAdd' : 'sortedSetRemove']('uid:' + uid + ':upvote', postData.timestamp, pid);
db.sortedSetAdd('users:reputation', newreputation, postData.uid); db[type === 'upvote' || unvote ? 'sortedSetRemove' : 'sortedSetAdd']('uid:' + uid + ':downvote', postData.timestamp, pid);
});
db.setAdd('pid:' + pid + ':' + type, uid, function(err) { user[type === 'upvote' ? 'incrementUserFieldBy' : 'decrementUserFieldBy'](postData.uid, 'reputation', 1, function (err, newreputation) {
db.setCount('pid:' + pid + ':' + type, function(err, count) { db.sortedSetAdd('users:reputation', newreputation, postData.uid);
posts.setPostField(pid, type, count); });
});
});
db.setRemove('pid:' + pid + ':' + notType, uid, function(err) { if (room_id) {
db.setCount('pid:' + pid + ':' + notType, function(err, count) { websockets.in(room_id).emit('event:' + (type === 'upvote' ? 'rep_up' : 'rep_down'), {
posts.setPostField(pid, notType, count); uid: postData.uid,
}); pid: pid
}); });
}
if (room_id) { socket.emit('posts.' + (unvote ? 'unvote' : type), {
websockets.in(room_id).emit('event:' + (type === 'upvote' ? 'rep_up' : 'rep_down'), { pid: pid
uid: postData.uid, });
pid: pid
}); adjustPostVotes(pid, uid, type, unvote, function() {
if (callback) {
callback();
} }
});
});
}
socket.emit('posts.' + type, { function adjustPostVotes(pid, uid, type, unvote, callback) {
pid: pid var notType = (type === 'upvote' ? 'downvote' : 'upvote');
async.series([
function(next) {
if (unvote) {
db.setRemove('pid:' + pid + ':' + type, uid, function(err) {
next(err);
});
} else {
db.setAdd('pid:' + pid + ':' + type, uid, function(err) {
next(err);
});
}
},
function(next) {
db.setRemove('pid:' + pid + ':' + notType, uid, function(err) {
next(err);
}); });
// } }
//}); ], function(err) {
async.parallel({
upvotes: function(next) {
db.setCount('pid:' + pid + ':upvote', next);
},
downvotes: function(next) {
db.setCount('pid:' + pid + ':downvote', next);
}
}, function(err, results) {
posts.setPostField(pid, 'votes', parseInt(results.upvotes, 10) - parseInt(results.downvotes, 10));
});
if (callback) {
callback();
}
});
} }
Favourites.upvote = function(pid, room_id, uid, socket) { Favourites.upvote = function(pid, room_id, uid, socket) {
Favourites.unvote(pid, room_id, uid, socket, function(err, postData) { Favourites.unvote(pid, room_id, uid, socket, function(err) {
vote('upvote', postData, pid, room_id, uid, socket); vote('upvote', false, pid, room_id, uid, socket);
}); });
}; };
Favourites.downvote = function(pid, room_id, uid, socket) { Favourites.downvote = function(pid, room_id, uid, socket) {
Favourites.unvote(pid, room_id, uid, socket, function(err, postData) { Favourites.unvote(pid, room_id, uid, socket, function(err) {
vote('downvote', postData, pid, room_id, uid, socket); vote('downvote', false, pid, room_id, uid, socket);
}); });
}; };
@ -83,79 +118,49 @@ var async = require('async'),
var websockets = require('./socket.io'); var websockets = require('./socket.io');
Favourites.hasVoted(pid, uid, function(err, voteStatus) { Favourites.hasVoted(pid, uid, function(err, voteStatus) {
posts.getPostFields(pid, ['uid', 'timestamp'], function (err, postData) { if (voteStatus.upvoted || voteStatus.downvoted) {
if (voteStatus === 'upvoted') { socket.emit('posts.unvote', {
db.sortedSetRemove('uid:' + uid + ':upvote'); pid: pid
});
db.setRemove('pid:' + pid + ':upvote', uid, function(err) {
db.setCount('pid:' + pid + ':upvote', function(err, count) {
posts.setPostField(pid, 'upvote', count);
});
});
user.decrementUserFieldBy(postData.uid, 'reputation', 1, function (err, newreputation) {
db.sortedSetAdd('users:reputation', newreputation, postData.uid);
});
if (room_id) {
websockets.in(room_id).emit('event:rep_down', {
uid: postData.uid,
pid: pid
});
}
} else if (voteStatus === 'downvoted') {
db.sortedSetRemove('uid:' + uid + ':downvote');
db.setRemove('pid:' + pid + ':downvote', uid, function(err) {
db.setCount('pid:' + pid + ':downvote', function(err, count) {
posts.setPostField(pid, 'downvote', count);
});
});
user.incrementUserFieldBy(postData.uid, 'reputation', 1, function (err, newreputation) {
db.sortedSetAdd('users:reputation', newreputation, postData.uid);
});
if (room_id) { return vote(voteStatus.upvoted ? 'downvote' : 'upvote', true, pid, room_id, uid, socket, function() {
websockets.in(room_id).emit('event:rep_up', { if (callback) {
uid: postData.uid, callback(err);
pid: pid
});
} }
} });
}
if (voteStatus) {
socket.emit('posts.unvote', {
pid: pid
});
}
if (callback) { if (callback) {
callback(err, postData); callback(err);
} }
});
}); });
}; };
Favourites.hasVoted = function(pid, uid, callback) { Favourites.hasVoted = function(pid, uid, callback) {
async.parallel({ async.parallel({
upvoted: function(each) { upvoted: function(next) {
db.isSetMember('pid:' + pid + ':upvote', uid, each); db.isSetMember('pid:' + pid + ':upvote', uid, next);
}, },
downvoted: function(each) { downvoted: function(next) {
db.isSetMember('pid:' + pid + ':downvote', uid, each); db.isSetMember('pid:' + pid + ':downvote', uid, next);
} }
}, function(err, results) { }, function(err, results) {
var voteStatus = ""; callback(err, results)
});
};
if (results.upvoted) { Favourites.getVoteStatusByPostIDs = function(pids, uid, callback) {
voteStatus = "upvoted"; var data = {};
} else if (results.downvoted) {
voteStatus = "downvoted"; function iterator(pid, next) {
} Favourites.hasVoted(pid, uid, function(err, voteStatus) {
data[pid] = voteStatus;
next()
});
}
callback(err, voteStatus) async.each(pids, iterator, function(err) {
callback(data);
}); });
}; };

@ -341,6 +341,12 @@ var async = require('async'),
}); });
} }
function getVoteStatusData(next) {
favourites.getVoteStatusByPostIDs(pids, current_user, function(vote_data) {
next(null, vote_data);
})
}
function addUserInfoToPosts(next) { function addUserInfoToPosts(next) {
function iterator(post, callback) { function iterator(post, callback) {
posts.addUserInfoToPost(post, function() { posts.addUserInfoToPost(post, function() {
@ -370,17 +376,21 @@ var async = require('async'),
} }
} }
async.parallel([getFavouritesData, addUserInfoToPosts, getPrivileges], function(err, results) { async.parallel([getFavouritesData, addUserInfoToPosts, getPrivileges, getVoteStatusData], function(err, results) {
if(err) { if(err) {
return callback(err); return callback(err);
} }
var fav_data = results[0], var fav_data = results[0],
privileges = results[2]; privileges = results[2],
voteStatus = results[3];
for (var i = 0; i < postData.length; ++i) { for (var i = 0; i < postData.length; ++i) {
var pid = postData[i].pid; var pid = postData[i].pid;
postData[i].favourited = fav_data[pid]; postData[i].favourited = fav_data[pid];
postData[i].upvoted = voteStatus[pid].upvoted;
postData[i].downvoted = voteStatus[pid].downvoted;
postData[i].votes = postData[i].votes || 0;
postData[i].display_moderator_tools = (current_user != 0) && privileges[pid].editable; postData[i].display_moderator_tools = (current_user != 0) && privileges[pid].editable;
postData[i].display_move_tools = privileges[pid].move; postData[i].display_move_tools = privileges[pid].move;
if(parseInt(postData[i].deleted, 10) === 1 && !privileges[pid].view_deleted) { if(parseInt(postData[i].deleted, 10) === 1 && !privileges[pid].view_deleted) {

Loading…
Cancel
Save