Merge pull request #12 from HideyoshiNakazone/devel
Devel - Better Loading Response and Validations
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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": {
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<div class="error-box" *ngIf="errorMessage">
|
||||||
|
{{errorMessage}}
|
||||||
|
</div>
|
||||||
@@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
14
src/app/header/header-popup/error-box/error-box.component.ts
Normal file
14
src/app/header/header-popup/error-box/error-box.component.ts
Normal 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() { }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
<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"
|
||||||
|
[@showErrorMessage]="showErrorMessage()">
|
||||||
|
</app-error-box>
|
||||||
|
|
||||||
|
<div class="container authentication-container"
|
||||||
|
[@hideAuthContainer]="hideErrorMessage()"
|
||||||
|
(@hideAuthContainer.done)="hideAuthContainer($event)">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-6 authentication-body">
|
<div class="col-lg-6 authentication-body">
|
||||||
<form [formGroup]="loginForm" (ngSubmit)="onLogin()">
|
<form [formGroup]="loginForm" (ngSubmit)="onLogin()">
|
||||||
@@ -27,6 +34,7 @@
|
|||||||
placeholder="Password">
|
placeholder="Password">
|
||||||
</div>
|
</div>
|
||||||
<button class="btn"
|
<button class="btn"
|
||||||
|
[disabled]="loginForm.invalid"
|
||||||
type="submit">
|
type="submit">
|
||||||
Login
|
Login
|
||||||
</button>
|
</button>
|
||||||
@@ -54,4 +62,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</app-popup>
|
</app-popup>
|
||||||
@@ -9,6 +9,9 @@ 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,7 +20,70 @@ 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 {
|
||||||
|
|
||||||
@@ -30,14 +96,14 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
@Output()
|
@Output()
|
||||||
stateChange = new EventEmitter<boolean>();
|
stateChange = new EventEmitter<boolean>();
|
||||||
|
|
||||||
popupState = false;
|
|
||||||
|
|
||||||
loginForm!: FormGroup;
|
loginForm!: FormGroup;
|
||||||
|
|
||||||
authSubject!: Subscription;
|
authSubject!: Subscription;
|
||||||
|
|
||||||
errorMessage!: string | null;
|
errorMessage!: string | null;
|
||||||
|
|
||||||
|
isShowErrorMessage = false;
|
||||||
|
|
||||||
_userIcon = faUser;
|
_userIcon = faUser;
|
||||||
|
|
||||||
_passwordIcon = faLock;
|
_passwordIcon = faLock;
|
||||||
@@ -59,8 +125,8 @@ export class LoginComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
<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="container m-0 overflow-hidden"
|
||||||
|
[@resizeContainerForErrorMessage]="hideErrorMessage()">
|
||||||
|
|
||||||
|
<app-error-box [errorMessage]="errorMessage"
|
||||||
|
[@showErrorMessage]="showErrorMessage()">
|
||||||
|
</app-error-box>
|
||||||
|
|
||||||
|
<div class="container authentication-container"
|
||||||
|
[@hideAuthContainer]="hideErrorMessage()"
|
||||||
|
(@hideAuthContainer.done)="hideAuthContainer($event)">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-6 auth-body auth-body-form">
|
<div class="col-lg-6 auth-body auth-body-form">
|
||||||
<form [formGroup]="signupForm" (ngSubmit)="onSignUp()">
|
<form [formGroup]="signupForm" (ngSubmit)="onSignUp()">
|
||||||
@@ -43,6 +53,7 @@
|
|||||||
placeholder="Password">
|
placeholder="Password">
|
||||||
</div>
|
</div>
|
||||||
<button class="btn"
|
<button class="btn"
|
||||||
|
[disabled]="!signupForm.valid"
|
||||||
type="submit">
|
type="submit">
|
||||||
SignUp
|
SignUp
|
||||||
</button>
|
</button>
|
||||||
@@ -70,4 +81,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</app-popup>
|
</app-popup>
|
||||||
@@ -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,7 +21,70 @@ 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 {
|
||||||
|
|
||||||
@@ -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;
|
||||||
@@ -59,12 +128,12 @@ export class SignupComponent implements OnInit {
|
|||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
|||||||
declarations: [
|
declarations: [
|
||||||
ClickedOutsideDirective,
|
ClickedOutsideDirective,
|
||||||
SliderItemComponent,
|
SliderItemComponent,
|
||||||
PopupComponent
|
PopupComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
|||||||
11
src/app/shared/validators/validate-email.validator.ts
Normal file
11
src/app/shared/validators/validate-email.validator.ts
Normal 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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
11
src/app/shared/validators/validate-password.validator.ts
Normal file
11
src/app/shared/validators/validate-password.validator.ts
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user