projects/web-mev/src/app/features/user/login/login.component.ts
Login Component
Support sign-in with email/password and Google sign-in
| selector | mev-login-form |
| styleUrls | ./login.component.scss |
| templateUrl | ./login.component.html |
Properties |
Methods |
Accessors |
constructor(formBuilder: FormBuilder, route: ActivatedRoute, router: Router, authenticationService: AuthenticationService, userService: UserService, socialAuthService: SocialAuthService)
|
|||||||||||||||||||||
|
Parameters :
|
| activateUser |
activateUser()
|
|
Returns :
void
|
| ngOnInit |
ngOnInit()
|
|
Initialize login form
Returns :
void
|
| onSubmit |
onSubmit()
|
|
Returns :
void
|
| signInWithGoogle |
signInWithGoogle()
|
|
Method to sign out with Google
Returns :
void
|
| signOut |
signOut()
|
|
Generic method to sign out, regardless of Auth provider
Returns :
void
|
| isUserActivated |
Type : null
|
Default value : null
|
| loading |
Default value : false
|
| loginForm |
Type : FormGroup
|
| returnUrl |
Type : string
|
| routeAnimationsElements |
Default value : ROUTE_ANIMATIONS_ELEMENTS
|
| submitted |
Default value : false
|
| token |
Type : string
|
| uid |
Type : string
|
| f |
getf()
|
|
Convenience getter for easy access to form fields |
import { Component, OnInit } from '@angular/core';
import { AuthenticationService } from '@app/core/authentication/authentication.service';
import { UserService } from '@app/core/user/user.service';
import { Router, ActivatedRoute } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { finalize } from 'rxjs/operators';
import { ROUTE_ANIMATIONS_ELEMENTS } from '@core/core.module';
import { GoogleLoginProvider, SocialAuthService } from 'angularx-social-login';
/**
* Login Component
*
* Support sign-in with email/password and Google sign-in
*/
@Component({
selector: 'mev-login-form',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
routeAnimationsElements = ROUTE_ANIMATIONS_ELEMENTS;
loginForm: FormGroup;
loading = false;
submitted = false;
returnUrl: string;
isUserActivated = null;
token: string;
uid: string;
constructor(
private formBuilder: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private authenticationService: AuthenticationService,
private userService: UserService,
private socialAuthService: SocialAuthService
) {
// redirect to home if already logged in
if (this.authenticationService.currentUserValue) {
this.router.navigate(['/workarea']);
}
// if uid and token exist, activate a new account
this.route.params.subscribe(params => {
if (params.token && params.uid) {
this.token = params.token;
this.uid = params.uid;
this.activateUser();
}
});
}
activateUser() {
this.isUserActivated = true;
this.userService.activate({ token: this.token, uid: this.uid }).subscribe(
data => {
this.isUserActivated = true;
},
err => {
this.isUserActivated = false;
}
);
}
/**
* Initialize login form
*/
ngOnInit(): void {
this.loginForm = this.formBuilder.group({
email: ['', Validators.required],
password: ['', Validators.required]
});
// get return url from route parameters or default to '/'
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
}
/**
* Convenience getter for easy access to form fields
*/
get f() {
return this.loginForm.controls;
}
onSubmit() {
this.submitted = true;
// stop here if form is invalid
if (this.loginForm.invalid) {
return;
}
this.loading = true;
this.authenticationService
.login(this.f.email.value, this.f.password.value)
.subscribe(
data => {
this.router.navigate([this.returnUrl]);
},
error => {
this.loading = false;
}
);
}
/**
* Method to sign out with Google
*/
signInWithGoogle(): void {
const socialPlatformProvider = GoogleLoginProvider.PROVIDER_ID;
this.loading = true;
this.socialAuthService.signIn(socialPlatformProvider).then(userData => {
// Google returns user data. Send user token to the server
localStorage.setItem('socialUser', JSON.stringify(userData));
this.authenticationService
.googleSignInExternal(userData.authToken)
.pipe(finalize(() => (this.loading = false)))
.subscribe(result => {
this.router.navigate(['/workarea']);
});
});
}
/**
* Generic method to sign out, regardless of Auth provider
*/
signOut(): void {
this.socialAuthService.signOut().then(data => {
// debugger;
this.router.navigate([`/login`]);
});
}
}
<div class="container" rtl>
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<div class="row justify-content-center">
<div class="col-md-8 form-group">
<mat-card>
<div class="login-note-text">
Sign In with Google:
</div>
<div class="row justify-content-center">
<button type="button" mat-raised-button class="google-button" (click)="signInWithGoogle()">
<span class="google-button__icon">
<svg viewBox="0 0 366 372" xmlns="http://www.w3.org/2000/svg"><path
d="M125.9 10.2c40.2-13.9 85.3-13.6 125.3 1.1 22.2 8.2 42.5 21 59.9 37.1-5.8 6.3-12.1 12.2-18.1 18.3l-34.2 34.2c-11.3-10.8-25.1-19-40.1-23.6-17.6-5.3-36.6-6.1-54.6-2.2-21 4.5-40.5 15.5-55.6 30.9-12.2 12.3-21.4 27.5-27 43.9-20.3-15.8-40.6-31.5-61-47.3 21.5-43 60.1-76.9 105.4-92.4z"
id="Shape" fill="#EA4335"/><path
d="M20.6 102.4c20.3 15.8 40.6 31.5 61 47.3-8 23.3-8 49.2 0 72.4-20.3 15.8-40.6 31.6-60.9 47.3C1.9 232.7-3.8 189.6 4.4 149.2c3.3-16.2 8.7-32 16.2-46.8z"
id="Shape" fill="#FBBC05"/><path
d="M361.7 151.1c5.8 32.7 4.5 66.8-4.7 98.8-8.5 29.3-24.6 56.5-47.1 77.2l-59.1-45.9c19.5-13.1 33.3-34.3 37.2-57.5H186.6c.1-24.2.1-48.4.1-72.6h175z"
id="Shape" fill="#4285F4"/><path
d="M81.4 222.2c7.8 22.9 22.8 43.2 42.6 57.1 12.4 8.7 26.6 14.9 41.4 17.9 14.6 3 29.7 2.6 44.4.1 14.6-2.6 28.7-7.9 41-16.2l59.1 45.9c-21.3 19.7-48 33.1-76.2 39.6-31.2 7.1-64.2 7.3-95.2-1-24.6-6.5-47.7-18.2-67.6-34.1-20.9-16.6-38.3-38-50.4-62 20.3-15.7 40.6-31.5 60.9-47.3z"
fill="#34A853"/></svg>
</span>
<span class="google-button__text">Sign in with Google</span>
</button>
</div>
<br>
<mat-divider></mat-divider>
<div class="login-note-text login-note-text--centered ">
or with email:
</div>
<!--span class="d-flex justify-content-between align-items-baseline">
<h2>{{ 'mev.menu.login' | translate }}</h2>
</span-->
<div class="msg msg--success" *ngIf="isUserActivated">
<span>Your account has been activated. Please use your email and password to log in</span>
</div>
<div class="msg msg--error" *ngIf="isUserActivated === false">
<span>Something went wrong. Your account has not been activated.</span>
</div>
<div class="row">
<mat-form-field class="col" [ngClass]="routeAnimationsElements">
<input matInput placeholder="E-mail"
formControlName="email" type="email">
<mat-error *ngIf="submitted && f.email.errors">
E-mail is required
</mat-error>
</mat-form-field>
</div>
<div class="row direction-col">
<mat-form-field class="col" [ngClass]="routeAnimationsElements">
<input matInput type="password" placeholder="Password"
formControlName="password">
<mat-error *ngIf="submitted && f.password.errors">
Password is required
</mat-error>
</mat-form-field>
<div class="forget-password-container">
<a class="forget-password-link help-text" [routerLink]="['/reset']">Forgot password?</a>
</div>
</div>
<div class="row buttons d-flex justify-content-center pad">
<button type="submit" mat-raised-button color="accent" [disabled]="loading"
[ngClass]="routeAnimationsElements">
<span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
Sign in
</button>
</div>
<div class="row buttons d-flex justify-content-center pad direction-col">
<div class="help-text">Don't have a MeV account?</div>
<button type="button" mat-raised-button color="primary" [ngClass]="routeAnimationsElements"
routerLink="/register">
Register
</button>
</div>
<!-- <div class="row justify-content-center">
<a class="footer-link" [routerLink]="['/reset']">Forgot password?</a>
</div> -->
</mat-card>
</div>
</div>
</form>
</div>
./login.component.scss
.main-heading {
text-transform: uppercase;
margin: 0 0 20px 0;
text-align: center;
}
mat-card {
margin-top: 50px;
margin-bottom: 20px;
}
mat-checkbox {
margin: 10px 0 20px 0;
}
.direction-col {
flex-direction: column;
}
.buttons {
margin: 20px 0;
align-items: center;
}
button {
margin-right: 5px;
margin-left: 5px;
width: 250px;
}
// Google Identity and Google+ Sign in buttons
// https://developers.google.com/+/branding-guidelines
.google-button {
height: 40px;
width: 250px;
border-width: 0;
background: white;
color: #737373;
border-radius: 5px;
white-space: nowrap;
box-shadow: 1px 1px 0px 1px rgba(0, 0, 0, 0.05);
transition-property: background-color, box-shadow;
transition-duration: 150ms;
transition-timing-function: ease-in-out;
padding: 0;
&:focus,
&:hover {
box-shadow: 1px 4px 5px 1px rgba(0, 0, 0, 0.1);
}
&:active {
background-color: #e5e5e5;
box-shadow: none;
transition-duration: 10ms;
}
}
.google-button__icon {
vertical-align: top;
margin: 8px 0 8px 8px;
width: 18px;
height: 20px;
box-sizing: border-box;
float: left;
svg {
vertical-align: top;
}
}
.google-button__icon--plus {
width: 27px;
}
.google-button__text {
display: inline-block;
vertical-align: middle;
padding: 0 24px;
font-size: 14px;
font-weight: bold;
font-family: 'Roboto', arial, sans-serif;
}
.msg {
padding: 10px 10px 20px;
color: #666;
font-size: 14px;
text-align: justify;
}
.msg--error {
color: red;
}
.msg--success {
color: green;
}
.login-note-text {
padding: 10px 10px 20px;
color: #666;
font-size: 20px;
text-align: center;
}
.forget-password-container {
padding-left: 15px;
margin-top: -5px;
}
.help-text {
font-size: 14px;
padding-bottom: 5px;
}