mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
templates
This commit is contained in:
1 parent
d5b1f623f8
commit
7fa4a58abe
112 files changed
+5726
No files matched your search
@@ -0,0 +1,137 @@
|
||||
{% extends "layout/wiki_base.html" %}
|
||||
{% block wiki_content %}
|
||||
<div class="section" data-heading-extract-to="#menu-item-about">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="about" data-heading>{{ _('About Vijos') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
{{ _('no_translation_warn')|safe }}
|
||||
<p>Vijos 全称为 Velocious Informatics Judge Online System (高效信息学在线评测系统),致力于为用户提供安全、完善、开放的在线评测及题目交流等服务。</p>
|
||||
<p>Vijos 是一个非营利性的公益网站,由 Mrw、同济大学和北京市第八十中学共同赞助。PingCAP、Google 和清华大学提供技术支持。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" data-heading-extract-to="#menu-item-about">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="contact" data-heading>{{ _('Contact Us') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<h3>{{ _('Discussion') }}:</h3>
|
||||
<blockquote>{{ _('QQ Group') }}: 248452688</blockquote>
|
||||
<h3>{{ _('Manager') }}:</h3>
|
||||
<blockquote>{{ _('QQ') }}: 514649176<br>{{ _('Email') }}: mrw # vijos.org</blockquote>
|
||||
<h3>{{ _('Development') }}:</h3>
|
||||
<blockquote>{{ _('QQ') }}: 490241327<br>{{ _('Email') }}: dev $ vijos.org</blockquote>
|
||||
<h3>{{ _('Ops') }}:</h3>
|
||||
<blockquote>{{ _('QQ') }}: 459834574<br>{{ _('Email') }}: ops [at] vijos.org</blockquote>
|
||||
<h3>{{ _('Feedback') }}:</h3>
|
||||
<blockquote>{{ _('QQ') }}: 1744540592<br>{{ _('Email') }}: feedback &#64; vijos.org</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" data-heading-extract-to="#menu-item-about">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="privacy" data-heading>{{ _('Privacy') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
{{ _('no_translation_warn')|safe }}
|
||||
<h4>1. 收集的信息</h4>
|
||||
<p>我们收集信息是为了向所有用户提供更好的服务。我们有两种信息收集方式:</p>
|
||||
<ul>
|
||||
<li><p>您向我们提供信息。在您注册 Vijos 帐户时,我们会要求您提供个人信息,例如您的电子邮件地址、QQ号码等。</p>
|
||||
</li>
|
||||
<li><p>我们在您使用服务的过程中获取信息。我们会收集关于您使用的服务以及使用方式的信息,例如您在何时使用了我们服务。</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h4>2. 如何使用收集到的信息</h4>
|
||||
<p>我们利用从所有服务中收集的信息来提供、维护、保护和改进这些服务,同时开发新的服务并保护 Vijos 以及用户的隐私。</p>
|
||||
<p>当我们要将信息用于本隐私权政策未载明的其它用途时,则会事先征求您的同意。</p>
|
||||
<h4>3. 访问和更新您的个人信息</h4>
|
||||
<p>无论您在何时使用我们的服务,我们都力求让您能够访问自己的个人信息。如果这些信息有误,我们会努力通过各种方式让您快速更新信息或删除信息。在更新您的个人信息时,我们可能会要求您先验证自己的身份,然后再处理您的请求。</p>
|
||||
<p>我们力求对服务进行完善的维护,以保护信息免遭意外或恶意的破坏。因此,当您从我们的服务中删除信息后,我们可能不会立即从在用的服务器中删除这些信息的残留副本,也可能不会从备份系统中删除相应的信息。</p>
|
||||
<h4>4. 信息安全</h4>
|
||||
<p>我们为您提供SSL加密访问服务,您可以通过SSL(https)使用我们的服务,这可以很大程度上保障在传输过程中您信息的安全。</p>
|
||||
<p>对于敏感数据(如您的密码),我们承诺在存储时进行高强度不可逆加密。Vijos 的管理员、维护人员等均不能够访问到敏感数据的明文,所有操作均无人工介入。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" data-heading-extract-to="#menu-item-about">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="tos" data-heading>{{ _('Terms of Service') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
{{ _('no_translation_warn')|safe }}
|
||||
<h4>0. 欢迎使用 Vijos</h4>
|
||||
<p>注册 Vijos 帐户和/或使用 Vijos 提供的服务(包括网页提供的在线服务和题目评测的非在线服务等),即表示您已同意本条款。请您务必审慎阅读,充分理解条款各项内容。</p>
|
||||
<h4>1. 使用服务</h4>
|
||||
<p>您必须遵守各项服务中提供的所有政策(包括但不限于讨论和题解的版规)。</p>
|
||||
<p>请勿滥用我们的服务。如,请勿干扰我们的服务,或尝试使用除我们提供的界面和指示以外的方法访问这些服务,或使用我们服务中出现的缺陷干扰其他网站或设施的正常运行。您仅能在法律允许的范围内使用我们的服务。</p>
|
||||
<p>您在使用我们服务时须遵守我们服务器所在地的法律法规,不得利用我们服务从事违法违规行为,包括但不限于:</p>
|
||||
<ol>
|
||||
<li>发布、传送、传播、储存危害国家安全统一、破坏社会稳定、违反公序良俗、侮辱、诽谤、淫秽、暴力以及任何违反国家法律法规的内容;</li>
|
||||
<li>发布、传送、传播、储存侵害他人知识产权、商业秘密等合法权利的内容;</li>
|
||||
<li>恶意虚构事实、隐瞒真相以误导、欺骗他人;</li>
|
||||
<li>发布、传送、传播广告信息及垃圾信息;</li>
|
||||
<li>其他法律法规禁止的行为。</li>
|
||||
</ol>
|
||||
<p>如果您违反了约定,相关国家相关机关或机构可能会对您提起诉讼、进行行政处罚或采取其他制裁措施,Vijos 将给于协助。造成损害的,您应依法予以赔偿,Vijos 不承担任何责任。</p>
|
||||
<p>如果 Vijos 发现或收到他人举报您发布的信息违反约定,Vijos 有权进行独立判断并采取技术手段予以删除、屏蔽或断开链接。同时,Vijos 有权视用户的行为性质,采取包括但不限于暂停或终止服务,限制、冻结或终止账户使用,追究法律责任等措施。</p>
|
||||
<h4>2. 版权</h4>
|
||||
<p>使用我们的服务并不代表您拥有我们的服务或您所访问的内容的任何知识产权。网站上的所有材料(包括但不限于题目内容、用户界面、Wiki)版权均受保护,归 Vijos 所有。除非另有说明,本网站上的材料和服务仅用于个人和非商业用途,未经 Vijos 书面许可,不得复制、修改、创建衍生作品、传播、出版、公开演示、公开展示和分发从本网站获得的任何信息、文件、产品或服务。</p>
|
||||
<h4>3. 您在我们服务中发布的内容</h4>
|
||||
<p>我们的某些服务允许您提交内容。您保留对该内容持有的任何知识产权的所有权。</p>
|
||||
<p>当您上传内容或通过其他方式向我们的服务提交内容时,您授予 Vijos 使用、持有、存储、复制、修改、创建衍生作品、传播、出版、公开演示、公开展示和分发此内容等权利。您在此许可中授予的权限,仅能用于运营、宣传和改进我们的服务,以及开发新的服务。该项许可在您停止使用我们的服务后依然有效。某些服务可能会向您提供一些方法,用于访问和删除您提供给该服务的内容。对于您提交至我们服务的任何内容,请确保您拥有向我们授予此许可的必要权利。我们有权在未通知您的情况下删除我们认为侵犯了知识产权或违反了相关法律法规的内容。</p>
|
||||
<h4>4. 对于发布题目的附加条款</h4>
|
||||
<p>您可以在 Vijos 上创建新题目。您上传到 Vijos 的题目,除了适用于本协议第三条(即“您在我们服务中发布的内容”)条款,还包含以下附加条款(若有冲突的条款,以附加条款中的优先):</p>
|
||||
<ol>
|
||||
<li><p>您上传到 Vijos 上的题目版权为 Vijos 和您共同拥有,我们会在相关页面或在对其进行分发、传播等操作时标明版权所有者。
|
||||
</p></li>
|
||||
<li><p>Vijos 尊重他人知识产权和合法权益,请您在上传题目前确保拥有题目内容(包括但不限于题目描述、数据、图片等)的著作权及信息网络传播权或者已经取得上述全部权利人的许可并不存在任何著作权纠纷。Vijos有权在不通知的情况下删除被认为侵权的题目。
|
||||
</p></li>
|
||||
<li><p>您可以申请将自己上传的优质题目合并到题库主干。我们的管理员会对您创建的题目的内容(包括但不限于评测数据等对用户不可见的信息)进行人工审核和适当修改以确认其符合国家基本法律法规。出于质量的考虑,我们也可能会拒绝您完全合法的合并到题库主干的请求。
|
||||
</p></li>
|
||||
<li><p>我们会维护服务的稳定,并对数据(包括您递交的题目)进行定期的备份,并尽量在关闭服务前通知您,但我们仍然不对任何题目(包括主干和非主干)提供永久存储或保留的承诺,出于安全的考虑推荐您自行保留题目的内容。
|
||||
</p></li>
|
||||
<li><p>您有权决定 Vijos 是否公开您上传的题目的数据。公开题目数据意味着 Vijos 上的用户均有权利获取到您递交的题目的所有评测数据,但相关版权协议仍然生效。</p>
|
||||
</li>
|
||||
</ol>
|
||||
<h4>5. 隐私保护</h4>
|
||||
<p><a href="{{ reverse_url('about') }}#privacy">Vijos 隐私声明</a>介绍了您在使用我们的服务时,我们会如何处理您的个人数据和保护您的隐私。使用我们的服务即表示您同意 Vijos 可以按照我们的隐私权政策使用您的个人数据。</p>
|
||||
<h4>6. 修改和终止服务</h4>
|
||||
<p>我们始终在不断更改和改进我们的服务。我们可能会增加或删除功能,也可能暂停或彻底停止某项服务。</p>
|
||||
<p>您可以随时停止使用我们的服务,尽管我们对此表示非常遗憾。Vijos 也可能随时停止向您提供服务,或随时对我们的服务增加或设置新的限制。</p>
|
||||
<h4>7. 保证和免责声明</h4>
|
||||
<p>我们对服务内容、服务的具体功能,或其可靠性、可用性或满足您需要的能力不作任何承诺。我们的服务是按照现有技术和条件所能达到的现状提供的。我们会尽最大努力向您提供服务,确保服务的连贯性和安全性。但我们不能随时预见和防范法律、技术以及其他风险,包括但不限于不可抗力、病毒、木马、黑客攻击、系统不稳定、第三方服务瑕疵、政府行为等原因可能导致的服务中断、数据丢失以及其他的损失和风险。</p>
|
||||
<h4>8. 关于本条款</h4>
|
||||
<p>我们可以修改上述条款或任何适用于某项服务的附加条款,您应当定期查阅本条款。所有修改的适用不具有追溯力,且会在公布十四天或更长时间后方始生效。但是,对服务新功能的特别修改或由于法律原因所作的修改将立即生效。如果您不同意服务的修改条款,应停止使用服务。</p>
|
||||
<h4>9. 其他</h4>
|
||||
<p>如果您对这个协议或我们的服务有意见或建议,可与我们联系,我们会给予您必要的帮助。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" data-heading-extract-to="#menu-item-about">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="discuss" data-heading>{{ _('Discussion: Terms Of Service') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
{{ _('no_translation_warn')|safe }}
|
||||
<p>为了更好地发挥讨论、题解的积极作用,使广大用户学到知识、获得利益,进一步规范讨论和题解功能的使用,我们制定了《讨论和题解版规》(简称《版规》)。您在发布(或回复)讨论和题解时,即代表您已充分阅读、理解、接受并保证遵守此版规。</p>
|
||||
<p>您在发布(或回复)讨论和题解或使用相关功能时须遵守以下规定:</p>
|
||||
<blockquote>
|
||||
<p>第一次使用编辑器前,要先阅读编辑器快速入门和 Markdown 详细帮助。</p>
|
||||
<p>不得将讨论、题解混淆。例如,不得将题解发布到讨论中,题解应发布在相应题目的题解区中。</p>
|
||||
<p>发布(或回复)的所有内容不得包含会干扰 Vijos 用户界面呈现的相关内容。</p>
|
||||
<p>发布(或回复)的所有内容不得包含恶意代码和指向恶意网站或 Vijos 明确禁止的网站的链接。</p>
|
||||
<p>特别地,发布(或回复)含有代码的内容时,应当将代码高亮。一个简单的方法是选中代码块然后按下 Tab 键。</p>
|
||||
<p>发布的题解禁止只包含无详细注释的代码。题解中难以理解的代码应当有尽可能详细的注释。</p>
|
||||
<p>打分、投票和评价应当客观。例如,对于题解的打分、投票和评价应当关注于题解本身的质量。</p>
|
||||
<p>我们欢迎原创作品,并会对其作者给予数量不等的 RP 奖励。</p>
|
||||
</blockquote>
|
||||
<p>您在发布、回复讨论和题解时还须遵守法律法规,不得发布违法违规内容,包括但不限于:</p>
|
||||
<blockquote>
|
||||
<p>危害国家安全统一、破坏社会稳定、违反公序良俗、侮辱、诽谤、淫秽、暴力以及任何违反国家法律法规的内容;</p>
|
||||
<p>侵害他人知识产权、商业秘密等合法权利的内容;</p>
|
||||
<p>恶意虚构事实、隐瞒真相以误导、欺骗他人的内容;</p>
|
||||
<p>广告信息及垃圾信息;</p>
|
||||
<p>其他法律法规禁止的内容。</p>
|
||||
</blockquote>
|
||||
<p>对于违反《版规》的,我们将进行警告并删除相关内容、临时冻结用户、永久冻结用户等操作。</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends "layout/mail.html" %}
|
||||
{% block title %}{{ _('P{0} - {1} Accepted!').format(pdoc['doc_id'], pdoc['title']) }}{% endblock %}
|
||||
{% block content %}
|
||||
<p>{{ _('Congratulations! Your submission is accepted.') }}</p>
|
||||
<p>{{ _('Problem') }}: <a href="{{ url_prefix }}{{ reverse_url('problem_detail', domain_id=pdoc['domain_id'], pid=pdoc['doc_id']) }}">P{{ pdoc['doc_id'] }} {{ pdoc['title'] }}</a></p>
|
||||
<p>{{ _('Code') }}:</p>
|
||||
<pre>
|
||||
{{ rdoc['code'] }}
|
||||
</pre>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Vijos System Error</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<style type="text/css">
|
||||
body {
|
||||
background: #272822;
|
||||
padding-top: 100px;
|
||||
}
|
||||
pre{
|
||||
font-family: "monaco", "Consolas", "Source Code Pro", "Courier New", monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="code-content" style="text-align: center"><pre style="font-size: 18px; line-height: 125%; display: inline-block; text-align: left; white-space: pre-wrap; word-wrap: break-word;"><span style="color: #75715e">#include <string.h></span>
|
||||
|
||||
<span style="color: #66d9ef">int</span> <span style="color: #a6e22e">main</span><span style="color: #f8f8f2">()</span> <span style="color: #f8f8f2">{</span>
|
||||
<span style="color: #66d9ef">char</span> <span style="color: #f8f8f2">answer[</span><span style="color: #ae81ff">42</span><span style="color: #f8f8f2">];</span>
|
||||
<span style="color: #f8f8f2">strcpy(answer,</span> <span style="color: #e6db74">"twd2 will tell you the answer to life the universe and everything,"</span><span style="color: #f8f8f2">);</span>
|
||||
<span style="color: #f8f8f2">strcpy(answer,</span> <span style="color: #e6db74">"but first of all, he is very sorry that Vijos meets some issues now."</span><span style="color: #f8f8f2">);</span>
|
||||
<span style="color: #f8f8f2">strcpy(answer,</span> <span style="color: #e6db74">"please <a href="javascript:window.location.reload()" style="color: #e6db74" title="Try again">wait patiently</a>, or <a style="color: #e6db74" href="mailto:twd2@163.com">contact twd2</a> impatiently about this error."</span><span style="color: #f8f8f2">);</span>
|
||||
<span style="color: #66d9ef">return</span> <span style="color: #ae81ff">0</span><span style="color: #f8f8f2">;</span>
|
||||
<span style="color: #f8f8f2">}</span>
|
||||
</pre></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,37 @@
|
||||
{% macro render(
|
||||
view, docs, udict,
|
||||
comment_ref,
|
||||
reply_ref,
|
||||
comment_post_perm,
|
||||
comment_edit_perm,
|
||||
comment_edit_self_perm,
|
||||
comment_delete_perm,
|
||||
comment_delete_self_perm,
|
||||
reply_post_perm,
|
||||
reply_edit_perm,
|
||||
reply_edit_self_perm,
|
||||
reply_delete_perm,
|
||||
reply_delete_self_perm,
|
||||
comment_placeholder = 'Write Your Comment',
|
||||
comment_post_op = 'reply',
|
||||
comment_edit_op = 'edit_reply',
|
||||
comment_post_text = 'Comment',
|
||||
comment_edit_text = 'Update',
|
||||
reply_post_op = 'tail_reply',
|
||||
reply_post_text = 'Reply',
|
||||
reply_edit_op = 'edit_tail_reply',
|
||||
reply_edit_text = 'Update',
|
||||
comment_delete_op = 'delete_reply',
|
||||
reply_delete_op = 'delete_tail_reply'
|
||||
) %}
|
||||
{% import "components/comments_base.html" as comment_base with context %}
|
||||
{% import "components/comments_"~view~".html" as comment_impl with context %}
|
||||
<ul class="dczcomments__list view--{{ view }}">
|
||||
{% if handler.has_perm(comment_post_perm) %}
|
||||
{{ comment_impl.comment(true, handler.user) }}
|
||||
{% endif %}
|
||||
{% for doc in docs %}
|
||||
{{ comment_impl.comment(false, udict[doc['owner_uid']], doc) }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,46 @@
|
||||
{% macro comment_form() %}
|
||||
<div class="hasjs--hide">
|
||||
<form method="post" class="dczcomments__box" name="dczcomments__box__form" data-hotkey="ctrl+enter:submit,esc:vjCommentBoxCancel">
|
||||
<div>
|
||||
<textarea name="content" class="textbox" data-markdown required></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" class="rounded primary button dczcomments__box__submit" value="{{ _(comment_post_text) }} (Ctrl+Enter)" data-value-reply="{{ _(reply_post_text) }} (Ctrl+Enter)" data-value-comment="{{ _(comment_post_text) }} (Ctrl+Enter)" data-value-comment-update="{{ _(comment_edit_text) }} (Ctrl+Enter)" data-value-reply-update="{{ _(reply_edit_text) }} (Ctrl+Enter)">
|
||||
<input type="button" class="rounded button nojs--hide" name="dczcomments__box__cancel" value="{{ _('Cancel') }} (Esc)">
|
||||
</div>
|
||||
<input type="hidden" name="operation" value="{{ comment_post_op }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
</form>
|
||||
</div>
|
||||
<div class="nojs--hide">
|
||||
<textarea class="textbox" name="dczcomments__dummy-box" readonly data-form="{{ {"operation": comment_post_op}|json }}" placeholder="{{ _(comment_placeholder) }}"></textarea>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro comment_operations(doc) %}
|
||||
<div class="dczcomments__operations nojs--hide">
|
||||
{% if handler.has_perm(reply_post_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Reply') }}" name="dczcomments__op-reply-comment" data-form="{{ {'operation': reply_post_op, comment_ref: doc['doc_id']}|json }}"><span class="icon icon-reply"></span></a>
|
||||
{% endif %}
|
||||
{% if handler.own(doc, comment_edit_self_perm) or handler.has_perm(comment_edit_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Edit') }}" name="dczcomments__op-edit-comment" data-form="{{ {'operation': comment_edit_op, comment_ref: doc['doc_id']}|json }}"><span class="icon icon-edit"></span></a>
|
||||
{% endif %}
|
||||
{% if handler.own(doc, comment_delete_self_perm) or handler.has_perm(comment_delete_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Delete') }}" name="dczcomments__op-delete-comment" data-form="{{ {'operation': comment_delete_op, comment_ref: doc['doc_id']}|json }}"><span class="icon icon-delete"></span></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro reply_operations(doc, rdoc) %}
|
||||
<div class="dczcomments__operations nojs--hide">
|
||||
{% if handler.has_perm(reply_post_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Reply') }}" name="dczcomments__op-reply-reply"><span class="icon icon-reply"></span></a>
|
||||
{% endif %}
|
||||
{% if handler.own(rdoc, reply_edit_self_perm) or handler.has_perm(reply_edit_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Edit') }}" name="dczcomments__op-edit-reply" data-form="{{ {'operation': reply_edit_op, comment_ref: doc['doc_id'], reply_ref: rdoc['_id']}|json }}"><span class="icon icon-edit"></span></a>
|
||||
{% endif %}
|
||||
{% if handler.own(rdoc, reply_delete_self_perm) or handler.has_perm(reply_delete_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Delete') }}" name="dczcomments__op-delete-reply" data-form="{{ {'operation': reply_delete_op, comment_ref: doc['doc_id'], reply_ref: rdoc['_id']}|json }}"><span class="icon icon-delete"></span></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,63 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% macro reply(mode_create, udoc, doc = {}, rdoc = {}) %}
|
||||
<li class="dczcomments__reply{% if mode_create %} commentbox-container{% endif %}">
|
||||
<div class="media">
|
||||
<div class="media__left top">
|
||||
<img src="{{ udoc['gravatar']|gravatar_url }}" width="50" height="50" class="medium user-profile-avatar">
|
||||
</div>
|
||||
<div class="media__body top no-heading">
|
||||
{% if not mode_create %}
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, dudict[udoc['_id']], avatar=false) }}
|
||||
@ {{ datetime_span(rdoc['_id'].generation_time) }}
|
||||
</div>
|
||||
{{ comment_base.reply_operations(doc, rdoc) }}
|
||||
</div>
|
||||
<div class="typo" data-emoji-enabled data-raw-url="{{ reverse_url('discussion_tail_reply_raw', did=doc['parent_doc_id'], drid=doc['doc_id'], drrid=rdoc['_id']) }}">
|
||||
{{ rdoc['content']|markdown }}
|
||||
</div>
|
||||
<div class="commentbox-edit-target"></div>
|
||||
{% else %}
|
||||
<div class="commentbox-placeholder"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro comment(mode_create, udoc, doc = {}) %}
|
||||
<li class="dczcomments__item">
|
||||
<div class="media">
|
||||
<div class="media__left top">
|
||||
<img src="{{ udoc['gravatar']|gravatar_url }}" width="60" height="60" class="medium user-profile-avatar">
|
||||
</div>
|
||||
<div class="media__body top no-heading">
|
||||
{% if not mode_create %}
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, dudict[udoc['_id']], avatar=false) }}
|
||||
@ {{ datetime_span(doc['_id'].generation_time) }}
|
||||
</div>
|
||||
{{ comment_base.comment_operations(doc) }}
|
||||
</div>
|
||||
<div class="typo" data-emoji-enabled data-raw-url="{{ reverse_url('discussion_reply_raw', did=doc['parent_doc_id'], drid=doc['doc_id']) }}">
|
||||
{{ doc['content']|markdown }}
|
||||
</div>
|
||||
<div class="commentbox-edit-target"></div>
|
||||
<ul class="dczcomments__replies commentbox-reply-target">
|
||||
{% for rdoc in doc['reply'] %}
|
||||
{{ reply(mode_create, udict[rdoc['owner_uid']], doc, rdoc) }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
{{ comment_base.comment_form() }}
|
||||
<div class="commentbox-placeholder"></div>
|
||||
<ul style="display:none">
|
||||
{{ reply(mode_create, udoc) }}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,96 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% macro reply(mode_create, udoc, doc = {}, rdoc = {}) %}
|
||||
<li class="dczcomments__reply{% if mode_create %} commentbox-container{% endif %}">
|
||||
<div class="media">
|
||||
<div class="media__body top no-heading">
|
||||
{% if not mode_create %}
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, badge=false) }}
|
||||
@ {{ datetime_span(rdoc['_id'].generation_time) }}
|
||||
</div>
|
||||
{{ comment_base.reply_operations(doc, rdoc) }}
|
||||
</div>
|
||||
<div class="typo" data-emoji-enabled data-raw-url="{{ reverse_url('problem_solution_reply_raw', pid=doc['parent_doc_id'], psid=doc['doc_id'], psrid=rdoc['_id']) }}">
|
||||
{{ rdoc['content']|markdown }}
|
||||
</div>
|
||||
<div class="commentbox-edit-target"></div>
|
||||
{% else %}
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, badge=false) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="commentbox-placeholder"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro comment(mode_create, udoc, doc = {}) %}
|
||||
<li class="dczcomments__item">
|
||||
<div class="media">
|
||||
<div class="media__left top">
|
||||
{% if not mode_create %}
|
||||
<div class="vote vote--discussion">
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_VOTE_PROBLEM_SOLUTION) %}
|
||||
<div class="vote-number rotator--enabled">{{ doc['vote'] }}</div>
|
||||
<div class="vote-op clearfix">
|
||||
<form method="post">
|
||||
<input type="hidden" name="operation" value="upvote">
|
||||
<input type="hidden" name="psid" value="{{ doc['doc_id'] }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="vote-button upvote{% if pssdict[doc['doc_id']]['vote'] == 1 %} active{% endif %}" data-tooltip="{{ _('Upvote') }}" data-tooltip-pos="bottom center" aria-label="{{ _('Upvote') }}"><span class="icon icon-vote--up"></span></button>
|
||||
</form>
|
||||
<form method="post">
|
||||
<input type="hidden" name="operation" value="downvote">
|
||||
<input type="hidden" name="psid" value="{{ doc['doc_id'] }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="vote-button downvote{% if pssdict[doc['doc_id']]['vote'] == -1 %} active{% endif %}" data-tooltip="{{ _('Downvote') }}" data-tooltip-pos="bottom center" aria-label="{{ _('Downvote') }}"><span class="icon icon-vote--down"></span></button>
|
||||
</form>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="vote-number">{{ doc['vote'] }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="vote vote--discussion">
|
||||
<div class="vote-number">0</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="media__body top no-heading">
|
||||
{% if not mode_create %}
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, dudict[udoc['_id']]) }}
|
||||
@ {{ datetime_span(doc['_id'].generation_time) }}
|
||||
</div>
|
||||
{{ comment_base.comment_operations(doc) }}
|
||||
</div>
|
||||
<div class="typo" data-emoji-enabled data-raw-url="{{ reverse_url('problem_solution_raw', pid=doc['parent_doc_id'], psid=doc['doc_id']) }}">
|
||||
{{ doc['content']|markdown }}
|
||||
</div>
|
||||
<div class="commentbox-edit-target"></div>
|
||||
<ul class="dczcomments__replies commentbox-reply-target">
|
||||
{% for rdoc in doc['reply'] %}
|
||||
{{ reply(mode_create, udict[rdoc['owner_uid']], doc, rdoc) }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, dudict[udoc['_id']]) }}
|
||||
</div>
|
||||
</div>
|
||||
{{ comment_base.comment_form() }}
|
||||
<div class="commentbox-placeholder"></div>
|
||||
<ul style="display:none">
|
||||
{{ reply(mode_create, udoc) }}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% macro render_time(tdoc_time) %}
|
||||
{{ datetime_span(tdoc_time, false, '%Y-%m-%d %H:%M') }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_duration(tdoc) %}
|
||||
{{ ((tdoc['end_at'] - tdoc['begin_at']).total_seconds() / 3600)|round(1) }}
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,201 @@
|
||||
{% macro form_begin() %}
|
||||
{% set label = kwargs.pop('label') %}
|
||||
{% set columns = kwargs.pop('columns') %}
|
||||
{% set last_column = kwargs.pop('last_column', true) %}
|
||||
{% set required = kwargs.pop('required', false) %}
|
||||
{% set hotkeys = kwargs.pop('hotkeys', none) %}
|
||||
{% set row = kwargs.pop('row', true) %}
|
||||
{% set no_label = kwargs.pop('no_label', false) %}
|
||||
{% set label_wrap = kwargs.pop('label_wrap', true) %}
|
||||
{% if row %}
|
||||
<div class="row">
|
||||
{% endif %}
|
||||
<div
|
||||
class="{% if columns %}medium-{{ columns }} {% endif %}columns form__item{% if last_column %} end{% endif %}"
|
||||
{% if hotkeys %}data-hotkey="{{ hotkeys }}"{% endif %}
|
||||
>
|
||||
{% if not no_label %}
|
||||
<label>
|
||||
{{ _(label) }}
|
||||
{% if required %}
|
||||
({{ _('required') }})
|
||||
{% endif %}
|
||||
{% if not label_wrap %}
|
||||
</label>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_end() %}
|
||||
{% set help_text = kwargs.pop('help_text', none) %}
|
||||
{% set row = kwargs.pop('row', true) %}
|
||||
{% set no_label = kwargs.pop('no_label', false) %}
|
||||
{% set label_wrap = kwargs.pop('label_wrap', true) %}
|
||||
{% if not no_label and label_wrap %}
|
||||
</label>
|
||||
{% endif %}
|
||||
{% if help_text %}
|
||||
<p class="help-text">{{ _(help_text)|safe }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if row %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_attr(form_class) %}
|
||||
{% set disabled = kwargs.pop('disabled', false) %}
|
||||
{% set required = kwargs.pop('required', false) %}
|
||||
{% set autofocus = kwargs.pop('autofocus', false) %}
|
||||
{% set date = kwargs.pop('date', false) %}
|
||||
{% set time = kwargs.pop('time', false) %}
|
||||
class="{{ form_class }}{% if extra_class %} {{ extra_class }}{% endif %}"
|
||||
{% if disabled %}disabled{% endif %}
|
||||
{% if required %}required{% endif %}
|
||||
{% if autofocus %}autofocus data-autofocus{% endif %}
|
||||
{% if date %}data-pick-date{% endif %}
|
||||
{% if time %}data-pick-time{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro container_attr(container_class) %}
|
||||
{% set extra_class = kwargs.pop('extra_class', none) %}
|
||||
class="{{ container_class }}{% if extra_class %} {{ extra_class }}{% endif %}"
|
||||
{% endmacro %}
|
||||
|
||||
{% macro select(options, name='', value='') %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
{{ container_attr('select-container', **kwargs) }}
|
||||
>
|
||||
<select
|
||||
name="{{ name }}"
|
||||
{{ form_attr('select', **kwargs) }}
|
||||
>
|
||||
{% for k, v in options %}
|
||||
<option value="{{ k }}"{% if value == k %} selected{% endif %}>
|
||||
{{ _(v) }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_select(columns=5) %}
|
||||
{{ form_begin(columns=columns, **kwargs) }}
|
||||
{{ select(columns=columns, **kwargs) }}
|
||||
{{ form_end(columns=columns, **kwargs) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro radio(options, name='', value='') %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
{{ container_attr('radiobox-container', **kwargs) }}
|
||||
>
|
||||
{% for k, v in options %}
|
||||
<label class="radiobox">
|
||||
<input
|
||||
value="{{ k }}"
|
||||
type="radio"
|
||||
name="{{ name }}"
|
||||
{{ form_attr('radiobox__input', **kwargs) }}
|
||||
{% if value == k %} checked{% endif %}
|
||||
/> {{ _(v) }}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_radio(columns=5) %}
|
||||
{{ form_begin(columns=columns, label_wrap=false, **kwargs) }}
|
||||
{{ radio(columns=columns, **kwargs) }}
|
||||
{{ form_end(columns=columns, label_wrap=false, **kwargs) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro image_radio(options, name='', value='', image_class='') %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
{{ container_attr('radiobox-container with-image', **kwargs) }}
|
||||
>
|
||||
{% for k, v in options %}
|
||||
<label class="radiobox with-image">
|
||||
<input
|
||||
value="{{ k }}"
|
||||
type="radio"
|
||||
name="{{ name }}"
|
||||
{{ form_attr('radiobox__input', **kwargs) }}
|
||||
{% if value == k %} checked{% endif %}
|
||||
/>
|
||||
<div class="radiobox__image-container" data-tooltip="{{ _(v) }}">
|
||||
<div class="radiobox__image {{ image_class.format(k) }}"></div>
|
||||
</div>
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_image_radio(columns=8) %}
|
||||
{{ form_begin(columns=columns, label_wrap=false, **kwargs) }}
|
||||
{{ image_radio(columns=columns, **kwargs) }}
|
||||
{{ form_end(columns=columns, label_wrap=false, **kwargs) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro text(name='', value='', placeholder='', type='text') %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
{{ container_attr('textbox-container', **kwargs) }}
|
||||
>
|
||||
<input
|
||||
type="{{ type }}"
|
||||
name="{{ name }}"
|
||||
value="{{ value }}"
|
||||
placeholder="{{ placeholder }}"
|
||||
{{ form_attr('textbox', **kwargs) }}
|
||||
>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_text(columns=5) %}
|
||||
{{ form_begin(columns=columns, **kwargs) }}
|
||||
{{ text(columns=columns, **kwargs) }}
|
||||
{{ form_end(columns=columns, **kwargs) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro textarea(name='', value='', placeholder='') %}
|
||||
{% set markdown = kwargs.pop('markdown', false) %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
{{ container_attr('textarea-container', **kwargs) }}
|
||||
>
|
||||
<textarea
|
||||
name="{{ name }}"
|
||||
placeholder="{{ placeholder }}"
|
||||
{% if markdown %}data-markdown{% endif %}
|
||||
{{ form_attr('textbox', **kwargs) }}
|
||||
>{{ value }}</textarea>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_textarea(columns=8) %}
|
||||
{{ form_begin(columns=columns, **kwargs) }}
|
||||
{{ textarea(columns=columns, **kwargs) }}
|
||||
{{ form_end(columns=columns, **kwargs) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro checkbox(label='', name='', value=false) %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
{{ container_attr('checkbox-container', **kwargs) }}
|
||||
>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="{{ name }}"{% if value %} checked{% endif %}
|
||||
{{ form_attr('checkbox', **kwargs) }}
|
||||
>{{ _(label) }}
|
||||
</label>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_checkbox(columns=5) %}
|
||||
{{ form_begin(columns=columns, no_label=True, **kwargs) }}
|
||||
{{ checkbox(columns=columns, **kwargs) }}
|
||||
{{ form_end(columns=columns, no_label=True, **kwargs) }}
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,17 @@
|
||||
{% import "components/sidemenu.html" as sidemenu with context %}
|
||||
{% macro render_sidebar() %}
|
||||
<div class="section side">
|
||||
<ol class="menu">
|
||||
{{ sidemenu.render_item('account--circle', 'user_detail', label='My Profile', uid=handler.user['_id']) }}
|
||||
{{ sidemenu.render_item('comment--multiple', 'home_messages') }}
|
||||
<li class="menu__seperator"></li>
|
||||
{{ sidemenu.render_item('wrench', 'home_account') }}
|
||||
{{ sidemenu.render_item('web', 'home_domain_account', label='@ '+handler.domain['name']) }}
|
||||
{{ sidemenu.render_item('sliders', 'home_preference') }}
|
||||
{{ sidemenu.render_item('security', 'home_security') }}
|
||||
<li class="menu__seperator"></li>
|
||||
{{ sidemenu.render_item('file', 'home_file') }}
|
||||
{{ sidemenu.render_item('web', 'home_domain') }}
|
||||
</ol>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% macro render_time(tdoc_time) %}
|
||||
{{ datetime_span(tdoc_time, false, '%Y-%m-%d %H:%M') }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_extension(tdoc) %}
|
||||
{{ ((tdoc['end_at'] - tdoc['penalty_since']).total_seconds() / 3600)|round(1) }}
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,29 @@
|
||||
<div class="section side">
|
||||
<div class="section__body typo">
|
||||
<dl>
|
||||
<dt>{{ _('Inline codes') }}</dt>
|
||||
<dd><pre>`std::cout()`</pre></dd>
|
||||
<dt>{{ _('Code blocks') }}</dt>
|
||||
<dd>
|
||||
<pre>```c++
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
```</pre>
|
||||
</dd>
|
||||
<dt>{{ _('Inline formulas') }}</dt>
|
||||
<dd><pre>$ E=mc^2 $</pre></dd>
|
||||
<dt>{{ _('Formula blocks') }}</dt>
|
||||
<dd><pre>$$ E=mc^2 $$</pre></dd>
|
||||
<dt>{{ _('Links') }}</dt>
|
||||
<dd><pre>[{{ _('Text') }}](http://...)</pre></dd>
|
||||
<dt>{{ _('Images') }}</dt>
|
||||
<dd><pre></pre></dd>
|
||||
</dl>
|
||||
<h2>{{ _('Learn More') }}</h2>
|
||||
<ul>
|
||||
<li><a href="http://commonmark.org/help/" target="_blank"><span class="icon icon-link--external"></span> {{ _('CommonMark Syntax') }}</a></li>
|
||||
<li><a href="http://www.onemathematicalcat.org/MathJaxDocumentation/TeXSyntax.htm" target="_blank"><span class="icon icon-link--external"></span> {{ _('LaTeX Expressions') }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
{% macro render() %}
|
||||
<noscript><div class="section__body no-padding">
|
||||
<blockquote class="warn">
|
||||
<p>{{ _('This page needs JavaScript to work.') }}</p>
|
||||
</blockquote>
|
||||
</div></noscript>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% macro render(text, compact=false) %}
|
||||
<div class="nothing-placeholder{% if compact %} compact{% endif %}">
|
||||
<div class="nothing-icon"></div>
|
||||
{{ _(text) }}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,25 @@
|
||||
{% macro render(page, num_pages, add_qs='') %}
|
||||
{% if num_pages > 0 %}
|
||||
<ul class="pager">
|
||||
{% for type, page0 in paginate(page, num_pages) %}
|
||||
<li>
|
||||
{% if type == 'first' %}
|
||||
<a class="pager__item first link" href="?page={{ page0 }}{% if add_qs %}&{{ add_qs }}{% endif %}">{{ _('pager_first') }}</a>
|
||||
{% elif type == 'previous' %}
|
||||
<a class="pager__item previous link" href="?page={{ page0 }}{% if add_qs %}&{{ add_qs }}{% endif %}">{{ _('pager_previous') }}</a>
|
||||
{% elif type == 'ellipsis' %}
|
||||
<span class="pager__item ellipsis">...</span>
|
||||
{% elif type == 'page' %}
|
||||
<a class="pager__item page link" href="?page={{ page0 }}{% if add_qs %}&{{ add_qs }}{% endif %}">{{ page0 }}</a>
|
||||
{% elif type == 'current' %}
|
||||
<span class="pager__item current">{{ page0 }}</span>
|
||||
{% elif type == 'next' %}
|
||||
<a class="pager__item next link" href="?page={{ page0 }}{% if add_qs %}&{{ add_qs }}{% endif %}">{{ _('pager_next') }}</a>
|
||||
{% elif type == 'last' %}
|
||||
<a class="pager__item last link" href="?page={{ page0 }}{% if add_qs %}&{{ add_qs }}{% endif %}">{{ _('pager_last') }}</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,40 @@
|
||||
{% macro render_problem_title(pdoc, tdoc=none, show_tags=true, show_invisible_flag=true, rp=none, invalid=false) %}
|
||||
{%- if not invalid %}
|
||||
<a
|
||||
{%- if tdoc is none %}
|
||||
href="{{ reverse_url('problem_detail', domain_id=pdoc['domain_id'], pid=pdoc['doc_id']) }}"
|
||||
{%- elif tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST %}
|
||||
href="{{ reverse_url('contest_detail_problem', domain_id=pdoc['domain_id'], pid=pdoc['doc_id'], tid=tdoc['doc_id']) }}"
|
||||
{%- elif tdoc['doc_type'] == vj4.model.document.TYPE_HOMEWORK %}
|
||||
href="{{ reverse_url('homework_detail_problem', domain_id=pdoc['domain_id'], pid=pdoc['doc_id'], tid=tdoc['doc_id']) }}"
|
||||
{%- endif %}
|
||||
>
|
||||
{%- endif %}
|
||||
{% if pdoc['doc_id']|string|length < 10 %}P{{ pdoc['doc_id'] }} {% endif %}{{ pdoc['title'] }}
|
||||
{%- if not invalid %}
|
||||
</a>
|
||||
{%- endif %}
|
||||
{%- if pdoc['hidden'] and show_invisible_flag %}
|
||||
<span class="text-orange">({{ _('Hidden') }})</span>
|
||||
{%- endif %}
|
||||
{%- if not rp is none %}
|
||||
<span class="problem__rp-tag">RP+{{ rp|round|int }}</span>
|
||||
{%- endif %}
|
||||
{%- if show_tags %}
|
||||
{{ render_problem_tags(pdoc) }}
|
||||
{%- endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_problem_tags(pdoc, show_none_label=false) %}
|
||||
{%- if pdoc['tag']|length > 0 %}
|
||||
<ul class="problem__tags">
|
||||
{%- for tag in pdoc['tag'] %}
|
||||
<li class="problem__tag"><a class="problem__tag-link" href="{{ reverse_url('problem_category', category=tag) }}">{{ tag }}</a></li>
|
||||
{%- endfor %}
|
||||
</ul>
|
||||
{%- else %}
|
||||
{%- if show_none_label %}
|
||||
{{ _('(None)') }}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,15 @@
|
||||
{% macro render_status_td(rdoc, rid_key='_id') %}
|
||||
<td class="col--status record-status--border {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}">
|
||||
<div class="col--status__text">
|
||||
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}"></span>
|
||||
<a href="{{ reverse_url('record_detail', rid=rdoc[rid_key], domain_id=rdoc['domain_id']) }}" class="record-status--text {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}">
|
||||
{{ vj4.constant.record.STATUS_TEXTS[rdoc['status']] }}
|
||||
</a>
|
||||
</div>
|
||||
{% if rdoc['status'] == vj4.constant.record.STATUS_JUDGING %}
|
||||
<div class="col--status__progress-container">
|
||||
<div class="col--status__progress" style="width: {{ rdoc['progress']|default(50)|int }}%"></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,15 @@
|
||||
{% macro render_item(icon_name, page_name, label=none) %}
|
||||
<li class="menu__item" id="menu-item-{{ page_name }}">
|
||||
{% set target_url = reverse_url(page_name, **kwargs) %}
|
||||
<a href="{{ target_url }}" class="menu__link{% if handler.request.path_qs == target_url %} active{% endif %}">
|
||||
{% if icon_name %}
|
||||
<span class="icon icon-{{ icon_name }}"></span>
|
||||
{% endif %}
|
||||
{% if label %}
|
||||
{{ _(label) }}
|
||||
{% else %}
|
||||
{{ _(page_name) }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</li>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,26 @@
|
||||
{% macro render_inline(
|
||||
udoc,
|
||||
dudoc={},
|
||||
avatar=true,
|
||||
badge=true,
|
||||
modbadge=true
|
||||
) %}
|
||||
<span class="user-profile-link">
|
||||
{% if avatar %}
|
||||
<img class="small user-profile-avatar v-center" src="{{ udoc['gravatar']|default('')|gravatar_url }}" width="20" height="20">
|
||||
{% endif %}
|
||||
<a class="user-profile-name" href="{{ reverse_url('user_detail', uid=udoc['_id']|default(0)) }}">
|
||||
{% if dudoc['display_name'] %}
|
||||
{{ dudoc['display_name'] }} ({{ udoc['uname'] }})
|
||||
{% else %}
|
||||
{{ udoc['uname'] }}
|
||||
{% endif %}
|
||||
</a>
|
||||
{% if badge %}
|
||||
<a class="user-profile-badge v-center badge--lv{{ dudoc['level']|default(0) }}" href="{{ reverse_url('user_detail', uid=udoc['_id']|default(0)) }}" title="LV {{ dudoc['level']|default(0) }}: Top {{ vj4.model.builtin.LEVELS[dudoc['level']|default(0)]|default('N/A') }}%">LV {{ dudoc['level']|default(0) }}</a>
|
||||
{% if modbadge and handler.dudoc_has_perm(udoc, dudoc, vj4.model.builtin.PERM_MOD_BADGE) %}
|
||||
<span class="user-profile-badge v-center badge--mod" title="Moderator">MOD</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,81 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/contest.html" as contest with context %}
|
||||
{% import "components/record.html" as record with context %}
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body typo">
|
||||
{{ tdoc['content']|markdown }}
|
||||
{% if handler.is_ongoing(tdoc) %}
|
||||
<blockquote class="warn">
|
||||
<p>{{ _('We will check code similarity after this contest.') }}</p>
|
||||
</blockquote>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if handler.is_ongoing(tdoc) or handler.is_done(tdoc) %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Problem') }}</h1>
|
||||
</div>
|
||||
{% if attended or handler.is_done(tdoc) %}
|
||||
<div class="section__body no-padding">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<col class="col--status">
|
||||
<col class="col--submit-at">
|
||||
{% endif %}
|
||||
<col class="col--problem">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<th class="col--status record-status--border">{{ _('Status') }}</th>
|
||||
<th class="col--submit-at">{{ _('Last Submit At') }}</th>
|
||||
{% endif %}
|
||||
<th class="col--problem">{{ _('Problem') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pid in tdoc['pids'] %}
|
||||
<tr>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
{% if psdict[pid] and psdict[pid]['rid'] %}
|
||||
{% with rdoc=rdict[psdict[pid]['rid']] %}
|
||||
{% if handler.can_show_record(tdoc) %}
|
||||
{{ record.render_status_td(rdoc) }}
|
||||
{% else %}
|
||||
<td class="col--status record-status--border"><a href="{{ reverse_url('record_detail', rid=rdoc['_id'], domain_id=handler.domain_id) }}">{{ _('Submitted') }}</a></td>
|
||||
{% endif %}
|
||||
<td class="col--submit-at">{{ datetime_span(rdoc['_id'].generation_time) }}</td>
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
<td class="col--status record-status--border">{{ _('No Submissions') }}</td>
|
||||
<td class="col--submit-at">-</td>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<td class="col--problem col--problem-name">
|
||||
#{{ loop.index }}:
|
||||
{{ problem.render_problem_title(pdict[pid], tdoc=tdoc, show_invisible_flag=false, show_tags=false) }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ nothing.render('Please attend contest to see the problems.') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% with owner_udoc=udict[tdoc['owner_uid']], owner_dudoc=dudict[tdoc['owner_uid']] %}
|
||||
{% include "partials/contest_sidebar.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,41 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
<div class="row">
|
||||
{{ form.form_select(columns=4, label='Rule', name='rule', options=rules, value=tdoc['rule']|default(''), row=False) }}
|
||||
{{ form.form_text(columns=8, label='Title', name='title', placeholder=_('title'), value=tdoc['title']|default(''), autofocus=True, row=False) }}
|
||||
</div><div class="row">
|
||||
{{ form.form_text(columns=4, label='Begin Date', name='begin_at_date', placeholder='YYYY-mm-dd', value=date_text, date=True, row=False) }}
|
||||
{{ form.form_text(columns=4, label='Begin Time', name='begin_at_time', placeholder='HH:MM', value=time_text, time=True, row=False) }}
|
||||
{{ form.form_text(columns=4, label='Duration (hours)', name='duration', value=duration|default('3'), row=False) }}
|
||||
</div>
|
||||
{{ form.form_text(columns=None, label='Problems', name='pids', value=pids) }}
|
||||
{{ form.form_textarea(columns=None, label='Content', name='content', value=tdoc['content']|default(''), markdown=True) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
{% if page_name == 'contest_edit' %}
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Update') }}
|
||||
</button>
|
||||
{% else %}
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Create') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% include 'components/md_hint.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,132 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/contest.html" as contest with context %}
|
||||
{% macro render_important_contest(view, title, tdoc) %}
|
||||
<div class="section immersive--content section--contest {{ view }}">
|
||||
<div class="media">
|
||||
<div class="media__body middle">
|
||||
<div class="section__body">
|
||||
<div>
|
||||
<h2 class="status_title">{{ _(title) }}</h2>
|
||||
</div>
|
||||
<h1>{{ tdoc['title'] }}</h1>
|
||||
<ul class="info">
|
||||
<li>
|
||||
<span class="icon icon-award"></span>
|
||||
{{ _('Rule') }}: {{ vj4.constant.contest.RULE_TEXTS[tdoc['rule']] }}
|
||||
</li>
|
||||
<li>
|
||||
<span class="icon icon-calendar"></span>
|
||||
{{ _('Start at') }}: {{ contest.render_time(tdoc['begin_at']) }}
|
||||
</li>
|
||||
<li>
|
||||
<span class="icon icon-schedule--fill"></span>
|
||||
{{ _('Duration') }}: {{ contest.render_duration(tdoc) }} {{ _('hour(s)') }}
|
||||
</li>
|
||||
<li>
|
||||
<span class="icon icon-user--multiple"></span>
|
||||
{{ _('Partic.') }}: {{ tdoc['attend']|default(0) }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__right middle">
|
||||
<div class="section__body">
|
||||
<a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" class="detail-button">{{ _('View Details') }}</a>
|
||||
<div class="typo text-center">
|
||||
{% if tsdict[tdoc['doc_id']]['attend'] == 1 %}
|
||||
<p><span class="icon icon-check"></span> {{ _('Attended') }}</p>
|
||||
{% else %}
|
||||
<p><span class="icon icon-schedule"></span> {{ _('Not Attended') }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
{% for tdoc in tdocs %}
|
||||
{% if handler.is_ongoing(tdoc) %}
|
||||
{{ render_important_contest('live', 'Live...', tdoc) }}
|
||||
{% elif handler.is_upcoming(tdoc) %}
|
||||
{{ render_important_contest('ready', 'Ready (☆▽☆)', tdoc) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{% if not rule %}{{ _('All Contests') }}{% else %}{{ _('All {0} Contests').format(_(vj4.constant.contest.RULE_TEXTS[rule])) }}{% endif %}</h1>
|
||||
<div class="section__tools">
|
||||
<form method="get" name="filter-form">
|
||||
{{ _('Show') }}:
|
||||
<select class="inline compact select" name="rule">
|
||||
<option value="0"{% if not rule %} selected{% endif %}>{{ _('All') }}</option>
|
||||
{% for k, v in vj4.constant.contest.RULE_TEXTS.items() %}
|
||||
<option value="{{ k }}"{% if rule == k %} selected{% endif %}>{{ _('All {0} Contests').format(_(v)) }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button type="submit" class="button hasjs--hide">
|
||||
{{ _('Go') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body no-padding">
|
||||
{% if not tdocs %}
|
||||
{{ nothing.render('There are no contests...') }}
|
||||
{% else %}
|
||||
<ol class="section__list contest__list">
|
||||
{% for tdoc in tdocs %}
|
||||
<li class="section__list__item contest__item contest-type--{{ vj4.constant.contest.RULE_ID[tdoc['rule']] }}">
|
||||
<div class="media">
|
||||
<div class="media__left medium">
|
||||
<div class="contest__date numbox">
|
||||
<div class="numbox__num large">{{ datetime_span(tdoc['begin_at'], false, '%d') }}</div>
|
||||
<div class="numbox__text">{{ datetime_span(tdoc['begin_at'], false, '%Y-%m') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body medium">
|
||||
<h1 class="contest__title"><a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
<a href="?rule={{ tdoc['rule'] }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ vj4.constant.contest.RULE_TEXTS[tdoc['rule']] }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<span class="icon icon-schedule--fill text-blue"></span> {{ contest.render_duration(tdoc) }} {{ _('hour(s)') }}
|
||||
</li>
|
||||
<li>
|
||||
<span class="icon icon-user--multiple"></span> {{ tdoc['attend']|default(0) }}
|
||||
</li>
|
||||
{% if tsdict[tdoc['doc_id']]['attend'] == 1 %}
|
||||
<li class="contest__info-attended">
|
||||
<span class="icon icon-check"></span> {{ _('Attended') }}
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
{{ paginator.render(page, tpcount, add_qs=qs) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_CREATE_CONTEST) %}
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">
|
||||
{{ _('Create Contest') }}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<p><a href="{{ reverse_url('contest_create') }}" class="expanded primary button">{{ _('Create a contest') }}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,58 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row"><div class="medium-12 columns">
|
||||
<div class="section visible">
|
||||
<div class="section__header">
|
||||
<a class="button" target="_blank" href="{{ reverse_url('contest_scoreboard_download' if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST else 'homework_scoreboard_download', tid=tdoc['doc_id'], ext='html') }}">
|
||||
<span class="icon icon-download"></span> {{ _('Export as HTML') }}
|
||||
</a>
|
||||
<a class="button" href="{{ reverse_url('contest_scoreboard_download' if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST else 'homework_scoreboard_download', tid=tdoc['doc_id'], ext='csv') }}">
|
||||
<span class="icon icon-download"></span> {{ _('Export as CSV') }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="section__body no-padding">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
{%- for column in rows[0] -%}
|
||||
<col class="col--{{ column['type'] }}">
|
||||
{%- endfor -%}
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
{%- for column in rows[0] -%}
|
||||
<th class="col--{{ column['type'] }}">
|
||||
{% if column['type'] == 'problem_detail' %}
|
||||
<a href="{{ reverse_url('contest_detail_problem' if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST else 'homework_detail_problem', tid=tdoc['doc_id'], pid=column['raw']['doc_id']) }}" data-tooltip="{{ column['raw']['title'] }}">{{ column['value'] }}</a>
|
||||
{% else %}
|
||||
{{ column['value'] }}
|
||||
{% endif %}
|
||||
</th>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for row in rows[1:] -%}
|
||||
<tr>
|
||||
{%- for column in row -%}
|
||||
<td class="col--{{ rows[0][loop.index0]['type'] }}">
|
||||
{% if column['type'] == 'user' %}
|
||||
{{ user.render_inline(column['raw'], badge=false) }}
|
||||
{% elif column['type'] == 'record' %}
|
||||
{% if column['raw'] %}
|
||||
<a href="{{ reverse_url('record_detail', rid=column['raw']) }}">{{ column['value']|nl2br }}</a>
|
||||
{% else %}
|
||||
{{ column['value']|nl2br }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ column['value']|nl2br }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,48 @@
|
||||
<meta charset="UTF-8">
|
||||
<style>
|
||||
body {
|
||||
font-family: "Open Sans", "Seravek", "Segoe UI", "Verdana", "PingFang SC", "Hiragino Sans GB", "Lantinghei SC", "Microsoft Yahei", "WenQuanYi Micro Hei", "sans";
|
||||
font-size: 14px;
|
||||
}
|
||||
table {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
font-size: inherit;
|
||||
}
|
||||
th, td {
|
||||
text-align: left;
|
||||
border: 1px solid #CCC;
|
||||
padding: 5px;
|
||||
}
|
||||
thead tr {
|
||||
background: #5f9fd6;
|
||||
color: #FFF;
|
||||
}
|
||||
tbody tr:nth-child(even) {
|
||||
background: #F0F0F0;
|
||||
}
|
||||
</style>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{%- for column in rows[0] -%}
|
||||
<th class="col--{{ column['type'] }}">
|
||||
{{ column['value'] }}
|
||||
</th>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for row in rows[1:] -%}
|
||||
<tr>
|
||||
{%- for column in row -%}
|
||||
<td>
|
||||
{{ column['value'] }}
|
||||
</td>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -0,0 +1,29 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Create Discussion in {0}').format(vnode['title']) }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
{% include "partials/discussion_edit_form.html" %}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Create') }} (Ctrl+Enter)
|
||||
</button>
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% include 'components/md_hint.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,131 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/comments.html" as comments with context %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body">
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
<a class="discussion-node-tag" href="{{ vj4.handler.discussion.node_url(handler, 'discussion_node', vj4.model.adaptor.discussion.node_id(ddoc)) }}">
|
||||
{% if ddoc['parent_doc_type'] == vj4.model.document.TYPE_DISCUSSION_NODE %}
|
||||
<span class="v-center icon icon-tag"></span>
|
||||
{% elif ddoc['parent_doc_type'] == vj4.model.document.TYPE_CONTEST %}
|
||||
<span class="v-center icon icon-award"></span>
|
||||
{% else %}
|
||||
<span class="v-center icon icon-flag"></span>
|
||||
{% endif %}
|
||||
{{ vnode['title'] }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ user.render_inline(udict[ddoc['owner_uid']], dudict[ddoc['owner_uid']]) }}
|
||||
@
|
||||
{{ datetime_span(ddoc['_id'].generation_time) }}
|
||||
</li>
|
||||
</ul>
|
||||
<div class="typo topic__content" data-emoji-enabled data-raw-url="{{ reverse_url('discussion_detail_raw', did=ddoc['_id']) }}">
|
||||
{{ ddoc['content']|markdown }}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="section__footer supplementary dot list">
|
||||
{% if handler.own(ddoc, vj4.model.builtin.PERM_EDIT_DISCUSSION_SELF) or handler.has_perm(vj4.model.builtin.PERM_EDIT_DISCUSSION) %}
|
||||
<li>
|
||||
<a href="{{ reverse_url('discussion_edit', did=ddoc['doc_id']) }}"><span class="icon icon-edit"></span> {{ _('Edit') }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
{{ _('{0} views').format(ddoc['views']) }}
|
||||
</li>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<li><form class="form--inline" method="post">
|
||||
<input type="hidden" name="operation" value="{% if not dsdoc['star'] %}star{% else %}unstar{% endif %}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button class="star{% if dsdoc['star'] %} activated{% endif %}" type="submit">
|
||||
<span class="starred--hide"><span class="icon icon-star--outline"></span> {{ _('Star Topic') }}</span>
|
||||
<span class="starred--show"><span class="icon icon-star"></span> {{ _('Unstar Topic') }}</span>
|
||||
</button>
|
||||
</form></li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{{ reverse_url('about') }}#contact"><span class="icon icon-warning"></span> {{ _('Report') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('{0} comments').format(drcount) }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
{{ comments.render(
|
||||
view = 'discussion',
|
||||
docs = drdocs,
|
||||
udict = udict,
|
||||
comment_ref = 'drid',
|
||||
reply_ref = 'drrid',
|
||||
comment_post_perm = vj4.model.builtin.PERM_REPLY_DISCUSSION,
|
||||
comment_edit_perm = vj4.model.builtin.PERM_NONE if handler.own(ddoc, vj4.model.builtin.PERM_EDIT_DISCUSSION_REPLY_SELF_DISCUSSION) else vj4.model.builtin.PERM_EDIT_DISCUSSION_REPLY,
|
||||
comment_edit_self_perm = vj4.model.builtin.PERM_EDIT_DISCUSSION_REPLY_SELF,
|
||||
comment_delete_perm = vj4.model.builtin.PERM_NONE if handler.own(ddoc, vj4.model.builtin.PERM_DELETE_DISCUSSION_REPLY_SELF_DISCUSSION) else vj4.model.builtin.PERM_DELETE_DISCUSSION_REPLY,
|
||||
comment_delete_self_perm = vj4.model.builtin.PERM_DELETE_DISCUSSION_REPLY_SELF,
|
||||
reply_post_perm = vj4.model.builtin.PERM_REPLY_DISCUSSION,
|
||||
reply_edit_perm = vj4.model.builtin.PERM_NONE if handler.own(ddoc, vj4.model.builtin.PERM_EDIT_DISCUSSION_REPLY_SELF_DISCUSSION) else vj4.model.builtin.PERM_EDIT_DISCUSSION_REPLY,
|
||||
reply_edit_self_perm = vj4.model.builtin.PERM_EDIT_DISCUSSION_REPLY_SELF,
|
||||
reply_delete_perm = vj4.model.builtin.PERM_NONE if handler.own(ddoc, vj4.model.builtin.PERM_DELETE_DISCUSSION_REPLY_SELF_DISCUSSION) else vj4.model.builtin.PERM_DELETE_DISCUSSION_REPLY,
|
||||
reply_delete_self_perm = vj4.model.builtin.PERM_DELETE_DISCUSSION_REPLY_SELF
|
||||
) }}
|
||||
{{ paginator.render(page, pcount) }}
|
||||
{% if drcount == 0 %}
|
||||
{{ nothing.render('No comments so far...') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% with udoc = udict[ddoc['owner_uid']], dudoc = dudict[ddoc['owner_uid']] %}
|
||||
<div class="section side">
|
||||
<div class="profile__bg user-profile-bg--{{ vj4.model.adaptor.setting.UserSetting(udoc, dudoc).get_setting('background_img') }}"></div>
|
||||
<div class="section__body">
|
||||
<div class="media sidebar-user-profile">
|
||||
<div class="media__left">
|
||||
<img src="{{ udoc['gravatar']|gravatar_url }}" width="80" height="80" class="medium user-profile-avatar">
|
||||
</div>
|
||||
<div class="media__body">
|
||||
<p>
|
||||
{{ user.render_inline(udoc, dudict[ddoc['owner_uid']], avatar=false, modbadge=false) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<div class="balancer sidebar-user-stat">
|
||||
<div class="balancer__body">
|
||||
<div class="numbox">
|
||||
<div class="numbox__num medium">{{ dudict[ddoc['owner_uid']]['num_accept'] or 0 }}</div>
|
||||
<div class="numbox__text">{{ _('Accepted') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="balancer__body">
|
||||
<div class="numbox">
|
||||
<div class="numbox__num medium">{{ dudict[ddoc['owner_uid']]['num_liked'] or 0 }}</div>
|
||||
<div class="numbox__text">{{ _('Solutions Liked') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="balancer__body">
|
||||
<div class="numbox">
|
||||
<div class="numbox__num medium">{{ dudict[ddoc['owner_uid']]['num_problems'] or 0 }}</div>
|
||||
<div class="numbox__text">{{ _('Upload Problem') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% if vnode['doc_type'] == vj4.model.document.TYPE_PROBLEM %}
|
||||
{% with pdoc=vnode, owner_udoc=udict[vnode['owner_uid']], owner_dudoc=dudict[vnode['owner_uid']] %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,31 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
{% include "partials/discussion_edit_form.html" %}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button name="operation" value="update" type="submit" class="rounded primary button">
|
||||
{{ _('Update') }} (Ctrl+Enter)
|
||||
</button>
|
||||
{% if handler.own(ddoc, vj4.model.builtin.PERM_DELETE_DISCUSSION_SELF) or handler.has_perm(vj4.model.builtin.PERM_DELETE_DISCUSSION) %}
|
||||
<button name="operation" value="delete" type="submit" class="rounded button">
|
||||
{{ _('Delete') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% include 'components/md_hint.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,44 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
{% include "partials/discussion_list.html" %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% if vnode['doc_type'] == vj4.model.document.TYPE_PROBLEM %}
|
||||
{% with pdoc=vnode, owner_udoc=udict[vnode['owner_uid']], owner_dudoc=dudict[vnode['owner_uid']] if dudict %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
{% elif vnode['doc_type'] == vj4.model.document.TYPE_CONTEST %}
|
||||
{% with tdoc=vnode, owner_udoc=udict[vnode['owner_uid']], owner_dudoc=dudict[vnode['owner_uid']] if dudict %}
|
||||
{% include "partials/contest_sidebar.html" %}
|
||||
{% endwith %}
|
||||
{% elif vnode['doc_type'] == vj4.model.document.TYPE_DISCUSSION_NODE %}
|
||||
<div class="section side">
|
||||
{% if vnode['pic'] %}<div class="discussion-node__bg {{ vnode['pic'] }}"></div>{% endif %}
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ vnode['title'] or _('Create Discussion') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
{% if vnode %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_CREATE_DISCUSSION) %}
|
||||
<p><a href="{{ reverse_url('discussion_create', doc_id=vnode['doc_id']) }}" class="expanded primary button">{{ _('Create a Discussion') }}</a></p>
|
||||
{% else %}
|
||||
{% if not handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<p><a href="javascript:showSignInDialog();" class="expanded primary button">{{ _('Login to Create a Discussion') }}</a></p>
|
||||
{% else %}
|
||||
<p><a href="javascript:;" class="disabled expanded primary button">{{ _('No Permission to Create a Discussion') }}</a></p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>{{ _('Select a node to create discussion.') }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% include 'discussion_nodes_widget.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,17 @@
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Discussion Nodes') }}</h1>
|
||||
</div>
|
||||
<div class="section__body"><ul class="group-list">
|
||||
{% for category, nodes in discussion_nodes.items() %}
|
||||
<li class="group-list__item">
|
||||
<h2 class="section__title">{{ category }}</h2>
|
||||
<ol class="chip-list">
|
||||
{% for node in nodes %}
|
||||
<li class="chip-list__item"><a class="typo-a" href="{{ reverse_url('discussion_node', doc_id=node['name']) }}">{{ node['name'] }}</a></li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul></div>
|
||||
</div>
|
||||
@@ -0,0 +1,40 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row" data-sticky-parent>
|
||||
<div class="medium-9 columns">
|
||||
{% block domain_content %}{% endblock %}
|
||||
</div>
|
||||
<div class="medium-3 columns"><div data-sticky="large">
|
||||
<div class="section side">
|
||||
<ol class="menu">
|
||||
<li class="menu__item">
|
||||
<div class="menu__link expandable">
|
||||
<span class="icon icon-info"></span> {{ _('Properties') }}
|
||||
</div>
|
||||
<ol class="menu collapsed">
|
||||
{{ sidemenu.render_item(null, 'domain_manage_dashboard') }}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_EDIT_DESCRIPTION) %}
|
||||
{{ sidemenu.render_item(null, 'domain_manage_edit') }}
|
||||
{{ sidemenu.render_item(null, 'domain_manage_join_applications') }}
|
||||
{{ sidemenu.render_item(null, 'domain_manage_discussion') }}
|
||||
{% endif %}
|
||||
<!-- Ranking Settings -->
|
||||
</ol>
|
||||
</li>
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_EDIT_PERM) %}
|
||||
<li class="menu__item">
|
||||
<div class="menu__link expandable">
|
||||
<span class="icon icon-user"></span> {{ _('Access Control') }}
|
||||
</div>
|
||||
<ol class="menu collapsed">
|
||||
{{ sidemenu.render_item(null, 'domain_manage_role') }}
|
||||
{{ sidemenu.render_item(null, 'domain_manage_user') }}
|
||||
{{ sidemenu.render_item(null, 'domain_manage_permission') }}
|
||||
</ol>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ol>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,26 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="domain_join__container">
|
||||
<div class="row columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">
|
||||
{{ _('Join {0}').format(handler.domain['name']) }}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<p>{{ _('By clicking the button, you will become a member of the domain {0}.').format(handler.domain['name']) }}</p>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<form method="post">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
{% if join_settings['method'] == vj4.constant.domain.JOIN_METHOD_CODE %}
|
||||
{{ form.form_text(columns=None, label='Invitation Code', name='code', required=true, help_text='You need to enter the invitation code to join the domain.', value=code, autofocus=True) }}
|
||||
{% endif %}
|
||||
<button type="submit" class="primary rounded button">{{ _('Join') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,205 @@
|
||||
{% set no_path_section = true %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/contest.html" as contest with context %}
|
||||
{% block content %}
|
||||
{% if handler.domain['bulletin'] %}
|
||||
<div class="row">
|
||||
<div class="large-12 columns">
|
||||
<div class="section">
|
||||
<div class="section__body typo">
|
||||
{{ handler.domain['bulletin']|markdown }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<div class="large-9 columns">
|
||||
{% if not tdocs %}
|
||||
<!-- no contest -->
|
||||
{% else %}
|
||||
<div class="section page--contest_main">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Contest') }}</h1>
|
||||
</div>
|
||||
<ol class="section__list contest__list">
|
||||
{% for tdoc in tdocs %}
|
||||
<li class="section__list__item contest__item contest-type--{{ vj4.constant.contest.RULE_ID[tdoc['rule']] }}">
|
||||
<div class="media">
|
||||
<div class="media__left medium">
|
||||
<div class="contest__date numbox">
|
||||
<div class="numbox__num large">{{ datetime_span(tdoc['begin_at'], false, '%d') }}</div>
|
||||
<div class="numbox__text">{{ datetime_span(tdoc['begin_at'], false, '%Y-%m') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body medium">
|
||||
<h1 class="contest__title"><a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
<a href="{{ reverse_url('contest_main') }}?rule={{ tdoc['rule'] }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ vj4.constant.contest.RULE_TEXTS[tdoc['rule']] }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<span class="icon icon-schedule--fill text-blue"></span> {{ contest.render_duration(tdoc) }} {{ _('hour(s)') }}
|
||||
</li>
|
||||
<li>
|
||||
<span class="icon icon-user--multiple"></span> {{ tdoc['attend']|default(0) }}
|
||||
</li>
|
||||
{% if tsdict[tdoc['doc_id']]['attend'] == 1 %}
|
||||
<li class="contest__info-attended">
|
||||
<span class="icon icon-check"></span> {{ _('Attended') }}
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not htdocs %}
|
||||
<!-- no homework -->
|
||||
{% else %}
|
||||
<div class="section page--homework_main">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Homework') }}</h1>
|
||||
</div>
|
||||
<ol class="section__list homework__list">
|
||||
{% for tdoc in htdocs %}
|
||||
<li class="section__list__item homework__item">
|
||||
<div class="media">
|
||||
<div class="media__left medium">
|
||||
<div class="homework__date numbox">
|
||||
<div class="numbox__num large">{{ datetime_span(tdoc['penalty_since'], false, '%d') }}</div>
|
||||
<div class="numbox__text">{{ datetime_span(tdoc['penalty_since'], false, '%Y-%m') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body medium">
|
||||
<h1 class="homework__title"><a href="{{ reverse_url('homework_detail', tid=tdoc['doc_id']) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
{{ _('Status') }}: <span class="homework-status--text {{ handler.get_status(tdoc) }}">{{ _(handler.status_text(tdoc)) }}</span>
|
||||
</li>
|
||||
<li>
|
||||
{{ _('Open Since') }}: {{ datetime_span(tdoc['begin_at']) }}
|
||||
</li>
|
||||
<li>
|
||||
{% if handler.is_homework_extended(tdoc) or handler.is_done(tdoc) %}
|
||||
{{ _('Hard Deadline') }}: {{ datetime_span(tdoc['end_at']) }}
|
||||
{% else %}
|
||||
{{ _('Deadline') }}: {{ datetime_span(tdoc['penalty_since']) }}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% if htsdict[tdoc['doc_id']]['attend'] == 1 %}
|
||||
<li class="homework__info-attended">
|
||||
<span class="icon icon-check"></span> {{ _('Claimed') }}
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not trdocs %}
|
||||
<!-- no training -->
|
||||
{% else %}
|
||||
<div class="section page--training_main">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Training') }}</h1>
|
||||
</div>
|
||||
{% with tdocs=trdocs, tsdict=trsdict %}
|
||||
<ol class="section__list all primary training__list">
|
||||
{% for tdoc in tdocs %}
|
||||
<li class="section__list__item training__item">
|
||||
<div class="media">
|
||||
<div class="media__left middle">
|
||||
<div class="training__participants numbox">
|
||||
<div class="numbox__num large">{{ tdoc['enroll']|default(0) }}</div>
|
||||
<div class="numbox__text">{{ _('Enrolled') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body middle">
|
||||
<h1 class="training__title"><a href="{{ reverse_url('training_detail', tid=tdoc['doc_id']) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<div class="training__intro typo">
|
||||
<p>{{ tdoc['content'] }}</p>
|
||||
</div>
|
||||
<ul class="supplementary list training__progress">
|
||||
<li>
|
||||
<span class="icon icon-flag text-blue"></span> {{ _('{0} sections').format(tdoc['dag']|length) }}, {{ _('{0} problems').format(training.get_pids(tdoc)|length) }}
|
||||
</li>
|
||||
<li>
|
||||
{% if tsdict[tdoc['doc_id']]['enroll'] %}
|
||||
{% if not tsdict[tdoc['doc_id']]['done'] %}
|
||||
<span class="icon training-status--icon progress"></span>
|
||||
<span class="training-status--text progress">{{ _('Completed') }} {{ (100 * tsdict[tdoc['doc_id']]['done_pids']|length / training.get_pids(tdoc)|length)|round|int }}%</span>
|
||||
{% else %}
|
||||
<span class="icon training-status--icon done"></span>
|
||||
<span class="training-status--text done">{{ _('Completed') }} 100%</span>
|
||||
{% endif %}
|
||||
{% elif handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<span class="icon training-status--icon outside"></span> <span class="training-status--text outside">{{ _('Not Enrolled') }}</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not ddocs %}
|
||||
<!-- no discussion -->
|
||||
{% else %}
|
||||
<div class="section page--discussion_main">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Discussion') }}</h1>
|
||||
</div>
|
||||
{% include "partials/discussion_list.html" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="large-3 columns">
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_VIEW_DISCUSSION) %}
|
||||
{% include 'discussion_nodes_widget.html' %}
|
||||
{% endif %}
|
||||
{% if domain_id == vj4.model.builtin.DOMAIN_ID_SYSTEM %}
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Recommended') }}</h1>
|
||||
</div>
|
||||
<div class="section__body"><ul class="group-list">
|
||||
<li class="group-list__item">
|
||||
<h2 class="section__title">{{ _('Chinese') }}</h2>
|
||||
<ol class="chip-list">
|
||||
<li class="chip-list__item"><a class="typo-a" href="https://www.xuetangx.com/courses/course-v1:TsinghuaX+30240184+sp/about" target="_blank">清华数据结构 MOOC 上</a><a class="typo-a" href="https://www.xuetangx.com/courses/course-v1:TsinghuaX+30240184_2X+sp/about" target="_blank">/下</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="https://www.51nod.com/" target="_blank">51Nod</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="https://www.luogu.org/" target="_blank">洛谷</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="https://www.rqnoj.cn/" target="_blank">RQNOJ</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="http://www.lydsy.com/JudgeOnline/" target="_blank">BZOJ</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="http://acm.zju.edu.cn/onlinejudge/" target="_blank">ZOJ</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="http://uoj.ac/" target="_blank">UOJ</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li class="group-list__item">
|
||||
<h2 class="section__title">{{ _('English') }}</h2>
|
||||
<ol class="chip-list">
|
||||
<li class="chip-list__item"><a class="typo-a" href="https://acm.njupt.edu.cn/" target="_blank">NOJ</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="https://www.topcoder.com/" target="_blank">TopCoder</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="https://uva.onlinejudge.org/" target="_blank">UVa</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="http://codeforces.com/" target="_blank">Codeforces</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="http://www.usaco.org/" target="_blank">USACO</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="http://spoj.pl/" target="_blank">SPOJ</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="http://poj.org/" target="_blank">POJ</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
</ul></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,22 @@
|
||||
{% import "components/user.html" as user %}
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
{% if handler.domain['bulletin'] %}
|
||||
<div class="section">
|
||||
<div class="section__body typo">
|
||||
{{ handler.domain['bulletin']|markdown }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" data-heading>{{ _('Information') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<dl class="large horizontal">
|
||||
<dt>{{ _('Gravatar') }}</dt><dd><img src="{{ handler.domain['gravatar']|gravatar_url }}" width="32" height="32"></dd>
|
||||
<dt>{{ _('Name') }}</dt><dd>{{ handler.domain['name'] }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,22 @@
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Initialize') }}</h1>
|
||||
<div class="section__tools">
|
||||
<form method="post">
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="rounded primary button">
|
||||
<span class="icon icon-add"></span> {{ _('Initialize') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% include 'discussion_nodes_widget.html' %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,21 @@
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
<div class="section">
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
{% with ddoc=handler.domain %}
|
||||
{% include "partials/domain_edit_form.html" %}
|
||||
{% endwith %}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Update') }}
|
||||
</button>
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,60 @@
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
{% if join_settings != None %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Information') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<p>{{ _('User can join this domain by visiting the following URL') }}:</p>
|
||||
<pre><code class="language-data">{{ handler.ui_context['url_prefix'] }}{{ reverse_url('domain_join') }}</code></pre>
|
||||
{% if join_settings['method'] == vj4.constant.domain.JOIN_METHOD_CODE %}
|
||||
<p>{{ _('Or, with automatically filled invitation code') }}:</p>
|
||||
<pre><code class="language-data">{{ handler.ui_context['url_prefix'] }}{{ reverse_url('domain_join') }}?code={{ join_settings['code']|urlencode }}</code></pre>
|
||||
{% endif %}
|
||||
{% if join_settings['expire'] != None %}
|
||||
<br/>
|
||||
<blockquote class="note">
|
||||
{{ (_('The link will be expired at {0}').format(datetime_span(join_settings['expire'], relative=false)))|safe }}
|
||||
</blockquote>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Settings') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<form method="POST">
|
||||
{{ form.form_radio(
|
||||
options=vj4.constant.domain.JOIN_METHOD_RANGE.items(),
|
||||
label='Method',
|
||||
name='method',
|
||||
value=join_settings['method']|default(vj4.constant.domain.JOIN_METHOD_NONE),
|
||||
columns=8) }}
|
||||
{{ form.form_select(
|
||||
options=roles_with_text,
|
||||
label='Role Assignment',
|
||||
name='role',
|
||||
help_text='The role to assign when user joining the domain.',
|
||||
value=join_settings['role']|default('')) }}
|
||||
{{ form.form_select(
|
||||
options=expirations.items(),
|
||||
label='Expire',
|
||||
name='expire',
|
||||
help_text='User will no longer be allowed to join the domain after expiration.'
|
||||
) }}
|
||||
{{ form.form_text(
|
||||
label='Invitation Code',
|
||||
name='invitation_code',
|
||||
help_text='The invitation code to enter to successfully join the domain. You can only use letters and numbers in the code and it should not be longer than 64 characters.',
|
||||
value=join_settings['code']|default('')) }}
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button class="rounded primary button" role="submit">
|
||||
{{ _('Update Settings') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,60 @@
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
<form method="post">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('{0}: Permissions').format(handler.domain['name']) }}</h1>
|
||||
</div>
|
||||
<div class="section__body no-padding domain-users">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--description">
|
||||
{% for role in roles %}
|
||||
<col class="col--p">
|
||||
{% endfor %}
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--description">{{ _('Permissions') }}</th>
|
||||
{% for role in roles %}
|
||||
<th class="col--p"><span data-tooltip="{{ role }}">{{ role }}</span></th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
{% for family, perms in vj4.model.builtin.PERMS_BY_FAMILY.items() %}
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="col--family" colspan="{{ (roles|length)+1 }}">
|
||||
{{ _(family) }}
|
||||
</td>
|
||||
</tr>
|
||||
{% for perm in perms %}
|
||||
<tr>
|
||||
<td class="col--description">
|
||||
{{ _(perm.desc) }}
|
||||
</td>
|
||||
{% for role in roles %}
|
||||
<td class="col--p">
|
||||
<label class="compact checkbox">
|
||||
<input name="{{ role }}" data-checkbox-group="{{ role }}" data-checkbox-range value="{{ perm.key }}" type="checkbox"{% if bitand(handler.domain['roles'][role], perm.key) == perm.key %} checked{% endif %}>
|
||||
</label>
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button class="rounded primary button" role="submit">
|
||||
{{ _('Update Permission') }}
|
||||
</button>
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,90 @@
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
<div style="display: none" class="dialog__body--create-role">
|
||||
<div>
|
||||
<div class="row"><div class="columns">
|
||||
<h1>{{ _('Create Role') }}</h1>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<blockquote class="note">
|
||||
<p>{{ _('Role name can only contains numbers, letters and underscores.') }}</p>
|
||||
</blockquote>
|
||||
{{ form.form_text(columns=None, label='Name', name='role', autofocus=True) }}
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('{0}: Roles').format(handler.domain['name']) }}</h1>
|
||||
<div class="section__tools">
|
||||
<button class="primary rounded button" name="create_role">{{ _('Create Role') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ noscript_note.render() }}
|
||||
<div class="section__body no-padding domain-roles">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--checkbox">
|
||||
<col class="col--id">
|
||||
<col class="col--description">
|
||||
<col class="col--users">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--checkbox">
|
||||
<label class="compact checkbox">
|
||||
<input type="checkbox" data-checkbox-toggle="role">
|
||||
</label>
|
||||
</th>
|
||||
<th class="col--id">{{ _('Role') }}</th>
|
||||
<th class="col--description">{{ _('Description') }}</th>
|
||||
<th class="col--users">{{ _('Users') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for role, rd in vj4.model.builtin.BUILTIN_ROLE_DESCRIPTORS.items() %}
|
||||
<tr>
|
||||
<td class="col--checkbox">
|
||||
<label class="compact checkbox">
|
||||
<input type="checkbox" data-checkbox-group="role" disabled>
|
||||
</label>
|
||||
</td>
|
||||
<td class="col--id">
|
||||
{{ role }}
|
||||
</td>
|
||||
<td class="col--description">
|
||||
{{ _('Built-in') }}: {{ _(rd.description) }}
|
||||
</td>
|
||||
<td class="col--users">
|
||||
{{ rucounts.get(role, '--') }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% for role in roles %}
|
||||
{% if role not in vj4.model.builtin.BUILTIN_ROLE_DESCRIPTORS %}
|
||||
<tr data-role="{{ role }}">
|
||||
<td class="col--checkbox">
|
||||
<label class="compact checkbox">
|
||||
<input type="checkbox" data-checkbox-group="role" data-checkbox-range>
|
||||
</label>
|
||||
</td>
|
||||
<td class="col--id">
|
||||
{{ role }}
|
||||
</td>
|
||||
<td class="col--description">
|
||||
{{ _('User-defined role') }}
|
||||
</td>
|
||||
<td class="col--users">
|
||||
{{ rucounts[role] }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<button class="rounded button" name="delete_selected">{{ _('Delete Selected Roles') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,101 @@
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
<div style="display: none" class="dialog__body--add-user">
|
||||
<div>
|
||||
<div class="row"><div class="columns">
|
||||
<h1>{{ _('Add User') }}</h1>
|
||||
</div></div>
|
||||
<div class="row">
|
||||
<div class="medium-6 columns">
|
||||
<label>
|
||||
{{ _('Username / UID') }}
|
||||
<input name="user" type="text" class="textbox" autocomplete="off" data-autofocus>
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-6 columns">
|
||||
<label>
|
||||
{{ _('Role') }}
|
||||
{{ form.select([('', _('Select a role'))] + roles_with_text, 'role') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: none" class="dialog__body--set-role">
|
||||
<div>
|
||||
<div class="row"><div class="columns">
|
||||
<h1>{{ _('Set Role') }}</h1>
|
||||
</div></div>
|
||||
<div class="row">
|
||||
<div class="medium-12 columns">
|
||||
<label>
|
||||
{{ _('Set Roles for selected users') }}
|
||||
{{ form.select([('', _('Select a role'))] + roles_with_text, 'role') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('{0}: Users').format(handler.domain['name']) }}</h1>
|
||||
<div class="section__tools">
|
||||
<button class="primary rounded button" name="add_user">{{ _('Add User to Domain') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ noscript_note.render() }}
|
||||
<div class="section__body no-padding domain-users">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--checkbox">
|
||||
<col class="col--uid">
|
||||
<col class="col--user">
|
||||
<col class="col--role">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--checkbox">
|
||||
<label class="compact checkbox">
|
||||
<input type="checkbox" name="select_all" data-checkbox-toggle="user">
|
||||
</label>
|
||||
</th>
|
||||
<th class="col--uid">{{ _('User ID') }}</th>
|
||||
<th class="col--user">{{ _('Username') }}</th>
|
||||
<th class="col--user">{{ _('Display Name') }}</th>
|
||||
<th class="col--role">{{ _('Role') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for role in roles %}
|
||||
{% for rudoc in rudocs[role] %}
|
||||
{% set is_disabled=(rudoc['uid'] == handler.domain['owner_uid']) %}
|
||||
<tr data-uid="{{ rudoc['uid'] }}">
|
||||
<td class="col--checkbox">
|
||||
<label class="compact checkbox">
|
||||
<input type="checkbox" data-checkbox-group="user" {% if is_disabled %}disabled{% else %}data-checkbox-range{% endif %}>
|
||||
</label>
|
||||
</td>
|
||||
<td class="col--uid">
|
||||
{{ rudoc['uid'] }}
|
||||
</td>
|
||||
<td class="col--user">
|
||||
{{ user.render_inline(udict[rudoc['uid']], badge=false) }}
|
||||
</td>
|
||||
<td class="col--name-alias">
|
||||
{{ rudoc['display_name']|default('') }}
|
||||
</td>
|
||||
<td class="col--role">
|
||||
{{ form.select(roles_with_text, 'role', value=rudoc['role'], extra_class='compact', disabled=is_disabled) }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<button class="rounded button" name="remove_selected">{{ _('Remove Selected User from Domain') }}</button>
|
||||
<button class="rounded button" name="set_roles">{{ _('Set Roles for Selected User') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,22 @@
|
||||
{% set no_path_section = true %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="error__container clearfix">
|
||||
<div class="error__icon-container">
|
||||
<div class="error__twd2"></div>
|
||||
</div>
|
||||
<div class="error__text-container">
|
||||
<h1>{{ _('Oops!') }}</h1>
|
||||
<p>{{ _(error.message).format(*error.args) }}</p>
|
||||
<p>{{ _('Technical Information') }}:</p>
|
||||
<p>{{ _('Type') }}: {{ error.__class__.__name__ }}</p>
|
||||
<p>{{ _('Arguments') }}:
|
||||
<ol>
|
||||
{% for arg in error.args %}
|
||||
<li>{{ arg }}</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,23 @@
|
||||
{% extends 'layout/simple.html' %}
|
||||
{% block body %}
|
||||
{% if fdoc %}
|
||||
<p>{{ _('Uploaded file info') }}:</p>
|
||||
<p>{{ _('ID') }}: {{ fdoc['_id'] }}</p>
|
||||
<p>{{ _('Userfile doc_id') }}: {{ ufid }}</p>
|
||||
<p>{{ _('MD5') }}: {{ fdoc['md5'] }}</p>
|
||||
<p>{{ _('Secret (keep it secret)') }}: {{ fdoc['metadata']['secret'] }}</p>
|
||||
<p>{{ _('URL') }}: {{ reverse_url('fs_get', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM, secret=fdoc['metadata']['secret']) }}</p>
|
||||
<p>{{ _('Image Markdown') }}: <pre> }})</pre></p>
|
||||
{% endif %}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<p>
|
||||
{{ _('New file') }}:
|
||||
<input type="text" name="desc" placeholder="{{ _('Description') }}">
|
||||
<input type="file" name="file">
|
||||
<input type="submit" value="{{ _('Upload') }}" class="rounded primary button">
|
||||
</p>
|
||||
<p>{{ _('Note: file size should be less than or equal to {0}, and file type should be in {1}. Empty files are not allowed.').format(vj4.handler.fs.FILE_MAX_LENGTH|format_size, vj4.handler.fs.ALLOWED_MIMETYPE_PREFIX) }}</p>
|
||||
<p>{{ _('Usage: {0}, Quota: {1}').format(usage|format_size, quota|format_size) }}</p>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,99 @@
|
||||
{% extends "layout/home_base.html" %}
|
||||
{% block home_content %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('My Domains') }}</h1>
|
||||
<div class="section__tools">
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_CREATE_DOMAIN) %}
|
||||
<a class="primary rounded button" href="{{ reverse_url('home_domain_create') }}"><span class="icon icon-add"></span> {{ _('Create Domain') }}</a>
|
||||
{% endif %}
|
||||
<a class="tool-button" href="{{ reverse_url('wiki_help') }}#domain"><span class="icon icon-help"></span> {{ _('What\'s domain?') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% if pending_ddocs|length > 0 %}
|
||||
<div class="section__body">
|
||||
<blockquote class="note">
|
||||
{{ _('You have uncompleted domain creation operation. You can click "Continue" to finish the creation.') }}
|
||||
</blockquote>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section__body no-padding">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--icon">
|
||||
<col class="col--name">
|
||||
<col class="col--role">
|
||||
<col class="col--action">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--icon"> </th>
|
||||
<th class="col--name">{{ _('Name') }} ({{ _('ID') }})</th>
|
||||
<th class="col--role">{{ _('My Role') }}</th>
|
||||
<th class="col--action">{{ _('Action') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for ddoc in pending_ddocs %}
|
||||
<tr>
|
||||
<td class="col--icon">
|
||||
<img src="{{ ddoc['gravatar']|gravatar_url }}" width="32" height="32">
|
||||
</td>
|
||||
<td class="col--name">
|
||||
<span class="text-red">{{ _('Uncompleted') }}</span>: {{ ddoc['name'] }} ({{ ddoc['_id'] }})
|
||||
</td>
|
||||
<td class="col--role">
|
||||
--
|
||||
</td>
|
||||
<td class="col--action"><form method="post">
|
||||
<input type="hidden" name="domain_id" value="{{ ddoc['_id'] }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="typo-a">{{ _('Continue') }}</button>
|
||||
</form></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% for ddoc in vj4.model.builtin.DOMAINS %}
|
||||
<tr>
|
||||
<td class="col--icon">
|
||||
<img src="{{ ddoc['gravatar']|gravatar_url }}" width="32" height="32">
|
||||
</td>
|
||||
<td class="col--name">
|
||||
<span data-tooltip="{{ _('This is a built-in domain that every user is in.') }}">{{ ddoc['name'] }} ({{ ddoc['_id'] }})</span>
|
||||
</td>
|
||||
<td class="col--role">
|
||||
{{ dudict.get(ddoc['_id'], {})['role']|default(vj4.model.builtin.ROLE_DEFAULT) }}
|
||||
</td>
|
||||
<td class="col--action">
|
||||
<a class="typo-a" href="{{ reverse_url('domain_main', domain_id=ddoc['_id']) }}">{{ _('Visit') }}</a>
|
||||
{% if can_manage[ddoc['_id']] %}
|
||||
· <a class="typo-a" href="{{ reverse_url('domain_manage', domain_id=ddoc['_id']) }}">{{ _('Manage') }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% for ddoc in ddocs %}
|
||||
{% if not ddoc['pending'] %}
|
||||
<tr>
|
||||
<td class="col--icon">
|
||||
<img src="{{ ddoc['gravatar']|gravatar_url }}" width="32" height="32">
|
||||
</td>
|
||||
<td class="col--name">
|
||||
{{ ddoc['name'] }} ({{ ddoc['_id'] }})
|
||||
</td>
|
||||
<td class="col--role">
|
||||
{{ dudict.get(ddoc['_id'], {})['role']|default(vj4.model.builtin.ROLE_DEFAULT) }}
|
||||
</td>
|
||||
<td class="col--action">
|
||||
<a class="typo-a" href="{{ reverse_url('domain_main', domain_id=ddoc['_id']) }}">{{ _('Visit') }}</a>
|
||||
{% if can_manage[ddoc['_id']] %}
|
||||
· <a class="typo-a" href="{{ reverse_url('domain_manage', domain_id=ddoc['_id']) }}">{{ _('Manage') }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,36 @@
|
||||
{% extends "layout/home_base.html" %}
|
||||
{% block home_content %}
|
||||
<div data-heading-extract-to="#menu-item-home_domain">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="create" data-heading>{{ _('Create Domain') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<blockquote class="note typo">
|
||||
<p>{{ _('A domain ID cannot be changed after creation. It is supposed to be:') }}</p>
|
||||
<ul>
|
||||
<li>{{ _('Unique') }}</li>
|
||||
<li>{{ _('At least 4 characters') }}</li>
|
||||
<li>{{ _('Not wrapped with space') }}</li>
|
||||
<li>{{ _('Not started with a number') }}</li>
|
||||
<li>{{ _('Only A-Z, a-z, 0-9 and _ are accepted') }}</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<form method="post">
|
||||
{% with ddoc={} %}
|
||||
{% include "partials/domain_edit_form.html" %}
|
||||
{% endwith %}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Create') }}
|
||||
</button>
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,44 @@
|
||||
{% extends "layout/home_base.html" %}
|
||||
{% block home_content %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('My Files') }}</h1>
|
||||
<div class="section__tools">
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_CREATE_FILE) %}
|
||||
<a class="primary rounded button" href="{{ reverse_url('fs_upload') }}" target="_blank"><span class="icon icon-add"></span> {{ _('Upload File') }}</a>
|
||||
{% endif %}
|
||||
<a class="tool-button" href="{{ reverse_url('wiki_help') }}#file"><span class="icon icon-help"></span> {{ _('What\'s file?') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body no-padding">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--desc">
|
||||
<col class="col--length">
|
||||
<col class="col--hash">
|
||||
<col class="col--action">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--desc">{{ _('Description') }}</th>
|
||||
<th class="col--length">{{ _('Size') }}</th>
|
||||
<th class="col--hash">{{ _('Hash') }}</th>
|
||||
<th class="col--action">{{ _('Action') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for ufdoc in ufdocs %}
|
||||
{% with fdoc = fdict.get(ufdoc['file_id'], {}) %}
|
||||
<tr>
|
||||
<td class="col--desc">{{ ufdoc['content'] }}</td>
|
||||
<td class="col--length">{{ fdoc['length']|format_size if fdoc['length'] else '?' }}</td>
|
||||
<td class="col--hash">{{ fdoc['md5']|default('?') }}</td>
|
||||
<td class="col--action"><a class="typo-a" href="{{ handler.file_url(fdoc) if 'metadata' in fdoc else '#' }}">{{ _('Download') }}</a> · <a class="typo-a" href="#">{{ _('Code') }}</a></td>
|
||||
</tr>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,24 @@
|
||||
{% extends "layout/home_base.html" %}
|
||||
{% block home_content %}
|
||||
<div style="display: none" class="dialog__body--user-select">
|
||||
<div>
|
||||
<div class="row"><div class="columns">
|
||||
<h1>{{ _('Select User') }}</h1>
|
||||
</div></div>
|
||||
<div class="row">
|
||||
<div class="columns">
|
||||
<label>
|
||||
{{ _('Username / UID') }}
|
||||
<input name="user" type="text" class="textbox" autocomplete="off" data-autofocus>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div id="messagePad">
|
||||
{{ noscript_note.render() }}
|
||||
<div class="loader-container"><div class="loader"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,99 @@
|
||||
{% extends "layout/home_base.html" %}
|
||||
{% block home_content %}
|
||||
<div data-heading-extract-to="#menu-item-home_security">
|
||||
<div class="row">
|
||||
<div class="medium-6 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="email" data-heading>{{ _('Change Email') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
{{ form.form_text(type='password', label='Current Password', columns=10, name='current_password', required=true) }}
|
||||
{{ form.form_text(type='text', label='Current Email', columns=10, name='current_email', value=handler.user['mail'], disabled=true) }}
|
||||
{{ form.form_text(type='text', label='New Email', columns=10, name='mail', required=true) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<input type="hidden" name="operation" value="change_mail">
|
||||
<input type="submit" class="rounded primary button" value="{{ _('Change Email') }}">
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-6 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="password" data-heading>{{ _('Change Password') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
{{ form.form_text(type='password', label='Current Password', columns=10, name='current_password', required=true) }}
|
||||
{{ form.form_text(type='password', label='New Password', columns=10, name='new_password', required=true) }}
|
||||
{{ form.form_text(type='password', label='Repeat Password', columns=10, name='verify_password', required=true) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<input type="hidden" name="operation" value="change_password">
|
||||
<input type="submit" class="rounded primary button" value="{{ _('Change Password') }}">
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="session" data-heading>{{ _('Active Sessions') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<ul class="sessionlist">
|
||||
{% for session in sessions %}
|
||||
<li class="sessionlist__item">
|
||||
<div class="media">
|
||||
<div class="media__left medium">
|
||||
<span class="sessionlist__icon icon icon-platform--{{ session['update_ua']['icon'] }}"></span>
|
||||
</div>
|
||||
<div class="media__body medium typo">
|
||||
<p>{{ _('Last Update At') }}: {{ datetime_span(session['update_at']) }}</p>
|
||||
<p>{{ _('Location') }}: {{ _(session['update_geoip']) }} ({{ session['update_ip'] }})</p>
|
||||
<p>{{ _('Operating System') }}: {{ session['update_ua']['os'] }}</p>
|
||||
<p>{{ _('Browser') }}: {{ session['update_ua']['browser'] }}</p>
|
||||
<!-- {{ _('User-Agent') }}: {{ session['update_ua']['str'] }} -->
|
||||
<p>{{ _('Type') }}: {{ _(vj4.handler.home.TOKEN_TYPE_TEXTS[session['token_type']]) }}</p>
|
||||
{% if session['is_current'] %}
|
||||
<p class="sessionlist__current-session"><span class="icon icon-check"></span> {{ _('This is the current session') }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if not session['is_current'] %}
|
||||
<div class="media__right medium">
|
||||
<form method="post">
|
||||
<input type="hidden" name="operation" value="delete_token">
|
||||
<input type="hidden" name="token_type" value="{{ session['token_type'] }}">
|
||||
<input type="hidden" name="token_digest" value="{{ session['token_digest'] }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<input type="submit" value="{{ _('Logout This Session') }}" class="rounded button">
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
<input type="hidden" name="operation" value="delete_all_tokens">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<input type="submit" value="{{ _('Logout All Sessions') }}" class="primary rounded button">
|
||||
</form>
|
||||
<div class="typo">
|
||||
<p><small>IP geo-location data is provided by <a href="http://www.maxmind.com" target="_blank">MaxMind</a>.</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,69 @@
|
||||
{% extends "layout/home_base.html" %}
|
||||
{% block home_content %}
|
||||
<div class="section" data-heading-extract-to="#menu-item-home_{{ category }}">
|
||||
<form method="post">
|
||||
{% for family, family_settings in settings|groupby('family') %}
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="{{ family }}" data-heading>{{ _(family) }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
{% for setting in family_settings %}
|
||||
{% if setting.ui == 'text' or setting.ui == 'password' %}
|
||||
{{ form.form_text(
|
||||
type=setting.ui,
|
||||
label=setting.name,
|
||||
help_text=setting.desc,
|
||||
name=setting.key,
|
||||
value=handler.get_setting(setting.key))
|
||||
}}
|
||||
{% elif setting.ui == 'select' %}
|
||||
{{ form.form_select(
|
||||
options=setting.range.items(),
|
||||
label=setting.name,
|
||||
help_text=setting.desc,
|
||||
name=setting.key,
|
||||
value=handler.get_setting(setting.key))
|
||||
}}
|
||||
{% elif setting.ui == 'radio' %}
|
||||
{{ form.form_radio(
|
||||
options=setting.range.items(),
|
||||
label=setting.name,
|
||||
help_text=setting.desc,
|
||||
name=setting.key,
|
||||
value=handler.get_setting(setting.key))
|
||||
}}
|
||||
{% elif setting.ui == 'image_radio' %}
|
||||
{{ form.form_image_radio(
|
||||
options=setting.range.items(),
|
||||
image_class=setting.image_class,
|
||||
label=setting.name,
|
||||
help_text=setting.desc,
|
||||
name=setting.key,
|
||||
value=handler.get_setting(setting.key))
|
||||
}}
|
||||
{% elif setting.ui == 'textarea' %}
|
||||
{{ form.form_textarea(
|
||||
label=setting.name,
|
||||
help_text=setting.desc,
|
||||
name=setting.key,
|
||||
value=handler.get_setting(setting.key))
|
||||
}}
|
||||
{% elif setting.ui == 'markdown' %}
|
||||
{{ form.form_textarea(
|
||||
label=setting.name,
|
||||
help_text=setting.desc,
|
||||
name=setting.key,
|
||||
value=handler.get_setting(setting.key),
|
||||
markdown=true)
|
||||
}}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="section__body">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<input type="submit" class="rounded primary button" value="{{ _('Save All Changes') }}">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,78 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/record.html" as record with context %}
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Homework Introduction') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
{{ tdoc['content']|markdown }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Problem') }}</h1>
|
||||
</div>
|
||||
{% if handler.is_not_started(tdoc) %}
|
||||
{{ nothing.render('This homework is not open and you cannot view problems.') }}
|
||||
{% else %}
|
||||
{% if attended or handler.is_done(tdoc) %}
|
||||
<div class="section__body no-padding">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<col class="col--status">
|
||||
<col class="col--submit-at">
|
||||
{% endif %}
|
||||
<col class="col--problem">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<th class="col--status record-status--border">{{ _('Status') }}</th>
|
||||
<th class="col--submit-at">{{ _('Last Submit At') }}</th>
|
||||
{% endif %}
|
||||
<th class="col--problem">{{ _('Problem') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pid in tdoc['pids'] %}
|
||||
<tr>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
{% if psdict[pid] and psdict[pid]['rid'] %}
|
||||
{% with rdoc=rdict[psdict[pid]['rid']] %}
|
||||
{% if handler.can_show_record(tdoc) %}
|
||||
{{ record.render_status_td(rdoc) }}
|
||||
{% else %}
|
||||
<td class="col--status record-status--border"><a href="{{ reverse_url('record_detail', rid=rdoc['_id'], domain_id=handler.domain_id) }}">{{ _('Submitted') }}</a></td>
|
||||
{% endif %}
|
||||
<td class="col--submit-at">{{ datetime_span(rdoc['_id'].generation_time) }}</td>
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
<td class="col--status record-status--border">{{ _('No Submissions') }}</td>
|
||||
<td class="col--submit-at">-</td>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<td class="col--problem col--problem-name">
|
||||
#{{ loop.index }}:
|
||||
{{ problem.render_problem_title(pdict[pid], tdoc=tdoc, show_invisible_flag=false, show_tags=false) }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ nothing.render('Please claim the assignment to see the problems.') }}
|
||||
{% endif %}{# attended or handler.is_done(tdoc) #}
|
||||
{% endif %}{# handler.is_not_started(tdoc) #}
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% include "partials/homework_sidebar.html" %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,48 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
{{ form.form_text(columns=8, label='Title', name='title', placeholder=_('title'), value=tdoc['title']|default(''), autofocus=True) }}
|
||||
<div class="row">
|
||||
{{ form.form_text(columns=4, label='Begin Date', name='begin_at_date', placeholder='YYYY-mm-dd', value=date_begin_text, date=True, row=False) }}
|
||||
{{ form.form_text(columns=4, last_column=True, label='Begin Time', name='begin_at_time', placeholder='HH:MM', value=time_begin_text, time=True, row=False) }}
|
||||
</div><div class="row">
|
||||
{{ form.form_text(columns=4, label='End Date', name='penalty_since_date', placeholder='YYYY-mm-dd', value=date_penalty_text, date=True, row=False) }}
|
||||
{{ form.form_text(columns=4, last_column=True, label='End Time', name='penalty_since_time', placeholder='HH:MM', value=time_penalty_text, time=True, row=False) }}
|
||||
</div>
|
||||
{{ form.form_text(columns=4, label='Extension (days)', name='extension_days', value=extension_days) }}
|
||||
<div class="row"><div class="columns">
|
||||
<label>
|
||||
{{ _('Extension Score Penalty') }}
|
||||
<textarea name="penalty_rules" class="monospace textbox">{% if tdoc %}{{ penalty_rules }}{% else %}{% include 'partials/homework_default_penalty_rules.yaml' %}{% endif %}</textarea>
|
||||
</label>
|
||||
</div></div>
|
||||
{{ form.form_text(columns=None, label='Problems', name='pids', value=pids) }}
|
||||
{{ form.form_textarea(columns=None, label='Content', name='content', value=tdoc['content']|default(''), markdown=True) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
{% if page_name == 'homework_edit' %}
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Update') }}
|
||||
</button>
|
||||
{% else %}
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Create') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% include 'components/md_hint.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,68 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<script>
|
||||
var Context = {{ {
|
||||
'docs': calendar_tdocs,
|
||||
}|json|safe }};
|
||||
</script>
|
||||
<div class="row">
|
||||
<div class="medium-12 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('All Homeworks') }}</h1>
|
||||
<div class="section__tools">
|
||||
<span class="nojs-hide">
|
||||
{{ _('View') }}:
|
||||
<select class="inline compact select" name="homework_display">
|
||||
<option value="calendar">{{ _('Calendar View') }}</option>
|
||||
<option value="list">{{ _('List View') }}</option>
|
||||
</select>
|
||||
</span>
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_CREATE_HOMEWORK) %}
|
||||
<a class="compact button" href="{{ reverse_url('homework_create') }}">{{ _('Create Homework') }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body no-padding">
|
||||
{% if not tdocs %}
|
||||
{{ nothing.render('There is no homework so far ╰(*°▽°*)╯') }}
|
||||
{% else %}
|
||||
<ol class="section__list homework__list hasjs--hide">
|
||||
{% for tdoc in tdocs %}
|
||||
<li class="section__list__item homework__item">
|
||||
<div class="media">
|
||||
<div class="media__left medium">
|
||||
<div class="homework__date numbox">
|
||||
<div class="numbox__num large">{{ datetime_span(tdoc['penalty_since'], false, '%d') }}</div>
|
||||
<div class="numbox__text">{{ datetime_span(tdoc['penalty_since'], false, '%Y-%m') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body medium">
|
||||
<h1 class="homework__title"><a href="{{ reverse_url('homework_detail', tid=tdoc['doc_id']) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
{{ _('Status') }}: <span class="homework-status--text {{ handler.get_status(tdoc) }}">{{ _(handler.status_text(tdoc)) }}</span>
|
||||
</li>
|
||||
<li>
|
||||
{{ _('Open Since') }}: {{ datetime_span(tdoc['begin_at']) }}
|
||||
</li>
|
||||
<li>
|
||||
{% if handler.is_homework_extended(tdoc) or handler.is_done(tdoc) %}
|
||||
{{ _('Hard Deadline') }}: {{ datetime_span(tdoc['end_at']) }}
|
||||
{% else %}
|
||||
{{ _('Deadline') }}: {{ datetime_span(tdoc['penalty_since']) }}
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
<div name="calendar_entry"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row"><div class="columns">
|
||||
<div id="messages"></div>
|
||||
</div></div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,19 @@
|
||||
{% set layout_name = "basic" %}
|
||||
{% extends "layout/html5.html" %}
|
||||
{% block body %}
|
||||
|
||||
{% include "partials/nav.html" %}
|
||||
|
||||
<div class="slideout-panel" id="panel">
|
||||
<div class="slideout-overlay"></div>
|
||||
{% include "partials/header_mobile.html" %}
|
||||
{% include "partials/header.html" %}
|
||||
<div class="main">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
{% include "partials/footer.html" %}
|
||||
</div>
|
||||
|
||||
{% include "partials/login_dialog.html" %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,13 @@
|
||||
{% import "components/home.html" as home with context %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row" data-sticky-parent>
|
||||
<div class="medium-9 columns">
|
||||
{% block home_content %}{% endblock %}
|
||||
</div>
|
||||
<div class="medium-3 columns"><div data-sticky="large">
|
||||
{{ home.render_sidebar() }}
|
||||
{% block home_sidebar %}{% endblock %}
|
||||
</div></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,46 @@
|
||||
{% import "components/form.html" as form with context %}
|
||||
{% import "components/sidemenu.html" as sidemenu with context %}
|
||||
{% import "components/paginator.html" as paginator with context %}
|
||||
{% import "components/nothing.html" as nothing with context %}
|
||||
{% import "components/noscript_note.html" as noscript_note with context %}
|
||||
{% import "components/user.html" as user with context %}
|
||||
<!DOCTYPE html>
|
||||
<html data-page="{{ page_name }}" data-layout="{{ layout_name }}" class="layout--{{ layout_name }} page--{{ page_name }} nojs" lang="{{ handler.view_lang }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ static_url('apple-touch-icon-180x180.png') }}">
|
||||
<link rel="icon" type="image/png" href="{{ static_url('favicon-32x32.png') }}" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="{{ static_url('android-chrome-192x192.png') }}" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="{{ static_url('favicon-96x96.png') }}" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="{{ static_url('favicon-16x16.png') }}" sizes="16x16">
|
||||
<link rel="manifest" href="{{ static_url('manifest.json') }}">
|
||||
<meta name="msapplication-TileColor" content="#579e9a">
|
||||
<meta name="msapplication-TileImage" content="{{ static_url('mstile-144x144.png') }}">
|
||||
<meta name="theme-color" content="#56758f">
|
||||
|
||||
<link rel="stylesheet" media="all" href="{{ static_url('vendors.css') }}">
|
||||
<link rel="stylesheet" media="all" href="{{ static_url('vj4.css') }}">
|
||||
<title>{{ handler.render_title(page_title) }}</title>
|
||||
<script>
|
||||
var _htmlNode = document.documentElement;
|
||||
_htmlNode.className = _htmlNode.className.replace(' nojs', ' hasjs');
|
||||
var UiContext = {{ handler.ui_context|json|safe }};
|
||||
var UserContext = {{ handler.user_context|json|safe }};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
<!-- TODO: includes jQuery, JSON3, ES5-shim in the shim -->
|
||||
<!--[if lte IE 8]>
|
||||
<script type="text/javascript" src="{{ static_url('shim.js') }}"></script>
|
||||
<![endif]-->
|
||||
<script type="text/javascript" src="{{ static_url('manifest.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ static_url('vendors.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ static_url('locale/{0}.js'.format(handler.view_lang)) }}"></script>
|
||||
<script type="text/javascript" src="{{ static_url('vj4.js') }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
{% set layout_name = "immersive" %}
|
||||
{% set no_path_section = true %}
|
||||
{% extends "layout/html5.html" %}
|
||||
{% block body %}
|
||||
|
||||
{% include "partials/nav.html" %}
|
||||
|
||||
<div class="slideout-panel" id="panel">
|
||||
<div class="slideout-overlay"></div>
|
||||
{% include "partials/header_mobile.html" %}
|
||||
<div class="nav--placeholder"></div>
|
||||
<div class="main">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
{% with show_topics = false %}
|
||||
{% include "partials/footer.html" %}
|
||||
{% endwith %}
|
||||
|
||||
</div>
|
||||
|
||||
{% include "partials/login_dialog.html" %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,30 @@
|
||||
{% set layout_name = "mail" %}
|
||||
<style>
|
||||
body, .vijos { margin:0;color:#333;font-size:14px;font-family:"Tahoma","Segoe UI","Verdana","微软雅黑","Microsoft YaHei","宋体";background:#F2F2F2; }
|
||||
.vijos { padding:30px; }
|
||||
.vijos-box { background:#fff;box-shadow:0 0 15px rgba(0,0,0,0.3);border-radius:5px; }
|
||||
.vijos-header { background:#3AA9DE;color:#FFF;padding:10px;line-height:200%;font-size:15px;border-radius:5px 5px 0 0;border-bottom:3px solid #85CAEB; }
|
||||
.vijos-footer { font-size:12px;color:#444;padding:10px;border-top:1px solid #DDD;background:#F4F4F4;border-radius:0 0 5px 5px; }
|
||||
.vijos-content { padding:30px; }
|
||||
.vijos-content p { margin:5px 0; }
|
||||
.vijos a,
|
||||
.vijos a:visited,
|
||||
.vijos a:link,
|
||||
.vijos a:active { color:#1D76C7;text-decoration:none; }
|
||||
.vijos a:hover { color:#3A93E2;text-decoration:underline; }
|
||||
.vijos blockquote { padding:5px 10px;border-left:10px solid #E2EFFA;margin:20px;margin-left:0;_zoom:1; }
|
||||
#vijos_mail .t { font-size:16px; }
|
||||
#vijos_mail .f { font-style:italic; }
|
||||
</style>
|
||||
<div class="vijos">
|
||||
<div class="vijos-box">
|
||||
<div class="vijos-header">{% block title %}{% endblock %} - Vijos</div>
|
||||
<div class="vijos-content">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<div class="vijos-footer">
|
||||
<p>{{ _('This email was sent by {0} automatically, and please do not reply directly.').format('<a href="' + url_prefix + '/" target="_blank">Vijos</a>')|safe }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{% set layout_name = "basic" %}
|
||||
{% extends "layout/html5.html" %}
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,16 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row" data-sticky-parent>
|
||||
<div class="medium-9 columns">
|
||||
{% block wiki_content %}{% endblock %}
|
||||
</div>
|
||||
<div class="medium-3 columns"><div data-sticky="large">
|
||||
<div class="section side">
|
||||
<ol class="menu">
|
||||
{{ sidemenu.render_item('info', 'about') }}
|
||||
{{ sidemenu.render_item('help', 'wiki_help') }}
|
||||
</ol>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,108 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% import "components/contest.html" as contest with context %}
|
||||
<div class="section side">
|
||||
{% if page_name != 'contest_detail' %}
|
||||
<a class="contest-sidebar__bg" href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">
|
||||
<div class="section__body">
|
||||
<h1>{{ tdoc['title'] }}</h1>
|
||||
<div class="contest-sidebar__status">
|
||||
{% if attended %}
|
||||
<span class="icon icon-check"></span> {{ _('Attended') }}
|
||||
{% else %}
|
||||
<span class="icon icon-schedule"></span> {{ _('Not Attended') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
<div>
|
||||
<ol class="menu">
|
||||
{% if page_name == 'discussion_node' %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_CREATE_DISCUSSION) %}
|
||||
<li class="menu__item"><a class="menu__link highlight" href="{{ reverse_url('discussion_create_document_as_node', doc_type=tdoc['doc_type'], doc_id=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-add"></span> {{ _('Create a Discussion') }}
|
||||
</a></li>
|
||||
{% else %}
|
||||
{% if not handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<li class="menu__item"><a class="menu__link" href="javascript:showSignInDialog();">
|
||||
<span class="icon icon-add"></span> {{ _('Login to Create a Discussion') }}</a></li>
|
||||
{% else %}
|
||||
<li class="menu__item"><a class="menu__link disabled" href="javascript:;">
|
||||
<span class="icon icon-add"></span> {{ _('No Permission to Create a Discussion') }}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li class="menu__seperator"></li>
|
||||
{% endif %}
|
||||
{% if page_name != 'contest_detail' %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-award"></span> {{ _('View Contest') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if not attended and not handler.is_done(tdoc) %}
|
||||
<li class="menu__item">
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_ATTEND_CONTEST) and handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<form action="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" method="POST">
|
||||
<input type="hidden" name="operation" value="attend">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button class="menu__link" type="submit">
|
||||
<span class="icon icon-add"></span> {{ _('Attend Contest') }}
|
||||
</button>
|
||||
</form>
|
||||
{% elif not handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<a class="menu__link" href="javascript:showSignInDialog()">
|
||||
<span class="icon icon-add"></span> {{ _('Login to Attend Contest') }}
|
||||
</a>
|
||||
{% else %}
|
||||
<a class="menu__link disabled" href="javascript:;">
|
||||
<span class="icon icon-add"></span> {{ _('No Permission to Attend Contest') }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if handler.can_show_scoreboard(tdoc, False) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('contest_scoreboard', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-statistics"></span> {{ _('Scoreboard') }}
|
||||
</a></li>
|
||||
{% elif handler.can_view_hidden_scoreboard(tdoc) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('contest_scoreboard', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-statistics"></span> {{ _('Scoreboard (Hidden)') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.own(tdoc, vj4.model.builtin.PERM_EDIT_CONTEST_SELF) or handler.has_perm(vj4.model.builtin.PERM_EDIT_CONTEST) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('contest_edit', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit Contest') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_READ_RECORD_CODE) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('contest_code', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-download"></span> {{ _('Export All Code') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('record_main') }}?tid={{ tdoc['doc_id'] }}">
|
||||
<span class="icon icon-flag"></span> {{ _('All Submissions') }}
|
||||
</a></li>
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('wiki_help') }}#contest">
|
||||
<span class="icon icon-help"></span> {{ _('Help') }}
|
||||
</a></li>
|
||||
<li class="menu__seperator"></li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<dl class="large horizontal">
|
||||
<dt>{{ _('Status') }}</dt><dd>{{ _(handler.status_text(tdoc)) }}</dd>
|
||||
<dt>{{ _('Rule') }}</dt><dd>{{ vj4.constant.contest.RULE_TEXTS[tdoc['rule']] }}</dd>
|
||||
<dt>{{ _('Problem') }}</dt><dd>{{ tdoc['pids']|length }}</dd>
|
||||
<dt>{{ _('Start at') }}</dt><dd>{{ contest.render_time(tdoc['begin_at']) }}</dd>
|
||||
<dt>{{ _('End at') }}</dt><dd>{{ contest.render_time(tdoc['end_at']) }}</dd>
|
||||
<dt>{{ _('Duration') }}</dt><dd>{{ contest.render_duration(tdoc) }} {{ _('hour(s)') }}</dd>
|
||||
<dt>{{ _('Host') }}</dt><dd>{{ user.render_inline(owner_udoc, dudoc=owner_dudoc, badge=false) }}</dd>
|
||||
<dt>{{ _('Partic.') }}</dt>
|
||||
<dd>
|
||||
{{ tdoc['attend']|default(0) }}
|
||||
{% if attended %}
|
||||
({{ _('Attended') }})
|
||||
{% endif %}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,6 @@
|
||||
{% import "components/form.html" as form with context %}
|
||||
{% if ddoc['highlight'] or handler.has_perm(vj4.model.builtin.PERM_HIGHLIGHT_DISCUSSION) %}
|
||||
{{ form.form_checkbox(label='Highlight', name='highlight', value=ddoc['highlight']|default(false)) }}
|
||||
{% endif %}
|
||||
{{ form.form_text(label='Title', name='title', value=ddoc['title']|default(''), autofocus=true, required=true) }}
|
||||
{{ form.form_textarea(columns=12, label='Content', name='content', value=ddoc['content']|default(''), hotkeys='ctrl+enter:submit', markdown=true, required=true) }}
|
||||
@@ -0,0 +1,46 @@
|
||||
{% import "components/nothing.html" as nothing with context %}
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% import "components/paginator.html" as paginator with context %}
|
||||
{% if not ddocs %}
|
||||
{{ nothing.render('no discussion yet...') }}
|
||||
{% else %}
|
||||
<ol class="section__list discussion__list">
|
||||
{% for ddoc in ddocs %}
|
||||
<li class="section__list__item discussion__item{% if ddoc['highlight'] %} highlight{% endif %}">
|
||||
<div class="media">
|
||||
<div class="media__left">
|
||||
<div class="discussion__replies numbox">
|
||||
<div class="numbox__num large">{{ ddoc['num_replies'] }}</div>
|
||||
<div class="numbox__text">{{ _('Comments') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body top">
|
||||
<h1 class="discussion__title"><a href="{{ reverse_url('discussion_detail', did=ddoc['doc_id']) }}#{{ handler.datetime_stamp(ddoc['update_at']) if ddoc['update_at'] else '' }}" data-emoji-enabled>{{ ddoc['title'] }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
<a class="discussion-node-tag" href="{{ vj4.handler.discussion.node_url(handler, 'discussion_node', vj4.model.adaptor.discussion.node_id(ddoc)) }}">
|
||||
{% if ddoc['parent_doc_type'] == vj4.model.document.TYPE_DISCUSSION_NODE %}
|
||||
<span class="v-center icon icon-tag"></span>
|
||||
{% elif ddoc['parent_doc_type'] == vj4.model.document.TYPE_CONTEST %}
|
||||
<span class="v-center icon icon-award"></span>
|
||||
{% else %}
|
||||
<span class="v-center icon icon-flag"></span>
|
||||
{% endif %}
|
||||
{{ vndict[vj4.model.adaptor.discussion.node_id(ddoc)]['title']|default(_('(missing)')) }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ user.render_inline(udict[ddoc['owner_uid']], dudoc=dudoc if dudoc else dudict[ddoc['owner_uid']], badge=false) }}
|
||||
@
|
||||
{{ datetime_span(ddoc['update_at'] or ddoc['_id'].generation_time) }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
{% if page != undefined and dpcount != undefined %}
|
||||
{{ paginator.render(page, dpcount) }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% import "components/form.html" as form with context %}
|
||||
{% if page_name == 'domain_manage_edit' %}
|
||||
{{ form.form_text(label='ID', name='id', value=ddoc['_id'], disabled=true) }}
|
||||
{% elif page_name == 'home_domain_create' %}
|
||||
{{ form.form_text(label='ID', name='id', autofocus=true, required=true) }}
|
||||
{% endif %}
|
||||
{{ form.form_text(label='Name', name='name', value=ddoc['name']|default(''), autofocus=(page_name == 'domain_manage_edit'), required=true) }}
|
||||
{{ form.form_text(label='Gravatar Email', help_text='Will be used as the domain icon.', name='gravatar', value=ddoc['gravatar']|default('')) }}
|
||||
{{ form.form_textarea(columns=12, label='Bulletin', name='bulletin', value=ddoc['bulletin']|default(''), markdown=true, required=false) }}
|
||||
@@ -0,0 +1,74 @@
|
||||
<div class="footer">
|
||||
<div class="row"><div class="columns">
|
||||
{% if show_topics|default(true) %}
|
||||
<div class="row footer__links">
|
||||
<div class="medium-3 large-2 columns footer__category expandable">
|
||||
<h1>
|
||||
{{ _('Status') }}
|
||||
<span class="expand-icon">
|
||||
<span class="icon icon-expand_more"></span>
|
||||
</span>
|
||||
</h1>
|
||||
<div class="footer__category__expander"><ul class="footer__category__list">
|
||||
<li class="footer__category__item"><a href="{{ reverse_url('record_main') }}">{{ _('Judging Queue') }}</a></li>
|
||||
<li class="footer__category__item"><a href="#">{{ _('Service Status') }}</a></li>
|
||||
</ul></div>
|
||||
</div>
|
||||
<div class="medium-3 large-2 columns footer__category expandable">
|
||||
<h1>
|
||||
{{ _('Development') }}
|
||||
<span class="expand-icon">
|
||||
<span class="icon icon-expand_more"></span>
|
||||
</span>
|
||||
</h1>
|
||||
<div class="footer__category__expander"><ul class="footer__category__list">
|
||||
<li class="footer__category__item"><a href="https://github.com/vijos/vj4" target="_blank">{{ _('Open Source') }}</a></li>
|
||||
<li class="footer__category__item"><a href="https://github.com/vijos/vj4/wiki">{{ _('API') }}</a></li>
|
||||
</ul></div>
|
||||
</div>
|
||||
<div class="medium-3 large-2 columns footer__category expandable end">
|
||||
<h1>
|
||||
{{ _('Support') }}
|
||||
<span class="expand-icon">
|
||||
<span class="icon icon-expand_more"></span>
|
||||
</span>
|
||||
</h1>
|
||||
<div class="footer__category__expander"><ul class="footer__category__list">
|
||||
{% if domain_id != vj4.model.builtin.DOMAIN_ID_SYSTEM %}
|
||||
<li class="footer__category__item"><a href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}">{{ _('Vijos') }}</a></li>
|
||||
{% endif %}
|
||||
<li class="footer__category__item"><a href="//vijos.github.io/about-vijos/">{{ _('Help') }}</a></li>
|
||||
<!--<li class="footer__category__item"><a href="#">{{ _('Blog') }}</a></li>-->
|
||||
<li class="footer__category__item"><a href="//vijos.github.io/about-vijos/about/contact-us/">{{ _('QQ Group') }}</a></li>
|
||||
</ul></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="footer__extra-link clearfix">
|
||||
<div class="footer__extra-left">
|
||||
<ol class="clearfix">
|
||||
<li class="footer__extra-link-item"><a href="//vijos.github.io/about-vijos/about/about-vijos/">{{ _('About') }}</a></li>
|
||||
<li class="footer__extra-link-item"><a href="//vijos.github.io/about-vijos/about/contact-us/">{{ _('Contact Us') }}</a></li>
|
||||
<li class="footer__extra-link-item"><a href="//vijos.github.io/about-vijos/about/privacy-policy/">{{ _('Privacy') }}</a></li>
|
||||
<li class="footer__extra-link-item"><a href="//vijos.github.io/about-vijos/about/terms-of-service/">{{ _('Terms of Service') }}</a></li>
|
||||
<li class="footer__extra-link-item"><a href="//vijos.github.io/about-vijos/about/copyright-complaint/">{{ _('Copyright Complaint') }}</a></li>
|
||||
<li class="footer__extra-link-item" data-dropdown-target="#menu-footer-lang">
|
||||
<span><span class="icon icon-global"></span> Language <span class="icon icon-expand_less"></span></span>
|
||||
<ol class="dropdown-target menu" id="menu-footer-lang">
|
||||
{% for code, name in vj4.util.locale.VIEW_LANGS.items() %}
|
||||
<li class="menu__item"><a class="menu__link" href="/lang/{{ code }}">{{ name }}</a></li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="footer__extra-right">
|
||||
<ol class="clearfix">
|
||||
{% for html in vj4.model.builtin.FOOTER_EXTRA_HTMLS %}
|
||||
<li class="footer__extra-link-item">{{ html|safe }}</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
<button type="button" class="header__hamburger">
|
||||
<div class="hamburger hamburger--spin">
|
||||
<span class="hamburger-box">
|
||||
<span class="hamburger-inner"></span>
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
@@ -0,0 +1,11 @@
|
||||
<div class="header{% if no_path_section %} mini{% endif %}">
|
||||
<div class="header__content"><div class="row"><div class="columns">
|
||||
{% if domain_id == vj4.model.builtin.DOMAIN_ID_SYSTEM %}
|
||||
<a class="header__logo" href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}" target="_self"></a>
|
||||
{% else %}
|
||||
<div class="header__logo--domain"><a href="{{ reverse_url('domain_main') }}" target="_self">{{ domain['name'] }}</a></div>
|
||||
<div class="header__logo--system"><a href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}" target="_blank">Powered by Vijos</a></div>
|
||||
{% endif %}
|
||||
</div></div></div>
|
||||
{% include "partials/path.html" %}
|
||||
</div>
|
||||
@@ -0,0 +1,17 @@
|
||||
{% if no_path_section %}
|
||||
<div class="header--mobile">
|
||||
<div class="row"><div class="columns clearfix">
|
||||
<div class="float-left">
|
||||
{% if domain_id == vj4.model.builtin.DOMAIN_ID_SYSTEM %}
|
||||
<a class="header--mobile__domain is--system" href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}" target="_self"> </a>
|
||||
{% else %}
|
||||
<a class="header--mobile__domain" href="{{ reverse_url('domain_main') }}" target="_self">{{ domain['name'] }}</a>
|
||||
<a class="header--mobile__system" href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}" target="_blank">Powered by Vijos</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="float-right">
|
||||
{% include "partials/hamburger.html" %}
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,6 @@
|
||||
# Format:
|
||||
# hours: coefficient
|
||||
1: 0.9
|
||||
3: 0.8
|
||||
12: 0.75
|
||||
9999: 0.5
|
||||
@@ -0,0 +1,85 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% import "components/homework.html" as homework with context %}
|
||||
<div class="section side">
|
||||
{% if page_name != 'homework_detail' %}
|
||||
<a class="contest-sidebar__bg" href="{{ reverse_url('homework_detail', tid=tdoc['doc_id']) }}">
|
||||
<div class="section__body">
|
||||
<h1>{{ tdoc['title'] }}</h1>
|
||||
<div class="contest-sidebar__status">
|
||||
{% if attended %}
|
||||
<span class="icon icon-check"></span> {{ _('Claimed') }}
|
||||
{% else %}
|
||||
<span class="icon icon-schedule"></span> {{ _('Not Claimed') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
<div>
|
||||
<ol class="menu">
|
||||
{% if page_name != 'homework_detail' %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('homework_detail', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-homework"></span> {{ _('View Homework') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if not attended and not handler.is_done(tdoc) %}
|
||||
<li class="menu__item">
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_ATTEND_HOMEWORK) and handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<form action="{{ reverse_url('homework_detail', tid=tdoc['doc_id']) }}" method="POST">
|
||||
<input type="hidden" name="operation" value="attend">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button class="menu__link" type="submit">
|
||||
<span class="icon icon-add"></span> {{ _('Claim Homework') }}
|
||||
</button>
|
||||
</form>
|
||||
{% elif not handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<a class="menu__link" href="javascript:showSignInDialog()">
|
||||
<span class="icon icon-add"></span> {{ _('Login to Claim Homework') }}
|
||||
</a>
|
||||
{% else %}
|
||||
<a class="menu__link disabled" href="javascript:;">
|
||||
<span class="icon icon-add"></span> {{ _('No Permission to Claim Homework') }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if handler.can_show_scoreboard(tdoc, False) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('homework_scoreboard', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-statistics"></span> {{ _('Scoreboard') }}
|
||||
</a></li>
|
||||
{% elif handler.can_view_hidden_scoreboard(tdoc) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('homework_scoreboard', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-statistics"></span> {{ _('Scoreboard (Hidden)') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.own(tdoc, vj4.model.builtin.PERM_EDIT_HOMEWORK_SELF) or handler.has_perm(vj4.model.builtin.PERM_EDIT_HOMEWORK) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('homework_edit', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit Homework') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_READ_RECORD_CODE) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('homework_code', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-download"></span> {{ _('Export All Code') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if attended %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('record_main') }}?uid_or_name={{ handler.user['_id'] }}&tid={{ tdoc['doc_id'] }}">
|
||||
<span class="icon icon-flag"></span> {{ _('My Recent Submissions') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('wiki_help') }}#homework">
|
||||
<span class="icon icon-help"></span> {{ _('Help') }}
|
||||
</a></li>
|
||||
<li class="menu__seperator"></li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<dl class="large horizontal">
|
||||
<dt>{{ _('Status') }}</dt><dd><span class="homework-status--text {{ handler.get_status(tdoc) }}">{{ _(handler.status_text(tdoc)) }}</span></dd>
|
||||
<dt>{{ _('Problem') }}</dt><dd>{{ tdoc['pids']|length }}</dd>
|
||||
<dt>{{ _('Open Since') }}</dt><dd>{{ homework.render_time(tdoc['begin_at']) }}</dd>
|
||||
<dt>{{ _('Deadline') }}</dt><dd>{{ homework.render_time(tdoc['penalty_since']) }}</dd>
|
||||
<dt>{{ _('Can be Extended For') }}</dt><dd>{{ homework.render_extension(tdoc) }} {{ _('hour(s)') }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,45 @@
|
||||
<div class="dialog dialog--signin" style="display:none">
|
||||
<div class="dialog__content">
|
||||
<div class="dialog--signin__bg">
|
||||
<div class="dialog--signin__side">
|
||||
<h1>{{ _('Don\'t have an account?') }}</h1>
|
||||
<p>{{ _('By signing up a Vijos universal account, you can submit code and join discussions in all online judging services provided by us.') }}</p>
|
||||
<div><a href="{{ reverse_url('user_register') }}" class="inverse rounded button">{{ _('Sign Up Now') }}</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog--signin__main">
|
||||
<form action="{{ reverse_url('user_login') }}" method="post">
|
||||
<div class="dialog--signin__close-container supplementary">
|
||||
<a name="dialog--signin__close" href="javascript:;">{{ _('CLOSE') }}</a>
|
||||
</div>
|
||||
<h1 class="dialog--signin__title">{{ _('SIGN IN') }}</h1>
|
||||
<p class="dialog--signin__note">{{ _('Using your Vijos universal account') }}</p>
|
||||
<div class="row"><div class="columns">
|
||||
<label class="material textbox">
|
||||
{{ _('Username') }}
|
||||
<input name="uname" type="text" data-autofocus>
|
||||
</label>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<label class="material textbox">
|
||||
{{ _('Password') }}
|
||||
<input name="password" type="password">
|
||||
</label>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="rememberme">{{ _('Remember me') }}
|
||||
</label>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<input type="submit" value="{{ _('Sign In') }}" class="expanded rounded primary button">
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<div class="supplementary text-center">
|
||||
<a href="{{ reverse_url('user_lostpass') }}">{{ _('Forgot password or username?') }}</a>
|
||||
</div>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,97 @@
|
||||
{% macro nav_item(target_page_name, target_page_prefix) %}
|
||||
<li class="nav__list-item">
|
||||
<a href="{{ reverse_url(target_page_name) }}" class="nav__item{% if page_name.startswith(target_page_prefix) %} nav--active{% endif %}">
|
||||
{{ _(target_page_name) }}
|
||||
</a>
|
||||
</li>
|
||||
{% endmacro %}
|
||||
|
||||
<nav class="nav slideout-menu" id="menu">
|
||||
<div class="row"><div class="columns clearfix">
|
||||
<ol class="nav__list nav__list--main clearfix">
|
||||
{% if domain_id == vj4.model.builtin.DOMAIN_ID_SYSTEM %}
|
||||
<li class="nav__list-item"><a href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}" class="nav__logo"> </a></li>
|
||||
{% endif %}
|
||||
{{ nav_item('domain_main', 'domain_main') }}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_VIEW_PROBLEM) %}
|
||||
{{ nav_item('problem_main', 'problem') }}
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_VIEW_TRAINING) %}
|
||||
{{ nav_item('training_main', 'training') }}
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_VIEW_DISCUSSION) %}
|
||||
{{ nav_item('discussion_main', 'discussion') }}
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_VIEW_CONTEST) %}
|
||||
{{ nav_item('contest_main', 'contest') }}
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_VIEW_HOMEWORK) %}
|
||||
{{ nav_item('homework_main', 'homework') }}
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_EDIT_DESCRIPTION) or handler.has_perm(vj4.model.builtin.PERM_EDIT_PERM) %}
|
||||
{{ nav_item('domain_manage', 'domain_manage') }}
|
||||
{% endif %}
|
||||
</ol>
|
||||
<ol class="nav__list nav__list--secondary clearfix">
|
||||
{% if not handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<li class="nav__list-item"><a href="{{ reverse_url('user_login') }}" class="nav__item" name="nav_login">{{ _('Login') }}</a></li>
|
||||
<li class="nav__list-item"><a href="{{ reverse_url('user_register') }}" class="nav__item--round">{{ _('Sign Up') }}</a></li>
|
||||
{% else %}
|
||||
<li class="nav__list-item" data-dropdown-pos="bottom right" data-dropdown-target="#menu-nav-user" data-dropdown-trigger-desktop-only>
|
||||
<a href="{{ reverse_url('user_detail', uid=handler.user['_id']) }}" class="nav__item">{{ handler.domain_user['display_name']|default(handler.user['uname'], true) }} <span class="icon icon-expand_more nojs--hide"></span></a>
|
||||
<ol class="dropdown-target menu" id="menu-nav-user">
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('user_detail', uid=handler.user['_id']) }}" class="menu__link">
|
||||
<span class="icon icon-account--circle"></span> {{ _('My Profile') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('home_messages') }}" class="menu__link">
|
||||
<span class="icon icon-comment--multiple"></span> {{ _('home_messages') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('home_account') }}" class="menu__link">
|
||||
<span class="icon icon-wrench"></span> {{ _('home_account') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('home_domain_account') }}" class="menu__link">
|
||||
<span class="icon icon-web"></span> @ {{ handler.domain['name'] }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('home_preference') }}" class="menu__link">
|
||||
<span class="icon icon-sliders"></span> {{ _('home_preference') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('home_security') }}" class="menu__link">
|
||||
<span class="icon icon-security"></span> {{ _('home_security') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('home_file') }}" class="menu__link">
|
||||
<span class="icon icon-file"></span> {{ _('My Files') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('home_domain') }}" class="menu__link">
|
||||
<span class="icon icon-web"></span> {{ _('My Domains') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('user_logout') }}" class="menu__link" name="nav_logout">
|
||||
<span class="icon icon-logout"></span> {{ _('Logout') }}
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ol>
|
||||
</div></div>
|
||||
</nav>
|
||||
<nav class="nav--shadow"></nav>
|
||||
@@ -0,0 +1,19 @@
|
||||
<div class="location" data-fragment-id="path">
|
||||
{% if not no_path_section %}
|
||||
<div class="row"><div class="columns">
|
||||
<div class="media">
|
||||
<div class="media__body">
|
||||
<div class="location-path">
|
||||
{% for c in path_components %}
|
||||
/ {% if c[1] %}<a href="{{ c[1] }}">{{ c[0] }}</a>{% endif %}
|
||||
{%- endfor %}
|
||||
</div>
|
||||
<h1 class="location-current" data-emoji-enabled>{{ path_components[-1][0] }}</h1>
|
||||
</div>
|
||||
<div class="media__right">
|
||||
{% include "partials/hamburger.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,99 @@
|
||||
# Background
|
||||
Special for beginners, ^_^
|
||||
|
||||
# Description
|
||||
Given two integers x and y, print the sum.
|
||||
|
||||
# Format
|
||||
|
||||
## Input
|
||||
Two integers x and y, satisfying 0 <= x, y <= 32767.
|
||||
|
||||
## Output
|
||||
One integer, the sum of x and y.
|
||||
|
||||
# Sample 1
|
||||
|
||||
## Input
|
||||
```
|
||||
123 500
|
||||
```
|
||||
|
||||
## Output
|
||||
```
|
||||
623
|
||||
```
|
||||
|
||||
# Limitation
|
||||
1s, 1024KiB for each test case.
|
||||
|
||||
# Hint
|
||||
|
||||
## Free Pascal Code
|
||||
|
||||
```pascal
|
||||
var a,b:longint;
|
||||
begin
|
||||
readln(a,b);
|
||||
writeln(a+b);
|
||||
end.
|
||||
```
|
||||
|
||||
## C Code
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
int main(void)
|
||||
{
|
||||
int a, b;
|
||||
scanf("%d%d", &a, &b);
|
||||
printf("%d\n", a + b);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## C++ Code
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
int main()
|
||||
{
|
||||
int a, b;
|
||||
cin >> a >> b;
|
||||
cout << a + b << endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Python Code
|
||||
|
||||
```python
|
||||
a, b = [int(i) for i in raw_input().split()]
|
||||
print(a + b)
|
||||
```
|
||||
|
||||
## Java Code
|
||||
|
||||
```java
|
||||
import java.io.*;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Main {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
int a = sc.nextInt();
|
||||
int b = sc.nextInt();
|
||||
System.out.println(a + b);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Source
|
||||
|
||||
**Vijos Original**
|
||||
@@ -0,0 +1,69 @@
|
||||
{% import "components/paginator.html" as paginator with context %}
|
||||
{% import "components/record.html" as record with context %}
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
{% import "components/nothing.html" as nothing with context %}
|
||||
<div data-fragment-id="problem_list">
|
||||
{% if not pdocs %}
|
||||
{{ nothing.render('Sorry, there is no problem in the problem set') }}
|
||||
{% else %}
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<col class="col--status">
|
||||
{% endif %}
|
||||
<col class="col--name">
|
||||
<col class="col--submit_n">
|
||||
<col class="col--ac_rate">
|
||||
<col class="col--difficulty">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<th class="col--status record-status--border">{{ _('Status') }}</th>
|
||||
{% endif %}
|
||||
<th class="col--name">{{ _('Problem') }}</th>
|
||||
<th class="col--submit_n">{{ _('Submit') }}</th>
|
||||
<th class="col--ac_rate">% {{ _('AC') }}</th>
|
||||
<th class="col--difficulty">{{ _('Difficulty') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pdoc in pdocs %}
|
||||
{% with psdoc = psdict[pdoc['doc_id']] %}
|
||||
<tr>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
{% if psdoc['rid'] %}
|
||||
{{ record.render_status_td(psdoc, rid_key='rid') }}
|
||||
{% else %}
|
||||
<td class="col--status record-status--border">
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<td class="col--name col--problem-name">
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<form class="form--inline" action="{{ reverse_url('problem_main') }}" method="post">
|
||||
<input type="hidden" name="pid" value="{{ pdoc['doc_id'] }}">
|
||||
<input type="hidden" name="operation" value="{% if not psdoc['star'] %}star{% else %}unstar{% endif %}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button class="star{% if psdoc['star'] %} activated{% endif %}" type="submit">
|
||||
<span class="starred--hide"><span class="icon icon-star--outline" data-tooltip="{{ _('Star') }}"></span></span>
|
||||
<span class="starred--show"><span class="icon icon-star" data-tooltip="{{ _('Unstar') }}"></span></span>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{{ problem.render_problem_title(
|
||||
pdoc,
|
||||
rp=vj4.job.rp.get_rp_expect(pdoc) if (not psdoc or psdoc['status'] != vj4.constant.record.STATUS_ACCEPTED) else none
|
||||
) }}
|
||||
</td>
|
||||
<td class="col--submit_n">{{ pdoc['num_submit'] }}</td>
|
||||
<td class="col--ac_rate">{{ (100 * pdoc['num_accept'] / pdoc['num_submit'])|round|int if pdoc['num_submit'] > 0 else _('?') }}</td>
|
||||
<td class="col--difficulty">{{ pdoc['difficulty'] or _('(None)') }}</td>
|
||||
</tr>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ paginator.render(page, ppcount) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,8 @@
|
||||
<div data-fragment-id="problem_lucky">
|
||||
<p>
|
||||
<a href="{% if not category %}{{ reverse_url('problem_random') }}{% else %}{{ reverse_url('problem_category_random', category=category) }}{% endif %}" class="expanded button" target="_blank"><span class="icon icon-feeling-lucky"></span> {{ _('Lucky') }}</a>
|
||||
</p>
|
||||
<div class="typo supplementary">
|
||||
<p>{{ _('Pick a problem randomly based on current filter') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,15 @@
|
||||
{% if tdoc %}
|
||||
{% if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST %}
|
||||
{% include "partials/problem_sidebar_contest.html" %}
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% include "partials/contest_sidebar.html" %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{% include "partials/problem_sidebar_homework.html" %}
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% include "partials/homework_sidebar.html" %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% include "partials/problem_sidebar_normal.html" %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,42 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
<div class="section side section--problem-sidebar">
|
||||
{% if page_name != 'problem_detail' and page_name != 'contest_detail_problem' %}
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ pdoc['title'] }}</h1>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
<ol class="menu">
|
||||
{% if handler.is_ongoing(tdoc) %}
|
||||
{% if page_name == 'contest_detail_problem' %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link highlight" name="problem-sidebar__open-scratchpad" href="javascript:;" data-global-hotkey="alt+e">
|
||||
<span class="icon icon-enlarge"></span> {{ _('Open Scratchpad') }} (Alt+E)
|
||||
</a></li>
|
||||
<li class="menu__item non-scratchpad--hide"><a class="menu__link" name="problem-sidebar__quit-scratchpad" href="javascript:;" data-global-hotkey="alt+q">
|
||||
<span class="icon icon-enlarge"></span> {{ _('Quit Scratchpad') }} (Alt+Q)
|
||||
</a></li>
|
||||
{% else %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('contest_detail_problem', tid=tdoc['doc_id'], pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-flag"></span> {{ _('View Problem') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link{% if page_name == 'contest_detail_problem_submit' %} active{% endif %}" href="{{ reverse_url('contest_detail_problem_submit', tid=tdoc['doc_id'], pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-send"></span> {{ _('Submit') }}
|
||||
</a></li>
|
||||
{% elif handler.is_done(tdoc) %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link" href="{{ reverse_url('problem_detail', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-send"></span> {{ _('Open in Problem Set') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.own(pdoc, vj4.model.builtin.PERM_EDIT_PROBLEM_SELF) or handler.has_perm(vj4.model.builtin.PERM_EDIT_PROBLEM) %}
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="{{ reverse_url('problem_edit', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||
</a></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="{{ reverse_url('problem_settings', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-wrench"></span> {{ _('Settings') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,42 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
<div class="section side section--problem-sidebar">
|
||||
{% if page_name != 'problem_detail' and page_name != 'homework_detail_problem' %}
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ pdoc['title'] }}</h1>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
<ol class="menu">
|
||||
{% if handler.is_ongoing(tdoc) or handler.is_homework_extended(tdoc) %}
|
||||
{% if page_name == 'homework_detail_problem' %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link highlight" name="problem-sidebar__open-scratchpad" href="javascript:;" data-global-hotkey="alt+e">
|
||||
<span class="icon icon-enlarge"></span> {{ _('Open Scratchpad') }} (Alt+E)
|
||||
</a></li>
|
||||
<li class="menu__item non-scratchpad--hide"><a class="menu__link" name="problem-sidebar__quit-scratchpad" href="javascript:;" data-global-hotkey="alt+q">
|
||||
<span class="icon icon-enlarge"></span> {{ _('Quit Scratchpad') }} (Alt+Q)
|
||||
</a></li>
|
||||
{% else %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('homework_detail_problem', tid=tdoc['doc_id'], pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-flag"></span> {{ _('View Problem') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link{% if page_name == 'homework_detail_problem_submit' %} active{% endif %}" href="{{ reverse_url('homework_detail_problem_submit', tid=tdoc['doc_id'], pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-send"></span> {{ _('Submit') }}
|
||||
</a></li>
|
||||
{% elif handler.is_done(tdoc) %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link" href="{{ reverse_url('problem_detail', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-send"></span> {{ _('Open in Problem Set') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.own(pdoc, vj4.model.builtin.PERM_EDIT_PROBLEM_SELF) or handler.has_perm(vj4.model.builtin.PERM_EDIT_PROBLEM) %}
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="{{ reverse_url('problem_edit', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||
</a></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="{{ reverse_url('problem_settings', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-wrench"></span> {{ _('Settings') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,192 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
<div class="section side section--problem-sidebar">
|
||||
{% if page_name != 'problem_detail' and page_name != 'contest_detail_problem' %}
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ pdoc['title'] }}</h1>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
<ol class="menu">
|
||||
{% if page_name == 'discussion_node' or page_name == 'discussion_detail' %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_CREATE_DISCUSSION) %}
|
||||
<li class="menu__item"><a class="menu__link highlight" href="{{ reverse_url('discussion_create_document_as_node', doc_type=pdoc['doc_type'], doc_id=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-add"></span> {{ _('Create a Discussion') }}
|
||||
</a></li>
|
||||
{% else %}
|
||||
{% if not handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<li class="menu__item"><a class="menu__link" href="javascript:showSignInDialog();">
|
||||
<span class="icon icon-add"></span> {{ _('Login to Create a Discussion') }}</a></li>
|
||||
{% else %}
|
||||
<li class="menu__item"><a class="menu__link disabled" href="javascript:;">
|
||||
<span class="icon icon-add"></span> {{ _('No Permission to Create a Discussion') }}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li class="menu__seperator"></li>
|
||||
{% endif %}
|
||||
{% if page_name == 'problem_detail' %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_SUBMIT_PROBLEM) %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link highlight" name="problem-sidebar__open-scratchpad" href="javascript:;" data-global-hotkey="alt+e">
|
||||
<span class="icon icon-enlarge"></span> {{ _('Open Scratchpad') }} (Alt+E)
|
||||
</a></li>
|
||||
<li class="menu__item non-scratchpad--hide"><a class="menu__link" name="problem-sidebar__quit-scratchpad" href="javascript:;" data-global-hotkey="alt+q">
|
||||
<span class="icon icon-enlarge"></span> {{ _('Quit Scratchpad') }} (Alt+Q)
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('problem_detail', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-flag"></span> {{ _('View Problem') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_SUBMIT_PROBLEM) %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link{% if page_name == 'problem_submit' %} active{% endif %}" href="{{ reverse_url('problem_submit', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-send"></span> {{ _('Submit') }}
|
||||
</a></li>
|
||||
{% elif not handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link{% if page_name == 'problem_submit' %} active{% endif %}" href="javascript:showSignInDialog();">
|
||||
<span class="icon icon-send"></span> {{ _('Login to Submit') }}
|
||||
</a></li>
|
||||
{% else %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link disabled{% if page_name == 'problem_submit' %} active{% endif %}" href="javascript:;">
|
||||
<span class="icon icon-send"></span> {{ _('No Permission to Submit') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_VIEW_DISCUSSION) or handler.has_perm(vj4.model.builtin.PERM_VIEW_PROBLEM_SOLUTION) %}
|
||||
<li class="menu__seperator"></li>
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_VIEW_DISCUSSION) %}
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'discussion_node' or page_name == 'discussion_detail' %} active{% endif %}" href="{{ reverse_url('discussion_node_document_as_node', doc_type=pdoc['doc_type'], doc_id=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-comment--text"></span> {{ _('Discussions') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_VIEW_PROBLEM_SOLUTION) %}
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_solution' %} active{% endif %}" href="{{ reverse_url('problem_solution', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-comment--text"></span> {{ _('Solutions') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if page_name == 'problem_detail' and handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item"><a class="menu__link" name="problem-sidebar__copy-to" href="javascript:;">
|
||||
<span class="icon icon-copy"></span> {{ _('Copy Problem') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.own(pdoc, vj4.model.builtin.PERM_EDIT_PROBLEM_SELF) or handler.has_perm(vj4.model.builtin.PERM_EDIT_PROBLEM) %}
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="{{ reverse_url('problem_edit', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||
</a></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="{{ reverse_url('problem_settings', pid=pdoc['doc_id']) }}">
|
||||
<span class="icon icon-wrench"></span> {{ _('Settings') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Information') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<dl class="large horizontal">
|
||||
{% if pdoc['doc_id']|string|length < 10 %}
|
||||
<dt>{{ _('ID') }}</dt>
|
||||
<dd>{{ pdoc['doc_id'] }}</dd>
|
||||
{% endif %}
|
||||
{% if page_name != 'discussion_node' and page_name != 'discussion_detail' %}
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<dt>{{ _('Submission') }}</dt>
|
||||
<dd>
|
||||
{% if pdoc['psdoc']['status'] %}
|
||||
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[pdoc['psdoc']['status']] }}"></span>
|
||||
<a href="{{ reverse_url('record_detail', rid=pdoc['psdoc']['rid'], domain_id=pdoc['psdoc']['domain_id']) }}" class="record-status--text {{ vj4.constant.record.STATUS_CODES[pdoc['psdoc']['status']] }}">
|
||||
{{ vj4.constant.record.STATUS_TEXTS[pdoc['psdoc']['status']] }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ _('(None)') }}
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% if pdoc['ac_msg'] and pdoc['psdoc']['status'] == vj4.constant.record.STATUS_ACCEPTED %}
|
||||
<dt>{{ _('AC Message') }}</dt>
|
||||
<dd>{{ pdoc['ac_msg'] }}</dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<dt>{{ _('Difficulty') }}</dt>
|
||||
<dd>{{ pdoc['difficulty'] or _('(None)') }}</dd>
|
||||
<dt>{{ _('Category') }}</dt>
|
||||
<dd>
|
||||
{% if pdoc['category'] %}
|
||||
<span class="hasjs--hide" name="problem-sidebar__categories">
|
||||
{% for category in pdoc['category'] %}
|
||||
<a href="{{ reverse_url('problem_category', category=category) }}">{{ category }}</a>
|
||||
{% if loop.index < pdoc['category']|length %}
|
||||
{% if category in vj4.model.builtin.PROBLEM_CATEGORIES %}
|
||||
{{ _('problem-category-delim') }}
|
||||
{% else %}
|
||||
{{ _('problem-subcategory-delim') }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</span>
|
||||
<span class="nojs--hide">
|
||||
<a href="javascript:;" name="problem-sidebar__show-category">{{ _('page.problem_detail.sidebar.show_category') }}</a>
|
||||
</span>
|
||||
{% else %}
|
||||
{{ _('(None)') }}
|
||||
{% endif %}
|
||||
</dd>
|
||||
<dt>{{ _('Tags') }}</dt>
|
||||
<dd>
|
||||
{{ problem.render_problem_tags(pdoc, true) }}
|
||||
</dd>
|
||||
<dt>{{ _('# Submissions') }}</dt>
|
||||
<dd><a href="{{ reverse_url('record_main') }}?pid={{ pdoc['doc_id'] }}">{{ pdoc['num_submit'] }}</a></dd>
|
||||
{% if page_name != 'discussion_node' and page_name != 'discussion_detail' %}
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<dt>{{ _('# My Submissions') }}</dt>
|
||||
<dd><a href="{{ reverse_url('record_main') }}?pid={{ pdoc['doc_id'] }}&uid_or_name={{ handler.user['_id'] }}">{{ pdoc['psdoc']['num_submit']|default(0) }}</a></dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<dt>{{ _('Accepted') }}</dt>
|
||||
<dd>{{ pdoc['num_accept'] }}</dd>
|
||||
<dt>{{ _('Accepted Ratio') }}</dt>
|
||||
<dd>{% if pdoc['num_submit'] > 0 %}{{ (100 * pdoc['num_accept'] / pdoc['num_submit'])|round|int }}%{% else %}{{ _('?') }}{% endif %}</dd>
|
||||
{% if pdoc['num_be_copied'] %}
|
||||
<dt>{{ _('Be Copied') }}</dt>
|
||||
<dd>{{ pdoc['num_be_copied'] }}</dd>
|
||||
{% endif %}
|
||||
{% if pdoc['owner_uid'] != 0 %}
|
||||
<dt>{{ _('Uploaded By') }}</dt>
|
||||
<dd>{{ user.render_inline(owner_udoc, owner_dudoc, badge=false) }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
{% if page_name == 'problem_detail' and (tdocs or ctdocs) %}
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Related') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
{% if tdocs %}
|
||||
<p>{{ _('In following training plans') }}: </p>
|
||||
{% for tdoc in tdocs %}
|
||||
<p><a href="{{ reverse_url('training_detail', tid=tdoc['doc_id']) }}">{{ tdoc['title'] }}</a></p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if ctdocs %}
|
||||
<p>{{ _('In following contests') }}: </p>
|
||||
{% for tdoc in ctdocs %}
|
||||
<p><a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">{{ tdoc['title'] }}</a></p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if htdocs %}
|
||||
<p>{{ _('In following homework') }}: </p>
|
||||
{% for tdoc in htdocs %}
|
||||
<p><a href="{{ reverse_url('homework_detail', tid=tdoc['doc_id']) }}">{{ tdoc['title'] }}</a></p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="section__body" data-fragment-id="problem_stat">
|
||||
<p>{{ _('{0} problems').format(pcount) }}</p>
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"_id": 1,
|
||||
"title": "最初的最初 - A+B Problem",
|
||||
"require_nids": [],
|
||||
"pids": [1000, "56c52ade2fefd90539000005"]
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"title": "最初的进阶",
|
||||
"require_nids": [1],
|
||||
"pids": [1001, 1002]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,63 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
<div class="row">
|
||||
<div class="medium-8 columns">
|
||||
<label>
|
||||
{{ _('Copy from') }}
|
||||
<input name="src_domain_id" placeholder="{{ _('Domain ID') }}" class="textbox" autocomplete="off">
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-2 columns">
|
||||
<label>
|
||||
{{ _('Settings') }}
|
||||
<br>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="numeric_pid" value="on" checked>{{ _('Numeric PID') }}
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-2 columns">
|
||||
<label>
|
||||
<br>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="hidden" value="on">{{ _('Hidden') }}
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row"><div class="columns">
|
||||
<label>
|
||||
{{ _('Problem ID List') }}
|
||||
<textarea name="src_pids" class="textbox" style="height: 300px"></textarea>
|
||||
</label>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Copy') }}
|
||||
</button>
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
<div class="section side">
|
||||
<div class="section__body typo">
|
||||
<h2>{{ _('What\'s this?') }}</h2>
|
||||
<p>{{ _('With this feature, you can copy problems that you can view from a domain to some other domain. Their title, content, tags and categories will be copied. However, their test data are not copied directly.') }}</p>
|
||||
<h2>{{ _('About test data') }}</h2>
|
||||
<p>{{ _('Instead of copying the test data directly, the test data of the copied problems will be linked to the test data of the source problems (called the source test data). Thus, the copied problems can observe the changes in the source test data. The permissions of the test data of the copied problems follow the source test data, e.g., you still might not download them but the judges can. By uploading some new test data, the link will be broken and the new test data will be used.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,94 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div style="display: none" class="dialog__body--copy-to">
|
||||
<div>
|
||||
<div class="row"><div class="columns">
|
||||
<h1>{{ _('Copy Problem To') }}</h1>
|
||||
</div></div>
|
||||
<div class="row">
|
||||
<div class="medium-12 columns">
|
||||
<label>
|
||||
{{ _('Destination Domain') }}
|
||||
<input name="domain_id" placeholder="{{ _('Domain ID') }}" type="text" class="textbox" autocomplete="off" data-autofocus>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="medium-12 columns">
|
||||
<label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="numeric_pid" checked>{{ _('Numeric PID') }}
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="hidden">{{ _('Hidden') }}
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var Context = {{ {
|
||||
'problemId': pdoc['doc_id'],
|
||||
'socketUrl': '{}-conn'.format(reverse_url('problem_pretest', pid=pdoc['doc_id'])),
|
||||
'postPretestUrl': reverse_url('problem_pretest', pid=pdoc['doc_id']),
|
||||
'postSubmitUrl': reverse_url('problem_submit', pid=pdoc['doc_id']) if not tdoc else reverse_url('contest_detail_problem_submit' if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST else 'homework_detail_problem_submit', tid=tdoc['doc_id'], pid=pdoc['doc_id']),
|
||||
'getSubmissionsUrl': reverse_url('problem_submit', pid=pdoc['doc_id']) if not tdoc else reverse_url('contest_detail_problem_submit' if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST else 'homework_detail_problem_submit', tid=tdoc['doc_id'], pid=pdoc['doc_id']),
|
||||
'getRecordDetailUrl': reverse_url('record_detail', rid='{rid}'),
|
||||
'code_lang': handler.get_setting('code_lang'),
|
||||
'code_template': handler.get_code_template(),
|
||||
}|json|safe }};
|
||||
</script>
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="problem-content-container"><div class="problem-content" data-marker-enabled>
|
||||
<div class="section__header non-scratchpad--hide">
|
||||
<h1>{{ pdoc['title'] }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
{% if not pdoc['data'] %}
|
||||
<blockquote class="warn">
|
||||
<p>{{ _('No dataset at present.') }}</p>
|
||||
</blockquote>
|
||||
{% endif %}
|
||||
{% if pdoc['data'] is mapping %}
|
||||
<blockquote class="note">
|
||||
<p>{{ _('Test data comes from') }} <a href="{{ reverse_url('problem_detail', domain_id=pdoc['data']['domain'], pid=pdoc['data']['pid']) }}" target="_blank">{{ pdoc['data']['domain'] }}/{{ pdoc['data']['pid'] }}</a></p>
|
||||
</blockquote>
|
||||
{% endif %}
|
||||
{% if tdoc %}
|
||||
{% if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST %}
|
||||
{% if handler.is_done(tdoc) %}
|
||||
<blockquote class="note">
|
||||
<p>{{ _('You cannot submit for this problem because the contest is ended. You can click "Open in Problem Set" to view this problem in normal mode.') }}</p>
|
||||
</blockquote>
|
||||
{% endif %}{# handler.is_done(tdoc) #}
|
||||
{% else %}{# tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST #}
|
||||
{% if handler.is_homework_extended(tdoc) %}
|
||||
<blockquote class="note">
|
||||
<p>{{ _('The homework\'s deadline is due but in extension. You can still submit for this problem but your score will be penalized.') }}</p>
|
||||
</blockquote>
|
||||
{% elif handler.is_done(tdoc) %}{# handler.is_homework_extended(tdoc) #}
|
||||
<blockquote class="note">
|
||||
<p>{{ _('You cannot submit for this problem because the homework\'s deadline is due.') }}</p>
|
||||
</blockquote>
|
||||
{% endif %}{# handler.is_homework_extended(tdoc) #}
|
||||
{% endif %}{# tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST #}
|
||||
{% endif %}{# tdoc #}
|
||||
{{ pdoc['content']|markdown }}
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="scratchpad-container" style="display:none">
|
||||
<div style="display:none" class="loader-container"><div class="loader"></div></div>
|
||||
<div id="scratchpad" style="opacity:0"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,70 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
<div class="row">
|
||||
<div class="medium-8 columns">
|
||||
<label>
|
||||
{{ _('Title') }}
|
||||
<input name="title" placeholder="{{ _('title') }}" value="{{ pdoc['title']|default('') }}" class="textbox" autofocus>
|
||||
</label>
|
||||
</div>
|
||||
{% if page_name == 'problem_create' %}
|
||||
<div class="medium-2 columns">
|
||||
<label>
|
||||
{{ _('Settings') }}
|
||||
<br>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="numeric_pid" value="on" checked>{{ _('Numeric PID') }}
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-2 columns">
|
||||
<label>
|
||||
<br>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="hidden" value="on"{% if pdoc['hidden'] %} checked{% endif %}>{{ _('Hidden') }}
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="row"><div class="columns">
|
||||
<label>
|
||||
{{ _('Content') }}
|
||||
<textarea name="content" class="textbox" data-markdown style="height: 500px">{% if pdoc %}{{ pdoc['content'] }}{% else %}{% include 'partials/problem_default.md' %}{% endif %}</textarea>
|
||||
</label>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
{% if page_name == 'problem_edit' %}
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Update') }}
|
||||
</button>
|
||||
{% else %}
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Create') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% if page_name == 'problem_edit' %}
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{% include 'components/md_hint.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,85 @@
|
||||
{% import "components/record.html" as record with context %}
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<script>
|
||||
var Context = {{ {
|
||||
'getProblemUrlWithCategory': reverse_url('problem_category', category='{category}'),
|
||||
'getProblemUrlWithoutCategory': reverse_url('problem_main'),
|
||||
'currentCategory': category,
|
||||
}|json|safe }};
|
||||
</script>
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body no-padding">
|
||||
{% include "partials/problem_list.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Categories') }}</h1>
|
||||
</div>
|
||||
<div class="section__body"><ul class="group-list" data-widget-cf-container>
|
||||
{% for category, sub_categories in categories.items() %}
|
||||
<li class="group-list__item">
|
||||
<h2 class="section__title"><a href="{{ reverse_url('problem_category', category=category|urlencode) }}">{{ category }}</a></h2>
|
||||
{% if sub_categories|length > 0 %}
|
||||
<ol class="chip-list">
|
||||
{% for sub_category in sub_categories %}
|
||||
<li class="chip-list__item"><a class="typo-a" href="{{ reverse_url('problem_category', category=(category|urlencode + ',' + sub_category|urlencode)) }}">{{ sub_category }}</a></li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul></div>
|
||||
<div class="section__body">
|
||||
{% include "partials/problem_lucky.html" %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Search') }}</h1>
|
||||
</div>
|
||||
<form method="get" action="{{ reverse_url('problem_search') }}">
|
||||
<div class="section__body">
|
||||
<!-- TODO: replace with form_builder -->
|
||||
<label>
|
||||
<input name="q" type="text" class="textbox" value="" placeholder="1001">
|
||||
</label>
|
||||
<button type="submit" class="primary button">{{ _('Search') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_CREATE_PROBLEM) %}
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Create Problem') }}</h1>
|
||||
</div>
|
||||
<ol class="menu">
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('problem_create') }}" class="menu__link"><span class="icon icon-add"></span> {{ _('Create Problem') }}</a>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('problem_copy') }}" class="menu__link"><span class="icon icon-copy"></span> {{ _('Copy Problem') }}</a>
|
||||
</li>
|
||||
</ol>
|
||||
<div class="section__body">
|
||||
<div class="typo supplementary">
|
||||
<p>{{ _('You have permissions to create problems for this domain.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Statistics') }}</h1>
|
||||
</div>
|
||||
{% include "partials/problem_stat.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,73 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Dataset') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<iframe src="{{ reverse_url('problem_upload', pid=pdoc['doc_id']) }}" frameborder="0" style="width: 100%; height: 100px;"></iframe>
|
||||
<p class="help-text">{{ _('Hint') }}: <a href="{{ reverse_url('wiki_help') }}#upload">{{ _('Dataset Format') }}</a>, {{ _('An example of dataset') }}: <a href="https://github.com/vijos/jd4/blob/master/jd4/testdata/aplusb-legacy.zip?raw=true">{{ _('Download') }}</a></p>
|
||||
{% if pdoc and (handler.own(pdoc, vj4.model.builtin.PERM_READ_PROBLEM_DATA_SELF) or handler.has_perm(vj4.model.builtin.PERM_READ_PROBLEM_DATA) or handler.has_priv(vj4.model.builtin.PRIV_READ_PROBLEM_DATA)) %}
|
||||
<p><a href="{{ reverse_url('problem_data', pid=pdoc['doc_id']) }}" class="expanded button">{{ _('Download Dataset') }}</a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Settings') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
{{ form.form_checkbox(label='Hidden', help_text='Note: Problem title may not be hidden.', name='hidden', value=pdoc['hidden']) }}
|
||||
{{ form.form_text(columns=12, label='Category', help_text='Format: category 1, sub category 1.1, sub category 1.2, ..., sub category 1.x, ..., category n, sub category n.1, sub category n.2, ..., sub category n.m, ...', name='category', value=pdoc['category']|join(', ')) }}
|
||||
{{ form.form_text(columns=12, label='Tags', help_text='Splitted by \', \'.', name='tag', value=pdoc['tag']|join(', ')) }}
|
||||
{{ form.form_text(columns=12, label='AC Message', help_text='This message will be presented to those whose submissions are accepted.', name='ac_msg', value=(pdoc['ac_msg'] or '' )) }}
|
||||
<div class="row">
|
||||
{{ form.form_select(columns=4, label='Difficulty', name='difficulty_setting', options=vj4.model.adaptor.problem.SETTING_DIFFICULTY_RANGE.items(), value=pdoc['difficulty_setting']|default(0), row=false) }}
|
||||
{{ form.form_text(columns=4, label='Evaluated difficulty', help_text='Effects only when Difficulty is not \'Use algorithm calculated\'.', name='difficulty_admin', placeholder='9', value=pdoc['difficulty_admin'] or '', row=False) }}
|
||||
<div class="medium-4 columns">
|
||||
<p class="help-text">{{ _('Difficulty displayed') }}: {{ pdoc['difficulty'] or _('(None)') }}</p>
|
||||
<p class="help-text">{{ _('Difficulty by algorithm') }}: {{ pdoc['difficulty_algo'] or _('(None)') }}</p>
|
||||
<p class="help-text">{{ _('Difficulty by admin') }}: {{ pdoc['difficulty_admin'] or _('(None)') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Update') }}
|
||||
</button>
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Categories') }} ({{ _('click to add') }})</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<!-- TODO: chip -->
|
||||
{% for category, sub_categories in categories.items() %}
|
||||
<div>
|
||||
<h2 class="section__title"><a class="category-a" href="javascript:;" data-category="{{ category }}">{{ category }}</a></h2>
|
||||
<ol>
|
||||
{% for sub_category in sub_categories %}
|
||||
<li><a class="category-a typo-a" href="javascript:;" data-category="{{ sub_category }}">{{ sub_category }}</a></li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,49 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/comments.html" as comments with context %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('{0} solutions').format(pscount) }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
{{ comments.render(
|
||||
view = 'solution',
|
||||
docs = psdocs,
|
||||
udict = udict,
|
||||
comment_ref = 'psid',
|
||||
reply_ref = 'psrid',
|
||||
comment_placeholder = 'Write Your Solution',
|
||||
comment_post_op = 'submit',
|
||||
comment_edit_op = 'edit_solution',
|
||||
comment_post_text = 'Share',
|
||||
reply_post_op = 'reply',
|
||||
reply_edit_op = 'edit_reply',
|
||||
comment_delete_op = 'delete_solution',
|
||||
reply_delete_op = 'delete_reply',
|
||||
comment_post_perm = vj4.model.builtin.PERM_CREATE_PROBLEM_SOLUTION,
|
||||
comment_edit_perm = vj4.model.builtin.PERM_EDIT_PROBLEM_SOLUTION,
|
||||
comment_edit_self_perm = vj4.model.builtin.PERM_EDIT_PROBLEM_SOLUTION_SELF,
|
||||
comment_delete_perm = vj4.model.builtin.PERM_DELETE_PROBLEM_SOLUTION,
|
||||
comment_delete_self_perm = vj4.model.builtin.PERM_DELETE_PROBLEM_SOLUTION_SELF,
|
||||
reply_post_perm = vj4.model.builtin.PERM_REPLY_PROBLEM_SOLUTION,
|
||||
reply_edit_perm = vj4.model.builtin.PERM_EDIT_PROBLEM_SOLUTION_REPLY,
|
||||
reply_edit_self_perm = vj4.model.builtin.PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF,
|
||||
reply_delete_perm = vj4.model.builtin.PERM_DELETE_PROBLEM_SOLUTION_REPLY,
|
||||
reply_delete_self_perm = vj4.model.builtin.PERM_DELETE_PROBLEM_SOLUTION_REPLY_SELF
|
||||
) }}
|
||||
{{ paginator.render(page, pcount) }}
|
||||
{% if drcount == 0 %}
|
||||
{{ nothing.render('No solutions so far...') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% with owner_udoc=udict[pdoc['owner_uid']], owner_dudoc=dudict[pdoc['owner_uid']] %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,20 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Submission Statistics') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
{{ _('Swx Template') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,64 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
{% if not tdoc or rdocs %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Recent {0} Records').format(10) }}</h1>
|
||||
</div>
|
||||
<div class="section__body no-padding">
|
||||
{% if not rdocs %}
|
||||
{{ nothing.render('You have not submitted any solutions for this problem') }}
|
||||
{% else %}
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--status">
|
||||
<col class="col--pretest">
|
||||
<col class="col--memory">
|
||||
<col class="col--time">
|
||||
<col class="col--submit-at">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--status record-status--border">{{ _('Status') }}</th>
|
||||
<th class="col--pretest">{{ _('Pretest?') }}</th>
|
||||
<th class="col--memory">{{ _('Peak Memory') }}</th>
|
||||
<th class="col--time">{{ _('Total Time') }}</th>
|
||||
<th class="col--submit-at">{{ _('Submit At') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for rdoc in rdocs %}
|
||||
{% include 'problem_submit_tr.html' %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Submit to Judge') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
{{ form.form_select(label='Code language', options=vj4.constant.language.LANG_TEXTS.items(), name='lang', value=handler.get_setting('code_lang')) }}
|
||||
{{ form.form_textarea(label='Code', columns=12, name='code', extra_class='monospace', autofocus=true) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<input type="submit" class="rounded primary button" value="{{ _('Submit') }}">
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,18 @@
|
||||
{% import "components/record.html" as record with context %}
|
||||
<tr data-rid="{{ rdoc['_id'] }}">
|
||||
{{ record.render_status_td(rdoc) }}
|
||||
<td class="col--pretest">
|
||||
{% if rdoc['type'] == vj4.constant.record.TYPE_PRETEST %}
|
||||
{{ _('Yes') }}
|
||||
{% else %}
|
||||
{{ _('No') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="col--memory">
|
||||
{{ (rdoc['memory_kb'] / 1000)|round(0, 'ceil')|int }} MB
|
||||
</td>
|
||||
<td class="col--time">
|
||||
{{ (rdoc['time_ms'] / 1000)|round(1) }}s
|
||||
</td>
|
||||
<td class="col--submit-at">{{ datetime_span(rdoc['_id'].generation_time) }}</td>
|
||||
</tr>
|
||||
@@ -0,0 +1,17 @@
|
||||
{% extends 'layout/simple.html' %}
|
||||
{% block body %}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% if pdoc['data'] is mapping %}
|
||||
<p><b>{{ _('Current dataset comes from') }} <a href="{{ reverse_url('problem_detail', domain_id=pdoc['data']['domain'], pid=pdoc['data']['pid']) }}" target="_blank">{{ pdoc['data']['domain'] }}/{{ pdoc['data']['pid'] }}</a></b></p>
|
||||
{% else %}
|
||||
<p>{{ _('Current dataset: {0}').format(pdoc['data']|default(_('(None)'))) }}</p>
|
||||
<p>{{ _('MD5: {0}').format(md5|default(_('(None)'))) }}</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
{{ _('New dataset') }}:
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<input type="file" name="file">
|
||||
<input type="submit" value="{{ _('Upload') }}" class="rounded primary button">
|
||||
</p>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,112 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
{% block content %}
|
||||
<script>
|
||||
var Context = {{ {
|
||||
'socketUrl': socket_url,
|
||||
}|json|safe }};
|
||||
</script>
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
{% if show_status %}
|
||||
{% include 'record_detail_status.html' %}
|
||||
{% endif %}
|
||||
{% if rdoc['code'] %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Code') }}</h1>
|
||||
</div>
|
||||
<div class="section__body" data-syntax-hl-show-line-number>
|
||||
<pre><code class="language-{{ vj4.constant.language.LANG_HIGHLIGHT_ID[rdoc['lang']] }}">{{ rdoc['code'] }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Information') }}</h1>
|
||||
</div>
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_REJUDGE) %}
|
||||
<div class="section__body no-padding">
|
||||
<ol class="menu">
|
||||
<li class="menu__item">
|
||||
<form method="post" action="{{ reverse_url('record_rejudge', rid=rdoc['_id']) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="menu__link">
|
||||
<span class="icon icon-refresh"></span> {{ _('Rejudge') }}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<form method="post" action="{{ reverse_url('judge_score', rid=rdoc['_id']) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<input type="hidden" name="score" value="0">
|
||||
<input type="hidden" name="message" value="{{ _('score canceled') }}">
|
||||
<button type="submit" class="menu__link">
|
||||
<span class="icon icon-close"></span> {{ _('Cancel Score') }}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section__body typo">
|
||||
<dl class="large horizontal">
|
||||
<dt>{{ _('Submit By') }}</dt>
|
||||
<dd>{{ user.render_inline(udoc, dudoc, modbadge=false) }}</dd>
|
||||
<dt>{{ _('Type') }}</dt>
|
||||
<dd>{{ _(vj4.constant.record.TYPE_TEXTS[rdoc['type']]) }}</dd>
|
||||
{% if pdoc %}
|
||||
<dt>{{ _('Problem') }}</dt>
|
||||
<dd>
|
||||
{{ problem.render_problem_title(pdoc, tdoc, show_tags=false, show_invisible_flag=false, rp=none) }}
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% if tdoc %}
|
||||
{% if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST %}
|
||||
<dt>{{ _('Contest') }}</dt>
|
||||
<dd>
|
||||
<a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">{{ tdoc['title'] }}</a>
|
||||
</dd>
|
||||
{% else %}{# tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST #}
|
||||
<dt>{{ _('Homework') }}</dt>
|
||||
<dd>
|
||||
<a href="{{ reverse_url('homework_detail', tid=tdoc['doc_id']) }}">{{ tdoc['title'] }}</a>
|
||||
</dd>
|
||||
{% endif %}{# tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST #}
|
||||
{% endif %}{# tdoc #}
|
||||
{% if rdoc['type'] == vj4.constant.record.TYPE_PRETEST and (handler.own(rdoc, priv=vj4.model.builtin.PRIV_READ_PRETEST_DATA_SELF, field='uid') or handler.has_priv(vj4.model.builtin.PRIV_READ_PRETEST_DATA)) %}
|
||||
<dt>{{ _('Pretest Data') }}</dt>
|
||||
<dd><a href="{{ reverse_url('record_pretest_data', rid=rdoc['_id']) }}"><span class="icon icon-download"></span> {{ _('Download') }}</a></dd>
|
||||
{% elif rdoc['type'] == vj4.constant.record.TYPE_SUBMISSION and pdoc and (handler.own(pdoc, vj4.model.builtin.PERM_READ_PROBLEM_DATA_SELF) or handler.has_perm(vj4.model.builtin.PERM_READ_PROBLEM_DATA) or handler.has_priv(vj4.model.builtin.PRIV_READ_PROBLEM_DATA)) %}
|
||||
<dt>{{ _('Problem Data') }}</dt>
|
||||
<dd><a href="{{ reverse_url('problem_data', pid=pdoc['doc_id']) }}"><span class="icon icon-download"></span> {{ _('Download') }}</a></dd>
|
||||
{% endif %}
|
||||
<dt>{{ _('Language') }}</dt>
|
||||
<dd>
|
||||
{{ vj4.constant.language.LANG_TEXTS[rdoc['lang']] }}
|
||||
</dd>
|
||||
<dt>
|
||||
{{ _('Submit At') }}
|
||||
</dt>
|
||||
<dd>
|
||||
{{ datetime_span(rdoc['_id'].generation_time) }}
|
||||
</dd>
|
||||
{% if rdoc['judge_at'] %}
|
||||
<dt>{{ _('Judged At') }}</dt>
|
||||
<dd>{{ datetime_span(rdoc['judge_at']) }}</dd>
|
||||
{% endif %}
|
||||
{% if judge_udoc %}
|
||||
<dt>{{ _('Judged By') }}</dt>
|
||||
<dd>{{ user.render_inline(judge_udoc, badge=false) }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
{% if show_status %}
|
||||
{% include 'record_detail_summary.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,57 @@
|
||||
<div class="section visible" id="status">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">
|
||||
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}"></span>
|
||||
<span class="record-status--text {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}">
|
||||
{{ vj4.constant.record.STATUS_TEXTS[rdoc['status']] }}
|
||||
</span>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<pre class="compiler-text">{{ rdoc['compiler_texts']|join('\n') }}</pre>
|
||||
</div>
|
||||
{% if rdoc['judge_texts'] %}
|
||||
<div class="section__body">
|
||||
<pre class="judge-text">{{ rdoc['judge_texts']|join('\n') }}</pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if rdoc['cases'] %}
|
||||
<div class="section__body no-padding">
|
||||
<table class="data-table record_detail__table">
|
||||
<colgroup>
|
||||
<col class="col--case">
|
||||
<col class="col--status">
|
||||
<col class="col--time">
|
||||
<col class="col--memory">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--case record-status--border">#</th>
|
||||
<th class="col--status">{{ _('Status') }}</th>
|
||||
<th class="col--time">{{ _('Time Cost') }}</th>
|
||||
<th class="col--memory">{{ _('Memory Cost') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for rcdoc in rdoc['cases'] %}
|
||||
<tr>
|
||||
<td class="col--case record-status--border {{ vj4.constant.record.STATUS_CODES[rcdoc['status']] }}">
|
||||
#{{ loop.index }}
|
||||
</td>
|
||||
<td class="col--status">
|
||||
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[rcdoc['status']] }}"></span>
|
||||
<span class="record-status--text {{ vj4.constant.record.STATUS_CODES[rcdoc['status']] }}">
|
||||
{{ vj4.constant.record.STATUS_TEXTS[rcdoc['status']] }}
|
||||
</span>
|
||||
<span>{{ rcdoc['judge_text'] }}</span>
|
||||
<a class="tool-button" href="{{ reverse_url('wiki_help') }}#status"><span class="icon icon-help"></span></a>
|
||||
</td>
|
||||
<td class="col--time">{% if rcdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rcdoc['time_ms'] }}ms</td>
|
||||
<td class="col--memory">{% if rcdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rcdoc['memory_kb']|format_size(1024) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,10 @@
|
||||
<dl class="large horizontal" id="summary">
|
||||
{% if rdoc['score'] is defined %}
|
||||
<dt>{{ _('Score') }}</dt>
|
||||
<dd>{{ rdoc['score'] }}</dd>
|
||||
{% endif %}
|
||||
<dt>{{ _('Total Time') }}</dt>
|
||||
<dd>{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc['time_ms'] }}ms</dd>
|
||||
<dt>{{ _('Peak Memory') }}</dt>
|
||||
<dd>{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc['memory_kb']|format_size(1024) }}</dd>
|
||||
</dl>
|
||||
@@ -0,0 +1,110 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<script>
|
||||
var Context = {{ {
|
||||
'socketUrl': socket_url,
|
||||
}|json|safe }};
|
||||
</script>
|
||||
<div class="row">
|
||||
<div class="medium-12 columns">
|
||||
<form method="get">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Filter') }}</h1>
|
||||
<div class="section__tools">
|
||||
<button type="submit" class="primary button"><span class="icon icon-filter"></span> {{ _('Filter') }}</button>
|
||||
<a href="{{ reverse_url('record_main') }}" class="button">{{ _('Reset') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<div class="row">
|
||||
<!-- TODO: replace with form_builder -->
|
||||
<div class="medium-4 columns">
|
||||
<label class="filter-user">
|
||||
{{ _('By Username / UID') }}
|
||||
<input name="uid_or_name" type="text" class="textbox" value="{{ filter_uid_or_name }}" autocomplete="off" data-autofocus>
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-4 columns">
|
||||
<label>
|
||||
{{ _('By Problem') }}
|
||||
<input name="pid" type="text" class="textbox" value="{{ filter_pid }}">
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-4 columns">
|
||||
<label>
|
||||
{{ _('By Contest') }}
|
||||
<input name="tid" type="text" class="textbox" value="{{ filter_tid }}">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="section">
|
||||
<div class="section__body no-padding">
|
||||
{% if not rdocs %}
|
||||
{% if not filter_uid_or_name and not filter_pid and not filter_tid %}
|
||||
{{ nothing.render('Oh, there is no task in the queue!') }}
|
||||
{% else %}
|
||||
{{ nothing.render('Oh, there is no task that matches the filter!') }}
|
||||
{% endif%}
|
||||
{% else %}
|
||||
<table class="data-table record_main__table">
|
||||
<colgroup>
|
||||
<col class="col--status">
|
||||
<col class="col--problem">
|
||||
<col class="col--submit-by">
|
||||
<col class="col--time">
|
||||
<col class="col--memory">
|
||||
<col class="col--lang">
|
||||
<col class="col--submit-at">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--status record-status--border">{{ _('Status') }}</th>
|
||||
<th class="col--problem">{{ _('Problem') }}</th>
|
||||
<th class="col--submit-by">{{ _('Submit By') }}</th>
|
||||
<th class="col--time">{{ _('Time') }}</th>
|
||||
<th class="col--memory">{{ _('Memory') }}</th>
|
||||
<th class="col--lang">{{ _('Language') }}</th>
|
||||
<th class="col--submit-at">{{ _('Submit At') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for rdoc in rdocs %}
|
||||
{% with udoc = udict[rdoc['uid']], dudoc = dudict[rdoc['uid']], pdoc = pdict[(rdoc['domain_id'], rdoc['pid'])] %}
|
||||
{% include 'record_main_tr.html' %}
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_VIEW_JUDGE_STATISTICS) %}
|
||||
<ul class="pager">
|
||||
<li>
|
||||
<a class="pager__item next link" href="?start={{ rdocs[-1]['_id'] }}&{{ query_string }}">{{ _('pager_next') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if statistics %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Statistics') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<dl class="large horizontal">
|
||||
<dt>{{ _('Day') }}</dt><dd>{{ statistics['day'] }}</dd>
|
||||
<dt>{{ _('Week') }}</dt><dd>{{ statistics['week'] }}</dd>
|
||||
<dt>{{ _('Month') }}</dt><dd>{{ statistics['month'] }}</dd>
|
||||
<dt>{{ _('Year') }}</dt><dd>{{ statistics['year'] }}</dd>
|
||||
<dt>{{ _('Total') }}</dt><dd>{{ statistics['total'] }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,37 @@
|
||||
{% import "components/record.html" as record with context %}
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
<tr data-rid="{{ rdoc['_id'] }}">
|
||||
{{ record.render_status_td(rdoc) }}
|
||||
<td class="col--problem col--problem-name">
|
||||
{% if (rdoc['domain_id'] == handler.domain_id and handler.has_perm(vj4.model.builtin.PERM_REJUDGE)) or handler.has_priv(vj4.model.builtin.PRIV_REJUDGE) %}
|
||||
<form class="form--inline" method="post" action="{{ reverse_url('record_rejudge', rid=rdoc['_id']) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="link text-maroon lighter">
|
||||
<span class="icon icon-refresh"></span>
|
||||
{{ _('Rejudge') }}
|
||||
</button> |
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if rdoc['type'] == vj4.constant.record.TYPE_PRETEST %}
|
||||
({{ _('Pretest') }})
|
||||
{% endif %}
|
||||
{% if pdoc and (not pdoc['hidden'] or (pdoc['domain_id'] == handler.domain_id and handler.has_perm(vj4.model.builtin.PERM_VIEW_PROBLEM_HIDDEN))) %}
|
||||
{{ problem.render_problem_title(pdoc, show_tags=false) }}
|
||||
{% else %}
|
||||
*
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="col--submit-by">
|
||||
<a href="{{ reverse_url('user_detail', uid=rdoc['uid']) }}">
|
||||
{% if dudoc['display_name'] %}
|
||||
{{ dudoc['display_name'] }} ({{ udoc['uname'] }})
|
||||
{% else %}
|
||||
{{ udoc['uname'] }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</td>
|
||||
<td class="col--time">{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc['time_ms'] }}ms</td>
|
||||
<td class="col--memory">{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc['memory_kb']|format_size(1024) }}</td>
|
||||
<td class="col--lang">{{ vj4.constant.language.LANG_TEXTS[rdoc['lang']] }}</td>
|
||||
<td class="col--submit-at">{{ datetime_span(rdoc['_id'].generation_time) }}</td>
|
||||
</tr>
|
||||
@@ -0,0 +1,205 @@
|
||||
{% import "components/record.html" as record with context %}
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body typo">
|
||||
{{ tdoc['content'] }}
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
{{ tdoc['desc']|default('')|markdown }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
{% if not tsdoc['enroll'] %}
|
||||
<div class="section__body">
|
||||
<blockquote class="typo warn">
|
||||
<p>{{ _('page.training_detail.invalid_when_not_enrolled') }}</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for node in tdoc['dag'] %}
|
||||
<div class="training__section {% if nsdict[node['_id']]['is_done'] %}done{% elif nsdict[node['_id']]['is_progress'] %}progress{% elif nsdict[node['_id']]['is_open'] %}open{% else %}invalid{% endif %} {% if nsdict[node['_id']]['is_progress'] or nsdict[node['_id']]['is_open'] %}expanded{% else %}collapsed{% endif %}">
|
||||
<div class="section__header clearfix">
|
||||
<div class="float-left">
|
||||
<h1 class="section__title">{{ _('Section') }} {{ node['_id'] }}. {{ node['title'] }}</h1>
|
||||
</div>
|
||||
<div class="float-right">
|
||||
<h1 class="section__title training-section-status--text {% if nsdict[node['_id']]['is_done'] %}done{% elif nsdict[node['_id']]['is_progress'] %}progress{% elif nsdict[node['_id']]['is_open'] %}open{% else %}invalid{% endif %}">
|
||||
<span class="icon training-section-status--icon {% if nsdict[node['_id']]['is_done'] %}done{% elif nsdict[node['_id']]['is_progress'] %}progress{% elif nsdict[node['_id']]['is_open'] %}open{% else %}invalid{% endif %}"></span>
|
||||
{% if nsdict[node['_id']]['is_done'] %}
|
||||
{{ _('Completed') }}
|
||||
{% elif nsdict[node['_id']]['is_progress'] %}
|
||||
{{ _('In Progress') }}
|
||||
{% elif nsdict[node['_id']]['is_open'] %}
|
||||
{{ _('Open') }}
|
||||
{% else %}
|
||||
{{ _('Invalid') }}
|
||||
{% endif %}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<ul class="supplementary dot list">
|
||||
<li>
|
||||
<a href="javascript:;" name="training__section__expand" class="expanded--hidden"><span class="icon icon-expand_more"></span> {{ _('expand') }}</a>
|
||||
<a href="javascript:;" name="training__section__collapse" class="collapsed--hidden"><span class="icon icon-expand_less"></span> {{ _('collapse') }}</a>
|
||||
</li>
|
||||
<!--
|
||||
TODO(twd2): twd2 todo
|
||||
<li>
|
||||
递交了 ? 次完成该章节 (TOP ?%)
|
||||
</li>
|
||||
<li>
|
||||
第 ? 个完成该章节 (总计 ? 用户完成)
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
</div>
|
||||
<div class="training__section__detail">
|
||||
{% if nsdict[node['_id']]['is_invalid'] %}
|
||||
<div class="section__body">
|
||||
<blockquote class="typo note">
|
||||
<p>{{ _('This section cannot be challenged at present, so please complete the following sections first') }}:</p>
|
||||
<ul>
|
||||
{% for nid in node['require_nids'] %}
|
||||
<li>{{ _('Section') }} {{ _(nid) }}. {{ ndict[nid]['title'] }} ({{ _('Completed') }} {{ nsdict[nid]['progress'] }}%)</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</blockquote>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if node['content'] %}
|
||||
<div class="section__body typo">
|
||||
{{ node['content']|markdown }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section__body no-padding training__problems">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<col class="col--status">
|
||||
{% endif %}
|
||||
<col class="col--name">
|
||||
<col class="col--submit_n">
|
||||
<col class="col--ac_rate">
|
||||
<col class="col--difficulty">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<th class="col--status record-status--border">{{ _('Status') }}</th>
|
||||
{% endif %}
|
||||
<th class="col--name">{{ _('Problem') }}</th>
|
||||
<th class="col--submit_n">{{ _('Submit') }}</th>
|
||||
<th class="col--ac_rate">% {{ _('AC') }}</th>
|
||||
<th class="col--difficulty">{{ _('Difficulty') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pid in node['pids'] %}
|
||||
{% if pid in pdict %}
|
||||
{% with pdoc=pdict[pid], psdoc=psdict[pid] %}
|
||||
<tr>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
{% if psdoc['rid'] %}
|
||||
{{ record.render_status_td(psdoc, rid_key='rid') }}
|
||||
{% else %}
|
||||
<td class="col--status record-status--border"></td>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<td class="col--name col--problem-name">
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<form class="form--inline" action="{{ reverse_url('problem_main') }}" method="post">
|
||||
<input type="hidden" name="pid" value="{{ pdoc['doc_id'] }}">
|
||||
<input type="hidden" name="operation" value="{% if not psdoc['star'] %}star{% else %}unstar{% endif %}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button class="star{% if psdoc['star'] %} activated{% endif %}" type="submit">
|
||||
<span class="starred--hide"><span class="icon icon-star--outline" data-tooltip="{{ _('Star') }}"></span></span>
|
||||
<span class="starred--show"><span class="icon icon-star" data-tooltip="{{ _('Unstar') }}"></span></span>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{{ problem.render_problem_title(
|
||||
pdoc,
|
||||
invalid=not tsdoc['enroll'],
|
||||
show_tags=false,
|
||||
rp=vj4.job.rp.get_rp_expect(pdoc) if (not psdoc or psdoc['status'] != vj4.constant.record.STATUS_ACCEPTED) else none
|
||||
) }}
|
||||
</td>
|
||||
<td class="col--submit_n">{{ pdoc['num_submit'] }}</td>
|
||||
<td class="col--ac_rate">{{ (100 * pdoc['num_accept'] / pdoc['num_submit'])|round|int if pdoc['num_submit'] > 0 else _('?') }}</td>
|
||||
<td class="col--difficulty">{{ pdoc['difficulty'] or _('(None)') }}</td>
|
||||
</tr>
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{% with pdoc = {'domain_id': handler.domain_id, 'doc_id': pid, 'hidden': true, 'title': '*'} %}
|
||||
<tr>
|
||||
<td class="col--status record-status--border">
|
||||
</td>
|
||||
<td class="col--name col--problem-name">
|
||||
{{ problem.render_problem_title(pdoc, invalid=true) }}
|
||||
</td>
|
||||
<td class="col--submit_n">*</td>
|
||||
<td class="col--ac_rate">*</td>
|
||||
<td class="col--difficulty">*</td>
|
||||
</tr>
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="section__body"> <!-- space placeholder --></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
<div class="section side">
|
||||
<div>
|
||||
<ol class="menu">
|
||||
{% if not tsdoc['enroll'] and handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<li class="menu__item">
|
||||
<form action="" method="POST">
|
||||
<input type="hidden" name="operation" value="enroll">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button class="menu__link" type="submit">
|
||||
<span class="icon icon-add"></span> {{ _('Enroll Training') }}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if handler.own(tdoc, vj4.model.builtin.PERM_EDIT_TRAINING_SELF) or handler.has_perm(vj4.model.builtin.PERM_EDIT_TRAINING) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('training_edit', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('wiki_help') }}#training">
|
||||
<span class="icon icon-help"></span> {{ _('Help') }}
|
||||
</a></li>
|
||||
<li class="menu__seperator"></li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<dl class="large horizontal">
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<dt>{{ _('Status') }}</dt><dd>{% if tsdoc['enroll'] %}{{ _('Completed' if tsdoc['done'] else 'In Progress') }}{% else %}{{ _('Not Enrolled') }}{% endif %}</dd>
|
||||
{% endif %}
|
||||
{% if tsdoc['enroll'] %}
|
||||
<dt>{{ _('Progress') }}</dt><dd>{{ _('Completed') }} {{ (100 * tsdoc['done_pids']|length / pids|length)|round|int }}%</dd>
|
||||
{% endif %}
|
||||
<dt>{{ _('Enrollees') }}</dt><dd>{{ tdoc['enroll']|default(0) }}</dd>
|
||||
<dt>{{ _('Created By') }}</dt>
|
||||
<dd>{{ user.render_inline(owner_udoc, owner_dudoc, badge=false) }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,58 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
<div class="row">
|
||||
<div class="medium-5 columns">
|
||||
<label>
|
||||
{{ _('Title') }}
|
||||
<input name="title" placeholder="{{ _('title') }}" value="{{ tdoc['title']|default('') }}" class="textbox" autofocus>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row"><div class="columns">
|
||||
<label>
|
||||
{{ _('Introduce') }}
|
||||
<textarea name="content" class="textbox">{{ tdoc['content']|default('') }}</textarea>
|
||||
<p class="help-text">{{ _('Introduce must not exceed 500 characters and it will be shown in the list view.') }}</p>
|
||||
</label>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<label>
|
||||
{{ _('Description') }}
|
||||
<textarea name="desc" class="textbox" data-markdown style="height: 200px">{{ tdoc['desc']|default('') }}</textarea>
|
||||
</label>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<label>
|
||||
{{ _('Plan') }}
|
||||
<textarea name="dag" class="textbox" style="height: 500px">{% if tdoc %}{{ dag }}{% else %}{% include 'partials/training_default.json' %}{% endif %}</textarea>
|
||||
</label>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
{% if page_name == 'training_edit' %}
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Update') }}
|
||||
</button>
|
||||
{% else %}
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Create') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
<button type="button" class="rounded button" onclick="window.history.go(-1)">
|
||||
{{ _('Cancel') }}
|
||||
</button>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% include 'components/md_hint.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,98 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="large-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('All Training Plans') }}</h1>
|
||||
</div>
|
||||
{% if not tdocs %}
|
||||
{{ nothing.render('Sorry, there is no training plan.') }}
|
||||
{% else %}
|
||||
<ol class="section__list all primary training__list">
|
||||
{% for tdoc in tdocs %}
|
||||
<li class="section__list__item training__item">
|
||||
<div class="media">
|
||||
<div class="media__left middle">
|
||||
<div class="training__participants numbox">
|
||||
<div class="numbox__num large">{{ tdoc['enroll']|default(0) }}</div>
|
||||
<div class="numbox__text">{{ _('Enrolled') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body middle">
|
||||
<h1 class="training__title"><a href="{{ reverse_url('training_detail', tid=tdoc['doc_id']) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<div class="training__intro typo">
|
||||
<p>{{ tdoc['content'] }}</p>
|
||||
</div>
|
||||
<ul class="supplementary list training__progress">
|
||||
<li>
|
||||
<span class="icon icon-flag text-blue"></span> {{ _('{0} sections').format(tdoc['dag']|length) }}, {{ _('{0} problems').format(handler.get_pids(tdoc)|length) }}
|
||||
</li>
|
||||
<li>
|
||||
{% if tsdict[tdoc['doc_id']]['enroll'] %}
|
||||
{% if not tsdict[tdoc['doc_id']]['done'] %}
|
||||
<span class="icon training-status--icon progress"></span>
|
||||
<span class="training-status--text progress">{{ _('Completed') }} {{ (100 * tsdict[tdoc['doc_id']]['done_pids']|length / handler.get_pids(tdoc)|length)|round|int }}%</span>
|
||||
{% else %}
|
||||
<span class="icon training-status--icon done"></span>
|
||||
<span class="training-status--text done">{{ _('Completed') }} 100%</span>
|
||||
{% endif %}
|
||||
{% elif handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<span class="icon training-status--icon outside"></span> <span class="training-status--text outside">{{ _('Not Enrolled') }}</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
{{ paginator.render(page, tpcount, add_qs=qs) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="large-3 columns">
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_USER_PROFILE) %}
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Enrolled') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<ol class="my secondary training__list">
|
||||
{% for tsdoc in tsdict.values() %}
|
||||
{% if tsdoc['enroll'] %}
|
||||
<li class="training__item"><div class="media">
|
||||
<div class="media__left">
|
||||
<span class="icon training-status--icon {% if tsdoc['done'] %}done{% else %}progress{% endif %}"></span>
|
||||
</div>
|
||||
<div class="media__body">
|
||||
<h1 class="training__title"><a href="{{ reverse_url('training_detail', tid=tsdoc['doc_id']) }}" data-emoji-enabled>{{ tdict[tsdoc['doc_id']]['title'] }}</a></h1>
|
||||
<div class="supplementary training__progress"><div class="training__progress-bar"><div class="training__progress-track" style="width:{{ (100 * tsdoc['done_pids']|length / handler.get_pids(tdict[tsdoc['doc_id']])|length)|round|int }}%;"></div></div> {{ _('Complete') }} {{ (100 * tsdoc['done_pids']|length / handler.get_pids(tdict[tsdoc['doc_id']])|length)|round|int }}%</div>
|
||||
</div>
|
||||
</div></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if handler.has_perm(vj4.model.builtin.PERM_CREATE_TRAINING) %}
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Create Training Plan') }}</h1>
|
||||
</div>
|
||||
<ol class="menu">
|
||||
<li class="menu__item">
|
||||
<a href="{{ reverse_url('training_create') }}" class="menu__link"><span class="icon icon-add"></span> {{ _('New Training Plan') }}</a>
|
||||
</li>
|
||||
</ol>
|
||||
<div class="section__body">
|
||||
<div class="typo supplementary">
|
||||
<p>{{ _('You can create your own training plans and share with others.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% extends "layout/mail.html" %}
|
||||
{% block title %}{{ _('Change Email') }}{% endblock %}
|
||||
{% block content %}
|
||||
<p>{{ _('Hello, {0}! You can click following link to active your new email of your Vijos account:').format(uname) }}</p>
|
||||
<p><a href="{{ url_prefix }}{{ url }}">{{ url_prefix }}{{ url }}</a></p>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% extends "layout/immersive.html" %}
|
||||
{% block content %}
|
||||
<div class="immersive--content immersive--center">
|
||||
<h1>{{ _('New Email') }}</h1>
|
||||
<div class="text-center">
|
||||
{{ _('Confirmation mail has been sent to your new email.') }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user