refactored to prepare for adding logout functionality

pull/9/head
Chris Veilleux 2018-10-28 00:38:13 -05:00
parent c037b77387
commit fedb8e7c6a
24 changed files with 292 additions and 256 deletions

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from "./login/login.component";
// import { PageNotFoundComponent } from "./page-not-found/page-not-found.component";
const routes: Routes = [
{ path: 'login', component: LoginComponent },
// { path: '', redirectTo: '/login', pathMatch: 'full' },
// { path: '**', component: PageNotFoundComponent }
];
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {
}

View File

@ -8,24 +8,5 @@ This condition is temporary it should be removed when the social login logic
is refactored and moved into Selene.
-->
<div *ngIf="!socialLoginDataFound">
<div class="split top"></div>
<div class="split bottom"></div>
<div fxLayout="column" fxLayoutAlign="center center">
<div align="center">
<img src="../../assets/mycroft-ai-no-logo.svg"/>
</div>
<div class="login-options">
<login-authenticate></login-authenticate>
<!--<mat-tab-group>-->
<!--<mat-tab label="LOG IN">-->
<!--<login-authenticate></login-authenticate>-->
<!--</mat-tab>-->
<!--<mat-tab label="SIGN UP">-->
<!--<login-auth-social></login-auth-social>-->
<!--<div class="mat-subheading-2">OR</div>-->
<!--<login-auth-antisocial></login-auth-antisocial>-->
<!--</mat-tab>-->
<!--</mat-tab-group>-->
</div>
</div>
<router-outlet></router-outlet>
</div>

View File

@ -1,27 +0,0 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to frontend!');
}));
});

View File

