diff --git a/Makefile b/Makefile index bc0c4536..f3440d04 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ lint-react: $(NPM) lint migrate-db: - $(FLASK) db migrate + $(FLASK) db migrate --directory $(MIGRATIONS) serve-python: $(FLASK) run --with-threads -h $(HOST) -p $(API_PORT) diff --git a/Makefile.config b/Makefile.config index 218443cc..49cc70f3 100644 --- a/Makefile.config +++ b/Makefile.config @@ -4,6 +4,7 @@ CLIENT_PORT = 3000 export REACT_APP_API_URL = http://$(HOST):$(API_PORT) export FLASK_APP = $(PWD)/mpwo_api/server.py +export FLASK_DEBUG = 1 export TEST_URL = http://$(HOST):$(CLIENT_PORT) export REQUIREMENTS = $(PWD)/mpwo_api/requirements.txt export DATABASE_URL = postgres://mpwo:mpwo@$(HOST):5432/mpwo diff --git a/mpwo_api/migrations/versions/b7cfe0c17708_.py b/mpwo_api/migrations/versions/b7cfe0c17708_.py new file mode 100644 index 00000000..25d5751d --- /dev/null +++ b/mpwo_api/migrations/versions/b7cfe0c17708_.py @@ -0,0 +1,56 @@ +"""empty message + +Revision ID: b7cfe0c17708 +Revises: 9741fc7834da +Create Date: 2018-01-21 17:24:52.587814 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'b7cfe0c17708' +down_revision = '9741fc7834da' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('sports', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('label', sa.String(length=50), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('label') + ) + op.create_table('activities', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('user_id', sa.Integer(), nullable=False), + sa.Column('sport_id', sa.Integer(), nullable=False), + sa.Column('gpx', sa.String(length=255), nullable=True), + sa.Column('creation_date', sa.DateTime(), nullable=True), + sa.Column('modification_date', sa.DateTime(), nullable=True), + sa.Column('activity_date', sa.DateTime(), nullable=False), + sa.Column('duration', sa.Interval(), nullable=False), + sa.Column('pauses', sa.Interval(), nullable=True), + sa.Column('moving', sa.Interval(), nullable=True), + sa.Column('distance', sa.Numeric(precision=5, scale=2), nullable=True), + sa.Column('min_alt', sa.Numeric(precision=5, scale=2), nullable=True), + sa.Column('max_alt', sa.Numeric(precision=5, scale=2), nullable=True), + sa.Column('descent', sa.Numeric(precision=5, scale=2), nullable=True), + sa.Column('ascent', sa.Numeric(precision=5, scale=2), nullable=True), + sa.Column('max_speed', sa.Numeric(precision=5, scale=2), nullable=True), + sa.Column('ave_speed', sa.Numeric(precision=5, scale=2), nullable=True), + sa.ForeignKeyConstraint(['sport_id'], ['sports.id'], ), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('activities') + op.drop_table('sports') + # ### end Alembic commands ### diff --git a/mpwo_api/mpwo_api/__init__.py b/mpwo_api/mpwo_api/__init__.py index 0e8f083d..64b046ec 100644 --- a/mpwo_api/mpwo_api/__init__.py +++ b/mpwo_api/mpwo_api/__init__.py @@ -25,9 +25,11 @@ migrate.init_app(app, db) from .users.auth import auth_blueprint # noqa from .users.users import users_blueprint # noqa +from .activities.activities import activities_blueprint # noqa app.register_blueprint(users_blueprint, url_prefix='/api') app.register_blueprint(auth_blueprint, url_prefix='/api') +app.register_blueprint(activities_blueprint, url_prefix='/api') if app.debug: logging.getLogger('sqlalchemy').setLevel(logging.WARNING) diff --git a/mpwo_api/mpwo_api/activities/__init__.py b/mpwo_api/mpwo_api/activities/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/mpwo_api/mpwo_api/activities/activities.py b/mpwo_api/mpwo_api/activities/activities.py new file mode 100644 index 00000000..31689b46 --- /dev/null +++ b/mpwo_api/mpwo_api/activities/activities.py @@ -0,0 +1,29 @@ +from flask import Blueprint, jsonify + +from ..users.utils import authenticate +from .models import Activity + +activities_blueprint = Blueprint('activities', __name__) + + +@activities_blueprint.route('/activities', methods=['GET']) +@authenticate +def get_activities(user_id): + """Get all activities""" + activities = Activity.query.all() + activities_list = [] + for activity in activities: + activity_object = { + 'id': activity.id, + 'user_id': activity.user_id, + 'sport_id': activity.sport_id, + 'creation_date': activity.creation_date + } + activities_list.append(activity_object) + response_object = { + 'status': 'success', + 'data': { + 'activities': activities_list + } + } + return jsonify(response_object), 200 diff --git a/mpwo_api/mpwo_api/activities/models.py b/mpwo_api/mpwo_api/activities/models.py new file mode 100644 index 00000000..18680981 --- /dev/null +++ b/mpwo_api/mpwo_api/activities/models.py @@ -0,0 +1,57 @@ +import datetime + +from mpwo_api import db + + +class Sport(db.Model): + __tablename__ = "sports" + id = db.Column(db.Integer, primary_key=True, autoincrement=True) + label = db.Column(db.String(50), unique=True, nullable=False) + activities = db.relationship('Activity', + lazy=True, + backref=db.backref('sports', lazy='joined')) + + def __repr__(self): + return self.label + + def __init__(self, label): + self.label = label + + +class Activity(db.Model): + __tablename__ = "activities" + id = db.Column( + db.Integer, + primary_key=True, + autoincrement=True) + user_id = db.Column( + db.Integer, + db.ForeignKey('users.id'), + nullable=False) + sport_id = db.Column( + db.Integer, + db.ForeignKey('sports.id'), + nullable=False) + gpx = db.Column(db.String(255), nullable=True) + creation_date = db.Column(db.DateTime, default=datetime.datetime.now) + modification_date = db.Column(db.DateTime, onupdate=datetime.datetime.now) + activity_date = db.Column(db.DateTime, nullable=False) + duration = db.Column(db.Interval, nullable=False) + pauses = db.Column(db.Interval, nullable=True) + moving = db.Column(db.Interval, nullable=True) + distance = db.Column(db.Numeric(5, 2), nullable=True) + min_alt = db.Column(db.Numeric(5, 2), nullable=True) + max_alt = db.Column(db.Numeric(5, 2), nullable=True) + descent = db.Column(db.Numeric(5, 2), nullable=True) + ascent = db.Column(db.Numeric(5, 2), nullable=True) + max_speed = db.Column(db.Numeric(5, 2), nullable=True) + ave_speed = db.Column(db.Numeric(5, 2), nullable=True) + + def __str__(self): + return self.sport.label + \ + " - " + self.activity_date.strftime('%Y-%m-%d') + + def __init__(self, user_id, sport_id, activity_date): + self.user_id = user_id + self.sport_id = sport_id + self.activity_date = activity_date diff --git a/mpwo_api/mpwo_api/users/models.py b/mpwo_api/mpwo_api/users/models.py index c8e56217..7e0e72c0 100644 --- a/mpwo_api/mpwo_api/users/models.py +++ b/mpwo_api/mpwo_api/users/models.py @@ -19,6 +19,9 @@ class User(db.Model): location = db.Column(db.String(80), nullable=True) bio = db.Column(db.String(200), nullable=True) picture = db.Column(db.String(255), nullable=True) + activities = db.relationship('Activity', + lazy=True, + backref=db.backref('users', lazy='joined')) def __repr__(self): return '' % self.username