Merge branch 'release-v0.6.9'

This commit is contained in:
Sam 2022-07-03 17:37:04 +02:00
commit 78e36f8530
182 changed files with 3838 additions and 2174 deletions

View File

@ -1,5 +1,34 @@
# Change log # Change log
## Version 0.6.9 (2022/07/03)
FitTrackee is now available in German (thanks to @gorgobacka).
And translations can be updated on Weblate.
### Issues Closed
#### Features
* [#200](https://github.com/SamR1/FitTrackee/issues/200) - Detect browser language to use matching translation if available
#### Bugs Fixed
* [PR#208](https://github.com/SamR1/FitTrackee/pull/208) - fix order on records cards
* [#201](https://github.com/SamR1/FitTrackee/issues/201) - html lang attribute is not updated when changing language
#### Translations
* [PR#197](https://github.com/SamR1/FitTrackee/pull/197) - Translations update from Weblate (French)
* [#196](https://github.com/SamR1/FitTrackee/issues/196) - Use translation management tool
* [#190](https://github.com/SamR1/FitTrackee/issues/190) - Add German translation
In this release 4 issues were closed.
Thanks to the contributors:
- @gorgobacka
- J. Lavoie (from Weblate)
## Version 0.6.8 (2022/06/22) ## Version 0.6.8 (2022/06/22)
### Issues Closed ### Issues Closed
@ -16,7 +45,7 @@
Note: it does not affect previously imported files Note: it does not affect previously imported files
* [cc4287e](https://github.com/SamR1/FitTrackee/commit/cc4287ed327faaba268a0c689841d16a7aecc3fb) - Fix docker env file * [cc4287e](https://github.com/SamR1/FitTrackee/commit/cc4287ed327faaba268a0c689841d16a7aecc3fb) - Fix docker env file
In this release 3 issues was closed. In this release 3 issues were closed.
## Version 0.6.7 (2022/06/11) ## Version 0.6.7 (2022/06/11)

View File

@ -17,13 +17,22 @@ First off, thank you for your interest in contributing!
The **GitHub** repository contains: The **GitHub** repository contains:
- source code (note that the repository also includes client build), - source code (note that the repository also includes client build),
- translations,
- tests, - tests,
- documentation (source and build). - documentation (source and build).
Translations can be updated through [Weblate](https://hosted.weblate.org/engage/fittrackee/).
Continuous integration workflows run on **Github Actions** platform (on **push** and **pull requests**). Continuous integration workflows run on **Github Actions** platform (on **push** and **pull requests**).
### Translations
The available languages are:
[![Translation status](https://hosted.weblate.org/widgets/fittrackee/-/multi-auto.svg)](https://hosted.weblate.org/engage/fittrackee/)
Translations files are located:
- on API side (emails): `fittrackee/emails/translations/` (implemented with [Babel](https://babel.pocoo.org/en/latest/))
- on client side: `fittrackee_client/src/locales` (implemented with [Vue I18n](https://vue-i18n.intlify.dev/))
Translations can be updated through [Weblate](https://hosted.weblate.org/engage/fittrackee/).
### How to install FitTrackee ### How to install FitTrackee
@ -62,14 +71,30 @@ Please make your changes from the development branch (`dev`).
$ make test-e2e $ make test-e2e
``` ```
* If needed, update translations.
* On client side, update files in `fittrackee_client/src/locales` folder.
* On API side (emails), to extract new strings into `messages.pot`:
```shell
$ make babel-extract
```
To add new strings in translations files (`fittrackee/emails/translations/<LANG>/LC_MESSAGES/messages.po`):
```shell
$ make babel-update
```
After updating strings in `messages.po`, compile the translations:
```shell
$ make babel-compile
```
* If needed, add or update tests. * If needed, add or update tests.
* If needed, update documentation (no need to build documentation, it will be done when releasing). * If needed, update documentation (no need to build documentation, it will be done when releasing).
* If updated code contains client-side changes, you can generate a build, in a **separate commit** to ease code review (or to easily drop it in case of conflicts when updating your branch). * If updated code contains client-side changes, you can generate javascript assets to check **FitTrackee** whithout starting client dev server:
```shell ```shell
$ make build-client $ make build-client
``` ```
No need to commit these files, dist files will be generated before merging or when releasing.
* Create your pull request to merge on `dev` branch. * Create your pull request to merge on `dev` branch.

View File

@ -6,6 +6,18 @@ make-p:
# Launch all P targets in parallel and exit as soon as one exits. # Launch all P targets in parallel and exit as soon as one exits.
set -m; (for p in $(P); do ($(MAKE) $$p || kill 0)& done; wait) set -m; (for p in $(P); do ($(MAKE) $$p || kill 0)& done; wait)
babel-extract:
$(PYBABEL) extract -F babel.cfg -k lazy_gettext -o messages.pot .
babel-init:
$(PYBABEL) init -i messages.pot -d fittrackee/emails/translations -l $(LANG)
babel-compile:
$(PYBABEL) compile -d fittrackee/emails/translations
babel-update:
$(PYBABEL) update -i messages.pot -d fittrackee/emails/translations
bandit: bandit:
$(BANDIT) -r fittrackee -c pyproject.toml $(BANDIT) -r fittrackee -c pyproject.toml

View File

@ -24,6 +24,7 @@ GUNICORN = $(VENV)/bin/gunicorn
BLACK = $(VENV)/bin/black BLACK = $(VENV)/bin/black
MYPY = $(VENV)/bin/mypy MYPY = $(VENV)/bin/mypy
BANDIT = $(VENV)/bin/bandit BANDIT = $(VENV)/bin/bandit
PYBABEL = $(VENV)/bin/pybabel
FTCLI = $(VENV)/bin/ftcli FTCLI = $(VENV)/bin/ftcli
# Node env # Node env

View File

@ -11,7 +11,7 @@
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
[![pipeline status](https://github.com/SamR1/FitTrackee/actions/workflows/.tests-python.yml/badge.svg)](https://github.com/SamR1/FitTrackee/actions/workflows/.tests-python.yml) [![pipeline status](https://github.com/SamR1/FitTrackee/actions/workflows/.tests-python.yml/badge.svg)](https://github.com/SamR1/FitTrackee/actions/workflows/.tests-python.yml)
[![pipeline status](https://github.com/SamR1/FitTrackee/actions/workflows/.tests-javascript.yml/badge.svg)](https://github.com/SamR1/FitTrackee/actions/workflows/.tests-javascript.yml) [![pipeline status](https://github.com/SamR1/FitTrackee/actions/workflows/.tests-javascript.yml/badge.svg)](https://github.com/SamR1/FitTrackee/actions/workflows/.tests-javascript.yml)
[![translation status](https://hosted.weblate.org/widgets/fittrackee/-/svg-badge.svg)](https://hosted.weblate.org/engage/fittrackee/)
--- ---

View File

@ -1 +1 @@
0.6.8 0.6.9

5
babel.cfg Normal file
View File

@ -0,0 +1,5 @@
[jinja2: fittrackee/emails/templates/**.html]
silent=False
[jinja2: fittrackee/emails/templates/**.txt]
silent=False

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: 99edd56615e14d7cc3e745b909626969 config: be957a0969da3c052862eb24f6a139c9
tags: 645f666f9bcd5a90fca523b33c5a78b7 tags: 645f666f9bcd5a90fca523b33c5a78b7

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 KiB

After

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 KiB

After

Width:  |  Height:  |  Size: 369 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

@ -1,5 +1,34 @@
# Change log # Change log
## Version 0.6.9 (2022/07/03)
FitTrackee is now available in German (thanks to @gorgobacka).
And translations can be updated on Weblate.
### Issues Closed
#### Features
* [#200](https://github.com/SamR1/FitTrackee/issues/200) - Detect browser language to use matching translation if available
#### Bugs Fixed
* [PR#208](https://github.com/SamR1/FitTrackee/pull/208) - fix order on records cards
* [#201](https://github.com/SamR1/FitTrackee/issues/201) - html lang attribute is not updated when changing language
#### Translations
* [PR#197](https://github.com/SamR1/FitTrackee/pull/197) - Translations update from Weblate (French)
* [#196](https://github.com/SamR1/FitTrackee/issues/196) - Use translation management tool
* [#190](https://github.com/SamR1/FitTrackee/issues/190) - Add German translation
In this release 4 issues were closed.
Thanks to the contributors:
- @gorgobacka
- J. Lavoie (from Weblate)
## Version 0.6.8 (2022/06/22) ## Version 0.6.8 (2022/06/22)
### Issues Closed ### Issues Closed
@ -16,7 +45,7 @@
Note: it does not affect previously imported files Note: it does not affect previously imported files
* [cc4287e](https://github.com/SamR1/FitTrackee/commit/cc4287ed327faaba268a0c689841d16a7aecc3fb) - Fix docker env file * [cc4287e](https://github.com/SamR1/FitTrackee/commit/cc4287ed327faaba268a0c689841d16a7aecc3fb) - Fix docker env file
In this release 3 issues was closed. In this release 3 issues were closed.
## Version 0.6.7 (2022/06/11) ## Version 0.6.7 (2022/06/11)

View File

@ -60,6 +60,7 @@ Workouts
Account & preferences Account & preferences
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
- A user can create, update and deleted his account. - A user can create, update and deleted his account.
- On registration, the user account is created with selected language in dropdown as user preference (*new in 0.6.9*).
- After registration, the user account is inactive and an email with confirmation instructions is sent to activate it. - After registration, the user account is inactive and an email with confirmation instructions is sent to activate it.
A user with an inactive account cannot log in. (*new in 0.6.0*) A user with an inactive account cannot log in. (*new in 0.6.0*)
@ -119,7 +120,9 @@ Administration
Translations Translations
^^^^^^^^^^^^ ^^^^^^^^^^^^
FitTrackee is available in English and French (which can be saved in the user preferences). FitTrackee is available in the following languages (which can be saved in the user preferences):
.. figure:: https://hosted.weblate.org/widgets/fittrackee/-/multi-auto.svg
Screenshots Screenshots

View File

@ -95,9 +95,9 @@ deployment method.
.. versionadded:: 0.4.0 .. versionadded:: 0.4.0
Directory containing uploaded files. **Absolute path** to the directory where `uploads` folder will be created.
:default: `fittrackee/uploads/` :default: `<application_directory>/fittrackee`
.. danger:: .. danger::
| With installation from PyPI, the directory will be located in | With installation from PyPI, the directory will be located in
@ -395,13 +395,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.6.8): - Download the last release (for now, it is the release v0.6.9):
.. code:: bash .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.6.9.tar.gz
$ tar -xzf v0.6.8.tar.gz $ tar -xzf v0.6.9.tar.gz
$ mv FitTrackee-0.6.8 FitTrackee $ mv FitTrackee-0.6.9 FitTrackee
$ cd FitTrackee $ cd FitTrackee
- Create **.env** from example and update it - Create **.env** from example and update it
@ -521,13 +521,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.6.8) and overwrite existing files: - Download the last release (for now, it is the release v0.6.9) and overwrite existing files:
.. code:: bash .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.6.9.tar.gz
$ tar -xzf v0.6.8.tar.gz $ tar -xzf v0.6.9.tar.gz
$ cp -R FitTrackee-0.6.8/* FitTrackee/ $ cp -R FitTrackee-0.6.9/* 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

@ -20,3 +20,9 @@ Administrator
fittrackee.emails.exceptions.InvalidEmailUrlScheme fittrackee.emails.exceptions.InvalidEmailUrlScheme
A valid ``EMAIL_URL`` must be provided (see `emails <../installation.html#emails>`__). A valid ``EMAIL_URL`` must be provided (see `emails <../installation.html#emails>`__).
`Map images are not displayed but map is shown in Workout detail`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Check the path in `environment variables <../installation.html#envvar-UPLOAD_FOLDER>`__. ``UPLOAD_FOLDER`` must be set with an absolute path.

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.6.8', VERSION: '0.6.9',
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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Authentication &#8212; FitTrackee 0.6.8 <title>Authentication &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</div> </div>
@ -170,6 +170,8 @@ to activate it.</p>
<li><p><strong>username</strong> (<em>string</em>) username (3 to 30 characters required)</p></li> <li><p><strong>username</strong> (<em>string</em>) username (3 to 30 characters required)</p></li>
<li><p><strong>email</strong> (<em>string</em>) user email</p></li> <li><p><strong>email</strong> (<em>string</em>) user email</p></li>
<li><p><strong>password</strong> (<em>string</em>) password (8 characters required)</p></li> <li><p><strong>password</strong> (<em>string</em>) password (8 characters required)</p></li>
<li><p><strong>lang</strong> (<em>string</em>) user language preferences (if not provided or invalid,
fallback to en (english))</p></li>
</ul> </ul>
</dd> </dd>
<dt class="field-even">Status Codes<span class="colon">:</span></dt> <dt class="field-even">Status Codes<span class="colon">:</span></dt>

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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Configuration &#8212; FitTrackee 0.6.8 <title>Configuration &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</div> </div>
@ -152,7 +152,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.6.8&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.6.9&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>
@ -192,7 +192,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.6.8&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.6.9&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>

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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>API documentation &#8212; FitTrackee 0.6.8 <title>API documentation &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Records &#8212; FitTrackee 0.6.8 <title>Records &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Sports &#8212; FitTrackee 0.6.8 <title>Sports &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Statistics &#8212; FitTrackee 0.6.8 <title>Statistics &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Users &#8212; FitTrackee 0.6.8 <title>Users &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Workouts &#8212; FitTrackee 0.6.8 <title>Workouts &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Command line interface &#8212; FitTrackee 0.6.8 <title>Command line interface &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Features &#8212; FitTrackee 0.6.8 <title>Features &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</div> </div>
@ -235,6 +235,7 @@
<h2>Account &amp; preferences<a class="headerlink" href="#account-preferences" title="Permalink to this heading"></a></h2> <h2>Account &amp; preferences<a class="headerlink" href="#account-preferences" title="Permalink to this heading"></a></h2>
<ul class="simple"> <ul class="simple">
<li><p>A user can create, update and deleted his account.</p></li> <li><p>A user can create, update and deleted his account.</p></li>
<li><p>On registration, the user account is created with selected language in dropdown as user preference (<em>new in 0.6.9</em>).</p></li>
<li><p>After registration, the user account is inactive and an email with confirmation instructions is sent to activate it. <li><p>After registration, the user account is inactive and an email with confirmation instructions is sent to activate it.
A user with an inactive account cannot log in. (<em>new in 0.6.0</em>)</p></li> A user with an inactive account cannot log in. (<em>new in 0.6.0</em>)</p></li>
</ul> </ul>
@ -313,7 +314,9 @@ A user with an inactive account cannot log in. (<em>new in 0.6.0</em>)</p></li>
</section> </section>
<section id="translations"> <section id="translations">
<h2>Translations<a class="headerlink" href="#translations" title="Permalink to this heading"></a></h2> <h2>Translations<a class="headerlink" href="#translations" title="Permalink to this heading"></a></h2>
<p>FitTrackee is available in English and French (which can be saved in the user preferences).</p> <p>FitTrackee is available in the following languages (which can be saved in the user preferences):</p>
<figure class="align-default">
<img alt="https://hosted.weblate.org/widgets/fittrackee/-/multi-auto.svg" src="https://hosted.weblate.org/widgets/fittrackee/-/multi-auto.svg" /></figure>
</section> </section>
<section id="screenshots"> <section id="screenshots">
<h2>Screenshots<a class="headerlink" href="#screenshots" title="Permalink to this heading"></a></h2> <h2>Screenshots<a class="headerlink" href="#screenshots" title="Permalink to this heading"></a></h2>

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.6.8 <title>Index &#8212; FitTrackee 0.6.9
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" />
@ -38,7 +38,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.6.8 <title>HTTP Routing Table &#8212; FitTrackee 0.6.9
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" />
@ -45,7 +45,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>FitTrackee &#8212; FitTrackee 0.6.8 <title>FitTrackee &#8212; FitTrackee 0.6.9
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="#"> <a class="navbar-brand" href="#">
FitTrackee</a> FitTrackee</a>
<span class="navbar-text navbar-version pull-left"><b>0.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Installation &#8212; FitTrackee 0.6.8 <title>Installation &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</div> </div>
@ -294,10 +294,10 @@ deployment method.</p>
<dd><div class="versionadded"> <dd><div class="versionadded">
<p><span class="versionmodified added">New in version 0.4.0.</span></p> <p><span class="versionmodified added">New in version 0.4.0.</span></p>
</div> </div>
<p>Directory containing uploaded files.</p> <p><strong>Absolute path</strong> to the directory where <cite>uploads</cite> folder will be created.</p>
<dl class="field-list simple"> <dl class="field-list simple">
<dt class="field-odd">Default<span class="colon">:</span></dt> <dt class="field-odd">Default<span class="colon">:</span></dt>
<dd class="field-odd"><p><cite>fittrackee/uploads/</cite></p> <dd class="field-odd"><p><cite>&lt;application_directory&gt;/fittrackee</cite></p>
</dd> </dd>
</dl> </dl>
<div class="admonition danger"> <div class="admonition danger">
@ -675,11 +675,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.6.8):</p></li> <li><p>Download the last release (for now, it is the release v0.6.9):</p></li>
</ul> </ul>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.9.tar.gz
$ tar -xzf v0.6.8.tar.gz $ tar -xzf v0.6.9.tar.gz
$ mv FitTrackee-0.6.8 FitTrackee $ mv FitTrackee-0.6.9 FitTrackee
$ <span class="nb">cd</span> FitTrackee $ <span class="nb">cd</span> FitTrackee
</pre></div> </pre></div>
</div> </div>
@ -799,11 +799,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.6.8) and overwrite existing files:</p></li> <li><p>Download the last release (for now, it is the release v0.6.9) 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.6.8.tar.gz <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.9.tar.gz
$ tar -xzf v0.6.8.tar.gz $ tar -xzf v0.6.9.tar.gz
$ cp -R FitTrackee-0.6.8/* FitTrackee/ $ cp -R FitTrackee-0.6.9/* FitTrackee/
$ <span class="nb">cd</span> FitTrackee $ <span class="nb">cd</span> FitTrackee
</pre></div> </pre></div>
</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.6.8 <title>Search &#8212; FitTrackee 0.6.9
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" />
@ -45,7 +45,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Administrator &#8212; FitTrackee 0.6.8 <title>Administrator &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</div> </div>
@ -81,6 +81,7 @@
aria-labelledby="dLabelLocalToc"><ul> aria-labelledby="dLabelLocalToc"><ul>
<li><a class="reference internal" href="#">Administrator</a><ul> <li><a class="reference internal" href="#">Administrator</a><ul>
<li><a class="reference internal" href="#fittrackee-fails-to-start"><cite>FitTrackee fails to start</cite></a></li> <li><a class="reference internal" href="#fittrackee-fails-to-start"><cite>FitTrackee fails to start</cite></a></li>
<li><a class="reference internal" href="#map-images-are-not-displayed-but-map-is-shown-in-workout-detail"><cite>Map images are not displayed but map is shown in Workout detail</cite></a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
@ -149,6 +150,12 @@
</li> </li>
</ul> </ul>
</section> </section>
<section id="map-images-are-not-displayed-but-map-is-shown-in-workout-detail">
<h2><cite>Map images are not displayed but map is shown in Workout detail</cite><a class="headerlink" href="#map-images-are-not-displayed-but-map-is-shown-in-workout-detail" title="Permalink to this heading"></a></h2>
<ul class="simple">
<li><p>Check the path in <a class="reference external" href="../installation.html#envvar-UPLOAD_FOLDER">environment variables</a>. <code class="docutils literal notranslate"><span class="pre">UPLOAD_FOLDER</span></code> must be set with an absolute path.</p></li>
</ul>
</section>
</section> </section>

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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>Troubleshooting &#8212; FitTrackee 0.6.8 <title>Troubleshooting &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</div> </div>
@ -133,6 +133,7 @@
<ul> <ul>
<li class="toctree-l1"><a class="reference internal" href="administrator.html">Administrator</a><ul> <li class="toctree-l1"><a class="reference internal" href="administrator.html">Administrator</a><ul>
<li class="toctree-l2"><a class="reference internal" href="administrator.html#fittrackee-fails-to-start"><cite>FitTrackee fails to start</cite></a></li> <li class="toctree-l2"><a class="reference internal" href="administrator.html#fittrackee-fails-to-start"><cite>FitTrackee fails to start</cite></a></li>
<li class="toctree-l2"><a class="reference internal" href="administrator.html#map-images-are-not-displayed-but-map-is-shown-in-workout-detail"><cite>Map images are not displayed but map is shown in Workout detail</cite></a></li>
</ul> </ul>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="user.html">User</a></li> <li class="toctree-l1"><a class="reference internal" href="user.html">User</a></li>

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.18.1: http://docutils.sourceforge.net/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
<title>User &#8212; FitTrackee 0.6.8 <title>User &#8212; FitTrackee 0.6.9
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" />
@ -41,7 +41,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.6.8 <span class="navbar-text navbar-version pull-left"><b>0.6.9
</b></span> </b></span>
</div> </div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 KiB

After

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 KiB

After

Width:  |  Height:  |  Size: 369 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

@ -60,6 +60,7 @@ Workouts
Account & preferences Account & preferences
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
- A user can create, update and deleted his account. - A user can create, update and deleted his account.
- On registration, the user account is created with selected language in dropdown as user preference (*new in 0.6.9*).
- After registration, the user account is inactive and an email with confirmation instructions is sent to activate it. - After registration, the user account is inactive and an email with confirmation instructions is sent to activate it.
A user with an inactive account cannot log in. (*new in 0.6.0*) A user with an inactive account cannot log in. (*new in 0.6.0*)
@ -119,7 +120,9 @@ Administration
Translations Translations
^^^^^^^^^^^^ ^^^^^^^^^^^^
FitTrackee is available in English and French (which can be saved in the user preferences). FitTrackee is available in the following languages (which can be saved in the user preferences):
.. figure:: https://hosted.weblate.org/widgets/fittrackee/-/multi-auto.svg
Screenshots Screenshots

View File

@ -95,9 +95,9 @@ deployment method.
.. versionadded:: 0.4.0 .. versionadded:: 0.4.0
Directory containing uploaded files. **Absolute path** to the directory where `uploads` folder will be created.
:default: `fittrackee/uploads/` :default: `<application_directory>/fittrackee`
.. danger:: .. danger::
| With installation from PyPI, the directory will be located in | With installation from PyPI, the directory will be located in
@ -395,13 +395,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.6.8): - Download the last release (for now, it is the release v0.6.9):
.. code:: bash .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.6.9.tar.gz
$ tar -xzf v0.6.8.tar.gz $ tar -xzf v0.6.9.tar.gz
$ mv FitTrackee-0.6.8 FitTrackee $ mv FitTrackee-0.6.9 FitTrackee
$ cd FitTrackee $ cd FitTrackee
- Create **.env** from example and update it - Create **.env** from example and update it
@ -521,13 +521,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.6.8) and overwrite existing files: - Download the last release (for now, it is the release v0.6.9) and overwrite existing files:
.. code:: bash .. code:: bash
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz $ wget https://github.com/SamR1/FitTrackee/archive/v0.6.9.tar.gz
$ tar -xzf v0.6.8.tar.gz $ tar -xzf v0.6.9.tar.gz
$ cp -R FitTrackee-0.6.8/* FitTrackee/ $ cp -R FitTrackee-0.6.9/* 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

@ -20,3 +20,9 @@ Administrator
fittrackee.emails.exceptions.InvalidEmailUrlScheme fittrackee.emails.exceptions.InvalidEmailUrlScheme
A valid ``EMAIL_URL`` must be provided (see `emails <../installation.html#emails>`__). A valid ``EMAIL_URL`` must be provided (see `emails <../installation.html#emails>`__).
`Map images are not displayed but map is shown in Workout detail`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Check the path in `environment variables <../installation.html#envvar-UPLOAD_FOLDER>`__. ``UPLOAD_FOLDER`` must be set with an absolute path.

View File

@ -1,3 +1,5 @@
from selenium.webdriver.common.by import By
from .utils import TEST_URL from .utils import TEST_URL
@ -9,7 +11,7 @@ class TestIndex:
def test_navbar_contains_all_links(self, selenium): def test_navbar_contains_all_links(self, selenium):
selenium.get(TEST_URL) selenium.get(TEST_URL)
nav = selenium.find_element_by_id('nav').text nav = selenium.find_element(By.ID, 'nav').text
assert "FitTrackee" in nav assert "FitTrackee" in nav
assert "Login" in nav assert "Login" in nav
assert "Register" in nav assert "Register" in nav

View File

@ -1,3 +1,5 @@
from selenium.webdriver.common.by import By
from .utils import TEST_URL, login_valid_user, register_valid_user_and_logout from .utils import TEST_URL, login_valid_user, register_valid_user_and_logout
URL = f'{TEST_URL}/login' URL = f'{TEST_URL}/login'
@ -7,24 +9,24 @@ class TestLogin:
def test_navbar_contains_login(self, selenium): def test_navbar_contains_login(self, selenium):
selenium.get(URL) selenium.get(URL)
nav = selenium.find_element_by_id('nav').text nav = selenium.find_element(By.ID, 'nav').text
assert 'Login' in nav assert 'Login' in nav
def test_it_displays_login_form(self, selenium): def test_it_displays_login_form(self, selenium):
selenium.get(URL) selenium.get(URL)
inputs = selenium.find_elements_by_tag_name('input') inputs = selenium.find_elements(By.TAG_NAME, 'input')
assert len(inputs) == 2 assert len(inputs) == 2
assert inputs[0].get_attribute('id') == 'email' assert inputs[0].get_attribute('id') == 'email'
assert inputs[0].get_attribute('type') == 'email' assert inputs[0].get_attribute('type') == 'email'
assert inputs[1].get_attribute('id') == 'password' assert inputs[1].get_attribute('id') == 'password'
assert inputs[1].get_attribute('type') == 'password' assert inputs[1].get_attribute('type') == 'password'
button = selenium.find_element_by_tag_name('button') button = selenium.find_element(By.TAG_NAME, 'button')
assert button.get_attribute('type') == 'submit' assert button.get_attribute('type') == 'submit'
assert 'Log in' in button.text assert 'Log in' in button.text
links = selenium.find_elements_by_class_name('links') links = selenium.find_elements(By.CLASS_NAME, 'links')
assert links[0].tag_name == 'a' assert links[0].tag_name == 'a'
assert 'Register' in links[0].text assert 'Register' in links[0].text
assert links[1].tag_name == 'a' assert links[1].tag_name == 'a'
@ -37,7 +39,7 @@ class TestLogin:
login_valid_user(selenium, user) login_valid_user(selenium, user)
nav = selenium.find_element_by_id('nav').text nav = selenium.find_element(By.ID, 'nav').text
assert 'Register' not in nav assert 'Register' not in nav
assert 'Login' not in nav assert 'Login' not in nav
assert 'Dashboard' in nav assert 'Dashboard' in nav

View File

@ -1,16 +1,18 @@
from selenium.webdriver.common.by import By
from .utils import register_valid_user from .utils import register_valid_user
class TestLogout: class TestLogout:
def test_user_can_log_out(self, selenium): def test_user_can_log_out(self, selenium):
user = register_valid_user(selenium) user = register_valid_user(selenium)
user_menu = selenium.find_element_by_class_name('nav-items-user-menu') user_menu = selenium.find_element(By.CLASS_NAME, 'nav-items-user-menu')
logout_link = user_menu.find_elements_by_class_name('nav-item')[2] logout_link = user_menu.find_elements(By.CLASS_NAME, 'nav-item')[2]
logout_link.click() logout_link.click()
selenium.implicitly_wait(1) selenium.implicitly_wait(1)
nav = selenium.find_element_by_id('nav').text nav = selenium.find_element(By.ID, 'nav').text
assert 'Register' in nav assert 'Register' in nav
assert 'Login' in nav assert 'Login' in nav
assert user['username'] not in nav assert user['username'] not in nav

View File

@ -1,3 +1,5 @@
from selenium.webdriver.common.by import By
from .utils import register_valid_user from .utils import register_valid_user
@ -5,18 +7,18 @@ class TestProfile:
def test_it_displays_user_profile(self, selenium): def test_it_displays_user_profile(self, selenium):
user = register_valid_user(selenium) user = register_valid_user(selenium)
app_menu = selenium.find_element_by_class_name('nav-items-user-menu') app_menu = selenium.find_element(By.CLASS_NAME, 'nav-items-user-menu')
profile_link = app_menu.find_elements_by_class_name('nav-item')[1] profile_link = app_menu.find_elements(By.CLASS_NAME, 'nav-item')[1]
profile_link.click() profile_link.click()
selenium.implicitly_wait(1) selenium.implicitly_wait(1)
user_header = selenium.find_element_by_class_name('user-header') user_header = selenium.find_element(By.CLASS_NAME, 'user-header')
assert user['username'] in user_header.text assert user['username'] in user_header.text
assert '0\nworkouts' in user_header.text assert '0\nworkouts' in user_header.text
assert '0\nkm' in user_header.text assert '0\nkm' in user_header.text
assert '0\nsports' in user_header.text assert '0\nsports' in user_header.text
user_infos = selenium.find_element_by_id('user-infos') user_infos = selenium.find_element(By.ID, 'user-infos')
assert 'Registration date' in user_infos.text assert 'Registration date' in user_infos.text
assert 'First name' in user_infos.text assert 'First name' in user_infos.text
assert 'Last name' in user_infos.text assert 'Last name' in user_infos.text

View File

@ -1,3 +1,5 @@
from selenium.webdriver.common.by import By
from .utils import ( from .utils import (
TEST_URL, TEST_URL,
random_string, random_string,
@ -13,7 +15,7 @@ class TestRegistration:
selenium.get(URL) selenium.get(URL)
selenium.implicitly_wait(1) selenium.implicitly_wait(1)
inputs = selenium.find_elements_by_tag_name('input') inputs = selenium.find_elements(By.TAG_NAME, 'input')
assert len(inputs) == 4 assert len(inputs) == 4
assert inputs[0].get_attribute('id') == 'username' assert inputs[0].get_attribute('id') == 'username'
assert inputs[0].get_attribute('type') == 'text' assert inputs[0].get_attribute('type') == 'text'
@ -22,7 +24,7 @@ class TestRegistration:
assert inputs[2].get_attribute('id') == 'password' assert inputs[2].get_attribute('id') == 'password'
assert inputs[2].get_attribute('type') == 'password' assert inputs[2].get_attribute('type') == 'password'
form_infos = selenium.find_elements_by_class_name('form-info') form_infos = selenium.find_elements(By.CLASS_NAME, 'form-info')
assert len(form_infos) == 3 assert len(form_infos) == 3
assert form_infos[0].text == ( assert form_infos[0].text == (
'3 to 30 characters required, only alphanumeric characters and ' '3 to 30 characters required, only alphanumeric characters and '
@ -31,11 +33,11 @@ class TestRegistration:
assert form_infos[1].text == 'Enter a valid email address.' assert form_infos[1].text == 'Enter a valid email address.'
assert form_infos[2].text == 'At least 8 characters required.' assert form_infos[2].text == 'At least 8 characters required.'
button = selenium.find_element_by_tag_name('button') button = selenium.find_element(By.TAG_NAME, 'button')
assert button.get_attribute('type') == 'submit' assert button.get_attribute('type') == 'submit'
assert 'Register' in button.text assert 'Register' in button.text
links = selenium.find_elements_by_class_name('links') links = selenium.find_elements(By.CLASS_NAME, 'links')
assert links[0].tag_name == 'a' assert links[0].tag_name == 'a'
assert 'Login' in links[0].text assert 'Login' in links[0].text
assert links[1].tag_name == 'a' assert links[1].tag_name == 'a'
@ -50,7 +52,7 @@ class TestRegistration:
register(selenium, user) register(selenium, user)
message = selenium.find_element_by_class_name('success-message').text message = selenium.find_element(By.CLASS_NAME, 'success-message').text
assert ( assert (
'A link to activate your account has been ' 'A link to activate your account has been '
'emailed to the address provided.' 'emailed to the address provided.'
@ -67,7 +69,7 @@ class TestRegistration:
register(selenium, user_infos) register(selenium, user_infos)
assert selenium.current_url == URL assert selenium.current_url == URL
nav = selenium.find_element_by_id('nav').text nav = selenium.find_element(By.ID, 'nav').text
assert 'Register' in nav assert 'Register' in nav
assert 'Login' in nav assert 'Login' in nav
@ -80,7 +82,7 @@ class TestRegistration:
register(selenium, user) register(selenium, user)
assert selenium.current_url == URL assert selenium.current_url == URL
errors = selenium.find_element_by_class_name('error-message').text errors = selenium.find_element(By.CLASS_NAME, 'error-message').text
assert 'Sorry, that username is already taken.' in errors assert 'Sorry, that username is already taken.' in errors
def test_user_does_not_return_error_if_email_is_already_taken( def test_user_does_not_return_error_if_email_is_already_taken(
@ -92,7 +94,7 @@ class TestRegistration:
register(selenium, user) register(selenium, user)
assert selenium.current_url == f'{TEST_URL}/login' assert selenium.current_url == f'{TEST_URL}/login'
message = selenium.find_element_by_class_name('success-message').text message = selenium.find_element(By.CLASS_NAME, 'success-message').text
assert ( assert (
'A link to activate your account has been ' 'A link to activate your account has been '
'emailed to the address provided.' 'emailed to the address provided.'

View File

@ -1,3 +1,4 @@
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select, WebDriverWait from selenium.webdriver.support.ui import Select, WebDriverWait
@ -7,36 +8,36 @@ from .utils import TEST_URL, register_valid_user
class TestWorkout: class TestWorkout:
def test_user_can_add_workout_without_gpx(self, selenium): def test_user_can_add_workout_without_gpx(self, selenium):
register_valid_user(selenium) register_valid_user(selenium)
app_menu = selenium.find_element_by_class_name('nav-items-app-menu') app_menu = selenium.find_element(By.CLASS_NAME, 'nav-items-app-menu')
add_workout_link = app_menu.find_elements_by_class_name('nav-item')[3] add_workout_link = app_menu.find_elements(By.CLASS_NAME, 'nav-item')[3]
add_workout_link.click() add_workout_link.click()
selenium.implicitly_wait(1) selenium.implicitly_wait(1)
radio_button = selenium.find_element_by_id('withoutGpx') radio_button = selenium.find_element(By.ID, 'withoutGpx')
radio_button.click() radio_button.click()
select = Select(selenium.find_element_by_id('sport')) select = Select(selenium.find_element(By.ID, 'sport'))
select.select_by_index(1) select.select_by_index(1)
selenium.find_element_by_name('title').send_keys('Workout title') selenium.find_element(By.NAME, 'title').send_keys('Workout title')
selenium.find_element_by_name('workout-date').send_keys('2018-12-20') selenium.find_element(By.NAME, 'workout-date').send_keys('2018-12-20')
selenium.find_element_by_name('workout-time').send_keys('14:05') selenium.find_element(By.NAME, 'workout-time').send_keys('14:05')
selenium.find_element_by_name('workout-duration-hour').send_keys('01') selenium.find_element(By.NAME, 'workout-duration-hour').send_keys('01')
selenium.find_element_by_name('workout-duration-minutes').send_keys( selenium.find_element(By.NAME, 'workout-duration-minutes').send_keys(
'00' '00'
) )
selenium.find_element_by_name('workout-duration-seconds').send_keys( selenium.find_element(By.NAME, 'workout-duration-seconds').send_keys(
'00' '00'
) )
selenium.find_element_by_name('workout-distance').send_keys('10') selenium.find_element(By.NAME, 'workout-distance').send_keys('10')
confirm_button = selenium.find_element_by_class_name('confirm') confirm_button = selenium.find_element(By.CLASS_NAME, 'confirm')
confirm_button.click() confirm_button.click()
WebDriverWait(selenium, 10).until( WebDriverWait(selenium, 10).until(
EC.url_changes(f"{TEST_URL}/workouts/add") EC.url_changes(f"{TEST_URL}/workouts/add")
) )
workout_details = selenium.find_element_by_id('workout-info').text workout_details = selenium.find_element(By.ID, 'workout-info').text
assert 'Duration: 1:00:00' in workout_details assert 'Duration: 1:00:00' in workout_details
assert 'Distance: 10 km' in workout_details assert 'Distance: 10 km' in workout_details
assert 'Average Speed: 10 km/h' in workout_details assert 'Average Speed: 10 km/h' in workout_details

View File

@ -5,6 +5,7 @@ import string
import time import time
import requests import requests
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from urllib3.util import parse_url from urllib3.util import parse_url
@ -25,24 +26,24 @@ def random_string(length=8):
def register(selenium, user): def register(selenium, user):
selenium.get(f'{TEST_URL}/register') selenium.get(f'{TEST_URL}/register')
selenium.implicitly_wait(1) selenium.implicitly_wait(1)
username = selenium.find_element_by_id('username') username = selenium.find_element(By.ID, 'username')
username.send_keys(user.get('username')) username.send_keys(user.get('username'))
email = selenium.find_element_by_id('email') email = selenium.find_element(By.ID, 'email')
email.send_keys(user.get('email')) email.send_keys(user.get('email'))
password = selenium.find_element_by_id('password') password = selenium.find_element(By.ID, 'password')
password.send_keys(user.get('password')) password.send_keys(user.get('password'))
submit_button = selenium.find_element_by_tag_name('button') submit_button = selenium.find_element(By.TAG_NAME, 'button')
submit_button.click() submit_button.click()
def login(selenium, user): def login(selenium, user):
selenium.get(f'{TEST_URL}/login') selenium.get(f'{TEST_URL}/login')
selenium.implicitly_wait(1) selenium.implicitly_wait(1)
email = selenium.find_element_by_id('email') email = selenium.find_element(By.ID, 'email')
email.send_keys(user.get('email')) email.send_keys(user.get('email'))
password = selenium.find_element_by_id('password') password = selenium.find_element(By.ID, 'password')
password.send_keys(user.get('password')) password.send_keys(user.get('password'))
submit_button = selenium.find_element_by_tag_name('button') submit_button = selenium.find_element(By.TAG_NAME, 'button')
submit_button.click() submit_button.click()
@ -61,8 +62,8 @@ def register_valid_user(selenium):
def register_valid_user_and_logout(selenium): def register_valid_user_and_logout(selenium):
user = register_valid_user(selenium) user = register_valid_user(selenium)
user_menu = selenium.find_element_by_class_name('nav-items-user-menu') user_menu = selenium.find_element(By.CLASS_NAME, 'nav-items-user-menu')
logout_link = user_menu.find_elements_by_class_name('nav-item')[2] logout_link = user_menu.find_elements(By.CLASS_NAME, 'nav-item')[2]
logout_link.click() logout_link.click()
return user return user

View File

@ -20,7 +20,7 @@ from sqlalchemy.exc import ProgrammingError
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.6.8' VERSION = __version__ = '0.6.9'
db = SQLAlchemy() db = SQLAlchemy()
bcrypt = Bcrypt() bcrypt = Bcrypt()
migrate = Migrate() migrate = Migrate()

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.6.8" "version": "0.6.9"
}, },
"status": "success" "status": "success"
} }
@ -98,7 +98,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.6.8" "version": "0.6.9"
}, },
"status": "success" "status": "success"
} }

View File

@ -46,6 +46,10 @@ class BaseConfig:
os.environ.get('DEFAULT_STATICMAP', 'False') == 'True' os.environ.get('DEFAULT_STATICMAP', 'False') == 'True'
), ),
} }
TRANSLATIONS_FOLDER = os.path.join(
current_app.root_path, 'emails/translations'
)
LANGUAGES = ['en', 'fr', 'de']
class DevelopmentConfig(BaseConfig): class DevelopmentConfig(BaseConfig):

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.87c31c45.js"></script><script defer="defer" src="/static/js/app.f559f6b1.js"></script><link href="/static/css/app.0bee5448.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.7123d468.js"></script><script defer="defer" src="/static/js/app.51b2bdb0.js"></script><link href="/static/css/app.32d0ced1.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

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([[193],{9161:function(e,s,t){t.r(s),t.d(s,{default:function(){return A}});t(6699);var a=t(6252),r=t(2262),l=t(3577),o=t(3324),n=t(9996);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-d693c7da"]]);var Z=F,x=t(5630),D=t(8602),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],{9161:function(e,s,t){t.r(s),t.d(s,{default:function(){return A}});t(6699);var a=t(6252),r=t(2262),l=t(3577),o=t(3324),n=t(9996);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-d693c7da"]]);var Z=F,x=t(5630),D=t(8602),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.6987952e.js.map //# sourceMappingURL=statistics.145d19e3.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

View File

@ -3,8 +3,9 @@ import smtplib
import ssl import ssl
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText from email.mime.text import MIMEText
from typing import Dict, Optional, Type, Union from typing import Dict, List, Optional, Type, Union
from babel.support import Translations
from flask import Flask from flask import Flask
from jinja2 import Environment, FileSystemLoader, select_autoescape from jinja2 import Environment, FileSystemLoader, select_autoescape
from urllib3.util import parse_url from urllib3.util import parse_url
@ -38,16 +39,43 @@ class EmailMessage:
class EmailTemplate: class EmailTemplate:
def __init__(self, template_directory: str) -> None: def __init__(
self,
template_directory: str,
translations_directory: str,
languages: List[str],
) -> None:
self._translations = self._get_translations(
translations_directory, languages
)
self._env = Environment( self._env = Environment(
autoescape=select_autoescape(['html', 'htm', 'xml']), autoescape=select_autoescape(['html', 'htm', 'xml']),
loader=FileSystemLoader(template_directory), loader=FileSystemLoader(template_directory),
extensions=['jinja2.ext.i18n'],
)
@staticmethod
def _get_translations(
translations_directory: str, languages: List[str]
) -> Dict:
translations = {}
for language in languages:
translations[language] = Translations.load(
dirname=translations_directory, locales=[language]
)
return translations
def _load_translation(self, lang: str) -> None:
self._env.install_gettext_translations( # type: ignore
self._translations[lang],
newstyle=True,
) )
def get_content( def get_content(
self, template_name: str, lang: str, part: str, data: Dict self, template_name: str, lang: str, part: str, data: Dict
) -> str: ) -> str:
template = self._env.get_template(f'{template_name}/{lang}/{part}') self._load_translation(lang)
template = self._env.get_template(f'{template_name}/{part}')
return template.render(data) return template.render(data)
def get_all_contents(self, template: str, lang: str, data: Dict) -> Dict: def get_all_contents(self, template: str, lang: str, data: Dict) -> Dict:
@ -92,7 +120,11 @@ class EmailService:
self.username = parsed_url['username'] self.username = parsed_url['username']
self.password = parsed_url['password'] self.password = parsed_url['password']
self.sender_email = app.config['SENDER_EMAIL'] self.sender_email = app.config['SENDER_EMAIL']
self.email_template = EmailTemplate(app.config['TEMPLATES_FOLDER']) self.email_template = EmailTemplate(
app.config['TEMPLATES_FOLDER'],
app.config['TRANSLATIONS_FOLDER'],
app.config['LANGUAGES'],
)
@staticmethod @staticmethod
def parse_email_url(email_url: str) -> Dict: def parse_email_url(email_url: str) -> Dict:

View File

@ -0,0 +1,26 @@
{% extends "layout.html" %}
{% block title %}{{ _('Confirm your account') }}{% endblock %}
{% block preheader %}{{ _('Use this link to confirm your account.') }}{% endblock %}
{% block content %}<p>{{ _('You have created an account on FitTrackee.') }} {{ _('Use the button below to confirm your address email.') }}</p>
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table width="100%" border="0" cellspacing="0" cellpadding="0" role="presentation">
<tr>
<td align="center">
<a href="{{account_confirmation_url}}" class="f-fallback button button--green" target="_blank">{{ _('Verify your email') }}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>{% endblock %}
{% block not_initiated %}{{ _("If this account creation wasn't initiated by you, please ignore this email.") }}{% endblock %}
{% block url_to_paste %}<table class="body-sub" role="presentation">
<tr>
<td>
<p class="f-fallback sub">{{ _("If you're having trouble with the button above, copy and paste the URL below into your web browser.") }}</p>
<p class="f-fallback sub">{{account_confirmation_url}}</p>
</td>
</tr>
</table>{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "layout.txt" %}{% block content %}{{ _('You have created an account on FitTrackee.') }}
{{ _('Use the link below to confirm your address email.') }}
{{ _('Verify your email') }}: {{ account_confirmation_url }}
{% if operating_system and browser_name %}{{ _('For security, this request was received from a %(operating_system)s device using %(browser_name)s.', operating_system=operating_system, browser_name=browser_name) }}
{% endif %}{{ _("If this account creation wasn't initiated by you, please ignore this email.") }}{% endblock %}

View File

@ -1,32 +0,0 @@
{% extends "layout.html" %}
{% block title %}Confirm your account{% endblock %}
{% block preheader %}Use this link to confirm your account.{% endblock %}
{% block content %}<h1>Hi {{username}},</h1>
<p>You have created an account on FitTrackee account. Use the link below to confirm your address email.</p>
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table width="100%" border="0" cellspacing="0" cellpadding="0" role="presentation">
<tr>
<td align="center">
<a href="{{account_confirmation_url}}" class="f-fallback button button--green" target="_blank">Verify your email</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p>
{% if operating_system and browser_name %}For security, this request was received from a {{operating_system}} device using {{browser_name}}.
{% endif %}If this account creation wasn't initiated by you, please ignore this email.
</p>
<p>Thanks,
<br>The FitTrackee Team</p>
<table class="body-sub" role="presentation">
<tr>
<td>
<p class="f-fallback sub">If youre having trouble with the button above, copy and paste the URL below into your web browser.</p>
<p class="f-fallback sub">{{account_confirmation_url}}</p>
</td>
</tr>
</table>{% endblock %}

View File

@ -1,12 +0,0 @@
Hi {{username}},
You have created an account on FitTrackee account. Use the link below to confirm your address email.
Verify your email: {{ account_confirmation_url }}
{% if operating_system and browser_name %}For security, this request was received from a {{operating_system}} device using {{browser_name}}.
{% endif %}If this account creation wasn't initiated by you, please ignore this email.
Thanks,
The FitTrackee Team
{{fittrackee_url}}

View File

@ -1 +0,0 @@
FitTrackee - Confirm your account

View File

@ -1,34 +0,0 @@
{% extends "layout.html" %}
{% block title %}Confirmer votre inscription{% endblock %}
{% block preheader %}Utiliser ce lien pour confirmer votre inscription.{% endblock %}
{% block content %}<h1>Bonjour {{username}},</h1>
<p>Vous avez créé un compte sur FitTrackee.
Cliquez sur le lien ci-dessous pour confirmer votre adresse email.
</p>
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table width="100%" border="0" cellspacing="0" cellpadding="0" role="presentation">
<tr>
<td align="center">
<a href="{{account_confirmation_url}}" class="f-fallback button button--green" target="_blank">Vérifier l'adresse email</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p>
{% if operating_system and browser_name %}Pour vérification, cette demande a été reçue à partir d'un appareil sous {{operating_system}}, utilisant le navigateur {{browser_name}}.
{% endif %}Si vous n'êtes pas à l'origine de la création de ce compte, vous pouvez ignorer cet e-mail.
</p>
<p>Merci,
<br>L'équipe FitTrackee</p>
<table class="body-sub" role="presentation">
<tr>
<td>
<p class="f-fallback sub">Si vous avez des problèmes avec le bouton, vous pouvez copier et coller le lien suivant dans votre navigateur</p>
<p class="f-fallback sub">{{account_confirmation_url}}</p>
</td>
</tr>
</table>{% endblock %}

View File

@ -1,13 +0,0 @@
Bonjour {{username}},
Vous avez créé un compte sur FitTrackee.
Cliquez sur le lien ci-dessous pour confirmer votre adresse email.
Vérifier l'adresse email : {{ account_confirmation_url }}
{% if operating_system and browser_name %}Pour vérification, cette demande a été reçue à partir d'un appareil sous {{operating_system}}, utilisant le navigateur {{browser_name}}.
{% endif %}Si vous n'êtes pas à l'origine de la création de ce compte, vous pouvez ignorer cet e-mail.
Merci,
L'équipe FitTrackee
{{fittrackee_url}}

View File

@ -1 +0,0 @@
FitTrackee - Confirmer votre inscription

View File

@ -0,0 +1 @@
FitTrackee - {{ _('Confirm your account') }}

View File

@ -0,0 +1,18 @@
{% extends "layout.html" %}
{% block title %}{{ _('Email changed') }}{% endblock %}
{% block preheader %}{{ _('Your email is being updated.') }}{% endblock %}
{% block content %}<p>{{ _('You recently requested to change your email address for your FitTrackee account to:') }}</p>
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table width="100%" border="0" cellspacing="0" cellpadding="0" role="presentation">
<tr>
<td align="center">
{{new_email_address}}
</td>
</tr>
</table>
</td>
</tr>
</table>{% endblock %}
{% block not_initiated %}{{ _("If this email change wasn't initiated by you, please change your password immediately or contact your administrator if your account is locked.") }}{% endblock %}

View File

@ -0,0 +1,4 @@
{% extends "layout.txt" %}{% block content %}{{ _('You recently requested to change your email address for your FitTrackee account to:') }} {{ new_email_address }}
{{ _('For security, this request was received from a %(operating_system)s device using %(browser_name)s.', operating_system=operating_system, browser_name=browser_name) }}
{{ _("If this email change wasn't initiated by you, please change your password immediately or contact your administrator if your account is locked.") }}{% endblock %}

View File

@ -1,26 +0,0 @@
{% extends "layout.html" %}
{% block title %}Email changed{% endblock %}
{% block preheader %}Your email is being updated.{% endblock %}
{% block content %}<h1>Hi {{username}},</h1>
<p>You recently requested to change your email address for your FitTrackee account to: </p>
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table width="100%" border="0" cellspacing="0" cellpadding="0" role="presentation">
<tr>
<td align="center">
{{new_email_address}}
</td>
</tr>
</table>
</td>
</tr>
</table>
<p>
For security, this request was received from a {{operating_system}} device using {{browser_name}}.
If this email change wasn't initiated by you, please change your password immediately or contact your administrator if your account is locked.
</p>
<p>Thanks,
<br>
The FitTrackee Team
</p>{% endblock %}

View File

@ -1,10 +0,0 @@
Hi {{username}},
You recently requested to change your email address for your FitTrackee account to: {{ new_email_address }}
For security, this request was received from a {{operating_system}} device using {{browser_name}}.
If this email change wasn't initiated by you, please change your password immediately or contact your administrator if your account is locked.
Thanks,
The FitTrackee Team
{{fittrackee_url}}

View File

@ -1 +0,0 @@
FitTrackee - Email changed

View File

@ -1,26 +0,0 @@
{% extends "layout.html" %}
{% block title %}Adresse email modifiée{% endblock %}
{% block preheader %}Votre adresse email est en cours de mise à jour.{% endblock %}
{% block content %}<h1>Bonjour {{username}},</h1>
<p>Vous avez récemment demandé la modification de l'adresse email associée à votre compte sur FitTrackee vers :</p>
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table width="100%" border="0" cellspacing="0" cellpadding="0" role="presentation">
<tr>
<td align="center">
{{ new_email_address }}
</td>
</tr>
</table>
</td>
</tr>
</table>
<p>
Pour vérification, cette demande a été reçue à partir d'un appareil sous {{operating_system}}, utilisant le navigateur {{browser_name}}.
Si vous n'êtes pas à l'origine de cette modification, veuillez changer votre mot de passe immédiatement ou contacter l'administrateur si votre compte est bloqué.
</p>
<p>Merci,
<br>
L'équipe FitTrackee
</p>{% endblock %}

View File

@ -1,10 +0,0 @@
Bonjour {{username}},
Vous avez récemment demandé la modification de l'adresse email associée à votre compte sur FitTrackee vers : {{ new_email_address }}
Pour vérification, cette demande a été reçue à partir d'un appareil sous {{operating_system}}, utilisant le navigateur {{browser_name}}.
Si vous n'êtes pas à l'origine de cette modification, veuillez changer votre mot de passe immédiatement ou contacter l'administrateur si votre compte est bloqué.
Merci,
L'équipe FitTrackee
{{fittrackee_url}}

View File

@ -1 +0,0 @@
FitTrackee - Adresse email modifiée

View File

@ -0,0 +1 @@
FitTrackee - {{ _('Email changed') }}

View File

@ -0,0 +1,26 @@
{% extends "layout.html" %}
{% block title %}{{ _('Confirm email change') }}{% endblock %}
{% block preheader %}{{ _('Use this link to confirm email change.') }}{% endblock %}
{% block content %}<p>{{ _('You recently requested to change your email address for your FitTrackee account.') }} {{ _('Use the button below to confirm this address.') }}</p>
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td align="center">
<table width="100%" border="0" cellspacing="0" cellpadding="0" role="presentation">
<tr>
<td align="center">
<a href="{{email_confirmation_url}}" class="f-fallback button button--green" target="_blank">{{ _('Verify your email') }}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>{% endblock %}
{% block not_initiated %}{{ _("If this email change wasn't initiated by you, please ignore this email.") }}{% endblock %}
{% block url_to_paste %}<table class="body-sub" role="presentation">
<tr>
<td>
<p class="f-fallback sub">{{ _("If you're having trouble with the button above, copy and paste the URL below into your web browser.") }}</p>
<p class="f-fallback sub">{{email_confirmation_url}}</p>
</td>
</tr>
</table>{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "layout.txt" %}{% block content %}{{ _('You recently requested to change your email address for your FitTrackee account.') }}
{{ _('Use the link below to confirm this address.') }}
{{ _('Verify your email') }}: {{ email_confirmation_url }}
{% if operating_system and browser_name %}{{ _('For security, this request was received from a %(operating_system)s device using %(browser_name)s.', operating_system=operating_system, browser_name=browser_name) }}
{% endif %}{{ _("If this email change wasn't initiated by you, please ignore this email.") }}{% endblock %}

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