2016-08-25 09:49:59 +09:00
|
|
|
import Users from 'meteor/nova:users';
|
2016-11-29 14:08:24 +01:00
|
|
|
import { hasUpvoted, hasDownvoted } from './helpers.js';
|
2016-12-13 11:40:24 +09:00
|
|
|
import { runCallbacks, runCallbacksAsync } from 'meteor/nova:core';
|
2017-01-22 10:12:05 +09:00
|
|
|
import update from 'immutability-helper';
|
2016-07-19 18:08:53 +09:00
|
|
|
|
2016-01-02 18:41:45 +01:00
|
|
|
// The equation to determine voting power. Defaults to returning 1 for everybody
|
2016-12-12 16:43:23 +09:00
|
|
|
export const getVotePower = function (user) {
|
2016-01-02 18:41:45 +01:00
|
|
|
return 1;
|
2014-12-20 17:34:15 +09:00
|
|
|
};
|
|
|
|
|
2017-01-22 10:12:05 +09:00
|
|
|
const keepVoteProperties = item => _.pick(item, '__typename', '_id', 'upvoters', 'downvoters', 'upvotes', 'downvotes', 'baseScore');
|
|
|
|
|
2017-01-18 10:19:23 +09:00
|
|
|
/*
|
|
|
|
|
|
|
|
- Simulation mode: runs all the operation and returns an objects without affecting the db.
|
|
|
|
- Regular mode: same, but updates the db too.
|
|
|
|
|
|
|
|
*/
|
|
|
|
export const operateOnItem = function (collection, originalItem, user, operation, isSimulation = false, context = 'edit') {
|
2015-07-10 11:05:13 +09:00
|
|
|
|
2015-03-10 21:05:29 -06:00
|
|
|
user = typeof user === "undefined" ? Meteor.user() : user;
|
2016-01-03 18:18:09 +01:00
|
|
|
|
2017-01-18 10:19:23 +09:00
|
|
|
let item = {
|
|
|
|
upvotes: 0,
|
|
|
|
downvotes: 0,
|
|
|
|
upvoters: [],
|
|
|
|
downvoters: [],
|
|
|
|
baseScore: 0,
|
|
|
|
...originalItem,
|
|
|
|
}; // we do not want to affect the original item directly
|
2016-11-03 14:07:58 +09:00
|
|
|
|
2016-12-12 16:43:23 +09:00
|
|
|
var votePower = getVotePower(user);
|
2016-11-29 18:52:13 +09:00
|
|
|
var hasUpvotedItem = hasUpvoted(user, item);
|
|
|
|
var hasDownvotedItem = hasDownvoted(user, item);
|
2017-01-22 10:12:05 +09:00
|
|
|
var modifier = {};
|
2016-01-03 18:18:09 +01:00
|
|
|
|
2017-01-09 15:42:24 +09:00
|
|
|
// console.log('// operateOnItem')
|
2017-01-18 10:19:23 +09:00
|
|
|
// console.log('isSimulation: ',isSimulation)
|
|
|
|
// console.log('context: ',context)
|
|
|
|
// console.log('collection: ',collection._name)
|
|
|
|
// console.log('operation: ',operation)
|
|
|
|
// console.log('item: ',item)
|
|
|
|
// console.log('user: ',user)
|
2016-11-02 13:29:43 +01:00
|
|
|
|
2016-12-12 11:17:13 +00:00
|
|
|
const collectionName = collection._name;
|
2016-11-02 13:29:43 +01:00
|
|
|
|
2016-12-12 11:17:13 +00:00
|
|
|
// make sure item and user are defined, and user can perform the operation
|
2016-11-02 13:29:43 +01:00
|
|
|
if (
|
|
|
|
!item ||
|
|
|
|
!user ||
|
|
|
|
!Users.canDo(user, `${collectionName}.${operation}`) ||
|
|
|
|
operation === "upvote" && hasUpvotedItem ||
|
|
|
|
operation === "downvote" && hasDownvotedItem ||
|
|
|
|
operation === "cancelUpvote" && !hasUpvotedItem ||
|
|
|
|
operation === "cancelDownvote" && !hasDownvotedItem
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-11-02 16:31:15 +09:00
|
|
|
|
2017-01-18 10:19:23 +09:00
|
|
|
const voter = isSimulation ? {__typename: "User", _id: user._id} : user._id;
|
2016-11-02 16:31:15 +09:00
|
|
|
|
2016-11-02 13:29:43 +01:00
|
|
|
// ------------------------------ Sync Callbacks ------------------------------ //
|
2016-11-02 16:31:15 +09:00
|
|
|
|
2016-12-13 11:40:24 +09:00
|
|
|
item = runCallbacks(operation, item, user);
|
2016-11-02 16:31:15 +09:00
|
|
|
|
2016-11-02 13:29:43 +01:00
|
|
|
switch (operation) {
|
2016-11-02 16:31:15 +09:00
|
|
|
|
2016-11-02 13:29:43 +01:00
|
|
|
case "upvote":
|
|
|
|
if (hasDownvotedItem) {
|
2017-01-18 10:19:23 +09:00
|
|
|
operateOnItem(collection, item, user, "cancelDownvote", isSimulation, context);
|
2016-11-02 13:29:43 +01:00
|
|
|
}
|
|
|
|
|
2017-01-22 10:12:05 +09:00
|
|
|
item = update(item, {
|
|
|
|
upvoters: {$push: [voter]},
|
|
|
|
upvotes: {$set: item.upvotes + 1},
|
|
|
|
baseScore: {$set: item.baseScore + votePower},
|
|
|
|
});
|
2016-11-02 13:29:43 +01:00
|
|
|
|
|
|
|
if (!isSimulation) {
|
2017-01-22 10:12:05 +09:00
|
|
|
modifier = {
|
2016-11-02 16:31:15 +09:00
|
|
|
$addToSet: {upvoters: user._id},
|
|
|
|
$inc: {upvotes: 1, baseScore: votePower}
|
|
|
|
}
|
2016-11-02 13:29:43 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "downvote":
|
|
|
|
if (hasUpvotedItem) {
|
2017-01-18 10:19:23 +09:00
|
|
|
operateOnItem(collection, item, user, "cancelUpvote", isSimulation, context);
|
2016-11-02 13:29:43 +01:00
|
|
|
}
|
|
|
|
|
2017-01-22 10:12:05 +09:00
|
|
|
item = update(item, {
|
|
|
|
downvoters: {$push: [voter]},
|
|
|
|
downvotes: {$set: item.downvotes + 1},
|
|
|
|
baseScore: {$set: item.baseScore - votePower},
|
|
|
|
});
|
2016-11-02 13:29:43 +01:00
|
|
|
|
|
|
|
if (!isSimulation) {
|
2017-01-22 10:12:05 +09:00
|
|
|
modifier = {
|
2016-11-02 16:31:15 +09:00
|
|
|
$addToSet: {downvoters: user._id},
|
|
|
|
$inc: {downvotes: 1, baseScore: -votePower}
|
|
|
|
}
|
2016-11-02 13:29:43 +01:00
|
|
|
}
|
|
|
|
break;
|
2016-11-02 16:31:15 +09:00
|
|
|
|
2016-11-02 13:29:43 +01:00
|
|
|
case "cancelUpvote":
|
2017-01-22 10:12:05 +09:00
|
|
|
item = update(item, {
|
|
|
|
upvoters: {$set: item.upvoters.filter(u => u._id !== user._id)},
|
|
|
|
upvotes: {$set: item.upvotes - 1},
|
|
|
|
baseScore: {$set: item.baseScore - votePower},
|
|
|
|
});
|
|
|
|
|
2016-11-02 13:29:43 +01:00
|
|
|
if (!isSimulation) {
|
2017-01-22 10:12:05 +09:00
|
|
|
modifier = {
|
2016-11-02 16:31:15 +09:00
|
|
|
$pull: {upvoters: user._id},
|
|
|
|
$inc: {upvotes: -1, baseScore: -votePower}
|
|
|
|
};
|
2016-11-02 13:29:43 +01:00
|
|
|
}
|
|
|
|
break;
|
2016-11-02 16:31:15 +09:00
|
|
|
|
2016-11-02 13:29:43 +01:00
|
|
|
case "cancelDownvote":
|
2017-01-22 10:12:05 +09:00
|
|
|
|
|
|
|
item = update(item, {
|
|
|
|
downvoters: {$set: item.downvoters.filter(u => u._id !== user._id)},
|
|
|
|
downvotes: {$set: item.upvotes - 1},
|
|
|
|
baseScore: {$set: item.baseScore + votePower},
|
|
|
|
});
|
2016-11-02 13:29:43 +01:00
|
|
|
|
|
|
|
if (!isSimulation) {
|
2017-01-22 10:12:05 +09:00
|
|
|
modifier = {
|
2016-11-02 16:31:15 +09:00
|
|
|
$pull: {downvoters: user._id},
|
|
|
|
$inc: {downvotes: -1, baseScore: votePower}
|
|
|
|
};
|
2016-11-02 13:29:43 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-11-02 16:31:15 +09:00
|
|
|
|
2017-01-24 11:58:57 +01:00
|
|
|
if (!isSimulation && context === 'edit') {
|
|
|
|
|
|
|
|
modifier["$set"] = {inactive: false};
|
|
|
|
collection.update({_id: item._id}, modifier);
|
2017-01-18 10:19:23 +09:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------- Server-Side Async Callbacks --------------------- //
|
2017-01-24 11:58:57 +01:00
|
|
|
// note: the upvote async callbacks on a "new" context (posts.new, comments.new) are
|
|
|
|
// triggered once the insert has been done, see server/callbacks.js
|
2017-01-18 10:19:23 +09:00
|
|
|
runCallbacksAsync(operation+".async", item, user, collection, operation, context);
|
|
|
|
|
2014-12-20 17:34:15 +09:00
|
|
|
}
|
2016-11-02 13:29:43 +01:00
|
|
|
|
2017-01-22 10:12:05 +09:00
|
|
|
const voteResult = item;
|
2017-01-09 15:42:24 +09:00
|
|
|
|
2016-11-02 13:29:43 +01:00
|
|
|
// if (isSimulation) {
|
2017-01-09 15:42:24 +09:00
|
|
|
// console.log('item from apollo store', voteResult);
|
2016-11-02 13:29:43 +01:00
|
|
|
// } else {
|
2017-01-09 15:42:24 +09:00
|
|
|
// console.log('item from mongo db', voteResult);
|
2016-11-02 13:29:43 +01:00
|
|
|
// }
|
|
|
|
|
2017-01-09 15:42:24 +09:00
|
|
|
return voteResult;
|
2016-12-12 11:17:13 +00:00
|
|
|
};
|