Switched from D3 to Chartjs added icons
35
package-lock.json
generated
@@ -4626,6 +4626,32 @@
|
|||||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
|
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"chart.js": {
|
||||||
|
"version": "2.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.3.tgz",
|
||||||
|
"integrity": "sha512-+2jlOobSk52c1VU6fzkh3UwqHMdSlgH1xFv9FKMqHiNCpXsGPQa/+81AFa+i3jZ253Mq9aAycPwDjnn1XbRNNw==",
|
||||||
|
"requires": {
|
||||||
|
"chartjs-color": "^2.1.0",
|
||||||
|
"moment": "^2.10.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chartjs-color": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==",
|
||||||
|
"requires": {
|
||||||
|
"chartjs-color-string": "^0.6.0",
|
||||||
|
"color-convert": "^1.9.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chartjs-color-string": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==",
|
||||||
|
"requires": {
|
||||||
|
"color-name": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"chokidar": {
|
"chokidar": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz",
|
||||||
@@ -4859,7 +4885,6 @@
|
|||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"color-name": "1.1.3"
|
"color-name": "1.1.3"
|
||||||
}
|
}
|
||||||
@@ -4867,8 +4892,7 @@
|
|||||||
"color-name": {
|
"color-name": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"color-string": {
|
"color-string": {
|
||||||
"version": "1.5.3",
|
"version": "1.5.3",
|
||||||
@@ -10012,6 +10036,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"moment": {
|
||||||
|
"version": "2.24.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
|
||||||
|
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
|
||||||
|
},
|
||||||
"move-concurrently": {
|
"move-concurrently": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"@angular/router": "~9.0.0",
|
"@angular/router": "~9.0.0",
|
||||||
"@angular/service-worker": "~9.0.0",
|
"@angular/service-worker": "~9.0.0",
|
||||||
"aws-amplify": "^1.2.2",
|
"aws-amplify": "^1.2.2",
|
||||||
|
"chart.js": "^2.9.3",
|
||||||
"d3": "^5.15.0",
|
"d3": "^5.15.0",
|
||||||
"rxjs": "~6.5.4",
|
"rxjs": "~6.5.4",
|
||||||
"tslib": "^1.10.0",
|
"tslib": "^1.10.0",
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export class ProfileComponent implements OnInit {
|
|||||||
async getUserInfo() {
|
async getUserInfo() {
|
||||||
this.profile = await Auth.currentUserInfo();
|
this.profile = await Auth.currentUserInfo();
|
||||||
this.user = await Auth.currentAuthenticatedUser();
|
this.user = await Auth.currentAuthenticatedUser();
|
||||||
console.log(this.profile);
|
// console.log(this.profile);
|
||||||
if ( this.profile.attributes.profile ) {
|
if ( this.profile.attributes.profile ) {
|
||||||
this.avatar = this.profile.attributes.profile;
|
this.avatar = this.profile.attributes.profile;
|
||||||
this.currentAvatarUrl = await Storage.vault.get(this.avatar) as string;
|
this.currentAvatarUrl = await Storage.vault.get(this.avatar) as string;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export class ConfigsComponent implements OnInit {
|
|||||||
certList.subscribe(
|
certList.subscribe(
|
||||||
data => {
|
data => {
|
||||||
this.options = data as string[];
|
this.options = data as string[];
|
||||||
console.log(data);
|
// console.log(data);
|
||||||
this.filteredOptions = this.certificateIDInput.valueChanges.pipe(
|
this.filteredOptions = this.certificateIDInput.valueChanges.pipe(
|
||||||
startWith(''),
|
startWith(''),
|
||||||
map(value => this._filter(value))
|
map(value => this._filter(value))
|
||||||
@@ -67,7 +67,7 @@ export class ConfigsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
buildForms() {
|
buildForms() {
|
||||||
const numberOfDevices = Object.keys(this.configDownloaded).length - 2;
|
const numberOfDevices = Object.keys(this.configDownloaded).length - 2;
|
||||||
console.log(numberOfDevices);
|
// console.log(numberOfDevices);
|
||||||
this.devicesArray.clear();
|
this.devicesArray.clear();
|
||||||
for (let i = this.devicesArray.length; i < numberOfDevices; i++) {
|
for (let i = this.devicesArray.length; i < numberOfDevices; i++) {
|
||||||
this.devicesArray.push(this.builder.group({
|
this.devicesArray.push(this.builder.group({
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
<div class="container">
|
<div class ="viewer">
|
||||||
<div class ="viewer">
|
<div class="container" fxLayout="row wrap" fxLayoutGap="30px">
|
||||||
<div class="container" fxLayout="row wrap" fxLayoutGap="30px">
|
Total Flow Rate {{ totalFlowRate }}
|
||||||
Total Flow Rate {{ totalFlowRate }}
|
|
||||||
|
|
||||||
<div class="flex-spacer"></div>
|
<div class="flex-spacer"></div>
|
||||||
|
|
||||||
<mat-menu #appMenu="matMenu">
|
<mat-menu #appMenu="matMenu">
|
||||||
<ng-container *ngFor="let item of groups; let i = index">
|
<ng-container *ngFor="let item of groups; let i = index">
|
||||||
<button mat-menu-item (click)="setRole(i)"> {{ item }}</button>
|
<button mat-menu-item (click)="setRole(i)"> {{ item }}</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
<button mat-icon-button [matMenuTriggerFor]="appMenu">
|
<button mat-icon-button [matMenuTriggerFor]="appMenu">
|
||||||
<mat-icon>more_vert</mat-icon>
|
<mat-icon>more_vert</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
|
||||||
<h2>{{ title }}</h2>
|
|
||||||
<svg width="1600" height="680"></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div id="charts"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,15 @@
|
|||||||
width: 250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: inline-block;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
.viewer {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
.flex-spacer {
|
.flex-spacer {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
@@ -21,3 +25,7 @@ table {
|
|||||||
th.mat-sort-header-sorted {
|
th.mat-sort-header-sorted {
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#charts {
|
||||||
|
display: flexbox;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,11 +4,7 @@ import Auth from '@aws-amplify/auth';
|
|||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table';
|
||||||
import { MatSort } from '@angular/material/sort';
|
import { MatSort } from '@angular/material/sort';
|
||||||
|
|
||||||
import * as d3 from 'd3-selection';
|
import { Chart } from 'chart.js';
|
||||||
import * as d3Scale from 'd3-scale';
|
|
||||||
import * as d3Array from 'd3-array';
|
|
||||||
import * as d3Axis from 'd3-axis';
|
|
||||||
import * as d3Color from 'd3-scale-chromatic';
|
|
||||||
|
|
||||||
|
|
||||||
export interface MyJSON {
|
export interface MyJSON {
|
||||||
@@ -55,20 +51,42 @@ export class HomeComponent implements OnInit, OnDestroy {
|
|||||||
private token: string;
|
private token: string;
|
||||||
|
|
||||||
title = 'Bar Chart';
|
title = 'Bar Chart';
|
||||||
private width: number;
|
charts = new Array<Chart>();
|
||||||
private height: number;
|
|
||||||
private margin = {top: 20, right: 20, bottom: 30, left: 40};
|
|
||||||
colorScale: any;
|
|
||||||
|
|
||||||
private x: any;
|
|
||||||
private y: any;
|
|
||||||
private svg: any;
|
|
||||||
private g: any;
|
|
||||||
|
|
||||||
@ViewChild(MatSort, {static: true}) sort: MatSort;
|
@ViewChild(MatSort, {static: true}) sort: MatSort;
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.initSvg();
|
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() {
|
ngOnDestroy() {
|
||||||
@@ -89,7 +107,7 @@ export class HomeComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
subscribeWS() {
|
subscribeWS() {
|
||||||
this.socket$.subscribe((message) => {
|
this.socket$.subscribe((message) => {
|
||||||
console.log(message);
|
// console.log(message);
|
||||||
if (message instanceof Array) {
|
if (message instanceof Array) {
|
||||||
message.forEach(element => {
|
message.forEach(element => {
|
||||||
this.updateList(element);
|
this.updateList(element);
|
||||||
@@ -100,22 +118,21 @@ export class HomeComponent implements OnInit, OnDestroy {
|
|||||||
this.totalFlowRate = this.totalFlowRates();
|
this.totalFlowRate = this.totalFlowRates();
|
||||||
// console.log(this.serverMessages);
|
// console.log(this.serverMessages);
|
||||||
this.serverMessages.sort((a, b) => a.location.localeCompare(b.location));
|
this.serverMessages.sort((a, b) => a.location.localeCompare(b.location));
|
||||||
this.g
|
this.charts.forEach(element => {
|
||||||
.append('g')
|
element.data.labels = this.serverMessages.map((d) => d.location);
|
||||||
.attr('transform', 'translate(0,' + this.height + ')')
|
element.data.datasets.forEach( dataset => {
|
||||||
.attr('class', 'x-axis')
|
dataset.label = 'Volume Flow';
|
||||||
.call(d3Axis.axisBottom(this.x));
|
dataset.data = this.serverMessages.map( d => d.volumeflow);
|
||||||
|
dataset.backgroundColor = dataset.data.map((item, index) => 'rgba(' +
|
||||||
// add the y Axis
|
index * (255 / this.serverMessages.length) + ',' +
|
||||||
this.g
|
0 + ',' +
|
||||||
.append('g')
|
(this.serverMessages.length - index) * (255 / this.serverMessages.length) + ',' + '0.8)');
|
||||||
.attr('transform', 'translate(0, 0 )')
|
});
|
||||||
.attr('class', 'y-axis')
|
element.update();
|
||||||
.call(d3Axis.axisLeft(this.y));
|
});
|
||||||
this.drawAxis();
|
|
||||||
},
|
},
|
||||||
(err) => console.error(err),
|
(err) => console.error(err),
|
||||||
() => console.warn('Completed!')
|
() => console.warn('Complete: Websocket closed')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,29 +143,25 @@ export class HomeComponent implements OnInit, OnDestroy {
|
|||||||
try {
|
try {
|
||||||
obj.volumeflow = Number(obj.volumeflow.toFixed(2));
|
obj.volumeflow = Number(obj.volumeflow.toFixed(2));
|
||||||
} catch {
|
} catch {
|
||||||
console.log('can transform to fixed decimal data missing or not a number');
|
// console.log('can transform to fixed decimal data missing or not a number');
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
obj.current = Number(obj.current.toFixed(2));
|
obj.current = Number(obj.current.toFixed(2));
|
||||||
} catch {
|
} catch {
|
||||||
console.log('can transform to fixed decimal data missing or not a number');
|
// console.log('can transform to fixed decimal data missing or not a number');
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
obj.intakepressure = Number(obj.intakepressure.toFixed(2));
|
obj.intakepressure = Number(obj.intakepressure.toFixed(2));
|
||||||
} catch {
|
} catch {
|
||||||
console.log('can transform to fixed decimal data missing or not a number');
|
// console.log('can transform to fixed decimal data missing or not a number');
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
obj.frequency = Number(obj.frequency.toFixed(2));
|
obj.frequency = Number(obj.frequency.toFixed(2));
|
||||||
} catch {
|
} catch {
|
||||||
console.log('can transform to fixed decimal data missing or not a number');
|
// console.log('can transform to fixed decimal data missing or not a number');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
this.svg
|
|
||||||
.selectAll('.bar')
|
|
||||||
.remove()
|
|
||||||
.exit();
|
|
||||||
this.serverMessages.push(obj);
|
this.serverMessages.push(obj);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -182,41 +195,9 @@ export class HomeComponent implements OnInit, OnDestroy {
|
|||||||
this.currentRole = this.roles[index];
|
this.currentRole = this.roles[index];
|
||||||
this.socket$.complete();
|
this.socket$.complete();
|
||||||
this.serverMessages = [];
|
this.serverMessages = [];
|
||||||
this.drawAxis();
|
|
||||||
this.connect();
|
this.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private initSvg() {
|
|
||||||
this.svg = d3.select('svg');
|
|
||||||
this.width = +this.svg.attr('width') - this.margin.left - this.margin.right;
|
|
||||||
this.height = +this.svg.attr('height') - this.margin.top - this.margin.bottom;
|
|
||||||
this.g = this.svg.append('g')
|
|
||||||
.attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
|
|
||||||
this.x = d3Scale.scaleBand().rangeRound([0, this.width]).padding(0.1);
|
|
||||||
this.y = d3Scale.scaleLinear().rangeRound([this.height, 0]);
|
|
||||||
this.colorScale = d3Scale.scaleOrdinal(d3Color.schemeCategory10);
|
|
||||||
}
|
|
||||||
|
|
||||||
private drawAxis() {
|
|
||||||
this.x.domain(this.serverMessages.map((d) => d.location));
|
|
||||||
this.y.domain([0, d3Array.max(this.serverMessages, d => d.volumeflow)]).ticks(10);
|
|
||||||
this.colorScale.domain(this.serverMessages.map(d => d.location));
|
|
||||||
this.g
|
|
||||||
.selectAll('.bar,.tick')
|
|
||||||
.remove()
|
|
||||||
.exit()
|
|
||||||
.data(this.serverMessages)
|
|
||||||
.enter()
|
|
||||||
.append('rect')
|
|
||||||
.attr('class', 'bar')
|
|
||||||
.attr('x', d => this.x(d.location))
|
|
||||||
.attr('width', this.x.bandwidth())
|
|
||||||
.attr('y', d => this.y(d.volumeflow))
|
|
||||||
.attr('height', d => this.height - this.y(d.volumeflow))
|
|
||||||
.attr('fill', d => this.colorScale(d.location));
|
|
||||||
this.g.select('.x-axis').call(d3Axis.axisBottom(this.x));
|
|
||||||
this.g.select('.y-axis').call(d3Axis.axisLeft(this.y));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 792 B After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 958 B After Width: | Height: | Size: 2.2 KiB |
BIN
src/favicon.ico
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 3.2 KiB |