From 2481d477b4660ef65d28e6eaa8f3fda0395a62b3 Mon Sep 17 00:00:00 2001
From: Martin Mares <mj@ucw.cz>
Date: Mon, 11 Jan 2021 18:49:30 +0100
Subject: [PATCH] =?UTF-8?q?Z=20p=C5=99ehledu=20=C5=99e=C5=A1en=C3=AD=20?=
 =?UTF-8?q?=C3=BAlohy=20jde=20i=20odevzd=C3=A1vat?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

V tabulce už jsou všichni účastníci, i ti, kteří úlohu neodevzdali.
Opraveny kontroly práv.
---
 mo/web/org_contest.py                  | 24 ++++++++++++-----------
 mo/web/templates/org_contest_task.html | 27 ++++++++++++--------------
 2 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/mo/web/org_contest.py b/mo/web/org_contest.py
index 6ed8b346..2ded03e9 100644
--- a/mo/web/org_contest.py
+++ b/mo/web/org_contest.py
@@ -5,7 +5,7 @@ import flask_wtf.file
 import locale
 import os
 import secrets
-from sqlalchemy import func
+from sqlalchemy import func, and_
 from sqlalchemy.orm import joinedload
 from sqlalchemy.orm.query import Query
 from typing import List, Tuple, Optional, Sequence, Dict
@@ -675,17 +675,19 @@ def get_solutions_query(
         for_contest: Optional[db.Contest] = None,
         for_site: Optional[db.Place] = None) -> Query:
     sess = db.get_session()
-    pions_filter = sess.query(db.Participation.user_id)
+    query = (sess.query(db.Participation, db.Solution)
+                 .select_from(db.Participation)
+                 .outerjoin(db.Solution, and_(db.Solution.task_id == task.task_id, db.Solution.user_id == db.Participation.user_id))
+                 .options(joinedload(db.Solution.user),
+                          joinedload(db.Solution.final_submit_obj),
+                          joinedload(db.Solution.final_feedback_obj)))
+
     if for_contest:
-        pions_filter = pions_filter.filter_by(contest=for_contest)
+        query = query.filter(db.Participation.contest == for_contest)
     if for_site:
-        pions_filter = pions_filter.filter_by(place=for_site)
-
-    solutions = sess.query(db.Solution).filter_by(task=task)
-    if for_contest or for_site:
-        solutions = solutions.filter(db.Solution.user_id.in_(pions_filter))
+        query = query.filter(db.Participation.place == for_site)
 
-    return solutions
+    return query
 
 
 @app.route('/org/contest/c/<int:contest_id>/task/<int:task_id>/')
@@ -695,7 +697,7 @@ def org_contest_task_submits(contest_id: int, task_id: int, site_id: Optional[in
 
     assert sc.task is not None
     q = get_solutions_query(sc.task, for_contest=sc.contest, for_site=sc.site)
-    solutions: List[db.Solution] = q.all()
+    rows: List[Tuple[db.Participation, db.Solution]] = q.all()
 
     def paper_link(paper: db.Paper) -> str:
         return url_for('org_submit_paper',
@@ -706,7 +708,7 @@ def org_contest_task_submits(contest_id: int, task_id: int, site_id: Optional[in
 
     return render_template(
         "org_contest_task.html",
-        sc=sc, solutions=solutions,
+        sc=sc, rows=rows,
         paper_link=paper_link,
     )
 
diff --git a/mo/web/templates/org_contest_task.html b/mo/web/templates/org_contest_task.html
index c7c42c4e..c6f1286f 100644
--- a/mo/web/templates/org_contest_task.html
+++ b/mo/web/templates/org_contest_task.html
@@ -13,19 +13,12 @@
 	» {{ task.code }} {{ task.name }}
 </h2>
 
-<div class="btn-group">
-	{% if can_upload_feedback %}
-	<a class="btn btn-primary" href="{{ url_for('org_contest_task_feedback', id=contest.contest_id, task_id=task.task_id) }}">Nahrávání oprav</a>
-	{% endif %}
-	{% if can_edit_points %}
-	<a class="btn btn-primary" href="{{ url_for('org_contest_task_points', id=contest.contest_id, task_id=task.task_id) }}">Zadávání bodů</a>
-	{% endif %}
-</div>
-
 <h3>Přehled odevzdaných řešení</h3>
 
 <p><i>U každého účastníka je zobrazeno jeho poslední odevzdané řešení a přidělené body. Historii všech odevzdání, oprav a bodů
-{% if can_upload_feedback or can_edit_points %} a možnost jejich změny{% endif %} naleznete v detailu řešení.</i></p>
+naleznete v detailu řešení.
+{% if sc.allow_upload_feedback or sc.allow_edit_points %}Tamtéž můžete odevzdávat nové verze.{% endif %}
+</i></p>
 
 <table class="data full">
 	<thead>
@@ -37,10 +30,11 @@
 			<th>Akce
 		</tr>
 	</thead>
-{% for sol in solutions %}
-	{% set u = sol.user %}
+{% for pion, sol in rows %}
+	{% set u = pion.user %}
 	<tr>
 		<td><a href="{{ url_for('org_user', id=u.user_id) }}">{{ u.full_name() }}</a>
+		{% if sol %}
 		<td>{% if sol.final_submit_obj %}
 			{% set p = sol.final_submit_obj %}
 			{% set late = p.check_deadline(round) %}
@@ -51,16 +45,19 @@
 			{% if p.uploaded_by_obj != u %}
 				<a href="{{ url_for('org_user', id=p.uploaded_by) }}" title="nahrál {{ p.uploaded_by_obj.full_name() }}" ><b>🛈</b></a>
 			{% endif %}
-		{% else %}–{% endif %}
+		    {% else %}–{% endif %}
 		<td>{% if sol.final_feedback_obj %}
 			{% set p = sol.final_feedback_obj %}
 			<a href='{{ paper_link(p) }}'>
 				{{ (p.uploaded_at if p else None)|timeformat }} ({{ p.pages|inflected('strana', 'strany', 'stran') }})
 			</a>
 			<a href="{{ url_for('org_user', id=p.uploaded_by) }}" title="nahrál {{ p.uploaded_by_obj.full_name() }}" ><b>🛈</b></a>
-		{% else %}–{% endif %}
+		    {% else %}–{% endif %}
 		<td>{{ sol.points if sol.points != None else '–' }}
-		<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 řešení</a>
+		{% else %}
+		<td>–<td>–
+		{% 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>
 	</tr>
 {% endfor %}
 </table>
-- 
GitLab