Made the map timeline more mobile-friendly

This commit is contained in:
Fabio Manganiello 2025-03-31 22:11:31 +02:00
parent 6a8f38a182
commit 94ca1ea193
Signed by: blacklight
GPG key ID: D90FBA7F76362774
2 changed files with 148 additions and 37 deletions
frontend/src/components

View file

@ -3,31 +3,24 @@
<h1 v-if="loading">Loading...</h1>
<h1 v-else-if="!points.length">No data to display</h1>
<div class="body" v-else>
<div class="options">
<button @click="toggleMetric('altitude')"
:class="{ selected: showMetrics.altitude }"
:title="(showMetrics.altitude ? 'Hide' : 'Show') + ' altitude'">
<font-awesome-icon icon="mountain" />
<div class="options-toggle until tablet">
<button @click="optionsVisible = !optionsVisible"
:title="(optionsVisible ? 'Hide' : 'Show') + ' options'"
:class="{ selected: optionsVisible }">
<font-awesome-icon icon="bars" />
</button>
</div>
<button @click="toggleMetric('distance')"
:class="{ selected: showMetrics.distance }"
:title="(showMetrics.distance ? 'Hide' : 'Show') + ' distance'">
<font-awesome-icon icon="ruler" />
</button>
<div class="options-container from tablet">
<TimelineOptions :showMetrics="showMetrics"
:hasBatteryInfo="hasBatteryInfo"
@show-metrics="$emit('show-metrics', $event)" />
</div>
<button @click="toggleMetric('speed')"
:class="{ selected: showMetrics.speed }"
: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 class="options-container until tablet" v-if="optionsVisible">
<TimelineOptions :showMetrics="showMetrics"
:hasBatteryInfo="hasBatteryInfo"
@show-metrics="$emit('show-metrics', $event)" />
</div>
<div class="page-button-container">
@ -48,7 +41,7 @@
</button>
</div>
<div class="page-button-container"
<div class="page-button-container reset-pagination"
v-if="locationQuery?.minId || locationQuery?.maxId">
<button @click="$emit('reset-page')"
title="Reset pagination">
@ -78,6 +71,7 @@ import Geo from '../mixins/Geo.vue';
import GPSPoint from '../models/GPSPoint';
import LocationQuery from '../models/LocationQuery';
import TimelineMetricsConfiguration from '../models/TimelineMetricsConfiguration';
import TimelineOptions from './TimelineOptions.vue';
ChartJS.register(
CategoryScale,
@ -97,9 +91,11 @@ export default {
'reset-page',
'show-metrics',
],
mixins: [Geo],
components: {
Line,
TimelineOptions,
},
props: {
@ -120,6 +116,12 @@ export default {
},
},
data() {
return {
optionsVisible: false,
}
},
computed: {
distances(): number[] {
if (!this.points.length) {
@ -394,22 +396,18 @@ $options-width: 5em;
}
}
.options {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
width: $options-width;
height: 100%;
margin-right: 1em;
.options-toggle {
position: absolute;
width: 2em;
height: 2em;
z-index: 1;
button {
width: 100%;
height: 2.5em;
height: 100%;
font-size: 1em;
background-color: var(--color-background);
border: 1px solid var(--vt-c-divider-light-1);
margin-left: 0.5em;
background-color: none;
border: 0;
cursor: pointer;
&:hover {
@ -417,12 +415,28 @@ $options-width: 5em;
}
&.selected {
background: var(--vt-c-blue-bg-dark);
color: var(--vt-c-white);
color: var(--color-accent);
}
}
}
.options-container {
width: $options-width;
height: 100%;
padding: 0.5em;
:deep(button) {
font-size: 0.8em;
}
&.until.tablet {
position: absolute;
left: 2.5em;
background-color: var(--color-background);
box-shadow: 0.25em 0.25em 0.5em 0.1em var(--color-border);
}
}
.page-button-container {
width: 3em;
height: 100%;
@ -444,4 +458,12 @@ $options-width: 5em;
}
}
}
.reset-pagination {
width: 2em;
height: 2em;
position: absolute;
top: 0;
right: 0;
}
</style>

View file

@ -0,0 +1,89 @@
<template>
<div class="options desktop">
<button @click="toggleMetric('altitude')"
:class="{ selected: showMetrics.altitude }"
:title="(showMetrics.altitude ? 'Hide' : 'Show') + ' altitude'">
<font-awesome-icon icon="mountain" />
</button>
<button @click="toggleMetric('distance')"
:class="{ selected: showMetrics.distance }"
:title="(showMetrics.distance ? 'Hide' : 'Show') + ' distance'">
<font-awesome-icon icon="ruler" />
</button>
<button @click="toggleMetric('speed')"
:class="{ selected: showMetrics.speed }"
: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>
</template>
<script lang="ts">
import TimelineMetricsConfiguration from '../models/TimelineMetricsConfiguration';
export default {
emits: [
'show-metrics',
],
props: {
hasBatteryInfo: {
type: Boolean,
default: false,
},
showMetrics: {
type: TimelineMetricsConfiguration,
default: () => new TimelineMetricsConfiguration(),
},
},
methods: {
toggleMetric(metric: string) {
this.$emit('show-metrics', {
...this.showMetrics,
[metric]: !(this.showMetrics as any)[metric],
});
},
},
}
</script>
<style scoped lang="scss">
.options {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
width: 100%;
height: 100%;
margin-right: 1em;
button {
width: 100%;
height: 2.5em;
font-size: 1em;
background-color: var(--color-background);
border: 1px solid var(--vt-c-divider-light-1);
margin-left: 0.5em;
cursor: pointer;
&:hover {
color: var(--color-hover);
}
&.selected {
background: var(--vt-c-blue-bg-dark);
color: var(--vt-c-white);
}
}
}
</style>