diff --git a/src/domain/service/note.ts b/src/domain/service/note.ts index c4ae5b52..07217462 100644 --- a/src/domain/service/note.ts +++ b/src/domain/service/note.ts @@ -225,16 +225,17 @@ export default class NoteService { } /** - * Returns note list by creator id + * Returns note list by user id * @param userId - id of the user * @param page - number of current page - * @returns list of the notes ordered by time of last visit + * @param filterByCreator - if true, returns only notes created by user, otherwise returns notes visited by user + * @returns list of the notes */ - public async getNoteListByUserId(userId: User['id'], page: number): Promise { + public async getNoteListByUserId(userId: User['id'], page: number, filterByCreator = false): Promise { const offset = (page - 1) * this.noteListPortionSize; return { - items: await this.noteRepository.getNoteListByUserId(userId, offset, this.noteListPortionSize), + items: await this.noteRepository.getNoteListByUserId(userId, offset, this.noteListPortionSize, filterByCreator), }; } diff --git a/src/presentation/http/router/noteList.ts b/src/presentation/http/router/noteList.ts index 49507d2f..2b21df3d 100644 --- a/src/presentation/http/router/noteList.ts +++ b/src/presentation/http/router/noteList.ts @@ -11,7 +11,6 @@ interface NoteListRouterOptions { * Note service instance */ noteService: NoteService; - } /** @@ -23,6 +22,49 @@ interface NoteListRouterOptions { const NoteListRouter: FastifyPluginCallback = (fastify, opts, done) => { const noteService = opts.noteService; + const noteListSchema = { + querystring: { + page: { + type: 'number', + minimum: 1, + maximum: 30, + }, + }, + response: { + '2xx': { + description: 'Query notelist', + properties: { + items: { + id: { type: 'string' }, + content: { type: 'string' }, + createdAt: { type: 'string' }, + creatorId: { type: 'string' }, + updatedAt: { type: 'string' }, + }, + }, + }, + }, + }; + + const createNoteListHandler = (filterByCreator: boolean) => { + return async (request: { userId: number | null; query: { page: number } }, reply: { send: (data: NoteListPublic) => void }): Promise => { + const userId = request.userId as number; + const page = request.query.page; + + const noteList = await noteService.getNoteListByUserId(userId, page, filterByCreator); + /** + * Wrapping Notelist for public use + */ + const noteListItemsPublic: NotePublic[] = noteList.items.map(definePublicNote); + + const noteListPublic: NoteListPublic = { + items: noteListItemsPublic, + }; + + return reply.send(noteListPublic); + }; + }; + /** * Get note list ordered by time of last visit */ @@ -36,46 +78,22 @@ const NoteListRouter: FastifyPluginCallback = (fastify, o 'authRequired', ], }, - schema: { - querystring: { - page: { - type: 'number', - minimum: 1, - maximum: 30, - }, - }, + schema: noteListSchema, + }, createNoteListHandler(false)); - response: { - '2xx': { - description: 'Query notelist', - properties: { - items: { - id: { type: 'string' }, - content: { type: 'string' }, - createdAt: { type: 'string' }, - creatorId: { type: 'string' }, - updatedAt: { type: 'string' }, - }, - }, - }, - }, - }, - }, async (request, reply) => { - const userId = request.userId as number; - const page = request.query.page; - - const noteList = await noteService.getNoteListByUserId(userId, page); - /** - * Wrapping Notelist for public use - */ - const noteListItemsPublic: NotePublic[] = noteList.items.map(definePublicNote); - - const noteListPublic: NoteListPublic = { - items: noteListItemsPublic, + /** + * Get note list created by the user + */ + fastify.get<{ + Querystring: { + page: number; }; - - return reply.send(noteListPublic); - }); + }>('/my', { + config: { + policy: ['authRequired'], + }, + schema: noteListSchema, + }, createNoteListHandler(true)); done(); }; diff --git a/src/repository/note.repository.ts b/src/repository/note.repository.ts index 234c0741..6ef7b78b 100644 --- a/src/repository/note.repository.ts +++ b/src/repository/note.repository.ts @@ -73,13 +73,14 @@ export default class NoteRepository { } /** - * Gets note list by creator id - * @param id - note creator id + * Gets note list by user id + * @param id - user id * @param offset - number of skipped notes * @param limit - number of notes to get + * @param filterByCreator - if true, returns only notes created by user, otherwise returns notes visited by user */ - public async getNoteListByUserId(id: number, offset: number, limit: number): Promise { - return await this.storage.getNoteListByUserId(id, offset, limit); + public async getNoteListByUserId(id: number, offset: number, limit: number, filterByCreator = false): Promise { + return await this.storage.getNoteListByUserId(id, offset, limit, filterByCreator); } /** diff --git a/src/repository/storage/postgres/orm/sequelize/note.ts b/src/repository/storage/postgres/orm/sequelize/note.ts index 1b9ba87c..b8b7c619 100644 --- a/src/repository/storage/postgres/orm/sequelize/note.ts +++ b/src/repository/storage/postgres/orm/sequelize/note.ts @@ -224,45 +224,60 @@ export default class NoteSequelizeStorage { } /** - * Gets note list by creator id + * Gets note list by user id * @param userId - id of certain user * @param offset - number of skipped notes * @param limit - number of notes to get + * @param filterByCreator - if true, returns only notes created by user, otherwise returns notes visited by user * @returns list of the notes */ - public async getNoteListByUserId(userId: number, offset: number, limit: number): Promise { - if (this.visitsModel === null) { - throw new Error('NoteStorage: NoteVisit model should be defined'); - } - + public async getNoteListByUserId(userId: number, offset: number, limit: number, filterByCreator = false): Promise { if (!this.settingsModel) { throw new Error('NoteStorage: Note settings model not initialized'); } - const reply = await this.model.findAll({ - offset: offset, - limit: limit, - where: { - '$noteVisits.user_id$': userId, - }, - order: [[ - { - model: this.visitsModel, - as: 'noteVisits', - }, - 'visited_at', - 'DESC', - ]], - include: [{ - model: this.visitsModel, - as: 'noteVisits', - duplicating: false, - }, { + if (!filterByCreator && this.visitsModel === null) { + throw new Error('NoteStorage: NoteVisit model should be defined'); + } + + const where: Record = filterByCreator + ? { creatorId: userId } + : { '$noteVisits.user_id$': userId }; + + const order = filterByCreator + ? [['updatedAt', 'DESC']] + : [[ + { + model: this.visitsModel!, + as: 'noteVisits', + }, + 'visited_at', + 'DESC', + ]]; + + const include: Array> = [ + { model: this.settingsModel, as: 'noteSettings', attributes: ['cover'], duplicating: false, - }], + }, + ]; + + if (!filterByCreator) { + include.unshift({ + model: this.visitsModel!, + as: 'noteVisits', + duplicating: false, + }); + } + + const reply = await this.model.findAll({ + offset, + limit, + where, + order: order as never, + include, }); /** @@ -356,7 +371,7 @@ export default class NoteSequelizeStorage { // Fetch all notes and relations in a recursive query const query = ` WITH RECURSIVE note_tree AS ( - SELECT + SELECT n.id AS "noteId", n.content, n.public_id AS "publicId", @@ -364,10 +379,10 @@ export default class NoteSequelizeStorage { FROM ${String(this.database.literal(this.tableName).val)} n LEFT JOIN ${String(this.database.literal('note_relations').val)} nr ON n.id = nr.note_id WHERE n.id = :startNoteId - + UNION ALL - SELECT + SELECT n.id AS "noteId", n.content, n.public_id AS "publicId",