started clean up of code.

This commit is contained in:
2018-09-10 22:25:08 -04:00
parent 4bcc4aceaa
commit 5262b6e2b4
11 changed files with 93 additions and 236 deletions

View File

@@ -1,13 +0,0 @@
<div *ngFor="let alert of alerts" class="{{ cssClass(alert) }} alert-dismissable" >
<mat-card class="lrCard">
<div>
<p class="alignleft"><b>{{alert.message}}</b></p>
<p class="alignright">
<a class="close" (click)="removeAlert(alert)">
<mat-icon class="alert-icon" fontSet="fa" fontIcon="fa-times" ></mat-icon>
</a>
</p>
<div style="clear: both;"></div>
</div>
</mat-card>
</div>

View File

@@ -1,51 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { Alert } from '../_classes/alert';
import { AlertType } from '../_classes/alertType';
import { AlertService } from '../_services/alert.service';
@Component({
selector: 'alert',
templateUrl: 'alert.component.html'
})
export class AlertComponent {
alerts: Alert[] = [];
constructor(private alertService: AlertService) { }
ngOnInit() {
this.alertService.getAlert().subscribe((alert: Alert) => {
if (!alert) {
// clear alerts when an empty alert is received
this.alerts = [];
return;
}
// add alert to array
this.alerts.push(alert);
});
}
removeAlert(alert: Alert) {
this.alerts = this.alerts.filter(x => x !== alert);
}
cssClass(alert: Alert) {
if (!alert) {
return;
}
// return css class based on alert type
switch (alert.type) {
case AlertType.Success:
return 'alert alert-success';
case AlertType.Error:
return 'alert alert-danger';
case AlertType.Info:
return 'alert alert-info';
case AlertType.Warning:
return 'alert alert-warning';
}
}
}

View File

@@ -1,59 +0,0 @@
import { Injectable } from '@angular/core';
import { Router, NavigationStart } from '@angular/router';
import { Observable } from 'rxjs';
import { Subject } from 'rxjs/Subject';
import { Alert } from '../_classes/alert';
import { AlertType } from '../_classes/alertType';
@Injectable()
export class AlertService {
private subject = new Subject<Alert>();
private keepAfterRouteChange = false;
constructor(private router: Router) {
// clear alert messages on route change unless 'keepAfterRouteChange' flag is true
router.events.subscribe(event => {
if (event instanceof NavigationStart) {
if (this.keepAfterRouteChange) {
// only keep for a single route change
this.keepAfterRouteChange = false;
} else {
// clear alert messages
this.clear();
}
}
});
}
getAlert(): Observable<any> {
return this.subject.asObservable();
}
success(message: string, keepAfterRouteChange = false) {
this.alert(AlertType.Success, message, keepAfterRouteChange);
}
error(message: string, keepAfterRouteChange = false) {
this.alert(AlertType.Error, message, keepAfterRouteChange);
}
info(message: string, keepAfterRouteChange = false) {
this.alert(AlertType.Info, message, keepAfterRouteChange);
}
warn(message: string, keepAfterRouteChange = false) {
this.alert(AlertType.Warning, message, keepAfterRouteChange);
}
alert(type: AlertType, message: string, keepAfterRouteChange = false) {
this.clear();
this.keepAfterRouteChange = keepAfterRouteChange;
this.subject.next(<Alert>{ type: type, message: message });
}
clear() {
// clear alerts
this.subject.next();
}
}

View File

