API & Client - add wind direction to workout detail - fix #134
This commit is contained in:
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"><link rel="stylesheet" href="/static/css/leaflet.css"><title>FitTrackee</title><link href="/static/css/admin.e77f8b26.css" rel="prefetch"><link href="/static/css/profile.8b668068.css" rel="prefetch"><link href="/static/css/reset.fc19709e.css" rel="prefetch"><link href="/static/css/statistics.2afdc8a9.css" rel="prefetch"><link href="/static/css/workouts.c5521765.css" rel="prefetch"><link href="/static/js/admin.5f46d0fe.js" rel="prefetch"><link href="/static/js/chunk-2d0c9189.c81458cc.js" rel="prefetch"><link href="/static/js/chunk-2d0cf391.020c75ea.js" rel="prefetch"><link href="/static/js/chunk-2d0da8f3.c8c3e7e8.js" rel="prefetch"><link href="/static/js/chunk-2d2248b6.d84473c1.js" rel="prefetch"><link href="/static/js/chunk-2d22523a.4b710d99.js" rel="prefetch"><link href="/static/js/profile.d25975e2.js" rel="prefetch"><link href="/static/js/reset.ca898ebe.js" rel="prefetch"><link href="/static/js/statistics.d03ca304.js" rel="prefetch"><link href="/static/js/workouts.dcd0b64a.js" rel="prefetch"><link href="/static/css/app.b54fa5fe.css" rel="preload" as="style"><link href="/static/js/app.15c3e6ab.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.6e2f6ef7.js" rel="preload" as="script"><link href="/static/css/app.b54fa5fe.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.6e2f6ef7.js"></script><script src="/static/js/app.15c3e6ab.js"></script></body></html>
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"><link rel="stylesheet" href="/static/css/leaflet.css"><title>FitTrackee</title><link href="/static/css/admin.e77f8b26.css" rel="prefetch"><link href="/static/css/profile.8b668068.css" rel="prefetch"><link href="/static/css/reset.fc19709e.css" rel="prefetch"><link href="/static/css/statistics.2afdc8a9.css" rel="prefetch"><link href="/static/css/workouts.fe5cb36d.css" rel="prefetch"><link href="/static/js/admin.5f46d0fe.js" rel="prefetch"><link href="/static/js/chunk-2d0c9189.c81458cc.js" rel="prefetch"><link href="/static/js/chunk-2d0cf391.020c75ea.js" rel="prefetch"><link href="/static/js/chunk-2d0da8f3.c8c3e7e8.js" rel="prefetch"><link href="/static/js/chunk-2d2248b6.d84473c1.js" rel="prefetch"><link href="/static/js/chunk-2d22523a.4b710d99.js" rel="prefetch"><link href="/static/js/profile.d25975e2.js" rel="prefetch"><link href="/static/js/reset.ca898ebe.js" rel="prefetch"><link href="/static/js/statistics.d03ca304.js" rel="prefetch"><link href="/static/js/workouts.becfe714.js" rel="prefetch"><link href="/static/css/app.b54fa5fe.css" rel="preload" as="style"><link href="/static/js/app.d9d90958.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.6e2f6ef7.js" rel="preload" as="script"><link href="/static/css/app.b54fa5fe.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.6e2f6ef7.js"></script><script src="/static/js/app.d9d90958.js"></script></body></html>
|
||||||
+8
-8
@@ -72,7 +72,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
|||||||
"url": "/img/workouts/start.svg"
|
"url": "/img/workouts/start.svg"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"revision": "c26adc3efe5f26cacdbb91b86e3a5e38",
|
"revision": "493ca68b0529951c123ad94e2e8864b1",
|
||||||
"url": "/index.html"
|
"url": "/index.html"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -88,7 +88,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
|||||||
"url": "/static/css/admin.e77f8b26.css"
|
"url": "/static/css/admin.e77f8b26.css"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"revision": "58739c2038f30839f6ea",
|
"revision": "be8240ee93d2f582e2be",
|
||||||
"url": "/static/css/app.b54fa5fe.css"
|
"url": "/static/css/app.b54fa5fe.css"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -112,8 +112,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
|||||||
"url": "/static/css/statistics.2afdc8a9.css"
|
"url": "/static/css/statistics.2afdc8a9.css"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"revision": "af09a25559d1f134383d",
|
"revision": "9276c3f7a6a4697c1656",
|
||||||
"url": "/static/css/workouts.c5521765.css"
|
"url": "/static/css/workouts.fe5cb36d.css"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"revision": "e719f9244c69e28e7d00e725ca1e280e",
|
"revision": "e719f9244c69e28e7d00e725ca1e280e",
|
||||||
@@ -200,8 +200,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
|||||||
"url": "/static/js/admin.5f46d0fe.js"
|
"url": "/static/js/admin.5f46d0fe.js"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"revision": "58739c2038f30839f6ea",
|
"revision": "be8240ee93d2f582e2be",
|
||||||
"url": "/static/js/app.15c3e6ab.js"
|
"url": "/static/js/app.d9d90958.js"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"revision": "bd7d183c9f68e5f4027d",
|
"revision": "bd7d183c9f68e5f4027d",
|
||||||
@@ -240,7 +240,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
|
|||||||
"url": "/static/js/statistics.d03ca304.js"
|
"url": "/static/js/statistics.d03ca304.js"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"revision": "af09a25559d1f134383d",
|
"revision": "9276c3f7a6a4697c1656",
|
||||||
"url": "/static/js/workouts.dcd0b64a.js"
|
"url": "/static/js/workouts.becfe714.js"
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
Vendored
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
|
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
|
||||||
|
|
||||||
importScripts(
|
importScripts(
|
||||||
"/precache-manifest.c7eccdefc201d4db22dbdf20aa0937a3.js"
|
"/precache-manifest.c471b20527d5a4f06820639e2531369f.js"
|
||||||
);
|
);
|
||||||
|
|
||||||
workbox.core.setCacheNameDetails({prefix: "fittrackee_client"});
|
workbox.core.setCacheNameDetails({prefix: "fittrackee_client"});
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -29,6 +29,7 @@ def get_weather(point: GPXRoutePoint) -> Optional[Dict]:
|
|||||||
'temperature': weather.temperature,
|
'temperature': weather.temperature,
|
||||||
'humidity': weather.humidity,
|
'humidity': weather.humidity,
|
||||||
'wind': weather.windSpeed,
|
'wind': weather.windSpeed,
|
||||||
|
'windBearing': weather.windBearing,
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
appLog.error(e)
|
appLog.error(e)
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wind">
|
||||||
|
<Distance
|
||||||
|
:distance="weather.wind"
|
||||||
|
unitFrom="m"
|
||||||
|
:digits="1"
|
||||||
|
:displayUnit="false"
|
||||||
|
:useImperialUnits="useImperialUnits"
|
||||||
|
/>
|
||||||
|
{{ useImperialUnits ? 'ft' : 'm' }}/s
|
||||||
|
<div class="wind-bearing">
|
||||||
|
<i
|
||||||
|
v-if="weather.windBearing"
|
||||||
|
class="fa fa-long-arrow-up"
|
||||||
|
:style="{
|
||||||
|
transform: `rotate(${weather.windBearing}deg)`,
|
||||||
|
}"
|
||||||
|
aria-hidden="true"
|
||||||
|
:title="getWindDirectionTitle(weather.windBearing)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { toRefs } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
import { IWeather } from '@/types/workouts'
|
||||||
|
import { convertDegreeToDirection } from '@/utils/weather'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
weather: IWeather
|
||||||
|
useImperialUnits: boolean
|
||||||
|
}
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
|
const { useImperialUnits, weather } = toRefs(props)
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
function getWindDirectionTitle(windBearing: number): string {
|
||||||
|
return t(
|
||||||
|
`workouts.WEATHER.WIND_DIRECTIONS.${convertDegreeToDirection(
|
||||||
|
windBearing
|
||||||
|
)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wind {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
.wind-bearing {
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -90,24 +90,16 @@
|
|||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Distance
|
<WeatherWind
|
||||||
:distance="workoutObject.weatherStart.wind"
|
:weather="workoutObject.weatherStart"
|
||||||
unitFrom="m"
|
|
||||||
:digits="1"
|
|
||||||
:displayUnit="false"
|
|
||||||
:useImperialUnits="useImperialUnits"
|
:useImperialUnits="useImperialUnits"
|
||||||
/>
|
/>
|
||||||
{{ useImperialUnits ? 'ft' : 'm' }}/s
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Distance
|
<WeatherWind
|
||||||
:distance="workoutObject.weatherEnd.wind"
|
:weather="workoutObject.weatherEnd"
|
||||||
unitFrom="m"
|
|
||||||
:digits="1"
|
|
||||||
:displayUnit="false"
|
|
||||||
:useImperialUnits="useImperialUnits"
|
:useImperialUnits="useImperialUnits"
|
||||||
/>
|
/>
|
||||||
{{ useImperialUnits ? 'ft' : 'm' }}/s
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -118,6 +110,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { toRefs } from 'vue'
|
import { toRefs } from 'vue'
|
||||||
|
|
||||||
|
import WeatherWind from '@/components/Workout/WorkoutDetail/WeatherWind.vue'
|
||||||
import { IWorkoutObject } from '@/types/workouts'
|
import { IWorkoutObject } from '@/types/workouts'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@@ -60,6 +60,24 @@
|
|||||||
"HUMIDITY": "humidity",
|
"HUMIDITY": "humidity",
|
||||||
"TEMPERATURE": "temperature",
|
"TEMPERATURE": "temperature",
|
||||||
"WIND": "wind",
|
"WIND": "wind",
|
||||||
|
"WIND_DIRECTIONS": {
|
||||||
|
"N": "N",
|
||||||
|
"NNE": "NNE",
|
||||||
|
"NE": "NE",
|
||||||
|
"ENE": "ENE",
|
||||||
|
"E": "E",
|
||||||
|
"ESE": "ESE",
|
||||||
|
"SE": "SE",
|
||||||
|
"SSE": "SSE",
|
||||||
|
"S": "S",
|
||||||
|
"SSW": "SSW",
|
||||||
|
"SW": "SW",
|
||||||
|
"WSW": "WSW",
|
||||||
|
"W": "W",
|
||||||
|
"WNW": "WNW",
|
||||||
|
"NW": "NW",
|
||||||
|
"NNW": "NNW"
|
||||||
|
},
|
||||||
"DARK_SKY": {
|
"DARK_SKY": {
|
||||||
"clear-day": "clear day",
|
"clear-day": "clear day",
|
||||||
"clear-night": "clear night",
|
"clear-night": "clear night",
|
||||||
@@ -70,7 +88,7 @@
|
|||||||
"rain": "rain",
|
"rain": "rain",
|
||||||
"sleet": "sleet",
|
"sleet": "sleet",
|
||||||
"snow": "snow",
|
"snow": "snow",
|
||||||
"wind": "wind"
|
"wind": "wind"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"WITH_GPX": "with .gpx file",
|
"WITH_GPX": "with .gpx file",
|
||||||
|
|||||||
@@ -60,6 +60,24 @@
|
|||||||
"HUMIDITY": "humidité",
|
"HUMIDITY": "humidité",
|
||||||
"TEMPERATURE": "température",
|
"TEMPERATURE": "température",
|
||||||
"WIND": "vent",
|
"WIND": "vent",
|
||||||
|
"WIND_DIRECTIONS": {
|
||||||
|
"N": "N",
|
||||||
|
"NNE": "NNE",
|
||||||
|
"NE": "NE",
|
||||||
|
"ENE": "ENE",
|
||||||
|
"E": "E",
|
||||||
|
"ESE": "ESE",
|
||||||
|
"SE": "SE",
|
||||||
|
"SSE": "SSE",
|
||||||
|
"S": "S",
|
||||||
|
"SSW": "SSO",
|
||||||
|
"SW": "SO",
|
||||||
|
"WSW": "OSO",
|
||||||
|
"W": "O",
|
||||||
|
"WNW": "ONO",
|
||||||
|
"NW": "NO",
|
||||||
|
"NNW": "NNO"
|
||||||
|
},
|
||||||
"DARK_SKY": {
|
"DARK_SKY": {
|
||||||
"clear-day": "ensoleillé",
|
"clear-day": "ensoleillé",
|
||||||
"clear-night": "nuit claire",
|
"clear-night": "nuit claire",
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export interface IWeather {
|
|||||||
summary: string
|
summary: string
|
||||||
temperature: number
|
temperature: number
|
||||||
wind: number
|
wind: number
|
||||||
|
windBearing?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IWorkout {
|
export interface IWorkout {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
const directions = [
|
||||||
|
'N',
|
||||||
|
'NNE',
|
||||||
|
'NE',
|
||||||
|
'ENE',
|
||||||
|
'E',
|
||||||
|
'ESE',
|
||||||
|
'SE',
|
||||||
|
'SSE',
|
||||||
|
'S',
|
||||||
|
'SSW',
|
||||||
|
'SW',
|
||||||
|
'WSW',
|
||||||
|
'W',
|
||||||
|
'WNW',
|
||||||
|
'NW',
|
||||||
|
'NNW',
|
||||||
|
]
|
||||||
|
|
||||||
|
export const convertDegreeToDirection = (angle: number): string => {
|
||||||
|
const value = Math.floor(angle / 22.5 + 0.5)
|
||||||
|
return directions[value % 16]
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { assert } from 'chai'
|
||||||
|
|
||||||
|
import { convertDegreeToDirection } from '@/utils/weather'
|
||||||
|
|
||||||
|
describe('convertDegreeToDirection', () => {
|
||||||
|
const testsParams: [number, string][] = [
|
||||||
|
[0, 'N'],
|
||||||
|
[45, 'NE'],
|
||||||
|
[90, 'E'],
|
||||||
|
[135, 'SE'],
|
||||||
|
[180, 'S'],
|
||||||
|
[225, 'SW'],
|
||||||
|
[270, 'W'],
|
||||||
|
[315, 'NW'],
|
||||||
|
[22, 'NNE'],
|
||||||
|
[359, 'N'],
|
||||||
|
]
|
||||||
|
testsParams.map((testParams) => {
|
||||||
|
it(`convert ${testParams[0]}° to ${testParams[1]}`, () => {
|
||||||
|
assert.equal(convertDegreeToDirection(testParams[0]), testParams[1])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user