From ad38c3c52a91c5922a1e44ebcd1f24ab8d563342 Mon Sep 17 00:00:00 2001 From: William Craig Date: Mon, 27 Nov 2023 16:52:27 +0000 Subject: [PATCH] VIH-10324 allow users to edit justice user properties (#1308) * Updated form * updated chart pr value * Test tweak * Added back end validation failure display in ui * number * added an additional test for coverage of validation fail condition * code coverage * updated package (cherry picked from commit ccc12dfc8fc165e23e11b5a30beae36456517953) --- .../packages.lock.json | 6 +-- .../AdminWebsite.UnitTests/packages.lock.json | 6 +-- AdminWebsite/AdminWebsite/AdminWebsite.csproj | 2 +- .../justice-user-form.component.spec.ts | 39 +++++++++++++++++-- .../justice-user-form.component.ts | 23 ++++++++--- .../src/app/services/clients/api-client.ts | 12 ++++++ .../services/justice-users.service.spec.ts | 5 ++- .../src/app/services/justice-users.service.ts | 5 ++- AdminWebsite/AdminWebsite/packages.lock.json | 6 +-- charts/vh-admin-web/values.dev.template.yaml | 2 +- 10 files changed, 84 insertions(+), 22 deletions(-) diff --git a/AdminWebsite/AdminWebsite.IntegrationTests/packages.lock.json b/AdminWebsite/AdminWebsite.IntegrationTests/packages.lock.json index fe922575b..2554b0682 100644 --- a/AdminWebsite/AdminWebsite.IntegrationTests/packages.lock.json +++ b/AdminWebsite/AdminWebsite.IntegrationTests/packages.lock.json @@ -102,8 +102,8 @@ }, "BookingsApi.Client": { "type": "Transitive", - "resolved": "1.49.10", - "contentHash": "oXH1qyRZhkrbVbdZB7QsO8O0a/6SRCrB71Hb0leiRNUGr/xb0IYdqpaTr6imTeo6zimGxieMiu9uKMsnFpVA/w==", + "resolved": "1.49.13", + "contentHash": "3+T2Q9IbsFFTVFRY7vTpNbfChHjilgQQIrAm4ptwPoH6HP9UWtrrM/JOj8/esfOMlajZvBziSXd7qfQPPnepuA==", "dependencies": { "Microsoft.AspNetCore.Mvc.Core": "2.2.5" } @@ -2101,7 +2101,7 @@ "type": "Project", "dependencies": { "AspNetCore.HealthChecks.Uris": "[6.0.3, )", - "BookingsApi.Client": "[1.49.10, )", + "BookingsApi.Client": "[1.49.13, )", "FluentValidation.AspNetCore": "[10.4.0, )", "LaunchDarkly.ServerSdk": "[7.0.3, )", "MicroElements.Swashbuckle.FluentValidation": "[5.7.0, )", diff --git a/AdminWebsite/AdminWebsite.UnitTests/packages.lock.json b/AdminWebsite/AdminWebsite.UnitTests/packages.lock.json index d09fa2d62..50e797b1f 100644 --- a/AdminWebsite/AdminWebsite.UnitTests/packages.lock.json +++ b/AdminWebsite/AdminWebsite.UnitTests/packages.lock.json @@ -107,8 +107,8 @@ }, "BookingsApi.Client": { "type": "Transitive", - "resolved": "1.49.10", - "contentHash": "oXH1qyRZhkrbVbdZB7QsO8O0a/6SRCrB71Hb0leiRNUGr/xb0IYdqpaTr6imTeo6zimGxieMiu9uKMsnFpVA/w==", + "resolved": "1.49.13", + "contentHash": "3+T2Q9IbsFFTVFRY7vTpNbfChHjilgQQIrAm4ptwPoH6HP9UWtrrM/JOj8/esfOMlajZvBziSXd7qfQPPnepuA==", "dependencies": { "Microsoft.AspNetCore.Mvc.Core": "2.2.5" } @@ -1979,7 +1979,7 @@ "type": "Project", "dependencies": { "AspNetCore.HealthChecks.Uris": "[6.0.3, )", - "BookingsApi.Client": "[1.49.10, )", + "BookingsApi.Client": "[1.49.13, )", "FluentValidation.AspNetCore": "[10.4.0, )", "LaunchDarkly.ServerSdk": "[7.0.3, )", "MicroElements.Swashbuckle.FluentValidation": "[5.7.0, )", diff --git a/AdminWebsite/AdminWebsite/AdminWebsite.csproj b/AdminWebsite/AdminWebsite/AdminWebsite.csproj index 3b5b1c15c..262cbaf7a 100644 --- a/AdminWebsite/AdminWebsite/AdminWebsite.csproj +++ b/AdminWebsite/AdminWebsite/AdminWebsite.csproj @@ -32,7 +32,7 @@ - + diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/manage-team/justice-user-form/justice-user-form.component.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/manage-team/justice-user-form/justice-user-form.component.spec.ts index c58134d1b..9d1ce95d0 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/manage-team/justice-user-form/justice-user-form.component.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/manage-team/justice-user-form/justice-user-form.component.spec.ts @@ -101,9 +101,9 @@ describe('JusticeUserFormComponent', () => { component.ngOnChanges(changes); // assert - expect(component.form.controls.contactTelephone.disabled).toBeTruthy(); - expect(component.form.controls.firstName.disabled).toBeTruthy(); - expect(component.form.controls.lastName.disabled).toBeTruthy(); + expect(component.form.controls.contactTelephone.disabled).toBeFalsy(); + expect(component.form.controls.firstName.disabled).toBeFalsy(); + expect(component.form.controls.lastName.disabled).toBeFalsy(); expect(component.form.controls.username.disabled).toBeTruthy(); }); }); @@ -189,7 +189,7 @@ describe('JusticeUserFormComponent', () => { expect(component.failedSaveMessage).toBe(Constants.Error.JusticeUserForm.SaveErrorDuplicateUser); })); - it('should set control errors for properties returned by a validationproblem object from the api', fakeAsync(() => { + it('should set control errors for properties returned by a validationproblem object from the api, from add mode', fakeAsync(() => { // arrange const validationProblem = new ValidationProblemDetails({ errors: { @@ -210,6 +210,37 @@ describe('JusticeUserFormComponent', () => { // act component.onSave(); + component.mode = 'add'; + tick(); + + // assert + expect(component.failedSaveMessage).toBe(validationProblem.title); + expect(component.form.controls.firstName.errors.errorMessage).toContain(validationProblem.errors.FirstName); + expect(component.form.controls.lastName.errors.errorMessage).toContain(validationProblem.errors.LastName); + })); + + it('should set control errors for properties returned by a validationproblem object from the api, from edit endpoint', fakeAsync(() => { + // arrange + const validationProblem = new ValidationProblemDetails({ + errors: { + FirstName: ['First name is required'], + LastName: ['Last Name is required'], + ContactEmail: ['Contact Email is required'] + }, + type: 'https://tools.ietf.org/html/rfc7231#section-6.5.1', + title: 'One or more validation errors occurred.', + status: 400 + }); + + justiceUsersServiceSpy.editJusticeUser.and.returnValue( + throwError( + () => new BookHearingException('Bad Request', 400, 'One or more validation errors occurred.', null, validationProblem) + ) + ); + + // act + component.mode = 'edit'; + component.onSave(); tick(); // assert diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/manage-team/justice-user-form/justice-user-form.component.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/manage-team/justice-user-form/justice-user-form.component.ts index 1eb802e49..c95ba3455 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/manage-team/justice-user-form/justice-user-form.component.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/manage-team/justice-user-form/justice-user-form.component.ts @@ -90,7 +90,7 @@ export class JusticeUserFormComponent implements OnChanges { ngOnChanges(changes: SimpleChanges): void { const mode = changes['mode']; if (mode.currentValue === 'edit') { - ['firstName', 'lastName', 'username', 'contactTelephone'].forEach(field => this.form.controls[field].disable()); + ['username'].forEach(field => this.form.controls[field].disable()); } } @@ -170,10 +170,23 @@ export class JusticeUserFormComponent implements OnChanges { private updateExistingUser() { const roles = this.getRoles(); - this.justiceUserService.editJusticeUser(this._justiceUser.id, this.form.getRawValue().username, roles).subscribe({ - next: newJusticeUser => this.onSaveSucceeded(newJusticeUser), - error: (error: string | BookHearingException) => this.onSaveFailed(error) - }); + this.justiceUserService + .editJusticeUser( + this._justiceUser.id, + this.form.getRawValue().username, + this.form.getRawValue().firstName, + this.form.getRawValue().lastName, + this.form.getRawValue().contactTelephone, + roles + ) + .pipe( + catchError((error: string | BookHearingException) => { + this.onSaveFailed(error); + this.cdRef.markForCheck(); + return NEVER; + }) + ) + .subscribe((newJusticeUser: JusticeUserResponse) => this.onSaveSucceeded(newJusticeUser)); } private getRoles(): JusticeUserRole[] { diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/clients/api-client.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/clients/api-client.ts index fd6e748d1..24cbc02f4 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/clients/api-client.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/clients/api-client.ts @@ -8286,6 +8286,9 @@ export class EditJusticeUserRequest implements IEditJusticeUserRequest { id?: string; username?: string | undefined; roles?: JusticeUserRole[] | undefined; + first_name?: string | undefined; + last_name?: string | undefined; + contact_telephone?: string | undefined; constructor(data?: IEditJusticeUserRequest) { if (data) { @@ -8303,6 +8306,9 @@ export class EditJusticeUserRequest implements IEditJusticeUserRequest { this.roles = [] as any; for (let item of _data['roles']) this.roles!.push(item); } + this.first_name = _data['first_name']; + this.last_name = _data['last_name']; + this.contact_telephone = _data['contact_telephone']; } } @@ -8321,6 +8327,9 @@ export class EditJusticeUserRequest implements IEditJusticeUserRequest { data['roles'] = []; for (let item of this.roles) data['roles'].push(item); } + data['first_name'] = this.first_name; + data['last_name'] = this.last_name; + data['contact_telephone'] = this.contact_telephone; return data; } } @@ -8329,6 +8338,9 @@ export interface IEditJusticeUserRequest { id?: string; username?: string | undefined; roles?: JusticeUserRole[] | undefined; + first_name?: string | undefined; + last_name?: string | undefined; + contact_telephone?: string | undefined; } export enum JusticeUserRole { diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/justice-users.service.spec.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/justice-users.service.spec.ts index 8f140f96c..b0657b878 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/justice-users.service.spec.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/justice-users.service.spec.ts @@ -198,10 +198,13 @@ describe('JusticeUsersService', () => { const request = new EditJusticeUserRequest({ id, username, + first_name: firstName, + last_name: lastName, + contact_telephone: telephone, roles: roles }); - combineLatest([service.allUsers$, service.editJusticeUser(id, username, roles)]).subscribe( + combineLatest([service.allUsers$, service.editJusticeUser(id, username, firstName, lastName, telephone, roles)]).subscribe( ([_, result]: [JusticeUserResponse[], JusticeUserResponse]) => { expect(clientApiSpy.getUserList).toHaveBeenCalledTimes(2); expect(result).toEqual(existingUser); diff --git a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/justice-users.service.ts b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/justice-users.service.ts index c16e868a5..869f07c43 100644 --- a/AdminWebsite/AdminWebsite/ClientApp/src/app/services/justice-users.service.ts +++ b/AdminWebsite/AdminWebsite/ClientApp/src/app/services/justice-users.service.ts @@ -67,10 +67,13 @@ export class JusticeUsersService { return this.apiClient.addNewJusticeUser(request).pipe(tap(() => this.refresh$.next())); } - editJusticeUser(id: string, username: string, roles: JusticeUserRole[]) { + editJusticeUser(id: string, username: string, firstName: string, lastName: string, telephone: string, roles: JusticeUserRole[]) { const request = new EditJusticeUserRequest({ id, username, + first_name: firstName, + last_name: lastName, + contact_telephone: telephone, roles }); return this.apiClient.editJusticeUser(request).pipe(tap(() => this.refresh$.next())); diff --git a/AdminWebsite/AdminWebsite/packages.lock.json b/AdminWebsite/AdminWebsite/packages.lock.json index a825bcc20..22d4c5f7e 100644 --- a/AdminWebsite/AdminWebsite/packages.lock.json +++ b/AdminWebsite/AdminWebsite/packages.lock.json @@ -14,9 +14,9 @@ }, "BookingsApi.Client": { "type": "Direct", - "requested": "[1.49.10, )", - "resolved": "1.49.10", - "contentHash": "oXH1qyRZhkrbVbdZB7QsO8O0a/6SRCrB71Hb0leiRNUGr/xb0IYdqpaTr6imTeo6zimGxieMiu9uKMsnFpVA/w==", + "requested": "[1.49.13, )", + "resolved": "1.49.13", + "contentHash": "3+T2Q9IbsFFTVFRY7vTpNbfChHjilgQQIrAm4ptwPoH6HP9UWtrrM/JOj8/esfOMlajZvBziSXd7qfQPPnepuA==", "dependencies": { "Microsoft.AspNetCore.Mvc.Core": "2.2.5" } diff --git a/charts/vh-admin-web/values.dev.template.yaml b/charts/vh-admin-web/values.dev.template.yaml index 8cc08891d..c653d0aa1 100644 --- a/charts/vh-admin-web/values.dev.template.yaml +++ b/charts/vh-admin-web/values.dev.template.yaml @@ -8,4 +8,4 @@ java: AZUREAD__POSTLOGOUTREDIRECTURI: https://${SERVICE_FQDN}/logout AZUREAD__REDIRECTURI: https://${SERVICE_FQDN}/home DOM1__POSTLOGOUTREDIRECTURI: https://${SERVICE_FQDN}/logout - DOM1__REDIRECTURI: https://${SERVICE_FQDN}/home + DOM1__REDIRECTURI: https://${SERVICE_FQDN}/home \ No newline at end of file