Merge pull request #11 from HideyoshiNakazone/better-loading-response

Better Loading Response and Validations
This commit is contained in:
2023-08-02 00:52:31 -03:00
committed by GitHub
22 changed files with 514 additions and 216 deletions

View File

@@ -4,7 +4,7 @@ root = true
[*] [*]
charset = utf-8 charset = utf-8
indent_style = space indent_style = space
indent_size = 2 indent_size = 4
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true

View File

@@ -2,7 +2,8 @@
"name": "frontend-hideyoshi.com", "name": "frontend-hideyoshi.com",
"version": "0.0.0", "version": "0.0.0",
"scripts": { "scripts": {
"start": "node ./server.js" "start": "node ./server.js",
"serve": "ng serve"
}, },
"proxy": { "proxy": {
"/callback": { "/callback": {

View File

@@ -1,5 +1,5 @@
const express = require('express'); const express = require('express');
var cors = require('cors'); const cors = require('cors');
const path = require('path'); const path = require('path');
const PKG_NAME = "frontend-hideyoshi.com"; const PKG_NAME = "frontend-hideyoshi.com";

View File

@@ -19,10 +19,16 @@ export class CallbackComponent implements OnInit {
let auth: 'google' | 'github' = p['auth']; let auth: 'google' | 'github' = p['auth'];
if (auth === 'google') { switch (auth) {
this.loginGoogle(p); case "github":
} else if (auth === 'github') { this.authService.loginGithubUser(p)
this.loginGithub(p); break;
case "google":
this.authService.loginGoogleUser(p)
break;
default:
console.log(`Unimplemented auth: ${auth}`)
break;
} }
this.router.navigate(['/home']) this.router.navigate(['/home'])
@@ -30,12 +36,4 @@ export class CallbackComponent implements OnInit {
}) })
} }
private loginGoogle(p: any) {
this.authService.loginGoogleUser(p)
}
private loginGithub(p: any) {
this.authService.loginGithubUser(p)
}
} }

View File

@@ -0,0 +1,11 @@
.error-box {
background-color: #ff00001a;
max-width: 320px;
display: flex;
border-radius: 5px;
padding: 25px;
margin: 0 auto;
color: #ff0000;
font-size: 14px;
font-weight: 500;
}

View File

