Contest and Org css
This commit is contained in:
parent
d6832a0550
commit
ba96d83db8
16 changed files with 648 additions and 676 deletions
|
@ -8,6 +8,7 @@ from django.core.cache.utils import make_template_fragment_key
|
||||||
from django.db.models.signals import post_delete, post_save
|
from django.db.models.signals import post_delete, post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
import judge
|
||||||
from judge.utils.problems import finished_submission
|
from judge.utils.problems import finished_submission
|
||||||
from .models import (
|
from .models import (
|
||||||
BlogPost,
|
BlogPost,
|
||||||
|
@ -22,6 +23,7 @@ from .models import (
|
||||||
Problem,
|
Problem,
|
||||||
Profile,
|
Profile,
|
||||||
Submission,
|
Submission,
|
||||||
|
NavigationBar,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -166,3 +168,8 @@ def contest_submission_update(sender, instance, **kwargs):
|
||||||
Submission.objects.filter(id=instance.submission_id).update(
|
Submission.objects.filter(id=instance.submission_id).update(
|
||||||
contest_object_id=instance.participation.contest_id
|
contest_object_id=instance.participation.contest_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=NavigationBar)
|
||||||
|
def navbar_update(sender, instance, **kwargs):
|
||||||
|
judge.template_context._nav_bar.dirty()
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import re
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -7,6 +8,7 @@ from django.core.cache import cache
|
||||||
from django.utils.functional import SimpleLazyObject, new_method_proxy
|
from django.utils.functional import SimpleLazyObject, new_method_proxy
|
||||||
|
|
||||||
from .models import MiscConfig, NavigationBar, Profile
|
from .models import MiscConfig, NavigationBar, Profile
|
||||||
|
from judge.caching import cache_wrapper
|
||||||
|
|
||||||
|
|
||||||
class FixedSimpleLazyObject(SimpleLazyObject):
|
class FixedSimpleLazyObject(SimpleLazyObject):
|
||||||
|
@ -50,22 +52,28 @@ def comet_location(request):
|
||||||
return {"EVENT_DAEMON_LOCATION": websocket, "EVENT_DAEMON_POLL_LOCATION": poll}
|
return {"EVENT_DAEMON_LOCATION": websocket, "EVENT_DAEMON_POLL_LOCATION": poll}
|
||||||
|
|
||||||
|
|
||||||
|
@cache_wrapper(prefix="nb")
|
||||||
|
def _nav_bar():
|
||||||
|
return NavigationBar.objects.all()
|
||||||
|
|
||||||
|
|
||||||
def __nav_tab(path):
|
def __nav_tab(path):
|
||||||
result = list(
|
nav_bar_list = list(_nav_bar())
|
||||||
NavigationBar.objects.extra(where=["%s REGEXP BINARY regex"], params=[path])[:1]
|
nav_bar_dict = {nb.id: nb for nb in nav_bar_list}
|
||||||
)
|
result = next((nb for nb in nav_bar_list if re.match(nb.regex, path)), None)
|
||||||
return (
|
if result:
|
||||||
result[0].get_ancestors(include_self=True).values_list("key", flat=True)
|
while result.parent_id:
|
||||||
if result
|
result = nav_bar_dict.get(result.parent_id)
|
||||||
else []
|
return result.key
|
||||||
)
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def general_info(request):
|
def general_info(request):
|
||||||
path = request.get_full_path()
|
path = request.get_full_path()
|
||||||
return {
|
return {
|
||||||
"nav_tab": FixedSimpleLazyObject(partial(__nav_tab, request.path)),
|
"nav_tab": FixedSimpleLazyObject(partial(__nav_tab, request.path)),
|
||||||
"nav_bar": NavigationBar.objects.all(),
|
"nav_bar": _nav_bar(),
|
||||||
"LOGIN_RETURN_PATH": "" if path.startswith("/accounts/") else path,
|
"LOGIN_RETURN_PATH": "" if path.startswith("/accounts/") else path,
|
||||||
"perms": PermWrapper(request.user),
|
"perms": PermWrapper(request.user),
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,20 +184,21 @@ class PostView(TitleMixin, CommentedDetailView, PageVoteDetailView, BookMarkDeta
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(PostView, self).get_context_data(**kwargs)
|
context = super(PostView, self).get_context_data(**kwargs)
|
||||||
context["og_image"] = self.object.og_image
|
context["og_image"] = self.object.og_image
|
||||||
context["valid_user_to_show_edit"] = False
|
context["editable_orgs"] = []
|
||||||
context["valid_org_to_show_edit"] = []
|
|
||||||
|
|
||||||
if self.request.profile in self.object.authors.all():
|
can_edit = False
|
||||||
context["valid_user_to_show_edit"] = True
|
if self.request.profile.id in self.object.get_authors():
|
||||||
|
can_edit = True
|
||||||
|
|
||||||
for valid_org_to_show_edit in self.object.organizations.all():
|
orgs = list(self.object.organizations.all())
|
||||||
if self.request.profile in valid_org_to_show_edit.admins.all():
|
for org in orgs:
|
||||||
context["valid_user_to_show_edit"] = True
|
if org.is_admin(self.request.profile):
|
||||||
|
can_edit = True
|
||||||
|
|
||||||
if context["valid_user_to_show_edit"]:
|
if can_edit:
|
||||||
for post_org in self.object.organizations.all():
|
for org in orgs:
|
||||||
if post_org in self.request.profile.organizations.all():
|
if org.is_member(self.request.profile):
|
||||||
context["valid_org_to_show_edit"].append(post_org)
|
context["editable_orgs"].append(org)
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
|
@ -486,9 +486,9 @@ class CommentedDetailView(TemplateResponseMixin, SingleObjectMixin, View):
|
||||||
).exists()
|
).exists()
|
||||||
)
|
)
|
||||||
|
|
||||||
context["has_comments"] = queryset.exists()
|
|
||||||
context["comment_lock"] = self.is_comment_locked()
|
context["comment_lock"] = self.is_comment_locked()
|
||||||
context["comment_list"] = list(queryset)
|
context["comment_list"] = list(queryset)
|
||||||
|
context["has_comments"] = len(context["comment_list"]) > 0
|
||||||
|
|
||||||
context["vote_hide_threshold"] = settings.DMOJ_COMMENT_VOTE_HIDE_THRESHOLD
|
context["vote_hide_threshold"] = settings.DMOJ_COMMENT_VOTE_HIDE_THRESHOLD
|
||||||
|
|
||||||
|
|
|
@ -235,31 +235,33 @@ class ContestList(
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(ContestList, self).get_context_data(**kwargs)
|
context = super(ContestList, self).get_context_data(**kwargs)
|
||||||
present, active, future = [], [], []
|
present, active, future = [], [], []
|
||||||
for contest in self._get_queryset().exclude(end_time__lt=self._now):
|
if not context["page_obj"] or context["page_obj"].number == 1:
|
||||||
if contest.start_time > self._now:
|
for contest in self._get_queryset().exclude(end_time__lt=self._now):
|
||||||
future.append(contest)
|
if contest.start_time > self._now:
|
||||||
else:
|
future.append(contest)
|
||||||
present.append(contest)
|
else:
|
||||||
|
present.append(contest)
|
||||||
|
|
||||||
if self.request.user.is_authenticated:
|
if self.request.user.is_authenticated:
|
||||||
for participation in (
|
for participation in (
|
||||||
ContestParticipation.objects.filter(
|
ContestParticipation.objects.filter(
|
||||||
virtual=0, user=self.request.profile, contest_id__in=present
|
virtual=0, user=self.request.profile, contest_id__in=present
|
||||||
)
|
)
|
||||||
.select_related("contest")
|
.select_related("contest")
|
||||||
.prefetch_related(
|
.prefetch_related(
|
||||||
"contest__authors", "contest__curators", "contest__testers"
|
"contest__authors", "contest__curators", "contest__testers"
|
||||||
)
|
)
|
||||||
.annotate(key=F("contest__key"))
|
.annotate(key=F("contest__key"))
|
||||||
):
|
):
|
||||||
if not participation.ended:
|
if not participation.ended:
|
||||||
active.append(participation)
|
active.append(participation)
|
||||||
present.remove(participation.contest)
|
present.remove(participation.contest)
|
||||||
|
|
||||||
|
if not ("contest" in self.request.GET and settings.ENABLE_FTS):
|
||||||
|
active.sort(key=attrgetter("end_time", "key"))
|
||||||
|
present.sort(key=attrgetter("end_time", "key"))
|
||||||
|
future.sort(key=attrgetter("start_time"))
|
||||||
|
|
||||||
if not ("contest" in self.request.GET and settings.ENABLE_FTS):
|
|
||||||
active.sort(key=attrgetter("end_time", "key"))
|
|
||||||
present.sort(key=attrgetter("end_time", "key"))
|
|
||||||
future.sort(key=attrgetter("start_time"))
|
|
||||||
context["active_participations"] = active
|
context["active_participations"] = active
|
||||||
context["current_contests"] = present
|
context["current_contests"] = present
|
||||||
context["future_contests"] = future
|
context["future_contests"] = future
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -240,6 +240,7 @@ a.view-pdf {
|
||||||
display: -webkit-flex;
|
display: -webkit-flex;
|
||||||
display: -ms-flexbox;
|
display: -ms-flexbox;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
.spacer {
|
.spacer {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
|
@ -9,14 +9,10 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.info-contest:first-child {
|
.info-contest:first-child, .info-contest:nth-child(2) {
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-contest:nth-child(2) {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-contest {
|
.info-contest {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
@ -155,64 +151,21 @@
|
||||||
|
|
||||||
.time-left {
|
.time-left {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: #777;
|
padding-bottom: 0.5em;
|
||||||
padding-top: 0.5em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.contest-list {
|
.list-contest {
|
||||||
td {
|
|
||||||
vertical-align: middle !important;
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
min-width: 4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(3) {
|
|
||||||
min-width: 6em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr {
|
|
||||||
height: 4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floating-time-left {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floating-time-right {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
line-height: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.floating-time {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contest-tags {
|
.contest-tags {
|
||||||
padding-left: 0.75em;
|
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contest-tag-hidden {
|
.contest-tag-hidden {
|
||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.participate-button {
|
|
||||||
display: inline-block;
|
|
||||||
width: 90px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.contest-block {
|
|
||||||
text-align: left;
|
|
||||||
padding: 0.5em 0.5em 0.5em 1em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.first-solve {
|
.first-solve {
|
||||||
|
@ -220,12 +173,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.contest-tag {
|
.contest-tag {
|
||||||
box-shadow: inset 0 -0.1em 0 rgba(0, 0, 0, 0.12);
|
|
||||||
padding: 0.15em 0.3em;
|
padding: 0.15em 0.3em;
|
||||||
border-radius: 0.15em;
|
border-radius: 0.15em;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-right: 0.45em;
|
margin-right: 0.45em;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contest-tag-edit {
|
.contest-tag-edit {
|
||||||
|
|
|
@ -52,4 +52,5 @@
|
||||||
.org-help-text {
|
.org-help-text {
|
||||||
display: block;
|
display: block;
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,15 +174,15 @@ ul.problem-list {
|
||||||
}
|
}
|
||||||
|
|
||||||
.organization-tag {
|
.organization-tag {
|
||||||
box-shadow: inset 0 -0.1em 0 rgba(0, 0, 0, 0.12);
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
padding: 0.15em 0.3em;
|
padding: 0.15em 0.3em;
|
||||||
border-radius: 0.15em;
|
border-radius: 0.15em;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-right: 0.45em;
|
margin-right: 0.45em;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
transform: translateY(+35%);
|
color: initial;
|
||||||
display: inline-block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.organization-tag a {
|
.organization-tag a {
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
{% if post.is_editable_by(request.user) %}
|
{% if post.is_editable_by(request.user) %}
|
||||||
<span> [<a href="{{ url('admin:judge_blogpost_change', post.id) }}">{{ _('Edit') }}</a>]</span>
|
<span> [<a href="{{ url('admin:judge_blogpost_change', post.id) }}">{{ _('Edit') }}</a>]</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if valid_user_to_show_edit %}
|
{% if editable_orgs %}
|
||||||
{% for org in valid_org_to_show_edit %}
|
{% for org in editable_orgs %}
|
||||||
<span> [<a href="{{ url('edit_organization_blog', org.id , org.slug , post.id) }}">{{ _('Edit in') }} {{org.slug}}</a>]</span>
|
<span> [<a href="{{ url('edit_organization_blog', org.id , org.slug , post.id) }}">{{ _('Edit in') }} {{org.slug}}</a>]</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
{% for post in posts %}
|
{% for post in posts %}
|
||||||
<section class="{% if post.sticky %}sticky {% endif %}blog-box">
|
<section class="{% if post.sticky %}sticky {% endif %}blog-box">
|
||||||
|
{% if post.is_organization_private and show_organization_private_icon %}
|
||||||
|
<div style="margin-bottom: 1em; display: flex;">
|
||||||
|
{% for org in post.organizations.all() %}
|
||||||
|
{% include "organization/tag.html" %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div style="margin-bottom: 0.5em">
|
<div style="margin-bottom: 0.5em">
|
||||||
<span class="post-content-header time">
|
<span class="post-content-header time">
|
||||||
{% with authors=post.get_authors() %}
|
{% with authors=post.get_authors() %}
|
||||||
|
@ -14,18 +21,6 @@
|
||||||
{{ relative_time(post.publish_on) }}
|
{{ relative_time(post.publish_on) }}
|
||||||
{%- if post.sticky %} •
|
{%- if post.sticky %} •
|
||||||
<i title="Sticky" class="fa fa-star fa-fw"></i>{% endif -%}
|
<i title="Sticky" class="fa fa-star fa-fw"></i>{% endif -%}
|
||||||
{% if post.is_organization_private and show_organization_private_icon %}
|
|
||||||
•
|
|
||||||
<span>
|
|
||||||
{% for org in post.organizations.all() %}
|
|
||||||
<span class="organization-tag" style="display: inherit;">
|
|
||||||
<a href="{{ org.get_absolute_url() }}">
|
|
||||||
<i class="fa fa-lock"></i> {{ org.name }}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
{% endfor %}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
</span>
|
||||||
<span style="float: right">
|
<span style="float: right">
|
||||||
<a href="{{ url('blog_post', post.id, post.slug) }}#comments" class="blog-comment-count-link">
|
<a href="{{ url('blog_post', post.id, post.slug) }}#comments" class="blog-comment-count-link">
|
||||||
|
|
|
@ -80,15 +80,11 @@
|
||||||
<div style="clear: both"></div>
|
<div style="clear: both"></div>
|
||||||
|
|
||||||
{% if contest.is_organization_private %}
|
{% if contest.is_organization_private %}
|
||||||
{% for org in contest.organizations.all() %}
|
<div style="display: flex; margin-bottom: 1em">
|
||||||
<div style="margin-bottom: 1em;">
|
{% for org in contest.organizations.all() %}
|
||||||
<span class="contest-tag contest-tag-org">
|
{% include "organization/tag.html" %}
|
||||||
<a href="{{ org.get_absolute_url() }}">
|
{% endfor %}
|
||||||
<i class="fa fa-lock"></i> {{ org.name }}
|
</div>
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if editable_organizations or is_clonable %}
|
{% if editable_organizations or is_clonable %}
|
||||||
|
|
|
@ -9,10 +9,6 @@
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-description ul {
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-contest {
|
.btn-contest {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 1px 6px;
|
padding: 1px 6px;
|
||||||
|
@ -20,6 +16,7 @@
|
||||||
|
|
||||||
.contest-group-header {
|
.contest-group-header {
|
||||||
padding-bottom: 1em;
|
padding-bottom: 1em;
|
||||||
|
margin-top: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
{% if page_obj and page_obj.number > 1%}
|
{% if page_obj and page_obj.number > 1%}
|
||||||
|
@ -115,8 +112,7 @@
|
||||||
<a href="{{ url('contest_view', contest.key) }}" class="contest-list-title" style="margin-right: 5px;">
|
<a href="{{ url('contest_view', contest.key) }}" class="contest-list-title" style="margin-right: 5px;">
|
||||||
{{contest.name}}
|
{{contest.name}}
|
||||||
</a>
|
</a>
|
||||||
<br>
|
<div class="contest-tags">
|
||||||
<div class="contest-tags" style="margin-top: 5px;">
|
|
||||||
{% if not contest.is_visible %}
|
{% if not contest.is_visible %}
|
||||||
<span class="contest-tag contest-tag-hidden">
|
<span class="contest-tag contest-tag-hidden">
|
||||||
<i class="fa fa-eye-slash"></i> {{ _('hidden') }}
|
<i class="fa fa-eye-slash"></i> {{ _('hidden') }}
|
||||||
|
@ -137,11 +133,7 @@
|
||||||
{% if not hide_contest_orgs %}
|
{% if not hide_contest_orgs %}
|
||||||
{% if contest.is_organization_private %}
|
{% if contest.is_organization_private %}
|
||||||
{% for org in contest.organizations.all() %}
|
{% for org in contest.organizations.all() %}
|
||||||
<span class="contest-tag contest-tag-org">
|
{% include "organization/tag.html" %}
|
||||||
<a href="{{ org.get_absolute_url() }}">
|
|
||||||
<i class="fa fa-lock"></i> {{ org.name }}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -162,15 +154,22 @@
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro time_left(contest, padding_top = true) %}
|
{% macro time_left(contest) %}
|
||||||
<div class="time time-left {{ 'non-padding-top' if padding_top == false }}">
|
<div class="time-left">
|
||||||
{% if contest.time_limit %}
|
{% if contest.time_limit %}
|
||||||
{{ contest.start_time|date(_("M j, Y, G:i")) }} -
|
<div>
|
||||||
{{ contest.end_time|date(_("M j, Y, G:i")) }}
|
<b>{{_("Start")}}</b>: {{ contest.start_time|date(_("g:i a d/m/Y")) }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>{{_("End")}}</b>: {{ contest.end_time|date(_("g:i a d/m/Y")) }}
|
||||||
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ contest.start_time|date(_("M j, Y, G:i")) }}
|
<div>
|
||||||
|
<b>{{_("Start")}}</b>: {{ contest.start_time|date(_("g:i a d/m/Y")) }}
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br>
|
</div>
|
||||||
|
<div class="time">
|
||||||
{% if contest.time_limit %}
|
{% if contest.time_limit %}
|
||||||
{% trans time_limit=contest.time_limit|timedelta('localized-no-seconds') %}{{ time_limit }} window{% endtrans %}
|
{% trans time_limit=contest.time_limit|timedelta('localized-no-seconds') %}{{ time_limit }} window{% endtrans %}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -206,48 +205,49 @@
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% block middle_content %}
|
{% block middle_content %}
|
||||||
<div class="content-description">
|
<form id="filter-form">
|
||||||
<form id="filter-form">
|
<input id="search-contest" type="text" name="contest" value="{{ contest_query or '' }}"
|
||||||
<input id="search-contest" type="text" name="contest" value="{{ contest_query or '' }}"
|
placeholder="{{ _('Search contests...') }}">
|
||||||
placeholder="{{ _('Search contests...') }}">
|
{% if organizations %}
|
||||||
{% if organizations %}
|
<select id="search-org" name="orgs" multiple>
|
||||||
<select id="search-org" name="orgs" multiple>
|
{% for org in organizations %}
|
||||||
{% for org in organizations %}
|
<option value="{{ org.id }}"{% if org.id in org_query %} selected{% endif %}>
|
||||||
<option value="{{ org.id }}"{% if org.id in org_query %} selected{% endif %}>
|
{{ org.name }}
|
||||||
{{ org.name }}
|
</option>
|
||||||
</option>
|
{% endfor %}
|
||||||
{% endfor %}
|
</select>
|
||||||
</select>
|
{% endif %}
|
||||||
{% endif %}
|
<button id="search-btn" class="btn-green small"> {{ _('Search')}} </button>
|
||||||
<button id="search-btn" class="btn-green small"> {{ _('Search')}} </button>
|
{% if organizations %}
|
||||||
{% if organizations %}
|
<div>
|
||||||
<div>
|
<input id="show_orgs" type="checkbox" name="show_orgs" value="1" {% if show_orgs %}checked{% endif %}>
|
||||||
<input id="show_orgs" type="checkbox" name="show_orgs" value="1" {% if show_orgs %}checked{% endif %}>
|
<label for="show_orgs">{{ _('Hide organization contests') }}</label>
|
||||||
<label for="show_orgs">{{ _('Hide organization contests') }}</label>
|
</div>
|
||||||
</div>
|
{% endif %}
|
||||||
{% endif %}
|
{% if create_url %}
|
||||||
{% if create_url %}
|
<a href="{{create_url}}" class="button small" style="float: right"><i class="fa fa-plus"></i> {{ _('Create')}}</a>
|
||||||
<a href="{{create_url}}" class="button small" style="float: right"><i class="fa fa-plus"></i> {{ _('Create')}}</a>
|
{% endif %}
|
||||||
{% endif %}
|
</form>
|
||||||
</form>
|
|
||||||
|
<div id="ongoing-table">
|
||||||
{% if active_participations %}
|
{% if active_participations %}
|
||||||
<h3 class="toggle open contest-group-header">
|
<h3 class="toggle open contest-group-header">
|
||||||
<i class="fa fa-chevron-right fa-fw"></i>
|
<i class="fa fa-chevron-right fa-fw"></i>
|
||||||
{{ _('Active Contests') }}
|
{{ _('Active Contests') }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="toggled">
|
<div class="toggled">
|
||||||
|
|
||||||
{% for participation in active_participations %}
|
{% for participation in active_participations %}
|
||||||
{% with contest=participation.contest %}
|
{% with contest=participation.contest %}
|
||||||
<div class="list-contest">
|
<div class="list-contest">
|
||||||
<div class="info-contest" style="flex: 1.5">
|
<div class="info-contest">
|
||||||
<div class="contest-title"> {{ _('Contests') }} </div>
|
<div class="contest-title"> {{ _('Contests') }} </div>
|
||||||
{{ contest_head(contest) }}
|
{{ contest_head(contest) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="info-contest" style="flex: 1.5">
|
<div class="info-contest">
|
||||||
<div class="contest-title"> {{ _('Time') }} </div>
|
<div class="contest-title"> {{ _('Time') }} </div>
|
||||||
<div class="contest-block">
|
<div class="contest-block">
|
||||||
{% if contest.start_time %}
|
{% if contest.start_time %}
|
||||||
|
{{ time_left(contest) }}
|
||||||
{% if contest.time_limit %}
|
{% if contest.time_limit %}
|
||||||
<span class="time">
|
<span class="time">
|
||||||
{% trans countdown=participation.end_time|as_countdown %}Window ends in {{countdown}}{% endtrans %}
|
{% trans countdown=participation.end_time|as_countdown %}Window ends in {{countdown}}{% endtrans %}
|
||||||
|
@ -255,15 +255,14 @@
|
||||||
{% elif contest.time_before_end %}
|
{% elif contest.time_before_end %}
|
||||||
<span class="time">{% trans countdown=contest.end_time|as_countdown %}Ends in {{countdown}}{% endtrans %}</span>
|
<span class="time">{% trans countdown=contest.end_time|as_countdown %}Ends in {{countdown}}{% endtrans %}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ time_left(contest) }}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-contest">
|
<div class="info-contest" style="flex: 0.5;">
|
||||||
<div class="contest-title"> {{ _('Format') }} </div>
|
<div class="contest-title"> {{ _('Format') }} </div>
|
||||||
{{ contest.format.name }}
|
{{ contest.format.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="info-contest">
|
<div class="info-contest" style="flex: 0.5;">
|
||||||
<div class="contest-title"> {{ _('Users') }} </div>
|
<div class="contest-title"> {{ _('Users') }} </div>
|
||||||
{{ user_count(contest, request.user) }}
|
{{ user_count(contest, request.user) }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -274,7 +273,6 @@
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<br>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<h3 class="toggle open contest-group-header">
|
<h3 class="toggle open contest-group-header">
|
||||||
|
@ -282,29 +280,29 @@
|
||||||
{{ _('Ongoing Contests') }}
|
{{ _('Ongoing Contests') }}
|
||||||
</h3>
|
</h3>
|
||||||
{% if current_contests %}
|
{% if current_contests %}
|
||||||
<div id="ongoing-table" class="toggled">
|
<div class="toggled">
|
||||||
{% for contest in current_contests %}
|
{% for contest in current_contests %}
|
||||||
<div class="list-contest">
|
<div class="list-contest">
|
||||||
<div class="info-contest" style="flex: 1.5">
|
<div class="info-contest">
|
||||||
<div class="contest-title"> {{ _('Contests') }} </div>
|
<div class="contest-title"> {{ _('Contests') }} </div>
|
||||||
{{ contest_head(contest) }}
|
{{ contest_head(contest) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="info-contest" style="flex: 1.5">
|
<div class="info-contest">
|
||||||
<div class="contest-title"> {{ _('Time') }} </div>
|
<div class="contest-title"> {{ _('Time') }} </div>
|
||||||
<div class="contest-block">
|
<div class="contest-block">
|
||||||
{% if contest.start_time %}
|
{% if contest.start_time %}
|
||||||
|
{{ time_left(contest) }}
|
||||||
{% if contest.time_before_end %}
|
{% if contest.time_before_end %}
|
||||||
<span class="time">{% trans countdown=contest.end_time|as_countdown %}Ends in {{countdown}}{% endtrans %}</span>
|
<span class="time">{% trans countdown=contest.end_time|as_countdown %}Ends in {{countdown}}{% endtrans %}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ time_left(contest) }}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-contest">
|
<div class="info-contest" style="flex: 0.5;">
|
||||||
<div class="contest-title"> {{ _('Format') }} </div>
|
<div class="contest-title"> {{ _('Format') }} </div>
|
||||||
{{ contest.format.name }}
|
{{ contest.format.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="info-contest">
|
<div class="info-contest" style="flex: 0.5;">
|
||||||
<div class="contest-title"> {{ _('Users') }} </div>
|
<div class="contest-title"> {{ _('Users') }} </div>
|
||||||
{{ user_count(contest, request.user) }}
|
{{ user_count(contest, request.user) }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -313,12 +311,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<br>
|
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="toggled">
|
<div class="toggled">
|
||||||
<i> {{ _('There is no ongoing contest at this time.') }} </i>
|
<i> {{ _('There is no ongoing contest at this time.') }} </i>
|
||||||
<br>
|
<br><br>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -330,22 +327,22 @@
|
||||||
<div class="toggled">
|
<div class="toggled">
|
||||||
{% for contest in future_contests %}
|
{% for contest in future_contests %}
|
||||||
<div class="list-contest">
|
<div class="list-contest">
|
||||||
<div class="info-contest" style="flex: 1.5">
|
<div class="info-contest">
|
||||||
<div class="contest-title"> {{ _('Contests') }} </div>
|
<div class="contest-title"> {{ _('Contests') }} </div>
|
||||||
{{ contest_head(contest) }}
|
{{ contest_head(contest) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="info-contest" style="flex: 1.5">
|
<div class="info-contest">
|
||||||
<div class="contest-title"> {{ _('Time') }} </div>
|
<div class="contest-title"> {{ _('Time') }} </div>
|
||||||
<div class="contest-block">
|
<div class="contest-block">
|
||||||
{% if contest.start_time %}
|
{% if contest.start_time %}
|
||||||
|
{{ time_left(contest) }}
|
||||||
{% if contest.time_before_start %}
|
{% if contest.time_before_start %}
|
||||||
<span class="time">{{ _('Starting in %(countdown)s.', countdown=contest.start_time|as_countdown) }}</span>
|
<span class="time">{{ _('Starting in %(countdown)s.', countdown=contest.start_time|as_countdown) }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ time_left(contest) }}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-contest">
|
<div class="info-contest" style="flex: 0.5;">
|
||||||
<div class="contest-title"> {{ _('Format') }} </div>
|
<div class="contest-title"> {{ _('Format') }} </div>
|
||||||
{{ contest.format.name }}
|
{{ contest.format.name }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -355,62 +352,61 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="toggled">
|
<div class="toggled">
|
||||||
<i>{{ _('There is no scheduled contest at this time.') }}</i>
|
<i>{{ _('There is no scheduled contest at this time.') }}</i>
|
||||||
<br>
|
<br><br>
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<h3 class="toggle open contest-group-header">
|
|
||||||
{{ _('Past Contests') }}
|
|
||||||
</h3>
|
|
||||||
{% if past_contests %}
|
|
||||||
{% if page_obj and page_obj.num_pages > 1 %}
|
|
||||||
<div style="margin-bottom: 10px;">
|
|
||||||
{% include "list-pages.html" %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% for contest in past_contests %}
|
|
||||||
<div class="list-contest">
|
|
||||||
<div class="info-contest" style="flex: 1.5">
|
|
||||||
<div class="contest-title"> {{ _('Contests') }} </div>
|
|
||||||
{{ contest_head(contest) }}
|
|
||||||
</div>
|
|
||||||
<div class="info-contest" style="flex: 1.5">
|
|
||||||
<div class="contest-title"> {{ _('Time') }} </div>
|
|
||||||
<div class="contest-block">
|
|
||||||
{{ time_left(contest, false) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="info-contest">
|
|
||||||
<div class="contest-title"> {{ _('Format') }} </div>
|
|
||||||
{{ contest.format.name }}
|
|
||||||
</div>
|
|
||||||
<div class="info-contest">
|
|
||||||
<div class="contest-title"> {{ _('Users') }} </div>
|
|
||||||
{{ user_count(contest, request.user) }}
|
|
||||||
</div>
|
|
||||||
{% if not request.in_contest %}
|
|
||||||
<div class="participate-button">
|
|
||||||
<form action="{{ url('contest_join', contest.key) }}" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
<input type="submit" class="unselectable button full small"
|
|
||||||
value="{{ _('Virtual join') }}">
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% if page_obj and page_obj.num_pages > 1 %}
|
|
||||||
<div style="margin-top: 10px;">
|
|
||||||
{% include "list-pages.html" %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
<div class="toggled">
|
|
||||||
<i> {{ _('There is no past contest.') }} </i>
|
|
||||||
<br>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h3 class="toggle open contest-group-header">
|
||||||
|
{{ _('Past Contests') }}
|
||||||
|
</h3>
|
||||||
|
{% if past_contests %}
|
||||||
|
{% if page_obj and page_obj.num_pages > 1 %}
|
||||||
|
<div style="margin-bottom: 10px;">
|
||||||
|
{% include "list-pages.html" %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for contest in past_contests %}
|
||||||
|
<div class="list-contest">
|
||||||
|
<div class="info-contest">
|
||||||
|
<div class="contest-title"> {{ _('Contests') }} </div>
|
||||||
|
{{ contest_head(contest) }}
|
||||||
|
</div>
|
||||||
|
<div class="info-contest">
|
||||||
|
<div class="contest-title"> {{ _('Time') }} </div>
|
||||||
|
<div class="contest-block">
|
||||||
|
{{ time_left(contest) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-contest" style="flex: 0.5;">
|
||||||
|
<div class="contest-title"> {{ _('Format') }} </div>
|
||||||
|
{{ contest.format.name }}
|
||||||
|
</div>
|
||||||
|
<div class="info-contest" style="flex: 0.5;">
|
||||||
|
<div class="contest-title"> {{ _('Users') }} </div>
|
||||||
|
{{ user_count(contest, request.user) }}
|
||||||
|
</div>
|
||||||
|
{% if not request.in_contest %}
|
||||||
|
<div class="participate-button">
|
||||||
|
<form action="{{ url('contest_join', contest.key) }}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="submit" class="unselectable button full small"
|
||||||
|
value="{{ _('Virtual join') }}">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% if page_obj and page_obj.num_pages > 1 %}
|
||||||
|
<div style="margin-top: 10px;">
|
||||||
|
{% include "list-pages.html" %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<div class="toggled">
|
||||||
|
<i> {{ _('There is no past contest.') }} </i>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
8
templates/organization/tag.html
Normal file
8
templates/organization/tag.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<a href="{{ org.get_absolute_url() }}">
|
||||||
|
<span class="organization-tag" style="gap: 0.2em;">
|
||||||
|
{% if org.logo_override_image %}
|
||||||
|
<img class="user-img" style="height: 1.5em; width: 1.5em;" loading="lazy" src="{{ org.logo_override_image }}">
|
||||||
|
{% endif %}
|
||||||
|
{{ org.name }}
|
||||||
|
</span>
|
||||||
|
</a>
|
|
@ -118,11 +118,7 @@
|
||||||
{% if problem.is_organization_private %}
|
{% if problem.is_organization_private %}
|
||||||
<span class="organization-tags">
|
<span class="organization-tags">
|
||||||
{% for org in problem.organizations.all() %}
|
{% for org in problem.organizations.all() %}
|
||||||
<span class="organization-tag">
|
{% include "organization/tag.html" %}
|
||||||
<a href="{{ org.get_absolute_url() }}">
|
|
||||||
<i class="fa fa-lock"></i> {{ org.name }}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
Loading…
Reference in a new issue