From 25a6302c01f0ada57fed08602d8336992472e757 Mon Sep 17 00:00:00 2001 From: psychobunny Date: Thu, 6 Feb 2014 14:30:59 -0500 Subject: [PATCH] upvoting / downvoting complete --- public/language/en_GB/topic.json | 2 +- public/src/forum/topic.js | 53 +++----- public/templates/topic.tpl | 8 +- src/favourites.js | 207 ++++++++++++++++--------------- src/topics.js | 14 ++- 5 files changed, 138 insertions(+), 146 deletions(-) diff --git a/public/language/en_GB/topic.json b/public/language/en_GB/topic.json index 8d38d4823f..e1d1651e0d 100644 --- a/public/language/en_GB/topic.json +++ b/public/language/en_GB/topic.json @@ -44,7 +44,7 @@ "vote.not_logged_in.title": "Not Logged In", "vote.not_logged_in.message": "Please log in in order to 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", "move_topic": "Move Topic", diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index 62ac232630..f107ba335e 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -445,9 +445,9 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { $('#post-container').on('click', '.upvote', function() { var post = $(this).parents('.post-row'), pid = post.attr('data-pid'), - upvoted = post.find('.votes').attr('data-vote-status') === 'upvoted'; - - if (upvoted === true) { + upvoted = post.find('.upvoted').length; + + if (upvoted) { socket.emit('posts.unvote', { pid: pid, room_id: app.currentRoom @@ -465,9 +465,9 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { $('#post-container').on('click', '.downvote', function() { var post = $(this).parents('.post-row'), 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', { pid: pid, room_id: app.currentRoom @@ -802,29 +802,18 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { socket.on('posts.upvote', function(data) { if (data && data.pid) { var post = $('li[data-pid="' + data.pid + '"]'), - upvote = post.find('.upvote'), - downvote = post.find('.downvote'), - votes = post.find('.votes'); + upvote = post.find('.upvote'); - upvote.addClass('btn-primary'); - downvote.removeClass('btn-primary'); - votes.attr('data-vote-status', 'upvoted'); + upvote.addClass('btn-primary upvoted'); } }); socket.on('posts.downvote', function(data) { if (data && data.pid) { var post = $('li[data-pid="' + data.pid + '"]'), - upvote = post.find('.upvote'), - downvote = post.find('.downvote'), - votes = post.find('.votes'), - 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'); + downvote = post.find('.downvote'); + + downvote.addClass('btn-primary downvoted'); } }); @@ -832,22 +821,10 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { if (data && data.pid) { var post = $('li[data-pid="' + data.pid + '"]'), upvote = post.find('.upvote'), - 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'); - } + downvote = post.find('.downvote'); - votes.html(currentVotes) - .attr('data-votes', currentVotes) - .attr('data-vote-status', ''); + upvote.removeClass('btn-primary upvoted'); + downvote.removeClass('btn-primary downvoted'); } }); @@ -903,8 +880,8 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { currentVotes += value; reputation += value; - reputationElements.html(currentVotes).attr('data-votes', currentVotes); - reputationElements.html(reputation); + votes.html(currentVotes).attr('data-votes', currentVotes); + reputationElements.html(reputation).attr('data-reputation', reputation); } function set_locked_state(locked, alert) { diff --git a/public/templates/topic.tpl b/public/templates/topic.tpl index 3837d6c420..4506f5d1d9 100644 --- a/public/templates/topic.tpl +++ b/public/templates/topic.tpl @@ -72,7 +72,7 @@ - - + + + diff --git a/src/favourites.js b/src/favourites.js index 0e8a310109..f638f4728b 100644 --- a/src/favourites.js +++ b/src/favourites.js @@ -8,74 +8,109 @@ var async = require('async'), (function (Favourites) { "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'); if (uid === 0) { return socket.emit('event:alert', { alert_id: 'post_vote', - title: '[[vote.not_logged_in.title]]', - message: '[[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]]', + title: '[[topic:vote.not_logged_in.title]]', + message: '[[topic:vote.not_logged_in.message]]', type: 'danger', timeout: 5000 }); } - //Favourites.hasVoted(type, pid, uid, function (err, hasVoted) { - // if (!hasVoted) { - var notType = (type === 'upvote' ? 'downvote' : 'upvote'); + posts.getPostFields(pid, ['uid', 'timestamp'], function (err, postData) { + if (uid === parseInt(postData.uid, 10)) { + 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); - db[type === 'upvote' ? 'sortedSetRemove' : 'sortedSetAdd']('uid:' + uid + ':downvote', postData.timestamp, pid); + if (callback) { + callback(false); + } + return false; + } - user[type === 'upvote' ? 'incrementUserFieldBy' : 'decrementUserFieldBy'](postData.uid, 'reputation', 1, function (err, newreputation) { - db.sortedSetAdd('users:reputation', newreputation, postData.uid); - }); + db[type === 'upvote' || !unvote ? 'sortedSetAdd' : 'sortedSetRemove']('uid:' + uid + ':upvote', postData.timestamp, pid); + db[type === 'upvote' || unvote ? 'sortedSetRemove' : 'sortedSetAdd']('uid:' + uid + ':downvote', postData.timestamp, pid); - db.setAdd('pid:' + pid + ':' + type, uid, function(err) { - db.setCount('pid:' + pid + ':' + type, function(err, count) { - posts.setPostField(pid, type, count); - }); - }); + user[type === 'upvote' ? 'incrementUserFieldBy' : 'decrementUserFieldBy'](postData.uid, 'reputation', 1, function (err, newreputation) { + db.sortedSetAdd('users:reputation', newreputation, postData.uid); + }); - db.setRemove('pid:' + pid + ':' + notType, uid, function(err) { - db.setCount('pid:' + pid + ':' + notType, function(err, count) { - posts.setPostField(pid, notType, count); - }); + if (room_id) { + websockets.in(room_id).emit('event:' + (type === 'upvote' ? 'rep_up' : 'rep_down'), { + uid: postData.uid, + pid: pid }); + } - if (room_id) { - websockets.in(room_id).emit('event:' + (type === 'upvote' ? 'rep_up' : 'rep_down'), { - uid: postData.uid, - pid: pid - }); + socket.emit('posts.' + (unvote ? 'unvote' : type), { + pid: pid + }); + + adjustPostVotes(pid, uid, type, unvote, function() { + if (callback) { + callback(); } + }); + }); + } - socket.emit('posts.' + type, { - pid: pid + function adjustPostVotes(pid, uid, type, unvote, callback) { + 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.unvote(pid, room_id, uid, socket, function(err, postData) { - vote('upvote', postData, pid, room_id, uid, socket); + Favourites.unvote(pid, room_id, uid, socket, function(err) { + vote('upvote', false, pid, room_id, uid, socket); }); }; Favourites.downvote = function(pid, room_id, uid, socket) { - Favourites.unvote(pid, room_id, uid, socket, function(err, postData) { - vote('downvote', postData, pid, room_id, uid, socket); + Favourites.unvote(pid, room_id, uid, socket, function(err) { + vote('downvote', false, pid, room_id, uid, socket); }); }; @@ -83,79 +118,49 @@ var async = require('async'), var websockets = require('./socket.io'); Favourites.hasVoted(pid, uid, function(err, voteStatus) { - posts.getPostFields(pid, ['uid', 'timestamp'], function (err, postData) { - if (voteStatus === 'upvoted') { - db.sortedSetRemove('uid:' + uid + ':upvote'); - - 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 (voteStatus.upvoted || voteStatus.downvoted) { + socket.emit('posts.unvote', { + pid: pid + }); - if (room_id) { - websockets.in(room_id).emit('event:rep_up', { - uid: postData.uid, - pid: pid - }); + return vote(voteStatus.upvoted ? 'downvote' : 'upvote', true, pid, room_id, uid, socket, function() { + if (callback) { + callback(err); } - } - - if (voteStatus) { - socket.emit('posts.unvote', { - pid: pid - }); - } + }); + } - if (callback) { - callback(err, postData); - } - }); + if (callback) { + callback(err); + } }); - }; Favourites.hasVoted = function(pid, uid, callback) { async.parallel({ - upvoted: function(each) { - db.isSetMember('pid:' + pid + ':upvote', uid, each); + upvoted: function(next) { + db.isSetMember('pid:' + pid + ':upvote', uid, next); }, - downvoted: function(each) { - db.isSetMember('pid:' + pid + ':downvote', uid, each); + downvoted: function(next) { + db.isSetMember('pid:' + pid + ':downvote', uid, next); } }, function(err, results) { - var voteStatus = ""; + callback(err, results) + }); + }; - if (results.upvoted) { - voteStatus = "upvoted"; - } else if (results.downvoted) { - voteStatus = "downvoted"; - } + Favourites.getVoteStatusByPostIDs = function(pids, uid, callback) { + var data = {}; + + 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); }); }; diff --git a/src/topics.js b/src/topics.js index 479c4401a4..5545826e51 100644 --- a/src/topics.js +++ b/src/topics.js @@ -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 iterator(post, callback) { 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) { return callback(err); } var fav_data = results[0], - privileges = results[2]; + privileges = results[2], + voteStatus = results[3]; for (var i = 0; i < postData.length; ++i) { var pid = postData[i].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_move_tools = privileges[pid].move; if(parseInt(postData[i].deleted, 10) === 1 && !privileges[pid].view_deleted) {