|
@@ -1,122 +1,127 @@
|
|
|
-module.exports = function(crowi) {
|
|
|
|
|
- const debug = require('debug')('growi:models:comment');
|
|
|
|
|
- const mongoose = require('mongoose');
|
|
|
|
|
- const ObjectId = mongoose.Schema.Types.ObjectId;
|
|
|
|
|
- const commentEvent = crowi.event('comment');
|
|
|
|
|
-
|
|
|
|
|
- const commentSchema = new mongoose.Schema({
|
|
|
|
|
- page: { type: ObjectId, ref: 'Page', index: true },
|
|
|
|
|
- creator: { type: ObjectId, ref: 'User', index: true },
|
|
|
|
|
- revision: { type: ObjectId, ref: 'Revision', index: true },
|
|
|
|
|
- comment: { type: String, required: true },
|
|
|
|
|
- commentPosition: { type: Number, default: -1 },
|
|
|
|
|
- isMarkdown: { type: Boolean, default: false },
|
|
|
|
|
- replyTo: { type: ObjectId },
|
|
|
|
|
- }, {
|
|
|
|
|
- timestamps: true,
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- commentSchema.statics.create = function(pageId, creatorId, revisionId, comment, position, isMarkdown, replyTo) {
|
|
|
|
|
- const Comment = this;
|
|
|
|
|
-
|
|
|
|
|
- return new Promise(((resolve, reject) => {
|
|
|
|
|
- const newComment = new Comment();
|
|
|
|
|
-
|
|
|
|
|
- newComment.page = pageId;
|
|
|
|
|
- newComment.creator = creatorId;
|
|
|
|
|
- newComment.revision = revisionId;
|
|
|
|
|
- newComment.comment = comment;
|
|
|
|
|
- newComment.commentPosition = position;
|
|
|
|
|
- newComment.isMarkdown = isMarkdown || false;
|
|
|
|
|
- newComment.replyTo = replyTo;
|
|
|
|
|
-
|
|
|
|
|
- newComment.save((err, data) => {
|
|
|
|
|
- if (err) {
|
|
|
|
|
- debug('Error on saving comment.', err);
|
|
|
|
|
- return reject(err);
|
|
|
|
|
- }
|
|
|
|
|
- debug('Comment saved.', data);
|
|
|
|
|
- return resolve(data);
|
|
|
|
|
- });
|
|
|
|
|
- }));
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- commentSchema.statics.getCommentsByPageId = function(id) {
|
|
|
|
|
- return this.find({ page: id }).sort({ createdAt: -1 });
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- commentSchema.statics.getCommentsByRevisionId = function(id) {
|
|
|
|
|
- return this.find({ revision: id }).sort({ createdAt: -1 });
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * @return {object} key: page._id, value: comments
|
|
|
|
|
- */
|
|
|
|
|
- commentSchema.statics.getPageIdToCommentMap = async function(pageIds) {
|
|
|
|
|
- const results = await this.aggregate()
|
|
|
|
|
- .match({ page: { $in: pageIds } })
|
|
|
|
|
- .group({ _id: '$page', comments: { $push: '$comment' } });
|
|
|
|
|
-
|
|
|
|
|
- // convert to map
|
|
|
|
|
- const idToCommentMap = {};
|
|
|
|
|
- results.forEach((result, i) => {
|
|
|
|
|
- idToCommentMap[result._id] = result.comments;
|
|
|
|
|
|
|
+import type { IUser } from '@growi/core/dist/interfaces';
|
|
|
|
|
+import {
|
|
|
|
|
+ Types, Document, Model, Schema,
|
|
|
|
|
+} from 'mongoose';
|
|
|
|
|
+
|
|
|
|
|
+import { IComment } from '~/interfaces/comment';
|
|
|
|
|
+import { getOrCreateModel } from '~/server/util/mongoose-utils';
|
|
|
|
|
+import loggerFactory from '~/utils/logger';
|
|
|
|
|
+
|
|
|
|
|
+const logger = loggerFactory('growi:models:comment');
|
|
|
|
|
+
|
|
|
|
|
+export interface CommentDocument extends IComment, Document {
|
|
|
|
|
+ removeWithReplies: () => Promise<void>
|
|
|
|
|
+ findCreatorsByPage: (pageId: Types.ObjectId) => Promise<CommentDocument[]>
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export interface CommentModel extends Model<CommentDocument> {
|
|
|
|
|
+ add: (
|
|
|
|
|
+ pageId: Types.ObjectId,
|
|
|
|
|
+ creatorId: Types.ObjectId,
|
|
|
|
|
+ revisionId: Types.ObjectId,
|
|
|
|
|
+ comment: string,
|
|
|
|
|
+ commentPosition: number,
|
|
|
|
|
+ replyTo?: Types.ObjectId | null,
|
|
|
|
|
+ ) => Promise<void>
|
|
|
|
|
+
|
|
|
|
|
+ getCommentsByPageId: (pageId: Types.ObjectId) => Promise<CommentDocument[]>
|
|
|
|
|
+
|
|
|
|
|
+ getCommentsByRevisionId: (revisionId: Types.ObjectId) => Promise<CommentDocument[]>
|
|
|
|
|
+
|
|
|
|
|
+ getPageIdToCommentMap: (pageIds: Types.ObjectId[]) => Promise<Record<string, CommentDocument[]>>
|
|
|
|
|
+
|
|
|
|
|
+ findCreatorsByPage: (pageId: Types.ObjectId) => Promise<IUser[]>
|
|
|
|
|
+
|
|
|
|
|
+ countCommentByPageId: (pageId: Types.ObjectId) => Promise<number>
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const commentSchema = new Schema<CommentDocument, CommentModel>({
|
|
|
|
|
+ page: { type: Schema.Types.ObjectId, ref: 'Page', index: true },
|
|
|
|
|
+ creator: { type: Schema.Types.ObjectId, ref: 'User', index: true },
|
|
|
|
|
+ revision: { type: Schema.Types.ObjectId, ref: 'Revision', index: true },
|
|
|
|
|
+ comment: { type: String, required: true },
|
|
|
|
|
+ commentPosition: { type: Number, default: -1 },
|
|
|
|
|
+ replyTo: { type: Schema.Types.ObjectId },
|
|
|
|
|
+}, {
|
|
|
|
|
+ timestamps: true,
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * post remove hook
|
|
|
|
|
+ */
|
|
|
|
|
+commentSchema.post('remove', async(savedComment) => {
|
|
|
|
|
+ await commentEvent.emit('delete', savedComment);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+commentSchema.statics.add = async function(
|
|
|
|
|
+ pageId: Types.ObjectId,
|
|
|
|
|
+ creatorId: Types.ObjectId,
|
|
|
|
|
+ revisionId: Types.ObjectId,
|
|
|
|
|
+ comment: string,
|
|
|
|
|
+ commentPosition: number,
|
|
|
|
|
+ replyTo?: string,
|
|
|
|
|
+) {
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const data = await this.create({
|
|
|
|
|
+ page: pageId.toString(),
|
|
|
|
|
+ creator: creatorId.toString(),
|
|
|
|
|
+ revision: revisionId.toString(),
|
|
|
|
|
+ comment,
|
|
|
|
|
+ commentPosition,
|
|
|
|
|
+ replyTo,
|
|
|
});
|
|
});
|
|
|
|
|
+ logger.debug('Comment saved.', data);
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (err) {
|
|
|
|
|
+ logger.debug('Error on saving comment.', err);
|
|
|
|
|
+ throw err;
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
- return idToCommentMap;
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- commentSchema.statics.countCommentByPageId = function(page) {
|
|
|
|
|
- const self = this;
|
|
|
|
|
-
|
|
|
|
|
- return new Promise(((resolve, reject) => {
|
|
|
|
|
- self.count({ page }, (err, data) => {
|
|
|
|
|
- if (err) {
|
|
|
|
|
- return reject(err);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return resolve(data);
|
|
|
|
|
- });
|
|
|
|
|
- }));
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- commentSchema.statics.updateCommentsByPageId = async function(comment, isMarkdown, commentId) {
|
|
|
|
|
- const Comment = this;
|
|
|
|
|
-
|
|
|
|
|
- const commentData = await Comment.findOneAndUpdate(
|
|
|
|
|
- { _id: commentId },
|
|
|
|
|
- { $set: { comment, isMarkdown } },
|
|
|
|
|
- );
|
|
|
|
|
|
|
+commentSchema.statics.getCommentsByPageId = function(id) {
|
|
|
|
|
+ return this.find({ page: id }).sort({ createdAt: -1 });
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
- await commentEvent.emit('update', commentData);
|
|
|
|
|
|
|
+commentSchema.statics.getCommentsByRevisionId = function(id) {
|
|
|
|
|
+ return this.find({ revision: id }).sort({ createdAt: -1 });
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
- return commentData;
|
|
|
|
|
- };
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @return {object} key: page._id, value: comments
|
|
|
|
|
+ */
|
|
|
|
|
+commentSchema.statics.getPageIdToCommentMap = async function(pageIds) {
|
|
|
|
|
+ const results = await this.aggregate()
|
|
|
|
|
+ .match({ page: { $in: pageIds } })
|
|
|
|
|
+ .group({ _id: '$page', comments: { $push: '$comment' } });
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * post remove hook
|
|
|
|
|
- */
|
|
|
|
|
- commentSchema.post('reomove', async(savedComment) => {
|
|
|
|
|
- await commentEvent.emit('delete', savedComment);
|
|
|
|
|
|
|
+ // convert to map
|
|
|
|
|
+ const idToCommentMap = {};
|
|
|
|
|
+ results.forEach((result, i) => {
|
|
|
|
|
+ idToCommentMap[result._id] = result.comments;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- commentSchema.methods.removeWithReplies = async function(comment) {
|
|
|
|
|
- const Comment = crowi.model('Comment');
|
|
|
|
|
|
|
+ return idToCommentMap;
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
- await Comment.remove({
|
|
|
|
|
- $or: (
|
|
|
|
|
- [{ replyTo: this._id }, { _id: this._id }]),
|
|
|
|
|
- });
|
|
|
|
|
|
|
+commentSchema.statics.findCreatorsByPage = async function(page) {
|
|
|
|
|
+ return this.distinct('creator', { page }).exec();
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
- await commentEvent.emit('delete', comment);
|
|
|
|
|
- return;
|
|
|
|
|
- };
|
|
|
|
|
|
|
+commentSchema.statics.countCommentByPageId = async function(page) {
|
|
|
|
|
+ return this.count({ page });
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
- commentSchema.statics.findCreatorsByPage = async function(page) {
|
|
|
|
|
- return this.distinct('creator', { page }).exec();
|
|
|
|
|
- };
|
|
|
|
|
|
|
+commentSchema.methods.removeWithReplies = async function(comment) {
|
|
|
|
|
+ await this.remove({
|
|
|
|
|
+ $or: (
|
|
|
|
|
+ [{ replyTo: this._id }, { _id: this._id }]),
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- return mongoose.model('Comment', commentSchema);
|
|
|
|
|
|
|
+ await commentEvent.emit('delete', comment);
|
|
|
|
|
+ return;
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
|
|
+export default getOrCreateModel<CommentDocument, CommentModel>('Comment', commentSchema);
|