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
## 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)
### Issues Closed
@ -16,7 +45,7 @@
Note: it does not affect previously imported files
* [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)

View File

@ -17,13 +17,22 @@ First off, thank you for your interest in contributing!
The **GitHub** repository contains:
- source code (note that the repository also includes client build),
- translations,
- tests,
- 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**).
### 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
@ -62,14 +71,30 @@ Please make your changes from the development branch (`dev`).
$ 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, 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
$ 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.

View File

@ -6,6 +6,18 @@ make-p:
# 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)
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) -r fittrackee -c pyproject.toml

View File

@ -24,6 +24,7 @@ GUNICORN = $(VENV)/bin/gunicorn
BLACK = $(VENV)/bin/black
MYPY = $(VENV)/bin/mypy
BANDIT = $(VENV)/bin/bandit
PYBABEL = $(VENV)/bin/pybabel
FTCLI = $(VENV)/bin/ftcli
# 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)
[![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)
[![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
# 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

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
## 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)
### Issues Closed
@ -16,7 +45,7 @@
Note: it does not affect previously imported files
* [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)

View File

@ -60,6 +60,7 @@ Workouts
Account & preferences
^^^^^^^^^^^^^^^^^^^^^
- 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.
A user with an inactive account cannot log in. (*new in 0.6.0*)
@ -119,7 +120,9 @@ Administration
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

View File

@ -95,9 +95,9 @@ deployment method.
.. 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::
| With installation from PyPI, the directory will be located in
@ -395,13 +395,13 @@ Production environment
.. warning::
| 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
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz
$ tar -xzf v0.6.8.tar.gz
$ mv FitTrackee-0.6.8 FitTrackee
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.9.tar.gz
$ tar -xzf v0.6.9.tar.gz
$ mv FitTrackee-0.6.9 FitTrackee
$ cd FitTrackee
- Create **.env** from example and update it
@ -521,13 +521,13 @@ Prod environment
- 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
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz
$ tar -xzf v0.6.8.tar.gz
$ cp -R FitTrackee-0.6.8/* FitTrackee/
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.9.tar.gz
$ tar -xzf v0.6.9.tar.gz
$ cp -R FitTrackee-0.6.9/* FitTrackee/
$ cd FitTrackee
- Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__).

View File

@ -19,4 +19,10 @@ Administrator
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 = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '0.6.8',
VERSION: '0.6.9',
LANGUAGE: 'en',
COLLAPSE_INDEX: false,
BUILDER: 'html',

View File

@ -5,7 +5,7 @@
<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/" />
<title>Authentication &#8212; FitTrackee 0.6.8
<title>Authentication &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</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>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>lang</strong> (<em>string</em>) user language preferences (if not provided or invalid,
fallback to en (english))</p></li>
</ul>
</dd>
<dt class="field-even">Status Codes<span class="colon">:</span></dt>

View File

@ -5,7 +5,7 @@
<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/" />
<title>Configuration &#8212; FitTrackee 0.6.8
<title>Configuration &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</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_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;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="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>
@ -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_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;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="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>

View File

@ -5,7 +5,7 @@
<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/" />
<title>API documentation &#8212; FitTrackee 0.6.8
<title>API documentation &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</div>

View File

@ -5,7 +5,7 @@
<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/" />
<title>Records &#8212; FitTrackee 0.6.8
<title>Records &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</div>

View File

@ -5,7 +5,7 @@
<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/" />
<title>Sports &#8212; FitTrackee 0.6.8
<title>Sports &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</div>

View File

@ -5,7 +5,7 @@
<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/" />
<title>Statistics &#8212; FitTrackee 0.6.8
<title>Statistics &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</div>

View File

@ -5,7 +5,7 @@
<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/" />
<title>Users &#8212; FitTrackee 0.6.8
<title>Users &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</div>

View File

@ -5,7 +5,7 @@
<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/" />
<title>Workouts &#8212; FitTrackee 0.6.8
<title>Workouts &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</div>

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
<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/" />
<title>Command line interface &#8212; FitTrackee 0.6.8
<title>Command line interface &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="index.html">
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>
</div>

View File

@ -5,7 +5,7 @@
<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/" />
<title>Features &#8212; FitTrackee 0.6.8
<title>Features &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="index.html">
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>
</div>
@ -235,6 +235,7 @@
<h2>Account &amp; preferences<a class="headerlink" href="#account-preferences" title="Permalink to this heading"></a></h2>
<ul class="simple">
<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.
A user with an inactive account cannot log in. (<em>new in 0.6.0</em>)</p></li>
</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 id="translations">
<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 id="screenshots">
<h2>Screenshots<a class="headerlink" href="#screenshots" title="Permalink to this heading"></a></h2>

View File

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<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>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -38,7 +38,7 @@
</button>
<a class="navbar-brand" href="index.html">
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>
</div>

View File

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<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>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -45,7 +45,7 @@
</button>
<a class="navbar-brand" href="index.html">
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>
</div>

View File

@ -5,7 +5,7 @@
<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/" />
<title>FitTrackee &#8212; FitTrackee 0.6.8
<title>FitTrackee &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -40,7 +40,7 @@
</button>
<a class="navbar-brand" href="#">
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>
</div>

View File

@ -5,7 +5,7 @@
<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/" />
<title>Installation &#8212; FitTrackee 0.6.8
<title>Installation &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="index.html">
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>
</div>
@ -294,10 +294,10 @@ deployment method.</p>
<dd><div class="versionadded">
<p><span class="versionmodified added">New in version 0.4.0.</span></p>
</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">
<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>
</dl>
<div class="admonition danger">
@ -675,11 +675,11 @@ $ make install-db
</div>
</div>
<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>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz
$ tar -xzf v0.6.8.tar.gz
$ mv FitTrackee-0.6.8 FitTrackee
<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.9.tar.gz
$ mv FitTrackee-0.6.9 FitTrackee
$ <span class="nb">cd</span> FitTrackee
</pre></div>
</div>
@ -799,11 +799,11 @@ $ <span class="nb">source</span> .env
<ul class="simple">
<li><p>Stop the application</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>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz
$ tar -xzf v0.6.8.tar.gz
$ cp -R FitTrackee-0.6.8/* FitTrackee/
<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.9.tar.gz
$ cp -R FitTrackee-0.6.9/* FitTrackee/
$ <span class="nb">cd</span> FitTrackee
</pre></div>
</div>

Binary file not shown.

View File

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<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>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
@ -45,7 +45,7 @@
</button>
<a class="navbar-brand" href="index.html">
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>
</div>

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<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/" />
<title>Administrator &#8212; FitTrackee 0.6.8
<title>Administrator &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</div>
@ -81,6 +81,7 @@
aria-labelledby="dLabelLocalToc"><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="#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>
</li>
</ul>
@ -149,6 +150,12 @@
</li>
</ul>
</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>

View File

@ -5,7 +5,7 @@
<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/" />
<title>Troubleshooting &#8212; FitTrackee 0.6.8
<title>Troubleshooting &#8212; FitTrackee 0.6.9
documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</div>
@ -133,6 +133,7 @@
<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#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>
</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 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>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/bootstrap-sphinx.css" />
@ -41,7 +41,7 @@
</button>
<a class="navbar-brand" href="../index.html">
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>
</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
^^^^^^^^^^^^^^^^^^^^^
- 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.
A user with an inactive account cannot log in. (*new in 0.6.0*)
@ -119,7 +120,9 @@ Administration
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

View File

@ -95,9 +95,9 @@ deployment method.
.. 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::
| With installation from PyPI, the directory will be located in
@ -395,13 +395,13 @@ Production environment
.. warning::
| 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
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz
$ tar -xzf v0.6.8.tar.gz
$ mv FitTrackee-0.6.8 FitTrackee
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.9.tar.gz
$ tar -xzf v0.6.9.tar.gz
$ mv FitTrackee-0.6.9 FitTrackee
$ cd FitTrackee
- Create **.env** from example and update it
@ -521,13 +521,13 @@ Prod environment
- 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
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.8.tar.gz
$ tar -xzf v0.6.8.tar.gz
$ cp -R FitTrackee-0.6.8/* FitTrackee/
$ wget https://github.com/SamR1/FitTrackee/archive/v0.6.9.tar.gz
$ tar -xzf v0.6.9.tar.gz
$ cp -R FitTrackee-0.6.9/* FitTrackee/
$ cd FitTrackee
- Update **.env** if needed (see `Environment variables <installation.html#environment-variables>`__).

View File

@ -19,4 +19,10 @@ Administrator
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
@ -9,7 +11,7 @@ class TestIndex:
def test_navbar_contains_all_links(self, selenium):
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 "Login" 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
URL = f'{TEST_URL}/login'
@ -7,24 +9,24 @@ class TestLogin:
def test_navbar_contains_login(self, selenium):
selenium.get(URL)
nav = selenium.find_element_by_id('nav').text
nav = selenium.find_element(By.ID, 'nav').text
assert 'Login' in nav
def test_it_displays_login_form(self, selenium):
selenium.get(URL)
inputs = selenium.find_elements_by_tag_name('input')
inputs = selenium.find_elements(By.TAG_NAME, 'input')
assert len(inputs) == 2
assert inputs[0].get_attribute('id') == 'email'
assert inputs[0].get_attribute('type') == 'email'
assert inputs[1].get_attribute('id') == '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 '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 'Register' in links[0].text
assert links[1].tag_name == 'a'
@ -37,7 +39,7 @@ class TestLogin:
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 'Login' not 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
class TestLogout:
def test_user_can_log_out(self, selenium):
user = register_valid_user(selenium)
user_menu = selenium.find_element_by_class_name('nav-items-user-menu')
logout_link = user_menu.find_elements_by_class_name('nav-item')[2]
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.click()
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 'Login' 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
@ -5,18 +7,18 @@ class TestProfile:
def test_it_displays_user_profile(self, selenium):
user = register_valid_user(selenium)
app_menu = selenium.find_element_by_class_name('nav-items-user-menu')
profile_link = app_menu.find_elements_by_class_name('nav-item')[1]
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.click()
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 '0\nworkouts' in user_header.text
assert '0\nkm' 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 'First 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 (
TEST_URL,
random_string,
@ -13,7 +15,7 @@ class TestRegistration:
selenium.get(URL)
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 inputs[0].get_attribute('id') == 'username'
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('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 form_infos[0].text == (
'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[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 '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 'Login' in links[0].text
assert links[1].tag_name == 'a'
@ -50,7 +52,7 @@ class TestRegistration:
register(selenium, user)
message = selenium.find_element_by_class_name('success-message').text
message = selenium.find_element(By.CLASS_NAME, 'success-message').text
assert (
'A link to activate your account has been '
'emailed to the address provided.'
@ -67,7 +69,7 @@ class TestRegistration:
register(selenium, user_infos)
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 'Login' in nav
@ -80,7 +82,7 @@ class TestRegistration:
register(selenium, user)
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
def test_user_does_not_return_error_if_email_is_already_taken(
@ -92,7 +94,7 @@ class TestRegistration:
register(selenium, user)
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 (
'A link to activate your account has been '
'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.ui import Select, WebDriverWait
@ -7,36 +8,36 @@ from .utils import TEST_URL, register_valid_user
class TestWorkout:
def test_user_can_add_workout_without_gpx(self, selenium):
register_valid_user(selenium)
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]
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.click()
selenium.implicitly_wait(1)
radio_button = selenium.find_element_by_id('withoutGpx')
radio_button = selenium.find_element(By.ID, 'withoutGpx')
radio_button.click()
select = Select(selenium.find_element_by_id('sport'))
select = Select(selenium.find_element(By.ID, 'sport'))
select.select_by_index(1)
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-time').send_keys('14:05')
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, 'title').send_keys('Workout title')
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-duration-hour').send_keys('01')
selenium.find_element(By.NAME, 'workout-duration-minutes').send_keys(
'00'
)
selenium.find_element_by_name('workout-duration-seconds').send_keys(
selenium.find_element(By.NAME, 'workout-duration-seconds').send_keys(
'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()
WebDriverWait(selenium, 10).until(
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 'Distance: 10 km' in workout_details
assert 'Average Speed: 10 km/h' in workout_details

View File

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

View File

@ -20,7 +20,7 @@ from sqlalchemy.exc import ProgrammingError
from fittrackee.emails.email import EmailService
from fittrackee.request import CustomRequest
VERSION = __version__ = '0.6.8'
VERSION = __version__ = '0.6.9'
db = SQLAlchemy()
bcrypt = Bcrypt()
migrate = Migrate()

View File

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

View File

@ -46,6 +46,10 @@ class BaseConfig:
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):

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}}]);
//# 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
from email.mime.multipart import MIMEMultipart
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 jinja2 import Environment, FileSystemLoader, select_autoescape
from urllib3.util import parse_url
@ -38,16 +39,43 @@ class EmailMessage:
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(
autoescape=select_autoescape(['html', 'htm', 'xml']),
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(
self, template_name: str, lang: str, part: str, data: Dict
) -> 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)
def get_all_contents(self, template: str, lang: str, data: Dict) -> Dict:
@ -92,7 +120,11 @@ class EmailService:
self.username = parsed_url['username']
self.password = parsed_url['password']
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
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