@@ -0,0 +1,3 @@
<div class="error-box" *ngIf="errorMessage">
{{errorMessage}}
</div>

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ErrorBoxComponent } from './error-box.component';
describe('ErrorBoxComponent', () => {
let component: ErrorBoxComponent;
let fixture: ComponentFixture<ErrorBoxComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ErrorBoxComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(ErrorBoxComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,14 @@
import {Component, Input} from '@angular/core';
@Component({
selector: 'app-error-box',
templateUrl: './error-box.component.html',
styleUrls: ['./error-box.component.css']
})
export class ErrorBoxComponent {
@Input()
errorMessage: string|null = "Error, please try again later."
constructor() { }
}

View File

@@ -78,13 +78,14 @@
background-color: #f44336; background-color: #f44336;
border-radius: 15px; border-radius: 15px;
} }
.input-div:hover:after { .input-div:hover:after,
.input-div:has(input.form-control:focus):after {
width: 100%; width: 100%;
transition: .4s; transition: .4s;
overflow: hidden; overflow: hidden;
} }
.input-div > .form-control, .input-div > .form-control:focus { .input-div > .form-control, .input-div > .form-control:hover{
border: none; border: none;
border-color: inherit; border-color: inherit;
-webkit-box-shadow: none; -webkit-box-shadow: none;
@@ -103,16 +104,21 @@
-webkit-box-shadow: 0 0 0px 1000px #ffffff inset; -webkit-box-shadow: 0 0 0px 1000px #ffffff inset;
} }
.input-div:has(input.form-control:focus) > .form-control::placeholder,
.input-div:hover > .form-control::placeholder, .input-div:hover > .form-control::placeholder,
.input-div:hover > .input-div-icon { .input-div:hover > .input-div-icon,
.input-div:has(input.form-control:focus) > .input-div-icon {
color: #D8291C; color: #D8291C;
transition: .3s; transition: .3s;
} }
.input-div:hover > .form-control::placeholder { .input-div:hover > .form-control::placeholder,
.input-div:has(input.form-control:focus) > .form-control::placeholder {
font-weight: 500; font-weight: 500;
transition: .3s; transition: .3s;
} }
@media (min-width:767px) { @media (min-width:767px) {
.authentication-container { .authentication-container {

View File

@@ -1,57 +1,67 @@
<app-popup [state]="popupState" <app-popup [state]="state"
(stateChange)="onStateChange($event)" (stateChange)="onStateChange($event)"
[ignoreClickOutside]="ignoreClickOutside"> [ignoreClickOutside]="ignoreClickOutside">
{{errorMessage}} <div class="container m-0 overflow-hidden"
[@resizeContainerForErrorMessage]="hideErrorMessage()">
<div class="container authentication-container"> <app-error-box [errorMessage]="errorMessage"
<div class="row"> [@showErrorMessage]="showErrorMessage()">
<div class="col-lg-6 authentication-body"> </app-error-box>
<form [formGroup]="loginForm" (ngSubmit)="onLogin()">
<div class="input-div"> <div class="container authentication-container"
<fa-icon class="input-div-icon" [@hideAuthContainer]="hideErrorMessage()"
[icon]="_userIcon"> (@hideAuthContainer.done)="hideAuthContainer($event)">
</fa-icon> <div class="row">
<input type="text" id="username" <div class="col-lg-6 authentication-body">
formControlName="username" <form [formGroup]="loginForm" (ngSubmit)="onLogin()">
class="form-control" <div class="input-div">
placeholder="Username"> <fa-icon class="input-div-icon"
</div> [icon]="_userIcon">
<div class="input-div"> </fa-icon>
<fa-icon class="input-div-icon" <input type="text" id="username"
[icon]="_passwordIcon"> formControlName="username"
</fa-icon> class="form-control"
<input type="password" id="password" placeholder="Username">
formControlName="password" </div>
class="form-control" <div class="input-div">
placeholder="Password"> <fa-icon class="input-div-icon"
</div> [icon]="_passwordIcon">
<button class="btn" </fa-icon>
type="submit"> <input type="password" id="password"
Login formControlName="password"
class="form-control"
placeholder="Password">
</div>
<button class="btn"
[disabled]="loginForm.invalid"
type="submit">
Login
</button>
</form>
</div>
<div class="separator-line">
<div class="line"></div>
</div>
<div class="col-lg-6 authentication-body">
<button mat-button
class="oauth-button d-flex justify-content-center align-items-center"
(click)="onGoogleLogin()">
<mat-icon style="width: 50px; height:30px"
svgIcon="google-logo"></mat-icon>
Login With Google
</button> </button>
</form> <button mat-button
</div> class="oauth-button d-flex justify-content-center align-items-center"
<div class="separator-line"> (click)="onGithubLogin()">
<div class="line"></div> <mat-icon style="width: 50px; height:30px"
</div> svgIcon="github-logo"></mat-icon>
<div class="col-lg-6 authentication-body"> Login With Github
<button mat-button </button>
class="oauth-button d-flex justify-content-center align-items-center" </div>
(click)="onGoogleLogin()">
<mat-icon style="width: 50px; height:30px"
svgIcon="google-logo"></mat-icon>
Login With Google
</button>
<button mat-button
class="oauth-button d-flex justify-content-center align-items-center"
(click)="onGithubLogin()">
<mat-icon style="width: 50px; height:30px"
svgIcon="github-logo"></mat-icon>
Login With Github
</button>
</div> </div>
</div> </div>
</div> </div>
</app-popup> </app-popup>

View File

@@ -3,12 +3,15 @@ import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MatIconRegistry } from '@angular/material/icon'; import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { faLock, faUser } from '@fortawesome/free-solid-svg-icons'; import { faLock, faUser } from '@fortawesome/free-solid-svg-icons';
import { Subscription } from 'rxjs'; import {Subscription} from 'rxjs';
import { AuthService } from 'src/app/shared/auth/auth.service'; import { AuthService } from 'src/app/shared/auth/auth.service';
import { HttpError } from 'src/app/shared/model/httpError/httpError.model'; import { HttpError } from 'src/app/shared/model/httpError/httpError.model';
import HttpErrorChecker from 'src/app/shared/model/httpError/httpErrorChecker'; import HttpErrorChecker from 'src/app/shared/model/httpError/httpErrorChecker';
import UserChecker from 'src/app/shared/model/user/user.checker'; import UserChecker from 'src/app/shared/model/user/user.checker';
import { User } from 'src/app/shared/model/user/user.model'; import { User } from 'src/app/shared/model/user/user.model';
import {animate, animateChild, group, query, state, style, transition, trigger} from "@angular/animations";
import {ValidatePasswordValidator} from "../../../shared/validators/validate-password.validator";
import {ValidateNotEmptyValidator} from "../../../shared/validators/validate-not-empty.validator";
const GOOGLE_LOGO_SVG = "assets/img/providers/google.svg"; const GOOGLE_LOGO_SVG = "assets/img/providers/google.svg";
@@ -17,20 +20,81 @@ const GITHUB_LOGO_SVG = "assets/img/providers/github.svg";
@Component({ @Component({
selector: 'app-login', selector: 'app-login',
templateUrl: './login.component.html', templateUrl: './login.component.html',
styleUrls: ['./login.component.css'] styleUrls: ['./login.component.css'],
animations: [
trigger('resizeContainerForErrorMessage', [
state('hide',
style({
height: '100px',
width: '320px',
})
),
transition(
'show => hide',
group([
query(
"@*",
animateChild(),
{ optional: true }
),
animate('1s ease')
])
)
]),
trigger('showErrorMessage', [
state('show',
style({
opacity: 1,
height: '100px',
width: '320px',
})
),
state('hide',
style({
opacity: 0,
height: '0px',
width: '0px',
})
),
transition(
'* => show',
animate(
'500ms ease-in'
)
),
]),
trigger('hideAuthContainer', [
state('hide',
style({
opacity: 0,
})
),
transition(
'show => hide',
group([
query(
"@*",
animateChild(),
{ optional: true }
),
animate(
'250ms ease-out'
)
])
)
]),
]
}) })
export class LoginComponent implements OnInit, AfterViewInit, OnDestroy { export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
@Input() @Input()
state: boolean = false; state: boolean = false;
@Input() @Input()
ignoreClickOutside!: HTMLDivElement[]; ignoreClickOutside!: HTMLDivElement[];
@Output() @Output()
stateChange = new EventEmitter<boolean>(); stateChange = new EventEmitter<boolean>();
popupState = false;
loginForm!: FormGroup; loginForm!: FormGroup;
@@ -38,6 +102,8 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
errorMessage!: string | null; errorMessage!: string | null;
isShowErrorMessage = false;
_userIcon = faUser; _userIcon = faUser;
_passwordIcon = faLock; _passwordIcon = faLock;
@@ -47,20 +113,20 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
private changeDetectorRef: ChangeDetectorRef, private changeDetectorRef: ChangeDetectorRef,
private matIconRegistry: MatIconRegistry, private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer) { private domSanitizer: DomSanitizer) {
this.matIconRegistry.addSvgIcon( this.matIconRegistry.addSvgIcon(
"google-logo", "google-logo",
this.domSanitizer.bypassSecurityTrustResourceUrl(GOOGLE_LOGO_SVG) this.domSanitizer.bypassSecurityTrustResourceUrl(GOOGLE_LOGO_SVG)
); );
this.matIconRegistry.addSvgIcon( this.matIconRegistry.addSvgIcon(
"github-logo", "github-logo",
this.domSanitizer.bypassSecurityTrustResourceUrl(GITHUB_LOGO_SVG) this.domSanitizer.bypassSecurityTrustResourceUrl(GITHUB_LOGO_SVG)
); );
} }
ngOnInit(): void { ngOnInit(): void {
this.loginForm = new FormGroup({ this.loginForm = new FormGroup({
'username': new FormControl(null, [Validators.required]), 'username': new FormControl(null, [Validators.required, ValidateNotEmptyValidator]),
'password': new FormControl(null, [Validators.required]) 'password': new FormControl(null, [Validators.required, ValidatePasswordValidator])
}); });
this.errorMessage = null; this.errorMessage = null;
this.authSubject = this.authService.authSubject.subscribe( this.authSubject = this.authService.authSubject.subscribe(
@@ -71,7 +137,6 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {
this.popupState = this.state;
this.changeDetectorRef.detectChanges(); this.changeDetectorRef.detectChanges();
} }
@@ -89,7 +154,6 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
password: this.loginForm.controls['password'].value password: this.loginForm.controls['password'].value
} }
this.authService.login(user); this.authService.login(user);
} }
onGoogleLogin() { onGoogleLogin() {
@@ -110,8 +174,29 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
} }
private closePopup() { private closePopup() {
this.popupState = false; this.state = false;
this.loginForm.reset(); this.loginForm.reset();
} }
public showErrorMessage(): string {
if (this.isShowErrorMessage) {
return "show";
}
return "hide";
}
public hideErrorMessage(): string {
if (!!this.errorMessage) {
return "hide";
}
return "show";
}
hideAuthContainer(event: any) {
if (event.toState === "hide") {
event.element.style.display = "none";
this.isShowErrorMessage = true;
}
}
} }

