Add toggle button

This commit is contained in:
cuom1999 2022-01-10 18:13:46 +07:00
parent 1f14ef7747
commit 39e3f2b1c2
15 changed files with 135 additions and 44 deletions

View file

@ -280,6 +280,7 @@ urlpatterns = [
url(r'^mailgun/mail_activate/$', mailgun.MailgunActivationView.as_view(), name='mailgun_activate'), url(r'^mailgun/mail_activate/$', mailgun.MailgunActivationView.as_view(), name='mailgun_activate'),
url(r'^widgets/', include([ url(r'^widgets/', include([
url(r'^contest_mode$', contests.update_contest_mode, name='contest_mode_ajax'),
url(r'^rejudge$', widgets.rejudge_submission, name='submission_rejudge'), url(r'^rejudge$', widgets.rejudge_submission, name='submission_rejudge'),
url(r'^single_submission$', submission.single_submission_query, name='submission_single_query'), url(r'^single_submission$', submission.single_submission_query, name='submission_single_query'),
url(r'^submission_testcases$', submission.SubmissionTestCaseQuery.as_view(), name='submission_testcases_query'), url(r'^submission_testcases$', submission.SubmissionTestCaseQuery.as_view(), name='submission_testcases_query'),

View file

@ -57,7 +57,9 @@ class ContestMiddleware(object):
profile.update_contest() profile.update_contest()
request.participation = profile.current_contest request.participation = profile.current_contest
request.in_contest = request.participation is not None request.in_contest = request.participation is not None
request.contest_mode = request.session.get('contest_mode', True)
else: else:
request.in_contest = False request.in_contest = False
request.participation = None request.participation = None
request.in_contest_mode = request.in_contest and request.contest_mode
return self.get_response(request) return self.get_response(request)

View file

@ -15,7 +15,7 @@ from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.db import IntegrityError from django.db import IntegrityError
from django.db.models import Case, Count, F, FloatField, IntegerField, Max, Min, Q, Sum, Value, When from django.db.models import Case, Count, F, FloatField, IntegerField, Max, Min, Q, Sum, Value, When
from django.db.models.expressions import CombinedExpression from django.db.models.expressions import CombinedExpression
from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect, JsonResponse from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect, JsonResponse, HttpResponseNotAllowed
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
from django.template.defaultfilters import date as date_filter from django.template.defaultfilters import date as date_filter
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
@ -46,7 +46,7 @@ from judge.widgets import HeavyPreviewPageDownWidget
__all__ = ['ContestList', 'ContestDetail', 'ContestRanking', 'ContestJoin', 'ContestLeave', 'ContestCalendar', __all__ = ['ContestList', 'ContestDetail', 'ContestRanking', 'ContestJoin', 'ContestLeave', 'ContestCalendar',
'ContestClone', 'ContestStats', 'ContestMossView', 'ContestMossDelete', 'contest_ranking_ajax', 'ContestClone', 'ContestStats', 'ContestMossView', 'ContestMossDelete', 'contest_ranking_ajax',
'ContestParticipationList', 'ContestParticipationDisqualify', 'get_contest_ranking_list', 'ContestParticipationList', 'ContestParticipationDisqualify', 'get_contest_ranking_list',
'base_contest_ranking_list', 'ContestClarificationView'] 'base_contest_ranking_list', 'ContestClarificationView', 'update_contest_mode']
def _find_contest(request, key, private_check=True): def _find_contest(request, key, private_check=True):
@ -428,6 +428,7 @@ class ContestLeave(LoginRequiredMixin, ContestMixin, BaseDetailView):
_('You are not in contest "%s".') % contest.key, 404) _('You are not in contest "%s".') % contest.key, 404)
profile.remove_contest() profile.remove_contest()
request.session['contest_mode'] = True # reset contest_mode
return HttpResponseRedirect(reverse('contest_view', args=(contest.key,))) return HttpResponseRedirect(reverse('contest_view', args=(contest.key,)))
@ -953,3 +954,12 @@ class ContestClarificationAjax(ContestMixin, DetailView):
cla['order'] = self.object.get_label_for_problem(problems.index(cla['problem'])) cla['order'] = self.object.get_label_for_problem(problems.index(cla['problem']))
return JsonResponse(queryset, safe=False, json_dumps_params={'ensure_ascii': False}) return JsonResponse(queryset, safe=False, json_dumps_params={'ensure_ascii': False})
def update_contest_mode(request):
if not request.is_ajax() or not request.method=='POST':
return HttpResponseNotAllowed(['POST'])
old_mode = request.session.get('contest_mode', True)
request.session['contest_mode'] = not old_mode
return HttpResponse()

View file

@ -71,7 +71,8 @@ class ProblemMixin(object):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
try: try:
return super(ProblemMixin, self).get(request, *args, **kwargs) return super(ProblemMixin, self).get(request, *args, **kwargs)
except Http404: except Http404 as e:
print(e)
return self.no_such_problem() return self.no_such_problem()
@ -90,7 +91,8 @@ class SolvedProblemMixin(object):
@cached_property @cached_property
def in_contest(self): def in_contest(self):
return self.profile is not None and self.profile.current_contest is not None return self.profile is not None and self.profile.current_contest is not None \
and self.request.in_contest_mode
@cached_property @cached_property
def contest(self): def contest(self):
@ -120,10 +122,9 @@ class ProblemSolution(SolvedProblemMixin, ProblemMixin, TitleMixin, CommentedDet
solution = get_object_or_404(Solution, problem=self.object) solution = get_object_or_404(Solution, problem=self.object)
if (not solution.is_public or solution.publish_on > timezone.now()) and \ if (not solution.is_public or solution.publish_on > timezone.now()) and \
not self.request.user.has_perm('judge.see_private_solution') or \ not self.request.user.has_perm('judge.see_private_solution'):
(self.request.user.is_authenticated and
self.request.profile.current_contest):
raise Http404() raise Http404()
context['solution'] = solution context['solution'] = solution
context['has_solved_problem'] = self.object.id in self.get_completed_problems() context['has_solved_problem'] = self.object.id in self.get_completed_problems()
return context return context

View file

@ -262,7 +262,8 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView):
@cached_property @cached_property
def in_contest(self): def in_contest(self):
return self.request.user.is_authenticated and self.request.profile.current_contest is not None return self.request.user.is_authenticated and self.request.profile.current_contest is not None \
and self.request.in_contest_mode
@cached_property @cached_property
def contest(self): def contest(self):

View file

@ -92,7 +92,8 @@ class UserPage(TitleMixin, UserMixin, DetailView):
@cached_property @cached_property
def in_contest(self): def in_contest(self):
return self.profile is not None and self.profile.current_contest is not None return self.profile is not None and self.profile.current_contest is not None \
and self.request.in_contest_mode
def get_completed_problems(self): def get_completed_problems(self):
if self.in_contest: if self.in_contest:
@ -374,8 +375,8 @@ class FixedContestRanking(ContestRanking):
def users(request): def users(request):
if request.user.is_authenticated: if request.user.is_authenticated:
if request.in_contest_mode:
participation = request.profile.current_contest participation = request.profile.current_contest
if participation is not None:
contest = participation.contest contest = participation.contest
return FixedContestRanking.as_view(contest=contest)(request, contest=contest.key) return FixedContestRanking.as_view(contest=contest)(request, contest=contest.key)
return user_list_view(request) return user_list_view(request)

View file

@ -485,12 +485,8 @@ noscript #noscript {
#contest-info { #contest-info {
font-size: 1.25em; font-size: 1.25em;
border: 5px solid $highlight_blue; border: 5px solid $highlight_blue;
border-left: 5px dotted white;
border-radius: 0 $widget_border_radius $widget_border_radius 0; border-radius: 0 $widget_border_radius $widget_border_radius 0;
background: rgba(0, 0, 0, 0.77);
z-index: 100000; z-index: 100000;
padding: 10px 12px;
color: white;
cursor: move; cursor: move;
position: fixed; position: fixed;
left: 20px; left: 20px;
@ -506,6 +502,34 @@ noscript #noscript {
} }
} }
#contest-info-main {
border-left: 5px dotted white;
background: rgba(0, 0, 0, 0.77);
padding: 10px 12px;
color: white;
display: inline;
}
#contest-info-toggle {
display: inline;
padding: 10px 12px;
border-radius: 0 10px 10px 0;
cursor: pointer;
}
.contest-info-toggle-mode-on {
background: rgba(0, 205, 0, 0.57);
}
.contest-info-toggle-mode-on:hover {
background: rgba(0, 205, 0, 0.97);
}
.contest-info-toggle-mode-off {
background: rgba(255, 0, 0, 0.57);
}
.contest-info-toggle-mode-off:hover {
background: rgba(255, 0, 0, 0.97);
}
#contest-time-remaining { #contest-time-remaining {
display: inline-block; display: inline-block;
} }

View file

@ -117,6 +117,12 @@
$("#contest-info").show(); $("#contest-info").show();
$("#contest-info-toggle").on('click', function() {
$.post("{{url('contest_mode_ajax')}}", function() {
window.location.reload();
})
});
$(document).mousemove(function (e) { $(document).mousemove(function (e) {
x_pos = e.screenX; x_pos = e.screenX;
y_pos = e.screenY; y_pos = e.screenY;
@ -190,6 +196,42 @@
</style> </style>
</noscript> </noscript>
<style> <style>
#contest-info {
font-size: 1.25em;
border: 5px solid $highlight_blue;
border-radius: 0 $widget_border_radius $widget_border_radius 0;
z-index: 100000;
cursor: move;
position: fixed;
left: 20px;
top: 90%;
display: none;
}
#contest-info-main {
border-left: 5px dotted white;
background: rgba(0, 0, 0, 0.77);
padding: 10px 12px;
color: white;
display: inline;
}
#contest-info-toggle {
display: inline;
padding: 10px 12px;
border-radius: 0 10px 10px 0;
cursor: pointer;
}
.contest-info-toggle-mode-on {
background: rgba(0, 205, 0, 0.57);
}
.contest-info-toggle-mode-on:hover {
background: rgba(0, 205, 0, 0.97);
}
.contest-info-toggle-mode-off {
background: rgba(255, 0, 0, 0.57);
}
.contest-info-toggle-mode-off:hover {
background: rgba(255, 0, 0, 0.97);
}
</style> </style>
</head> </head>
<body> <body>
@ -284,7 +326,8 @@
</nav> </nav>
{% if request.in_contest %} {% if request.in_contest %}
<div id="contest-info"> <div id="contest-info">
<a href="{{ url('contest_view', request.participation.contest.key) }}" style="vertical-align: middle"> <div id="contest-info-main">
<a href="{{ url('contest_view', request.participation.contest.key) }}" style="vertical-align: middle; display: inline">
{{ request.participation.contest.name }} - {{ request.participation.contest.name }} -
{% if request.participation.spectate %} {% if request.participation.spectate %}
{{ _('spectating') }} {{ _('spectating') }}
@ -297,6 +340,14 @@
{% endif %} {% endif %}
</a> </a>
</div> </div>
<div id="contest-info-toggle" class="{{'contest-info-toggle-mode-on' if request.contest_mode else 'contest-info-toggle-mode-off'}}">
{% if request.contest_mode %}
<i class="fa fa-toggle-on" style="color: white"></i> {{_('Compete')}}
{% else %}
<i class="fa fa-toggle-off" style="color: white"></i> {{_('General')}}
{% endif %}
</div>
</div>
{% endif %} {% endif %}
<div id="page-container"> <div id="page-container">
<noscript> <noscript>

View file

@ -110,7 +110,7 @@
</div> </div>
<div class="blog-sidebar"> <div class="blog-sidebar">
{% if request.in_contest and request.participation.contest.use_clarifications %} {% if request.in_contest_mode and request.participation.contest.use_clarifications %}
<div class="blog-sidebox sidebox"> <div class="blog-sidebox sidebox">
<h3>{{ _('Clarifications') }} <h3>{{ _('Clarifications') }}
<i class="fa fa-question-circle"></i> <i class="fa fa-question-circle"></i>

View file

@ -9,7 +9,7 @@
} }
</style> </style>
</noscript> </noscript>
{% if not request.in_contest %} {% if not request.in_contest_mode %}
<style> <style>
#search-org { #search-org {
width: 100%; width: 100%;
@ -131,7 +131,7 @@
}); });
</script> </script>
{% endcompress %} {% endcompress %}
{% if request.in_contest %} {% if request.in_contest_mode %}
{% compress js %} {% compress js %}
<script src="{{ static('libs/tablesorter.js') }}" type="text/javascript"></script> <script src="{{ static('libs/tablesorter.js') }}" type="text/javascript"></script>
<script type="text/javascript"> <script type="text/javascript">
@ -184,7 +184,7 @@
<div id="common-content"> <div id="common-content">
{% block before_table %}{% endblock %} {% block before_table %}{% endblock %}
{% if not request.in_contest %} {% if not request.in_contest_mode %}
<div id="content-right" class="problems"> <div id="content-right" class="problems">
<div class="info-float"> <div class="info-float">
{% include "problem/search-form.html" %} {% include "problem/search-form.html" %}
@ -207,7 +207,7 @@
<table id="problem-table" class="table striped"> <table id="problem-table" class="table striped">
<thead> <thead>
<tr> <tr>
{% if request.in_contest %} {% if request.in_contest_mode %}
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
<th class="solved"><i class="fa fa-check"></i></th> <th class="solved"><i class="fa fa-check"></i></th>
{% endif %} {% endif %}
@ -268,7 +268,7 @@
{% if problem.id in completed_problem_ids %} {% if problem.id in completed_problem_ids %}
<td solved="1"> <td solved="1">
<a href="{{ url('user_submissions', problem.code, request.user.username) }}"> <a href="{{ url('user_submissions', problem.code, request.user.username) }}">
{% if problem.is_public or request.in_contest %} {% if problem.is_public or request.in_contest_mode %}
<i class="solved-problem-color fa fa-check-circle"></i> <i class="solved-problem-color fa fa-check-circle"></i>
{% else %} {% else %}
<i class="solved-problem-color fa fa-lock"></i> <i class="solved-problem-color fa fa-lock"></i>
@ -278,7 +278,7 @@
{% elif problem.id in attempted_problems %} {% elif problem.id in attempted_problems %}
<td solved="0"> <td solved="0">
<a href="{{ url('user_submissions', problem.code, request.user.username) }}"> <a href="{{ url('user_submissions', problem.code, request.user.username) }}">
{% if problem.is_public or request.in_contest %} {% if problem.is_public or request.in_contest_mode %}
<i class="attempted-problem-color fa fa-minus-circle"></i> <i class="attempted-problem-color fa fa-minus-circle"></i>
{% else %} {% else %}
<i class="attempted-problem-color fa fa-lock"></i> <i class="attempted-problem-color fa fa-lock"></i>
@ -287,7 +287,7 @@
</td> </td>
{% else %} {% else %}
<td solved="-1"> <td solved="-1">
{% if problem.is_public or request.in_contest %} {% if problem.is_public or request.in_contest_mode %}
<i class="unsolved-problem-color fa fa-minus-circle"></i> <i class="unsolved-problem-color fa fa-minus-circle"></i>
{% else %} {% else %}
<i class="unsolved-problem-color fa fa-lock"></i> <i class="unsolved-problem-color fa fa-lock"></i>
@ -312,12 +312,12 @@
</td> </td>
{% endif %} {% endif %}
<td class="p">{{ problem.points|floatformat }}{% if problem.partial %}p{% endif %}</td> <td class="p">{{ problem.points|floatformat }}{% if problem.partial %}p{% endif %}</td>
{% if not request.in_contest %} {% if not request.in_contest_mode %}
<td class="ac-rate">{{ problem.ac_rate|floatformat(1) }}%</td> <td class="ac-rate">{{ problem.ac_rate|floatformat(1) }}%</td>
{% endif %} {% endif %}
<td class="users"> <td class="users">
<a href="{{ url('ranked_submissions', problem.code) }}"> <a href="{{ url('ranked_submissions', problem.code) }}">
{% if not request.in_contest or not hide_contest_scoreboard %} {% if not request.in_contest_mode or not hide_contest_scoreboard %}
{{ problem.user_count }} {{ problem.user_count }}
{% else %} {% else %}
??? ???
@ -335,7 +335,7 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% if request.in_contest and request.participation.contest.use_clarifications %} {% if request.in_contest_mode and request.participation.contest.use_clarifications %}
<br><br> <br><br>
{% if can_edit_contest %} {% if can_edit_contest %}
<div style="float: right; font-size: 1.2em"> <div style="float: right; font-size: 1.2em">

