From af853c31a1b45a9e580555396eaa8b9663ae0696 Mon Sep 17 00:00:00 2001 From: Konstantinos Kamaropoulos Date: Mon, 2 Mar 2020 18:35:30 +0200 Subject: [PATCH] feat: Add Live Update toggle --- src/app/chart/chart.component.ts | 34 +++---- src/app/logs.service.ts | 4 + src/app/map/map.component.ts | 80 +++++++++-------- src/app/shell/header/header.component.html | 13 +++ src/app/shell/header/header.component.scss | 100 +++++++++++++++++++++ src/app/shell/header/header.component.ts | 3 +- src/translations/el-GR.json | 3 +- src/translations/en-US.json | 3 +- 8 files changed, 182 insertions(+), 58 deletions(-) diff --git a/src/app/chart/chart.component.ts b/src/app/chart/chart.component.ts index 53c99e3..5890731 100644 --- a/src/app/chart/chart.component.ts +++ b/src/app/chart/chart.component.ts @@ -91,23 +91,25 @@ export class ChartComponent implements OnInit { this.chart.render(); this.sub = interval(1000).subscribe(async val => { - let data = await this.logsService.getUpdates(); - let sensorReadings: any = data.map(log => { - let d = log['sensorReadings']; - d['time'] = log['createdAt']; - return d; - }); - sensorReadings.forEach((element: any) => { - for (const key in element) { - if (element.hasOwnProperty(key) && key != 'time') { - const value = element[key]; - this.dataPoints[key].push({ x: new Date(element['time']), y: parseInt(value) }); - dpsLength = this.dataPoints.length; + if (this.logsService.liveUpdate) { + let data = await this.logsService.getUpdates(); + let sensorReadings: any = data.map(log => { + let d = log['sensorReadings']; + d['time'] = log['createdAt']; + return d; + }); + sensorReadings.forEach((element: any) => { + for (const key in element) { + if (element.hasOwnProperty(key) && key != 'time') { + const value = element[key]; + this.dataPoints[key].push({ x: new Date(element['time']), y: parseInt(value) }); + dpsLength = this.dataPoints.length; + } } - } - dpsLength++; - }); - this.chart.render(); + dpsLength++; + }); + this.chart.render(); + } }); } } diff --git a/src/app/logs.service.ts b/src/app/logs.service.ts index 56e6e71..0fa6a71 100644 --- a/src/app/logs.service.ts +++ b/src/app/logs.service.ts @@ -9,6 +9,8 @@ import { map, catchError, last } from 'rxjs/operators'; export class LogsService { constructor(private httpClient: HttpClient) {} + liveUpdate: Boolean = true; + previousData: Array | undefined = undefined; getLogs(): Promise> { @@ -30,6 +32,8 @@ export class LogsService { } async getUpdates(): Promise> { + console.log(this.liveUpdate); + let prevData = this.previousData; if (!this.previousData) { let data = await this.getLogs(); diff --git a/src/app/map/map.component.ts b/src/app/map/map.component.ts index 4bd766e..53bb5fd 100644 --- a/src/app/map/map.component.ts +++ b/src/app/map/map.component.ts @@ -48,49 +48,51 @@ export class MapComponent implements OnInit { var firstRun: Boolean = true; this.sub = interval(1000).subscribe(async val => { - let data: Array; - if (firstRun) { - data = await this.logsService.getLogsFirstRun(); - firstRun = false; - if (data.length > this.pointsToDisplay) { - this.ommitedPoints = data.length - this.pointsToDisplay; - data = data.slice(data.length - this.pointsToDisplay, data.length); + if (this.logsService.liveUpdate || firstRun) { + let data: Array; + if (firstRun) { + data = await this.logsService.getLogsFirstRun(); + firstRun = false; + if (data.length > this.pointsToDisplay) { + this.ommitedPoints = data.length - this.pointsToDisplay; + data = data.slice(data.length - this.pointsToDisplay, data.length); + } + } else { + data = await this.logsService.getUpdates(); } - } else { - data = await this.logsService.getUpdates(); - } - let newPointsCount = 0; - this.displayedPoints = this.displayedPoints + data.length; - for (let log of data) { - if (log['gps_data']['status'] == 'A') { - newPointsCount++; - let html = - log['gps_data']['datestamp'] + - ' ' + - log['gps_data']['timestamp'] + - '
'; - for (let record in log['sensorReadings']) { - if (Object.prototype.hasOwnProperty.call(log['sensorReadings'], record)) { - html += '' + ''; + let newPointsCount = 0; + this.displayedPoints = this.displayedPoints + data.length; + for (let log of data) { + if (log['gps_data']['status'] == 'A') { + newPointsCount++; + let html = + log['gps_data']['datestamp'] + + ' ' + + log['gps_data']['timestamp'] + + '
Sensor     Reading
' + record + '' + log['sensorReadings'][record] + '
'; + for (let record in log['sensorReadings']) { + if (Object.prototype.hasOwnProperty.call(log['sensorReadings'], record)) { + html += '' + ''; + } } + html += '
Sensor     Reading
' + record + '' + log['sensorReadings'][record] + '
'; + var popup = new mapboxgl.Popup({ offset: 25 }).setHTML(html); + var marker = new mapboxgl.Marker({ + draggable: false + }) + .setLngLat([log['gps_data']['longitude'], log['gps_data']['latitude']]) + .setPopup(popup) + .addTo(this.map); } - html += ''; - var popup = new mapboxgl.Popup({ offset: 25 }).setHTML(html); - var marker = new mapboxgl.Marker({ - draggable: false - }) - .setLngLat([log['gps_data']['longitude'], log['gps_data']['latitude']]) - .setPopup(popup) - .addTo(this.map); + this.lastPoint = [log['gps_data']['longitude'], log['gps_data']['latitude']]; + } + if (newPointsCount) { + this.map.flyTo({ + center: [this.lastPoint[0], this.lastPoint[1]], + essential: true, // this animation is considered essential with respect to prefers-reduced-motion + zoom: 22 + }); } - this.lastPoint = [log['gps_data']['longitude'], log['gps_data']['latitude']]; - } - if (newPointsCount) { - this.map.flyTo({ - center: [this.lastPoint[0], this.lastPoint[1]], - essential: true, // this animation is considered essential with respect to prefers-reduced-motion - zoom: 22 - }); } }); } diff --git a/src/app/shell/header/header.component.html b/src/app/shell/header/header.component.html index ff0e629..3935e02 100644 --- a/src/app/shell/header/header.component.html +++ b/src/app/shell/header/header.component.html @@ -35,6 +35,19 @@ + diff --git a/src/app/shell/header/header.component.scss b/src/app/shell/header/header.component.scss index c4e8bd6..7178cec 100644 --- a/src/app/shell/header/header.component.scss +++ b/src/app/shell/header/header.component.scss @@ -7,3 +7,103 @@ .nav-link.dropdown-toggle { cursor: pointer; } + +$sw-height: 30px; +$sw-width: 51px; + +input { + &.sw { + opacity: 0; + position: absolute; + left: -9999px; + & + label { + user-select: none; + transition: 0.2s ease; + display: inline-block; + height: $sw-height; + width: $sw-width; + position: relative; + box-shadow: inset 0 0 0px 2px #e4e4e4; + border-radius: 60px; + &:before { + content: ""; + position: absolute; + display: block; + height: $sw-height; + width: $sw-height; + top: 0; + left: 0; + border-radius: $sw-height/2; + background: rgba(76, 217, 100, 0); + transition: 0.2s cubic-bezier(0.24, 0, 0.5, 1); + } + + /* White toggle */ + &:after { + content: ""; + position: absolute; + display: block; + height: 28px; + width: 28px; + top: 50%; + margin-top: -14px; + left: 1px; + border-radius: 60px; + background: #fff; + box-shadow: 0 0 0 1px hsla(0, 0%, 0%, 0.1), 0 4px 0px 0 hsla(0, 0%, 0%, 0.04), 0 4px 9px hsla(0, 0%, 0%, 0.13), + 0 3px 3px hsla(0, 0%, 0%, 0.05); + transition: 0.35s cubic-bezier(0.54, 1.6, 0.5, 1); + } + span { + white-space: nowrap; + height: $sw-height; + line-height: $sw-height; + margin-left: $sw-width; + padding-left: 16px; + } + } + &:checked { + & + label:before { + width: $sw-width; + background: #2196f3; + transition: width 0.2s cubic-bezier(0, 0, 0, 0.1) !important; + } + + & + label:after { + left: $sw-width - $sw-height + 1; + } + + & + label { + box-shadow: inset 0 0 0px 25px #e4e4e4; + transition: box-shadow 2.5s cubic-bezier(0, 1.2, 0.94, 0.95); + } + } + } +} + +/* Tooltip container */ +.tooltip { + position: relative; + display: inline-block; + border-bottom: 1px dotted black; /* If you want dots under the hoverable text */ +} + +/* Tooltip text */ +.tooltip .tooltiptext { + visibility: hidden; + width: 120px; + background-color: black; + color: #fff; + text-align: center; + padding: 5px 0; + border-radius: 6px; + + /* Position the tooltip text - see examples below! */ + position: absolute; + z-index: 1; +} + +/* Show the tooltip text when you mouse over the tooltip container */ +.tooltip:hover .tooltiptext { + visibility: visible; +} diff --git a/src/app/shell/header/header.component.ts b/src/app/shell/header/header.component.ts index 09dc991..660d514 100644 --- a/src/app/shell/header/header.component.ts +++ b/src/app/shell/header/header.component.ts @@ -1,6 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { I18nService } from '@app/core'; +import { LogsService } from '@app/logs.service'; @Component({ selector: 'app-header', @@ -10,7 +11,7 @@ import { I18nService } from '@app/core'; export class HeaderComponent implements OnInit { menuHidden = true; - constructor(private i18nService: I18nService) {} + constructor(private i18nService: I18nService, private logService: LogsService) {} ngOnInit() {} diff --git a/src/translations/el-GR.json b/src/translations/el-GR.json index 8f5fcf7..b6ce945 100644 --- a/src/translations/el-GR.json +++ b/src/translations/el-GR.json @@ -6,5 +6,6 @@ "Home | Aiolos": "Αρχική | Αίολος", "Map | Aiolos": "Χάρτης | Αίολος", "Chart | Aiolos": "Γράφημα | Αίολος", - "ChartTitle": "Μετρήσεις Αισθητήρων" + "ChartTitle": "Μετρήσεις Αισθητήρων", + "Live Update": "Ζωντανή Ενημέρωση" } diff --git a/src/translations/en-US.json b/src/translations/en-US.json index d92ecf4..38d62e8 100644 --- a/src/translations/en-US.json +++ b/src/translations/en-US.json @@ -6,5 +6,6 @@ "Home | Aiolos": "Home | Aiolos", "Map | Aiolos": "Map | Aiolos", "Chart | Aiolos": "Chart | Aiolos", - "ChartTitle": "Sensor Readings" + "ChartTitle": "Sensor Readings", + "Live Update": "Live Update" }