Browse Source

feat: Add Live Update toggle

master
Konstantinos Kamaropoulos 5 years ago
parent
commit
af853c31a1
  1. 34
      src/app/chart/chart.component.ts
  2. 4
      src/app/logs.service.ts
  3. 80
      src/app/map/map.component.ts
  4. 13
      src/app/shell/header/header.component.html
  5. 100
      src/app/shell/header/header.component.scss
  6. 3
      src/app/shell/header/header.component.ts
  7. 3
      src/translations/el-GR.json
  8. 3
      src/translations/en-US.json

34
src/app/chart/chart.component.ts

@ -91,23 +91,25 @@ export class ChartComponent implements OnInit {
this.chart.render(); this.chart.render();
this.sub = interval(1000).subscribe(async val => { this.sub = interval(1000).subscribe(async val => {
let data = await this.logsService.getUpdates(); if (this.logsService.liveUpdate) {
let sensorReadings: any = data.map(log => { let data = await this.logsService.getUpdates();
let d = log['sensorReadings']; let sensorReadings: any = data.map(log => {
d['time'] = log['createdAt']; let d = log['sensorReadings'];
return d; d['time'] = log['createdAt'];
}); return d;
sensorReadings.forEach((element: any) => { });
for (const key in element) { sensorReadings.forEach((element: any) => {
if (element.hasOwnProperty(key) && key != 'time') { for (const key in element) {
const value = element[key]; if (element.hasOwnProperty(key) && key != 'time') {
this.dataPoints[key].push({ x: new Date(element['time']), y: parseInt(value) }); const value = element[key];
dpsLength = this.dataPoints.length; this.dataPoints[key].push({ x: new Date(element['time']), y: parseInt(value) });
dpsLength = this.dataPoints.length;
}
} }
} dpsLength++;
dpsLength++; });
}); this.chart.render();
this.chart.render(); }
}); });
} }
} }

4
src/app/logs.service.ts

