diff --git a/dmoj/urls.py b/dmoj/urls.py
index 91a649a..9f1832d 100644
--- a/dmoj/urls.py
+++ b/dmoj/urls.py
@@ -627,6 +627,13 @@ urlpatterns = [
"contest_user_submissions_ajax",
),
),
+ url(
+ r"^/submissions",
+ paged_list_view(
+ submission.ContestSubmissions,
+ "contest_submissions",
+ ),
+ ),
url(
r"^/participations$",
contests.ContestParticipationList.as_view(),
diff --git a/judge/views/contests.py b/judge/views/contests.py
index b578c20..1403e71 100644
--- a/judge/views/contests.py
+++ b/judge/views/contests.py
@@ -362,6 +362,19 @@ class ContestMixin(object):
return context
+ def contest_access_check(self, contest):
+ try:
+ contest.access_check(self.request.user)
+ except Contest.PrivateContest:
+ raise PrivateContestError(
+ contest.name,
+ contest.is_private,
+ contest.is_organization_private,
+ contest.organizations.all(),
+ )
+ except Contest.Inaccessible:
+ raise Http404()
+
def get_object(self, queryset=None):
contest = super(ContestMixin, self).get_object(queryset)
profile = self.request.profile
@@ -377,19 +390,9 @@ class ContestMixin(object):
if self.should_bypass_access_check(contest):
return contest
- try:
- contest.access_check(self.request.user)
- except Contest.PrivateContest:
- raise PrivateContestError(
- contest.name,
- contest.is_private,
- contest.is_organization_private,
- contest.organizations.all(),
- )
- except Contest.Inaccessible:
- raise Http404()
- else:
- return contest
+ self.contest_access_check(contest)
+
+ return contest
def dispatch(self, request, *args, **kwargs):
try:
diff --git a/judge/views/organization.py b/judge/views/organization.py
index 1ccaef2..8f4a6ce 100644
--- a/judge/views/organization.py
+++ b/judge/views/organization.py
@@ -71,7 +71,7 @@ from judge.utils.views import (
from judge.utils.problems import user_attempted_ids, user_completed_ids
from judge.views.problem import ProblemList
from judge.views.contests import ContestList
-from judge.views.submission import AllSubmissions, SubmissionsListBase
+from judge.views.submission import SubmissionsListBase
from judge.views.feed import FeedView
from judge.tasks import rescore_contest
diff --git a/judge/views/submission.py b/judge/views/submission.py
index d5eab0d..ba172c6 100644
--- a/judge/views/submission.py
+++ b/judge/views/submission.py
@@ -50,6 +50,7 @@ from judge.utils.views import DiggPaginatorMixin
from judge.utils.infinite_paginator import InfinitePaginationMixin
from judge.utils.views import TitleMixin
from judge.utils.timedelta import nice_repr
+from judge.views.contests import ContestMixin
def submission_related(queryset):
@@ -308,6 +309,9 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView):
def access_check(self, request):
pass
+ def hide_contest_in_row(self):
+ return self.request.in_contest_mode
+
@cached_property
def in_contest(self):
return (
@@ -477,6 +481,7 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView):
context["friend_submissions_link"] = self.get_friend_submissions_page()
context["all_submissions_link"] = self.get_all_submissions_page()
context["page_type"] = self.page_type
+ context["hide_contest_in_row"] = self.hide_contest_in_row()
context["in_hidden_subtasks_contest"] = self.in_hidden_subtasks_contest()
if context["in_hidden_subtasks_contest"]:
@@ -849,6 +854,38 @@ class ForceContestMixin(object):
return super(ForceContestMixin, self).get(request, *args, **kwargs)
+class ContestSubmissions(
+ LoginRequiredMixin, ContestMixin, ForceContestMixin, SubmissionsListBase
+):
+ check_contest_in_access_check = True
+ template_name = "contest/submissions.html"
+ context_object_name = "submissions"
+
+ def hide_contest_in_row(self):
+ return True
+
+ def access_check(self, request):
+ super().contest_access_check(self.contest)
+ super().access_check(request)
+
+ def get_title(self):
+ return _("Submissions in") + " " + self.contest.name
+
+ def get_content_title(self):
+ return format_html(
+ _('Submissions in {1}'),
+ reverse("contest_view", args=[self.contest.key]),
+ self.contest.name,
+ )
+
+ def get_context_data(self, **kwargs):
+ self.object = self.contest
+ context = super(ContestSubmissions, self).get_context_data(**kwargs)
+ context["contest"] = self.contest
+ context["page_type"] = "submissions"
+ return context
+
+
class UserContestSubmissions(ForceContestMixin, UserProblemSubmissions):
check_contest_in_access_check = True
diff --git a/locale/vi/LC_MESSAGES/django.po b/locale/vi/LC_MESSAGES/django.po
index 2b5085a..c81ddae 100644
--- a/locale/vi/LC_MESSAGES/django.po
+++ b/locale/vi/LC_MESSAGES/django.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: lqdoj2\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-04-27 10:48+0700\n"
+"POT-Creation-Date: 2024-04-30 09:07+0700\n"
"PO-Revision-Date: 2021-07-20 03:44\n"
"Last-Translator: Icyene\n"
"Language-Team: Vietnamese\n"
@@ -533,76 +533,76 @@ msgstr "Báo cáo lỗi"
msgid "Courses"
msgstr "Khóa học"
-#: judge/forms.py:124
+#: judge/forms.py:120
msgid "File size exceeds the maximum allowed limit of 5MB."
msgstr "File tải lên không được quá 5MB."
-#: judge/forms.py:155
+#: judge/forms.py:151
msgid "Any judge"
msgstr ""
-#: judge/forms.py:355
+#: judge/forms.py:351
msgid "Enter usernames separating by space"
msgstr "Nhập các tên đăng nhập, cách nhau bởi dấu cách"
-#: judge/forms.py:356 judge/views/stats.py:166 templates/stats/site.html:27
+#: judge/forms.py:352 judge/views/stats.py:166 templates/stats/site.html:27
msgid "New users"
msgstr "Thành viên mới"
-#: judge/forms.py:373
+#: judge/forms.py:369
#, python-brace-format
msgid "These usernames don't exist: {usernames}"
msgstr "Các tên đăng nhập này không tồn tại: {usernames}"
-#: judge/forms.py:433
+#: judge/forms.py:429
msgid "Username/Email"
msgstr "Tên đăng nhập / Email"
-#: judge/forms.py:435 judge/views/email.py:22
+#: judge/forms.py:431 judge/views/email.py:22
#: templates/registration/registration_form.html:46
#: templates/registration/registration_form.html:60
#: templates/user/edit-profile.html:115 templates/user/import/table_csv.html:5
msgid "Password"
msgstr "Mật khẩu"
-#: judge/forms.py:461
+#: judge/forms.py:457
msgid "Two Factor Authentication tokens must be 6 decimal digits."
msgstr "Two Factor Authentication phải chứa 6 chữ số."
-#: judge/forms.py:474 templates/registration/totp_auth.html:32
+#: judge/forms.py:470 templates/registration/totp_auth.html:32
msgid "Invalid Two Factor Authentication token."
msgstr "Token Two Factor Authentication không hợp lệ."
-#: judge/forms.py:481 judge/models/problem.py:133
+#: judge/forms.py:477 judge/models/problem.py:133
msgid "Problem code must be ^[a-z0-9]+$"
msgstr "Mã bài phải có dạng ^[a-z0-9]+$"
-#: judge/forms.py:488
+#: judge/forms.py:484
msgid "Problem with code already exists."
msgstr "Mã bài đã tồn tại."
-#: judge/forms.py:495 judge/models/contest.py:96
+#: judge/forms.py:491 judge/models/contest.py:96
msgid "Contest id must be ^[a-z0-9]+$"
msgstr "Mã kỳ thi phải có dạng ^[a-z0-9]+$"
-#: judge/forms.py:502 templates/contest/clone.html:47
+#: judge/forms.py:498 templates/contest/clone.html:47
#: templates/problem/search-form.html:39
msgid "Group"
msgstr "Nhóm"
-#: judge/forms.py:510
+#: judge/forms.py:506
msgid "Contest with key already exists."
msgstr "Mã kỳ thi đã tồn tại."
-#: judge/forms.py:518
+#: judge/forms.py:514
msgid "Group doesn't exist."
msgstr "Nhóm không tồn tại."
-#: judge/forms.py:520
+#: judge/forms.py:516
msgid "You don't have permission in this group."
msgstr "Bạn không có quyền trong nhóm này."
-#: judge/forms.py:570
+#: judge/forms.py:566
msgid "This problem is duplicated."
msgstr "Bài này bị lặp"
@@ -2798,17 +2798,17 @@ msgstr "Bạn phải giải ít nhất một bài trước khi được phép b
msgid "Posted comment"
msgstr "Bình luận đã đăng"
-#: judge/views/contests.py:122 judge/views/contests.py:402
-#: judge/views/contests.py:407 judge/views/contests.py:707
+#: judge/views/contests.py:122 judge/views/contests.py:405
+#: judge/views/contests.py:410 judge/views/contests.py:710
msgid "No such contest"
msgstr "Không có contest nào như vậy"
-#: judge/views/contests.py:123 judge/views/contests.py:403
+#: judge/views/contests.py:123 judge/views/contests.py:406
#, python-format
msgid "Could not find a contest with the key \"%s\"."
msgstr "Không tìm thấy kỳ thi với mã \"%s\"."
-#: judge/views/contests.py:142 judge/views/contests.py:1477
+#: judge/views/contests.py:142 judge/views/contests.py:1480
#: judge/views/stats.py:178 templates/contest/list.html:247
#: templates/contest/list.html:291 templates/contest/list.html:335
#: templates/contest/list.html:377
@@ -2817,113 +2817,113 @@ msgstr "Không tìm thấy kỳ thi với mã \"%s\"."
msgid "Contests"
msgstr "Kỳ thi"
-#: judge/views/contests.py:407
+#: judge/views/contests.py:410
msgid "Could not find such contest."
msgstr "Không tìm thấy kỳ thi nào như vậy."
-#: judge/views/contests.py:415
+#: judge/views/contests.py:418
#, python-format
msgid "Access to contest \"%s\" denied"
msgstr "Truy cập tới kỳ thi \"%s\" bị từ chối"
-#: judge/views/contests.py:493
+#: judge/views/contests.py:496
msgid "Clone Contest"
msgstr "Nhân bản kỳ thi"
-#: judge/views/contests.py:585
+#: judge/views/contests.py:588
msgid "Contest not ongoing"
msgstr "Kỳ thi đang không diễn ra"
-#: judge/views/contests.py:586
+#: judge/views/contests.py:589
#, python-format
msgid "\"%s\" is not currently ongoing."
msgstr "\"%s\" kỳ thi đang không diễn ra."
-#: judge/views/contests.py:599
+#: judge/views/contests.py:602
msgid "Banned from joining"
msgstr "Bị cấm tham gia"
-#: judge/views/contests.py:601
+#: judge/views/contests.py:604
msgid ""
"You have been declared persona non grata for this contest. You are "
"permanently barred from joining this contest."
msgstr "Bạn không được phép tham gia kỳ thi này."
-#: judge/views/contests.py:691
+#: judge/views/contests.py:694
#, python-format
msgid "Enter access code for \"%s\""
msgstr "Nhập mật khẩu truy cập cho \"%s\""
-#: judge/views/contests.py:708
+#: judge/views/contests.py:711
#, python-format
msgid "You are not in contest \"%s\"."
msgstr "Bạn không ở trong kỳ thi \"%s\"."
-#: judge/views/contests.py:731
+#: judge/views/contests.py:734
msgid "ContestCalendar requires integer year and month"
msgstr "Lịch thi yêu cầu giá trị cho năm và tháng là số nguyên"
-#: judge/views/contests.py:789
+#: judge/views/contests.py:792
#, python-format
msgid "Contests in %(month)s"
msgstr "Các kỳ thi trong %(month)s"
-#: judge/views/contests.py:790
+#: judge/views/contests.py:793
msgid "F Y"
msgstr "F Y"
-#: judge/views/contests.py:850
+#: judge/views/contests.py:853
#, python-format
msgid "%s Statistics"
msgstr "%s Thống kê"
-#: judge/views/contests.py:1158
+#: judge/views/contests.py:1161
#, python-format
msgid "%s Rankings"
msgstr "%s Bảng điểm"
-#: judge/views/contests.py:1169
+#: judge/views/contests.py:1172
msgid "???"
msgstr "???"
-#: judge/views/contests.py:1196
+#: judge/views/contests.py:1199
#, python-format
msgid "Your participation in %s"
msgstr "Lần tham gia trong %s"
-#: judge/views/contests.py:1197
+#: judge/views/contests.py:1200
#, python-format
msgid "%s's participation in %s"
msgstr "Lần tham gia của %s trong %s"
-#: judge/views/contests.py:1211
+#: judge/views/contests.py:1214
msgid "Live"
msgstr "Trực tiếp"
-#: judge/views/contests.py:1230 templates/contest/contest-tabs.html:21
+#: judge/views/contests.py:1233 templates/contest/contest-tabs.html:21
msgid "Participation"
msgstr "Lần tham gia"
-#: judge/views/contests.py:1279
+#: judge/views/contests.py:1282
#, python-format
msgid "%s MOSS Results"
msgstr "%s Kết quả MOSS"
-#: judge/views/contests.py:1315
+#: judge/views/contests.py:1318
#, python-format
msgid "Running MOSS for %s..."
msgstr "Đang chạy MOSS cho %s..."
-#: judge/views/contests.py:1338
+#: judge/views/contests.py:1341
#, python-format
msgid "Contest tag: %s"
msgstr "Nhãn kỳ thi: %s"
-#: judge/views/contests.py:1353 judge/views/ticket.py:67
+#: judge/views/contests.py:1356 judge/views/ticket.py:67
msgid "Issue description"
msgstr "Mô tả vấn đề"
-#: judge/views/contests.py:1396
+#: judge/views/contests.py:1399
#, python-format
msgid "New clarification for %s"
msgstr "Thông báo mới cho %s"
@@ -3082,11 +3082,9 @@ msgstr "%s Thành viên"
msgid "All submissions in {0}"
msgstr "Bài nộp trong {0}"
-#: judge/views/organization.py:482
-#, fuzzy
-#| msgid "Submissions"
+#: judge/views/organization.py:482 judge/views/submission.py:872
msgid "Submissions in"
-msgstr "Bài nộp"
+msgstr "Bài nộp trong"
#: judge/views/organization.py:507 judge/views/organization.py:513
#: judge/views/organization.py:520
@@ -3219,7 +3217,7 @@ msgstr "Bạn không được phép chỉnh sửa tổ chức này."
#: judge/views/organization.py:963 templates/blog/blog.html:31
#: templates/comments/content-list.html:53
#: templates/comments/content-list.html:66
-#: templates/contest/contest-tabs.html:37 templates/contest/list.html:128
+#: templates/contest/contest-tabs.html:36 templates/contest/list.html:128
#: templates/contest/tag-title.html:9 templates/flatpages/admin_link.html:3
#: templates/license.html:10 templates/problem/editorial.html:15
#: templates/problem/feed/items.html:50
@@ -3411,7 +3409,7 @@ msgstr "Đăng ký"
msgid "Authentication failure"
msgstr "Xác thực thất bại"
-#: judge/views/resolver.py:11 templates/contest/contest-tabs.html:28
+#: judge/views/resolver.py:11 templates/contest/contest-tabs.html:27
#, fuzzy
#| msgid "solve rate"
msgid "Resolver"
@@ -3421,8 +3419,9 @@ msgstr "Tỉ lệ giải đúng"
msgid "Language statistics"
msgstr "Thống kê ngôn ngữ"
-#: judge/views/stats.py:154 templates/organization/org-left-sidebar.html:6
-#: templates/stats/site.html:15 templates/user/user-tabs.html:6
+#: judge/views/stats.py:154 templates/contest/contest-tabs.html:22
+#: templates/organization/org-left-sidebar.html:6 templates/stats/site.html:15
+#: templates/user/user-tabs.html:6
msgid "Submissions"
msgstr "Bài nộp"
@@ -3451,60 +3450,65 @@ msgstr "Kết quả chấm"
msgid "Version matrix"
msgstr "Ma trận phiên bản"
-#: judge/views/submission.py:91 judge/views/submission.py:99
+#: judge/views/submission.py:99 judge/views/submission.py:107
#, python-format
msgid "Submission of %(problem)s by %(user)s"
msgstr "Bài nộp của %(user)s cho bài %(problem)s"
-#: judge/views/submission.py:277 judge/views/submission.py:278
+#: judge/views/submission.py:291 judge/views/submission.py:292
#: templates/problem/problem.html:188
msgid "All submissions"
msgstr "Tất cả bài nộp"
-#: judge/views/submission.py:548 judge/views/submission.py:553
+#: judge/views/submission.py:566 judge/views/submission.py:571
msgid "All my submissions"
msgstr "Tất cả bài nộp của tôi"
-#: judge/views/submission.py:549
+#: judge/views/submission.py:567
#, python-format
msgid "All submissions by %s"
msgstr "Tất cả bài nộp của %s"
-#: judge/views/submission.py:555
+#: judge/views/submission.py:573
#, python-brace-format
msgid "All submissions by {0}"
msgstr "Tất cả bài nộp của {0}"
-#: judge/views/submission.py:576
+#: judge/views/submission.py:594
#, fuzzy
#| msgid "All submissions"
msgid "All friend submissions"
msgstr "Tất cả bài nộp"
-#: judge/views/submission.py:605
+#: judge/views/submission.py:623
#, python-format
msgid "All submissions for %s"
msgstr "Tất cả bài nộp cho %s"
-#: judge/views/submission.py:633
+#: judge/views/submission.py:651
msgid "Must pass a problem"
msgstr "Phải làm được một bài"
-#: judge/views/submission.py:691
+#: judge/views/submission.py:709
#, python-format
msgid "My submissions for %(problem)s"
msgstr "Bài nộp của tôi cho %(problem)s"
-#: judge/views/submission.py:692
+#: judge/views/submission.py:710
#, python-format
msgid "%(user)s's submissions for %(problem)s"
msgstr "Các bài nộp của %(user)s cho %(problem)s"
-#: judge/views/submission.py:834
+#: judge/views/submission.py:852
msgid "Must pass a contest"
msgstr "Phải qua một kỳ thi"
-#: judge/views/submission.py:864
+#: judge/views/submission.py:876
+#, python-brace-format
+msgid "Submissions in {1}"
+msgstr "Bài nộp trong {1}"
+
+#: judge/views/submission.py:914
#, python-brace-format
msgid ""
"{0}'s submissions for {2} in {0} cho {2} trong {4}"
-#: judge/views/submission.py:876
+#: judge/views/submission.py:926
#, python-brace-format
msgid ""
"{0}'s submissions for problem {2} in {3}"
@@ -3522,11 +3526,9 @@ msgstr ""
"Các bài nộp của {0} cho bài {2} trong {3}"
""
-#: judge/views/submission.py:1010
-#, fuzzy
-#| msgid "You do not have the permission to rejudge submissions."
+#: judge/views/submission.py:1060
msgid "You don't have permission to access."
-msgstr "Bạn không có quyền chấm lại bài."
+msgstr "Bạn không có quyền truy cập."
#: judge/views/test_formatter/test_formatter.py:64
#: judge/views/test_formatter/test_formatter.py:107
@@ -4128,15 +4130,11 @@ msgstr "Thống kê"
msgid "Rankings"
msgstr "Bảng xếp hạng"
-#: templates/contest/contest-tabs.html:24
-msgid "Hidden Rankings"
-msgstr "Bảng xếp hạng ẩn"
-
-#: templates/contest/contest-tabs.html:31
+#: templates/contest/contest-tabs.html:30
msgid "Final rankings"
msgstr "BXH chung cuộc"
-#: templates/contest/contest-tabs.html:35
+#: templates/contest/contest-tabs.html:34
msgid "MOSS"
msgstr "MOSS"
@@ -6119,6 +6117,15 @@ msgstr "Thông tin"
msgid "Check all"
msgstr "Chọn tất cả"
+#~ msgid "Submissions in {0}"
+#~ msgstr "Bài nộp trong {0}"
+
+#~ msgid "Submissions in %s"
+#~ msgstr "Bài nộp trong %s"
+
+#~ msgid "Hidden Rankings"
+#~ msgstr "Bảng xếp hạng ẩn"
+
#, fuzzy
#~| msgid "Banned from joining"
#~ msgid "banned from voting"
diff --git a/resources/blog.scss b/resources/blog.scss
index ea3ac14..e8f626c 100644
--- a/resources/blog.scss
+++ b/resources/blog.scss
@@ -289,6 +289,8 @@
padding: 0.8em 0.2em 0.8em 0.2em;
display: inline-block;
flex: 1;
+ min-width: 5em;
+ overflow-wrap: anywhere;
.sidebar-icon {
display: none;
@@ -301,6 +303,8 @@
border-radius: 7px;
display: flex;
background: inherit;
+ gap: 0.3em;
+ overflow-x: scroll;
}
.blog-box {
@@ -363,10 +367,13 @@
max-width: 11%;
min-width: 11%;
position: fixed;
- height: 100%;
- margin-top: -4em;
- padding-top: 4em;
- border-right: 1px;
+ height: calc(100vh - $navbar_height - 20px);
+ overflow-y: auto;
+
+ &::-webkit-scrollbar {
+ width: 0;
+ background-color: transparent;
+ }
}
.feed-table {
diff --git a/templates/contest/contest-tabs.html b/templates/contest/contest-tabs.html
index 83cf03b..3d02e13 100644
--- a/templates/contest/contest-tabs.html
+++ b/templates/contest/contest-tabs.html
@@ -19,9 +19,8 @@
{{ make_tab_item('ranking', 'fa fa-bar-chart', url('contest_ranking', contest.key), _('Rankings')) }}
{% if request.user.is_authenticated and can_access %}
{{ make_tab_item('participation', 'fa fa-users', url('contest_participation_own', contest.key), _('Participation')) }}
+ {{ make_tab_item('submissions', 'fa fa-code', url('contest_submissions', contest.key), _('Submissions')) }}
{% endif %}
- {% else %}
- {{ make_tab_item('ranking', 'fa fa-bar-chart', None, _('Hidden Rankings')) }}
{% endif %}
{% endif %}
{% if request.user.is_superuser and contest_has_hidden_subtasks %}
diff --git a/templates/contest/submissions.html b/templates/contest/submissions.html
new file mode 100644
index 0000000..e4cc7e0
--- /dev/null
+++ b/templates/contest/submissions.html
@@ -0,0 +1,4 @@
+{% extends "submission/list.html" %}
+{% block left_sidebar %}
+ {% include "contest/contest-tabs.html" %}
+{% endblock %}
\ No newline at end of file
diff --git a/templates/submission/row.html b/templates/submission/row.html
index 1a354cb..4961d0d 100644
--- a/templates/submission/row.html
+++ b/templates/submission/row.html
@@ -55,7 +55,7 @@
{{ submission.language.short_display_name }}
{{ relative_time(submission.date, format=_("d/m/Y"))}}
- {% if not request.in_contest_mode and submission.contest_object_id %}
+ {% if not hide_contest_in_row and submission.contest_object_id %}