@ -16,7 +16,7 @@ export class AppComponent implements OnInit {
ngOnInit () {
let uriParams = decodeURIComponent(window.location.search);
if (uriParams) {
if (!window.location.pathname && uriParams) {
this.socialLoginDataFound = true;
window.opener.postMessage(uriParams, window.location.origin);
window.close();

View File

@ -4,15 +4,17 @@ import { FlexLayoutModule } from "@angular/flex-layout";
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AuthModule } from "./auth/auth.module";
import { AppRoutingModule } from "./app-routing.module";
import { LoginModule } from "./login/login.module";
@NgModule({
declarations: [ AppComponent ],
imports: [
BrowserModule,
AuthModule,
LoginModule,
BrowserAnimationsModule,
FlexLayoutModule
FlexLayoutModule,
AppRoutingModule
],
providers: [ ],
bootstrap: [ AppComponent ]

View File

@ -1,75 +0,0 @@
@import '../../stylesheets/global';
button {
@include login-button;
}
.social {
padding: 20px;
button {
margin-bottom: 15px;
}
fa-icon {
margin-right: 15px;
font-size: 28px;
}
.facebook-button {
background-color: #3b5998;
padding-left: 5px;
}
.github-button {
background-color: #333333;
margin-right: 12px;
padding-left: 5px;
}
.google-button {
background-color: #4285F4;
padding-left: 1px;
img {
margin-right: 10px;
width: 14%;
}
}
}
button {
@include login-button;
}
form {
background-color: $mycroft-white;
border-radius: 10px;
padding: 20px;
fa-icon {
color: $mycroft-dark-grey;
margin-right: 15px;
}
mat-checkbox {
color: $mycroft-dark-grey;
}
.forgot-password {
margin-left: 30px;
}
button {
background-color: $mycroft-primary;
margin-top: 30px;
text-align: center;
}
button:hover {
background-color: $mycroft-tertiary-green;
color: $mycroft-secondary;
}
}
.mat-body-2 {
color: $mycroft-tertiary-red;
padding: 15px;
}
.mat-subheading-2 {
color: $mycroft-dark-grey;
margin-bottom: -15px;
margin-top: -15px;
text-align: center;
}

View File

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

View File

@ -1,55 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { faFacebook, faGithub } from "@fortawesome/free-brands-svg-icons";
import { faLock, faUser } from "@fortawesome/free-solid-svg-icons";
import { AuthResponse, AuthService } from "./auth.service";
@Component({
selector: 'login-authenticate',
templateUrl: './auth.component.html',
styleUrls: ['./auth.component.scss']
})
export class AuthComponent implements OnInit {
public facebookIcon = faFacebook;
public githubIcon = faGithub;
public authFailed: boolean;
public password: string;
public passwordIcon = faLock;
public username: string;
public usernameIcon = faUser;
constructor(private authService: AuthService) { }
ngOnInit() { }
authenticateFacebook(): void {
this.authService.authenticateWithFacebook()
}
authenticateGithub(): void {
this.authService.authenticateWithGithub();
}
authenticateGoogle(): void {
this.authService.authenticateWithGoogle();
}
authorizeUser(): void {
this.authService.authorizeAntisocial(this.username, this.password).subscribe(
(response) => {this.onAuthSuccess(response)},
(response) => {this.onAuthFailure(response)}
);
}
onAuthSuccess(authResponse: AuthResponse) {
this.authFailed = false;
this.authService.generateTokenCookies(authResponse);
window.history.back();
}
onAuthFailure(authorizeUserResponse) {
if (authorizeUserResponse.status === 401) {
this.authFailed = true;
}
}
}

View File

@ -1,13 +0,0 @@
import { AuthModule } from './auth.module';
describe('AuthModule', () => {
let authenticateModule: AuthModule;
beforeEach(() => {
authenticateModule = new AuthModule();
});
it('should create an instance', () => {
expect(authenticateModule).toBeTruthy();
});
});

View File

@ -1,15 +0,0 @@
import { TestBed, inject } from '@angular/core/testing';
import { AuthService } from './auth.service';
describe('AuthenticateService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [AuthService]
});
});
it('should be created', inject([AuthService], (service: AuthService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,7 @@
<div class="split top"></div>
<div class="split bottom"></div>
<div fxLayout="column" fxLayoutAlign="center center">
<div align="center">
<img src="../../assets/mycroft-ai-no-logo.svg"/>
</div>
</div>

View File

@ -0,0 +1,30 @@
@import "../../stylesheets/global";
/* Split the screen in half */
.split {
height: 50%;
left: 0;
overflow-x: hidden;
padding-top: 20px;
position: fixed;
width: 100%;
z-index: -1;
}
/* Top Half */
.top {
top: 0;
background-color: $mycroft-primary;
}
/* Bottom Half */
.bottom {
bottom: 0;
background-color: #e5e5e5;
}
img {
margin-bottom: 50px;
margin-top: 50px;
width: 600px;
}

View File

@ -0,0 +1,14 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'login-background',
templateUrl: './background.component.html',
styleUrls: ['./background.component.scss']
})
export class BackgroundComponent implements OnInit {
constructor() { }
ngOnInit() { }
}

View File

@ -1,18 +1,3 @@
<div class="social">
<button mat-button class="google-button" (click)="authenticateGoogle()">
<img src="../../../assets/google-logo.svg">
Log in with Google
</button>
<button mat-button class="facebook-button" (click)="authenticateFacebook()">
<fa-icon [icon]="facebookIcon"></fa-icon>
Continue with Facebook
</button>
<button mat-button class="github-button" (click)="authenticateGithub()">
<fa-icon [icon]="githubIcon"></fa-icon>
Log in with GitHub
</button>
</div>
<div class="mat-subheading-2">OR</div>
<form
fxLayout="column"
#loginForm="ngForm"

View File

@ -0,0 +1,36 @@
@import '../../../stylesheets/global';
button {
@include login-button;
}
form {
background-color: $mycroft-white;
border-radius: 10px;
padding: 20px;
fa-icon {
color: $mycroft-dark-grey;
margin-right: 15px;
}
mat-checkbox {
color: $mycroft-dark-grey;
}
.forgot-password {
margin-left: 30px;
}
button {
background-color: $mycroft-primary;
margin-top: 30px;
text-align: center;
}
button:hover {
background-color: $mycroft-tertiary-green;
color: $mycroft-secondary;
}
}
.mat-body-2 {
color: $mycroft-tertiary-red;
padding: 15px;
}

View File

@ -0,0 +1,45 @@
import { Component, OnInit } from '@angular/core';
import { faLock, faUser } from "@fortawesome/free-solid-svg-icons";
import { AuthResponse, LoginService } from "../login.service";
@Component({
selector: 'login-antisocial',
templateUrl: './antisocial.component.html',
styleUrls: ['./antisocial.component.scss']
})
export class AntisocialComponent implements OnInit {
public authFailed: boolean;
public password: string;
public passwordIcon = faLock;
private redirectUri: string;
public username: string;
public usernameIcon = faUser;
constructor(private authService: LoginService) { }
ngOnInit() {
this.redirectUri = decodeURIComponent(window.location.search).slice(10);
}
authorizeUser(): void {
this.authService.authorizeAntisocial(this.username, this.password).subscribe(
(response) => {this.onAuthSuccess(response)},
(response) => {this.onAuthFailure(response)}
);
}
onAuthSuccess(authResponse: AuthResponse): void {
this.authFailed = false;
this.authService.generateTokenCookies(authResponse);
window.location.assign(this.redirectUri);
}
onAuthFailure(authorizeUserResponse): void {
if (authorizeUserResponse.status === 401) {
this.authFailed = true;
}
}
}

View File

@ -0,0 +1,8 @@
<login-background></login-background>
<div fxLayout="column" fxLayoutAlign="center center">
<div class="login-options">
<login-social></login-social>
<div class="mat-subheading-2">OR</div>
<login-antisocial></login-antisocial>
</div>
</div>

View File

@ -0,0 +1,15 @@
@import '../../stylesheets/global';
.login-options {
background-color: $mycroft-white;
border-radius: 10px;
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.12);
width: 320px;
}
.mat-subheading-2 {
color: $mycroft-dark-grey;
margin-bottom: -15px;
margin-top: -15px;
text-align: center;
}

View File

@ -0,0 +1,16 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'login-authenticate',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
private redirectUri: string;
constructor() { }
ngOnInit() {
this.redirectUri = decodeURIComponent(window.location.search).slice(10);
}
}

View File

@ -14,12 +14,21 @@ import {
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { AuthComponent } from './auth.component';
import { AuthService } from "./auth.service";
import { AntisocialComponent } from './antisocial/antisocial.component';
import { LoginComponent } from './login.component';
import { LoginService } from "./login.service";
import { BackgroundComponent } from '../background/background.component';
import { SocialComponent } from './social/social.component';
@NgModule({
declarations: [ AuthComponent ],
exports: [ AuthComponent ],
declarations: [
AntisocialComponent,
LoginComponent,
BackgroundComponent,
SocialComponent
],
entryComponents: [ LoginComponent ],
exports: [ LoginComponent ],
imports: [
CommonModule,
FlexLayoutModule,
@ -33,6 +42,6 @@ import { AuthService } from "./auth.service";
MatInputModule,
MatSnackBarModule
],
providers: [ AuthService ]
providers: [ LoginService ]
})
export class AuthModule { }
export class LoginModule { }

View File

@ -20,7 +20,7 @@ export interface SocialLoginData {
}
@Injectable()
export class AuthService {
export class LoginService {
private antisocialAuthUrl = '/api/antisocial';
private facebookAuthUrl = '/api/social/facebook';
private githubAuthUrl = '/api/social/github';

View File

@ -0,0 +1,14 @@
<div class="social" fxLayout="column" fxLayoutAlign="center center">
<button mat-button class="google-button" (click)="authenticateGoogle()">
<img src="../../../assets/google-logo.svg">
Log in with Google
</button>
<button mat-button class="facebook-button" (click)="authenticateFacebook()">
<fa-icon [icon]="facebookIcon"></fa-icon>
Continue with Facebook
</button>
<button mat-button class="github-button" (click)="authenticateGithub()">
<fa-icon [icon]="githubIcon"></fa-icon>
Log in with GitHub
</button>
</div>

View File

@ -0,0 +1,33 @@
@import '../../../stylesheets/global';
button {
@include login-button;
}
.social {
padding: 20px;
button {
margin-bottom: 15px;
}
fa-icon {
margin-right: 15px;
font-size: 28px;
}
.facebook-button {
background-color: #3b5998;
padding-left: 5px;
}
.github-button {
background-color: #333333;
padding-left: 5px;
}
.google-button {
background-color: #4285F4;
padding-left: 1px;
img {
margin-right: 10px;
width: 14%;
}
}
}

View File

@ -0,0 +1,33 @@
import { Component, OnInit } from '@angular/core';
import { faFacebook, faGithub } from "@fortawesome/free-brands-svg-icons";
import { LoginService } from "../login.service";
@Component({
selector: 'login-social',
templateUrl: './social.component.html',
styleUrls: ['./social.component.scss']
})
export class SocialComponent implements OnInit {
public facebookIcon = faFacebook;
public githubIcon = faGithub;
constructor(private authService: LoginService) { }
ngOnInit() {
}
authenticateFacebook(): void {
this.authService.authenticateWithFacebook()
}
authenticateGithub(): void {
this.authService.authenticateWithGithub();
}
authenticateGoogle(): void {
this.authService.authenticateWithGoogle();
}
}