comment.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import type { IUser } from '@growi/core/dist/interfaces';
  2. import type { Document, Model, Query, Types } from 'mongoose';
  3. import { Schema } from 'mongoose';
  4. import type { IComment } from '~/interfaces/comment';
  5. import { getOrCreateModel } from '~/server/util/mongoose-utils';
  6. import loggerFactory from '~/utils/logger';
  7. const logger = loggerFactory('growi:models:comment');
  8. export interface CommentDocument extends IComment, Document {
  9. removeWithReplies: () => Promise<void>;
  10. findCreatorsByPage: (pageId: Types.ObjectId) => Promise<CommentDocument[]>;
  11. }
  12. type Add = (
  13. pageId: Types.ObjectId,
  14. creatorId: Types.ObjectId,
  15. revisionId: Types.ObjectId,
  16. comment: string,
  17. commentPosition: number,
  18. replyTo?: Types.ObjectId | null,
  19. ) => Promise<CommentDocument>;
  20. type FindCommentsByPageId = (
  21. pageId: Types.ObjectId,
  22. ) => Query<CommentDocument[], CommentDocument>;
  23. type FindCommentsByRevisionId = (
  24. revisionId: Types.ObjectId,
  25. ) => Query<CommentDocument[], CommentDocument>;
  26. type FindCreatorsByPage = (pageId: Types.ObjectId) => Promise<IUser[]>;
  27. type CountCommentByPageId = (pageId: Types.ObjectId) => Promise<number>;
  28. export interface CommentModel extends Model<CommentDocument> {
  29. add: Add;
  30. findCommentsByPageId: FindCommentsByPageId;
  31. findCommentsByRevisionId: FindCommentsByRevisionId;
  32. findCreatorsByPage: FindCreatorsByPage;
  33. countCommentByPageId: CountCommentByPageId;
  34. }
  35. const commentSchema = new Schema<CommentDocument, CommentModel>(
  36. {
  37. page: { type: Schema.Types.ObjectId, ref: 'Page', index: true },
  38. creator: { type: Schema.Types.ObjectId, ref: 'User', index: true },
  39. revision: { type: Schema.Types.ObjectId, ref: 'Revision', index: true },
  40. comment: { type: String, required: true },
  41. commentPosition: { type: Number, default: -1 },
  42. replyTo: { type: Schema.Types.ObjectId },
  43. },
  44. {
  45. timestamps: true,
  46. },
  47. );
  48. const add: Add = async function (
  49. this: CommentModel,
  50. pageId,
  51. creatorId,
  52. revisionId,
  53. comment,
  54. commentPosition,
  55. replyTo?,
  56. ): Promise<CommentDocument> {
  57. try {
  58. const data = await this.create({
  59. page: pageId.toString(),
  60. creator: creatorId.toString(),
  61. revision: revisionId.toString(),
  62. comment,
  63. commentPosition,
  64. replyTo,
  65. });
  66. logger.debug({ data }, 'Comment saved.');
  67. return data;
  68. } catch (err) {
  69. logger.debug({ err }, 'Error on saving comment.');
  70. throw err;
  71. }
  72. };
  73. commentSchema.statics.add = add;
  74. commentSchema.statics.findCommentsByPageId = function (id) {
  75. return this.find({ page: id }).sort({ createdAt: -1 });
  76. };
  77. commentSchema.statics.findCommentsByRevisionId = function (id) {
  78. return this.find({ revision: id }).sort({ createdAt: -1 });
  79. };
  80. commentSchema.statics.findCreatorsByPage = async function (page) {
  81. return this.distinct('creator', { page }).exec();
  82. };
  83. commentSchema.statics.countCommentByPageId = async function (page) {
  84. return this.count({ page });
  85. };
  86. commentSchema.statics.removeWithReplies = async function (comment) {
  87. await this.deleteMany({
  88. $or: [{ replyTo: comment._id }, { _id: comment._id }],
  89. });
  90. };
  91. export const Comment = getOrCreateModel<CommentDocument, CommentModel>(
  92. 'Comment',
  93. commentSchema,
  94. );