View File

@@ -81,7 +81,8 @@
background-color: #f44336; background-color: #f44336;
border-radius: 15px; border-radius: 15px;
} }
.input-div:hover:after { .input-div:hover:after,
.input-div:has(input.form-control:focus):after {
width: 100%; width: 100%;
transition: .4s; transition: .4s;
overflow: hidden; overflow: hidden;
@@ -106,12 +107,15 @@
-webkit-box-shadow: 0 0 0px 1000px #ffffff inset; -webkit-box-shadow: 0 0 0px 1000px #ffffff inset;
} }
.input-div:has(input.form-control:focus) > .form-control::placeholder,
.input-div:hover > .form-control::placeholder, .input-div:hover > .form-control::placeholder,
.input-div:hover > .input-div-icon { .input-div:hover > .input-div-icon,
.input-div:has(input.form-control:focus) > .input-div-icon {
color: #D8291C; color: #D8291C;
transition: .3s; transition: .3s;
} }
.input-div:hover > .form-control::placeholder { .input-div:hover > .form-control::placeholder,
.input-div:focus > .form-control::placeholder{
font-weight: 500; font-weight: 500;
transition: .3s; transition: .3s;
} }

View File

@@ -1,73 +1,86 @@
<app-popup [state]="state" <app-popup [state]="state"
(stateChange)="onStateChange($event)" (stateChange)="onStateChange($event)"
[ignoreClickOutside]="ignoreClickOutside"> [ignoreClickOutside]="ignoreClickOutside">
{{errorMessage}}
<div class="container authentication-container">
<div class="row"> <div class="container m-0 overflow-hidden"
<div class="col-lg-6 auth-body auth-body-form"> [@resizeContainerForErrorMessage]="hideErrorMessage()">
<form [formGroup]="signupForm" (ngSubmit)="onSignUp()">
<div class="input-div"> <app-error-box [errorMessage]="errorMessage"
<fa-icon class="input-div-icon" [@showErrorMessage]="showErrorMessage()">
[icon]="_fullnameIcon"> </app-error-box>
</fa-icon>
<input type="text" id="fullname" <div class="container authentication-container"
formControlName="fullname" [@hideAuthContainer]="hideErrorMessage()"
class="form-control" (@hideAuthContainer.done)="hideAuthContainer($event)">
placeholder="Full Name"> <div class="row">
</div> <div class="col-lg-6 auth-body auth-body-form">
<div class="input-div"> <form [formGroup]="signupForm" (ngSubmit)="onSignUp()">
<fa-icon class="input-div-icon" <div class="input-div">
[icon]="_emailIcon"> <fa-icon class="input-div-icon"
</fa-icon> [icon]="_fullnameIcon">
<input type="text" id="email" </fa-icon>
formControlName="email" <input type="text" id="fullname"
class="form-control" formControlName="fullname"
placeholder="Email"> class="form-control"
</div> placeholder="Full Name">
<div class="input-div"> </div>
<fa-icon class="input-div-icon" <div class="input-div">
[icon]="_userIcon"> <fa-icon class="input-div-icon"
</fa-icon> [icon]="_emailIcon">
<input type="text" id="username" </fa-icon>
formControlName="username" <input type="text" id="email"
class="form-control" formControlName="email"
placeholder="Username"> class="form-control"
</div> placeholder="Email">
<div class="input-div"> </div>
<fa-icon class="input-div-icon" <div class="input-div">
[icon]="_passwordIcon"> <fa-icon class="input-div-icon"
</fa-icon> [icon]="_userIcon">
<input type="password" id="password" </fa-icon>
formControlName="password" <input type="text" id="username"
class="form-control" formControlName="username"
placeholder="Password"> class="form-control"
</div> placeholder="Username">
<button class="btn" </div>
type="submit"> <div class="input-div">
SignUp <fa-icon class="input-div-icon"
[icon]="_passwordIcon">
</fa-icon>
<input type="password" id="password"
formControlName="password"
class="form-control"
placeholder="Password">
</div>
<button class="btn"
[disabled]="!signupForm.valid"
type="submit">
SignUp
</button>
</form>
</div>
<div class="separator-line">
<div class="line"></div>
</div>
<div class="col-lg-6 auth-body auth-body-links">
<button mat-button
class="oauth-button d-flex justify-content-center align-items-center"
(click)="onGoogleLogin()">
<mat-icon style="width: 50px; height:30px"
svgIcon="google-logo"></mat-icon>
Login With Google
</button> </button>
</form> <button mat-button
</div> class="oauth-button d-flex justify-content-center align-items-center"
<div class="separator-line"> (click)="onGithubLogin()">
<div class="line"></div> <mat-icon style="width: 50px; height:30px"
</div> svgIcon="github-logo"></mat-icon>
<div class="col-lg-6 auth-body auth-body-links"> Login With Github
<button mat-button </button>
class="oauth-button d-flex justify-content-center align-items-center" </div>
(click)="onGoogleLogin()">
<mat-icon style="width: 50px; height:30px"
svgIcon="google-logo"></mat-icon>
Login With Google
</button>
<button mat-button
class="oauth-button d-flex justify-content-center align-items-center"
(click)="onGithubLogin()">
<mat-icon style="width: 50px; height:30px"
svgIcon="github-logo"></mat-icon>
Login With Github
</button>
</div> </div>
</div> </div>
</div> </div>
</app-popup> </app-popup>

