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

Diplomy/UI: Schvalování diplomů

parent 1fd41280
Branches
No related tags found
1 merge request!137Sazba diplomů
...@@ -7,6 +7,7 @@ from markupsafe import Markup ...@@ -7,6 +7,7 @@ from markupsafe import Markup
import os import os
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from typing import Tuple, Optional, Dict from typing import Tuple, Optional, Dict
import werkzeug.exceptions
import wtforms import wtforms
from wtforms import validators from wtforms import validators
...@@ -85,6 +86,12 @@ class CertSetForm(FlaskForm): ...@@ -85,6 +86,12 @@ class CertSetForm(FlaskForm):
return ok return ok
class CertApproveForm(FlaskForm):
ctype = wtforms.HiddenField()
approve = wtforms.SubmitField("Schválit")
unapprove = wtforms.SubmitField("Zrušit schválení")
@app.route('/org/contest/c/<int:ct_id>/certificates', methods=('GET', 'POST')) @app.route('/org/contest/c/<int:ct_id>/certificates', methods=('GET', 'POST'))
def org_certificates(ct_id: int): def org_certificates(ct_id: int):
ctx = get_context(ct_id=ct_id, right_needed=Right.view_contestants) ctx = get_context(ct_id=ct_id, right_needed=Right.view_contestants)
...@@ -119,10 +126,30 @@ def org_certificates(ct_id: int): ...@@ -119,10 +126,30 @@ def org_certificates(ct_id: int):
del form.tex_hacks del form.tex_hacks
if new_cset: if new_cset:
del form.delete del form.delete
approve_form = CertApproveForm()
else: else:
form = None form = None
approve_form = None
if approve_form and approve_form.validate_on_submit() and (approve_form.approve.data or approve_form.unapprove.data):
try:
ctype = db.CertType.coerce(approve_form.ctype.data)
except ValueError:
raise werkzeug.exceptions.UnprocessableEntity()
cfile = sess.query(db.CertFile).filter_by(cert_set_id=ct_id, type=ctype).one_or_none()
if cfile:
if approve_form.approve.data:
cfile.approved = True
flash(f'Diplomy ({ctype.friendly_name()}) schváleny.', 'success')
elif approve_form.unapprove.data:
cfile.approved = False
flash(f'Odvoláno schválení diplomů ({ctype.friendly_name()}).', 'success')
sess.commit()
return redirect(ctx.url_for('org_certificates'))
else:
flash('Tento typ diplomů nebyl vytvořen.', 'danger')
if form: elif form:
if not form.is_submitted(): if not form.is_submitted():
pass pass
elif not form.validate() or not form.osmo_validate(cset): elif not form.validate() or not form.osmo_validate(cset):
...@@ -201,6 +228,7 @@ def org_certificates(ct_id: int): ...@@ -201,6 +228,7 @@ def org_certificates(ct_id: int):
cert_files_by_type: Dict[db.CertType, Optional[db.CertFile]] = {} cert_files_by_type: Dict[db.CertType, Optional[db.CertFile]] = {}
for cf in sess.query(db.CertFile).filter_by(cert_set_id=ct_id).all(): for cf in sess.query(db.CertFile).filter_by(cert_set_id=ct_id).all():
cert_files_by_type[cf.type] = cf cert_files_by_type[cf.type] = cf
cert_file_columns = [(t, cert_files_by_type.get(t)) for t in db.CertType]
certs_by_uid_type: Dict[Tuple[int, db.CertType], db.Certificate] = {} certs_by_uid_type: Dict[Tuple[int, db.CertType], db.Certificate] = {}
for c in sess.query(db.Certificate).filter_by(cert_set_id=ct_id).all(): for c in sess.query(db.Certificate).filter_by(cert_set_id=ct_id).all():
...@@ -211,9 +239,10 @@ def org_certificates(ct_id: int): ...@@ -211,9 +239,10 @@ def org_certificates(ct_id: int):
ctx=ctx, ctx=ctx,
group_rounds=group_rounds, group_rounds=group_rounds,
form=form, form=form,
approve_form=approve_form,
cset=cset, cset=cset,
users_pions=users_pions, users_pions=users_pions,
cert_files_by_type=cert_files_by_type, cert_file_columns=cert_file_columns,
certs_by_uid_type=certs_by_uid_type, certs_by_uid_type=certs_by_uid_type,
settings_changed=(cset.changed_at is not None and (cset.certs_issued_at is None or cset.certs_issued_at < cset.changed_at)), settings_changed=(cset.changed_at is not None and (cset.certs_issued_at is None or cset.certs_issued_at < cset.changed_at)),
scoretable_changed=(cset.scoretable != contest.scoretable), scoretable_changed=(cset.scoretable != contest.scoretable),
... ...
......
...@@ -31,8 +31,12 @@ ...@@ -31,8 +31,12 @@
Zde je možné vytvořit účastnické listy pro všechny soutěžící, Zde je možné vytvořit účastnické listy pro všechny soutěžící,
po vytvoření oficiální výsledkové listiny také diplomy vítězů / úspěšných řešitelů po vytvoření oficiální výsledkové listiny také diplomy vítězů / úspěšných řešitelů
a pochvalná uznání (pokud se v tomto kole vydávají). a pochvalná uznání (pokud se v tomto kole vydávají).
</p>
<p>
Hotové diplomy si můžete stáhnout a vytisknout. Hotové diplomy si můžete stáhnout a vytisknout.
Po uzavření kola budou také dostupné soutěžícím v OSMO. Pokud je schválíte, po uzavření kola budou dostupné soutěžícím a jejich
školním garantům v OSMO.
</p> </p>
<h3>Diplomy</h3> <h3>Diplomy</h3>
...@@ -53,17 +57,24 @@ Po uzavření kola budou také dostupné soutěžícím v OSMO. ...@@ -53,17 +57,24 @@ Po uzavření kola budou také dostupné soutěžícím v OSMO.
<thead> <thead>
<tr> <tr>
<th>Jméno <th>Jméno
{% for t in CertType %} {% for t, cfile in cert_file_columns %}
<th class=ac>{{ t.friendly_name()|titlecase }} <th class=ac>{{ t.friendly_name()|titlecase }}<br>
{% if cfile %}
{% if cfile.approved %}
<em>(schváleno)</em>
{% else %}
<em>(neschváleno)</em>
{% endif %}
{% endif %}
{% endfor %} {% endfor %}
<tbody> <tbody>
{% for user, pion in users_pions %} {% for user, pion in users_pions %}
<tr class="state-{{ pion.state.name }}"> <tr class="state-{{ pion.state.name }}">
<td>{{ user.full_name() }} <td><a href='{{ url_for('org_contest_user', ct_id=ctx.ct_id, user_id=user.user_id) }}'>{{ user.full_name() }}</a>
{% if pion.state != PartState.active %} {% if pion.state != PartState.active %}
({{ pion.state.friendly_name() }}) ({{ pion.state.friendly_name() }})
{% endif %} {% endif %}
{% for t in CertType %} {% for t, cfile in cert_file_columns %}
{% set cert = certs_by_uid_type[user.user_id, t] %} {% set cert = certs_by_uid_type[user.user_id, t] %}
{% if cert %} {% if cert %}
<td class=ac><a href="{{ ctx.url_for('org_cert_file', cert_type=t.name, user_id=user.user_id, filename=t.file_name(False) + '.pdf') }}">{{ cert.achievement }}</a> <td class=ac><a href="{{ ctx.url_for('org_cert_file', cert_type=t.name, user_id=user.user_id, filename=t.file_name(False) + '.pdf') }}">{{ cert.achievement }}</a>
...@@ -75,14 +86,31 @@ Po uzavření kola budou také dostupné soutěžícím v OSMO. ...@@ -75,14 +86,31 @@ Po uzavření kola budou také dostupné soutěžícím v OSMO.
<tfoot> <tfoot>
<tr> <tr>
<th>Všichni dohromady <th>Všichni dohromady
{% for t in CertType %} {% for t, cfile in cert_file_columns %}
{% set cfile = cert_files_by_type[t] %}
{% if cfile %} {% if cfile %}
<th class=ac><a href="{{ ctx.url_for('org_cert_file', cert_type=t.name, filename=t.file_name(True) + '.pdf') }}">stáhnout</a> <th class=ac><a href="{{ ctx.url_for('org_cert_file', cert_type=t.name, filename=t.file_name(True) + '.pdf') }}">stáhnout</a>
{% else %} {% else %}
<th> <th>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if approve_form %}
<tr>
<th>Akce
{% for t, cfile in cert_file_columns %}
<td class=ac>
{% if cfile %}
<form method="POST" action="">
{{ approve_form.csrf_token }}
<input type="hidden" name="ctype" value="{{t.name}}">
{% if cfile.approved %}
{{ approve_form.unapprove(class='btn btn-xs btn-danger') }}
{% else %}
{{ approve_form.approve(class='btn btn-xs btn-success') }}
{% endif %}
</form>
{% endif %}
{% endfor %}
{% endif %}
</table> </table>
{% if settings_changed or scoretable_changed %} {% if settings_changed or scoretable_changed %}
... ...
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment