Merge branch 'release-v0.7.10'

This commit is contained in:
Sam 2022-12-21 12:45:28 +01:00
commit 0fce603c7a
125 changed files with 3716 additions and 2466 deletions

View File

@ -1,5 +1,20 @@
# Change log # Change log
## Version 0.7.10 (2022/12/21)
### Features and enhancements
* [#92](https://github.com/SamR1/FitTrackee/issues/92) - Add ascent and descent parameters in workout import without GPX file
### Translations
* [#279](https://github.com/SamR1/FitTrackee/issues/279) - [Translation Request] - Italian (thanks to @dperruso)
* [c88a515](https://github.com/SamR1/FitTrackee/commit/c88a5158fea5f9e2fa8c41ecc2c100f6d9319371) - Translations update from Hosted Weblate (Dutch, thanks to @bjornclauw)
* [f96dcef](https://github.com/SamR1/FitTrackee/commit/f96dcef0dc69d00f65a036fa2e33c22612004cb1) - Translations update (German)
**Note:** This release contains database migration (see upgrade instructions in [documentation](https://samr1.github.io/FitTrackee/installation.html#upgrade))
## Version 0.7.9 (2022/12/11) ## Version 0.7.9 (2022/12/11)
### Features and enhancements ### Features and enhancements

View File

@ -26,7 +26,7 @@ Examples for Android (non-exhaustive list):
Maps are displayed using [Open Street Map](https://www.openstreetmap.org). Maps are displayed using [Open Street Map](https://www.openstreetmap.org).
It is also possible to add a workout without a gpx file. It is also possible to add a workout without a gpx file.
Translations can be updated through [Weblate](https://hosted.weblate.org/engage/fittrackee/): Translations status on [Weblate](https://hosted.weblate.org/engage/fittrackee/):
[![Translation status](https://hosted.weblate.org/widgets/fittrackee/-/multi-auto.svg)](https://hosted.weblate.org/engage/fittrackee/) [![Translation status](https://hosted.weblate.org/widgets/fittrackee/-/multi-auto.svg)](https://hosted.weblate.org/engage/fittrackee/)
**Still under heavy development (some features may be unstable).** **Still under heavy development (some features may be unstable).**

View File

@ -1 +1 @@
0.7.9 0.7.10

View File

@ -1,4 +1,4 @@
# Sphinx build info version 1 # Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: b4432b1990857f41af30f27460fb619b config: 5abf538cacc290d4cea92d1f42946aba
tags: 645f666f9bcd5a90fca523b33c5a78b7 tags: 645f666f9bcd5a90fca523b33c5a78b7

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 KiB

After

Width:  |  Height:  |  Size: 567 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 KiB

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -1,5 +1,20 @@
# Change log # Change log
## Version 0.7.10 (2022/12/21)
### Features and enhancements
* [#92](https://github.com/SamR1/FitTrackee/issues/92) - Add ascent and descent parameters in workout import without GPX file
### Translations
* [#279](https://github.com/SamR1/FitTrackee/issues/279) - [Translation Request] - Italian (thanks to @dperruso)
* [c88a515](https://github.com/SamR1/FitTrackee/commit/c88a5158fea5f9e2fa8c41ecc2c100f6d9319371) - Translations update from Hosted Weblate (Dutch, thanks to @bjornclauw)
* [f96dcef](https://github.com/SamR1/FitTrackee/commit/f96dcef0dc69d00f65a036fa2e33c22612004cb1) - Translations update (German)
**Note:** This release contains database migration (see upgrade instructions in [documentation](https://samr1.github.io/FitTrackee/installation.html#upgrade))
## Version 0.7.9 (2022/12/11) ## Version 0.7.9 (2022/12/11)
### Features and enhancements ### Features and enhancements

View File

@ -38,7 +38,9 @@ Workouts
It can be overridden in user preferences. It can be overridden in user preferences.
- Dashboard with month calendar displaying workouts and record. The week can start on Sunday or Monday (which can be changed in the user preferences). The calendar displays up to 100 workouts. - Dashboard with month calendar displaying workouts and record. The week can start on Sunday or Monday (which can be changed in the user preferences). The calendar displays up to 100 workouts.
- Workout creation by uploading a gpx file (related data are stored in database with metric system). A workout can even be created without gpx (the user must enter date, time, duration and distance). - Workout creation by uploading a gpx file (related data are stored in database with metric system).
- | A workout can even be created without gpx (the user must enter date, time, duration and distance).
| Ascent and descent can also be provided (*new in 0.7.10*).
- | A workout with a gpx file can be displayed with map and charts (speed and elevation). - | A workout with a gpx file can be displayed with map and charts (speed and elevation).
| Controls allow full screen view and position reset (*new in 0.5.5*). | Controls allow full screen view and position reset (*new in 0.5.5*).
- | If DarkSky API key is provided, weather is displayed in workout detail. - | If DarkSky API key is provided, weather is displayed in workout detail.
@ -142,6 +144,7 @@ FitTrackee is available in the following languages (which can be saved in the us
- French (*new in 0.2.3*) - French (*new in 0.2.3*)
- German (*new in 0.6.9*) - German (*new in 0.6.9*)
- Dutch (*new in 0.7.8*) - Dutch (*new in 0.7.8*)
- Italian (*new in 0.7.10*)
Translations status on `Weblate <https://hosted.weblate.org/engage/fittrackee/>`__: Translations status on `Weblate <https://hosted.weblate.org/engage/fittrackee/>`__:

View File

@ -28,7 +28,7 @@ Prerequisites
- optional - optional
- Redis for task queue (if email sending is enabled) and API rate limits - Redis for task queue (if email sending is enabled) and API rate limits
- SMTP provider (if email sending is enabled) - SMTP provider (if email sending is enabled)
- API key from `Dark Sky <https://darksky.net/dev>`__ - API key from `Dark Sky <https://darksky.net/dev>`__ (deprecated, DarkSky will stop on March 31st, 2023)
- `Poetry <https://poetry.eustace.io>`__ (for installation from sources only) - `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
- `Yarn <https://yarnpkg.com>`__ (for development only) - `Yarn <https://yarnpkg.com>`__ (for development only)
- Docker and Docker Compose (for development or evaluation purposes) - Docker and Docker Compose (for development or evaluation purposes)
@ -480,13 +480,13 @@ Production environment
.. warning:: .. warning::
| Note that FitTrackee is under heavy development, some features may be unstable. | Note that FitTrackee is under heavy development, some features may be unstable.
- Download the last release (for now, it is the release v0.7.9): - Download the last release (for now, it is the release v0.7.10):
.. code:: bash .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.9.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
$ tar -xzf v0.7.9.tar.gz $ tar -xzf v0.7.10.tar.gz
$ mv FitTrackee-0.7.9 FitTrackee $ mv FitTrackee-0.7.10 FitTrackee
$ cd FitTrackee $ cd FitTrackee
- Create **.env** from example and update it - Create **.env** from example and update it
@ -606,13 +606,13 @@ Prod environment
- Change to the directory where FitTrackee directory is located - Change to the directory where FitTrackee directory is located
- Download the last release (for now, it is the release v0.7.9) and overwrite existing files: - Download the last release (for now, it is the release v0.7.10) and overwrite existing files:
.. code:: bash .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.9.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
$ tar -xzf v0.7.9.tar.gz $ tar -xzf v0.7.10.tar.gz
$ cp -R FitTrackee-0.7.9/* FitTrackee/ $ cp -R FitTrackee-0.7.10/* FitTrackee/
$ cd FitTrackee $ cd FitTrackee
- Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__). - Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__).

View File

@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = { var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '0.7.9', VERSION: '0.7.10',
LANGUAGE: 'en', LANGUAGE: 'en',
COLLAPSE_INDEX: false, COLLAPSE_INDEX: false,
BUILDER: 'html', BUILDER: 'html',

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Authentication &#8212; FitTrackee 0.7.9 <title>Authentication &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -1239,7 +1239,7 @@ for other reasons.</p></li>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Configuration &#8212; FitTrackee 0.7.9 <title>Configuration &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -155,7 +155,7 @@
<span class="w"> </span><span class="nt">&quot;max_users&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;max_users&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;max_zip_file_size&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10485760</span><span class="p">,</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;max_zip_file_size&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10485760</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;map_attribution&quot;</span><span class="p">:</span><span class="w"> </span><span class="nt">&quot;&amp;copy; &lt;a href=http://www.openstreetmap.org/copyright&gt;OpenStreetMap&lt;/a&gt; contributors&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;map_attribution&quot;</span><span class="p">:</span><span class="w"> </span><span class="nt">&quot;&amp;copy; &lt;a href=http://www.openstreetmap.org/copyright&gt;OpenStreetMap&lt;/a&gt; contributors&quot;</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.7.9&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.7.10&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span> <span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;success&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;success&quot;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span> <span class="p">}</span><span class="w"></span>
@ -196,7 +196,7 @@
<span class="w"> </span><span class="nt">&quot;max_users&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;max_users&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;max_zip_file_size&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10485760</span><span class="p">,</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;max_zip_file_size&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">10485760</span><span class="p">,</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;map_attribution&quot;</span><span class="p">:</span><span class="w"> </span><span class="nt">&quot;&amp;copy; &lt;a href=http://www.openstreetmap.org/copyright&gt;OpenStreetMap&lt;/a&gt; contributors&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;map_attribution&quot;</span><span class="p">:</span><span class="w"> </span><span class="nt">&quot;&amp;copy; &lt;a href=http://www.openstreetmap.org/copyright&gt;OpenStreetMap&lt;/a&gt; contributors&quot;</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.7.9&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.7.10&quot;</span><span class="w"></span>
<span class="w"> </span><span class="p">},</span><span class="w"></span> <span class="w"> </span><span class="p">},</span><span class="w"></span>
<span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;success&quot;</span><span class="w"></span> <span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;success&quot;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span> <span class="p">}</span><span class="w"></span>
@ -279,7 +279,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>API documentation &#8212; FitTrackee 0.7.9 <title>API documentation &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -160,7 +160,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>OAuth2 &#8212; FitTrackee 0.7.9 <title>OAuth2 &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -694,7 +694,7 @@ are supported by FitTrackee)</p></li>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Records &#8212; FitTrackee 0.7.9 <title>Records &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -262,7 +262,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Sports &#8212; FitTrackee 0.7.9 <title>Sports &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -492,7 +492,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Statistics &#8212; FitTrackee 0.7.9 <title>Statistics &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -419,7 +419,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Users &#8212; FitTrackee 0.7.9 <title>Users &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -663,7 +663,7 @@ one admin.</p>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Workouts &#8212; FitTrackee 0.7.9 <title>Workouts &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -961,13 +961,17 @@ Double quotes in notes must be escaped.</p></li>
<dl class="field-list simple"> <dl class="field-list simple">
<dt class="field-odd">Request JSON Object<span class="colon">:</span></dt> <dt class="field-odd">Request JSON Object<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple"> <dd class="field-odd"><ul class="simple">
<li><p><strong>workout_date</strong> (<em>string</em>) workout date, in user timezone <li><p><strong>ascent</strong> (<em>float</em>) workout ascent (not mandatory,
(format: <code class="docutils literal notranslate"><span class="pre">%Y-%m-%d</span> <span class="pre">%H:%M</span></code>)</p></li> must be provided with descent)</p></li>
<li><p><strong>descent</strong> (<em>float</em>) workout descent (not mandatory,
must be provided with ascent)</p></li>
<li><p><strong>distance</strong> (<em>float</em>) workout distance in km</p></li> <li><p><strong>distance</strong> (<em>float</em>) workout distance in km</p></li>
<li><p><strong>duration</strong> (<em>integer</em>) workout duration in seconds</p></li> <li><p><strong>duration</strong> (<em>integer</em>) workout duration in seconds</p></li>
<li><p><strong>notes</strong> (<em>string</em>) notes (not mandatory)</p></li> <li><p><strong>notes</strong> (<em>string</em>) notes (not mandatory)</p></li>
<li><p><strong>sport_id</strong> (<em>integer</em>) workout sport id</p></li> <li><p><strong>sport_id</strong> (<em>integer</em>) workout sport id</p></li>
<li><p><strong>title</strong> (<em>string</em>) workout title</p></li> <li><p><strong>title</strong> (<em>string</em>) workout title (not mandatory)</p></li>
<li><p><strong>workout_date</strong> (<em>string</em>) workout date, in user timezone
(format: <code class="docutils literal notranslate"><span class="pre">%Y-%m-%d</span> <span class="pre">%H:%M</span></code>)</p></li>
</ul> </ul>
</dd> </dd>
<dt class="field-even">Request Headers<span class="colon">:</span></dt> <dt class="field-even">Request Headers<span class="colon">:</span></dt>
@ -1088,9 +1092,10 @@ Double quotes in notes must be escaped.</p></li>
</dd> </dd>
<dt class="field-even">Request JSON Object<span class="colon">:</span></dt> <dt class="field-even">Request JSON Object<span class="colon">:</span></dt>
<dd class="field-even"><ul class="simple"> <dd class="field-even"><ul class="simple">
<li><p><strong>workout_date</strong> (<em>string</em>) workout date in user timezone <li><p><strong>ascent</strong> (<em>float</em>) workout ascent
(format: <code class="docutils literal notranslate"><span class="pre">%Y-%m-%d</span> <span class="pre">%H:%M</span></code>) (only for workout without gpx, must be provided with descent)</p></li>
(only for workout without gpx)</p></li> <li><p><strong>descent</strong> (<em>float</em>) workout descent
(only for workout without gpx, must be provided with ascent)</p></li>
<li><p><strong>distance</strong> (<em>float</em>) workout distance in km <li><p><strong>distance</strong> (<em>float</em>) workout distance in km
(only for workout without gpx)</p></li> (only for workout without gpx)</p></li>
<li><p><strong>duration</strong> (<em>integer</em>) workout duration in seconds <li><p><strong>duration</strong> (<em>integer</em>) workout duration in seconds
@ -1098,6 +1103,9 @@ Double quotes in notes must be escaped.</p></li>
<li><p><strong>notes</strong> (<em>string</em>) notes</p></li> <li><p><strong>notes</strong> (<em>string</em>) notes</p></li>
<li><p><strong>sport_id</strong> (<em>integer</em>) workout sport id</p></li> <li><p><strong>sport_id</strong> (<em>integer</em>) workout sport id</p></li>
<li><p><strong>title</strong> (<em>string</em>) workout title</p></li> <li><p><strong>title</strong> (<em>string</em>) workout title</p></li>
<li><p><strong>workout_date</strong> (<em>string</em>) workout date in user timezone
(format: <code class="docutils literal notranslate"><span class="pre">%Y-%m-%d</span> <span class="pre">%H:%M</span></code>)
(only for workout without gpx)</p></li>
</ul> </ul>
</dd> </dd>
<dt class="field-odd">Request Headers<span class="colon">:</span></dt> <dt class="field-odd">Request Headers<span class="colon">:</span></dt>
@ -1179,7 +1187,7 @@ Double quotes in notes must be escaped.</p></li>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Third-party applications &#8212; FitTrackee 0.7.9 <title>Third-party applications &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -259,7 +259,7 @@ It is recommended to use PKCE to provide a better security.</p>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Command line interface &#8212; FitTrackee 0.7.9 <title>Command line interface &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -288,7 +288,7 @@ Commands:
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Features &#8212; FitTrackee 0.7.9 <title>Features &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -194,7 +194,12 @@
</div> </div>
<ul> <ul>
<li><p>Dashboard with month calendar displaying workouts and record. The week can start on Sunday or Monday (which can be changed in the user preferences). The calendar displays up to 100 workouts.</p></li> <li><p>Dashboard with month calendar displaying workouts and record. The week can start on Sunday or Monday (which can be changed in the user preferences). The calendar displays up to 100 workouts.</p></li>
<li><p>Workout creation by uploading a gpx file (related data are stored in database with metric system). A workout can even be created without gpx (the user must enter date, time, duration and distance).</p></li> <li><p>Workout creation by uploading a gpx file (related data are stored in database with metric system).</p></li>
<li><div class="line-block">
<div class="line">A workout can even be created without gpx (the user must enter date, time, duration and distance).</div>
<div class="line">Ascent and descent can also be provided (<em>new in 0.7.10</em>).</div>
</div>
</li>
<li><div class="line-block"> <li><div class="line-block">
<div class="line">A workout with a gpx file can be displayed with map and charts (speed and elevation).</div> <div class="line">A workout with a gpx file can be displayed with map and charts (speed and elevation).</div>
<div class="line">Controls allow full screen view and position reset (<em>new in 0.5.5</em>).</div> <div class="line">Controls allow full screen view and position reset (<em>new in 0.5.5</em>).</div>
@ -338,6 +343,7 @@ A user with an inactive account cannot log in. (<em>new in 0.6.0</em>)</p></li>
<li><p>French (<em>new in 0.2.3</em>)</p></li> <li><p>French (<em>new in 0.2.3</em>)</p></li>
<li><p>German (<em>new in 0.6.9</em>)</p></li> <li><p>German (<em>new in 0.6.9</em>)</p></li>
<li><p>Dutch (<em>new in 0.7.8</em>)</p></li> <li><p>Dutch (<em>new in 0.7.8</em>)</p></li>
<li><p>Italian (<em>new in 0.7.10</em>)</p></li>
</ul> </ul>
<p>Translations status on <a class="reference external" href="https://hosted.weblate.org/engage/fittrackee/">Weblate</a>:</p> <p>Translations status on <a class="reference external" href="https://hosted.weblate.org/engage/fittrackee/">Weblate</a>:</p>
<figure class="align-default"> <figure class="align-default">
@ -394,7 +400,7 @@ A user with an inactive account cannot log in. (<em>new in 0.6.0</em>)</p></li>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -4,7 +4,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Index &#8212; FitTrackee 0.7.9 <title>Index &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -188,7 +188,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -4,7 +4,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>HTTP Routing Table &#8212; FitTrackee 0.7.9 <title>HTTP Routing Table &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -47,7 +47,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -410,7 +410,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>FitTrackee &#8212; FitTrackee 0.7.9 <title>FitTrackee &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -42,7 +42,7 @@
</button> </button>
<a class="navbar-brand" href="#"> <a class="navbar-brand" href="#">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -180,7 +180,7 @@ Map</a>.</div>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Installation &#8212; FitTrackee 0.7.9 <title>Installation &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -209,7 +209,7 @@
<dt>optional</dt><dd><ul> <dt>optional</dt><dd><ul>
<li><p>Redis for task queue (if email sending is enabled) and API rate limits</p></li> <li><p>Redis for task queue (if email sending is enabled) and API rate limits</p></li>
<li><p>SMTP provider (if email sending is enabled)</p></li> <li><p>SMTP provider (if email sending is enabled)</p></li>
<li><p>API key from <a class="reference external" href="https://darksky.net/dev">Dark Sky</a></p></li> <li><p>API key from <a class="reference external" href="https://darksky.net/dev">Dark Sky</a> (deprecated, DarkSky will stop on March 31st, 2023)</p></li>
<li><p><a class="reference external" href="https://poetry.eustace.io">Poetry</a> (for installation from sources only)</p></li> <li><p><a class="reference external" href="https://poetry.eustace.io">Poetry</a> (for installation from sources only)</p></li>
<li><p><a class="reference external" href="https://yarnpkg.com">Yarn</a> (for development only)</p></li> <li><p><a class="reference external" href="https://yarnpkg.com">Yarn</a> (for development only)</p></li>
<li><p>Docker and Docker Compose (for development or evaluation purposes)</p></li> <li><p>Docker and Docker Compose (for development or evaluation purposes)</p></li>
@ -795,11 +795,11 @@ $ make install-db
</div> </div>
</div> </div>
<ul class="simple"> <ul class="simple">
<li><p>Download the last release (for now, it is the release v0.7.9):</p></li> <li><p>Download the last release (for now, it is the release v0.7.10):</p></li>
</ul> </ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.9.tar.gz <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
$ tar -xzf v0.7.9.tar.gz $ tar -xzf v0.7.10.tar.gz
$ mv FitTrackee-0.7.9 FitTrackee $ mv FitTrackee-0.7.10 FitTrackee
$ <span class="nb">cd</span> FitTrackee $ <span class="nb">cd</span> FitTrackee
</pre></div> </pre></div>
</div> </div>
@ -919,11 +919,11 @@ $ <span class="nb">source</span> .env
<ul class="simple"> <ul class="simple">
<li><p>Stop the application</p></li> <li><p>Stop the application</p></li>
<li><p>Change to the directory where FitTrackee directory is located</p></li> <li><p>Change to the directory where FitTrackee directory is located</p></li>
<li><p>Download the last release (for now, it is the release v0.7.9) and overwrite existing files:</p></li> <li><p>Download the last release (for now, it is the release v0.7.10) and overwrite existing files:</p></li>
</ul> </ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.9.tar.gz <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
$ tar -xzf v0.7.9.tar.gz $ tar -xzf v0.7.10.tar.gz
$ cp -R FitTrackee-0.7.9/* FitTrackee/ $ cp -R FitTrackee-0.7.10/* FitTrackee/
$ <span class="nb">cd</span> FitTrackee $ <span class="nb">cd</span> FitTrackee
</pre></div> </pre></div>
</div> </div>
@ -1182,7 +1182,7 @@ $ make docker-test-python <span class="c1"># run unit tests on API</span>
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

Binary file not shown.

View File

@ -4,7 +4,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Search &#8212; FitTrackee 0.7.9 <title>Search &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -47,7 +47,7 @@
</button> </button>
<a class="navbar-brand" href="index.html"> <a class="navbar-brand" href="index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -154,7 +154,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Administrator &#8212; FitTrackee 0.7.9 <title>Administrator &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -174,7 +174,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Troubleshooting &#8212; FitTrackee 0.7.9 <title>Troubleshooting &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -157,7 +157,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

View File

@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>User &#8212; FitTrackee 0.7.9 <title>User &#8212; FitTrackee 0.7.10
documentation</title> documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" /> <link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" /> <link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -43,7 +43,7 @@
</button> </button>
<a class="navbar-brand" href="../index.html"> <a class="navbar-brand" href="../index.html">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.7.9 <span class="navbar-text navbar-version pull-left"><b>0.7.10
</b></span> </b></span>
</div> </div>
@ -148,7 +148,7 @@
</p> </p>
<p> <p>
&copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>. &copy; Copyright 2018 - 2022, SamR1 <a rel="me" href="https://fosstodon.org/@FitTrackee"><i class="fa fa-mastodon" aria-hidden="true"></i></a>.
Last updated on Dec 11, 2022.<br/> Last updated on Dec 21, 2022.<br/>
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/> Created using <a href="http://sphinx-doc.org/">Sphinx</a> 5.3.0.<br/>
</p> </p>
</div> </div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 KiB

After

Width:  |  Height:  |  Size: 567 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 KiB

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -38,7 +38,9 @@ Workouts
It can be overridden in user preferences. It can be overridden in user preferences.
- Dashboard with month calendar displaying workouts and record. The week can start on Sunday or Monday (which can be changed in the user preferences). The calendar displays up to 100 workouts. - Dashboard with month calendar displaying workouts and record. The week can start on Sunday or Monday (which can be changed in the user preferences). The calendar displays up to 100 workouts.
- Workout creation by uploading a gpx file (related data are stored in database with metric system). A workout can even be created without gpx (the user must enter date, time, duration and distance). - Workout creation by uploading a gpx file (related data are stored in database with metric system).
- | A workout can even be created without gpx (the user must enter date, time, duration and distance).
| Ascent and descent can also be provided (*new in 0.7.10*).
- | A workout with a gpx file can be displayed with map and charts (speed and elevation). - | A workout with a gpx file can be displayed with map and charts (speed and elevation).
| Controls allow full screen view and position reset (*new in 0.5.5*). | Controls allow full screen view and position reset (*new in 0.5.5*).
- | If DarkSky API key is provided, weather is displayed in workout detail. - | If DarkSky API key is provided, weather is displayed in workout detail.
@ -142,6 +144,7 @@ FitTrackee is available in the following languages (which can be saved in the us
- French (*new in 0.2.3*) - French (*new in 0.2.3*)
- German (*new in 0.6.9*) - German (*new in 0.6.9*)
- Dutch (*new in 0.7.8*) - Dutch (*new in 0.7.8*)
- Italian (*new in 0.7.10*)
Translations status on `Weblate <https://hosted.weblate.org/engage/fittrackee/>`__: Translations status on `Weblate <https://hosted.weblate.org/engage/fittrackee/>`__:

View File

@ -28,7 +28,7 @@ Prerequisites
- optional - optional
- Redis for task queue (if email sending is enabled) and API rate limits - Redis for task queue (if email sending is enabled) and API rate limits
- SMTP provider (if email sending is enabled) - SMTP provider (if email sending is enabled)
- API key from `Dark Sky <https://darksky.net/dev>`__ - API key from `Dark Sky <https://darksky.net/dev>`__ (deprecated, DarkSky will stop on March 31st, 2023)
- `Poetry <https://poetry.eustace.io>`__ (for installation from sources only) - `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
- `Yarn <https://yarnpkg.com>`__ (for development only) - `Yarn <https://yarnpkg.com>`__ (for development only)
- Docker and Docker Compose (for development or evaluation purposes) - Docker and Docker Compose (for development or evaluation purposes)
@ -480,13 +480,13 @@ Production environment
.. warning:: .. warning::
| Note that FitTrackee is under heavy development, some features may be unstable. | Note that FitTrackee is under heavy development, some features may be unstable.
- Download the last release (for now, it is the release v0.7.9): - Download the last release (for now, it is the release v0.7.10):
.. code:: bash .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.9.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
$ tar -xzf v0.7.9.tar.gz $ tar -xzf v0.7.10.tar.gz
$ mv FitTrackee-0.7.9 FitTrackee $ mv FitTrackee-0.7.10 FitTrackee
$ cd FitTrackee $ cd FitTrackee
- Create **.env** from example and update it - Create **.env** from example and update it
@ -606,13 +606,13 @@ Prod environment
- Change to the directory where FitTrackee directory is located - Change to the directory where FitTrackee directory is located
- Download the last release (for now, it is the release v0.7.9) and overwrite existing files: - Download the last release (for now, it is the release v0.7.10) and overwrite existing files:
.. code:: bash .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.7.9.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.7.10.tar.gz
$ tar -xzf v0.7.9.tar.gz $ tar -xzf v0.7.10.tar.gz
$ cp -R FitTrackee-0.7.9/* FitTrackee/ $ cp -R FitTrackee-0.7.10/* FitTrackee/
$ cd FitTrackee $ cd FitTrackee
- Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__). - Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__).

View File

@ -25,7 +25,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
from fittrackee.emails.email import EmailService from fittrackee.emails.email import EmailService
from fittrackee.request import CustomRequest from fittrackee.request import CustomRequest
VERSION = __version__ = '0.7.9' VERSION = __version__ = '0.7.10'
REDIS_URL = os.getenv('REDIS_URL', 'redis://') REDIS_URL = os.getenv('REDIS_URL', 'redis://')
API_RATE_LIMITS = os.environ.get('API_RATE_LIMITS', '300 per 5 minutes').split( API_RATE_LIMITS = os.environ.get('API_RATE_LIMITS', '300 per 5 minutes').split(
',' ','

View File

@ -48,7 +48,7 @@ def get_application_config() -> Union[Dict, HttpResponse]:
"max_users": 0, "max_users": 0,
"max_zip_file_size": 10485760, "max_zip_file_size": 10485760,
"map_attribution": "&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors" "map_attribution": "&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"
"version": "0.7.9" "version": "0.7.10"
}, },
"status": "success" "status": "success"
} }
@ -100,7 +100,7 @@ def update_application_config(auth_user: User) -> Union[Dict, HttpResponse]:
"max_users": 10, "max_users": 10,
"max_zip_file_size": 10485760, "max_zip_file_size": 10485760,
"map_attribution": "&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors" "map_attribution": "&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"
"version": "0.7.9" "version": "0.7.10"
}, },
"status": "success" "status": "success"
} }

View File

@ -60,9 +60,9 @@ class BaseConfig:
'en', 'en',
'fr', 'fr',
'de', 'de',
'it',
# 'nb', # disabled for now # 'nb', # disabled for now
'nl', 'nl',
# 'it', # disabled for now
] ]
OAUTH2_TOKEN_EXPIRES_IN = { OAUTH2_TOKEN_EXPIRES_IN = {
'authorization_code': 864000, # 10 days 'authorization_code': 864000, # 10 days

View File

@ -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><script defer="defer" src="/static/js/chunk-vendors.b65fdc2f.js"></script><script defer="defer" src="/static/js/app.f6f0ca0c.js"></script><link href="/static/css/app.7cddaab1.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></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><script defer="defer" src="/static/js/chunk-vendors.a82f8875.js"></script><script defer="defer" src="/static/js/app.c4c614bd.js"></script><link href="/static/css/app.2461bfc8.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></body></html>

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

View File

@ -1,2 +1,2 @@
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[328],{6e3:function(t,e,i){i.r(e),i.d(e,{default:function(){return _}});var a=i(6252),n=i(2262),s=i(8273),c=i(5801),r=i(9917);const S=t=>((0,a.dD)("data-v-64629971"),t=t(),(0,a.Cn)(),t),l={id:"admin",class:"view"},p={key:0,class:"container"},u=S((()=>(0,a._)("div",{id:"bottom"},null,-1)));var T=(0,a.aZ)({__name:"AdminView",setup(t){const e=(0,r.o)(),i=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_CONFIG])),S=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_STATS])),T=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.IS_ADMIN])),d=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.USER_LOADING]));return(0,a.wF)((()=>e.dispatch(c.SY.ACTIONS.GET_APPLICATION_STATS))),(t,e)=>{const c=(0,a.up)("router-view");return(0,a.wg)(),(0,a.iD)("div",l,[(0,n.SU)(d)?(0,a.kq)("",!0):((0,a.wg)(),(0,a.iD)("div",p,[(0,n.SU)(T)?((0,a.wg)(),(0,a.j4)(c,{key:0,appConfig:(0,n.SU)(i),appStatistics:(0,n.SU)(S)},null,8,["appConfig","appStatistics"])):((0,a.wg)(),(0,a.j4)(s.Z,{key:1})),u]))])}}}),d=i(3744);const o=(0,d.Z)(T,[["__scopeId","data-v-64629971"]]);var _=o}}]); "use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[328],{6e3:function(t,e,i){i.r(e),i.d(e,{default:function(){return _}});var a=i(6252),n=i(2262),s=i(8273),c=i(5801),r=i(9917);const S=t=>((0,a.dD)("data-v-64629971"),t=t(),(0,a.Cn)(),t),l={id:"admin",class:"view"},p={key:0,class:"container"},u=S((()=>(0,a._)("div",{id:"bottom"},null,-1)));var T=(0,a.aZ)({__name:"AdminView",setup(t){const e=(0,r.o)(),i=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_CONFIG])),S=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_STATS])),T=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.IS_ADMIN])),d=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.USER_LOADING]));return(0,a.wF)((()=>e.dispatch(c.SY.ACTIONS.GET_APPLICATION_STATS))),(t,e)=>{const c=(0,a.up)("router-view");return(0,a.wg)(),(0,a.iD)("div",l,[(0,n.SU)(d)?(0,a.kq)("",!0):((0,a.wg)(),(0,a.iD)("div",p,[(0,n.SU)(T)?((0,a.wg)(),(0,a.j4)(c,{key:0,appConfig:(0,n.SU)(i),appStatistics:(0,n.SU)(S)},null,8,["appConfig","appStatistics"])):((0,a.wg)(),(0,a.j4)(s.Z,{key:1})),u]))])}}}),d=i(3744);const o=(0,d.Z)(T,[["__scopeId","data-v-64629971"]]);var _=o}}]);
//# sourceMappingURL=admin.4d1d1ecc.js.map //# sourceMappingURL=admin.443044dd.js.map

View File

@ -1 +1 @@
{"version":3,"file":"static/js/admin.4d1d1ecc.js","mappings":"mOAGA,MAAMA,EAAeC,KAAMC,EAAAA,EAAAA,IAAa,mBAAmBD,EAAEA,KAAIE,EAAAA,EAAAA,MAAcF,GACzEG,EAAa,CACjBC,GAAI,QACJC,MAAO,QAEHC,EAAa,CACjBC,IAAK,EACLF,MAAO,aAEHG,EAA2BT,GAAa,KAAmBU,EAAAA,EAAAA,GAAoB,MAAO,CAAEL,GAAI,UAAY,MAAO,KAUrH,OAA4BM,EAAAA,EAAAA,IAAiB,CAC3CC,OAAQ,YACRC,MAAMC,GAEN,MAAMC,GAAQC,EAAAA,EAAAA,KAERC,GAAqCC,EAAAA,EAAAA,KACzC,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,cAEhBC,GAA6CH,EAAAA,EAAAA,KACjD,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,aAEhBE,GAAuCJ,EAAAA,EAAAA,KAC3C,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,YAEhBC,GAAoCN,EAAAA,EAAAA,KACxC,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,gBAKxB,OAFEE,EAAAA,EAAAA,KAAc,IAAMV,EAAMW,SAASN,EAAAA,GAAAA,QAAAA,yBAE9B,CAACO,EAAUC,KAChB,MAAMC,GAAyBC,EAAAA,EAAAA,IAAkB,eAEjD,OAAQC,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAO5B,EAAY,EACzD6B,EAAAA,EAAAA,IAAOT,IAWLU,EAAAA,EAAAA,IAAoB,IAAI,KAVvBH,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAOzB,EAAY,EACnD0B,EAAAA,EAAAA,IAAOX,KACHS,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaN,EAAwB,CAClDrB,IAAK,EACLS,WAAWgB,EAAAA,EAAAA,IAAOhB,GAClBI,eAAeY,EAAAA,EAAAA,IAAOZ,IACrB,KAAM,EAAG,CAAC,YAAa,qBACzBU,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaC,EAAAA,EAAU,CAAE5B,IAAK,KACjDC,MAGN,CAEJ,I,UCvDA,MAAM4B,GAA2B,OAAgB,EAAQ,CAAC,CAAC,YAAY,qBAEvE,O","sources":["webpack://fittrackee_client/./src/views/AdminView.vue?67de","webpack://fittrackee_client/./src/views/AdminView.vue"],"sourcesContent":["import { defineComponent as _defineComponent } from 'vue'\nimport { unref as _unref, resolveComponent as _resolveComponent, openBlock as _openBlock, createBlock as _createBlock, createCommentVNode as _createCommentVNode, createElementVNode as _createElementVNode, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-64629971\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = {\n id: \"admin\",\n class: \"view\"\n}\nconst _hoisted_2 = {\n key: 0,\n class: \"container\"\n}\nconst _hoisted_3 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode(\"div\", { id: \"bottom\" }, null, -1))\n\nimport { computed, ComputedRef, onBeforeMount } from 'vue'\n\n import NotFound from '@/components/Common/NotFound.vue'\n import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'\n import { TAppConfig, IAppStatistics } from '@/types/application'\n import { useStore } from '@/use/useStore'\n\n \nexport default /*#__PURE__*/_defineComponent({\n __name: 'AdminView',\n setup(__props) {\n\n const store = useStore()\n\n const appConfig: ComputedRef<TAppConfig> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]\n )\n const appStatistics: ComputedRef<IAppStatistics> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_STATS]\n )\n const isAuthUserAmin: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.IS_ADMIN]\n )\n const userLoading: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]\n )\n\n onBeforeMount(() => store.dispatch(ROOT_STORE.ACTIONS.GET_APPLICATION_STATS))\n\nreturn (_ctx: any,_cache: any) => {\n const _component_router_view = _resolveComponent(\"router-view\")!\n\n return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [\n (!_unref(userLoading))\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_2, [\n (_unref(isAuthUserAmin))\n ? (_openBlock(), _createBlock(_component_router_view, {\n key: 0,\n appConfig: _unref(appConfig),\n appStatistics: _unref(appStatistics)\n }, null, 8, [\"appConfig\", \"appStatistics\"]))\n : (_openBlock(), _createBlock(NotFound, { key: 1 })),\n _hoisted_3\n ]))\n : _createCommentVNode(\"\", true)\n ]))\n}\n}\n\n})","import script from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\nexport * from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\n\nimport \"./AdminView.vue?vue&type=style&index=0&id=64629971&lang=scss&scoped=true\"\n\nimport exportComponent from \"/mnt/data-lnx/Devs/00_Perso/FitTrackee/fittrackee_client/node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['__scopeId',\"data-v-64629971\"]])\n\nexport default __exports__"],"names":["_withScopeId","n","_pushScopeId","_popScopeId","_hoisted_1","id","class","_hoisted_2","key","_hoisted_3","_createElementVNode","_defineComponent","__name","setup","__props","store","useStore","appConfig","computed","getters","ROOT_STORE","appStatistics","isAuthUserAmin","AUTH_USER_STORE","userLoading","onBeforeMount","dispatch","_ctx","_cache","_component_router_view","_resolveComponent","_openBlock","_createElementBlock","_unref","_createCommentVNode","_createBlock","NotFound","__exports__"],"sourceRoot":""} {"version":3,"file":"static/js/admin.443044dd.js","mappings":"mOAGA,MAAMA,EAAeC,KAAMC,EAAAA,EAAAA,IAAa,mBAAmBD,EAAEA,KAAIE,EAAAA,EAAAA,MAAcF,GACzEG,EAAa,CACjBC,GAAI,QACJC,MAAO,QAEHC,EAAa,CACjBC,IAAK,EACLF,MAAO,aAEHG,EAA2BT,GAAa,KAAmBU,EAAAA,EAAAA,GAAoB,MAAO,CAAEL,GAAI,UAAY,MAAO,KAUrH,OAA4BM,EAAAA,EAAAA,IAAiB,CAC3CC,OAAQ,YACRC,MAAMC,GAEN,MAAMC,GAAQC,EAAAA,EAAAA,KAERC,GAAqCC,EAAAA,EAAAA,KACzC,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,cAEhBC,GAA6CH,EAAAA,EAAAA,KACjD,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,aAEhBE,GAAuCJ,EAAAA,EAAAA,KAC3C,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,YAEhBC,GAAoCN,EAAAA,EAAAA,KACxC,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,gBAKxB,OAFEE,EAAAA,EAAAA,KAAc,IAAMV,EAAMW,SAASN,EAAAA,GAAAA,QAAAA,yBAE9B,CAACO,EAAUC,KAChB,MAAMC,GAAyBC,EAAAA,EAAAA,IAAkB,eAEjD,OAAQC,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAO5B,EAAY,EACzD6B,EAAAA,EAAAA,IAAOT,IAWLU,EAAAA,EAAAA,IAAoB,IAAI,KAVvBH,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAOzB,EAAY,EACnD0B,EAAAA,EAAAA,IAAOX,KACHS,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaN,EAAwB,CAClDrB,IAAK,EACLS,WAAWgB,EAAAA,EAAAA,IAAOhB,GAClBI,eAAeY,EAAAA,EAAAA,IAAOZ,IACrB,KAAM,EAAG,CAAC,YAAa,qBACzBU,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaC,EAAAA,EAAU,CAAE5B,IAAK,KACjDC,MAGN,CAEJ,I,UCvDA,MAAM4B,GAA2B,OAAgB,EAAQ,CAAC,CAAC,YAAY,qBAEvE,O","sources":["webpack://fittrackee_client/./src/views/AdminView.vue?67de","webpack://fittrackee_client/./src/views/AdminView.vue"],"sourcesContent":["import { defineComponent as _defineComponent } from 'vue'\nimport { unref as _unref, resolveComponent as _resolveComponent, openBlock as _openBlock, createBlock as _createBlock, createCommentVNode as _createCommentVNode, createElementVNode as _createElementVNode, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-64629971\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = {\n id: \"admin\",\n class: \"view\"\n}\nconst _hoisted_2 = {\n key: 0,\n class: \"container\"\n}\nconst _hoisted_3 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode(\"div\", { id: \"bottom\" }, null, -1))\n\nimport { computed, ComputedRef, onBeforeMount } from 'vue'\n\n import NotFound from '@/components/Common/NotFound.vue'\n import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'\n import { TAppConfig, IAppStatistics } from '@/types/application'\n import { useStore } from '@/use/useStore'\n\n \nexport default /*#__PURE__*/_defineComponent({\n __name: 'AdminView',\n setup(__props) {\n\n const store = useStore()\n\n const appConfig: ComputedRef<TAppConfig> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]\n )\n const appStatistics: ComputedRef<IAppStatistics> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_STATS]\n )\n const isAuthUserAmin: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.IS_ADMIN]\n )\n const userLoading: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]\n )\n\n onBeforeMount(() => store.dispatch(ROOT_STORE.ACTIONS.GET_APPLICATION_STATS))\n\nreturn (_ctx: any,_cache: any) => {\n const _component_router_view = _resolveComponent(\"router-view\")!\n\n return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [\n (!_unref(userLoading))\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_2, [\n (_unref(isAuthUserAmin))\n ? (_openBlock(), _createBlock(_component_router_view, {\n key: 0,\n appConfig: _unref(appConfig),\n appStatistics: _unref(appStatistics)\n }, null, 8, [\"appConfig\", \"appStatistics\"]))\n : (_openBlock(), _createBlock(NotFound, { key: 1 })),\n _hoisted_3\n ]))\n : _createCommentVNode(\"\", true)\n ]))\n}\n}\n\n})","import script from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\nexport * from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\n\nimport \"./AdminView.vue?vue&type=style&index=0&id=64629971&lang=scss&scoped=true\"\n\nimport exportComponent from \"/mnt/data-lnx/Devs/00_Perso/FitTrackee/fittrackee_client/node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['__scopeId',\"data-v-64629971\"]])\n\nexport default __exports__"],"names":["_withScopeId","n","_pushScopeId","_popScopeId","_hoisted_1","id","class","_hoisted_2","key","_hoisted_3","_createElementVNode","_defineComponent","__name","setup","__props","store","useStore","appConfig","computed","getters","ROOT_STORE","appStatistics","isAuthUserAmin","AUTH_USER_STORE","userLoading","onBeforeMount","dispatch","_ctx","_cache","_component_router_view","_resolveComponent","_openBlock","_createElementBlock","_unref","_createCommentVNode","_createBlock","NotFound","__exports__"],"sourceRoot":""}

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

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

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

View File

@ -1,2 +1,2 @@
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[845],{4264:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});r(7658);var n=r(6252),a=r(2262),s=r(3577),u=r(2201),o=r(7167),c=r(5801),i=r(9917);const l={key:0,id:"account-confirmation",class:"center-card with-margin"},E={class:"error-message"};var _=(0,n.aZ)({__name:"AccountConfirmationView",setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),_=(0,i.o)(),d=(0,n.Fl)((()=>_.getters[c.SY.GETTERS.ERROR_MESSAGES])),S=(0,n.Fl)((()=>t.query.token));function m(){S.value?_.dispatch(c.YN.ACTIONS.CONFIRM_ACCOUNT,{token:S.value}):r.push("/")}return(0,n.wF)((()=>m())),(0,n.Ah)((()=>_.commit(c.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(e,t)=>{const r=(0,n.up)("router-link");return(0,a.SU)(d)?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n.Wm)(r,{class:"links",to:"/account-confirmation/resend"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("buttons.ACCOUNT-CONFIRMATION-RESEND"))+"? ",1)])),_:1})])])):(0,n.kq)("",!0)}}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-785df978"]]);var m=S},8160:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});r(7658);var n=r(6252),a=r(2262),s=r(3577),u=r(2201),o=r(7167),c=r(5801),i=r(9917);const l={key:0,id:"email-update",class:"center-card with-margin"},E={class:"error-message"};var _=(0,n.aZ)({__name:"EmailUpdateView",setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),_=(0,i.o)(),d=(0,n.Fl)((()=>_.getters[c.YN.GETTERS.AUTH_USER_PROFILE])),S=(0,n.Fl)((()=>_.getters[c.YN.GETTERS.IS_AUTHENTICATED])),m=(0,n.Fl)((()=>_.getters[c.SY.GETTERS.ERROR_MESSAGES])),p=(0,n.Fl)((()=>t.query.token));function R(){p.value?_.dispatch(c.YN.ACTIONS.CONFIRM_EMAIL,{token:p.value,refreshUser:S.value}):r.push("/")}return(0,n.wF)((()=>R())),(0,n.Ah)((()=>_.commit(c.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(0,n.YP)((()=>m.value),(e=>{d.value.username&&e&&r.push("/")})),(e,t)=>{const r=(0,n.up)("router-link"),u=(0,n.up)("i18n-t");return(0,a.SU)(m)&&!(0,a.SU)(d).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n._)("span",null,[(0,n.Wm)(u,{keypath:"user.PROFILE.ERRORED_EMAIL_UPDATE"},{default:(0,n.w5)((()=>[(0,n.Wm)(r,{to:"/login"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("user.LOG_IN")),1)])),_:1})])),_:1})])])])):(0,n.kq)("",!0)}}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-8c2ec9ce"]]);var m=S},1133:function(e,t,r){r.r(t),r.d(t,{default:function(){return d}});var n=r(6252),a=r(2262),s=r(5801),u=r(9917);const o=e=>((0,n.dD)("data-v-6646c65e"),e=e(),(0,n.Cn)(),e),c={key:0,id:"profile",class:"view"},i=o((()=>(0,n._)("div",{id:"bottom"},null,-1)));var l=(0,n.aZ)({__name:"ProfileView",setup(e){const t=(0,u.o)(),r=(0,n.Fl)((()=>t.getters[s.YN.GETTERS.AUTH_USER_PROFILE]));return(e,t)=>{const s=(0,n.up)("router-view");return(0,a.SU)(r).username?((0,n.wg)(),(0,n.iD)("div",c,[(0,n.Wm)(s,{user:(0,a.SU)(r)},null,8,["user"]),i])):(0,n.kq)("",!0)}}}),E=r(3744);const _=(0,E.Z)(l,[["__scopeId","data-v-6646c65e"]]);var d=_},9453:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(6252),a=r(2262),s=r(2201),u=r(2179),o=r(1585),c=r(5801),i=r(9917);const l={key:0,id:"user",class:"view"},E={class:"box"};var _=(0,n.aZ)({__name:"UserView",props:{fromAdmin:{type:Boolean}},setup(e){const t=e,{fromAdmin:r}=(0,a.BK)(t),_=(0,s.yj)(),d=(0,i.o)(),S=(0,n.Fl)((()=>d.getters[c.RT.GETTERS.USER]));return(0,n.wF)((()=>{_.params.username&&"string"===typeof _.params.username&&d.dispatch(c.RT.ACTIONS.GET_USER,_.params.username)})),(0,n.Jd)((()=>{d.dispatch(c.RT.ACTIONS.EMPTY_USER)})),(e,t)=>(0,a.SU)(S).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(u.Z,{user:(0,a.SU)(S)},null,8,["user"]),(0,n._)("div",E,[(0,n.Wm)(o.Z,{user:(0,a.SU)(S),"from-admin":(0,a.SU)(r)},null,8,["user","from-admin"])])])):(0,n.kq)("",!0)}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-af7007f4"]]);var m=S}}]); "use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[845],{4264:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});r(7658);var n=r(6252),a=r(2262),s=r(3577),u=r(2201),o=r(7167),c=r(5801),i=r(9917);const l={key:0,id:"account-confirmation",class:"center-card with-margin"},E={class:"error-message"};var _=(0,n.aZ)({__name:"AccountConfirmationView",setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),_=(0,i.o)(),d=(0,n.Fl)((()=>_.getters[c.SY.GETTERS.ERROR_MESSAGES])),S=(0,n.Fl)((()=>t.query.token));function m(){S.value?_.dispatch(c.YN.ACTIONS.CONFIRM_ACCOUNT,{token:S.value}):r.push("/")}return(0,n.wF)((()=>m())),(0,n.Ah)((()=>_.commit(c.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(e,t)=>{const r=(0,n.up)("router-link");return(0,a.SU)(d)?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n.Wm)(r,{class:"links",to:"/account-confirmation/resend"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("buttons.ACCOUNT-CONFIRMATION-RESEND"))+"? ",1)])),_:1})])])):(0,n.kq)("",!0)}}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-785df978"]]);var m=S},8793:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});r(7658);var n=r(6252),a=r(2262),s=r(3577),u=r(2201),o=r(7167),c=r(5801),i=r(9917);const l={key:0,id:"email-update",class:"center-card with-margin"},E={class:"error-message"};var _=(0,n.aZ)({__name:"EmailUpdateView",setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),_=(0,i.o)(),d=(0,n.Fl)((()=>_.getters[c.YN.GETTERS.AUTH_USER_PROFILE])),S=(0,n.Fl)((()=>_.getters[c.YN.GETTERS.IS_AUTHENTICATED])),m=(0,n.Fl)((()=>_.getters[c.SY.GETTERS.ERROR_MESSAGES])),p=(0,n.Fl)((()=>t.query.token));function R(){p.value?_.dispatch(c.YN.ACTIONS.CONFIRM_EMAIL,{token:p.value,refreshUser:S.value}):r.push("/")}return(0,n.wF)((()=>R())),(0,n.Ah)((()=>_.commit(c.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(0,n.YP)((()=>m.value),(e=>{d.value.username&&e&&r.push("/")})),(e,t)=>{const r=(0,n.up)("router-link"),u=(0,n.up)("i18n-t");return(0,a.SU)(m)&&!(0,a.SU)(d).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n._)("span",null,[(0,n.Wm)(u,{keypath:"user.PROFILE.ERRORED_EMAIL_UPDATE"},{default:(0,n.w5)((()=>[(0,n.Wm)(r,{to:"/login"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("user.LOG_IN")),1)])),_:1})])),_:1})])])])):(0,n.kq)("",!0)}}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-8c2ec9ce"]]);var m=S},1133:function(e,t,r){r.r(t),r.d(t,{default:function(){return d}});var n=r(6252),a=r(2262),s=r(5801),u=r(9917);const o=e=>((0,n.dD)("data-v-6646c65e"),e=e(),(0,n.Cn)(),e),c={key:0,id:"profile",class:"view"},i=o((()=>(0,n._)("div",{id:"bottom"},null,-1)));var l=(0,n.aZ)({__name:"ProfileView",setup(e){const t=(0,u.o)(),r=(0,n.Fl)((()=>t.getters[s.YN.GETTERS.AUTH_USER_PROFILE]));return(e,t)=>{const s=(0,n.up)("router-view");return(0,a.SU)(r).username?((0,n.wg)(),(0,n.iD)("div",c,[(0,n.Wm)(s,{user:(0,a.SU)(r)},null,8,["user"]),i])):(0,n.kq)("",!0)}}}),E=r(3744);const _=(0,E.Z)(l,[["__scopeId","data-v-6646c65e"]]);var d=_},9453:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(6252),a=r(2262),s=r(2201),u=r(2179),o=r(1585),c=r(5801),i=r(9917);const l={key:0,id:"user",class:"view"},E={class:"box"};var _=(0,n.aZ)({__name:"UserView",props:{fromAdmin:{type:Boolean}},setup(e){const t=e,{fromAdmin:r}=(0,a.BK)(t),_=(0,s.yj)(),d=(0,i.o)(),S=(0,n.Fl)((()=>d.getters[c.RT.GETTERS.USER]));return(0,n.wF)((()=>{_.params.username&&"string"===typeof _.params.username&&d.dispatch(c.RT.ACTIONS.GET_USER,_.params.username)})),(0,n.Jd)((()=>{d.dispatch(c.RT.ACTIONS.EMPTY_USER)})),(e,t)=>(0,a.SU)(S).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(u.Z,{user:(0,a.SU)(S)},null,8,["user"]),(0,n._)("div",E,[(0,n.Wm)(o.Z,{user:(0,a.SU)(S),"from-admin":(0,a.SU)(r)},null,8,["user","from-admin"])])])):(0,n.kq)("",!0)}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-af7007f4"]]);var m=S}}]);
//# sourceMappingURL=profile.24318810.js.map //# sourceMappingURL=profile.d9355913.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[193],{7885:function(e,s,t){t.r(s),t.d(s,{default:function(){return A}});var a=t(6252),r=t(2262),l=t(3577),o=(t(7658),t(9150)),n=t(436);const c={class:"chart-menu"},i={class:"chart-arrow"},u={class:"time-frames custom-checkboxes-group"},d={class:"time-frames-checkboxes custom-checkboxes"},p=["id","name","checked","onInput"],m={class:"chart-arrow"};var v=(0,a.aZ)({__name:"StatsMenu",emits:["arrowClick","timeFrameUpdate"],setup(e,{emit:s}){const t=(0,r.iH)("month"),o=["week","month","year"];function n(e){t.value=e,s("timeFrameUpdate",e)}return(e,r)=>((0,a.wg)(),(0,a.iD)("div",c,[(0,a._)("div",i,[(0,a._)("i",{class:"fa fa-chevron-left","aria-hidden":"true",onClick:r[0]||(r[0]=e=>s("arrowClick",!0))})]),(0,a._)("div",u,[(0,a._)("div",d,[((0,a.wg)(),(0,a.iD)(a.HY,null,(0,a.Ko)(o,(s=>(0,a._)("div",{class:"time-frame custom-checkbox",key:s},[(0,a._)("label",null,[(0,a._)("input",{type:"radio",id:s,name:s,checked:t.value===s,onInput:e=>n(s)},null,40,p),(0,a._)("span",null,(0,l.zw)(e.$t(`statistics.TIME_FRAMES.${s}`)),1)])]))),64))])]),(0,a._)("div",m,[(0,a._)("i",{class:"fa fa-chevron-right","aria-hidden":"true",onClick:r[1]||(r[1]=e=>s("arrowClick",!1))})])]))}}),k=t(3744);const _=(0,k.Z)(v,[["__scopeId","data-v-22d55de2"]]);var S=_,w=t(631);const f={class:"sports-menu"},h=["id","name","checked","onInput"],U={class:"sport-label"};var b=(0,a.aZ)({__name:"StatsSportsMenu",props:{userSports:null,selectedSportIds:{default:()=>[]}},emits:["selectedSportIdsUpdate"],setup(e,{emit:s}){const t=e,{t:n}=(0,o.QT)(),c=(0,a.f3)("sportColors"),{selectedSportIds:i}=(0,r.BK)(t),u=(0,a.Fl)((()=>(0,w.xH)(t.userSports,n)));function d(e){s("selectedSportIdsUpdate",e)}return(e,s)=>{const t=(0,a.up)("SportImage");return(0,a.wg)(),(0,a.iD)("div",f,[((0,a.wg)(!0),(0,a.iD)(a.HY,null,(0,a.Ko)((0,r.SU)(u),(e=>((0,a.wg)(),(0,a.iD)("label",{type:"checkbox",key:e.id,style:(0,l.j5)({color:e.color?e.color:(0,r.SU)(c)[e.label]})},[(0,a._)("input",{type:"checkbox",id:e.id,name:e.label,checked:(0,r.SU)(i).includes(e.id),onInput:s=>d(e.id)},null,40,h),(0,a.Wm)(t,{"sport-label":e.label,color:e.color},null,8,["sport-label","color"]),(0,a._)("span",U,(0,l.zw)(e.translatedLabel),1)],4)))),128))])}}});const I=b;var g=I,T=t(9318);const y={key:0,id:"user-statistics"};var C=(0,a.aZ)({__name:"index",props:{sports:null,user:null},setup(e){const s=e,{t:t}=(0,o.QT)(),{sports:l,user:c}=(0,r.BK)(s),i=(0,r.iH)("month"),u=(0,r.iH)(v(i.value)),d=(0,a.Fl)((()=>(0,w.xH)(s.sports,t))),p=(0,r.iH)(_(s.sports));function m(e){i.value=e,u.value=v(i.value)}function v(e){return(0,T.aZ)(new Date,e,s.user.weekm)}function k(e){u.value=(0,T.FN)(u.value,e,s.user.weekm)}function _(e){return e.map((e=>e.id))}function f(e){p.value.includes(e)?p.value=p.value.filter((s=>s!==e)):p.value.push(e)}return(0,a.YP)((()=>s.sports),(e=>{p.value=_(e)})),(e,s)=>(0,r.SU)(d)?((0,a.wg)(),(0,a.iD)("div",y,[(0,a.Wm)(S,{onTimeFrameUpdate:m,onArrowClick:k}),(0,a.Wm)(n.Z,{sports:(0,r.SU)(l),user:(0,r.SU)(c),chartParams:u.value,"displayed-sport-ids":p.value,fullStats:!0},null,8,["sports","user","chartParams","displayed-sport-ids"]),(0,a.Wm)(g,{"selected-sport-ids":p.value,"user-sports":(0,r.SU)(l),onSelectedSportIdsUpdate:f},null,8,["selected-sport-ids","user-sports"])])):(0,a.kq)("",!0)}});const F=(0,k.Z)(C,[["__scopeId","data-v-30799d13"]]);var Z=F,x=t(5630),D=t(5801),H=t(9917);const E={id:"statistics",class:"view"},R={key:0,class:"container"};var W=(0,a.aZ)({__name:"StatisticsView",setup(e){const s=(0,H.o)(),t=(0,a.Fl)((()=>s.getters[D.YN.GETTERS.AUTH_USER_PROFILE])),o=(0,a.Fl)((()=>s.getters[D.O8.GETTERS.SPORTS].filter((e=>t.value.sports_list.includes(e.id)))));return(e,s)=>{const n=(0,a.up)("Card");return(0,a.wg)(),(0,a.iD)("div",E,[(0,r.SU)(t).username?((0,a.wg)(),(0,a.iD)("div",R,[(0,a.Wm)(n,null,{title:(0,a.w5)((()=>[(0,a.Uk)((0,l.zw)(e.$t("statistics.STATISTICS")),1)])),content:(0,a.w5)((()=>[(0,a.Wm)(Z,{class:(0,l.C_)({"stats-disabled":0===(0,r.SU)(t).nb_workouts}),user:(0,r.SU)(t),sports:(0,r.SU)(o)},null,8,["class","user","sports"])])),_:1}),0===(0,r.SU)(t).nb_workouts?((0,a.wg)(),(0,a.j4)(x.Z,{key:0})):(0,a.kq)("",!0)])):(0,a.kq)("",!0)])}}});const P=(0,k.Z)(W,[["__scopeId","data-v-2e341d4e"]]);var A=P}}]); "use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[193],{7885:function(e,s,t){t.r(s),t.d(s,{default:function(){return A}});var a=t(6252),r=t(2262),l=t(3577),o=(t(7658),t(9150)),n=t(436);const c={class:"chart-menu"},i={class:"chart-arrow"},u={class:"time-frames custom-checkboxes-group"},d={class:"time-frames-checkboxes custom-checkboxes"},p=["id","name","checked","onInput"],m={class:"chart-arrow"};var v=(0,a.aZ)({__name:"StatsMenu",emits:["arrowClick","timeFrameUpdate"],setup(e,{emit:s}){const t=(0,r.iH)("month"),o=["week","month","year"];function n(e){t.value=e,s("timeFrameUpdate",e)}return(e,r)=>((0,a.wg)(),(0,a.iD)("div",c,[(0,a._)("div",i,[(0,a._)("i",{class:"fa fa-chevron-left","aria-hidden":"true",onClick:r[0]||(r[0]=e=>s("arrowClick",!0))})]),(0,a._)("div",u,[(0,a._)("div",d,[((0,a.wg)(),(0,a.iD)(a.HY,null,(0,a.Ko)(o,(s=>(0,a._)("div",{class:"time-frame custom-checkbox",key:s},[(0,a._)("label",null,[(0,a._)("input",{type:"radio",id:s,name:s,checked:t.value===s,onInput:e=>n(s)},null,40,p),(0,a._)("span",null,(0,l.zw)(e.$t(`statistics.TIME_FRAMES.${s}`)),1)])]))),64))])]),(0,a._)("div",m,[(0,a._)("i",{class:"fa fa-chevron-right","aria-hidden":"true",onClick:r[1]||(r[1]=e=>s("arrowClick",!1))})])]))}}),k=t(3744);const _=(0,k.Z)(v,[["__scopeId","data-v-22d55de2"]]);var S=_,w=t(631);const f={class:"sports-menu"},h=["id","name","checked","onInput"],U={class:"sport-label"};var b=(0,a.aZ)({__name:"StatsSportsMenu",props:{userSports:null,selectedSportIds:{default:()=>[]}},emits:["selectedSportIdsUpdate"],setup(e,{emit:s}){const t=e,{t:n}=(0,o.QT)(),c=(0,a.f3)("sportColors"),{selectedSportIds:i}=(0,r.BK)(t),u=(0,a.Fl)((()=>(0,w.xH)(t.userSports,n)));function d(e){s("selectedSportIdsUpdate",e)}return(e,s)=>{const t=(0,a.up)("SportImage");return(0,a.wg)(),(0,a.iD)("div",f,[((0,a.wg)(!0),(0,a.iD)(a.HY,null,(0,a.Ko)((0,r.SU)(u),(e=>((0,a.wg)(),(0,a.iD)("label",{type:"checkbox",key:e.id,style:(0,l.j5)({color:e.color?e.color:(0,r.SU)(c)[e.label]})},[(0,a._)("input",{type:"checkbox",id:e.id,name:e.label,checked:(0,r.SU)(i).includes(e.id),onInput:s=>d(e.id)},null,40,h),(0,a.Wm)(t,{"sport-label":e.label,color:e.color},null,8,["sport-label","color"]),(0,a._)("span",U,(0,l.zw)(e.translatedLabel),1)],4)))),128))])}}});const I=b;var g=I,T=t(9318);const y={key:0,id:"user-statistics"};var C=(0,a.aZ)({__name:"index",props:{sports:null,user:null},setup(e){const s=e,{t:t}=(0,o.QT)(),{sports:l,user:c}=(0,r.BK)(s),i=(0,r.iH)("month"),u=(0,r.iH)(v(i.value)),d=(0,a.Fl)((()=>(0,w.xH)(s.sports,t))),p=(0,r.iH)(_(s.sports));function m(e){i.value=e,u.value=v(i.value)}function v(e){return(0,T.aZ)(new Date,e,s.user.weekm)}function k(e){u.value=(0,T.FN)(u.value,e,s.user.weekm)}function _(e){return e.map((e=>e.id))}function f(e){p.value.includes(e)?p.value=p.value.filter((s=>s!==e)):p.value.push(e)}return(0,a.YP)((()=>s.sports),(e=>{p.value=_(e)})),(e,s)=>(0,r.SU)(d)?((0,a.wg)(),(0,a.iD)("div",y,[(0,a.Wm)(S,{onTimeFrameUpdate:m,onArrowClick:k}),(0,a.Wm)(n.Z,{sports:(0,r.SU)(l),user:(0,r.SU)(c),chartParams:u.value,"displayed-sport-ids":p.value,fullStats:!0},null,8,["sports","user","chartParams","displayed-sport-ids"]),(0,a.Wm)(g,{"selected-sport-ids":p.value,"user-sports":(0,r.SU)(l),onSelectedSportIdsUpdate:f},null,8,["selected-sport-ids","user-sports"])])):(0,a.kq)("",!0)}});const F=(0,k.Z)(C,[["__scopeId","data-v-30799d13"]]);var Z=F,x=t(5630),D=t(5801),H=t(9917);const E={id:"statistics",class:"view"},R={key:0,class:"container"};var W=(0,a.aZ)({__name:"StatisticsView",setup(e){const s=(0,H.o)(),t=(0,a.Fl)((()=>s.getters[D.YN.GETTERS.AUTH_USER_PROFILE])),o=(0,a.Fl)((()=>s.getters[D.O8.GETTERS.SPORTS].filter((e=>t.value.sports_list.includes(e.id)))));return(e,s)=>{const n=(0,a.up)("Card");return(0,a.wg)(),(0,a.iD)("div",E,[(0,r.SU)(t).username?((0,a.wg)(),(0,a.iD)("div",R,[(0,a.Wm)(n,null,{title:(0,a.w5)((()=>[(0,a.Uk)((0,l.zw)(e.$t("statistics.STATISTICS")),1)])),content:(0,a.w5)((()=>[(0,a.Wm)(Z,{class:(0,l.C_)({"stats-disabled":0===(0,r.SU)(t).nb_workouts}),user:(0,r.SU)(t),sports:(0,r.SU)(o)},null,8,["class","user","sports"])])),_:1}),0===(0,r.SU)(t).nb_workouts?((0,a.wg)(),(0,a.j4)(x.Z,{key:0})):(0,a.kq)("",!0)])):(0,a.kq)("",!0)])}}});const P=(0,k.Z)(W,[["__scopeId","data-v-2e341d4e"]]);var A=P}}]);
//# sourceMappingURL=statistics.560b3502.js.map //# sourceMappingURL=statistics.31ee4368.js.map

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