View file

@ -58,7 +58,7 @@
{% endblock %} {% endblock %}
{% block content_js_media %} {% block content_js_media %}
{% if request.in_contest %} {% if request.in_contest_mode %}
<script type="text/javascript"> <script type="text/javascript">
window.register_contest_notification("{{url('contest_clarification_ajax', request.participation.contest.key)}}"); window.register_contest_notification("{{url('contest_clarification_ajax', request.participation.contest.key)}}");
</script> </script>
@ -88,7 +88,7 @@
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
{% if problem.id in completed_problem_ids %} {% if problem.id in completed_problem_ids %}
<a href="{{ url('user_submissions', problem.code, request.user.username) }}"> <a href="{{ url('user_submissions', problem.code, request.user.username) }}">
{% if problem.is_public or request.in_contest %} {% if problem.is_public or request.in_contest_mode %}
<i class="solved-problem-color title-state fa fa-check-circle"></i> <i class="solved-problem-color title-state fa fa-check-circle"></i>
{% else %} {% else %}
<i class="solved-problem-color title-state fa fa-lock"></i> <i class="solved-problem-color title-state fa fa-lock"></i>
@ -96,7 +96,7 @@
</a> </a>
{% elif problem.id in attempted_problems %} {% elif problem.id in attempted_problems %}
<a href="{{ url('user_submissions', problem.code, request.user.username) }}"> <a href="{{ url('user_submissions', problem.code, request.user.username) }}">
{% if problem.is_public or request.in_contest %} {% if problem.is_public or request.in_contest_mode %}
<i class="attempted-problem-color title-state fa fa-minus-circle"></i> <i class="attempted-problem-color title-state fa fa-minus-circle"></i>
{% else %} {% else %}
<i class="attempted-problem-color title-state fa fa-lock"></i> <i class="attempted-problem-color title-state fa fa-lock"></i>
@ -133,7 +133,7 @@
{% endblock %} {% endblock %}
{% block info_float %} {% block info_float %}
{% if request.user.is_authenticated and request.in_contest and submission_limit %} {% if request.user.is_authenticated and request.in_contest_mode and submission_limit %}
{% if submissions_left > 0 %} {% if submissions_left > 0 %}
<a href="{{ url('problem_submit', problem.code) }}" class="unselectable button full"> <a href="{{ url('problem_submit', problem.code) }}" class="unselectable button full">
{{ _('Submit solution') }} {{ _('Submit solution') }}

View file

@ -1,4 +1,4 @@
{% if request.in_contest and request.participation.contest.logo_override_image %} {% if request.in_contest_mode and request.participation.contest.logo_override_image %}
<img src="{{ request.participation.contest.logo_override_image|camo }}" alt="{{ SITE_NAME }}" height="44" style="border: none"> <img src="{{ request.participation.contest.logo_override_image|camo }}" alt="{{ SITE_NAME }}" height="44" style="border: none">
{% elif logo_override_image is defined and logo_override_image %} {% elif logo_override_image is defined and logo_override_image %}
<img src="{{ logo_override_image|camo }}" alt="{{ SITE_NAME }}" height="44" style="border: none"> <img src="{{ logo_override_image|camo }}" alt="{{ SITE_NAME }}" height="44" style="border: none">

View file

@ -2,7 +2,7 @@
{% block js_media %} {% block js_media %}
<script type="text/javascript"> <script type="text/javascript">
{% if dynamic_update and last_msg %} {% if dynamic_update and last_msg %}
{% if request.in_contest %} {% if request.in_contest_mode %}
window.current_contest = '{{request.participation.contest.key}}'; window.current_contest = '{{request.participation.contest.key}}';
{% else %} {% else %}
window.current_contest = null; window.current_contest = null;

View file

