diff --git a/app/src/app/components/view-profile/view-profile.component.html b/app/src/app/components/view-profile/view-profile.component.html index 5d69200c0..442a4b83e 100644 --- a/app/src/app/components/view-profile/view-profile.component.html +++ b/app/src/app/components/view-profile/view-profile.component.html @@ -1,26 +1,26 @@
- arrow_back + arrow_back

{{'APP.EDIT_PROFILE.MY_PROFILE' | translate}}

-
- +
+ {{ generalSectionDropdown ? 'expand_more' : 'chevron_right'}}

{{'APP.EDIT_PROFILE.GENERAL' | translate}}

-
- -
@@ -56,6 +56,9 @@

{{personDetails?.telephone}}

+ + {{ 'APP.EDIT_PROFILE.INVALID_INPUT' | translate }} +
@@ -63,62 +66,9 @@

{{personDetails?.mobile}}

-
-
-
- - -
-
-
- - {{ loginSectionDropdown ? 'expand_more' : 'chevron_right'}} -

{{'APP.EDIT_PROFILE.LOGIN' | translate}}

-
- -
- -
-
- - -
-
- -
-
-
-

{{'APP.EDIT_PROFILE.USERNAME' | translate}}

-

{{personDetails?.id}}

-
- -
-

{{'APP.EDIT_PROFILE.EMAIL' | translate}}

-

{{personDetails?.email}}

-
- -
-

{{'APP.EDIT_PROFILE.PASSWORD' | translate}}

-

-
- -
-

{{'APP.EDIT_PROFILE.OLD_PASSWORD' | translate}}

- - -
- -
-

{{'APP.EDIT_PROFILE.NEW_PASSWORD' | translate}}

- -
- -
-

{{'APP.EDIT_PROFILE.VERIFY_PASSWORD' | translate}}

- + + {{ 'APP.EDIT_PROFILE.INVALID_INPUT' | translate }} +
@@ -126,29 +76,31 @@
-
- +
+ {{ contactSectionDropdown ? 'expand_more' : 'chevron_right'}}

{{'APP.EDIT_PROFILE.COMPANY_DETAILS' | translate}}

-
- -
-
+

{{'APP.EDIT_PROFILE.NAME' | translate}}

-

{{personDetails?.company?.organization}}

+

{{personDetails?.company?.organization}}

+
@@ -157,28 +109,32 @@
- -
-

{{'APP.EDIT_PROFILE.POST_CODE' | translate}}

+ +
+

{{'APP.EDIT_PROFILE.POSTCODE' | translate}}

{{personDetails?.company?.postcode}}

-
- -
+ +

{{'APP.EDIT_PROFILE.TELEPHONE' | translate}}

{{personDetails?.company?.telephone}}

- + + {{ 'APP.EDIT_PROFILE.INVALID_INPUT' | translate }} +
- +

{{'APP.EDIT_PROFILE.EMAIL' | translate}}

{{personDetails?.company?.email}}

