comment.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. module.exports = function(crowi) {
  2. const debug = require('debug')('growi:models:comment');
  3. const mongoose = require('mongoose');
  4. const ObjectId = mongoose.Schema.Types.ObjectId;
  5. const commentEvent = crowi.event('comment');
  6. const commentSchema = new mongoose.Schema({
  7. page: { type: ObjectId, ref: 'Page', index: true },
  8. creator: { type: ObjectId, ref: 'User', index: true },
  9. revision: { type: ObjectId, ref: 'Revision', index: true },
  10. comment: { type: String, required: true },
  11. commentPosition: { type: Number, default: -1 },
  12. isMarkdown: { type: Boolean, default: false },
  13. replyTo: { type: ObjectId },
  14. }, {
  15. timestamps: true,
  16. });
  17. commentSchema.statics.create = function(pageId, creatorId, revisionId, comment, position, isMarkdown, replyTo) {
  18. const Comment = this;
  19. return new Promise(((resolve, reject) => {
  20. const newComment = new Comment();
  21. newComment.page = pageId;
  22. newComment.creator = creatorId;
  23. newComment.revision = revisionId;
  24. newComment.comment = comment;
  25. newComment.commentPosition = position;
  26. newComment.isMarkdown = isMarkdown || false;
  27. newComment.replyTo = replyTo;
  28. newComment.save((err, data) => {
  29. if (err) {
  30. debug('Error on saving comment.', err);
  31. return reject(err);
  32. }
  33. debug('Comment saved.', data);
  34. return resolve(data);
  35. });
  36. }));
  37. };
  38. commentSchema.statics.getCommentsByPageId = function(id) {
  39. return this.find({ page: id }).sort({ createdAt: -1 });
  40. };
  41. commentSchema.statics.getCommentsByRevisionId = function(id) {
  42. return this.find({ revision: id }).sort({ createdAt: -1 });
  43. };
  44. /**
  45. * @return {object} key: page._id, value: comments
  46. */
  47. commentSchema.statics.getPageIdToCommentMap = async function(pageIds) {
  48. const results = await this.aggregate()
  49. .match({ page: { $in: pageIds } })
  50. .group({ _id: '$page', comments: { $push: '$comment' } });
  51. // convert to map
  52. const idToCommentMap = {};
  53. results.forEach((result, i) => {
  54. idToCommentMap[result._id] = result.comments;
  55. });
  56. return idToCommentMap;
  57. };
  58. commentSchema.statics.countCommentByPageId = function(page) {
  59. const self = this;
  60. return new Promise(((resolve, reject) => {
  61. self.count({ page }, (err, data) => {
  62. if (err) {
  63. return reject(err);
  64. }
  65. return resolve(data);
  66. });
  67. }));
  68. };
  69. commentSchema.statics.updateCommentsByPageId = async function(comment, isMarkdown, commentId) {
  70. const Comment = this;
  71. const commentData = await Comment.findOneAndUpdate(
  72. { _id: commentId },
  73. { $set: { comment, isMarkdown } },
  74. );
  75. await commentEvent.emit('update', commentData);
  76. return commentData;
  77. };
  78. /**
  79. * post remove hook
  80. */
  81. commentSchema.post('reomove', async(savedComment) => {
  82. await commentEvent.emit('delete', savedComment);
  83. });
  84. commentSchema.methods.removeWithReplies = async function(comment) {
  85. const Comment = crowi.model('Comment');
  86. await Comment.remove({
  87. $or: (
  88. [{ replyTo: this._id }, { _id: this._id }]),
  89. });
  90. await commentEvent.emit('delete', comment);
  91. return;
  92. };
  93. commentSchema.statics.findCreatorsByPage = async function(page) {
  94. return this.distinct('creator', { page }).exec();
  95. };
  96. return mongoose.model('Comment', commentSchema);
  97. };