Vulcan/packages/vulcan-voting/lib/modules/vote.js

144 lines
4.3 KiB
JavaScript
Raw Normal View History

2017-03-23 16:27:59 +09:00
import Users from 'meteor/vulcan:users';
2016-11-29 14:08:24 +01:00
import { hasUpvoted, hasDownvoted } from './helpers.js';
2017-09-25 22:09:09 +02:00
import { runCallbacks, runCallbacksAsync, registerSetting, getSetting } from 'meteor/vulcan:core';
import update from 'immutability-helper';
2017-09-25 22:09:09 +02:00
import Votes from './votes/collection.js';
registerSetting('voting.maxVotes', 1, 'How many times a user can vote on the same document');
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
2017-09-25 22:09:09 +02:00
export const getVotePower = (user, operationType) => {
return operationType === 'upvote' ? 1 : -1;
};
const keepVoteProperties = item => _.pick(item, '__typename', '_id', 'upvoters', 'downvoters', 'upvotes', 'downvotes', 'baseScore');
/*
Runs all the operation and returns an objects without affecting the db.
*/
2017-09-25 22:09:09 +02:00
export const voteOnItem = function (collection, document, user, operationType = 'upvote') {
2017-09-25 22:09:09 +02:00
const collectionName = collection.options.collectionName;
let result = {};
2017-09-25 22:09:09 +02:00
// make sure item and user are defined
if (!document || !user) {
throw new Error(`Cannot perform operation '${collectionName}.${operationType}'`);
}
2017-01-26 13:09:27 +09:00
/*
2017-09-25 22:09:09 +02:00
First, handle vote cancellation.
Just remove last vote and subtract its power from the base score
2017-01-26 13:09:27 +09:00
*/
2017-09-25 22:09:09 +02:00
if (operationType === 'cancelVote') {
// create a "lite" version of the document that only contains relevant fields
const newDocument = {
_id: document._id,
currentUserVotes: document.currentUserVotes || [],
// voters: document.voters || [],
baseScore: document.baseScore || 0,
__typename: collection.options.typeName,
}; // we do not want to affect the original item directly
// if document has votes
if (newDocument.currentUserVotes.length) {
// remove one vote
const cancelledVote = _.last(newDocument.currentUserVotes);
newDocument.currentUserVotes = _.initial(newDocument.currentUserVotes);
result.vote = cancelledVote;
// update base score
newDocument.baseScore -= cancelledVote.power;
}
// console.log('// voteOnItem')
// console.log('collection: ', collectionName)
// console.log('document:', document)
// console.log('newDocument:', newDocument)
result.document = newDocument;
} else {
/*
2017-01-26 13:09:27 +09:00
2017-09-25 22:09:09 +02:00
Next, handle all other vote types (upvote, downvote, etc.)
*/
2017-09-25 22:09:09 +02:00
const power = getVotePower(user, operationType);
// create vote object
const vote = {
_id: Random.id(),
itemId: document._id,
collectionName,
userId: user._id,
voteType: operationType,
power,
votedAt: new Date(),
__typename: 'Vote'
};
// create a "lite" version of the document that only contains relevant fields
const currentUserVotes = document.currentUserVotes || [];
const newDocument = {
_id: document._id,
currentUserVotes: [...currentUserVotes, vote],
// voters: document.voters || [],
baseScore: document.baseScore || 0,
__typename: collection.options.typeName,
}; // we do not want to affect the original item directly
// update score
newDocument.baseScore += power;
// console.log('// voteOnItem')
// console.log('collection: ', collectionName)
// console.log('document:', document)
// console.log('newDocument:', newDocument)
// make sure item and user are defined, and user can perform the operation
if (newDocument.currentUserVotes.length > getSetting('voting.maxVotes')) {
throw new Error(`Cannot perform operation '${collectionName}.${operationType}'`);
}
// ------------------------------ Sync Callbacks ------------------------------ //
// item = runCallbacks(operation, item, user, operation, isClient);
result = {
document: newDocument,
vote
};
}
2017-09-25 22:09:09 +02:00
return result;
2017-09-25 22:09:09 +02:00
};
2017-09-25 22:09:09 +02:00
export const cancelVote = function (collection, document, user, voteType = 'vote') {
};
/*
Call operateOnItem, update the db with the result, run callbacks.
*/
2017-09-25 22:09:09 +02:00
// export const mutateItem = function (collection, originalItem, user, operation) {
// const newItem = operateOnItem(collection, originalItem, user, operation, false);
// newItem.inactive = false;
2017-09-25 22:09:09 +02:00
// collection.update({_id: newItem._id}, newItem, {bypassCollection2:true});
2017-09-25 22:09:09 +02:00
// // --------------------- Server-Side Async Callbacks --------------------- //
// runCallbacksAsync(operation+'.async', newItem, user, collection, operation);
2017-09-25 22:09:09 +02:00
// return newItem;
// }