View File

@@ -9,6 +9,10 @@ import { HttpError } from 'src/app/shared/model/httpError/httpError.model';
import HttpErrorChecker from 'src/app/shared/model/httpError/httpErrorChecker'; import HttpErrorChecker from 'src/app/shared/model/httpError/httpErrorChecker';
import UserChecker from 'src/app/shared/model/user/user.checker'; import UserChecker from 'src/app/shared/model/user/user.checker';
import { User } from 'src/app/shared/model/user/user.model'; import { User } from 'src/app/shared/model/user/user.model';
import {animate, animateChild, group, query, state, style, transition, trigger} from "@angular/animations";
import {ValidateEmailValidator} from "../../../shared/validators/validate-email.validator";
import {ValidatePasswordValidator} from "../../../shared/validators/validate-password.validator";
import {ValidateNotEmptyValidator} from "../../../shared/validators/validate-not-empty.validator";
const GOOGLE_LOGO_SVG = "assets/img/providers/google.svg"; const GOOGLE_LOGO_SVG = "assets/img/providers/google.svg";
@@ -17,18 +21,81 @@ const GITHUB_LOGO_SVG = "assets/img/providers/github.svg";
@Component({ @Component({
selector: 'app-signup', selector: 'app-signup',
templateUrl: './signup.component.html', templateUrl: './signup.component.html',
styleUrls: ['./signup.component.css'] styleUrls: ['./signup.component.css'],
animations: [
trigger('resizeContainerForErrorMessage', [
state('hide',
style({
height: '100px',
width: '320px',
})
),
transition(
'show => hide',
group([
query(
"@*",
animateChild(),
{ optional: true }
),
animate('1s ease')
])
)
]),
trigger('showErrorMessage', [
state('show',
style({
opacity: 1,
height: '100px',
width: '320px',
})
),
state('hide',
style({
opacity: 0,
height: '0px',
width: '0px',
})
),
transition(
'* => show',
animate(
'500ms ease-in'
)
),
]),
trigger('hideAuthContainer', [
state('hide',
style({
opacity: 0,
})
),
transition(
'show => hide',
group([
query(
"@*",
animateChild(),
{ optional: true }
),
animate(
'250ms ease-out'
)
])
)
]),
]
}) })
export class SignupComponent implements OnInit { export class SignupComponent implements OnInit {
@Input() @Input()
state: boolean = false; state: boolean = false;
@Input() @Input()
ignoreClickOutside!: HTMLDivElement[]; ignoreClickOutside!: HTMLDivElement[];
@Output() @Output()
stateChange = new EventEmitter<boolean>(); stateChange = new EventEmitter<boolean>();
signupForm!: FormGroup; signupForm!: FormGroup;
@@ -36,6 +103,8 @@ export class SignupComponent implements OnInit {
errorMessage!: string | null; errorMessage!: string | null;
isShowErrorMessage = false;
_fullnameIcon = faFingerprint; _fullnameIcon = faFingerprint;
_emailIcon = faEnvelope; _emailIcon = faEnvelope;
@@ -47,24 +116,24 @@ export class SignupComponent implements OnInit {
constructor(private authService: AuthService, constructor(private authService: AuthService,
private matIconRegistry: MatIconRegistry, private matIconRegistry: MatIconRegistry,
private domSanitizer: DomSanitizer) { private domSanitizer: DomSanitizer) {
this.matIconRegistry.addSvgIcon( this.matIconRegistry.addSvgIcon(
"google-logo", "google-logo",
this.domSanitizer.bypassSecurityTrustResourceUrl(GOOGLE_LOGO_SVG) this.domSanitizer.bypassSecurityTrustResourceUrl(GOOGLE_LOGO_SVG)
); );
this.matIconRegistry.addSvgIcon( this.matIconRegistry.addSvgIcon(
"github-logo", "github-logo",
this.domSanitizer.bypassSecurityTrustResourceUrl(GITHUB_LOGO_SVG) this.domSanitizer.bypassSecurityTrustResourceUrl(GITHUB_LOGO_SVG)
); );
} }
ngOnInit(): void { ngOnInit(): void {
this.signupForm = new FormGroup({ this.signupForm = new FormGroup({
'fullname': new FormControl(null, [Validators.required]), 'fullname': new FormControl(null, [Validators.required, ValidateNotEmptyValidator]),
// Create a Email Validator // Create a Email Validator
'email': new FormControl(null, [Validators.required]), 'email': new FormControl(null, [Validators.required, ValidateEmailValidator]),
'username': new FormControl(null, [Validators.required]), 'username': new FormControl(null, [Validators.required, ValidateNotEmptyValidator]),
// Create a Password Validator // Create a Password Validator
'password': new FormControl(null, [Validators.required]) 'password': new FormControl(null, [Validators.required, ValidatePasswordValidator])
}); });
this.errorMessage = null; this.errorMessage = null;
this.authSubject = this.authService.authSubject.subscribe( this.authSubject = this.authService.authSubject.subscribe(
@@ -110,5 +179,26 @@ export class SignupComponent implements OnInit {
this.signupForm.reset(); this.signupForm.reset();
} }
public showErrorMessage(): string {
if (this.isShowErrorMessage) {
return "show";
}
return "hide";
}
public hideErrorMessage(): string {
if (!!this.errorMessage) {
return "hide";
}
return "show";
}
hideAuthContainer(event: any) {
if (event.toState === "hide") {
event.element.style.display = "none";
this.isShowErrorMessage = true;
}
}
} }

View File

@@ -1,5 +1,5 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import {CommonModule, NgOptimizedImage} from '@angular/common';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations' import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
import { HeaderComponent } from './header.component'; import { HeaderComponent } from './header.component';
@@ -15,6 +15,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { SignupComponent } from './header-popup/signup/signup.component'; import { SignupComponent } from './header-popup/signup/signup.component';
import { CallbackComponent } from './header-popup/callback/callback.component'; import { CallbackComponent } from './header-popup/callback/callback.component';
import {MatIconModule} from '@angular/material/icon'; import {MatIconModule} from '@angular/material/icon';
import { ErrorBoxComponent } from './header-popup/error-box/error-box.component';
@@ -27,7 +28,8 @@ import {MatIconModule} from '@angular/material/icon';
HeaderDropdownComponent, HeaderDropdownComponent,
LoginComponent, LoginComponent,
SignupComponent, SignupComponent,
CallbackComponent CallbackComponent,
ErrorBoxComponent,
], ],
imports: [ imports: [
CommonModule, CommonModule,
@@ -37,7 +39,8 @@ import {MatIconModule} from '@angular/material/icon';
FormsModule, FormsModule,
ReactiveFormsModule, ReactiveFormsModule,
MatIconModule, MatIconModule,
SharedModule SharedModule,
NgOptimizedImage
], exports: [ ], exports: [
HeaderComponent, HeaderComponent,
HeaderSliderComponent, HeaderSliderComponent,

View File

@@ -1,8 +1,8 @@
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { first, firstValueFrom, Observable, Subject, take } from 'rxjs'; import {first, firstValueFrom, Observable, of, Subject, take} from 'rxjs';
import { catchError } from 'rxjs/operators';
import { environment } from 'src/environments/environment'; import { environment } from 'src/environments/environment';
import { param } from 'ts-interface-checker';
import { HttpError } from '../model/httpError/httpError.model'; import { HttpError } from '../model/httpError/httpError.model';
import { Token } from '../model/token/token.model'; import { Token } from '../model/token/token.model';
import { User } from '../model/user/user.model'; import { User } from '../model/user/user.model';
@@ -133,18 +133,6 @@ export class AuthService {
) )
} }
private validateUser(userAuthAtempt: Observable<User>) {
userAuthAtempt.subscribe({
next: userAuthentication => {
this.userAuthenticated = <User>userAuthentication;
this.authSubject.next(this.userAuthenticated);
},
error: err => {
this.authSubject.next(<HttpError>err.error);
}
});
}
private refreshAccessToken() { private refreshAccessToken() {
return firstValueFrom(this.http.post( return firstValueFrom(this.http.post(
this.BACKEND_PATH + "/user/login/refresh", this.BACKEND_PATH + "/user/login/refresh",
@@ -157,19 +145,37 @@ export class AuthService {
return this.http.get<User>( return this.http.get<User>(
this.BACKEND_PATH + '/session/validate', this.BACKEND_PATH + '/session/validate',
{ withCredentials: true } { withCredentials: true }
).pipe(
first()
); );
} }
private destroySessions() { private destroySessions() {
return this.http.post( return this.http.delete(
this.BACKEND_PATH + '/session/destroy', this.BACKEND_PATH + '/session/destroy',
{},
{ withCredentials: true } { withCredentials: true }
).pipe(
take(1)
); );
} }
private validateUser(userAuthAtempt: Observable<User>) {
userAuthAtempt.pipe(
catchError(error => {
if (error.status == 0) {
return of(<HttpError>{
title: "Service Unavailable",
status: 500,
details: "Service Unavailable, please try again later.",
developerMessage: "Service Unavailable, please try again later.",
timestamp: new Date().toISOString()
});
}
return of(<HttpError>error.error);
}),
first()
).subscribe({
next: userAuthentication => {
this.userAuthenticated = <User>userAuthentication;
this.authSubject.next(this.userAuthenticated);
}
});
}
} }

View File

@@ -64,7 +64,7 @@
.popup-body { .popup-body {
height: calc(100% - 120px); height: calc(100% - 120px);
padding: 0px 60px; padding: 0px 30px;
width: 100%; width: 100%;
margin: 0; margin: 0;
} }

View File

@@ -11,7 +11,7 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
declarations: [ declarations: [
ClickedOutsideDirective, ClickedOutsideDirective,
SliderItemComponent, SliderItemComponent,
PopupComponent PopupComponent,
], ],
imports: [ imports: [
CommonModule, CommonModule,

View File

@@ -0,0 +1,11 @@
import {AbstractControl} from "@angular/forms";
export function ValidateEmailValidator(control: AbstractControl) {
const email = control.value;
const emailRegex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/g;
const emailValid = emailRegex.test(email);
if (!emailValid) {
return { invalidEmail: true };
}
return null;
}

View File

@@ -0,0 +1,9 @@
import {AbstractControl} from "@angular/forms";
export function ValidateNotEmptyValidator(control: AbstractControl) {
const value = control.value;
if (!value || value.length === 0) {
return { invalidNotEmpty: true };
}
return null;
}

View File

@@ -0,0 +1,11 @@
import {AbstractControl} from "@angular/forms";
export function ValidatePasswordValidator(control: AbstractControl) {
var password = control.value;
var passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/g;
var passwordValid = passwordRegex.test(password);
if (!passwordValid) {
return { invalidPassword: true };
}
return null;
}