From 07f44dde895963cc258546ba7a7e68bc20fdad1b Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Thu, 5 Jan 2023 23:01:19 +0530 Subject: [PATCH] forgot password design changes --- demo-shell/src/app/app.routes.ts | 2 + .../forgot-password.component.html | 101 +++++++++------ .../forgot-password.component.scss | 66 ++++++++-- .../forgot-password.component.spec.ts | 116 ++++++++++++++++++ .../forgot-password.component.ts | 11 +- .../lib/login/components/login.component.scss | 13 +- .../lib/login/components/login.component.ts | 14 +-- lib/core/src/lib/styles/_index.scss | 1 + 8 files changed, 248 insertions(+), 76 deletions(-) create mode 100644 lib/core/src/lib/forgot-password/forgot-password.component.spec.ts diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts index 0f3612b8cd..dc5b0df286 100644 --- a/demo-shell/src/app/app.routes.ts +++ b/demo-shell/src/app/app.routes.ts @@ -56,10 +56,12 @@ import { ProcessCloudLayoutComponent } from './components/cloud/process-cloud-la import { ServiceTaskListCloudDemoComponent } from './components/cloud/service-task-list-cloud-demo.component'; import { AspectListSampleComponent } from './components/aspect-list-sample/aspect-list-sample.component'; import { SearchFilterChipsComponent } from './components/search/search-filter-chips.component'; +import { ForgotPasswordComponent } from 'lib/core/src/lib/forgot-password/forgot-password.component'; export const appRoutes: Routes = [ { path: 'login', loadChildren: () => import('./components/login/login.module').then(m => m.AppLoginModule) }, { path: 'logout', component: LogoutComponent }, + { path: 'forgot-password', component: ForgotPasswordComponent }, { path: 'settings', loadChildren: () => import('./components/settings/settings.module').then(m => m.AppSettingsModule) diff --git a/lib/core/src/lib/forgot-password/forgot-password.component.html b/lib/core/src/lib/forgot-password/forgot-password.component.html index 76e8f300ae..309668eb68 100644 --- a/lib/core/src/lib/forgot-password/forgot-password.component.html +++ b/lib/core/src/lib/forgot-password/forgot-password.component.html @@ -1,46 +1,71 @@ -
-
+
- + + + + + {{ 'RECOVER-PASSWORD.RECOVER-PASSWORD' | translate }} + + + +
+ + + +

{{ 'RECOVER-PASSWORD.MESSAGES.FILLER' | translate }}

+
-
-
- {{ 'RECOVER-PASSWORD.RECOVER-PASSWORD' | translate }} -
-
-
- -
-

{{ 'RECOVER-PASSWORD.MESSAGES.FILLER' | translate }}

