Add Seasons.
This commit is contained in:
48
app.py
48
app.py
@@ -2,7 +2,7 @@ import functools
|
||||
from flask import Flask, g, render_template, request, redirect, session
|
||||
|
||||
import db
|
||||
import model
|
||||
import models
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
@@ -76,7 +76,45 @@ def landing():
|
||||
@app.route('/seasons')
|
||||
@authorize
|
||||
def seasons():
|
||||
return render_template('seasons.html')
|
||||
sql, args = db.load_season()
|
||||
results = db. query_db(sql, args, cls=models.Season)
|
||||
model = {
|
||||
'seasons': results,
|
||||
'columns': [
|
||||
('game', 'Game'),
|
||||
('description', 'Season Description'),
|
||||
('start', 'Started At'),
|
||||
('end', 'Ended At')
|
||||
]
|
||||
}
|
||||
return render_template('seasons.html', model=model)
|
||||
|
||||
|
||||
@app.route('/newseason', methods=['GET'])
|
||||
@authorize
|
||||
def new_season():
|
||||
return render_template('editseason.html', model={})
|
||||
|
||||
|
||||
@app.route('/seasons/edit/<id>')
|
||||
@authorize
|
||||
def edit_season(id: int):
|
||||
sql, args = db.load_season(id)
|
||||
loaded = db.query_db(sql, args, one=True, cls=models.Season)
|
||||
return render_template('editseason.html', model=loaded)
|
||||
|
||||
|
||||
@app.route('/saveseason', methods=['POST'])
|
||||
@authorize
|
||||
def save_season():
|
||||
try:
|
||||
season = models.Season.from_form(request.form)
|
||||
except AttributeError as err:
|
||||
print(err)
|
||||
return render_template('editseason.html', model={})
|
||||
sql, args = db.save_season_query(season)
|
||||
res = db.update_db(sql, args)
|
||||
return redirect('/seasons')
|
||||
|
||||
|
||||
@app.route('/newplayer', methods=['GET'])
|
||||
@@ -87,9 +125,9 @@ def new_player():
|
||||
|
||||
@app.route('/saveplayer', methods=['POST'])
|
||||
@authorize
|
||||
def update_player():
|
||||
def save_player():
|
||||
data = request.form
|
||||
player = model.Player(
|
||||
player = models.Player(
|
||||
id=data.get('id', None),
|
||||
real_name=data['real_name'],
|
||||
alias=data['alias'],
|
||||
@@ -153,7 +191,7 @@ def new_drink():
|
||||
@app.route('/savedrink', methods=['POST'])
|
||||
@authorize
|
||||
def save_drink():
|
||||
drink = model.Drink.from_form(request.form)
|
||||
drink = models.Drink.from_form(request.form)
|
||||
res = db.save_drink(drink)
|
||||
return redirect('/drinks')
|
||||
|
||||
|
||||
36
db.py
36
db.py
@@ -2,7 +2,7 @@ import sqlite3
|
||||
import logging as log
|
||||
from flask import g
|
||||
|
||||
import model
|
||||
import models
|
||||
|
||||
|
||||
DATABASE = 'es_debug.db'
|
||||
@@ -18,12 +18,14 @@ def connect_db():
|
||||
return db
|
||||
|
||||
|
||||
def query_db(query, args=(), one=False):
|
||||
"""Runs an SQL query on an new database connection, returning the fetched rows"""
|
||||
def query_db(query, args=(), one=False, cls=None):
|
||||
"""Runs an SQL query on an new database connection, returning the fetched rv"""
|
||||
log.info(f'Running query ({query})\nwith arguments ({args})')
|
||||
cur = connect_db().execute(query, args)
|
||||
rv = cur.fetchall()
|
||||
cur.close()
|
||||
if cls:
|
||||
rv = [cls(**row) for row in rv]
|
||||
return (rv[0] if rv else None) if one else rv
|
||||
|
||||
|
||||
@@ -79,7 +81,7 @@ def load_players(id=None):
|
||||
args = (id, )
|
||||
sql += ' order by player.id'
|
||||
rows = query_db(sql, args)
|
||||
players = [model.Player(**row) for row in rows]
|
||||
players = [models.Player(**row) for row in rows]
|
||||
return players
|
||||
|
||||
|
||||
@@ -91,7 +93,7 @@ def load_drinks(id=None):
|
||||
args = (id, )
|
||||
sql += ' order by drink.id'
|
||||
rows = query_db(sql, args)
|
||||
drinks = [model.Drink(**row) for row in rows]
|
||||
drinks = [models.Drink(**row) for row in rows]
|
||||
return drinks
|
||||
|
||||
|
||||
@@ -120,5 +122,27 @@ def load_enemies(id=None):
|
||||
args = (id, )
|
||||
sql += ' order by enemy.id'
|
||||
rows = query_db(sql, args)
|
||||
enemies = [model.Enemy(**row) for row in rows]
|
||||
enemies = [models.Enemy(**row) for row in rows]
|
||||
return enemies
|
||||
|
||||
|
||||
def save_season_query(season):
|
||||
if not season.id:
|
||||
sql = 'insert into season values (?, ?, ?, ?, ?)'
|
||||
args = (None, season.game, season.description, season.start, season.end)
|
||||
else:
|
||||
sql = 'update season ' \
|
||||
'set game=?, description=?, start=?, end=? ' \
|
||||
'where id==?'
|
||||
args = (season.game, season.description, season.start, season.end, season.id)
|
||||
return sql, args
|
||||
|
||||
|
||||
def load_season(id=None):
|
||||
sql = 'select * from season'
|
||||
args = ()
|
||||
if id:
|
||||
sql += ' where season.id = ?'
|
||||
args = (id, )
|
||||
sql += ' order by season.start'
|
||||
return sql, args
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from _ctypes import ArgumentError
|
||||
import datetime
|
||||
from dataclasses import dataclass
|
||||
|
||||
INVALID_STR = 'Form entry "{}" is invalid'
|
||||
@@ -35,12 +35,12 @@ class Drink:
|
||||
|
||||
name = form.get('name', None)
|
||||
if not name:
|
||||
raise ArgumentError('Form data contains no field "name"')
|
||||
raise AttributeError('Form data contains no field "name"')
|
||||
name = str(name)
|
||||
|
||||
vol = form.get('vol', None)
|
||||
if not vol:
|
||||
raise ArgumentError('Form data contains no field "vol"')
|
||||
raise AttributeError('Form data contains no field "vol"')
|
||||
vol = float(vol)
|
||||
|
||||
self = cls(id=id, name=name, vol=vol)
|
||||
@@ -60,13 +60,49 @@ class Enemy:
|
||||
|
||||
name = form.get('name', None)
|
||||
if not name:
|
||||
raise ArgumentError(INVALID_STR.format('name'))
|
||||
raise AttributeError(INVALID_STR.format('name'))
|
||||
name = str(name)
|
||||
|
||||
boss = form.get('boss', '')
|
||||
if boss not in [True, False, 'True', 'False']:
|
||||
raise ArgumentError(INVALID_STR.format('boss'))
|
||||
raise AttributeError(INVALID_STR.format('boss'))
|
||||
|
||||
self = cls(id=id, name=name, boss=boss)
|
||||
return self
|
||||
|
||||
|
||||
@dataclass
|
||||
class Season:
|
||||
id: int
|
||||
game: str
|
||||
description: str
|
||||
start: datetime.date
|
||||
end: datetime.date
|
||||
|
||||
@classmethod
|
||||
def from_form(cls, form):
|
||||
id = form.get('id', None)
|
||||
id = int(id) if id else None
|
||||
|
||||
game = form.get('game', None)
|
||||
if not game:
|
||||
raise AttributeError(INVALID_STR.format('game'))
|
||||
game = str(game)
|
||||
|
||||
description = form.get('description', None)
|
||||
|
||||
start = form.get('start', None)
|
||||
try:
|
||||
start = datetime.date.fromisoformat(start)
|
||||
except Exception:
|
||||
raise AttributeError(INVALID_STR.format('start'))
|
||||
|
||||
end = form.get('end', None)
|
||||
if end:
|
||||
try:
|
||||
end = datetime.date.fromisoformat(end)
|
||||
except Exception:
|
||||
raise INVALID_STR.format('end')
|
||||
|
||||
self = cls(id, game, description, start, end)
|
||||
return self
|
||||
79
templates/editseason.html
Normal file
79
templates/editseason.html
Normal file
@@ -0,0 +1,79 @@
|
||||
{% extends "base.html" %}
|
||||
{% set active_page = "seasons" %}
|
||||
{% block title %}Seasons{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<form class="needs-validation" novalidate action="/saveseason" method="post">
|
||||
<div class="form-group">
|
||||
<label for="id">ID</label>
|
||||
<input name="id"
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="id"
|
||||
value="{{ model['id'] }}"
|
||||
readonly>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="game">Game Name</label>
|
||||
<input name="game"
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="game"
|
||||
placeholder="The game name..."
|
||||
value="{{ model['game'] }}"
|
||||
required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="description">Season Description</label>
|
||||
<input name="description"
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="description"
|
||||
placeholder="The season description..."
|
||||
value="{{ model['description'] }}"
|
||||
required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="start">Season Start</label>
|
||||
<input name="start"
|
||||
type="date"
|
||||
class="form-control"
|
||||
id="start"
|
||||
placeholder="YYYY-MM-DD"
|
||||
value="{{ model['start'] }}"
|
||||
required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="end">Season End</label>
|
||||
<input name="end"
|
||||
type="date"
|
||||
class="form-control"
|
||||
id="start"
|
||||
placeholder="Season end date..."
|
||||
value="{{ model['end'] }}">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
// Example starter JavaScript for disabling form submissions if there are invalid fields
|
||||
(function() {
|
||||
'use strict';
|
||||
window.addEventListener('load', function() {
|
||||
// Fetch all the forms we want to apply custom Bootstrap validation styles to
|
||||
let forms = document.getElementsByClassName('needs-validation');
|
||||
// Loop over them and prevent submission
|
||||
let validation = Array.prototype.filter.call(forms, function (form) {
|
||||
form.addEventListener('submit', function (event) {
|
||||
if (form.checkValidity() === false) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
form.classList.add('was-validated');
|
||||
}, false);
|
||||
});
|
||||
}, false);
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -3,5 +3,48 @@
|
||||
{% block title %}Seasons{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
There are no seasons.
|
||||
{% if g.is_editor %}
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<a class="btn btn-primary" href="/newseason" role="button">New Season</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not model.seasons %}
|
||||
There are no seasons.
|
||||
{% else %}
|
||||
<table class="table table-hover table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for prop, caption in model.columns %}
|
||||
<th scope="col" class="col-sm-auto text-center">{{ caption }}</th>
|
||||
{% endfor %}
|
||||
|
||||
<th scope="col" class="col-sm-auto text-center"></th>
|
||||
|
||||
{% if g.is_editor %}
|
||||
<th scope="col" class="col-sm-auto text-center">Editor</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in model.seasons %}
|
||||
<tr>
|
||||
{% for prop, caption in model.columns %}
|
||||
<td class="col-sm-auto text-center">{{ item[prop] }}</td>
|
||||
{% endfor %}
|
||||
|
||||
<td class="col-sm-auto text-center">
|
||||
<a class="btn btn-dark" href="/seasons/{{ item.id }}">Show</a>
|
||||
</td>
|
||||
|
||||
{% if g.is_editor %}
|
||||
<td class="col-sm-auto text-center">
|
||||
<a class="btn btn-dark" href="/seasons/edit/{{ item.id }}">Edit</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user