organization and added a data service
This commit is contained in:
@@ -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)],
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
mode="over"
|
||||
class="sidenav">
|
||||
<div class="content">
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let route of nav">
|
||||
<a mat-button routerLink="{{route.path}}" routerLinkActive="active" (click)="toggleMobileNav(lnav)">{{route.title}}</a>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
<mat-accordion >
|
||||
<mat-expansion-panel *ngFor="let location of this.dataservice.serverMessages">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>{{location.location}}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<p *ngFor="let keys of location | keyvalue">{{keys.key}} {{keys.value}}</p>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
</div>
|
||||
</mat-sidenav>
|
||||
<mat-sidenav-content class="sidenav-content">
|
||||
@@ -25,6 +28,9 @@
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
{{title}}
|
||||
<div *ngFor="let route of nav">
|
||||
<a mat-button routerLink="{{route.path}}" routerLinkActive="active" (click)="toggleMobileNav(lnav)">{{route.title}}</a>
|
||||
</div>
|
||||
<div class="fill-space"></div>
|
||||
<span whoami></span>
|
||||
</mat-toolbar>
|
||||
@@ -33,11 +39,14 @@
|
||||
mode="side"
|
||||
[opened]="!mobileQuery.matches">
|
||||
<div class="content">
|
||||
<mat-list>
|
||||
<mat-list-item *ngFor="let route of nav">
|
||||
<a mat-button routerLink="{{route.path}}" routerLinkActive="active" (click)="toggleMobileNav(lnav)">{{route.title}}</a>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
<mat-accordion >
|
||||
<mat-expansion-panel *ngFor="let location of this.dataservice.serverMessages">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>{{location.location}}</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<p *ngFor="let keys of location | keyvalue">{{keys.key}}: {{keys.value}}</p>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
</div>
|
||||
</mat-drawer>
|
||||
<mat-drawer-content>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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]
|
||||
})
|
||||
|
||||
@@ -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<HomeComponent>;
|
||||
describe('DashboardComponent', () => {
|
||||
let component: DashboardComponent;
|
||||
let fixture: ComponentFixture<DashboardComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ HomeComponent ]
|
||||
declarations: [ DashboardComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HomeComponent);
|
||||
fixture = TestBed.createComponent(DashboardComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
58
src/app/dashboard/dashboard.component.ts
Normal file
58
src/app/dashboard/dashboard.component.ts
Normal file
@@ -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<Chart>();
|
||||
messages: Array<MyJSON>;
|
||||
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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<any>;
|
||||
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<Chart>();
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
16
src/app/services/data.service.spec.ts
Normal file
16
src/app/services/data.service.spec.ts
Normal file
@@ -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();
|
||||
});
|
||||
});
|
||||
93
src/app/services/data.service.ts
Normal file
93
src/app/services/data.service.ts
Normal file
@@ -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<MyJSON> = [];
|
||||
public message = new Subject<MyJSON[]>();
|
||||
private socket$: WebSocketSubject<any>;
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user