Merge branch 'LQDJudge:master' into master

This commit is contained in:
pcthuoc 2024-06-22 16:38:36 +07:00 committed by GitHub
commit ff9b86ea13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2370 changed files with 30872 additions and 13914 deletions

View file

@ -2,7 +2,7 @@
{% block body %}
{% if request.organization %}
{% cache 3600 'organization_html' request.organization.id MATH_ENGINE %}
{% cache 3600 'organization_html' request.organization.id %}
{{ request.organization.about|markdown|reference|str|safe }}
{% endcache %}
{% else %}

View file

@ -11,25 +11,25 @@
class="like-button actionbar-button {% if pagevote.vote_score(request.profile) == 1 %}voted{% endif %}"
onclick="javascript:pagevote_upvote({{ pagevote.id }}, event)">
<span class="pagevote-score" id="pagevote-score-{{pagevote.id}}">{{ pagevote.score }}</span>
<i class="fa fa-thumbs-o-up" style="font-size: large;"></i>
<i class="far fa-thumbs-up" style="font-size: large;"></i>
<span class="actionbar-text">{{_("Like")}}</span>
</span>
<span id="dislike-button-{{pagevote.id}}"
class="dislike-button actionbar-button {% if pagevote.vote_score(request.profile) == -1 %}voted{% endif %}"
onclick="javascript:pagevote_downvote({{ pagevote.id }}, event)">
<i class="fa fa-thumbs-o-down" style="font-size: large;"></i>
<i class="far fa-thumbs-down" style="font-size: large;"></i>
</span>
</span>
{% if not hide_actionbar_comment %}
<span class="actionbar-block">
<span class="actionbar-button actionbar-comment">
<i class="fa fa-comment-o" style="font-size: large;"></i>
<i class="far fa-comment" style="font-size: large;"></i>
<span class="actionbar-text">
{{_("Comment")}}
</span>
{% if comment_count %}
{% if all_comment_count %}
<span style="margin-left: 0.2em">
({{ comment_count }})
({{ all_comment_count }})
</span>
{% endif %}
</span>
@ -37,9 +37,9 @@
{% endif %}
<span class="actionbar-block">
<span id="bookmark-button-{{bookmark.id}}"
class="bookmark-button actionbar-button {% if bookmark.get_bookmark(request.profile) == True %} bookmarked {% endif %}"
class="bookmark-button actionbar-button {% if bookmark.is_bookmarked_by(request.profile) %} bookmarked {% endif %}"
onclick="javascript:bookmark({{ bookmark.id }}, event)">
<i class="fa fa-bookmark-o" style="font-size: large;"></i>
<i class="far fa-bookmark" style="font-size: large;"></i>
<span class="actionbar-text">{{_("Bookmark")}}</span>
</span>
</span>
@ -53,7 +53,7 @@
{% if actionbar_report_url %}
<span class="actionbar-block">
<a class="actionbar-button black" href="{{actionbar_report_url}}">
<i class="fa fa-flag-o" style="font-size: large;"></i>
<i class="fa fa-flag" style="font-size: large;"></i>
<span class="actionbar-text">{{_("Report")}}</span>
</a>
</span>

View file

@ -50,10 +50,9 @@
<link rel="stylesheet" type="text/css" href="{{ static('markdown.css') }}">
{% compress css %}
<link rel="stylesheet" href="{{ static('style.css') }}">
{% if PYGMENT_THEME %}
<link rel="stylesheet" href="{{ static(PYGMENT_THEME) }}">
{% endif %}{% if INLINE_FONTAWESOME %}
<link rel="stylesheet" href="{{ static('libs/fontawesome/font-awesome.css') }}">{% endif %}
{% if INLINE_FONTAWESOME %}
<link rel="stylesheet" href="{{ static('fontawesome/css/all.min.css') }}">
{% endif %}
<link rel="stylesheet" type="text/css" href="{{ static('libs/featherlight/featherlight.min.css') }}">
<link rel="stylesheet" type="text/css" href="{{ static('libs/clipboard/tooltip.css') }}">
<link rel="stylesheet" type="text/css" href="{{ static('libs/select2/select2.css') }}">
@ -70,10 +69,8 @@
{% endif %}
{% block media %}{% endblock %}
{% if use_darkmode %}
{% compress css %}
<link rel="stylesheet" href="{{ static('darkmode.css') }}">
<link rel="stylesheet" href="{{ static('darkmode-svg.css') }}">
{% endcompress %}
<link rel="stylesheet" href="{{ static('darkmode.css') }}">
<link rel="stylesheet" href="{{ static('darkmode-svg.css') }}">
{% endif %}
<noscript>
@ -92,10 +89,19 @@
@media(min-width: 800px) {
#page-container {
background: {{request.profile.css_background|safe}};
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-attachment: fixed;
}
}
</style>
{% endif %}
{% if not INLINE_JQUERY %}
<script src="{{ JQUERY_JS }}"></script>
{% else %}
<script src="{{ static('libs/jquery-3.4.1.min.js') }}"></script>
{% endif %}
</head>
<body>
<svg width="0" height="0" style="display: block">
@ -113,11 +119,11 @@
<li>
<a href="{{ node.path }}" id="fa-icon-links" class="normal-text nav-{{ node.key }}{% if node.key in nav_tab %} active{% endif %}">
<span class="nav-fa-icon{{'-active' if node.key in nav_tab else''}}">
{% if node.key == "problems" %} <i class="fa fa-pencil"></i> {% endif %}
{% if node.key == "problems" %} <i class="fa fa-puzzle-piece"></i> {% endif %}
{% if node.key == "submit" %} <i class="fa fa-code"></i> {% endif %}
{% if node.key == "user" %} <i class="fa fa-user"></i> {% endif %}
{% if node.key == "contest" %} <i class="fa fa-graduation-cap"></i> {% endif %}
{% if node.key == "group" %} <i class="fa fa-group"></i> {% endif %}
{% if node.key == "contest" %} <i class="fa fa-ranking-star"></i> {% endif %}
{% if node.key == "group" %} <i class="fa fa-building-columns"></i> {% endif %}
{% if node.key == "about" %} <i class="fa fa-at"></i> {% endif %}
</span>
{{ user_trans(node.label) }}
@ -135,7 +141,7 @@
<div style="display: flex; font-size: larger; align-items: center; height: 100%; gap: 1em;">
{% if request.user.is_authenticated %}
<span title="{{_('Chat')}}">
<a id="chat-icon" href="{{ url('chat', '') }}" class="fa fa-wechat navbar-icon" aria-hidden="true" style="font-size: 22.5px;">
<a id="chat-icon" href="{{ url('chat', '') }}" class="fab fa-weixin navbar-icon" aria-hidden="true" style="font-size: 22.5px;">
{% set unread_chat = request.profile.count_unread_chat_boxes %}
{% if unread_chat %}
<sub class="unread_boxes">{{unread_chat}}</sub>
@ -145,7 +151,7 @@
{% set unseen_cnt = request.profile.count_unseen_notifications %}
<span title="{{_('Notification')}}" class="{{ 'notification-open' if unseen_cnt > 0 }}">
<a href="{{ url('notification') }}" class="fa fa-bell-o navbar-icon" id="notification" aria-hidden="true" style="font-size: 22.5px;">
<a href="{{ url('notification') }}" class="far fa-bell navbar-icon" id="notification" aria-hidden="true" style="font-size: 22.5px;">
{% if unseen_cnt > 0 %}
<sub class="unread_boxes">{{unseen_cnt}}</sub>
{% endif %}
@ -168,43 +174,48 @@
{{ language.name_local }}
</div>
{% endfor %}
<div class="popper-arrow" data-popper-arrow></div>
</div>
</span>
<span title="{{_('Dark Mode')}}">
<a class="fa fa-moon-o navbar-icon black" id="nav-darkmode-icon" aria-hidden="true" href="?darkmode=1" style="font-size: 22.5px;"></a>
<a class="far fa-moon navbar-icon black" id="nav-darkmode-icon" aria-hidden="true" href="?darkmode=1" style="font-size: 22.5px;"></a>
</span>
{% if request.user.is_authenticated %}
<span id="user-links">
<img src="{{ gravatar(request.profile, 32) }}" height="24" width="24">
<img class="user-img" src="{{ gravatar(request.profile, 32) }}" height="24" width="24">
<i class="fa fa-angle-down" style="font-size: 18px; padding-top: 8px;"></i>
</span>
<div class="dropdown" id="userlink_dropdown" role="tooptip">
<div class="popper-arrow" data-popper-arrow></div>
<a href="{{ url('user_page') }}">
<div class="dropdown-item">{{ _('Profile') }}</div>
<div class="dropdown-item"><i class="fa fa-user"></i> {{ _('Profile') }}</div>
</a>
{% if request.user.is_staff or request.user.is_superuser %}
<a href="{{ url('admin:index') }}">
<div class="dropdown-item">{{ _('Admin') }}</div>
<div class="dropdown-item"><i class="fa fa-user-shield"></i> {{ _('Admin') }}</div>
</a>
{% endif %}
{% if request.user.is_superuser %}
<a href="{{ url('internal_problem') }}">
<div class="dropdown-item">{{ _('Internal') }}</div>
<div class="dropdown-item"><i class="fa fa-circle-info"></i> {{ _('Internal') }}</div>
</a>
<a href="{{ url('site_stats') }}">
<div class="dropdown-item">{{ _('Stats') }}</div>
<div class="dropdown-item"><i class="fa fa-chart-pie"></i> {{ _('Stats') }}</div>
</a>
{% endif %}
<a href="{{ url('user_bookmark') }}">
<div class="dropdown-item"><i class="fa fa-bookmark"></i> {{ _('Bookmarks') }}</div>
</a>
<a href="{{ url('user_edit_profile') }}">
<div class="dropdown-item">{{ _('Edit profile') }}</div>
<div class="dropdown-item"><i class="fa fa-gear"></i> {{ _('Settings') }}</div>
</a>
{% if request.user.is_impersonate %}
<a href="{{ url('impersonate-stop') }}">
<div class="dropdown-item">Stop impersonating</div>
<div class="dropdown-item"><i class="fa fa-eye"></i> {{_('Stop impersonating')}}</div>
</a>
{% else %}
<a href="#" id="logout" class="red">
<div class="dropdown-item">
<div class="dropdown-item"><i class="fa fa-right-from-bracket"></i>
{{ _('Log out') }}
<form id="logout-form" action="{{ url('auth_logout') }}" method="POST">
{% csrf_token %}
@ -242,9 +253,9 @@
</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 white"></i> {{_('Compete')}}
<i class="fa fa-toggle-on white"></i> {{_('In contest')}}
{% else %}
<i class="fa fa-toggle-off white"></i> {{_('General')}}
<i class="fa fa-toggle-off white"></i> {{_('Out contest')}}
{% endif %}
</div>
</div>
@ -272,15 +283,9 @@
<div id="announcement">{{ i18n_config.announcement|safe }}</div>
{% endif %}
{% if not INLINE_JQUERY %}
<script src="{{ JQUERY_JS }}"></script>
{% endif %}
<script src="https://unpkg.com/@popperjs/core@2"></script>
{% compress js %}
<script>{{ inlinei18n(LANGUAGE_CODE)|safe }}</script>
{% if INLINE_JQUERY %}
<script src="{{ static('libs/jquery-3.4.1.min.js') }}"></script>
{% endif %}
<script src="{{ static('libs/popper.min.js') }}"></script>
<script src="{{ static('libs/jquery-cookie.js') }}"></script>
<script src="{{ static('libs/jquery-taphold.js') }}"></script>
<script src="{{ static('libs/jquery.unveil.js') }}"></script>
@ -290,6 +295,7 @@
{% include "extra_js.html" %}
<script src="{{ static('common.js') }}"></script>
<script src="{{ static('libs/clipboard/tooltip.js') }}"></script>
<script type="text/javascript" src="{{ static('libs/featherlight/featherlight.min.js') }}"></script>
<script>
moment.locale('{{ LANGUAGE_CODE }}');
$(function () {
@ -373,15 +379,12 @@
{{ misc_config.analytics|safe }}
{% endif %}
{# Don't run userscript since it may be malicious #}
{% if request.user.is_authenticated and request.profile.user_script and not request.user.is_impersonate %}
<script type="text/javascript">{{ request.profile.user_script|safe }}</script>
{% endif %}
<div id="extra_js">
{% block extra_js %}{% endblock %}
</div>
{% block bodyend %}{% endblock %}
<script src="{{ static('katex_config.js') }}"></script>
{% include "katex-load.html" %}
{% block footer %}
<footer>
<span id="footer-content">

View file

@ -19,7 +19,7 @@
<div class="post-full">
<div class="post-title">{{ title }}</div>
<div class="time">
{% with authors=post.authors.all() %}
{% with authors=post.get_authors() %}
{% if authors %}
<span class="post-authors">{{ link_users(authors) }}</span>
{% endif %}
@ -30,14 +30,14 @@
{% if post.is_editable_by(request.user) %}
<span> [<a href="{{ url('admin:judge_blogpost_change', post.id) }}">{{ _('Edit') }}</a>]</span>
{% endif %}
{% if valid_user_to_show_edit %}
{% for org in valid_org_to_show_edit %}
{% if editable_orgs %}
{% for org in editable_orgs %}
<span> [<a href="{{ url('edit_organization_blog', org.id , org.slug , post.id) }}">{{ _('Edit in') }} {{org.slug}}</a>]</span>
{% endfor %}
{% endif %}
</div>
<div class="body content-description">
{% cache 86400 'post_content' post.id MATH_ENGINE %}
{% cache 86400 'post_content' post.id %}
{{ post.content|markdown|reference|str|safe}}
{% endcache %}
</div>
@ -49,8 +49,5 @@
{% block bodyend %}
{{ super() }}
{% if REQUIRE_JAX %}
{% include "mathjax-load.html" %}
{% endif %}
{% include "comments/math.html" %}
{% endblock %}

View file

@ -1,35 +1,32 @@
{% for post in posts%}
{% for post in posts %}
<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">
<span class="time">
{% with authors=post.authors.all() %}
<span class="post-content-header time">
{% with authors=post.get_authors() %}
{%- if authors -%}
<img src="{{gravatar(authors[0])}}" style="width: 1.5em; border-radius: 50%; margin-bottom: -0.3em">
<span class="user-img" style="width: 1.5em; height: 1.5em">
<img src="{{gravatar(authors[0])}}" loading="lazy">
</span>
<span class="post-authors">{{ link_users(authors) }}</span>
{%- endif -%}
{% endwith %}
&#8226;
{{ relative_time(post.publish_on, abs=_('on {time}'), rel=_('{time}')) -}}
{{ relative_time(post.publish_on) }}
{%- if post.sticky %} &#8226;
<i title="Sticky" class="fa fa-star fa-fw"></i>{% endif -%}
{% if post.is_organization_private and show_organization_private_icon %}
&#8226;
<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 style="float: right">
<a href="{{ url('blog_post', post.id, post.slug) }}#comments" class="blog-comment-count-link">
<i class="fa fa-comments blog-comment-icon"></i>
<span class="blog-comment-count">
{{- post.comments.filter(hidden=False).count() or 0 -}}
{{ comment_count(post) }}
</span>
</a>
</span>
@ -39,8 +36,8 @@
</h2>
<div class="blog-description">
<div class="summary content-description">
{% cache 86400 'post_summary' post.id %}
{{ post.summary|default(post.content, true)|markdown(lazy_load=True)|reference|str|safe }}
{% cache 86400 'post_content' post.id %}
{{ post.content|markdown(lazy_load=True)|reference|str|safe }}
{% endcache %}
</div>
<div class="show-more"> {{_("...More")}} </div>

View file

@ -2,19 +2,20 @@
{% block three_col_media %}
{% include "blog/media-css.html" %}
<style>
@media (max-width: 799px) {
.title {
clear: both;
}
}
.time {
margin-left: 0;
}
.no-clarifications-message {
font-style: italic;
text-align: center;
}
.org-logo {
height: 2em;
width: 2em;
margin-right: 0.5em;
}
.organization-row:last-child {
border-bottom: none;
}
</style>
{% endblock %}
@ -100,8 +101,9 @@
</div>
</div>
{% endif %}
{% include 'profile-table.html' %}
{% include 'contests-countdown.html' %}
{% include 'recent-organization.html' %}
{% include 'top-users.html' %}
{% include 'recent-organization.html' %}
</div>
{% endblock %}

View file

@ -5,9 +5,6 @@
{% block title %} {{_('Chat Box')}} {% endblock %}
{% block js_media %}
{% if REQUIRE_JAX %}
{% include "mathjax-load.html" %}
{% endif %}
{% include "comments/math.html" %}
<script type="text/javascript" src="{{ static('event.js') }}"></script>
<script type="module" src="https://unpkg.com/emoji-picker-element@1"></script>
@ -82,13 +79,15 @@
{% include 'chat/user_online_status.html' %}
</div>
<div id="chat-box">
<img src="{{static('loading.gif')}}" id="loader" style="display: none;">
<span id="loader" style="font-size: 2em; display: none;">
<i class="fa fa-spinner fa-pulse"></i>
</span>
<ul id="chat-log">
{% include 'chat/message_list.html' %}
</ul>
</div>
<div id="chat-input-container">
<textarea maxlength="5000" id="chat-input" placeholder="{{_('Enter your message')}}"></textarea>
<textarea maxlength="{{5000 if room else 200}}" id="chat-input" placeholder="{{_('Enter your message')}}"></textarea>
<div class="chat-input-icon" id="emoji-button" href="#" title="{{_('Emoji')}}"><i class="icofont-slightly-smile"></i>
</div>
<div class="chat-input-icon" id="submit-button">

View file

@ -66,7 +66,6 @@
.profile-pic {
height: 2.6em;
width: 2.6em;
border-radius: 50%;
margin-top: 0.1em;
float: left;
}
@ -115,7 +114,17 @@
#setting {
position: relative;
}
#setting-button {
.setting-button {
height: 2.3em;
width: 2.5em;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
padding-top: 2px;
}
.user-setting-button {
height: 2.3em;
width: 2.5em;
border-radius: 50%;
@ -217,9 +226,15 @@
.active-span {
display: none;
}
#chat-area {
display: none;
}
{% if not room %}
#chat-area {
display: none;
}
{% else %}
.chat-left-panel {
display: none;
}
{% endif %}
.back-button {
margin-right: 1em;
font-size: 1.5em;

View file

@ -2,6 +2,11 @@
let isMobile = window.matchMedia("only screen and (max-width: 799px)").matches;
function load_next_page(last_id, refresh_html=false) {
if (refresh_html) {
window.lock = true;
$('#chat-log').html('');
$('#loader').show();
}
var param = {
'last_id': last_id,
'only_messages': true,
@ -9,12 +14,11 @@
$.get("{{ url('chat', '') }}" + window.room_id, param)
.fail(function() {
console.log("Fail to load page, last_id = " + last_id);
window.lock = false;
})
.done(function(data) {
if (refresh_html) {
$('#chat-log').html('');
$('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
window.lock = true;
}
var time = refresh_html ? 0 : 200;
@ -32,8 +36,7 @@
$('#chat-log').prepend(data);
}
register_time($('.time-with-rel'));
merge_authors();
postProcessMessages();
if (!refresh_html) {
$chat_box.scrollTop(scrollTopOfBottom($chat_box) - lastMsgPos);
@ -47,6 +50,13 @@
})
}
function postProcessMessages() {
register_time($('.time-with-rel'));
renderKatex();
populateCopyButton();
merge_authors();
}
function scrollTopOfBottom(container) {
return container[0].scrollHeight - container.innerHeight()
}
@ -64,7 +74,7 @@
}
})}
function refresh_status() {
function refresh_status(refresh_chat_info=false) {
$.get("{{url('online_status_ajax')}}")
.fail(function() {
console.log("Fail to get online status");
@ -78,6 +88,7 @@
register_toggle($(this));
});
register_click_space();
register_setting(false);
color_selected_room();
}
})
@ -86,6 +97,10 @@
'user': window.other_user_id,
};
if (refresh_chat_info) {
$('#chat-info').html('');
}
$.get("{{url('user_online_status_ajax')}}", data)
.fail(function() {
console.log("Fail to get user online status");
@ -93,7 +108,7 @@
.done(function(data) {
$('#chat-info').html(data);
register_time($('.time-with-rel'));
register_setting();
register_setting(true);
})
}
@ -102,9 +117,7 @@
$('#chat-log').append($data);
$('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
register_time($('.time-with-rel'));
MathJax.typeset();
merge_authors();
postProcessMessages();
}
function add_new_message(message, room, is_self_author) {
@ -157,10 +170,8 @@
else {
add_new_message(message, room, true);
}
MathJax.typeset();
register_time($('.time-with-rel'));
remove_unread_current_user();
merge_authors();
postProcessMessages();
},
error: function (data) {
console.log('Fail to check message');
@ -219,7 +230,6 @@
if ($("#chat-input").val().trim()) {
$('#chat-input-container').height('auto');
var body = $('#chat-input').val().trim();
// body = body.split('\n').join('\n\n');
var message = {
body: body,
@ -228,12 +238,16 @@
};
$('#chat-input').val('');
$('#chat-input').css('height', '70%');
add_message_from_template(body, message.tmp_id);
$.post("{{ url('post_chat_message') }}", message)
.fail(function(res) {
console.log('Fail to send message');
var $body = $('#message-text-'+ message.tmp_id);
$body.css('text-decoration', 'line-through');
$body.css('background', 'red');
})
.done(function(res, status) {
$('#empty_msg').hide();
@ -295,9 +309,11 @@
history.replaceState(null, '', "{{url('chat', '')}}" + window.room_id);
load_next_page(null, true);
update_last_seen();
refresh_status();
$('#chat-input').focus();
refresh_status(true);
show_right_panel();
$('#chat-input').focus();
$('#chat-input').val('').trigger('input');
}
window.lock_click_space = true;
if (encrypted_user) {
@ -307,6 +323,7 @@
window.other_user_id = data.other_user_id;
color_selected_room();
callback();
$('#chat-input').attr('maxlength', 5000);
})
.fail(function() {
console.log('Fail to get_or_create_room');
@ -317,6 +334,7 @@
window.other_user_id = '';
color_selected_room();
callback();
$('#chat-input').attr('maxlength', 200);
}
window.lock_click_space = false;
}
@ -363,18 +381,22 @@
}
}
function register_setting() {
$('#setting-button').on('click', function() {
$('#setting-content').toggle();
function register_setting(is_on_user_status_bar) {
let $setting_button = is_on_user_status_bar ? $('.user-setting-button') : $('.setting-button');
$setting_button.on('click', function(e) {
e.stopPropagation();
$('.setting-content').not($(this).siblings('.setting-content')).hide();
$(this).siblings('.setting-content').toggle();
});
$('#setting-content li').on('click', function() {
$(this).children('a')[0].click();
})
$('#setting-content a').on('click', function() {
$('.setting-content a').on('click', function(e) {
e.stopPropagation();
var href = $(this).attr('href');
href += '?next=' + window.location.pathname;
$(this).attr('href', href);
})
$(document).on('click', function() {
$('.setting-content').hide();
});
}
$(function() {
$('#loader').hide();
@ -456,12 +478,13 @@
const button = document.querySelector('#emoji-button');
const tooltip = document.querySelector('.tooltip');
Popper.createPopper(button, tooltip, {
placement: isMobile ? 'auto-end' : 'left-end',
const popper = Popper.createPopper(button, tooltip, {
placement: isMobile ? 'auto-end' : 'left',
});
function toggleEmoji() {
tooltip.classList.toggle('shown')
tooltip.classList.toggle('shown');
popper.update();
}
$('#emoji-button').on('click', function(e) {
e.preventDefault();
@ -500,7 +523,9 @@
$('#search-handle').select2({
placeholder: '<i class="fa fa-search"></i> {{ _('Search by handle...') }}',
ajax: {
url: '{{ url('chat_user_search_select2_ajax') }}'
url: '{{ url('chat_user_search_select2_ajax') }}',
delay: 250,
cache: true,
},
minimumInputLength: 1,
escapeMarkup: function (markup) {
@ -547,7 +572,8 @@
characterData: false
})
}
register_setting();
register_setting(true);
register_setting(false);
color_selected_room();
$('#chat-input').on('input', function() {
@ -560,5 +586,8 @@
});
$('#submit-button').on('click', submit_chat);
register_copy_clipboard($("#chat-input"), () => {
$('#chat-input').trigger('input');
});
});
</script>

View file

@ -1,6 +1,6 @@
<li class="message" id="message-{{ message.id }}" message-id="{{ message.id }}">
<a href="{{ url('user_page', message.author.username) }}">
<img src="{{ gravatar(message.author, 135) }}" class="profile-pic">
<img loading="lazy" src="{{ gravatar(message.author, 135) }}" class="profile-pic user-img">
</a>
<div class="body-message">
<div class="user-time">
@ -23,7 +23,7 @@
{{_('Mute')}}
</a>
{% endif %}
<div class="message-text message-text-other">
<div class="message-text message-text-other" id="message-text-{{ message.id }}">
{{message.body|markdown(lazy_load=False)|reference|str|safe }}
</div>
</div>

View file

@ -6,4 +6,5 @@
{% endfor %}
{% else %}
<center id="empty_msg">{{_('You are connect now. Say something to start the conversation.')}}</center>
{% endif %}
{% endif %}

View file

@ -1,6 +1,6 @@
<li class="status-row" id="lobby_row">
<div class="status-container">
<img src="{{ static('icons/logo.png') }}" style="height:1.3em">
<img loading="lazy" src="{{ static('icons/icon.svg') }}" style="height:32px">
</div>
<span style="padding-left:0.5em">
<b>{{_('Lobby')}}</b>
@ -23,10 +23,9 @@
{% for user in section.user_list %}
<li class="click_space status-row" id="click_space_{{user.user.id}}" value="{{user.url}}">
<div class="status-container">
<img src="{{ gravatar(user.user, 135) }}" class="status-pic">
<img loading="lazy" src="{{ gravatar(user.user, 135) }}" class="status-pic user-img">
<svg style="position:absolute;" height="32" width="32">
<circle class="status-circle"
fill="{{'green' if user.is_online else 'red'}}"/>
<circle class="status-circle" fill="{{'green' if user.is_online else 'red'}}"/>
</svg>
</div>
<div class="status-user">
@ -44,8 +43,19 @@
{{user.unread_count}}
</span>
{% endif %}
<div style="margin-right: 0.3em; position: relative;">
<div class="control-button small setting-button">
<i class="fa fa-ellipsis-h"></i>
</div>
<div class="setting-content">
<a href="{{url('toggle_ignore', user.user.id)}}" class="red">
{{_('Ignore')}}
</a>
</div>
</div>
</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}

View file

@ -3,7 +3,7 @@
</div>
{% if other_user %}
<div class="status-container" style="height: 3em; width: 3em;">
<img src="{{ gravatar(other_user, 135) }}" class="info-pic">
<img src="{{ gravatar(other_user, 135) }}" class="info-pic user-img">
<svg style="position:absolute; height:100%; width: 100%; transform: rotate(180deg);" >
<circle class="info-circle"
fill="{{'green' if other_online else 'red'}}"/>
@ -11,7 +11,7 @@
</div>
{% else %}
<div class="status-container" style="height: 3em;">
<img src="{{ static('icons/logo.png') }}" class="info-pic" style="border-radius: 0px;">
<img src="{{ static('icons/icon.svg') }}" class="info-pic" style="border-radius: 0px;">
</div>
{% endif %}
<span class="info-name username">
@ -27,22 +27,20 @@
{% endif %}
{% if other_user %}
<span style="margin-right: 0.3em" id="setting">
<div class="control-button small" style="" id="setting-button">
<div style="margin-right: 0.3em; position: relative;">
<div class="control-button small user-setting-button">
<i class="fa fa-ellipsis-h"></i>
</div>
<div id="setting-content">
<li>
<a href="{{url('toggle_ignore', other_user.id)}}" class=" {{'green' if is_ignored else 'red'}}">
{% if is_ignored %}
{{_('Unignore')}}
{% else %}
{{_('Ignore')}}
{% endif %}
</a>
</li>
<div class="setting-content">
<a href="{{url('toggle_ignore', other_user.id)}}" class=" {{'green' if is_ignored else 'red'}}">
{% if is_ignored %}
{{_('Unignore')}}
{% else %}
{{_('Ignore')}}
{% endif %}
</a>
</div>
</span>
</div>
{% else %}
<span class="active-span">{{online_count}} {{_('users are online')}}</span>
{% endif %}

View file

@ -1,5 +1,5 @@
{% for node in mptt_tree(comment_list) recursive %}
<li id="comment-{{ node.id }}" data-revision="{{ node.revisions - 1 }}" data-max-revision="{{ node.revisions - 1 }}"
<li id="comment-{{ node.id }}" data-revision="{{ node.revision_count - 1 }}" data-max-revision="{{ node.revision_count - 1 }}"
data-revision-ajax="{{ url('comment_revision_ajax', node.id) }}" class="comment">
<div class="comment-display{% if node.score <= vote_hide_threshold %} bad-comment{% endif %}">
<div class="info">
@ -24,21 +24,16 @@
</div>
<div class="detail">
<div class="header">
{% with author=node.author, user=node.author.user %}
<a href="{{ url('user_page', user.username) }}" class="user comment-img">
<img src="{{ gravatar(author, 135) }}" class="gravatar">
</a>
{% endwith %}
{{ link_user(node.author) }},&nbsp;
{{ link_user(node.author_id, show_image=True) }}&nbsp;&nbsp;
{{ relative_time(node.time, abs=_('{time}'), rel=_('{time}')) }}
<span class="comment-spacer"></span>
<span class="comment-operation">
{% if node.revisions > 1 %}
{% if node.revision_count > 1 %}
<span class="comment-edits">
<a href="javascript:show_revision({{ node.id }}, -1)" class="previous-revision">&larr;</a>
<span class="comment-edit-text">
{% if node.revisions > 2 %}
{% trans edits=node.revisions - 1 %}edit {{ edits }}{% endtrans %}
{% if node.revision_count > 2 %}
{% trans edits=node.revision_count - 1 %}edit {{ edits }}{% endtrans %}
{% else %}
{{ _('edited') }}
{% endif %}
@ -53,10 +48,9 @@
<i class="fa fa-link fa-fw"></i>
</a>
{% if profile and not comment_lock %}
{% set can_edit = node.author.id == profile.id and not profile.mute %}
{% set can_edit = node.author_id == profile.id and not profile.mute %}
{% if can_edit %}
<a data-featherlight="{{ url('comment_edit_ajax', node.id) }}"
href="{{ url('comment_edit', node.id) }}" title="{{ _('Edit') }}" class="edit-link">
<a data-featherlight="{{ url('comment_edit_ajax', node.id) }}" href="#" title="{{ _('Edit') }}" class="edit-link">
<i class="fa fa-pencil fa-fw"></i>
</a>
{% else %}
@ -69,9 +63,9 @@
<a href="javascript:reply_comment({{ node.id }})" title="{{ _('Reply') }}"><i
class="fa fa-reply fa-fw"></i></a>
{% else %}
<a data-featherlight="{{ url('comment_edit_ajax', node.id) }}"
href="{{ url('comment_edit', node.id) }}" title="{{ _('Edit') }}" class="edit-link"><i
class="fa fa-pencil fa-fw"></i></a>
<a data-featherlight="{{ url('comment_edit_ajax', node.id) }}" href="#" title="{{ _('Edit') }}" class="edit-link">
<i class="fa fa-pencil fa-fw"></i>
</a>
{% endif %}
<a href="javascript:" title="{{ _('Hide') }}" data-id="{{ node.id }}" class="hide-comment"><i
class="fa fa-trash fa-fw"></i></a>

View file

@ -5,11 +5,11 @@
{{ comment.page_title }}
</a>
</h3>
{% with author=comment.author %}
{% if author %}
{% with author_id=comment.author_id %}
{% if author_id %}
<div class="problem-feed-info-entry">
<i class="fa fa-pencil-square-o fa-fw"></i>
<span class="pi-value">{{ link_user(author) }}</span>
<i class="far fa-pen-to-square"></i>
<span class="pi-value">{{ link_user(author_id) }}</span>
</div>
{% endif %}
{% endwith %}

View file

@ -1,36 +1,8 @@
<script src="{{ static('libs/featherlight/featherlight.min.js') }}" type="text/javascript"></script>
{% compress js %}
{{ comment_form.media.js }}
{% if not REQUIRE_JAX %}
<script type="text/javascript">
$(function () {
$('#id_body').keypress(function () {
if (!("MathJax" in window)) {
$.ajax({
type: "GET",
url: '{{ static('mathjax3_config.js') }}',
dataType: "script",
cache: true,
success: function () {
$.ajax({
type: "GET",
url: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js',
dataType: "script",
cache: true,
success: function () {
mathjax_pagedown($);
}
});
}
});
}
});
});
</script>
{% endif %}
<script type="text/javascript">
$(document).ready(function () {
let loading_gif = "<img src=\"{{static('loading.gif')}}\" style=\"height: 3em; margin-bottom: 3px\" class=\"loading\">";
let loading_gif = "<i class=\"fa fa-spinner fa-pulse loading\" style=\"font-size: 1.5em; margin-bottom: 1em;\"></i>";
window.reply_comment = function (parent) {
var $comment_reply = $('#comment-' + parent + '-reply');
var reply_id = 'reply-' + parent;
@ -61,10 +33,8 @@
});
function update_math($comment) {
if ('MathJax' in window) {
var $body = $comment.find('.comment-body');
MathJax.typeset($body[0]);
}
var $body = $comment.find('.comment-body');
renderKatex($body[0]);
}
window.show_revision = function (comment_id, offset) {
@ -145,7 +115,7 @@
$comment_loading.hide();
var $comment = $("#comment-" + id + "-children");
$comment.append(data);
MathJax.typeset($('#comments')[0]);
renderKatex($('#comments')[0]);
register_time($('.time-with-rel'));
}
})
@ -188,7 +158,7 @@
var $comment = $("#comment-" + id + "-children");
$comment.append(data);
}
MathJax.typeset($('#comments')[0]);
renderKatex($('#comments')[0]);
register_time($('.time-with-rel'));
}
})
@ -241,13 +211,14 @@
afterOpen: function () {
register_dmmd_preview($('#id-edit-comment-body-preview'));
if ('DjangoPagedown' in window) {
DjangoPagedown.createEditor(
$('#wmd-input-id-edit-comment-body').closest('.wmd-wrapper')[0]
);
register_copy_clipboard($('#wmd-input-id-edit-comment-body'));
var $wmd = $('.featherlight .wmd-wrapper');
if ($wmd.length) {
window.DjangoPagedown.createEditor($wmd.get(0));
if ('MathJax' in window) {
var preview = $('.featherlight div.wmd-preview')[0];
MathJax.typeset(preview);
}
var preview = $('.featherlight div.wmd-preview')[0];
renderKatex(preview);
}
}
$('#comment-edit').submit(function (event) {
@ -271,6 +242,11 @@
});
});
},
beforeClose: function() {
DjangoPagedown.destroyEditor(
$('#wmd-input-id-edit-comment-body').closest('.wmd-wrapper')[0]
);
},
variant: 'featherlight-edit'
});

