#12 Handle login errors
This commit is contained in:
parent
9deecb3cbd
commit
019b20fd02
|
@ -1,10 +1,13 @@
|
||||||
import {Component} from '@angular/core'
|
import {Component, HostListener, ViewChild} from '@angular/core'
|
||||||
import {FormBuilder, FormControl, Validators} from '@angular/forms'
|
import {FormControl, Validators} from '@angular/forms'
|
||||||
import {SubscribingComponent} from '../shared/components/subscribing.component'
|
import {ErrorHandlingComponent} from '../shared/components/subscribing.component'
|
||||||
import {AccountService} from './services/account.service'
|
import {AccountService} from './services/account.service'
|
||||||
import {AppState} from '../shared/app-state'
|
import {AppState} from '../shared/app-state'
|
||||||
import {ErrorService} from '../shared/service/error.service'
|
import {ErrorHandler, ErrorService} from '../shared/service/error.service'
|
||||||
import {ActivatedRoute, Router} from '@angular/router'
|
import {ActivatedRoute, Router} from '@angular/router'
|
||||||
|
import {CreForm, ICreForm} from "../shared/components/forms/forms";
|
||||||
|
import {take, takeUntil} from "rxjs/operators";
|
||||||
|
import {AlertService} from "../shared/service/alert.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cre-login',
|
selector: 'cre-login',
|
||||||
|
@ -13,13 +16,20 @@ import {ActivatedRoute, Router} from '@angular/router'
|
||||||
'cre-form { min-width: 25rem; margin-top: 50vh; transform: translateY(-70%) }'
|
'cre-form { min-width: 25rem; margin-top: 50vh; transform: translateY(-70%) }'
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class Login extends SubscribingComponent {
|
export class Login extends ErrorHandlingComponent {
|
||||||
|
@ViewChild(CreForm) form: ICreForm
|
||||||
|
|
||||||
userIdControl = new FormControl(null, Validators.compose([Validators.required, Validators.pattern(new RegExp('^[0-9]+$'))]))
|
userIdControl = new FormControl(null, Validators.compose([Validators.required, Validators.pattern(new RegExp('^[0-9]+$'))]))
|
||||||
passwordControl = new FormControl(null, Validators.required)
|
passwordControl = new FormControl(null, Validators.required)
|
||||||
|
|
||||||
|
errorHandlers: ErrorHandler[] = [{
|
||||||
|
filter: error => error.status === 403,
|
||||||
|
messageProducer: () => 'Les identifiants entrés sont invalides'
|
||||||
|
}]
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private formBuilder: FormBuilder,
|
|
||||||
private accountService: AccountService,
|
private accountService: AccountService,
|
||||||
|
private alertService: AlertService,
|
||||||
private appState: AppState,
|
private appState: AppState,
|
||||||
errorService: ErrorService,
|
errorService: ErrorService,
|
||||||
router: Router,
|
router: Router,
|
||||||
|
@ -29,12 +39,27 @@ export class Login extends SubscribingComponent {
|
||||||
this.appState.title = 'Connexion'
|
this.appState.title = 'Connexion'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allows to send the form by pressing Enter
|
||||||
|
@HostListener('window:keyup.enter', ['$event'])
|
||||||
|
onEnterKeyEvent() {
|
||||||
|
if (this.form.formGroup) {
|
||||||
|
this.submit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
this.accountService.login(
|
// Does not use SubscribingComponent shortcut because backend doesn't return expected error type
|
||||||
this.userIdControl.value,
|
this.accountService.login(this.userIdControl.value, this.passwordControl.value)
|
||||||
this.passwordControl.value,
|
.pipe(take(1), takeUntil(this.destroy$))
|
||||||
() => this.urlUtils.navigateTo('/color')
|
.subscribe({
|
||||||
)
|
error: error => this.handleLoginError(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleLoginError(error) {
|
||||||
|
if (error.status === 403) {
|
||||||
|
this.alertService.pushError('Les identifiants entrés sont invalides')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get controls(): { userId: FormControl, password: FormControl } {
|
get controls(): { userId: FormControl, password: FormControl } {
|
||||||
|
|
|
@ -18,10 +18,11 @@
|
||||||
</cre-input>
|
</cre-input>
|
||||||
</cre-form-content>
|
</cre-form-content>
|
||||||
<cre-form-actions>
|
<cre-form-actions>
|
||||||
<cre-submit-button
|
<cre-accent-button
|
||||||
text="Connexion"
|
type="submit"
|
||||||
[form]="form"
|
[disabled]="!form.valid"
|
||||||
(submit)="submit()">
|
(click)="submit()">
|
||||||
</cre-submit-button>
|
Connexion
|
||||||
|
</cre-accent-button>
|
||||||
</cre-form-actions>
|
</cre-form-actions>
|
||||||
</cre-form>
|
</cre-form>
|
||||||
|
|
|
@ -44,10 +44,12 @@ export class LoginComponent extends ErrorHandlingComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
this.accountService.login(
|
this.subscribe(
|
||||||
this.idFormControl.value,
|
this.accountService.login(
|
||||||
this.passwordFormControl.value,
|
this.idFormControl.value,
|
||||||
() => this.router.navigate(['/color'])
|
this.passwordFormControl.value
|
||||||
|
),
|
||||||
|
response => console.log(response)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {Injectable, OnDestroy} from '@angular/core'
|
import {Injectable, OnDestroy} from '@angular/core'
|
||||||
import {Subject} from 'rxjs'
|
import {Observable, Subject} from 'rxjs'
|
||||||
import {take, takeUntil} from 'rxjs/operators'
|
import {take, takeUntil, tap} from 'rxjs/operators'
|
||||||
import {AppState} from '../../shared/app-state'
|
import {AppState} from '../../shared/app-state'
|
||||||
import {HttpClient, HttpResponse} from '@angular/common/http'
|
import {HttpClient, HttpResponse} from '@angular/common/http'
|
||||||
import {environment} from '../../../../environments/environment'
|
import {environment} from '../../../../environments/environment'
|
||||||
|
@ -55,7 +55,32 @@ export class AccountService implements OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
login(id: number, password: string, success: () => void) {
|
login(userId: number, password: string): Observable<any> {
|
||||||
|
globalLoadingWheel.show()
|
||||||
|
const request$ = this.http.post<any>(`${environment.apiUrl}/login`, {id: userId, password}, {
|
||||||
|
withCredentials: true,
|
||||||
|
observe: 'response' as 'body'
|
||||||
|
}).pipe(
|
||||||
|
take(1),
|
||||||
|
takeUntil(this.destroy$)
|
||||||
|
)
|
||||||
|
|
||||||
|
request$.subscribe({
|
||||||
|
next: (response: HttpResponse<any>) => {
|
||||||
|
globalLoadingWheel.hide()
|
||||||
|
|
||||||
|
// TODO: Login user
|
||||||
|
},
|
||||||
|
error: error => {
|
||||||
|
globalLoadingWheel.hide()
|
||||||
|
this.errorService.handleError(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return request$
|
||||||
|
}
|
||||||
|
|
||||||
|
loginOld(id: number, password: string, success: () => void) {
|
||||||
const loginForm = {id, password}
|
const loginForm = {id, password}
|
||||||
globalLoadingWheel.show()
|
globalLoadingWheel.show()
|
||||||
this.http.post<any>(`${environment.apiUrl}/login`, loginForm, {
|
this.http.post<any>(`${environment.apiUrl}/login`, loginForm, {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<cre-primary-button routerLink="/color/list">Retour</cre-primary-button>
|
<cre-primary-button routerLink="/color/list">Retour</cre-primary-button>
|
||||||
</cre-action-group>
|
</cre-action-group>
|
||||||
<cre-action-group>
|
<cre-action-group>
|
||||||
<cre-submit-button [form]="recipeForm.creForm" (submit)="recipeForm.submit()"></cre-submit-button>
|
<cre-form-submit-button [form]="recipeForm.creForm" (submit)="recipeForm.submit()"></cre-form-submit-button>
|
||||||
</cre-action-group>
|
</cre-action-group>
|
||||||
</cre-action-bar>
|
</cre-action-bar>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {Component, ContentChild, EventEmitter, Input, Output} from '@angular/cor
|
||||||
import {ICreForm} from './forms';
|
import {ICreForm} from './forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cre-submit-button',
|
selector: 'cre-form-submit-button',
|
||||||
templateUrl: 'submit-button.html'
|
templateUrl: 'submit-button.html'
|
||||||
})
|
})
|
||||||
export class CreSubmitButton {
|
export class CreSubmitButton {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</mat-card-title>
|
</mat-card-title>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
<mat-card-content [class.no-action]="!hasActions">
|
<mat-card-content [class.no-action]="!hasActions">
|
||||||
<form [formGroup]="form">
|
<form [formGroup]="formGroup">
|
||||||
<ng-content select="cre-form-content"></ng-content>
|
<ng-content select="cre-form-content"></ng-content>
|
||||||
</form>
|
</form>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {Component, ContentChild, Directive, Input, OnInit, ViewEncapsulation} fr
|
||||||
import {FormBuilder, FormGroup} from '@angular/forms'
|
import {FormBuilder, FormGroup} from '@angular/forms'
|
||||||
|
|
||||||
export interface ICreForm {
|
export interface ICreForm {
|
||||||
form: FormGroup
|
formGroup: FormGroup
|
||||||
valid: boolean
|
valid: boolean
|
||||||
invalid: boolean
|
invalid: boolean
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ export class CreForm implements ICreForm, OnInit {
|
||||||
@ContentChild(CreFormActions) formActions: CreFormActions
|
@ContentChild(CreFormActions) formActions: CreFormActions
|
||||||
@Input() formControls: { [key: string]: any }
|
@Input() formControls: { [key: string]: any }
|
||||||
|
|
||||||
form: FormGroup
|
formGroup: FormGroup
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private formBuilder: FormBuilder
|
private formBuilder: FormBuilder
|
||||||
|
@ -43,7 +43,7 @@ export class CreForm implements ICreForm, OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.form = this.formBuilder.group(this.formControls)
|
this.formGroup = this.formBuilder.group(this.formControls)
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasActions(): boolean {
|
get hasActions(): boolean {
|
||||||
|
@ -51,10 +51,10 @@ export class CreForm implements ICreForm, OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
get valid(): boolean {
|
get valid(): boolean {
|
||||||
return this.form && this.form.valid
|
return this.formGroup && this.formGroup.valid
|
||||||
}
|
}
|
||||||
|
|
||||||
get invalid(): boolean {
|
get invalid(): boolean {
|
||||||
return !this.form || this.form.invalid
|
return !this.formGroup || this.formGroup.invalid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
AfterViewInit, ChangeDetectorRef,
|
AfterViewInit,
|
||||||
|
ChangeDetectorRef,
|
||||||
Component,
|
Component,
|
||||||
ContentChild,
|
ContentChild,
|
||||||
Directive,
|
Directive,
|
||||||
|
@ -16,7 +17,7 @@ import {
|
||||||
import {AbstractControl, FormControl, ValidationErrors, ValidatorFn, Validators} from '@angular/forms'
|
import {AbstractControl, FormControl, ValidationErrors, ValidatorFn, Validators} from '@angular/forms'
|
||||||
import {COMMA, ENTER} from '@angular/cdk/keycodes'
|
import {COMMA, ENTER} from '@angular/cdk/keycodes'
|
||||||
import {isObservable, Observable, Subject} from 'rxjs'
|
import {isObservable, Observable, Subject} from 'rxjs'
|
||||||
import {map, startWith, takeUntil} from 'rxjs/operators'
|
import {map, takeUntil} from 'rxjs/operators'
|
||||||
import {MatChipInputEvent} from '@angular/material/chips'
|
import {MatChipInputEvent} from '@angular/material/chips'
|
||||||
import {MatAutocomplete, MatAutocompleteSelectedEvent} from '@angular/material/autocomplete'
|
import {MatAutocomplete, MatAutocompleteSelectedEvent} from '@angular/material/autocomplete'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue