Merged with dev and fixed conflicts
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import re
|
||||
from importlib import import_module, reload
|
||||
from typing import Any
|
||||
|
||||
@@ -15,10 +15,12 @@ from flask_bcrypt import Bcrypt
|
||||
from flask_dramatiq import Dramatiq
|
||||
from flask_migrate import Migrate
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from sqlalchemy.exc import ProgrammingError
|
||||
|
||||
from fittrackee.emails.email import EmailService
|
||||
from fittrackee.request import CustomRequest
|
||||
|
||||
VERSION = __version__ = '0.5.7'
|
||||
VERSION = __version__ = '0.6.10'
|
||||
db = SQLAlchemy()
|
||||
bcrypt = Bcrypt()
|
||||
migrate = Migrate()
|
||||
@@ -33,9 +35,17 @@ logging.basicConfig(
|
||||
appLog = logging.getLogger('fittrackee')
|
||||
|
||||
|
||||
def create_app() -> Flask:
|
||||
class CustomFlask(Flask):
|
||||
# add custom Request to handle user-agent parsing
|
||||
# (removed in Werkzeug 2.1)
|
||||
request_class = CustomRequest
|
||||
|
||||
|
||||
def create_app(init_email: bool = True) -> Flask:
|
||||
# instantiate the app
|
||||
app = Flask(__name__, static_folder='dist/static', template_folder='dist')
|
||||
app = CustomFlask(
|
||||
__name__, static_folder='dist/static', template_folder='dist'
|
||||
)
|
||||
|
||||
# set config
|
||||
with app.app_context():
|
||||
@@ -54,8 +64,15 @@ def create_app() -> Flask:
|
||||
migrate.init_app(app, db)
|
||||
dramatiq.init_app(app)
|
||||
|
||||
# set up email
|
||||
email_service.init_email(app)
|
||||
# set up email if 'EMAIL_URL' is initialized
|
||||
if init_email:
|
||||
if app.config['EMAIL_URL']:
|
||||
email_service.init_email(app)
|
||||
app.config['CAN_SEND_EMAILS'] = True
|
||||
else:
|
||||
appLog.warning(
|
||||
'EMAIL_URL is not provided, email sending is deactivated.'
|
||||
)
|
||||
|
||||
# get configuration from database
|
||||
from .application.utils import (
|
||||
@@ -66,9 +83,16 @@ def create_app() -> Flask:
|
||||
with app.app_context():
|
||||
# Note: check if "app_config" table exist to avoid errors when
|
||||
# dropping tables on dev environments
|
||||
if db.engine.dialect.has_table(db.engine.connect(), 'app_config'):
|
||||
db_app_config = get_or_init_config()
|
||||
update_app_config_from_database(app, db_app_config)
|
||||
try:
|
||||
if db.engine.dialect.has_table(db.engine.connect(), 'app_config'):
|
||||
db_app_config = get_or_init_config()
|
||||
update_app_config_from_database(app, db_app_config)
|
||||
except ProgrammingError as e:
|
||||
# avoid error on AppConfig migration
|
||||
if re.match(
|
||||
r'psycopg2.errors.UndefinedColumn(.*)app_config.', str(e)
|
||||
):
|
||||
pass
|
||||
|
||||
from .application.app_config import config_blueprint # noqa
|
||||
from .users.auth import auth_blueprint # noqa
|
||||
@@ -96,7 +120,7 @@ def create_app() -> Flask:
|
||||
appLog.setLevel(logging.DEBUG)
|
||||
|
||||
# Enable CORS
|
||||
@app.after_request
|
||||
@app.after_request # type: ignore
|
||||
def after_request(response: Response) -> Response:
|
||||
response.headers.add('Access-Control-Allow-Origin', '*')
|
||||
response.headers.add(
|
||||
@@ -129,17 +153,4 @@ def create_app() -> Flask:
|
||||
else:
|
||||
return render_template('index.html')
|
||||
|
||||
@app.cli.command('drop-db')
|
||||
def drop_db() -> None:
|
||||
"""Empty database and delete uploaded files for dev environments."""
|
||||
if app_settings == 'fittrackee.config.ProductionConfig':
|
||||
print('This is a production server, aborting!')
|
||||
return
|
||||
db.engine.execute("DROP TABLE IF EXISTS alembic_version;")
|
||||
db.drop_all()
|
||||
db.session.commit()
|
||||
print('Database dropped.')
|
||||
shutil.rmtree(app.config['UPLOAD_FOLDER'], ignore_errors=True)
|
||||
print('Uploaded files deleted.')
|
||||
|
||||
return app
|
||||
|
@@ -3,16 +3,23 @@
|
||||
import os
|
||||
from typing import Dict, Optional
|
||||
|
||||
import click
|
||||
import gunicorn.app.base
|
||||
from flask import Flask
|
||||
from flask_migrate import upgrade
|
||||
|
||||
from fittrackee import create_app
|
||||
from fittrackee.users.exceptions import UserNotFoundException
|
||||
from fittrackee.users.utils.admin import UserManagerService
|
||||
|
||||
HOST = os.getenv('HOST', '0.0.0.0')
|
||||
HOST = os.getenv('HOST', '127.0.0.1')
|
||||
PORT = os.getenv('PORT', '5000')
|
||||
WORKERS = os.getenv('APP_WORKERS', 1)
|
||||
BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
||||
WARNING_MESSAGE = (
|
||||
"\nThis command is deprecated, it will be removed in a next version.\n"
|
||||
"Please use ftcli instead.\n"
|
||||
)
|
||||
app = create_app()
|
||||
|
||||
|
||||
@@ -37,7 +44,39 @@ class StandaloneApplication(gunicorn.app.base.BaseApplication):
|
||||
return self.application
|
||||
|
||||
|
||||
# DEPRECATED COMMANDS
|
||||
@click.group()
|
||||
def users_cli() -> None:
|
||||
pass
|
||||
|
||||
|
||||
@users_cli.command('set_admin')
|
||||
@click.argument('username')
|
||||
def set_admin(username: str) -> None:
|
||||
"""
|
||||
[deprecated] Set admin rights for given user.
|
||||
|
||||
It will be removed in a next version.
|
||||
"""
|
||||
print(WARNING_MESSAGE)
|
||||
with app.app_context():
|
||||
try:
|
||||
user_manager_service = UserManagerService(username)
|
||||
user_manager_service.update(
|
||||
is_admin=True,
|
||||
)
|
||||
print(f"User '{username}' updated.")
|
||||
except UserNotFoundException:
|
||||
print(f"User '{username}' not found.")
|
||||
|
||||
|
||||
def upgrade_db() -> None:
|
||||
"""
|
||||
[deprecated] Apply migrations.
|
||||
|
||||
It will be removed in a next version.
|
||||
"""
|
||||
print(WARNING_MESSAGE)
|
||||
with app.app_context():
|
||||
upgrade(directory=BASEDIR + '/migrations')
|
||||
|
||||
|
@@ -11,6 +11,7 @@ from fittrackee.responses import (
|
||||
)
|
||||
from fittrackee.users.decorators import authenticate_as_admin
|
||||
from fittrackee.users.models import User
|
||||
from fittrackee.users.utils.controls import is_valid_email
|
||||
|
||||
from .models import AppConfig
|
||||
from .utils import update_app_config_from_database, verify_app_config
|
||||
@@ -39,13 +40,15 @@ def get_application_config() -> Union[Dict, HttpResponse]:
|
||||
|
||||
{
|
||||
"data": {
|
||||
"admin_contact": "admin@example.com",
|
||||
"gpx_limit_import": 10,
|
||||
"is_email_sending_enabled": true,
|
||||
"is_registration_enabled": false,
|
||||
"max_single_file_size": 1048576,
|
||||
"max_zip_file_size": 10485760,
|
||||
"max_users": 0,
|
||||
"max_zip_file_size": 10485760,
|
||||
"map_attribution": "© <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"
|
||||
"version": "0.5.7"
|
||||
"version": "0.6.10"
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
@@ -87,20 +90,25 @@ def update_application_config(auth_user: User) -> Union[Dict, HttpResponse]:
|
||||
|
||||
{
|
||||
"data": {
|
||||
"admin_contact": "admin@example.com",
|
||||
"gpx_limit_import": 10,
|
||||
"is_registration_enabled": true,
|
||||
"is_email_sending_enabled": true,
|
||||
"is_registration_enabled": false,
|
||||
"max_single_file_size": 1048576,
|
||||
"max_users": 10,
|
||||
"max_zip_file_size": 10485760,
|
||||
"max_users": 10
|
||||
"map_attribution": "© <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"
|
||||
"version": "0.6.10"
|
||||
},
|
||||
"status": "success"
|
||||
}
|
||||
|
||||
:<json string admin_contact: email to contact the administrator
|
||||
:<json integer gpx_limit_import: max number of files in zip archive
|
||||
:<json boolean is_registration_enabled: is registration enabled ?
|
||||
:<json integer max_single_file_size: max size of a single file
|
||||
:<json integer max_zip_file_size: max size of a zip archive
|
||||
:<json integer max_users: max users allowed to register on instance
|
||||
:<json integer max_zip_file_size: max size of a zip archive
|
||||
|
||||
:reqheader Authorization: OAuth 2.0 Bearer Token
|
||||
|
||||
@@ -110,6 +118,7 @@ def update_application_config(auth_user: User) -> Union[Dict, HttpResponse]:
|
||||
- provide a valid auth token
|
||||
- signature expired, please log in again
|
||||
- invalid token, please log in again
|
||||
- valid email must be provided for admin contact
|
||||
:statuscode 403: you do not have permissions
|
||||
:statuscode 500: error when updating configuration
|
||||
"""
|
||||
@@ -118,6 +127,9 @@ def update_application_config(auth_user: User) -> Union[Dict, HttpResponse]:
|
||||
return InvalidPayloadErrorResponse()
|
||||
|
||||
ret = verify_app_config(config_data)
|
||||
admin_contact = config_data.get('admin_contact')
|
||||
if admin_contact and not is_valid_email(admin_contact):
|
||||
ret.append('valid email must be provided for admin contact')
|
||||
if ret:
|
||||
return InvalidPayloadErrorResponse(message=ret)
|
||||
|
||||
@@ -133,6 +145,8 @@ def update_application_config(auth_user: User) -> Union[Dict, HttpResponse]:
|
||||
config.max_zip_file_size = config_data.get('max_zip_file_size')
|
||||
if 'max_users' in config_data:
|
||||
config.max_users = config_data.get('max_users')
|
||||
if 'admin_contact' in config_data:
|
||||
config.admin_contact = admin_contact if admin_contact else None
|
||||
|
||||
if config.max_zip_file_size < config.max_single_file_size:
|
||||
return InvalidPayloadErrorResponse(
|
||||
|
@@ -23,6 +23,7 @@ class AppConfig(BaseModel):
|
||||
db.Integer, default=1048576, nullable=False
|
||||
)
|
||||
max_zip_file_size = db.Column(db.Integer, default=10485760, nullable=False)
|
||||
admin_contact = db.Column(db.String(255), nullable=True)
|
||||
|
||||
@property
|
||||
def is_registration_enabled(self) -> bool:
|
||||
@@ -43,7 +44,9 @@ class AppConfig(BaseModel):
|
||||
|
||||
def serialize(self) -> Dict:
|
||||
return {
|
||||
'admin_contact': self.admin_contact,
|
||||
'gpx_limit_import': self.gpx_limit_import,
|
||||
'is_email_sending_enabled': current_app.config['CAN_SEND_EMAILS'],
|
||||
'is_registration_enabled': self.is_registration_enabled,
|
||||
'max_single_file_size': self.max_single_file_size,
|
||||
'max_zip_file_size': self.max_zip_file_size,
|
||||
|
14
fittrackee/cli/__init__.py
Normal file
14
fittrackee/cli/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import click
|
||||
|
||||
from fittrackee.migrations.commands import db_cli
|
||||
from fittrackee.users.commands import users_cli
|
||||
|
||||
|
||||
@click.group()
|
||||
def cli() -> None:
|
||||
"""FitTrackee Command Line Interface"""
|
||||
pass
|
||||
|
||||
|
||||
cli.add_command(db_cli)
|
||||
cli.add_command(users_cli)
|
3
fittrackee/cli/app.py
Normal file
3
fittrackee/cli/app.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from fittrackee import create_app
|
||||
|
||||
app = create_app(init_email=False)
|
@@ -12,7 +12,6 @@ else:
|
||||
|
||||
|
||||
class BaseConfig:
|
||||
"""Base configuration"""
|
||||
|
||||
DEBUG = False
|
||||
TESTING = False
|
||||
@@ -30,6 +29,7 @@ class BaseConfig:
|
||||
UI_URL = os.environ.get('UI_URL')
|
||||
EMAIL_URL = os.environ.get('EMAIL_URL')
|
||||
SENDER_EMAIL = os.environ.get('SENDER_EMAIL')
|
||||
CAN_SEND_EMAILS = False
|
||||
DRAMATIQ_BROKER = broker
|
||||
TILE_SERVER = {
|
||||
'URL': os.environ.get(
|
||||
@@ -43,40 +43,42 @@ class BaseConfig:
|
||||
' contributors',
|
||||
),
|
||||
'DEFAULT_STATICMAP': (
|
||||
os.environ.get('DEFAULT_STATICMAP', 'False') == 'True'
|
||||
os.environ.get('DEFAULT_STATICMAP', 'false').lower() == 'true'
|
||||
),
|
||||
'STATICMAP_SUBDOMAINS': os.environ.get('STATICMAP_SUBDOMAINS', ''),
|
||||
}
|
||||
TRANSLATIONS_FOLDER = os.path.join(
|
||||
current_app.root_path, 'emails/translations'
|
||||
)
|
||||
LANGUAGES = ['en', 'fr', 'de']
|
||||
|
||||
|
||||
class DevelopmentConfig(BaseConfig):
|
||||
"""Development configuration"""
|
||||
|
||||
DEBUG = True
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
|
||||
SECRET_KEY = 'development key'
|
||||
SECRET_KEY = 'development key' # nosec
|
||||
BCRYPT_LOG_ROUNDS = 4
|
||||
DRAMATIQ_BROKER_URL = os.getenv('REDIS_URL', 'redis://')
|
||||
|
||||
|
||||
class TestingConfig(BaseConfig):
|
||||
"""Testing configuration"""
|
||||
|
||||
DEBUG = True
|
||||
TESTING = True
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_TEST_URL')
|
||||
SECRET_KEY = 'test key'
|
||||
SECRET_KEY = 'test key' # nosec
|
||||
BCRYPT_LOG_ROUNDS = 4
|
||||
TOKEN_EXPIRATION_DAYS = 0
|
||||
TOKEN_EXPIRATION_SECONDS = 3
|
||||
PASSWORD_TOKEN_EXPIRATION_SECONDS = 3
|
||||
UPLOAD_FOLDER = '/tmp/fitTrackee/uploads'
|
||||
UI_URL = 'http://0.0.0.0:5000'
|
||||
SENDER_EMAIL = 'fittrackee@example.com'
|
||||
|
||||
|
||||
class ProductionConfig(BaseConfig):
|
||||
"""Production configuration"""
|
||||
class End2EndTestingConfig(TestingConfig):
|
||||
DRAMATIQ_BROKER_URL = os.getenv('REDIS_URL', 'redis://')
|
||||
|
||||
|
||||
class ProductionConfig(BaseConfig):
|
||||
DEBUG = False
|
||||
# https://docs.sqlalchemy.org/en/13/core/pooling.html#using-connection-pools-with-multiprocessing-or-os-fork # noqa
|
||||
SQLALCHEMY_ENGINE_OPTIONS = (
|
||||
|
2
fittrackee/dist/index.html
vendored
2
fittrackee/dist/index.html
vendored
@@ -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.f76e2e3d.js"></script><script defer="defer" src="/static/js/app.3c006379.js"></script><link href="/static/css/app.28b1f60f.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.7132edc6.js"></script><script defer="defer" src="/static/js/app.bf1d4e1c.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>
|
2
fittrackee/dist/service-worker.js
vendored
2
fittrackee/dist/service-worker.js
vendored
File diff suppressed because one or more lines are too long
2
fittrackee/dist/service-worker.js.map
vendored
2
fittrackee/dist/service-worker.js.map
vendored
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/app.28b1f60f.css
vendored
1
fittrackee/dist/static/css/app.28b1f60f.css
vendored
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/app.32d0ced1.css
vendored
Normal file
1
fittrackee/dist/static/css/app.32d0ced1.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/profile.203e78e2.css
vendored
Normal file
1
fittrackee/dist/static/css/profile.203e78e2.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
#account-confirmation[data-v-785df978]{display:flex;flex-direction:column;align-items:center}#account-confirmation svg[data-v-785df978]{stroke:none;fill-rule:nonzero;fill:var(--app-color);filter:var(--svg-filter);width:100px}#account-confirmation .error-message[data-v-785df978]{font-size:1.1em;text-align:center;display:flex;flex-direction:column}@media screen and (max-width:1000px){#account-confirmation .error-message[data-v-785df978]{font-size:1em}}#email-update[data-v-8c2ec9ce]{display:flex;flex-direction:column;align-items:center}#email-update svg[data-v-8c2ec9ce]{stroke:none;fill-rule:nonzero;fill:var(--app-color);filter:var(--svg-filter);width:100px}#email-update .error-message[data-v-8c2ec9ce]{font-size:1.1em;text-align:center;display:flex;flex-direction:column}@media screen and (max-width:1000px){#email-update .error-message[data-v-8c2ec9ce]{font-size:1em}}#profile[data-v-05463732],#profile[data-v-05463732] .profile-form{display:flex;flex-direction:column}#profile[data-v-05463732] .profile-form hr{border-color:var(--card-border-color);border-width:1px 0 0 0}#profile[data-v-05463732] .profile-form .form-items{display:flex;flex-direction:column}#profile[data-v-05463732] .profile-form .form-items input{margin:5px 0}#profile[data-v-05463732] .profile-form .form-items select{height:35px;padding:5px 0}#profile[data-v-05463732] .profile-form .form-items ::v-deep(.custom-textarea) textarea{padding:5px}#profile[data-v-05463732] .profile-form .form-items .form-item{display:flex;flex-direction:column;padding:10px}#profile[data-v-05463732] .profile-form .form-items .birth-date{height:20px}#profile[data-v-05463732] .profile-form .form-buttons{display:flex;margin-top:10px;padding:10px 0;gap:10px}#user[data-v-af7007f4]{margin:auto;width:700px}@media screen and (max-width:1000px){#user[data-v-af7007f4]{width:100%;margin:0 auto 50px auto}}
|
@@ -1 +0,0 @@
|
||||
#profile[data-v-163d82f7],#profile[data-v-163d82f7] .profile-form{display:flex;flex-direction:column}#profile[data-v-163d82f7] .profile-form hr{border-color:var(--card-border-color);border-width:1px 0 0 0}#profile[data-v-163d82f7] .profile-form .form-items{display:flex;flex-direction:column}#profile[data-v-163d82f7] .profile-form .form-items input{margin:5px 0}#profile[data-v-163d82f7] .profile-form .form-items select{height:35px;padding:5px 0}#profile[data-v-163d82f7] .profile-form .form-items ::v-deep(.custom-textarea) textarea{padding:5px}#profile[data-v-163d82f7] .profile-form .form-items .form-item{display:flex;flex-direction:column;padding:10px}#profile[data-v-163d82f7] .profile-form .form-items .birth-date{height:20px}#profile[data-v-163d82f7] .profile-form .form-buttons{display:flex;margin-top:10px;padding:10px 0;gap:10px}#user[data-v-10e7b479]{margin:auto;width:700px}@media screen and (max-width:1000px){#user[data-v-10e7b479]{width:100%;margin:0 auto 50px auto}}
|
@@ -1 +0,0 @@
|
||||
#password-action-done[data-v-18334f6d]{display:flex;flex-direction:column;align-items:center}#password-action-done svg[data-v-18334f6d]{stroke:none;fill-rule:nonzero;fill:var(--app-color);filter:var(--svg-filter);width:100px}#password-action-done .password-message[data-v-18334f6d]{font-size:1.1em;text-align:center}@media screen and (max-width:1000px){#password-action-done .password-message[data-v-18334f6d]{font-size:1em}}#password-reset-request[data-v-68377e44] .card .card-content #user-form{width:100%}#password-reset[data-v-f5e39b60]{display:flex}#password-reset .container[data-v-f5e39b60]{display:flex;justify-content:center;width:50%}@media screen and (max-width:700px){#password-reset .container[data-v-f5e39b60]{width:100%;margin:0 auto 50px auto}}
|
1
fittrackee/dist/static/css/reset.e2527ec6.css
vendored
Normal file
1
fittrackee/dist/static/css/reset.e2527ec6.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
#account-confirmation-email[data-v-66aca424]{display:flex;flex-direction:column}#account-confirmation-email .email-sent[data-v-66aca424]{display:flex;flex-direction:column;align-items:center}#account-confirmation-email .email-sent svg[data-v-66aca424]{stroke:none;fill-rule:nonzero;fill:var(--app-color);filter:var(--svg-filter);width:100px}#account-confirmation-email .email-sent .email-sent-message[data-v-66aca424]{font-size:1.1em;text-align:center}@media screen and (max-width:1000px){#account-confirmation-email .email-sent .email-sent-message[data-v-66aca424]{font-size:1em}}#account-confirmation-email[data-v-66aca424] .card .card-content #user-auth-form{margin-top:0}#account-confirmation-email[data-v-66aca424] .card .card-content #user-auth-form #user-form{width:100%}#account-confirmation[data-v-35aad344]{display:flex}#account-confirmation .container[data-v-35aad344]{display:flex;justify-content:center;width:50%}@media screen and (max-width:700px){#account-confirmation .container[data-v-35aad344]{width:100%}}#password-action-done[data-v-eac78356]{display:flex;flex-direction:column;align-items:center}#password-action-done svg[data-v-eac78356]{stroke:none;fill-rule:nonzero;fill:var(--app-color);filter:var(--svg-filter);width:100px}#password-action-done .password-message[data-v-eac78356]{font-size:1.1em;text-align:center}@media screen and (max-width:1000px){#password-action-done .password-message[data-v-eac78356]{font-size:1em}}#password-reset-request[data-v-68377e44] .card .card-content #user-form{width:100%}#password-reset[data-v-a1cc55c4]{display:flex}#password-reset .container[data-v-a1cc55c4]{display:flex;justify-content:center;width:50%}@media screen and (max-width:700px){#password-reset .container[data-v-a1cc55c4]{width:100%}}
|
@@ -1 +0,0 @@
|
||||
.chart-menu[data-v-af15954c]{display:flex}.chart-menu .chart-arrow[data-v-af15954c],.chart-menu .time-frames[data-v-af15954c]{flex-grow:1;text-align:center}.chart-menu .chart-arrow[data-v-af15954c]{cursor:pointer}.sports-menu{display:flex;flex-wrap:wrap;padding:10px}.sports-menu label{display:flex;align-items:center;font-size:.9em;font-weight:400;min-width:120px;padding:10px}@media screen and (max-width:1000px){.sports-menu label{min-width:100px}}@media screen and (max-width:500px){.sports-menu label{min-width:20px}.sports-menu label .sport-label{display:none}}.sports-menu .sport-img{padding:3px;width:20px;height:20px}#user-statistics.stats-disabled[data-v-7d54529b]{opacity:.3;pointer-events:none}#user-statistics[data-v-7d54529b] .chart-radio{justify-content:space-around;padding:30px 10px 10px 10px}#statistics[data-v-0d93da6e]{display:flex;width:100%}#statistics .container[data-v-0d93da6e]{display:flex;flex-direction:column;width:100%}
|
1
fittrackee/dist/static/css/statistics.d0356685.css
vendored
Normal file
1
fittrackee/dist/static/css/statistics.d0356685.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.chart-menu[data-v-22d55de2]{display:flex}.chart-menu .chart-arrow[data-v-22d55de2],.chart-menu .time-frames[data-v-22d55de2]{flex-grow:1;text-align:center}.chart-menu .chart-arrow[data-v-22d55de2]{cursor:pointer}.sports-menu{display:flex;flex-wrap:wrap;padding:10px}.sports-menu label{display:flex;align-items:center;font-size:.9em;font-weight:400;min-width:120px;padding:10px}@media screen and (max-width:1000px){.sports-menu label{min-width:100px}}@media screen and (max-width:500px){.sports-menu label{min-width:20px}.sports-menu label .sport-label{display:none}}.sports-menu .sport-img{padding:3px;width:20px;height:20px}#user-statistics.stats-disabled[data-v-d693c7da]{opacity:.3;pointer-events:none}#user-statistics[data-v-d693c7da] .chart-radio{justify-content:space-around;padding:30px 10px 10px 10px}#statistics[data-v-2e341d4e]{display:flex;width:100%}#statistics .container[data-v-2e341d4e]{display:flex;flex-direction:column;width:100%}
|
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/css/workouts.fa95a9cb.css
vendored
Normal file
1
fittrackee/dist/static/css/workouts.fa95a9cb.css
vendored
Normal file
File diff suppressed because one or more lines are too long
7
fittrackee/dist/static/js/243.8b4f71d5.js
vendored
7
fittrackee/dist/static/js/243.8b4f71d5.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7
fittrackee/dist/static/js/243.b773e58b.js
vendored
Normal file
7
fittrackee/dist/static/js/243.b773e58b.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/243.b773e58b.js.map
vendored
Normal file
1
fittrackee/dist/static/js/243.b773e58b.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
fittrackee/dist/static/js/633.2b820738.js
vendored
7
fittrackee/dist/static/js/633.2b820738.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7
fittrackee/dist/static/js/633.69dd3969.js
vendored
Normal file
7
fittrackee/dist/static/js/633.69dd3969.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/633.69dd3969.js.map
vendored
Normal file
1
fittrackee/dist/static/js/633.69dd3969.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/admin.92270942.js
vendored
2
fittrackee/dist/static/js/admin.92270942.js
vendored
@@ -1,2 +0,0 @@
|
||||
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[328],{6e3:function(t,e,i){i.r(e),i.d(e,{default:function(){return _}});var a=i(6252),s=i(2262),n=i(8273),c=i(8602),r=i(9917);const S=t=>((0,a.dD)("data-v-64629971"),t=t(),(0,a.Cn)(),t),l={id:"admin",class:"view"},p={key:0,class:"container"},u=S((()=>(0,a._)("div",{id:"bottom"},null,-1)));var T=(0,a.aZ)({setup(t){const e=(0,r.o)(),i=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_CONFIG])),S=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_STATS])),T=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.IS_ADMIN])),o=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.USER_LOADING]));return(0,a.wF)((()=>e.dispatch(c.SY.ACTIONS.GET_APPLICATION_STATS))),(t,e)=>{const c=(0,a.up)("router-view");return(0,a.wg)(),(0,a.iD)("div",l,[(0,s.SU)(o)?(0,a.kq)("",!0):((0,a.wg)(),(0,a.iD)("div",p,[(0,s.SU)(T)?((0,a.wg)(),(0,a.j4)(c,{key:0,appConfig:(0,s.SU)(i),appStatistics:(0,s.SU)(S)},null,8,["appConfig","appStatistics"])):((0,a.wg)(),(0,a.j4)(n.Z,{key:1})),u]))])}}}),o=i(3744);const d=(0,o.Z)(T,[["__scopeId","data-v-64629971"]]);var _=d}}]);
|
||||
//# sourceMappingURL=admin.92270942.js.map
|
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"static/js/admin.92270942.js","mappings":"mOAGA,MAAMA,EAAeC,KAAMC,EAAAA,EAAAA,IAAa,mBAAmBD,EAAEA,KAAIE,EAAAA,EAAAA,MAAcF,GACzEG,EAAa,CACjBC,GAAI,QACJC,MAAO,QAEHC,EAAa,CACjBC,IAAK,EACLF,MAAO,aAEHG,EAA2BT,GAAa,KAAmBU,EAAAA,EAAAA,GAAoB,MAAO,CAAEL,GAAI,UAAY,MAAO,KAUrH,OAA4BM,EAAAA,EAAAA,IAAiB,CAC3CC,MAAMC,GAEN,MAAMC,GAAQC,EAAAA,EAAAA,KAERC,GAAqCC,EAAAA,EAAAA,KACzC,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,cAEhBC,GAA6CH,EAAAA,EAAAA,KACjD,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,aAEhBE,GAAuCJ,EAAAA,EAAAA,KAC3C,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,YAEhBC,GAAoCN,EAAAA,EAAAA,KACxC,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,gBAKxB,OAFEE,EAAAA,EAAAA,KAAc,IAAMV,EAAMW,SAASN,EAAAA,GAAAA,QAAAA,yBAE9B,CAACO,EAAUC,KAChB,MAAMC,GAAyBC,EAAAA,EAAAA,IAAkB,eAEjD,OAAQC,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAO3B,EAAY,EACzD4B,EAAAA,EAAAA,IAAOT,IAWLU,EAAAA,EAAAA,IAAoB,IAAI,KAVvBH,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAOxB,EAAY,EACnDyB,EAAAA,EAAAA,IAAOX,KACHS,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaN,EAAwB,CAClDpB,IAAK,EACLQ,WAAWgB,EAAAA,EAAAA,IAAOhB,GAClBI,eAAeY,EAAAA,EAAAA,IAAOZ,IACrB,KAAM,EAAG,CAAC,YAAa,qBACzBU,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaC,EAAAA,EAAU,CAAE3B,IAAK,KACjDC,W,UCjDV,MAAM2B,GAA2B,OAAgB,EAAQ,CAAC,CAAC,YAAY,qBAEvE","sources":["webpack://fittrackee_client/./src/views/AdminView.vue?67de","webpack://fittrackee_client/./src/views/AdminView.vue"],"sourcesContent":["import { defineComponent as _defineComponent } from 'vue'\nimport { unref as _unref, resolveComponent as _resolveComponent, openBlock as _openBlock, createBlock as _createBlock, createCommentVNode as _createCommentVNode, createElementVNode as _createElementVNode, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-64629971\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = {\n id: \"admin\",\n class: \"view\"\n}\nconst _hoisted_2 = {\n key: 0,\n class: \"container\"\n}\nconst _hoisted_3 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode(\"div\", { id: \"bottom\" }, null, -1))\n\nimport { computed, ComputedRef, onBeforeMount } from 'vue'\n\n import NotFound from '@/components/Common/NotFound.vue'\n import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'\n import { TAppConfig, IAppStatistics } from '@/types/application'\n import { useStore } from '@/use/useStore'\n\n \nexport default /*#__PURE__*/_defineComponent({\n setup(__props) {\n\n const store = useStore()\n\n const appConfig: ComputedRef<TAppConfig> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]\n )\n const appStatistics: ComputedRef<IAppStatistics> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_STATS]\n )\n const isAuthUserAmin: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.IS_ADMIN]\n )\n const userLoading: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]\n )\n\n onBeforeMount(() => store.dispatch(ROOT_STORE.ACTIONS.GET_APPLICATION_STATS))\n\nreturn (_ctx: any,_cache: any) => {\n const _component_router_view = _resolveComponent(\"router-view\")!\n\n return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [\n (!_unref(userLoading))\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_2, [\n (_unref(isAuthUserAmin))\n ? (_openBlock(), _createBlock(_component_router_view, {\n key: 0,\n appConfig: _unref(appConfig),\n appStatistics: _unref(appStatistics)\n }, null, 8, [\"appConfig\", \"appStatistics\"]))\n : (_openBlock(), _createBlock(NotFound, { key: 1 })),\n _hoisted_3\n ]))\n : _createCommentVNode(\"\", true)\n ]))\n}\n}\n\n})","import script from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\nexport * from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\n\nimport \"./AdminView.vue?vue&type=style&index=0&id=64629971&lang=scss&scoped=true\"\n\nimport exportComponent from \"/mnt/data-lnx/Devs/00_Perso/FitTrackee/fittrackee_client/node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['__scopeId',\"data-v-64629971\"]])\n\nexport default __exports__"],"names":["_withScopeId","n","_pushScopeId","_popScopeId","_hoisted_1","id","class","_hoisted_2","key","_hoisted_3","_createElementVNode","_defineComponent","setup","__props","store","useStore","appConfig","computed","getters","ROOT_STORE","appStatistics","isAuthUserAmin","AUTH_USER_STORE","userLoading","onBeforeMount","dispatch","_ctx","_cache","_component_router_view","_resolveComponent","_openBlock","_createElementBlock","_unref","_createCommentVNode","_createBlock","NotFound","__exports__"],"sourceRoot":""}
|
2
fittrackee/dist/static/js/admin.b19d15cc.js
vendored
Normal file
2
fittrackee/dist/static/js/admin.b19d15cc.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[328],{6e3:function(t,e,i){i.r(e),i.d(e,{default:function(){return _}});var a=i(6252),n=i(2262),s=i(8273),c=i(8602),r=i(9917);const S=t=>((0,a.dD)("data-v-64629971"),t=t(),(0,a.Cn)(),t),l={id:"admin",class:"view"},p={key:0,class:"container"},u=S((()=>(0,a._)("div",{id:"bottom"},null,-1)));var T=(0,a.aZ)({__name:"AdminView",setup(t){const e=(0,r.o)(),i=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_CONFIG])),S=(0,a.Fl)((()=>e.getters[c.SY.GETTERS.APP_STATS])),T=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.IS_ADMIN])),d=(0,a.Fl)((()=>e.getters[c.YN.GETTERS.USER_LOADING]));return(0,a.wF)((()=>e.dispatch(c.SY.ACTIONS.GET_APPLICATION_STATS))),(t,e)=>{const c=(0,a.up)("router-view");return(0,a.wg)(),(0,a.iD)("div",l,[(0,n.SU)(d)?(0,a.kq)("",!0):((0,a.wg)(),(0,a.iD)("div",p,[(0,n.SU)(T)?((0,a.wg)(),(0,a.j4)(c,{key:0,appConfig:(0,n.SU)(i),appStatistics:(0,n.SU)(S)},null,8,["appConfig","appStatistics"])):((0,a.wg)(),(0,a.j4)(s.Z,{key:1})),u]))])}}}),d=i(3744);const o=(0,d.Z)(T,[["__scopeId","data-v-64629971"]]);var _=o}}]);
|
||||
//# sourceMappingURL=admin.b19d15cc.js.map
|
1
fittrackee/dist/static/js/admin.b19d15cc.js.map
vendored
Normal file
1
fittrackee/dist/static/js/admin.b19d15cc.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"static/js/admin.b19d15cc.js","mappings":"mOAGA,MAAMA,EAAeC,KAAMC,EAAAA,EAAAA,IAAa,mBAAmBD,EAAEA,KAAIE,EAAAA,EAAAA,MAAcF,GACzEG,EAAa,CACjBC,GAAI,QACJC,MAAO,QAEHC,EAAa,CACjBC,IAAK,EACLF,MAAO,aAEHG,EAA2BT,GAAa,KAAmBU,EAAAA,EAAAA,GAAoB,MAAO,CAAEL,GAAI,UAAY,MAAO,KAUrH,OAA4BM,EAAAA,EAAAA,IAAiB,CAC3CC,OAAQ,YACRC,MAAMC,GAEN,MAAMC,GAAQC,EAAAA,EAAAA,KAERC,GAAqCC,EAAAA,EAAAA,KACzC,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,cAEhBC,GAA6CH,EAAAA,EAAAA,KACjD,IAAMH,EAAMI,QAAQC,EAAAA,GAAAA,QAAAA,aAEhBE,GAAuCJ,EAAAA,EAAAA,KAC3C,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,YAEhBC,GAAoCN,EAAAA,EAAAA,KACxC,IAAMH,EAAMI,QAAQI,EAAAA,GAAAA,QAAAA,gBAKxB,OAFEE,EAAAA,EAAAA,KAAc,IAAMV,EAAMW,SAASN,EAAAA,GAAAA,QAAAA,yBAE9B,CAACO,EAAUC,KAChB,MAAMC,GAAyBC,EAAAA,EAAAA,IAAkB,eAEjD,OAAQC,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAO5B,EAAY,EACzD6B,EAAAA,EAAAA,IAAOT,IAWLU,EAAAA,EAAAA,IAAoB,IAAI,KAVvBH,EAAAA,EAAAA,OAAcC,EAAAA,EAAAA,IAAoB,MAAOzB,EAAY,EACnD0B,EAAAA,EAAAA,IAAOX,KACHS,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaN,EAAwB,CAClDrB,IAAK,EACLS,WAAWgB,EAAAA,EAAAA,IAAOhB,GAClBI,eAAeY,EAAAA,EAAAA,IAAOZ,IACrB,KAAM,EAAG,CAAC,YAAa,qBACzBU,EAAAA,EAAAA,OAAcI,EAAAA,EAAAA,IAAaC,EAAAA,EAAU,CAAE5B,IAAK,KACjDC,W,UClDV,MAAM4B,GAA2B,OAAgB,EAAQ,CAAC,CAAC,YAAY,qBAEvE","sources":["webpack://fittrackee_client/./src/views/AdminView.vue?67de","webpack://fittrackee_client/./src/views/AdminView.vue"],"sourcesContent":["import { defineComponent as _defineComponent } from 'vue'\nimport { unref as _unref, resolveComponent as _resolveComponent, openBlock as _openBlock, createBlock as _createBlock, createCommentVNode as _createCommentVNode, createElementVNode as _createElementVNode, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-64629971\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = {\n id: \"admin\",\n class: \"view\"\n}\nconst _hoisted_2 = {\n key: 0,\n class: \"container\"\n}\nconst _hoisted_3 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode(\"div\", { id: \"bottom\" }, null, -1))\n\nimport { computed, ComputedRef, onBeforeMount } from 'vue'\n\n import NotFound from '@/components/Common/NotFound.vue'\n import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'\n import { TAppConfig, IAppStatistics } from '@/types/application'\n import { useStore } from '@/use/useStore'\n\n \nexport default /*#__PURE__*/_defineComponent({\n __name: 'AdminView',\n setup(__props) {\n\n const store = useStore()\n\n const appConfig: ComputedRef<TAppConfig> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]\n )\n const appStatistics: ComputedRef<IAppStatistics> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_STATS]\n )\n const isAuthUserAmin: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.IS_ADMIN]\n )\n const userLoading: ComputedRef<boolean> = computed(\n () => store.getters[AUTH_USER_STORE.GETTERS.USER_LOADING]\n )\n\n onBeforeMount(() => store.dispatch(ROOT_STORE.ACTIONS.GET_APPLICATION_STATS))\n\nreturn (_ctx: any,_cache: any) => {\n const _component_router_view = _resolveComponent(\"router-view\")!\n\n return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [\n (!_unref(userLoading))\n ? (_openBlock(), _createElementBlock(\"div\", _hoisted_2, [\n (_unref(isAuthUserAmin))\n ? (_openBlock(), _createBlock(_component_router_view, {\n key: 0,\n appConfig: _unref(appConfig),\n appStatistics: _unref(appStatistics)\n }, null, 8, [\"appConfig\", \"appStatistics\"]))\n : (_openBlock(), _createBlock(NotFound, { key: 1 })),\n _hoisted_3\n ]))\n : _createCommentVNode(\"\", true)\n ]))\n}\n}\n\n})","import script from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\nexport * from \"./AdminView.vue?vue&type=script&setup=true&lang=ts\"\n\nimport \"./AdminView.vue?vue&type=style&index=0&id=64629971&lang=scss&scoped=true\"\n\nimport exportComponent from \"/mnt/data-lnx/Devs/00_Perso/FitTrackee/fittrackee_client/node_modules/vue-loader/dist/exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['__scopeId',\"data-v-64629971\"]])\n\nexport default __exports__"],"names":["_withScopeId","n","_pushScopeId","_popScopeId","_hoisted_1","id","class","_hoisted_2","key","_hoisted_3","_createElementVNode","_defineComponent","__name","setup","__props","store","useStore","appConfig","computed","getters","ROOT_STORE","appStatistics","isAuthUserAmin","AUTH_USER_STORE","userLoading","onBeforeMount","dispatch","_ctx","_cache","_component_router_view","_resolveComponent","_openBlock","_createElementBlock","_unref","_createCommentVNode","_createBlock","NotFound","__exports__"],"sourceRoot":""}
|
2
fittrackee/dist/static/js/app.3c006379.js
vendored
2
fittrackee/dist/static/js/app.3c006379.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/app.bf1d4e1c.js
vendored
Normal file
2
fittrackee/dist/static/js/app.bf1d4e1c.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/app.bf1d4e1c.js.map
vendored
Normal file
1
fittrackee/dist/static/js/app.bf1d4e1c.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
60
fittrackee/dist/static/js/chunk-vendors.7132edc6.js
vendored
Normal file
60
fittrackee/dist/static/js/chunk-vendors.7132edc6.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/chunk-vendors.7132edc6.js.map
vendored
Normal file
1
fittrackee/dist/static/js/chunk-vendors.7132edc6.js.map
vendored
Normal file
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
2
fittrackee/dist/static/js/password.332510b4.js
vendored
Normal file
2
fittrackee/dist/static/js/password.332510b4.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/password.332510b4.js.map
vendored
Normal file
1
fittrackee/dist/static/js/password.332510b4.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/profile.12bdb140.js
vendored
Normal file
2
fittrackee/dist/static/js/profile.12bdb140.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[845],{4264:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(6252),a=r(2262),s=r(3577),u=r(2201),o=r(7167),i=r(8602),c=r(9917);const l={key:0,id:"account-confirmation",class:"center-card with-margin"},E={class:"error-message"};var _=(0,n.aZ)({__name:"AccountConfirmationView",setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),_=(0,c.o)(),d=(0,n.Fl)((()=>_.getters[i.SY.GETTERS.ERROR_MESSAGES])),S=(0,n.Fl)((()=>t.query.token));function m(){S.value?_.dispatch(i.YN.ACTIONS.CONFIRM_ACCOUNT,{token:S.value}):r.push("/")}return(0,n.wF)((()=>m())),(0,n.Ah)((()=>_.commit(i.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(e,t)=>{const r=(0,n.up)("router-link");return(0,a.SU)(d)?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n.Wm)(r,{class:"links",to:"/account-confirmation/resend"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("buttons.ACCOUNT-CONFIRMATION-RESEND"))+"? ",1)])),_:1})])])):(0,n.kq)("",!0)}}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-785df978"]]);var m=S},8160:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(6252),a=r(2262),s=r(3577),u=r(2201),o=r(7167),i=r(8602),c=r(9917);const l={key:0,id:"email-update",class:"center-card with-margin"},E={class:"error-message"};var _=(0,n.aZ)({__name:"EmailUpdateView",setup(e){const t=(0,u.yj)(),r=(0,u.tv)(),_=(0,c.o)(),d=(0,n.Fl)((()=>_.getters[i.YN.GETTERS.AUTH_USER_PROFILE])),S=(0,n.Fl)((()=>_.getters[i.YN.GETTERS.IS_AUTHENTICATED])),m=(0,n.Fl)((()=>_.getters[i.SY.GETTERS.ERROR_MESSAGES])),p=(0,n.Fl)((()=>t.query.token));function R(){p.value?_.dispatch(i.YN.ACTIONS.CONFIRM_EMAIL,{token:p.value,refreshUser:S.value}):r.push("/")}return(0,n.wF)((()=>R())),(0,n.Ah)((()=>_.commit(i.SY.MUTATIONS.EMPTY_ERROR_MESSAGES))),(0,n.YP)((()=>m.value),(e=>{d.value.username&&e&&r.push("/")})),(e,t)=>{const r=(0,n.up)("router-link"),u=(0,n.up)("i18n-t");return(0,a.SU)(m)&&!(0,a.SU)(d).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(o.Z),(0,n._)("p",E,[(0,n._)("span",null,(0,s.zw)(e.$t("error.SOMETHING_WRONG"))+".",1),(0,n._)("span",null,[(0,n.Wm)(u,{keypath:"user.PROFILE.ERRORED_EMAIL_UPDATE"},{default:(0,n.w5)((()=>[(0,n.Wm)(r,{to:"/login"},{default:(0,n.w5)((()=>[(0,n.Uk)((0,s.zw)(e.$t("user.LOG_IN")),1)])),_:1})])),_:1})])])])):(0,n.kq)("",!0)}}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-8c2ec9ce"]]);var m=S},6266:function(e,t,r){r.r(t),r.d(t,{default:function(){return d}});var n=r(6252),a=r(2262),s=r(8602),u=r(9917);const o=e=>((0,n.dD)("data-v-05463732"),e=e(),(0,n.Cn)(),e),i={key:0,id:"profile",class:"container view"},c=o((()=>(0,n._)("div",{id:"bottom"},null,-1)));var l=(0,n.aZ)({__name:"ProfileView",setup(e){const t=(0,u.o)(),r=(0,n.Fl)((()=>t.getters[s.YN.GETTERS.AUTH_USER_PROFILE]));return(e,t)=>{const s=(0,n.up)("router-view");return(0,a.SU)(r).username?((0,n.wg)(),(0,n.iD)("div",i,[(0,n.Wm)(s,{user:(0,a.SU)(r)},null,8,["user"]),c])):(0,n.kq)("",!0)}}}),E=r(3744);const _=(0,E.Z)(l,[["__scopeId","data-v-05463732"]]);var d=_},9453:function(e,t,r){r.r(t),r.d(t,{default:function(){return m}});var n=r(6252),a=r(2262),s=r(2201),u=r(2179),o=r(7408),i=r(8602),c=r(9917);const l={key:0,id:"user",class:"view"},E={class:"box"};var _=(0,n.aZ)({__name:"UserView",props:{fromAdmin:{type:Boolean}},setup(e){const t=e,{fromAdmin:r}=(0,a.BK)(t),_=(0,s.yj)(),d=(0,c.o)(),S=(0,n.Fl)((()=>d.getters[i.RT.GETTERS.USER]));return(0,n.wF)((()=>{_.params.username&&"string"===typeof _.params.username&&d.dispatch(i.RT.ACTIONS.GET_USER,_.params.username)})),(0,n.Jd)((()=>{d.dispatch(i.RT.ACTIONS.EMPTY_USER)})),(e,t)=>(0,a.SU)(S).username?((0,n.wg)(),(0,n.iD)("div",l,[(0,n.Wm)(u.Z,{user:(0,a.SU)(S)},null,8,["user"]),(0,n._)("div",E,[(0,n.Wm)(o.Z,{user:(0,a.SU)(S),"from-admin":(0,a.SU)(r)},null,8,["user","from-admin"])])])):(0,n.kq)("",!0)}}),d=r(3744);const S=(0,d.Z)(_,[["__scopeId","data-v-af7007f4"]]);var m=S}}]);
|
||||
//# sourceMappingURL=profile.12bdb140.js.map
|
1
fittrackee/dist/static/js/profile.12bdb140.js.map
vendored
Normal file
1
fittrackee/dist/static/js/profile.12bdb140.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[845],{2023:function(e,r,t){t.r(r),t.d(r,{default:function(){return f}});var s=t(6252),a=t(2262),n=t(8602),u=t(9917);const i=e=>((0,s.dD)("data-v-163d82f7"),e=e(),(0,s.Cn)(),e),c={key:0,id:"profile",class:"container view"},d=i((()=>(0,s._)("div",{id:"bottom"},null,-1)));var o=(0,s.aZ)({setup(e){const r=(0,u.o)(),t=(0,s.Fl)((()=>r.getters[n.YN.GETTERS.AUTH_USER_PROFILE]));return(e,r)=>{const n=(0,s.up)("router-view");return(0,a.SU)(t).username?((0,s.wg)(),(0,s.iD)("div",c,[(0,s.Wm)(n,{user:(0,a.SU)(t)},null,8,["user"]),d])):(0,s.kq)("",!0)}}}),l=t(3744);const v=(0,l.Z)(o,[["__scopeId","data-v-163d82f7"]]);var f=v},8368:function(e,r,t){t.r(r),t.d(r,{default:function(){return m}});var s=t(6252),a=t(2262),n=t(2119),u=t(5160),i=t(2165),c=t(8602),d=t(9917);const o={key:0,id:"user",class:"view"},l={class:"box"};var v=(0,s.aZ)({setup(e){const r=(0,n.yj)(),t=(0,d.o)(),v=(0,s.Fl)((()=>t.getters[c.RT.GETTERS.USER]));return(0,s.wF)((()=>{r.params.username&&"string"===typeof r.params.username&&t.dispatch(c.RT.ACTIONS.GET_USER,r.params.username)})),(0,s.Jd)((()=>{t.dispatch(c.RT.ACTIONS.EMPTY_USER)})),(e,r)=>(0,a.SU)(v).username?((0,s.wg)(),(0,s.iD)("div",o,[(0,s.Wm)(u.Z,{user:(0,a.SU)(v)},null,8,["user"]),(0,s._)("div",l,[(0,s.Wm)(i.Z,{user:(0,a.SU)(v),"from-admin":!0},null,8,["user"])])])):(0,s.kq)("",!0)}}),f=t(3744);const p=(0,f.Z)(v,[["__scopeId","data-v-10e7b479"]]);var m=p}}]);
|
||||
//# sourceMappingURL=profile.97ac14b7.js.map
|
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/reset.75789a8c.js
vendored
2
fittrackee/dist/static/js/reset.75789a8c.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/reset.90b2d965.js
vendored
Normal file
2
fittrackee/dist/static/js/reset.90b2d965.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/reset.90b2d965.js.map
vendored
Normal file
1
fittrackee/dist/static/js/reset.90b2d965.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/statistics.1ad194e3.js
vendored
Normal file
2
fittrackee/dist/static/js/statistics.1ad194e3.js
vendored
Normal file
@@ -0,0 +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.1ad194e3.js.map
|
1
fittrackee/dist/static/js/statistics.1ad194e3.js.map
vendored
Normal file
1
fittrackee/dist/static/js/statistics.1ad194e3.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
"use strict";(self["webpackChunkfittrackee_client"]=self["webpackChunkfittrackee_client"]||[]).push([[193],{2319:function(e,s,t){t.r(s),t.d(s,{default:function(){return A}});var r=t(6252),a=t(2262),l=t(3577),o=t(3324),c=t(9472);const n={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,r.aZ)({emits:["arrowClick","timeFrameUpdate"],setup(e,{emit:s}){let t=(0,a.iH)("month");const o=["week","month","year"];function c(e){t.value=e,s("timeFrameUpdate",e)}return(e,v)=>((0,r.wg)(),(0,r.iD)("div",n,[(0,r._)("div",i,[(0,r._)("i",{class:"fa fa-chevron-left","aria-hidden":"true",onClick:v[0]||(v[0]=e=>s("arrowClick",!0))})]),(0,r._)("div",u,[(0,r._)("div",d,[((0,r.wg)(),(0,r.iD)(r.HY,null,(0,r.Ko)(o,(s=>(0,r._)("div",{class:"time-frame custom-checkbox",key:s},[(0,r._)("label",null,[(0,r._)("input",{type:"radio",id:s,name:s,checked:(0,a.SU)(t)===s,onInput:e=>c(s)},null,40,p),(0,r._)("span",null,(0,l.zw)(e.$t(`statistics.TIME_FRAMES.${s}`)),1)])]))),64))])]),(0,r._)("div",m,[(0,r._)("i",{class:"fa fa-chevron-right","aria-hidden":"true",onClick:v[1]||(v[1]=e=>s("arrowClick",!1))})])]))}}),k=t(3744);const S=(0,k.Z)(v,[["__scopeId","data-v-af15954c"]]);var w=S,f=t(631);const _={class:"sports-menu"},h=["id","name","checked","onInput"],U={class:"sport-label"};var b=(0,r.aZ)({props:{userSports:null,selectedSportIds:{default:()=>[]}},emits:["selectedSportIdsUpdate"],setup(e,{emit:s}){const t=e,{t:c}=(0,o.QT)(),n=(0,r.f3)("sportColors"),{selectedSportIds:i}=(0,a.BK)(t),u=(0,r.Fl)((()=>(0,f.xH)(t.userSports,c)));function d(e){s("selectedSportIdsUpdate",e)}return(e,s)=>{const t=(0,r.up)("SportImage");return(0,r.wg)(),(0,r.iD)("div",_,[((0,r.wg)(!0),(0,r.iD)(r.HY,null,(0,r.Ko)((0,a.SU)(u),(e=>((0,r.wg)(),(0,r.iD)("label",{type:"checkbox",key:e.id,style:(0,l.j5)({color:e.color?e.color:(0,a.SU)(n)[e.label]})},[(0,r._)("input",{type:"checkbox",id:e.id,name:e.label,checked:(0,a.SU)(i).includes(e.id),onInput:s=>d(e.id)},null,40,h),(0,r.Wm)(t,{"sport-label":e.label,color:e.color},null,8,["sport-label","color"]),(0,r._)("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,r.aZ)({props:{sports:null,user:null},setup(e){const s=e,{t:t}=(0,o.QT)(),{sports:l,user:n}=(0,a.BK)(s);let i=(0,a.iH)("month");const u=(0,a.iH)(v(i.value)),d=(0,r.Fl)((()=>(0,f.xH)(s.sports,t))),p=(0,a.iH)(S(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 S(e){return e.map((e=>e.id))}function _(e){p.value.includes(e)?p.value=p.value.filter((s=>s!==e)):p.value.push(e)}return(0,r.YP)((()=>s.sports),(e=>{p.value=S(e)})),(e,s)=>(0,a.SU)(d)?((0,r.wg)(),(0,r.iD)("div",y,[(0,r.Wm)(w,{onTimeFrameUpdate:m,onArrowClick:k}),(0,r.Wm)(c.Z,{sports:(0,a.SU)(l),user:(0,a.SU)(n),chartParams:u.value,"displayed-sport-ids":p.value,fullStats:!0},null,8,["sports","user","chartParams","displayed-sport-ids"]),(0,r.Wm)(g,{"selected-sport-ids":p.value,"user-sports":(0,a.SU)(l),onSelectedSportIdsUpdate:_},null,8,["selected-sport-ids","user-sports"])])):(0,r.kq)("",!0)}});const F=(0,k.Z)(C,[["__scopeId","data-v-7d54529b"]]);var Z=F,D=t(5630),H=t(8602),x=t(9917);const E={id:"statistics",class:"view"},R={key:0,class:"container"};var W=(0,r.aZ)({setup(e){const s=(0,x.o)(),t=(0,r.Fl)((()=>s.getters[H.YN.GETTERS.AUTH_USER_PROFILE])),o=(0,r.Fl)((()=>s.getters[H.O8.GETTERS.SPORTS].filter((e=>t.value.sports_list.includes(e.id)))));return(e,s)=>{const c=(0,r.up)("Card");return(0,r.wg)(),(0,r.iD)("div",E,[(0,a.SU)(t).username?((0,r.wg)(),(0,r.iD)("div",R,[(0,r.Wm)(c,null,{title:(0,r.w5)((()=>[(0,r.Uk)((0,l.zw)(e.$t("statistics.STATISTICS")),1)])),content:(0,r.w5)((()=>[(0,r.Wm)(Z,{class:(0,l.C_)({"stats-disabled":0===(0,a.SU)(t).nb_workouts}),user:(0,a.SU)(t),sports:(0,a.SU)(o)},null,8,["class","user","sports"])])),_:1}),0===(0,a.SU)(t).nb_workouts?((0,r.wg)(),(0,r.j4)(D.Z,{key:0})):(0,r.kq)("",!0)])):(0,r.kq)("",!0)])}}});const P=(0,k.Z)(W,[["__scopeId","data-v-0d93da6e"]]);var A=P}}]);
|
||||
//# sourceMappingURL=statistics.221180ef.js.map
|
File diff suppressed because one or more lines are too long
2
fittrackee/dist/static/js/workouts.22600b70.js
vendored
Normal file
2
fittrackee/dist/static/js/workouts.22600b70.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/workouts.22600b70.js.map
vendored
Normal file
1
fittrackee/dist/static/js/workouts.22600b70.js.map
vendored
Normal file
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
1
fittrackee/dist/workbox-03ef139c.js.map
vendored
1
fittrackee/dist/workbox-03ef139c.js.map
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
fittrackee/dist/workbox-2d118ab0.js.map
vendored
Normal file
1
fittrackee/dist/workbox-2d118ab0.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -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:
|
||||
@@ -131,9 +163,11 @@ class EmailService:
|
||||
with self.smtp(
|
||||
self.host, self.port, **connection_params # type: ignore
|
||||
) as smtp:
|
||||
if self.use_tls:
|
||||
smtp.ehlo()
|
||||
smtp.starttls(context=context)
|
||||
smtp.ehlo()
|
||||
if self.username and self.password:
|
||||
smtp.login(self.username, self.password) # type: ignore
|
||||
if self.use_tls:
|
||||
smtp.starttls(context=context)
|
||||
smtp.sendmail(self.sender_email, recipient, message.as_string())
|
||||
smtp.quit()
|
||||
|
@@ -11,3 +11,43 @@ def reset_password_email(user: Dict, email_data: Dict) -> None:
|
||||
recipient=user['email'],
|
||||
data=email_data,
|
||||
)
|
||||
|
||||
|
||||
@dramatiq.actor(queue_name='fittrackee_emails')
|
||||
def email_updated_to_current_address(user: Dict, email_data: Dict) -> None:
|
||||
email_service.send(
|
||||
template='email_update_to_current_email',
|
||||
lang=user['language'],
|
||||
recipient=user['email'],
|
||||
data=email_data,
|
||||
)
|
||||
|
||||
|
||||
@dramatiq.actor(queue_name='fittrackee_emails')
|
||||
def email_updated_to_new_address(user: Dict, email_data: Dict) -> None:
|
||||
email_service.send(
|
||||
template='email_update_to_new_email',
|
||||
lang=user['language'],
|
||||
recipient=user['email'],
|
||||
data=email_data,
|
||||
)
|
||||
|
||||
|
||||
@dramatiq.actor(queue_name='fittrackee_emails')
|
||||
def password_change_email(user: Dict, email_data: Dict) -> None:
|
||||
email_service.send(
|
||||
template='password_change',
|
||||
lang=user['language'],
|
||||
recipient=user['email'],
|
||||
data=email_data,
|
||||
)
|
||||
|
||||
|
||||
@dramatiq.actor(queue_name='fittrackee_emails')
|
||||
def account_confirmation_email(user: Dict, email_data: Dict) -> None:
|
||||
email_service.send(
|
||||
template='account_confirmation',
|
||||
lang=user['language'],
|
||||
recipient=user['email'],
|
||||
data=email_data,
|
||||
)
|
||||
|
26
fittrackee/emails/templates/account_confirmation/body.html
Normal file
26
fittrackee/emails/templates/account_confirmation/body.html
Normal 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 %}
|
@@ -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 %}
|
@@ -0,0 +1 @@
|
||||
FitTrackee - {{ _('Confirm your account') }}
|
@@ -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 %}
|
@@ -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 %}
|
@@ -0,0 +1 @@
|
||||
FitTrackee - {{ _('Email changed') }}
|
@@ -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 %}
|
@@ -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 %}
|
@@ -0,0 +1 @@
|
||||
FitTrackee - {{ _('Confirm email change') }}
|
@@ -4,7 +4,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="x-apple-disable-message-reformatting" content=""/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Fittrackee - Password reset request</title>
|
||||
<title>FitTrackee - {% block title %}{% endblock %}</title>
|
||||
<style type="text/css" rel="stylesheet" media="all">
|
||||
|
||||
body {
|
||||
@@ -194,14 +194,14 @@
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<span class="preheader">Use this link to reset your password. The link is only valid for {{ expiration_delay }}.</span>
|
||||
<span class="preheader">{% block preheader %}{% endblock %}</span>
|
||||
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table class="email-content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td class="email-masthead">
|
||||
<a href="https://example.com" class="f-fallback email-masthead-name">
|
||||
<a href="{{fittrackee_url}}" class="f-fallback email-masthead-name">
|
||||
FitTrackee
|
||||
</a>
|
||||
</td>
|
||||
@@ -212,37 +212,15 @@
|
||||
<tr>
|
||||
<td class="content-cell">
|
||||
<div class="f-fallback">
|
||||
<h1>Hi {{username}},</h1>
|
||||
<p>You recently requested to reset your password for your account. Use the button below to reset it.
|
||||
<strong>This password reset link is only valid for {{ expiration_delay }}.</strong>
|
||||
</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="{{password_reset_url}}" class="f-fallback button button--green" target="_blank">Reset your password</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h1>{{ _('Hi %(username)s,', username=username) }}</h1>
|
||||
{% block content %}{% endblock %}
|
||||
<p>
|
||||
For security, this request was received from a {{operating_system}} device using {{browser_name}}.
|
||||
If you did not request a password reset, please ignore this email.
|
||||
{% 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 %}{% block not_initiated %}{% endblock %}
|
||||
</p>
|
||||
<p>Thanks,
|
||||
<br>The FitTrackee Team</p>
|
||||
<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">{{password_reset_url}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>{{ _('Thanks,') }}
|
||||
<br>{{ _('The FitTrackee Team') }}</p>
|
||||
{% block url_to_paste %}{% endblock %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
7
fittrackee/emails/templates/layout.txt
Normal file
7
fittrackee/emails/templates/layout.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
{{ _('Hi %(username)s,', username=username) }}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
{{ _('Thanks,') }}
|
||||
{{ _('The FitTrackee Team') }}
|
||||
{{fittrackee_url}}
|
5
fittrackee/emails/templates/password_change/body.html
Normal file
5
fittrackee/emails/templates/password_change/body.html
Normal file
@@ -0,0 +1,5 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block title %}{{ _('Password changed') }}{% endblock %}
|
||||
{% block preheader %}{{ _('Your password has been changed.') }}{% endblock %}
|
||||
{% block content %}<p>{{ _('The password for your FitTrackee account has been changed.') }}</p>{% endblock %}
|
||||
{% block not_initiated %}{{ _("If this password change wasn't initiated by you, please change your password immediately or contact your administrator if your account is locked.") }}{% endblock %}
|
4
fittrackee/emails/templates/password_change/body.txt
Normal file
4
fittrackee/emails/templates/password_change/body.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
{% extends "layout.txt" %}{% block content %}{{ _('The password for your FitTrackee account has been changed.') }}
|
||||
|
||||
{% 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 password change wasn't initiated by you, please change your password immediately or contact your administrator if your account is locked.") }}{% endblock %}
|
1
fittrackee/emails/templates/password_change/subject.txt
Normal file
1
fittrackee/emails/templates/password_change/subject.txt
Normal file
@@ -0,0 +1 @@
|
||||
FitTrackee - {{ _('Password changed') }}
|
28
fittrackee/emails/templates/password_reset_request/body.html
Normal file
28
fittrackee/emails/templates/password_reset_request/body.html
Normal file
@@ -0,0 +1,28 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block title %}{{ _('Password reset request') }}{% endblock %}
|
||||
{% block preheader %}{{ _('Use this link to reset your password. The link is only valid for %(expiration_delay)s.', expiration_delay=expiration_delay) }}{% endblock %}
|
||||
{% block content %}<p>{{ _('You recently requested to reset your password for your FitTrackee account.') }} {{ _('Use the button below to reset it.') }}
|
||||
<strong>{{ _('This password reset link is only valid for %(expiration_delay)s.', expiration_delay=expiration_delay) }}</strong>
|
||||
</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="{{password_reset_url}}" class="f-fallback button button--green" target="_blank">{{ _('Reset your password') }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>{% endblock %}
|
||||
{% block not_initiated %}{{ _('If you did not request a password reset, 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">{{password_reset_url}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>{% endblock %}
|
@@ -0,0 +1,7 @@
|
||||
{% extends "layout.txt" %}{% block content %}{{ _('You recently requested to reset your password for your FitTrackee account.') }} {{ _('Use the link below to reset it.') }}
|
||||
{{ _('This password reset link is only valid for %(expiration_delay)s.', expiration_delay=expiration_delay) }}
|
||||
|
||||
{{ _('Reset your password') }}: {{ password_reset_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 you did not request a password reset, please ignore this email.') }}{% endblock %}
|
@@ -1,10 +0,0 @@
|
||||
Hi {{username}},
|
||||
|
||||
You recently requested to reset your password for your FitTrackee account. Use the button below to reset it. This password reset link is only valid for {{ expiration_delay }}.
|
||||
|
||||
Reset your password ( {{ password_reset_url }} )
|
||||
|
||||
For security, this request was received from a {{operating_system}} device using {{browser_name}}. If you did not request a password reset, please ignore this email.
|
||||
|
||||
Thanks,
|
||||
The FitTrackee Team
|
@@ -1 +0,0 @@
|
||||
FitTrackee - Password reset request
|
@@ -1,269 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="x-apple-disable-message-reformatting" content=""/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>FitTrackee - Réinitialiser le mot de passe</title>
|
||||
<style type="text/css" rel="stylesheet" media="all">
|
||||
|
||||
body {
|
||||
background-color: #F4F4F7;
|
||||
color: #51545E;
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3869D4;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
td {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.preheader {
|
||||
display: none !important;
|
||||
visibility: hidden;
|
||||
mso-hide: all;
|
||||
font-size: 1px;
|
||||
line-height: 1px;
|
||||
max-height: 0;
|
||||
max-width: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body,
|
||||
td,
|
||||
th {
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
color: #333333;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #51545E;
|
||||
margin: .4em 0 1.1875em;
|
||||
font-size: 16px;
|
||||
line-height: 1.625;
|
||||
}
|
||||
|
||||
p.sub {
|
||||
color: #6B6E76;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.button {
|
||||
background-color: #3869D4;
|
||||
border-top: 10px solid #3869D4;
|
||||
border-right: 18px solid #3869D4;
|
||||
border-bottom: 10px solid #3869D4;
|
||||
border-left: 18px solid #3869D4;
|
||||
display: inline-block;
|
||||
color: #FFF;
|
||||
text-decoration: none;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
|
||||
-webkit-text-size-adjust: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.button--green {
|
||||
background-color: #22BC66;
|
||||
border-top: 10px solid #22BC66;
|
||||
border-right: 18px solid #22BC66;
|
||||
border-bottom: 10px solid #22BC66;
|
||||
border-left: 18px solid #22BC66;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
.button {
|
||||
width: 100% !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
}
|
||||
|
||||
.email-wrapper {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #F4F4F7;
|
||||
}
|
||||
|
||||
.email-content {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.email-masthead {
|
||||
padding: 25px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.email-masthead-name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #A8AAAF;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px 0 white;
|
||||
}
|
||||
|
||||
.email-body {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.email-body-inner {
|
||||
width: 570px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.body-action {
|
||||
width: 100%;
|
||||
margin: 30px auto;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.body-sub {
|
||||
margin-top: 25px;
|
||||
padding-top: 25px;
|
||||
border-top: 1px solid #EAEAEC;
|
||||
}
|
||||
|
||||
.content-cell {
|
||||
padding: 35px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
.email-body-inner,
|
||||
.email-footer {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body,
|
||||
.email-body,
|
||||
.email-body-inner,
|
||||
.email-content,
|
||||
.email-wrapper,
|
||||
.email-masthead,
|
||||
.email-footer {
|
||||
background-color: #333333 !important;
|
||||
color: #FFF !important;
|
||||
}
|
||||
p,
|
||||
h1 {
|
||||
color: #FFF !important;
|
||||
}
|
||||
.email-masthead-name {
|
||||
text-shadow: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<!--[if mso]>
|
||||
<style type="text/css">
|
||||
.f-fallback {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<span class="preheader">Utiliser ce lien pour réinitialiser le mot de passe. Ce lien n'est valide que pendant {{ expiration_delay }}.</span>
|
||||
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table class="email-content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td class="email-masthead">
|
||||
<a href="https://example.com" class="f-fallback email-masthead-name">
|
||||
FitTrackee
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="email-body" width="100%" cellpadding="0" cellspacing="0">
|
||||
<table class="email-body-inner" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td class="content-cell">
|
||||
<div class="f-fallback">
|
||||
<h1>Bonjour {{username}},</h1>
|
||||
<p>Vous avez récemment demander la réinitilisation du mot de passe de votre compte sur FitTrackee.
|
||||
Cliquez sur le bouton ci-dessous pour le réinitialiser.
|
||||
<strong>Cette réinitialisation n'est valide que pendant {{ expiration_delay }}.</strong>
|
||||
</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="{{password_reset_url}}" class="f-fallback button button--green" target="_blank">Réinitialiser le mot de passe</a>
|
||||
</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'avez pas demandé de réinitalisation, 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">{{password_reset_url}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td class="content-cell" align="center">
|
||||
<p class="f-fallback sub align-center">© FitTrackee.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
@@ -1,12 +0,0 @@
|
||||
Bonjour {{username}},
|
||||
|
||||
Vous avez récemment demander la réinitilisation du mot de passe de votre compte sur FitTrackee.
|
||||
Cliquez sur le lien ci-dessous pour le réinitialiser. Ce lien n'est valide que pendant {{ expiration_delay }}.
|
||||
|
||||
Réinitialiser le mot de passe: ( {{ password_reset_url }} )
|
||||
|
||||
Pour vérification, cette demande a été reçue à partir d'un appareil sous {{operating_system}}, utilisant le navigateur {{browser_name}}.
|
||||
Si vous n'avez pas demandé de réinitalisation, vous pouvez ignorer cet e-mail.
|
||||
|
||||
Merci,
|
||||
L'équipe FitTrackee
|
@@ -1 +0,0 @@
|
||||
FitTrackee - Réinitialiser votre mot de passe
|
@@ -0,0 +1 @@
|
||||
FitTrackee - {{ _('Password reset request') }}
|
BIN
fittrackee/emails/translations/de/LC_MESSAGES/messages.mo
Normal file
BIN
fittrackee/emails/translations/de/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
231
fittrackee/emails/translations/de/LC_MESSAGES/messages.po
Normal file
231
fittrackee/emails/translations/de/LC_MESSAGES/messages.po
Normal file
@@ -0,0 +1,231 @@
|
||||
# German translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-07-03 07:58+0200\n"
|
||||
"PO-Revision-Date: 2022-07-02 18:25+0200\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: de\n"
|
||||
"Language-Team: de <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.10.3\n"
|
||||
|
||||
#: fittrackee/emails/templates/layout.html:215
|
||||
#: fittrackee/emails/templates/layout.txt:1
|
||||
#, python-format
|
||||
msgid "Hi %(username)s,"
|
||||
msgstr "Hallo %(username)s,"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:6
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:3
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:6
|
||||
#: fittrackee/emails/templates/layout.html:218
|
||||
#: fittrackee/emails/templates/password_change/body.txt:3
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:6
|
||||
#, python-format
|
||||
msgid ""
|
||||
"For security, this request was received from a %(operating_system)s "
|
||||
"device using %(browser_name)s."
|
||||
msgstr ""
|
||||
"Zur Sicherheit: Diese Anfrage wurde von einem %(operating_system)s Gerät "
|
||||
"mit %(browser_name)s ausgelöst."
|
||||
|
||||
#: fittrackee/emails/templates/layout.html:221
|
||||
#: fittrackee/emails/templates/layout.txt:5
|
||||
msgid "Thanks,"
|
||||
msgstr "Danke"
|
||||
|
||||
#: fittrackee/emails/templates/layout.html:222
|
||||
#: fittrackee/emails/templates/layout.txt:6
|
||||
msgid "The FitTrackee Team"
|
||||
msgstr "Dein FitTrackee Team"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:2
|
||||
#: fittrackee/emails/templates/account_confirmation/subject.txt:1
|
||||
msgid "Confirm your account"
|
||||
msgstr "Bestätige Dein Konto"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:3
|
||||
msgid "Use this link to confirm your account."
|
||||
msgstr "Verwendet diesen Link um Dein Konto zu bestätigen."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:4
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:1
|
||||
msgid "You have created an account on FitTrackee."
|
||||
msgstr "Du hast ein Konto bei FitTrackee angelegt."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:4
|
||||
msgid "Use the button below to confirm your address email."
|
||||
msgstr "Verwende den unteren Button um Deine E-Mail Adresse zu bestätigen."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:11
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:4
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:11
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:4
|
||||
msgid "Verify your email"
|
||||
msgstr "Bestätige Deine E-Mail"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:18
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:7
|
||||
msgid ""
|
||||
"If this account creation wasn't initiated by you, please ignore this "
|
||||
"email."
|
||||
msgstr ""
|
||||
"Falls die Kontoerstellung nicht von Dir initiiert wurde, ignoriere diese "
|
||||
"E-Mail bitte."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:22
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:22
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:24
|
||||
msgid ""
|
||||
"If you're having trouble with the button above, copy and paste the URL "
|
||||
"below into your web browser."
|
||||
msgstr ""
|
||||
"Falls Du Probleme mit dem oberen Button hast, kopiere diese URL und gebe "
|
||||
"sie in Deinen Webbrowser ein."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:2
|
||||
msgid "Use the link below to confirm your address email."
|
||||
msgstr "Verwende den unteren Link um Deine E-Mail Adresse zu bestätigen."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:2
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/subject.txt:1
|
||||
msgid "Email changed"
|
||||
msgstr "E-Mail Adresse geändert"
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:3
|
||||
msgid "Your email is being updated."
|
||||
msgstr "Deine E-Mail Adresse wure aktualisiert."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:4
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:1
|
||||
msgid ""
|
||||
"You recently requested to change your email address for your FitTrackee "
|
||||
"account to:"
|
||||
msgstr ""
|
||||
"Du hast kürzlich beantragt, die E-Mail Adresse Deines FitTrackee Kontos "
|
||||
"zu ändern. Neue Adresse:"
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:18
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:4
|
||||
msgid ""
|
||||
"If this email change wasn't initiated by you, please change your password"
|
||||
" immediately or contact your administrator if your account is locked."
|
||||
msgstr ""
|
||||
"Falls die Änderung der E-Mail Adresse nicht von Dir initiiert wurde, "
|
||||
"ändere bitte sofort Dein Passwort oder kontaktiere den Administrator, "
|
||||
"falls Dein Konto gesperrt ist."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:2
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/subject.txt:1
|
||||
msgid "Confirm email change"
|
||||
msgstr "Bestätige E-Mail Änderung"
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:3
|
||||
msgid "Use this link to confirm email change."
|
||||
msgstr "Verwende den unteren Link um Deine Adresse zu bestätigen."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:4
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:1
|
||||
msgid ""
|
||||
"You recently requested to change your email address for your FitTrackee "
|
||||
"account."
|
||||
msgstr ""
|
||||
"Du hast kürzlich beantragt, die E-Mail Adresse Deines FitTrackee Kontos "
|
||||
"zu ändern."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:4
|
||||
msgid "Use the button below to confirm this address."
|
||||
msgstr "Verwende den unteren Button um Deine Adresse zu bestätigen."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:18
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:7
|
||||
msgid "If this email change wasn't initiated by you, please ignore this email."
|
||||
msgstr ""
|
||||
"Falls die Änderung der E-Mail Adresse nicht von Dir initiiert wurde, "
|
||||
"ignoriere diese E-Mail bitte."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:2
|
||||
msgid "Use the link below to confirm this address."
|
||||
msgstr "Verwende den unteren Link um Deine Adresse zu bestätigen."
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:2
|
||||
#: fittrackee/emails/templates/password_change/subject.txt:1
|
||||
msgid "Password changed"
|
||||
msgstr "Passwort geändert"
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:3
|
||||
msgid "Your password has been changed."
|
||||
msgstr "Dein Passwort wurde geändert."
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:4
|
||||
#: fittrackee/emails/templates/password_change/body.txt:1
|
||||
msgid "The password for your FitTrackee account has been changed."
|
||||
msgstr "Das Passwort Deines FitTrackee Kontos wurde geändert."
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:5
|
||||
#: fittrackee/emails/templates/password_change/body.txt:4
|
||||
msgid ""
|
||||
"If this password change wasn't initiated by you, please change your "
|
||||
"password immediately or contact your administrator if your account is "
|
||||
"locked."
|
||||
msgstr ""
|
||||
"Falls die Änderung des Passworts nicht von Dir initiiert wurde, ändere "
|
||||
"bitte sofort Dein Passwort oder kontaktiere den Administrator, falls Dein"
|
||||
" Konto gesperrt ist."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:2
|
||||
#: fittrackee/emails/templates/password_reset_request/subject.txt:1
|
||||
msgid "Password reset request"
|
||||
msgstr "Anfrage zum Zurücksetzen des Passworts"
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:3
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Use this link to reset your password. The link is only valid for "
|
||||
"%(expiration_delay)s."
|
||||
msgstr ""
|
||||
"Verwende den unteren Link um Dein Passwort zurückzusetzen. Der Link ist "
|
||||
"nur für %(expiration_delay)s gültig."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:4
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:1
|
||||
msgid "You recently requested to reset your password for your FitTrackee account."
|
||||
msgstr ""
|
||||
"Du hast kürzlich beantragt, das Passwort Deines FitTrackee Kontos "
|
||||
"zurückzusetzen."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:4
|
||||
msgid "Use the button below to reset it."
|
||||
msgstr "Verwende den unteren Button um es zurückzusetzen."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:5
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:2
|
||||
#, python-format
|
||||
msgid "This password reset link is only valid for %(expiration_delay)s."
|
||||
msgstr "Der Link ist nur für %(expiration_delay)s gültig."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:13
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:4
|
||||
msgid "Reset your password"
|
||||
msgstr "Setze Dein Passwort zurück"
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:20
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:7
|
||||
msgid "If you did not request a password reset, please ignore this email."
|
||||
msgstr ""
|
||||
"Falls Du das Zurücksetzen des Passworts nicht angefordert hast, igoniere "
|
||||
"diese E-Mail bitte."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:1
|
||||
msgid "Use the link below to reset it."
|
||||
msgstr "Verwende den unteren Link um es zurückzusetzen."
|
||||
|
BIN
fittrackee/emails/translations/en/LC_MESSAGES/messages.mo
Normal file
BIN
fittrackee/emails/translations/en/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
224
fittrackee/emails/translations/en/LC_MESSAGES/messages.po
Normal file
224
fittrackee/emails/translations/en/LC_MESSAGES/messages.po
Normal file
@@ -0,0 +1,224 @@
|
||||
# English translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-07-03 07:58+0200\n"
|
||||
"PO-Revision-Date: 2022-07-02 18:25+0200\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: en\n"
|
||||
"Language-Team: en <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.10.3\n"
|
||||
|
||||
#: fittrackee/emails/templates/layout.html:215
|
||||
#: fittrackee/emails/templates/layout.txt:1
|
||||
#, python-format
|
||||
msgid "Hi %(username)s,"
|
||||
msgstr "Hi %(username)s,"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:6
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:3
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:6
|
||||
#: fittrackee/emails/templates/layout.html:218
|
||||
#: fittrackee/emails/templates/password_change/body.txt:3
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:6
|
||||
#, python-format
|
||||
msgid ""
|
||||
"For security, this request was received from a %(operating_system)s "
|
||||
"device using %(browser_name)s."
|
||||
msgstr ""
|
||||
"For security, this request was received from a %(operating_system)s "
|
||||
"device using %(browser_name)s."
|
||||
|
||||
#: fittrackee/emails/templates/layout.html:221
|
||||
#: fittrackee/emails/templates/layout.txt:5
|
||||
msgid "Thanks,"
|
||||
msgstr "Thanks,"
|
||||
|
||||
#: fittrackee/emails/templates/layout.html:222
|
||||
#: fittrackee/emails/templates/layout.txt:6
|
||||
msgid "The FitTrackee Team"
|
||||
msgstr "The FitTrackee Team"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:2
|
||||
#: fittrackee/emails/templates/account_confirmation/subject.txt:1
|
||||
msgid "Confirm your account"
|
||||
msgstr "Confirm your account"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:3
|
||||
msgid "Use this link to confirm your account."
|
||||
msgstr "Use this link to confirm your account."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:4
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:1
|
||||
msgid "You have created an account on FitTrackee."
|
||||
msgstr "You have created an account on FitTrackee."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:4
|
||||
msgid "Use the button below to confirm your address email."
|
||||
msgstr "Use the button below to confirm your address email."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:11
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:4
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:11
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:4
|
||||
msgid "Verify your email"
|
||||
msgstr "Verify your email"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:18
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:7
|
||||
msgid ""
|
||||
"If this account creation wasn't initiated by you, please ignore this "
|
||||
"email."
|
||||
msgstr ""
|
||||
"If this account creation wasn't initiated by you, please ignore this "
|
||||
"email."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:22
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:22
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:24
|
||||
msgid ""
|
||||
"If you're having trouble with the button above, copy and paste the URL "
|
||||
"below into your web browser."
|
||||
msgstr ""
|
||||
"If you're having trouble with the button above, copy and paste the URL "
|
||||
"below into your web browser."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:2
|
||||
msgid "Use the link below to confirm your address email."
|
||||
msgstr "Use the link below to confirm your address email."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:2
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/subject.txt:1
|
||||
msgid "Email changed"
|
||||
msgstr "Email changed"
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:3
|
||||
msgid "Your email is being updated."
|
||||
msgstr "Your email is being updated."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:4
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:1
|
||||
msgid ""
|
||||
"You recently requested to change your email address for your FitTrackee "
|
||||
"account to:"
|
||||
msgstr ""
|
||||
"You recently requested to change your email address for your FitTrackee "
|
||||
"account to:"
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:18
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:4
|
||||
msgid ""
|
||||
"If this email change wasn't initiated by you, please change your password"
|
||||
" immediately or contact your administrator if your account is locked."
|
||||
msgstr ""
|
||||
"If this email change wasn't initiated by you, please change your password"
|
||||
" immediately or contact your administrator if your account is locked."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:2
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/subject.txt:1
|
||||
msgid "Confirm email change"
|
||||
msgstr "Confirm email change"
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:3
|
||||
msgid "Use this link to confirm email change."
|
||||
msgstr "Use this link to confirm email change."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:4
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:1
|
||||
msgid ""
|
||||
"You recently requested to change your email address for your FitTrackee "
|
||||
"account."
|
||||
msgstr ""
|
||||
"You recently requested to change your email address for your FitTrackee "
|
||||
"account."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:4
|
||||
msgid "Use the button below to confirm this address."
|
||||
msgstr "Use the button below to confirm this address."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:18
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:7
|
||||
msgid "If this email change wasn't initiated by you, please ignore this email."
|
||||
msgstr "If this email change wasn't initiated by you, please ignore this email."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:2
|
||||
msgid "Use the link below to confirm this address."
|
||||
msgstr "Use the link below to confirm this address."
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:2
|
||||
#: fittrackee/emails/templates/password_change/subject.txt:1
|
||||
msgid "Password changed"
|
||||
msgstr "Password changed"
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:3
|
||||
msgid "Your password has been changed."
|
||||
msgstr "Your password has been changed."
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:4
|
||||
#: fittrackee/emails/templates/password_change/body.txt:1
|
||||
msgid "The password for your FitTrackee account has been changed."
|
||||
msgstr "The password for your FitTrackee account has been changed."
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:5
|
||||
#: fittrackee/emails/templates/password_change/body.txt:4
|
||||
msgid ""
|
||||
"If this password change wasn't initiated by you, please change your "
|
||||
"password immediately or contact your administrator if your account is "
|
||||
"locked."
|
||||
msgstr ""
|
||||
"If this password change wasn't initiated by you, please change your "
|
||||
"password immediately or contact your administrator if your account is "
|
||||
"locked."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:2
|
||||
#: fittrackee/emails/templates/password_reset_request/subject.txt:1
|
||||
msgid "Password reset request"
|
||||
msgstr "Password reset request"
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:3
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Use this link to reset your password. The link is only valid for "
|
||||
"%(expiration_delay)s."
|
||||
msgstr ""
|
||||
"Use this link to reset your password. The link is only valid for "
|
||||
"%(expiration_delay)s."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:4
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:1
|
||||
msgid "You recently requested to reset your password for your FitTrackee account."
|
||||
msgstr "You recently requested to reset your password for your FitTrackee account."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:4
|
||||
msgid "Use the button below to reset it."
|
||||
msgstr "Use the button below to reset it."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:5
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:2
|
||||
#, python-format
|
||||
msgid "This password reset link is only valid for %(expiration_delay)s."
|
||||
msgstr "This password reset link is only valid for %(expiration_delay)s."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:13
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:4
|
||||
msgid "Reset your password"
|
||||
msgstr "Reset your password"
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:20
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:7
|
||||
msgid "If you did not request a password reset, please ignore this email."
|
||||
msgstr "If you did not request a password reset, please ignore this email."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:1
|
||||
msgid "Use the link below to reset it."
|
||||
msgstr "Use the link below to reset it."
|
||||
|
BIN
fittrackee/emails/translations/fr/LC_MESSAGES/messages.mo
Normal file
BIN
fittrackee/emails/translations/fr/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
231
fittrackee/emails/translations/fr/LC_MESSAGES/messages.po
Normal file
231
fittrackee/emails/translations/fr/LC_MESSAGES/messages.po
Normal file
@@ -0,0 +1,231 @@
|
||||
# French translations for PROJECT.
|
||||
# Copyright (C) 2022 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2022-07-03 07:58+0200\n"
|
||||
"PO-Revision-Date: 2022-07-02 17:27+0200\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language: fr\n"
|
||||
"Language-Team: fr <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 2.10.3\n"
|
||||
|
||||
#: fittrackee/emails/templates/layout.html:215
|
||||
#: fittrackee/emails/templates/layout.txt:1
|
||||
#, python-format
|
||||
msgid "Hi %(username)s,"
|
||||
msgstr "Bonjour %(username)s,"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:6
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:3
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:6
|
||||
#: fittrackee/emails/templates/layout.html:218
|
||||
#: fittrackee/emails/templates/password_change/body.txt:3
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:6
|
||||
#, python-format
|
||||
msgid ""
|
||||
"For security, this request was received from a %(operating_system)s "
|
||||
"device using %(browser_name)s."
|
||||
msgstr ""
|
||||
"Pour vérification, cette demande a été reçue à partir d'un appareil sous "
|
||||
"%(operating_system)s, utilisant le navigateur %(browser_name)s."
|
||||
|
||||
#: fittrackee/emails/templates/layout.html:221
|
||||
#: fittrackee/emails/templates/layout.txt:5
|
||||
msgid "Thanks,"
|
||||
msgstr "Merci,"
|
||||
|
||||
#: fittrackee/emails/templates/layout.html:222
|
||||
#: fittrackee/emails/templates/layout.txt:6
|
||||
msgid "The FitTrackee Team"
|
||||
msgstr "L'équipe FitTrackee"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:2
|
||||
#: fittrackee/emails/templates/account_confirmation/subject.txt:1
|
||||
msgid "Confirm your account"
|
||||
msgstr "Confirmer votre inscription"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:3
|
||||
msgid "Use this link to confirm your account."
|
||||
msgstr "Utiliser ce lien pour confirmer votre inscription."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:4
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:1
|
||||
msgid "You have created an account on FitTrackee."
|
||||
msgstr "Vous avez créé un compte sur FitTrackee."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:4
|
||||
msgid "Use the button below to confirm your address email."
|
||||
msgstr "Cliquez sur le bouton pour confirmer votre adresse email."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:11
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:4
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:11
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:4
|
||||
msgid "Verify your email"
|
||||
msgstr "Vérifier l'adresse email"
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:18
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:7
|
||||
msgid ""
|
||||
"If this account creation wasn't initiated by you, please ignore this "
|
||||
"email."
|
||||
msgstr ""
|
||||
"Si vous n'êtes pas à l'origine de la création de ce compte, vous pouvez "
|
||||
"ignorer cet e-mail."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.html:22
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:22
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:24
|
||||
msgid ""
|
||||
"If you're having trouble with the button above, copy and paste the URL "
|
||||
"below into your web browser."
|
||||
msgstr ""
|
||||
"Si vous avez des problèmes avec le bouton, vous pouvez copier et coller "
|
||||
"le lien suivant dans votre navigateur."
|
||||
|
||||
#: fittrackee/emails/templates/account_confirmation/body.txt:2
|
||||
msgid "Use the link below to confirm your address email."
|
||||
msgstr "Cliquez sur le lien ci-dessous pour confirmer votre adresse email."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:2
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/subject.txt:1
|
||||
msgid "Email changed"
|
||||
msgstr "Adresse email modifiée"
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:3
|
||||
msgid "Your email is being updated."
|
||||
msgstr "Votre adresse email est en cours de mise à jour."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:4
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:1
|
||||
msgid ""
|
||||
"You recently requested to change your email address for your FitTrackee "
|
||||
"account to:"
|
||||
msgstr ""
|
||||
"Vous avez récemment demandé la modification de l'adresse email associée à"
|
||||
" votre compte sur FitTrackee vers :"
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.html:18
|
||||
#: fittrackee/emails/templates/email_update_to_current_email/body.txt:4
|
||||
msgid ""
|
||||
"If this email change wasn't initiated by you, please change your password"
|
||||
" immediately or contact your administrator if your account is locked."
|
||||
msgstr ""
|
||||
"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é."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:2
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/subject.txt:1
|
||||
msgid "Confirm email change"
|
||||
msgstr "Confirmer le changement d'adresse email"
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:3
|
||||
msgid "Use this link to confirm email change."
|
||||
msgstr "Confirmer le changement d'adresse email."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:4
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:1
|
||||
msgid ""
|
||||
"You recently requested to change your email address for your FitTrackee "
|
||||
"account."
|
||||
msgstr ""
|
||||
"Vous avez récemment demandé la modification de l'adresse email associée à"
|
||||
" votre compte sur FitTrackee."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:4
|
||||
msgid "Use the button below to confirm this address."
|
||||
msgstr "Cliquez sur le bouton ci-dessous pour confirmer cette adresse email."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.html:18
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:7
|
||||
msgid "If this email change wasn't initiated by you, please ignore this email."
|
||||
msgstr ""
|
||||
"Si vous n'êtes pas à l'origine de cette modification, vous pouvez ignorer"
|
||||
" cet e-mail."
|
||||
|
||||
#: fittrackee/emails/templates/email_update_to_new_email/body.txt:2
|
||||
msgid "Use the link below to confirm this address."
|
||||
msgstr "Cliquez sur le lien ci-dessous pour confirmer cette adresse email."
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:2
|
||||
#: fittrackee/emails/templates/password_change/subject.txt:1
|
||||
msgid "Password changed"
|
||||
msgstr "Mot de passe modifié"
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:3
|
||||
msgid "Your password has been changed."
|
||||
msgstr "Votre mot de passe a été modifié."
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:4
|
||||
#: fittrackee/emails/templates/password_change/body.txt:1
|
||||
msgid "The password for your FitTrackee account has been changed."
|
||||
msgstr "Le mot de passe de votre compte FitTrackee a été modifié."
|
||||
|
||||
#: fittrackee/emails/templates/password_change/body.html:5
|
||||
#: fittrackee/emails/templates/password_change/body.txt:4
|
||||
msgid ""
|
||||
"If this password change wasn't initiated by you, please change your "
|
||||
"password immediately or contact your administrator if your account is "
|
||||
"locked."
|
||||
msgstr ""
|
||||
"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é."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:2
|
||||
#: fittrackee/emails/templates/password_reset_request/subject.txt:1
|
||||
msgid "Password reset request"
|
||||
msgstr "Réinitialiser votre mot de passe"
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:3
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Use this link to reset your password. The link is only valid for "
|
||||
"%(expiration_delay)s."
|
||||
msgstr ""
|
||||
"Utiliser ce lien pour réinitialiser le mot de passe. Ce lien n'est valide"
|
||||
" que pendant %(expiration_delay)s."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:4
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:1
|
||||
msgid "You recently requested to reset your password for your FitTrackee account."
|
||||
msgstr ""
|
||||
"Vous avez récemment demandé la réinitialisation du mot de passe de votre "
|
||||
"compte sur FitTrackee."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:4
|
||||
msgid "Use the button below to reset it."
|
||||
msgstr "Cliquez sur le bouton pour le réinitialiser."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:5
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:2
|
||||
#, python-format
|
||||
msgid "This password reset link is only valid for %(expiration_delay)s."
|
||||
msgstr "Ce lien n'est valide que pendant %(expiration_delay)s."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:13
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:4
|
||||
msgid "Reset your password"
|
||||
msgstr "Réinitialiser le mot de passe"
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.html:20
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:7
|
||||
msgid "If you did not request a password reset, please ignore this email."
|
||||
msgstr ""
|
||||
"Si vous n'avez pas demandé de réinitialisation, vous pouvez ignorer cet "
|
||||
"e-mail."
|
||||
|
||||
#: fittrackee/emails/templates/password_reset_request/body.txt:1
|
||||
msgid "Use the link below to reset it."
|
||||
msgstr "Cliquez sur le lien ci-dessous pour le réinitialiser."
|
||||
|
44
fittrackee/migrations/commands.py
Normal file
44
fittrackee/migrations/commands.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import click
|
||||
from flask_migrate import upgrade
|
||||
|
||||
from fittrackee import db
|
||||
from fittrackee.cli.app import app
|
||||
|
||||
BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
||||
app_settings = os.getenv('APP_SETTINGS', 'fittrackee.config.ProductionConfig')
|
||||
|
||||
|
||||
@click.group(name='db')
|
||||
def db_cli() -> None:
|
||||
"""Manage database."""
|
||||
pass
|
||||
|
||||
|
||||
@db_cli.command('upgrade')
|
||||
def upgrade_db() -> None:
|
||||
"""Apply migrations."""
|
||||
with app.app_context():
|
||||
upgrade(directory=BASEDIR)
|
||||
|
||||
|
||||
@db_cli.command('drop')
|
||||
def drop_db() -> None:
|
||||
"""Empty database and delete uploaded files for dev environments."""
|
||||
with app.app_context():
|
||||
if app_settings == 'fittrackee.config.ProductionConfig':
|
||||
click.echo(
|
||||
click.style(
|
||||
'This is a production server, aborting!', bold=True
|
||||
),
|
||||
err=True,
|
||||
)
|
||||
return
|
||||
db.engine.execute("DROP TABLE IF EXISTS alembic_version;")
|
||||
db.drop_all()
|
||||
db.session.commit()
|
||||
click.echo('Database dropped.')
|
||||
shutil.rmtree(app.config['UPLOAD_FOLDER'], ignore_errors=True)
|
||||
click.echo('Uploaded files deleted.')
|
@@ -0,0 +1,59 @@
|
||||
"""update User and AppConfig tables
|
||||
|
||||
Revision ID: 5e3a3a31c432
|
||||
Revises: e30007d681cb
|
||||
Create Date: 2022-02-23 11:05:24.223304
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '5e3a3a31c432'
|
||||
down_revision = 'e30007d681cb'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.alter_column(
|
||||
'users', 'username', existing_type=sa.String(length=20),
|
||||
type_=sa.String(length=255), existing_nullable=False
|
||||
)
|
||||
op.alter_column(
|
||||
'users', 'email', existing_type=sa.String(length=120),
|
||||
type_=sa.String(length=255), existing_nullable=False
|
||||
)
|
||||
op.add_column(
|
||||
'users',
|
||||
sa.Column('is_active', sa.Boolean(), default=False, nullable=True))
|
||||
op.execute("UPDATE users SET is_active = true")
|
||||
op.alter_column('users', 'is_active', nullable=False)
|
||||
op.add_column(
|
||||
'users',
|
||||
sa.Column('email_to_confirm', sa.String(length=255), nullable=True))
|
||||
op.add_column(
|
||||
'users',
|
||||
sa.Column('confirmation_token', sa.String(length=255), nullable=True))
|
||||
|
||||
op.add_column(
|
||||
'app_config',
|
||||
sa.Column('admin_contact', sa.String(length=255), nullable=True)
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_column('app_config', 'admin_contact')
|
||||
|
||||
op.drop_column('users', 'confirmation_token')
|
||||
op.drop_column('users', 'email_to_confirm')
|
||||
op.drop_column('users', 'is_active')
|
||||
op.alter_column(
|
||||
'users', 'email', existing_type=sa.String(length=255),
|
||||
type_=sa.String(length=120), existing_nullable=False
|
||||
)
|
||||
op.alter_column(
|
||||
'users', 'username', existing_type=sa.String(length=255),
|
||||
type_=sa.String(length=20), existing_nullable=False
|
||||
)
|
24
fittrackee/request.py
Normal file
24
fittrackee/request.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from flask import Request
|
||||
from ua_parser import user_agent_parser
|
||||
from werkzeug.user_agent import UserAgent as IUserAgent
|
||||
|
||||
|
||||
class UserAgent(IUserAgent):
|
||||
def __init__(self, string: str):
|
||||
super().__init__(string)
|
||||
self.platform, self.browser = self._parse_user_agent(self.string)
|
||||
|
||||
@staticmethod
|
||||
def _parse_user_agent(
|
||||
user_agent: str,
|
||||
) -> Tuple[Optional[str], Optional[str]]:
|
||||
parsed_string = user_agent_parser.Parse(user_agent)
|
||||
platform = parsed_string.get('os', {}).get('family')
|
||||
browser = parsed_string.get('user_agent', {}).get('family')
|
||||
return platform, browser
|
||||
|
||||
|
||||
class CustomRequest(Request):
|
||||
user_agent_class = UserAgent
|
@@ -1,14 +1,30 @@
|
||||
import json
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
|
||||
import fittrackee
|
||||
from fittrackee.application.models import AppConfig
|
||||
from fittrackee.users.models import User
|
||||
|
||||
from ..api_test_case import ApiTestCaseMixin
|
||||
from ..mixins import ApiTestCaseMixin
|
||||
from ..utils import jsonify_dict
|
||||
|
||||
|
||||
class TestGetConfig(ApiTestCaseMixin):
|
||||
def test_it_gets_application_config_for_unauthenticated_user(
|
||||
self, app: Flask
|
||||
) -> None:
|
||||
app_config = AppConfig.query.first()
|
||||
client = app.test_client()
|
||||
|
||||
response = client.get('/api/config')
|
||||
|
||||
data = json.loads(response.data.decode())
|
||||
assert response.status_code == 200
|
||||
assert 'success' in data['status']
|
||||
assert data['data'] == jsonify_dict(app_config.serialize())
|
||||
|
||||
def test_it_gets_application_config(
|
||||
self, app: Flask, user_1: User
|
||||
) -> None:
|
||||
@@ -24,17 +40,6 @@ class TestGetConfig(ApiTestCaseMixin):
|
||||
data = json.loads(response.data.decode())
|
||||
assert response.status_code == 200
|
||||
assert 'success' in data['status']
|
||||
assert data['data']['gpx_limit_import'] == 10
|
||||
assert data['data']['is_registration_enabled'] is True
|
||||
assert data['data']['max_single_file_size'] == 1048576
|
||||
assert data['data']['max_zip_file_size'] == 10485760
|
||||
assert data['data']['max_users'] == 100
|
||||
assert data['data']['map_attribution'] == (
|
||||
'© <a href="http://www.openstreetmap.org/copyright" '
|
||||
'target="_blank" rel="noopener noreferrer">OpenStreetMap</a> '
|
||||
'contributors'
|
||||
)
|
||||
assert data['data']['version'] == fittrackee.__version__
|
||||
|
||||
def test_it_returns_error_if_application_has_no_config(
|
||||
self, app_no_config: Flask, user_1_admin: User
|
||||
@@ -96,12 +101,14 @@ class TestUpdateConfig(ApiTestCaseMixin):
|
||||
client, auth_token = self.get_test_client_and_auth_token(
|
||||
app, user_1_admin.email
|
||||
)
|
||||
admin_email = self.random_email()
|
||||
|
||||
response = client.patch(
|
||||
'/api/config',
|
||||
content_type='application/json',
|
||||
data=json.dumps(
|
||||
dict(
|
||||
admin_contact=admin_email,
|
||||
gpx_limit_import=20,
|
||||
max_single_file_size=10000,
|
||||
max_zip_file_size=25000,
|
||||
@@ -111,9 +118,10 @@ class TestUpdateConfig(ApiTestCaseMixin):
|
||||
headers=dict(Authorization=f'Bearer {auth_token}'),
|
||||
)
|
||||
|
||||
data = json.loads(response.data.decode())
|
||||
assert response.status_code == 200
|
||||
data = json.loads(response.data.decode())
|
||||
assert 'success' in data['status']
|
||||
assert data['data']['admin_contact'] == admin_email
|
||||
assert data['data']['gpx_limit_import'] == 20
|
||||
assert data['data']['is_registration_enabled'] is True
|
||||
assert data['data']['max_single_file_size'] == 10000
|
||||
@@ -262,3 +270,57 @@ class TestUpdateConfig(ApiTestCaseMixin):
|
||||
self.assert_400(
|
||||
response, 'Max. files in a zip archive must be greater than 0'
|
||||
)
|
||||
|
||||
def test_it_raises_error_if_admin_contact_is_invalid(
|
||||
self, app: Flask, user_1_admin: User
|
||||
) -> None:
|
||||
client, auth_token = self.get_test_client_and_auth_token(
|
||||
app, user_1_admin.email
|
||||
)
|
||||
|
||||
response = client.patch(
|
||||
'/api/config',
|
||||
content_type='application/json',
|
||||
data=json.dumps(
|
||||
dict(
|
||||
admin_contact=self.random_string(),
|
||||
)
|
||||
),
|
||||
headers=dict(Authorization=f'Bearer {auth_token}'),
|
||||
)
|
||||
|
||||
self.assert_400(
|
||||
response, 'valid email must be provided for admin contact'
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'input_description,input_email', [('input string', ''), ('None', None)]
|
||||
)
|
||||
def test_it_empties_error_if_admin_contact_is_an_empty(
|
||||
self,
|
||||
app: Flask,
|
||||
user_1_admin: User,
|
||||
input_description: str,
|
||||
input_email: Optional[str],
|
||||
) -> None:
|
||||
client, auth_token = self.get_test_client_and_auth_token(
|
||||
app, user_1_admin.email
|
||||
)
|
||||
app_config = AppConfig.query.first()
|
||||
app_config.admin_contact = self.random_email()
|
||||
|
||||
response = client.patch(
|
||||
'/api/config',
|
||||
content_type='application/json',
|
||||
data=json.dumps(
|
||||
dict(
|
||||
admin_contact=input_email,
|
||||
)
|
||||
),
|
||||
headers=dict(Authorization=f'Bearer {auth_token}'),
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = json.loads(response.data.decode())
|
||||
assert 'success' in data['status']
|
||||
assert data['data']['admin_contact'] is None
|
||||
|
@@ -1,21 +1,60 @@
|
||||
from flask import Flask
|
||||
|
||||
from fittrackee import VERSION
|
||||
from fittrackee.application.models import AppConfig
|
||||
from fittrackee.users.models import User
|
||||
|
||||
|
||||
class TestConfigModel:
|
||||
def test_application_config(self, app: Flask) -> None:
|
||||
app_config = AppConfig.query.first()
|
||||
assert 1 == app_config.id
|
||||
app_config.admin_contact = 'admin@example.com'
|
||||
|
||||
assert app_config.is_registration_enabled is True
|
||||
assert (
|
||||
app_config.map_attribution
|
||||
== app.config['TILE_SERVER']['ATTRIBUTION']
|
||||
)
|
||||
|
||||
serialized_app_config = app_config.serialize()
|
||||
assert serialized_app_config['gpx_limit_import'] == 10
|
||||
assert serialized_app_config['is_registration_enabled'] is True
|
||||
assert serialized_app_config['max_single_file_size'] == 1048576
|
||||
assert serialized_app_config['max_zip_file_size'] == 10485760
|
||||
assert serialized_app_config['max_users'] == 100
|
||||
assert serialized_app_config['map_attribution'] == (
|
||||
'© <a href="http://www.openstreetmap.org/copyright" '
|
||||
'target="_blank" rel="noopener noreferrer">OpenStreetMap</a> '
|
||||
'contributors'
|
||||
assert (
|
||||
serialized_app_config['admin_contact'] == app_config.admin_contact
|
||||
)
|
||||
assert (
|
||||
serialized_app_config['gpx_limit_import']
|
||||
== app_config.gpx_limit_import
|
||||
)
|
||||
assert serialized_app_config['is_email_sending_enabled'] is True
|
||||
assert serialized_app_config['is_registration_enabled'] is True
|
||||
assert (
|
||||
serialized_app_config['max_single_file_size']
|
||||
== app_config.max_single_file_size
|
||||
)
|
||||
assert (
|
||||
serialized_app_config['max_zip_file_size']
|
||||
== app_config.max_zip_file_size
|
||||
)
|
||||
assert serialized_app_config['max_users'] == app_config.max_users
|
||||
assert (
|
||||
serialized_app_config['map_attribution']
|
||||
== app_config.map_attribution
|
||||
)
|
||||
assert serialized_app_config['version'] == VERSION
|
||||
|
||||
def test_it_returns_registration_disabled_when_users_count_exceeds_limit(
|
||||
self, app: Flask, user_1: User, user_2: User
|
||||
) -> None:
|
||||
app_config = AppConfig.query.first()
|
||||
app_config.max_users = 2
|
||||
serialized_app_config = app_config.serialize()
|
||||
|
||||
assert app_config.is_registration_enabled is False
|
||||
assert serialized_app_config['is_registration_enabled'] is False
|
||||
|
||||
def test_it_returns_email_sending_disabled_when_no_email_url_provided(
|
||||
self, app_wo_email_activation: Flask, user_1: User, user_2: User
|
||||
) -> None:
|
||||
app_config = AppConfig.query.first()
|
||||
serialized_app_config = app_config.serialize()
|
||||
|
||||
assert serialized_app_config['is_email_sending_enabled'] is False
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user