@ -24,7 +24,7 @@
<div> <div>
{{ link_user(submission.user) }} {{ link_user(submission.user) }}
<span class="time">{{ relative_time(submission.date) }}</span> <span class="time">{{ relative_time(submission.date) }}</span>
{% if not request.in_contest and submission.contest_object_id %} {% if not request.in_contest_mode and submission.contest_object_id %}
<a href="{{ url('contest_view', submission.contest_object.key) }}" <a href="{{ url('contest_view', submission.contest_object.key) }}"
class="submission-contest"> class="submission-contest">
<i title="{{ submission.contest_object.name }}" class="fa fa-dot-circle-o"></i> <i title="{{ submission.contest_object.name }}" class="fa fa-dot-circle-o"></i>

View file

@ -32,7 +32,7 @@
<tr id="overall-row" class="case-row overall-result-{{submission.result}}"> <tr id="overall-row" class="case-row overall-result-{{submission.result}}">
<td><span class="col-title">{{_('Overall: ')}}</span> <td><span class="col-title">{{_('Overall: ')}}</span>
{% if request.in_contest and submission.contest_or_none %} {% if request.in_contest_mode and submission.contest_or_none %}
{% with contest=submission.contest_or_none %} {% with contest=submission.contest_or_none %}
({{ _('%(points)s/%(total)s points', points=contest.points|roundfloat(3), ({{ _('%(points)s/%(total)s points', points=contest.points|roundfloat(3),
total=contest.problem.points|floatformat(-1)) }}) total=contest.problem.points|floatformat(-1)) }})