From 02b396f1887a4da64ccd139530fd9f44a8b55ce2 Mon Sep 17 00:00:00 2001 From: Evan Langlais Date: Tue, 9 Apr 2019 11:13:12 -0400 Subject: [PATCH 1/2] Cleaning code Implementing new material card layout with status of generators Implemented better token management with server validation Created actual generator interfaces to ensure types and such Added bunch of material modules for use in dashboard --- angular.json | 2 +- src/app/app.module.ts | 18 +++---- .../authentication.component.ts | 2 +- src/app/generator-object.ts | 17 +++++++ .../generator-search.component.css | 7 ++- .../generator-search.component.html | 47 +++++++++++-------- .../generator-search.component.ts | 28 ++++++----- src/app/header/header.component.ts | 26 +++++----- src/app/material.module.ts | 21 +++++++-- src/app/services/generator.service.ts | 46 +++++++++++++++--- src/app/services/login.service.ts | 20 +++++++- src/app/statistics/statistics.component.ts | 7 +-- .../visualize-all.component.html | 2 +- .../visualize-all/visualize-all.component.ts | 21 +++++---- .../visualize-one/visualize-one.component.ts | 23 ++++----- src/styles.css | 2 +- 16 files changed, 192 insertions(+), 97 deletions(-) create mode 100644 src/app/generator-object.ts diff --git a/angular.json b/angular.json index 277517d..fda1246 100644 --- a/angular.json +++ b/angular.json @@ -130,4 +130,4 @@ } }, "defaultProject": "frontend" -} +} \ No newline at end of file diff --git a/src/app/app.module.ts b/src/app/app.module.ts index fc57795..081e939 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -41,15 +41,15 @@ import { VisualizeOneComponent } from './visualize-one/visualize-one.component'; GaugesModule, RouterModule.forRoot([ - {path: 'dashboard', component: FrontpageComponent}, - {path: '', component: AuthenticationComponent}, - {path: 'generator-search', component: GeneratorSearchComponent}, - {path: 'statistics', component: StatisticsComponent}, - {path: 'warnings', component: WarningsComponent}, - {path: 'history', component: HistoryComponent}, - {path: 'sign_up', component: SignUpComponent}, - {path: 'visualize-all', component: VisualizeAllComponent}, - {path: 'visualize-one', component: VisualizeOneComponent}, + {path: 'dashboard', component: FrontpageComponent}, + {path: '', component: AuthenticationComponent}, + {path: 'generator-search', component: GeneratorSearchComponent}, + {path: 'statistics', component: StatisticsComponent}, + {path: 'warnings', component: WarningsComponent}, + {path: 'history', component: HistoryComponent}, + {path: 'sign_up', component: SignUpComponent}, + {path: 'visualize-all', component: VisualizeAllComponent}, + {path: 'visualize-one', component: VisualizeOneComponent}, ]), diff --git a/src/app/authentication/authentication.component.ts b/src/app/authentication/authentication.component.ts index ca2e123..d7072d7 100644 --- a/src/app/authentication/authentication.component.ts +++ b/src/app/authentication/authentication.component.ts @@ -48,7 +48,7 @@ export class AuthenticationComponent implements OnInit { } - ngOnInit() { + ngOnInit() { localStorage.removeItem('gen_id'); localStorage.removeItem('org_id'); localStorage.removeItem('gen_name'); diff --git a/src/app/generator-object.ts b/src/app/generator-object.ts new file mode 100644 index 0000000..f2b5f0b --- /dev/null +++ b/src/app/generator-object.ts @@ -0,0 +1,17 @@ +export interface GeneratorObject { + gen_id: number; + gen_name: string; + org_id: number; + zip: number; + state: GeneratorState | null; +} + +export interface GeneratorState { + online: boolean; + status: string; + status_code: number; + fault_count: number | null; + fault_codes: Array | null; + ip: string; +} + diff --git a/src/app/generator-search/generator-search.component.css b/src/app/generator-search/generator-search.component.css index fb6e2aa..336075e 100644 --- a/src/app/generator-search/generator-search.component.css +++ b/src/app/generator-search/generator-search.component.css @@ -11,4 +11,9 @@ a#genLink { margin: 10px; display: inline-block; text-decoration: none; -} */ \ No newline at end of file +} */ + +mat-card.generator-card { + width: calc(100% - 70px); + height: calc(100% - 70px); +} diff --git a/src/app/generator-search/generator-search.component.html b/src/app/generator-search/generator-search.component.html index 952db49..42085a7 100644 --- a/src/app/generator-search/generator-search.component.html +++ b/src/app/generator-search/generator-search.component.html @@ -1,23 +1,32 @@ -
+
-

Your Generators

- -
-
-
- - - {{ generator.gen_name }} -

- zipcode: {{ generator.zip }}
- (insert statistics preview here) -

-
- - -
-
+

Your Generators

+ + + + + + {{ generator.gen_name }} + {{ generator.state.status }} + + + + error +

+ Active Faults: {{ generator.state.fault_count }} +

+
+ + settings_ethernet +

+ IP Address: {{ generator.state.ip }} +

+
+
+
+
+
-
\ No newline at end of file +
diff --git a/src/app/generator-search/generator-search.component.ts b/src/app/generator-search/generator-search.component.ts index c45e194..2b1266f 100644 --- a/src/app/generator-search/generator-search.component.ts +++ b/src/app/generator-search/generator-search.component.ts @@ -1,6 +1,8 @@ import { Component, OnInit } from '@angular/core'; import { GeneratorService } from '../services/generator.service'; import { Router } from '@angular/router'; +import { GeneratorObject } from '../generator-object'; +import {LoginService} from '../services/login.service'; @Component({ selector: 'app-generator-search', @@ -10,35 +12,39 @@ import { Router } from '@angular/router'; export class GeneratorSearchComponent implements OnInit { - constructor(public data: GeneratorService, private router: Router) { } + constructor(public data: GeneratorService, private router: Router, private login: LoginService) { } - public generators$: Object; + public generators$: Array; + private loading$: boolean; - goToGenerator(gen_id, org_id, gen_name) { + goToGenerator(gen: GeneratorObject) { this.router.navigateByUrl('/statistics'); // console.log(gen_id); // console.log(org_id); - localStorage.setItem('gen_id', gen_id); - localStorage.setItem('org_id', org_id); - localStorage.setItem('gen_name', gen_name); + localStorage.setItem('gen_id', gen.gen_id.toString()); + localStorage.setItem('org_id', gen.org_id.toString()); + localStorage.setItem('gen_name', gen.gen_name); } - ngOnInit() { + async ngOnInit() { + this.loading$ = true; localStorage.removeItem('gen_id'); localStorage.removeItem('org_id'); localStorage.removeItem('gen_name'); localStorage.removeItem('data_type'); localStorage.removeItem('fault_type'); - const jsonToken = localStorage.getItem('auth_token'); - try { - this.data.getGenerators(jsonToken).subscribe((data) => { + const auth_token: string = await this.login.getToken(); + this.generators$ = await this.data.getGenerators(auth_token); + this.loading$ = false; + /*try { + this.data.getGenerators(jsonToken).subscribe((data: Array) => { // console.log(data); this.generators$ = data; return this.generators$; }); } catch (err) { return err; - } + }*/ // this.generators$ = this.getGeneratorName(); } diff --git a/src/app/header/header.component.ts b/src/app/header/header.component.ts index 6f1e0a3..5938bb4 100644 --- a/src/app/header/header.component.ts +++ b/src/app/header/header.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; +import {LoginService} from '../services/login.service'; @Component({ selector: 'app-header', @@ -8,7 +9,7 @@ import { Router } from '@angular/router'; }) export class HeaderComponent implements OnInit { - constructor(private router: Router) { } + constructor(private router: Router, private login: LoginService) { } resetAndClear() { this.router.navigateByUrl('#'); @@ -16,29 +17,24 @@ export class HeaderComponent implements OnInit { } resetGenerator() { - if (localStorage.getItem('auth_token') != null) { - this.router.navigateByUrl('/generator-search'); - localStorage.removeItem('gen_id'); - localStorage.removeItem('org_id'); - localStorage.removeItem('gen_name'); - localStorage.removeItem('data_type'); - } else { - console.log('You need to log in'); - this.router.navigateByUrl('#'); - } + this.resetAndRedirect('/generator-search'); } resetGenAndVisualize() { - if (localStorage.getItem('auth_token') != null) { - this.router.navigateByUrl('/visualize-all'); + this.resetAndRedirect('/visualize-all'); + } + + resetAndRedirect(url: string) { + this.login.getToken().then(() => { + this.router.navigateByUrl(url); localStorage.removeItem('gen_id'); localStorage.removeItem('org_id'); localStorage.removeItem('gen_name'); localStorage.removeItem('data_type'); - } else { + }, () => { console.log('You need to log in'); this.router.navigateByUrl('#'); - } + }); } ngOnInit() { diff --git a/src/app/material.module.ts b/src/app/material.module.ts index 4c3728f..7a23211 100644 --- a/src/app/material.module.ts +++ b/src/app/material.module.ts @@ -4,7 +4,15 @@ import { NgModule } from '@angular/core'; import { MatDatepickerModule, MatNativeDateModule, MatFormFieldModule, - MatInputModule } from '@angular/material'; + MatInputModule, + MatCardModule, + MatButtonModule, + MatGridListModule, + MatRippleModule, + MatProgressSpinnerModule, + MatIconModule, + MatListModule, +} from '@angular/material'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ @@ -20,9 +28,16 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; MatFormFieldModule, MatNativeDateModule, MatInputModule, - BrowserAnimationsModule + BrowserAnimationsModule, + MatCardModule, + MatButtonModule, + MatGridListModule, + MatRippleModule, + MatProgressSpinnerModule, + MatIconModule, + MatListModule, ], providers: [ MatDatepickerModule ], }) -export class MaterialModule {} \ No newline at end of file +export class MaterialModule {} diff --git a/src/app/services/generator.service.ts b/src/app/services/generator.service.ts index 56a7358..f4fc231 100644 --- a/src/app/services/generator.service.ts +++ b/src/app/services/generator.service.ts @@ -1,18 +1,50 @@ import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; +import {HttpClient, HttpResponse} from '@angular/common/http'; +import {GeneratorObject, GeneratorState} from '../generator-object'; +import {LoginService} from './login.service'; @Injectable({ providedIn: 'root' }) export class GeneratorService { - constructor(private http: HttpClient) { } + constructor(private http: HttpClient, private login: LoginService) { } - getGenerators(token) { - return this.http.get('http://sd5-backend.engr.uconn.edu/user/generators', { - headers: { - Authorization: 'Bearer ' + token - } + getGenerators(token: string): Promise> { + return new Promise>((resolve, reject) => { + this.http.get('http://sd5-backend.engr.uconn.edu/user/generators', { + headers: { + Authorization: 'Bearer ' + token + } + }).subscribe(async (raw_generators: Array) => { + const generators: Array = []; + for (const generator of raw_generators) { + await this.getGeneratorStatus(generator.gen_id, token).then((state: GeneratorState) => { + generator.state = state; + generators.push(generator); + }, (error) => { + reject(error); + }); + } + resolve(generators); + }, (error) => { + reject(error); + }); }); } + + getGeneratorStatus(gen_id: number, token: string): Promise { + return new Promise((resolve, reject) => { + this.http.get('http://sd5-backend.engr.uconn.edu/generator/' + gen_id + '/status', { + headers: { + Authorization: 'Bearer ' + token + } + }).subscribe((state: GeneratorState) => { + resolve(state); + }, (error) => { + reject(error); + }); + }); + } + } diff --git a/src/app/services/login.service.ts b/src/app/services/login.service.ts index 4b780dd..6448efd 100644 --- a/src/app/services/login.service.ts +++ b/src/app/services/login.service.ts @@ -3,7 +3,6 @@ import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/observable/throw'; import 'rxjs/add/operator/catch'; -import { ReplaySubject } from 'rxjs'; @Injectable({ providedIn: 'root' @@ -30,4 +29,23 @@ export class LoginService { } }); } + + getToken(): Promise { + return new Promise((resolve, reject) => { + const token = localStorage.getItem('auth_token'); + if (!token) { reject('No Token'); } + this.http.get('http://sd5-backend.engr.uconn.edu/auth/verify', { + headers: { + Authorization: 'Bearer ' + token + }, + observe: 'response' + }).subscribe((response) => { + if (response.status === 200) { + resolve(token); + } else { + reject('Invalid Token'); + } + }); + }); + } } diff --git a/src/app/statistics/statistics.component.ts b/src/app/statistics/statistics.component.ts index a2cec69..6ea5ee5 100644 --- a/src/app/statistics/statistics.component.ts +++ b/src/app/statistics/statistics.component.ts @@ -2,6 +2,7 @@ import {Component, OnInit} from '@angular/core'; import {MetricsService} from '../services/metrics.service'; import {HttpClient, HttpHeaders} from '@angular/common/http'; import { Router } from '@angular/router'; +import {LoginService} from '../services/login.service'; @Component({ selector: 'app-statistics', @@ -11,7 +12,7 @@ import { Router } from '@angular/router'; export class StatisticsComponent implements OnInit { - constructor(public data: MetricsService, private http: HttpClient, private router: Router) { + constructor(public data: MetricsService, private http: HttpClient, private router: Router, private login: LoginService) { @@ -98,11 +99,11 @@ export class StatisticsComponent implements OnInit { } - ngOnInit() { + async ngOnInit() { localStorage.removeItem('data_type'); localStorage.removeItem('fault_type'); - const jsonToken = localStorage.getItem('auth_token'); + const jsonToken = await this.login.getToken(); diff --git a/src/app/visualize-all/visualize-all.component.html b/src/app/visualize-all/visualize-all.component.html index 914154f..0e337d4 100644 --- a/src/app/visualize-all/visualize-all.component.html +++ b/src/app/visualize-all/visualize-all.component.html @@ -53,4 +53,4 @@ - \ No newline at end of file + diff --git a/src/app/visualize-all/visualize-all.component.ts b/src/app/visualize-all/visualize-all.component.ts index 30c4722..30f01fa 100644 --- a/src/app/visualize-all/visualize-all.component.ts +++ b/src/app/visualize-all/visualize-all.component.ts @@ -10,6 +10,8 @@ import 'rxjs/add/operator/map'; import { $ } from 'protractor'; import * as moment from 'moment'; import { MatDatepickerModule, MatDatepicker } from '@angular/material/datepicker'; +import {GeneratorObject} from '../generator-object'; +import {LoginService} from '../services/login.service'; @Component({ selector: 'app-visualize-all', @@ -17,7 +19,7 @@ import { MatDatepickerModule, MatDatepicker } from '@angular/material/datepicker styleUrls: ['./visualize-all.component.css'] }) export class VisualizeAllComponent implements OnInit { - public generators$: Object; + public generators$: Array; public chart$: Object; public unit$: any = null; public function$: any = null; @@ -27,12 +29,13 @@ export class VisualizeAllComponent implements OnInit { public laymanDataVal$: any = null; public chart: any = null; public signal = false; + private jsonToken$: string; events: string[] = []; @ViewChild('time_span') timeSpan: ElementRef; @ViewChild('start_time') startTime: ElementRef; @ViewChild('end_time') endTime: ElementRef; - constructor(public data: DataService, public graphData: VisualizeService, public genData: GeneratorService, + constructor(public data: DataService, public graphData: VisualizeService, public genData: GeneratorService, private login: LoginService, private router: Router, private http: HttpClient) { } // create real chart based off of user data @@ -137,12 +140,11 @@ export class VisualizeAllComponent implements OnInit { } if (this.signal === false) { - const jsonToken = localStorage.getItem('auth_token'); const labels = []; const data = []; try { // create chart based on user input - this.graphData.getDataForVis(jsonToken, timeStart, timeEnd, funcVal, genVal, dataVal) + this.graphData.getDataForVis(this.jsonToken$, timeStart, timeEnd, funcVal, genVal, dataVal) .subscribe((graphData) => { this.chart$ = graphData; let sig; @@ -182,7 +184,7 @@ export class VisualizeAllComponent implements OnInit { } - ngOnInit() { + async ngOnInit() { localStorage.removeItem('gen_id'); localStorage.removeItem('org_id'); localStorage.removeItem('gen_name'); @@ -190,15 +192,16 @@ export class VisualizeAllComponent implements OnInit { localStorage.removeItem('fault_type'); this.dataNames$ = this.data.getAllNames('layman'); - const jsonToken = localStorage.getItem('auth_token'); - try { + this.jsonToken$ = await this.login.getToken(); + this.generators$ = await this.genData.getGenerators(this.jsonToken$); + /*try { this.genData.getGenerators(jsonToken).subscribe((genData) => { this.generators$ = genData; return this.generators$; }); } catch (err) { return err; - } + }*/ const labels = []; const data = []; @@ -206,7 +209,7 @@ export class VisualizeAllComponent implements OnInit { try { // create example chart - this.graphData.getDataForVis(jsonToken, '2019/03/13', '2019/03/14', 'sum', '1', 'oil.temp').subscribe((graphData) => { + this.graphData.getDataForVis(this.jsonToken$, '2019/03/13', '2019/03/14', 'sum', '1', 'oil.temp').subscribe((graphData) => { this.chart$ = graphData; let count; for (let n = 0; n < (Object.keys(this.chart$['outputs'][0]['dps']).length); n++) { diff --git a/src/app/visualize-one/visualize-one.component.ts b/src/app/visualize-one/visualize-one.component.ts index 621cc5a..179eb31 100644 --- a/src/app/visualize-one/visualize-one.component.ts +++ b/src/app/visualize-one/visualize-one.component.ts @@ -10,6 +10,7 @@ import 'rxjs/add/operator/map'; import { $ } from 'protractor'; import * as moment from 'moment'; import { MatDatepickerModule, MatDatepicker } from '@angular/material/datepicker'; +import {LoginService} from '../services/login.service'; @Component({ selector: 'app-visualize-one', @@ -30,13 +31,14 @@ export class VisualizeOneComponent implements OnInit { public laymanDataVal$: any = null; public chart: any = null; public signal$ = false; + private jsonToken$: string; events: string[] = []; @ViewChild('time_span') timeSpan: ElementRef; @ViewChild('start_time') startTime: ElementRef; @ViewChild('end_time') endTime: ElementRef; constructor(public data: DataService, public graphData: VisualizeService, public genData: GeneratorService, - private router: Router, private http: HttpClient) { } + private router: Router, private http: HttpClient, private login: LoginService) { } returnToStatistics() { this.router.navigateByUrl('/statistics'); @@ -123,12 +125,11 @@ export class VisualizeOneComponent implements OnInit { } if (this.signal$ === false) { - const jsonToken = localStorage.getItem('auth_token'); const labels = []; const data = []; try { // create chart based on user input - this.graphData.getDataForVis(jsonToken, timeStart, timeEnd, funcVal, localStorage.getItem('gen_id'), dataVal) + this.graphData.getDataForVis(this.jsonToken$, timeStart, timeEnd, funcVal, localStorage.getItem('gen_id'), dataVal) .subscribe((graphData) => { this.chart$ = graphData; let sig; @@ -166,18 +167,10 @@ export class VisualizeOneComponent implements OnInit { console.log('invalid entry'); } } - ngOnInit() { + async ngOnInit() { this.dataNames$ = this.data.getAllNames('layman'); - const jsonToken = localStorage.getItem('auth_token'); - try { - this.genData.getGenerators(jsonToken).subscribe((genData) => { - this.generators$ = genData; - return this.generators$; - }); - } catch (err) { - return err; - } + this.jsonToken$ = await this.login.getToken(); const labels = []; const data = []; @@ -193,7 +186,7 @@ export class VisualizeOneComponent implements OnInit { this.dataSig$ = false; this.dataType$ = this.data.convertNames(dataType, 'layman'); } - this.graphData.getDataForVis(jsonToken, '2019/03/13', '2019/03/14', 'sum', localStorage.getItem('gen_id'), dataType) + this.graphData.getDataForVis(this.jsonToken$, '2019/03/13', '2019/03/14', 'sum', localStorage.getItem('gen_id'), dataType) .subscribe((graphData) => { this.chart$ = graphData; let count; @@ -222,4 +215,4 @@ export class VisualizeOneComponent implements OnInit { } } -} \ No newline at end of file +} diff --git a/src/styles.css b/src/styles.css index 0f2b66f..d0fb837 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,4 +1,4 @@ /* You can add global styles to this file, and also import other style files */ html, body { height: 100%; } -body { margin: 0; font-family: 'Roboto', sans-serif; } \ No newline at end of file +body { margin: 0; font-family: 'Roboto', sans-serif; } From c2f31dc5ca53ab4eb6a46e43d4a15525bb0b03c3 Mon Sep 17 00:00:00 2001 From: Evan Langlais Date: Tue, 9 Apr 2019 11:31:31 -0400 Subject: [PATCH 2/2] Modifying loading variable permission --- src/app/generator-search/generator-search.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/generator-search/generator-search.component.ts b/src/app/generator-search/generator-search.component.ts index 2b1266f..dab738a 100644 --- a/src/app/generator-search/generator-search.component.ts +++ b/src/app/generator-search/generator-search.component.ts @@ -15,7 +15,7 @@ export class GeneratorSearchComponent implements OnInit { constructor(public data: GeneratorService, private router: Router, private login: LoginService) { } public generators$: Array; - private loading$: boolean; + public loading$: boolean; goToGenerator(gen: GeneratorObject) { this.router.navigateByUrl('/statistics');