Skip to content

Commit

Permalink
sign in, sign out, dashboard, admin initial
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchbregs committed Mar 31, 2020
1 parent 0f57eb2 commit a478f26
Show file tree
Hide file tree
Showing 29 changed files with 716 additions and 283 deletions.
25 changes: 21 additions & 4 deletions application/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
from flask import Flask
from werkzeug.utils import import_string

from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
from flask_login import LoginManager
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData

# Possible configurations
# TODO :: Make production the default at some point
Expand All @@ -16,8 +19,18 @@
"default": "application.config.TestConfig"
}

# Database index naming conventions
naming_convention = {
"ix": 'ix_%(column_0_label)s',
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(column_0_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}

# Set globals
db = SQLAlchemy()
admininstrator = Admin(name='Betfund')
db = SQLAlchemy(metadata=MetaData(naming_convention=naming_convention))
migrate = Migrate()
login_manager = LoginManager()

Expand All @@ -34,9 +47,11 @@ def create_app(test_config=True):
app.config.from_object(config)

# Initialize plug-ins
admininstrator.init_app(app)
db.init_app(app)
db.app = app
migrate.init_app(app, db)
# TODO :: `render_as_batch` only for SQLite..
migrate.init_app(app, db, render_as_batch=True)
login_manager.init_app(app)

with app.app_context():
Expand All @@ -47,13 +62,15 @@ def create_app(test_config=True):
from application.loggedin.loggedin_routes import loggedin_bp
from application.signup.signup_routes import signup_bp
from application.login.login_routes import login_bp
from application.admin.admin_routes import admin_bp
from application.admin.admin_routes import add_admin_views

# Register Blueprints
app.register_blueprint(home_bp, url_prefix='/')
app.register_blueprint(loggedin_bp)
app.register_blueprint(signup_bp)
app.register_blueprint(login_bp)
app.register_blueprint(admin_bp)

# Admin Handling
add_admin_views(admininstrator)

return app
53 changes: 28 additions & 25 deletions application/admin/admin_routes.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
from flask import Blueprint, jsonify
from flask_admin.contrib.sqla import ModelView

from application.models import User
from application import db
from application.models import (
Fund,
FundLedger,
FundUser,
FundUserLedger,
Investment,
Line,
LineVote,
Result,
Strategy,
User,
UserLedger
)
from flask_login import login_required

admin_bp = Blueprint('admin_bp', __name__, template_folder='templates')


@admin_bp.route('/admin', methods=['GET', 'POST'])
@login_required
def admin():
"""
Admin end point.
TODO :: This DEFINITELY needs to be updated. We'll
want to build out an actual admin end point with
`flask_admin`, most likely. For now, this just
returns all of the user data from the database.
"""
users = User.query.all()
users_json = [{
'id': u.id,
'first': u.first_name,
'last': u.last_name,
'email': u.email_address,
'pass': u.password
} for u in users]

return jsonify(users_json)
def add_admin_views(administrator):
"""Register views to admin"""
administrator.add_view(ModelView(Fund, session=db.session, name='Fund'))
administrator.add_view(ModelView(FundLedger, session=db.session, name='FundLedger'))
administrator.add_view(ModelView(FundUser, session=db.session, name='FundUser'))
administrator.add_view(ModelView(FundUserLedger, session=db.session, name='FundUserLedger'))
administrator.add_view(ModelView(Investment, session=db.session, name='Investment'))
administrator.add_view(ModelView(Line, session=db.session, name='Line'))
administrator.add_view(ModelView(LineVote, session=db.session, name='LineVote'))
administrator.add_view(ModelView(Result, session=db.session, name='Result'))
administrator.add_view(ModelView(Strategy, session=db.session, name='Strategy'))
administrator.add_view(ModelView(User, session=db.session, name='User'))
administrator.add_view(ModelView(UserLedger, session=db.session, name='UserLedger'))
2 changes: 2 additions & 0 deletions application/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class Config:
DEBUG = False
TESTING = False

FLASK_ADMIN_SWATCH = 'cyborg'


class ProductionConfig(Config):
pass
Expand Down
31 changes: 17 additions & 14 deletions application/forms.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
from flask_wtf import FlaskForm
from wtforms import PasswordField, StringField, SubmitField
from wtforms.validators import DataRequired, Email, EqualTo
from wtforms.validators import DataRequired, Email, EqualTo, Length


class SignUpForm(FlaskForm):
"""
Class to encapsulate sign up form
"""
first_name = StringField(
'First Name:',
validators=[DataRequired()]
'First name',
validators=[DataRequired(message="Please enter your first name.")]
)
last_name = StringField(
'Last Name:',
validators=[DataRequired()]
'Last name',
validators=[DataRequired(message="Please enter your last name.")]
)
email_address = StringField(
'Email Address:',
'Email address',
validators=[
DataRequired(),
DataRequired(message="Please enter an email."),
Email(message='Enter a valid email.')
]
)
password = PasswordField(
'Password:',
validators=[DataRequired()]
'Password',
validators=[
DataRequired(message="Please enter a password."),
Length(min=8, max=24, message="Password must be between 8 and 24 characters.")
]
)
password_check = PasswordField(
'Reenter Password:',
'Re-enter password',
validators=[
DataRequired(message="Please re-enter a password."),
EqualTo('password', message='Passwords must match.')
Expand All @@ -42,15 +45,15 @@ class LogInForm(FlaskForm):
Class to encapsulate log in form
"""
email_address = StringField(
'Email Address:',
'Email address',
validators=[
DataRequired(),
DataRequired(message="Please enter your email."),
Email(message='Enter a valid email.')
]
)
password = PasswordField(
'Password:',
validators=[DataRequired()]
'Password',
validators=[DataRequired(message="Please enter your password.")]
)

submit = SubmitField('Log In')
8 changes: 5 additions & 3 deletions application/home/home_routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from flask import Blueprint, render_template
from flask import Blueprint, redirect, render_template, url_for
from flask_login import current_user

home_bp = Blueprint('home_bp', __name__, template_folder='templates')

Expand All @@ -10,11 +11,12 @@ def home():
TODO :: This needs to be updated.
"""
if current_user.is_authenticated:
return redirect(url_for('loggedin_bp.dashboard'))

return render_template(
'index.html',
title='Home',
template='template main',
body="Home"
)


Expand Down
106 changes: 102 additions & 4 deletions application/home/templates/index.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,106 @@
{% extends "layout.html" %}
{% extends "base.html" %}

{% block content %}

{% include "navigation-default.html" %}
<div class="container">
<h1>{{body}}</h1>
</div>

<main role="main">
<section class="jumbotron text-center">
<div class="container">
<h1 class="jumbotron-heading">Bet smarter with groups.</h1>
<p class="lead text-muted">Something short and leading about the collection below—its contents, the creator, etc. Make it short and sweet, but not too short so folks don't simply skip over it entirely.</p>
<p>
<a href="#" class="btn btn-primary my-2">Our funds</a>
<a href="#" class="btn btn-secondary my-2">Our strategies</a>
</p>
</div>
</section>
<div class="album py-5 bg-light">
<div class="container">
<div class="row">
<div class="col-md-4">
<div class="card mb-4 box-shadow">
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=35585c&fg=eceeef&text=NFL Money Lines" alt="Card image cap">
<div class="card-body">
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-4 box-shadow">
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=51599c&fg=eceeef&text=Prop Bets Only" alt="Card image cap">
<div class="card-body">
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-4 box-shadow">
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=61495c&fg=eceeef&text=Underdog Cash Flow" alt="Card image cap">
<div class="card-body">
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-4 box-shadow">
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=84695c&fg=eceeef&text=NBA Over Unders" alt="Card image cap">
<div class="card-body">
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-4 box-shadow">
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=25495c&fg=eceeef&text=Political Action" alt="Card image cap">
<div class="card-body">
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-4 box-shadow">
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=73768c&fg=eceeef&text=Bet The House" alt="Card image cap">
<div class="card-body">
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>

{% include "footer-default.html" %}

{% endblock %}
15 changes: 10 additions & 5 deletions application/loggedin/loggedin_routes.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
from flask import Blueprint, render_template
from flask_login import login_required
from flask import Blueprint, redirect, render_template, url_for
from flask_login import current_user, login_required

from application import login_manager

loggedin_bp = Blueprint('loggedin_bp', __name__, template_folder='templates')


@login_manager.unauthorized_handler
def unauthorized_callback():
return redirect(url_for('login_bp.login'))


@loggedin_bp.route('/dashboard', methods=['GET', 'POST'])
@login_required
def dashboard():
Expand All @@ -14,7 +21,5 @@ def dashboard():
"""
return render_template(
'dashboard.html',
title='Dashboard',
template='template main',
body="Dashboard"
title='Dashboard'
)
2 changes: 2 additions & 0 deletions application/loggedin/templates/dashboard-container-end.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
</div>
</div
2 changes: 2 additions & 0 deletions application/loggedin/templates/dashboard-container-start.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<div class="container-fluid">
<div class="row">
Loading

0 comments on commit a478f26

Please sign in to comment.