Merge remote-tracking branch 'origin/master'
Conflicts: app/create_database.py
This commit is contained in:
commit
d323a7065c
21 changed files with 256 additions and 63 deletions
|
@ -1,8 +1,10 @@
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
from flask.ext.bootstrap import Bootstrap
|
||||||
from flask.ext.sqlalchemy import SQLAlchemy
|
from flask.ext.sqlalchemy import SQLAlchemy
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config.from_object('config.Configuration')
|
app.config.from_object('config.Configuration')
|
||||||
|
Bootstrap(app)
|
||||||
|
|
||||||
db = SQLAlchemy(app)
|
db = SQLAlchemy(app)
|
||||||
|
|
|
@ -9,7 +9,8 @@ feli.configure("feliciaan", True, 0)
|
||||||
db.session.add(feli)
|
db.session.add(feli)
|
||||||
|
|
||||||
destro = User()
|
destro = User()
|
||||||
destro.configure('destro', True, 0)
|
destro.configure('wout', True, 0)
|
||||||
|
db.session.add(destro)
|
||||||
|
|
||||||
# To future developers, add yourself here
|
# To future developers, add yourself here
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,9 @@ from app import app, db
|
||||||
from admin import admin
|
from admin import admin
|
||||||
from login import login_manager
|
from login import login_manager
|
||||||
from models import *
|
from models import *
|
||||||
|
from forms import *
|
||||||
|
from utils import *
|
||||||
from views import *
|
from views import *
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=True)
|
app.run()
|
||||||
|
|
31
app/forms.py
Normal file
31
app/forms.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from flask_wtf import Form
|
||||||
|
from wtforms import SelectField, DateTimeField, validators, SubmitField, HiddenField
|
||||||
|
from models import User, Location
|
||||||
|
from utils import euro
|
||||||
|
|
||||||
|
__author__ = 'feliciaan'
|
||||||
|
|
||||||
|
|
||||||
|
class OrderForm(Form):
|
||||||
|
courrier_id = SelectField('Courrier', coerce=int)
|
||||||
|
location_id = SelectField('Location', coerce=int, validators=[validators.required()])
|
||||||
|
starttime = DateTimeField('Starttime', default=datetime.now)
|
||||||
|
stoptime = DateTimeField('Stoptime')
|
||||||
|
submit_button = SubmitField('Submit')
|
||||||
|
|
||||||
|
def populate(self):
|
||||||
|
self.courrier_id.choices = [(0, None)] + \
|
||||||
|
[(u.id, u.username) for u in User.query.order_by('username')]
|
||||||
|
self.location_id.choices = [(l.id, l.name)
|
||||||
|
for l in Location.query.order_by('name')]
|
||||||
|
if self.stoptime.data is None:
|
||||||
|
self.stoptime.data = datetime.now() + timedelta(hours=1)
|
||||||
|
|
||||||
|
|
||||||
|
class OrderItemForm(Form):
|
||||||
|
food_id = SelectField('Item', coerce=int)
|
||||||
|
submit_button = SubmitField('Submit')
|
||||||
|
|
||||||
|
def populate(self, location):
|
||||||
|
self.food_id.choices = [(i.id, (i.name + ": " + euro(i.price))) for i in location.food]
|
|
@ -43,6 +43,8 @@ class Location(db.Model):
|
||||||
address = db.Column(db.String(254))
|
address = db.Column(db.String(254))
|
||||||
website = db.Column(db.String(120))
|
website = db.Column(db.String(120))
|
||||||
food = db.relationship('Food', backref='location', lazy='dynamic')
|
food = db.relationship('Food', backref='location', lazy='dynamic')
|
||||||
|
orders = db.relationship('Order', backref='location', lazy='dynamic')
|
||||||
|
|
||||||
|
|
||||||
def configure(self, name, address, website):
|
def configure(self, name, address, website):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -85,7 +87,7 @@ class Order(db.Model):
|
||||||
self.stoptime = stoptime
|
self.stoptime = stoptime
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'Order'
|
return 'Order %s' % (self.location.name)
|
||||||
|
|
||||||
|
|
||||||
class OrderItem(db.Model):
|
class OrderItem(db.Model):
|
||||||
|
|
|
@ -3,6 +3,7 @@ Flask-Admin==1.0.9
|
||||||
Flask-Login==0.2.11
|
Flask-Login==0.2.11
|
||||||
Flask-SQLAlchemy==2.0
|
Flask-SQLAlchemy==2.0
|
||||||
Flask-WTF==0.10.3
|
Flask-WTF==0.10.3
|
||||||
|
Flask-Bootstrap==3.3.2.1
|
||||||
Jinja2==2.7.2
|
Jinja2==2.7.2
|
||||||
MarkupSafe==0.23
|
MarkupSafe==0.23
|
||||||
SQLAlchemy==0.9.8
|
SQLAlchemy==0.9.8
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{% extends "layout.html" %}
|
{% extends "layout.html" -%}
|
||||||
|
{% set active_page = "about" -%}
|
||||||
|
|
||||||
{% block content %}
|
{% block container %}
|
||||||
<h1>About</h1>
|
<h1>About</h1>
|
||||||
<p>This is an About page for FoodBot. Don't I look good? Oh stop, you're making me blush.</p>
|
<p>This is an About page for FoodBot. Don't I look good? Oh stop, you're making me blush.</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
9
app/templates/errors/401.html
Normal file
9
app/templates/errors/401.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{% extends "layout.html" -%}
|
||||||
|
|
||||||
|
{% block container %}
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1>Unauthorized</h1>
|
||||||
|
<p>You're not authorized to look to this page!</p>
|
||||||
|
<p><a href="{{ url_for('home') }}">Go somewhere nice</a></p>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
9
app/templates/errors/404.html
Normal file
9
app/templates/errors/404.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{% extends "layout.html" -%}
|
||||||
|
|
||||||
|
{% block container %}
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1>Page Not Found</h1>
|
||||||
|
<p>What you were looking for is just not there.</p>
|
||||||
|
<p><a href="{{ url_for('home') }}">Go somewhere nice</a></p>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends "layout.html" %}
|
{% extends "layout.html" -%}
|
||||||
{% block content %}
|
{% set active_page = "home" -%}
|
||||||
|
{% block container %}
|
||||||
<div class="jumbotron">
|
<div class="jumbotron">
|
||||||
<h2>Welcome to FoodBot</h2>
|
<h2>Welcome to FoodBot</h2>
|
||||||
<h3>This is the home page for FoodBot</h3>
|
<h3>This is the home page for FoodBot</h3>
|
||||||
|
|
14
app/templates/home_loggedin.html
Normal file
14
app/templates/home_loggedin.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{% extends "home.html" %}
|
||||||
|
{% block container %}
|
||||||
|
{{ super() }}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<h3>Open orders:</h3>
|
||||||
|
<ul>
|
||||||
|
{% for order in orders %}
|
||||||
|
<li><a href="{{ url_for('order', id=order.id) }}">{{ order.location.name }}-{{ order.stoptime }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -1,16 +1,24 @@
|
||||||
<!DOCTYPE html>
|
{% extends "bootstrap/base.html" %}
|
||||||
<html>
|
|
||||||
<head lang="en">
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>FoodBot</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
|
{% set navbar = [
|
||||||
|
('home', 'Home'),
|
||||||
|
('orders', 'Orders'),
|
||||||
|
('about', 'About'),
|
||||||
|
('stats', 'Stats'),
|
||||||
|
] -%}
|
||||||
|
{% if not current_user.is_anonymous() and current_user.is_admin() -%}
|
||||||
|
{% set navbar = navbar + [('admin.index', 'Admin')] -%}
|
||||||
|
{% endif -%}
|
||||||
|
{% set active_page = active_page|default('index') -%}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
FoodBot
|
||||||
|
{% endblock %}
|
||||||
|
{% block styles %}
|
||||||
|
{{ super() }}
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
|
||||||
|
{% endblock %}
|
||||||
</head>
|
{% block navbar %}
|
||||||
<body>
|
|
||||||
<nav class="navbar navbar-default navbar-fixed-top">
|
<nav class="navbar navbar-default navbar-fixed-top">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
|
@ -24,9 +32,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="navbar" class="navbar-collapse collapse">
|
<div id="navbar" class="navbar-collapse collapse">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li><a href="{{ url_for('home') }}">Home</a></li>
|
{% for id, text in navbar -%}
|
||||||
<li><a href="{{ url_for('about') }}">About</a></li>
|
<li class="{{ 'active' if id == active_page else '' }}">
|
||||||
<li><a href="{{ url_for('stats') }}">Stats</a></li>
|
<a href="{{ url_for(id) }}">{{ text|e }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor -%}
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
{% if current_user.is_anonymous() %}
|
{% if current_user.is_anonymous() %}
|
||||||
|
@ -39,13 +49,11 @@
|
||||||
</div><!--/.nav-collapse -->
|
</div><!--/.nav-collapse -->
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content -%}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% block content %}
|
{% block container -%}
|
||||||
{% endblock %}
|
{%- endblock %}
|
||||||
</div>
|
</div>
|
||||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
{%- endblock %}
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
|
|
||||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
|
||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
{% extends "layout.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<section class="container">
|
|
||||||
<div class="login">
|
|
||||||
<h1>Login with Zeus-Account</h1>
|
|
||||||
<form method="post" action="{{ url_for('home') }}">
|
|
||||||
<p><input type="text" name="login" value="" placeholder="Zeus e-mail "></p>
|
|
||||||
<p><input type="password" name="password" value="" placeholder="Password"></p>
|
|
||||||
<p class="remember_me">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" name="remember_me" id="remember_me">
|
|
||||||
Remember me on this computer
|
|
||||||
</label>
|
|
||||||
</p>
|
|
||||||
<p class="submit"><input type="submit" name="commit" value="Login"></p>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="login-help">
|
|
||||||
<p>Forgot your password? <a href="{{ url_for('home') }}">Click here to reset it</a>.</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{% endblock %}
|
|
18
app/templates/order.html
Normal file
18
app/templates/order.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{% extends "layout.html" %}
|
||||||
|
{% set active_page = "orders" -%}
|
||||||
|
|
||||||
|
{% block container %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12"><!-- Shitty html-->
|
||||||
|
<h3>Order {{ order.id }}</h3>
|
||||||
|
Courrier: {{ order.courrier.username }}<br/>
|
||||||
|
Location: <a href="{{ order.location.website }}">{{ order.location.name }}</a><br/>
|
||||||
|
Starttime: {{ order.starttime }}<br/>
|
||||||
|
Stoptime: {{ order.stoptime }}<br/>
|
||||||
|
<h3>Orders</h3>
|
||||||
|
{% for item in order.orders %}
|
||||||
|
{{ item.user.username }} - {{ item.food.name }} - {{ item.food.price|euro }}<br/>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
9
app/templates/order_form.html
Normal file
9
app/templates/order_form.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{% extends "layout.html" %}
|
||||||
|
{% set active_page = "orders" -%}
|
||||||
|
|
||||||
|
{% import "bootstrap/wtf.html" as wtf %}
|
||||||
|
{% block container %}
|
||||||
|
<div class="row">
|
||||||
|
{{ wtf.quick_form(form, action=url, button_map={'submit_button': 'primary'}) }}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
20
app/templates/orders.html
Normal file
20
app/templates/orders.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{% extends 'layout.html' %}
|
||||||
|
{% set active_page = "orders" -%}
|
||||||
|
|
||||||
|
{% import "bootstrap/wtf.html" as wtf %}
|
||||||
|
{% block container %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-5">
|
||||||
|
<h3>Open orders:</h3>
|
||||||
|
<ul>
|
||||||
|
{% for order in orders %}
|
||||||
|
<li><a href="{{ url_for('order', id=order.id) }}">{{ order.location.name }}-{{ order.stoptime }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-push-1 col-md-6">
|
||||||
|
{{ wtf.quick_form(form, action=url_for('order_create'), button_map={'submit_button': 'primary'}, form_type='horizontal') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -1,6 +1,6 @@
|
||||||
{% extends "layout.html" %}
|
{% extends "layout.html" -%}
|
||||||
|
{% set active_page = "stats" -%}
|
||||||
{% block content %}
|
{% block container %}
|
||||||
<h1>Stats bruh</h1>
|
<h1>Stats bruh</h1>
|
||||||
<p>TOP 4</p>
|
<p>TOP 4</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
17
app/utils.py
Normal file
17
app/utils.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
from flask import render_template
|
||||||
|
|
||||||
|
from app import app
|
||||||
|
__author__ = 'feliciaan'
|
||||||
|
|
||||||
|
@app.template_filter('euro')
|
||||||
|
def euro(value):
|
||||||
|
result = '€' + str(value/100)
|
||||||
|
return result
|
||||||
|
|
||||||
|
@app.errorhandler(404)
|
||||||
|
def handle404(e):
|
||||||
|
return render_template('errors/404.html'), 404
|
||||||
|
|
||||||
|
@app.errorhandler(401)
|
||||||
|
def handle401(e):
|
||||||
|
return render_template('errors/401.html'), 401
|
|
@ -1,11 +1,20 @@
|
||||||
from flask import url_for, render_template
|
__author__ = 'feliciaan'
|
||||||
|
|
||||||
from app import app
|
from flask import url_for, render_template, abort, redirect, request
|
||||||
|
from flask.ext.login import current_user, login_required
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from app import app, db
|
||||||
|
from models import Order, OrderItem
|
||||||
|
|
||||||
|
# import views
|
||||||
|
import views.order
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def home():
|
def home():
|
||||||
|
if not current_user.is_anonymous():
|
||||||
|
orders = Order.query.filter((Order.stoptime > datetime.now()) | (Order.stoptime == None)).all()
|
||||||
|
return render_template('home_loggedin.html', orders=orders)
|
||||||
return render_template('home.html')
|
return render_template('home.html')
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,23 +24,25 @@ def about():
|
||||||
|
|
||||||
|
|
||||||
@app.route('/stats/')
|
@app.route('/stats/')
|
||||||
|
@login_required
|
||||||
def stats():
|
def stats():
|
||||||
return render_template('stats.html')
|
return render_template('stats.html')
|
||||||
|
|
||||||
|
|
||||||
if app.debug: # add route information
|
if app.debug: # add route information
|
||||||
@app.route('/routes')
|
@app.route('/routes')
|
||||||
def list_routes(self):
|
@login_required
|
||||||
|
def list_routes():
|
||||||
import urllib
|
import urllib
|
||||||
output = []
|
output = []
|
||||||
for rule in app.url_map.iter_rules():
|
for rule in app.url_map.iter_rules():
|
||||||
options = {}
|
options = {}
|
||||||
for arg in rule.arguments:
|
for arg in rule.arguments:
|
||||||
options[arg] = "[{0}]".format(arg)
|
options[arg] = "[{0}]".format(arg)
|
||||||
|
print(rule.endpoint)
|
||||||
methods = ','.join(rule.methods)
|
methods = ','.join(rule.methods)
|
||||||
url = url_for(rule.endpoint, **options)
|
url = url_for(rule.endpoint, **options)
|
||||||
line = urllib.unquote(
|
line = urllib.parse.unquote(
|
||||||
"{:50s} {:20s} {}".format(rule.endpoint, methods, url))
|
"{:50s} {:20s} {}".format(rule.endpoint, methods, url))
|
||||||
output.append(line)
|
output.append(line)
|
||||||
|
|
61
app/views/order.py
Normal file
61
app/views/order.py
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
__author__ = 'feliciaan'
|
||||||
|
from flask import url_for, render_template, abort, redirect
|
||||||
|
from flask.ext.login import current_user, login_required
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from app import app, db
|
||||||
|
from models import Order, OrderItem
|
||||||
|
from forms import OrderItemForm, OrderForm
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/order/<id>')
|
||||||
|
@login_required
|
||||||
|
def order(id):
|
||||||
|
order = Order.query.filter(Order.id == id).first()
|
||||||
|
if order is not None:
|
||||||
|
return render_template('order.html', order=order)
|
||||||
|
return abort(404)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/order/<id>/create', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def order_item_create(id):
|
||||||
|
order = Order.query.filter(Order.id == id).first()
|
||||||
|
if order is not None:
|
||||||
|
form = OrderItemForm()
|
||||||
|
form.populate(order.location)
|
||||||
|
if form.validate_on_submit():
|
||||||
|
item = OrderItem()
|
||||||
|
form.populate_obj(item)
|
||||||
|
item.order_id = id
|
||||||
|
item.user_id = current_user.id
|
||||||
|
db.session.add(item)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('order', id=id))
|
||||||
|
return render_template('order_form.html', form=form, url=url_for("order_item_create", id=id))
|
||||||
|
return abort(404)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/order/create', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def order_create():
|
||||||
|
orderForm = OrderForm()
|
||||||
|
orderForm.populate()
|
||||||
|
if orderForm.validate_on_submit():
|
||||||
|
order = Order()
|
||||||
|
orderForm.populate_obj(order)
|
||||||
|
db.session.add(order)
|
||||||
|
db.session.commit()
|
||||||
|
return redirect(url_for('order', id=order.id))
|
||||||
|
|
||||||
|
return render_template('order_form.html', form=orderForm, url=url_for("order_create"))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/order')
|
||||||
|
@login_required
|
||||||
|
def orders():
|
||||||
|
orders = Order.query.filter((Order.stoptime > datetime.now()) | (Order.stoptime == None)).all()
|
||||||
|
orderForm = OrderForm()
|
||||||
|
orderForm.populate()
|
||||||
|
return render_template('orders.html', orders=orders, form=orderForm)
|
||||||
|
|
|
@ -60,7 +60,7 @@ def get_zeus_oauth_token():
|
||||||
|
|
||||||
def login_and_redirect_user(user):
|
def login_and_redirect_user(user):
|
||||||
login_user(user)
|
login_user(user)
|
||||||
return redirect(url_for("admin.index"))
|
return redirect(url_for("home"))
|
||||||
|
|
||||||
|
|
||||||
def create_user(username):
|
def create_user(username):
|
||||||
|
|
Loading…
Reference in a new issue