mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-15 10:16:12 +01:00
upvoting / downvoting complete
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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 = post.find('.downvote');
|
||||
|
||||
downvote.addClass('btn-primary');
|
||||
upvote.removeClass('btn-primary');
|
||||
votes.html(currentVotes)
|
||||
.attr('data-votes', currentVotes)
|
||||
.attr('data-vote-status', 'downvoted');
|
||||
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);
|
||||
downvote = post.find('.downvote');
|
||||
|
||||
if (status === 'upvoted') {
|
||||
currentVotes --;
|
||||
upvote.removeClass('btn-primary');
|
||||
} else if (status === 'downvoted') {
|
||||
currentVotes ++;
|
||||
downvote.removeClass('btn-primary');
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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 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="post_rep_{posts.pid}">{posts.favourited} </span>
|
||||
<span class="post_rep_{posts.pid}">{posts.reputation} </span>
|
||||
<!-- IF posts.favourited -->
|
||||
<i class="fa fa-star"></i>
|
||||
<!-- ELSE -->
|
||||
@@ -82,9 +82,9 @@
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<button class="upvote btn btn-sm btn-default"><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="downvote btn btn-sm btn-default"><i class="fa fa-chevron-down"></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-votes="{posts.votes}" disabled>{posts.votes}</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>
|
||||
|
||||
<!-- IF privileges.write -->
|
||||
|
||||
@@ -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');
|
||||
|
||||
db[type === 'upvote' ? 'sortedSetAdd' : 'sortedSetRemove']('uid:' + uid + ':upvote', postData.timestamp, pid);
|
||||
db[type === 'upvote' ? 'sortedSetRemove' : 'sortedSetAdd']('uid:' + uid + ':downvote', postData.timestamp, pid);
|
||||
|
||||
|
||||
user[type === 'upvote' ? 'incrementUserFieldBy' : 'decrementUserFieldBy'](postData.uid, 'reputation', 1, function (err, newreputation) {
|
||||
db.sortedSetAdd('users:reputation', newreputation, postData.uid);
|
||||
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.setAdd('pid:' + pid + ':' + type, uid, function(err) {
|
||||
db.setCount('pid:' + pid + ':' + type, function(err, count) {
|
||||
posts.setPostField(pid, type, count);
|
||||
});
|
||||
});
|
||||
|
||||
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 (callback) {
|
||||
callback(false);
|
||||
}
|
||||
|
||||
socket.emit('posts.' + type, {
|
||||
return false;
|
||||
}
|
||||
|
||||
db[type === 'upvote' || !unvote ? 'sortedSetAdd' : 'sortedSetRemove']('uid:' + uid + ':upvote', postData.timestamp, pid);
|
||||
db[type === 'upvote' || unvote ? 'sortedSetRemove' : 'sortedSetAdd']('uid:' + uid + ':downvote', postData.timestamp, pid);
|
||||
|
||||
user[type === 'upvote' ? 'incrementUserFieldBy' : 'decrementUserFieldBy'](postData.uid, 'reputation', 1, function (err, newreputation) {
|
||||
db.sortedSetAdd('users:reputation', newreputation, postData.uid);
|
||||
});
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
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');
|
||||
if (voteStatus.upvoted || voteStatus.downvoted) {
|
||||
socket.emit('posts.unvote', {
|
||||
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
|
||||
});
|
||||
return vote(voteStatus.upvoted ? 'downvote' : 'upvote', true, pid, room_id, uid, socket, function() {
|
||||
if (callback) {
|
||||
callback(err);
|
||||
}
|
||||
} 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) {
|
||||
websockets.in(room_id).emit('event:rep_up', {
|
||||
uid: postData.uid,
|
||||
pid: pid
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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 = {};
|
||||
|
||||
callback(err, voteStatus)
|
||||
function iterator(pid, next) {
|
||||
Favourites.hasVoted(pid, uid, function(err, voteStatus) {
|
||||
data[pid] = voteStatus;
|
||||
next()
|
||||
});
|
||||
}
|
||||
|
||||
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 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) {
|
||||
|
||||
Reference in New Issue
Block a user