diff --git a/mo/web/org_contest.py b/mo/web/org_contest.py index 4e27f3e3a5c62d5d3f4f02092a80e8010aad68c6..98546219b4da0e50be3c43a289e41cec62b32001 100644 --- a/mo/web/org_contest.py +++ b/mo/web/org_contest.py @@ -1016,12 +1016,22 @@ def org_contest_task(contest_id: int, task_id: int, site_id: Optional[int] = Non ) +class ContestSolutionsEditForm(FlaskForm): + submit = wtforms.SubmitField("Založit označená řešení") + + @app.route('/org/contest/c/<int:id>/solutions', methods=('GET', 'POST')) @app.route('/org/contest/c/<int:id>/site/<int:site_id>/solutions', methods=('GET', 'POST')) +@app.route('/org/contest/c/<int:id>/solutions/edit', methods=('GET', 'POST'), endpoint="org_contest_solutions_edit") +@app.route('/org/contest/c/<int:id>/site/<int:site_id>/solutions/edit', methods=('GET', 'POST'), endpoint="org_contest_solutions_edit") def org_contest_solutions(id: int, site_id: Optional[int] = None): sc = get_solution_context(id, None, None, site_id) sess = db.get_session() + edit_action = request.endpoint == "org_contest_solutions_edit" + if edit_action and not sc.allow_create_solutions: + raise werkzeug.exceptions.Forbidden() + pions_subq = sess.query(db.Participation.user_id).filter_by(contest=sc.contest) if sc.site: pions_subq = pions_subq.filter_by(place=sc.site) @@ -1064,11 +1074,46 @@ def org_contest_solutions(id: int, site_id: Optional[int] = None): for s in sols: task_sols[s.task_id][s.user_id] = s + edit_form: Optional[ContestSolutionsEditForm] = None + if edit_action: + edit_form = ContestSolutionsEditForm() + if edit_form.validate_on_submit(): + new_sol_count = 0 + for task in tasks: + for pion in pions: + if pion.user_id in task_sols[task.task_id]: + continue # již existuje + if not request.form.get(f"create_sol_{task.task_id}_{pion.user_id}"): + continue # nikdo nežádá o vytvoření + + sol = db.Solution(task=task, user=pion.user) + sess.add(sol) + mo.util.log( + type=db.LogType.participant, + what=pion.user_id, + details={ + 'action': 'solution-created', + 'task': task.task_id, + }, + ) + app.logger.info(f"Řešení úlohy {task.code} od účastníka {pion.user_id} založeno") + new_sol_count += 1 + + 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_solutions', id=id, site_id=site_id)) + return render_template( 'org_contest_solutions.html', contest=sc.contest, site=sc.site, sc=sc, pions=pions, tasks=tasks, tasks_sols=task_sols, paper_counts=paper_counts, paper_link=lambda u, p: mo.web.util.org_paper_link(sc.contest, sc.site, u, p), + edit_form=edit_form, ) diff --git a/mo/web/templates/org_contest_solutions.html b/mo/web/templates/org_contest_solutions.html index dc718baef49b73b11b85b738b467e44d3b68b1e7..dcb73a6f713c7b2386521b024525a0d7ee0ba0d6 100644 --- a/mo/web/templates/org_contest_solutions.html +++ b/mo/web/templates/org_contest_solutions.html @@ -4,10 +4,10 @@ {% set site_id = site.place_id if site else None %} {% block title %} -Tabulka řešení {% if site %}soutěžního místa {{ site.name }}{% else %}oblasti {{ contest.place.name }}{% endif %} +{{ "Založení řešení" if edit_form else "Tabulka řešení" }} {% if site %}soutěžního místa {{ site.name }}{% else %}oblasti {{ contest.place.name }}{% endif %} {% endblock %} {% block breadcrumbs %} -{{ contest_breadcrumbs(round=round, contest=contest, site=site, action="Tabulka řešení") }} +{{ contest_breadcrumbs(round=round, contest=contest, site=site, action="Založení řešení" if edit_form else "Tabulka řešení") }} {% endblock %} {% block body %} @@ -20,10 +20,22 @@ Tabulka řešení {% if site %}soutěžního místa {{ site.name }}{% else %}obl {% include "parts/org_submit_warning.html" %} -<p>Všechna odevzdání od účastníka k úloze můžete vidět po kliknutí na ikonku <span class="icon">🔍</span>. +<p><i> +{% if edit_form %} +Zaškrtnutím políček u řešení, která dosud neexistují, a odesláním tlačítkem pod tabulkou tato řešení založíte. +To se hodí, pokud se nechystáte do systému nahrávat soubory řešení, ale jen chcete řešení vytvořit, aby jim +bylo možné vyplnit body. Pokud nějaké řešení založíte omylem, lze toto prázdné řešení smazat v jeho detailu. +{% else %} +Všechna odevzdání od účastníka k úloze můžete vidět po kliknutí na ikonku <span class="icon">🔍</span>. Odkazem v záhlaví se lze dostat na detailní výpis odevzdání všech uživatelů pro -konkrétní úlohu. Symbol <span class="icon">🗐</span> značí, že existuje více verzí dostupných v detailu.</p> +konkrétní úlohu. Symbol <span class="icon">🗐</span> značí, že existuje více verzí dostupných v detailu. +{% endif %} +</i></p> +{% if edit_form %} +<form class="form" method="POST"> +{{ edit_form.csrf_token }} +{% endif %} <table class="data full center"> <colgroup><col span="2"></colgroup> {% for task in tasks %} @@ -87,7 +99,13 @@ konkrétní úlohu. Symbol <span class="icon">🗐</span> značí, že existuje {% endif %} <td class="sol"> {% else %} - <td colspan=3>– + <td colspan=3> + {% if edit_form %} + <label> + <input type="checkbox" name="create_sol_{{task.task_id}}_{{u.user_id}}"> + Založit + </label> + {% else %}–{% endif %} <td> {% endif %} <a class="btn btn-xs btn-link icon" title="Detail řešení" href="{{ url_for('org_submit_list', contest_id=contest.contest_id, user_id=u.user_id, task_id=task.task_id, site_id=site_id) }}">🔍</a> @@ -108,5 +126,18 @@ konkrétní úlohu. Symbol <span class="icon">🗐</span> značí, že existuje <td> </tfoot> </table> +{% if edit_form %} + <div class='btn-group'> + {{ wtf.form_field(edit_form.submit, class="btn btn-primary") }} + <a class="btn btn-default" href="{{ url_for('org_contest_solutions', id=contest.contest_id, site_id=site_id) }}">Zrušit</a> + </div> +</form> +{% else %} +<div class='btn-group'> + {% if sc.allow_create_solutions %} + <a class="btn btn-primary" href="{{ url_for('org_contest_solutions_edit', id=contest.contest_id, site_id=site_id) }}">Založit řešení</a> + {% endif %} +</div> +{% endif %} {% endblock %}