- - -
-
\ No newline at end of file + + + + + + + + + + + +
+ +
+ + + + + + {{ 'RECOVER-PASSWORD.RECOVER-PASSWORD' | translate }} + + + +
+ + +
+ +
+ + + + +
+ +
+ +
\ No newline at end of file diff --git a/lib/core/src/lib/forgot-password/forgot-password.component.scss b/lib/core/src/lib/forgot-password/forgot-password.component.scss index 77a583a8e1..eb15a90223 100644 --- a/lib/core/src/lib/forgot-password/forgot-password.component.scss +++ b/lib/core/src/lib/forgot-password/forgot-password.component.scss @@ -1,10 +1,29 @@ -.app-dialog { - height: 100%; +.forgot-password-div { + width: 100%; + height: 100vh; display: flex; - flex-direction: column; + flex-direction: row; + justify-content: center; + align-items: center; + position: fixed; + top: 0; + left: 0; + transform: translate(calc(50vw - 50%)); + border-radius: 12px; + background-color: var(--theme-forgot-password-background); } -.app-mat-dialog-title { +mat-card { + padding: 24px 24px; + width: 371px; + //height: 264px; +} + +::ng-deep .mat-card-header-text { + margin: 0 !important; +} + +.forgot-password-title { font-style: normal; font-weight: 400; font-size: 20px; @@ -12,13 +31,14 @@ letter-spacing: 0.15px; color: var(--theme-forgot-password-title-color); padding: 2px 0; + margin: 0 !important; } hr { margin: 12px 0; } -.app-dialog-filler { +.filler { display: flex; flex-direction: row; align-items: center; @@ -33,7 +53,12 @@ hr { margin: 0 0 8px 0; } -.app-forgot-password-label { +.forgot-password-form-field { + height: 64px; + margin-top: 24px; +} + +.forgot-password-label { height: 32px; padding: 6px 0; font-style: normal; @@ -44,7 +69,7 @@ hr { color: var(--theme-forgot-password-title-color); } -.app-forgot-password-field { +.forgot-password-field { text-decoration: none; height: 32px; line-height: 32px; @@ -69,6 +94,20 @@ hr { margin: 24px 0 0 0 !important; } +.close-button { + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: var(--theme-forgot-password-input-background-color); + color: var(--theme-forgot-password-title-color); + margin-top: 8px; + padding: 4px 12px; + height: 32px; + border-radius: 6px; +} + .password-reset-link-message { height: 52px; padding: 6px 0; @@ -80,8 +119,11 @@ hr { color: var(--theme-forgot-password-title-color); } -.close-button { - float: right; - top: -24px; - right: -24px; -} \ No newline at end of file + + + + + + + + diff --git a/lib/core/src/lib/forgot-password/forgot-password.component.spec.ts b/lib/core/src/lib/forgot-password/forgot-password.component.spec.ts new file mode 100644 index 0000000000..53d8f894c2 --- /dev/null +++ b/lib/core/src/lib/forgot-password/forgot-password.component.spec.ts @@ -0,0 +1,116 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Router } from '@angular/router'; +import { CoreTestingModule } from '../testing/core.testing.module'; +import { ForgotPasswordComponent } from './forgot-password.component'; + + +describe('ResetPasswordComponent', () => { + let component: ForgotPasswordComponent; + let fixture: ComponentFixture; + let router: Router; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [CoreTestingModule], + declarations: [ForgotPasswordComponent], + providers: [] + }); + + fixture = TestBed.createComponent(ForgotPasswordComponent); + component = fixture.componentInstance; + component.ngOnInit(); + router = TestBed.inject(Router); + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + }); + + it('send instructions button should be disabled by default', async () => { + component.ngOnInit(); + + fixture.detectChanges(); + await fixture.whenStable(); + + expect(component.isButtonDisabled).toBeTruthy(); + }); + + it('send instructions button should be disabled if username field is empty', async () => { + component.ngOnInit(); + component.forgotPasswordForm.controls['userName'].setValue(''); + + fixture.detectChanges(); + await fixture.whenStable(); + + expect(component.isButtonDisabled).toBeTruthy(); + }); + + it('send instructions button should be enabled when username field is not empty', async () => { + component.ngOnInit(); + fixture.detectChanges(); + await fixture.whenStable(); + + component.forgotPasswordForm.controls['userName'].setValue('userABC'); + spyOn(component, 'isButtonDisabled').and.callThrough(); + const sendInstructionsBtn = fixture.debugElement.nativeElement.querySelector('.send-instructions-button'); + + fixture.detectChanges(); + await fixture.whenStable(); + + expect(component.isButtonDisabled).toHaveBeenCalled(); + expect(sendInstructionsBtn.disabled).toBeFalsy(); + }); + + it('should send instructions to the email id corresponding to the username when the send instructions button is clicked', async () => { + component.ngOnInit(); + component.forgotPasswordForm.controls['userName'].setValue('userABC'); + spyOn(component, 'sendInstructions').and.callThrough(); + + + fixture.detectChanges(); + await fixture.whenStable(); + + const sendInstructionsBtn = fixture.debugElement.nativeElement.querySelector('.send-instructions-button'); + sendInstructionsBtn.dispatchEvent(new Event('click')); + + fixture.detectChanges(); + await fixture.whenStable(); + + expect(component.sendInstructions).toHaveBeenCalled(); + }); + + it('should route user back to login page when the close button is clicked', async () => { + component.ngOnInit(); + spyOn(component, 'close').and.callThrough(); + spyOn(router, 'navigate'); + + fixture.detectChanges(); + await fixture.whenStable(); + + const closeBtn = fixture.debugElement.nativeElement.querySelector('.close-button'); + closeBtn.dispatchEvent(new Event('click')); + + fixture.detectChanges(); + await fixture.whenStable(); + + expect(component.close).toHaveBeenCalled(); + expect(router.navigate).toHaveBeenCalledWith(['./login']); + }); +}); diff --git a/lib/core/src/lib/forgot-password/forgot-password.component.ts b/lib/core/src/lib/forgot-password/forgot-password.component.ts index 4640192de6..fc5941b382 100644 --- a/lib/core/src/lib/forgot-password/forgot-password.component.ts +++ b/lib/core/src/lib/forgot-password/forgot-password.component.ts @@ -10,9 +10,10 @@ import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { PeopleApi, ClientBody } from '@alfresco/js-api'; import { AlfrescoApiService } from '@alfresco/adf-core'; +import { Router } from '@angular/router'; @Component({ - selector: 'app-forgot-password', + selector: 'adf-forgot-password', templateUrl: './forgot-password.component.html', styleUrls: ['./forgot-password.component.scss'] }) @@ -24,9 +25,11 @@ export class ForgotPasswordComponent implements OnInit { constructor( private apiService: AlfrescoApiService, - private formBuilder: FormBuilder) { } + private formBuilder: FormBuilder, + private router: Router) { } ngOnInit(): void { + this.passwordResetStatus = false; this.forgotPasswordForm = this.formBuilder.group({ userName: ['', [Validators.required]] }); @@ -50,4 +53,8 @@ export class ForgotPasswordComponent implements OnInit { isButtonDisabled(): boolean { return this.forgotPasswordForm.invalid || this.isSaveInProgress; } + + close() { + this.router.navigate(['./login']); + } } diff --git a/lib/core/src/lib/login/components/login.component.scss b/lib/core/src/lib/login/components/login.component.scss index 243210fe1e..da6e07ab89 100644 --- a/lib/core/src/lib/login/components/login.component.scss +++ b/lib/core/src/lib/login/components/login.component.scss @@ -257,15 +257,4 @@ border-top: 1px solid rgba(0, 0, 0, 0.1); margin-top: 23px; } -} - -.forgot-password-backdrop-background { - background-color: #E5E5E5; - opacity: 1 !important; -} - -.forgot-password-dialog-box { - border: 1px solid var(--theme-forgot-password-dialog-border-color) !important; - box-shadow: 0px 0px 24px var(--theme-forgot-password-dialog-shadow-color) !important; - border-radius: 12px !important; -} +} \ No newline at end of file diff --git a/lib/core/src/lib/login/components/login.component.ts b/lib/core/src/lib/login/components/login.component.ts index d5f823bc48..6480204fac 100644 --- a/lib/core/src/lib/login/components/login.component.ts +++ b/lib/core/src/lib/login/components/login.component.ts @@ -37,8 +37,6 @@ import { import { DomSanitizer, SafeStyle } from '@angular/platform-browser'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { ForgotPasswordComponent } from '../../forgot-password/forgot-password.component'; -import { MatDialog } from '@angular/material/dialog'; // eslint-disable-next-line no-shadow enum LoginSteps { @@ -140,8 +138,7 @@ export class LoginComponent implements OnInit, OnDestroy { private userPreferences: UserPreferencesService, private route: ActivatedRoute, private sanitizer: DomSanitizer, - private alfrescoApiService: AlfrescoApiService, - private dialog: MatDialog + private alfrescoApiService: AlfrescoApiService ) { } @@ -192,14 +189,7 @@ export class LoginComponent implements OnInit, OnDestroy { } forgotPassword() { - this.dialog.open(ForgotPasswordComponent, { - width: '371px', - data: { - title: 'Recover' - }, - backdropClass: 'forgot-password-backdrop-background', - panelClass: 'forgot-password-dialog-box' - }); + this.router.navigate(['./forgot-password']); } redirectToImplicitLogin() { diff --git a/lib/core/src/lib/styles/_index.scss b/lib/core/src/lib/styles/_index.scss index 84e903f1f8..69f19b26bb 100644 --- a/lib/core/src/lib/styles/_index.scss +++ b/lib/core/src/lib/styles/_index.scss @@ -96,6 +96,7 @@ --adf-theme-mat-grey-color-a200: mat.get-color-from-palette(mat.$grey-palette, A200), --adf-theme-mat-grey-color-a400: mat.get-color-from-palette(mat.$grey-palette, A400), --adf-theme-mat-grey-color-50: mat.get-color-from-palette(mat.$grey-palette, 50), + --theme-forgot-password-background: #E5E5E5, --theme-forgot-password-title-color: #212121, --theme-forgot-password-label-color: rgba(33, 35, 40, 0.7), --theme-forgot-password-input-background-color: rgba(33, 33, 33, 0.05),