From a63afd6f3caff81f8f56f4aa60bb8cff5fb4fb3c Mon Sep 17 00:00:00 2001 From: cuom1999 Date: Mon, 29 Apr 2024 21:08:48 -0500 Subject: [PATCH] Add contest submissions page --- dmoj/urls.py | 7 ++ judge/views/contests.py | 29 ++--- judge/views/organization.py | 2 +- judge/views/submission.py | 37 +++++++ locale/vi/LC_MESSAGES/django.po | 161 +++++++++++++++------------- resources/blog.scss | 15 ++- templates/contest/contest-tabs.html | 3 +- templates/contest/submissions.html | 4 + templates/submission/row.html | 2 +- 9 files changed, 162 insertions(+), 98 deletions(-) create mode 100644 templates/contest/submissions.html 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 %}