diff --git a/src/app/features/content/agents/agent-detail/agent-detail-smart.component.ts b/src/app/features/content/agents/agent-detail/agent-detail-smart.component.ts index a51b9c27..75a23e70 100644 --- a/src/app/features/content/agents/agent-detail/agent-detail-smart.component.ts +++ b/src/app/features/content/agents/agent-detail/agent-detail-smart.component.ts @@ -8,6 +8,7 @@ import { IAgentDTO, IAgentRequest, AgentTranslation, + IAgentTranslationRequest, } from '@models/agent'; import { AgentService } from '@core/services/api/agent.service'; import { Constants } from '@utils/constants'; @@ -242,7 +243,28 @@ export class AgentDetailSmartComponent implements OnInit { } private setTranslation(): void { - const requestPayload = this.buildPayload(); - // TODO: send request to update/create the translation records in the database + const requestPayload = this.buildPayload(), + translationForLanguage = this.agent.hasTranslationList.find( + (language) => language.code === this.languageCode, + ), + translationPayload: IAgentTranslationRequest = { + dynamicContent: requestPayload.dynamicContent, + }; + + translationForLanguage.hasTranslation + ? this.updateTranslation(translationPayload) + : this.createTranslation(translationPayload); + } + + private createTranslation(payload: IAgentTranslationRequest): void { + this.agentService + .createTranslation(payload, this.agent.id) + .subscribe(() => this.router.navigateByUrl('/content/agent-list')); + } + + private updateTranslation(payload: IAgentTranslationRequest): void { + this.agentService + .updateTranslation(payload, this.agent.id) + .subscribe(() => this.router.navigateByUrl('/content/agent-list')); } } diff --git a/src/app/infrastructure/core/services/api/agent.service.spec.ts b/src/app/infrastructure/core/services/api/agent.service.spec.ts index f3b161c3..3420e81e 100644 --- a/src/app/infrastructure/core/services/api/agent.service.spec.ts +++ b/src/app/infrastructure/core/services/api/agent.service.spec.ts @@ -15,6 +15,11 @@ import { AgentRequest, IAgentDTO, IAgentRequest, + IAgentTranslationRequest, + AgentTranslationRequest, + IAgentTranslation, + IAgentTranslationList, + AgentTranslation, } from '@models/agent'; import { getTranslocoModule } from '@utils/test/transloco-testing-module'; import { Logger } from '@utils/logger'; @@ -24,10 +29,53 @@ import { ToastrTestingModule } from '@utils/test/toastr-testing-module'; ? Logger.log('Unit skipped') : describe('[Unit] AgentService', () => { const route = `${environment.apiRoute}/agents`; - let testAgent: IAgentDTO; - let service: AgentService; let apiService: ApiService; let httpTestingController: HttpTestingController; + let service: AgentService; + const testAgent: IAgentDTO = new AgentDTO({ + id: 1, + name: 'Test Tester', + email: 'test@test.com', + dynamicContent: { + 'en-US': { + description: 'This is a test', + }, + }, + phoneNumber: '5595551234', + address: { + address1: '123 Main St.', + address2: '', + city: 'Fresno', + state: 'CA', + zipCode: '93721', + }, + }); + const anotherTestAgent: IAgentDTO = new AgentDTO({ + id: 2, + name: 'Test Tester Testing', + email: 'test+1@test.com', + dynamicContent: { + 'en-US': { + description: 'This is a test', + }, + }, + phoneNumber: '5595555555', + address: { + address1: '123 Main St.', + address2: '', + city: 'Fresno', + state: 'CA', + zipCode: '93721', + }, + }); + const testAgentSetTranslation: IAgentDTO = { + ...testAgent, + dynamicContent: { + 'es-MX': { + description: 'Esto es una prueba', + }, + }, + }; beforeEach(() => { TestBed.configureTestingModule({ @@ -44,25 +92,8 @@ import { ToastrTestingModule } from '@utils/test/toastr-testing-module'; apiService = TestBed.inject(ApiService); // Inject the http service and test controller for each test httpTestingController = TestBed.inject(HttpTestingController); - testAgent = new AgentDTO({ - id: 1, - name: 'Test Tester', - email: 'test@test.com', - dynamicContent: { - 'en-US': { - description: 'This is a test', - }, - }, - phoneNumber: '5595551234', - address: { - address1: '123 Main St.', - address2: '', - city: 'Fresno', - state: 'CA', - zipCode: '93721', - }, - }); }); + it('should be created', () => { expect(service).toBeTruthy(); }); @@ -90,8 +121,8 @@ import { ToastrTestingModule } from '@utils/test/toastr-testing-module'; describe('createAgent()', () => { it('should use POST as the request method', () => { - const newUser: IAgentRequest = new AgentRequest(); - service.createAgent(newUser).subscribe(); + const newAgent: IAgentRequest = new AgentRequest(); + service.createAgent(newAgent).subscribe(); const req = httpTestingController.expectOne(route); expect(req.request.method).toBe('POST'); @@ -182,4 +213,152 @@ import { ToastrTestingModule } from '@utils/test/toastr-testing-module'; expect(response).toEqual(expectedValue); }); }); + + describe('unpackAgentTranslationList', () => { + it('should return empty translated content when language code requested does not exist on the agent data', () => { + const agent: IAgentDTO = { ...testAgent }; + const content: IAgentTranslationList = agent.dynamicContent; + const expectedValue: IAgentTranslation = { + description: '', + }; + const value: IAgentTranslation = service.unpackAgentTranslationList( + content, + 'es-MX', + ); + + expect({ ...value }).toEqual({ ...expectedValue }); + }); + + it('should return the translated content for the requested agent', () => { + const agent: IAgentDTO = { ...testAgent }; + const content: IAgentTranslationList = agent.dynamicContent; + const expectedValue: IAgentTranslation = { + description: 'This is a test', + }; + const value: IAgentTranslation = service.unpackAgentTranslationList( + content, + 'en-US', + ); + + expect({ ...value }).toEqual({ ...expectedValue }); + }); + }); + + describe('getTranslatedAgent()', () => { + it('should return the equivalent to the entire JSON value of the requested agent when the language requested does not exist on the agent data', () => { + const agent: IAgentDTO = new AgentDTO({ ...testAgent }); + const expectedValue: IAgentDTO = { ...testAgent }; + const value: IAgentDTO = service.getTranslatedAgent(agent, 'es-MX'); + + expect({ ...value }).toEqual({ ...expectedValue }); + }); + + it('should return the requested agent with the requested translated content', () => { + const translatedContent = new AgentTranslation({ + description: 'This is a test', + }); + const agent: IAgentDTO = new AgentDTO({ ...testAgent }); + const expectedValue: IAgentDTO = { + ...testAgent, + translatedContentForDisplay: translatedContent, + }; + const value: IAgentDTO = service.getTranslatedAgent(agent, 'en-US'); + + expect({ ...value }).toEqual({ ...expectedValue }); + }); + }); + + describe('getTranslatedAgentList()', () => { + it('should return the agents in the list with translated content unpacked', () => { + const translatedContent = new AgentTranslation({ + description: 'This is a test', + }); + const agentList: IAgentDTO[] = new Array( + { ...testAgent }, + { ...anotherTestAgent }, + ); + const expectedValue: IAgentDTO[] = [ + { + ...testAgent, + translatedContentForDisplay: translatedContent, + }, + { + ...anotherTestAgent, + translatedContentForDisplay: translatedContent, + }, + ]; + const value: IAgentDTO[] = service.getTranslatedAgentList( + agentList, + 'en-US', + ); + + expect(value).toEqual(expectedValue); + }); + }); + + describe('createTranslation()', () => { + it('should use POST as the request method', () => { + const newTranslation: IAgentTranslationRequest = new AgentTranslationRequest(); + service.createTranslation(newTranslation, 1).subscribe(); + const translationRoute = `${route}/1/translations`; + const req = httpTestingController.expectOne(translationRoute); + + expect(req.request.method).toBe('POST'); + }); + + it('should return the requested agent on creation', () => { + const newAgentTranslation: IAgentTranslationRequest = new AgentTranslationRequest( + { + dynamicContent: { + 'es-MX': { + description: 'Esto es una prueba', + }, + }, + }, + ); + const expectedValue: IAgentDTO = { ...testAgentSetTranslation }; + let response: IAgentDTO; + spyOn(apiService, 'post').and.returnValue( + observableOf(expectedValue), + ); + + service.createTranslation(newAgentTranslation, 1).subscribe((res) => { + response = res; + }); + + expect(response).toEqual(expectedValue); + }); + }); + + describe('updateTranslation()', () => { + it('should use PUT as the request method', () => { + const agentTranslation: IAgentTranslationRequest = new AgentTranslationRequest(); + service.updateTranslation(agentTranslation, 1).subscribe(); + const translationRoute = `${route}/1/translations`; + const req = httpTestingController.expectOne(translationRoute); + + expect(req.request.method).toBe('PUT'); + }); + + it('should return the requested agent on successful update', () => { + const agentTranslation: IAgentTranslationRequest = new AgentTranslationRequest( + { + dynamicContent: { + 'es-MX': { + description: 'Esto es una prueba', + }, + }, + }, + ); + const expectedValue: IAgentDTO = { ...testAgentSetTranslation }; + let response: IAgentDTO; + spyOn(apiService, 'put').and.returnValue(observableOf(expectedValue)); + + service.updateTranslation(agentTranslation, 1).subscribe((res) => { + response = res; + }); + + expect(response).toEqual(expectedValue); + }); + }); }); diff --git a/src/app/infrastructure/core/services/api/agent.service.ts b/src/app/infrastructure/core/services/api/agent.service.ts index 6829fd9d..8db7bb21 100644 --- a/src/app/infrastructure/core/services/api/agent.service.ts +++ b/src/app/infrastructure/core/services/api/agent.service.ts @@ -10,6 +10,7 @@ import { IAgentRequest, IAgentTranslation, IAgentTranslationList, + IAgentTranslationRequest, } from '@models/agent'; import { environment } from '@env/environment'; import { Message } from '@models/message'; @@ -130,4 +131,42 @@ export class AgentService { return agentList; } + + public createTranslation( + payload: IAgentTranslationRequest, + agentId: number, + ): Observable { + const endpoint = `${this.url}/${agentId}/translations`; + + return this.apiService + .post(endpoint, payload) + .pipe( + tap(() => { + const notificationTranslationKeys: INotificationTranslationKey = new NotificationTranslationKey(); + const message: Message = new Message({ + message: notificationTranslationKeys.translationCreated, + }); + return this.notificationService.showSuccess([message]); + }), + ); + } + + public updateTranslation( + payload: IAgentTranslationRequest, + agentId: number, + ): Observable { + const endpoint = `${this.url}/${agentId}/translations`; + + return this.apiService + .put(endpoint, payload) + .pipe( + tap(() => { + const notificationTranslationKeys: INotificationTranslationKey = new NotificationTranslationKey(); + const message: Message = new Message({ + message: notificationTranslationKeys.translationUpdated, + }); + return this.notificationService.showSuccess([message]); + }), + ); + } } diff --git a/src/app/infrastructure/models/agent.ts b/src/app/infrastructure/models/agent.ts index e0658e5d..72344f8b 100644 --- a/src/app/infrastructure/models/agent.ts +++ b/src/app/infrastructure/models/agent.ts @@ -88,3 +88,17 @@ export class AgentRequest implements IAgentRequest { } } } + +export interface IAgentTranslationRequest { + dynamicContent: IAgentTranslationList; +} + +export class AgentTranslationRequest implements IAgentTranslationRequest { + dynamicContent: IAgentTranslationList = new AgentTranslationList(); + + constructor(configOverride?: Partial) { + if (configOverride) { + Object.assign(this, configOverride); + } + } +} diff --git a/src/app/infrastructure/models/translation/notification.ts b/src/app/infrastructure/models/translation/notification.ts index d088abc6..18d9d8d8 100644 --- a/src/app/infrastructure/models/translation/notification.ts +++ b/src/app/infrastructure/models/translation/notification.ts @@ -24,6 +24,8 @@ export interface INotificationTranslationKey { returningToDashboard: string; returningToUserList: string; serverError: string; + translationCreated: string; + translationUpdated: string; unableToCompleteRequest: string; unableToLoadAgencies: string; unableToLoadAgency: string; @@ -64,6 +66,8 @@ export class NotificationTranslationKey implements INotificationTranslationKey { returningToDashboard: string = 'notification.returningToDashboard'; returningToUserList: string = 'notification.returningToUserList'; serverError: string = 'notification.serverError'; + translationCreated: string = 'notification.translationCreated'; + translationUpdated: string = 'notification.translationUpdated'; unableToCompleteRequest: string = 'notification.unableToCompleteRequest'; unableToLoadAgencies: string = 'notification.unableToLoadAgencies'; unableToLoadAgency: string = 'notification.unableToLoadAgency'; diff --git a/src/assets/i18n/en-US.json b/src/assets/i18n/en-US.json index d9561c07..d1735dff 100644 --- a/src/assets/i18n/en-US.json +++ b/src/assets/i18n/en-US.json @@ -186,6 +186,8 @@ "returningToDashboard": "Returning to the dashboard.", "returningToUserList": "Returning to user list.", "serverError": "Server Error.", + "translationCreated": "Translation {{ notification.created }}.", + "translationUpdated": "Translation {{ notification.updated }}.", "unableToCompleteRequest": "Unable to complete request.", "unableToLoadAgencies": "Unable to load agencies. {{ notification.returningToUserList }}", "unableToLoadAgency": "Unable to load agency. Returning to agency list.", diff --git a/src/assets/i18n/es-MX.json b/src/assets/i18n/es-MX.json index 4a71bc8f..88f3f864 100644 --- a/src/assets/i18n/es-MX.json +++ b/src/assets/i18n/es-MX.json @@ -186,6 +186,8 @@ "returningToDashboard": "Volviendo al tablero.", "returningToUserList": "Volviendo a la lista de usuarios.", "serverError": "Error del Servidor.", + "translationCreated": "Traducción {{ notification.created }}.", + "translationUpdated": "Traducción {{ notification.updated }}.", "unableToCompleteRequest": "No se pudo completar la solicitud.", "unableToLoadAgencies": "No se pueden cargar agencias. {{ notification.returningToUserList }}", "unableToLoadAgency": "No se pudo cargar la agencia. Volviendo a la lista de agencias.", diff --git a/src/assets/i18n/tl.json b/src/assets/i18n/tl.json index e77c24f3..3d663f9a 100644 --- a/src/assets/i18n/tl.json +++ b/src/assets/i18n/tl.json @@ -186,6 +186,8 @@ "returningToDashboard": "Bumabalik sa dashboard.", "returningToUserList": "Bumabalik sa listahan ng gumagamit.", "serverError": "Error sa Server.", + "translationCreated": "Nilikha ang pagsasalin.", + "translationUpdated": "Na-update ang pagsasalin.", "unableToCompleteRequest": "Hindi makumpleto ang kahilingan.", "unableToLoadAgencies": "Hindi mai-load ang mga ahensya. {{ notification.returningToUserList }}", "unableToLoadAgency": "Hindi mai-load ang ahensya. Bumabalik sa listahan ng ahensya.", diff --git a/src/assets/i18n/vi-VN.json b/src/assets/i18n/vi-VN.json index 7221b478..b2bc6990 100644 --- a/src/assets/i18n/vi-VN.json +++ b/src/assets/i18n/vi-VN.json @@ -184,6 +184,8 @@ "returningToDashboard": "Quay lại trang tổng quan.", "returningToUserList": "Quay lại danh sách người dùng.", "serverError": "Lỗi máy chủ.", + "translationCreated": "Bản dịch đã tạo.", + "translationUpdated": "Đã cập nhật bản dịch.", "unableToCompleteRequest": "Không thể hoàn thành yêu cầu.", "unableToLoadAgencies": "Không thể tải đại lý. {{ notification.returningToUserList }}", "unableToLoadAgency": "Không thể tải đại lý. Quay lại danh sách đại lý.",