View file

@ -1,4 +1 @@
{{ preview_data|markdown|reference|str|safe }}
{% if REQUIRE_JAX %}
<div data-config="{{ static('mathjax3_config.js') }}" class="require-mathjax-support"></div>
{% endif %}
{{ preview_data|markdown|reference|str|safe }}

View file

@ -21,34 +21,6 @@
info_float.width(container.width());
}
}
// TODO: remove this
var copyButton;
$('pre code').each(function () {
$(this).parent().before($('<div>', {'class': 'copy-clipboard'})
.append(copyButton = $('<span>', {
'class': 'btn-clipboard',
'data-clipboard-text': $(this).text(),
'title': 'Click to copy'
}).text('Copy')));
$(copyButton.get(0)).mouseleave(function () {
$(this).attr('class', 'btn-clipboard');
$(this).removeAttr('aria-label');
});
var curClipboard = new Clipboard(copyButton.get(0));
curClipboard.on('success', function (e) {
e.clearSelection();
showTooltip(e.trigger, 'Copied!');
});
curClipboard.on('error', function (e) {
showTooltip(e.trigger, fallbackMessage(e.action));
});
});
});
</script>
{% endcompress %}
@ -71,10 +43,4 @@
{% block comments %}{% endblock %}
</div>
</div>
{% endblock %}
{% block bodyend %}
{% if REQUIRE_JAX %}
{% include "mathjax-load.html" %}
{% endif %}
{% endblock %}
{% endblock %}

View file

@ -0,0 +1,7 @@
<script type="text/javascript">
$(document).ready(function () {
$('.time-remaining').each(function () {
count_down($(this));
});
});
</script>

View file

@ -1,10 +1,3 @@
<script type="text/javascript">
$(document).ready(function () {
$('.time-remaining').each(function () {
count_down($(this));
});
});
</script>
<div id="banner">
<a href="https://www.timeanddate.com/worldclock/fixedtime.html?msg={{ contest.name|urlquote('') }}&amp;iso=
{{- contest.start_time|utc|date('Y-m-d\TH:i:s') }}" class="date">

View file

@ -1,5 +1,8 @@
<div class="left-sidebar">
{{ make_tab_item('list', 'fa fa-list', url('contest_list'), _('List')) }}
{{ make_tab_item('list', 'fa fa-list', url('contest_list'), _('All')) }}
{{ make_tab_item('official', 'far fa-check-circle', url('official_contest_list'), _('Official')) }}
{{ make_tab_item('calendar', 'fa fa-calendar', url('contest_calendar', now.year, now.month), _('Calendar')) }}
{{ make_tab_item('admin', 'fa fa-edit', url('admin:judge_contest_changelist'), _('Admin')) }}
{% if perms.judge.change_contest %}
{{ make_tab_item('admin', 'fa fa-edit', url('admin:judge_contest_changelist'), _('Admin'), force_new_page=True) }}
{% endif %}
</div>

View file

@ -9,7 +9,7 @@
<div class="left-sidebar">
{% if can_access %}
{{ make_tab_item('detail', 'fa fa-info-circle', url('contest_view', contest.key), _('Info')) }}
{% if contest.ended or can_edit %}
{% if (contest.ended and not contest.is_in_contest(request.user)) or can_edit %}
{{ make_tab_item('stats', 'fa fa-pie-chart', url('contest_stats', contest.key), _('Statistics')) }}
{% endif %}
{% endif %}
@ -19,13 +19,12 @@
{{ 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 %}
{{ make_tab_item('resolver', 'fa fa-check', url('resolver', contest.key), _('Resolver')) }}
{{ make_tab_item('resolver', 'fa fa-check', url('resolver', contest.key), _('Resolver'), force_new_page=True) }}
{% endif %}
{% if show_final_ranking %}
{{ make_tab_item('final_ranking', 'fa fa-bar-chart', url('contest_final_ranking', contest.key), _('Final rankings')) }}
@ -34,6 +33,6 @@
{% if perms.judge.moss_contest and has_moss_api_key %}
{{ make_tab_item('moss', 'fa fa-gavel', url('contest_moss', contest.key), _('MOSS')) }}
{% endif %}
{{ make_tab_item('edit', 'fa fa-edit', url('admin:judge_contest_change', contest.id), _('Edit')) }}
{{ make_tab_item('edit', 'fa fa-edit', url('admin:judge_contest_change', contest.id), _('Edit'), force_new_page=True) }}
{% endif %}
</div>

View file

@ -14,6 +14,7 @@
{% include "contest/media-js.html" %}
{% include "comments/media-js.html" %}
{% include "actionbar/media-js.html" %}
{% include "contest/contest-datetime-js.html" %}
{% endblock %}
{% block two_col_media %}
@ -77,11 +78,15 @@
</form>
{% endif %}
<div style="clear: both"></div>
<div class="content-description">
{% cache 3600 'contest_html' contest.id MATH_ENGINE %}
{{ contest.description|markdown|reference|str|safe }}
{% endcache %}
</div>
{% if contest.is_organization_private %}
<div style="display: flex; margin-bottom: 1em">
{% for org in contest.organizations.all() %}
{% include "organization/tag.html" %}
{% endfor %}
</div>
{% endif %}
{% if editable_organizations or is_clonable %}
<div style="display: flex; gap: 0.5em;">
{% for org in editable_organizations %}
@ -95,6 +100,12 @@
</div>
{% endif %}
<div style="padding: 0 1em;">
{% cache 3600 'contest_html' contest.id %}
{{ contest.description|markdown|reference|str|safe }}
{% endcache %}
</div>
{% if contest.ended or request.user.is_superuser or is_editor or is_tester %}
<hr>
<div class="contest-problems">

View file

@ -42,16 +42,17 @@
</tr>
</thead>
<tbody>
{% for rank, item in total_rank %}
{% for rank, item in page_obj %}
<tr>
<td>
{{ rank }}
</td>
<td>
<div>
<span class="username {{ item.css_class }} wrapline" href="{{url('user_page', item.user.username)}}" >{{item.user.username}}</span>
<a href="{{url('user_page', item.username)}}"> <span class="username {{ item.css_class }} wrapline">{{item.username}}</span></a>
</div>
<div>{{item.user.first_name}}</div>
<div>{{item.first_name}}</div>
<div>{{item.last_name}}</div>
</td>
{% for point_contest, rank_contest in item.point_contests %}
<td>
@ -68,4 +69,9 @@
{% endfor %}
</tbody>
</table>
{% if page_obj and page_obj.num_pages > 1 %}
<div style="margin-top: 10px;">
{% include "list-pages.html" %}
</div>
{% endif %}
{% endblock %}

View file

@ -1,83 +1,51 @@
{% extends "two-column-content.html" %}
{% extends "three-column-content.html" %}
{% block meta %}
<meta name="description" content="The {{ SITE_NAME }}'s contest list - past, present, and future.">
{% endblock %}
{% block two_col_media %}
{% block three_col_media %}
<style>
.non-padding-top {
padding-top: 0;
}
.content-description ul {
padding: 0 !important;
}
.btn-contest {
display: inline-block;
padding: 1px 6px;
}
.contest-group-header {
padding-bottom: 1em;
#search-contest {
width: 100%;
height: 2.3em;
}
{% if page_obj and page_obj.number > 1%}
#ongoing-table {
display: none;
}
{% endif %}
@media (max-width: 500px) {
#search-contest, #search-org, #search-btn {
width: 100%;
margin-bottom: 0.5em;
}
#search-contest {
height: 2.5em;
}
#search-btn {
margin-top: 0.5em;
}
#filter-form input {
padding-left: 8px;
}
#search-org {
width: 100%;
}
@media (min-width: 500px) {
#filter-form input {
margin: 0 0.5em 0 0!important;
padding-left: 8px;
padding-top: 8px;
}
#search-contest {
width: 30%;
height: 2.3em;
margin-right: 1em;
margin-bottom: 0;
padding-top: 4px !important;
}
#search-org {
width: 40%;
}
#search-btn {
display: inline-block;
height: 2.3em;
margin-left: 0.5em;
}
.contest-format-user {
flex: 0.5 !important;
}
.participate-button {
float: right;
}
</style>
{% block contest_list_media %}{% endblock %}
{% endblock %}
{% block two_col_js %}
<script src="{{ static('libs/featherlight/featherlight.min.js') }}" type="text/javascript"></script>
{% block three_col_js %}
<script type="text/javascript">
$(document).ready(function () {
$('#active-url').attr('href', changeTabParameter('active'));
$('#current-url').attr('href', changeTabParameter('current'));
$('#future-url').attr('href', changeTabParameter('future'));
$('#past-url').attr('href', changeTabParameter('past'));
var $form = $('form#filter-form');
$('input#show_orgs').click(function () {
$form.submit();
$('#hide_organization_contests').click(function () {
submitFormWithParams($form, "POST");
});
$('#go').click(function() {
submitFormWithParams($form, "GET");
});
$('.time-remaining').each(function () {
count_down($(this));
@ -86,12 +54,29 @@
$('.contest-tag').find('a[data-featherlight]').featherlight();
$('.join-warning').click(function () {
return confirm('{{ _('Are you sure you want to join?') }}\n' +
'{{ _('Joining a contest for the first time starts your timer, after which it becomes unstoppable.') }}');
let q = '{{ _('Are you sure you want to join?') }}\n' +
'{{ _('Joining a contest for the first time starts your timer, after which it becomes unstoppable.') }}';
{% if request.in_contest %}
q += " {{ _('By joining in this contest, you will automatically leave contest') }} \"{{ request.participation.contest.name }}\". ";
{% endif %}
return confirm(q);
});
$('#search-org').select2({multiple: 1, placeholder: '{{ _('Groups') }}...'})
.css({'visibility': 'visible'});
$form.on('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
}
});
$('#search-contest').keypress(function (e) {
if (e.keyCode === 13) {
$('#go').click();
}
});
$('#search-org').select2({multiple: 1, placeholder: '{{ _('Groups') }}...'});
$('#order').select2();
// var tooltip_classes = 'tooltipped tooltipped-e';
//
@ -105,300 +90,145 @@
// });
});
</script>
{% block contest_list_js %}{% endblock %}
{% endblock %}
{% block left_sidebar %}
{% include "contest/contest-list-tabs.html" %}
{% endblock %}
{% macro contest_head(contest) %}
<a href="{{ url('contest_view', contest.key) }}" class="contest-list-title" style="margin-right: 5px;">
{{contest.name}}
</a>
<br>
<div class="contest-tags" style="margin-top: 5px;">
{% if not contest.is_visible %}
<span class="contest-tag contest-tag-hidden">
<i class="fa fa-eye-slash"></i> {{ _('hidden') }}
</span>
{% endif %}
{% if contest.is_editable %}
<span class="contest-tag contest-tag-edit">
<a href="{{ url('organization_contest_edit', organization.id, organization.slug, contest.key) }}" class="white">
<i class="fa fa-edit"></i> {{ _('Edit') }}
</a>
</span>
{% endif %}
{% if contest.is_private %}
<span class="contest-tag contest-tag-private">
<i class="fa fa-lock"></i> {{ _('private') }}
</span>
{% endif %}
{% if not hide_contest_orgs %}
{% if contest.is_organization_private %}
{% for org in contest.organizations.all() %}
<span class="contest-tag contest-tag-org">
<a href="{{ org.get_absolute_url() }}">
<i class="fa fa-lock"></i> {{ org.name }}
</a>
</span>
{% endfor %}
{% endif %}
{% endif %}
{% if contest.is_rated %}
<span class="contest-tag contest-tag-rated">
<i class="fa fa-bar-chart"></i> {{ _('rated') }}
</span>
{% endif %}
{% for tag in contest.tags.all() %}
<span style="background-color: {{ tag.color }}" class="contest-tag">
<a href="{{ url('contest_tag', tag.name) }}"
style="color: {{ tag.text_color }}"
data-featherlight="{{ url('contest_tag_ajax', tag.name) }}">
{{- tag.name -}}
</a>
</span>
{% endfor %}
{% block right_sidebar %}
<div class="right-sidebar">
{% include "contest/search-form.html" %}
</div>
{% endmacro %}
{% endblock %}
{% macro time_left(contest, padding_top = true) %}
<div class="time time-left {{ 'non-padding-top' if padding_top == false }}">
{% if contest.time_limit %}
{{ contest.start_time|date(_("M j, Y, G:i")) }} -
{{ contest.end_time|date(_("M j, Y, G:i")) }}
{% else %}
{{ contest.start_time|date(_("M j, Y, G:i")) }}
{% endif %}
<br>
{% if contest.time_limit %}
{% trans time_limit=contest.time_limit|timedelta('localized-no-seconds') %}{{ time_limit }} window{% endtrans %}
{% else %}
{% trans duration=contest.contest_window_length|timedelta('localized-no-seconds') %}{{ duration }} long{% endtrans %}
{% endif %}
</div>
{% endmacro %}
{% from "contest/macros.html" import contest_head, time_left, user_count, contest_format_user %}
{% macro user_count(contest, user) %}
{% if contest.can_see_own_scoreboard(user) %}
<a href="{{ url('contest_ranking', contest.key) }}">{{ contest.user_count }}</a>
{% macro contest_join(contest, request, is_past=False) %}
{% if request.in_contest and request.participation.contest == contest %}
<button class="small" disabled>{{ _('In contest') }}</button>
{% elif is_past %}
<form action="{{ url('contest_join', contest.key) }}" method="post">
{% csrf_token %}
<input type="submit" class="unselectable button full small"
value="{{ _('Virtual join') }}">
</form>
{% elif request.profile.id in contest.editor_ids or request.profile.id in contest.tester_ids %}
<form action="{{ url('contest_join', contest.key) }}" method="post">
{% csrf_token %}
<input type="submit" class="unselectable button full small"
value="{{ _('Spectate') }}">
</form>
{% else %}
{{ contest.user_count }}
{% endif %}
{% endmacro %}
{% macro contest_join(contest, request) %}
{% if not request.in_contest %}
{% if request.profile in contest.authors.all() or request.profile in contest.curators.all() or request.profile in contest.testers.all() %}
<form action="{{ url('contest_join', contest.key) }}" method="post">
{% csrf_token %}
<input type="submit" class="unselectable button full small"
value="{{ _('Spectate') }}">
</form>
{% else %}
<form action="{{ url('contest_join', contest.key) }}" method="post">
{% csrf_token %}
<input type="submit" class="unselectable button full small join-warning"
value="{{ _('Join') }}">
</form>
{% endif %}
<form action="{{ url('contest_join', contest.key) }}" method="post">
{% csrf_token %}
<input type="submit" class="unselectable button full small join-warning"
value="{{ _('Join') }}">
</form>
{% endif %}
{% endmacro %}
{% block middle_content %}
<div class="content-description">
<form id="filter-form">
<input id="search-contest" type="text" name="contest" value="{{ contest_query or '' }}"
placeholder="{{ _('Search contests...') }}">
{% if organizations %}
<select id="search-org" name="orgs" multiple>
{% for org in organizations %}
<option value="{{ org.id }}"{% if org.id in org_query %} selected{% endif %}>
{{ org.name }}
</option>
{% endfor %}
</select>
<div class="tabs tabs-no-flex" style="width: 100%;margin-left: auto;margin-right: auto;">
<ul>
{% if request.user.is_authenticated %}
<li class="{{'active' if current_tab=='active'}}">
<a id='active-url'>{{ _('Active') }}
{% if active_count %}
({{active_count}})
{% endif %}
</a>
</li>
{% endif %}
<button id="search-btn" class="btn-green small"> {{ _('Search')}} </button>
{% if organizations %}
<div>
<input id="show_orgs" type="checkbox" name="show_orgs" value="1" {% if show_orgs %}checked{% endif %}>
<label for="show_orgs">{{ _('Hide organization contests') }}</label>
</div>
{% endif %}
{% if create_url %}
<a href="{{create_url}}" class="button small" style="float: right"><i class="fa fa-plus"></i> {{ _('Create')}}</a>
{% endif %}
</form>
{% if active_participations %}
<h3 class="toggle open contest-group-header">
<i class="fa fa-chevron-right fa-fw"></i>
{{ _('Active Contests') }}
</h3>
<div class="toggled">
<li class="{{'active' if current_tab=='current'}}">
<a id='current-url'>{{ _('Ongoing') }}
{% if current_count %}
({{current_count}})
{% endif %}
</a>
</li>
<li class="{{'active' if current_tab=='future'}}">
<a id='future-url'>{{ _('Upcoming') }}
{% if future_count %}
({{future_count}})
{% endif %}
</a>
</li>
<li class="{{'active' if current_tab=='past'}}">
<a id='past-url'>{{ _('Past') }}</a>
</li>
</ul>
</div>
{% for participation in active_participations %}
{% with contest=participation.contest %}
<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">
{% if contest.start_time %}
{% if contest.time_limit %}
<span class="time">
{% trans countdown=participation.end_time|as_countdown %}Window ends in {{countdown}}{% endtrans %}
</span>
{% elif contest.time_before_end %}
<span class="time">{% trans countdown=contest.end_time|as_countdown %}Ends in {{countdown}}{% endtrans %}</span>
{% endif %}
{{ time_left(contest) }}
{% if request.user.is_authenticated and current_tab == 'active' %}
{% if contests %}
{% for participation in contests %}
{% with contest=participation.contest %}
<div class="list-contest">
<div class="info-contest">
<div class="contest-title"> {{ _('Contests') }} </div>
{{ contest_head(contest, organization) }}
</div>
<div class="info-contest">
<div class="contest-title"> {{ _('Time') }} </div>
<div class="contest-block">
{% if contest.start_time %}
{{ time_left(contest) }}
{% if contest.time_limit %}
<span class="time">
{% trans countdown=participation.end_time|as_countdown %}Window ends in {{countdown}}{% endtrans %}
</span>
{% elif contest.time_before_end %}
<span class="time">{% trans countdown=contest.end_time|as_countdown %}Ends in {{countdown}}{% endtrans %}</span>
{% endif %}
</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) }}
{% endif %}
</div>
</div>
<div class="info-contest contest-format-user">
{{ contest_format_user(contest, request, is_official=is_official) }}
<div class="participate-button">
{{ contest_join(contest, request) }}
</div>
</div>
{% endwith %}
{% endfor %}
</div>
<br>
</div>
{% endwith %}
{% endfor %}
{% if page_obj and page_obj.num_pages > 1 %}
<div style="margin-top: 10px;">
{% include "list-pages.html" %}
</div>
{% endif %}
{% else %}
<i> {{ _('There is no active contest at this time.') }} </i>
{% endif %}
{% endif %}
<h3 class="toggle open contest-group-header">
<i class="fa fa-chevron-right fa-fw"></i>
{{ _('Ongoing Contests') }}
</h3>
{% if current_contests %}
<div id="ongoing-table" class="toggled">
{% for contest in current_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">
{% if contest.start_time %}
{% if contest.time_before_end %}
<span class="time">{% trans countdown=contest.end_time|as_countdown %}Ends in {{countdown}}{% endtrans %}</span>
{% endif %}
{{ time_left(contest) }}
{% if current_tab == 'current' %}
{% if contests %}
{% for contest in contests %}
<div class="list-contest">
<div class="info-contest">
<div class="contest-title"> {{ _('Contests') }} </div>
{{ contest_head(contest, organization) }}
</div>
<div class="info-contest">
<div class="contest-title"> {{ _('Time') }} </div>
<div class="contest-block">
{% if contest.start_time %}
{{ time_left(contest) }}
{% if contest.time_before_end %}
<span class="time">{% trans countdown=contest.end_time|as_countdown %}Ends in {{countdown}}{% endtrans %}</span>
{% endif %}
</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) }}
{% endif %}
</div>
</div>
<div class="info-contest contest-format-user">
{{ contest_format_user(contest, request, is_official=is_official) }}
<div class="participate-button">
{{ contest_join(contest, request) }}
</div>
</div>
{% endfor %}
<br>
</div>
{% else %}
<div class="toggled">
<i> {{ _('There is no ongoing contest at this time.') }} </i>
<br>
</div>
{% endif %}
<h3 class="toggle open contest-group-header">
<i class="fa fa-chevron-right fa-fw"></i>
{{ _('Upcoming Contests') }}
</h3>
{% if future_contests %}
<div class="toggled">
{% for contest in future_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">
{% if contest.start_time %}
{% if contest.time_before_start %}
<span class="time">{{ _('Starting in %(countdown)s.', countdown=contest.start_time|as_countdown) }}</span>
{% endif %}
{{ time_left(contest) }}
{% endif %}
</div>
</div>
<div class="info-contest">
<div class="contest-title"> {{ _('Format') }} </div>
{{ contest.format.name }}
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="toggled">
<i>{{ _('There is no scheduled contest at this time.') }}</i>
<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 %}
@ -407,10 +237,73 @@
</div>
{% endif %}
{% else %}
<div class="toggled">
<i> {{ _('There is no past contest.') }} </i>
<br>
</div>
<i> {{ _('There is no ongoing contest at this time.') }} </i>
{% endif %}
</div>
{% endif %}
{% if current_tab == 'future' %}
{% if contests %}
{% for contest in contests %}
<div class="list-contest">
<div class="info-contest">
<div class="contest-title"> {{ _('Contests') }} </div>
{{ contest_head(contest, organization) }}
</div>
<div class="info-contest">
<div class="contest-title"> {{ _('Time') }} </div>
<div class="contest-block">
{% if contest.start_time %}
{{ time_left(contest) }}
{% if contest.time_before_start %}
<span class="time">{{ _('Starting in %(countdown)s.', countdown=contest.start_time|as_countdown) }}</span>
{% endif %}
{% endif %}
</div>
</div>
<div class="info-contest contest-format-user">
{{ contest_format_user(contest, request, show_user=False, is_official=is_official) }}
</div>
</div>
{% endfor %}
{% if page_obj and page_obj.num_pages > 1 %}
<div style="margin-top: 10px;">
{% include "list-pages.html" %}
</div>
{% endif %}
{% else %}
<i>{{ _('There is no scheduled contest at this time.') }}</i>
{% endif %}
{% endif %}
{% if current_tab == 'past' %}
{% if contests %}
{% for contest in contests %}
<div class="list-contest">
<div class="info-contest">
<div class="contest-title"> {{ _('Contests') }} </div>
{{ contest_head(contest, organization) }}
</div>
<div class="info-contest">
<div class="contest-title"> {{ _('Time') }} </div>
<div class="contest-block">
{{ time_left(contest) }}
</div>
</div>
<div class="info-contest contest-format-user">
{{ contest_format_user(contest, request, is_official=is_official) }}
<div class="participate-button">
{{ contest_join(contest, request, is_past=True) }}
</div>
</div>
</div>
{% endfor %}
{% if page_obj and page_obj.num_pages > 1 %}
<div style="margin-top: 10px;">
{% include "list-pages.html" %}
</div>
{% endif %}
{% else %}
<i> {{ _('There is no past contest.') }} </i>
{% endif %}
{% endif %}
{% endblock %}

View file

@ -0,0 +1,100 @@
{% macro contest_head(contest, organization=None) %}
<a href="{{ url('contest_view', contest.key) }}" class="contest-list-title" style="margin-right: 5px;">
{{contest.name}}
</a>
<div class="contest-tags">
{% if not contest.is_visible %}
<span class="contest-tag contest-tag-hidden">
<i class="fa fa-eye-slash"></i> {{ _('hidden') }}
</span>
{% endif %}
{% if organization and contest.is_editable %}
<span class="contest-tag contest-tag-edit">
<a href="{{ url('organization_contest_edit', organization.id, organization.slug, contest.key) }}" class="white">
<i class="fa fa-edit"></i> {{ _('Edit') }}
</a>
</span>
{% endif %}
{% if contest.is_private %}
<span class="contest-tag contest-tag-private">
<i class="fa fa-lock"></i> {{ _('private') }}
</span>
{% endif %}
{% if not organization %}
{% if contest.is_organization_private %}
{% for org in contest.organizations.all() %}
{% include "organization/tag.html" %}
{% endfor %}
{% endif %}
{% endif %}
{% if contest.is_rated %}
<span class="contest-tag contest-tag-rated">
<i class="fa fa-bar-chart"></i> {{ _('rated') }}
</span>
{% endif %}
{% for tag in contest.tags.all() %}
<span style="background-color: {{ tag.color }}" class="contest-tag">
<a href="{{ url('contest_tag', tag.name) }}"
style="color: {{ tag.text_color }}"
data-featherlight="{{ url('contest_tag_ajax', tag.name) }}">
{{- tag.name -}}
</a>
</span>
{% endfor %}
</div>
{% endmacro %}
{% macro time_left(contest) %}
<div class="time-left">
{% if contest.time_limit %}
<div>
<b>{{_("Start")}}</b>: {{ contest.start_time|date(_("H:i d/m/Y")) }}
</div>
<div>
<b>{{_("End")}}</b>: {{ contest.end_time|date(_("H:i d/m/Y")) }}
</div>
{% else %}
<div>
<b>{{_("Start")}}</b>: {{ contest.start_time|date(_("H:i d/m/Y")) }}
</div>
{% endif %}
<div>
<b>{{_("Length")}}</b>:
{% if contest.time_limit %}
{% trans time_limit=contest.time_limit|timedelta('localized-no-seconds') %}{{ time_limit }}{% endtrans %}
{% else %}
{% trans duration=contest.contest_window_length|timedelta('localized-no-seconds') %}{{ duration }}{% endtrans %}
{% endif %}
</div>
</div>
{% endmacro %}
{% macro user_count(contest, user) %}
{% if contest.can_see_own_scoreboard(user) %}
<a href="{{ url('contest_ranking', contest.key) }}"><i class="fa fa-users"></i> {{ contest.user_count }}</a>
{% else %}
<i class="fa fa-users"></i>{{ contest.user_count }}
{% endif %}
{% endmacro %}
{% macro contest_format_user(contest, request, show_user=True, is_official=False) %}
{% if is_official %}
<div style="display: flex; flex-direction: column;">
<div><b>{{ _('Format') }}</b>: {{ contest.format.name }}</div>
<div><b>{{ _('Category') }}</b>: {{ contest.official.category.name }}</div>
<div><b>{{ _('Location') }}</b>: {{ contest.official.location.name }}</div>
<div><b>{{ _('Year') }}</b>: {{ contest.official.year }}</div>
{% if show_user %}
<div class="contest-title" style="margin-top: 0.4em">{{ user_count(contest, request.user) }}</div>
{% endif %}
</div>
{% else %}
<div style="display: flex; flex-direction: column;">
<div class="contest-title"> {{ _('Format') }} </div>
<div style="flex-grow: 1">{{ contest.format.name }}</div>
{% if show_user %}
<div class="contest-title" style="margin-top: 0.4em">{{ user_count(contest, request.user) }}</div>
{% endif %}
</div>
{% endif %}
{% endmacro %}

View file

@ -149,8 +149,12 @@
});
$('.first-join').click(function () {
return confirm('{{ _('Are you sure you want to join?') }}\n' +
'{{ _('Joining a contest starts your timer, after which it becomes unstoppable.') }}');
let q = '{{ _('Are you sure you want to join?') }}\n' +
'{{ _('Joining a contest starts your timer, after which it becomes unstoppable.') }}';
{% if current_contest %}
q += " {{ _('By joining in this contest, you will automatically leave contest') }} \"{{ current_contest.name }}\". ";
{% endif %}
return confirm(q);
});
var url = '{{ url('contest_participation', contest.key, '__username__') }}';
@ -161,7 +165,9 @@
$('#search-contest').select2({
placeholder: placeholder,
ajax: {
url: '{{ url('contest_user_search_select2_ajax', contest.key) }}'
url: '{{ url('contest_user_search_select2_ajax', contest.key) }}',
cache: true,
delay: 250,
},
minimumInputLength: 1,
escapeMarkup: function (markup) {

View file

@ -0,0 +1,57 @@
<div class="sidebox">
<h3 class="colored-text"><i class="fa fa-search"></i>{{ _('Contest search') }}</h3>
<div class="sidebox-content">
<form id="filter-form" method="GET">
<input id="search-contest" type="text" name="contest" value="{{ contest_query or '' }}"
placeholder="{{ _('Search contests...') }}">
<div class="filter-form-group">
<label class="bold-text margin-label" for="year_from"><i class="non-italics">{{ _('Year') }}</i></label>
<div class="year-range">
<input type="number" name="year_from" id="year_from" value="{{ year_from or '' }}"
placeholder="{{ _('From') }}">
<input type="number" name="year_to" id="year_to" value="{{ year_to or '' }}"
placeholder="{{ _('To') }}" style="float: right">
</div>
</div>
<div class="filter-form-group">
<label class="bold-text margin-label" for="category"><i class="non-italics">{{ _('Category') }}</i></label>
<select id="category" name="category" multiple>
{% for cat in categories %}
<option value="{{ cat.id }}"{% if cat.id in selected_categories %} selected{% endif %}>
{{ cat.name }}
</option>
{% endfor %}
</select>
</div>
<div class="filter-form-group">
<label class="bold-text margin-label" for="location"><i class="non-italics">{{ _('Location') }}</i></label>
<select id="location" name="location" style="width: 100%" multiple>
{% for loc in locations %}
<option value="{{ loc.id }}"{% if loc.id in selected_locations %} selected{% endif %}>
{{ loc.name }}
</option>
{% endfor %}
</select>
</div>
<div class="filter-form-group">
<label for="order" class="bold-text margin-label">{{ _('Order by') }}</label>
<select id="order" name="order" style="width: 100%">
<option value="">---</option>
{% for value, name in all_sort_options %}
<option value="{{value}}"{% if selected_order == value%} selected{% endif %}>
{{ name }}
</option>
{% endfor %}
</select>
</div>
<div class="form-submit-group">
<a id="go" class="button small">{{ _('Go') }}</a>
</div>
</form>
</div>
</div>

View file

@ -0,0 +1,42 @@
{% extends "contest/list.html" %}
{% block contest_list_media %}
<style type="text/css">
.contest-format-user {
flex: 1 !important;
}
.year-range {
display: inline;
}
.year-range input {
width: 45%;
}
</style>
{% endblock %}
{% block contest_list_js %}
<script type="text/javascript">
$(function() {
$("#category").select2();
$("#location").select2();
$('#year_from').keypress(function (e) {
if (e.keyCode === 13) {
$('#go').click();
}
});
$('#year_to').keypress(function (e) {
if (e.keyCode === 13) {
$('#go').click();
}
});
});
</script>
{% endblock %}
{% block right_sidebar %}
<div class="right-sidebar">
{% include "contest/official-search-form.html" %}
</div>
{% endblock %}

View file

@ -1,4 +1 @@
{{ preview_data|markdown|reference|str|safe }}
{% if REQUIRE_JAX %}
<div data-config="{{ static('mathjax3_config.js') }}" class="require-mathjax-support"></div>
{% endif %}

View file

@ -1,10 +1,6 @@
<style>
#users-table .username {
min-width: 15em;
}
#users-table td {
height: 2.5em;
min-height: 2.5em;
}
#users-table a {
@ -32,8 +28,11 @@
}
.user-name {
position: relative;
padding-left: 2em !important;
padding-left: 1em !important;
padding-right: 1em !important;
display: flex;
min-width: max-content;
align-items: center;
}
.organization-column {
@ -43,7 +42,6 @@
}
.featherlight-content {
border-radius: 10px;
height: 80%;
width: 60%;
overflow: auto;

View file

@ -13,18 +13,23 @@
{% endblock %}
{% block user_footer %}
{% if user.user.first_name %}
{% set profile = user.user %}
{% if profile.first_name %}
<div style="font-weight: 600; display: none" class="fullname gray">
{{ user.user.first_name }}
{{ profile.first_name }}
</div>
{% endif %}
{% if user.user.last_name %}
{% if profile.last_name %}
<div class="school gray" style="display: none"><div style="font-weight: 600">
{{- user.user.last_name -}}
{{ profile.last_name }}
</div></div>
{% endif %}
{% endblock %}
{% block user_link %}
{{ link_user(user.user, show_image=True) }}
{% endblock %}
{% block user_data %}
{% if user.participation.virtual %}
<sub class="gray">[{{user.participation.virtual}}]</sub>

View file

@ -9,6 +9,7 @@
{% endblock %}
{% block users_js_media %}
{% include "contest/contest-datetime-js.html" %}
{% if can_edit %}
<script type="text/javascript">
$(function () {
@ -127,12 +128,14 @@
{% block before_table %}
{% include "contest/contest-datetime.html" %}
<div style="margin-bottom: 0.5em">
{% if page_type == 'participation' %}
{% if contest.can_see_full_scoreboard(request.user) %}
{% if page_type == 'participation' %}
{% if contest.can_see_full_scoreboard(request.user) %}
<div style="margin-bottom: 0.5em">
<input id="search-contest" type="text" placeholder="{{ _('View user participation') }}">
{% endif %}
</div>
{% endif %}
{% endif %}
<div style="margin-bottom: 0.5em">
<input id="show-schools-checkbox" type="checkbox" style="vertical-align: bottom">
<label for="show-schools-checkbox" style="vertical-align: bottom; margin-right: 1em;">{{ _('Show schools') }}</label>
@ -147,8 +150,8 @@
<label for="show-total-score-checkbox" style="vertical-align: bottom; margin-right: 1em;">{{ _('Total score only') }}</label>
<input id="show-virtual-checkbox" type="checkbox" style="vertical-align: bottom;">
<label id="show-virtual-label" for="show-virtual-checkbox" style="vertical-align: bottom; margin-right: 1em;">{{ _('Show virtual participation') }}</label>
<img src="{{static('loading.gif')}}" style="height: 1em; display:none;" id="loading-gif"></img>
<a href="#" onclick="download_ranking_as_csv()" style="float: right;">
<i class="fa fa-spinner fa-pulse" style="display: none" id="loading-gif"></i>
<a href="#" onclick="download_ranking_as_csv()">
<i class="fa fa-download" aria-hidden="true"></i>
{{ _('Download as CSV') }}
</a>

View file

@ -0,0 +1,40 @@
<div class="sidebox">
<h3 class="colored-text"><i class="fa fa-search"></i>{{ _('Contest search') }}</h3>
<div class="sidebox-content">
<form id="filter-form" method="GET">
<input id="search-contest" type="text" name="contest" value="{{ contest_query or '' }}"
placeholder="{{ _('Search contests...') }}">
{% if organizations %}
<div style="margin-bottom: 1em;">
<input id="hide_organization_contests" type="checkbox" name="hide_organization_contests" value="1" {% if hide_organization_contests %}checked{% endif %}>
<label for="hide_organization_contests">{{ _('Hide organization contests') }}</label>
</div>
<label for="search-org" class="bold-text margin-label">{{ _('Group') }}</label>
<select id="search-org" name="orgs" multiple>
{% for org in organizations %}
<option value="{{ org.id }}"{% if org.id in org_query %} selected{% endif %}>
{{ org.name }}
</option>
{% endfor %}
</select>
{% endif %}
<div class="filter-form-group">
<label for="order" class="bold-text margin-label">{{ _('Order by') }}</label>
<select id="order" name="order" style="width: 100%">
<option value="">---</option>
{% for value, name in all_sort_options %}
<option value="{{value}}"{% if selected_order == value%} selected{% endif %}>
{{ name }}
</option>
{% endfor %}
</select>
</div>
<div class="form-submit-group">
<a id="go" class="button small">{{ _('Go') }}</a>
{% if create_url %}
<a href="{{ create_url }}" class="button small"><i class="fa fa-plus"></i> {{ _('Create') }}</a>
{% endif %}
</div>
</form>
</div>
</div>

View file

@ -0,0 +1,4 @@
{% extends "submission/list.html" %}
{% block left_sidebar %}
{% include "contest/contest-tabs.html" %}
{% endblock %}

View file

@ -4,4 +4,4 @@
<hr>
{% endif %}
{{ tag.description|markdown }}
{{ tag.description }}

View file

@ -1,6 +1,6 @@
{% if current_contests %}
<div class="blog-sidebox sidebox">
<h3 class="bold-text colored-text"><i class="fa fa-trophy"></i> {{ _('Ongoing contests') }}</h3>
<h3 class="bold-text colored-text"><i class="fa fa-ranking-star"></i> {{ _('Ongoing contests') }}</h3>
<div class="sidebox-content">
{% for contest in current_contests %}
<div class="contest">
@ -18,7 +18,7 @@
{% if future_contests %}
<div class="blog-sidebox sidebox">
<h3 class="bold-text colored-text"><i class="fa fa-trophy"></i>{{ _('Upcoming contests') }}</h3>
<h3 class="bold-text colored-text"><i class="fa fa-ranking-star"></i>{{ _('Upcoming contests') }}</h3>
<div class="sidebox-content">
{% for contest in future_contests %}
<div class="contest">

View file

@ -1,12 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Courses</title>
</head>
<body>
</body>
</html>
{% extends "two-column-content.html" %}
{% block left_sidebar %}
{% include "course/left_sidebar.html" %}
{% endblock %}

View file

@ -0,0 +1,39 @@
{% extends "course/base.html" %}
{% block middle_content %}
<center><h2>{{title}}</h2></center>
<h3 class="course-content-title">{{_("About")}}</h3>
<div>
{{ course.about|markdown|reference|str|safe }}
</div>
<h3 class="course-content-title">{{_("Lessons")}}</h3>
<ul class="lesson-list">
{% for lesson in lessons %}
<a href="{{url('course_lesson_detail', course.slug, lesson.id)}}">
{% set progress = lesson_progress[lesson.id] %}
<li>
<div class="lesson-title">
{{ lesson.title }}
<div class="lesson-points">
{{progress['achieved_points'] | floatformat(1)}} / {{lesson.points}}
</div>
</div>
<div class="progress-container">
<div class="progress-bar" style="width: {{progress['percentage']}}%;">{{progress['percentage']|floatformat(0)}}%</div>
</div>
</li>
</a>
{% endfor %}
</ul>
<h3 class="course-content-title">
{% set total_progress = lesson_progress['total'] %}
{% set achieved_points = total_progress['achieved_points'] %}
{% set total_points = total_progress['total_points'] %}
{% set percentage = total_progress['percentage'] %}
{{_("Total achieved points")}}:
<span style="float: right; font-weight: normal;">
{{ achieved_points | floatformat(2) }} / {{ total_points }} ({{percentage|floatformat(1)}}%)
</span>
</h3>
{% endblock %}

View file

@ -0,0 +1,58 @@
{% extends "course/base.html" %}
{% block two_col_media %}
{{ form.media.css }}
<style type="text/css">
.field-order, .field-title, .field-points {
display: inline-flex;
}
.form-header {
margin-bottom: 0.5em;
}
</style>
{% endblock %}
{% block two_col_js %}
{{ form.media.js }}
{% endblock %}
{% block middle_content %}
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<h3 class="toggle {{'open' if form.errors else 'closed'}} form-header"><i class="fa fa-chevron-right fa-fw"></i>
{% if form.title.value() %}
{{form.order.value()}}. {{form.title.value()}}
{% else %}
+ {{_("Add new")}}
{% endif %}
</h3>
<div class="toggled" style="{{'display: none;' if not form.errors}} margin-bottom: 1em">
{{form.id}}
{% if form.errors %}
<div class="alert alert-danger alert-dismissable">
<a href="#" class="close">x</a>
{{_("Please fix below errors")}}
</div>
{% endif %}
{% for field in form %}
{% if not field.is_hidden %}
<div style="margin-bottom: 1em;">
{{ field.errors }}
<label for="{{field.id_for_label }}"><b>{{ field.label }}{% if field.field.required %}<span class="red"> * </span>{% endif %}:</b> </label>
<div class="org-field-wrapper field-{{field.name}}" id="org-field-wrapper-{{field.html_name}}">
{{ field }}
</div>
{% if field.help_text %}
<small class="org-help-text"><i class="fa fa-exclamation-circle"></i> {{ field.help_text|safe }}</small>
{% endif %}
</div>
{% endif %}
{% endfor %}
<hr/>
</div>
{% endfor %}
<input type="submit" value="{{_('Save')}}" style="float: right">
</form>
{% endblock %}

View file

@ -0,0 +1,127 @@
{% extends "course/base.html" %}
{% block two_col_media %}
<style type="text/css">
table {
font-size: 15px;
}
td {
height: 2.5em;
}
.user-name {
padding-left: 1em !important;
}
#search-input {
float: right;
margin-bottom: 1em;
}
</style>
{% endblock %}
{% block two_col_js %}
<script>
$(document).ready(function(){
var $searchInput = $("#search-input");
var $usersTable = $("#users-table");
var tableBorderColor = $('#users-table td').css('border-bottom-color');
$searchInput.on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#users-table tbody tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
if(value) {
$('#users-table').css('border-bottom', '1px solid ' + tableBorderColor);
} else {
$('#users-table').css('border-bottom', '');
}
});
$('#sortSelect').select2({
minimumResultsForSearch: -1,
width: "10em",
});
$('#sortSelect').on('change', function() {
var rows = $('#users-table tbody tr').get();
var sortBy = $(this).val();
rows.sort(function(a, b) {
var keyA = $(a).find(sortBy === 'username' ? '.user-name' : 'td:last-child').text().trim();
var keyB = $(b).find(sortBy === 'username' ? '.user-name' : 'td:last-child').text().trim();
if(sortBy === 'total') {
// Convert percentage string to number for comparison
keyA = -parseFloat(keyA.replace('%', ''));
keyB = -parseFloat(keyB.replace('%', ''));
}
else {
keyA = keyA.toLowerCase();
keyB = keyB.toLowerCase();
}
if(keyA < keyB) return -1;
if(keyA > keyB) return 1;
return 0;
});
$.each(rows, function(index, row) {
$('#users-table tbody').append(row);
});
});
});
</script>
{% endblock %}
{% block middle_content %}
<center><h2>{{title}}</h2></center>
{% set lessons = course.lessons.all() %}
{{_("Sort by")}}:
<select id="sortSelect">
<option value="username">{{_("Username")}}</option>
<option value="total">{{_("Score")}}</option>
</select>
<input type="text" id="search-input" placeholder="{{_('Search')}}" autofocus>
<table class="table striped" id="users-table">
<thead>
<tr>
<th>{{_('Student')}}</th>
{% if grades|length > 0 %}
{% for lesson in lessons %}
<th class="points">
<a href="{{url('course_lesson_detail', course.slug, lesson.id)}}">
{{ lesson.title }}
<div class="point-denominator">{{lesson.points}}</div>
</a>
</th>
{% endfor %}
{% endif %}
<th>{{_('Total')}}</th>
</tr>
</thead>
<tbody>
{% for student, grade in grades.items() %}
<tr>
<td class="user-name">
<div>
{{link_user(student)}}
</div>
<div>
{{student.first_name}}
</div>
</td>
{% for lesson in lessons %}
<td class="partial-score">
<a href="{{url('course_lesson_detail', course.slug, lesson.id)}}?user={{student.username}}">
{{ grade[lesson.id]['percentage'] | floatformat(0) }}%
</a>
</td>
{% endfor %}
<td style="font-weight: bold">
{{ grade['total']['percentage'] | floatformat(0) }}%
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View file

@ -0,0 +1,10 @@
<div class="left-sidebar">
{{ make_tab_item('home', 'fa fa-home', course.get_absolute_url(), _('Home')) }}
{% if is_editable %}
{{ make_tab_item('edit_lesson', 'fa fa-edit', url('edit_course_lessons', course.slug), _('Edit lessons')) }}
{{ make_tab_item('grades', 'fa fa-check-square', url('course_grades', course.slug), _('Grades')) }}
{% endif %}
{% if perms.judge.change_course %}
{{ make_tab_item('admin', 'fa fa-edit', url('admin:judge_course_change', course.id), _('Admin'), force_new_page=True) }}
{% endif %}
</div>

View file

@ -0,0 +1,39 @@
{% extends "course/base.html" %}
{% block two_col_media %}
<style>
</style>
{% endblock %}
{% block middle_content %}
<center><h2>{{title}}</h2></center>
<h3 class="course-content-title">{{_("Content")}}</h3>
<div>
{{ lesson.content|markdown|reference|str|safe }}
</div>
<h3 class="course-content-title">{{_("Problems")}}</h3>
<ul class="course-problem-list">
{% for problem in lesson.problems.all() %}
<a href="{{url('problem_detail', problem.code)}}">
<li>
{% if problem.id in completed_problem_ids %}
<i class="solved-problem-color fa fa-check-circle"></i>
{% elif problem.id in attempted_problems %}
<i class="attempted-problem-color fa fa-minus-circle"></i>
{% else %}
<i class="unsolved-problem-color fa fa-minus-circle"></i>
{% endif %}
<span class="problem-name">{{problem.name}}</span>
{% set pp = problem_points[problem.id] %}
<span class="score">
{% if pp %}
{{pp.case_points|floatformat(1)}} / {{pp.case_total|floatformat(0)}}
{% else %}
0
{% endif %}
</span>
</li>
</a>
{% endfor %}
</ul>
{% endblock %}

View file

@ -1,19 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Enrolling</h1>
{% for course in enrolling %}
<h2> {{ course }} </h2>
{% extends "two-column-content.html" %}
{% block two_col_media %}
{% endblock %}
{% block left_sidebar %}
<div class="left-sidebar">
{{ make_tab_item('list', 'fa fa-list', url('course_list'), _('Courses')) }}
</div>
{% endblock %}
{% block middle_content %}
<div class="course-list">
{% for course in courses %}
<div class="course-item">
<div class="course-image">
<img loading="lazy" src="{{course.image_url}}">
</div>
<div class="course-content">
<a href="{{url('course_detail', course.slug)}}" class="course-name">{{course.name}}</a>
{% set teachers = course.get_teachers() %}
{% if teachers %}
<div class="course-teachers">{{_('Teachers')}}: {{link_users(teachers)}}</div>
{% endif %}
</div>
</div>
{% endfor %}
<h1> Available </h1>
{% for course in available %}
<h2> {{ course }} </h2>
{% endfor %}
</body>
</html>
</div>
{% endblock %}

View file

@ -0,0 +1,16 @@
{% extends "base.html" %}
{% block body %}
<center>
{% if file_url %}
<p>{{_('Your file has been uploaded successfully')}}: <a href="{{ file_url }}" target="_blank">{{ file_url }}</a></p>
<a href="{{ url('custom_file_upload') }}" class="button small" style="width: fit-content;">{{_('Upload another file')}}</a>
{% else %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p() }}
<button type="submit">{{_('Upload file')}}</button>
</form>
{% endif %}
</center>
{% endblock %}

View file

@ -30,9 +30,8 @@
window.loading_page = false;
window.has_next_page = parseInt($(".has_next").attr("value"));
window.page++;
MathJax.typeset($('.middle-content')[0]);
renderKatex($('.middle-content')[0]);
onWindowReady();
activateBlogBoxOnClick();
})
}

View file

@ -2,8 +2,4 @@
{% block body %}
<div class="content-description">{{ flatpage.content|markdown|reference }}</div>
{% endblock %}
{% block bodyend %}
{% if REQUIRE_JAX %}{% include "mathjax-load.html" %}{% endif %}
{% endblock %}

View file

@ -0,0 +1,4 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" integrity="sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js" integrity="sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"
onload="renderKatex();"></script>

View file

