Skip to content
Snippets Groups Projects
Commit e75733ff authored by Jiří Setnička's avatar Jiří Setnička
Browse files

Vytváření řešení ze stránky úlohy

Vytvořen nový endpoint org_contest_task_create. Vše v pozadí obsluhuje
stejná univerzální tabulka, jen na správných místech vypisuje správné
formuláře ve správném módu (má teď mód zobrazení, zakládání řešení a
bodování).

Přidány odkazy z různých míst.
parent b373cee5
No related branches found
No related tags found
No related merge requests found
...@@ -901,20 +901,24 @@ class TaskPointsForm(FlaskForm): ...@@ -901,20 +901,24 @@ class TaskPointsForm(FlaskForm):
submit = wtforms.SubmitField("Uložit body") submit = wtforms.SubmitField("Uložit body")
class TaskCreateForm(FlaskForm):
submit = wtforms.SubmitField("Založit označená řešení")
@app.route('/org/contest/c/<int:contest_id>/task/<int:task_id>/') @app.route('/org/contest/c/<int:contest_id>/task/<int:task_id>/')
@app.route('/org/contest/c/<int:contest_id>/site/<int:site_id>/task/<int:task_id>/') @app.route('/org/contest/c/<int:contest_id>/site/<int:site_id>/task/<int:task_id>/')
@app.route('/org/contest/c/<int:contest_id>/task/<int:task_id>/points', methods=('GET', 'POST'), endpoint="org_contest_task_points") @app.route('/org/contest/c/<int:contest_id>/task/<int:task_id>/points', methods=('GET', 'POST'), endpoint="org_contest_task_points")
@app.route('/org/contest/c/<int:contest_id>/task/<int:task_id>/create', methods=('GET', 'POST'), endpoint="org_contest_task_create")
@app.route('/org/contest/c/<int:contest_id>/site/<int:site_id>/task/<int:task_id>/create', methods=('GET', 'POST'), endpoint="org_contest_task_create")
def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = None): def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = None):
sc = get_solution_context(contest_id, None, task_id, site_id) sc = get_solution_context(contest_id, None, task_id, site_id)
edit_points = request.endpoint == "org_contest_task_points" action_create = request.endpoint == "org_contest_task_create"
if edit_points: action_points = request.endpoint == "org_contest_task_points"
assert site_id is None if action_create and not sc.allow_create_solutions:
if not sc.allow_edit_points: raise werkzeug.exceptions.Forbidden()
if action_points and not sc.allow_edit_points:
raise werkzeug.exceptions.Forbidden() raise werkzeug.exceptions.Forbidden()
if sc.round.state != db.RoundState.grading:
flash("Kolo není ve stavu opravování, nelze zadávat body", "warning")
return redirect(url_for('org_contest_task', contest_id=contest_id, task_id=task_id))
sess = db.get_session() sess = db.get_session()
...@@ -923,8 +927,41 @@ def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = Non ...@@ -923,8 +927,41 @@ def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = Non
rows.sort(key=lambda r: r[0].user.sort_key()) rows.sort(key=lambda r: r[0].user.sort_key())
points_form: Optional[TaskPointsForm] = None points_form: Optional[TaskPointsForm] = None
create_form: Optional[TaskCreateForm] = None
if action_create:
create_form = TaskCreateForm()
if create_form.validate_on_submit():
new_sol_count = 0
for pion, sol in rows:
if sol:
continue # již existuje
if not request.form.get(f"create_sol_{pion.user_id}"):
continue # nikdo nežádá o vytvoření
sol = db.Solution(task=sc.task, user=pion.user)
sess.add(sol)
mo.util.log(
type=db.LogType.participant,
what=pion.user_id,
details={
'action': 'solution-created',
'task': task_id,
},
)
app.logger.info(f"Řešení úlohy {sc.task.code} od účastníka {pion.user_id} založeno")
new_sol_count += 1
if edit_points: if new_sol_count > 0:
sess.commit()
flash(inflect_by_number(new_sol_count, "Založeno", "Založena", "Založeno") + ' '
+ inflect_number(new_sol_count, "nové řešení", "nová řešení", "nových řešení"),
"success")
else:
flash("Žádné změny k uložení", "info")
return redirect(url_for('org_contest_task', contest_id=contest_id, task_id=task_id, site_id=site_id))
if action_points:
points_form = TaskPointsForm() points_form = TaskPointsForm()
if points_form.validate_on_submit(): if points_form.validate_on_submit():
count = 0 count = 0
...@@ -933,10 +970,13 @@ def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = Non ...@@ -933,10 +970,13 @@ def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = Non
if sol is None: if sol is None:
continue continue
points = request.form.get(f"points_{sol.user_id}", type=int) points = request.form.get(f"points_{sol.user_id}", type=int)
if points and points < 0: if points is None:
continue
if points < 0:
flash('Nelze zadat záporné body', 'danger') flash('Nelze zadat záporné body', 'danger')
ok = False ok = False
break break
if points != sol.points: if points != sol.points:
# Save points # Save points
sol.points = points sol.points = points
...@@ -951,7 +991,7 @@ def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = Non ...@@ -951,7 +991,7 @@ def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = Non
if ok: if ok:
if count > 0: if count > 0:
sess.commit() sess.commit()
flash("Změněny body u " + inflect_number(count, "řešitele", "řešitelů", "řešitelů"), "success") flash("Změněny body u " + inflect_number(count, "řešení", "řešení", "řešení"), "success")
else: else:
flash("Žádné změny k uložení", "info") flash("Žádné změny k uložení", "info")
return redirect(url_for('org_contest_task', contest_id=contest_id, task_id=task_id)) return redirect(url_for('org_contest_task', contest_id=contest_id, task_id=task_id))
...@@ -970,8 +1010,7 @@ def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = Non ...@@ -970,8 +1010,7 @@ def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = Non
"org_contest_task.html", "org_contest_task.html",
sc=sc, rows=rows, paper_counts=paper_counts, sc=sc, rows=rows, paper_counts=paper_counts,
paper_link=lambda u, p: mo.web.util.org_paper_link(sc.contest, sc.site, u, p), paper_link=lambda u, p: mo.web.util.org_paper_link(sc.contest, sc.site, u, p),
can_upload=sc.allow_upload_feedback, points_form=points_form, create_form=create_form, request_form=request.form,
points_form=points_form, request_form=request.form,
) )
......
...@@ -98,6 +98,9 @@ ...@@ -98,6 +98,9 @@
{% if can_upload %} {% if can_upload %}
<a class='btn btn-xs btn-primary' href="{{ url_for('org_contest_task_upload', contest_id=contest.contest_id, task_id=task.task_id, site_id=site_id) }}">Nahrát</a> <a class='btn btn-xs btn-primary' href="{{ url_for('org_contest_task_upload', contest_id=contest.contest_id, task_id=task.task_id, site_id=site_id) }}">Nahrát</a>
{% endif %} {% endif %}
{% if can_create_solutions %}
<a class="btn btn-xs btn-primary" href="{{ url_for('org_contest_task_create', contest_id=contest.contest_id, task_id=task.task_id, site_id=site_id) }}">Založit řešení</a>
{% endif %}
{% if not site and can_edit_points %} {% if not site and can_edit_points %}
<a class="btn btn-xs btn-primary" href="{{ url_for('org_contest_task_points', contest_id=contest.contest_id, task_id=task.task_id) }}">Zadat body</a> <a class="btn btn-xs btn-primary" href="{{ url_for('org_contest_task_points', contest_id=contest.contest_id, task_id=task.task_id) }}">Zadat body</a>
{% endif %} {% endif %}
......
...@@ -7,9 +7,9 @@ ...@@ -7,9 +7,9 @@
{% set site_id = site.place_id if site else None %} {% set site_id = site.place_id if site else None %}
{% set task = sc.task %} {% set task = sc.task %}
{% block title %}{% if points_form %}Editace bodů{% else %}Odevzdaná řešení{% endif %} úlohy {{ task.code }} {{ task.name }}{% endblock %} {% block title %}{{ "Zadávání bodů" if points_form else "Založení řešení" if create_form else "Odevzdaná řešení" }} úlohy {{ task.code }} {{ task.name }}{% endblock %}
{% block breadcrumbs %} {% block breadcrumbs %}
{{ contest_breadcrumbs(round=round, contest=contest, site=site, task=task, action="Editace bodů" if points_form else None) }} {{ contest_breadcrumbs(round=round, contest=contest, site=site, task=task, action="Zadávání bodů" if points_form else "Založení řešení" if create_form else None) }}
{% endblock %} {% endblock %}
{% block body %} {% block body %}
...@@ -23,17 +23,18 @@ ...@@ -23,17 +23,18 @@
{% include "parts/org_submit_warning.html" %} {% include "parts/org_submit_warning.html" %}
{% if points_form %} {% set form = points_form or create_form %}
{% if form %}
<form class="form" method="POST"> <form class="form" method="POST">
{{ points_form.csrf_token }} {{ form.csrf_token }}
{% endif %} {% endif %}
{% with for_user=None, for_task=task, rows=rows %} {% with for_user=None, for_task=task, rows=rows %}
{% include "parts/org_solution_table.html" %} {% include "parts/org_solution_table.html" %}
{% endwith %} {% endwith %}
{% if points_form %} {% if form %}
<div class='btn-group'> <div class='btn-group'>
{{ wtf.form_field(points_form.submit, class="btn btn-primary") }} {{ wtf.form_field(form.submit, class="btn btn-success" if create_form else "btn btn-primary" ) }}
<a class="btn btn-default" href="{{ url_for('org_contest_task', contest_id=ct_id, task_id=task.task_id) }}">Zrušit editaci bodů</a> <a class="btn btn-default" href="{{ url_for('org_contest_task', contest_id=ct_id, task_id=task.task_id, site_id=site_id) }}">Zrušit</a>
</div> </div>
</form> </form>
{% else %} {% else %}
...@@ -42,6 +43,9 @@ ...@@ -42,6 +43,9 @@
{% if sc.allow_upload_feedback %} {% if sc.allow_upload_feedback %}
<a class='btn btn-primary' href="{{ url_for('org_contest_task_upload', contest_id=ct_id, site_id=site_id, task_id=task.task_id) }}">Nahrát opravená řešení</a> <a class='btn btn-primary' href="{{ url_for('org_contest_task_upload', contest_id=ct_id, site_id=site_id, task_id=task.task_id) }}">Nahrát opravená řešení</a>
{% endif %} {% endif %}
{% if sc.allow_create_solutions %}
<a class="btn btn-primary" href="{{ url_for('org_contest_task_create', contest_id=ct_id, task_id=task.task_id, site_id=site_id) }}">Založit řešení</a>
{% endif %}
{% if not site and sc.allow_edit_points %} {% if not site and sc.allow_edit_points %}
<a class="btn btn-primary" href="{{ url_for('org_contest_task_points', contest_id=ct_id, task_id=task.task_id) }}">Zadat body</a> <a class="btn btn-primary" href="{{ url_for('org_contest_task_points', contest_id=ct_id, task_id=task.task_id) }}">Zadat body</a>
{% endif %} {% endif %}
......
<p><i>{% if for_user %}U každé úlohy je zobrazeno účastníkovo {% else %}U každého účastníka je zobrazeno jeho {% endif %} <p><i>{% if for_user %}U každé úlohy je zobrazeno účastníkovo {% else %}U každého účastníka je zobrazeno jeho {% endif %}
finální řešení, finální oprava a přidělené body. Historii všech odevzdání, oprav a bodů naleznete v detailu řešení. finální řešení, finální oprava a přidělené body. Historii všech odevzdání, oprav a bodů naleznete v detailu řešení.
{% if sc.allow_upload_feedback or sc.allow_edit_points %}Tamtéž můžete odevzdávat nové verze a změnit, které řešení/oprava je {% if sc.allow_upload_feedback or sc.allow_edit_points %}Tamtéž můžete odevzdávat nové verze a změnit, které řešení/oprava je
finální (ve výchozím stavu poslední nahrané).{% endif %} finální (ve výchozím stavu poslední nahrané).{% elif sc.allow_upload_solutions %}Tamtéž můžete odevzdat nové řešení.{% endif %}
</i></p> </i></p>
<p><i>Legenda k symbolům: <span class='sol-warn icon'></span> odevzdané po termínu, <p><i>Legenda k symbolům: <span class='sol-warn icon'></span> odevzdané po termínu,
...@@ -15,11 +15,11 @@ finální (ve výchozím stavu poslední nahrané).{% endif %} ...@@ -15,11 +15,11 @@ finální (ve výchozím stavu poslední nahrané).{% endif %}
{% if for_task %}<th>Stav účasti{% endif %} {% if for_task %}<th>Stav účasti{% endif %}
<th>Finální řešení <th>Finální řešení
<th>Finální oprava <th>Finální oprava
<th>Poznámky
<th>Přidělené body <th>Přidělené body
{% if not for_user and not site and sc.allow_edit_points and not points_form %} {% if not for_user and not site and sc.allow_edit_points and not points_form %}
<a title="Editovat body" href="{{ url_for('org_contest_task_points', contest_id=contest.contest_id, task_id=task.task_id) }}" class="icon pull-right"></a> <a title="Editovat body" href="{{ url_for('org_contest_task_points', contest_id=contest.contest_id, task_id=task.task_id) }}" class="icon pull-right"></a>
{% endif %} {% endif %}
<th>Poznámky
<th>Akce <th>Akce
</tr> </tr>
</thead> </thead>
...@@ -73,19 +73,25 @@ finální (ve výchozím stavu poslední nahrané).{% endif %} ...@@ -73,19 +73,25 @@ finální (ve výchozím stavu poslední nahrané).{% endif %}
<span title="Celkem {{ paper_counts[key]|inflected('verze', 'verze', 'verzí') }}" class="icon">🗐</span> <span title="Celkem {{ paper_counts[key]|inflected('verze', 'verze', 'verzí') }}" class="icon">🗐</span>
{% endif %} {% endif %}
{% else %}–{% endif %} {% else %}–{% endif %}
<td>{% if points_form %} <td style="text-align: center;">
<input type="number" class="form-control" name="points_{{sol.user_id}}" value="{{ request_form.get("points_{}".format(sol.user_id)) or sol.points }}" size="4"> {% if sol.note %}<span class="icon" title="Poznámka pro řešitele: {{ sol.note }}">🗩</span>{% endif %}
{% if sol.org_note %} <span class="icon" title="Interní poznámka: {{ sol.org_note }}">🗩</span>{% endif %}
<td>
{% if points_form %}
<input type="number" class="form-control" name="points_{{u.user_id}}" value="{{ request_form.get("points_{}".format(u.user_id)) or sol.points }}" size="4">
{% else %} {% else %}
{% if sol.points is not none %}{{ sol.points}}{% else %}<span class="unknown">?</span>{% endif %} {% if sol.points is not none %}{{ sol.points}}{% else %}<span class="unknown">?</span>{% endif %}
{% endif %} {% endif %}
{% else %} {% else %}
<td><td><td> <td colspan="4" class="text-center">
{% if create_form %}
<input type="checkbox" name="create_sol_{{u.user_id}}" id="create_sol_{{u.user_id}}"{% if request_form.get("create_sol_{}".format(u.user_id)) %}checked{% endif %}>
<label for="create_sol_{{u.user_id}}">Založit řešení</label>
{% else %}–{% endif %}
{% endif %} {% endif %}
<td style="text-align: center;"> <td><div class="btn-group">
{% if sol and sol.note %}<span class="icon" title="Poznámka pro řešitele: {{ sol.note }}">🗩</span>{% endif %}
{% if sol and sol.org_note %} <span class="icon" title="Interní poznámka: {{ sol.org_note }}">🗩</span>{% endif %}
<td>
<a class="btn btn-xs btn-primary" href="{{ url_for('org_submit_list', contest_id=ct_id, user_id=u.user_id, task_id=task.task_id, site_id=site_id) }}">Detail</a> <a class="btn btn-xs btn-primary" href="{{ url_for('org_submit_list', contest_id=ct_id, user_id=u.user_id, task_id=task.task_id, site_id=site_id) }}">Detail</a>
</div>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
...@@ -172,6 +172,13 @@ nav#main-menu a.active { ...@@ -172,6 +172,13 @@ nav#main-menu a.active {
border-radius: 4px 4px; border-radius: 4px 4px;
} }
.checked_toggle input.toggle:checked ~ .checked_hide {
display: none;
}
.checked_toggle input.toggle:not(:checked) ~ .checked_show {
display: none;
}
/* Round states */ /* Round states */
.rstate-preparing { .rstate-preparing {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment