Skip to content
Snippets Groups Projects
Commit ff67c7ca authored by Martin Mareš's avatar Martin Mareš
Browse files

Kousky stránek pro účastníky

parent e28c24ee
No related branches found
No related tags found
1 merge request!9WIP: Zárodek uživatelské části webu a submitování
...@@ -27,6 +27,7 @@ Bootstrap(app) # make bootstrap libs accessible for the app ...@@ -27,6 +27,7 @@ Bootstrap(app) # make bootstrap libs accessible for the app
# - kořenový logger dostane flaskový handler, aby se logovaly hlášky ze všech komponent # - kořenový logger dostane flaskový handler, aby se logovaly hlášky ze všech komponent
# - app.logger (což Flask založil jako podřízený logger) nastavíme, aby nepropagoval výše # - app.logger (což Flask založil jako podřízený logger) nastavíme, aby nepropagoval výše
# FIXME: Ještě je potřeba dořešit, že flaskový development server loguje každý request dvojmo. # FIXME: Ještě je potřeba dořešit, že flaskový development server loguje každý request dvojmo.
# FIXME: Logování dotazů v sqlalchemy také.
app.logger.setLevel(logging.DEBUG) app.logger.setLevel(logging.DEBUG)
app.logger.propagate = False app.logger.propagate = False
root_logger = logging.getLogger() root_logger = logging.getLogger()
...@@ -80,6 +81,9 @@ def init_request(): ...@@ -80,6 +81,9 @@ def init_request():
raise NeedLoginError() raise NeedLoginError()
if not (user.is_org or user.is_admin): if not (user.is_org or user.is_admin):
raise werkzeug.exceptions.Forbidden() raise werkzeug.exceptions.Forbidden()
elif path.startswith('/user/'):
if not user:
raise NeedLoginError()
app.before_request(init_request) app.before_request(init_request)
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
<li>{{ r.name }} <li>{{ r.name }}
{% endfor %} {% endfor %}
</ul> </ul>
{% elif g.user.is_admin %}
<p>Žádná, ale to správci nevadí :)
{% else %} {% else %}
<p>Žádná. <p>Žádná.
{% endif %} {% endif %}
......
{% extends "base.html" %}
{% block body %}
<h2>{{ contest.round.name }} {{ contest.round.year }}. ročníku kategorie {{ contest.round.category }}</h2>
<h2>{{ contest.place.name }}</h2>
<p>FIXME: Uvést stav contestu
<h3>Úlohy</h3>
<table class=data>
<thead>
<tr>
<th>Úloha
<tbody>
{% for task, sol in task_sols %}
<tr>
<td>{{ task.code }} {{ task.name }}
{% endfor %}
</table>
{% endblock %}
...@@ -2,4 +2,35 @@ ...@@ -2,4 +2,35 @@
{% block body %} {% block body %}
<h2>Vítejte</h2> <h2>Vítejte</h2>
{% if pions %}
<p>Jste přihlášen do následujících kol MO:
<table class=data>
<thead>
<tr>
<th title='ročník MO'>Roč.
<th title='kategorie'>Kat.
<th>Kolo
<th>Oblast
<th>Stav
<th>Akce
<tbody>
{% for pion, contest, round in pions %}
<tr>
<td>{{ round.year }}
<td>{{ round.category }}
<td>{{ round.name }}
<td>{{ contest.place.name }}
<td>{{ round.state.friendly_name() }}
<td><div class="btn-group">
{% if submit_allowed(round) %}
<a class='btn btn-xs btn-success' href='{{ url_for('user_contest', id=contest.contest_id) }}'>Odevzdávat</a>
{% endif %}
</div>
{% endfor %}
</table>
{% else %}
<p>Momentálně nejste přihlášen do žádného kola MO.
{% endif %}
{% endblock %} {% endblock %}
...@@ -3,16 +3,81 @@ from flask_wtf import FlaskForm ...@@ -3,16 +3,81 @@ from flask_wtf import FlaskForm
import werkzeug.exceptions import werkzeug.exceptions
import wtforms import wtforms
import wtforms.validators as validators import wtforms.validators as validators
from sqlalchemy import or_
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from typing import Optional from typing import Optional
import mo.util import mo.util
import mo.db as db import mo.db as db
import mo.rights from mo.web import app, get_request_time
import mo.users
from mo.web import app, NeedLoginError
# Bylo by elegantní, kdyby tohle byla metoda třídy Round, ale ta by zase
# nemohla mít k dispozici čas aktuálního requestu.
def user_submit_allowed(round: db.Round):
if round.state != db.RoundState.running:
return False
if round.submit_start is None or round.ct_submit_end is None:
return False
now = get_request_time()
return round.submit_start <= now <= round.ct_submit_end
@app.route('/user') @app.route('/user')
def user_index(): def user_index():
return render_template('user_main.html') sess = db.get_session()
pions = (sess.query(db.Participation, db.Contest, db.Round)
.select_from(db.Participation)
.join(db.Contest)
.join(db.Round)
.filter(db.Participation.user == g.user)
.filter(db.Round.state != db.RoundState.preparing)
.options(joinedload(db.Contest.place))
.all())
return render_template(
'user_main.html',
pions=pions,
submit_allowed=user_submit_allowed,
)
def get_contest(id: int) -> db.Contest:
contest = (db.get_session().query(db.Contest)
.options(joinedload(db.Contest.place),
joinedload(db.Contest.round))
.get(id))
if not contest:
raise werkzeug.exceptions.NotFound()
# FIXME: Časem chceme účastníky pustit i v jiných stavech
if contest.round.state != db.RoundState.running:
raise werkzeug.exceptions.Forbidden()
return contest
@app.route('/user/contest/<int:id>/')
def user_contest(id: int):
contest = get_contest(id)
task_sols = (db.get_session().query(db.Task, db.Solution)
.select_from(db.Task)
.outerjoin(db.Solution)
.filter(db.Task.round == contest.round)
.filter(or_(db.Solution.user_id == None, db.Solution.user == g.user))
.options(joinedload(db.Solution.last_submit_obj),
joinedload(db.Solution.last_feedback_obj))
.all())
print(task_sols)
return render_template(
'user_contest.html',
contest=contest,
task_sols=task_sols,
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment