From 877b8dcf7890bdd80af28a57a7e13fe13eac6d73 Mon Sep 17 00:00:00 2001 From: Oleksandr Kitsera Date: Wed, 30 Apr 2025 14:38:26 +0300 Subject: [PATCH 1/3] Improvements to popup logic --- .../df-login/df-login.component.ts | 34 +++++- .../df-password-reset.component.ts | 13 ++- .../services/df-auth.service.ts | 4 +- src/app/app.component.ts | 3 +- .../df-popup/df-popup.component.html | 24 ++++ .../df-popup/df-popup.component.scss | 110 ++++++++++++++++++ .../components/df-popup/df-popup.component.ts | 42 +++++++ .../components/df-popup/popup-config.ts | 8 ++ .../df-popup/popup-overlay.service.ts | 36 ++++++ src/app/shared/services/popup.service.ts | 26 +++++ src/styles.scss | 6 + 11 files changed, 299 insertions(+), 7 deletions(-) create mode 100644 src/app/shared/components/df-popup/df-popup.component.html create mode 100644 src/app/shared/components/df-popup/df-popup.component.scss create mode 100644 src/app/shared/components/df-popup/df-popup.component.ts create mode 100644 src/app/shared/components/df-popup/popup-config.ts create mode 100644 src/app/shared/components/df-popup/popup-overlay.service.ts create mode 100644 src/app/shared/services/popup.service.ts diff --git a/src/app/adf-user-management/df-login/df-login.component.ts b/src/app/adf-user-management/df-login/df-login.component.ts index 85f955fc..dd913a93 100644 --- a/src/app/adf-user-management/df-login/df-login.component.ts +++ b/src/app/adf-user-management/df-login/df-login.component.ts @@ -32,6 +32,9 @@ import { UntilDestroy } from '@ngneat/until-destroy'; import { DfThemeService } from 'src/app/shared/services/df-theme.service'; import { CommonModule } from '@angular/common'; import { DfSnackbarService } from 'src/app/shared/services/df-snackbar.service'; +import { PopupService } from 'src/app/shared/services/popup.service'; +import { PopupOverlayService } from 'src/app/shared/components/df-popup/popup-overlay.service'; + @UntilDestroy({ checkProperties: true }) @Component({ selector: 'df-user-login', @@ -58,6 +61,7 @@ import { DfSnackbarService } from 'src/app/shared/services/df-snackbar.service'; ], }) export class DfLoginComponent implements OnInit { + private readonly MINIMUM_PASSWORD_LENGTH = 17; alertMsg = ''; showAlert = false; alertType: AlertType = 'error'; @@ -78,7 +82,9 @@ export class DfLoginComponent implements OnInit { private authService: DfAuthService, private router: Router, private themeService: DfThemeService, - private snackbarService: DfSnackbarService + private snackbarService: DfSnackbarService, + private popupService: PopupService, + private popupOverlay: PopupOverlayService ) { this.loginForm = this.fb.group({ services: [''], @@ -132,6 +138,13 @@ export class DfLoginComponent implements OnInit { if (this.loginForm.invalid) { return; } + + if (this.loginForm.value.password.length < this.MINIMUM_PASSWORD_LENGTH) { + this.popupOverlay.open({ + message: `Your current password is shorter than recommended (less than ${this.MINIMUM_PASSWORD_LENGTH} characters). For better security, we recommend updating your password to a longer one.`, + showRemindMeLater: true + }); + } const credentials: LoginCredentials = { password: this.loginForm.value.password, }; @@ -147,8 +160,23 @@ export class DfLoginComponent implements OnInit { .login(credentials) .pipe( catchError(err => { - this.alertMsg = err.error.error.message; - this.showAlert = true; + if ( + this.loginForm.value.password.length < this.MINIMUM_PASSWORD_LENGTH && + err.status === 401 + ) { + this.router.navigate([ROUTES.AUTH, ROUTES.RESET_PASSWORD], { + state: { + showPasswordUpgradePrompt: true, + popupConfig: { + message: `It looks like your password is too short. Our new system requires at least ${this.MINIMUM_PASSWORD_LENGTH} characters. Please reset your password to continue.`, + showRemindMeLater: false + } + } + }); + } else { + this.alertMsg = err.error?.error?.message || 'Login failed'; + this.showAlert = true; + } return throwError(() => new Error(err)); }) ) diff --git a/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts b/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts index 1fd6a75d..60f7a3f6 100644 --- a/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts +++ b/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts @@ -20,6 +20,7 @@ import { } from '../../shared/components/df-alert/df-alert.component'; import { DfAuthService } from '../services/df-auth.service'; import { ActivatedRoute, Router } from '@angular/router'; +import { PopupOverlayService } from 'src/app/shared/components/df-popup/popup-overlay.service'; import { MatButtonModule } from '@angular/material/button'; import { MatInputModule } from '@angular/material/input'; @@ -62,7 +63,8 @@ export class DfPasswordResetComponent implements OnInit { private systemConfigDataService: DfSystemConfigDataService, private authService: DfAuthService, private router: Router, - private route: ActivatedRoute + private route: ActivatedRoute, + private popupOverlay: PopupOverlayService ) { this.passwordResetForm = this.fb.group({ username: ['', [Validators.required]], @@ -102,6 +104,15 @@ export class DfPasswordResetComponent implements OnInit { this.type = data['type']; } }); + + if (history.state && history.state.popupConfig) { + this.popupOverlay.open(history.state.popupConfig); + } else if (history.state && history.state.showPasswordUpgradePrompt) { + this.popupOverlay.open({ + message: 'It looks like your password is too short. Our new system requires at least 17 characters. Please reset your password to continue.', + showRemindMeLater: false + }); + } } get isAdmin() { diff --git a/src/app/adf-user-management/services/df-auth.service.ts b/src/app/adf-user-management/services/df-auth.service.ts index 6d49db53..fa0c4cfe 100644 --- a/src/app/adf-user-management/services/df-auth.service.ts +++ b/src/app/adf-user-management/services/df-auth.service.ts @@ -104,7 +104,7 @@ export class DfAuthService { ); } - logout() { + logout(redirectTo: any[] = [ROUTES.AUTH, ROUTES.LOGIN]) { this.http .delete( this.userDataService.userData?.isSysAdmin @@ -114,7 +114,7 @@ export class DfAuthService { .subscribe(() => { this.userDataService.clearToken(); this.userDataService.userData = null; - this.router.navigate([ROUTES.AUTH, ROUTES.LOGIN]); + this.router.navigate(redirectTo); }); } } diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 553f32bf..e1831b3c 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -8,6 +8,7 @@ import { UntilDestroy } from '@ngneat/until-destroy'; import { AuthService } from './shared/services/auth.service'; import { LoggingService } from './shared/services/logging.service'; import { LoginResponse } from './shared/types/auth.types'; +import { PopupComponent } from './shared/components/df-popup/df-popup.component'; @UntilDestroy({ checkProperties: true }) @Component({ @@ -15,7 +16,7 @@ import { LoginResponse } from './shared/types/auth.types'; templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], standalone: true, - imports: [DfSideNavComponent, RouterOutlet, NgIf, AsyncPipe], + imports: [DfSideNavComponent, RouterOutlet, NgIf, AsyncPipe, PopupComponent], }) export class AppComponent implements OnInit { title = 'df-admin-interface'; diff --git a/src/app/shared/components/df-popup/df-popup.component.html b/src/app/shared/components/df-popup/df-popup.component.html new file mode 100644 index 00000000..b20b0ac5 --- /dev/null +++ b/src/app/shared/components/df-popup/df-popup.component.html @@ -0,0 +1,24 @@ + diff --git a/src/app/shared/components/df-popup/df-popup.component.scss b/src/app/shared/components/df-popup/df-popup.component.scss new file mode 100644 index 00000000..7d6b8d50 --- /dev/null +++ b/src/app/shared/components/df-popup/df-popup.component.scss @@ -0,0 +1,110 @@ +// Popup Container +.popup-container { + display: flex; + justify-content: center; + align-items: center; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + z-index: 10000; +} + +.popup { + position: relative; + width: 90%; + max-width: 500px; + background: #ffffff; + border-radius: 12px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); + padding: 24px; + z-index: 10001; + animation: popupFadeIn 0.3s ease-out; + + .popup-header { + margin-bottom: 20px; + text-align: center; + + h2 { + margin: 0; + color: #333333; + font-size: 1.5rem; + font-weight: 600; + } + } + + .popup-content { + margin-bottom: 24px; + text-align: center; + + p { + margin: 8px 0; + color: #666666; + line-height: 1.5; + } + } + + .popup-actions { + display: flex; + justify-content: center; + gap: 12px; + + button { + min-width: 120px; + padding: 8px 16px; + font-weight: 500; + transition: all 0.2s ease; + + &:hover { + transform: translateY(-1px); + } + } + } +} + +@keyframes popupFadeIn { + from { + opacity: 0; + transform: translateY(-20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.actions { + display: flex; + flex-direction: row; +} + +// Popup Header +.popup-header { + font-size: 18px; + font-weight: bold; + color: #6d4ec9; // Matches sidebar color + margin-bottom: 10px; +} + +// Popup Content +.popup-content { + font-size: 14px; + margin-bottom: 15px; +} + +// Close Button +.popup-close { + background: #6d4ec9; // Match theme + color: #fff; + border: none; + padding: 10px 15px; + border-radius: 8px; + cursor: pointer; + font-size: 14px; + transition: background 0.3s ease; + + &:hover { + background: #5a3bb3; // Darker on hover + } +} diff --git a/src/app/shared/components/df-popup/df-popup.component.ts b/src/app/shared/components/df-popup/df-popup.component.ts new file mode 100644 index 00000000..cbb7c58c --- /dev/null +++ b/src/app/shared/components/df-popup/df-popup.component.ts @@ -0,0 +1,42 @@ +import { Component, Inject, Optional } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialogModule } from '@angular/material/dialog'; +import { TranslocoPipe } from '@ngneat/transloco'; +import { Router } from '@angular/router'; +import { ROUTES } from '../../types/routes'; +import { PopupOverlayService } from './popup-overlay.service'; +import { DfAuthService } from 'src/app/adf-user-management/services/df-auth.service'; +import { POPUP_CONFIG, PopupConfig } from './popup-config'; + +@Component({ + selector: 'df-popup', + templateUrl: './df-popup.component.html', + standalone: true, + styleUrls: ['./df-popup.component.scss'], + imports: [CommonModule, MatButtonModule, MatDialogModule, TranslocoPipe], +}) +export class PopupComponent { + constructor( + private router: Router, + private popupOverlay: PopupOverlayService, + private authService: DfAuthService, + @Optional() @Inject(POPUP_CONFIG) public config: PopupConfig + ) {} + + get message() { + return this.config?.message || + 'Your current password is shorter than recommended (less than 17 characters). For better security, we recommend updating your password to a longer one.'; + } + get showRemindMeLater() { + return this.config?.showRemindMeLater !== false; + } + + closePopup(shouldRedirect = false) { + this.popupOverlay.close(); + if (shouldRedirect) { + this.authService.logout(); + this.router.navigate([ROUTES.AUTH, ROUTES.RESET_PASSWORD]); + } + } +} diff --git a/src/app/shared/components/df-popup/popup-config.ts b/src/app/shared/components/df-popup/popup-config.ts new file mode 100644 index 00000000..4a7cf18f --- /dev/null +++ b/src/app/shared/components/df-popup/popup-config.ts @@ -0,0 +1,8 @@ +import { InjectionToken } from '@angular/core'; + +export interface PopupConfig { + message: string; + showRemindMeLater: boolean; +} + +export const POPUP_CONFIG = new InjectionToken('POPUP_CONFIG'); \ No newline at end of file diff --git a/src/app/shared/components/df-popup/popup-overlay.service.ts b/src/app/shared/components/df-popup/popup-overlay.service.ts new file mode 100644 index 00000000..f5bd06fc --- /dev/null +++ b/src/app/shared/components/df-popup/popup-overlay.service.ts @@ -0,0 +1,36 @@ +import { Injectable, Injector } from '@angular/core'; +import { Overlay, OverlayRef } from '@angular/cdk/overlay'; +import { ComponentPortal } from '@angular/cdk/portal'; +import { PopupComponent } from './df-popup.component'; +import { POPUP_CONFIG, PopupConfig } from './popup-config'; + +@Injectable({ providedIn: 'root' }) +export class PopupOverlayService { + private overlayRef: OverlayRef | null = null; + + constructor(private overlay: Overlay, private injector: Injector) {} + + open(config?: PopupConfig) { + if (this.overlayRef) return; // Prevent multiple overlays + const injector = Injector.create({ + providers: [ + { provide: POPUP_CONFIG, useValue: config } + ], + parent: this.injector + }); + this.overlayRef = this.overlay.create({ + hasBackdrop: true, + backdropClass: 'popup-backdrop', + positionStrategy: this.overlay.position().global().centerHorizontally().centerVertically(), + scrollStrategy: this.overlay.scrollStrategies.block(), + }); + const portal = new ComponentPortal(PopupComponent, null, injector); + this.overlayRef.attach(portal); + this.overlayRef.backdropClick().subscribe(() => this.close()); + } + + close() { + this.overlayRef?.dispose(); + this.overlayRef = null; + } +} \ No newline at end of file diff --git a/src/app/shared/services/popup.service.ts b/src/app/shared/services/popup.service.ts new file mode 100644 index 00000000..a6c64216 --- /dev/null +++ b/src/app/shared/services/popup.service.ts @@ -0,0 +1,26 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class PopupService { + private storageKey = 'showPasswordPopup'; + private popupStateSubject = new BehaviorSubject(false); + popupState$ = this.popupStateSubject.asObservable(); + + constructor() { + // Initialize from localStorage + const savedState = this.shouldShowPopup(); + this.popupStateSubject.next(savedState); + } + + setShowPopup(value: boolean): void { + localStorage.setItem(this.storageKey, JSON.stringify(value)); + this.popupStateSubject.next(value); + } + + shouldShowPopup(): boolean { + return JSON.parse(localStorage.getItem(this.storageKey) || 'false'); + } +} diff --git a/src/styles.scss b/src/styles.scss index 123f7800..6164c694 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -230,3 +230,9 @@ a { .swagger-ui .opblock .opblock-section-header { background: unset !important; } + +.popup-backdrop { + background: rgba(0,0,0,0.6) !important; + backdrop-filter: blur(6px) !important; + -webkit-backdrop-filter: blur(6px) !important; +} From 7c5fe4b28e46ea19091153ba11660505c746ab08 Mon Sep 17 00:00:00 2001 From: Oleksandr Kitsera Date: Wed, 30 Apr 2025 16:49:37 +0300 Subject: [PATCH 2/3] Refactor --- .../df-login/df-login.component.ts | 32 +++++++------------ .../df-password-reset.component.ts | 14 +------- src/app/app.component.ts | 4 +-- .../components/df-popup/popup-config.ts | 2 +- .../df-popup/popup-overlay.service.ts | 21 +++++++----- src/styles.scss | 2 +- 6 files changed, 29 insertions(+), 46 deletions(-) diff --git a/src/app/adf-user-management/df-login/df-login.component.ts b/src/app/adf-user-management/df-login/df-login.component.ts index dd913a93..41e9e74f 100644 --- a/src/app/adf-user-management/df-login/df-login.component.ts +++ b/src/app/adf-user-management/df-login/df-login.component.ts @@ -32,7 +32,6 @@ import { UntilDestroy } from '@ngneat/until-destroy'; import { DfThemeService } from 'src/app/shared/services/df-theme.service'; import { CommonModule } from '@angular/common'; import { DfSnackbarService } from 'src/app/shared/services/df-snackbar.service'; -import { PopupService } from 'src/app/shared/services/popup.service'; import { PopupOverlayService } from 'src/app/shared/components/df-popup/popup-overlay.service'; @UntilDestroy({ checkProperties: true }) @@ -83,7 +82,6 @@ export class DfLoginComponent implements OnInit { private router: Router, private themeService: DfThemeService, private snackbarService: DfSnackbarService, - private popupService: PopupService, private popupOverlay: PopupOverlayService ) { this.loginForm = this.fb.group({ @@ -139,12 +137,7 @@ export class DfLoginComponent implements OnInit { return; } - if (this.loginForm.value.password.length < this.MINIMUM_PASSWORD_LENGTH) { - this.popupOverlay.open({ - message: `Your current password is shorter than recommended (less than ${this.MINIMUM_PASSWORD_LENGTH} characters). For better security, we recommend updating your password to a longer one.`, - showRemindMeLater: true - }); - } + const isPasswordTooShort = this.loginForm.value.password.length < this.MINIMUM_PASSWORD_LENGTH; const credentials: LoginCredentials = { password: this.loginForm.value.password, }; @@ -156,22 +149,15 @@ export class DfLoginComponent implements OnInit { } else { credentials.email = this.loginForm.value.email; } + this.authService .login(credentials) .pipe( catchError(err => { - if ( - this.loginForm.value.password.length < this.MINIMUM_PASSWORD_LENGTH && - err.status === 401 - ) { - this.router.navigate([ROUTES.AUTH, ROUTES.RESET_PASSWORD], { - state: { - showPasswordUpgradePrompt: true, - popupConfig: { - message: `It looks like your password is too short. Our new system requires at least ${this.MINIMUM_PASSWORD_LENGTH} characters. Please reset your password to continue.`, - showRemindMeLater: false - } - } + if (err.status === 401 && isPasswordTooShort) { + this.popupOverlay.open({ + message: `It looks like your password is too short. Our new system requires at least ${this.MINIMUM_PASSWORD_LENGTH} characters. Please reset your password to continue.`, + showRemindMeLater: false, }); } else { this.alertMsg = err.error?.error?.message || 'Login failed'; @@ -182,6 +168,12 @@ export class DfLoginComponent implements OnInit { ) .subscribe(() => { this.showAlert = false; + if (isPasswordTooShort) { + this.popupOverlay.open({ + message: `Your current password is shorter than recommended (less than ${this.MINIMUM_PASSWORD_LENGTH} characters). For better security, we recommend updating your password to a longer one.`, + showRemindMeLater: true, + }); + } this.router.navigate([ROUTES.HOME]); }); } diff --git a/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts b/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts index 60f7a3f6..f13549d5 100644 --- a/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts +++ b/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts @@ -20,7 +20,6 @@ import { } from '../../shared/components/df-alert/df-alert.component'; import { DfAuthService } from '../services/df-auth.service'; import { ActivatedRoute, Router } from '@angular/router'; -import { PopupOverlayService } from 'src/app/shared/components/df-popup/popup-overlay.service'; import { MatButtonModule } from '@angular/material/button'; import { MatInputModule } from '@angular/material/input'; @@ -63,9 +62,7 @@ export class DfPasswordResetComponent implements OnInit { private systemConfigDataService: DfSystemConfigDataService, private authService: DfAuthService, private router: Router, - private route: ActivatedRoute, - private popupOverlay: PopupOverlayService - ) { + private route: ActivatedRoute ) { this.passwordResetForm = this.fb.group({ username: ['', [Validators.required]], email: ['', [Validators.required, Validators.email]], @@ -104,15 +101,6 @@ export class DfPasswordResetComponent implements OnInit { this.type = data['type']; } }); - - if (history.state && history.state.popupConfig) { - this.popupOverlay.open(history.state.popupConfig); - } else if (history.state && history.state.showPasswordUpgradePrompt) { - this.popupOverlay.open({ - message: 'It looks like your password is too short. Our new system requires at least 17 characters. Please reset your password to continue.', - showRemindMeLater: false - }); - } } get isAdmin() { diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e1831b3c..d11f663d 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -2,13 +2,11 @@ import { Component, OnInit } from '@angular/core'; import { DfLoadingSpinnerService } from './shared/services/df-loading-spinner.service'; import { NgIf, AsyncPipe } from '@angular/common'; import { RouterOutlet, Router, ActivatedRoute } from '@angular/router'; -import { DfSideNavComponent } from './shared/components/df-side-nav/df-side-nav.component'; import { DfLicenseCheckService } from './shared/services/df-license-check.service'; import { UntilDestroy } from '@ngneat/until-destroy'; import { AuthService } from './shared/services/auth.service'; import { LoggingService } from './shared/services/logging.service'; import { LoginResponse } from './shared/types/auth.types'; -import { PopupComponent } from './shared/components/df-popup/df-popup.component'; @UntilDestroy({ checkProperties: true }) @Component({ @@ -16,7 +14,7 @@ import { PopupComponent } from './shared/components/df-popup/df-popup.component' templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], standalone: true, - imports: [DfSideNavComponent, RouterOutlet, NgIf, AsyncPipe, PopupComponent], + imports: [RouterOutlet, NgIf, AsyncPipe], }) export class AppComponent implements OnInit { title = 'df-admin-interface'; diff --git a/src/app/shared/components/df-popup/popup-config.ts b/src/app/shared/components/df-popup/popup-config.ts index 4a7cf18f..fb157bb3 100644 --- a/src/app/shared/components/df-popup/popup-config.ts +++ b/src/app/shared/components/df-popup/popup-config.ts @@ -5,4 +5,4 @@ export interface PopupConfig { showRemindMeLater: boolean; } -export const POPUP_CONFIG = new InjectionToken('POPUP_CONFIG'); \ No newline at end of file +export const POPUP_CONFIG = new InjectionToken('POPUP_CONFIG'); diff --git a/src/app/shared/components/df-popup/popup-overlay.service.ts b/src/app/shared/components/df-popup/popup-overlay.service.ts index f5bd06fc..20bd5ed5 100644 --- a/src/app/shared/components/df-popup/popup-overlay.service.ts +++ b/src/app/shared/components/df-popup/popup-overlay.service.ts @@ -8,20 +8,25 @@ import { POPUP_CONFIG, PopupConfig } from './popup-config'; export class PopupOverlayService { private overlayRef: OverlayRef | null = null; - constructor(private overlay: Overlay, private injector: Injector) {} + constructor( + private overlay: Overlay, + private injector: Injector + ) {} open(config?: PopupConfig) { - if (this.overlayRef) return; // Prevent multiple overlays + if (this.overlayRef) return; const injector = Injector.create({ - providers: [ - { provide: POPUP_CONFIG, useValue: config } - ], - parent: this.injector + providers: [{ provide: POPUP_CONFIG, useValue: config }], + parent: this.injector, }); this.overlayRef = this.overlay.create({ hasBackdrop: true, backdropClass: 'popup-backdrop', - positionStrategy: this.overlay.position().global().centerHorizontally().centerVertically(), + positionStrategy: this.overlay + .position() + .global() + .centerHorizontally() + .centerVertically(), scrollStrategy: this.overlay.scrollStrategies.block(), }); const portal = new ComponentPortal(PopupComponent, null, injector); @@ -33,4 +38,4 @@ export class PopupOverlayService { this.overlayRef?.dispose(); this.overlayRef = null; } -} \ No newline at end of file +} diff --git a/src/styles.scss b/src/styles.scss index 6164c694..67e2c05d 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -232,7 +232,7 @@ a { } .popup-backdrop { - background: rgba(0,0,0,0.6) !important; + background: rgba(0, 0, 0, 0.6) !important; backdrop-filter: blur(6px) !important; -webkit-backdrop-filter: blur(6px) !important; } From 8c787b4bbfb56ce56ab7b5eece1f1aa6bee5c3ab Mon Sep 17 00:00:00 2001 From: Oleksandr Kitsera Date: Wed, 30 Apr 2025 17:24:57 +0300 Subject: [PATCH 3/3] Fix typo --- .../df-password-reset/df-password-reset.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts b/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts index f13549d5..1fd6a75d 100644 --- a/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts +++ b/src/app/adf-user-management/df-password-reset/df-password-reset.component.ts @@ -62,7 +62,8 @@ export class DfPasswordResetComponent implements OnInit { private systemConfigDataService: DfSystemConfigDataService, private authService: DfAuthService, private router: Router, - private route: ActivatedRoute ) { + private route: ActivatedRoute + ) { this.passwordResetForm = this.fb.group({ username: ['', [Validators.required]], email: ['', [Validators.required, Validators.email]],