From b037bfb71c8d9bd2a928ee680b1683d05bd4e628 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Mon, 30 Sep 2024 16:48:58 +0200 Subject: [PATCH] feat: include favorite projects in personal dashboard (#8309) --- .../personal-dashboard-controller.e2e.test.ts | 37 +++++++++++++++++++ .../personal-dashboard-service.ts | 9 +++-- .../project/fake-project-read-model.ts | 3 ++ .../project/project-read-model-type.ts | 1 + .../features/project/project-read-model.ts | 12 ++++++ 5 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/lib/features/personal-dashboard/personal-dashboard-controller.e2e.test.ts b/src/lib/features/personal-dashboard/personal-dashboard-controller.e2e.test.ts index 6304c7eb5953..ad46766963b7 100644 --- a/src/lib/features/personal-dashboard/personal-dashboard-controller.e2e.test.ts +++ b/src/lib/features/personal-dashboard/personal-dashboard-controller.e2e.test.ts @@ -81,6 +81,13 @@ const createProject = async (name: string, user: IUser) => { return project; }; +const favoriteProject = async (projectName = 'default') => { + await app.request + .post(`/api/admin/projects/${projectName}/favorites`) + .set('Content-Type', 'application/json') + .expect(200); +}; + test('should return personal dashboard with membered projects', async () => { const { body: user1 } = await loginUser('user1@test.com'); const projectA = await createProject('Project A', user1); @@ -118,6 +125,36 @@ test('should return personal dashboard with membered projects', async () => { { name: projectC.name, id: projectC.id, + health: 100, + memberCount: 1, + featureCount: 0, + }, + ], + }); +}); + +test('should return personal dashboard with user favorited projects', async () => { + const { body: user1 } = await loginUser('user1@test.com'); + const projectA = await createProject('Project A', user1); + + await loginUser('user2@test.com'); + await favoriteProject(projectA.id); + + const { body } = await app.request.get(`/api/admin/personal-dashboard`); + + expect(body).toMatchObject({ + projects: [ + { + name: 'Default', + id: 'default', + health: 100, + memberCount: 0, + featureCount: 0, + }, + { + name: projectA.name, + id: projectA.id, + health: 100, memberCount: 1, featureCount: 0, }, diff --git a/src/lib/features/personal-dashboard/personal-dashboard-service.ts b/src/lib/features/personal-dashboard/personal-dashboard-service.ts index f6a15d64cae4..9aaccc4dcc8f 100644 --- a/src/lib/features/personal-dashboard/personal-dashboard-service.ts +++ b/src/lib/features/personal-dashboard/personal-dashboard-service.ts @@ -71,12 +71,13 @@ export class PersonalDashboardService { } async getPersonalProjects(userId: number): Promise { - // TODO: add favorite projects in addition to membership projects - const userProjectIds = - await this.projectReadModel.getProjectsByUser(userId); + const [userProjectIds, userFavoritedProjectIds] = await Promise.all([ + this.projectReadModel.getProjectsByUser(userId), + this.projectReadModel.getProjectsFavoritedByUser(userId), + ]); const projects = await this.projectReadModel.getProjectsForAdminUi({ - ids: userProjectIds, + ids: [...new Set([...userProjectIds, ...userFavoritedProjectIds])], archived: false, }); diff --git a/src/lib/features/project/fake-project-read-model.ts b/src/lib/features/project/fake-project-read-model.ts index 3a861cd54047..445970eccc93 100644 --- a/src/lib/features/project/fake-project-read-model.ts +++ b/src/lib/features/project/fake-project-read-model.ts @@ -17,4 +17,7 @@ export class FakeProjectReadModel implements IProjectReadModel { getProjectsByUser(): Promise { return Promise.resolve([]); } + getProjectsFavoritedByUser(): Promise { + return Promise.resolve([]); + } } diff --git a/src/lib/features/project/project-read-model-type.ts b/src/lib/features/project/project-read-model-type.ts index a3d2270edc02..19d6176c1113 100644 --- a/src/lib/features/project/project-read-model-type.ts +++ b/src/lib/features/project/project-read-model-type.ts @@ -38,4 +38,5 @@ export interface IProjectReadModel { featureName: string, ): Promise<{ project: string; createdAt: Date } | null>; getProjectsByUser(userId: number): Promise; + getProjectsFavoritedByUser(userId: number): Promise; } diff --git a/src/lib/features/project/project-read-model.ts b/src/lib/features/project/project-read-model.ts index b15ab461f501..06bb57cb196e 100644 --- a/src/lib/features/project/project-read-model.ts +++ b/src/lib/features/project/project-read-model.ts @@ -284,4 +284,16 @@ export class ProjectReadModel implements IProjectReadModel { .pluck('project'); return projects; } + + async getProjectsFavoritedByUser(userId: number): Promise { + const favoritedProjects = await this.db + .select('favorite_projects.project') + .from('favorite_projects') + .leftJoin('projects', 'favorite_projects.project', 'projects.id') + .where('favorite_projects.user_id', userId) + .andWhere('projects.archived_at', null) + .pluck('project'); + + return favoritedProjects; + } }