Merge remote-tracking branch 'origin/master'

Conflicts:
	app/create_database.py
This commit is contained in:
Wout Schellaert 2015-03-28 00:08:27 +01:00
commit d323a7065c
21 changed files with 256 additions and 63 deletions

View file

@ -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)

View file

@ -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

View file

@ -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
View 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]

View file

@ -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):

View file

@ -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

View file

@ -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 %}

View 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 %}

View 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 %}

View file

@ -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>

View 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 %}

View file

@ -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>

View file

@ -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
View 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 %}

View 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
View 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 %}

View file

@ -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
View 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

View file

@ -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
View 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)

View file

@ -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):