From a2c7773d61bb19a1a3a3fff58120c40f41a6f7a8 Mon Sep 17 00:00:00 2001 From: Steve Grosbois Date: Tue, 2 Jan 2024 12:16:33 +0100 Subject: [PATCH] fix(import): Fixed import of new or already existing keys and values --- src/groups/group.entity.ts | 6 +- src/projects/dto/create-language.dto.ts | 8 +- src/projects/projects.service.ts | 97 ++++++++++----------- tests/languages/languages.e2e-spec.ts | 109 +++++++++++++++++------- 4 files changed, 135 insertions(+), 85 deletions(-) diff --git a/src/groups/group.entity.ts b/src/groups/group.entity.ts index 50025ba..55a3efe 100644 --- a/src/groups/group.entity.ts +++ b/src/groups/group.entity.ts @@ -25,7 +25,11 @@ export default class Group { @ApiProperty() readonly updatedAt: Date; + @Column("int") + @ApiProperty() + projectId: number; + @ManyToOne(() => Project, {onDelete: "CASCADE"}) @ApiHideProperty() public project: Project; -} \ No newline at end of file +} diff --git a/src/projects/dto/create-language.dto.ts b/src/projects/dto/create-language.dto.ts index 3df3677..3a354f3 100644 --- a/src/projects/dto/create-language.dto.ts +++ b/src/projects/dto/create-language.dto.ts @@ -1,6 +1,6 @@ import * as Joi from "@hapi/joi"; import BaseDto from "../../data/base.dto"; -import CreateValueDto from "../../translation/dto/create-value.dto"; +import CreateGroupDto from "../../groups/dto/create-group.dto"; export default class CreateLanguageDto extends BaseDto { public static schema: Joi.ObjectSchema = Joi.object({ @@ -9,11 +9,11 @@ export default class CreateLanguageDto extends BaseDto { .required() .max(80), - values: Joi + groups: Joi .array() .optional() }); public name: string; - public values: CreateValueDto[]; -} \ No newline at end of file + public groups: CreateGroupDto[]; +} diff --git a/src/projects/projects.service.ts b/src/projects/projects.service.ts index f62621c..4eade94 100644 --- a/src/projects/projects.service.ts +++ b/src/projects/projects.service.ts @@ -1,17 +1,17 @@ import {ForbiddenException, forwardRef, Inject, Injectable, Logger, MethodNotAllowedException, NotFoundException} from "@nestjs/common"; import {InjectRepository} from "@nestjs/typeorm"; -import {getManager, In, Repository} from "typeorm"; +import {In, Repository} from "typeorm"; import Group, {DefaultGroupName} from "../groups/group.entity"; import GroupService from "../groups/group.service"; -import Invitation, {InvitationTableName} from "../invitations/invitation.entity"; +import Invitation from "../invitations/invitation.entity"; import Language from "../languages/language.entity"; import Role from "../roles/role.enum"; import QuantityString from "../translation/quantity_string.enum"; import TranslationService from "../translation/translation.service"; import TranslationKey from "../translation/translation_key.entity"; import TranslationValue from "../translation/translation_value.entity"; -import UserProject, {UsersProjectsTableName} from "../users-projects/user_project.entity"; -import User, {UsersTableName} from "../users/user.entity"; +import UserProject from "../users-projects/user_project.entity"; +import User from "../users/user.entity"; import DetailedProject from "./detailed-model/detailed-project.model"; import CreateLanguageDto from "./dto/create-language.dto"; import CreateProjectDto from "./dto/create-project.dto"; @@ -132,17 +132,6 @@ export default class ProjectsService { } public async getUserProjects(userId: string): Promise { - /*const usersProjectsSubQuery = getManager() - .createQueryBuilder(UsersProjectsTableName, UsersProjectsTableName) - .select('"projectId"') - .where('"userId" = :id', {id: userId}); - - return await this.projectsRepository - .createQueryBuilder("project") - .where("project.id IN (" + usersProjectsSubQuery.getQuery() + ")") - .setParameters(usersProjectsSubQuery.getParameters()) - .getMany();*/ - return await this.projectsRepository.find({ where: { userProjects: { @@ -201,42 +190,54 @@ export default class ProjectsService { language.project = project; const createdLanguage = await this.languagesRepository.save(language); - // Find all translation keys of the project - const projectKeys: TranslationKey[] = await this.keyRepository.findBy({projectId: projectId}); - - if (!createLanguageDto.values || createLanguageDto.values.length === 0) { - // For each key, automatically create values in the new added language - await Promise.all(projectKeys.map(async (key) => { - if (key.isPlural) { - await Promise.all(Object.values(QuantityString).map(async (quantity) => { - const value = new TranslationValue(); - value.name = ""; - value.key = key; - value.quantityString = quantity; - value.language = language; - - return await this.valueRepository.save(value); - })); - } else { - const value = new TranslationValue(); - value.name = ""; - value.key = key; - value.language = language; + // We check if the language to create has groups + if (createLanguageDto.groups && createLanguageDto.groups.length > 0) { + await Promise.all(createLanguageDto.groups.map(async (groupToCreate) => { + // We check if the group already exists + let group = await this.groupRepository.findOneBy({name: groupToCreate.name, projectId: projectId}); + // If not, we create it + if (!group) { + group = new Group(); + group.project = project; + group.name = groupToCreate.name; + console.log("Group to create: ", group); + group = await this.groupRepository.save(group); + } - return await this.valueRepository.save(value); + // We check if the group has keys + if (groupToCreate.keys && groupToCreate.keys.length > 0) { + await Promise.all(groupToCreate.keys.map(async (keyToCreate) => { + // We check if the key already exists + let key = await this.keyRepository.findOneBy({name: keyToCreate.name, groupId: group.id}); + // If not, we create it + if (!key) { + key = new TranslationKey(); + key.project = project; + key.group = group; + key.name = keyToCreate.name; + key.isPlural = keyToCreate.isPlural; + key = await this.keyRepository.save(key); + } + + // We check if the key has values + if (keyToCreate.values && keyToCreate.values.length > 0) { + await Promise.all(keyToCreate.values.map(async (valueToCreate) => { + // We check if values already exists + const values = await this.valueRepository.findBy({keyId: key.id}); + // If not, we create it + if (!values || values.length === 0) { + const value = new TranslationValue(); + value.key = key; + value.name = valueToCreate.name; + value.language = createdLanguage; + value.quantityString = valueToCreate.quantityString; + await this.valueRepository.save(value); + } + })); + } + })); } })); - } else { - //Create values from DTO - await Promise.all(createLanguageDto.values.map(async (value) => { - const translationValue = new TranslationValue(); - translationValue.keyId = value.keyId; - translationValue.language = language; - translationValue.name = value.name; - translationValue.quantityString = value.quantityString; - - return await this.valueRepository.save(translationValue); - })) } return createdLanguage; diff --git a/tests/languages/languages.e2e-spec.ts b/tests/languages/languages.e2e-spec.ts index 98c1cbd..5bb3280 100644 --- a/tests/languages/languages.e2e-spec.ts +++ b/tests/languages/languages.e2e-spec.ts @@ -16,7 +16,8 @@ import CreateProjectDto from "../../src/projects/dto/create-project.dto"; import TranslationValue from "../../src/translation/translation_value.entity"; import TranslationKey from "../../src/translation/translation_key.entity"; import Group, {DefaultGroupName} from "../../src/groups/group.entity"; -import CreateValueDto from "../../src/translation/dto/create-value.dto"; +import CreateGroupDto from "../../src/groups/dto/create-group.dto"; +import CreateKeyDto from "../../src/translation/dto/create-key.dto"; describe("Languages of a project E2E", () => { let app: INestApplication; @@ -150,11 +151,9 @@ describe("Languages of a project E2E", () => { const createdLanguage: Language = languages[0]; - const values_singular = await valuesRepository.find({where: {language: createdLanguage, keyId: 1}}); - const values_plural = await valuesRepository.find({where: {language: createdLanguage, keyId: 2}}); + const values = await valuesRepository.find({where: {languageId: createdLanguage.id}}); - expect(values_singular.length).toBe(0); - expect(values_plural.length).toBe(0); + expect(values.length).toBe(0); }); it("Creating a language with existing values", async () => { @@ -164,23 +163,70 @@ describe("Languages of a project E2E", () => { .set("mocked_user_id", TestsHelpers.MOCKED_USER_ID_1) .send(new CreateLanguageDto({ name: "fr", - values: [ - new CreateValueDto({ - name: "singular_key_fr", - keyId: 1, - quantityString: null - }), new CreateValueDto({ - name: "plural_key_fr_zero", - keyId: 2, - quantityString: "zero" - }), new CreateValueDto({ - name: "plural_key_fr_one", - keyId: 2, - quantityString: "one" - }), new CreateValueDto({ - name: "plural_key_fr_other", - keyId: 2, - quantityString: "other" + groups: [ + // This group exists in the project, but the keys and values should be created + new CreateGroupDto({ + name: "common", + keys: [ + new CreateKeyDto({ + name: "singular_key", + isPlural: false, + values: [ + new CreateGroupDto({ + name: "singular_key_fr", + quantityString: null + }) + ], + }), + new CreateKeyDto({ + name: "plural_key", + isPlural: true, + values: [ + new CreateGroupDto({ + name: "plural_key_fr_zero", + quantityString: "zero" + }), new CreateGroupDto({ + name: "plural_key_fr_one", + quantityString: "one" + }), new CreateGroupDto({ + name: "plural_key_fr_other", + quantityString: "other" + }) + ], + }) + ] + }), + // This group is new and should be created + new CreateGroupDto({ + name: "new_group", + keys: [ + new CreateKeyDto({ + name: "singular_key", + isPlural: false, + values: [ + new CreateGroupDto({ + name: "singular_key_fr", + quantityString: null + }) + ], + }), + new CreateKeyDto({ + name: "plural_key", + isPlural: true, + values: [ + new CreateGroupDto({ + name: "plural_key_fr_zero", + quantityString: "zero" + }), new CreateGroupDto({ + name: "plural_key_fr_one", + quantityString: "one" + }), new CreateGroupDto({ + name: "plural_key_fr_other", + quantityString: "other" + }) + ], + }) + ] }) ] })); @@ -194,16 +240,15 @@ describe("Languages of a project E2E", () => { const createdLanguage: Language = languages[0]; - const values_singular = await valuesRepository.find({where: {language: createdLanguage, keyId: 1}}); - const values_plural = await valuesRepository.find({where: {language: createdLanguage, keyId: 2}}); - - /* TODO : There is a bug here, the values are not created - expect(values_singular.length).toBe(1); - expect(values_singular[0].name).toBe("singular_key_fr"); - expect(values_plural.length).toBe(1); - values_plural.forEach(value => { - expect(value.name).toBe(`plural_key_fr_${value.quantityString}`); - })*/ + const values = await valuesRepository.find({where: {languageId: createdLanguage.id}}); + expect(values.length).toBe(8); + values.forEach(value => { + if (value.quantityString) { + expect(value.name).toBe(`plural_key_fr_${value.quantityString}`); + } else { + expect(value.name).toBe(`singular_key_fr`); + } + }) }); it("Already existing language", async () => {