diff --git a/src/invitations/dto/create-invitation.dto.ts b/src/invitations/dto/create-invitation.dto.ts index 129a1f8..60691aa 100644 --- a/src/invitations/dto/create-invitation.dto.ts +++ b/src/invitations/dto/create-invitation.dto.ts @@ -16,10 +16,18 @@ export default class CreateInvitationDto extends BaseDto { projectId: Joi .number() - .required() + .required(), + + sourceLanguagesIds: Joi + .string(), + + targetLanguagesIds: Joi + .string() }); public projectId: number; public email: string; public role: string; -} \ No newline at end of file + public sourceLanguagesIds: string; + public targetLanguagesIds: string; +} diff --git a/src/invitations/invitation.entity.ts b/src/invitations/invitation.entity.ts index 5ffb559..5768108 100644 --- a/src/invitations/invitation.entity.ts +++ b/src/invitations/invitation.entity.ts @@ -51,4 +51,12 @@ export default class Invitation { @CreateDateColumn() @ApiProperty() readonly createdAt: Date; -} \ No newline at end of file + + @Column({nullable: true}) + @ApiProperty() + sourceLanguagesIds: string; + + @Column({nullable: true}) + @ApiProperty() + targetLanguagesIds: string; +} diff --git a/src/invitations/invitation.service.ts b/src/invitations/invitation.service.ts index 0c130fd..21df746 100644 --- a/src/invitations/invitation.service.ts +++ b/src/invitations/invitation.service.ts @@ -37,6 +37,8 @@ export default class InvitationService { invitation.guest = guest; invitation.owner = owner; invitation.project = project; + invitation.sourceLanguagesIds = createInvitationDto.sourceLanguagesIds; + invitation.targetLanguagesIds = createInvitationDto.targetLanguagesIds; invitation.role = createInvitationDto.role; return await this.invitationRepository.save(invitation); } @@ -57,19 +59,25 @@ export default class InvitationService { } public async acceptInvitation(userId: string, invitationId: number): Promise { - const invitation = await this.invitationRepository.findOneById(invitationId); + const invitation = await this.invitationRepository.findOneBy({id: invitationId}); if (!invitation) { throw new NotFoundException(); } if (userId !== invitation.guestId) { throw new ForbiddenException(null, "Can't accept invitation for someone else"); } - await this.projectsService.createUserProjectRelation(userId, invitation.projectId, invitation.role); + await this.projectsService.createUserProjectRelation( + userId, + invitation.projectId, + invitation.role, + invitation.sourceLanguagesIds, + invitation.targetLanguagesIds + ); await this.invitationRepository.delete(invitationId); } public async declineInvitation(userId: string, invitationId: number): Promise { - const invitation = await this.invitationRepository.findOneById(invitationId); + const invitation = await this.invitationRepository.findOneBy({id: invitationId}); if (!invitation) { throw new NotFoundException(); } @@ -80,7 +88,7 @@ export default class InvitationService { } public async deleteInvitation(userId: string, invitationId: number): Promise { - const invitation = await this.invitationRepository.findOneById(invitationId); + const invitation = await this.invitationRepository.findOneBy({id: invitationId}); if (!invitation) { throw new NotFoundException(); } @@ -94,4 +102,4 @@ export default class InvitationService { } await this.invitationRepository.delete(invitationId); } -} \ No newline at end of file +} diff --git a/src/languages/language.entity.ts b/src/languages/language.entity.ts index 88469a5..98c6973 100644 --- a/src/languages/language.entity.ts +++ b/src/languages/language.entity.ts @@ -5,6 +5,13 @@ import {PostgresUniqueKeys} from "../data/database/postgres-unique-keys.enum"; export const ProjectLanguagesTableName: string = "project_languages"; + +export enum LanguageAccess { + all = "all", + source = "source", + target = "target" +} + @Entity(ProjectLanguagesTableName) @Unique(PostgresUniqueKeys.LanguageInProject, ["name", "project"]) export default class Language { @@ -32,4 +39,7 @@ export default class Language { @UpdateDateColumn() @ApiProperty() readonly updatedAt: Date; -} \ No newline at end of file + + @ApiProperty() + public access: LanguageAccess = LanguageAccess.all; +} diff --git a/src/projects/projects.service.ts b/src/projects/projects.service.ts index f3bfb65..08ff637 100644 --- a/src/projects/projects.service.ts +++ b/src/projects/projects.service.ts @@ -4,7 +4,7 @@ import {In, Repository} from "typeorm"; import Group, {DefaultGroupName} from "../groups/group.entity"; import GroupService from "../groups/group.service"; import Invitation from "../invitations/invitation.entity"; -import Language from "../languages/language.entity"; +import Language, {LanguageAccess} from "../languages/language.entity"; import Role from "../roles/role.enum"; import TranslationService from "../translation/translation.service"; import TranslationKey from "../translation/translation_key.entity"; @@ -45,11 +45,13 @@ export default class ProjectsService { private readonly logger = new Logger("ProjectsService"); - public async createUserProjectRelation(userId: string, projectId: number, role: Role): Promise { + public async createUserProjectRelation(userId: string, projectId: number, role: Role, sourceLanguagesIds: string = null, targetLanguagesIds: string = null): Promise { return this.usersProjectsRepository.save({ "projectId": projectId, "userId": userId, - "role": role + "role": role, + "sourceLanguagesIds": sourceLanguagesIds, + "targetLanguagesIds": targetLanguagesIds, }); } @@ -243,18 +245,37 @@ export default class ProjectsService { public async getAllLanguages(userId: string, projectId: number): Promise { const project = await this.getProject(userId, projectId); - return await this.languagesRepository.find({ + const languages = await this.languagesRepository.find({ where: { project: { id: project.id } } }); + const userProject = project.userProjects.find(relation => relation.userId === userId); + if (userProject.sourceLanguagesIds === null || userProject.targetLanguagesIds === null) { + return languages; + } else { + const sourceLanguagesIds = userProject.sourceLanguagesIds.split(",").map(id => parseInt(id)); + const targetLanguagesIds = userProject.targetLanguagesIds.split(",").map(id => parseInt(id)); + const languagesIds = sourceLanguagesIds.concat(targetLanguagesIds); + return languages + .filter(language => languagesIds.indexOf(language.id) >= 0) + .map(language => { + if (sourceLanguagesIds.indexOf(language.id) >= 0) { + language.access = LanguageAccess.source; + } + if (targetLanguagesIds.indexOf(language.id) >= 0) { + language.access = LanguageAccess.target; + } + return language + }); + } } public async getLanguage(userId: string, projectId: number, languageId: number): Promise { const project = await this.getProject(userId, projectId); - const language: Language = await this.languagesRepository.findOneById(languageId); + const language: Language = await this.languagesRepository.findOneBy({id: languageId}); if (!language || language.projectId != project.id) { throw new NotFoundException(); diff --git a/src/users-projects/user_project.entity.ts b/src/users-projects/user_project.entity.ts index 732a4b8..c693d18 100644 --- a/src/users-projects/user_project.entity.ts +++ b/src/users-projects/user_project.entity.ts @@ -31,4 +31,12 @@ export default class UserProject { @Column() @ApiProperty() public role: Role; -} \ No newline at end of file + + @Column({nullable: true}) + @ApiProperty() + sourceLanguagesIds: string; + + @Column({nullable: true}) + @ApiProperty() + targetLanguagesIds: string; +} diff --git a/tests/invitations/invitations.e2e-spec.ts b/tests/invitations/invitations.e2e-spec.ts index ebba781..a829d84 100644 --- a/tests/invitations/invitations.e2e-spec.ts +++ b/tests/invitations/invitations.e2e-spec.ts @@ -131,7 +131,9 @@ describe("Invitations", () => { .send(new CreateInvitationDto({ email: "user_c@lokapp.io", projectId: populatedProjects[0].id, - role: Role.Manager + role: Role.Manager, + sourceLanguagesIds: "1", + targetLanguagesIds: "2" })); expect(invitationResp.status).toEqual(201); });