Skip to content

Commit 1c0d84e

Browse files
committed
feat: add endpoint to retrieve notes created by user, ordered by creation time
1 parent 9f2f501 commit 1c0d84e

4 files changed

Lines changed: 127 additions & 0 deletions

File tree

src/domain/service/note.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,20 @@ export default class NoteService {
238238
};
239239
}
240240

241+
/**
242+
* Returns notes created by user, ordered by creation time
243+
* @param userId - id of the user
244+
* @param page - number of current page
245+
* @returns list of the notes ordered by creation time
246+
*/
247+
public async getNotesByCreatorId(userId: User['id'], page: number): Promise<NoteList> {
248+
const offset = (page - 1) * this.noteListPortionSize;
249+
250+
return {
251+
items: await this.noteRepository.getNotesByCreatorId(userId, offset, this.noteListPortionSize),
252+
};
253+
}
254+
241255
/**
242256
* Create note relation
243257
* @param noteId - id of the current note

src/presentation/http/router/noteList.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,60 @@ const NoteListRouter: FastifyPluginCallback<NoteListRouterOptions> = (fastify, o
7777
return reply.send(noteListPublic);
7878
});
7979

80+
/**
81+
* Get note list created by user, ordered by creation time
82+
*/
83+
fastify.get<{
84+
Querystring: {
85+
page: number;
86+
};
87+
}>('/created', {
88+
config: {
89+
policy: [
90+
'authRequired',
91+
],
92+
},
93+
schema: {
94+
querystring: {
95+
page: {
96+
type: 'number',
97+
minimum: 1,
98+
maximum: 30,
99+
},
100+
},
101+
102+
response: {
103+
'2xx': {
104+
description: 'Query notelist',
105+
properties: {
106+
items: {
107+
id: { type: 'string' },
108+
content: { type: 'string' },
109+
createdAt: { type: 'string' },
110+
creatorId: { type: 'string' },
111+
updatedAt: { type: 'string' },
112+
},
113+
},
114+
},
115+
},
116+
},
117+
}, async (request, reply) => {
118+
const userId = request.userId as number;
119+
const page = request.query.page;
120+
121+
const noteList = await noteService.getNotesByCreatorId(userId, page);
122+
/**
123+
* Wrapping Notelist for public use
124+
*/
125+
const noteListItemsPublic: NotePublic[] = noteList.items.map(definePublicNote);
126+
127+
const noteListPublic: NoteListPublic = {
128+
items: noteListItemsPublic,
129+
};
130+
131+
return reply.send(noteListPublic);
132+
});
133+
80134
done();
81135
};
82136

src/repository/note.repository.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ export default class NoteRepository {
8282
return await this.storage.getRecentNotesByUserId(id, offset, limit);
8383
}
8484

85+
/**
86+
* Gets notes created by user, ordered by creation time
87+
* @param creatorId - note creator id
88+
* @param offset - number of skipped notes
89+
* @param limit - number of notes to get
90+
*/
91+
public async getNotesByCreatorId(creatorId: number, offset: number, limit: number): Promise<Note[]> {
92+
return await this.storage.getNotesByCreatorId(creatorId, offset, limit);
93+
}
94+
8595
/**
8696
* Get all notes based on their ids
8797
* @param noteIds : list of note ids

src/repository/storage/postgres/orm/sequelize/note.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,55 @@ export default class NoteSequelizeStorage {
285285
});
286286
}
287287

288+
/**
289+
* Gets notes created by user, ordered by creation time
290+
* @param creatorId - id of note creator
291+
* @param offset - number of skipped notes
292+
* @param limit - number of notes to get
293+
* @returns list of the notes ordered by creation time
294+
*/
295+
public async getNotesByCreatorId(creatorId: number, offset: number, limit: number): Promise<Note[]> {
296+
if (!this.settingsModel) {
297+
throw new Error('NoteStorage: Note settings model not initialized');
298+
}
299+
300+
const reply = await this.model.findAll({
301+
offset: offset,
302+
limit: limit,
303+
where: {
304+
creatorId: creatorId,
305+
},
306+
order: [
307+
['createdAt', 'DESC'],
308+
],
309+
include: [{
310+
model: this.settingsModel,
311+
as: 'noteSettings',
312+
attributes: ['cover'],
313+
duplicating: false,
314+
}],
315+
});
316+
317+
/**
318+
* Convert note model data to Note entity with cover property
319+
*/
320+
return reply.map((note) => {
321+
return {
322+
id: note.id,
323+
/**
324+
* noteSettings is required to be, because we make join
325+
*/
326+
cover: note.noteSettings!.cover,
327+
content: note.content,
328+
updatedAt: note.updatedAt,
329+
createdAt: note.createdAt,
330+
publicId: note.publicId,
331+
creatorId: note.creatorId,
332+
tools: note.tools,
333+
};
334+
});
335+
}
336+
288337
/**
289338
* Gets note by id
290339
* @param hostname - custom hostname

0 commit comments

Comments
 (0)