diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 54e91b4..264e9b3 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,6 +1,6 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; -import { HomeComponent } from './home/home.component'; +import { DashboardComponent } from './dashboard/dashboard.component'; import { AuthComponent } from './auth/auth.component'; import { SignInComponent } from './auth/sign-in/sign-in.component'; import { SignUpComponent } from './auth/sign-up/sign-up.component'; @@ -34,7 +34,7 @@ const routes: Routes = [ } ]}, { path: 'configs', component: ConfigsComponent, canActivate: [AuthGuard]}, - { path: '', component: HomeComponent, canActivate: [AuthGuard] }]; + { path: '', component: DashboardComponent, canActivate: [AuthGuard] }]; @NgModule({ imports: [RouterModule.forRoot(routes)], diff --git a/src/app/app.component.html b/src/app/app.component.html index 5c7c82b..5a40902 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -6,11 +6,14 @@ mode="over" class="sidenav">
- - - {{route.title}} - - + + + + {{location.location}} + +

{{keys.key}} {{keys.value}}

+
+
@@ -25,6 +28,9 @@ menu {{title}} +
+ {{route.title}} +
@@ -33,11 +39,14 @@ mode="side" [opened]="!mobileQuery.matches">
- - - {{route.title}} - - + + + + {{location.location}} + +

{{keys.key}}: {{keys.value}}

+
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e0fc16b..c8e5681 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,6 +1,8 @@ import { Component, ChangeDetectorRef, EventEmitter, Output } from '@angular/core'; import { MediaMatcher } from '@angular/cdk/layout'; import { MatSidenav } from '@angular/material/sidenav'; +import { DataService } from './services/data.service'; + @Component({ selector: 'app-root', @@ -24,13 +26,17 @@ export class AppComponent { path: '/configs' } ]; + private mobileQueryListener: () => void; @Output() toggleSideNav = new EventEmitter(); - constructor( changeDetectorRef: ChangeDetectorRef, media: MediaMatcher ) { + + constructor( changeDetectorRef: ChangeDetectorRef, media: MediaMatcher , public dataservice: DataService) { this.mobileQuery = media.matchMedia('(max-width: 600px)'); this.mobileQueryListener = () => changeDetectorRef.detectChanges(); this.mobileQuery.addListener(this.mobileQueryListener); } + + toggleMobileNav(nav: MatSidenav) { if (this.mobileQuery.matches) { nav.toggle(); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3699bfd..b46c9e0 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -4,7 +4,7 @@ import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { MaterialModule } from './material/material.module'; -import { HomeComponent } from './home/home.component'; +import { DashboardComponent } from './dashboard/dashboard.component'; import { ServiceWorkerModule } from '@angular/service-worker'; import { environment } from '../environments/environment'; import { ReactiveFormsModule, FormsModule } from '@angular/forms'; @@ -21,10 +21,11 @@ import { MatSortModule } from '@angular/material/sort'; import { MatTableModule } from '@angular/material/table'; import { ConfigsComponent } from './configs/configs.component'; import { HttpClientModule } from '@angular/common/http'; +import { DataService } from './services/data.service'; @NgModule({ declarations: [ AppComponent, - HomeComponent, + DashboardComponent, AuthComponent, LoaderComponent, CountryCodeSelectComponent, @@ -48,7 +49,7 @@ import { HttpClientModule } from '@angular/common/http'; MatSortModule, HttpClientModule ], - providers: [], + providers: [DataService], bootstrap: [AppComponent], entryComponents: [LoaderComponent, CountryCodeSelectComponent] }) diff --git a/src/app/home/home.component.html b/src/app/dashboard/dashboard.component.html similarity index 100% rename from src/app/home/home.component.html rename to src/app/dashboard/dashboard.component.html diff --git a/src/app/home/home.component.scss b/src/app/dashboard/dashboard.component.scss similarity index 100% rename from src/app/home/home.component.scss rename to src/app/dashboard/dashboard.component.scss diff --git a/src/app/home/home.component.spec.ts b/src/app/dashboard/dashboard.component.spec.ts similarity index 55% rename from src/app/home/home.component.spec.ts rename to src/app/dashboard/dashboard.component.spec.ts index 490e81b..9c996c3 100644 --- a/src/app/home/home.component.spec.ts +++ b/src/app/dashboard/dashboard.component.spec.ts @@ -1,20 +1,20 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { HomeComponent } from './home.component'; +import { DashboardComponent } from './dashboard.component'; -describe('HomeComponent', () => { - let component: HomeComponent; - let fixture: ComponentFixture; +describe('DashboardComponent', () => { + let component: DashboardComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ HomeComponent ] + declarations: [ DashboardComponent ] }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(HomeComponent); + fixture = TestBed.createComponent(DashboardComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts new file mode 100644 index 0000000..e80b4e8 --- /dev/null +++ b/src/app/dashboard/dashboard.component.ts @@ -0,0 +1,58 @@ +import { Component, OnInit } from '@angular/core'; +import { Chart } from 'chart.js'; +import { DataService, MyJSON } from '../services/data.service'; +@Component({ + selector: 'app-home', + templateUrl: './dashboard.component.html', + styleUrls: ['./dashboard.component.scss'] +}) + +export class DashboardComponent implements OnInit { + + constructor(private dataservice: DataService) { } + + title = 'Bar Chart'; + charts = new Array(); + messages: Array; + charttypes = ['bar', 'line', 'radar', 'doughnut', 'pie', 'polarArea', 'bubble', 'scatter']; + ngOnInit() { + for (let i = 0; i < 8; i++) { + const chart = document.createElement('canvas'); + chart.id = 'chart-' + i.toString(); + chart.style.width = '100%'; + chart.style.height = '500px'; + document.getElementById('charts').appendChild(chart); + this.charts.push(new Chart(document.getElementById('chart-' + i.toString()), { + type: this.charttypes[i], + data: { + labels: [], + datasets: [{ + label: '', + data: [] + }] + } + })); + } + this.dataservice.message.subscribe((data) => { + this.messages = data; + this.populate(); + }); + } + + populate() { + this.charts.forEach(element => { + element.data.labels = this.messages.map((d) => d.location); + element.data.datasets.forEach( dataset => { + dataset.label = 'Volume Flow'; + dataset.data = this.messages.map( d => d.volumeflow); + dataset.backgroundColor = dataset.data.map((item, index) => 'rgba(' + + index * (255 / this.messages.length) + ',' + + 0 + ',' + + (this.messages.length - index) * (255 / this.messages.length) + ',' + '0.8)'); + }); + element.update(); + }); + } +} + + diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts deleted file mode 100644 index 93b1964..0000000 --- a/src/app/home/home.component.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'; -import { WebSocketSubject } from 'rxjs/webSocket'; -import Auth from '@aws-amplify/auth'; -import { MatTableDataSource } from '@angular/material/table'; -import { MatSort } from '@angular/material/sort'; - -import { Chart } from 'chart.js'; - - -export interface MyJSON { - location: string; - company: string; - volumeflow: number; - field: string; - intakepressure: number; - current: number; - frequency: number; -} - - - -@Component({ - selector: 'app-home', - templateUrl: './home.component.html', - styleUrls: ['./home.component.scss'] -}) - -export class HomeComponent implements OnInit, OnDestroy { - - constructor() { - Auth.currentAuthenticatedUser().then(data => { - // console.log(data); - this.roles = data.signInUserSession.idToken.payload['cognito:roles']; - this.groups = data.signInUserSession.idToken.payload['cognito:groups']; - this.groups.forEach( (element, index, array) => { - array[index] = element.replace(/_/g, ' '); - }); - this.currentRole = data.signInUserSession.idToken.payload['cognito:roles'][0]; - this.token = data.signInUserSession.accessToken.jwtToken; - this.connect(); - }); - } - - public serverMessages: MyJSON[] = []; - private socket$: WebSocketSubject; - private currentMessage = {location: '', company: '', volumeflow: '', field: ''}; - totalFlowRate = 0; - private roles: string[]; - private groups: string[]; - private currentRole: string; - private token: string; - - title = 'Bar Chart'; - charts = new Array(); - - @ViewChild(MatSort, {static: true}) sort: MatSort; - - ngOnInit() { - const chart = document.createElement('CANVAS'); - chart.id = 'myChart'; - chart.style.width = '100%'; - chart.style.height = '500px'; - document.getElementById('charts').appendChild(chart); - const chart1 = document.createElement('canvas'); - chart1.id = 'yourChart'; - chart1.style.width = '100%'; - chart1.style.height = '400px'; - document.getElementById('charts').appendChild(chart1); - - this.charts.push(new Chart(document.getElementById('myChart'), { - type: 'bar', - data: { - labels: [], - datasets: [{ - label: '', - data: [] - }] - } - })); - this.charts.push(new Chart(document.getElementById('yourChart'), { - type: 'line', - data: { - labels: [], - datasets: [{ - label: '', - data: [] - }] - } - })); - } - - ngOnDestroy() { - this.socket$.complete(); - } - - connect() { - this.connectWS(this.token, this.currentRole); - this.subscribeWS(); - this.socket$.next({action: 'getDashboardData', policy: this.currentRole}); - } - - connectWS(token: string, role: string) { - this.socket$ = new WebSocketSubject('wss://3fseaywb8b.execute-api.us-east-1.amazonaws.com/prototype?token=' + token + - '&role=' + role); - // console.log(this.socket$); - } - - subscribeWS() { - this.socket$.subscribe((message) => { - // console.log(message); - if (message instanceof Array) { - message.forEach(element => { - this.updateList(element); - }); - } else { - this.updateList(message); - } - this.totalFlowRate = this.totalFlowRates(); - // console.log(this.serverMessages); - this.serverMessages.sort((a, b) => a.location.localeCompare(b.location)); - this.charts.forEach(element => { - element.data.labels = this.serverMessages.map((d) => d.location); - element.data.datasets.forEach( dataset => { - dataset.label = 'Volume Flow'; - dataset.data = this.serverMessages.map( d => d.volumeflow); - dataset.backgroundColor = dataset.data.map((item, index) => 'rgba(' + - index * (255 / this.serverMessages.length) + ',' + - 0 + ',' + - (this.serverMessages.length - index) * (255 / this.serverMessages.length) + ',' + '0.8)'); - }); - element.update(); - }); - }, - (err) => console.error(err), - () => console.warn('Complete: Websocket closed') - ); - } - - updateList(obj: MyJSON) { - // console.log(this.serverMessages); - // console.log(obj); - const index = this.serverMessages.findIndex((e) => e.location === obj.location); - try { - obj.volumeflow = Number(obj.volumeflow.toFixed(2)); - } catch { - // console.log('can transform to fixed decimal data missing or not a number'); - } - try { - obj.current = Number(obj.current.toFixed(2)); - } catch { - // console.log('can transform to fixed decimal data missing or not a number'); - } - try { - obj.intakepressure = Number(obj.intakepressure.toFixed(2)); - } catch { - // console.log('can transform to fixed decimal data missing or not a number'); - } - try { - obj.frequency = Number(obj.frequency.toFixed(2)); - } catch { - // console.log('can transform to fixed decimal data missing or not a number'); - } - - if (index === -1) { - this.serverMessages.push(obj); - - } else { - if (! obj.volumeflow) { - obj.volumeflow = this.serverMessages[index].volumeflow; - } - if (! obj.current) { - obj.current = this.serverMessages[index].current; - } - if (! obj.frequency) { - obj.frequency = this.serverMessages[index].frequency; - } - if (! obj.intakepressure) { - obj.intakepressure = this.serverMessages[index].intakepressure; - } - this.serverMessages[index] = obj; - } - } - - totalFlowRates() { - let temp = 0; - this.serverMessages.forEach(element => { - if (element.volumeflow) { - temp += element.volumeflow; - } - }); - return Number(temp.toFixed(2)); - } - - setRole(index: number) { - this.currentRole = this.roles[index]; - this.socket$.complete(); - this.serverMessages = []; - this.connect(); - } - -} - - diff --git a/src/app/services/data.service.spec.ts b/src/app/services/data.service.spec.ts new file mode 100644 index 0000000..38e8d9e --- /dev/null +++ b/src/app/services/data.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { DataService } from './data.service'; + +describe('DataService', () => { + let service: DataService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(DataService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/data.service.ts b/src/app/services/data.service.ts new file mode 100644 index 0000000..30c50ad --- /dev/null +++ b/src/app/services/data.service.ts @@ -0,0 +1,93 @@ +import { Injectable } from '@angular/core'; +import Auth from '@aws-amplify/auth'; +import { WebSocketSubject } from 'rxjs/webSocket'; +import { Observable, Subject } from 'rxjs'; +export interface MyJSON { + [key: string]: any; +} + +@Injectable({ + providedIn: 'root' +}) + + +export class DataService { + public serverMessages: Array = []; + public message = new Subject(); + private socket$: WebSocketSubject; + totalFlowRate = 0; + private roles: string[]; + private groups: string[]; + private currentRole: string; + private token: string; + + constructor() { + Auth.currentAuthenticatedUser().then(data => { + // console.log(data); + this.roles = data.signInUserSession.idToken.payload['cognito:roles']; + this.groups = data.signInUserSession.idToken.payload['cognito:groups']; + this.groups.forEach( (element, index, array) => { + array[index] = element.replace(/_/g, ' '); + }); + this.currentRole = data.signInUserSession.idToken.payload['cognito:roles'][0]; + this.token = data.signInUserSession.accessToken.jwtToken; + this.message.subscribe({ + next: d => d + }); + this.connect(); + }); } + + connect() { + this.connectWS(this.token, this.currentRole); + this.subscribeWS(); + this.socket$.next({action: 'getDashboardData', policy: this.currentRole}); + } + + connectWS(token: string, role: string) { + this.socket$ = new WebSocketSubject('wss://3fseaywb8b.execute-api.us-east-1.amazonaws.com/prototype?token=' + token + + '&role=' + role); + // console.log(this.socket$); + } + + subscribeWS() { + this.socket$.subscribe((message) => { + // console.log(message); + if (message instanceof Array) { + message.forEach(element => { + this.updateList(element); + }); + } else { + this.updateList(message); + } + // console.log(this.serverMessages); + this.serverMessages.sort((a, b) => a.location.localeCompare(b.location)); + this.message.next(this.serverMessages); + }, + (err) => console.error(err), + () => console.warn('Complete: Websocket closed') + ); + } + + updateList(obj: MyJSON) { + // console.log(this.serverMessages); + // console.log(obj); + const index = this.serverMessages.findIndex((e) => e.location === obj.location); + + if (index === -1) { + this.serverMessages.push(obj); + + } else { + Object.keys(obj).forEach(element => { + this.serverMessages[index][element] = obj[element]; + }); + } + } + + setRole(index: number) { + this.currentRole = this.roles[index]; + this.socket$.complete(); + this.serverMessages = []; + this.connect(); + } + +}