parent
aca1aeead4
commit
3eaf721ffd
3 changed files with 65 additions and 3 deletions
frontend/src
|
@ -55,7 +55,7 @@
|
|||
{{ device.name }}
|
||||
</p>
|
||||
|
||||
<p class="battery" :style="{ color: batteryColor }" v-if="point.battery">
|
||||
<p class="battery" :style="{ color: batteryColor ?? 'initial' }" v-if="point.battery">
|
||||
<font-awesome-icon :icon="batteryIconClass" />
|
||||
<span>{{ point.battery }}%</span>
|
||||
</p>
|
||||
|
|
|
@ -21,6 +21,13 @@
|
|||
:title="(showMetrics.speed ? 'Hide' : 'Show') + ' speed'">
|
||||
<font-awesome-icon icon="tachometer-alt" />
|
||||
</button>
|
||||
|
||||
<button @click="toggleMetric('battery')"
|
||||
:class="{ selected: showMetrics.battery }"
|
||||
:title="(showMetrics.battery ? 'Hide' : 'Show') + ' battery level'"
|
||||
v-if="hasBatteryInfo">
|
||||
<font-awesome-icon icon="battery-full" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="page-button-container">
|
||||
|
@ -128,12 +135,25 @@ export default {
|
|||
})
|
||||
},
|
||||
|
||||
hasBatteryInfo(): boolean {
|
||||
return this.points.some((point: GPSPoint) => point.battery != null)
|
||||
},
|
||||
|
||||
battery(): (number | null)[] {
|
||||
return this.points
|
||||
.map((point: GPSPoint) => point.battery ?? null)
|
||||
},
|
||||
|
||||
speed(): number[] {
|
||||
if (!this.points.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
return this.points.map((point: GPSPoint, index: number) => {
|
||||
if (point.speed != null) {
|
||||
return point.speed
|
||||
}
|
||||
|
||||
if (index === 0) {
|
||||
return 0
|
||||
}
|
||||
|
@ -185,6 +205,19 @@ export default {
|
|||
)
|
||||
}
|
||||
|
||||
if (this.showMetrics.battery) {
|
||||
datasets.push(
|
||||
{
|
||||
label: 'Battery (%)',
|
||||
backgroundColor: '#0989f8',
|
||||
borderColor: '#5959a8',
|
||||
fill: false,
|
||||
data: this.battery,
|
||||
yAxisID: 'percentage',
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
labels: this.points.map((point: GPSPoint) => point.timestamp),
|
||||
datasets: datasets,
|
||||
|
@ -242,6 +275,31 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
if (this.showMetrics.battery) {
|
||||
let position = 'left'
|
||||
if (yAxes.meters || yAxes.speed) {
|
||||
position = 'right'
|
||||
}
|
||||
|
||||
yAxes.percentage = {
|
||||
type: 'linear',
|
||||
position: position,
|
||||
display: true,
|
||||
min: 0,
|
||||
max: 100,
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Percentage',
|
||||
},
|
||||
grid: {
|
||||
drawOnChartArea: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const xTicks = {} as { min?: Date, max?: Date }
|
||||
if (this.points.length > 1) {
|
||||
xTicks.min = this.points[0].timestamp
|
||||
|
|
|
@ -2,13 +2,14 @@ class TimelineMetricsConfiguration {
|
|||
public altitude: boolean = false;
|
||||
public distance: boolean = true;
|
||||
public speed: boolean = false;
|
||||
public battery: boolean = false;
|
||||
|
||||
constructor(data: any | null = null) {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const key of ['altitude', 'distance', 'speed']) {
|
||||
for (const key of ['altitude', 'distance', 'speed', 'battery']) {
|
||||
const value = String(
|
||||
data[key] ?? data['show' + key.charAt(0).toUpperCase() + key.slice(1)]
|
||||
)
|
||||
|
@ -39,13 +40,16 @@ class TimelineMetricsConfiguration {
|
|||
case 'speed':
|
||||
this.speed = !this.speed;
|
||||
break;
|
||||
case 'battery':
|
||||
this.battery = !this.battery;
|
||||
break;
|
||||
default:
|
||||
throw new TypeError(`Invalid timeline metric: ${metric}`);
|
||||
}
|
||||
}
|
||||
|
||||
toQuery(): Record<string, string> {
|
||||
return ['altitude', 'distance', 'speed'].reduce((acc: Record<string, string>, key: string) => {
|
||||
return ['altitude', 'distance', 'speed', 'battery'].reduce((acc: Record<string, string>, key: string) => {
|
||||
acc['show' + key.charAt(0).toUpperCase() + key.slice(1)] = String((this as any)[key]);
|
||||
return acc;
|
||||
}, {});
|
||||
|
|
Loading…
Add table
Reference in a new issue