bookmark-folder.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { isValidObjectId } from '@growi/core/src/utils/objectid-utils';
  2. import {
  3. Types, Document, Model, Schema,
  4. } from 'mongoose';
  5. import { IBookmarkFolder } from '~/interfaces/bookmark-info';
  6. import loggerFactory from '../../utils/logger';
  7. import { getOrCreateModel } from '../util/mongoose-utils';
  8. import { InvalidParentBookmarkFolderError } from './errors';
  9. const logger = loggerFactory('growi:models:bookmark-folder');
  10. export interface BookmarkFolderItems {
  11. _id: string
  12. name: string
  13. children: this[]
  14. }
  15. export interface BookmarkFolderDocument extends Document {
  16. _id: Types.ObjectId
  17. name: string
  18. owner: Types.ObjectId
  19. parent?: [this]
  20. }
  21. export interface BookmarkFolderModel extends Model<BookmarkFolderDocument>{
  22. createByParameters(params: IBookmarkFolder): BookmarkFolderDocument
  23. findFolderAndChildren(user: Types.ObjectId | string, parentId?: Types.ObjectId | string): BookmarkFolderItems[]
  24. findChildFolderById(parentBookmarkFolder: Types.ObjectId | string): Promise<BookmarkFolderDocument[]>
  25. deleteFolderAndChildren(bookmarkFolderId: string): {deletedCount: number}
  26. updateBookmarkFolder(bookmarkFolderId: string, name: string, parent: string): BookmarkFolderDocument | null
  27. }
  28. const bookmarkFolderSchema = new Schema<BookmarkFolderDocument, BookmarkFolderModel>({
  29. name: { type: String },
  30. owner: { type: Schema.Types.ObjectId, ref: 'User', index: true },
  31. parent: { type: Schema.Types.ObjectId, ref: 'BookmarkFolder', required: false },
  32. });
  33. bookmarkFolderSchema.virtual('children', {
  34. ref: 'BookmarkFolder',
  35. localField: '_id',
  36. foreignField: 'parent',
  37. });
  38. bookmarkFolderSchema.statics.createByParameters = async function(params: IBookmarkFolder): Promise<BookmarkFolderDocument> {
  39. const { name, owner, parent } = params;
  40. let bookmarkFolder;
  41. if (parent == null) {
  42. bookmarkFolder = await this.create({ name, owner }) as unknown as BookmarkFolderDocument;
  43. }
  44. else {
  45. // Check if parent folder id is valid and parent folder exists
  46. const isParentFolderIdValid = isValidObjectId(parent as string);
  47. if (!isParentFolderIdValid) {
  48. throw new InvalidParentBookmarkFolderError('Parent folder id is invalid');
  49. }
  50. const parentFolder = await this.findById(parent);
  51. if (parentFolder == null) {
  52. throw new InvalidParentBookmarkFolderError('Parent folder not found');
  53. }
  54. bookmarkFolder = await this.create({ name, owner, parent: parentFolder._id }) as unknown as BookmarkFolderDocument;
  55. }
  56. return bookmarkFolder;
  57. };
  58. bookmarkFolderSchema.statics.findFolderAndChildren = async function(
  59. userId: Types.ObjectId | string,
  60. parentId?: Types.ObjectId | string,
  61. ): Promise<BookmarkFolderItems[]> {
  62. const parentFolder = await this.findById(parentId) as unknown as BookmarkFolderDocument;
  63. const bookmarks = await this.find({ owner: userId, parent: parentFolder }).populate({ path: 'children' }).exec() as unknown as BookmarkFolderItems[];
  64. return bookmarks;
  65. };
  66. bookmarkFolderSchema.statics.findChildFolderById = async function(parentFolderId: Types.ObjectId | string): Promise<BookmarkFolderDocument[]> {
  67. const parentFolder = await this.findById(parentFolderId) as unknown as BookmarkFolderDocument;
  68. const childFolders = await this.find({ parent: parentFolder });
  69. return childFolders;
  70. };
  71. bookmarkFolderSchema.statics.deleteFolderAndChildren = async function(boookmarkFolderId: Types.ObjectId | string): Promise<{deletedCount: number}> {
  72. // Delete parent and all children folder
  73. const bookmarkFolder = await this.findByIdAndDelete(boookmarkFolderId);
  74. let deletedCount = 0;
  75. if (bookmarkFolder != null) {
  76. const childFolders = await this.deleteMany({ parent: bookmarkFolder?.id });
  77. deletedCount = childFolders.deletedCount + 1;
  78. }
  79. return { deletedCount };
  80. };
  81. bookmarkFolderSchema.statics.updateBookmarkFolder = async function(bookmarkFolderId: string, name: string, parent: string):
  82. Promise<BookmarkFolderDocument | null> {
  83. const parentFolder = await this.findById(parent);
  84. const updateFields = {
  85. name, parent: parentFolder?._id || null,
  86. };
  87. const bookmarkFolder = await this.findByIdAndUpdate(bookmarkFolderId, { $set: updateFields }, { new: true });
  88. return bookmarkFolder;
  89. };
  90. bookmarkFolderSchema.set('toObject', { virtuals: true });
  91. export default getOrCreateModel<BookmarkFolderDocument, BookmarkFolderModel>('BookmarkFolder', bookmarkFolderSchema);