Compare commits
4 Commits
adf6d6e99a
...
1c126796a9
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c126796a9 | |||
| 26ad2c6881 | |||
| ddca2748b3 | |||
| b8316cc236 |
@ -37,7 +37,6 @@ def reload_static_data(db):
|
||||
Team.query.delete()
|
||||
Driver.query.delete()
|
||||
Race.query.delete()
|
||||
User.query.delete()
|
||||
|
||||
# Reload static data
|
||||
for row in load_csv("static_data/teams.csv"):
|
||||
@ -46,8 +45,6 @@ def reload_static_data(db):
|
||||
db.session.add(Driver().from_csv(row))
|
||||
for row in load_csv("static_data/races.csv"):
|
||||
db.session.add(Race().from_csv(row))
|
||||
for row in load_csv("static_data/users.csv"):
|
||||
db.session.add(User().from_csv(row))
|
||||
|
||||
db.session.commit()
|
||||
|
||||
@ -55,6 +52,8 @@ def reload_static_data(db):
|
||||
def reload_dynamic_data(db):
|
||||
print("Initializing Database with Dynamic Values...")
|
||||
|
||||
db.create_all()
|
||||
|
||||
# Clear dynamic data
|
||||
User.query.delete()
|
||||
RaceResult.query.delete()
|
||||
|
||||
25
model.py
25
model.py
@ -83,13 +83,14 @@ class User(db.Model):
|
||||
|
||||
class RaceResult(db.Model):
|
||||
__tablename__ = "raceresult"
|
||||
__csv_header__ = ["id", "race_id", "pxx_ids_json", "dnf_ids_json"]
|
||||
__csv_header__ = ["id", "race_id", "pxx_ids_json", "dnf_ids_json", "exclude_ids_json"]
|
||||
|
||||
def from_csv(self, row):
|
||||
self.id = int(row[0])
|
||||
self.race_id = int(row[1])
|
||||
self.pxx_ids_json = str(row[2])
|
||||
self.dnf_ids_json = str(row[3])
|
||||
self.exclude_ids_json = str(row[4])
|
||||
return self
|
||||
|
||||
def to_csv(self):
|
||||
@ -97,13 +98,15 @@ class RaceResult(db.Model):
|
||||
self.id,
|
||||
self.race_id,
|
||||
self.pxx_ids_json,
|
||||
self.dnf_ids_json
|
||||
self.dnf_ids_json,
|
||||
self.exclude_ids_json
|
||||
]
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
race_id: Mapped[int] = mapped_column(ForeignKey("race.id"))
|
||||
pxx_ids_json: Mapped[str] = mapped_column(String(1024))
|
||||
dnf_ids_json: Mapped[str] = mapped_column(String(1024))
|
||||
exclude_ids_json: Mapped[str] = mapped_column(String(1024))
|
||||
|
||||
@property
|
||||
def pxx_ids(self) -> List[str]:
|
||||
@ -121,10 +124,19 @@ class RaceResult(db.Model):
|
||||
def dnf_ids(self, new_dnf_ids: List[str]):
|
||||
self.dnf_ids_json = json.dumps(new_dnf_ids)
|
||||
|
||||
@property
|
||||
def exclude_ids(self) -> List[str]:
|
||||
return json.loads(self.exclude_ids_json)
|
||||
|
||||
@exclude_ids.setter
|
||||
def exclude_ids(self, new_exclude_ids: List[str]):
|
||||
self.exclude_ids_json = json.dumps(new_exclude_ids)
|
||||
|
||||
# Relationships
|
||||
race: Mapped["Race"] = relationship("Race", foreign_keys=[race_id])
|
||||
_pxxs = None
|
||||
_dnfs = None
|
||||
_excludes = None
|
||||
|
||||
@property
|
||||
def pxxs(self) -> List[Driver]:
|
||||
@ -144,6 +156,15 @@ class RaceResult(db.Model):
|
||||
|
||||
return self._dnfs
|
||||
|
||||
@property
|
||||
def excludes(self) -> List[Driver]:
|
||||
if self._excludes is None:
|
||||
self._excludes = [
|
||||
driver for driver in Driver.query.all() if driver.name in self.exclude_ids
|
||||
]
|
||||
|
||||
return self._excludes
|
||||
|
||||
|
||||
class RaceGuess(db.Model):
|
||||
__tablename__ = "raceguess"
|
||||
|
||||
78
static/script/draggable.js
Normal file
78
static/script/draggable.js
Normal file
@ -0,0 +1,78 @@
|
||||
// https://codepen.io/retrofuturistic/pen/DJWYBv
|
||||
|
||||
let dragSrcEl = null;
|
||||
|
||||
function handleDragStart(e) {
|
||||
// Target (this) element is the source node.
|
||||
dragSrcEl = this;
|
||||
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
e.dataTransfer.setData('text/html', this.outerHTML);
|
||||
|
||||
this.classList.add('dragElem');
|
||||
}
|
||||
|
||||
function handleDragOver(e) {
|
||||
if (e.preventDefault) {
|
||||
e.preventDefault(); // Necessary. Allows us to drop.
|
||||
}
|
||||
this.classList.add('over');
|
||||
|
||||
e.dataTransfer.dropEffect = 'move'; // See the section on the DataTransfer object.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleDragEnter(e) {
|
||||
// this / e.target is the current hover target.
|
||||
}
|
||||
|
||||
function handleDragLeave(e) {
|
||||
this.classList.remove('over'); // this / e.target is previous target element.
|
||||
}
|
||||
|
||||
function handleDrop(e) {
|
||||
// this/e.target is current target element.
|
||||
|
||||
if (e.stopPropagation) {
|
||||
e.stopPropagation(); // Stops some browsers from redirecting.
|
||||
}
|
||||
|
||||
// Don't do anything if dropping the same column we're dragging.
|
||||
if (dragSrcEl != this) {
|
||||
// Set the source column's HTML to the HTML of the column we dropped on.
|
||||
//alert(this.outerHTML);
|
||||
//dragSrcEl.innerHTML = this.innerHTML;
|
||||
//this.innerHTML = e.dataTransfer.getData('text/html');
|
||||
this.parentNode.removeChild(dragSrcEl);
|
||||
let dropHTML = e.dataTransfer.getData('text/html');
|
||||
this.insertAdjacentHTML('beforebegin', dropHTML);
|
||||
let dropElem = this.previousSibling;
|
||||
addDnDHandlers(dropElem);
|
||||
}
|
||||
|
||||
this.classList.remove('over');
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleDragEnd(e) {
|
||||
// this/e.target is the source node.
|
||||
this.classList.remove('over');
|
||||
|
||||
/*[].forEach.call(cols, function (col) {
|
||||
col.classList.remove('over');
|
||||
});*/
|
||||
}
|
||||
|
||||
function addDnDHandlers(elem) {
|
||||
elem.addEventListener('dragstart', handleDragStart, false);
|
||||
elem.addEventListener('dragenter', handleDragEnter, false)
|
||||
elem.addEventListener('dragover', handleDragOver, false);
|
||||
elem.addEventListener('dragleave', handleDragLeave, false);
|
||||
elem.addEventListener('drop', handleDrop, false);
|
||||
elem.addEventListener('dragend', handleDragEnd, false);
|
||||
|
||||
}
|
||||
|
||||
const cols = document.querySelectorAll('#columns .column');
|
||||
[].forEach.call(cols, addDnDHandlers);
|
||||
21
static/style/draggable.css
Normal file
21
static/style/draggable.css
Normal file
@ -0,0 +1,21 @@
|
||||
/* https://codepen.io/retrofuturistic/pen/DJWYBv */
|
||||
|
||||
[draggable] {
|
||||
-moz-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
/* Required to make elements draggable in old WebKit */
|
||||
-khtml-user-drag: element;
|
||||
-webkit-user-drag: element;
|
||||
}
|
||||
|
||||
.column {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.column.over {
|
||||
//border: 2px dashed #000;
|
||||
border-top: 2px solid blue;
|
||||
}
|
||||
52
templates/enter.jinja
Normal file
52
templates/enter.jinja
Normal file
@ -0,0 +1,52 @@
|
||||
{% extends 'base.jinja' %}
|
||||
|
||||
{% set active_page = "/enter" %}
|
||||
{% set active_user = none %}
|
||||
|
||||
{% block title %}Formula 10 - Race Result{% endblock title %}
|
||||
|
||||
{% block head_extra %}
|
||||
<link href="../static/style/draggable.css" rel="stylesheet">
|
||||
<script src="../static/script/draggable.js" defer></script>
|
||||
{% endblock head_extra %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="card shadow-sm" style="width: 450px;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{ race.grandprix }}</h5>
|
||||
|
||||
<form action="/enterresult" method="post">
|
||||
<ul id="columns" class="list-group list-group-flush">
|
||||
{% for driver in drivers %}
|
||||
<li class="list-group-item column p-1" draggable="true">
|
||||
{{ driver.name }}
|
||||
|
||||
<div class="d-inline-block float-end">
|
||||
{# Driver DNFed #}
|
||||
<div class="form-check form-check-reverse d-inline-block">
|
||||
<input type="checkbox" class="form-check-input" value="{{ driver.name }}"
|
||||
id="dnf-{{ driver.name }}" name="dnf-drivers">
|
||||
<label for="dnf-{{ driver.name }}" class="form-check-label text-muted">DNF</label>
|
||||
</div>
|
||||
|
||||
{# Driver Excluded #}
|
||||
<div class="form-check form-check-reverse d-inline-block mx-2">
|
||||
<input type="checkbox" class="form-check-input" value="{{ driver.name }}"
|
||||
id="exclude-{{ driver.name }}" name="exclude-drivers">
|
||||
<label for="exclude-{{ driver.name }}" class="form-check-label text-muted">Exclude</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Standing order #}
|
||||
<input type="hidden" name="pxxdrivers" value="{{ driver.name }}"></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<input type="submit" class="btn btn-danger mt-2" value="Save">
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock body %}
|
||||
@ -1,12 +1,13 @@
|
||||
{% extends 'base.jinja' %}
|
||||
|
||||
{% set active_page = "/users" %}
|
||||
{% set active_user = none %}
|
||||
|
||||
{% block title %}Formula 10 - Users{% endblock title %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="card">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Add User</h5>
|
||||
|
||||
@ -25,7 +26,7 @@
|
||||
</div>
|
||||
|
||||
{% if users | length > 0 %}
|
||||
<div class="card mt-2">
|
||||
<div class="card mt-2 shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Registered Users</h5>
|
||||
|
||||
@ -37,7 +38,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-2">
|
||||
<div class="card mt-2 shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Delete user</h5>
|
||||
|
||||
@ -67,7 +68,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="card mt-2 border-danger">
|
||||
<div class="card mt-2 border-danger shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Functions that should not be public</h5>
|
||||
<h6 class="card-subtitle mb-2">(Fuck you if you click this without knowing what it does)</h6>
|
||||
|
||||
Reference in New Issue
Block a user