@ -9,6 +9,8 @@ import { map, catchError, last } from 'rxjs/operators';
export class LogsService { export class LogsService {
constructor(private httpClient: HttpClient) {} constructor(private httpClient: HttpClient) {}
liveUpdate: Boolean = true;
previousData: Array<Object> | undefined = undefined; previousData: Array<Object> | undefined = undefined;
getLogs(): Promise<Array<Object>> { getLogs(): Promise<Array<Object>> {
@ -30,6 +32,8 @@ export class LogsService {
} }
async getUpdates(): Promise<Array<Object>> { async getUpdates(): Promise<Array<Object>> {
console.log(this.liveUpdate);
let prevData = this.previousData; let prevData = this.previousData;
if (!this.previousData) { if (!this.previousData) {
let data = await this.getLogs(); let data = await this.getLogs();

80
src/app/map/map.component.ts

@ -48,49 +48,51 @@ export class MapComponent implements OnInit {
var firstRun: Boolean = true; var firstRun: Boolean = true;
this.sub = interval(1000).subscribe(async val => { this.sub = interval(1000).subscribe(async val => {
let data: Array<Object>; if (this.logsService.liveUpdate || firstRun) {
if (firstRun) { let data: Array<Object>;
data = await this.logsService.getLogsFirstRun(); if (firstRun) {
firstRun = false; data = await this.logsService.getLogsFirstRun();
if (data.length > this.pointsToDisplay) { firstRun = false;
this.ommitedPoints = data.length - this.pointsToDisplay; if (data.length > this.pointsToDisplay) {
data = data.slice(data.length - this.pointsToDisplay, data.length); this.ommitedPoints = data.length - this.pointsToDisplay;
data = data.slice(data.length - this.pointsToDisplay, data.length);
}
} else {
data = await this.logsService.getUpdates();
} }
} else { let newPointsCount = 0;
data = await this.logsService.getUpdates(); this.displayedPoints = this.displayedPoints + data.length;
} for (let log of data) {
let newPointsCount = 0; if (log['gps_data']['status'] == 'A') {
this.displayedPoints = this.displayedPoints + data.length; newPointsCount++;
for (let log of data) { let html =
if (log['gps_data']['status'] == 'A') { log['gps_data']['datestamp'] +
newPointsCount++; ' ' +
let html = log['gps_data']['timestamp'] +
log['gps_data']['datestamp'] + '<br><table><tr><th>Sensor&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th><th>Reading</th></tr>';
' ' + for (let record in log['sensorReadings']) {
log['gps_data']['timestamp'] + if (Object.prototype.hasOwnProperty.call(log['sensorReadings'], record)) {
'<br><table><tr><th>Sensor&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th><th>Reading</th></tr>'; html += '<tr><td>' + record + '</td>' + '<td>' + log['sensorReadings'][record] + '</td></tr>';
for (let record in log['sensorReadings']) { }
if (Object.prototype.hasOwnProperty.call(log['sensorReadings'], record)) {
html += '<tr><td>' + record + '</td>' + '<td>' + log['sensorReadings'][record] + '</td></tr>';
} }
html += '</table>';
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 += '</table>'; this.lastPoint = [log['gps_data']['longitude'], log['gps_data']['latitude']];
var popup = new mapboxgl.Popup({ offset: 25 }).setHTML(html); }
var marker = new mapboxgl.Marker({ if (newPointsCount) {
draggable: false this.map.flyTo({
}) center: [this.lastPoint[0], this.lastPoint[1]],
.setLngLat([log['gps_data']['longitude'], log['gps_data']['latitude']]) essential: true, // this animation is considered essential with respect to prefers-reduced-motion
.setPopup(popup) zoom: 22
.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
});
} }
}); });
} }

13
src/app/shell/header/header.component.html

@ -35,6 +35,19 @@
</button> </button>
</div> </div>
</div> </div>
<div class="nav-item" style="padding-top: 6px;" ngbDropdown display="dynamic" placement="bottom-right">
<div title="{{ 'Live Update' | translate }}">
<input
type="checkbox"
name="toggle"
class="sw"
id="toggle-1"
[checked]="logService.liveUpdate"
(change)="logService.liveUpdate = !logService.liveUpdate"
/>
<label for="toggle-1"></label>
</div>
</div>
</div> </div>
</div> </div>
</nav> </nav>

100
src/app/shell/header/header.component.scss

@ -7,3 +7,103 @@
.nav-link.dropdown-toggle { .nav-link.dropdown-toggle {
cursor: pointer; 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;
}

3
src/app/shell/header/header.component.ts

@ -1,6 +1,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { I18nService } from '@app/core'; import { I18nService } from '@app/core';
import { LogsService } from '@app/logs.service';
@Component({ @Component({
selector: 'app-header', selector: 'app-header',
@ -10,7 +11,7 @@ import { I18nService } from '@app/core';
export class HeaderComponent implements OnInit { export class HeaderComponent implements OnInit {
menuHidden = true; menuHidden = true;
constructor(private i18nService: I18nService) {} constructor(private i18nService: I18nService, private logService: LogsService) {}
ngOnInit() {} ngOnInit() {}

3
src/translations/el-GR.json

@ -6,5 +6,6 @@
"Home | Aiolos": "Αρχική | Αίολος", "Home | Aiolos": "Αρχική | Αίολος",
"Map | Aiolos": "Χάρτης | Αίολος", "Map | Aiolos": "Χάρτης | Αίολος",
"Chart | Aiolos": "Γράφημα | Αίολος", "Chart | Aiolos": "Γράφημα | Αίολος",
"ChartTitle": "Μετρήσεις Αισθητήρων" "ChartTitle": "Μετρήσεις Αισθητήρων",
"Live Update": "Ζωντανή Ενημέρωση"
} }

3
src/translations/en-US.json

@ -6,5 +6,6 @@
"Home | Aiolos": "Home | Aiolos", "Home | Aiolos": "Home | Aiolos",
"Map | Aiolos": "Map | Aiolos", "Map | Aiolos": "Map | Aiolos",
"Chart | Aiolos": "Chart | Aiolos", "Chart | Aiolos": "Chart | Aiolos",
"ChartTitle": "Sensor Readings" "ChartTitle": "Sensor Readings",
"Live Update": "Live Update"
} }

Loading…
Cancel
Save