From 7cbcd06f12e6022f8e658738657a524513794dc1 Mon Sep 17 00:00:00 2001 From: brianjd Date: Wed, 17 Dec 2014 00:26:14 -0800 Subject: [PATCH 1/4] Update index.coffee shema -> schema --- src/index.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/index.coffee b/src/index.coffee index 2de165b..36238fe 100644 --- a/src/index.coffee +++ b/src/index.coffee @@ -5,7 +5,7 @@ Schema = mongoose.Schema module.exports = rattlePlugin = (schema, options) -> options = {} if (!options) - options.UserShemaName = 'User' if (!options.UserShemaName) + options.UserSchemaName = 'User' if (!options.UserSchemaName) options.UserIdType = Schema.Types.ObjectId if (!options.UserIdType) # Schema strategies for embedded comments @@ -14,15 +14,15 @@ module.exports = rattlePlugin = (schema, options) -> CommentSchema = new Schema message: type: String, required: true, max: 2000, min: 1 - creator: type: options.UserIdType, ref: options.UserShemaName, required: true - likes: [type: options.UserIdType, ref: options.UserShemaName] + creator: type: options.UserIdType, ref: options.UserSchemaName, required: true + likes: [type: options.UserIdType, ref: options.UserSchemaName] likesCount: type: Number, default: 0 dateCreation: type: Date dateUpdate: type: Date schema.add - creator: type: options.UserIdType, ref: options.UserShemaName, required: true - likes: [type: options.UserIdType, ref: options.UserShemaName] + creator: type: options.UserIdType, ref: options.UserShcemaName, required: true + likes: [type: options.UserIdType, ref: options.UserSchemaName] likesCount: type: Number, default: 0 comments: [CommentSchema] dateCreation: type: Date From e35014708ac41cb7baa2b9b48a57869e149f6f9e Mon Sep 17 00:00:00 2001 From: brianjd Date: Wed, 17 Dec 2014 00:27:29 -0800 Subject: [PATCH 2/4] Update thingy.coffee shema -> schema --- test/models/thingy.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/models/thingy.coffee b/test/models/thingy.coffee index 6d935b5..57af269 100644 --- a/test/models/thingy.coffee +++ b/test/models/thingy.coffee @@ -5,7 +5,7 @@ Schema = mongoose.Schema RattlePlugin = require '../../src/index' ThingySchema = new Schema() -ThingySchema.plugin RattlePlugin, UserShemaName: 'User' +ThingySchema.plugin RattlePlugin, UserSchemaName: 'User' Thingy = mongoose.model "Thingy", ThingySchema From 7ba66582e36ca1029df620afe8496c69c26d8fc8 Mon Sep 17 00:00:00 2001 From: brianjd Date: Tue, 13 Jan 2015 23:09:28 -0800 Subject: [PATCH 3/4] quick fix to work with keystonejs --- src/index.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/index.coffee b/src/index.coffee index 36238fe..c29b536 100644 --- a/src/index.coffee +++ b/src/index.coffee @@ -1,4 +1,6 @@ -mongoose = require 'mongoose' +keystone = require 'keystone' + +mongoose = keystone.mongoose moment = require 'moment' Schema = mongoose.Schema From 9dbd5e29a23c4f96334346beadf85eeaf3dcab32 Mon Sep 17 00:00:00 2001 From: brianjd Date: Tue, 13 Jan 2015 23:23:26 -0800 Subject: [PATCH 4/4] added compiled version to git --- .gitignore | 1 - lib/index.js | 450 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 450 insertions(+), 1 deletion(-) create mode 100644 lib/index.js diff --git a/.gitignore b/.gitignore index 491fc35..3c3629e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ node_modules -lib diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..5ec4eba --- /dev/null +++ b/lib/index.js @@ -0,0 +1,450 @@ +// Generated by CoffeeScript 1.5.0 +(function() { + var Schema, keystone, moment, mongoose, rattlePlugin; + + keystone = require('keystone'); + + mongoose = keystone.mongoose; + + moment = require('moment'); + + Schema = mongoose.Schema; + + module.exports = rattlePlugin = function(schema, options) { + var CommentSchema; + if (!options) { + options = {}; + } + if (!options.UserSchemaName) { + options.UserSchemaName = 'User'; + } + if (!options.UserIdType) { + options.UserIdType = Schema.Types.ObjectId; + } + CommentSchema = new Schema({ + message: { + type: String, + required: true, + max: 2000, + min: 1 + }, + creator: { + type: options.UserIdType, + ref: options.UserSchemaName, + required: true + }, + likes: [ + { + type: options.UserIdType, + ref: options.UserSchemaName + } + ], + likesCount: { + type: Number, + "default": 0 + }, + dateCreation: { + type: Date + }, + dateUpdate: { + type: Date + } + }); + schema.add({ + creator: { + type: options.UserIdType, + ref: options.UserShcemaName, + required: true + }, + likes: [ + { + type: options.UserIdType, + ref: options.UserSchemaName + } + ], + likesCount: { + type: Number, + "default": 0 + }, + comments: [CommentSchema], + dateCreation: { + type: Date + }, + dateUpdate: { + type: Date + } + }); + schema.pre("save", function(next) { + if (this.isNew) { + this.emit('objectCreation', this._id, this, this.creator); + this.dateCreation = moment().toDate(); + } + this.dateUpdate = moment().toDate(); + this.likesCount = this.likes.length; + return next(); + }); + CommentSchema.pre("save", function(next) { + this.likesCount = this.likes.length; + return next(); + }); + /** + * Get the list of rattles with limited amount of comments + * + * @param {Number} num - number of rattles + * @param {Number} maxLastComments - number max of comments retrieved + * @param {Object} options: + * fromCreationDate: creation date from which we retrieve rattles + * populate: list of fields to populate (example: 'fieldName' or 'fieldName1 fieldName2') + * @callback(err, rattles) + */ + + schema.statics.getList = function(num, maxLastComments, options, callback) { + var fields, query; + if ('function' === typeof options) { + callback = options; + options = {}; + } + query = {}; + if (options.fromCreationDate) { + query = { + dateCreation: { + $lt: options.fromCreationDate + } + }; + } + fields = { + text: 1, + creator: 1, + dateCreation: 1, + dateUpdate: 1, + likesCount: 1 + }; + if (maxLastComments > 0) { + fields.comments = { + $slice: [-maxLastComments, maxLastComments] + }; + } + query = this.find(query, fields).sort('-dateCreation').limit(num); + if (options.populate) { + query.populate(options.populate); + } + return query.exec(callback); + }; + /** + * Get the list of comments from a rattle id + * + * @param {Number} rattleId - id of the rattle + * @param {Number} num - number of comments required + * @param {Number} offsetFromEnd - offset from end of the list of comments + * @callback(err, comments) + */ + + schema.statics.getListOfCommentsById = function(rattleId, num, offsetFromEnd, callback) { + var self; + self = this; + return this.aggregate({ + $unwind: "$comments" + }, { + $group: { + _id: '', + count: { + $sum: 1 + } + } + }, function(err, summary) { + var diff, fields, limit, start; + start = -num - offsetFromEnd; + limit = num; + if (summary[0].count < Math.abs(start)) { + diff = Math.abs(start) - summary[0].count; + start += diff; + limit -= diff; + } + if (limit <= 0) { + return callback(null, []); + } + fields = { + comments: { + $slice: [start, limit] + } + }; + return self.findById(rattleId, fields).exec(function(err, rattle) { + if (err) { + return callback(err); + } + return callback(null, rattle.comments); + }); + }); + }; + /** + * Emit an event + * + * @param {String} eventName - event name + * @param {Number} targetId - object to which the event occured + * @param {Object} resource - object from which the event occured + * @param {Number} actor - actor who triggered the event + */ + + schema.methods.emit = function(eventName, targetId, resource, actor) { + if (options.emitter) { + return options.emitter.emit(eventName, targetId, resource, actor); + } + }; + /** + * Add a comment + * + * @param {Number} userId - user id adding comment + * @param {String} message - text message + * @callback(err, updatedRattle) + */ + + schema.methods.addComment = function(userId, message, callback) { + var comment, self; + self = this; + comment = { + message: message, + creator: userId, + dateCreation: moment().toDate(), + dateUpdate: moment().toDate() + }; + this.comments.push(comment); + this.save(function(err, updatedRattle) { + if (err !== null) { + return callback(err); + } + self.emit('addComment', comment._id, self, userId); + return callback(err, updatedRattle); + }); + return this.comments[this.comments.length - 1]._id; + }; + /** + * Add a reply to a comment + * + * @param {Number} userId - user id replying to the comment + * @param {Number} commentId - comment id on which the user reply + * @param {String} message - text message + * @callback(err, updatedRattle) + */ + + schema.methods.addReplyToComment = function(userId, commentId, message, callback) { + var comment, reply, self; + comment = this.getComment(commentId); + if (!comment) { + return callback(new Error('Comment doesn\'t exist')); + } + self = this; + reply = { + message: message, + creator: userId, + dateCreation: moment().toDate(), + dateUpdate: moment().toDate() + }; + comment.comments.push(reply); + this.save(function(err, updatedRattle) { + if (err !== null) { + return callback(err); + } + self.emit('addReplyToComment', reply._id, comment, userId); + return callback(err, updatedRattle); + }); + return comment.comments[comment.comments.length - 1]._id; + }; + /** + * Edit a comment + * + * @param {Number} userId - user id editing the comment + * @param {Number} commentId - comment id on which the user edit + * @param {String} message - text message + * @callback(err, updatedRattle) + */ + + schema.methods.editComment = function(userId, commentId, message, callback) { + var comment, self; + comment = this.getComment(commentId); + if (!comment) { + return callback(new Error('Comment doesn\'t exist')); + } + if (String(comment.creator) !== String(userId)) { + return callback(new Error('Only owner can edit comment')); + } + comment.message = message; + comment.dateUpdate = moment().toDate(); + self = this; + this.save(function(err, updatedRattle) { + if (err !== null) { + return callback(err); + } + self.emit('editComment', comment._id, self, userId); + return callback(err, updatedRattle); + }); + return this.comments[this.comments.length - 1]._id; + }; + /** + * Remove a comment + * + * @param {Number} userId - user id removing the comment + * @param {Number} commentId - comment id removed + * @callback(err, updatedRattle) + */ + + schema.methods.removeComment = function(userId, commentId, callback) { + var found, self; + if (!this.getComment(commentId)) { + return callback(new Error('Comment doesn\'t exist')); + } + found = false; + this.comments = this.comments.filter(function(comment) { + var keep; + keep = String(comment.creator) !== String(userId) || String(comment._id) !== String(commentId); + found = found || !keep; + return keep; + }); + if (!found) { + return callback(new Error('Comment not found among creator\'s comments'), this); + } + self = this; + return this.save(function(err, updatedRattle) { + if (err !== null) { + return callback(err); + } + self.emit('removeComment', self._id, self, userId); + return callback(err, updatedRattle); + }); + }; + /** + * Like a rattle + * + * @param {Number} userId - user id liking + * @callback(err, updatedRattle) + */ + + schema.methods.addLike = function(userId, callback) { + var hasAlreadyLiked, self; + hasAlreadyLiked = this.likes.some(function(likeUserId) { + return String(likeUserId) === String(userId); + }); + if (hasAlreadyLiked) { + return callback(new Error('User has already liked this'), this); + } + this.likes.push(userId); + self = this; + return this.save(function(err, updatedRattle) { + if (err !== null) { + return callback(err); + } + self.emit('addLike', userId, self, userId); + return callback(err, updatedRattle); + }); + }; + /** + * Like a comment + * + * @param {Number} userId - user id liking + * @param {Number} commentId - comment id to be liked + * @callback(err, updatedRattle) + */ + + schema.methods.addLikeToComment = function(userId, commentId, callback) { + var comment, hasAlreadyLiked, self; + comment = this.getComment(commentId); + if (!comment) { + return callback(new Error('Comment doesn\'t exist')); + } + hasAlreadyLiked = comment.likes.some(function(likeUserId) { + return String(likeUserId) === String(userId); + }); + if (hasAlreadyLiked) { + return callback(new Error('User has already liked this comment'), this); + } + comment.likes.push(userId); + self = this; + return this.save(function(err, updatedRattle) { + if (err !== null) { + return callback(err); + } + self.emit('addLikeToComment', commentId, self, userId); + return callback(err, updatedRattle); + }); + }; + /** + * Unlike a rattle + * + * @param {Number} userId - user id unliking + * @callback(err, updatedRattle) + */ + + schema.methods.removeLike = function(userId, callback) { + var found, self; + found = false; + this.likes = this.likes.filter(function(likeUserId) { + var keep; + keep = String(likeUserId) !== String(userId); + found = found || !keep; + return keep; + }); + if (!found) { + return callback(new Error('User\'s like not found among document\'s likes'), this); + } + self = this; + return this.save(function(err, updatedRattle) { + if (err !== null) { + return callback(err); + } + self.emit('removeLike', userId, self, userId); + return callback(err, updatedRattle); + }); + }; + /** + * Unlike a comment + * + * @param {Number} userId - user id unliking + * @param {Number} commentId - comment id to be unliked + * @callback(err, updatedRattle) + */ + + schema.methods.removeLikeFromComment = function(userId, commentId, callback) { + var comment, found, self; + comment = this.getComment(commentId); + if (!comment) { + return callback(new Error('Comment doesn\'t exist')); + } + found = false; + comment.likes = comment.likes.filter(function(likeUserId) { + var keep; + keep = String(likeUserId) !== String(userId); + found = found || !keep; + return keep; + }); + if (!found) { + return callback(new Error('User\'s like not found among comment\'s likes'), this); + } + self = this; + return this.save(function(err, updatedRattle) { + if (err !== null) { + return callback(err); + } + self.emit('removeLikeFromComment', commentId, self, userId); + return callback(err, updatedRattle); + }); + }; + /** + * Get comment by id + * + * @param {Number} commentId - comment id to be retrieved + * @return {Object} comment found + */ + + return schema.methods.getComment = function(commentId) { + var comment, _i, _len, _ref; + _ref = this.comments; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + comment = _ref[_i]; + if (String(comment._id) === String(commentId)) { + return comment; + } + } + return null; + }; + }; + +}).call(this);