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

Merge branch 'mj/edit-statement' into 'devel'

Upload zadání

See merge request !75
parents ea743f62 9b94de78
Branches
No related tags found
1 merge request!75Upload zadání
import decimal import decimal
from flask import render_template, g, redirect, url_for, flash, request from flask import render_template, g, redirect, url_for, flash, request
import locale import locale
import flask_wtf.file
from flask_wtf.form import FlaskForm from flask_wtf.form import FlaskForm
import bleach import bleach
from bleach.sanitizer import ALLOWED_TAGS from bleach.sanitizer import ALLOWED_TAGS
import markdown import markdown
import os
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from sqlalchemy.sql.functions import coalesce from sqlalchemy.sql.functions import coalesce
...@@ -426,7 +428,6 @@ class RoundEditForm(FlaskForm): ...@@ -426,7 +428,6 @@ class RoundEditForm(FlaskForm):
) )
# Only the desktop Firefox does not support datetime-local field nowadays, # Only the desktop Firefox does not support datetime-local field nowadays,
# other browsers does provide date and time picker UI :( # other browsers does provide date and time picker UI :(
tasks_file = wtforms.StringField("Soubor se zadáním", description="Cesta k ručně uploadovanému souboru", filters=[lambda x: x or None])
ct_tasks_start = MODateTimeField("Čas zveřejnění úloh pro účastníky", validators=[validators.Optional()]) ct_tasks_start = MODateTimeField("Čas zveřejnění úloh pro účastníky", validators=[validators.Optional()])
pr_tasks_start = MODateTimeField("Čas zveřejnění úloh pro dozor", validators=[validators.Optional()]) pr_tasks_start = MODateTimeField("Čas zveřejnění úloh pro dozor", validators=[validators.Optional()])
ct_submit_end = MODateTimeField("Konec odevzdávání pro účastníky", validators=[validators.Optional()]) ct_submit_end = MODateTimeField("Konec odevzdávání pro účastníky", validators=[validators.Optional()])
...@@ -520,6 +521,61 @@ def org_task_statement(id: int): ...@@ -520,6 +521,61 @@ def org_task_statement(id: int):
return mo.web.util.send_task_statement(round) return mo.web.util.send_task_statement(round)
class StatementEditForm(FlaskForm):
file = flask_wtf.file.FileField("Soubor", render_kw={'autofocus': True})
upload = wtforms.SubmitField('Nahrát')
delete = wtforms.SubmitField('Smazat')
@app.route('/org/contest/r/<int:id>/task-statement/edit', methods=('GET', 'POST'))
def org_edit_statement(id: int):
sess = db.get_session()
round, _, rr = get_round_rr(id, Right.manage_round, True)
def log_changes():
if sess.is_modified(round):
changes = db.get_object_changes(round)
app.logger.info(f"Kolo #{id} změněno, změny: {changes}")
mo.util.log(
type=db.LogType.round,
what=id,
details={'action': 'edit', 'changes': changes},
)
form = StatementEditForm()
if form.validate_on_submit():
if form.upload.data:
if form.file.data is not None:
file = form.file.data.stream
secure_category = werkzeug.utils.secure_filename(round.category)
stmt_dir = f'{round.year}-{secure_category}-{round.seq}'
full_dir = os.path.join(mo.util.data_dir('statements'), stmt_dir)
os.makedirs(full_dir, exist_ok=True)
full_name = mo.util.link_to_dir(file.name, full_dir, suffix='.pdf')
file_name = os.path.join(stmt_dir, os.path.basename(full_name))
app.logger.info(f'Nahráno zadání: {file_name}')
round.tasks_file = file_name
log_changes()
sess.commit()
flash('Zadání nahráno', 'success')
return redirect(url_for('org_round', id=id))
else:
flash('Vyberte si prosím soubor', 'danger')
if form.delete.data:
round.tasks_file = None
log_changes()
sess.commit()
flash('Zadání smazáno', 'success')
return redirect(url_for('org_round', id=id))
return render_template(
'org_edit_statement.html',
round=round,
form=form,
)
class MessageAddForm(FlaskForm): class MessageAddForm(FlaskForm):
title = wtforms.StringField('Nadpis', validators=[validators.Required()]) title = wtforms.StringField('Nadpis', validators=[validators.Required()])
markdown = wtforms.TextAreaField( markdown = wtforms.TextAreaField(
......
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Zadání kola {{ round.round_code() }}{% endblock %}
{% block breadcrumbs %}
{{ contest_breadcrumbs(round=round, action="Zadáni") }}
{% endblock %}
{% block body %}
{{ wtf.quick_form(form, form_type='horizontal', button_map={'upload': 'primary', 'delete': 'danger'}) }}
{% endblock %}
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
</table> </table>
<table class=data style="float: left;"> <table class=data style="float: left;">
<thead> <thead>
<tr><th colspan=2>Termíny <tr><th colspan=2>Termíny a zadání
</thead> </thead>
<tr><td>Účastníci vidí zadání od<td>{{ round.ct_tasks_start|time_and_timedelta }} <tr><td>Účastníci vidí zadání od<td>{{ round.ct_tasks_start|time_and_timedelta }}
<tr><td>Účastníci odevzdávají do<td>{{ round.ct_submit_end|time_and_timedelta }} <tr><td>Účastníci odevzdávají do<td>{{ round.ct_submit_end|time_and_timedelta }}
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
{% endif %} {% endif %}
{% if can_manage_round %} {% if can_manage_round %}
<a class="btn btn-default" href='{{ url_for('org_round_edit', id=round.round_id) }}'>Nastavení a termíny</a> <a class="btn btn-default" href='{{ url_for('org_round_edit', id=round.round_id) }}'>Nastavení a termíny</a>
<a class="btn btn-default" href='{{ url_for('org_edit_statement', id=round.round_id) }}'>Zadání</a>
{% endif %} {% endif %}
{% if round.has_messages %} {% if round.has_messages %}
<a class="btn btn-default" href='{{ url_for('org_round_messages', id=round.round_id) }}'>Zprávičky</a> <a class="btn btn-default" href='{{ url_for('org_round_messages', id=round.round_id) }}'>Zprávičky</a>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment