#12 Handle login errors

This commit is contained in:
FyloZ 2021-12-06 23:33:41 -05:00
parent 9deecb3cbd
commit 019b20fd02
Signed by: william
GPG Key ID: 835378AE9AF4AE97
9 changed files with 87 additions and 33 deletions

View File

@ -1,10 +1,13 @@
import {Component} from '@angular/core'
import {FormBuilder, FormControl, Validators} from '@angular/forms'
import {SubscribingComponent} from '../shared/components/subscribing.component'
import {Component, HostListener, ViewChild} from '@angular/core'
import {FormControl, Validators} from '@angular/forms'
import {ErrorHandlingComponent} from '../shared/components/subscribing.component'
import {AccountService} from './services/account.service'
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 {CreForm, ICreForm} from "../shared/components/forms/forms";
import {take, takeUntil} from "rxjs/operators";
import {AlertService} from "../shared/service/alert.service";
@Component({
selector: 'cre-login',
@ -13,13 +16,20 @@ import {ActivatedRoute, Router} from '@angular/router'
'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]+$'))]))
passwordControl = new FormControl(null, Validators.required)
errorHandlers: ErrorHandler[] = [{
filter: error => error.status === 403,
messageProducer: () => 'Les identifiants entrés sont invalides'
}]
constructor(
private formBuilder: FormBuilder,
private accountService: AccountService,
private alertService: AlertService,
private appState: AppState,
errorService: ErrorService,
router: Router,
@ -29,12 +39,27 @@ export class Login extends SubscribingComponent {
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() {
this.accountService.login(
this.userIdControl.value,
this.passwordControl.value,
() => this.urlUtils.navigateTo('/color')
)
// Does not use SubscribingComponent shortcut because backend doesn't return expected error type
this.accountService.login(this.userIdControl.value, this.passwordControl.value)
.pipe(take(1), takeUntil(this.destroy$))
.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 } {

View File

@ -18,10 +18,11 @@
</cre-input>
</cre-form-content>
<cre-form-actions>
<cre-submit-button
text="Connexion"
[form]="form"
(submit)="submit()">
</cre-submit-button>
<cre-accent-button
type="submit"
[disabled]="!form.valid"
(click)="submit()">
Connexion
</cre-accent-button>
</cre-form-actions>
</cre-form>

View File

@ -44,10 +44,12 @@ export class LoginComponent extends ErrorHandlingComponent implements OnInit {
}
submit() {
this.accountService.login(
this.idFormControl.value,
this.passwordFormControl.value,
() => this.router.navigate(['/color'])
this.subscribe(
this.accountService.login(
this.idFormControl.value,
this.passwordFormControl.value
),
response => console.log(response)
)
}
}

View File

@ -1,6 +1,6 @@
import {Injectable, OnDestroy} from '@angular/core'
import {Subject} from 'rxjs'
import {take, takeUntil} from 'rxjs/operators'
import {Observable, Subject} from 'rxjs'
import {take, takeUntil, tap} from 'rxjs/operators'
import {AppState} from '../../shared/app-state'
import {HttpClient, HttpResponse} from '@angular/common/http'
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}
globalLoadingWheel.show()
this.http.post<any>(`${environment.apiUrl}/login`, loginForm, {

View File

@ -3,7 +3,7 @@
<cre-primary-button routerLink="/color/list">Retour</cre-primary-button>
</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-bar>

View File

@ -2,7 +2,7 @@ import {Component, ContentChild, EventEmitter, Input, Output} from '@angular/cor
import {ICreForm} from './forms';
@Component({
selector: 'cre-submit-button',
selector: 'cre-form-submit-button',
templateUrl: 'submit-button.html'
})
export class CreSubmitButton {

View File

@ -5,7 +5,7 @@
</mat-card-title>
</mat-card-header>
<mat-card-content [class.no-action]="!hasActions">
<form [formGroup]="form">
<form [formGroup]="formGroup">
<ng-content select="cre-form-content"></ng-content>
</form>
</mat-card-content>

View File

@ -2,7 +2,7 @@ import {Component, ContentChild, Directive, Input, OnInit, ViewEncapsulation} fr
import {FormBuilder, FormGroup} from '@angular/forms'
export interface ICreForm {
form: FormGroup
formGroup: FormGroup
valid: boolean
invalid: boolean
}
@ -35,7 +35,7 @@ export class CreForm implements ICreForm, OnInit {
@ContentChild(CreFormActions) formActions: CreFormActions
@Input() formControls: { [key: string]: any }
form: FormGroup
formGroup: FormGroup
constructor(
private formBuilder: FormBuilder
@ -43,7 +43,7 @@ export class CreForm implements ICreForm, OnInit {
}
ngOnInit(): void {
this.form = this.formBuilder.group(this.formControls)
this.formGroup = this.formBuilder.group(this.formControls)
}
get hasActions(): boolean {
@ -51,10 +51,10 @@ export class CreForm implements ICreForm, OnInit {
}
get valid(): boolean {
return this.form && this.form.valid
return this.formGroup && this.formGroup.valid
}
get invalid(): boolean {
return !this.form || this.form.invalid
return !this.formGroup || this.formGroup.invalid
}
}

View File

@ -1,5 +1,6 @@
import {
AfterViewInit, ChangeDetectorRef,
AfterViewInit,
ChangeDetectorRef,
Component,
ContentChild,
Directive,
@ -16,7 +17,7 @@ import {
import {AbstractControl, FormControl, ValidationErrors, ValidatorFn, Validators} from '@angular/forms'
import {COMMA, ENTER} from '@angular/cdk/keycodes'
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 {MatAutocomplete, MatAutocompleteSelectedEvent} from '@angular/material/autocomplete'