View File

@ -8,21 +8,23 @@ msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2022-12-11 09:25+0100\n" "POT-Creation-Date: 2022-12-11 09:25+0100\n"
"PO-Revision-Date: 2022-12-11 09:25+0100\n" "PO-Revision-Date: 2022-12-12 19:48+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: Donato Perruso <dperruso@protonmail.com>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/fittrackee/"
"fittrackee-api-emails/it/>\n"
"Language: it\n" "Language: it\n"
"Language-Team: it <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.15-dev\n"
"Generated-By: Babel 2.11.0\n" "Generated-By: Babel 2.11.0\n"
#: fittrackee/emails/templates/layout.html:215 #: fittrackee/emails/templates/layout.html:215
#: fittrackee/emails/templates/layout.txt:1 #: fittrackee/emails/templates/layout.txt:1
#, python-format #, python-format
msgid "Hi %(username)s," msgid "Hi %(username)s,"
msgstr "" msgstr "Ciao %(username)s,"
#: fittrackee/emails/templates/account_confirmation/body.txt:6 #: fittrackee/emails/templates/account_confirmation/body.txt:6
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:3 #: fittrackee/emails/templates/email_update_to_current_email/body.txt:3
@ -35,41 +37,43 @@ msgid ""
"For security, this request was received from a %(operating_system)s " "For security, this request was received from a %(operating_system)s "
"device using %(browser_name)s." "device using %(browser_name)s."
msgstr "" msgstr ""
"Per sicurezza, questa richiesta è stata ricevuta da %(operating_system)s "
"utilizzando il browser %(browser_name)s."
#: fittrackee/emails/templates/layout.html:221 #: fittrackee/emails/templates/layout.html:221
#: fittrackee/emails/templates/layout.txt:5 #: fittrackee/emails/templates/layout.txt:5
msgid "Thanks," msgid "Thanks,"
msgstr "" msgstr "Grazie,"
#: fittrackee/emails/templates/layout.html:222 #: fittrackee/emails/templates/layout.html:222
#: fittrackee/emails/templates/layout.txt:6 #: fittrackee/emails/templates/layout.txt:6
msgid "The FitTrackee Team" msgid "The FitTrackee Team"
msgstr "" msgstr "Il Team FitTrackee"
#: fittrackee/emails/templates/account_confirmation/body.html:2 #: fittrackee/emails/templates/account_confirmation/body.html:2
#: fittrackee/emails/templates/account_confirmation/subject.txt:1 #: fittrackee/emails/templates/account_confirmation/subject.txt:1
msgid "Confirm your account" msgid "Confirm your account"
msgstr "" msgstr "Conferma il tuo account"
#: fittrackee/emails/templates/account_confirmation/body.html:3 #: fittrackee/emails/templates/account_confirmation/body.html:3
msgid "Use this link to confirm your account." msgid "Use this link to confirm your account."
msgstr "" msgstr "Usa questo link per confermare il tuo account."
#: fittrackee/emails/templates/account_confirmation/body.html:4 #: fittrackee/emails/templates/account_confirmation/body.html:4
#: fittrackee/emails/templates/account_confirmation/body.txt:1 #: fittrackee/emails/templates/account_confirmation/body.txt:1
msgid "You have created an account on FitTrackee." msgid "You have created an account on FitTrackee."
msgstr "" msgstr "Hai creato un account su FitTrackee."
#: fittrackee/emails/templates/account_confirmation/body.html:4 #: fittrackee/emails/templates/account_confirmation/body.html:4
msgid "Use the button below to confirm your address email." msgid "Use the button below to confirm your address email."
msgstr "" msgstr "Usa il bottone qui sotto per confermare il tuo indirizzo email."
#: fittrackee/emails/templates/account_confirmation/body.html:11 #: fittrackee/emails/templates/account_confirmation/body.html:11
#: fittrackee/emails/templates/account_confirmation/body.txt:4 #: fittrackee/emails/templates/account_confirmation/body.txt:4
#: fittrackee/emails/templates/email_update_to_new_email/body.html:11 #: fittrackee/emails/templates/email_update_to_new_email/body.html:11
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:4 #: fittrackee/emails/templates/email_update_to_new_email/body.txt:4
msgid "Verify your email" msgid "Verify your email"
msgstr "" msgstr "Verifica la tua email"
#: fittrackee/emails/templates/account_confirmation/body.html:18 #: fittrackee/emails/templates/account_confirmation/body.html:18
#: fittrackee/emails/templates/account_confirmation/body.txt:7 #: fittrackee/emails/templates/account_confirmation/body.txt:7
@ -77,6 +81,8 @@ msgid ""
"If this account creation wasn't initiated by you, please ignore this " "If this account creation wasn't initiated by you, please ignore this "
"email." "email."
msgstr "" msgstr ""
"Se la creazione di quest'account non è stata iniziata da te, per favore "
"ignora quest'email."
#: fittrackee/emails/templates/account_confirmation/body.html:22 #: fittrackee/emails/templates/account_confirmation/body.html:22
#: fittrackee/emails/templates/email_update_to_new_email/body.html:22 #: fittrackee/emails/templates/email_update_to_new_email/body.html:22
@ -85,26 +91,28 @@ msgid ""
"If you're having trouble with the button above, copy and paste the URL " "If you're having trouble with the button above, copy and paste the URL "
"below into your web browser." "below into your web browser."
msgstr "" msgstr ""
"Se stai avendo problemi con il bottone qui sopra, copia ed incolla l'URL qui "
"sotto nel tuo web browser."
#: fittrackee/emails/templates/account_confirmation/body.txt:2 #: fittrackee/emails/templates/account_confirmation/body.txt:2
msgid "Use the link below to confirm your address email." msgid "Use the link below to confirm your address email."
msgstr "" msgstr "Usa il link qui sotto per confermare la tua email."
#: fittrackee/emails/templates/email_update_to_current_email/body.html:2 #: fittrackee/emails/templates/email_update_to_current_email/body.html:2
#: fittrackee/emails/templates/email_update_to_current_email/subject.txt:1 #: fittrackee/emails/templates/email_update_to_current_email/subject.txt:1
msgid "Email changed" msgid "Email changed"
msgstr "" msgstr "Email modificata"
#: fittrackee/emails/templates/email_update_to_current_email/body.html:3 #: fittrackee/emails/templates/email_update_to_current_email/body.html:3
msgid "Your email is being updated." msgid "Your email is being updated."
msgstr "" msgstr "La tua email sta venendo aggiornata."
#: fittrackee/emails/templates/email_update_to_current_email/body.html:4 #: fittrackee/emails/templates/email_update_to_current_email/body.html:4
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:1 #: fittrackee/emails/templates/email_update_to_current_email/body.txt:1
msgid "" msgid ""
"You recently requested to change your email address for your FitTrackee " "You recently requested to change your email address for your FitTrackee "
"account to:" "account to:"
msgstr "" msgstr "Hai richiesto di cambiare la tua mail di FitTrackee in:"
#: fittrackee/emails/templates/email_update_to_current_email/body.html:18 #: fittrackee/emails/templates/email_update_to_current_email/body.html:18
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:4 #: fittrackee/emails/templates/email_update_to_current_email/body.txt:4
@ -112,15 +120,18 @@ msgid ""
"If this email change wasn't initiated by you, please change your password" "If this email change wasn't initiated by you, please change your password"
" immediately or contact your administrator if your account is locked." " immediately or contact your administrator if your account is locked."
msgstr "" msgstr ""
"Se il cambio di email non è stato iniziato da te, per favore cambia "
"immediatamente la tua password o contatta un amministratore se il tuo "
"account è bloccato."
#: fittrackee/emails/templates/email_update_to_new_email/body.html:2 #: fittrackee/emails/templates/email_update_to_new_email/body.html:2
#: fittrackee/emails/templates/email_update_to_new_email/subject.txt:1 #: fittrackee/emails/templates/email_update_to_new_email/subject.txt:1
msgid "Confirm email change" msgid "Confirm email change"
msgstr "" msgstr "Conferma cambio email"
#: fittrackee/emails/templates/email_update_to_new_email/body.html:3 #: fittrackee/emails/templates/email_update_to_new_email/body.html:3
msgid "Use this link to confirm email change." msgid "Use this link to confirm email change."
msgstr "" msgstr "Usa questo link per confermare il cambio dell'email."
#: fittrackee/emails/templates/email_update_to_new_email/body.html:4 #: fittrackee/emails/templates/email_update_to_new_email/body.html:4
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:1 #: fittrackee/emails/templates/email_update_to_new_email/body.txt:1
@ -128,33 +139,37 @@ msgid ""
"You recently requested to change your email address for your FitTrackee " "You recently requested to change your email address for your FitTrackee "
"account." "account."
msgstr "" msgstr ""
"Hai richiesto di recente di cambiare l'indirizzo email associato con il tuo "
"account FitTrackee."
#: fittrackee/emails/templates/email_update_to_new_email/body.html:4 #: fittrackee/emails/templates/email_update_to_new_email/body.html:4
msgid "Use the button below to confirm this address." msgid "Use the button below to confirm this address."
msgstr "" msgstr "Usa il bottone qui sotto per confermare questo indirizzo."
#: fittrackee/emails/templates/email_update_to_new_email/body.html:18 #: fittrackee/emails/templates/email_update_to_new_email/body.html:18
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:7 #: fittrackee/emails/templates/email_update_to_new_email/body.txt:7
msgid "If this email change wasn't initiated by you, please ignore this email." msgid "If this email change wasn't initiated by you, please ignore this email."
msgstr "" msgstr ""
"Se il cambio d'email non è stato iniziato da te, per favore ignora questa "
"mail."
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:2 #: fittrackee/emails/templates/email_update_to_new_email/body.txt:2
msgid "Use the link below to confirm this address." msgid "Use the link below to confirm this address."
msgstr "" msgstr "Usa il link qui in basso per confermare quest'indirizzo."
#: fittrackee/emails/templates/password_change/body.html:2 #: fittrackee/emails/templates/password_change/body.html:2
#: fittrackee/emails/templates/password_change/subject.txt:1 #: fittrackee/emails/templates/password_change/subject.txt:1
msgid "Password changed" msgid "Password changed"
msgstr "" msgstr "Password cambiata"
#: fittrackee/emails/templates/password_change/body.html:3 #: fittrackee/emails/templates/password_change/body.html:3
msgid "Your password has been changed." msgid "Your password has been changed."
msgstr "" msgstr "La tua password è stata cambiata."
#: fittrackee/emails/templates/password_change/body.html:4 #: fittrackee/emails/templates/password_change/body.html:4
#: fittrackee/emails/templates/password_change/body.txt:1 #: fittrackee/emails/templates/password_change/body.txt:1
msgid "The password for your FitTrackee account has been changed." msgid "The password for your FitTrackee account has been changed."
msgstr "" msgstr "La password per il tuo account FitTrackee è stata cambiata."
#: fittrackee/emails/templates/password_change/body.html:5 #: fittrackee/emails/templates/password_change/body.html:5
#: fittrackee/emails/templates/password_change/body.txt:4 #: fittrackee/emails/templates/password_change/body.txt:4
@ -163,11 +178,14 @@ msgid ""
"password immediately or contact your administrator if your account is " "password immediately or contact your administrator if your account is "
"locked." "locked."
msgstr "" msgstr ""
"Se questo cambio di password non è stato iniziato da te, per favore cambia "
"immediatamente la tua password e contatta un amministratore se il tuo "
"account è bloccato."
#: fittrackee/emails/templates/password_reset_request/body.html:2 #: fittrackee/emails/templates/password_reset_request/body.html:2
#: fittrackee/emails/templates/password_reset_request/subject.txt:1 #: fittrackee/emails/templates/password_reset_request/subject.txt:1
msgid "Password reset request" msgid "Password reset request"
msgstr "" msgstr "Richiesta di reset della password"
#: fittrackee/emails/templates/password_reset_request/body.html:3 #: fittrackee/emails/templates/password_reset_request/body.html:3
#, python-format #, python-format
@ -175,33 +193,37 @@ msgid ""
"Use this link to reset your password. The link is only valid for " "Use this link to reset your password. The link is only valid for "
"%(expiration_delay)s." "%(expiration_delay)s."
msgstr "" msgstr ""
"Usa questo link per resettare la password. Il link è valido solo per "
"%(expiration_delay)s."
#: fittrackee/emails/templates/password_reset_request/body.html:4 #: fittrackee/emails/templates/password_reset_request/body.html:4
#: fittrackee/emails/templates/password_reset_request/body.txt:1 #: fittrackee/emails/templates/password_reset_request/body.txt:1
msgid "You recently requested to reset your password for your FitTrackee account." msgid "You recently requested to reset your password for your FitTrackee account."
msgstr "" msgstr ""
"Hai richiesto di recente di resettare la password per il tuo account "
"FitTrackee."
#: fittrackee/emails/templates/password_reset_request/body.html:4 #: fittrackee/emails/templates/password_reset_request/body.html:4
msgid "Use the button below to reset it." msgid "Use the button below to reset it."
msgstr "" msgstr "Usa il bottone qui sotto per resettarla."
#: fittrackee/emails/templates/password_reset_request/body.html:5 #: fittrackee/emails/templates/password_reset_request/body.html:5
#: fittrackee/emails/templates/password_reset_request/body.txt:2 #: fittrackee/emails/templates/password_reset_request/body.txt:2
#, python-format #, python-format
msgid "This password reset link is only valid for %(expiration_delay)s." msgid "This password reset link is only valid for %(expiration_delay)s."
msgstr "" msgstr "Questo link di reset è valido solo per %(expiration_delay)s."
#: fittrackee/emails/templates/password_reset_request/body.html:13 #: fittrackee/emails/templates/password_reset_request/body.html:13
#: fittrackee/emails/templates/password_reset_request/body.txt:4 #: fittrackee/emails/templates/password_reset_request/body.txt:4
msgid "Reset your password" msgid "Reset your password"
msgstr "" msgstr "Resetta password"
#: fittrackee/emails/templates/password_reset_request/body.html:20 #: fittrackee/emails/templates/password_reset_request/body.html:20
#: fittrackee/emails/templates/password_reset_request/body.txt:7 #: fittrackee/emails/templates/password_reset_request/body.txt:7
msgid "If you did not request a password reset, please ignore this email." msgid "If you did not request a password reset, please ignore this email."
msgstr "" msgstr ""
"Se non hai richiesto un reset della password, per favore ignora quest'email."
#: fittrackee/emails/templates/password_reset_request/body.txt:1 #: fittrackee/emails/templates/password_reset_request/body.txt:1
msgid "Use the link below to reset it." msgid "Use the link below to reset it."
msgstr "" msgstr "Usa il link qui sotto per resettarla."