@ -1,21 +1,23 @@
{% set layout='no_wrapper' %}
{% extends "base.html" %}
{% block media %}
<style>
main{
body{
overflow: hidden;
}
#content{
width: 100%;
}
#content.wrapper{
height: calc(100vh - 50px);
margin-bottom: 0;
padding: 0;
}
.form-area{
float: left;
width: 47%;
height: 100%
#content-body {
padding: 0;
height: 100%;
display: flex;
}
.wmd-preview{
float: right;
margin-top: 0;
@ -23,60 +25,53 @@
.width-controller{
width: 51%;
}
.wmd-input{
height: calc(100vh - 72px);
#id_body-preview{
overflow: scroll;
}
.right-markdown{
height: calc(100vh - 72px);
overflow-y: scroll;
}
.wrap{
display: flex;
.form-area {
flex-grow: 1;
}
</style>
{% endblock %}
{% block js_media %}
<script>
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const context = this;
const later = () => {
clearTimeout(timeout);
func.apply(context, args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
function update_preview() {
$.ajax({
url: "{{url('blog_preview')}}",
type: 'POST',
data: {
preview: $(this).val()
},
success: function(data) {
$('#display').html(data);
renderKatex();
populateCopyButton();
},
error: function(error) {
console.log(error.message);
}
})
}
$(document).ready(function(){
$("#wmd-input-id_body").on("keyup", function() {
const csrfToken = "{{ csrf_token }}";
$.ajax({
url: "{{url('blog_preview')}}",
type: 'POST',
headers: {
'X-CSRFToken': csrfToken, // Include the CSRF token in the headers
},
data: {
preview: $(this).val()
},
success: function(data) {
$('#display').html(data);
MathJax.typeset();
},
error: function(error) {
alert(error);
console.log(error.message)
}
})
});
});
</script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const leftDiv = document.getElementById("wmd-input-id_body");
const rightDiv = document.getElementById("display");
leftDiv.addEventListener("scroll", function() {
rightDiv.scrollTop = leftDiv.scrollTop;
});
rightDiv.addEventListener("scroll", function() {
leftDiv.scrollTop = rightDiv.scrollTop;
});
const debounced_update_preview = debounce(update_preview, 250);
$("#wmd-input-id_body").on("keyup", debounced_update_preview);
});
</script>
@ -86,8 +81,6 @@
<script src="{{ static('pagedown/Markdown.Editor.js') }}"></script>
<script src="{{ static('pagedown-extra/Markdown.Extra.js') }}"></script>
<script src="{{ static('pagedown_init.js') }}"></script>
<script src="{{ static('mathjax3_config.js') }}"></script>
<script src="http://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
<script src="{{ static('pagedown_math.js') }}"></script>
{% endblock %}
@ -98,46 +91,44 @@
{% endblock %}
{% block body %}
<div class="wrap">
<div id="new-comment" class="form-area">
<input type="hidden" name="parent" id="id_parent">
<div class="comment-post-wrapper">
<div id="comment-form-body"><div class="wmd-wrapper image-upload-enabled">
<div class="wmd-panel">
<div id="wmd-button-bar-id_body"></div>
<textarea id="wmd-input-id_body" class="wmd-input" name="body" required=""></textarea>
</div>
<div id="id_body-preview" data-preview-url="{{url('comment_preview')}}" data-textarea-id="wmd-input-id_body" data-timeout="1000" class="wmd-panel wmd-preview dmmd-preview dmmd-no-button">
<div class="dmmd-preview-update"><i class="fa fa-refresh"></i> {{_('Update Preview')}}</div>
<div class="dmmd-preview-content content-description"></div>
</div>
<div class="pagedown-image-upload">
<h2>{{_('Insert Image')}}</h2>
<div class="form-row">
<div>
<label class="label">{{_('From the web')}}</label>
<input class="url-input" type="text" placeholder="http://">
</div>
</div>
<div class="form-row">
<div>
<label class="label">{{_('From your computer')}}</label>
<input class="file-input" type="file" name="image" id="file" data-action="/pagedown/image-upload/" accept="image/*">
</div>
</div>
<div class="submit-row">
<div class="submit-loading"></div>
<input class="submit-input show" type="submit" value="{{_('Save')}}" name="_addanother">
<p class="deletelink-box"><a href="#" class="close-image-upload deletelink">{{_('Cancel')}}</a></p>
<div id="new-comment" class="form-area">
<input type="hidden" name="parent" id="id_parent">
<div class="comment-post-wrapper">
<div id="comment-form-body"><div class="wmd-wrapper image-upload-enabled">
<div class="wmd-panel">
<div id="wmd-button-bar-id_body"></div>
<textarea id="wmd-input-id_body" class="wmd-input" name="body" required=""></textarea>
</div>
<div id="id_body-preview" data-preview-url="{{url('comment_preview')}}" data-textarea-id="wmd-input-id_body" data-timeout="1000" class="wmd-panel wmd-preview dmmd-preview dmmd-no-button">
<div class="dmmd-preview-update"><i class="fa fa-refresh"></i> {{_('Update Preview')}}</div>
<div class="dmmd-preview-content content-description"></div>
</div>
<div class="pagedown-image-upload">
<h2>{{_('Insert Image')}}</h2>
<div class="form-row">
<div>
<label class="label">{{_('From the web')}}</label>
<input class="url-input" type="text" placeholder="http://">
</div>
</div>
</div></div>
</div>
<div class="form-row">
<div>
<label class="label">{{_('From your computer')}}</label>
<input class="file-input" type="file" name="image" id="file" data-action="/pagedown/image-upload/" accept="image/*">
</div>
</div>
<div class="submit-row">
<div class="submit-loading"></div>
<input class="submit-input show" type="submit" value="{{_('Save')}}" name="_addanother">
<p class="deletelink-box"><a href="#" class="close-image-upload deletelink">{{_('Cancel')}}</a></p>
</div>
</div>
</div></div>
</div>
</div>
<div id="id_body-preview" data-preview-url="{{url('comment_preview')}}" data-textarea-id="wmd-input-id_body" data-timeout="1000" class="width-controller wmd-panel wmd-preview dmmd-preview dmmd-no-button dmmd-preview-has-content">
<div class="right-markdown dmmd-preview-content content-description" id="display"></div>
</div>
<div id="id_body-preview" data-preview-url="{{url('comment_preview')}}" data-textarea-id="wmd-input-id_body" data-timeout="1000" class="width-controller wmd-panel wmd-preview dmmd-preview dmmd-no-button dmmd-preview-has-content">
<div class="right-markdown dmmd-preview-content content-description" id="display"></div>
</div>
{% endblock %}

View file

@ -1,2 +0,0 @@
<script type="text/javascript" src="{{ static('mathjax3_config.js') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>

View file

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block body %}
{% if not has_notifications %}
{% if not notifications %}
<h2 style="text-align: center;">{{ _('You have no notifications') }}</h2>
{% else %}
<table class="table">
@ -14,7 +14,7 @@
{% for notification in notifications %}
<tr class="{{ 'highlight' if not notification.seen }}">
<td>
{{ link_user(notification.author) }}
{{ link_user(notification.author_id) }}
</td>
<td>
{{ notification.category }}
@ -31,5 +31,8 @@
{% endfor %}
</table>
{% endif %}
<div style="margin-top: 10px;">
{% include "list-pages.html" %}
</div>
{% endblock %}

View file

@ -13,7 +13,8 @@
#org-field-wrapper-end_time,
#org-field-wrapper-time_limit,
#org-field-wrapper-format_name,
#org-field-wrapper-freeze_after {
#org-field-wrapper-freeze_after,
#org-field-wrapper-rate_limit {
display: inline-flex;
}
.problems-problem {

View file

@ -14,10 +14,5 @@
$(this).parent().submit();
}
});
$('#control-panel a').on('click', function(e) {
e.preventDefault();
navigateTo($(this));
})
});
</script>

View file

@ -10,16 +10,9 @@
{% block middle_title %}
<div class="page-title">
<div class="tabs" style="border: none;">
<h2><img src="{{logo_override_image}}" style="height: 3rem; vertical-align: middle">
<h2><img src="{{logo_override_image}}" style="height: 3rem; vertical-align: middle; border-radius: 5px;">
{{title}}
</h2>
{% if is_member %}
<div>
<a href="{{organization_subdomain}}" target="_blank">
{{_('Subdomain')}}
</a>
</div>
{% endif %}
<span class="spacer"></span>
{% if request.user.is_authenticated %}
@ -31,7 +24,8 @@
</form>
{% else %}
<a href="{{ url('request_organization', organization.id, organization.slug) }}"
class="unselectable button">{{ _('Request membership') }}</a>
class="unselectable button">
{{ _('Request membership') }}</a>
{% endif %}
{% endif %}
</div>
@ -47,7 +41,7 @@
<h3><i class="fa fa-info-circle"></i>{{ _('About') }}</h3>
<div class="sidebox-content">
<div style="margin: 0.3em;">
{% cache 3600 'organization_html' organization.id MATH_ENGINE %}
{% cache 3600 'organization_html' organization.id %}
{{ organization.about|markdown|reference|str|safe }}
{% endcache %}
</div>

View file

@ -1,49 +1,110 @@
{% extends "two-column-content.html" %}
{% extends "three-column-content.html" %}
{% block two_col_media %}
<style>
.organization-container .organization-row:last-child {
border-bottom: none;
}
{% block three_col_js %}
<script type="text/javascript">
$(document).ready(function () {
$('#mine-tab').attr('href', changeTabParameter('mine'));
$('#public-tab').attr('href', changeTabParameter('public'));
$('#private-tab').attr('href', changeTabParameter('private'));
.org-logo {
vertical-align: middle;
height: 2em;
width: 2em;
display: inline-block;
margin-right: 1em;
margin-left: 0.5em;
}
.toggle {
cursor: pointer;
}
</style>
var $form = $('form#filter-form');
$('#go').click(function() {
submitFormWithParams($form, "GET");
});
$form.on('keypress', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
}
});
$('#search-organization').keypress(function (e) {
if (e.keyCode === 13) {
$('#go').click();
}
});
$('#order').select2();
});
</script>
{% block contest_list_js %}{% endblock %}
{% endblock %}
{% block title_ruler %}{% endblock %}
{% block left_sidebar %}
{% include "user/user-left-sidebar.html" %}
<div class="left-sidebar">
{% if request.user.is_authenticated %}
{{ make_tab_item('mine', 'fa fa-user', request.path + '?tab=mine', _('Mine')) }}
{% endif %}
{{ make_tab_item('public', 'fa fa-globe', request.path + '?tab=public', _('Public')) }}
{{ make_tab_item('private', 'fa fa-lock', request.path + '?tab=private', _('Private')) }}
{% if request.user.is_superuser %}
{{ make_tab_item('import', 'fa fa-table', url('import_users'), _('Import'), force_new_page=True) }}
{% endif %}
</div>
{% endblock %}
{% macro org_list(title, queryset) %}
{% block right_sidebar %}
<div class="right-sidebar">
{% include "organization/search-form.html" %}
</div>
{% endblock %}
{% macro org_list(queryset, tab) %}
{% if queryset %}
<h3 style="padding-bottom: 1em" class="toggle open"><i class="fa fa-chevron-right fa-fw"></i> {{title}} ({{queryset.count()}})</h3>
<div class="organization-container toggled">
<div class="organization-container">
{% for org in queryset %}
<a href="{{ org.get_absolute_url() }}" class="organization-row" title="{{org.about}}">
<img class="org-logo" data-src="{{ org.logo_override_image or static('icons/icon.png') }}">
<span style="margin-right: auto">{{ org.name }}</span>
<span style="font-weight: normal"><i>{{ org.member_count }} {{_('members')}}</i></span>
</a>
<div class="organization-card" style="cursor: pointer;" onclick="location.href='{{ org.get_absolute_url() }}';">
{% if org.logo_override_image %}
<img class="org-logo" loading="lazy" src="{{ org.logo_override_image }}">
{% else %}
<img class="org-logo" loading="lazy" src="{{ static('icons/icon.svg') }}" onerror="this.onerror=null;this.src='{{ static('icons/logo.svg') }}';">
{% endif %}
<div class="org-details">
<span style="font-weight: bold;">{{ org.name }}</span>
<span style="margin-bottom: 0"><i>{{ org.member_count }} {{ _('members') }}</i></span>
</div>
{% if tab == 'mine' %}
<div class="background-royalblue button small">{{ _('View') }}</div>
{% elif tab == 'public' %}
<form method="post" action="{{ url('join_organization', org.id, org.slug) }}">
{% csrf_token %}
<input type="submit" style="width: 100%" class="background-royalblue button small" value="{{ _('Join') }}">
</form>
{% else %}
<a href="{{ url('request_organization', org.id, org.slug) }}" style="font-size: 15px;" class="background-royalblue button small">{{ _('Request membership') }}</a>
{% endif %}
</div>
{% endfor %}
</div>
{% if page_obj and page_obj.num_pages > 1 %}
{% include "list-pages.html" %}
{% endif %}
{% endif %}
{% endmacro %}
{% block middle_content %}
<a style="float: right" class="button small" href="{{url('organization_add')}}">{{_("Create group")}}</a>
{{ org_list(_('My groups'), my_organizations) }}
{{ org_list(_('Open groups'), open_organizations) }}
{{ org_list(_('Private groups'), private_organizations) }}
{% endblock %}
{% if current_tab == 'mine' %}
{% if organizations %}
{{ org_list(organizations, 'mine') }}
{% else %}
<i> {{ _('You have not joined any organization yet.') }} </i>
{% endif %}
{% endif %}
{% if current_tab == 'public' %}
{% if organizations %}
{{ org_list(organizations, 'public') }}
{% else %}
<i> {{ _('There is no public organization.') }} </i>
{% endif %}
{% endif %}
{% if current_tab == 'private' %}
{% if organizations %}
{{ org_list(organizations, 'private') }}
{% else %}
<i> {{ _('There is no private organization.') }} </i>
{% endif %}
{% endif %}
{% endblock %}

View file

@ -1,14 +1,14 @@
<div class="left-sidebar">
{{ make_tab_item('home', 'fa fa-home', organization.get_absolute_url(), _('Home')) }}
{% if is_member or can_edit %}
{{ make_tab_item('problems', 'fa fa-list', organization.get_problems_url(), _('Problems')) }}
{{ make_tab_item('contests', 'fa fa-trophy', organization.get_contests_url(), _('Contests')) }}
{{ make_tab_item('submissions', 'fa fa-book', organization.get_submissions_url(), _('Submissions')) }}
{{ make_tab_item('problems', 'fa fa-puzzle-piece', organization.get_problems_url(), _('Problems')) }}
{{ make_tab_item('contests', 'fa fa-ranking-star', organization.get_contests_url(), _('Contests')) }}
{{ make_tab_item('submissions', 'fa fa-code', organization.get_submissions_url(), _('Submissions')) }}
{% endif %}
{% if is_member or can_edit or organization.is_open %}
{{ make_tab_item('users', 'fa fa-user', organization.get_users_url(), _('Members')) }}
{{ make_tab_item('users', 'fa fa-users', organization.get_users_url(), _('Members')) }}
{% endif %}
{% if perms.judge.change_organization %}
{{ make_tab_item('admin', 'fa fa-edit', url('admin:judge_organization_change', organization.id), _('Admin')) }}
{{ make_tab_item('admin', 'fa fa-edit', url('admin:judge_organization_change', organization.id), _('Admin'), force_new_page=True) }}
{% endif %}
</div>

View file

@ -4,62 +4,64 @@
<h3><i class="fa fa-cog"></i>{{ _('Controls') }}</h3>
<ul id="control-list" class="sidebox-content" style="margin: 0;">
{% if can_edit %}
<li>
<div>
<a href="{{ url('edit_organization', organization.id, organization.slug) }}">{{ _('Edit group') }}</a>
</div>
</li>
<div class="link-row">
<a href="{{ url('edit_organization', organization.id, organization.slug) }}">
<i class="fa fa-edit"></i>{{ _('Edit group') }}</a>
</div>
{% endif %}
{% if can_edit and not organization.is_open %}
<li>
<div>
<a href="{{ url('organization_requests_pending', organization.id, organization.slug) }}">{{ _('View requests') }}</a>
{% if pending_count > 0 %}
<span id="pending-count-box">
{{pending_count}}
</span>
{% endif %}
</div>
</li>
{% endif %}
{% if can_edit %}
<li>
<div>
<a href="{{ url('add_organization_member', organization.id, organization.slug) }}">{{ _('Add members') }}</a>
</div>
</li>
{% endif %}
{% if is_member %}
<li>
<div>
<a href="{{ url('add_organization_blog', organization.id, organization.slug) }}">{{ _('Add blog') }}</a>
</div>
</li>
{% endif %}
<li>
<div>
<a href="{{ url('organization_pending_blogs', organization.id, organization.slug) }}">{{ _('Pending blogs') }}</a>
{% if pending_blog_count > 0 %}
<div class="link-row">
<a href="{{ url('organization_requests_pending', organization.id, organization.slug) }}">
<i class="fa fa-inbox"></i>{{ _('View requests') }}</a>
{% if pending_count > 0 %}
<span id="pending-count-box">
{{pending_blog_count}}
{{pending_count}}
</span>
{% endif %}
</div>
</li>
{% endif %}
{% if can_edit %}
<li>
<div>
<a href="{{ url('organization_contest_add', organization.id, organization.slug) }}">{{ _('Add contest') }}</a>
</div>
</li>
<div class="link-row">
<a href="{{ url('add_organization_member', organization.id, organization.slug) }}">
<i class="fa fa-user-plus"></i>{{ _('Add members') }}</a>
</div>
{% endif %}
{% if is_member %}
<div class="link-row">
<a href="{{ url('add_organization_blog', organization.id, organization.slug) }}">
<i class="fa fa-pencil"></i>{{ _('Add blog') }}</a>
</div>
{% endif %}
<div class="link-row">
<a href="{{ url('organization_pending_blogs', organization.id, organization.slug) }}">
<i class="fa fa-clipboard-list"></i>{{ _('Pending blogs') }}</a>
{% if pending_blog_count > 0 %}
<span id="pending-count-box">
{{pending_blog_count}}
</span>
{% endif %}
</div>
{% if can_edit %}
<div class="link-row">
<a href="{{ url('organization_contest_add', organization.id, organization.slug) }}">
<i class="fa fa-calendar-plus"></i>{{ _('Add contest') }}</a>
</div>
{% endif %}
{% if is_member %}
<div class="link-row">
<a href="{{ organization_subdomain }}" target="_blank">
<i class="fa fa-globe"></i>{{_('Subdomain')}}
</a>
</div>
{% endif %}
{% if is_member and not is_admin %}
<li>
<div class="link-row" style="color: red;">
<form method="post" action="{{ url('leave_organization', organization.id, organization.slug) }}">
{% csrf_token %}
<a href="#" class="leave-organization">{{ _('Leave group') }}</a>
<a href="#" class="leave-organization">
<i class="fa fa-sign-out-alt"></i>{{ _('Leave group') }}</a>
</form>
</li>
</div>
{% endif %}
</ul>
</div>
@ -72,7 +74,7 @@
<h3><i class="fa fa-info-circle"></i>{{ _('About') }}</h3>
<div class="sidebox-content">
<div style="margin: 0.3em;">
{% cache 3600 'organization_html' organization.id MATH_ENGINE %}
{% cache 3600 'organization_html' organization.id %}
{{ organization.about|markdown|reference|str|safe }}
{% endcache %}
</div>

View file

@ -1,4 +1 @@
{{ preview_data|markdown|reference|str|safe }}
{% if REQUIRE_JAX %}
<div data-config="{{ static('mathjax3_config.js') }}" class="require-mathjax-support"></div>
{% endif %}

View file

@ -0,0 +1,24 @@
<div class="sidebox">
<h3 class="colored-text"><i class="fa fa-search"></i>{{ _('Organization search') }}</h3>
<div class="sidebox-content">
<form id="filter-form" method="GET">
<input id="search-organization" type="text" name="organization" value="{{ organization_query or '' }}"
placeholder="{{ _('Search organizations...') }}">
<div class="filter-form-group">
<label for="order" class="bold-text margin-label">{{ _('Order by') }}</label>
<select id="order" name="order" style="width: 100%">
<option value="">---</option>
{% for value, name in all_sort_options %}
<option value="{{value}}"{% if selected_order == value%} selected{% endif %}>
{{ name }}
</option>
{% endfor %}
</select>
</div>
<div class="form-submit-group">
<a class="button small" href="{{url('organization_add')}}">{{_("Create group")}}</a>
<a id="go" class="button small">{{ _('Go') }}</a>
</div>
</form>
</div>
</div>

View 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>

View file

@ -12,23 +12,24 @@
{% endif %}
{% if image_upload_enabled %}
<div class="pagedown-image-upload">
<h2>Insert Image</h2>
<h2>{{_("Insert Image")}}</h2>
<div class="form-row">
<div>
<label class="label">From the web</label>
<label class="label">{{_("From the web")}}</label>
<input class="url-input" type="text" placeholder="http://" />
</div>
</div>
<br>
<div class="form-row">
<div>
<label class="label">From your computer</label>
<label class="label">{{_("From your computer")}}</label>
<input class="file-input" type="file" name="image" id="file" data-action="{{ url('pagedown-image-upload') }}" accept="image/*"/>
</div>
</div>
<div class="submit-row">
<div class="submit-loading"></div>
<input class="submit-input show" type="submit" value="Save" name="_addanother">
<p class="deletelink-box"><a href="#" class="close-image-upload deletelink">Cancel</a></p>
<input class="submit-input show small" type="submit" value="{{_('Save')}}" name="_addanother">
<p class="deletelink-box"><a href="#" class="close-image-upload deletelink">{{_("Cancel")}}</a></p>
</div>
</div>
{% endif %}

View file

