Merge pull request #55 from SamR1/project-refactoring-and-packaging
Project refactoring and packaging
@ -1,4 +1,4 @@
|
||||
[run]
|
||||
omit =
|
||||
fittrackee_api/.venv/*
|
||||
fittrackee_api/fittrackee_api/tests/*
|
||||
fittrackee/.venv/*
|
||||
fittrackee/tests/*
|
||||
|
28
.env.example
Normal file
@ -0,0 +1,28 @@
|
||||
# Custom variables initialisation
|
||||
# (can overwrite variables present in Makefile.config)
|
||||
|
||||
# Application
|
||||
# export FLASK_APP=fittrackee
|
||||
# export HOST=
|
||||
# export PORT=
|
||||
# export APP_SETTINGS=fittrackee.config.ProductionConfig
|
||||
export APP_SECRET_KEY=
|
||||
# export APP_WORKERS=
|
||||
export APP_LOG=fittrackee.log
|
||||
export UPLOAD_FOLDER=
|
||||
|
||||
# Database
|
||||
# export DATABASE_URL=postgres://fittrackee:fittrackee@${HOST}:5432/fittrackee
|
||||
export DATABASE_DISABLE_POOLING=
|
||||
|
||||
# Emails
|
||||
export UI_URL=
|
||||
export EMAIL_URL=
|
||||
export SENDER_EMAIL=
|
||||
export REDIS_URL=
|
||||
# export WORKERS_PROCESSES=
|
||||
|
||||
# Activities
|
||||
export TILE_SERVER_URL=
|
||||
export MAP_ATTRIBUTION=
|
||||
export WEATHER_API_KEY=
|
7
.flake8
@ -1,5 +1,6 @@
|
||||
[flake8]
|
||||
per-file-ignores =
|
||||
fittrackee_api/fittrackee_api/activities/stats.py:E501
|
||||
fittrackee_api/fittrackee_api/tests/test_email.py:E501
|
||||
fittrackee_api/fittrackee_api/tests/test_email_template_password_request.py:E501
|
||||
fittrackee/activities/stats.py:E501
|
||||
fittrackee/application/app_config.py:E501
|
||||
fittrackee/tests/test_email.py:E501
|
||||
fittrackee/tests/test_email_template_password_request.py:E501
|
||||
|
8
.gitignore
vendored
@ -3,18 +3,20 @@
|
||||
|
||||
Makefile.custom.config
|
||||
|
||||
# MPWO_API
|
||||
# API
|
||||
###############
|
||||
__pycache__
|
||||
uploads
|
||||
.cache
|
||||
.coverage
|
||||
coverage.xml
|
||||
.env
|
||||
.pytest_cache
|
||||
.venv
|
||||
/fittrackee_api.egg-info/
|
||||
/fittrackee.egg-info/
|
||||
/dist
|
||||
|
||||
# MPWO_CLIENT
|
||||
# CLIENT
|
||||
###############
|
||||
|
||||
# dependencies
|
||||
|
65
.gitlab-ci.yml
Normal file
@ -0,0 +1,65 @@
|
||||
image: python:3.8
|
||||
|
||||
variables:
|
||||
POSTGRES_DB: fittrackee_test
|
||||
POSTGRES_USER: fittrackee
|
||||
POSTGRES_PASSWORD: fittrackee
|
||||
POSTGRES_HOST: postgres
|
||||
APP_SETTINGS: fittrackee.config.TestingConfig
|
||||
DATABASE_TEST_URL: postgres://fittrackee:fittrackee@postgres:5432/fittrackee_test
|
||||
EMAIL_URL: smtp://none:none@0.0.0.0:1025
|
||||
FLASK_APP: fittrackee/__main__.py
|
||||
SENDER_EMAIL: fittrackee@example.com
|
||||
|
||||
services:
|
||||
- name: postgres:latest
|
||||
alias: postgres
|
||||
|
||||
stages:
|
||||
- tests
|
||||
- selenium
|
||||
|
||||
.python:
|
||||
stage: tests
|
||||
before_script:
|
||||
- pip install --quiet poetry
|
||||
- poetry config virtualenvs.create false
|
||||
- poetry install --no-interaction --quiet
|
||||
script:
|
||||
- pytest fittrackee -p no:warnings --cov fittrackee --cov-report term-missing
|
||||
|
||||
lint:
|
||||
extends: .python
|
||||
script:
|
||||
- pytest --flake8 --isort --black -m "flake8 or isort or black" fittrackee e2e --ignore=fittrackee/migrations
|
||||
|
||||
python-3.7:
|
||||
extends: .python
|
||||
image: python:3.7
|
||||
|
||||
python-3.8:
|
||||
extends: .python
|
||||
|
||||
python-3.9-rc:
|
||||
extends: .python
|
||||
image: python:3.9-rc
|
||||
allow_failure: true
|
||||
|
||||
firefox:
|
||||
stage: selenium
|
||||
services:
|
||||
- name: postgres:latest
|
||||
alias: postgres
|
||||
- name: selenium/standalone-firefox
|
||||
alias: selenium
|
||||
before_script:
|
||||
- pip install --quiet poetry
|
||||
- poetry config virtualenvs.create false
|
||||
- poetry install --no-interaction --quiet
|
||||
- flask db upgrade --directory fittrackee/migrations
|
||||
- flask init-data
|
||||
- setsid nohup flask run --with-threads -h 0.0.0.0 -p 5000 >> nohup.out 2>&1 &
|
||||
- export TEST_APP_URL=http://$(hostname --ip-address):5000
|
||||
- sleep 5
|
||||
script:
|
||||
- pytest e2e --driver Remote --capability browserName firefox --host selenium --port 4444
|
49
.travis.yml
@ -1,49 +0,0 @@
|
||||
language: node_js
|
||||
node_js: '13'
|
||||
|
||||
dist: trusty
|
||||
sudo: required
|
||||
|
||||
addons:
|
||||
chrome: stable
|
||||
apt:
|
||||
update: true
|
||||
packages:
|
||||
- dpkg
|
||||
- fluxbox
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
env:
|
||||
global:
|
||||
- DOCKER_COMPOSE_VERSION=1.22.0
|
||||
|
||||
before_install:
|
||||
- stty cols 80
|
||||
- sudo rm /usr/local/bin/docker-compose
|
||||
- curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
|
||||
- chmod +x docker-compose
|
||||
- sudo mv docker-compose /usr/local/bin
|
||||
|
||||
before_script:
|
||||
- export DATABASE_TEST_URL=postgres://postgres:@localhost:5432/fittrackee_test
|
||||
- export APP_SETTINGS=fittrackee_api.config.TestingConfig
|
||||
- export REACT_APP_API_URL=http://127.0.0.1
|
||||
- export NODE_ENV=development
|
||||
- export TEST_URL=http://127.0.0.1
|
||||
- export UI_URL=http://127.0.0.1:3000
|
||||
- export EMAIL_URL=smtp://none:none@0.0.0.0:1025
|
||||
- export SENDER_EMAIL=fittrackee@example.com
|
||||
- export DISPLAY=:99.0
|
||||
- export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
- sleep 3
|
||||
- fluxbox >/dev/null 2>&1 &
|
||||
- docker-compose -f docker-compose-ci.yml up --build -d
|
||||
|
||||
script:
|
||||
- sh test.sh
|
||||
|
||||
after_script:
|
||||
- docker-compose down
|
11
CHANGELOG.md
@ -1,14 +1,21 @@
|
||||
# Change log
|
||||
|
||||
## Version 0.x.x (unreleased)
|
||||
## Version 0.4.0 (unreleased)
|
||||
|
||||
This version introduces some major changes:
|
||||
- Installation becomes more easy.
|
||||
⚠️ Warning: please read [installation documentation](https://samr1.github.io/FitTrackee/installation.html), some environment variables and files have been renamed.
|
||||
- It's now possible to change the tile provider for maps. The default tile server is now **OpenStreetMap**'s standard tile layer (replacing **ThunderForest Outdoors**),
|
||||
see [Map tile server in documentation](https://samr1.github.io/FitTrackee/installation.html#map-tile-server).
|
||||
|
||||
### Issues Closed
|
||||
|
||||
#### New Features
|
||||
|
||||
* [#54](https://github.com/SamR1/Fittrackee/issues/54) - Tile server can be changed
|
||||
* [#53](https://github.com/SamR1/Fittrackee/issues/53) - Simplify FitTrackee installation
|
||||
|
||||
In this release 1 issue weas closed.
|
||||
In this release 2 issue were closed.
|
||||
|
||||
|
||||
## Version 0.3.0 - Administration (2020/07/15)
|
||||
|
68
Makefile
@ -1,17 +1,20 @@
|
||||
include Makefile.config
|
||||
-include Makefile.custom.config
|
||||
-include .env
|
||||
.SILENT:
|
||||
|
||||
make-p:
|
||||
# Launch all P targets in parallel and exit as soon as one exits.
|
||||
set -m; (for p in $(P); do ($(MAKE) $$p || kill 0)& done; wait)
|
||||
|
||||
build-client:
|
||||
$(NPM) build
|
||||
build-client: lint-client
|
||||
cd fittrackee_client && $(NPM) build
|
||||
|
||||
clean-install:
|
||||
rm -fr $(NODE_MODULES)
|
||||
rm -fr $(VENV)
|
||||
rm -rf *.egg-info
|
||||
rm -rf .pytest_cache
|
||||
rm -rf dist/
|
||||
|
||||
html:
|
||||
rm -rf docsrc/build
|
||||
@ -25,9 +28,9 @@ html:
|
||||
cp -a docsrc/build/html/. docs
|
||||
|
||||
install-db:
|
||||
psql -U postgres -f fittrackee_api/db/create.sql
|
||||
psql -U postgres -f db/create.sql
|
||||
$(FLASK) db upgrade --directory $(MIGRATIONS)
|
||||
$(FLASK) initdata
|
||||
$(FLASK) init-data
|
||||
|
||||
init-app-config:
|
||||
$(FLASK) init-app-config
|
||||
@ -35,15 +38,16 @@ init-app-config:
|
||||
init-db:
|
||||
$(FLASK) drop-db
|
||||
$(FLASK) db upgrade --directory $(MIGRATIONS)
|
||||
$(FLASK) initdata
|
||||
$(FLASK) init-data
|
||||
|
||||
install: install-client install-python
|
||||
|
||||
install-client:
|
||||
$(NPM) install --prod
|
||||
cd fittrackee_client && $(NPM) install --prod
|
||||
|
||||
install-client-dev:
|
||||
$(NPM) install
|
||||
# https://github.com/facebook/create-react-app/issues/8688
|
||||
cd fittrackee_client && $(NPM) install && sed -i '/process.env.CI/ s/isInteractive [|]*//' node_modules/react-scripts/scripts/start.js
|
||||
|
||||
install-dev: install-client-dev install-python-dev
|
||||
|
||||
@ -53,21 +57,21 @@ install-python:
|
||||
install-python-dev:
|
||||
$(POETRY) install
|
||||
|
||||
lint-all: lint-python lint-react
|
||||
lint-all: lint-python lint-client
|
||||
|
||||
lint-all-fix: lint-python-fix lint-react-fix
|
||||
lint-all-fix: lint-python-fix lint-client-fix
|
||||
|
||||
lint-python:
|
||||
$(PYTEST) --flake8 --isort --black -m "flake8 or isort or black" fittrackee_api --ignore=fittrackee_api/migrations
|
||||
$(PYTEST) --flake8 --isort --black -m "flake8 or isort or black" fittrackee e2e --ignore=fittrackee/migrations
|
||||
|
||||
lint-python-fix:
|
||||
$(BLACK) fittrackee_api
|
||||
$(BLACK) fittrackee e2e
|
||||
|
||||
lint-react:
|
||||
$(NPM) lint
|
||||
lint-client:
|
||||
cd fittrackee_client && $(NPM) lint
|
||||
|
||||
lint-react-fix:
|
||||
$(NPM) lint-fix
|
||||
lint-client-fix:
|
||||
cd fittrackee_client && $(NPM) lint-fix
|
||||
|
||||
mail:
|
||||
docker run -d -e "MH_STORAGE=maildir" -v /tmp/maildir:/maildir -p 1025:1025 -p 8025:8025 mailhog/mailhog
|
||||
@ -79,43 +83,37 @@ recalculate:
|
||||
$(FLASK) recalculate
|
||||
|
||||
run:
|
||||
$(MAKE) P="run-server run-workers run-client" make-p
|
||||
|
||||
run-client:
|
||||
serve -s fittrackee_client/build -l 3000 >> serve.log 2>&1
|
||||
$(MAKE) P="run-server run-workers" make-p
|
||||
|
||||
run-server:
|
||||
cd fittrackee_api && $(GUNICORN) -b 127.0.0.1:5000 "fittrackee_api:create_app()" --error-logfile ../gunicorn.log
|
||||
cd fittrackee && $(GUNICORN) -b 127.0.0.1:5000 "fittrackee:create_app()" --error-logfile ../gunicorn.log
|
||||
|
||||
run-workers:
|
||||
$(FLASK) worker --processes=$(WORKERS_PROCESSES) >> dramatiq.log 2>&1
|
||||
|
||||
serve-python:
|
||||
$(FLASK) run --with-threads -h $(HOST) -p $(API_PORT)
|
||||
$(FLASK) run --with-threads -h $(HOST) -p $(PORT)
|
||||
|
||||
serve-python-dev:
|
||||
$(FLASK) run --with-threads -h $(HOST) -p $(API_PORT) --cert=adhoc
|
||||
$(FLASK) run --with-threads -h $(HOST) -p $(PORT) --cert=adhoc
|
||||
|
||||
serve-react:
|
||||
$(NPM) start
|
||||
serve-client:
|
||||
cd fittrackee_client && $(NPM) start
|
||||
|
||||
serve:
|
||||
$(MAKE) P="serve-react serve-python" make-p
|
||||
$(MAKE) P="serve-client serve-python" make-p
|
||||
|
||||
serve-dev:
|
||||
$(MAKE) P="serve-react serve-python-dev" make-p
|
||||
$(MAKE) P="serve-client serve-python-dev" make-p
|
||||
|
||||
test-e2e: init-db
|
||||
$(NPM) test
|
||||
$(PYTEST) e2e --driver firefox $(PYTEST_ARGS)
|
||||
|
||||
test-e2e-client: init-db
|
||||
E2E_ARGS=client $(PYTEST) e2e --driver firefox $(PYTEST_ARGS)
|
||||
|
||||
test-python:
|
||||
$(PYTEST) fittrackee_api --cov-config .coveragerc --cov=fittrackee_api --cov-report term-missing $(PYTEST_ARGS)
|
||||
|
||||
test-python-xml:
|
||||
$(PYTEST) fittrackee_api --cov-config .coveragerc --cov=fittrackee_api --cov-report xml
|
||||
|
||||
update-cov: test-python-xml
|
||||
$(COV) -r coverage.xml
|
||||
$(PYTEST) fittrackee --cov-config .coveragerc --cov=fittrackee --cov-report term-missing $(PYTEST_ARGS)
|
||||
|
||||
upgrade-db:
|
||||
$(FLASK) db upgrade --directory $(MIGRATIONS)
|
||||
|
@ -1,14 +1,20 @@
|
||||
HOST = 0.0.0.0
|
||||
API_PORT = 5000
|
||||
CLIENT_PORT = 3000
|
||||
export HOST = 0.0.0.0
|
||||
export PORT = 5000
|
||||
export CLIENT_PORT = 3000
|
||||
|
||||
export FLASK_APP = $(PWD)/fittrackee_api/server.py
|
||||
export APP_SETTINGS=fittrackee_api.config.DevelopmentConfig
|
||||
export FLASK_ENV=development
|
||||
export TEST_URL = http://$(HOST):$(CLIENT_PORT)
|
||||
export FLASK_APP = $(PWD)/fittrackee/__main__.py
|
||||
export MIGRATIONS = $(PWD)/fittrackee/migrations
|
||||
export APP_WORKERS = 1
|
||||
export WORKERS_PROCESSES = 1
|
||||
|
||||
# for dev env
|
||||
export FLASK_ENV = development
|
||||
export APP_SETTINGS = fittrackee.config.DevelopmentConfig
|
||||
export DATABASE_URL = postgres://fittrackee:fittrackee@$(HOST):5432/fittrackee
|
||||
export DATABASE_TEST_URL = postgres://fittrackee:fittrackee@$(HOST):5432/fittrackee_test
|
||||
export MIGRATIONS = $(PWD)/fittrackee_api/migrations
|
||||
export TEST_APP_URL = http://$(HOST):$(PORT)
|
||||
export TEST_CLIENT_URL = http://$(HOST):$(CLIENT_PORT)
|
||||
export REACT_APP_API_URL= $(TEST_APP_URL)
|
||||
|
||||
# Python env
|
||||
PYTHON_VERSION ?= python
|
||||
@ -18,11 +24,10 @@ POETRY = poetry
|
||||
FLASK = $(VENV)/bin/flask
|
||||
PYTEST = $(VENV)/bin/py.test -c pyproject.toml -W ignore::DeprecationWarning
|
||||
GUNICORN = $(VENV)/bin/gunicorn
|
||||
COV = $(VENV)/bin/python-codacy-coverage
|
||||
BLACK = $(VENV)/bin/black
|
||||
|
||||
# Node env
|
||||
NODE_MODULES = $(PWD)/node_modules
|
||||
NODE_MODULES = $(PWD)/fittrackee_client/node_modules
|
||||
NPM ?= yarn
|
||||
|
||||
#Sphinx Docs
|
||||
|
@ -1,13 +0,0 @@
|
||||
WORKERS_PROCESSES = 1
|
||||
|
||||
export REACT_APP_API_URL=
|
||||
export TILE_SERVER_URL=
|
||||
export MAP_ATTRIBUTION=
|
||||
export WEATHER_API=
|
||||
export UI_URL=
|
||||
export EMAIL_URL=
|
||||
export SENDER_EMAIL=
|
||||
export REDIS_URL=
|
||||
|
||||
# for dev env
|
||||
export CODACY_PROJECT_TOKEN=
|
@ -7,8 +7,8 @@
|
||||
[![React Version](https://img.shields.io/badge/react-16.13-brightgreen.svg)](https://reactjs.org/)
|
||||
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
|
||||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/290a285f22e94132904dc13b4dd19d1d)](https://www.codacy.com/app/SamR1/FitTrackee)
|
||||
[![Codacy Coverage Badge](https://api.codacy.com/project/badge/Coverage/290a285f22e94132904dc13b4dd19d1d)](https://www.codacy.com/app/SamR1/FitTrackee)<sup><sup>1</sup></sup>
|
||||
[![Build Status](https://travis-ci.org/SamR1/FitTrackee.svg?branch=master)](https://travis-ci.org/SamR1/FitTrackee)
|
||||
[![pipeline status](https://gitlab.com/SamR1/FitTrackee/badges/master/pipeline.svg)](https://gitlab.com/SamR1/FitTrackee/-/commits/master) <sup><sup>1</sup></sup>
|
||||
[![coverage report](https://gitlab.com/SamR1/FitTrackee/badges/master/coverage.svg)](https://gitlab.com/SamR1/FitTrackee/-/commits/master)
|
||||
|
||||
---
|
||||
|
||||
@ -24,10 +24,10 @@ Examples (for Android):
|
||||
Maps are displayed using [Open Street Map](https://www.openstreetmap.org).
|
||||
It is also possible to add a workout without a gpx file.
|
||||
|
||||
**Still under development (not ready for production).**
|
||||
**Still under heavy development (some features may be unstable).**
|
||||
(see [issues](https://github.com/SamR1/FitTrackee/issues) and [documentation](https://samr1.github.io/FitTrackee) for more information)
|
||||
|
||||
![FitTrackee Dashboard](docsrc/source/_images/fittrackee_screenshot-01.png)
|
||||
![FitTrackee Dashboard Screenshot](https://samr1.github.io/FitTrackee/_images/fittrackee_screenshot-01.png)
|
||||
|
||||
---
|
||||
|
||||
|
@ -1,59 +0,0 @@
|
||||
version: '3.3'
|
||||
|
||||
services:
|
||||
|
||||
fittrackee-db:
|
||||
container_name: fittrackee-db
|
||||
build: https://github.com/SamR1/FitTrackee.git#${BRANCH}:fittrackee_api/db
|
||||
ports:
|
||||
- 5435:5432
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
|
||||
fittrackee-api:
|
||||
container_name: fittrackee-api
|
||||
build: https://github.com/SamR1/FitTrackee.git#${BRANCH}:fittrackee_api
|
||||
ports:
|
||||
- 5001:5000
|
||||
environment:
|
||||
- DATABASE_URL=postgres://postgres:postgres@fittrackee-db:5432/fittrackee
|
||||
- DATABASE_TEST_URL=postgres://postgres:postgres@fittrackee-db:5432/fittrackee_test
|
||||
- UI_URL=http://127.0.0.1:3000
|
||||
- EMAIL_URL=smtp://none:none@0.0.0.0:1025
|
||||
- SENDER_EMAIL=fittrackee@example.com
|
||||
- FLASK_APP=server.py
|
||||
- FLASK_DEBUG=1
|
||||
- APP_SETTINGS=fittrackee_api.config.TestingConfig
|
||||
depends_on:
|
||||
- fittrackee-db
|
||||
links:
|
||||
- fittrackee-db
|
||||
|
||||
fittrackee-client:
|
||||
container_name: fittrackee-client
|
||||
build:
|
||||
context: https://github.com/SamR1/FitTrackee.git#${BRANCH}
|
||||
dockerfile: ./fittrackee_client/Dockerfile
|
||||
args:
|
||||
- NODE_ENV=development
|
||||
- REACT_APP_API_URL=${REACT_APP_API_URL}
|
||||
- CI=true
|
||||
ports:
|
||||
- 3007:3000
|
||||
depends_on:
|
||||
- fittrackee-api
|
||||
links:
|
||||
- fittrackee-api
|
||||
|
||||
nginx:
|
||||
container_name: nginx
|
||||
build: ./nginx
|
||||
restart: always
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- fittrackee-api
|
||||
- fittrackee-client
|
||||
links:
|
||||
- fittrackee-api
|
@ -1,58 +0,0 @@
|
||||
version: '3.3'
|
||||
|
||||
services:
|
||||
|
||||
fittrackee-db:
|
||||
container_name: fittrackee-db
|
||||
build: ./fittrackee_api/db
|
||||
ports:
|
||||
- 5435:5432
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
|
||||
fittrackee-api:
|
||||
container_name: fittrackee-api
|
||||
build: ./fittrackee_api
|
||||
ports:
|
||||
- 5001:5000
|
||||
environment:
|
||||
- DATABASE_URL=postgres://postgres:postgres@fittrackee-db:5432/fittrackee
|
||||
- DATABASE_TEST_URL=postgres://postgres:postgres@fittrackee-db:5432/fittrackee_test
|
||||
- UI_URL=http://127.0.0.1:3000
|
||||
- EMAIL_URL=smtp://none:none@0.0.0.0:1025
|
||||
- SENDER_EMAIL=fittrackee@example.com
|
||||
- FLASK_APP=server.py
|
||||
- FLASK_DEBUG=1
|
||||
- APP_SETTINGS=fittrackee_api.config.DevelopmentConfig
|
||||
depends_on:
|
||||
- fittrackee-db
|
||||
links:
|
||||
- fittrackee-db
|
||||
|
||||
fittrackee-client:
|
||||
container_name: fittrackee-client
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: ./fittrackee_client/Dockerfile
|
||||
args:
|
||||
- NODE_ENV=development
|
||||
- REACT_APP_API_URL=${REACT_APP_API_URL}
|
||||
ports:
|
||||
- 3007:3000
|
||||
depends_on:
|
||||
- fittrackee-api
|
||||
links:
|
||||
- fittrackee-api
|
||||
|
||||
nginx:
|
||||
container_name: nginx
|
||||
build: ./nginx
|
||||
restart: always
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- fittrackee-api
|
||||
- fittrackee-client
|
||||
links:
|
||||
- fittrackee-api
|
@ -1,4 +1,4 @@
|
||||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 34499f264a902c7412afeba2617f15cb
|
||||
config: 3bbd9f6e4f2cf4ec861ef46913ee1f93
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
Before Width: | Height: | Size: 598 KiB After Width: | Height: | Size: 596 KiB |
Before Width: | Height: | Size: 541 KiB After Width: | Height: | Size: 374 KiB |
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 197 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 69 KiB |
@ -1,7 +1,7 @@
|
||||
Activities
|
||||
##########
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
activities.get_activities,
|
||||
activities.get_activity,
|
||||
|
@ -1,7 +1,7 @@
|
||||
Authentication
|
||||
##############
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
auth.register_user,
|
||||
auth.login_user,
|
||||
|
@ -1,7 +1,7 @@
|
||||
Configuration
|
||||
#############
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
config.get_application_config,
|
||||
config.update_application_config,
|
||||
|
@ -1,6 +1,6 @@
|
||||
Records
|
||||
#######
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
records.get_records
|
||||
|
@ -1,7 +1,7 @@
|
||||
Sports
|
||||
######
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
sports.get_sports,
|
||||
sports.get_sport,
|
||||
|
@ -1,7 +1,7 @@
|
||||
Statistics
|
||||
##########
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
stats.get_activities_by_time,
|
||||
stats.get_activities_by_sport,
|
||||
|
@ -1,7 +1,7 @@
|
||||
Users
|
||||
#####
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
users.get_users,
|
||||
users.get_single_user,
|
||||
|
@ -1,14 +1,21 @@
|
||||
# Change log
|
||||
|
||||
## Version 0.x.x (unreleased)
|
||||
## Version 0.4.0 (unreleased)
|
||||
|
||||
This version introduces some major changes:
|
||||
- Installation becomes more easy.
|
||||
⚠️ Warning: please read [installation documentation](https://samr1.github.io/FitTrackee/installation.html), some environment variables and files have been renamed.
|
||||
- It's now possible to change the tile provider for maps. The default tile server is now **OpenStreetMap**'s standard tile layer (replacing **ThunderForest Outdoors**),
|
||||
see [Map tile server in documentation](https://samr1.github.io/FitTrackee/installation.html#map-tile-server).
|
||||
|
||||
### Issues Closed
|
||||
|
||||
#### New Features
|
||||
|
||||
* [#54](https://github.com/SamR1/Fittrackee/issues/54) - Tile server can be changed
|
||||
* [#53](https://github.com/SamR1/Fittrackee/issues/53) - Simplify FitTrackee installation
|
||||
|
||||
In this release 1 issue weas closed.
|
||||
In this release 2 issue were closed.
|
||||
|
||||
|
||||
## Version 0.3.0 - Administration (2020/07/15)
|
||||
|
@ -4,13 +4,10 @@ Features
|
||||
List
|
||||
~~~~
|
||||
|
||||
Account
|
||||
^^^^^^^
|
||||
- A user can create, update and deleted his account
|
||||
- Password reset is now available
|
||||
|
||||
Administration
|
||||
^^^^^^^^^^^^^^
|
||||
(*new in 0.3.0*)
|
||||
|
||||
- **Application**
|
||||
|
||||
The following parameters can be set:
|
||||
@ -30,6 +27,12 @@ Administration
|
||||
|
||||
- enable or disable a sport (a sport can be disabled even if activity with this sport exists)
|
||||
|
||||
Account
|
||||
^^^^^^^
|
||||
- A user can create, update and deleted his account
|
||||
- A user can reset his password (*new in 0.3.0*)
|
||||
|
||||
|
||||
Activities/Workouts
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
- 6 sports supported:
|
||||
|
@ -22,7 +22,7 @@ FitTrackee
|
||||
Map <https://www.openstreetmap.org>`__.
|
||||
| It is also possible to add a workout without a gpx file.
|
||||
|
||||
| **Still under development (not ready for production).**
|
||||
| **Still under heavy development (some features may be unstable).**
|
||||
| (see `issues <https://github.com/SamR1/FitTrackee/issues>`__ for more information)
|
||||
|
||||
.. figure:: _images/fittrackee_screenshot-01.png
|
||||
|
@ -22,194 +22,221 @@ Prerequisites
|
||||
- PostgreSQL database (10+)
|
||||
- Redis for task queue
|
||||
- Python 3.7+
|
||||
- `Poetry <https://poetry.eustace.io>`__
|
||||
- `Yarn <https://yarnpkg.com>`__ and
|
||||
`serve <https://github.com/zeit/serve>`__
|
||||
- `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
|
||||
- API key from `Dark Sky <https://darksky.net/dev>`__ [not mandatory]
|
||||
- SMTP provider
|
||||
- `Yarn <https://yarnpkg.com>`__ (for development only)
|
||||
- Docker (for development only, to start `MailHog <https://github.com/mailhog/MailHog>`__)
|
||||
|
||||
|
||||
Installation
|
||||
~~~~~~~~~~~~
|
||||
|
||||
| The following steps describe an installation on Linux systems (tested
|
||||
.. note::
|
||||
| The following steps describe an installation on Linux systems (tested
|
||||
on Debian and Arch).
|
||||
| On other OS, some issues can be encountered and adaptations may be
|
||||
| On other OS, some issues can be encountered and adaptations may be
|
||||
necessary.
|
||||
|
||||
.. warning::
|
||||
Since FitTrackee 0.2.1, Python packages installation needs Poetry. To install it on ArchLinux:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ yay poetry
|
||||
$ poetry --version
|
||||
Poetry 1.0.5
|
||||
|
||||
# optional
|
||||
$ poetry config virtualenvs.in-project true
|
||||
|
||||
For other OS, see `Poetry Documentation <https://python-poetry.org/docs/#installation>`__
|
||||
|
||||
|
||||
Dev environment
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- Clone this repo:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ git clone https://github.com/SamR1/FitTrackee.git
|
||||
$ cd FitTrackee
|
||||
|
||||
- Update **Makefile.config** file if needed and copy/paste the
|
||||
**ThunderForest** and **Dark Sky** API keys value in
|
||||
**Makefile.custom.config** file (see `Environment variables <installation.html#environment-variables>`__).
|
||||
|
||||
- Install Python virtualenv, React and all related packages and
|
||||
initialize the database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-dev
|
||||
$ make install-db
|
||||
|
||||
- Start the server and the client:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make serve
|
||||
|
||||
- Run dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run-workers
|
||||
|
||||
Open http://localhost:3000 and login (the email is ``admin@example.com``
|
||||
and the password ``mpwoadmin``) or register
|
||||
|
||||
Prod environment
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. warning::
|
||||
Note that FitTrackee is not production-ready yet
|
||||
|
||||
- Download the last release (for now, it is the beta release v0.3.0):
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.3.0-beta.tar.gz
|
||||
$ tar -xzf v0.3.0-beta.tar.gz
|
||||
$ mv FitTrackee-0.3.0-beta FitTrackee
|
||||
$ cd FitTrackee
|
||||
|
||||
- Update **Makefile.config** file if needed and copy/paste the
|
||||
**ThunderForest** and **Dark Sky** API keys value in
|
||||
**Makefile.custom.config** file (see `Environment variables <installation.html#environment-variables>`__).
|
||||
|
||||
- Install Python virtualenv, React and all related packages and
|
||||
initialize the database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install
|
||||
$ make install-db
|
||||
|
||||
- Build the client:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make build-client
|
||||
|
||||
- Start the server and the client:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run
|
||||
|
||||
- Run dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run-workers
|
||||
|
||||
Open http://localhost:3000, log in as admin (the email is
|
||||
``admin@example.com`` and the password ``mpwoadmin``) and change the
|
||||
password
|
||||
|
||||
Upgrade
|
||||
~~~~~~~
|
||||
|
||||
.. warning::
|
||||
| Before upgrading, make a backup of all data:
|
||||
| - database (with `pg_dump <https://www.postgresql.org/docs/11/app-pgdump.html>`__ for instance)
|
||||
| - upload directory: **FitTrackee/fittrackee_api/fittrackee_api/uploads/**
|
||||
|
||||
|
||||
Dev environment
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- Stop the application and pull the repository:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ git pull
|
||||
|
||||
- Update **Makefile.config** and **Makefile.custom.config** file if needed
|
||||
|
||||
- Upgrade packages and database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-dev
|
||||
$ make upgrade-db
|
||||
|
||||
- Restart the server and the client:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make serve
|
||||
|
||||
|
||||
Prod environment
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
``TODO``
|
||||
|
||||
|
||||
Environment variables
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following environment variables must be defined in **Makefile.custom.config**:
|
||||
.. warning::
|
||||
| Since FitTrackee 0.4.0, ``Makefile.custom.config`` is replaced by ``.env``
|
||||
|
||||
.. cssclass:: table-bordered table-striped
|
||||
The following environment variables are used by **FitTrackee** web application
|
||||
or the task processing library. They are not all mandatory depending on
|
||||
deployment method.
|
||||
|
||||
===================================== ============================================== ====================================
|
||||
variable description app default value
|
||||
===================================== ============================================== ====================================
|
||||
``REACT_APP_API_URL`` Fittrackee API URL no default value, must be initialized
|
||||
``REACT_APP_GPX_LIMIT_IMPORT`` max. number of gpx file in zip archive 10 (*deprecated in 0.3.0*)
|
||||
``REACT_APP_MAX_SINGLE_FILE_SIZE`` max. size of a gpx or picture file 1MB (*deprecated in 0.3.0*)
|
||||
``REACT_APP_MAX_ZIP_FILE_SIZE`` max. size of a zip archive 10MB (*deprecated in 0.3.0*)
|
||||
``REACT_APP_ALLOW_REGISTRATION`` allows users to register true (*deprecated in 0.3.0*)
|
||||
``REACT_APP_THUNDERFOREST_API_KEY`` ThunderForest API key (*deprecated in 0.x.x*, use ``TILE_SERVER_URL`` **and** ``MAP_ATTRIBUTION`` instead)
|
||||
``TILE_SERVER_URL`` Tile server URL (with api key if needed) ``https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png``
|
||||
``MAP_ATTRIBUTION`` Map attribution (if using another tile server) ``© <a href="http://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">OpenStreetMap</a> contributors``
|
||||
``UI_URL`` application URL no default value, must be initialized
|
||||
``EMAIL_URL`` email URL with credentials no default value, must be initialized (see below)
|
||||
``SENDER_EMAIL`` application sender email address no default value, must be initialized
|
||||
``REDIS_URL`` Redis instance used by Dramatiq local Redis instance
|
||||
``WORKERS_PROCESSES`` number of process used by Dramatiq no default value, must be initialized
|
||||
===================================== ============================================== ====================================
|
||||
.. envvar:: FLASK_APP
|
||||
|
||||
| Name of the module to import at flask run.
|
||||
| ``FLASK_APP`` should contain ``$(PWD)/fittrackee/__main__.py`` with installation from sources, else ``fittrackee``.
|
||||
|
||||
|
||||
.. envvar:: HOST
|
||||
|
||||
**FitTrackee** host.
|
||||
|
||||
:default: 0.0.0.0
|
||||
|
||||
|
||||
.. envvar:: PORT
|
||||
|
||||
**FitTrackee** port.
|
||||
|
||||
:default: 5000
|
||||
|
||||
|
||||
.. envvar:: APP_SETTINGS
|
||||
|
||||
**FitTrackee** configuration.
|
||||
|
||||
:default: fittrackee.config.ProductionConfig
|
||||
|
||||
|
||||
.. envvar:: APP_SECRET_KEY
|
||||
|
||||
**FitTrackee** secret key, must be initialized in production environment.
|
||||
|
||||
|
||||
.. envvar:: APP_WORKERS
|
||||
|
||||
Number of workers spawned by **Gunicorn**.
|
||||
|
||||
:default: 1
|
||||
|
||||
|
||||
.. envvar:: APP_LOG 🆕
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Path to log file
|
||||
|
||||
|
||||
.. envvar:: UPLOAD_FOLDER 🆕
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Directory containing uploaded files.
|
||||
|
||||
:default: `fittrackee/uploads/`
|
||||
|
||||
.. danger::
|
||||
| With installation from PyPI, the directory will be located in
|
||||
**virtualenv** directory if the variable is not initialized.
|
||||
|
||||
.. envvar:: DATABASE_URL
|
||||
|
||||
| Database URL with username and password, must be initialized in production environment.
|
||||
| For example in dev environment : ``postgres://fittrackee:fittrackee@localhost:5432/fittrackee``
|
||||
|
||||
|
||||
.. envvar:: DATABASE_DISABLE_POOLING 🆕
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Disable pooling if needed (when starting application with **FitTrackee** entry point and not directly with **Gunicorn**),
|
||||
see `SqlAlchemy documentation <https://docs.sqlalchemy.org/en/13/core/pooling.html#using-connection-pools-with-multiprocessing-or-os-fork>`__.
|
||||
|
||||
:default: false
|
||||
|
||||
.. envvar:: UI_URL
|
||||
|
||||
**FitTrackee** URL, needed for links in emails.
|
||||
|
||||
|
||||
.. envvar:: EMAIL_URL
|
||||
|
||||
.. versionadded:: 0.3.0
|
||||
|
||||
Email URL with credentials, see `Emails <installation.html#emails>`__.
|
||||
|
||||
|
||||
.. envvar:: SENDER_EMAIL
|
||||
|
||||
.. versionadded:: 0.3.0
|
||||
|
||||
**FitTrackee** sender email address.
|
||||
|
||||
|
||||
.. envvar:: REDIS_URL
|
||||
|
||||
.. versionadded:: 0.3.0
|
||||
|
||||
Redis instance used by **Dramatiq**.
|
||||
|
||||
:default: local Redis instance (``redis://``)
|
||||
|
||||
|
||||
.. envvar:: WORKERS_PROCESSES
|
||||
|
||||
.. versionadded:: 0.3.0
|
||||
|
||||
Number of processes used by **Dramatiq**.
|
||||
|
||||
|
||||
.. envvar:: TILE_SERVER_URL 🆕
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Tile server URL (with api key if needed), see `Map tile server <installation.html#map-tile-server>`__.
|
||||
|
||||
:default: `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`
|
||||
|
||||
|
||||
.. envvar:: MAP_ATTRIBUTION 🆕
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Map attribution (if using another tile server), see `Map tile server <installation.html#map-tile-server>`__.
|
||||
|
||||
:default: `© <a href="http://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">OpenStreetMap</a> contributors`
|
||||
|
||||
|
||||
.. envvar:: WEATHER_API_KEY
|
||||
|
||||
.. versionchanged:: 0.4.0 ⚠️ replaces ``WEATHER_API``
|
||||
|
||||
**Dark Sky** API key for weather data (not mandatory).
|
||||
|
||||
|
||||
.. envvar:: REACT_APP_API_URL
|
||||
|
||||
**FitTrackee** API URL, only needed in dev environment.
|
||||
|
||||
|
||||
|
||||
Deprecated variables
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. envvar:: REACT_APP_GPX_LIMIT_IMPORT
|
||||
|
||||
.. deprecated:: 0.3.0 now stored in database
|
||||
|
||||
Maximum number of gpx file in zip archive.
|
||||
|
||||
:default: 10
|
||||
|
||||
|
||||
.. envvar:: REACT_APP_MAX_SINGLE_FILE_SIZE
|
||||
|
||||
.. deprecated:: 0.3.0 now stored in database
|
||||
|
||||
Maximum size of a gpx or picture file.
|
||||
|
||||
:default: 1MB
|
||||
|
||||
|
||||
.. envvar:: REACT_APP_MAX_ZIP_FILE_SIZE
|
||||
|
||||
.. deprecated:: 0.3.0 now stored in database
|
||||
|
||||
Maximum size of a zip archive.
|
||||
|
||||
:default: 10MB
|
||||
|
||||
|
||||
.. envvar:: REACT_APP_ALLOW_REGISTRATION
|
||||
|
||||
.. deprecated:: 0.3.0 now stored in database
|
||||
|
||||
Allows users to register.
|
||||
|
||||
:default: true
|
||||
|
||||
|
||||
.. envvar:: REACT_APP_THUNDERFOREST_API_KEY
|
||||
|
||||
.. deprecated:: 0.4.0 see `TILE_SERVER_URL <installation.html#envvar-TILE_SERVER_URL>`__
|
||||
|
||||
ThunderForest API key.
|
||||
|
||||
.. warning::
|
||||
Since FitTrackee 0.3.0, some applications parameters are now stored in database.
|
||||
Related environment variables are needed to initialize database.
|
||||
| Since FitTrackee 0.3.0, some applications parameters are now stored in database.
|
||||
| Related environment variables are needed to initialize database when upgrading from version prior 0.3.0.
|
||||
|
||||
|
||||
Emails
|
||||
^^^^^^
|
||||
*new in 0.3.0*
|
||||
.. versionadded:: 0.3.0
|
||||
|
||||
To send emails, a valid ``EMAIL_URL`` must be provided:
|
||||
|
||||
@ -220,15 +247,392 @@ To send emails, a valid ``EMAIL_URL`` must be provided:
|
||||
|
||||
Map tile server
|
||||
^^^^^^^^^^^^^^^
|
||||
*new in 0.x.x*
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Default tile server is now **OpenStreetMap**'s standard tile layer (if environment variables are not initialized).
|
||||
The tile server can be changed by updating ``TILE_SERVER_URL`` and ``MAP_ATTRIBUTION`` variables (`list of tile servers <https://wiki.openstreetmap.org/wiki/Tile_servers>`__).
|
||||
|
||||
To keep using ThunderForest Outdoors, the configuration is:
|
||||
To keep using **ThunderForest Outdoors**, the configuration is:
|
||||
|
||||
- ``TILE_SERVER_URL=https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=XXXX`` where **XXXX** is ThunderForest API key
|
||||
- ``TILE_SERVER_URL=https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=XXXX`` where **XXXX** is **ThunderForest** API key
|
||||
- ``MAP_ATTRIBUTION=© <a href="http://www.thunderforest.com/">Thunderforest</a>, © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors``
|
||||
|
||||
.. note::
|
||||
Check the terms of service of tile provider for map attribution
|
||||
| Check the terms of service of tile provider for map attribution
|
||||
|
||||
From PyPI
|
||||
~~~~~~~~~
|
||||
|
||||
.. note::
|
||||
| Recommended way on production.
|
||||
|
||||
.. warning::
|
||||
| Note that FitTrackee is under heavy development, some features may be unstable.
|
||||
|
||||
Installation
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- Create and activate a virtualenv
|
||||
|
||||
- Install **FitTrackee** with pip
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install fittrackee
|
||||
|
||||
- Create ``fittrackee`` database
|
||||
|
||||
Example :
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
CREATE DATABASE fittrackee;
|
||||
CREATE USER fittrackee WITH PASSWORD '<PASSWORD>';
|
||||
GRANT ALL PRIVILEGES ON DATABASE fittrackee TO fittrackee;
|
||||
|
||||
- Initialize environment variables, see `Environment variables <installation.html#environment-variables>`__
|
||||
|
||||
For instance, copy and update ``.env`` file from ``.env.example`` and source the file.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ nano .env
|
||||
$ source .env
|
||||
|
||||
|
||||
- Upgrade database schema
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ fittrackee_upgrade_db
|
||||
|
||||
- Initialize database
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ fittrackee_init_data
|
||||
|
||||
- Start the application
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ fittrackee
|
||||
|
||||
- Start task queue workers
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ fittrackee_worker --processes 2
|
||||
|
||||
.. note::
|
||||
| To start application and workers with **systemd** service, see `Deployment <installation.html#deployment>`__
|
||||
|
||||
|
||||
Upgrade
|
||||
^^^^^^^
|
||||
|
||||
.. warning::
|
||||
| Before upgrading, make a backup of all data:
|
||||
| - database (with `pg_dump <https://www.postgresql.org/docs/11/app-pgdump.html>`__ for instance)
|
||||
| - upload directory (see `Environment variables <installation.html#environment-variables>`__)
|
||||
|
||||
- Activate the virtualenv
|
||||
|
||||
- Upgrade with pip
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install -U fittrackee
|
||||
|
||||
- Update environment variables if needed and source environment variables file
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ nano .env
|
||||
$ source .env
|
||||
|
||||
- Upgrade database if needed
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ fittrackee_upgrade_db
|
||||
|
||||
|
||||
- Restart the application and task queue workers.
|
||||
|
||||
|
||||
From sources
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
.. warning::
|
||||
| Since FitTrackee 0.2.1, Python packages installation needs Poetry.
|
||||
| To install it on ArchLinux:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ yay poetry
|
||||
$ poetry --version
|
||||
Poetry 1.0.10
|
||||
|
||||
# optional
|
||||
$ poetry config virtualenvs.in-project true
|
||||
|
||||
For other OS, see `Poetry Documentation <https://python-poetry.org/docs/#installation>`__
|
||||
|
||||
|
||||
Installation
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Dev environment
|
||||
"""""""""""""""
|
||||
|
||||
- Clone this repo:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ git clone https://github.com/SamR1/FitTrackee.git
|
||||
$ cd FitTrackee
|
||||
|
||||
- Create **Makefile.custom.config** from example and update it
|
||||
(see `Environment variables <installation.html#environment-variables>`__).
|
||||
|
||||
- Install Python virtualenv, React and all related packages and
|
||||
initialize the database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-dev
|
||||
$ make install-db
|
||||
|
||||
- Start the server and the client:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make serve
|
||||
|
||||
- Run dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run-workers
|
||||
|
||||
Open http://localhost:3000 and log in (the email is ``admin@example.com``
|
||||
and the password ``mpwoadmin``) or register
|
||||
|
||||
|
||||
Production environment
|
||||
""""""""""""""""""""""
|
||||
|
||||
.. warning::
|
||||
| Note that FitTrackee is under heavy development, some features may be unstable.
|
||||
|
||||
- Download the last release (for now, it is the release v0.4.0):
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.4.0.tar.gz
|
||||
$ tar -xzf v0.4.0.tar.gz
|
||||
$ mv FitTrackee-0.4.0 FitTrackee
|
||||
$ cd FitTrackee
|
||||
|
||||
- Create **Makefile.custom.config** from example and update it
|
||||
(see `Environment variables <installation.html#environment-variables>`__).
|
||||
|
||||
- Install Python virtualenv and all related packages:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-python
|
||||
|
||||
- Initialize the database (**after updating** ``db/create.sql`` **to change
|
||||
database credentials**):
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-db
|
||||
|
||||
- Start the server and dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run
|
||||
|
||||
Open http://localhost:5000, log in as admin (the email is
|
||||
``admin@example.com`` and the password ``mpwoadmin``) and change the
|
||||
password
|
||||
|
||||
Upgrade
|
||||
^^^^^^^
|
||||
|
||||
.. warning::
|
||||
| Before upgrading, make a backup of all data:
|
||||
| - database (with `pg_dump <https://www.postgresql.org/docs/11/app-pgdump.html>`__ for instance)
|
||||
| - upload directory (see `Environment variables <installation.html#environment-variables>`__)
|
||||
|
||||
|
||||
Dev environment
|
||||
"""""""""""""""
|
||||
|
||||
- Stop the application and pull the repository:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ git pull
|
||||
|
||||
- Update **.env** if needed
|
||||
|
||||
- Upgrade packages and database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-dev
|
||||
$ make upgrade-db
|
||||
|
||||
- Restart the server:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make serve
|
||||
|
||||
- Run dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run-workers
|
||||
|
||||
Prod environment
|
||||
""""""""""""""""
|
||||
|
||||
- Stop the application and pull the repository:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ git pull
|
||||
|
||||
- Update **Makefile.custom.config** if needed
|
||||
|
||||
- Upgrade packages and database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install
|
||||
$ make upgrade-db
|
||||
|
||||
- Restart the server and dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run
|
||||
|
||||
|
||||
Deployment
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
There are several ways to start **FitTrackee** web application and task queue
|
||||
library.
|
||||
One way is to use a **systemd** services and **Nginx** to proxy pass to **Gunicorn**.
|
||||
|
||||
Examples (to update depending on your application configuration and given distribution):
|
||||
|
||||
- for application: ``fittrackee.service``
|
||||
|
||||
.. code-block::
|
||||
|
||||
[Unit]
|
||||
Description=FitTrackee service
|
||||
After=network.target
|
||||
After=postgresql.service
|
||||
After=redis.service
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
User=<USER>
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=fittrackee
|
||||
Environment="APP_SECRET_KEY="
|
||||
Environment="APP_LOG="
|
||||
Environment="UPLOAD_FOLDER="
|
||||
Environment="DATABASE_URL="
|
||||
Environment="UI_URL="
|
||||
Environment="EMAIL_URL="
|
||||
Environment="SENDER_EMAIL="
|
||||
Environment="REDIS_URL="
|
||||
Environment="TILE_SERVER_URL="
|
||||
Environment="MAP_ATTRIBUTION="
|
||||
Environment="WEATHER_API_KEY="
|
||||
WorkingDirectory=/home/<USER>/<FITTRACKEE DIRECTORY>
|
||||
ExecStart=/home/<USER>/<FITTRACKEE DIRECTORY>/.venv/bin/gunicorn -b 127.0.0.1:5000 "fittrackee:create_app()" --error-logfile /home/<USER>/<FITTRACKEE DIRECTORY>/gunicorn.log
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
- for task queue workers: ``fittrackee_workers.service``
|
||||
|
||||
.. code-block::
|
||||
|
||||
[Unit]
|
||||
Description=FitTrackee task queue service
|
||||
After=network.target
|
||||
After=postgresql.service
|
||||
After=redis.service
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
User=<USER>
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=fittrackee_workers
|
||||
Environment="FLASK_APP=fittrackee"
|
||||
Environment="APP_SECRET_KEY="
|
||||
Environment="APP_LOG="
|
||||
Environment="UPLOAD_FOLDER="
|
||||
Environment="DATABASE_URL="
|
||||
Environment="UI_URL="
|
||||
Environment="EMAIL_URL="
|
||||
Environment="SENDER_EMAIL="
|
||||
Environment="REDIS_URL="
|
||||
WorkingDirectory=/home/<USER>/<FITTRACKEE DIRECTORY>
|
||||
ExecStart=/home/<USER>/<FITTRACKEE DIRECTORY>/.venv/bin/flask worker --processes <NUMBER OF PROCESSES>
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
- **Nginx** configuration:
|
||||
|
||||
.. code-block::
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name example.com;
|
||||
ssl_certificate fullchain.pem;
|
||||
ssl_certificate_key privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:5000;
|
||||
proxy_redirect default;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name example.com;
|
||||
location / {
|
||||
return 301 https://example.com$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
.. note::
|
||||
More information on `Gunicorn documentation <https://docs.gunicorn.org/en/stable/deploy.html>`__
|
31
docs/_static/custom.css
vendored
@ -54,18 +54,37 @@ body {
|
||||
}
|
||||
|
||||
.alert-danger {
|
||||
background-color: #dc6460;
|
||||
border-color: transparent;
|
||||
background-color: #f2dede;
|
||||
border-color: #dca7a7;
|
||||
color: #a94442;
|
||||
}
|
||||
|
||||
.alert-info {
|
||||
background-color: #3eb3e3;
|
||||
border-color: transparent;
|
||||
background-color: #d9edf7;
|
||||
border-color: #9acfea;
|
||||
color: #31708f;
|
||||
}
|
||||
|
||||
.alert-warning {
|
||||
background-color: #f5894f;
|
||||
border-color: transparent;
|
||||
background-color: #fcf8e3;
|
||||
border-color: #f5e79e;
|
||||
color: #8a6d3b;
|
||||
}
|
||||
|
||||
.descname {
|
||||
border-top: solid 3px #a18bac;
|
||||
border-radius: unset;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
dl.field-list > dt {
|
||||
background: #f0f0f0;
|
||||
border-left: solid 3px #ccc;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.envvar {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
|
2
docs/_static/documentation_options.js
vendored
@ -1,6 +1,6 @@
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||
VERSION: '0.3.0-beta',
|
||||
VERSION: '0.4.0',
|
||||
LANGUAGE: 'None',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Activities — FitTrackee 0.3.0-beta
|
||||
<title>Activities — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Authentication — FitTrackee 0.3.0-beta
|
||||
<title>Authentication — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Configuration — FitTrackee 0.3.0-beta
|
||||
<title>Configuration — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
@ -145,7 +146,8 @@
|
||||
<span class="nt">"is_registration_enabled"</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
|
||||
<span class="nt">"max_single_file_size"</span><span class="p">:</span> <span class="mi">1048576</span><span class="p">,</span>
|
||||
<span class="nt">"max_zip_file_size"</span><span class="p">:</span> <span class="mi">10485760</span><span class="p">,</span>
|
||||
<span class="nt">"max_users"</span><span class="p">:</span> <span class="mi">0</span>
|
||||
<span class="nt">"max_users"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
|
||||
<span class="nt">"map_attribution"</span><span class="p">:</span> <span class="s2">"&copy; <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"</span>
|
||||
<span class="p">},</span>
|
||||
<span class="nt">"status"</span><span class="p">:</span> <span class="s2">"success"</span>
|
||||
<span class="p">}</span>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>API documentation — FitTrackee 0.3.0-beta
|
||||
<title>API documentation — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Records — FitTrackee 0.3.0-beta
|
||||
<title>Records — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sports — FitTrackee 0.3.0-beta
|
||||
<title>Sports — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Statistics — FitTrackee 0.3.0-beta
|
||||
<title>Statistics — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Users — FitTrackee 0.3.0-beta
|
||||
<title>Users — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Change log — FitTrackee 0.3.0-beta
|
||||
<title>Change log — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
@ -39,7 +39,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
@ -76,7 +77,7 @@
|
||||
role="menu"
|
||||
aria-labelledby="dLabelLocalToc"><ul>
|
||||
<li><a class="reference internal" href="#">Change log</a><ul>
|
||||
<li><a class="reference internal" href="#version-0-x-x-unreleased">Version 0.x.x (unreleased)</a><ul>
|
||||
<li><a class="reference internal" href="#version-0-4-0-unreleased">Version 0.4.0 (unreleased)</a><ul>
|
||||
<li><a class="reference internal" href="#issues-closed">Issues Closed</a><ul>
|
||||
<li><a class="reference internal" href="#new-features">New Features</a></li>
|
||||
</ul>
|
||||
@ -195,16 +196,23 @@
|
||||
|
||||
<div class="section" id="change-log">
|
||||
<h1>Change log<a class="headerlink" href="#change-log" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="version-0-x-x-unreleased">
|
||||
<h2>Version 0.x.x (unreleased)<a class="headerlink" href="#version-0-x-x-unreleased" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="version-0-4-0-unreleased">
|
||||
<h2>Version 0.4.0 (unreleased)<a class="headerlink" href="#version-0-4-0-unreleased" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This version introduces some major changes:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Installation becomes more easy.<br />⚠️ Warning: please read <a class="reference external" href="https://samr1.github.io/FitTrackee/installation.html">installation documentation</a>, some environment variables and files have been renamed.</p></li>
|
||||
<li><p>It’s now possible to change the tile provider for maps. The default tile server is now <strong>OpenStreetMap</strong>’s standard tile layer (replacing <strong>ThunderForest Outdoors</strong>),
|
||||
see <a class="reference external" href="https://samr1.github.io/FitTrackee/installation.html#map-tile-server">Map tile server in documentation</a>.</p></li>
|
||||
</ul>
|
||||
<div class="section" id="issues-closed">
|
||||
<h3>Issues Closed<a class="headerlink" href="#issues-closed" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="section" id="new-features">
|
||||
<h4>New Features<a class="headerlink" href="#new-features" title="Permalink to this headline">¶</a></h4>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/54">#54</a> - Tile server can be changed</p></li>
|
||||
<li><p><a class="reference external" href="https://github.com/SamR1/Fittrackee/issues/53">#53</a> - Simplify FitTrackee installation</p></li>
|
||||
</ul>
|
||||
<p>In this release 1 issue weas closed.</p>
|
||||
<p>In this release 2 issue were closed.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Features — FitTrackee 0.3.0-beta
|
||||
<title>Features — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
@ -78,8 +79,8 @@
|
||||
aria-labelledby="dLabelLocalToc"><ul>
|
||||
<li><a class="reference internal" href="#">Features</a><ul>
|
||||
<li><a class="reference internal" href="#list">List</a><ul>
|
||||
<li><a class="reference internal" href="#account">Account</a></li>
|
||||
<li><a class="reference internal" href="#administration">Administration</a></li>
|
||||
<li><a class="reference internal" href="#account">Account</a></li>
|
||||
<li><a class="reference internal" href="#activities-workouts">Activities/Workouts</a></li>
|
||||
<li><a class="reference internal" href="#translations">Translations</a></li>
|
||||
</ul>
|
||||
@ -142,15 +143,9 @@
|
||||
<h1>Features<a class="headerlink" href="#features" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="list">
|
||||
<h2>List<a class="headerlink" href="#list" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="account">
|
||||
<h3>Account<a class="headerlink" href="#account" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>A user can create, update and deleted his account</p></li>
|
||||
<li><p>Password reset is now available</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="administration">
|
||||
<h3>Administration<a class="headerlink" href="#administration" title="Permalink to this headline">¶</a></h3>
|
||||
<p>(<em>new in 0.3.0</em>)</p>
|
||||
<ul>
|
||||
<li><p><strong>Application</strong></p>
|
||||
<p>The following parameters can be set:</p>
|
||||
@ -175,6 +170,13 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="account">
|
||||
<h3>Account<a class="headerlink" href="#account" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>A user can create, update and deleted his account</p></li>
|
||||
<li><p>A user can reset his password (<em>new in 0.3.0</em>)</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="activities-workouts">
|
||||
<h3>Activities/Workouts<a class="headerlink" href="#activities-workouts" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Index — FitTrackee 0.3.0-beta
|
||||
<title>Index — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
@ -38,7 +38,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
@ -111,8 +112,68 @@
|
||||
<h1 id="index">Index</h1>
|
||||
|
||||
<div class="genindex-jumpbox">
|
||||
<a href="#E"><strong>E</strong></a>
|
||||
|
||||
</div>
|
||||
<h2 id="E">E</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li>
|
||||
environment variable
|
||||
|
||||
<ul>
|
||||
<li><a href="installation.html#envvar-APP_LOG">APP_LOG 🆕</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-APP_SECRET_KEY">APP_SECRET_KEY</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-APP_SETTINGS">APP_SETTINGS</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-APP_WORKERS">APP_WORKERS</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-DATABASE_DISABLE_POOLING">DATABASE_DISABLE_POOLING 🆕</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-DATABASE_URL">DATABASE_URL</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-EMAIL_URL">EMAIL_URL</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-FLASK_APP">FLASK_APP</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-HOST">HOST</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-MAP_ATTRIBUTION">MAP_ATTRIBUTION 🆕</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-PORT">PORT</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-REACT_APP_ALLOW_REGISTRATION">REACT_APP_ALLOW_REGISTRATION</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-REACT_APP_API_URL">REACT_APP_API_URL</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-REACT_APP_GPX_LIMIT_IMPORT">REACT_APP_GPX_LIMIT_IMPORT</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-REACT_APP_MAX_SINGLE_FILE_SIZE">REACT_APP_MAX_SINGLE_FILE_SIZE</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-REACT_APP_MAX_ZIP_FILE_SIZE">REACT_APP_MAX_ZIP_FILE_SIZE</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-REACT_APP_THUNDERFOREST_API_KEY">REACT_APP_THUNDERFOREST_API_KEY</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-REDIS_URL">REDIS_URL</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-SENDER_EMAIL">SENDER_EMAIL</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-TILE_SERVER_URL">TILE_SERVER_URL 🆕</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-UI_URL">UI_URL</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-UPLOAD_FOLDER">UPLOAD_FOLDER 🆕</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-WEATHER_API_KEY">WEATHER_API_KEY</a>
|
||||
</li>
|
||||
<li><a href="installation.html#envvar-WORKERS_PROCESSES">WORKERS_PROCESSES</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>HTTP Routing Table — FitTrackee 0.3.0-beta
|
||||
<title>HTTP Routing Table — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
@ -45,7 +45,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>FitTrackee — FitTrackee 0.3.0-beta
|
||||
<title>FitTrackee — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
@ -39,7 +39,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
@ -142,7 +143,7 @@ Map</a>.</div>
|
||||
<div class="line">It is also possible to add a workout without a gpx file.</div>
|
||||
</div>
|
||||
<div class="line-block">
|
||||
<div class="line"><strong>Still under development (not ready for production).</strong></div>
|
||||
<div class="line"><strong>Still under heavy development (some features may be unstable).</strong></div>
|
||||
<div class="line">(see <a class="reference external" href="https://github.com/SamR1/FitTrackee/issues">issues</a> for more information)</div>
|
||||
</div>
|
||||
<div class="figure align-default">
|
||||
@ -155,9 +156,10 @@ Map</a>.</div>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="installation.html#prerequisites">Prerequisites</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="installation.html#id1">Installation</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="installation.html#upgrade">Upgrade</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="installation.html#environment-variables">Environment variables</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="installation.html#from-pypi">From PyPI</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="installation.html#from-sources">From sources</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="installation.html#deployment">Deployment</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="features.html">Features</a><ul>
|
||||
@ -185,7 +187,7 @@ Map</a>.</div>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="changelog.html">Change log</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-x-x-unreleased">Version 0.x.x (unreleased)</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-4-0-unreleased">Version 0.4.0 (unreleased)</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-3-0-administration-2020-07-15">Version 0.3.0 - Administration (2020/07/15)</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-2-5-fix-and-improvements-2020-01-31">Version 0.2.5 - Fix and improvements (2020/01/31)</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="changelog.html#version-0-2-4-minor-fix-2020-01-30">Version 0.2.4 - Minor fix (2020/01/30)</a></li>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Installation — FitTrackee 0.3.0-beta
|
||||
<title>Installation — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
@ -78,21 +79,31 @@
|
||||
aria-labelledby="dLabelLocalToc"><ul>
|
||||
<li><a class="reference internal" href="#">Installation</a><ul>
|
||||
<li><a class="reference internal" href="#prerequisites">Prerequisites</a></li>
|
||||
<li><a class="reference internal" href="#id1">Installation</a><ul>
|
||||
<li><a class="reference internal" href="#dev-environment">Dev environment</a></li>
|
||||
<li><a class="reference internal" href="#prod-environment">Prod environment</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#upgrade">Upgrade</a><ul>
|
||||
<li><a class="reference internal" href="#id2">Dev environment</a></li>
|
||||
<li><a class="reference internal" href="#id3">Prod environment</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#environment-variables">Environment variables</a><ul>
|
||||
<li><a class="reference internal" href="#deprecated-variables">Deprecated variables</a></li>
|
||||
<li><a class="reference internal" href="#emails">Emails</a></li>
|
||||
<li><a class="reference internal" href="#map-tile-server">Map tile server</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#from-pypi">From PyPI</a><ul>
|
||||
<li><a class="reference internal" href="#id1">Installation</a></li>
|
||||
<li><a class="reference internal" href="#upgrade">Upgrade</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#from-sources">From sources</a><ul>
|
||||
<li><a class="reference internal" href="#id2">Installation</a><ul>
|
||||
<li><a class="reference internal" href="#dev-environment">Dev environment</a></li>
|
||||
<li><a class="reference internal" href="#production-environment">Production environment</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#id3">Upgrade</a><ul>
|
||||
<li><a class="reference internal" href="#id4">Dev environment</a></li>
|
||||
<li><a class="reference internal" href="#prod-environment">Prod environment</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#deployment">Deployment</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@ -174,234 +185,316 @@
|
||||
<li><p>PostgreSQL database (10+)</p></li>
|
||||
<li><p>Redis for task queue</p></li>
|
||||
<li><p>Python 3.7+</p></li>
|
||||
<li><p><a class="reference external" href="https://poetry.eustace.io">Poetry</a></p></li>
|
||||
<li><p><a class="reference external" href="https://yarnpkg.com">Yarn</a> and
|
||||
<a class="reference external" href="https://github.com/zeit/serve">serve</a></p></li>
|
||||
<li><p><a class="reference external" href="https://poetry.eustace.io">Poetry</a> (for installation from sources only)</p></li>
|
||||
<li><p>API key from <a class="reference external" href="https://darksky.net/dev">Dark Sky</a> [not mandatory]</p></li>
|
||||
<li><p>SMTP provider</p></li>
|
||||
<li><p><a class="reference external" href="https://yarnpkg.com">Yarn</a> (for development only)</p></li>
|
||||
<li><p>Docker (for development only, to start <a class="reference external" href="https://github.com/mailhog/MailHog">MailHog</a>)</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="id1">
|
||||
<h2>Installation<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<div class="line-block">
|
||||
<div class="line">The following steps describe an installation on Linux systems (tested
|
||||
on Debian and Arch).</div>
|
||||
<div class="line">On other OS, some issues can be encountered and adaptations may be
|
||||
necessary.</div>
|
||||
</div>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<p>Since FitTrackee 0.2.1, Python packages installation needs Poetry. To install it on ArchLinux:</p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ yay poetry
|
||||
$ poetry --version
|
||||
Poetry <span class="m">1</span>.0.5
|
||||
|
||||
<span class="c1"># optional</span>
|
||||
$ poetry config virtualenvs.in-project <span class="nb">true</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>For other OS, see <a class="reference external" href="https://python-poetry.org/docs/#installation">Poetry Documentation</a></p>
|
||||
</div>
|
||||
<div class="section" id="dev-environment">
|
||||
<h3>Dev environment<a class="headerlink" href="#dev-environment" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Clone this repo:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ git clone https://github.com/SamR1/FitTrackee.git
|
||||
$ <span class="nb">cd</span> FitTrackee
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Update <strong>Makefile.config</strong> file if needed and copy/paste the
|
||||
<strong>ThunderForest</strong> and <strong>Dark Sky</strong> API keys value in
|
||||
<strong>Makefile.custom.config</strong> file (see <a class="reference external" href="installation.html#environment-variables">Environment variables</a>).</p></li>
|
||||
<li><p>Install Python virtualenv, React and all related packages and
|
||||
initialize the database:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make install-dev
|
||||
$ make install-db
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Start the server and the client:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make serve
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Run dramatiq workers:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make run-workers
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Open <a class="reference external" href="http://localhost:3000">http://localhost:3000</a> and login (the email is <code class="docutils literal notranslate"><span class="pre">admin@example.com</span></code>
|
||||
and the password <code class="docutils literal notranslate"><span class="pre">mpwoadmin</span></code>) or register</p>
|
||||
</div>
|
||||
<div class="section" id="prod-environment">
|
||||
<h3>Prod environment<a class="headerlink" href="#prod-environment" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<p>Note that FitTrackee is not production-ready yet</p>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Download the last release (for now, it is the beta release v0.3.0):</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.3.0-beta.tar.gz
|
||||
$ tar -xzf v0.3.0-beta.tar.gz
|
||||
$ mv FitTrackee-0.3.0-beta FitTrackee
|
||||
$ <span class="nb">cd</span> FitTrackee
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Update <strong>Makefile.config</strong> file if needed and copy/paste the
|
||||
<strong>ThunderForest</strong> and <strong>Dark Sky</strong> API keys value in
|
||||
<strong>Makefile.custom.config</strong> file (see <a class="reference external" href="installation.html#environment-variables">Environment variables</a>).</p></li>
|
||||
<li><p>Install Python virtualenv, React and all related packages and
|
||||
initialize the database:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make install
|
||||
$ make install-db
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Build the client:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make build-client
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Start the server and the client:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make run
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Run dramatiq workers:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make run-workers
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Open <a class="reference external" href="http://localhost:3000">http://localhost:3000</a>, log in as admin (the email is
|
||||
<code class="docutils literal notranslate"><span class="pre">admin@example.com</span></code> and the password <code class="docutils literal notranslate"><span class="pre">mpwoadmin</span></code>) and change the
|
||||
password</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="upgrade">
|
||||
<h2>Upgrade<a class="headerlink" href="#upgrade" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<div class="line-block">
|
||||
<div class="line">Before upgrading, make a backup of all data:</div>
|
||||
<div class="line">- database (with <a class="reference external" href="https://www.postgresql.org/docs/11/app-pgdump.html">pg_dump</a> for instance)</div>
|
||||
<div class="line">- upload directory: <strong>FitTrackee/fittrackee_api/fittrackee_api/uploads/</strong></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="id2">
|
||||
<h3>Dev environment<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Stop the application and pull the repository:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ git pull
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Update <strong>Makefile.config</strong> and <strong>Makefile.custom.config</strong> file if needed</p></li>
|
||||
<li><p>Upgrade packages and database:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make install-dev
|
||||
$ make upgrade-db
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Restart the server and the client:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make serve
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="id3">
|
||||
<h3>Prod environment<a class="headerlink" href="#id3" title="Permalink to this headline">¶</a></h3>
|
||||
<p><code class="docutils literal notranslate"><span class="pre">TODO</span></code></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="environment-variables">
|
||||
<h2>Environment variables<a class="headerlink" href="#environment-variables" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The following environment variables must be defined in <strong>Makefile.custom.config</strong>:</p>
|
||||
<table class="table-bordered table-striped docutils align-default">
|
||||
<colgroup>
|
||||
<col style="width: 17%" />
|
||||
<col style="width: 21%" />
|
||||
<col style="width: 61%" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr class="row-odd"><th class="head"><p>variable</p></th>
|
||||
<th class="head"><p>description</p></th>
|
||||
<th class="head"><p>app default value</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">REACT_APP_API_URL</span></code></p></td>
|
||||
<td><p>Fittrackee API URL</p></td>
|
||||
<td><p>no default value, must be initialized</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">REACT_APP_GPX_LIMIT_IMPORT</span></code></p></td>
|
||||
<td><p>max. number of gpx file in zip archive</p></td>
|
||||
<td><p>10 (<em>deprecated in 0.3.0</em>)</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">REACT_APP_MAX_SINGLE_FILE_SIZE</span></code></p></td>
|
||||
<td><p>max. size of a gpx or picture file</p></td>
|
||||
<td><p>1MB (<em>deprecated in 0.3.0</em>)</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">REACT_APP_MAX_ZIP_FILE_SIZE</span></code></p></td>
|
||||
<td><p>max. size of a zip archive</p></td>
|
||||
<td><p>10MB (<em>deprecated in 0.3.0</em>)</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">REACT_APP_ALLOW_REGISTRATION</span></code></p></td>
|
||||
<td><p>allows users to register</p></td>
|
||||
<td><p>true (<em>deprecated in 0.3.0</em>)</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">REACT_APP_THUNDERFOREST_API_KEY</span></code></p></td>
|
||||
<td><p>ThunderForest API key</p></td>
|
||||
<td><p>(<em>deprecated in 0.x.x</em>, use <code class="docutils literal notranslate"><span class="pre">TILE_SERVER_URL</span></code> <strong>and</strong> <code class="docutils literal notranslate"><span class="pre">MAP_ATTRIBUTION</span></code> instead)</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">TILE_SERVER_URL</span></code></p></td>
|
||||
<td><p>Tile server URL (with api key if needed)</p></td>
|
||||
<td><p><code class="docutils literal notranslate"><span class="pre">https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png</span></code></p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">MAP_ATTRIBUTION</span></code></p></td>
|
||||
<td><p>Map attribution (if using another tile server)</p></td>
|
||||
<td><p><code class="docutils literal notranslate"><span class="pre">&copy;</span> <span class="pre"><a</span> <span class="pre">href="http://www.openstreetmap.org/copyright"</span> <span class="pre">target="_blank"</span> <span class="pre">rel="noopener</span> <span class="pre">noreferrer">OpenStreetMap</a></span> <span class="pre">contributors</span></code></p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">UI_URL</span></code></p></td>
|
||||
<td><p>application URL</p></td>
|
||||
<td><p>no default value, must be initialized</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">EMAIL_URL</span></code></p></td>
|
||||
<td><p>email URL with credentials</p></td>
|
||||
<td><p>no default value, must be initialized (see below)</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">SENDER_EMAIL</span></code></p></td>
|
||||
<td><p>application sender email address</p></td>
|
||||
<td><p>no default value, must be initialized</p></td>
|
||||
</tr>
|
||||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">REDIS_URL</span></code></p></td>
|
||||
<td><p>Redis instance used by Dramatiq</p></td>
|
||||
<td><p>local Redis instance</p></td>
|
||||
</tr>
|
||||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">WORKERS_PROCESSES</span></code></p></td>
|
||||
<td><p>number of process used by Dramatiq</p></td>
|
||||
<td><p>no default value, must be initialized</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<p>Since FitTrackee 0.3.0, some applications parameters are now stored in database.
|
||||
Related environment variables are needed to initialize database.</p>
|
||||
<div class="line-block">
|
||||
<div class="line">Since FitTrackee 0.4.0, <code class="docutils literal notranslate"><span class="pre">Makefile.custom.config</span></code> is replaced by <code class="docutils literal notranslate"><span class="pre">.env</span></code></div>
|
||||
</div>
|
||||
</div>
|
||||
<p>The following environment variables are used by <strong>FitTrackee</strong> web application
|
||||
or the task processing library. They are not all mandatory depending on
|
||||
deployment method.</p>
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-FLASK_APP">
|
||||
<code class="sig-name descname">FLASK_APP</code><a class="headerlink" href="#envvar-FLASK_APP" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="line-block">
|
||||
<div class="line">Name of the module to import at flask run.</div>
|
||||
<div class="line"><code class="docutils literal notranslate"><span class="pre">FLASK_APP</span></code> should contain <code class="docutils literal notranslate"><span class="pre">$(PWD)/fittrackee/__main__.py</span></code> with installation from sources, else <code class="docutils literal notranslate"><span class="pre">fittrackee</span></code>.</div>
|
||||
</div>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-HOST">
|
||||
<code class="sig-name descname">HOST</code><a class="headerlink" href="#envvar-HOST" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p><strong>FitTrackee</strong> host.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p>0.0.0.0</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-PORT">
|
||||
<code class="sig-name descname">PORT</code><a class="headerlink" href="#envvar-PORT" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p><strong>FitTrackee</strong> port.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p>5000</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-APP_SETTINGS">
|
||||
<code class="sig-name descname">APP_SETTINGS</code><a class="headerlink" href="#envvar-APP_SETTINGS" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p><strong>FitTrackee</strong> configuration.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p>fittrackee.config.ProductionConfig</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-APP_SECRET_KEY">
|
||||
<code class="sig-name descname">APP_SECRET_KEY</code><a class="headerlink" href="#envvar-APP_SECRET_KEY" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p><strong>FitTrackee</strong> secret key, must be initialized in production environment.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-APP_WORKERS">
|
||||
<code class="sig-name descname">APP_WORKERS</code><a class="headerlink" href="#envvar-APP_WORKERS" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Number of workers spawned by <strong>Gunicorn</strong>.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p>1</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-APP_LOG">
|
||||
<span id="envvar-APP_LOG 🆕"></span><code class="sig-name descname">APP_LOG 🆕</code><a class="headerlink" href="#envvar-APP_LOG" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.4.0.</span></p>
|
||||
</div>
|
||||
<p>Path to log file</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-UPLOAD_FOLDER">
|
||||
<span id="envvar-UPLOAD_FOLDER 🆕"></span><code class="sig-name descname">UPLOAD_FOLDER 🆕</code><a class="headerlink" href="#envvar-UPLOAD_FOLDER" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.4.0.</span></p>
|
||||
</div>
|
||||
<p>Directory containing uploaded files.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p><cite>fittrackee/uploads/</cite></p>
|
||||
</dd>
|
||||
</dl>
|
||||
<div class="admonition danger">
|
||||
<p class="admonition-title">Danger</p>
|
||||
<div class="line-block">
|
||||
<div class="line">With installation from PyPI, the directory will be located in
|
||||
<strong>virtualenv</strong> directory if the variable is not initialized.</div>
|
||||
</div>
|
||||
</div>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-DATABASE_URL">
|
||||
<code class="sig-name descname">DATABASE_URL</code><a class="headerlink" href="#envvar-DATABASE_URL" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="line-block">
|
||||
<div class="line">Database URL with username and password, must be initialized in production environment.</div>
|
||||
<div class="line">For example in dev environment : <code class="docutils literal notranslate"><span class="pre">postgres://fittrackee:fittrackee@localhost:5432/fittrackee</span></code></div>
|
||||
</div>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-DATABASE_DISABLE_POOLING">
|
||||
<span id="envvar-DATABASE_DISABLE_POOLING 🆕"></span><code class="sig-name descname">DATABASE_DISABLE_POOLING 🆕</code><a class="headerlink" href="#envvar-DATABASE_DISABLE_POOLING" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.4.0.</span></p>
|
||||
</div>
|
||||
<p>Disable pooling if needed (when starting application with <strong>FitTrackee</strong> entry point and not directly with <strong>Gunicorn</strong>),
|
||||
see <a class="reference external" href="https://docs.sqlalchemy.org/en/13/core/pooling.html#using-connection-pools-with-multiprocessing-or-os-fork">SqlAlchemy documentation</a>.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p>false</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-UI_URL">
|
||||
<code class="sig-name descname">UI_URL</code><a class="headerlink" href="#envvar-UI_URL" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p><strong>FitTrackee</strong> URL, needed for links in emails.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-EMAIL_URL">
|
||||
<code class="sig-name descname">EMAIL_URL</code><a class="headerlink" href="#envvar-EMAIL_URL" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.3.0.</span></p>
|
||||
</div>
|
||||
<p>Email URL with credentials, see <a class="reference external" href="installation.html#emails">Emails</a>.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-SENDER_EMAIL">
|
||||
<code class="sig-name descname">SENDER_EMAIL</code><a class="headerlink" href="#envvar-SENDER_EMAIL" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.3.0.</span></p>
|
||||
</div>
|
||||
<p><strong>FitTrackee</strong> sender email address.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-REDIS_URL">
|
||||
<code class="sig-name descname">REDIS_URL</code><a class="headerlink" href="#envvar-REDIS_URL" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.3.0.</span></p>
|
||||
</div>
|
||||
<p>Redis instance used by <strong>Dramatiq</strong>.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p>local Redis instance (<code class="docutils literal notranslate"><span class="pre">redis://</span></code>)</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-WORKERS_PROCESSES">
|
||||
<code class="sig-name descname">WORKERS_PROCESSES</code><a class="headerlink" href="#envvar-WORKERS_PROCESSES" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.3.0.</span></p>
|
||||
</div>
|
||||
<p>Number of processes used by <strong>Dramatiq</strong>.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-TILE_SERVER_URL">
|
||||
<span id="envvar-TILE_SERVER_URL 🆕"></span><code class="sig-name descname">TILE_SERVER_URL 🆕</code><a class="headerlink" href="#envvar-TILE_SERVER_URL" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.4.0.</span></p>
|
||||
</div>
|
||||
<p>Tile server URL (with api key if needed), see <a class="reference external" href="installation.html#map-tile-server">Map tile server</a>.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p><cite>https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png</cite></p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-MAP_ATTRIBUTION">
|
||||
<span id="envvar-MAP_ATTRIBUTION 🆕"></span><code class="sig-name descname">MAP_ATTRIBUTION 🆕</code><a class="headerlink" href="#envvar-MAP_ATTRIBUTION" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.4.0.</span></p>
|
||||
</div>
|
||||
<p>Map attribution (if using another tile server), see <a class="reference external" href="installation.html#map-tile-server">Map tile server</a>.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p><cite>&copy; <a href=”http://www.openstreetmap.org/copyright” target=”_blank” rel=”noopener noreferrer”>OpenStreetMap</a> contributors</cite></p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-WEATHER_API_KEY">
|
||||
<code class="sig-name descname">WEATHER_API_KEY</code><a class="headerlink" href="#envvar-WEATHER_API_KEY" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="versionchanged">
|
||||
<p><span class="versionmodified changed">Changed in version 0.4.0: </span>⚠️ replaces <code class="docutils literal notranslate"><span class="pre">WEATHER_API</span></code></p>
|
||||
</div>
|
||||
<p><strong>Dark Sky</strong> API key for weather data (not mandatory).</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-REACT_APP_API_URL">
|
||||
<code class="sig-name descname">REACT_APP_API_URL</code><a class="headerlink" href="#envvar-REACT_APP_API_URL" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p><strong>FitTrackee</strong> API URL, only needed in dev environment.</p>
|
||||
</dd></dl>
|
||||
|
||||
<div class="section" id="deprecated-variables">
|
||||
<h3>Deprecated variables<a class="headerlink" href="#deprecated-variables" title="Permalink to this headline">¶</a></h3>
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-REACT_APP_GPX_LIMIT_IMPORT">
|
||||
<code class="sig-name descname">REACT_APP_GPX_LIMIT_IMPORT</code><a class="headerlink" href="#envvar-REACT_APP_GPX_LIMIT_IMPORT" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="deprecated">
|
||||
<p><span class="versionmodified deprecated">Deprecated since version 0.3.0: </span>now stored in database</p>
|
||||
</div>
|
||||
<p>Maximum number of gpx file in zip archive.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p>10</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-REACT_APP_MAX_SINGLE_FILE_SIZE">
|
||||
<code class="sig-name descname">REACT_APP_MAX_SINGLE_FILE_SIZE</code><a class="headerlink" href="#envvar-REACT_APP_MAX_SINGLE_FILE_SIZE" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="deprecated">
|
||||
<p><span class="versionmodified deprecated">Deprecated since version 0.3.0: </span>now stored in database</p>
|
||||
</div>
|
||||
<p>Maximum size of a gpx or picture file.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p>1MB</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-REACT_APP_MAX_ZIP_FILE_SIZE">
|
||||
<code class="sig-name descname">REACT_APP_MAX_ZIP_FILE_SIZE</code><a class="headerlink" href="#envvar-REACT_APP_MAX_ZIP_FILE_SIZE" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="deprecated">
|
||||
<p><span class="versionmodified deprecated">Deprecated since version 0.3.0: </span>now stored in database</p>
|
||||
</div>
|
||||
<p>Maximum size of a zip archive.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p>10MB</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-REACT_APP_ALLOW_REGISTRATION">
|
||||
<code class="sig-name descname">REACT_APP_ALLOW_REGISTRATION</code><a class="headerlink" href="#envvar-REACT_APP_ALLOW_REGISTRATION" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="deprecated">
|
||||
<p><span class="versionmodified deprecated">Deprecated since version 0.3.0: </span>now stored in database</p>
|
||||
</div>
|
||||
<p>Allows users to register.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Default</dt>
|
||||
<dd class="field-odd"><p>true</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="std envvar">
|
||||
<dt id="envvar-REACT_APP_THUNDERFOREST_API_KEY">
|
||||
<code class="sig-name descname">REACT_APP_THUNDERFOREST_API_KEY</code><a class="headerlink" href="#envvar-REACT_APP_THUNDERFOREST_API_KEY" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><div class="deprecated">
|
||||
<p><span class="versionmodified deprecated">Deprecated since version 0.4.0: </span>see <a class="reference external" href="installation.html#envvar-TILE_SERVER_URL">TILE_SERVER_URL</a></p>
|
||||
</div>
|
||||
<p>ThunderForest API key.</p>
|
||||
</dd></dl>
|
||||
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<div class="line-block">
|
||||
<div class="line">Since FitTrackee 0.3.0, some applications parameters are now stored in database.</div>
|
||||
<div class="line">Related environment variables are needed to initialize database when upgrading from version prior 0.3.0.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="emails">
|
||||
<h3>Emails<a class="headerlink" href="#emails" title="Permalink to this headline">¶</a></h3>
|
||||
<p><em>new in 0.3.0</em></p>
|
||||
<div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.3.0.</span></p>
|
||||
</div>
|
||||
<p>To send emails, a valid <code class="docutils literal notranslate"><span class="pre">EMAIL_URL</span></code> must be provided:</p>
|
||||
<ul class="simple">
|
||||
<li><p>with an unencrypted SMTP server: <code class="docutils literal notranslate"><span class="pre">smtp://username:password@smtp.example.com:25</span></code></p></li>
|
||||
@ -411,20 +504,402 @@ Related environment variables are needed to initialize database.</p>
|
||||
</div>
|
||||
<div class="section" id="map-tile-server">
|
||||
<h3>Map tile server<a class="headerlink" href="#map-tile-server" title="Permalink to this headline">¶</a></h3>
|
||||
<p><em>new in 0.x.x</em></p>
|
||||
<div class="versionadded">
|
||||
<p><span class="versionmodified added">New in version 0.4.0.</span></p>
|
||||
</div>
|
||||
<p>Default tile server is now <strong>OpenStreetMap</strong>’s standard tile layer (if environment variables are not initialized).
|
||||
The tile server can be changed by updating <code class="docutils literal notranslate"><span class="pre">TILE_SERVER_URL</span></code> and <code class="docutils literal notranslate"><span class="pre">MAP_ATTRIBUTION</span></code> variables (<a class="reference external" href="https://wiki.openstreetmap.org/wiki/Tile_servers">list of tile servers</a>).</p>
|
||||
<p>To keep using ThunderForest Outdoors, the configuration is:</p>
|
||||
<p>To keep using <strong>ThunderForest Outdoors</strong>, the configuration is:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">TILE_SERVER_URL=https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=XXXX</span></code> where <strong>XXXX</strong> is ThunderForest API key</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">TILE_SERVER_URL=https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=XXXX</span></code> where <strong>XXXX</strong> is <strong>ThunderForest</strong> API key</p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">MAP_ATTRIBUTION=&copy;</span> <span class="pre"><a</span> <span class="pre">href="http://www.thunderforest.com/">Thunderforest</a>,</span> <span class="pre">&copy;</span> <span class="pre"><a</span> <span class="pre">href="http://www.openstreetmap.org/copyright">OpenStreetMap</a></span> <span class="pre">contributors</span></code></p></li>
|
||||
</ul>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<p>Check the terms of service of tile provider for map attribution</p>
|
||||
<div class="line-block">
|
||||
<div class="line">Check the terms of service of tile provider for map attribution</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="from-pypi">
|
||||
<h2>From PyPI<a class="headerlink" href="#from-pypi" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<div class="line-block">
|
||||
<div class="line">Recommended way on production.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<div class="line-block">
|
||||
<div class="line">Note that FitTrackee is under heavy development, some features may be unstable.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="id1">
|
||||
<h3>Installation<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><p>Create and activate a virtualenv</p></li>
|
||||
<li><p>Install <strong>FitTrackee</strong> with pip</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ pip install fittrackee
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Create <code class="docutils literal notranslate"><span class="pre">fittrackee</span></code> database</p></li>
|
||||
</ul>
|
||||
<p>Example :</p>
|
||||
<div class="highlight-sql notranslate"><div class="highlight"><pre><span></span><span class="k">CREATE</span> <span class="k">DATABASE</span> <span class="n">fittrackee</span><span class="p">;</span>
|
||||
<span class="k">CREATE</span> <span class="k">USER</span> <span class="n">fittrackee</span> <span class="k">WITH</span> <span class="n">PASSWORD</span> <span class="s1">'<PASSWORD>'</span><span class="p">;</span>
|
||||
<span class="k">GRANT</span> <span class="k">ALL</span> <span class="k">PRIVILEGES</span> <span class="k">ON</span> <span class="k">DATABASE</span> <span class="n">fittrackee</span> <span class="k">TO</span> <span class="n">fittrackee</span><span class="p">;</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Initialize environment variables, see <a class="reference external" href="installation.html#environment-variables">Environment variables</a></p></li>
|
||||
</ul>
|
||||
<p>For instance, copy and update <code class="docutils literal notranslate"><span class="pre">.env</span></code> file from <code class="docutils literal notranslate"><span class="pre">.env.example</span></code> and source the file.</p>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ nano .env
|
||||
$ <span class="nb">source</span> .env
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Upgrade database schema</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ fittrackee_upgrade_db
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Initialize database</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ fittrackee_init_data
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Start the application</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ fittrackee
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Start task queue workers</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ fittrackee_worker --processes <span class="m">2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<div class="line-block">
|
||||
<div class="line">To start application and workers with <strong>systemd</strong> service, see <a class="reference external" href="installation.html#deployment">Deployment</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="upgrade">
|
||||
<h3>Upgrade<a class="headerlink" href="#upgrade" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<div class="line-block">
|
||||
<div class="line">Before upgrading, make a backup of all data:</div>
|
||||
<div class="line">- database (with <a class="reference external" href="https://www.postgresql.org/docs/11/app-pgdump.html">pg_dump</a> for instance)</div>
|
||||
<div class="line">- upload directory (see <a class="reference external" href="installation.html#environment-variables">Environment variables</a>)</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Activate the virtualenv</p></li>
|
||||
<li><p>Upgrade with pip</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ pip install -U fittrackee
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Update environment variables if needed and source environment variables file</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ nano .env
|
||||
$ <span class="nb">source</span> .env
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Upgrade database if needed</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ fittrackee_upgrade_db
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Restart the application and task queue workers.</p></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="from-sources">
|
||||
<h2>From sources<a class="headerlink" href="#from-sources" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<div class="line-block">
|
||||
<div class="line">Since FitTrackee 0.2.1, Python packages installation needs Poetry.</div>
|
||||
<div class="line">To install it on ArchLinux:</div>
|
||||
</div>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ yay poetry
|
||||
$ poetry --version
|
||||
Poetry <span class="m">1</span>.0.10
|
||||
|
||||
<span class="c1"># optional</span>
|
||||
$ poetry config virtualenvs.in-project <span class="nb">true</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>For other OS, see <a class="reference external" href="https://python-poetry.org/docs/#installation">Poetry Documentation</a></p>
|
||||
</div>
|
||||
<div class="section" id="id2">
|
||||
<h3>Installation<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="section" id="dev-environment">
|
||||
<h4>Dev environment<a class="headerlink" href="#dev-environment" title="Permalink to this headline">¶</a></h4>
|
||||
<ul class="simple">
|
||||
<li><p>Clone this repo:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ git clone https://github.com/SamR1/FitTrackee.git
|
||||
$ <span class="nb">cd</span> FitTrackee
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Create <strong>Makefile.custom.config</strong> from example and update it
|
||||
(see <a class="reference external" href="installation.html#environment-variables">Environment variables</a>).</p></li>
|
||||
<li><p>Install Python virtualenv, React and all related packages and
|
||||
initialize the database:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make install-dev
|
||||
$ make install-db
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Start the server and the client:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make serve
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Run dramatiq workers:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make run-workers
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Open <a class="reference external" href="http://localhost:3000">http://localhost:3000</a> and log in (the email is <code class="docutils literal notranslate"><span class="pre">admin@example.com</span></code>
|
||||
and the password <code class="docutils literal notranslate"><span class="pre">mpwoadmin</span></code>) or register</p>
|
||||
</div>
|
||||
<div class="section" id="production-environment">
|
||||
<h4>Production environment<a class="headerlink" href="#production-environment" title="Permalink to this headline">¶</a></h4>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<div class="line-block">
|
||||
<div class="line">Note that FitTrackee is under heavy development, some features may be unstable.</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Download the last release (for now, it is the release v0.4.0):</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ wget https://github.com/SamR1/FitTrackee/archive/v0.4.0.tar.gz
|
||||
$ tar -xzf v0.4.0.tar.gz
|
||||
$ mv FitTrackee-0.4.0 FitTrackee
|
||||
$ <span class="nb">cd</span> FitTrackee
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Create <strong>Makefile.custom.config</strong> from example and update it
|
||||
(see <a class="reference external" href="installation.html#environment-variables">Environment variables</a>).</p></li>
|
||||
<li><p>Install Python virtualenv and all related packages:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make install-python
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Initialize the database (<strong>after updating</strong> <code class="docutils literal notranslate"><span class="pre">db/create.sql</span></code> <strong>to change
|
||||
database credentials</strong>):</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make install-db
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Start the server and dramatiq workers:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make run
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Open <a class="reference external" href="http://localhost:5000">http://localhost:5000</a>, log in as admin (the email is
|
||||
<code class="docutils literal notranslate"><span class="pre">admin@example.com</span></code> and the password <code class="docutils literal notranslate"><span class="pre">mpwoadmin</span></code>) and change the
|
||||
password</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="id3">
|
||||
<h3>Upgrade<a class="headerlink" href="#id3" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="admonition warning">
|
||||
<p class="admonition-title">Warning</p>
|
||||
<div class="line-block">
|
||||
<div class="line">Before upgrading, make a backup of all data:</div>
|
||||
<div class="line">- database (with <a class="reference external" href="https://www.postgresql.org/docs/11/app-pgdump.html">pg_dump</a> for instance)</div>
|
||||
<div class="line">- upload directory (see <a class="reference external" href="installation.html#environment-variables">Environment variables</a>)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="id4">
|
||||
<h4>Dev environment<a class="headerlink" href="#id4" title="Permalink to this headline">¶</a></h4>
|
||||
<ul class="simple">
|
||||
<li><p>Stop the application and pull the repository:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ git pull
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Update <strong>.env</strong> if needed</p></li>
|
||||
<li><p>Upgrade packages and database:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make install-dev
|
||||
$ make upgrade-db
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Restart the server:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make serve
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Run dramatiq workers:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make run-workers
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="prod-environment">
|
||||
<h4>Prod environment<a class="headerlink" href="#prod-environment" title="Permalink to this headline">¶</a></h4>
|
||||
<ul class="simple">
|
||||
<li><p>Stop the application and pull the repository:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ git pull
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Update <strong>Makefile.custom.config</strong> if needed</p></li>
|
||||
<li><p>Upgrade packages and database:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make install
|
||||
$ make upgrade-db
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>Restart the server and dramatiq workers:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ make run
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="deployment">
|
||||
<h2>Deployment<a class="headerlink" href="#deployment" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There are several ways to start <strong>FitTrackee</strong> web application and task queue
|
||||
library.
|
||||
One way is to use a <strong>systemd</strong> services and <strong>Nginx</strong> to proxy pass to <strong>Gunicorn</strong>.</p>
|
||||
<p>Examples (to update depending on your application configuration and given distribution):</p>
|
||||
<ul class="simple">
|
||||
<li><p>for application: <code class="docutils literal notranslate"><span class="pre">fittrackee.service</span></code></p></li>
|
||||
</ul>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">Unit</span><span class="p">]</span>
|
||||
<span class="n">Description</span><span class="o">=</span><span class="n">FitTrackee</span> <span class="n">service</span>
|
||||
<span class="n">After</span><span class="o">=</span><span class="n">network</span><span class="o">.</span><span class="n">target</span>
|
||||
<span class="n">After</span><span class="o">=</span><span class="n">postgresql</span><span class="o">.</span><span class="n">service</span>
|
||||
<span class="n">After</span><span class="o">=</span><span class="n">redis</span><span class="o">.</span><span class="n">service</span>
|
||||
<span class="n">StartLimitIntervalSec</span><span class="o">=</span><span class="mi">0</span>
|
||||
|
||||
<span class="p">[</span><span class="n">Service</span><span class="p">]</span>
|
||||
<span class="n">Type</span><span class="o">=</span><span class="n">simple</span>
|
||||
<span class="n">Restart</span><span class="o">=</span><span class="n">always</span>
|
||||
<span class="n">RestartSec</span><span class="o">=</span><span class="mi">1</span>
|
||||
<span class="n">User</span><span class="o">=<</span><span class="n">USER</span><span class="o">></span>
|
||||
<span class="n">StandardOutput</span><span class="o">=</span><span class="n">syslog</span>
|
||||
<span class="n">StandardError</span><span class="o">=</span><span class="n">syslog</span>
|
||||
<span class="n">SyslogIdentifier</span><span class="o">=</span><span class="n">fittrackee</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"APP_SECRET_KEY="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"APP_LOG="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"UPLOAD_FOLDER="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"DATABASE_URL="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"UI_URL="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"EMAIL_URL="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"SENDER_EMAIL="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"REDIS_URL="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"TILE_SERVER_URL="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"MAP_ATTRIBUTION="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"WEATHER_API_KEY="</span>
|
||||
<span class="n">WorkingDirectory</span><span class="o">=/</span><span class="n">home</span><span class="o">/<</span><span class="n">USER</span><span class="o">>/<</span><span class="n">FITTRACKEE</span> <span class="n">DIRECTORY</span><span class="o">></span>
|
||||
<span class="n">ExecStart</span><span class="o">=/</span><span class="n">home</span><span class="o">/<</span><span class="n">USER</span><span class="o">>/<</span><span class="n">FITTRACKEE</span> <span class="n">DIRECTORY</span><span class="o">>/.</span><span class="n">venv</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">gunicorn</span> <span class="o">-</span><span class="n">b</span> <span class="mf">127.0</span><span class="o">.</span><span class="mf">0.1</span><span class="p">:</span><span class="mi">5000</span> <span class="s2">"fittrackee:create_app()"</span> <span class="o">--</span><span class="n">error</span><span class="o">-</span><span class="n">logfile</span> <span class="o">/</span><span class="n">home</span><span class="o">/<</span><span class="n">USER</span><span class="o">>/<</span><span class="n">FITTRACKEE</span> <span class="n">DIRECTORY</span><span class="o">>/</span><span class="n">gunicorn</span><span class="o">.</span><span class="n">log</span>
|
||||
<span class="n">Restart</span><span class="o">=</span><span class="n">always</span>
|
||||
|
||||
<span class="p">[</span><span class="n">Install</span><span class="p">]</span>
|
||||
<span class="n">WantedBy</span><span class="o">=</span><span class="n">multi</span><span class="o">-</span><span class="n">user</span><span class="o">.</span><span class="n">target</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p>for task queue workers: <code class="docutils literal notranslate"><span class="pre">fittrackee_workers.service</span></code></p></li>
|
||||
</ul>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">Unit</span><span class="p">]</span>
|
||||
<span class="n">Description</span><span class="o">=</span><span class="n">FitTrackee</span> <span class="n">task</span> <span class="n">queue</span> <span class="n">service</span>
|
||||
<span class="n">After</span><span class="o">=</span><span class="n">network</span><span class="o">.</span><span class="n">target</span>
|
||||
<span class="n">After</span><span class="o">=</span><span class="n">postgresql</span><span class="o">.</span><span class="n">service</span>
|
||||
<span class="n">After</span><span class="o">=</span><span class="n">redis</span><span class="o">.</span><span class="n">service</span>
|
||||
<span class="n">StartLimitIntervalSec</span><span class="o">=</span><span class="mi">0</span>
|
||||
|
||||
<span class="p">[</span><span class="n">Service</span><span class="p">]</span>
|
||||
<span class="n">Type</span><span class="o">=</span><span class="n">simple</span>
|
||||
<span class="n">Restart</span><span class="o">=</span><span class="n">always</span>
|
||||
<span class="n">RestartSec</span><span class="o">=</span><span class="mi">1</span>
|
||||
<span class="n">User</span><span class="o">=<</span><span class="n">USER</span><span class="o">></span>
|
||||
<span class="n">StandardOutput</span><span class="o">=</span><span class="n">syslog</span>
|
||||
<span class="n">StandardError</span><span class="o">=</span><span class="n">syslog</span>
|
||||
<span class="n">SyslogIdentifier</span><span class="o">=</span><span class="n">fittrackee_workers</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"FLASK_APP=fittrackee"</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"APP_SECRET_KEY="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"APP_LOG="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"UPLOAD_FOLDER="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"DATABASE_URL="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"UI_URL="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"EMAIL_URL="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"SENDER_EMAIL="</span>
|
||||
<span class="n">Environment</span><span class="o">=</span><span class="s2">"REDIS_URL="</span>
|
||||
<span class="n">WorkingDirectory</span><span class="o">=/</span><span class="n">home</span><span class="o">/<</span><span class="n">USER</span><span class="o">>/<</span><span class="n">FITTRACKEE</span> <span class="n">DIRECTORY</span><span class="o">></span>
|
||||
<span class="n">ExecStart</span><span class="o">=/</span><span class="n">home</span><span class="o">/<</span><span class="n">USER</span><span class="o">>/<</span><span class="n">FITTRACKEE</span> <span class="n">DIRECTORY</span><span class="o">>/.</span><span class="n">venv</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">flask</span> <span class="n">worker</span> <span class="o">--</span><span class="n">processes</span> <span class="o"><</span><span class="n">NUMBER</span> <span class="n">OF</span> <span class="n">PROCESSES</span><span class="o">></span>
|
||||
<span class="n">Restart</span><span class="o">=</span><span class="n">always</span>
|
||||
|
||||
<span class="p">[</span><span class="n">Install</span><span class="p">]</span>
|
||||
<span class="n">WantedBy</span><span class="o">=</span><span class="n">multi</span><span class="o">-</span><span class="n">user</span><span class="o">.</span><span class="n">target</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ul class="simple">
|
||||
<li><p><strong>Nginx</strong> configuration:</p></li>
|
||||
</ul>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>server {
|
||||
listen 443 ssl;
|
||||
server_name example.com;
|
||||
ssl_certificate fullchain.pem;
|
||||
ssl_certificate_key privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:5000;
|
||||
proxy_redirect default;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name example.com;
|
||||
location / {
|
||||
return 301 https://example.com$request_uri;
|
||||
}
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<p>More information on <a class="reference external" href="https://docs.gunicorn.org/en/stable/deploy.html">Gunicorn documentation</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
BIN
docs/objects.inv
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Search — FitTrackee 0.3.0-beta
|
||||
<title>Search — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
@ -44,7 +44,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Administrator — FitTrackee 0.3.0-beta
|
||||
<title>Administrator — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Troubleshooting — FitTrackee 0.3.0-beta
|
||||
<title>Troubleshooting — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>User — FitTrackee 0.3.0-beta
|
||||
<title>User — FitTrackee 0.4.0
|
||||
documentation</title>
|
||||
<link rel="stylesheet" href="../_static/bootstrap-sphinx.css" type="text/css" />
|
||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||||
@ -40,7 +40,8 @@
|
||||
</button>
|
||||
<a class="navbar-brand" href="../index.html">
|
||||
FitTrackee</a>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.3.0</b></span>
|
||||
<span class="navbar-text navbar-version pull-left"><b>0.4.0
|
||||
</b></span>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse nav-collapse">
|
||||
|
Before Width: | Height: | Size: 598 KiB After Width: | Height: | Size: 596 KiB |
Before Width: | Height: | Size: 541 KiB After Width: | Height: | Size: 374 KiB |
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 197 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 69 KiB |
@ -54,18 +54,37 @@ body {
|
||||
}
|
||||
|
||||
.alert-danger {
|
||||
background-color: #dc6460;
|
||||
border-color: transparent;
|
||||
background-color: #f2dede;
|
||||
border-color: #dca7a7;
|
||||
color: #a94442;
|
||||
}
|
||||
|
||||
.alert-info {
|
||||
background-color: #3eb3e3;
|
||||
border-color: transparent;
|
||||
background-color: #d9edf7;
|
||||
border-color: #9acfea;
|
||||
color: #31708f;
|
||||
}
|
||||
|
||||
.alert-warning {
|
||||
background-color: #f5894f;
|
||||
border-color: transparent;
|
||||
background-color: #fcf8e3;
|
||||
border-color: #f5e79e;
|
||||
color: #8a6d3b;
|
||||
}
|
||||
|
||||
.descname {
|
||||
border-top: solid 3px #a18bac;
|
||||
border-radius: unset;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
dl.field-list > dt {
|
||||
background: #f0f0f0;
|
||||
border-left: solid 3px #ccc;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.envvar {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
|
@ -1,7 +1,7 @@
|
||||
Activities
|
||||
##########
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
activities.get_activities,
|
||||
activities.get_activity,
|
||||
|
@ -1,7 +1,7 @@
|
||||
Authentication
|
||||
##############
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
auth.register_user,
|
||||
auth.login_user,
|
||||
|
@ -1,7 +1,7 @@
|
||||
Configuration
|
||||
#############
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
config.get_application_config,
|
||||
config.update_application_config,
|
||||
|
@ -1,6 +1,6 @@
|
||||
Records
|
||||
#######
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
records.get_records
|
||||
|
@ -1,7 +1,7 @@
|
||||
Sports
|
||||
######
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
sports.get_sports,
|
||||
sports.get_sport,
|
||||
|
@ -1,7 +1,7 @@
|
||||
Statistics
|
||||
##########
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
stats.get_activities_by_time,
|
||||
stats.get_activities_by_sport,
|
||||
|
@ -1,7 +1,7 @@
|
||||
Users
|
||||
#####
|
||||
|
||||
.. autoflask:: fittrackee_api:create_app()
|
||||
.. autoflask:: fittrackee:create_app()
|
||||
:endpoints:
|
||||
users.get_users,
|
||||
users.get_single_user,
|
||||
|
@ -16,7 +16,7 @@ from pathlib import Path
|
||||
|
||||
import sphinx_bootstrap_theme
|
||||
|
||||
sys.path.insert(0, os.path.abspath('../../fittrackee_api'))
|
||||
sys.path.insert(0, os.path.abspath('../../fittrackee'))
|
||||
|
||||
|
||||
def setup(app):
|
||||
|
@ -4,13 +4,10 @@ Features
|
||||
List
|
||||
~~~~
|
||||
|
||||
Account
|
||||
^^^^^^^
|
||||
- A user can create, update and deleted his account
|
||||
- Password reset is now available
|
||||
|
||||
Administration
|
||||
^^^^^^^^^^^^^^
|
||||
(*new in 0.3.0*)
|
||||
|
||||
- **Application**
|
||||
|
||||
The following parameters can be set:
|
||||
@ -30,6 +27,12 @@ Administration
|
||||
|
||||
- enable or disable a sport (a sport can be disabled even if activity with this sport exists)
|
||||
|
||||
Account
|
||||
^^^^^^^
|
||||
- A user can create, update and deleted his account
|
||||
- A user can reset his password (*new in 0.3.0*)
|
||||
|
||||
|
||||
Activities/Workouts
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
- 6 sports supported:
|
||||
|
@ -22,7 +22,7 @@ FitTrackee
|
||||
Map <https://www.openstreetmap.org>`__.
|
||||
| It is also possible to add a workout without a gpx file.
|
||||
|
||||
| **Still under development (not ready for production).**
|
||||
| **Still under heavy development (some features may be unstable).**
|
||||
| (see `issues <https://github.com/SamR1/FitTrackee/issues>`__ for more information)
|
||||
|
||||
.. figure:: _images/fittrackee_screenshot-01.png
|
||||
|
@ -22,194 +22,221 @@ Prerequisites
|
||||
- PostgreSQL database (10+)
|
||||
- Redis for task queue
|
||||
- Python 3.7+
|
||||
- `Poetry <https://poetry.eustace.io>`__
|
||||
- `Yarn <https://yarnpkg.com>`__ and
|
||||
`serve <https://github.com/zeit/serve>`__
|
||||
- `Poetry <https://poetry.eustace.io>`__ (for installation from sources only)
|
||||
- API key from `Dark Sky <https://darksky.net/dev>`__ [not mandatory]
|
||||
- SMTP provider
|
||||
- `Yarn <https://yarnpkg.com>`__ (for development only)
|
||||
- Docker (for development only, to start `MailHog <https://github.com/mailhog/MailHog>`__)
|
||||
|
||||
|
||||
Installation
|
||||
~~~~~~~~~~~~
|
||||
|
||||
| The following steps describe an installation on Linux systems (tested
|
||||
.. note::
|
||||
| The following steps describe an installation on Linux systems (tested
|
||||
on Debian and Arch).
|
||||
| On other OS, some issues can be encountered and adaptations may be
|
||||
| On other OS, some issues can be encountered and adaptations may be
|
||||
necessary.
|
||||
|
||||
.. warning::
|
||||
Since FitTrackee 0.2.1, Python packages installation needs Poetry. To install it on ArchLinux:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ yay poetry
|
||||
$ poetry --version
|
||||
Poetry 1.0.5
|
||||
|
||||
# optional
|
||||
$ poetry config virtualenvs.in-project true
|
||||
|
||||
For other OS, see `Poetry Documentation <https://python-poetry.org/docs/#installation>`__
|
||||
|
||||
|
||||
Dev environment
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- Clone this repo:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ git clone https://github.com/SamR1/FitTrackee.git
|
||||
$ cd FitTrackee
|
||||
|
||||
- Update **Makefile.config** file if needed and copy/paste the
|
||||
**ThunderForest** and **Dark Sky** API keys value in
|
||||
**Makefile.custom.config** file (see `Environment variables <installation.html#environment-variables>`__).
|
||||
|
||||
- Install Python virtualenv, React and all related packages and
|
||||
initialize the database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-dev
|
||||
$ make install-db
|
||||
|
||||
- Start the server and the client:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make serve
|
||||
|
||||
- Run dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run-workers
|
||||
|
||||
Open http://localhost:3000 and login (the email is ``admin@example.com``
|
||||
and the password ``mpwoadmin``) or register
|
||||
|
||||
Prod environment
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. warning::
|
||||
Note that FitTrackee is not production-ready yet
|
||||
|
||||
- Download the last release (for now, it is the beta release v0.3.0):
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.3.0-beta.tar.gz
|
||||
$ tar -xzf v0.3.0-beta.tar.gz
|
||||
$ mv FitTrackee-0.3.0-beta FitTrackee
|
||||
$ cd FitTrackee
|
||||
|
||||
- Update **Makefile.config** file if needed and copy/paste the
|
||||
**ThunderForest** and **Dark Sky** API keys value in
|
||||
**Makefile.custom.config** file (see `Environment variables <installation.html#environment-variables>`__).
|
||||
|
||||
- Install Python virtualenv, React and all related packages and
|
||||
initialize the database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install
|
||||
$ make install-db
|
||||
|
||||
- Build the client:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make build-client
|
||||
|
||||
- Start the server and the client:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run
|
||||
|
||||
- Run dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run-workers
|
||||
|
||||
Open http://localhost:3000, log in as admin (the email is
|
||||
``admin@example.com`` and the password ``mpwoadmin``) and change the
|
||||
password
|
||||
|
||||
Upgrade
|
||||
~~~~~~~
|
||||
|
||||
.. warning::
|
||||
| Before upgrading, make a backup of all data:
|
||||
| - database (with `pg_dump <https://www.postgresql.org/docs/11/app-pgdump.html>`__ for instance)
|
||||
| - upload directory: **FitTrackee/fittrackee_api/fittrackee_api/uploads/**
|
||||
|
||||
|
||||
Dev environment
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
- Stop the application and pull the repository:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ git pull
|
||||
|
||||
- Update **Makefile.config** and **Makefile.custom.config** file if needed
|
||||
|
||||
- Upgrade packages and database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-dev
|
||||
$ make upgrade-db
|
||||
|
||||
- Restart the server and the client:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make serve
|
||||
|
||||
|
||||
Prod environment
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
``TODO``
|
||||
|
||||
|
||||
Environment variables
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following environment variables must be defined in **Makefile.custom.config**:
|
||||
.. warning::
|
||||
| Since FitTrackee 0.4.0, ``Makefile.custom.config`` is replaced by ``.env``
|
||||
|
||||
.. cssclass:: table-bordered table-striped
|
||||
The following environment variables are used by **FitTrackee** web application
|
||||
or the task processing library. They are not all mandatory depending on
|
||||
deployment method.
|
||||
|
||||
===================================== ============================================== ====================================
|
||||
variable description app default value
|
||||
===================================== ============================================== ====================================
|
||||
``REACT_APP_API_URL`` Fittrackee API URL no default value, must be initialized
|
||||
``REACT_APP_GPX_LIMIT_IMPORT`` max. number of gpx file in zip archive 10 (*deprecated in 0.3.0*)
|
||||
``REACT_APP_MAX_SINGLE_FILE_SIZE`` max. size of a gpx or picture file 1MB (*deprecated in 0.3.0*)
|
||||
``REACT_APP_MAX_ZIP_FILE_SIZE`` max. size of a zip archive 10MB (*deprecated in 0.3.0*)
|
||||
``REACT_APP_ALLOW_REGISTRATION`` allows users to register true (*deprecated in 0.3.0*)
|
||||
``REACT_APP_THUNDERFOREST_API_KEY`` ThunderForest API key (*deprecated in 0.x.x*, use ``TILE_SERVER_URL`` **and** ``MAP_ATTRIBUTION`` instead)
|
||||
``TILE_SERVER_URL`` Tile server URL (with api key if needed) ``https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png``
|
||||
``MAP_ATTRIBUTION`` Map attribution (if using another tile server) ``© <a href="http://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">OpenStreetMap</a> contributors``
|
||||
``UI_URL`` application URL no default value, must be initialized
|
||||
``EMAIL_URL`` email URL with credentials no default value, must be initialized (see below)
|
||||
``SENDER_EMAIL`` application sender email address no default value, must be initialized
|
||||
``REDIS_URL`` Redis instance used by Dramatiq local Redis instance
|
||||
``WORKERS_PROCESSES`` number of process used by Dramatiq no default value, must be initialized
|
||||
===================================== ============================================== ====================================
|
||||
.. envvar:: FLASK_APP
|
||||
|
||||
| Name of the module to import at flask run.
|
||||
| ``FLASK_APP`` should contain ``$(PWD)/fittrackee/__main__.py`` with installation from sources, else ``fittrackee``.
|
||||
|
||||
|
||||
.. envvar:: HOST
|
||||
|
||||
**FitTrackee** host.
|
||||
|
||||
:default: 0.0.0.0
|
||||
|
||||
|
||||
.. envvar:: PORT
|
||||
|
||||
**FitTrackee** port.
|
||||
|
||||
:default: 5000
|
||||
|
||||
|
||||
.. envvar:: APP_SETTINGS
|
||||
|
||||
**FitTrackee** configuration.
|
||||
|
||||
:default: fittrackee.config.ProductionConfig
|
||||
|
||||
|
||||
.. envvar:: APP_SECRET_KEY
|
||||
|
||||
**FitTrackee** secret key, must be initialized in production environment.
|
||||
|
||||
|
||||
.. envvar:: APP_WORKERS
|
||||
|
||||
Number of workers spawned by **Gunicorn**.
|
||||
|
||||
:default: 1
|
||||
|
||||
|
||||
.. envvar:: APP_LOG 🆕
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Path to log file
|
||||
|
||||
|
||||
.. envvar:: UPLOAD_FOLDER 🆕
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Directory containing uploaded files.
|
||||
|
||||
:default: `fittrackee/uploads/`
|
||||
|
||||
.. danger::
|
||||
| With installation from PyPI, the directory will be located in
|
||||
**virtualenv** directory if the variable is not initialized.
|
||||
|
||||
.. envvar:: DATABASE_URL
|
||||
|
||||
| Database URL with username and password, must be initialized in production environment.
|
||||
| For example in dev environment : ``postgres://fittrackee:fittrackee@localhost:5432/fittrackee``
|
||||
|
||||
|
||||
.. envvar:: DATABASE_DISABLE_POOLING 🆕
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Disable pooling if needed (when starting application with **FitTrackee** entry point and not directly with **Gunicorn**),
|
||||
see `SqlAlchemy documentation <https://docs.sqlalchemy.org/en/13/core/pooling.html#using-connection-pools-with-multiprocessing-or-os-fork>`__.
|
||||
|
||||
:default: false
|
||||
|
||||
.. envvar:: UI_URL
|
||||
|
||||
**FitTrackee** URL, needed for links in emails.
|
||||
|
||||
|
||||
.. envvar:: EMAIL_URL
|
||||
|
||||
.. versionadded:: 0.3.0
|
||||
|
||||
Email URL with credentials, see `Emails <installation.html#emails>`__.
|
||||
|
||||
|
||||
.. envvar:: SENDER_EMAIL
|
||||
|
||||
.. versionadded:: 0.3.0
|
||||
|
||||
**FitTrackee** sender email address.
|
||||
|
||||
|
||||
.. envvar:: REDIS_URL
|
||||
|
||||
.. versionadded:: 0.3.0
|
||||
|
||||
Redis instance used by **Dramatiq**.
|
||||
|
||||
:default: local Redis instance (``redis://``)
|
||||
|
||||
|
||||
.. envvar:: WORKERS_PROCESSES
|
||||
|
||||
.. versionadded:: 0.3.0
|
||||
|
||||
Number of processes used by **Dramatiq**.
|
||||
|
||||
|
||||
.. envvar:: TILE_SERVER_URL 🆕
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Tile server URL (with api key if needed), see `Map tile server <installation.html#map-tile-server>`__.
|
||||
|
||||
:default: `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`
|
||||
|
||||
|
||||
.. envvar:: MAP_ATTRIBUTION 🆕
|
||||
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Map attribution (if using another tile server), see `Map tile server <installation.html#map-tile-server>`__.
|
||||
|
||||
:default: `© <a href="http://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">OpenStreetMap</a> contributors`
|
||||
|
||||
|
||||
.. envvar:: WEATHER_API_KEY
|
||||
|
||||
.. versionchanged:: 0.4.0 ⚠️ replaces ``WEATHER_API``
|
||||
|
||||
**Dark Sky** API key for weather data (not mandatory).
|
||||
|
||||
|
||||
.. envvar:: REACT_APP_API_URL
|
||||
|
||||
**FitTrackee** API URL, only needed in dev environment.
|
||||
|
||||
|
||||
|
||||
Deprecated variables
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. envvar:: REACT_APP_GPX_LIMIT_IMPORT
|
||||
|
||||
.. deprecated:: 0.3.0 now stored in database
|
||||
|
||||
Maximum number of gpx file in zip archive.
|
||||
|
||||
:default: 10
|
||||
|
||||
|
||||
.. envvar:: REACT_APP_MAX_SINGLE_FILE_SIZE
|
||||
|
||||
.. deprecated:: 0.3.0 now stored in database
|
||||
|
||||
Maximum size of a gpx or picture file.
|
||||
|
||||
:default: 1MB
|
||||
|
||||
|
||||
.. envvar:: REACT_APP_MAX_ZIP_FILE_SIZE
|
||||
|
||||
.. deprecated:: 0.3.0 now stored in database
|
||||
|
||||
Maximum size of a zip archive.
|
||||
|
||||
:default: 10MB
|
||||
|
||||
|
||||
.. envvar:: REACT_APP_ALLOW_REGISTRATION
|
||||
|
||||
.. deprecated:: 0.3.0 now stored in database
|
||||
|
||||
Allows users to register.
|
||||
|
||||
:default: true
|
||||
|
||||
|
||||
.. envvar:: REACT_APP_THUNDERFOREST_API_KEY
|
||||
|
||||
.. deprecated:: 0.4.0 see `TILE_SERVER_URL <installation.html#envvar-TILE_SERVER_URL>`__
|
||||
|
||||
ThunderForest API key.
|
||||
|
||||
.. warning::
|
||||
Since FitTrackee 0.3.0, some applications parameters are now stored in database.
|
||||
Related environment variables are needed to initialize database.
|
||||
| Since FitTrackee 0.3.0, some applications parameters are now stored in database.
|
||||
| Related environment variables are needed to initialize database when upgrading from version prior 0.3.0.
|
||||
|
||||
|
||||
Emails
|
||||
^^^^^^
|
||||
*new in 0.3.0*
|
||||
.. versionadded:: 0.3.0
|
||||
|
||||
To send emails, a valid ``EMAIL_URL`` must be provided:
|
||||
|
||||
@ -220,15 +247,392 @@ To send emails, a valid ``EMAIL_URL`` must be provided:
|
||||
|
||||
Map tile server
|
||||
^^^^^^^^^^^^^^^
|
||||
*new in 0.x.x*
|
||||
.. versionadded:: 0.4.0
|
||||
|
||||
Default tile server is now **OpenStreetMap**'s standard tile layer (if environment variables are not initialized).
|
||||
The tile server can be changed by updating ``TILE_SERVER_URL`` and ``MAP_ATTRIBUTION`` variables (`list of tile servers <https://wiki.openstreetmap.org/wiki/Tile_servers>`__).
|
||||
|
||||
To keep using ThunderForest Outdoors, the configuration is:
|
||||
To keep using **ThunderForest Outdoors**, the configuration is:
|
||||
|
||||
- ``TILE_SERVER_URL=https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=XXXX`` where **XXXX** is ThunderForest API key
|
||||
- ``TILE_SERVER_URL=https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=XXXX`` where **XXXX** is **ThunderForest** API key
|
||||
- ``MAP_ATTRIBUTION=© <a href="http://www.thunderforest.com/">Thunderforest</a>, © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors``
|
||||
|
||||
.. note::
|
||||
Check the terms of service of tile provider for map attribution
|
||||
| Check the terms of service of tile provider for map attribution
|
||||
|
||||
From PyPI
|
||||
~~~~~~~~~
|
||||
|
||||
.. note::
|
||||
| Recommended way on production.
|
||||
|
||||
.. warning::
|
||||
| Note that FitTrackee is under heavy development, some features may be unstable.
|
||||
|
||||
Installation
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- Create and activate a virtualenv
|
||||
|
||||
- Install **FitTrackee** with pip
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install fittrackee
|
||||
|
||||
- Create ``fittrackee`` database
|
||||
|
||||
Example :
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
CREATE DATABASE fittrackee;
|
||||
CREATE USER fittrackee WITH PASSWORD '<PASSWORD>';
|
||||
GRANT ALL PRIVILEGES ON DATABASE fittrackee TO fittrackee;
|
||||
|
||||
- Initialize environment variables, see `Environment variables <installation.html#environment-variables>`__
|
||||
|
||||
For instance, copy and update ``.env`` file from ``.env.example`` and source the file.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ nano .env
|
||||
$ source .env
|
||||
|
||||
|
||||
- Upgrade database schema
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ fittrackee_upgrade_db
|
||||
|
||||
- Initialize database
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ fittrackee_init_data
|
||||
|
||||
- Start the application
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ fittrackee
|
||||
|
||||
- Start task queue workers
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ fittrackee_worker --processes 2
|
||||
|
||||
.. note::
|
||||
| To start application and workers with **systemd** service, see `Deployment <installation.html#deployment>`__
|
||||
|
||||
|
||||
Upgrade
|
||||
^^^^^^^
|
||||
|
||||
.. warning::
|
||||
| Before upgrading, make a backup of all data:
|
||||
| - database (with `pg_dump <https://www.postgresql.org/docs/11/app-pgdump.html>`__ for instance)
|
||||
| - upload directory (see `Environment variables <installation.html#environment-variables>`__)
|
||||
|
||||
- Activate the virtualenv
|
||||
|
||||
- Upgrade with pip
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install -U fittrackee
|
||||
|
||||
- Update environment variables if needed and source environment variables file
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ nano .env
|
||||
$ source .env
|
||||
|
||||
- Upgrade database if needed
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ fittrackee_upgrade_db
|
||||
|
||||
|
||||
- Restart the application and task queue workers.
|
||||
|
||||
|
||||
From sources
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
.. warning::
|
||||
| Since FitTrackee 0.2.1, Python packages installation needs Poetry.
|
||||
| To install it on ArchLinux:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ yay poetry
|
||||
$ poetry --version
|
||||
Poetry 1.0.10
|
||||
|
||||
# optional
|
||||
$ poetry config virtualenvs.in-project true
|
||||
|
||||
For other OS, see `Poetry Documentation <https://python-poetry.org/docs/#installation>`__
|
||||
|
||||
|
||||
Installation
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Dev environment
|
||||
"""""""""""""""
|
||||
|
||||
- Clone this repo:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ git clone https://github.com/SamR1/FitTrackee.git
|
||||
$ cd FitTrackee
|
||||
|
||||
- Create **Makefile.custom.config** from example and update it
|
||||
(see `Environment variables <installation.html#environment-variables>`__).
|
||||
|
||||
- Install Python virtualenv, React and all related packages and
|
||||
initialize the database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-dev
|
||||
$ make install-db
|
||||
|
||||
- Start the server and the client:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make serve
|
||||
|
||||
- Run dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run-workers
|
||||
|
||||
Open http://localhost:3000 and log in (the email is ``admin@example.com``
|
||||
and the password ``mpwoadmin``) or register
|
||||
|
||||
|
||||
Production environment
|
||||
""""""""""""""""""""""
|
||||
|
||||
.. warning::
|
||||
| Note that FitTrackee is under heavy development, some features may be unstable.
|
||||
|
||||
- Download the last release (for now, it is the release v0.4.0):
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ wget https://github.com/SamR1/FitTrackee/archive/v0.4.0.tar.gz
|
||||
$ tar -xzf v0.4.0.tar.gz
|
||||
$ mv FitTrackee-0.4.0 FitTrackee
|
||||
$ cd FitTrackee
|
||||
|
||||
- Create **Makefile.custom.config** from example and update it
|
||||
(see `Environment variables <installation.html#environment-variables>`__).
|
||||
|
||||
- Install Python virtualenv and all related packages:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-python
|
||||
|
||||
- Initialize the database (**after updating** ``db/create.sql`` **to change
|
||||
database credentials**):
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-db
|
||||
|
||||
- Start the server and dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run
|
||||
|
||||
Open http://localhost:5000, log in as admin (the email is
|
||||
``admin@example.com`` and the password ``mpwoadmin``) and change the
|
||||
password
|
||||
|
||||
Upgrade
|
||||
^^^^^^^
|
||||
|
||||
.. warning::
|
||||
| Before upgrading, make a backup of all data:
|
||||
| - database (with `pg_dump <https://www.postgresql.org/docs/11/app-pgdump.html>`__ for instance)
|
||||
| - upload directory (see `Environment variables <installation.html#environment-variables>`__)
|
||||
|
||||
|
||||
Dev environment
|
||||
"""""""""""""""
|
||||
|
||||
- Stop the application and pull the repository:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ git pull
|
||||
|
||||
- Update **.env** if needed
|
||||
|
||||
- Upgrade packages and database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install-dev
|
||||
$ make upgrade-db
|
||||
|
||||
- Restart the server:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make serve
|
||||
|
||||
- Run dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run-workers
|
||||
|
||||
Prod environment
|
||||
""""""""""""""""
|
||||
|
||||
- Stop the application and pull the repository:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ git pull
|
||||
|
||||
- Update **Makefile.custom.config** if needed
|
||||
|
||||
- Upgrade packages and database:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make install
|
||||
$ make upgrade-db
|
||||
|
||||
- Restart the server and dramatiq workers:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
$ make run
|
||||
|
||||
|
||||
Deployment
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
There are several ways to start **FitTrackee** web application and task queue
|
||||
library.
|
||||
One way is to use a **systemd** services and **Nginx** to proxy pass to **Gunicorn**.
|
||||
|
||||
Examples (to update depending on your application configuration and given distribution):
|
||||
|
||||
- for application: ``fittrackee.service``
|
||||
|
||||
.. code-block::
|
||||
|
||||
[Unit]
|
||||
Description=FitTrackee service
|
||||
After=network.target
|
||||
After=postgresql.service
|
||||
After=redis.service
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
User=<USER>
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=fittrackee
|
||||
Environment="APP_SECRET_KEY="
|
||||
Environment="APP_LOG="
|
||||
Environment="UPLOAD_FOLDER="
|
||||
Environment="DATABASE_URL="
|
||||
Environment="UI_URL="
|
||||
Environment="EMAIL_URL="
|
||||
Environment="SENDER_EMAIL="
|
||||
Environment="REDIS_URL="
|
||||
Environment="TILE_SERVER_URL="
|
||||
Environment="MAP_ATTRIBUTION="
|
||||
Environment="WEATHER_API_KEY="
|
||||
WorkingDirectory=/home/<USER>/<FITTRACKEE DIRECTORY>
|
||||
ExecStart=/home/<USER>/<FITTRACKEE DIRECTORY>/.venv/bin/gunicorn -b 127.0.0.1:5000 "fittrackee:create_app()" --error-logfile /home/<USER>/<FITTRACKEE DIRECTORY>/gunicorn.log
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
- for task queue workers: ``fittrackee_workers.service``
|
||||
|
||||
.. code-block::
|
||||
|
||||
[Unit]
|
||||
Description=FitTrackee task queue service
|
||||
After=network.target
|
||||
After=postgresql.service
|
||||
After=redis.service
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
User=<USER>
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=fittrackee_workers
|
||||
Environment="FLASK_APP=fittrackee"
|
||||
Environment="APP_SECRET_KEY="
|
||||
Environment="APP_LOG="
|
||||
Environment="UPLOAD_FOLDER="
|
||||
Environment="DATABASE_URL="
|
||||
Environment="UI_URL="
|
||||
Environment="EMAIL_URL="
|
||||
Environment="SENDER_EMAIL="
|
||||
Environment="REDIS_URL="
|
||||
WorkingDirectory=/home/<USER>/<FITTRACKEE DIRECTORY>
|
||||
ExecStart=/home/<USER>/<FITTRACKEE DIRECTORY>/.venv/bin/flask worker --processes <NUMBER OF PROCESSES>
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
- **Nginx** configuration:
|
||||
|
||||
.. code-block::
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name example.com;
|
||||
ssl_certificate fullchain.pem;
|
||||
ssl_certificate_key privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:5000;
|
||||
proxy_redirect default;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Host $server_name;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name example.com;
|
||||
location / {
|
||||
return 301 https://example.com$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
.. note::
|
||||
More information on `Gunicorn documentation <https://docs.gunicorn.org/en/stable/deploy.html>`__
|
38
e2e/test_activities.py
Normal file
@ -0,0 +1,38 @@
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.support.ui import Select, WebDriverWait
|
||||
|
||||
from .utils import TEST_URL, register_valid_user
|
||||
|
||||
|
||||
class TestActivity:
|
||||
def test_user_can_add_activity_without_gpx(self, selenium):
|
||||
register_valid_user(selenium)
|
||||
nav_items = selenium.find_elements_by_class_name('nav-item')
|
||||
|
||||
nav_items[3].click()
|
||||
selenium.implicitly_wait(1)
|
||||
radio_buttons = selenium.find_elements_by_class_name(
|
||||
'add-activity-radio'
|
||||
)
|
||||
radio_buttons[1].click()
|
||||
|
||||
selenium.find_element_by_name('title').send_keys('Activity title')
|
||||
select = Select(selenium.find_element_by_name('sport_id'))
|
||||
select.select_by_index(1)
|
||||
selenium.find_element_by_name('activity_date').send_keys('2018-12-20')
|
||||
selenium.find_element_by_name('activity_time').send_keys('14:05')
|
||||
selenium.find_element_by_name('duration').send_keys('01:00:00')
|
||||
selenium.find_element_by_name('distance').send_keys('10')
|
||||
selenium.find_element_by_class_name('btn-primary').click()
|
||||
|
||||
WebDriverWait(selenium, 10).until(
|
||||
EC.url_changes(f"{TEST_URL}/activities/add")
|
||||
)
|
||||
|
||||
activity_details = selenium.find_element_by_class_name(
|
||||
'activity-details'
|
||||
).text
|
||||
assert 'Duration: 1:00:00' in activity_details
|
||||
assert 'Distance: 10 km' in activity_details
|
||||
assert 'Average speed: 10 km/h' in activity_details
|
||||
assert 'Max. speed: 10 km/h' in activity_details
|
17
e2e/test_index.py
Normal file
@ -0,0 +1,17 @@
|
||||
from .utils import TEST_URL
|
||||
|
||||
|
||||
class TestIndex:
|
||||
def test_title_contains_fittrackee(self, selenium):
|
||||
selenium.get(TEST_URL)
|
||||
assert 'FitTrackee' in selenium.title
|
||||
|
||||
def test_navbar_contains_all_links(self, selenium):
|
||||
selenium.get(TEST_URL)
|
||||
|
||||
nav = selenium.find_element_by_tag_name('nav').text
|
||||
assert "FitTrackee" in nav
|
||||
assert "Dashboard" in nav
|
||||
assert "Login" in nav
|
||||
assert "Register" in nav
|
||||
assert "en" in nav
|
40
e2e/test_login.py
Normal file
@ -0,0 +1,40 @@
|
||||
from .utils import TEST_URL, assert_navbar, login_valid_user
|
||||
|
||||
URL = f'{TEST_URL}/login'
|
||||
|
||||
|
||||
class TestLogin:
|
||||
def test_navbar_contains_login(self, selenium):
|
||||
selenium.get(URL)
|
||||
|
||||
nav = selenium.find_element_by_tag_name('nav').text
|
||||
assert 'Login' in nav
|
||||
|
||||
def test_h1_contains_login(self, selenium):
|
||||
selenium.get(URL)
|
||||
|
||||
title = selenium.find_element_by_tag_name('h1').text
|
||||
assert 'Login' in title
|
||||
|
||||
def test_it_displays_login_form(self, selenium):
|
||||
selenium.get(URL)
|
||||
|
||||
inputs = selenium.find_elements_by_tag_name('input')
|
||||
assert len(inputs) == 3
|
||||
assert inputs[0].get_attribute('name') == 'email'
|
||||
assert inputs[0].get_attribute('type') == 'email'
|
||||
assert inputs[1].get_attribute('name') == 'password'
|
||||
assert inputs[1].get_attribute('type') == 'password'
|
||||
assert inputs[2].get_attribute('name') == ''
|
||||
assert inputs[2].get_attribute('type') == 'submit'
|
||||
|
||||
def test_user_can_log_in(self, selenium):
|
||||
user = {
|
||||
'username': 'admin',
|
||||
'email': 'admin@example.com',
|
||||
'password': 'mpwoadmin',
|
||||
}
|
||||
|
||||
login_valid_user(selenium, user)
|
||||
|
||||
assert_navbar(selenium, user)
|
19
e2e/test_logout.py
Normal file
@ -0,0 +1,19 @@
|
||||
from .utils import register_valid_user
|
||||
|
||||
|
||||
class TestLogout:
|
||||
def test_user_can_log_out(self, selenium):
|
||||
user = register_valid_user(selenium)
|
||||
nav_items = selenium.find_elements_by_class_name('nav-item')
|
||||
|
||||
nav_items[5].click()
|
||||
selenium.implicitly_wait(1)
|
||||
|
||||
nav = selenium.find_element_by_tag_name('nav').text
|
||||
assert 'Register' in nav
|
||||
assert 'Login' in nav
|
||||
assert user['username'] not in nav
|
||||
assert 'Logout' not in nav
|
||||
|
||||
message = selenium.find_element_by_class_name('card-body').text
|
||||
assert 'You are now logged out. Click here to log back in.' in message
|
20
e2e/test_profile.py
Normal file
@ -0,0 +1,20 @@
|
||||
from .utils import TEST_URL, register_valid_user
|
||||
|
||||
URL = f'{TEST_URL}/profile'
|
||||
|
||||
|
||||
class TestProfile:
|
||||
def test_it_displays_user_profile(self, selenium):
|
||||
user = register_valid_user(selenium)
|
||||
|
||||
selenium.get(URL)
|
||||
|
||||
assert 'Profile' in selenium.find_element_by_tag_name('h1').text
|
||||
assert (
|
||||
user['username']
|
||||
in selenium.find_element_by_class_name('userName').text
|
||||
)
|
||||
assert (
|
||||
user['username']
|
||||
in selenium.find_element_by_class_name('userName').text
|
||||
)
|
141
e2e/test_registration.py
Normal file
@ -0,0 +1,141 @@
|
||||
from .utils import (
|
||||
TEST_URL,
|
||||
assert_navbar,
|
||||
random_string,
|
||||
register,
|
||||
register_valid_user,
|
||||
)
|
||||
|
||||
URL = f'{TEST_URL}/register'
|
||||
|
||||
|
||||
class TestRegistration:
|
||||
def test_it_displays_registration_form(self, selenium):
|
||||
selenium.get(URL)
|
||||
selenium.implicitly_wait(1)
|
||||
|
||||
inputs = selenium.find_elements_by_tag_name('input')
|
||||
assert len(inputs) == 5
|
||||
assert inputs[0].get_attribute('name') == 'username'
|
||||
assert inputs[0].get_attribute('type') == 'text'
|
||||
assert inputs[1].get_attribute('name') == 'email'
|
||||
assert inputs[1].get_attribute('type') == 'email'
|
||||
assert inputs[2].get_attribute('name') == 'password'
|
||||
assert inputs[2].get_attribute('type') == 'password'
|
||||
assert inputs[3].get_attribute('name') == 'password_conf'
|
||||
assert inputs[3].get_attribute('type') == 'password'
|
||||
assert inputs[4].get_attribute('name') == ''
|
||||
assert inputs[4].get_attribute('type') == 'submit'
|
||||
|
||||
def test_user_can_register(self, selenium):
|
||||
user = register_valid_user(selenium)
|
||||
|
||||
assert_navbar(selenium, user)
|
||||
|
||||
def test_user_can_not_register_with_invalid_email(self, selenium):
|
||||
user_name = random_string()
|
||||
user_infos = {
|
||||
'username': user_name,
|
||||
'email': user_name,
|
||||
'password': 'p@ssw0rd',
|
||||
'password_conf': 'p@ssw0rd',
|
||||
}
|
||||
|
||||
register(selenium, user_infos)
|
||||
|
||||
assert selenium.current_url == URL
|
||||
nav = selenium.find_element_by_tag_name('nav').text
|
||||
assert 'Register' in nav
|
||||
assert 'Login' in nav
|
||||
|
||||
def test_user_can_not_register_if_username_is_already_taken(
|
||||
self, selenium
|
||||
):
|
||||
user_name = random_string()
|
||||
user_infos = {
|
||||
'username': 'admin',
|
||||
'email': f'{user_name}@example.com',
|
||||
'password': 'p@ssw0rd',
|
||||
'password_conf': 'p@ssw0rd',
|
||||
}
|
||||
|
||||
register(selenium, user_infos)
|
||||
|
||||
assert selenium.current_url == URL
|
||||
errors = selenium.find_element_by_tag_name('code').text
|
||||
assert 'Sorry. That user already exists.' in errors
|
||||
|
||||
def test_user_can_not_register_if_email_is_already_taken(self, selenium):
|
||||
user_name = random_string()
|
||||
user_infos = {
|
||||
'username': user_name,
|
||||
'email': 'admin@example.com',
|
||||
'password': 'p@ssw0rd',
|
||||
'password_conf': 'p@ssw0rd',
|
||||
}
|
||||
|
||||
register(selenium, user_infos)
|
||||
|
||||
assert selenium.current_url == URL
|
||||
errors = selenium.find_element_by_tag_name('code').text
|
||||
assert 'Sorry. That user already exists.' in errors
|
||||
|
||||
def test_user_can_not_register_if_username_is_too_short(self, selenium):
|
||||
user_name = random_string(2)
|
||||
user_infos = {
|
||||
'username': user_name,
|
||||
'email': 'admin@example.com',
|
||||
'password': 'p@ssw0rd',
|
||||
'password_conf': 'p@ssw0rd',
|
||||
}
|
||||
|
||||
register(selenium, user_infos)
|
||||
|
||||
assert selenium.current_url == URL
|
||||
errors = selenium.find_element_by_tag_name('code').text
|
||||
assert '3 to 12 characters required for username.' in errors
|
||||
|
||||
def test_user_can_not_register_if_username_is_too_long(self, selenium):
|
||||
user_name = random_string(13)
|
||||
user_infos = {
|
||||
'username': user_name,
|
||||
'email': 'admin@example.com',
|
||||
'password': 'p@ssw0rd',
|
||||
'password_conf': 'p@ssw0rd',
|
||||
}
|
||||
|
||||
register(selenium, user_infos)
|
||||
|
||||
assert selenium.current_url == URL
|
||||
errors = selenium.find_element_by_tag_name('code').text
|
||||
assert '3 to 12 characters required for username.' in errors
|
||||
|
||||
def test_it_displays_error_if_passwords_do_not_match(self, selenium):
|
||||
user_name = random_string()
|
||||
user_infos = {
|
||||
'username': user_name,
|
||||
'email': f'{user_name}@example.com',
|
||||
'password': 'p@ssw0rd',
|
||||
'password_conf': 'password',
|
||||
}
|
||||
|
||||
register(selenium, user_infos)
|
||||
|
||||
assert selenium.current_url == URL
|
||||
errors = selenium.find_element_by_tag_name('code').text
|
||||
assert 'Password and password confirmation don\'t match' in errors
|
||||
|
||||
def test_it_displays_error_if_password_is_too_short(self, selenium):
|
||||
user_name = random_string()
|
||||
user_infos = {
|
||||
'username': user_name,
|
||||
'email': f'{user_name}@example.com',
|
||||
'password': 'p@ss',
|
||||
'password_conf': 'p@ss',
|
||||
}
|
||||
|
||||
register(selenium, user_infos)
|
||||
|
||||
assert selenium.current_url == URL
|
||||
errors = selenium.find_element_by_tag_name('code').text
|
||||
assert '8 characters required for password.' in errors
|
73
e2e/utils.py
Normal file
@ -0,0 +1,73 @@
|
||||
import os
|
||||
import random
|
||||
import string
|
||||
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
|
||||
TEST_APP_URL = os.getenv('TEST_APP_URL')
|
||||
TEST_CLIENT_URL = os.getenv('TEST_CLIENT_URL')
|
||||
E2E_ARGS = os.getenv('E2E_ARGS')
|
||||
TEST_URL = TEST_CLIENT_URL if E2E_ARGS == 'client' else TEST_APP_URL
|
||||
|
||||
|
||||
def random_string(length=8):
|
||||
return ''.join(random.choice(string.ascii_letters) for x in range(length))
|
||||
|
||||
|
||||
def register(selenium, user):
|
||||
selenium.get(f'{TEST_URL}/register')
|
||||
selenium.implicitly_wait(1)
|
||||
username = selenium.find_element_by_name('username')
|
||||
username.send_keys(user.get('username'))
|
||||
email = selenium.find_element_by_name('email')
|
||||
email.send_keys(user.get('email'))
|
||||
password = selenium.find_element_by_name('password')
|
||||
password.send_keys(user.get('password'))
|
||||
password_conf = selenium.find_element_by_name('password_conf')
|
||||
password_conf.send_keys(user.get('password_conf'))
|
||||
submit_button = selenium.find_element_by_class_name('btn')
|
||||
submit_button.click()
|
||||
|
||||
|
||||
def login(selenium, user):
|
||||
selenium.get(f'{TEST_URL}/login')
|
||||
selenium.implicitly_wait(1)
|
||||
email = selenium.find_element_by_name('email')
|
||||
email.send_keys(user.get('email'))
|
||||
password = selenium.find_element_by_name('password')
|
||||
password.send_keys(user.get('password'))
|
||||
submit_button = selenium.find_element_by_class_name('btn')
|
||||
submit_button.click()
|
||||
|
||||
|
||||
def register_valid_user(selenium):
|
||||
user_name = random_string()
|
||||
user = {
|
||||
'username': user_name,
|
||||
'email': f'{user_name}@example.com',
|
||||
'password': 'p@ssw0rd',
|
||||
'password_conf': 'p@ssw0rd',
|
||||
}
|
||||
register(selenium, user)
|
||||
WebDriverWait(selenium, 10).until(EC.url_changes(f"{TEST_URL}/register"))
|
||||
return user
|
||||
|
||||
|
||||
def login_valid_user(selenium, user):
|
||||
login(selenium, user)
|
||||
WebDriverWait(selenium, 10).until(EC.url_changes(f"{TEST_URL}/login"))
|
||||
return user
|
||||
|
||||
|
||||
def assert_navbar(selenium, user):
|
||||
nav = selenium.find_element_by_tag_name('nav').text
|
||||
assert 'Register' not in nav
|
||||
assert 'Login' not in nav
|
||||
assert 'Dashboard' in nav
|
||||
assert 'Workouts' in nav
|
||||
assert 'Statistics' in nav
|
||||
assert 'Add workout' in nav
|
||||
assert user['username'] in nav
|
||||
assert 'Logout' in nav
|
||||
assert 'en' in nav
|
@ -2,7 +2,7 @@ import logging
|
||||
import os
|
||||
from importlib import import_module, reload
|
||||
|
||||
from flask import Flask
|
||||
from flask import Flask, render_template, send_file
|
||||
from flask_bcrypt import Bcrypt
|
||||
from flask_dramatiq import Dramatiq
|
||||
from flask_migrate import Migrate
|
||||
@ -15,19 +15,27 @@ bcrypt = Bcrypt()
|
||||
migrate = Migrate()
|
||||
email_service = Email()
|
||||
dramatiq = Dramatiq()
|
||||
appLog = logging.getLogger('fittrackee_api')
|
||||
log_file = os.getenv('APP_LOG')
|
||||
logging.basicConfig(
|
||||
filename=log_file,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - ' '%(message)s',
|
||||
datefmt='%Y/%m/%d %H:%M:%S',
|
||||
)
|
||||
appLog = logging.getLogger('fittrackee')
|
||||
|
||||
|
||||
def create_app():
|
||||
# instantiate the app
|
||||
app = Flask(__name__)
|
||||
app = Flask(__name__, static_folder='dist/static', template_folder='dist')
|
||||
|
||||
# set config
|
||||
with app.app_context():
|
||||
app_settings = os.getenv('APP_SETTINGS')
|
||||
if app_settings == 'fittrackee_api.config.TestingConfig':
|
||||
app_settings = os.getenv(
|
||||
'APP_SETTINGS', 'fittrackee.config.ProductionConfig'
|
||||
)
|
||||
if app_settings == 'fittrackee.config.TestingConfig':
|
||||
# reload config on tests
|
||||
config = import_module('fittrackee_api.config')
|
||||
config = import_module('fittrackee.config')
|
||||
reload(config)
|
||||
app.config.from_object(app_settings)
|
||||
|
||||
@ -91,4 +99,17 @@ def create_app():
|
||||
)
|
||||
return response
|
||||
|
||||
@app.route('/favicon.ico')
|
||||
def favicon():
|
||||
return send_file(os.path.join(app.root_path, 'dist/favicon.ico'))
|
||||
|
||||
@app.route('/', defaults={'path': ''})
|
||||
@app.route('/<path:path>')
|
||||
def catch_all(path):
|
||||
# workaround to serve images (not in static directory)
|
||||
if path.startswith('img/'):
|
||||
return send_file(os.path.join(app.root_path, 'dist', path))
|
||||
else:
|
||||
return render_template('index.html')
|
||||
|
||||
return app
|
103
fittrackee/__main__.py
Normal file
@ -0,0 +1,103 @@
|
||||
# source for StandaloneApplication class:
|
||||
# http://docs.gunicorn.org/en/stable/custom.html
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import gunicorn.app.base
|
||||
from fittrackee import create_app, db
|
||||
from fittrackee.activities.models import Activity
|
||||
from fittrackee.activities.utils import update_activity
|
||||
from fittrackee.application.utils import init_config
|
||||
from fittrackee.database_utils import init_database
|
||||
from flask_dramatiq import worker
|
||||
from flask_migrate import upgrade
|
||||
from tqdm import tqdm
|
||||
|
||||
HOST = os.getenv('HOST', '0.0.0.0')
|
||||
PORT = os.getenv('PORT', '5000')
|
||||
WORKERS = os.getenv('APP_WORKERS', 1)
|
||||
BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
||||
app = create_app()
|
||||
dramatiq_worker = worker
|
||||
|
||||
|
||||
class StandaloneApplication(gunicorn.app.base.BaseApplication):
|
||||
def __init__(self, current_app, options=None):
|
||||
self.options = options or {}
|
||||
self.application = current_app
|
||||
super().__init__()
|
||||
|
||||
def load_config(self):
|
||||
config = {
|
||||
key: value
|
||||
for key, value in self.options.items()
|
||||
if key in self.cfg.settings and value is not None
|
||||
}
|
||||
for key, value in config.items():
|
||||
self.cfg.set(key.lower(), value)
|
||||
|
||||
def load(self):
|
||||
return self.application
|
||||
|
||||
|
||||
def upgrade_db():
|
||||
with app.app_context():
|
||||
upgrade(directory=BASEDIR + '/migrations')
|
||||
|
||||
|
||||
@app.cli.command('drop-db')
|
||||
def drop_db():
|
||||
"""Empty database for dev environments."""
|
||||
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.')
|
||||
|
||||
|
||||
@app.cli.command('init-data')
|
||||
def init_data():
|
||||
"""Init the database and application config."""
|
||||
init_database(app)
|
||||
|
||||
|
||||
@app.cli.command()
|
||||
def recalculate():
|
||||
print("Starting activities data refresh")
|
||||
activities = (
|
||||
Activity.query.filter(Activity.gpx != None) # noqa
|
||||
.order_by(Activity.activity_date.asc()) # noqa
|
||||
.all()
|
||||
)
|
||||
if len(activities) == 0:
|
||||
print('➡️ no activities to upgrade.')
|
||||
return None
|
||||
pbar = tqdm(activities)
|
||||
for activity in pbar:
|
||||
update_activity(activity)
|
||||
pbar.set_postfix(activitiy_id=activity.id)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
@app.cli.command('init-app-config')
|
||||
def init_app_config():
|
||||
"""Init application configuration."""
|
||||
print("Init application configuration")
|
||||
config_created, _ = init_config()
|
||||
if config_created:
|
||||
print("Creation done!")
|
||||
else:
|
||||
print(
|
||||
"Application configuration already existing in database. "
|
||||
"Please use web application to update it."
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
options = {'bind': f'{HOST}:{PORT}', 'workers': WORKERS}
|
||||
StandaloneApplication(app, options).run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
@ -4,7 +4,7 @@ import shutil
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import requests
|
||||
from fittrackee_api import appLog, db
|
||||
from fittrackee import appLog, db
|
||||
from flask import Blueprint, Response, current_app, jsonify, request, send_file
|
||||
from sqlalchemy import exc
|
||||
|
@ -1,7 +1,7 @@
|
||||
import datetime
|
||||
import os
|
||||
|
||||
from fittrackee_api import db
|
||||
from fittrackee import db
|
||||
from sqlalchemy.dialects import postgresql
|
||||
from sqlalchemy.event import listens_for
|
||||
from sqlalchemy.ext.hybrid import hybrid_property
|
@ -1,4 +1,4 @@
|
||||
from fittrackee_api import appLog, db
|
||||
from fittrackee import appLog, db
|
||||
from flask import Blueprint, jsonify, request
|
||||
from sqlalchemy import exc
|
||||
|
@ -1,6 +1,6 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from fittrackee_api import appLog, db
|
||||
from fittrackee import appLog, db
|
||||
from flask import Blueprint, jsonify, request
|
||||
from sqlalchemy import func
|
||||
|
@ -6,7 +6,7 @@ from datetime import datetime, timedelta
|
||||
|
||||
import gpxpy.gpx
|
||||
import pytz
|
||||
from fittrackee_api import appLog, db
|
||||
from fittrackee import appLog, db
|
||||
from flask import current_app
|
||||
from sqlalchemy import exc
|
||||
from staticmap import Line, StaticMap
|
@ -2,9 +2,9 @@ import os
|
||||
|
||||
import forecastio
|
||||
import pytz
|
||||
from fittrackee_api import appLog
|
||||
from fittrackee import appLog
|
||||
|
||||
API_KEY = os.getenv('WEATHER_API')
|
||||
API_KEY = os.getenv('WEATHER_API_KEY')
|
||||
|
||||
|
||||
def get_weather(point):
|
@ -1,4 +1,4 @@
|
||||
from fittrackee_api import appLog, db
|
||||
from fittrackee import appLog, db
|
||||
from flask import Blueprint, current_app, jsonify, request
|
||||
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
|
||||
|
||||
@ -34,7 +34,8 @@ def get_application_config():
|
||||
"is_registration_enabled": false,
|
||||
"max_single_file_size": 1048576,
|
||||
"max_zip_file_size": 10485760,
|
||||
"max_users": 0
|
||||
"max_users": 0,
|
||||
"map_attribution": "© <a href=http://www.openstreetmap.org/copyright>OpenStreetMap</a> contributors"
|
||||
},
|
||||
"status": "success"
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
from fittrackee_api import db
|
||||
from fittrackee import db
|
||||
from flask import current_app
|
||||
from sqlalchemy.event import listens_for
|
||||
|
@ -1,7 +1,7 @@
|
||||
import os
|
||||
|
||||
from fittrackee_api import db
|
||||
from fittrackee_api.users.models import User
|
||||
from fittrackee import db
|
||||
from fittrackee.users.models import User
|
||||
|
||||
from .models import AppConfig
|
||||
|
@ -3,8 +3,9 @@ import os
|
||||
from dramatiq.brokers.redis import RedisBroker
|
||||
from dramatiq.brokers.stub import StubBroker
|
||||
from flask import current_app
|
||||
from sqlalchemy.pool import NullPool
|
||||
|
||||
if os.getenv('APP_SETTINGS') == 'fittrackee_api.config.TestingConfig':
|
||||
if os.getenv('APP_SETTINGS') == 'fittrackee.config.TestingConfig':
|
||||
broker = StubBroker
|
||||
else:
|
||||
broker = RedisBroker
|
||||
@ -20,7 +21,9 @@ class BaseConfig:
|
||||
TOKEN_EXPIRATION_DAYS = 30
|
||||
TOKEN_EXPIRATION_SECONDS = 0
|
||||
PASSWORD_TOKEN_EXPIRATION_SECONDS = 3600
|
||||
UPLOAD_FOLDER = os.path.join(current_app.root_path, 'uploads')
|
||||
UPLOAD_FOLDER = os.path.join(
|
||||
os.getenv('UPLOAD_FOLDER', current_app.root_path), 'uploads'
|
||||
)
|
||||
PICTURE_ALLOWED_EXTENSIONS = {'jpg', 'png', 'gif'}
|
||||
ACTIVITY_ALLOWED_EXTENSIONS = {'gpx', 'zip'}
|
||||
TEMPLATES_FOLDER = os.path.join(current_app.root_path, 'email/templates')
|
||||
@ -68,3 +71,18 @@ class TestingConfig(BaseConfig):
|
||||
TOKEN_EXPIRATION_SECONDS = 3
|
||||
PASSWORD_TOKEN_EXPIRATION_SECONDS = 3
|
||||
UPLOAD_FOLDER = '/tmp/fitTrackee/uploads'
|
||||
|
||||
|
||||
class ProductionConfig(BaseConfig):
|
||||
"""Production configuration"""
|
||||
|
||||
DEBUG = False
|
||||
# https://docs.sqlalchemy.org/en/13/core/pooling.html#using-connection-pools-with-multiprocessing-or-os-fork # noqa
|
||||
SQLALCHEMY_ENGINE_OPTIONS = (
|
||||
{'poolclass': NullPool}
|
||||
if os.getenv('DATABASE_DISABLE_POOLING', False)
|
||||
else {}
|
||||
)
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
|
||||
SECRET_KEY = os.getenv('APP_SECRET_KEY')
|
||||
DRAMATIQ_BROKER_URL = os.getenv('REDIS_URL', 'redis://')
|
46
fittrackee/database_utils.py
Normal file
@ -0,0 +1,46 @@
|
||||
from fittrackee import db
|
||||
from fittrackee.activities.models import Sport
|
||||
from fittrackee.application.utils import (
|
||||
init_config,
|
||||
update_app_config_from_database,
|
||||
)
|
||||
from fittrackee.users.models import User
|
||||
|
||||
|
||||
def init_database(app):
|
||||
"""Init the database."""
|
||||
admin = User(
|
||||
username='admin', email='admin@example.com', password='mpwoadmin'
|
||||
)
|
||||
admin.admin = True
|
||||
admin.timezone = 'Europe/Paris'
|
||||
db.session.add(admin)
|
||||
sport = Sport(label='Cycling (Sport)')
|
||||
sport.img = '/img/sports/cycling-sport.png'
|
||||
sport.is_default = True
|
||||
db.session.add(sport)
|
||||
sport = Sport(label='Cycling (Transport)')
|
||||
sport.img = '/img/sports/cycling-transport.png'
|
||||
sport.is_default = True
|
||||
db.session.add(sport)
|
||||
sport = Sport(label='Hiking')
|
||||
sport.img = '/img/sports/hiking.png'
|
||||
sport.is_default = True
|
||||
db.session.add(sport)
|
||||
sport = Sport(label='Mountain Biking')
|
||||
sport.img = '/img/sports/mountain-biking.png'
|
||||
sport.is_default = True
|
||||
db.session.add(sport)
|
||||
sport = Sport(label='Running')
|
||||
sport.img = '/img/sports/running.png'
|
||||
sport.is_default = True
|
||||
db.session.add(sport)
|
||||
sport = Sport(label='Walking')
|
||||
sport.img = '/img/sports/walking.png'
|
||||
sport.is_default = True
|
||||
db.session.add(sport)
|
||||
db.session.commit()
|
||||
_, db_app_config = init_config()
|
||||
update_app_config_from_database(app, db_app_config)
|
||||
|
||||
print('Initial data stored in database.')
|
26
fittrackee/dist/asset-manifest.json
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.9eb63bc2.chunk.css",
|
||||
"main.js": "/static/js/main.474f2b2e.chunk.js",
|
||||
"main.js.map": "/static/js/main.474f2b2e.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.2d7c76f9.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.2d7c76f9.js.map",
|
||||
"static/js/2.8ad7236a.chunk.js": "/static/js/2.8ad7236a.chunk.js",
|
||||
"static/js/2.8ad7236a.chunk.js.map": "/static/js/2.8ad7236a.chunk.js.map",
|
||||
"index.html": "/index.html",
|
||||
"precache-manifest.da13c9560c293f42e6b23c2cfaa288b6.js": "/precache-manifest.da13c9560c293f42e6b23c2cfaa288b6.js",
|
||||
"service-worker.js": "/service-worker.js",
|
||||
"static/css/main.9eb63bc2.chunk.css.map": "/static/css/main.9eb63bc2.chunk.css.map",
|
||||
"static/js/2.8ad7236a.chunk.js.LICENSE.txt": "/static/js/2.8ad7236a.chunk.js.LICENSE.txt",
|
||||
"static/media/en.501888db.svg": "/static/media/en.501888db.svg",
|
||||
"static/media/fr.b75cd962.svg": "/static/media/fr.b75cd962.svg",
|
||||
"static/media/mail-send.66b8d739.svg": "/static/media/mail-send.66b8d739.svg",
|
||||
"static/media/password.488f5f4c.svg": "/static/media/password.488f5f4c.svg"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/js/runtime-main.2d7c76f9.js",
|
||||
"static/js/2.8ad7236a.chunk.js",
|
||||
"static/css/main.9eb63bc2.chunk.css",
|
||||
"static/js/main.474f2b2e.chunk.js"
|
||||
]
|
||||
}
|
BIN
fittrackee/dist/favicon.ico
vendored
Normal file
After Width: | Height: | Size: 318 B |