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