From f2760f91689b99719b695ad4f789d25292e18668 Mon Sep 17 00:00:00 2001 From: Sacha Greif Date: Wed, 24 Dec 2014 10:13:48 +0900 Subject: [PATCH] refactoring comment submit method --- client/views/comments/comment_form.js | 45 ++++- collections/comments.js | 173 ++++++++++++------ collections/posts.js | 19 +- .../lib/notifications.js | 2 +- 4 files changed, 169 insertions(+), 70 deletions(-) diff --git a/client/views/comments/comment_form.js b/client/views/comments/comment_form.js index 3ffaf0c00..0487fd4ee 100644 --- a/client/views/comments/comment_form.js +++ b/client/views/comments/comment_form.js @@ -6,39 +6,72 @@ Template[getTemplate('comment_form')].helpers({ Template[getTemplate('comment_form')].events({ 'submit form': function(e, instance){ - var $commentForm = instance.$('#comment'); + e.preventDefault(); $(e.target).addClass('disabled'); clearSeenMessages(); - var content = $commentForm.val(); + + var comment = {}; + var $commentForm = instance.$('#comment'); + var body = $commentForm.val(); + if(getCurrentTemplate() == 'comment_reply'){ + // child comment + + comment = { + postId: parentComment.postId, + parentCommentId: parentComment._id, + body: body + }; + var parentComment = this.comment; - Meteor.call('comment', parentComment.postId, parentComment._id, content, function(error, newComment){ - if(error){ + + Meteor.call('submitComment', comment, function(error, newComment){ + + if (error) { + console.log(error); flashMessage(error.reason, "error"); - }else{ + + } else { + trackEvent("newComment", newComment); + Router.go('post_page_comment', { _id: parentComment.postId, commentId: newComment._id }); + } + }); + }else{ + // root comment var post = postObject; - Meteor.call('comment', post._id, null, content, function(error, newComment){ + comment = { + postId: post._id, + body: body + } + + Meteor.call('submitComment', comment, function(error, newComment){ + if(error){ + console.log(error); flashMessage(error.reason, "error"); + }else{ + trackEvent("newComment", newComment); Session.set('scrollToCommentId', newComment._id); $commentForm.val(''); + } + }); } } diff --git a/collections/comments.js b/collections/comments.js index eb61ee285..468191fa3 100644 --- a/collections/comments.js +++ b/collections/comments.js @@ -87,6 +87,10 @@ Comments.allow({ remove: canEditById }); +// ------------------------------------------------------------------------------------------- // +// ------------------------------------------ Hooks ------------------------------------------ // +// ------------------------------------------------------------------------------------------- // + Comments.before.insert(function (userId, doc) { if(Meteor.isServer) doc.htmlBody = sanitize(marked(doc.body)); @@ -100,76 +104,133 @@ Comments.before.update(function (userId, doc, fieldNames, modifier, options) { } }); +commentAfterSubmitMethodCallbacks.push(function (comment) { + + var userId = comment.userId, + commentAuthor = Meteor.users.findOne(userId); + + // increment comment count + Meteor.users.update({_id: userId}, { + $inc: {'commentCount': 1} + }); + + // update post + Posts.update(comment.postId, { + $inc: {commentCount: 1}, + $set: {lastCommentedAt: new Date()}, + $addToSet: {commenters: userId} + }); + + // upvote comment + Meteor.call('upvoteComment', comment); + +}); + +// ------------------------------------------------------------------------------------------- // +// -------------------------------------- Submit Comment ------------------------------------- // +// ------------------------------------------------------------------------------------------- // + +submitComment = function (comment) { + + var userId = comment.userId; // at this stage, a userId is expected + + // ------------------------------ Checks ------------------------------ // + + // Don't allow empty comments + if (!comment.body) + throw new Meteor.Error(704,i18n.t('your_comment_is_empty')); + + // ------------------------------ Properties ------------------------------ // + + var defaultProperties = { + createdAt: new Date(), + postedAt: new Date(), + upvotes: 0, + downvotes: 0, + baseScore: 0, + score: 0, + author: getDisplayNameById(userId) + }; + + comment = _.extend(defaultProperties, comment); + + // ------------------------------ Callbacks ------------------------------ // + + // run all post submit server callbacks on comment object successively + comment = commentSubmitMethodCallbacks.reduce(function(result, currentFunction) { + return currentFunction(result); + }, comment); + + // -------------------------------- Insert -------------------------------- // + + comment._id = Comments.insert(comment); + + // --------------------- Server-side Async Callbacks --------------------- // + + // run all post submit server callbacks on comment object successively + if (Meteor.isServer) { + Meteor.setTimeout(function () { // use setTimeout to avoid holding up client + comment = commentAfterSubmitMethodCallbacks.reduce(function(result, currentFunction) { + return currentFunction(result); + }, comment); + }, 1); + } + + return comment; +} + +// ------------------------------------------------------------------------------------------- // +// ----------------------------------------- Methods ----------------------------------------- // +// ------------------------------------------------------------------------------------------- // + Meteor.methods({ - comment: function(postId, parentCommentId, text){ + submitComment: function(comment){ + + // required properties: + // postId + // content + + // optional properties: + // parentCommentId + var user = Meteor.user(), - post = Posts.findOne(postId), - postUser = Meteor.users.findOne(post.userId), - timeSinceLastComment = timeSinceLast(user, Comments), - commentInterval = Math.abs(parseInt(getSetting('commentInterval',15))), - now = new Date(); + hasAdminRights = isAdmin(user); + + // ------------------------------ Checks ------------------------------ // // check that user can comment if (!user || !canComment(user)) throw new Meteor.Error(i18n.t('you_need_to_login_or_be_invited_to_post_new_comments')); - // check that user waits more than 15 seconds between comments - if(!this.isSimulation && (timeSinceLastComment < commentInterval)) - throw new Meteor.Error(704, i18n.t('please_wait')+(commentInterval-timeSinceLastComment)+i18n.t('seconds_before_commenting_again')); - - // Don't allow empty comments - if (!text) - throw new Meteor.Error(704,i18n.t('your_comment_is_empty')); - - var comment = { - postId: postId, - body: text, - userId: user._id, - createdAt: now, - postedAt: now, - upvotes: 0, - downvotes: 0, - baseScore: 0, - score: 0, - author: getDisplayName(user) - }; + // ------------------------------ Rate Limiting ------------------------------ // - if(parentCommentId) - comment.parentCommentId = parentCommentId; + if (!hasAdminRights) { + + var timeSinceLastComment = timeSinceLast(user, Comments), + commentInterval = Math.abs(parseInt(getSetting('commentInterval',15))); + // check that user waits more than 15 seconds between comments + if((timeSinceLastComment < commentInterval)) + throw new Meteor.Error(704, i18n.t('please_wait')+(commentInterval-timeSinceLastComment)+i18n.t('seconds_before_commenting_again')); + + } - // ------------------------------ Callbacks ------------------------------ // + // ------------------------------ Properties ------------------------------ // - // run all post submit server callbacks on comment object successively - comment = commentSubmitMethodCallbacks.reduce(function(result, currentFunction) { - return currentFunction(result); - }, comment); + // admin-only properties + // userId - // -------------------------------- Insert ------------------------------- // + // if user is not admin, clear restricted properties + if (!hasAdminRights) { + delete post.userId; + } - comment._id = Comments.insert(comment); + // if no userId has been set, default to current user id + if (!comment.userId) { + comment.userId = user._id + } - // ------------------------------ Callbacks ------------------------------ // - - // run all post submit server callbacks on comment object successively - comment = commentAfterSubmitMethodCallbacks.reduce(function(result, currentFunction) { - return currentFunction(result); - }, comment); - - // increment comment count - Meteor.users.update({_id: user._id}, { - $inc: {'commentCount': 1} - }); - - Posts.update(postId, { - $inc: {commentCount: 1}, - $set: {lastCommentedAt: now}, - $addToSet: {commenters: user._id} - }); - - Meteor.call('upvoteComment', comment); - - return comment; + return submitComment(comment); }, removeComment: function(commentId){ var comment = Comments.findOne(commentId); diff --git a/collections/posts.js b/collections/posts.js index 9bec2e0ca..df4fef435 100644 --- a/collections/posts.js +++ b/collections/posts.js @@ -291,6 +291,7 @@ checkForPostsWithSameUrl = function (url) { currentPost = function () { return Posts.findOne(Router.current().data()._id); } + // ------------------------------------------------------------------------------------------- // // ------------------------------------------ Hooks ------------------------------------------ // // ------------------------------------------------------------------------------------------- // @@ -329,6 +330,7 @@ submitPost = function (post) { var userId = post.userId, // at this stage, a userId is expected user = Meteor.users.findOne(userId); + // ------------------------------ Checks ------------------------------ // // check that a title was provided @@ -369,12 +371,12 @@ submitPost = function (post) { return currentFunction(result); }, post); - // ------------------------------ Insert ------------------------------ // + // -------------------------------- Insert ------------------------------- // // console.log(post) post._id = Posts.insert(post); - // ------------------------------ Server-Side Callbacks ------------------------------ // + // --------------------- Server-Side Async Callbacks --------------------- // if (Meteor.isServer) { Meteor.setTimeout(function () { // use setTimeout to avoid holding up client @@ -382,7 +384,8 @@ submitPost = function (post) { post = postAfterSubmitMethodCallbacks.reduce(function(result, currentFunction) { return currentFunction(result); }, post); - }, 1);} + }, 1); + } return post; } @@ -419,19 +422,21 @@ Meteor.methods({ // --------------------------- Rate Limiting -------------------------- // - var timeSinceLastPost=timeSinceLast(user, Posts), + if(!hasAdminRights){ + + var timeSinceLastPost=timeSinceLast(user, Posts), numberOfPostsInPast24Hours=numberOfItemsInPast24Hours(user, Posts), postInterval = Math.abs(parseInt(getSetting('postInterval', 30))), maxPostsPer24Hours = Math.abs(parseInt(getSetting('maxPostsPerDay', 30))); - if(!hasAdminRights){ // check that user waits more than X seconds between posts - if(!this.isSimulation && timeSinceLastPost < postInterval) + if(timeSinceLastPost < postInterval) throw new Meteor.Error(604, i18n.t('please_wait')+(postInterval-timeSinceLastPost)+i18n.t('seconds_before_posting_again')); // check that the user doesn't post more than Y posts per day - if(!this.isSimulation && numberOfPostsInPast24Hours > maxPostsPer24Hours) + if(numberOfPostsInPast24Hours > maxPostsPer24Hours) throw new Meteor.Error(605, i18n.t('sorry_you_cannot_submit_more_than')+maxPostsPer24Hours+i18n.t('posts_per_day')); + } // ------------------------------ Properties ------------------------------ // diff --git a/packages/telescope-notifications/lib/notifications.js b/packages/telescope-notifications/lib/notifications.js index 460cd78cb..c550a6971 100644 --- a/packages/telescope-notifications/lib/notifications.js +++ b/packages/telescope-notifications/lib/notifications.js @@ -14,7 +14,7 @@ commentAfterSubmitMethodCallbacks.push(function (comment) { if(Meteor.isServer){ var parentCommentId = comment.parentCommentId; - var user = Meteor.user(); + var user = Meteor.users.findOne(comment.userId); var post = Posts.findOne(comment.postId); var postUser = Meteor.users.findOne(post.userId);