From d8c05da06b1ecd5a029e3cea267c3cec857e15f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=A0=D1=83?= =?UTF-8?q?=D0=B1=D1=86=D0=BE=D0=B2?= Date: Mon, 31 Mar 2025 13:18:39 +0300 Subject: [PATCH 1/6] feat: split task status to separate template --- webapp/templates/student/task.jinja | 45 ++-------------------- webapp/templates/student/task_status.jinja | 42 ++++++++++++++++++++ 2 files changed, 45 insertions(+), 42 deletions(-) create mode 100644 webapp/templates/student/task_status.jinja diff --git a/webapp/templates/student/task.jinja b/webapp/templates/student/task.jinja index faef0645..f6038819 100644 --- a/webapp/templates/student/task.jinja +++ b/webapp/templates/student/task.jinja @@ -28,48 +28,9 @@ status.external.group_title }} -
-
- Состояние задачи -
-
- В данной секции Вы можете отслеживать состояние задания после отправки решения. -
- {% if status.status == 4 %} - {% else %} -
- {{ status.name }} -
- {% if status.error_message is not none and status.error_message and (not registration or student) %} -
Подробные сведения об ошибке:
-
{{ status.error_message | e }}
- {% else %} -
- {% endif %} - {% endif %} -
-{% if status.show_achievements %} -
-
- Разблокированные достижения - - {{ status.earned }} из {{ status.achievements | length }} - -
-
- Сможете ли Вы решить задачу всеми способами, известными искусственной нейронной сети? -
- {% if status.achievements %} - {% for dto in status.achievements %} -
-
{{ dto.title }} {{ '✓' if dto.active else '' }}
- {{ dto.description }} -
- {% endfor %} - {% endif %} -
-{% endif %} + +{% include 'student/task_status.jinja' %} +
Добавить новый ответ
diff --git a/webapp/templates/student/task_status.jinja b/webapp/templates/student/task_status.jinja new file mode 100644 index 00000000..7f9d0057 --- /dev/null +++ b/webapp/templates/student/task_status.jinja @@ -0,0 +1,42 @@ +
+
+ Состояние задачи +
+
+ В данной секции Вы можете отслеживать состояние задания после отправки решения. +
+ {% if status.status == 4 %} + {% else %} +
+ {{ status.name }} +
+ {% if status.error_message is not none and status.error_message and (not registration or student) %} +
Подробные сведения об ошибке:
+
{{ status.error_message | e }}
+ {% else %} +
+ {% endif %} + {% endif %} +
+{% if status.show_achievements %} +
+
+ Разблокированные достижения + + {{ status.earned }} из {{ status.achievements | length }} + +
+
+ Сможете ли Вы решить задачу всеми способами, известными искусственной нейронной сети? +
+ {% if status.achievements %} + {% for dto in status.achievements %} +
+
{{ dto.title }} {{ '✓' if dto.active else '' }}
+ {{ dto.description }} +
+ {% endfor %} + {% endif %} +
+{% endif %} From 591e21829347d9474df13116ed694a6892f9c891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=A0=D1=83?= =?UTF-8?q?=D0=B1=D1=86=D0=BE=D0=B2?= Date: Mon, 31 Mar 2025 17:22:46 +0300 Subject: [PATCH 2/6] feat: move task status to a div --- webapp/templates/student/task.jinja | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webapp/templates/student/task.jinja b/webapp/templates/student/task.jinja index f6038819..3041c247 100644 --- a/webapp/templates/student/task.jinja +++ b/webapp/templates/student/task.jinja @@ -29,7 +29,9 @@
+
{% include 'student/task_status.jinja' %} +
From bc6257a94c194bfdedb9129046c52ee61c43b4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=A0=D1=83?= =?UTF-8?q?=D0=B1=D1=86=D0=BE=D0=B2?= Date: Mon, 31 Mar 2025 17:24:14 +0300 Subject: [PATCH 3/6] feat: redirect successful task submission back to task page --- webapp/views/student.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/webapp/views/student.py b/webapp/views/student.py index 8f4f8087..c97e1e86 100644 --- a/webapp/views/student.py +++ b/webapp/views/student.py @@ -232,14 +232,7 @@ def submit_task(student: Student | None, gid: int, vid: int, tid: int): session_id = request.cookies.get("anonymous_identifier") db.messages.submit_task(tid, vid, gid, form.code.data, ip, sid, session_id) db.statuses.submit_task(tid, vid, gid, form.code.data, ip) - return render_template( - "student/success.jinja", - status=status, - registration=config.config.registration, - group_rating=config.config.groups, - exam=config.config.exam, - student=student, - ) + return redirect(f"/group/{gid}/variant/{vid}/task/{tid}") return render_template( "student/task.jinja", highlight=config.config.highlight_syntax, From d0a77cc5f194e4cf62b067b920ae837b0fe823eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=A0=D1=83?= =?UTF-8?q?=D0=B1=D1=86=D0=BE=D0=B2?= Date: Mon, 31 Mar 2025 17:24:48 +0300 Subject: [PATCH 4/6] feat: add endpoint with task status --- webapp/views/student.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/webapp/views/student.py b/webapp/views/student.py index c97e1e86..b1a08701 100644 --- a/webapp/views/student.py +++ b/webapp/views/student.py @@ -14,7 +14,7 @@ from webapp.forms import StudentChangePasswordForm, StudentLoginForm, StudentMessageForm, StudentRegisterForm from webapp.managers import AppConfigManager, GroupManager, HomeManager, StatusManager, StudentManager -from webapp.models import Student +from webapp.models import Status, Student from webapp.repositories import AppDatabase from webapp.utils import authorize, get_exception_info, get_greeting_msg, get_real_ip, logout @@ -245,6 +245,25 @@ def submit_task(student: Student | None, gid: int, vid: int, tid: int): ) +@blueprint.route('/group//variant//task//status', methods=["GET"]) +@authorize(db.students) +def task_status(student: Student | None, gid: int, vid: int, tid: int): + if config.config.registration and not student: + return redirect("/login") + if student and not student.teacher and student.group != gid: + return redirect("/") + status = statuses.get_task_status(gid, vid, tid) + if status.status not in [Status.Submitted, Status.CheckedSubmitted]: + return render_template( + "student/task_status.jinja", + registration=config.config.registration, + status=status, + student=student, + ) + else: + return ('', 418) + + @blueprint.route("/files/task//group/", methods=["GET"]) @authorize(db.students) def files(student: Student | None, tid: int, gid: int): From 3a2e292f38e14c4c1382c94380b7e83350bad345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=A0=D1=83?= =?UTF-8?q?=D0=B1=D1=86=D0=BE=D0=B2?= Date: Mon, 31 Mar 2025 17:37:23 +0300 Subject: [PATCH 5/6] feat: add live updating of task status --- webapp/static/js/autoreload.js | 13 +++++++++++++ webapp/templates/student/task.jinja | 3 +++ 2 files changed, 16 insertions(+) create mode 100644 webapp/static/js/autoreload.js diff --git a/webapp/static/js/autoreload.js b/webapp/static/js/autoreload.js new file mode 100644 index 00000000..70d4ca1d --- /dev/null +++ b/webapp/static/js/autoreload.js @@ -0,0 +1,13 @@ +let statusPath = window.location.href + "/status"; +let f = () => fetch(statusPath).then(res => { + if(res.status == 418) { + return new Promise(r => setTimeout(r, 2000)).then(f) + } + if(!res.ok) { + return + } + return res.text().then(b => { + document.getElementById("task-status").innerHTML = b; + }) +}); +f() diff --git a/webapp/templates/student/task.jinja b/webapp/templates/student/task.jinja index 3041c247..91a80d7b 100644 --- a/webapp/templates/student/task.jinja +++ b/webapp/templates/student/task.jinja @@ -29,6 +29,9 @@
+{% if status.status == 0 or status.status == 5 %} + +{% endif %}
{% include 'student/task_status.jinja' %}
From 954de4ccfbc4d05c2275d57e69a33d9a091468ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B9=20=D0=A0=D1=83?= =?UTF-8?q?=D0=B1=D1=86=D0=BE=D0=B2?= Date: Tue, 29 Apr 2025 10:09:08 +0300 Subject: [PATCH 6/6] chore: add is_submitted property to TaskStatusDto --- webapp/dto.py | 10 ++++++++++ webapp/templates/student/task.jinja | 2 +- webapp/views/student.py | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/webapp/dto.py b/webapp/dto.py index 80fae584..b55a12b8 100644 --- a/webapp/dto.py +++ b/webapp/dto.py @@ -170,6 +170,16 @@ def show_achievements(self) -> bool: Status.CheckedFailed: True, }) + @property + def is_submitted(self) -> bool: + if self.status in [Status.Submitted, Status.CheckedSubmitted]: + return True + if self.status in [Status.Checked, Status.Failed, Status.NotSubmitted, Status.CheckedFailed]: + return False + else: + assert False, "unhandled status" + return False + def map_achievements(self, status: TaskStatus | None, achievements: list[int]): dtos = [] for order, count in enumerate(achievements): diff --git a/webapp/templates/student/task.jinja b/webapp/templates/student/task.jinja index 91a80d7b..a575eb6e 100644 --- a/webapp/templates/student/task.jinja +++ b/webapp/templates/student/task.jinja @@ -29,7 +29,7 @@ -{% if status.status == 0 or status.status == 5 %} +{% if status.is_submitted %} {% endif %}
diff --git a/webapp/views/student.py b/webapp/views/student.py index b1a08701..1f99b3ad 100644 --- a/webapp/views/student.py +++ b/webapp/views/student.py @@ -253,7 +253,7 @@ def task_status(student: Student | None, gid: int, vid: int, tid: int): if student and not student.teacher and student.group != gid: return redirect("/") status = statuses.get_task_status(gid, vid, tid) - if status.status not in [Status.Submitted, Status.CheckedSubmitted]: + if not status.is_submitted: return render_template( "student/task_status.jinja", registration=config.config.registration,