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'^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'^single_submission$', submission.single_submission_query, name='submission_single_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()
request.participation = profile.current_contest
request.in_contest = request.participation is not None
request.contest_mode = request.session.get('contest_mode', True)
else:
request.in_contest = False
request.participation = None
request.in_contest_mode = request.in_contest and request.contest_mode
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.models import Case, Count, F, FloatField, IntegerField, Max, Min, Q, Sum, Value, When
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.template.defaultfilters import date as date_filter
from django.urls import reverse, reverse_lazy
@ -46,7 +46,7 @@ from judge.widgets import HeavyPreviewPageDownWidget
__all__ = ['ContestList', 'ContestDetail', 'ContestRanking', 'ContestJoin', 'ContestLeave', 'ContestCalendar',
'ContestClone', 'ContestStats', 'ContestMossView', 'ContestMossDelete', 'contest_ranking_ajax',
'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):
@ -428,6 +428,7 @@ class ContestLeave(LoginRequiredMixin, ContestMixin, BaseDetailView):
_('You are not in contest "%s".') % contest.key, 404)
profile.remove_contest()
request.session['contest_mode'] = True # reset contest_mode
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']))
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):
try:
return super(ProblemMixin, self).get(request, *args, **kwargs)
except Http404:
except Http404 as e:
print(e)
return self.no_such_problem()
@ -90,7 +91,8 @@ class SolvedProblemMixin(object):
@cached_property
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
def contest(self):
@ -120,10 +122,9 @@ class ProblemSolution(SolvedProblemMixin, ProblemMixin, TitleMixin, CommentedDet
solution = get_object_or_404(Solution, problem=self.object)
if (not solution.is_public or solution.publish_on > timezone.now()) and \
not self.request.user.has_perm('judge.see_private_solution') or \
(self.request.user.is_authenticated and
self.request.profile.current_contest):
not self.request.user.has_perm('judge.see_private_solution'):
raise Http404()
context['solution'] = solution
context['has_solved_problem'] = self.object.id in self.get_completed_problems()
return context

View file

@ -262,7 +262,8 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView):
@cached_property
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
def contest(self):

View file

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

View file

@ -485,12 +485,8 @@ noscript #noscript {
#contest-info {
font-size: 1.25em;
border: 5px solid $highlight_blue;
border-left: 5px dotted white;
border-radius: 0 $widget_border_radius $widget_border_radius 0;
background: rgba(0, 0, 0, 0.77);
z-index: 100000;
padding: 10px 12px;
color: white;
cursor: move;
position: fixed;
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 {
display: inline-block;
}

View file

@ -117,6 +117,12 @@
$("#contest-info").show();
$("#contest-info-toggle").on('click', function() {
$.post("{{url('contest_mode_ajax')}}", function() {
window.location.reload();
})
});
$(document).mousemove(function (e) {
x_pos = e.screenX;
y_pos = e.screenY;
@ -190,6 +196,42 @@
</style>
</noscript>
<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>
</head>
<body>
@ -284,18 +326,27 @@
</nav>
{% if request.in_contest %}
<div id="contest-info">
<a href="{{ url('contest_view', request.participation.contest.key) }}" style="vertical-align: middle">
{{ request.participation.contest.name }} -
{% if request.participation.spectate %}
{{ _('spectating') }}
{% elif request.participation.end_time %}
<div id="contest-time-remaining" data-secs="{{request.participation.end_time}}">
{{ request.participation.time_remaining|timedelta("localized") }}
</div>
<div id="contest-info-main">
<a href="{{ url('contest_view', request.participation.contest.key) }}" style="vertical-align: middle; display: inline">
{{ request.participation.contest.name }} -
{% if request.participation.spectate %}
{{ _('spectating') }}
{% elif request.participation.end_time %}
<div id="contest-time-remaining" data-secs="{{request.participation.end_time}}">
{{ request.participation.time_remaining|timedelta("localized") }}
</div>
{% else %}
{{ _('virtual') }}
{% endif %}
</a>
</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 %}
{{ _('virtual') }}
<i class="fa fa-toggle-off" style="color: white"></i> {{_('General')}}
{% endif %}
</a>
</div>
</div>
{% endif %}
<div id="page-container">

View file

@ -110,7 +110,7 @@
</div>
<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">
<h3>{{ _('Clarifications') }}
<i class="fa fa-question-circle"></i>

View file

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

View file

@ -58,7 +58,7 @@
{% endblock %}
{% block content_js_media %}
{% if request.in_contest %}
{% if request.in_contest_mode %}
<script type="text/javascript">
window.register_contest_notification("{{url('contest_clarification_ajax', request.participation.contest.key)}}");
</script>
@ -88,7 +88,7 @@
{% if request.user.is_authenticated %}
{% if problem.id in completed_problem_ids %}
<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>
{% else %}
<i class="solved-problem-color title-state fa fa-lock"></i>
@ -96,7 +96,7 @@
</a>
{% elif problem.id in attempted_problems %}
<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>
{% else %}
<i class="attempted-problem-color title-state fa fa-lock"></i>
@ -133,7 +133,7 @@
{% endblock %}
{% 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 %}
<a href="{{ url('problem_submit', problem.code) }}" class="unselectable button full">
{{ _('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">
{% elif logo_override_image is defined and logo_override_image %}
<img src="{{ logo_override_image|camo }}" alt="{{ SITE_NAME }}" height="44" style="border: none">

View file

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

View file

@ -24,7 +24,7 @@
<div>
{{ link_user(submission.user) }}
<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) }}"
class="submission-contest">
<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}}">
<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 %}
({{ _('%(points)s/%(total)s points', points=contest.points|roundfloat(3),
total=contest.problem.points|floatformat(-1)) }})