@@ -1,9 +1,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map' import 'rxjs/add/operator/map'
import { User } from '../_classes/user'; import { User } from '../_classes/user';
@Injectable({ @Injectable({
@@ -12,6 +9,7 @@ import { User } from '../_classes/user';
export class LoginService { export class LoginService {
/* URL to the mock DB to be intercepted by the web-api in memory data service */
private loginUrl = "api/users"; private loginUrl = "api/users";
constructor( constructor(
@@ -19,7 +17,9 @@ export class LoginService {
) { } ) { }
login(userData : any) { login(userData : any) {
/* Look at that god like RegEX... We got a ^ AND a ?. /s */
const url = this.loginUrl + '/?userName=^' + userData.userName + '$&password=^' + userData.password + '$' ; const url = this.loginUrl + '/?userName=^' + userData.userName + '$&password=^' + userData.password + '$' ;
/* Run the request expecting a user class back */
return this.http.get<User>(url) return this.http.get<User>(url)
.map(user => { .map(user => {
return user; return user;

View File

@@ -1,2 +1 @@
<alert></alert>
<router-outlet></router-outlet> <router-outlet></router-outlet>

View File

@@ -13,8 +13,7 @@ import { JsonpModule } from '@angular/http';
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api'; import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from './_mockdata/mock-data-nasdaq'; import { InMemoryDataService } from './_mockdata/mock-data-nasdaq';
import { AlertComponent } from './_helpers/alert.component';
import { AlertService } from './_services/alert.service';
import { EmitcomService } from './_services/emitcom.service'; import { EmitcomService } from './_services/emitcom.service';
import { AuthGuard } from './_guards/auth.guard'; import { AuthGuard } from './_guards/auth.guard';
@@ -30,7 +29,8 @@ import { MatIconRegistry } from "@angular/material";
import { MatDividerModule } from '@angular/material/divider'; import { MatDividerModule } from '@angular/material/divider';
import { MatListModule } from '@angular/material/list'; import { MatListModule } from '@angular/material/list';
import { WatcherViewComponent } from './watcher-view/watcher-view.component'; import { WatcherViewComponent } from './watcher-view/watcher-view.component';
import {MatMenuModule} from '@angular/material/menu'; import { MatMenuModule } from '@angular/material/menu';
import { MatSnackBarModule } from '@angular/material/snack-bar';
@NgModule({ @NgModule({
@@ -39,7 +39,6 @@ import {MatMenuModule} from '@angular/material/menu';
LoginComponent, LoginComponent,
HomeComponent, HomeComponent,
UserAdminComponent, UserAdminComponent,
AlertComponent,
SearchViewComponent, SearchViewComponent,
StockViewComponent, StockViewComponent,
WatcherViewComponent, WatcherViewComponent,
@@ -61,10 +60,11 @@ import {MatMenuModule} from '@angular/material/menu';
MatDividerModule, MatDividerModule,
MatListModule, MatListModule,
JsonpModule, JsonpModule,
MatMenuModule MatMenuModule,
MatSnackBarModule
], ],
providers: [ providers: [
AlertService,
EmitcomService, EmitcomService,
MatIconRegistry, MatIconRegistry,
AuthGuard AuthGuard

View File

@@ -11,6 +11,9 @@ export class HomeComponent implements OnInit {
constructor() { } constructor() { }
ngOnInit() { ngOnInit() {
/* So much more can be done here however I'm really just using the home component as a shell/container for the others to live within. */
} }
} }

View File

@@ -1,36 +1,41 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms'; import { FormGroup, FormControl, Validators } from '@angular/forms';
import { LoginService } from '../_services/login.service'; import { LoginService } from '../_services/login.service';
import { AlertService } from '../_services/alert.service'; import { MatSnackBar } from '@angular/material';
@Component({ @Component({
selector: 'app-login', selector: 'app-login',
templateUrl: './login.component.html', templateUrl: './login.component.html',
styleUrls: ['./login.component.css'] styleUrls: ['./login.component.css']
}) })
export class LoginComponent implements OnInit { export class LoginComponent implements OnInit {
public form: any; public form: any;
private snackBar: MatSnackBar;
constructor( constructor(
private loginService: LoginService, private loginService: LoginService,
private alertService: AlertService, private router: Router,
private router: Router private matSnackBar: MatSnackBar
) { } ) { }
ngOnInit() { ngOnInit() {
this.loginService.logout(); this.loginService.logout();
this.buildForm(); this.buildForm();
this.snackBar = this.matSnackBar;
} }
buildForm(){ buildForm(){
const formGroup = {}; const formGroup = {};
/* Create form controls with a method to map custom validation with Angular provided ones. */
formGroup["userName"] = new FormControl( "", this.mapValidators({ required: true }) ); formGroup["userName"] = new FormControl( "", this.mapValidators({ required: true }) );
formGroup["password"] = new FormControl( "", this.mapValidators({ required: true }) ); formGroup["password"] = new FormControl( "", this.mapValidators({ required: true }) );
/* Pass form entitie object to create a FormGroup to be used by the template */
this.form = new FormGroup(formGroup); this.form = new FormGroup(formGroup);
} }
@@ -49,24 +54,27 @@ export class LoginComponent implements OnInit {
login( form ) { login( form ) {
this.alertService.clear(); /* Reset for values */
this.form.controls.userName.setValue("", false); this.form.controls.userName.setValue("", false);
this.form.controls.password.setValue("", false); this.form.controls.password.setValue("", false);
/* Hit up the login service for verification of credentials */
this.loginService.login( form ) this.loginService.login( form )
.subscribe( .subscribe(
data => { data => {
/* Reason for checking keys is simple, i'm not great at writing regular expressions and thats what i'm using for the mock DB. */
if( Object.keys(data).length === 0 ){ if( Object.keys(data).length === 0 ){
this.alertService.error( "Bad username or password" ); /* Bad login, show message */
this.snackBar.open('Yeah No... Try again?');
}else{ }else{
//console.log(data[0].userName); /* Good login! set user object and redirect */
localStorage.setItem('currentUser', JSON.stringify(data[0])); localStorage.setItem('currentUser', JSON.stringify(data[0]));
this.router.navigate(["home"]); this.router.navigate(["home"]);
} }
}, },
error => { error => {
//console.log(error) /* Bad login, show message */
this.alertService.error( "Bad username or password" ); this.snackBar.open('Yeah No... Try again?');
}); });
} }

View File

@@ -1,23 +1,26 @@
<div class="cardContainer"> <div class="cardContainer">
<mat-card id="searchCard"> <mat-card id="searchCard">
<mat-card-header class="fullWidth"> <mat-card-header class="fullWidth">
<div class="ipoContainer"> <div class="ipoContainer">
<mat-card-title> <mat-card-title>
<h2>Search IPO's</h2> <h2>Search IPO's</h2>
</mat-card-title> </mat-card-title>
<div class="spacer"></div>
<button mat-icon-button [matMenuTriggerFor]="menu"> <div class="spacer"></div>
<mat-icon class="addWatchListIcon" fontSet="fa" fontIcon="fa-bars" ></mat-icon>
</button> <button mat-icon-button [matMenuTriggerFor]="menu">
<mat-icon class="addWatchListIcon" fontSet="fa" fontIcon="fa-bars" ></mat-icon>
</button>
<mat-menu #menu="matMenu"> <mat-menu #menu="matMenu">
<button mat-menu-item>Item 1</button> <button mat-menu-item [routerLink]="['/about']">About</button>
<button mat-menu-item>Item 2</button> <button mat-menu-item (click)="logout();" >Logout</button>
</mat-menu> </mat-menu>
</div> </div>
</mat-card-header> </mat-card-header>
<mat-form-field class="fullWidth"> <mat-form-field class="fullWidth">
<input matInput placeholder="Company" <input matInput placeholder="Company"
[id]="'company'" [id]="'company'"
@@ -28,7 +31,7 @@
<mat-divider></mat-divider> <mat-divider></mat-divider>
<div> <div class="listContainer" >
<mat-nav-list> <mat-nav-list>
<mat-list-item *ngFor="let company of searchResults"> <mat-list-item *ngFor="let company of searchResults">
<div class="ipoContainer"> <div class="ipoContainer">
@@ -40,5 +43,6 @@
</mat-list-item> </mat-list-item>
</mat-nav-list> </mat-nav-list>
</div> </div>
</mat-card> </mat-card>
</div> </div>

View File

@@ -1,10 +1,10 @@
import { Component, OnInit, HostListener } from '@angular/core'; import { Component, OnInit, HostListener } from '@angular/core';
import { Router } from '@angular/router';
import { EmitcomService } from '../_services/emitcom.service'; import { EmitcomService } from '../_services/emitcom.service';
import { NasdaqSearchService } from '../_services/nasdaq-search.service'; import { NasdaqSearchService } from '../_services/nasdaq-search.service';
import { StockService } from '../_services/stock.service'; import { StockService } from '../_services/stock.service';
import { WatcherService } from '../_services/watcher.service'; import { WatcherService } from '../_services/watcher.service';
import { AlertService } from '../_services/alert.service';
@Component({ @Component({
selector: 'app-search-view', selector: 'app-search-view',
@@ -20,8 +20,8 @@ export class SearchViewComponent implements OnInit {
private emitcomService: EmitcomService, private emitcomService: EmitcomService,
private nasdaqSearchService: NasdaqSearchService, private nasdaqSearchService: NasdaqSearchService,
private stockService: StockService, private stockService: StockService,
private alertService: AlertService, private watcherService: WatcherService,
private watcherService: WatcherService private router: Router
) { } ) { }
ngOnInit() { ngOnInit() {
@@ -31,7 +31,6 @@ export class SearchViewComponent implements OnInit {
searchCompany( searchData ){ searchCompany( searchData ){
/* clear out IPO list at each key press */ /* clear out IPO list at each key press */
this.clearIpoList(); this.clearIpoList();
this.alertService.clear();
if( searchData.length >= 3 ){ if( searchData.length >= 3 ){
this.nasdaqSearchService.query( searchData ) this.nasdaqSearchService.query( searchData )
@@ -39,7 +38,6 @@ export class SearchViewComponent implements OnInit {
data => { data => {
if( Object.keys(data).length === 0 ){ if( Object.keys(data).length === 0 ){
/* We only need this here becasue i'm not great at regular expressions */ /* We only need this here becasue i'm not great at regular expressions */
this.alertService.error( "No IPO's Found" );
}else{ }else{
if( data.length > 0 ){ if( data.length > 0 ){
/* Data found in mock DB slice out the first six results and call method for logos. */ /* Data found in mock DB slice out the first six results and call method for logos. */
@@ -48,10 +46,10 @@ export class SearchViewComponent implements OnInit {
} }
}, },
error => { error => {
/* 404 not found in mock DB send alert to user. */ /* 404 not found in mock DB. */
this.alertService.error( "No IPO's Found" );
}); });
}else if( searchData.length === 0 ){ }else if( searchData.length === 0 ){
/* Emit event to clear chart when search bar is empty*/
this.emitcomService.destroyChart(); this.emitcomService.destroyChart();
} }
} }
@@ -71,11 +69,12 @@ export class SearchViewComponent implements OnInit {
} }
}, },
error => { error => {
/* in this circumstance we don't care about error as the logo return is static from the service. We will find another way to validate images. */ /* in this circumstance we don't care about error as the logo return is static from the service. We have another way to validate images. */
}); });
} }
/* Move to helper class? */
imgError( event ){ imgError( event ){
event.target.src = "http://www.lazypug.net/img/pug.jpg"; event.target.src = "http://www.lazypug.net/img/pug.jpg";
} }
@@ -89,20 +88,11 @@ export class SearchViewComponent implements OnInit {
this.watcherService.addWatching( symbol ) this.watcherService.addWatching( symbol )
.subscribe( .subscribe(
data => { data => {
if( Object.keys(data).length === 0 ){ /* send update to Watching componet to refresh list */
/* We only have to check for the object key becasue i'm not great with regex... */ this.emitcomService.updateWatcher();
/* If nothing is found do nothing */
}else{
/* Now that we have the search results and company IPO logos to match we can set the data and let the template take over. */
//this.searchResults = companySearchResults;
//this.searchResultLogos = data;
console.log( data )
this.emitcomService.updateWatcher();
}
}, },
error => { error => {
console.log( error ); /* We could alert the user something went south but as this is a mock DB it won't fail :/ */
/* in this circumstance we don't care about error as the logo return is static from the service. We will find another way to validate images. */
}); });
} }
@@ -110,4 +100,8 @@ export class SearchViewComponent implements OnInit {
this.searchResults = null; this.searchResults = null;
} }
logout(){
this.router.navigate(["login"]);
}
} }

View File

@@ -10,66 +10,50 @@ import * as Chart from 'chart.js'
}) })
export class StockViewComponent implements OnInit { export class StockViewComponent implements OnInit {
/* Grab the eleiment for the chart */
@ViewChild('chartView') private chartRef; @ViewChild('chartView') private chartRef;
chart: any; chart: any;
constructor( constructor(
private emitcomService: EmitcomService, private emitcomService: EmitcomService,
private stockService: StockService private stockService: StockService
) { } ) { }
ngOnInit() { ngOnInit() {
this.emitcomService.change.subscribe(data => { this.emitcomService.change.subscribe(data => {
if( data.type == "action" && data.data == "destroyChart" ){ /* check com's sent by other components and apply actions as needed */
if( this.chart !== undefined ){ if (data.type == "action" && data.data == "destroyChart") {
this.chart.destroy(); if (this.chart !== undefined) {
} this.chart.destroy();
}else if( data.type == "ipo" ){ }
this.getStockByChart( data.data, "1m" ); } else if (data.type == "ipo") {
this.getStockByChart(data.data, "1m");
} }
}); });
} }
getStockByChart(symbol, timeFrame) {
this.stockService.getCharByTime(symbol, timeFrame)
getStockByChart( symbol, timeFrame ){
this.stockService.getCharByTime( symbol, timeFrame )
.subscribe( .subscribe(
data => { data => {
if( Object.keys(data).length === 0 ){ if (data.length > 0) {
//this.alertService.error( "Bad username or password" );
}else{
//console.log(data[0].userName);
//localStorage.setItem('currentUser', JSON.stringify(data[0]));
//this.router.navigate(["home"]);
//console.log( data );
//this.searchResults = data;
if( data.length > 0 ){
console.log( data );
//[n].close
//[n].date
let date = data.map(data => data.date); let date = data.map(data => data.date);
let close = data.map(data => data.close); let close = data.map(data => data.close);
// console.log(date); if (this.chart !== undefined) {
// console.log(close); this.chart.destroy();
if( this.chart !== undefined ){
this.chart.destroy();
} }
this.chart = new Chart(this.chartRef.nativeElement, { this.chart = new Chart(this.chartRef.nativeElement, {
type: 'line', type: 'line',
data:{ data: {
labels: date, labels: date,
datasets: [{ datasets: [{
data: close, data: close,
@@ -77,38 +61,26 @@ export class StockViewComponent implements OnInit {
fill: false fill: false
}] }]
}, },
options:{ options: {
legend:{ legend: {
display: false display: false
}, },
scales:{ scales: {
xAxes:[{ xAxes: [{
display: true display: true
}], }],
yAxes:[{ yAxes: [{
display: true display: true
}] }]
} }
} }
}); });
/*
let dates = [];
dates.forEach((res) =>{
let jsdate = new Date(res * 1000)
dates.push( jsdate.toLocalTimeString('en') )
})
*/
} }
}
}, },
error => { error => {
//console.log(error) /* Something went south send notification */
//this.alertService.error( "Bad username or password" );
}); });
} }