+ + {{ 'APP.EDIT_PROFILE.INVALID_INPUT' | translate }} +
diff --git a/app/src/app/components/view-profile/view-profile.component.scss b/app/src/app/components/view-profile/view-profile.component.scss index db59b801b..5b40d3808 100644 --- a/app/src/app/components/view-profile/view-profile.component.scss +++ b/app/src/app/components/view-profile/view-profile.component.scss @@ -52,7 +52,7 @@ app-view-profile { border-bottom-right-radius: 0; } - .app-profile-general-div { + .app-profile-general-section { display: flex; width: 60%; padding-top: 1rem; @@ -92,6 +92,8 @@ app-view-profile { .app-general-edit { margin: 0.7rem; background: var(--theme-grey-text-background-color); + height: 30px; + margin: 1rem; } .app-general-edit:hover { @@ -99,12 +101,18 @@ app-view-profile { } .app-general-cancel-btn { - margin: 0.7rem; + height: 30px; + margin: 1rem; + margin-left: .5rem; background-color: var(--theme-grey-text-background-color); + padding-top: .25px; } .app-general-save-btn { - margin: 0.7rem; + width: 75px; + height: 30px; + margin: 1rem; + margin-left: .5rem; color: white; background-color: var(--theme-blue-button-color); } @@ -177,4 +185,9 @@ app-view-profile { border: 1px solid var(--theme-grey-background-color); border-radius: 1rem; } + + .app-error-message { + padding-top: 2rem; + padding-left: .5rem; + } } diff --git a/app/src/app/components/view-profile/view-profile.component.spec.ts b/app/src/app/components/view-profile/view-profile.component.spec.ts new file mode 100644 index 000000000..b928f0939 --- /dev/null +++ b/app/src/app/components/view-profile/view-profile.component.spec.ts @@ -0,0 +1,165 @@ +/* + * Copyright © 2005 - 2021 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +import { TestBed, ComponentFixture } from '@angular/core/testing'; +import { AppConfigModule } from '@alfresco/adf-core'; +import { ViewProfileComponent } from './view-profile.component'; +import { AppTestingModule } from '../../testing/app-testing.module'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { By } from '@angular/platform-browser'; +import { Router } from '@angular/router'; + +describe('ViewProfileComponent', () => { + let fixture: ComponentFixture; + let component: ViewProfileComponent; + let router: Router; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [AppTestingModule, AppConfigModule, FormsModule, ReactiveFormsModule], + declarations: [ViewProfileComponent] + }); + + fixture = TestBed.createComponent(ViewProfileComponent); + component = fixture.componentInstance; + router = TestBed.inject(Router); + router.initialNavigation(); + }); + + it('should company dropdown remains close', async () => { + expect(component.loginSectionDropdown).toBe(false); + expect(component.contactSectionDropdown).toBe(false); + }); + + it('should save button is disabled if form has invalid mobile number', () => { + component.ngOnInit(); + const profileFormGroup = component.profileForm; + + profileFormGroup.setValue({ + jobTitle: 'Developer', + location: 'US', + telephone: '2744245', + mobile: 'AB8866322112', + oldPassword: 'admin@123', + newPassword: 'admin@1234', + verifyPassword: 'admin@1234', + companyName: 'test Name', + companyPostCode: '12345', + companyAddress: 'test address', + companyTelephone: '27442266', + companyEmail: 'email@test.com' + }); + + expect(profileFormGroup.valid).toEqual(false); + expect(component.isSaveButtonDisabled()).toBeTruthy(); + }); + + it('should save button is disabled if form has invalid email', () => { + component.ngOnInit(); + const profileFormGroup = component.profileForm; + + profileFormGroup.setValue({ + jobTitle: 'Developer', + location: 'US', + telephone: '27442445', + mobile: '457554', + oldPassword: 'admin@123', + newPassword: 'admin@1234', + verifyPassword: 'admin@1234', + companyName: 'test Name', + companyPostCode: '12345', + companyAddress: 'test address', + companyTelephone: '27442266', + companyEmail: 'email' + }); + + expect(profileFormGroup.valid).toEqual(false); + expect(component.isSaveButtonDisabled()).toBeTruthy(); + }); + + it('should save button is enabled if form has valid inputs', () => { + component.ngOnInit(); + const profileFormGroup = component.profileForm; + + profileFormGroup.setValue({ + jobTitle: 'Developer', + location: 'US', + telephone: '274-422-55', + mobile: '886-632-2112', + oldPassword: 'test@123', + newPassword: 'test@1234', + verifyPassword: 'test@1234', + companyName: 'testCompany', + companyPostCode: '12345', + companyAddress: 'test address', + companyTelephone: '274-22-66', + companyEmail: 'testEmail@test.com' + }); + + expect(profileFormGroup.valid).toEqual(true); + expect(component.isSaveButtonDisabled()).toBeFalsy(); + }); + + it('should navigate to personal files when back button is clicked', () => { + const navigateSpy = spyOn(router, 'navigate'); + component.navigateToPersonalFiles(); + + expect(navigateSpy).toHaveBeenCalledWith(['/personal-files'], { replaceUrl: true }); + }); + + it('should expand or compress general dropdown when arrow button is clicked', () => { + spyOn(component, 'toggleGeneralDropdown').and.callThrough(); + component.generalSectionDropdown = false; + fixture.detectChanges(); + + const generalToggleIcon = fixture.debugElement.query(By.css('#toggle-general-dropdown')); + generalToggleIcon.triggerEventHandler('click', null); + + expect(component.toggleGeneralDropdown).toHaveBeenCalled(); + expect(component.generalSectionButtonsToggle).toBe(true); + }); + + it('should expand or compress contact dropdown when arrow button is clicked', () => { + spyOn(component, 'toggleContactDropdown').and.callThrough(); + component.contactSectionDropdown = false; + fixture.detectChanges(); + + const contactToggleIcon = fixture.debugElement.query(By.css('#toggle-contact-dropdown')); + contactToggleIcon.triggerEventHandler('click', null); + + expect(component.toggleContactDropdown).toHaveBeenCalled(); + expect(component.contactSectionButtonsToggle).toBe(true); + }); + + it('should toggle form view when edit or cancel buttons is clicked for general form', () => { + spyOn(component, 'toggleGeneralButtons').and.callThrough(); + fixture.detectChanges(); + + const generalEditButton = fixture.debugElement.query(By.css('#general-edit-button')); + generalEditButton.triggerEventHandler('click', null); + fixture.detectChanges(); + + const generalCancelButton = fixture.debugElement.query(By.css('#general-cancel-button')); + generalCancelButton.triggerEventHandler('click', null); + + expect(component.toggleGeneralButtons).toHaveBeenCalledTimes(2); + }); + + it('should toggle form view when edit or cancel buttons is clicked for contact form', () => { + spyOn(component, 'toggleContactButtons').and.callThrough(); + fixture.detectChanges(); + + const contactEditButton = fixture.debugElement.query(By.css('#contact-edit-button')); + contactEditButton.triggerEventHandler('click', null); + fixture.detectChanges(); + + const contactCancelButton = fixture.debugElement.query(By.css('#contact-cancel-button')); + contactCancelButton.triggerEventHandler('click', null); + + expect(component.toggleContactButtons).toHaveBeenCalledTimes(2); + }); +}); diff --git a/app/src/app/components/view-profile/view-profile.component.ts b/app/src/app/components/view-profile/view-profile.component.ts index 3dd831859..a316057c7 100644 --- a/app/src/app/components/view-profile/view-profile.component.ts +++ b/app/src/app/components/view-profile/view-profile.component.ts @@ -8,7 +8,7 @@ import { AlfrescoApiService } from '@alfresco/adf-core'; import { PeopleApi, Person } from '@alfresco/js-api'; import { Component, OnInit, ViewEncapsulation } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; import { Router } from '@angular/router'; import { throwError } from 'rxjs'; @@ -34,13 +34,12 @@ export class ViewProfileComponent implements OnInit { contactSectionDropdown = false; contactSectionButtonsToggle = true; - constructor(private formBuilder: FormBuilder, private router: Router, apiService: AlfrescoApiService) { + constructor(private router: Router, apiService: AlfrescoApiService) { this.peopleApi = new PeopleApi(apiService.getInstance()); } ngOnInit() { this.populateForm(this.personDetails); - this.peopleApi .getPerson('-me-') .then((userInfo) => { @@ -53,18 +52,19 @@ export class ViewProfileComponent implements OnInit { } populateForm(userInfo: Person) { - this.profileForm = this.formBuilder.group({ - jobTitle: [userInfo?.jobTitle || ''], - location: [userInfo?.location || ''], - telephone: [userInfo?.telephone || '', Validators.pattern('^[0-9]*$')], - mobile: [userInfo?.mobile || '', Validators.pattern('^[0-9]*$')], - oldPassword: [''], - newPassword: [''], - verifyPassword: [''], - companyPostCode: [userInfo?.company?.postcode || ''], - companyAddress: [userInfo?.company?.address1 || ''], - companyTelephone: [userInfo?.company?.telephone || '', Validators.pattern('^[0-9]*$')], - companyEmail: [userInfo?.company?.email || '', Validators.email] + this.profileForm = new FormGroup({ + jobTitle: new FormControl(userInfo?.jobTitle || ''), + location: new FormControl(userInfo?.location || ''), + telephone: new FormControl(userInfo?.telephone || '', [Validators.pattern('^([0-9]+-)*[0-9]+$')]), + mobile: new FormControl(userInfo?.mobile || '', [Validators.pattern('^([0-9]+-)*[0-9]+$')]), + oldPassword: new FormControl(''), + newPassword: new FormControl(''), + verifyPassword: new FormControl(''), + companyName: new FormControl(userInfo?.company?.organization || ''), + companyPostCode: new FormControl(userInfo?.company?.postcode || ''), + companyAddress: new FormControl(userInfo?.company?.address1 || ''), + companyTelephone: new FormControl(userInfo?.company?.telephone || '', [Validators.pattern('^([0-9]+-)*[0-9]+$')]), + companyEmail: new FormControl(userInfo?.company?.email || '', [Validators.email]) }); } @@ -142,12 +142,13 @@ export class ViewProfileComponent implements OnInit { updatePersonDetails(event) { if (this.profileForm.valid) { this.peopleApi - .updatePerson(this.personDetails.id, { + .updatePerson('-me-', { jobTitle: event.value.jobTitle, location: event.value.location, telephone: event.value.telephone, mobile: event.value.mobile, company: { + organization: event.value.companyName, postcode: event.value.companyPostCode, address1: event.value.companyAddress, telephone: event.value.companyTelephone, @@ -166,4 +167,8 @@ export class ViewProfileComponent implements OnInit { this.populateForm(this.personDetails); } } + + isSaveButtonDisabled(): boolean { + return this.profileForm.invalid; + } } diff --git a/app/src/assets/i18n/en.json b/app/src/assets/i18n/en.json index 9b2393e4c..db94bf1e6 100644 --- a/app/src/assets/i18n/en.json +++ b/app/src/assets/i18n/en.json @@ -70,7 +70,8 @@ "COMPANY_DETAILS": "Company details", "NAME": "Name", "ADDRESS": "Address", - "POST_CODE": "Post code" + "POSTCODE": "Postcode", + "INVALID_INPUT": "Invalid Input" }, "LOCKED_BY": "Locked by: ", "PREVIEW": {