View File

@ -0,0 +1,78 @@
"""update elevation precision
Revision ID: 0f375c44e659
Revises: a8cc0adfe1d3
Create Date: 2022-12-14 18:01:54.662987
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '0f375c44e659'
down_revision = 'a8cc0adfe1d3'
branch_labels = None
depends_on = None
def upgrade():
op.alter_column(
'workouts',
'descent',
existing_type=sa.NUMERIC(precision=7, scale=2),
type_=sa.Numeric(precision=8, scale=3),
existing_nullable=True,
)
op.alter_column(
'workouts',
'ascent',
existing_type=sa.NUMERIC(precision=7, scale=3),
type_=sa.Numeric(precision=8, scale=3),
existing_nullable=True,
)
op.alter_column(
'workout_segments',
'descent',
existing_type=sa.NUMERIC(precision=7, scale=2),
type_=sa.Numeric(precision=8, scale=3),
existing_nullable=True,
)
op.alter_column(
'workout_segments',
'ascent',
existing_type=sa.NUMERIC(precision=7, scale=3),
type_=sa.Numeric(precision=8, scale=3),
existing_nullable=True,
)
def downgrade():
op.alter_column(
'workout_segments',
'ascent',
existing_type=sa.NUMERIC(precision=8, scale=3),
type_=sa.Numeric(precision=7, scale=2),
existing_nullable=True,
)
op.alter_column(
'workout_segments',
'descent',
existing_type=sa.NUMERIC(precision=8, scale=3),
type_=sa.Numeric(precision=7, scale=2),
existing_nullable=True,
)
op.alter_column(
'workouts',
'ascent',
existing_type=sa.NUMERIC(precision=8, scale=3),
type_=sa.Numeric(precision=7, scale=2),
existing_nullable=True,
)
op.alter_column(
'workouts',
'descent',
existing_type=sa.NUMERIC(precision=8, scale=3),
type_=sa.Numeric(precision=7, scale=2),
existing_nullable=True,
)

View File

@ -886,6 +886,49 @@ class TestPostWorkoutWithoutGpx(ApiTestCaseMixin):
assert len(data['data']['workouts']) == 1 assert len(data['data']['workouts']) == 1
assert_workout_data_wo_gpx(data) assert_workout_data_wo_gpx(data)
@pytest.mark.parametrize(
'input_ascent, input_descent',
[
(100, 150),
(0, 150),
(100, 0),
],
)
def test_it_adds_workout_with_ascent_and_descent_when_provided(
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
input_ascent: int,
input_descent: int,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app, user_1.email
)
response = client.post(
'/api/workouts/no_gpx',
content_type='application/json',
data=json.dumps(
dict(
sport_id=1,
duration=3600,
workout_date='2018-05-15 14:05',
distance=10,
ascent=input_ascent,
descent=input_descent,
)
),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
data = json.loads(response.data.decode())
assert response.status_code == 201
assert 'created' in data['status']
assert len(data['data']['workouts']) == 1
assert data['data']['workouts'][0]['ascent'] == input_ascent
assert data['data']['workouts'][0]['descent'] == input_descent
@pytest.mark.parametrize( @pytest.mark.parametrize(
'description,input_data', 'description,input_data',
[ [
@ -940,6 +983,82 @@ class TestPostWorkoutWithoutGpx(ApiTestCaseMixin):
self.assert_400(response) self.assert_400(response)
@pytest.mark.parametrize(
'description,input_data',
[
("only ascent", {"ascent": 100}),
("only descent", {"descent": 150}),
],
)
def test_it_returns_400_when_ascent_or_descent_are_missing(
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
description: str,
input_data: Dict,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app, user_1.email
)
response = client.post(
'/api/workouts/no_gpx',
content_type='application/json',
data=json.dumps(
{
'sport_id': 1,
'duration': 3600,
'workout_date': '2018-05-15 14:05',
'distance': 10,
**input_data,
}
),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
self.assert_400(response)
@pytest.mark.parametrize(
'description,input_data',
[
("ascent is below 0", {"ascent": -100, "descent": 100}),
("descent is below 0", {"ascent": 150, "descent": -100}),
("ascent is None", {"ascent": None, "descent": 100}),
("descent is None", {"ascent": 150, "descent": None}),
("ascent is invalid", {"ascent": "a", "descent": 100}),
("descent is invalid", {"ascent": 150, "descent": "b"}),
],
)
def test_it_returns_400_when_ascent_or_descent_are_invalid(
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
description: str,
input_data: Dict,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app, user_1.email
)
response = client.post(
'/api/workouts/no_gpx',
content_type='application/json',
data=json.dumps(
{
'sport_id': 1,
'duration': 3600,
'workout_date': '2018-05-15 14:05',
'distance': 10,
**input_data,
}
),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
self.assert_400(response)
def test_it_returns_500_if_workout_date_format_is_invalid( def test_it_returns_500_if_workout_date_format_is_invalid(
self, app: Flask, user_1: User, sport_1_cycling: Sport self, app: Flask, user_1: User, sport_1_cycling: Sport
) -> None: ) -> None:

View File

@ -578,6 +578,93 @@ class TestEditWorkoutWithoutGpx(ApiTestCaseMixin):
assert records[3]['workout_date'] == 'Mon, 01 Jan 2018 00:00:00 GMT' assert records[3]['workout_date'] == 'Mon, 01 Jan 2018 00:00:00 GMT'
assert records[3]['value'] == 20.0 assert records[3]['value'] == 20.0
def test_it_updates_ascent_and_descent_values(
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
workout_cycling_user_1: Workout,
) -> None:
workout_short_id = workout_cycling_user_1.short_id
client, auth_token = self.get_test_client_and_auth_token(
app, user_1.email
)
ascent = 10
descent = 0
response = client.patch(
f'/api/workouts/{workout_short_id}',
content_type='application/json',
data=json.dumps(dict(ascent=ascent, descent=descent)),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
data = json.loads(response.data.decode())
assert response.status_code == 200
assert 'success' in data['status']
assert len(data['data']['workouts']) == 1
assert data['data']['workouts'][0]['ascent'] == ascent
assert data['data']['workouts'][0]['descent'] == descent
records = data['data']['workouts'][0]['records']
assert len(records) == 5
assert records[0]['sport_id'] == sport_1_cycling.id
assert records[0]['workout_id'] == workout_short_id
assert records[0]['record_type'] == 'HA'
assert records[0]['workout_date'] == 'Mon, 01 Jan 2018 00:00:00 GMT'
assert records[0]['value'] == ascent
assert records[1]['sport_id'] == sport_1_cycling.id
assert records[1]['workout_id'] == workout_short_id
assert records[1]['record_type'] == 'MS'
assert records[1]['workout_date'] == 'Mon, 01 Jan 2018 00:00:00 GMT'
assert records[1]['value'] == 10.0
assert records[2]['sport_id'] == sport_1_cycling.id
assert records[2]['workout_id'] == workout_short_id
assert records[2]['record_type'] == 'LD'
assert records[2]['workout_date'] == 'Mon, 01 Jan 2018 00:00:00 GMT'
assert records[2]['value'] == '1:00:00'
assert records[3]['sport_id'] == sport_1_cycling.id
assert records[3]['workout_id'] == workout_short_id
assert records[3]['record_type'] == 'FD'
assert records[3]['workout_date'] == 'Mon, 01 Jan 2018 00:00:00 GMT'
assert records[3]['value'] == 10.0
assert records[4]['sport_id'] == sport_1_cycling.id
assert records[4]['workout_id'] == workout_short_id
assert records[4]['record_type'] == 'AS'
assert records[4]['workout_date'] == 'Mon, 01 Jan 2018 00:00:00 GMT'
assert records[4]['value'] == 10.0
def test_it_empties_ascent_and_descent_values(
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
workout_cycling_user_1: Workout,
) -> None:
workout_short_id = workout_cycling_user_1.short_id
client, auth_token = self.get_test_client_and_auth_token(
app, user_1.email
)
workout_cycling_user_1.ascent = 100
workout_cycling_user_1.descent = 150
response = client.patch(
f'/api/workouts/{workout_short_id}',
content_type='application/json',
data=json.dumps(dict(ascent=None, descent=None)),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
data = json.loads(response.data.decode())
assert response.status_code == 200
assert 'success' in data['status']
assert len(data['data']['workouts']) == 1
assert data['data']['workouts'][0]['ascent'] is None
assert data['data']['workouts'][0]['descent'] is None
records = data['data']['workouts'][0]['records']
assert len(records) == 4
assert 'HA' not in [record['record_type'] for record in records]
def test_it_returns_400_if_payload_is_empty( def test_it_returns_400_if_payload_is_empty(
self, self,
app: Flask, app: Flask,
@ -646,3 +733,64 @@ class TestEditWorkoutWithoutGpx(ApiTestCaseMixin):
data = self.assert_404(response) data = self.assert_404(response)
assert len(data['data']['workouts']) == 0 assert len(data['data']['workouts']) == 0
@pytest.mark.parametrize(
'input_ascent, input_descent',
[
(100, None),
(None, 150),
(100, -10),
(-100, 150),
(100, 'O'),
('O', 150),
],
)
def test_it_returns_400_if_ascent_or_descent_are_invalid(
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
workout_cycling_user_1: Workout,
input_ascent: int,
input_descent: int,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app, user_1.email
)
response = client.patch(
f'/api/workouts/{workout_cycling_user_1.short_id}',
content_type='application/json',
data=json.dumps(
dict(
ascent=input_ascent,
descent=input_descent,
)
),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
self.assert_400(response)
@pytest.mark.parametrize(
'input_key',
['ascent', 'descent'],
)
def test_it_returns_400_if_only_one_value_ascent_or_descent_is_provided(
self,
app: Flask,
user_1: User,
sport_1_cycling: Sport,
workout_cycling_user_1: Workout,
input_key: str,
) -> None:
client, auth_token = self.get_test_client_and_auth_token(
app, user_1.email
)
response = client.patch(
f'/api/workouts/{workout_cycling_user_1.short_id}',
content_type='application/json',
data=json.dumps({input_key: 100}),
headers=dict(Authorization=f'Bearer {auth_token}'),
)
self.assert_400(response)

View File

@ -75,6 +75,48 @@ class TestWorkoutModel:
assert serialized_workout['with_gpx'] is False assert serialized_workout['with_gpx'] is False
assert str(serialized_workout['workout_date']) == '2018-01-01 00:00:00' assert str(serialized_workout['workout_date']) == '2018-01-01 00:00:00'
def test_serialize_for_workout_without_gpx_and_with_ascent_and_descent(
self,
app: Flask,
sport_1_cycling: Sport,
user_1: User,
workout_cycling_user_1: Workout,
) -> None:
workout = workout_cycling_user_1
workout.ascent = 0
workout.descent = 10
serialized_workout = workout.serialize()
assert serialized_workout['ascent'] == workout.ascent
assert serialized_workout['ave_speed'] == float(workout.ave_speed)
assert serialized_workout['bounds'] == []
assert 'creation_date' in serialized_workout
assert serialized_workout['descent'] == workout.descent
assert serialized_workout['distance'] == float(workout.distance)
assert serialized_workout['duration'] == str(workout.duration)
assert serialized_workout['id'] == workout.short_id
assert serialized_workout['map'] is None
assert serialized_workout['max_alt'] is None
assert serialized_workout['max_speed'] == float(workout.max_speed)
assert serialized_workout['min_alt'] is None
assert serialized_workout['modification_date'] is not None
assert serialized_workout['moving'] == str(workout.moving)
assert serialized_workout['next_workout'] is None
assert serialized_workout['notes'] is None
assert serialized_workout['pauses'] is None
assert serialized_workout['previous_workout'] is None
assert serialized_workout['records'] == [
record.serialize() for record in workout.records
]
assert serialized_workout['segments'] == []
assert serialized_workout['sport_id'] == workout.sport_id
assert serialized_workout['title'] == workout.title
assert serialized_workout['user'] == workout.user.username
assert serialized_workout['weather_end'] is None
assert serialized_workout['weather_start'] is None
assert serialized_workout['with_gpx'] is False
assert str(serialized_workout['workout_date']) == '2018-01-01 00:00:00'
def test_serialize_for_workout_with_gpx( def test_serialize_for_workout_with_gpx(
self, self,
app: Flask, app: Flask,

View File

@ -148,8 +148,8 @@ class Workout(BaseModel):
distance = db.Column(db.Numeric(6, 3), nullable=True) # kilometers distance = db.Column(db.Numeric(6, 3), nullable=True) # kilometers
min_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters min_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters
max_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters max_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters
descent = db.Column(db.Numeric(7, 2), nullable=True) # meters descent = db.Column(db.Numeric(8, 3), nullable=True) # meters
ascent = db.Column(db.Numeric(7, 2), nullable=True) # meters ascent = db.Column(db.Numeric(8, 3), nullable=True) # meters
max_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h max_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h
ave_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h ave_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h
bounds = db.Column(postgresql.ARRAY(db.Float), nullable=True) bounds = db.Column(postgresql.ARRAY(db.Float), nullable=True)
@ -296,8 +296,10 @@ class Workout(BaseModel):
'distance': float(self.distance) if self.distance else None, 'distance': float(self.distance) if self.distance else None,
'min_alt': float(self.min_alt) if self.min_alt else None, 'min_alt': float(self.min_alt) if self.min_alt else None,
'max_alt': float(self.max_alt) if self.max_alt else None, 'max_alt': float(self.max_alt) if self.max_alt else None,
'descent': float(self.descent) if self.descent else None, 'descent': float(self.descent)
'ascent': float(self.ascent) if self.ascent else None, if self.descent is not None
else None,
'ascent': float(self.ascent) if self.ascent is not None else None,
'max_speed': float(self.max_speed) if self.max_speed else None, 'max_speed': float(self.max_speed) if self.max_speed else None,
'ave_speed': float(self.ave_speed) if self.ave_speed else None, 'ave_speed': float(self.ave_speed) if self.ave_speed else None,
'with_gpx': self.gpx is not None, 'with_gpx': self.gpx is not None,
@ -413,8 +415,8 @@ class WorkoutSegment(BaseModel):
distance = db.Column(db.Numeric(6, 3), nullable=True) # kilometers distance = db.Column(db.Numeric(6, 3), nullable=True) # kilometers
min_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters min_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters
max_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters max_alt = db.Column(db.Numeric(6, 2), nullable=True) # meters
descent = db.Column(db.Numeric(7, 2), nullable=True) # meters descent = db.Column(db.Numeric(8, 3), nullable=True) # meters
ascent = db.Column(db.Numeric(7, 2), nullable=True) # meters ascent = db.Column(db.Numeric(8, 3), nullable=True) # meters
max_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h max_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h
ave_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h ave_speed = db.Column(db.Numeric(6, 2), nullable=True) # km/h

View File

@ -160,6 +160,8 @@ def create_workout(
else float(new_workout.distance) / (duration.seconds / 3600) else float(new_workout.distance) / (duration.seconds / 3600)
) )
new_workout.max_speed = new_workout.ave_speed new_workout.max_speed = new_workout.ave_speed
new_workout.ascent = workout_data.get('ascent')
new_workout.descent = workout_data.get('descent')
return new_workout return new_workout
@ -239,6 +241,12 @@ def edit_workout(
else float(workout.distance) / (workout.duration.seconds / 3600) else float(workout.distance) / (workout.duration.seconds / 3600)
) )
workout.max_speed = workout.ave_speed workout.max_speed = workout.ave_speed
if 'ascent' in workout_data:
workout.ascent = workout_data.get('ascent')
if 'descent' in workout_data:
workout.descent = workout_data.get('descent')
return workout return workout

View File

@ -1132,13 +1132,17 @@ def post_workout_no_gpx(
"status": "success" "status": "success"
} }
:<json string workout_date: workout date, in user timezone :<json float ascent: workout ascent (not mandatory,
(format: ``%Y-%m-%d %H:%M``) must be provided with descent)
:<json float descent: workout descent (not mandatory,
must be provided with ascent)
:<json float distance: workout distance in km :<json float distance: workout distance in km
:<json integer duration: workout duration in seconds :<json integer duration: workout duration in seconds
:<json string notes: notes (not mandatory) :<json string notes: notes (not mandatory)
:<json integer sport_id: workout sport id :<json integer sport_id: workout sport id
:<json string title: workout title :<json string title: workout title (not mandatory)
:<json string workout_date: workout date, in user timezone
(format: ``%Y-%m-%d %H:%M``)
:reqheader Authorization: OAuth 2.0 Bearer Token :reqheader Authorization: OAuth 2.0 Bearer Token
@ -1161,6 +1165,20 @@ def post_workout_no_gpx(
): ):
return InvalidPayloadErrorResponse() return InvalidPayloadErrorResponse()
ascent = workout_data.get('ascent')
descent = workout_data.get('descent')
try:
if (
(ascent is None and descent is not None)
or (ascent is not None and descent is None)
or (
(ascent is not None and descent is not None)
and (float(ascent) < 0 or float(descent) < 0)
)
):
return InvalidPayloadErrorResponse()
except ValueError:
return InvalidPayloadErrorResponse()
try: try:
new_workout = create_workout(auth_user, workout_data) new_workout = create_workout(auth_user, workout_data)
db.session.add(new_workout) db.session.add(new_workout)
@ -1285,9 +1303,10 @@ def update_workout(
:param string workout_short_id: workout short id :param string workout_short_id: workout short id
:<json string workout_date: workout date in user timezone :<json float ascent: workout ascent
(format: ``%Y-%m-%d %H:%M``) (only for workout without gpx, must be provided with descent)
(only for workout without gpx) :<json float descent: workout descent
(only for workout without gpx, must be provided with ascent)
:<json float distance: workout distance in km :<json float distance: workout distance in km
(only for workout without gpx) (only for workout without gpx)
:<json integer duration: workout duration in seconds :<json integer duration: workout duration in seconds
@ -1295,6 +1314,9 @@ def update_workout(
:<json string notes: notes :<json string notes: notes
:<json integer sport_id: workout sport id :<json integer sport_id: workout sport id
:<json string title: workout title :<json string title: workout title
:<json string workout_date: workout date in user timezone
(format: ``%Y-%m-%d %H:%M``)
(only for workout without gpx)
:reqheader Authorization: OAuth 2.0 Bearer Token :reqheader Authorization: OAuth 2.0 Bearer Token
@ -1322,6 +1344,33 @@ def update_workout(
if response_object: if response_object:
return response_object return response_object
if not workout.gpx:
try:
# for workout without gpx file, both elevation values must be
# provided.
if (
(
'ascent' in workout_data
and 'descent' not in workout_data
)
or (
'ascent' not in workout_data
and 'descent' in workout_data
)
) or (
not (
workout_data.get('ascent') is None
and workout_data.get('descent') is None
)
and (
float(workout_data.get('ascent')) < 0
or float(workout_data.get('descent')) < 0
)
):
return InvalidPayloadErrorResponse()
except (TypeError, ValueError):
return InvalidPayloadErrorResponse()
workout = edit_workout(workout, workout_data, auth_user) workout = edit_workout(workout, workout_data, auth_user)
db.session.commit() db.session.commit()
return { return {

View File

@ -1,6 +1,6 @@
{ {
"name": "fittrackee_client", "name": "fittrackee_client",
"version": "0.7.8", "version": "0.7.10",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
@ -20,7 +20,7 @@
"@zxcvbn-ts/language-fr": "^2.2.0", "@zxcvbn-ts/language-fr": "^2.2.0",
"@zxcvbn-ts/language-it": "^2.1.0", "@zxcvbn-ts/language-it": "^2.1.0",
"axios": "^1.2.1", "axios": "^1.2.1",
"chart.js": "^4.0.1", "chart.js": "^4.1.1",
"chartjs-plugin-datalabels": "^2.2.0", "chartjs-plugin-datalabels": "^2.2.0",
"core-js": "^3.26.1", "core-js": "^3.26.1",
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
@ -29,7 +29,7 @@
"linkify-html": "^4.0.2", "linkify-html": "^4.0.2",
"linkifyjs": "^4.0.2", "linkifyjs": "^4.0.2",
"register-service-worker": "^1.7.1", "register-service-worker": "^1.7.1",
"sanitize-html": "^2.7.3", "sanitize-html": "^2.8.0",
"vue": "^3.2.45", "vue": "^3.2.45",
"vue-chart-3": "3.1.1", "vue-chart-3": "3.1.1",
"vue-fullscreen": "^3.1.1", "vue-fullscreen": "^3.1.1",
@ -41,9 +41,9 @@
"@intlify/vue-i18n-loader": "^4.2.0", "@intlify/vue-i18n-loader": "^4.2.0",
"@types/chai": "^4.3.4", "@types/chai": "^4.3.4",
"@types/mocha": "^10.0.1", "@types/mocha": "^10.0.1",
"@types/sanitize-html": "^2.6.2", "@types/sanitize-html": "^2.8.0",
"@typescript-eslint/eslint-plugin": "^5.46.0", "@typescript-eslint/eslint-plugin": "^5.47.0",
"@typescript-eslint/parser": "^5.46.0", "@typescript-eslint/parser": "^5.47.0",
"@vue/cli-plugin-babel": "~5.0.8", "@vue/cli-plugin-babel": "~5.0.8",
"@vue/cli-plugin-eslint": "~5.0.8", "@vue/cli-plugin-eslint": "~5.0.8",
"@vue/cli-plugin-pwa": "~5.0.8", "@vue/cli-plugin-pwa": "~5.0.8",
@ -55,14 +55,14 @@
"@vue/eslint-config-typescript": "^11.0.2", "@vue/eslint-config-typescript": "^11.0.2",
"@vue/test-utils": "^2.2.6", "@vue/test-utils": "^2.2.6",
"chai": "^4.3.7", "chai": "^4.3.7",
"eslint": "8.29.0", "eslint": "8.30.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-typescript": "^3.5.2", "eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.8.0", "eslint-plugin-vue": "^9.8.0",
"prettier": "^2.8.1", "prettier": "^2.8.1",
"sass": "^1.56.2", "sass": "^1.57.1",
"sass-loader": "^13.2.0", "sass-loader": "^13.2.0",
"typescript": "^4.9.4", "typescript": "^4.9.4",
"vue-cli-plugin-i18n": "~2.3.1" "vue-cli-plugin-i18n": "~2.3.1"

View File

@ -114,7 +114,7 @@
/> />
</div> </div>
</div> </div>
<div class="data altitude" v-if="workout && workout.with_gpx"> <div class="data altitude" v-if="hasElevation(workout)">
<i class="fa fa-location-arrow" aria-hidden="true" /> <i class="fa fa-location-arrow" aria-hidden="true" />
<div class="data-values"> <div class="data-values">
+<Distance +<Distance
@ -167,6 +167,10 @@
const locale: ComputedRef<Locale> = computed( const locale: ComputedRef<Locale> = computed(
() => store.getters[ROOT_STORE.GETTERS.LOCALE] () => store.getters[ROOT_STORE.GETTERS.LOCALE]
) )
function hasElevation(workout: IWorkout): boolean {
return workout && workout.ascent !== null && workout.descent !== null
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -37,7 +37,7 @@
</div> </div>
</div> </div>
<div class="form-item"> <div class="form-item">
<label> {{ $t('workouts.SPORT', 1) }}: </label> <label> {{ $t('workouts.SPORT', 1) }}*: </label>
<select <select
id="sport" id="sport"
required required
@ -57,7 +57,7 @@
<div class="form-item" v-if="isCreation && withGpx"> <div class="form-item" v-if="isCreation && withGpx">
<label for="gpxFile"> <label for="gpxFile">
{{ $t('workouts.GPX_FILE') }} {{ $t('workouts.GPX_FILE') }}
{{ $t('workouts.ZIP_ARCHIVE_DESCRIPTION') }}: {{ $t('workouts.ZIP_ARCHIVE_DESCRIPTION') }}*:
</label> </label>
<input <input
id="gpxFile" id="gpxFile"
@ -105,7 +105,7 @@
<div v-if="!withGpx"> <div v-if="!withGpx">
<div class="workout-date-duration"> <div class="workout-date-duration">
<div class="form-item"> <div class="form-item">
<label>{{ $t('workouts.WORKOUT_DATE') }}:</label> <label>{{ $t('workouts.WORKOUT_DATE') }}*:</label>
<div class="workout-date-time"> <div class="workout-date-time">
<input <input
id="workout-date" id="workout-date"
@ -129,7 +129,7 @@
</div> </div>
</div> </div>
<div class="form-item"> <div class="form-item">
<label>{{ $t('workouts.DURATION') }}:</label> <label>{{ $t('workouts.DURATION') }}*:</label>
<div> <div>
<input <input
id="workout-duration-hour" id="workout-duration-hour"
@ -181,23 +181,59 @@
</div> </div>
</div> </div>
</div> </div>
<div class="form-item"> <div class="workout-data">
<label> <div class="form-item">
{{ $t('workouts.DISTANCE') }} ({{ <label>
authUser.imperial_units ? 'mi' : 'km' {{ $t('workouts.DISTANCE') }} ({{
}}): authUser.imperial_units ? 'mi' : 'km'
</label> }})*:
<input </label>
:class="{ errored: isDistanceInvalid() }" <input
name="workout-distance" :class="{ errored: isDistanceInvalid() }"
type="number" name="workout-distance"
min="0" type="number"
step="0.001" min="0"
required step="0.001"
@invalid="invalidateForm" required
:disabled="loading" @invalid="invalidateForm"
v-model="workoutForm.workoutDistance" :disabled="loading"
/> v-model="workoutForm.workoutDistance"
/>
</div>
<div class="form-item">
<label>
{{ $t('workouts.ASCENT') }} ({{
authUser.imperial_units ? 'ft' : 'm'
}}):
</label>
<input
:class="{ errored: isElevationInvalid() }"
name="workout-ascent"
type="number"
min="0"
step="0.01"
@invalid="invalidateForm"
:disabled="loading"
v-model="workoutForm.workoutAscent"
/>
</div>
<div class="form-item">
<label>
{{ $t('workouts.DESCENT') }} ({{
authUser.imperial_units ? 'ft' : 'm'
}}):
</label>
<input
:class="{ errored: isElevationInvalid() }"
name="workout-descent"
type="number"
min="0"
step="0.01"
@invalid="invalidateForm"
:disabled="loading"
v-model="workoutForm.workoutDescent"
/>
</div>
</div> </div>
</div> </div>
<div class="form-item"> <div class="form-item">
@ -305,6 +341,8 @@
workoutDurationMinutes: '', workoutDurationMinutes: '',
workoutDurationSeconds: '', workoutDurationSeconds: '',
workoutDistance: '', workoutDistance: '',
workoutAscent: '',
workoutDescent: '',
}) })
const withGpx = ref( const withGpx = ref(
props.workout.id ? props.workout.with_gpx : props.isCreation props.workout.id ? props.workout.with_gpx : props.isCreation
@ -343,14 +381,30 @@
const duration = workout.duration.split(':') const duration = workout.duration.split(':')
workoutForm.workoutDistance = `${ workoutForm.workoutDistance = `${
authUser.value.imperial_units authUser.value.imperial_units
? convertDistance(workout.distance, 'km', 'mi', 2) ? convertDistance(workout.distance, 'km', 'mi', 3)
: parseFloat(workout.distance.toFixed(2)) : parseFloat(workout.distance.toFixed(3))
}` }`
workoutForm.workoutDate = workoutDateTime.workout_date workoutForm.workoutDate = workoutDateTime.workout_date
workoutForm.workoutTime = workoutDateTime.workout_time workoutForm.workoutTime = workoutDateTime.workout_time
workoutForm.workoutDurationHour = duration[0] workoutForm.workoutDurationHour = duration[0]
workoutForm.workoutDurationMinutes = duration[1] workoutForm.workoutDurationMinutes = duration[1]
workoutForm.workoutDurationSeconds = duration[2] workoutForm.workoutDurationSeconds = duration[2]
workoutForm.workoutAscent =
workout.ascent === null
? ''
: `${
authUser.value.imperial_units
? convertDistance(workout.ascent, 'm', 'ft', 2)
: parseFloat(workout.ascent.toFixed(2))
}`
workoutForm.workoutDescent =
workout.descent === null
? ''
: `${
authUser.value.imperial_units
? convertDistance(workout.descent, 'm', 'ft', 2)
: parseFloat(workout.descent.toFixed(2))
}`
} }
} }
function isDistanceInvalid() { function isDistanceInvalid() {
@ -359,6 +413,11 @@
function isDurationInvalid() { function isDurationInvalid() {
return payloadErrorMessages.value.includes('workouts.INVALID_DURATION') return payloadErrorMessages.value.includes('workouts.INVALID_DURATION')
} }
function isElevationInvalid() {
return payloadErrorMessages.value.includes(
'workouts.INVALID_ASCENT_OR_DESCENT'
)
}
function formatPayload(payload: IWorkoutForm) { function formatPayload(payload: IWorkoutForm) {
payloadErrorMessages.value = [] payloadErrorMessages.value = []
payload.title = workoutForm.title payload.title = workoutForm.title
@ -376,6 +435,24 @@
payloadErrorMessages.value.push('workouts.INVALID_DISTANCE') payloadErrorMessages.value.push('workouts.INVALID_DISTANCE')
} }
payload.workout_date = `${workoutForm.workoutDate} ${workoutForm.workoutTime}` payload.workout_date = `${workoutForm.workoutDate} ${workoutForm.workoutTime}`
payload.ascent =
workoutForm.workoutAscent === ''
? null
: authUser.value.imperial_units
? convertDistance(+workoutForm.workoutAscent, 'ft', 'm', 3)
: +workoutForm.workoutAscent
payload.descent =
workoutForm.workoutDescent === ''
? null
: authUser.value.imperial_units
? convertDistance(+workoutForm.workoutDescent, 'ft', 'm', 3)
: +workoutForm.workoutDescent
if (
(payload.ascent !== null && payload.descent === null) ||
(payload.ascent === null && payload.descent !== null)
) {
payloadErrorMessages.value.push('workouts.INVALID_ASCENT_OR_DESCENT')
}
} }
function updateWorkout() { function updateWorkout() {
const payload: IWorkoutForm = { const payload: IWorkoutForm = {
@ -388,10 +465,17 @@
} else { } else {
formatPayload(payload) formatPayload(payload)
} }
store.dispatch(WORKOUTS_STORE.ACTIONS.EDIT_WORKOUT, { if (payloadErrorMessages.value.length > 0) {
workoutId: props.workout.id, store.commit(
data: payload, ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGES,
}) payloadErrorMessages.value
)
} else {
store.dispatch(WORKOUTS_STORE.ACTIONS.EDIT_WORKOUT, {
workoutId: props.workout.id,
data: payload,
})
}
} else { } else {
if (withGpx.value) { if (withGpx.value) {
if (!gpxFile) { if (!gpxFile) {
@ -536,6 +620,22 @@
} }
} }
} }
.workout-data {
display: flex;
flex-direction: row;
justify-content: space-between;
.form-item {
width: 30%;
}
@media screen and (max-width: $medium-limit) {
flex-direction: column;
.form-item {
width: initial;
}
}
}
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More