@ -6,36 +6,38 @@
window.big_input = (window.valid_files.length > 100);
</script>
<script type="text/javascript" src="{{ static('jquery-ui.min.js') }}"></script>
<script type="text/javascript" src="{{ static('libs/featherlight/featherlight.min.js') }}"></script>
<script type="text/javascript" src="{{ static('fine-uploader/jquery.fine-uploader.js') }}"></script>
<script type="text/javascript">
$(function () {
$("#problem-data-zipfile_fine_uploader").fineUploader({
request: {
endpoint: "{{url('problem_zip_upload', problem.code)}}",
params: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
if (!window.PAGE_FROM_BACK_BUTTON_CACHE) {
$("#problem-data-zipfile_fine_uploader").fineUploader({
request: {
endpoint: "{{url('problem_zip_upload', problem.code)}}",
params: {
'csrfmiddlewaretoken': '{{ csrf_token }}'
}
},
chunking: {
enabled: true,
partSize: 40000000,
},
resume: {
enabled: true
},
validation: {
allowedExtensions: ['zip'],
},
}).on('complete', function (event, id, name, responseJSON) {
console.log(responseJSON);
if (!responseJSON.success) {
alert('Fail to upload: ' + responseJSON.error);
}
},
chunking: {
enabled: true,
partSize: 40000000,
},
resume: {
enabled: true
},
validation: {
allowedExtensions: ['zip'],
},
}).on('complete', function (event, id, name, responseJSON) {
console.log(responseJSON);
if (!responseJSON.success) {
alert('Fail to upload: ' + responseJSON.error);
}
else {
$('#submit-button').click();
}
});;
else {
$('#submit-button').click();
}
});
toggle_custom();
}
function update_select2() {
$('tbody:not(.extra-row-body) .type-column select').select2({
@ -133,11 +135,11 @@
}).change();
}
(function toggle_custom() {
function toggle_custom() {
let $checker = $('#id_problem-data-checker')
let $custom_checker = $('#id_problem-data-custom_checker');
let $validator = $('#id_problem-data-custom_validator');
let $validator = $('#id_problem-data-custom_checker_cpp');
let $interactive = $('#id_problem-data-interactive_judge');
let $sig_handler = $('#id_problem-data-signature_handler');
let $sig_header = $('#id_problem-data-signature_header');
@ -165,17 +167,17 @@
$checker.change(function () {
$tr_checker.toggle($checker.val() == 'custom').change();
$tr_validator.toggle($checker.val() == 'customval' || $checker.val() == 'testlib').change();
$tr_validator.toggle($checker.val() == 'customcpp' || $checker.val() == 'testlib').change();
$tr_interactive.toggle($checker.val() == 'interact').change();
$sample.toggle(['custom', 'customval', 'interact'].includes($checker.val())).change();
$sample.toggle(['custom', 'customcpp', 'interact'].includes($checker.val())).change();
}).change();
$ioi_signature.change(function() {
$tr_sig_header.toggle($ioi_signature.is(':checked')).change();
$tr_sig_handler.toggle($ioi_signature.is(':checked')).change();
}).change();
})();
};
checker_precision($('#id_problem-data-checker'));

View file

@ -27,7 +27,9 @@
<p>Authors: {{ link_users(authors) }}</p>
{% endif %}
{% endwith %}
{{ solution.content|markdown|reference|str|safe }}
{% cache 86400 'solution_content' solution.id %}
{{ solution.content|markdown(lazy_load=True)|reference|str|safe }}
{% endcache %}
</div>
<hr>
{% include "actionbar/list.html" %}
@ -36,8 +38,5 @@
{% endblock %}
{% block bodyend %}
{% if REQUIRE_JAX %}
{% include "mathjax-load.html" %}
{% endif %}
{% include "comments/math.html" %}
{% endblock %}

View file

@ -7,7 +7,7 @@
{% endblock %}
{% block middle_content %}
<div class="tabs tabs-no-flex" style="width: 90%;margin-left: auto;margin-right: auto;">
<div class="tabs tabs-no-flex">
<ul>
<li class="{{'active' if feed_type=='for_you'}}">
<a href="{{url('problem_feed')}}">{{_('FOR YOU')}}</a>
@ -27,5 +27,5 @@
<li><a href="{{url('admin:judge_volunteerproblemvote_changelist')}}">{{_('View your votes')}}</a></li>
</ul>
{% endif %}
{% include "problem/feed/problems.html" %}
{% include "problem/feed/items.html" %}
{% endblock %}

View file

@ -12,10 +12,10 @@
<i class="unsolved-problem-color fa fa-minus-circle"></i>
{% endif %}
</h3>
{% with authors=problem.authors.all() %}
{% with authors=problem.get_authors() %}
{% if authors %}
<div class="problem-feed-info-entry">
<i class="fa fa-pencil-square-o fa-fw"></i>
<i class="far fa-pen-to-square"></i>
<span class="pi-value">{{ link_users(authors) }}</span>
</div>
{% endif %}
@ -30,7 +30,7 @@
{% endif %}
<div class="blog-description">
<div class='content-description'>
{% cache 86400 'problem_html' problem.id MATH_ENGINE LANGUAGE_CODE %}
{% cache 86400 'problem_html' problem.id LANGUAGE_CODE %}
{{ problem.description|markdown(lazy_load=True)|reference|str|safe }}
{% endcache %}
{% if problem.pdf_description %}

View file

@ -1,9 +1,9 @@
{% if not show_contest_mode %}
<div class="left-sidebar">
{{ make_tab_item('feed', 'fa fa-pagelines', url('problem_feed'), _('Feed')) }}
{{ make_tab_item('feed', 'far fa-lightbulb', url('problem_feed'), _('Feed')) }}
{{ make_tab_item('list', 'fa fa-list', url('problem_list'), _('List')) }}
{% if request.user.is_superuser %}
{{ make_tab_item('admin', 'fa fa-edit', url('admin:judge_problem_changelist'), _('Admin')) }}
{{ make_tab_item('admin', 'fa fa-edit', url('admin:judge_problem_changelist'), _('Admin'), force_new_page=True) }}
{% endif %}
</div>
{% endif %}

View file

@ -86,12 +86,17 @@
}
$category.select2().css({'visibility': 'visible'}).change(clean_submit);
$('#types').select2({multiple: 1, placeholder: '{{ _('Filter by type...') }}'})
.css({'visibility': 'visible'});
$('#search-org').select2({multiple: 1, placeholder: '{{ _('Groups') }}...'})
.css({'visibility': 'visible'});
$('#search-author').select2({multiple: 1, placeholder: '{{ _('Authors') }}...'})
.css({'visibility': 'visible'});
$('#types').select2({multiple: 1, placeholder: '{{ _('Filter by type...') }}'});
$('#search-org').select2({multiple: 1, placeholder: '{{ _('Groups') }}...'});
$('#search-author').select2({
multiple: 1,
placeholder: '{{ _('Authors') }}...',
ajax: {
url: '{{ url('problem_authors_select2_ajax') }}',
delay: 250,
cache: true,
}
});
// This is incredibly nasty to do but it's needed because otherwise the select2 steals the focus
$search.keypress(function (e) {
@ -108,7 +113,7 @@
$('#go').click(clean_submit);
$('input#full_text, input#hide_solved, input#show_types, input#have_editorial, input#show_solved_only').click(function () {
$('input#full_text, input#hide_solved, input#show_types, input#have_editorial, input#show_solved_only, input#show_editorial').click(function () {
prep_form();
($('<form>').attr('action', window.location.pathname + '?' + form_serialize())
.append($('<input>').attr('type', 'hidden').attr('name', 'csrfmiddlewaretoken')
@ -149,8 +154,7 @@
$(".edit-btn").on('click', function() {
var pid = $(this).attr('pid');
$('#volunteer-types-' + pid).css({'width': '100%'});
$('#volunteer-types-' + pid).select2({multiple: 1, placeholder: '{{ _('Add types...') }}'})
.css({'visibility': 'visible'});
$('#volunteer-types-' + pid).select2({multiple: 1, placeholder: '{{ _('Add types...') }}'});
$('#form-' + pid).show();
$('#submit-' + pid).show();

View file

@ -59,6 +59,21 @@
placeholder: '{{ _('Leave empty to not filter by result') }}'
});
$('#by-contest-filter').select2({
multiple: true,
placeholder: '{{ _('Leave empty to not filter by contest') }}',
ajax: {
url: "{{url('contest_select2')}}",
data: function(params) {
return {
term: params.term,
problem_id: {{problem.id}}
};
},
delay: 250,
}
});
$('#rescore-all').click(function (e) {
e.preventDefault();
if (confirm(this.dataset.warning)) {
@ -157,10 +172,14 @@
{% endfor %}
</select>
</div>
{% if in_contest %}
<label for="in-contest" name="in_contest">{{ _('In current contest') }}:</label>
<input type="checkbox" name="in_contest">
{% endif %}
<div class="control-group">
<label for="by-contest-filter">{{ _('Filter by contest:') }}</label>
<select id="by-contest-filter" name="contest" multiple>
{% if current_contest %}
<option selected value="{{current_contest.id}}">{{ current_contest }}</option>
{% endif %}
</select>
</div>
</form>
</div>
<div class="pane">

View file

@ -1,4 +1 @@
{{ preview_data|markdown|reference|str|safe }}
{% if REQUIRE_JAX %}
<div data-config="{{ static('mathjax3_config.js') }}" class="require-mathjax-support"></div>
{% endif %}
{{ preview_data|markdown|reference|str|safe }}

View file

@ -1,4 +1,7 @@
{% extends "common-content.html" %}
{% set has_hidden_subtasks = request.in_contest_mode and request.participation.contest.format.has_hidden_subtasks %}
{% block content_media %}
{% include "comments/media-css.html" %}
<style>
@ -62,11 +65,17 @@
e.preventDefault();
if (!$('#raw_problem').attr('src')) {
$('#raw_problem').attr('src', '{{problem.code}}/raw')
$('#raw_problem').on('load', function() {
renderKatex(frames['raw_problem'].document);
setTimeout(() => {
frames['raw_problem'].print();
}, 500);
});
}
while(!$('.math-loaded', frames['raw_problem'].document).length){
await new Promise(r => setTimeout(r, 200));
else {
frames['raw_problem'].print();
return;
}
frames['raw_problem'].print();
});
$('#clarification_header').on('click', function() {
$('#clarification_header_container').hide();
@ -86,7 +95,7 @@
{% block title_row %}
<div class="problem-title">
{% if request.user.is_authenticated %}
{% if request.user.is_authenticated and not has_hidden_subtasks %}
{% 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_mode %}
@ -109,15 +118,10 @@
{% if problem.is_organization_private %}
<span class="organization-tags">
{% for org in problem.organizations.all() %}
<span class="organization-tag">
<a href="{{ org.get_absolute_url() }}">
<i class="fa fa-lock"></i> {{ org.name }}
</a>
</span>
{% include "organization/tag.html" %}
{% endfor %}
</span>
{% endif %}
<span class="spacer"></span>
{% if has_render %}
<a href="{{ url('problem_pdf', problem.code) }}" class="view-pdf" target="_blank">
@ -127,7 +131,7 @@
<a id="pdf_button" class="view-pdf" href='#'>
{% endif %}
<span class="pdf-icon">
<span class="fa fa-file-pdf-o pdf-icon-logo"></span>
<span class="fa fa-file-pdf pdf-icon-logo"></span>
<span class="pdf-icon-bar"></span>
</span>
{{ _('View as PDF') }}
@ -135,11 +139,17 @@
</div>
{% endblock %}
{% block info_float %}
{% 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 btn-green small">
{{ _('Submit solution') }}
<a href="{{ url('problem_submit', problem.code) }}">
<button class="btn-green btn btn-primary btn-block btn-round">
<span>{{ _('Submit') }}</span>
<div class="icon icon-round d-flex align-items-center justify-content-center">
<i class="fa fa-paper-plane"></i>
</div>
</button>
</a>
<div class="submissions-left">
{% trans trimmed counter=submissions_left %}
@ -149,116 +159,138 @@
{% endtrans %}
</div>
{% else %}
<a class="unselectable button full disabled small">{{ _('Submit solution') }}</a>
<button class="btn btn-disabled btn-block btn-round">
<span>{{ _('Submit') }}</span>
<div class="icon icon-round d-flex align-items-center justify-content-center">
<i class="fa fa-paper-plane"></i>
</div>
</button>
<div class="no-submissions-left submissions-left">{{ _('0 submissions left') }}</div>
{% endif %}
{% else %}
<a href="{{ url('problem_submit', problem.code) }}" class="unselectable button full btn-green small">
{{ _('Submit solution') }}
<a href="{{ url('problem_submit', problem.code) }}">
<button class="btn-green btn btn-primary btn-block btn-round">
<span>{{ _('Submit') }}</span>
<div class="icon icon-round d-flex align-items-center justify-content-center">
<i class="fa fa-paper-plane"></i>
</div>
</button>
</a>
{% endif %}
<hr style="padding-bottom: 0.3em">
{% if request.user.is_authenticated and has_submissions %}
<div>
<a href="{{ url('user_submissions', problem.code, request.user.username) }}">{{ _('My submissions') }}</a>
<div class="link-row">
<a href="{{url('user_submissions', problem.code, request.user.username) }}">
<i class="fa fa-address-book"></i><span> {{ _('My submissions') }}</span>
</a>
</div>
{% endif %}
<div><a href="{{ url('chronological_submissions', problem.code) }}">{{ _('All submissions') }}</a></div>
<div><a href="{{ url('ranked_submissions', problem.code) }}">{{ _('Best submissions') }}</a></div>
{% if editorial and editorial.is_public and
not (request.user.is_authenticated and request.in_contest_mode) %}
<hr>
<div><a href="{{ url('problem_editorial', problem.code) }}">{{ _('Read editorial') }}</a></div>
{% endif %}
{% if can_edit_problem %}
<hr>
<div>
<a href="{{ url('problem_ticket_list', problem.code) }}">{{ _('Manage tickets') }}
{% if num_open_tickets %}<span class="badge">{{ num_open_tickets }}</span>{% endif %}
<div class="link-row">
<a href="{{ url('chronological_submissions', problem.code) }}">
<i class="fa fa-rectangle-list"></i><span> {{ _('All submissions') }}</span>
</a>
</div>
<div><a href="{{ url('admin:judge_problem_change', problem.id) }}">{{ _('Edit problem') }}</a></div>
{% if not problem.is_manually_managed %}
<div><a href="{{ url('problem_data', problem.code) }}">{{ _('Edit test data') }}</a></div>
<div class="link-row">
<a href="{{ url('ranked_submissions', problem.code) }}">
<i class="fa fa-list-check"></i><span> {{ _('Best submissions') }}</span>
</a>
</div>
{% if editorial and editorial.is_public and not (request.user.is_authenticated and request.in_contest_mode) %}
<hr>
<div class="link-row">
<a href="{{ url('problem_editorial', problem.code) }}">
<i class="fa fa-newspaper"></i><span> {{ _('Read editorial') }}</span>
</a>
</div>
{% endif %}
{% elif request.user.is_authenticated and has_tickets %}
<hr>
<div>
<a href="{{ url('problem_ticket_list', problem.code) }}">{{ _('My tickets') }}
{% if num_open_tickets %}<span class="badge">{{ num_open_tickets }}</span>{% endif %}
</a>
</div>
{% endif %}
{% if problem.is_subs_manageable_by(request.user) %}
<div>
<a href="{{ url('problem_manage_submissions', problem.code) }}">{{ _('Manage submissions') }}</a>
</div>
{% endif %}
{% if perms.judge.clone_problem %}
<div>
<a href="{{ url('problem_clone', problem.code) }}">{{ _('Clone problem') }}</a>
</div>
{% endif %}
<hr style="padding-top: 0.3em">
<div class="problem-info-entry">
<i class="fa fa-check fa-fw"></i><span class="pi-name">{{ _('Points:') }}</span>
<span class="pi-value">
{% if contest_problem %}
{{ contest_problem.points }}{% if contest_problem.partial %} {{ _('(partial)') }}{% endif %}
{% else %}
{{ problem.points|floatformat }}{% if problem.partial %} {{ _('(partial)') }}{% endif %}
{% if can_edit_problem %}
<hr>
<div class="link-row">
<a href="{{ url('problem_ticket_list', problem.code) }}">
<i class="fa fa-clipboard-list"></i><span> {{ _('Manage tickets') }}
{% if num_open_tickets %}<span class="badge">{{ num_open_tickets }}</span>{% endif %}
</span>
</a>
</div>
<div class="link-row">
<a href="{{ url('admin:judge_problem_change', problem.id) }}">
<i class="fa fa-edit"></i><span> {{ _('Edit problem') }}</span>
</a>
</div>
{% if not problem.is_manually_managed %}
<div class="link-row">
<a href="{{ url('problem_data', problem.code) }}">
<i class="fa fa-database"></i><span> {{ _('Edit test data') }}</span>
</a>
</div>
{% endif %}
</span>
</div>
<div class="problem-info-entry">
<i class="fa fa-clock-o fa-fw"></i><span class="pi-name">{{ _('Time limit:') }}</span>
<span class="pi-value">{{ problem.time_limit }}s</span>
</div>
<div class="problem-lang-limits">
{% for name, limit in problem.language_time_limit %}
<div class="lang-limit">
<span class="lang-name">{{ name }}</span>
<span class="lang-tl">{{ limit }}s</span>
{% elif request.user.is_authenticated and has_tickets %}
<hr>
<div class="link-row">
<a href="{{ url('problem_ticket_list', problem.code) }}">
<i class="fa fa-inbox"></i><span> {{ _('My tickets') }}
{% if num_open_tickets %}<span class="badge">{{ num_open_tickets }}</span>{% endif %}
</span>
</a>
</div>
{% endfor %}
</div>
<div class="problem-info-entry">
<i class="fa fa-server fa-fw"></i><span class="pi-name">{{ _('Memory limit:') }}</span>
<span class="pi-value">{{ problem.memory_limit|kbsimpleformat }}</span>
</div>
<div class="problem-lang-limits">
{% for name, limit in problem.language_memory_limit %}
<div class="lang-limit">
<span class="lang-name">{{ name }}</span>
<span class="lang-ml">{{ limit|kbsimpleformat }}</span>
{% endif %}
{% if problem.is_subs_manageable_by(request.user) %}
<div class="link-row">
<a href="{{ url('problem_manage_submissions', problem.code) }}">
<i class="fas fa-table"></i><span> {{ _('Manage submissions') }}</span>
</a>
</div>
{% endfor %}
</div>
<div class="problem-info-entry">
<i class="fa fa-file-o fa-fw"></i><span class="pi-name">{{ _('Input:') }}</span>
<span class="pi-value">
{{ fileio_input or _('stdin') }}
</span>
</div>
<div class="problem-info-entry">
<i class="fa fa-file fa-fw"></i><span class="pi-name">{{ _('Output:') }}</span>
<span class="pi-value">{{ fileio_output or _('stdout') }}</span>
</div>
{% endif %}
<hr style="padding-top: 0.7em">
{% if perms.judge.clone_problem %}
<div class="link-row">
<a href="{{ url('problem_clone', problem.code) }}">
<i class="fas fa-clone"></i><span> {{ _('Clone problem') }}</span>
</a>
</div>
{% endif %}
{% cache 86400 'problem_authors' problem.id LANGUAGE_CODE %}
{% with authors=problem.authors.all() %}
{% if problem.language_time_limit or problem.language_memory_limit %}
<hr style="padding-top: 0.3em">
{% endif %}
{% if problem.language_time_limit %}
<div class="problem-info-entry">
<i class="fa fa-clock"></i><span class="pi-name"> {{ _('Time limit:') }}</span>
</div>
<div class="problem-lang-limits">
{% for name, limit in problem.language_time_limit %}
<div class="lang-limit">
<span class="lang-name">{{ name }}</span>
<span class="lang-tl">{{ limit }}s</span>
</div>
{% endfor %}
</div>
{% endif %}
{% if problem.language_memory_limit %}
<div class="problem-info-entry">
<i class="fa fa-server"></i><span class="pi-name"> {{ _('Memory limit:') }}</span>
</div>
<div class="problem-lang-limits">
{% for name, limit in problem.language_memory_limit %}
<div class="lang-limit">
<span class="lang-name">{{ name }}</span>
<span class="lang-ml">{{ limit|kbsimpleformat }}</span>
</div>
{% endfor %}
</div>
{% endif%}
<hr style="padding-top: 0.7em">
{% with authors=problem.get_authors() %}
{% if authors %}
<div class="problem-info-entry">
<i class="fa fa-pencil-square-o fa-fw"></i><span
class="pi-name">{% trans trimmed count=authors|length %}
<i class="far fa-pen-to-square"></i><span
class="pi-name"> {% trans trimmed count=authors|length %}
Author:
{% pluralize count %}
Authors:
@ -267,68 +299,67 @@
</div>
{% endif %}
{% endwith %}
{% endcache %}
{% if not contest_problem or not contest_problem.contest.hide_problem_tags %}
<div id="problem-types">
{% with types=problem.types_list %}
<div class="toggle closed unselectable">
<i class="fa fa-chevron-right fa-fw"></i>{% trans trimmed count=problem.types_list|length %}
Problem type
{% pluralize count %}
Problem types
{% endtrans %}
</div>
<div style="display:none" class="toggled">{{ problem.types_list|join(", ") }}</div>
{% endwith %}
</div>
{% endif %}
{% if show_languages %}
<div id="allowed-langs">
<div class="toggle open unselectable">
<i class="fa fa-chevron-right fa-fw"></i>{{ _('Allowed languages') }}
</div>
<div class="toggled">
{% with usable=problem.usable_common_names, langs=problem.languages_list() %}
{% for lang in langs %}
{%- if lang in usable -%}
{{ lang }}
{%- else -%}
<s title="{{ _('No %(lang)s judge online', lang=lang) }}">{{ lang }}</s>
{%- endif -%}
{% if not loop.last %}, {% endif -%}
{% endfor %}
{% if not contest_problem or not contest_problem.contest.hide_problem_tags %}
<div id="problem-types">
{% with types=problem.types_list %}
<div class="toggle closed unselectable">
<i class="fa fa-chevron-right"></i> {% trans trimmed count=problem.types_list|length %}
Problem type
{% pluralize count %}
Problem types
{% endtrans %}
</div>
<div style="display:none" class="toggled">{{ problem.types_list|join(", ") }}</div>
{% endwith %}
</div>
</div>
{% endif %}
{% if problem.is_editable_by(request.user) %}
<div id="available-judges">
<div class="toggle closed" id="judge-toggle">
<i class="fa fa-chevron-right fa-fw"></i><span
class="pi-name">{% trans trimmed count=available_judges|length %}
Judge
{% pluralize count %}
Judges
{% endtrans %}
</span>
</div>
<div class="pi-value judges-value toggled" style="display: none;">
{% if available_judges %}
{% if perms.judge.change_judge %}
{% for judge in available_judges %}
<a href="{{ url('admin:judge_judge_change', judge.id) }}">{{ judge.name }}</a>
{%- if not loop.last %}, {% endif %}
{% endif %}
{% if show_languages %}
<div id="allowed-langs">
<div class="toggle open unselectable">
<i class="fa fa-chevron-right"></i> {{ _('Allowed languages') }}
</div>
<div class="toggled">
{% with usable=problem.usable_common_names, langs=problem.languages_list() %}
{% for lang in langs %}
{%- if lang in usable -%}
{{ lang }}
{%- else -%}
<s title="{{ _('No %(lang)s judge online', lang=lang) }}">{{ lang }}</s>
{%- endif -%}
{% if not loop.last %}, {% endif -%}
{% endfor %}
{% else %}
{{ available_judges|join(", ") }}
{% endif %}
{% else %}
<i class="red">{{ _('none available') }}</i>
{% endif %}
{% endwith %}
</div>
</div>
</div>
{% endif %}
{% endif %}
{% if problem.is_editable_by(request.user) %}
<div id="available-judges">
<div class="toggle closed" id="judge-toggle">
<i class="fa fa-chevron-right"></i><span
class="pi-name"> {% trans trimmed count=available_judges|length %}
Judge
{% pluralize count %}
Judges
{% endtrans %}
</span>
</div>
<div class="pi-value judges-value toggled" style="display: none;">
{% if available_judges %}
{% if perms.judge.change_judge %}
{% for judge in available_judges %}
<a href="{{ url('admin:judge_judge_change', judge.id) }}">{{ judge.name }}</a>
{%- if not loop.last %}, {% endif %}
{% endfor %}
{% else %}
{{ available_judges|join(", ") }}
{% endif %}
{% else %}
<i class="red">{{ _('none available') }}</i>
{% endif %}
</div>
</div>
{% endif %}
{% endblock %}
{% block description %}
@ -342,8 +373,42 @@
</a>
</div>
{% endif %}
<div class = "new-problem-info d-flex-problem">
<span class="info-block">
<i class="fa fa-check"></i><span class="pi-name"> {{ _('Points:') }}</span>
<span class="new-pi-value">
{% if contest_problem %}
{{ contest_problem.points }} {% if contest_problem.partial %}(p){% endif %}
{% else %}
{{ problem.points|floatformat }} {% if problem.partial %}(p){% endif %}
{% endif %}
</span>
</span>
{% cache 86400 'problem_html' problem.id MATH_ENGINE LANGUAGE_CODE %}
<span class="info-block">
<i class="fa fa-clock"></i><span class="pi-name"> {{ _('Time limit:') }}</span>
<span class="new-pi-value">{{ problem.time_limit }}s</span>
</span>
<span class="info-block">
<i class="fa fa-server"></i><span class="pi-name"> {{ _('Memory limit:') }}</span>
<span class="new-pi-value">{{ problem.memory_limit|kbsimpleformat }}</span>
</span>
<span class="info-block">
<i class="fa fa-file"></i><span class="pi-name"> {{ _('Input:') }}</span>
<span class="new-pi-value">
{{ fileio_input or _('stdin') }}
</span>
</span>
<span>
<i class="fa fa-file"></i><span class="pi-name"> {{ _('Output:') }}</span>
<span class="new-pi-value">{{ fileio_output or _('stdout') }}</span>
</span>
</div>
{% cache 86400 'problem_html' problem.id LANGUAGE_CODE %}
{{ description|markdown(lazy_load=True)|reference|str|safe }}
{% endcache %}

View file

@ -92,16 +92,7 @@
<div class="content-description printing">
{{ description|markdown|reference|absolutify(url)|str|safe }}
</div>
<script type="text/javascript" src="{{ static('mathjax3_config.js') }}"></script>
<script type="text/javascript" src="mathjax3_config.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_HTML"></script>
<script type="text/javascript">
MathJax.Hub.Register.StartupHook("End", function () {
if (typeof window.callPhantom === 'function')
window.callPhantom({'action': 'snapshot'});
document.body.classList.add('math-loaded');
});
</script>
<script src="{{ static('katex_config.js') }}"></script>
{% include "katex-load.html" %}
</body>
</html>

View file

@ -47,11 +47,11 @@
</div>
{% endif %}
<div class="filter-form-group">
<label class="bold-text margin-label" for="type"><i class="non-italics">{{ _('Author') }}</i></label>
<label class="bold-text margin-label" for="search-author"><i class="non-italics">{{ _('Author') }}</i></label>
<select id="search-author" name="authors" multiple>
{% for author in all_authors %}
<option value="{{ author.id }}"{% if author.id in author_query %} selected{% endif %}>
{{ author.user__username }}
{% for author in author_query %}
<option value="{{ author.id }}" selected>
{{ author.username }}
</option>
{% endfor %}
</select>
@ -84,8 +84,10 @@
</select>
</div>
{% if point_values %}
<div style="margin-top: 5px;" class="bold-text margin-label" class="form-label">{{ _('Point range') }}</div>
<div id="point-slider"></div>
<div class="filter-form-group">
<div class="bold-text margin-label" class="form-label">{{ _('Point range') }}</div>
<div id="point-slider"></div>
</div>
{% endif %}
<input id="point-start" type="hidden" name="point_start" {% if point_start and point_start != point_values.min %}value="{{ point_start }}"{% else %}disabled{% endif %}>
<input id="point-end" type="hidden" name="point_end" {% if point_end and point_end != point_values.max %}value="{{ point_end }}"{% else %}disabled{% endif %}>

View file

@ -12,7 +12,6 @@
});
});
</script>
<script type="text/javascript" src="{{ static('libs/featherlight/featherlight.min.js') }}"></script>
<script type="text/javascript">
</script>
{% endblock %}

View file

@ -32,7 +32,31 @@
}
{% endif %}
}
{% if request.in_contest and next_valid_submit_time and not (submission_limit and submissions_left <= 0) %}
$(function () {
const $submitButton = $("#submit-button");
$submitButton.prop('disabled', true);
const nextValidDate = new Date("{{next_valid_submit_time}}");
function updateCountdown() {
var now = new Date();
var timeUntilNextValid = nextValidDate - now;
if (timeUntilNextValid > 0) {
var seconds = Math.floor(timeUntilNextValid / 1000);
$("#countdown-timer").text("{{_("Wait")}} " + seconds + "s");
setTimeout(updateCountdown, 1000);
} else {
$("#countdown-timer").text("");
$submitButton.prop('disabled', false);
}
}
updateCountdown();
});
{% endif %}
</script>
{% compress js %}
<script type="text/javascript">
$(function () {
@ -228,8 +252,9 @@
{{ form.source_file }}
<div class="submit-bar">
{{ form.judge }}
<input type="submit" value="{{ _('Submit!') }}" class="button small"
{% if request.in_contest and submission_limit and not submissions_left %}disabled{% endif %}>
<input id="submit-button" type="submit" value="{{ _('Submit!') }}" class="button small"
{% if request.in_contest and submission_limit and submissions_left <= 0 %}disabled{% endif %}>
<span id="countdown-timer"></span>
</div>
{% endif %}
</form>

View file

@ -1,20 +1,5 @@
{% extends "base.html" %}
{% block body %}
<div class="source-wrap">
<table>
<tr>
<td class="source-ln">
<div>
{% for line in raw_source.split('\n') %}
<a href="#line-{{ loop.index }}" name="line-{{ loop.index }}">
<pre>{{ loop.index }}</pre>
</a>
{% endfor %}
</div>
</td>
<td class="source-code">{{ highlighted_source }}</td>
</tr>
</table>
</div>
{{ highlighted_source }}</td>
{% endblock %}

View file

@ -0,0 +1,77 @@
{% if request.profile %}
<div class="blog-sidebox sidebox">
<h3 class="bold-text colored-text"><i class="fa fa-user"></i>{{ _('Profile') }}</h3>
<div class="toggled sidebox-content">
<div class="profile-card">
<div class="card-header">
<a href="{{url('user_page')}}">
<img class="avatar" src="{{ gravatar(request.profile) }}" alt="User Avatar">
</a>
<h4>{{ link_user(request.profile) }}</h4>
</div>
<div class="card-body">
<div class="user-info">
<div><i class="fa fa-star {{request.profile.css_class}}"></i> {{_('Rating')}}</div>
<div class="{{ request.profile.css_class }}">{{ request.profile.rating if request.profile.rating else '-' }}</div>
</div>
<div class="user-info">
<div
title="
{%- trans trimmed counter=request.profile.problem_count %}
{{ counter }} problem solved
{% pluralize %}
{{ counter }} problems solved
{% endtrans -%}"
><i class="green icofont-tick-mark"></i> {{_('Problems')}}</div>
<span class="user-info-body">{{ request.profile.problem_count }}</span>
</div>
<div class="user-info">
<div
title="{{_('Total points')}}"
><i class="fa fa-trophy darkcyan"></i> {{_('Points')}}</div>
<div class="user-info-body"><span title="{{ request.profile.performance_points|floatformat(2) }}">
{{ request.profile.performance_points|floatformat(0) }}
</span></div>
</div>
<div class="user-info">
<div title="{{_('Rank by rating')}}"><i class="fa fa-globe peru" ></i> {{_('Rating')}} #</div>
<div class="user-info-body">{{rating_rank if rating_rank else '-'}}</div>
</div>
<div class="user-info">
<div title="{{_('Rank by points')}}"><i class="fa fa-globe blue" ></i> {{_('Points')}} #</div>
<div class="user-info-body">{{points_rank if points_rank else '-'}}</div>
</div>
{% if awards.medals %}
<div class="user-info">
<div title="{{ _('Awards') }}"><i class="fa fa-medal"></i> {{ _('Awards') }}</div>
</div>
{% endif %}
</div>
{% if awards %}
<div class="medals-container">
{% if awards.gold_count > 0 %}
<div class="medal-item">
<img src="{{ static('awards/gold-medal.png') }}" alt="Gold Medal">
<span class="medal-count">{{ awards.gold_count }}</span>
</div>
{% endif %}
{% if awards.silver_count > 0 %}
<div class="medal-item">
<img src="{{ static('awards/silver-medal.png') }}" alt="Silver Medal">
<span class="medal-count">{{ awards.silver_count }}</span>
</div>
{% endif %}
{% if awards.bronze_count > 0 %}
<div class="medal-item">
<img src="{{ static('awards/bronze-medal.png') }}" alt="Bronze Medal">
<span class="medal-count">{{ awards.bronze_count }}</span>
</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
</div>
{% endif %}

View file

@ -1,29 +1,15 @@
{% block two_col_media %}
<style>
.org-logo {
vertical-align: middle;
height: 2em;
width: 2em;
display: inline-block;
margin-right: 0.5em;
}
.toggle {
cursor: pointer;
}
.organization-row:last-child {
border-bottom: none;
}
</style>
{% endblock %}
{% if recent_organizations %}
<div class="blog-sidebox sidebox">
<h3 class="bold-text colored-text"><i class="fa fa-users"></i>{{ _('Recent groups') }}</h3>
<h3 class="bold-text colored-text"><i class="fa fa-building-columns"></i>{{ _('Recent groups') }}</h3>
<div class="toggled sidebox-content">
{% for organization in recent_organizations %}
<a href="{{ url('organization_home', organization.organization.pk, organization.organization.slug) }}" class="organization-row" title="{{organization.organization.about}}">
<img class="org-logo" data-src="{{ organization.organization.logo_override_image or static('icons/icon.png') }}">
<span style="word-break: break-word;">{{ organization.organization }}</span>
<a href="{{ url('organization_home', organization.pk, organization.slug) }}" class="organization-row">
{% if organization.logo_override_image %}
<img class="org-logo user-img" loading="lazy" src="{{ organization.logo_override_image }}">
{% else %}
<img class="org-logo" loading="lazy" src="{{ static('icons/icon.svg') }}" onerror="{{static('icons/logo.svg')}}">
{% endif %}
<span style="word-break: break-word;">{{ organization.name }}</span>
</a>
{% endfor %}
</div>

View file

@ -4,7 +4,7 @@
{% set username = user.get_username() %}
{% set button_text = _("Activate") %}
{% set domain = site.domain %}
{% set protocol = "http" %}
{% set protocol = "https" if request.is_secure() else "http" %}
{% include "general_email.html" %}
<br>
{{_("Alternatively, you can reply to this message to activate your account. Your reply must keep the following text intact for this to work:")}}

View file

@ -6,7 +6,7 @@
{% csrf_token %}
{% if form.errors %}
<div id="form-errors">
<p class="error">{{ _('Invalid username or password.') }}</p>
<p class="error">{{ _('Invalid username/email or password.') }}</p>
</div>
{% endif %}
<table border="0" style="text-align:left">
@ -33,17 +33,17 @@
<h4>{{ _('Or log in with...') }}</h4>
{% if form.has_google_auth %}
<a href="{{ url('social:begin', "google-oauth2") }}?next={{ next }}" class="social google-icon">
<i class="fa fa-google-plus-square"></i>
<i class="fab fa-square-google-plus"></i>
</a>
{% endif %}
{% if form.has_facebook_auth %}
<a href="{{ url('social:begin', "facebook") }}?next={{ next }}" class="social facebook-icon">
<i class="fa fa-facebook-square"></i>
<i class="fab fa-facebook-square"></i>
</a>
{% endif %}
{% if form.has_github_auth %}
<a href="{{ url('social:begin', "github-secure") }}?next={{ next }}" class="social github-icon">
<i class="fa fa-github-square"></i>
<i class="fab fa-github-square"></i>
</a>
{% endif %}
{% endif %}

View file

@ -30,11 +30,13 @@
{% block js_media %}{{ form.media.js }}{% endblock %}
{% block body %}
<form action="" method="post" class="form-area">
{% csrf_token %}
<table border="0" style="text-align:left">{{ form.as_table() }}</table>
<input type="submit" style="float:right;" value="{{ _('Continue >') }}">
</form>
<div id="center-float" class="registration-form">
<form action="" method="post" class="form-area">
{% csrf_token %}
<table border="0" style="text-align:left">{{ form.as_table() }}</table>
<input type="submit" style="float:right;" value="{{ _('Continue >') }}">
</form>
</div>
<div class="map-wrap">
<div class="map-inset">

View file

@ -5,6 +5,6 @@
{% elif logo_override_image is defined and logo_override_image %}
<img src="{{ logo_override_image|camo }}" alt="{{ SITE_NAME }}" height="44" style="border: none">
{% else %}
<img src="{{ static('icons/logo.png') }}" alt="{{ SITE_NAME }}" height="44"
<img src="{{ static('icons/logo.svg') }}" alt="{{ SITE_NAME }}" height="44"
onerror="this.src=&quot;{{ static('icons/logo.png') }}&quot;; this.onerror=null" style="border: none">
{% endif %}

View file

@ -1,4 +1 @@
{{ preview_data|markdown|reference|str|safe }}
{% if REQUIRE_JAX %}
<div data-config="{{ static('mathjax3_config.js') }}" class="require-mathjax-support"></div>
{% endif %}

View file

@ -13,6 +13,6 @@
{% if request.profile.id in submission.problem.editor_ids or perms.judge.edit_all_problem %}
<hr style="float:left;width:30%"><br>
<h4>{{ _('Error information') }}</h4>
<code>{{ submission.error|highlight('pytb', linenos=False) }}</code>
<code>{{ submission.error|highlight('pytb', linenos=True) }}</code>
{% endif %}
{% endif %}

View file

@ -1,4 +1,7 @@
{% extends "three-column-content.html" %}
{% set has_hidden_subtasks = request.in_contest_mode and request.participation.contest.format.has_hidden_subtasks %}
{% block three_col_js %}
<script type="text/javascript">
{% if dynamic_update and last_msg %}
@ -249,7 +252,7 @@
</script>
{% endcompress %}
{% if dynamic_update and last_msg %}
{% if dynamic_update and last_msg and not has_hidden_subtasks %}
<script type="text/javascript">
$(function () {
load_dynamic_update({{last_msg}});
@ -272,10 +275,6 @@
col.sub-info, td.sub-info {
width: 78%
}
#status, #language {
visibility: hidden;
}
</style>
{% endif %}
@ -392,7 +391,7 @@
{{ make_tab_item('friend_tab', 'fa fa-users', friend_submissions_link, _('Friends')) }}
{% endif %}
{% if perms.judge.change_submission %}
{{ make_tab_item('admin', 'fa fa-edit', url('admin:judge_submission_changelist'), _('Admin')) }}
{{ make_tab_item('admin', 'fa fa-edit', url('admin:judge_submission_changelist'), _('Admin'), force_new_page=True) }}
{% endif %}
</div>
{% endblock %}

View file

@ -1,82 +1,69 @@
{% set can_view = submission.is_accessible_by(profile) %}
<div class="sub-result {{ submission._result_class if in_hidden_subtasks_contest else submission.result_class }}">
<div class="score">
{%- if submission.is_graded -%}
{%- if submission.status in ('IE', 'CE', 'AB') -%}
---
{%- else -%}
{{ submission.case_points|floatformat(0) }} / {{ submission.case_total|floatformat(0) }}
{%- endif -%}
{%- else -%}
<i class="fa fa-spinner fa-pulse"></i>
{%- endif -%}
</div>
<div class="state">
{% if in_hidden_subtasks_contest and submission.is_graded %}
<span>
{% set ns = namespace(is_first=False) %}
{% for batch in submission.batches %}
{% if batch.id %}
{{ '+' if ns.is_first else '' }}
{% set ns.is_first = True %}
<span class={{'green' if batch.AC else 'red'}}>
{{ batch.points|floatformat(0) }}
</span>
{% endif %}
{% endfor %}
</span>
{% else %}
{% if not in_hidden_subtasks_contest or submission.status in ('IE', 'CE', 'AB') %}
<span title="{{ submission.long_status }}" class="status">{{ submission.short_status }}</span> |
{% endif %}
<span class="language">{{ submission.language.short_display_name }}</span>
{% set can_view = submission.is_accessible_by(profile, check_contest=False) or is_in_editable_contest %}
<div class="sub-user-img user-img">
<img loading="lazy" src="{{gravatar(submission.user)}}">
</div>
<div class="sub-details">
<div class="sub-info{% if submission.status == 'G' %} sub-info-grading{% endif %}">
<div class="sub-user" style="max-width: {{50 if show_problem else 100}}%">
{{ link_user(submission.user) }}
</div>
{% if show_problem %}
<span></span>
<div class="sub-problem"><a href="{{ url('problem_detail', submission.problem.code) }}">{{ problem_name }}</a></div>
{% endif %}
</div>
</div>
<div class="sub-info{% if submission.status == 'G' %} sub-info-grading{% endif %}">
{% if show_problem %}
<div class="name"><a href="{{ url('problem_detail', submission.problem.code) }}">{{ problem_name }}</a></div>
{% endif %}
<div>
{{ link_user(submission.user) }}
<span class="time">{{ relative_time(submission.date) }}</span>
{% if not request.in_contest_mode and submission.contest_object_id %}
<div class="sub-result">
<div class="state {{ submission._result_class if in_hidden_subtasks_contest else submission.result_class }}">
{% if in_hidden_subtasks_contest and submission.is_graded %}
<span>
{% set ns = namespace(is_first=False) %}
{% for batch in submission.batches %}
{% if batch.id %}
{{ '+' if ns.is_first else '' }}
{% set ns.is_first = True %}
<span class={{'green' if batch.AC else 'red'}}>
{{ batch.points|floatformat(0) }}
</span>
{% endif %}
{% endfor %}
</span>
{% else %}
{% if not in_hidden_subtasks_contest or submission.status in ('IE', 'CE', 'AB') %}
<span title="{{ submission.long_status }}" class="status">{{ submission.short_status }}</span>
{% endif %}
{% endif %}
</div>
<div class="score">
{%- if submission.is_graded -%}
{%- if submission.status in ('IE', 'CE', 'AB') -%}
---
{%- else -%}
{{ submission.case_points|floatformat(0) }} / {{ submission.case_total|floatformat(0) }}
{%- endif -%}
{%- else -%}
<i class="fa fa-spinner fa-pulse"></i>
{% if submission.status == 'G' and not in_hidden_subtasks_contest %}
<span class="sub-testcase">
{%- if submission.current_testcase > 0 -%}
{{ _('%(point)s / #%(case)s', point=submission.points|floatformat(1), case=submission.current_testcase-1) }}
{%- endif -%}
</span>
{% endif %}
{%- endif -%}
</div>
<div class="language">
{{ submission.language.short_display_name }}
</div>
<span class="time">{{ relative_time(submission.date, format=_("d/m/Y"))}}</span>
{% if not hide_contest_in_row 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>
<i title="{{ submission.contest_object.name }}" class="far fa-dot-circle"></i>
</a>
{% endif %}
</div>
</div>
{% if submission.status == 'G' and not in_hidden_subtasks_contest %}
<div class="sub-testcase">
{%- if submission.current_testcase > 0 -%}
{{ _('Point %(point)s / Case #%(case)s', point=submission.points|floatformat(1), case=submission.current_testcase) }}
{%- else -%}
...
{%- endif -%}
</div>
{% endif %}
{% if can_view %}
<div class="sub-prop"><div>
<a href="{{ url('submission_status', submission.id) }}">
<i class="fa fa-eye fa-fw"></i><span class="label">{{ _('view') }}</span>
</a>
{% if perms.judge.rejudge_submission %} ·
<a href="#" onclick="rejudge_submission({{ submission.id }}, event);return false">
<i class="fa fa-refresh fa-fw"></i><span class="label">{{ _('rejudge') }}</span>
</a>
{% endif %}
{% if perms.judge.change_submission %} ·
<a href="{{ url('admin:judge_submission_change', submission.id) }}">
<i class="fa fa-cog fa-fw"></i><span class="label">{{ _('admin') }}</span>
</a>
{% endif %}
</div></div>
{% endif %}
<div class="sub-usage">
{% if submission.status in ('QU', 'P', 'G', 'CE', 'IE', 'AB') or in_hidden_subtasks_contest %}
<div class="time">---</div>
@ -91,4 +78,21 @@
{% endif %}
<div class="memory">{{ (submission.memory_bytes|filesizeformat(True)).replace('i', '') }}</div>
{% endif %}
{% if can_view %}
<div class="sub-prop"><div>
<a href="{{ url('submission_status', submission.id) }}">
<i class="fa fa-eye fa-fw"></i><span class="label">{{ _('view') }}</span>
</a>
{% if perms.judge.rejudge_submission %} ·
<a href="#" onclick="rejudge_submission({{ submission.id }}, event);return false">
<i class="fa fa-refresh fa-fw"></i><span class="label">{{ _('rejudge') }}</span>
</a>
{% endif %}
{% if perms.judge.change_submission %} ·
<a href="{{ url('admin:judge_submission_change', submission.id) }}">
<i class="fa fa-cog fa-fw"></i><span class="label">{{ _('admin') }}</span>
</a>
{% endif %}
</div></div>
{% endif %}
</div>

View file

@ -1,64 +0,0 @@
{% extends "submission/info-base.html" %}
{% block media %}
<style>
.line {
position: relative;
}
.highlighter {
position: absolute;
width: 9999px;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
a:active .line .highlighter {
background: rgba(255, 212, 0, 0.48);
}
.copy-clipboard {
margin-top: 0;
}
</style>
{% endblock %}
{% block body %}
<div style="clear: both"></div>
<br>
<div><a href="{{ url('submission_status', submission.id) }}">{{ _('View status') }}</a></div>
<div><a href="{{ url('submission_source_raw', submission.id) }}">{{ _('View raw source') }}</a></div>
{% if request.user == submission.user.user or perms.judge.resubmit_other %}
<div><a href="{{ url('problem_submit', submission.problem.code, submission.id) }}">{{ _('Resubmit') }}</a></div>
{% endif %}
{% if perms.judge.rejudge_submission %}
<div>
<form action="{{ url('submission_rejudge') }}" method="post">
{% csrf_token %}
<a href="#" onclick="parentNode.submit()">{{ _('Rejudge') }}</a>
<input type="hidden" name="id" value="{{ submission.id }}">
<input type="hidden" name="path" value="{{ url('submission_status', submission.id) }}">
</form>
</div>
{% endif %}
<br>
<hr>
<br>
<div class="source-wrap">
<table style="width: 100%">
<tr>
<td class="source-ln" style="width: 0">
<div>
{% for line in raw_source.split('\n') %}
<a href="#line-{{ loop.index }}" name="line-{{ loop.index }}">
<pre class="line">{{ loop.index }}</pre>
</a>
{% endfor %}
</div>
</td>
<td class="source-code">{{ highlighted_source }}</td>
</tr>
</table>
</div>
{% endblock %}

View file

@ -10,14 +10,14 @@
<pre>{{ submission.error|ansi2html }}</pre>
{% else %}
{% if submission.error %}
<h3><i class="fa fa-exclamation-triangle fa-fw"></i>{{ _('Compilation Warnings') }}</h3>
<h3><i class="fa fa-exclamation-triangle"></i>{{ _('Compilation Warnings') }}</h3>
<pre>{{ submission.error|ansi2html }}</pre>
<hr><br>
{% endif %}
{% if is_pretest %}
<h3><i class="fa fa-check-square-o fa-fw"></i>{{ _('Pretest Execution Results') }}</h3>
<h3><i class="far fa-check-square"></i> {{ _('Pretest Execution Results') }}</h3>
{% else %}
<h3><i class="fa fa-check-square-o fa-fw"></i>{{ _('Execution Results') }}</h3>
<h3><i class="far fa-check-square"></i> {{ _('Execution Results') }}</h3>
{% endif %}
{% for batch in batches %}

View file

@ -135,37 +135,28 @@
{% block body %}
<div style="clear: both"></div>
<br>
{% if request.user == submission.user.user or perms.judge.resubmit_other %}
<div><a href="{{ url('problem_submit', submission.problem.code, submission.id) }}">{{ _('Resubmit') }}</a></div>
{% endif %}
{% if perms.judge.rejudge_submission %}
<div>
<form action="{{ url('submission_rejudge') }}" method="post">
{% csrf_token %}
<a href="#" onclick="parentNode.submit()">{{ _('Rejudge') }}</a>
<input type="hidden" name="id" value="{{ submission.id }}">
<input type="hidden" name="path" value="{{ url('submission_status', submission.id) }}">
</form>
</div>
{% endif %}
<div style="width: fit-content;">
{% if request.profile == submission.user or perms.judge.resubmit_other %}
<div class="link-row"><a href="{{ url('problem_submit', submission.problem.code, submission.id) }}">
<i class="fa fa-upload"></i>{{ _('Resubmit') }}</a></div>
{% endif %}
{% if perms.judge.rejudge_submission %}
<div class="link-row">
<form action="{{ url('submission_rejudge') }}" method="post">
{% csrf_token %}
<a href="#" onclick="parentNode.submit()">
<i class="fa fa-rotate-right"></i>{{ _('Rejudge') }}</a>
<input type="hidden" name="id" value="{{ submission.id }}">
<input type="hidden" name="path" value="{{ url('submission_status', submission.id) }}">
</form>
</div>
{% endif %}
</div>
<br>
<h3 id="source-header" class="toggle closed"><i class="fa fa-chevron-right fa-fw"></i>{{_('Source code')}}</h3>
<div class="source-wrap toggled" style="display: none; margin-bottom: 1em">
<table style="width: 100%">
<tr>
<td class="source-ln" style="width: 0">
<div>
{% for line in raw_source.split('\n') %}
<a href="#line-{{ loop.index }}" name="line-{{ loop.index }}">
<pre class="line">{{ loop.index }}</pre>
</a>
{% endfor %}
</div>
</td>
<td class="source-code">{{ highlighted_source }}</td>
</tr>
</table>
<div class="toggled" style="display: none; margin-bottom: 1em">
{{ highlighted_source }}
</div>
<div id="test-cases">{% include "submission/status-testcases.html" %}</div>

View file

@ -0,0 +1,91 @@
{% extends 'base.html' %}
{% block media %}
<style>
.container {
width: 100%;
margin: auto;
}
.preview-container {
padding-bottom: 16px;
}
#preview {
background-color: rgb(220, 220, 220);
border: solid 2px rgb(180, 180, 180);
padding: 8px;
max-height: 134px;
height: 20%;
overflow-y: scroll;
}
.button-container {
text-align:left;
}
.button {
display:inline-block;
}
.copyright {
position: absolute;
bottom: 48px;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
{% endblock %}
{% block js_media %}
<script>
$(document).ready(function(){
$("#download").on("click", function(event) {
event.preventDefault()
var file_path = document.getElementById('file_path').value;
$.ajax({
url: "{{url('test_formatter_download')}}",
type: 'POST',
data: {
file_path: file_path
},
xhrFields: {
responseType: 'blob'
},
success: function(data) {
var url = window.URL.createObjectURL(data);
var a = document.createElement('a');
a.href = url;
a.download = file_path.split('/').pop();
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
},
error: function(error) {
alert(error);
console.log(error.message)
}
})
});
});
</script>
{% endblock %}
{% block body %}
<div class="container">
<input type="hidden" id="file_path" value={{file_path}}>
<input type="hidden" id="file_path_getnames" value={{file_path_getnames}}>
<div class="preview-container">
<h2>{{_('Download')}}</h2><br>
<h4>{{file_name}}</h4><br>
<div id="preview">
{{ response|safe }}
</div>
</div>
<div class="button-container">
<button type="submit" id="download" class="button">{{_('Download')}}</button>
<a href="{{url('test_formatter_edit')}}?file_path={{file_path_getnames}}" id="edit" class="button">{{_('Edit')}}</a>
</div>
<div class="copyright">
<p >{{_('Copyright')}} Nguyễn Tiến Trung Kiên</p>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,140 @@
{% extends 'base.html' %}
{% block media %}
<style>
.container {
width: 100%;
margin: auto;
}
.column {
flex: 50%;
}
.left {
padding-right: 16px;
}
.right {
padding-left: 16px;
}
.row {
display: flex;
}
input {
width: 100%;
}
.preview-container {
padding-bottom: 16px;
}
.copyright {
position: absolute;
bottom: 48px;
left: 50%;
transform: translate(-50%, -50%);
}
#preview {
background-color: rgb(220, 220, 220);
border: solid 2px rgb(180, 180, 180);
padding: 8px;
max-height: 134px;
height: 20%;
overflow-y: scroll;
}
.button-container {
text-align:left;
}
.button {
display:inline-block;
}
</style>
{% endblock %}
{% block js_media %}
<script>
$(document).ready(function(){
$("#convert").on("click", function(event) {
event.preventDefault()
$.ajax({
url: "{{url('test_formatter_edit')}}",
type: 'POST',
data: {
action: 'convert',
bef_inp_format: $("#bef_inp_format").val(),
bef_out_format: $("#bef_out_format").val(),
aft_inp_format: $("#aft_inp_format").val(),
aft_out_format: $("#aft_out_format").val(),
file_name: $('#file_name').val()
},
success: function(data) {
console.log(data)
$('#preview').html(data);
},
error: function(error) {
alert(error);
console.log(error.message)
}
})
});
});
$(document).ready(function(){
$("#download").on("click", function(event) {
event.preventDefault()
$.ajax({
url: "{{url('test_formatter_edit')}}",
type: 'POST',
data: {
action: 'download'
},
success: function(data) {
var file_path = data;
window.location.href = "{{url('test_formatter_download')}}" + "?file_path="+file_path;
},
error: function(error) {
alert(error);
console.log(error.message)
}
})
});
});
</script>
{% endblock %}
{% block body %}
<div class="container">
<div class="row">
{% csrf_token %}
<div class="column left">
<h3>{{_('Before')}}</h3><br>
<label for="fname">{{_('Input format')}}</label><br>
<input type="text" id="bef_inp_format" value="{{files_list[0]}}" readonly><br>
<label for="lname">{{_('Output format')}}</label><br>
<input type="text" id="bef_out_format" value="{{files_list[1]}}" readonly><br><br>
</div>
<div class="column right">
<h3>{{_('After')}}</h3><br>
<label for="fname">{{_('Input format')}}</label><br>
<input type="text" id="aft_inp_format" value="input.000"><br>
<label for="lname">{{_('Output format')}}</label><br>
<input type="text" id="aft_out_format" value="output.000"><br><br>
</div>
</div>
<div class="preview-container">
<h3>{{_('Preview')}}</h3><br>
<div id="preview">
{{ res|safe }}
</div>
</div>
<div class="filename-container">
<h3>{{_('File name')}}</h3><br>
<input type="text" id="file_name" value="{{file_name}}"><br><br>
</div>
<div class="button-container">
<button type="submit" id="convert" class="button">{{_('Convert')}}</button>
<button type="submit" id="download" class="button">{{_('Download')}}</button>
</div>
<div class="copyright">
<p >{{_('Copyright')}} Nguyễn Tiến Trung Kiên</p>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,23 @@
{% extends 'base.html' %}
{% block media %}
<style>
.copyright {
position: absolute;
bottom: 48px;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
{% endblock %}
{% block body %}
<center>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<button type="submit" style="margin-top: 2em">{{_('Upload')}}</button>
</form>
<div class="copyright">
<p >{{_('Copyright')}} Nguyễn Tiến Trung Kiên</p>
</div>
</center>
{% endblock %}

View file

@ -30,37 +30,17 @@
<script type="text/javascript">
let loadingPage;
function activateBlogBoxOnClick() {
$('.blog-box').on('click', function () {
var $description = $(this).children('.blog-description');
var max_height = $description.css('max-height');
if (max_height !== 'fit-content') {
$description.css('max-height', 'fit-content');
$(this).css('cursor', 'auto');
$(this).removeClass('pre-expand-blog');
$(this).children().children('.show-more').hide();
}
});
$('.blog-box').each(function () {
var $precontent = $(this).children('.blog-description').height();
var $content = $(this).children().children('.content-description').height();
if ($content == undefined) {
$content = $(this).children().children('.md-typeset').height()
}
if ($content > $precontent - 30) {
$(this).addClass('pre-expand-blog');
$(this).css('cursor', 'pointer');
} else {
$(this).children().children('.show-more').hide();
}
});
}
function navigateTo($elem, update_sidebar = false) {
var url = $elem.attr('href');
var force_new_page = $elem.data('force_new_page');
if (url === '#') return;
if (force_new_page) {
window.location.href = url;
return;
}
if (update_sidebar) {
$('.left-sidebar-item').removeClass('active');
$elem.addClass('active');
@ -75,6 +55,7 @@
$('html, body').animate({scrollTop: 0}, 'fast');
$('.middle-right-content').html(reload_content.first().html());
$('#extra_js').html(bodyend_script.first().html());
$("#loading-bar").stop(true, true);
$("#loading-bar").hide().css({ width: 0});
if (reload_content.hasClass("wrapper")) {
$('.middle-right-content').addClass("wrapper");
@ -83,9 +64,8 @@
$('.middle-right-content').removeClass("wrapper");
}
$(document).prop('title', $(data).filter('title').text());
MathJax.typeset($('.middle-right-content')[0]);
renderKatex($('.middle-right-content')[0]);
onWindowReady();
activateBlogBoxOnClick();
$('.xdsoft_datetimepicker').hide();
registerNavigation();
}
@ -96,12 +76,16 @@
}
function registerNavigation() {
const links = ['.pagination a', '.tabs li a'];
for (link of links) {
$(link).on('click', function (e) {
e.preventDefault();
navigateTo($(this));
})
const links = ['.pagination a', '.tabs li a', '#control-panel a'];
for (let linkSelector of links) {
$(linkSelector).each(function() {
if ($(this).attr('target') !== '_blank') {
$(this).on('click', function(e) {
e.preventDefault();
navigateTo($(this));
});
}
});
}
}
@ -109,7 +93,6 @@
window.addEventListener('popstate', (e) => {
window.location.href = e.currentTarget.location.href;
});
activateBlogBoxOnClick();
$('.left-sidebar-item').on('click', function (e) {
e.preventDefault();
@ -123,8 +106,8 @@
</script>
{% endblock %}
{% macro make_tab_item(name, fa, url, text) %}
<a class="left-sidebar-item {% if page_type == name %}active{% endif %}" href="{{ url }}" id="{{ name }}-tab">
{% macro make_tab_item(name, fa, url, text, force_new_page=False) %}
<a class="left-sidebar-item {% if page_type == name %}active{% endif %}" href="{{ url }}" id="{{ name }}-tab" {% if force_new_page%}data-force_new_page="1"{% endif %}>
<span class="sidebar-icon"><i class="{{ fa }}"></i></span>
<span class="sidebar-text">{{ text }}</span>
</a>
@ -152,8 +135,5 @@
{% block bodyend %}
{{ super() }}
{% if REQUIRE_JAX %}
{% include "mathjax-load.html" %}
{% endif %}
{% include "comments/math.html" %}
{% endblock %}

View file

@ -8,20 +8,21 @@
{{ ticket.title }}
</a>
</h3>
{% with author=ticket.user %}
{% if author %}
{% with author_id = ticket.user_id %}
{% if author_id %}
<div class="problem-feed-info-entry">
<i class="fa fa-pencil-square-o fa-fw"></i>
<span class="pi-value">{{ link_user(author) }}</span>
<i class="far fa-pen-to-square"></i>
<span class="pi-value">{{ link_user(author_id) }}</span>
</div>
{% endif %}
{% endwith %}
{% set last_message = ticket.messages.last() %}
<div class="problem-feed-types">
<i class="fa fa-tag"></i>
{{link_user(ticket.messages.last().user)}} {{_(' replied')}}
{{link_user(last_message.user_id)}} {{_('replied')}}
</div>
<div class='blog-description content-description'>
{{ ticket.messages.last().body|markdown(lazy_load=True)|reference|str|safe }}
{{ last_message.body|markdown(lazy_load=True)|reference|str|safe }}
<div class="show-more"> {{_("...More")}} </div>
</div>
</div>

View file

@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block media %}
<style>
#ticket-list .fa-check-circle-o {
#ticket-list .fa-check-circle {
color: #00a900;
}
@ -131,10 +131,10 @@
if ($row.length) {
var $status = $row.find('td').first().find('i');
if (ticket.open) {
$status.removeClass('fa-check-circle-o').addClass('fa-exclamation-circle');
$status.removeClass('fa-check-circle').addClass('fa-exclamation-circle');
notify('ticket', '{{ _('Reopened: ') }}' + ticket.title);
} else {
$status.removeClass('fa-exclamation-circle').addClass('fa-check-circle-o');
$status.removeClass('fa-exclamation-circle').addClass('fa-check-circle');
notify('ticket', '{{ _('Closed: ') }}' + ticket.title);
}
}
@ -193,6 +193,8 @@
}
};
},
delay: 250,
cache: true,
},
};

View file

@ -4,7 +4,7 @@
<div class="header">
<div class="info">
<a class="user-container" href="{{ url('user_page', message.user.user.username) }}" class="user">
<img src="{{ gravatar(message.user, 135) }}" class="gravatar">
<img loading="lazy" src="{{ gravatar(message.user, 135) }}" class="gravatar">
<span class="username {{ message.user.css_class }}">{{ message.user.user.username }}</span>
</a>
</div>

View file

@ -1,4 +1 @@
{{ preview_data|markdown|reference|str|safe }}
{% if REQUIRE_JAX %}
<div data-config="{{ static('mathjax3_config.js') }}" class="require-mathjax-support"></div>
{% endif %}
{{ preview_data|markdown|reference|str|safe }}

View file

@ -1,5 +1,5 @@
<tr id="ticket-{{ ticket.id }}">
<td><i class="fa {% if ticket.is_open %}fa-exclamation-circle{% else %}fa-check-circle-o{% endif %}"></i></td>
<td><i class="fa {% if ticket.is_open %}fa-exclamation-circle{% else %}fa-check-circle{% endif %}"></i></td>
<td>{{ ticket.id }}</td>
<td><a href="{{ url('ticket', ticket.id) }}">{{ ticket.title }}</a></td>
<td>{{ link_user(ticket.user) }}</td>

View file

@ -5,7 +5,6 @@
{% block js_media %}
{{ form.media.js }}
<script src="{{ static('libs/featherlight/featherlight.min.js') }}" type="text/javascript"></script>
<script type="text/javascript" src="{{ static('event.js') }}"></script>
<script type="text/javascript">
$(function () {
@ -14,9 +13,9 @@
function update_ticket_state(open) {
if (open)
$status.removeClass('fa-check-circle-o').addClass('fa-exclamation-circle');
$status.removeClass('fa-check-circle').addClass('fa-exclamation-circle');
else
$status.removeClass('fa-exclamation-circle').addClass('fa-check-circle-o');
$status.removeClass('fa-exclamation-circle').addClass('fa-check-circle');
$('.close-ticket').toggle(open);
$('.open-ticket').toggle(!open);
}
@ -145,7 +144,7 @@
{% block content_title %}
<span class="status">
<i class="fa {% if ticket.is_open %}fa-exclamation-circle{% else %}fa-check-circle-o{% endif %}"></i>
<i class="fa {% if ticket.is_open %}fa-exclamation-circle{% else %}fa-check-circle{% endif %}"></i>
</span>
<span class="title">{{ ticket.title }}</span><small>#{{ ticket.id }}</small>
{% endblock %}
@ -162,7 +161,7 @@
<section class="message new-message">
<div class="info">
<a href="{{ url('user_page', request.user.username) }}" class="user">
<img src="{{ gravatar(request.profile, 135) }}" class="gravatar">
<img loading="lazy" src="{{ gravatar(request.profile, 135) }}" class="gravatar">
<div class="username {{ request.profile.css_class }}">{{ request.user.username }}</div>
</a>
</div>
@ -227,8 +226,5 @@
{% block bodyend %}
{{ super() }}
{% if REQUIRE_JAX %}
{% include "mathjax-load.html" %}
{% endif %}
{% include "comments/math.html" %}
{% endblock %}

View file

@ -1,5 +1,4 @@
{% compress js %}
<script src="{{ static('libs/featherlight/featherlight.min.js') }}" type="text/javascript"></script>
<script type="text/javascript" src="{{ static('libs/timezone-map/timezone-picker.js') }}"></script>
<script type="text/javascript">
$(function () {

View file

@ -9,8 +9,9 @@
<style>
@media (min-width: 800px) {
.middle-content {
max-width: none;
padding-left: 1em;
min-width: 96%;
max-width: 96%;
margin-left: 2%;
}
}
</style>

Some files were not shown because too many files have changed in this diff Show more