-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add contributors page gf-250 #334
Changes from 25 commits
f5d9de6
7461829
4d0e9b8
2289706
22e6216
659e7f5
02234ce
a653cba
e2ea3e5
15cf55d
9d0ef9e
412a653
aa352f5
89c6bc0
7f20e8c
d00ce32
012f5b4
8784427
dbaa681
bed8389
cca9651
98f4be6
77bf018
2eb91d1
e3fd7cb
1bd48f1
1362f3e
55ade8b
8cd5d9f
702150d
05436d8
35c8304
8fab5d3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { APIPath } from "~/libs/enums/enums.js"; | ||
import { | ||
type APIHandlerResponse, | ||
BaseController, | ||
} from "~/libs/modules/controller/controller.js"; | ||
import { HTTPCode } from "~/libs/modules/http/http.js"; | ||
import { type Logger } from "~/libs/modules/logger/logger.js"; | ||
|
||
import { type ContributorService } from "./contributor.service.js"; | ||
import { ContributorsApiPath } from "./libs/enums/enums.js"; | ||
|
||
/** | ||
* @swagger | ||
* components: | ||
* schemas: | ||
* Contributor: | ||
* type: object | ||
* properties: | ||
* id: | ||
* type: number | ||
* minimum: 1 | ||
* name: | ||
* type: string | ||
* gitEmails: | ||
* type: array | ||
* items: | ||
* type: object | ||
* properties: | ||
* id: | ||
* type: number | ||
* minimum: 1 | ||
* email: | ||
* type: string | ||
* projects: | ||
* type: array | ||
* items: | ||
* type: object | ||
* properties: | ||
* id: | ||
* type: number | ||
* minimum: 1 | ||
* name: | ||
* type: string | ||
*/ | ||
class ContributorController extends BaseController { | ||
private contributorService: ContributorService; | ||
|
||
public constructor(logger: Logger, contributorService: ContributorService) { | ||
super(logger, APIPath.CONTRIBUTORS); | ||
|
||
this.contributorService = contributorService; | ||
|
||
this.addRoute({ | ||
handler: () => this.findAll(), | ||
method: "GET", | ||
path: ContributorsApiPath.ROOT, | ||
}); | ||
} | ||
|
||
/** | ||
* @swagger | ||
* /contributors: | ||
* get: | ||
* description: Returns an array of contributors | ||
* responses: | ||
* 200: | ||
* description: Successful operation | ||
* content: | ||
* application/json: | ||
* schema: | ||
* type: object | ||
* properties: | ||
* items: | ||
* type: array | ||
* items: | ||
* $ref: "#/components/schemas/Contributor" | ||
*/ | ||
private async findAll(): Promise<APIHandlerResponse> { | ||
return { | ||
payload: await this.contributorService.findAll(), | ||
status: HTTPCode.OK, | ||
}; | ||
} | ||
} | ||
|
||
export { ContributorController }; |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -2,19 +2,26 @@ import { ExceptionMessage } from "~/libs/enums/enums.js"; | |||
import { HTTPCode } from "~/libs/modules/http/http.js"; | ||||
import { type Service } from "~/libs/types/types.js"; | ||||
|
||||
import { type ProjectService } from "../projects/project.service.js"; | ||||
import { ContributorEntity } from "./contributor.entity.js"; | ||||
import { type ContributorRepository } from "./contributor.repository.js"; | ||||
import { ContributorError } from "./libs/exceptions/exceptions.js"; | ||||
import { | ||||
type ContributorCreateRequestDto, | ||||
type ContributorGetAllItemResponseDto, | ||||
type ContributorGetAllResponseDto, | ||||
} from "./libs/types/types.js"; | ||||
|
||||
class ContributorService implements Service { | ||||
private contributorRepository: ContributorRepository; | ||||
private projectService: ProjectService; | ||||
|
||||
public constructor(contributorRepository: ContributorRepository) { | ||||
public constructor( | ||||
contributorRepository: ContributorRepository, | ||||
projectService: ProjectService, | ||||
) { | ||||
this.contributorRepository = contributorRepository; | ||||
this.projectService = projectService; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like we no longer need this
Suggested change
|
||||
} | ||||
|
||||
public async create( | ||||
|
@@ -45,19 +52,53 @@ class ContributorService implements Service { | |||
}); | ||||
} | ||||
|
||||
return item.toObject(); | ||||
const projects = await this.projectService.findProjectsByContributorId(id); | ||||
|
||||
return { ...item.toObject(), projects: projects.items }; | ||||
} | ||||
|
||||
public findAll(): ReturnType<Service["findAll"]> { | ||||
return Promise.resolve({ items: [] }); | ||||
public async findAll(): Promise<ContributorGetAllResponseDto> { | ||||
const contributors = await this.contributorRepository.findAll(); | ||||
|
||||
const contributorsWithProjects = await Promise.all( | ||||
contributors.items.map(async (item) => { | ||||
const contributor = item.toObject(); | ||||
|
||||
const projects = await this.projectService.findProjectsByContributorId( | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can join projects inside contributors repository findAll method? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I thought that such logic should be through services. You mean that I should remove it completely from projectRepository, and create such method in contributorRepository, or make contributorRepository dependent of projectRepository? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I was thinking about calculating it as a custom field somehow inside the query in contributors repository, but looks like it will be complicated There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so the problem is that it's not really good to make a separate query for each item. Also, we need to use for of, instead of Promise all, because this may make too many simultaneous db requests, which is bad. And the concern here is that with for of it will work slow There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and if there is a possibility to compute or somehow join this inside the contributors query, this would be better, otherwise, we need to use for of here, which can be slow There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, alright, I'll try to figure out what we could do with it tomorrow. Resolving a lot of conflicts today got me feeling fried😂 |
||||
contributor.id, | ||||
); | ||||
|
||||
return { | ||||
...contributor, | ||||
gitEmails: contributor.gitEmails.map((gitEmail) => ({ | ||||
email: gitEmail.email, | ||||
id: gitEmail.id, | ||||
})), | ||||
projects: projects.items.map((project) => ({ | ||||
id: project.id, | ||||
name: project.name, | ||||
})), | ||||
}; | ||||
}), | ||||
); | ||||
|
||||
return { items: contributorsWithProjects }; | ||||
} | ||||
|
||||
public async findByName( | ||||
name: string, | ||||
): Promise<ContributorGetAllItemResponseDto | null> { | ||||
const item = await this.contributorRepository.findByName(name); | ||||
|
||||
return item ? item.toObject() : null; | ||||
if (!item) { | ||||
return null; | ||||
} | ||||
|
||||
const projects = await this.projectService.findProjectsByContributorId( | ||||
item.toObject().id, | ||||
); | ||||
|
||||
return { ...item.toObject(), projects: projects.items }; | ||||
} | ||||
|
||||
public update(): ReturnType<Service["update"]> { | ||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,21 @@ | ||
import { logger } from "~/libs/modules/logger/logger.js"; | ||
|
||
import { projectService } from "../projects/projects.js"; | ||
import { ContributorController } from "./contributor.controller.js"; | ||
import { ContributorModel } from "./contributor.model.js"; | ||
import { ContributorRepository } from "./contributor.repository.js"; | ||
import { ContributorService } from "./contributors.service.js"; | ||
import { ContributorService } from "./contributor.service.js"; | ||
|
||
const contributorRepository = new ContributorRepository(ContributorModel); | ||
const contributorService = new ContributorService(contributorRepository); | ||
const contributorService = new ContributorService( | ||
contributorRepository, | ||
projectService, | ||
); | ||
const contributorController = new ContributorController( | ||
logger, | ||
contributorService, | ||
); | ||
|
||
export { ContributorModel } from "./contributor.model.js"; | ||
export { ContributorRepository } from "./contributor.repository.js"; | ||
export { ContributorService } from "./contributors.service.js"; | ||
export { contributorService }; | ||
export { ContributorService } from "./contributor.service.js"; | ||
export { contributorController, contributorService }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { ContributorsApiPath } from "@git-fit/shared"; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -75,6 +75,22 @@ class ProjectRepository implements Repository { | |||||
return item ? ProjectEntity.initialize(item) : null; | ||||||
} | ||||||
|
||||||
public async findProjectsByContributorId( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
contributorId: number, | ||||||
): Promise<{ items: ProjectEntity[] }> { | ||||||
const projects = await this.projectModel | ||||||
.query() | ||||||
.select("projects.*") | ||||||
.join("activity_logs", "activity_logs.project_id", "projects.id") | ||||||
.join("git_emails", "git_emails.id", "activity_logs.git_email_id") | ||||||
.where("git_emails.contributor_id", contributorId) | ||||||
.distinct(); | ||||||
GvoFor marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
return { | ||||||
items: projects.map((project) => ProjectEntity.initialize(project)), | ||||||
}; | ||||||
} | ||||||
|
||||||
public async patch( | ||||||
id: number, | ||||||
projectData: ProjectPatchRequestDto, | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we leave
return ContributorEntity.initialize(contributor);
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, now that we have one query for that, we can, I forgot to change it. Thanks!