mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 17:38:19 +08:00
ui-default: init
将ui-default合并至主存储库便于维护
This commit is contained in:
1 parent
6317c9057f
commit
5faa54c7ca
564 files changed
+23083
-14
No files matched your search
@@ -0,0 +1,122 @@
|
||||
{% extends "layout/wiki_base.html" %}
|
||||
{% block wiki_content %}
|
||||
<div class="section" data-heading-extract-to="#menu-item-wiki_about">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="about" data-heading>{{ _('About Hydro') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<p><a href="https://hydro.js.org">Hydro</a> 致力于为用户提供安全、完善、开放的在线评测及题目交流等服务。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" data-heading-extract-to="#menu-item-wiki_about">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="contact" data-heading>{{ _('Contact Us') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<a href="https://hydro.js.org/#%E8%81%94%E7%B3%BB%E6%88%91%E4%BB%AC">联系我们</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" data-heading-extract-to="#menu-item-wiki_about">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="privacy" data-heading>{{ _('Privacy') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<h4>1. 收集的信息</h4>
|
||||
<p>我们收集信息是为了向所有用户提供更好的服务。我们有两种信息收集方式:</p>
|
||||
<ul>
|
||||
<li><p>您向我们提供信息。在您注册 Hydro 帐户时,我们会要求您提供个人信息,例如您的电子邮件地址、QQ号码等。</p>
|
||||
</li>
|
||||
<li><p>我们在您使用服务的过程中获取信息。我们会收集关于您使用的服务以及使用方式的信息,例如您在何时使用了我们服务。</p>
|
||||
</li>
|
||||
</ul>
|
||||
<h4>2. 如何使用收集到的信息</h4>
|
||||
<p>我们利用从所有服务中收集的信息来提供、维护、保护和改进这些服务,同时开发新的服务并保护 Hydro 以及用户的隐私。</p>
|
||||
<p>当我们要将信息用于本隐私权政策未载明的其它用途时,则会事先征求您的同意。</p>
|
||||
<h4>3. 访问和更新您的个人信息</h4>
|
||||
<p>无论您在何时使用我们的服务,我们都力求让您能够访问自己的个人信息。如果这些信息有误,我们会努力通过各种方式让您快速更新信息或删除信息。在更新您的个人信息时,我们可能会要求您先验证自己的身份,然后再处理您的请求。</p>
|
||||
<p>我们力求对服务进行完善的维护,以保护信息免遭意外或恶意的破坏。因此,当您从我们的服务中删除信息后,我们可能不会立即从在用的服务器中删除这些信息的残留副本,也可能不会从备份系统中删除相应的信息。</p>
|
||||
<h4>4. 信息安全</h4>
|
||||
<p>我们为您提供SSL加密访问服务,您可以通过SSL(https)使用我们的服务,这可以很大程度上保障在传输过程中您信息的安全。</p>
|
||||
<p>对于敏感数据(如您的密码),我们承诺在存储时进行高强度不可逆加密。Hydro 的管理员、维护人员等均不能够访问到敏感数据的明文,所有操作均无人工介入。</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" data-heading-extract-to="#menu-item-wiki_about">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="tos" data-heading>{{ _('Terms of Service') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<h4>0. 欢迎使用 Hydro</h4>
|
||||
<p>注册 Hydro 帐户和/或使用 Hydro 提供的服务(包括网页提供的在线服务和题目评测的非在线服务等),即表示您已同意本条款。请您务必审慎阅读,充分理解条款各项内容。</p>
|
||||
<h4>1. 使用服务</h4>
|
||||
<p>您必须遵守各项服务中提供的所有政策(包括但不限于讨论和题解的版规)。</p>
|
||||
<p>请勿滥用我们的服务。如,请勿干扰我们的服务,或尝试使用除我们提供的界面和指示以外的方法访问这些服务,或使用我们服务中出现的缺陷干扰其他网站或设施的正常运行。您仅能在法律允许的范围内使用我们的服务。</p>
|
||||
<p>您在使用我们服务时须遵守我们服务器所在地的法律法规,不得利用我们服务从事违法违规行为,包括但不限于:</p>
|
||||
<ol>
|
||||
<li>发布、传送、传播、储存危害国家安全统一、破坏社会稳定、违反公序良俗、侮辱、诽谤、淫秽、暴力以及任何违反国家法律法规的内容;</li>
|
||||
<li>发布、传送、传播、储存侵害他人知识产权、商业秘密等合法权利的内容;</li>
|
||||
<li>恶意虚构事实、隐瞒真相以误导、欺骗他人;</li>
|
||||
<li>发布、传送、传播广告信息及垃圾信息;</li>
|
||||
<li>其他法律法规禁止的行为。</li>
|
||||
</ol>
|
||||
<p>如果您违反了约定,相关国家相关机关或机构可能会对您提起诉讼、进行行政处罚或采取其他制裁措施,Hydro 将给于协助。造成损害的,您应依法予以赔偿,Hydro 不承担任何责任。</p>
|
||||
<p>如果 Hydro 发现或收到他人举报您发布的信息违反约定,Hydro 有权进行独立判断并采取技术手段予以删除、屏蔽或断开链接。同时,Hydro 有权视用户的行为性质,采取包括但不限于暂停或终止服务,限制、冻结或终止账户使用,追究法律责任等措施。</p>
|
||||
<h4>2. 版权</h4>
|
||||
<p>使用我们的服务并不代表您拥有我们的服务或您所访问的内容的任何知识产权。网站上的所有材料(包括但不限于题目内容、用户界面、Wiki)版权均受保护,归 Hydro 所有。除非另有说明,本网站上的材料和服务仅用于个人和非商业用途,未经 Hydro 书面许可,不得复制、修改、创建衍生作品、传播、出版、公开演示、公开展示和分发从本网站获得的任何信息、文件、产品或服务。</p>
|
||||
<h4>3. 您在我们服务中发布的内容</h4>
|
||||
<p>我们的某些服务允许您提交内容。您保留对该内容持有的任何知识产权的所有权。</p>
|
||||
<p>当您上传内容或通过其他方式向我们的服务提交内容时,您授予 Hydro 使用、持有、存储、复制、修改、创建衍生作品、传播、出版、公开演示、公开展示和分发此内容等权利。您在此许可中授予的权限,仅能用于运营、宣传和改进我们的服务,以及开发新的服务。该项许可在您停止使用我们的服务后依然有效。某些服务可能会向您提供一些方法,用于访问和删除您提供给该服务的内容。对于您提交至我们服务的任何内容,请确保您拥有向我们授予此许可的必要权利。我们有权在未通知您的情况下删除我们认为侵犯了知识产权或违反了相关法律法规的内容。</p>
|
||||
<h4>4. 对于发布题目的附加条款</h4>
|
||||
<p>您可以在 Hydro 上创建新题目。您上传到 Hydro 的题目,除了适用于本协议第三条(即“您在我们服务中发布的内容”)条款,还包含以下附加条款(若有冲突的条款,以附加条款中的优先):</p>
|
||||
<ol>
|
||||
<li><p>您上传到 Hydro 上的题目版权为 Hydro 和您共同拥有,我们会在相关页面或在对其进行分发、传播等操作时标明版权所有者。
|
||||
</p></li>
|
||||
<li><p>Hydro 尊重他人知识产权和合法权益,请您在上传题目前确保拥有题目内容(包括但不限于题目描述、数据、图片等)的著作权及信息网络传播权或者已经取得上述全部权利人的许可并不存在任何著作权纠纷。Hydro有权在不通知的情况下删除被认为侵权的题目。
|
||||
</p></li>
|
||||
<li><p>您可以申请将自己上传的优质题目合并到题库主干。我们的管理员会对您创建的题目的内容(包括但不限于评测数据等对用户不可见的信息)进行人工审核和适当修改以确认其符合国家基本法律法规。出于质量的考虑,我们也可能会拒绝您完全合法的合并到题库主干的请求。
|
||||
</p></li>
|
||||
<li><p>我们会维护服务的稳定,并对数据(包括您递交的题目)进行定期的备份,并尽量在关闭服务前通知您,但我们仍然不对任何题目(包括主干和非主干)提供永久存储或保留的承诺,出于安全的考虑推荐您自行保留题目的内容。
|
||||
</p></li>
|
||||
<li><p>您有权决定 Hydro 是否公开您上传的题目的数据。公开题目数据意味着 Hydro 上的用户均有权利获取到您递交的题目的所有评测数据,但相关版权协议仍然生效。</p>
|
||||
</li>
|
||||
</ol>
|
||||
<h4>5. 隐私保护</h4>
|
||||
<p><a href="{{ url('about') }}#privacy">Hydro 隐私声明</a>介绍了您在使用我们的服务时,我们会如何处理您的个人数据和保护您的隐私。使用我们的服务即表示您同意 Hydro 可以按照我们的隐私权政策使用您的个人数据。</p>
|
||||
<h4>6. 修改和终止服务</h4>
|
||||
<p>我们始终在不断更改和改进我们的服务。我们可能会增加或删除功能,也可能暂停或彻底停止某项服务。</p>
|
||||
<p>您可以随时停止使用我们的服务,尽管我们对此表示非常遗憾。Hydro 也可能随时停止向您提供服务,或随时对我们的服务增加或设置新的限制。</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-wiki_about">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" id="discuss" data-heading>{{ _('Discussion: Terms Of Service') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<p>为了更好地发挥讨论、题解的积极作用,使广大用户学到知识、获得利益,进一步规范讨论和题解功能的使用,我们制定了《讨论和题解版规》(简称《版规》)。您在发布(或回复)讨论和题解时,即代表您已充分阅读、理解、接受并保证遵守此版规。</p>
|
||||
<p>您在发布(或回复)讨论和题解或使用相关功能时须遵守以下规定:</p>
|
||||
<blockquote>
|
||||
<p>第一次使用编辑器前,要先阅读编辑器快速入门和 Markdown 详细帮助。</p>
|
||||
<p>不得将讨论、题解混淆。例如,不得将题解发布到讨论中,题解应发布在相应题目的题解区中。</p>
|
||||
<p>发布(或回复)的所有内容不得包含会干扰 Hydro 用户界面呈现的相关内容。</p>
|
||||
<p>发布(或回复)的所有内容不得包含恶意代码和指向恶意网站或 Hydro 明确禁止的网站的链接。</p>
|
||||
<p>特别地,发布(或回复)含有代码的内容时,应当将代码高亮。一个简单的方法是选中代码块然后按下 Tab 键。</p>
|
||||
<p>发布的题解禁止只包含无详细注释的代码。题解中难以理解的代码应当有尽可能详细的注释。</p>
|
||||
<p>打分、投票和评价应当客观。例如,对于题解的打分、投票和评价应当关注于题解本身的质量。</p>
|
||||
</blockquote>
|
||||
<p>您在发布、回复讨论和题解时还须遵守法律法规,不得发布违法违规内容,包括但不限于:</p>
|
||||
<blockquote>
|
||||
<p>危害国家安全统一、破坏社会稳定、违反公序良俗、侮辱、诽谤、淫秽、暴力以及任何违反国家法律法规的内容;</p>
|
||||
<p>侵害他人知识产权、商业秘密等合法权利的内容;</p>
|
||||
<p>恶意虚构事实、隐瞒真相以误导、欺骗他人的内容;</p>
|
||||
<p>广告信息及垃圾信息;</p>
|
||||
<p>其他法律法规禁止的内容。</p>
|
||||
</blockquote>
|
||||
<p>对于违反《版规》的,我们将进行警告并删除相关内容、临时冻结用户、永久冻结用户等操作。</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Hydro 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">"undefined 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, she is very sorry that Hydro 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:i@undefined.moe">contact undefined</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>
|
||||
<span style="color: #75715e">/*</span>
|
||||
<span style="color: #75715e">{{ error.message }}</span>
|
||||
<span style="color: #75715e">{{ error.stack }}</span>
|
||||
<span style="color: #75715e">*/</span>
|
||||
</pre>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,149 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
|
||||
{% 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'
|
||||
) %}
|
||||
<ul class="dczcomments__list view--discussion">
|
||||
{% if handler.user.hasPerm(comment_post_perm) %}
|
||||
<li class="dczcomments__item">
|
||||
<div class="media">
|
||||
<div class="media__left top">
|
||||
<img src="{{ gravatar(handler.user.gravatar, 60) }}" width="60" height="60" class="medium user-profile-avatar">
|
||||
</div>
|
||||
<div class="media__body top no-heading">
|
||||
<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="csrfToken" value="{{ handler.csrfToken }}">
|
||||
</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>
|
||||
<div class="commentbox-placeholder"></div>
|
||||
<ul style="display:none">
|
||||
<li class="dczcomments__reply commentbox-container">
|
||||
<div class="media">
|
||||
<div class="media__left top">
|
||||
<img src="{{ gravatar(handler.user.gravatar, 50) }}" width="50" height="50" class="medium user-profile-avatar">
|
||||
</div>
|
||||
<div class="media__body top no-heading">
|
||||
<div class="commentbox-placeholder"></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{%- for doc in docs -%}
|
||||
{% set udoc = udict[doc.owner] %}
|
||||
<li class="dczcomments__item">
|
||||
<div class="media">
|
||||
<div class="media__left top">
|
||||
<img src="{{ gravatar(udoc.gravatar, 60) }}" width="60" height="60" class="medium user-profile-avatar">
|
||||
</div>
|
||||
<div class="media__body top no-heading">
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, avatar=false) }}
|
||||
@ {{ datetimeSpan(doc['_id'])|safe }}
|
||||
</div>
|
||||
<div class="dczcomments__operations nojs--hide">
|
||||
{% if handler.user.hasPerm(reply_post_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Reply') }}" name="dczcomments__op-reply-comment"
|
||||
data-form="{{ {operation: reply_post_op, drid: doc._id}|json }}"
|
||||
><span class="icon icon-reply"></span></a>
|
||||
{% endif %}
|
||||
{% if (handler.user.hasPerm(comment_edit_self_perm) and doc.owner == handler.user._id) or handler.user.hasPerm(comment_edit_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Edit') }}" name="dczcomments__op-edit-comment"
|
||||
data-form="{{ {operation: comment_edit_op, drid: doc._id}|json }}"
|
||||
><span class="icon icon-edit"></span></a>
|
||||
{% endif %}
|
||||
{% if (handler.user.hasPerm(comment_delete_self_perm) and doc.owner == handler.user._id) or handler.user.hasPerm(comment_delete_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Delete') }}" name="dczcomments__op-delete-comment"
|
||||
data-form="{{ {operation: comment_delete_op, drid: doc._id}|json }}"
|
||||
><span class="icon icon-delete"></span></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="typo" data-emoji-enabled data-raw-url="{{ url('discussion_reply_raw', did=doc.parentId, drid=doc._id) }}">
|
||||
{{ doc['content']|markdown|safe }}
|
||||
</div>
|
||||
<div class="commentbox-edit-target"></div>
|
||||
<ul class="dczcomments__replies commentbox-reply-target">
|
||||
{%- for rdoc in doc['reply'] -%}
|
||||
{% set udoc = udict[rdoc.owner] %}
|
||||
<li class="dczcomments__reply{% if mode_create %} commentbox-container{% endif %}">
|
||||
<div class="media">
|
||||
<div class="media__left top">
|
||||
<img src="{{ gravatar(udoc.gravatar, 50) }}" width="50" height="50" class="medium user-profile-avatar">
|
||||
</div>
|
||||
<div class="media__body top no-heading">
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, avatar=false) }}
|
||||
@ {{ datetimeSpan(rdoc._id)|safe }}
|
||||
</div>
|
||||
<div class="dczcomments__operations nojs--hide">
|
||||
{% if handler.user.hasPerm(reply_post_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Reply') }}" name="dczcomments__op-reply-reply"><span class="icon icon-reply"></span></a>
|
||||
{% endif %}
|
||||
{% if doc.owner == handler.user._id or handler.user.hasPerm(reply_edit_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Edit') }}" name="dczcomments__op-edit-reply"
|
||||
data-form="{{ {operation: reply_edit_op, drid: doc._id, drrid: rdoc._id}|json }}"
|
||||
><span class="icon icon-edit"></span></a>
|
||||
{% endif %}
|
||||
{% if doc.owner == handler.user._id or handler.user.hasPerm(reply_delete_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Delete') }}" name="dczcomments__op-delete-reply"
|
||||
data-form="{{ {operation: reply_delete_op, drid: doc._id, drrid: rdoc._id}|json }}"
|
||||
><span class="icon icon-delete"></span></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="typo" data-emoji-enabled data-raw-url="{{ url('discussion_tail_reply_raw', did=doc.parentId, drid=doc._id, drrid=rdoc._id) }}">
|
||||
{{ rdoc.content|markdown|safe }}
|
||||
</div>
|
||||
<div class="commentbox-edit-target"></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,177 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% macro reply(mode_create, udoc, doc = {}, rdoc = {}) %}
|
||||
|
||||
{% endmacro %}
|
||||
|
||||
{% 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'
|
||||
) %}
|
||||
<ul class="dczcomments__list view--solution">
|
||||
{% if handler.user.hasPerm(comment_post_perm) %}
|
||||
<li class="dczcomments__item">
|
||||
<div class="media">
|
||||
<div class="media__left top">
|
||||
<div class="vote vote--discussion">
|
||||
<div class="vote-number">0</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body top no-heading">
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(handler.user) }}
|
||||
</div>
|
||||
</div>
|
||||
<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="csrfToken" value="{{ handler.csrfToken }}">
|
||||
</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>
|
||||
<div class="commentbox-placeholder"></div>
|
||||
<ul style="display:none">
|
||||
<li class="dczcomments__reply commentbox-container">
|
||||
<div class="media">
|
||||
<div class="media__body top no-heading">
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(handler.user, badge=false) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="commentbox-placeholder"></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{%- for doc in docs -%}
|
||||
{% set udoc = udict[doc.owner] %}
|
||||
<li class="dczcomments__item">
|
||||
<div class="media">
|
||||
<div class="media__left top">
|
||||
<div class="vote vote--discussion">
|
||||
{% if handler.user.hasPerm(perm.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._id }}">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button type="submit" class="vote-button upvote{% if pssdict[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._id }}">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button type="submit" class="vote-button downvote{% if pssdict[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>
|
||||
</div>
|
||||
<div class="media__body top no-heading">
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc) }}
|
||||
@ {{ datetimeSpan(doc._id)|safe }}
|
||||
</div>
|
||||
<div class="dczcomments__operations nojs--hide">
|
||||
{% if handler.user.hasPerm(reply_post_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Reply') }}" name="dczcomments__op-reply-comment"
|
||||
data-form="{{ {operation: reply_post_op, psid: doc._id}|json }}"
|
||||
><span class="icon icon-reply"></span></a>
|
||||
{% endif %}
|
||||
{% if (handler.user.hasPerm(comment_edit_self_perm) and doc.owner == handler.user._id) or handler.user.hasPerm(comment_edit_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Edit') }}" name="dczcomments__op-edit-comment"
|
||||
data-form="{{ {operation: comment_edit_op, psid: doc._id}|json }}"
|
||||
><span class="icon icon-edit"></span></a>
|
||||
{% endif %}
|
||||
{% if (handler.user.hasPerm(comment_delete_self_perm) and doc.owner == handler.user._id) or handler.user.hasPerm(comment_delete_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Delete') }}" name="dczcomments__op-delete-comment"
|
||||
data-form="{{ {operation: comment_delete_op, psid: doc._id}|json }}"
|
||||
><span class="icon icon-delete"></span></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="typo" data-emoji-enabled data-raw-url="{{ url('problem_solution_raw', pid=doc.parentId, psid=doc._id) }}">
|
||||
{{ doc['content']|markdown|safe }}
|
||||
</div>
|
||||
<div class="commentbox-edit-target"></div>
|
||||
<ul class="dczcomments__replies commentbox-reply-target">
|
||||
{%- for rdoc in doc['reply'] -%}
|
||||
{% set udoc = udict[rdoc['owner']] %}
|
||||
<li class="dczcomments__reply{% if mode_create %} commentbox-container{% endif %}">
|
||||
<div class="media">
|
||||
<div class="media__body top no-heading">
|
||||
<div class="clearfix">
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, badge=false) }} @ {{ datetimeSpan(rdoc['_id'])|safe }}
|
||||
</div>
|
||||
<div class="dczcomments__operations nojs--hide">
|
||||
{% if handler.user.hasPerm(reply_post_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Reply') }}" name="dczcomments__op-reply-reply"><span class="icon icon-reply"></span></a>
|
||||
{% endif %}
|
||||
{% if (handler.user.hasPerm(reply_edit_self_perm) and doc.owner == handler.user._id) or handler.user.hasPerm(reply_edit_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Edit') }}" name="dczcomments__op-edit-reply"
|
||||
data-form="{{ {operation: reply_edit_op, psid: doc._id, psrid: rdoc._id}|json }}"
|
||||
><span class="icon icon-edit"></span></a>
|
||||
{% endif %}
|
||||
{% if (handler.user.hasPerm(reply_delete_self_perm) and doc.owner == handler.user._id) or handler.user.hasPerm(reply_delete_perm) %}
|
||||
<a href="javascript:;" data-tooltip="{{ _('Delete') }}" name="dczcomments__op-delete-reply"
|
||||
data-form="{{ {operation: reply_delete_op, psid: doc._id, psrid: rdoc._id}|json }}"
|
||||
><span class="icon icon-delete"></span></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="typo" data-emoji-enabled data-raw-url="{{ url('problem_solution_reply_raw', pid=doc.parentId, psid=doc._id, psrid=rdoc._id) }}">
|
||||
{{ rdoc['content']|markdown|safe }}
|
||||
</div>
|
||||
<div class="commentbox-edit-target"></div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% macro render_time(tdoc_time) %}
|
||||
{{ datetimeSpan(tdoc_time, false, '%Y-%m-%d %H:%M')|safe }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_duration(tdoc) %}
|
||||
{{ ((tdoc.endAt.getTime() - tdoc.beginAt.getTime()) /1000 / 3600)|round(1) }}
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,203 @@
|
||||
{% macro form_begin(args) %}
|
||||
{% set label = args.label %}
|
||||
{% set columns = args.columns %}
|
||||
{% set last_column = args.last_column|default(true) %}
|
||||
{% set required = args.required or false %}
|
||||
{% set hotkeys = args.hotkeys or none %}
|
||||
{% set row = args.row|default(true) %}
|
||||
{% set no_label = args.no_label or false %}
|
||||
{% set label_wrap = args.label_wrap|default(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(args) %}
|
||||
{% set help_text = args.help_text or none %}
|
||||
{% set row = args.row|default(true) %}
|
||||
{% set no_label = args.no_label or false %}
|
||||
{% set label_wrap = args.label_wrap|default(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, args) %}
|
||||
{% set disabled = args.disabled or false %}
|
||||
{% set required = args.required or false %}
|
||||
{% set autofocus = args.autofocus or false %}
|
||||
{% set extra_style = args.extra_style or false %}
|
||||
{% set date = args.date or false %}
|
||||
{% set time = args.time or 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 %}
|
||||
{% if extra_style %}style="{{extra_style}}"{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro container_attr(container_class, args) %}
|
||||
{% set extra_class = args.extra_class or none %}
|
||||
class="{{ container_class }}{% if extra_class %} {{ extra_class }}{% endif %}"
|
||||
{% endmacro %}
|
||||
|
||||
{% macro select(args) %}
|
||||
<div
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('select-container', args) }}
|
||||
>
|
||||
<select
|
||||
name="{{ args.name }}"
|
||||
{{ form_attr('select', args) }}
|
||||
>
|
||||
{%- for k, v in args.options -%}
|
||||
<option value="{{ k }}"{% if args.value == k %} selected{% endif %}>
|
||||
{{ _(v) }}
|
||||
</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_select(args) %}
|
||||
{{ form_begin({columns:5}|assign(args)) }}
|
||||
{{ select(args) }}
|
||||
{{ form_end(args) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro radio(args) %}
|
||||
<div
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('radiobox-container', args) }}
|
||||
>
|
||||
{%- for k, v in options -%}
|
||||
<label class="radiobox">
|
||||
<input
|
||||
value="{{ k }}"
|
||||
type="radio"
|
||||
name="{{ v }}"
|
||||
{{ form_attr('radiobox__input', args) }}
|
||||
{% if value == args.id %} checked{% endif %}
|
||||
/> {{ _(v) }}
|
||||
</label>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_radio(args) %}
|
||||
{{ form_begin({columns:5, label_wrap:false}|assign(args)) }}
|
||||
{{ radio(args) }}
|
||||
{{ form_end({label_warp:false}|assign(args)) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro image_radio(args) %}
|
||||
<div
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('radiobox-container with-image', args) }}
|
||||
>
|
||||
{%- for k, v in options -%}
|
||||
<label class="radiobox with-image">
|
||||
<input
|
||||
value="{{ k }}"
|
||||
type="radio"
|
||||
name="{{ args.name }}"
|
||||
{{ form_attr('radiobox__input', args) }}
|
||||
{% 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(args) %}
|
||||
{{ form_begin({columns:8, label_warp:false}|assign(args)) }}
|
||||
{{ image_radio(args) }}
|
||||
{{ form_end({label_warp:false}|assign(args)) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro text(args) %}
|
||||
<div
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('textbox-container', args) }}
|
||||
>
|
||||
<input
|
||||
type="{{ args.type or 'text' }}"
|
||||
name="{{ args.name }}"
|
||||
value="{{ args.value }}"
|
||||
placeholder="{{ args.placeholder }}"
|
||||
{{ form_attr('textbox', args) }}
|
||||
>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_text(args) %}
|
||||
{{ form_begin({columns:5}|assign(args)) }}
|
||||
{{ text(args) }}
|
||||
{{ form_end(args) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro textarea(args) %}
|
||||
{% set markdown = args.markdown or false %}
|
||||
<div
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('textarea-container', args) }}
|
||||
>
|
||||
<textarea
|
||||
name="{{ args.name }}"
|
||||
placeholder="{{ args.placeholder }}"
|
||||
{% if markdown %}data-markdown{% endif %}
|
||||
{{ form_attr('textbox', args) }}
|
||||
>{{ args.value }}</textarea>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_textarea(args) %}
|
||||
{{ form_begin({columns:8}|assign(args)) }}
|
||||
{{ textarea(args) }}
|
||||
{{ form_end(args) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro checkbox(args) %}
|
||||
<div
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('checkbox-container', args) }}
|
||||
>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="{{ args.name }}"{% if args.value %} checked{% endif %}
|
||||
{{ form_attr('checkbox', args) }}
|
||||
>{{ _(args.label) }}
|
||||
</label>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_checkbox(args) %}
|
||||
{{ form_begin({columns:5, no_label:true}|assign(args)) }}
|
||||
{{ checkbox(args) }}
|
||||
{{ form_end({no_label:true}|assign(args)) }}
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,15 @@
|
||||
{% 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', {uid:handler.user._id}, label='My Profile') }}
|
||||
{{ sidemenu.render_item('comment--multiple', 'home_messages') }}
|
||||
<li class="menu__seperator"></li>
|
||||
{{ sidemenu.render_item('web', 'home_settings', {category:'domain'}, label='Domain Settings') }}
|
||||
<li class="menu__seperator"></li>
|
||||
{{ sidemenu.render_item('wrench', 'home_settings', {category:'account'}, label='Account Settings') }}
|
||||
{{ sidemenu.render_item('sliders', 'home_settings', {category:'preference'}, label='Preference Settings')}}
|
||||
{{ sidemenu.render_item('security', 'home_security') }}
|
||||
</ol>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,8 @@
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% macro render_time(tdoc_time) %}
|
||||
{{ datetimeSpan(tdoc_time, false, '%Y-%m-%d %H:%M')|safe }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_extension(tdoc) %}
|
||||
{{ ((tdoc['endAt'].getTime() - tdoc['penaltySince'].getTime())/ 1000 / 3600)|round(1) }}
|
||||
{% endmacro %}
|
||||
@@ -0,0 +1,37 @@
|
||||
<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') }}](https://...)</pre></dd>
|
||||
<dt>{{ _('Highlight') }}</dt>
|
||||
<dd><pre>=={{ _('Text') }}==</pre></dd>
|
||||
<dt>{{ _('Images') }}</dt>
|
||||
<dd><pre></pre></dd>
|
||||
<dt>{{ _('Images With Size') }}</dt>
|
||||
<dd><pre></pre></dd>
|
||||
<dt>{{ _('Footnote') }}</dt>
|
||||
<dd><pre>Here is a reference[^1].
|
||||
|
||||
[^1]: Here is the footnote.</pre></dd>
|
||||
<dt>{{ _('Videos') }}</dt>
|
||||
<dd><pre>@[{{ _('Description') }}](https://.../file.mp4)</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,15 @@
|
||||
{% macro render() %}
|
||||
{% if not isIE(handler.request.headers['user-agent']) %}
|
||||
<noscript><div class="section__body no-padding">
|
||||
<blockquote class="warn">
|
||||
<p>{{ _('This page needs JavaScript to work.') }}</p>
|
||||
</blockquote>
|
||||
</div></noscript>
|
||||
{% else %}
|
||||
<div class="section__body no-padding">
|
||||
<blockquote class="warn">
|
||||
<p>{{ _('This page needs JavaScript to work.') }}</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% 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,37 @@
|
||||
{% macro render_problem_title(pdoc, tdoc=none, show_tags=true, show_invisible_flag=true, invalid=false) %}
|
||||
{%- if not invalid %}
|
||||
<a
|
||||
{%- if tdoc and tdoc.docType == model.document.TYPE_CONTEST %}
|
||||
href="{{ url('contest_detail_problem', tid=tdoc.docId, pid=pdoc.docId) }}"
|
||||
{%- elif tdoc and tdoc.docType == model.document.TYPE_HOMEWORK %}
|
||||
href="{{ url('homework_detail_problem', tid=tdoc.docId, pid=pdoc.docId) }}"
|
||||
{%- else %}
|
||||
href="{{ url('problem_detail', pid=pdoc.pid|default(pdoc.docId)) }}"
|
||||
{%- endif %}
|
||||
>
|
||||
{%- endif %}
|
||||
{{ pdoc.pid if pdoc.pid else 'P'+pdoc.docId }} {{ pdoc.title }}
|
||||
{%- if not invalid %}
|
||||
</a>
|
||||
{%- endif %}
|
||||
{%- if pdoc.hidden and show_invisible_flag %}
|
||||
<span class="text-orange">({{ _('Hidden') }})</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="{{ 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 {{ model.builtin.STATUS_CODES[rdoc.status] }}">
|
||||
<div class="col--status__text">
|
||||
<span class="icon record-status--icon {{ model.builtin.STATUS_CODES[rdoc.status] }}"></span>
|
||||
<a href="{{ url('record_detail', rid=rdoc[rid_key]) }}" class="record-status--text {{ model.builtin.STATUS_CODES[rdoc.status] }}">
|
||||
{{ model.builtin.STATUS_TEXTS[rdoc.status] }}
|
||||
</a>
|
||||
</div>
|
||||
{% if rdoc.status == STATUS.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, args={}, label=none) %}
|
||||
{% set target_url = url(page_name, args) if page_name else '#' %}
|
||||
<li class="menu__item" id="menu-item-{{ page_name }}">
|
||||
<a href="{{ target_url }}" class="menu__link{% if handler.request.path == 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,35 @@
|
||||
{% macro render_inline(udoc, avatar=true, badge=true, modbadge=true) %}
|
||||
{% if udoc %}
|
||||
<span class="user-profile-link">
|
||||
{% if avatar %}
|
||||
<img class="small user-profile-avatar v-center" src="{{ gravatar(udoc.gravatar|default('')) }}" width="20" height="20">
|
||||
{% endif %}
|
||||
<a class="user-profile-name" href="{{ url('user_detail', uid=udoc._id) }}">
|
||||
{% if udoc.displayName %}
|
||||
{{ udoc.displayName }} ({{ udoc.uname }})
|
||||
{% else %}
|
||||
{{ udoc.uname }}
|
||||
{% endif %}
|
||||
</a>
|
||||
{% if badge %}
|
||||
{% set level = udoc.level|default(0) %}
|
||||
<a class="user-profile-badge v-center badge--lv{{ level }}" href="{{ url('user_detail', uid=udoc._id) }}" title="LV {{ level }}: Top {{ model.builtin.LEVELS[level]|default('N/A') }}%">LV {{ level }}</a>
|
||||
{% if modbadge and udoc.hasPerm(perm.PERM_MOD_BADGE) %}
|
||||
<span class="user-profile-badge v-center badge--mod" title="Moderator">MOD</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="user-profile-link">
|
||||
{% if avatar %}
|
||||
<img class="small user-profile-avatar v-center" src="{{ static_url('img/avatar.png') }}" width="20" height="20">
|
||||
{% endif %}
|
||||
<a class="user-profile-name" href="#">
|
||||
{{ _('Unknown User') }}
|
||||
</a>
|
||||
{% if badge %}
|
||||
<a class="user-profile-badge v-center badge--lv0" href="#" title="LV0">LV 0</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
@@ -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">
|
||||
{{ form.form_textarea({
|
||||
columns:null,
|
||||
label:'Content',
|
||||
name:'content',
|
||||
value:''
|
||||
}) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Send') }}
|
||||
</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,79 @@
|
||||
{% 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|safe }}
|
||||
{% if model.contest.isOngoing(tdoc) %}
|
||||
<blockquote class="warn">
|
||||
<p>{{ _('We will check code similarity after this contest.') }}</p>
|
||||
</blockquote>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if model.contest.isOngoing(tdoc) or model.contest.isDone(tdoc) %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Problem') }}</h1>
|
||||
</div>
|
||||
{% if attended or model.contest.isDone(tdoc) %}
|
||||
<div class="section__body no-padding">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
<col class="col--status">
|
||||
<col class="col--submit-at">
|
||||
{% endif %}
|
||||
<col class="col--problem">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
{% if handler.user.hasPriv(PRIV.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.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
{% if psdict[pid] and psdict[pid].rid %}
|
||||
{% set rdoc = rdict[psdict[pid].rid] %}
|
||||
{% if handler.canShowRecord(tdoc) %}
|
||||
{{ record.render_status_td(rdoc) }}
|
||||
{% else %}
|
||||
<td class="col--status record-status--border"><a href="{{ url('record_detail', rid=rdoc._id) }}">{{ _('Submitted') }}</a></td>
|
||||
{% endif %}
|
||||
<td class="col--submit-at">{{ datetimeSpan(rdoc._id)|safe }}</td>
|
||||
{% 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">
|
||||
{% set owner_udoc = udict[tdoc.owner] %}
|
||||
{% include "partials/contest_sidebar.html" %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,97 @@
|
||||
{% 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:4,
|
||||
label:'Title',
|
||||
name:'title',
|
||||
placeholder:_('title'),
|
||||
value:tdoc.title|default(''),
|
||||
autofocus:true,
|
||||
row:false
|
||||
}) }}
|
||||
{{ form.form_checkbox({
|
||||
columns:4,
|
||||
label:'Rated',
|
||||
name:'rated',
|
||||
placeholder:_('Is rated'),
|
||||
value:tdoc.rated|default(true),
|
||||
row:false
|
||||
}) }}
|
||||
</div><div class="row">
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
label:'Begin Date',
|
||||
name:'beginAtDate',
|
||||
placeholder:'YYYY-mm-dd',
|
||||
value:date_text,
|
||||
date:true,
|
||||
row:false
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
label:'Begin Time',
|
||||
name:'beginAtTime',
|
||||
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:null,
|
||||
label:'Problems',
|
||||
name:'pids',
|
||||
value:pids
|
||||
}) }}
|
||||
{{ form.form_textarea({
|
||||
columns:null,
|
||||
label:'Content',
|
||||
name:'content',
|
||||
value:tdoc['content']|default(''),
|
||||
markdown:true
|
||||
}) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
{% 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') }}: {{ model.contest.RULES[tdoc['rule']].TEXT }}
|
||||
</li>
|
||||
<li>
|
||||
<span class="icon icon-calendar"></span>
|
||||
{{ _('Start at') }}: {{ contest.render_time(tdoc.beginAt) }}
|
||||
</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="{{ url('contest_detail', tid=tdoc.docId) }}" class="detail-button">{{ _('View Details') }}</a>
|
||||
<div class="typo text-center">
|
||||
{% if tsdict[tdoc.docId].attend %}
|
||||
<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 model.contest.isOngoing(tdoc) %}
|
||||
{{ render_important_contest('live', 'Live...', tdoc) }}
|
||||
{% elif model.contest.isUpcoming(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(_(model.contest.RULES[rule].TEXT)) }}{% 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 model.contest.RULES -%}
|
||||
<option value="{{ k }}"{% if rule == k %} selected{% endif %}>{{ _('All {0} Contests').format(_(v.TEXT)) }}</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
<button type="submit" class="button hasjs--hide">
|
||||
{{ _('Search') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body no-padding">
|
||||
{% if not tdocs.length %}
|
||||
{{ 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--{{ tdoc['rule'] }}">
|
||||
<div class="media">
|
||||
<div class="media__left medium">
|
||||
<div class="contest__date numbox">
|
||||
<div class="numbox__num large">{{ datetimeSpan(tdoc['beginAt'], false, '%d')|safe }}</div>
|
||||
<div class="numbox__text">{{ datetimeSpan(tdoc['beginAt'], false, '%Y-%m')|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body medium">
|
||||
<h1 class="contest__title"><a href="{{ url('contest_detail', tid=tdoc.docId) }}" 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>{{ model.contest.RULES[tdoc.rule].TEXT }}</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.docId]['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.user.hasPerm(perm.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="{{ url('contest_create') }}" class="expanded primary button">{{ _('Create a contest') }}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,55 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% set type = 'homework' if tdoc.docType == 60 else 'contest' %}
|
||||
{% block content %}
|
||||
<div class="row"><div class="medium-12 columns">
|
||||
<div class="section visible">
|
||||
<div class="section__header">
|
||||
<a class="button" target="_blank" href="{{ url(type + '_scoreboard_download', tid=tdoc.docId, ext='html') }}">
|
||||
<span class="icon icon-download"></span> {{ _('Export as HTML') }}
|
||||
</a>
|
||||
<a class="button" href="{{ url(type + '_scoreboard_download', tid=tdoc.docId, 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="{{ url(type + '_detail_problem', tid=tdoc.docId, pid=column.raw) }}" data-tooltip="{{ pdict[column.raw].title }}">{{ column.value }}</a>
|
||||
{% else %}
|
||||
{{ column.value }}
|
||||
{% endif %}
|
||||
</th>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for row in rows -%}{% if loop.index0>0 %}
|
||||
<tr>
|
||||
{%- for column in row -%}
|
||||
<td class="col--{{ rows[0][loop.index0]['type'] }}">
|
||||
{% if column.type == 'user' %}
|
||||
{{ user.render_inline(udict[column.raw], badge=false) }}
|
||||
{% elif column.type == 'record' and column.raw %}
|
||||
<a href="{{ url('record_detail', rid=column.raw) }}">{{ column.value }}</a>
|
||||
{% else %}
|
||||
{{ column.value }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
{% endif %}{%- 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 -%}{% if loop.index0 %}
|
||||
<tr>
|
||||
{%- for column in row -%}
|
||||
<td>
|
||||
{{ column['value'] }}
|
||||
</td>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
{% endif %}{%- 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="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<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,130 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/comments_discussion.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="{{ url('discussion_node', type=model.discussion.typeDisplay[vnode.type], name=vnode.id) }}">
|
||||
{% if ddoc.parentType == model.document.TYPE_DISCUSSION_NODE %}
|
||||
<span class="v-center icon icon-tag"></span>
|
||||
{% elif ddoc.parentType == 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]) }}
|
||||
@
|
||||
{{ datetimeSpan(ddoc._id)|safe }}
|
||||
</li>
|
||||
</ul>
|
||||
<div class="typo topic__content" data-emoji-enabled data-raw-url="{{ url('discussion_raw', did=ddoc.docId) }}">
|
||||
{{ ddoc['content']|markdown|safe }}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="section__footer supplementary dot list">
|
||||
{% if handler.user.hasPerm(perm.PERM_EDIT_DISCUSSION) or (ddoc.owner == handler.user._id and handler.user.hasPerm(perm.PERM_EDIT_DISCUSSION_SELF)) %}
|
||||
<li>
|
||||
<a href="{{ url('discussion_edit', did=ddoc.docId) }}"><span class="icon icon-edit"></span> {{ _('Edit') }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
{{ _('{0} views').format(ddoc.views) }}
|
||||
</li>
|
||||
{% if handler.user.hasPriv(PRIV.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="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<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="{{ url('wiki_help', anchor='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_op = 'reply',
|
||||
reply_post_op = 'tail_reply',
|
||||
comment_edit_op = 'edit_reply',
|
||||
comment_delete_op = 'delete_reply',
|
||||
reply_edit_op = 'edit_tail_reply',
|
||||
reply_delete_op = 'delete_tail_reply',
|
||||
comment_post_perm = perm.PERM_REPLY_DISCUSSION,
|
||||
comment_edit_perm = perm.PERM_NEVER,
|
||||
comment_delete_perm = perm.PERM_DELETE_DISCUSSION_REPLY_SELF_DISCUSSION if ddoc.owner == handler.user._id else perm.PERM_DELETE_DISCUSSION_REPLY,
|
||||
comment_edit_self_perm = perm.PERM_EDIT_DISCUSSION_REPLY_SELF,
|
||||
comment_delete_self_perm = perm.PERM_DELETE_DISCUSSION_REPLY_SELF,
|
||||
reply_post_perm = perm.PERM_REPLY_DISCUSSION,
|
||||
reply_edit_perm = perm.PERM_NEVER,
|
||||
reply_delete_perm = perm.PERM_DELETE_DISCUSSION_REPLY_SELF_DISCUSSION if ddoc.owner == handler.user._id else perm.PERM_DELETE_DISCUSSION_REPLY,
|
||||
reply_edit_self_perm = perm.PERM_EDIT_DISCUSSION_REPLY_SELF,
|
||||
reply_delete_self_perm = perm.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">
|
||||
{% set udoc = udict[ddoc.owner] %}
|
||||
<div class="section side">
|
||||
<div class="profile__bg user-profile-bg--1"></div>
|
||||
<div class="section__body">
|
||||
<div class="media sidebar-user-profile">
|
||||
<div class="media__left">
|
||||
<img src="{{ gravatar(udoc.gravatar, 80) }}" width="80" height="80" class="medium user-profile-avatar">
|
||||
</div>
|
||||
<div class="media__body">
|
||||
<p>
|
||||
{{ user.render_inline(udoc, 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">{{ udoc.nAccept|default(0) }}</div>
|
||||
<div class="numbox__text">{{ _('Accepted') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="balancer__body">
|
||||
<div class="numbox">
|
||||
<div class="numbox__num medium">{{ udoc.nLike|default(0) }}</div>
|
||||
<div class="numbox__text">{{ _('Solutions Liked') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if vnode.type == model.document.TYPE_PROBLEM %}
|
||||
{% set pdoc = vnode %}
|
||||
{% set owner_udoc = udict[vnode.owner] %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% 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="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button name="operation" value="update" type="submit" class="rounded primary button">
|
||||
{{ _('Update') }} (Ctrl+Enter)
|
||||
</button>
|
||||
{% if ddoc.owner == handler.user._id or handler.user.hasPerm(perm.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.type == model.document.TYPE_PROBLEM %}
|
||||
{% set pdoc = vnode %}
|
||||
{% set owner_udoc = udict[vnode.owner] %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% elif vnode.type == model.document.TYPE_CONTEST %}
|
||||
{% set tdoc = vnode %}
|
||||
{% set owner_udoc = udict[vnode.owner] %}
|
||||
{% include "partials/contest_sidebar.html" %}
|
||||
{% elif vnode.type == 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.user.hasPerm(perm.PERM_CREATE_DISCUSSION) %}
|
||||
<p><a href="{{ url('discussion_create', type=model.discussion.typeDisplay[vnode.type], name=vnode.id) }}" class="expanded primary button">{{ _('Create a Discussion') }}</a></p>
|
||||
{% else %}
|
||||
{% if not handler.user.hasPriv(PRIV.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 'partials/discussion_nodes_widget.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,34 @@
|
||||
{% 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_dashboard') }}
|
||||
{{ sidemenu.render_item(null, 'domain_edit') }}
|
||||
{{ sidemenu.render_item(null, 'domain_join_applications') }}
|
||||
</ol>
|
||||
</li>
|
||||
<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_role') }}
|
||||
{{ sidemenu.render_item(null, 'domain_user') }}
|
||||
{{ sidemenu.render_item(null, 'domain_permission') }}
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,56 @@
|
||||
{% 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" 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">
|
||||
{{ form.form_text({
|
||||
label:'ID',
|
||||
name:'id',
|
||||
autofocus:true,
|
||||
required:true
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
label:'Name',
|
||||
name:'name',
|
||||
required:true
|
||||
}) }}
|
||||
{{ form.form_textarea({
|
||||
label:'Bulletin',
|
||||
name:'bulletin',
|
||||
markdown:true,
|
||||
required:true
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
label:'Gravatar',
|
||||
name:'gravatar'
|
||||
}) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<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>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,28 @@
|
||||
{% import "components/user.html" as user %}
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
{% if domain.bulletin %}
|
||||
<div class="section">
|
||||
<div class="section__body typo">
|
||||
{{ domain.bulletin|markdown|safe }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" data-heading>{{ _('Information') }}</h1>
|
||||
<div class="section__tools">
|
||||
<form method="post">
|
||||
<input type="hidden" name="operation" value="init_discussion_node">
|
||||
<button type="submit" class="primary rounded button"><span class="icon icon-wrench"></span> {{ _('Init Discussion Nodes') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<dl class="large horizontal">
|
||||
<dt>{{ _('Gravatar') }}</dt><dd><img src="{{ gravatar(domain.gravatar) }}" width="32" height="32"></dd>
|
||||
<dt>{{ _('Name') }}</dt><dd>{{ domain.name }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
<div class="section">
|
||||
{% include "partials/setting.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,34 @@
|
||||
{% 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="csrfToken" value="{{ handler.csrfToken }}">
|
||||
{% if joinSettings['method'] == model.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,62 @@
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
{% if joinSettings %}
|
||||
<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">{{ url_prefix|safe }}domain/join?domainId={{ handler.args.domainId }}</code></pre>
|
||||
{% if joinSettings['method'] == model.domain.JOIN_METHOD_CODE %}
|
||||
<p>{{ _('Or, with automatically filled invitation code') }}:</p>
|
||||
<pre><code class="language-data">{{ url_prefix|safe }}domain/join?domainId={{ handler.args.domainId }}&code={{ joinSettings.code|urlencode }}</code></pre>
|
||||
{% endif %}
|
||||
{% if not joinSettings['expire'] %}
|
||||
<br/>
|
||||
<blockquote class="note">
|
||||
{{ (_('The link will be expired at {0}').format(datetimeSpan(joinSettings.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_select({
|
||||
options:model.domain.JOIN_METHOD_RANGE,
|
||||
label:'Method',
|
||||
name:'method',
|
||||
value:joinSettings['method']|default(model.domain.JOIN_METHOD_NONE)
|
||||
}) }}
|
||||
{{ form.form_select({
|
||||
options:rolesWithText,
|
||||
label:'Role Assignment',
|
||||
name:'role',
|
||||
help_text:'The role to assign when user joining the domain.',
|
||||
value:joinSettings['role']|default('')
|
||||
}) }}
|
||||
{{ form.form_select({
|
||||
options:expirations,
|
||||
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:'invitationCode',
|
||||
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:joinSettings['code']|default('')
|
||||
}) }}
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button class="rounded primary button" role="submit">
|
||||
{{ _('Update Settings') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,67 @@
|
||||
{% extends "domain_base.html" %}
|
||||
{% block domain_content %}
|
||||
<form method="post">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('{0}: Permissions').format(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._id }}">{{ role._id }}</span></th>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</thead>
|
||||
{%- for family, perms in PERMS_BY_FAMILY -%}
|
||||
<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._id }}" data-checkbox-group="{{ role._id }}" data-checkbox-range value="{{ log2(perm.key) }}" type="checkbox"{% if role.perm|bitand(perm.key) %} checked{% endif %}{% if role._id == 'admin' %} disabled{% endif %}>
|
||||
</label>
|
||||
</td>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
{%- endfor -%}
|
||||
<tbody style="display:none">
|
||||
<tr><td class="col--family" colspan="{{ (roles|length)+1 }}">placeholder</td></tr>
|
||||
<tr>
|
||||
<td class="col--description">placeholder</td>
|
||||
{%- for role in roles -%}
|
||||
<td class="col--p">
|
||||
<label class="compact checkbox">
|
||||
<input name="{{ role._id }}" data-checkbox-group="{{ role._id }}" data-checkbox-range value="100" type="checkbox" checked{% if role._id == 'admin' %} disabled{% endif %}>
|
||||
</label>
|
||||
</td>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<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,72 @@
|
||||
{% 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(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--users">{{ _('Users') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for role in roles -%}
|
||||
{% set isBuiltin = role._id in ['default', 'guest', 'admin'] %}
|
||||
<tr{% if not isBuiltin %} data-role="{{ role._id }}"{% endif %}>
|
||||
<td class="col--checkbox">
|
||||
<label class="compact checkbox">
|
||||
<input type="checkbox" data-checkbox-group="role" {{ "disabled" if isBuiltin else "data-checkbox-range" }}>
|
||||
</label>
|
||||
</td>
|
||||
<td class="col--id">
|
||||
{{ _('Built-in') if isBuiltin else _('User-defined role') }}: {{ role._id }}
|
||||
</td>
|
||||
<td class="col--users">
|
||||
{{ role.count|default('--') }}
|
||||
</td>
|
||||
</tr>
|
||||
{%- 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,112 @@
|
||||
{% 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({
|
||||
label:_('Select a role'),
|
||||
options:rolesSelect,
|
||||
name:'role',
|
||||
value:'default'
|
||||
}) }}
|
||||
</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({
|
||||
label:_('Select a role'),
|
||||
options:rolesSelect,
|
||||
name:'role'
|
||||
}) }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('{0}: Users').format(domain.name) }}</h1>
|
||||
<div class="section__tools">
|
||||
<button class="primary rounded button" name="add_user">{{ _('Add User') }}</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--role">{{ _('Role') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for role in roles -%}
|
||||
{%- for rudoc in rudocs[role._id] -%}
|
||||
{% set is_disabled=(rudoc._id == handler.user._id) %}
|
||||
<tr data-uid="{{ rudoc._id }}">
|
||||
<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._id }}
|
||||
</td>
|
||||
<td class="col--user">
|
||||
{{ user.render_inline(udict[rudoc._id], badge=false) }}
|
||||
</td>
|
||||
<td class="col--role">
|
||||
{{ form.select({
|
||||
options:rolesSelect,
|
||||
name:'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') }}</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).formatFromArray(error.params) }}</p>
|
||||
<p>{{ _('Technical Information') }}:</p>
|
||||
<p>{{ _('Type') }}: {{ error.code }}</p>
|
||||
<p>{{ _('Arguments') }}:
|
||||
<ol>
|
||||
{%- for param in error.params -%}
|
||||
<li>{{ param }}</li>
|
||||
{%- endfor -%}
|
||||
</ol>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,46 @@
|
||||
/* {% if header_logo %} */
|
||||
.header__logo {
|
||||
background: url({{header_logo}})
|
||||
}
|
||||
/* {% endif %} */
|
||||
|
||||
/* {% if header_background %} */
|
||||
.header {
|
||||
background: url({{header_background}})
|
||||
}
|
||||
/* {% endif %} */
|
||||
|
||||
/* {% if nav_logo_light %} */
|
||||
.nav__logo, .header--mobile__domain.is--system {
|
||||
background-image: url({{nav_logo_light}})
|
||||
}
|
||||
/* {% endif %} */
|
||||
|
||||
/* {% if nav_logo_dark %} */
|
||||
.nav.floating .nav__logo, .nojs .nav .nav__logo {
|
||||
background-image: url({{nav_logo_dark}}) !important
|
||||
}
|
||||
/* {% endif %} */
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 1.5dppx), only screen and (min-resolution: 144dpi) {
|
||||
/* {% if header_2x %} */
|
||||
.header__logo {
|
||||
background-image: url({{header_2x}})
|
||||
}
|
||||
/* {% endif %} */
|
||||
/* {% if header_background_2x %} */
|
||||
.header {
|
||||
background-image: url({{header_background_2x}})
|
||||
}
|
||||
/* {% endif %} */
|
||||
/* {% if nav_logo_light_2x %} */
|
||||
.nav__logo, .header--mobile__domain.is--system {
|
||||
background-image: url({{nav_logo_light_2x}}) !important
|
||||
}
|
||||
/* {% endif %} */
|
||||
/* {% if nav_logo_dark_2x %} */
|
||||
.nav.floating .nav__logo, .nojs .nav .nav__logo, .header--mobile__domain.is--system {
|
||||
background-image: url({{nav_logo_dark_2x}}) !important
|
||||
}
|
||||
/* {% endif %} */
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{% 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>{{ _('URL') }}: {{ model.file.url(fdoc) }}</p>
|
||||
{% endif %}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<p>
|
||||
{{ _('New file') }}:
|
||||
<input type="text" name="title" 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(size(FILE_MAX_LENGTH), ALLOWED_MIMETYPE_PREFIX) }}</p>
|
||||
<p>{{ _('Usage: {0}, Quota: {1}').format(size(usage), size(quota)) }}</p>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,53 @@
|
||||
{% 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.user.hasPriv(model.builtin.PRIV.PRIV_CREATE_DOMAIN) %}
|
||||
<a class="primary rounded button" href="{{ url('home_domain_create') }}"><span class="icon icon-add"></span> {{ _('Create Domain') }}</a>
|
||||
{% endif %}
|
||||
<a class="tool-button" href="{{ url('wiki_help', anchor='domain') }}"><span class="icon icon-help"></span> {{ _("What's domain?") }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<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 ddocs -%}
|
||||
<tr>
|
||||
<td class="col--icon">
|
||||
<img src="{{ gravatar(ddoc.gravatar) }}" width="32" height="32">
|
||||
</td>
|
||||
<td class="col--name">
|
||||
{{ ddoc['name'] }} ({{ ddoc['_id'] }})
|
||||
</td>
|
||||
<td class="col--role">
|
||||
{{ dudict[ddoc._id].role|default('default') }}
|
||||
</td>
|
||||
<td class="col--action">
|
||||
<a class="typo-a" href="{{ url('homepage', domainId=ddoc['_id']) }}">{{ _('Visit') }}</a>
|
||||
{% if canManage[ddoc['_id']] %}
|
||||
· <a class="typo-a" href="{{ url('domain_dashboard', domainId=ddoc['_id']) }}">{{ _('Manage') }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{%- 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,147 @@
|
||||
{% extends "layout/home_base.html" %}
|
||||
{% block home_content %}
|
||||
<div data-heading-extract-to="#menu-item-home_security">
|
||||
<div class="row">
|
||||
{% if handler.user.mail.endsWith('.local') %}
|
||||
<div class="medium-12 columns">
|
||||
<div class="section">
|
||||
<div class="section__body">
|
||||
<blockquote class="warn">{{ _("You haven't set an email.")}}</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<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:'password',
|
||||
required:true
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
type:'text',
|
||||
label:'Current Email',
|
||||
columns:10,
|
||||
name:'currentEmail',
|
||||
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="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<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',
|
||||
required:true
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
type:'password',
|
||||
label:'New Password',
|
||||
columns:10,
|
||||
name:'password',
|
||||
required:true
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
type:'password',
|
||||
label:'Repeat Password',
|
||||
columns:10,
|
||||
name:'verifyPassword',
|
||||
required:true
|
||||
}) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<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--{{ icon(session.updateUa.os) }}"></span>
|
||||
</div>
|
||||
<div class="media__body medium typo">
|
||||
<p>{{ _('Last Update At') }}: {{ datetimeSpan(session.updateAt)|safe }}</p>
|
||||
{% if session.createHost %}
|
||||
<p>{{ _('Hostname') }}: {{ session.createHost }}</p>
|
||||
{% endif %}
|
||||
<p>{{ _('Location') }}: {{ _(session.updateGeoip.display) }} ({{ session.updateIp }})</p>
|
||||
<p>{{ _('Operating System') }}: {{ session.updateUa.os }}</p>
|
||||
<p>{{ _('Browser') }}: {{ session.updateUa.name }} {{ session.updateUa.version }}</p>
|
||||
{% if session.isCurrent %}
|
||||
<p class="sessionlist__current-session"><span class="icon icon-check"></span> {{ _('This is the current session') }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if not session.isCurrent %}
|
||||
<div class="media__right medium">
|
||||
<form method="post">
|
||||
<input type="hidden" name="operation" value="delete_token">
|
||||
<input type="hidden" name="tokenDigest" value="{{ session._id }}">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<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="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<input type="submit" value="{{ _('Logout All Sessions') }}" class="primary rounded button">
|
||||
</form>
|
||||
{% if geoipProvider %}
|
||||
<div class="typo">
|
||||
<p><small>IP geo-location data is provided by {{ geoipProvider|safe }}.</small></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% extends "layout/home_base.html" %}
|
||||
{% block home_content %}
|
||||
<div class="section" data-heading-extract-to="#menu-item-home_{{ category }}">
|
||||
{% include "partials/setting.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,77 @@
|
||||
{% 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|safe }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Problem') }}</h1>
|
||||
</div>
|
||||
{% if model.contest.isNotStarted(tdoc) %}
|
||||
{{ nothing.render('This homework is not open and you cannot view problems.') }}
|
||||
{% else %}
|
||||
{% if attended or model.contest.isDone(tdoc) %}
|
||||
<div class="section__body no-padding">
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
<col class="col--status">
|
||||
<col class="col--submit-at">
|
||||
{% endif %}
|
||||
<col class="col--problem">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
{% if handler.user.hasPriv(PRIV.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.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
{% if psdict[pid] and psdict[pid]['rid'] %}
|
||||
{% set rdoc = rdict[psdict[pid]['rid']] %}
|
||||
{% if handler.canShowRecord(tdoc) %}
|
||||
{{ record.render_status_td(rdoc) }}
|
||||
{% else %}
|
||||
<td class="col--status record-status--border"><a href="{{ url('record_detail', rid=rdoc._id) }}">{{ _('Submitted') }}</a></td>
|
||||
{% endif %}
|
||||
<td class="col--submit-at">{{ datetimeSpan(rdoc['_id'])|safe }}</td>
|
||||
{% 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,105 @@
|
||||
{% 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:'beginAtDate',
|
||||
placeholder:'YYYY-mm-dd',
|
||||
value:dateBeginText,
|
||||
date:true,
|
||||
row:false
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
last_column:true,
|
||||
label:'Begin Time',
|
||||
name:'beginAtTime',
|
||||
placeholder:'HH:MM',
|
||||
value:timeBeginText,
|
||||
time:true,
|
||||
row:false
|
||||
}) }}
|
||||
</div><div class="row">
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
label:'End Date',
|
||||
name:'penaltySinceDate',
|
||||
placeholder:'YYYY-mm-dd',
|
||||
value:datePenaltyText,
|
||||
date:true,
|
||||
row:false
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
last_column:true,
|
||||
label:'End Time',
|
||||
name:'penaltySinceTime',
|
||||
placeholder:'HH:MM',
|
||||
value:timePenaltyText,
|
||||
time:true,
|
||||
row:false
|
||||
}) }}
|
||||
</div>
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
label:'Extension (days)',
|
||||
name:'extensionDays',
|
||||
value:extension_days
|
||||
}) }}
|
||||
<div class="row"><div class="columns">
|
||||
<label>
|
||||
{{ _('Extension Score Penalty') }}
|
||||
<textarea name="penaltyRules" class="monospace textbox">{% if tdoc %}{{ penaltyRules }}{% else %}{% include 'partials/homework_default_penalty_rules.yaml' %}{% endif %}</textarea>
|
||||
</label>
|
||||
</div></div>
|
||||
{{ form.form_text({
|
||||
columns:null,
|
||||
label:'Problems',
|
||||
name:'pids',
|
||||
value:pids
|
||||
}) }}
|
||||
{{ form.form_textarea({
|
||||
columns:null,
|
||||
label:'Content',
|
||||
name:'content',
|
||||
value:tdoc['content']|default(''),
|
||||
markdown:true
|
||||
}) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
{% 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,64 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
{{ set(UiContext, 'docs', calendar) }}
|
||||
<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.user.hasPerm(perm.PERM_CREATE_HOMEWORK) %}
|
||||
<a class="compact button" href="{{ url('homework_create') }}">{{ _('Create Homework') }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body no-padding">
|
||||
{% if not tdocs.length %}
|
||||
{{ 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">{{ datetimeSpan(tdoc['penaltySince'], false, '%d')|safe }}</div>
|
||||
<div class="numbox__text">{{ datetimeSpan(tdoc['penaltySince'], false, '%Y-%m')|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body medium">
|
||||
<h1 class="homework__title"><a href="{{ url('homework_detail', tid=tdoc.docId) }}" data-emoji-enabled>{{ tdoc.title }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
{{ _('Status') }}: <span class="homework-status--text {{ model.contest.getStatus(tdoc) }}">{{ _(model.contest.statusText(tdoc)) }}</span>
|
||||
</li>
|
||||
<li>
|
||||
{{ _('Open Since') }}: {{ datetimeSpan(tdoc['beginAt'])|safe }}
|
||||
</li>
|
||||
<li>
|
||||
{% if model.contest.isExtended(tdoc) or model.contest.isDone(tdoc) %}
|
||||
{{ _('Hard Deadline') }}: {{ datetimeSpan(tdoc['endAt'])|safe }}
|
||||
{% else %}
|
||||
{{ _('Deadline') }}: {{ datetimeSpan(tdoc['penaltySince'])|safe }}
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ol>
|
||||
<div name="calendar_entry"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</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,52 @@
|
||||
{% 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.viewLang }}">
|
||||
<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">
|
||||
<meta name="msapplication-TileColor" content="#579e9a">
|
||||
<meta name="msapplication-TileImage" content="{{ static_url('mstile-144x144.png') }}">
|
||||
<meta name="theme-color" content="#56758f">
|
||||
{% block ogp %}
|
||||
<meta property="og:site_name" content="{{ model.system.get('server.name') }}" />
|
||||
<meta property="og:title" content="{{ handler.renderTitle(page_name) }}" />
|
||||
<meta property="og:url" content="{{ handler.ctx.request.href }}" />
|
||||
<meta property="og:image" content="{{ static_url('favicon-96x96.png') }}" />
|
||||
{% endblock %}
|
||||
<link rel="stylesheet" media="all" href="{{ static_url('theme.' + handler.user.theme|default('default') + '.css') }}">
|
||||
<link rel="stylesheet" media="all" href="{{ url('ui_extracss') }}">
|
||||
<title>{{ handler.renderTitle(page_name) }}</title>
|
||||
{% if not isIE(handler.request.headers['user-agent']) %}
|
||||
<script>
|
||||
var _htmlNode = document.documentElement;
|
||||
_htmlNode.className = _htmlNode.className.replace(' nojs', ' hasjs');
|
||||
</script>
|
||||
{% endif %}
|
||||
</head>
|
||||
<body>
|
||||
{{ handler.request.headers.hmr|default('')|safe }}
|
||||
{% block body %}{% endblock %}
|
||||
{% if not isIE(handler.request.headers['user-agent']) %}
|
||||
<script>
|
||||
var UiContext = {{ UiContext|json|safe }};
|
||||
var UserContext = {{ UserContext|json|safe }};
|
||||
</script>
|
||||
<script type="text/javascript" src="{{ ('/locale/{0}.js'.format(handler.translate('__id'))) }}"></script>
|
||||
<script type="text/javascript" src="/ui-constants.js"></script>
|
||||
<script type="module" src="{{ static_url('hydro.js') }}"></script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
{% 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>
|
||||
|
||||
{% set show_topics = false %}
|
||||
{% include "partials/footer.html" %}
|
||||
</div>
|
||||
|
||||
{% include "partials/login_dialog.html" %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,30 @@
|
||||
{% set layout_name = "mail" %}
|
||||
<style>
|
||||
body, .hydro { margin:0;color:#333;font-size:14px;font-family:"Tahoma","Segoe UI","Verdana","微软雅黑","Microsoft YaHei","宋体";background:#F2F2F2; }
|
||||
.hydro { padding:30px; }
|
||||
.hydro-box { background:#fff;box-shadow:0 0 15px rgba(0,0,0,0.3);border-radius:5px; }
|
||||
.hydro-header { background:#3AA9DE;color:#FFF;padding:10px;line-height:200%;font-size:15px;border-radius:5px 5px 0 0;border-bottom:3px solid #85CAEB; }
|
||||
.hydro-footer { font-size:12px;color:#444;padding:10px;border-top:1px solid #DDD;background:#F4F4F4;border-radius:0 0 5px 5px; }
|
||||
.hydro-content { padding:30px; }
|
||||
.hydro-content p { margin:5px 0; }
|
||||
.hydro a,
|
||||
.hydro a:visited,
|
||||
.hydro a:link,
|
||||
.hydro a:active { color:#1D76C7;text-decoration:none; }
|
||||
.hydro a:hover { color:#3A93E2;text-decoration:underline; }
|
||||
.hydro blockquote { padding:5px 10px;border-left:10px solid #E2EFFA;margin:20px;margin-left:0;_zoom:1; }
|
||||
#hydro_mail .t { font-size:16px; }
|
||||
#hydro_mail .f { font-style:italic; }
|
||||
</style>
|
||||
<div class="hydro">
|
||||
<div class="hydro-box">
|
||||
<div class="hydro-header">{% block title %}{% endblock %} - Hydro</div>
|
||||
<div class="hydro-content">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<div class="hydro-footer">
|
||||
<p>{{ _('This email was sent by {0} automatically, and please do not reply directly.').format('<a href="' + url_prefix + '/" target="_blank">Hydro</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', 'wiki_about') }}
|
||||
{{ sidemenu.render_item('help', 'wiki_help') }}
|
||||
</ol>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,210 @@
|
||||
{% set no_path_section = true %}
|
||||
{% set page_name = "homepage" %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/contest.html" as contest with context %}
|
||||
{% block content %}
|
||||
{% if domain['bulletin'] %}
|
||||
<div class="row">
|
||||
<div class="large-12 columns">
|
||||
<div class="section">
|
||||
<div class="section__body typo">
|
||||
{{ domain['bulletin']|markdown|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<div class="large-9 columns">
|
||||
{% if tdocs.length %}
|
||||
<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--{{ tdoc.rule }}">
|
||||
<div class="media">
|
||||
<div class="media__left medium">
|
||||
<div class="contest__date numbox">
|
||||
<div class="numbox__num large">{{ datetimeSpan(tdoc['beginAt'], false, '%d')|safe }}</div>
|
||||
<div class="numbox__text">{{ datetimeSpan(tdoc['beginAt'], false, '%Y-%m')|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body medium">
|
||||
<h1 class="contest__title"><a href="{{ url('contest_detail', tid=tdoc.docId) }}" data-emoji-enabled>{{ tdoc.title }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
<a href="{{ url('contest_main', query={rule:tdoc.rule}) }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ model.contest.RULES[tdoc.rule].TEXT }}</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.docId]['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 htdocs.length %}
|
||||
<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">{{ datetimeSpan(tdoc['penaltySince'], false, '%d')|safe }}</div>
|
||||
<div class="numbox__text">{{ datetimeSpan(tdoc['penaltySince'], false, '%Y-%m')|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body medium">
|
||||
<h1 class="homework__title"><a href="{{ url('homework_detail', tid=tdoc.docId) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
{{ _('Status') }}: <span class="homework-status--text {{ model.contest.getStatus(tdoc) }}">{{ _(model.contest.statusText(tdoc)) }}</span>
|
||||
</li>
|
||||
<li>
|
||||
{{ _('Open Since') }}: {{ datetimeSpan(tdoc['beginAt'])|safe }}
|
||||
</li>
|
||||
<li>
|
||||
{% if model.contest.isExtended(tdoc) or model.contest.isDone(tdoc) %}
|
||||
{{ _('Hard Deadline') }}: {{ datetimeSpan(tdoc['endAt'])|safe }}
|
||||
{% else %}
|
||||
{{ _('Deadline') }}: {{ datetimeSpan(tdoc['penaltySince'])|safe }}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% if htsdict[tdoc['docId']]['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 trdocs.length %}
|
||||
<div class="section page--training_main">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Training') }}</h1>
|
||||
</div>
|
||||
{% set tdocs = trdocs %}
|
||||
{% set 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="{{ url('training_detail', tid=tdoc.docId) }}" 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(model.training.getPids(tdoc.dag)|length) }}
|
||||
</li>
|
||||
<li>
|
||||
{% if tsdict[tdoc.docId]['enroll'] %}
|
||||
{% if not tsdict[tdoc.docId]['done'] %}
|
||||
<span class="icon training-status--icon progress"></span>
|
||||
<span class="training-status--text progress">{{ _('Completed') }} {{ (100 * tsdict[tdoc.docId]['donePids']|length / model.training.getPids(tdoc.dag)|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.user.hasPriv(PRIV.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>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if ddocs.length %}
|
||||
<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">
|
||||
<div class="section side nojs--hide">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Hitokoto') }}</h1>
|
||||
</div>
|
||||
<div class="section__body" name="hitokoto"></div>
|
||||
</div>
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Check In') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">还没做好(前端不会做欢迎来帮忙)</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if handler.user.hasPerm(perm.PERM_VIEW_DISCUSSION) %}
|
||||
{% include 'partials/discussion_nodes_widget.html' %}
|
||||
{% endif %}
|
||||
<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.com.cn/" 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="https://zoj.pintia.cn/" target="_blank">ZOJ</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="https://uoj.ac/" target="_blank">UOJ</a></li>
|
||||
<li class="chip-list__item"><a class="typo-a" href="https://loj.ac/" target="_blank">LibreOJ</a></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="https://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>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,25 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row" data-sticky-parent>
|
||||
<div class="medium-9 columns">
|
||||
{% block manage_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, 'manage_dashboard') }}
|
||||
{{ sidemenu.render_item(null, 'manage_script') }}
|
||||
{{ sidemenu.render_item(null, 'manage_user_import') }}
|
||||
{{ sidemenu.render_item(null, 'manage_setting') }}
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,27 @@
|
||||
{% import "components/user.html" as user %}
|
||||
{% extends "manage_base.html" %}
|
||||
{% block manage_content %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" data-heading>{{ _('Messages') }}</h1>
|
||||
</div>
|
||||
<div class="section__body typo" id="messages"></div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" data-heading>{{ _('Information') }}</h1>
|
||||
<div class="section__tools">
|
||||
<form method="post">
|
||||
<input type="hidden" name="operation" value="restart">
|
||||
<button type="submit" class="primary rounded button"><span class="icon icon-refresh"></span> {{ _('Restart') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body typo">
|
||||
<dl class="large horizontal">
|
||||
<dt>{{ _('Gravatar') }}</dt><dd><img src="{{ gravatar(domain.gravatar) }}" width="32" height="32"></dd>
|
||||
<dt>{{ _('Name') }}</dt><dd>{{ domain.name }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,56 @@
|
||||
{% extends "manage_base.html" %}
|
||||
{% block manage_content %}
|
||||
<div style="display: none" class="dialog__body--run-script">
|
||||
<div>
|
||||
<div class="row"><div class="columns">
|
||||
<h1>{{ _('Run script') }}</h1>
|
||||
</div></div>
|
||||
<div class="row">
|
||||
<div class="medium-12 columns">
|
||||
<label>
|
||||
{{ _('Params') }}
|
||||
<input name="args" type="text" class="textbox" autocomplete="off" data-autofocus>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Scripts') }}</h1>
|
||||
<div class="section__tools">
|
||||
<a class="tool-button" href="{{ url('wiki_help', anchor='script') }}"><span class="icon icon-help"></span> {{ _("What's script?") }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body no-padding">
|
||||
{{ noscript_note.render() }}
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--id">
|
||||
<col class="col--desc">
|
||||
<col class="col--action">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--id">{{ _('ID') }}</th>
|
||||
<th class="col--desc">{{ _('Description') }}</th>
|
||||
<th class="col--action">{{ _('Action') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for id, script in scripts -%}
|
||||
{% if not script.hidden %}
|
||||
<tr>
|
||||
<td class="col--id">{{ id }}</td>
|
||||
<td class="col--desc">{{ _(script.description|default(_('None'))) }}</td>
|
||||
<td class="col--action">
|
||||
<a class="typo-a" href="javascript: window.runScript('{{ id }}')">{{ _('Run') }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,6 @@
|
||||
{% extends "manage_base.html" %}
|
||||
{% block manage_content %}
|
||||
<div class="section">
|
||||
{% include "partials/setting.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,22 @@
|
||||
{% import "components/user.html" as user %}
|
||||
{% extends "manage_base.html" %}
|
||||
{% block manage_content %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title" data-heading>{{ _('Import User') }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
{{ noscript_note.render() }}
|
||||
<p name="messages"></p>
|
||||
{{ form.form_textarea({
|
||||
columns:null,
|
||||
label:'Users',
|
||||
name:'users'
|
||||
}) }}
|
||||
<div class="row"><div class="column">
|
||||
<button name="preview" class="rounded primary button">{{ _('Preview') }}</button>
|
||||
<button name="submit" class="rounded button">{{ _('Submit') }}</button>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,18 @@
|
||||
<ul class="group-list" data-widget-cf-container>
|
||||
{%- for category, sub_categories in model.system.get('problem.categories')|parseYaml -%}
|
||||
<li class="group-list__item">
|
||||
<h2 class="section__title">
|
||||
<a href="{{ url('problem_category', category=category) }}" data-category="{{ category }}">{{ 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="{{ url('problem_category', category=(category + ',' + sub_category)) }}">{{ sub_category }}</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ol>
|
||||
{% endif %}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
@@ -0,0 +1,92 @@
|
||||
{% 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="{{ url('contest_detail', tid=tdoc.docId) }}">
|
||||
<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 != 'contest_detail' %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('contest_detail', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-award"></span> {{ _('View Contest') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if not attended and not model.contest.isDone(tdoc) %}
|
||||
<li class="menu__item">
|
||||
{% if handler.user.hasPerm(perm.PERM_ATTEND_CONTEST) and handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
<form action="{{ url('contest_detail', tid=tdoc.docId) }}" method="POST">
|
||||
<input type="hidden" name="operation" value="attend">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button class="menu__link" type="submit">
|
||||
<span class="icon icon-add"></span> {{ _('Attend Contest') }}
|
||||
</button>
|
||||
</form>
|
||||
{% elif not handler.user.hasPriv(PRIV.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.canShowScoreboard(tdoc, False) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('contest_scoreboard', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-statistics"></span> {{ _('Scoreboard') }}
|
||||
</a></li>
|
||||
{% elif handler.canViewHiddenScoreboard(tdoc) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('contest_scoreboard', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-statistics"></span> {{ _('Scoreboard (Hidden)') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if user._id == tdoc.owner or handler.user.hasPerm(perm.PERM_EDIT_CONTEST) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('contest_edit', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit Contest') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.user.hasPerm(perm.PERM_READ_RECORD_CODE) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('contest_code', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-download"></span> {{ _('Export All Code') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('record_main', query={tid:tdoc.docId}) }}">
|
||||
<span class="icon icon-flag"></span> {{ _('All Submissions') }}
|
||||
</a></li>
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('wiki_help', anchor='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>{{ _(model.contest.statusText(tdoc)) }}</dd>
|
||||
<dt>{{ _('Rule') }}</dt><dd>{{ model.contest.RULES[tdoc.rule].TEXT }}</dd>
|
||||
<dt>{{ _('Problem') }}</dt><dd>{{ tdoc.pids.length }}</dd>
|
||||
<dt>{{ _('Start at') }}</dt><dd>{{ contest.render_time(tdoc.beginAt) }}</dd>
|
||||
<dt>{{ _('End at') }}</dt><dd>{{ contest.render_time(tdoc.endAt) }}</dd>
|
||||
<dt>{{ _('Duration') }}</dt><dd>{{ contest.render_duration(tdoc) }} {{ _('hour(s)') }}</dd>
|
||||
<dt>{{ _('Host') }}</dt><dd>{{ user.render_inline(owner_udoc, badge=false) }}</dd>
|
||||
<dt>{{ _('Partic.') }}</dt>
|
||||
<dd>
|
||||
{{ tdoc['attend']|default(0) }}
|
||||
{% if attended %}
|
||||
({{ _('Attended') }})
|
||||
{% endif %}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,46 @@
|
||||
{% import "components/form.html" as form with context %}
|
||||
<div class="row">
|
||||
<div class="medium-8 columns">
|
||||
<label>
|
||||
{{ _('Title') }}
|
||||
<input
|
||||
name="title" placeholder="{{ _('title') }}"
|
||||
value="{{ ddoc.title|default('') }}"
|
||||
class="textbox" autofocus>
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-2 columns">
|
||||
<label>
|
||||
{{ _('Highlight') }}
|
||||
<br>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="highlight" value="on"
|
||||
{%- if ddoc.highlight %} checked{% endif -%}
|
||||
{%- if not handler.user.hasPerm(perm.PERM_HIGHLIGHT_DISCUSSION) %} disabled{% endif -%}
|
||||
>{{ _('Highlight') }}
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-2 columns">
|
||||
<label>
|
||||
{{ _('Pin') }}
|
||||
<br>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="pin" value="on"
|
||||
{%- if ddoc.pin %} checked{% endif -%}
|
||||
{%- if not handler.user.hasPerm(perm.PERM_PIN_DISCUSSION) %} disabled{% endif -%}
|
||||
>{{ _('Pin') }}
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{{ form.form_textarea({
|
||||
columns:12,
|
||||
label:'Content',
|
||||
name:'content',
|
||||
value:ddoc.content|default(''),
|
||||
hotkeys:'ctrl+enter:submit',
|
||||
markdown:true,
|
||||
required:true,
|
||||
extra_style:'height: 500px'
|
||||
}) }}
|
||||
@@ -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.length %}
|
||||
{{ 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.nReply }}</div>
|
||||
<div class="numbox__text">{{ _('Comments') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body top">
|
||||
<h1 class="discussion__title"><a href="{{ url('discussion_detail', did=ddoc._id, anchor=ddoc.updateAt.getTime()) }}" data-emoji-enabled>{{ ddoc['title'] }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
<a class="discussion-node-tag" href="{{ url('discussion_node', type=model.discussion.typeDisplay[ddoc.parentType], name=ddoc.parentId) }}">
|
||||
{% if ddoc.parentType == model.document.TYPE_PROBLEM %}
|
||||
<span class="v-center icon icon-tag"></span>
|
||||
{% elif ddoc.parentType == model.document.TYPE_CONTEST %}
|
||||
<span class="v-center icon icon-award"></span>
|
||||
{% else %}
|
||||
<span class="v-center icon icon-flag"></span>
|
||||
{% endif %}
|
||||
{{ vndict[ddoc.parentType][ddoc.parentId].title|default(_('(missing)')) }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{{ user.render_inline(udict[ddoc.owner], badge=false) }}
|
||||
@
|
||||
{{ datetimeSpan(ddoc.updateAt)|safe }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ol>
|
||||
{% if page != undefined and dpcount != undefined %}
|
||||
{{ paginator.render(page, dpcount) }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -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 vnodes|groupby('content') -%}
|
||||
<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="{{ url('discussion_node', type=model.discussion.typeDisplay[model.document.TYPE_DISCUSSION_NODE], name=node.docId) }}">{{ node.docId }}</a></li>
|
||||
{%- endfor -%}
|
||||
</ol>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul></div>
|
||||
</div>
|
||||
@@ -0,0 +1,75 @@
|
||||
{% if not isIE(handler.request.headers['user-agent']) %}
|
||||
<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="{{ url('record_main') }}">{{ _('Judging Queue') }}</a></li>
|
||||
<li class="footer__category__item"><a href="{{ url('status') }}">{{ _('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/hydro-dev/Hydro" target="_blank">{{ _('Open Source') }}</a></li>
|
||||
<li class="footer__category__item"><a href="{{ url('wiki_api') }}">{{ _('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">
|
||||
<li class="footer__category__item"><a href="{{ url('wiki_help') }}">{{ _('Help') }}</a></li>
|
||||
<!--<li class="footer__category__item"><a href="#">{{ _('Blog') }}</a></li>-->
|
||||
<li class="footer__category__item"><a href="{{ url('wiki_about', anchor='contact') }}">{{ _('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="{{ url('wiki_about') }}">{{ _('About') }}</a></li>
|
||||
<li class="footer__extra-link-item"><a href="{{ url('wiki_about', anchor='contact') }}">{{ _('Contact Us') }}</a></li>
|
||||
<li class="footer__extra-link-item"><a href="{{ url('wiki_about', anchor='privacy') }}">{{ _('Privacy') }}</a></li>
|
||||
<li class="footer__extra-link-item"><a href="{{ url('wiki_about', anchor='tos') }}">{{ _('Terms of Service') }}</a></li>
|
||||
<li class="footer__extra-link-item"><a href="https://hydro.js.org/#%E8%81%94%E7%B3%BB%E6%88%91%E4%BB%AC">{{ _('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 k, v in model.setting.SETTINGS_BY_KEY['viewLang'].range -%}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('switch_language', lang=k) }}">{{ v }}</a></li>
|
||||
{%- endfor -%}
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="footer__extra-right">
|
||||
<ol class="clearfix">
|
||||
<!-- TODO -->
|
||||
{%- for html in (model.system.get('ui-default.footer_extra_html')|default('')).split('\n') -%}
|
||||
<li class="footer__extra-link-item">{{ html|safe }}</li>
|
||||
{%- endfor -%}
|
||||
<li class="footer__extra-link-item">Powered by <a href="https://hydro.js.org">Hydro</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -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,6 @@
|
||||
<div class="header{% if no_path_section %} mini{% endif %}">
|
||||
<div class="header__content"><div class="row"><div class="columns">
|
||||
<a class="header__logo" href="/" target="_self"></a>
|
||||
</div></div></div>
|
||||
{% include "partials/path.html" %}
|
||||
</div>
|
||||
@@ -0,0 +1,12 @@
|
||||
{% if no_path_section %}
|
||||
<div class="header--mobile">
|
||||
<div class="row"><div class="columns clearfix">
|
||||
<div class="float-left">
|
||||
<a class="header--mobile__domain is--system" href="/" target="_self"> </a>
|
||||
</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="{{ url('homework_detail', tid=tdoc.docId) }}">
|
||||
<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="{{ url('homework_detail', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-homework"></span> {{ _('View Homework') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if not attended and not model.contest.isDone(tdoc) %}
|
||||
<li class="menu__item">
|
||||
{% if handler.user.hasPerm(perm.PERM_ATTEND_HOMEWORK) and handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
<form action="{{ url('homework_detail', tid=tdoc.docId) }}" method="POST">
|
||||
<input type="hidden" name="operation" value="attend">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button class="menu__link" type="submit">
|
||||
<span class="icon icon-add"></span> {{ _('Claim Homework') }}
|
||||
</button>
|
||||
</form>
|
||||
{% elif not handler.user.hasPriv(PRIV.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.canShowScoreboard(tdoc, false) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('homework_scoreboard', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-statistics"></span> {{ _('Scoreboard') }}
|
||||
</a></li>
|
||||
{% elif handler.canViewHiddenScoreboard(tdoc) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('homework_scoreboard', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-statistics"></span> {{ _('Scoreboard (Hidden)') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if tdoc.owner == handler.user._id or handler.user.hasPerm(perm.PERM_EDIT_HOMEWORK) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('homework_edit', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit Homework') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.user.hasPerm(perm.PERM_READ_RECORD_CODE) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('homework_code', tid=tdoc.docId) }}">
|
||||
<span class="icon icon-download"></span> {{ _('Export All Code') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if attended %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('record_main', query={uidOrName:handler.user._id, tid:tdoc.docId}) }}">
|
||||
<span class="icon icon-flag"></span> {{ _('My Recent Submissions') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ url('wiki', page='help', anchor='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 {{ model.contest.getStatus(tdoc) }}">{{ _(model.contest.statusText(tdoc)) }}</span></dd>
|
||||
<dt>{{ _('Problem') }}</dt><dd>{{ tdoc['pids']|length }}</dd>
|
||||
<dt>{{ _('Open Since') }}</dt><dd>{{ homework.render_time(tdoc['beginAt']) }}</dd>
|
||||
<dt>{{ _('Deadline') }}</dt><dd>{{ homework.render_time(tdoc['penaltySince']) }}</dd>
|
||||
<dt>{{ _('Can be Extended For') }}</dt><dd>{{ homework.render_extension(tdoc) }} {{ _('hour(s)') }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,53 @@
|
||||
<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 Hydro universal account, you can submit code and join discussions in all online judging services provided by us.') }}</p>
|
||||
<div><a href="{{ url('user_register') }}" class="inverse rounded button">{{ _('Sign Up Now') }}</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog--signin__main">
|
||||
<form action="{{ 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 Hydro universal account') }}</p>
|
||||
{% if model.system.get('server.login') %}
|
||||
<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>
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<div class="row"><div class="columns">
|
||||
<input type="submit" value="{{ _('Sign In') }}" class="expanded rounded primary button">
|
||||
</div></div>
|
||||
{% endif %}
|
||||
{%- for v in handler.loginMethods -%}
|
||||
<div class="row"><div class="columns">
|
||||
<a href="{{ url('user_oauth', type=v.id) }}" class="expanded rounded button">{{ _(v.text) }}</a>
|
||||
</div></div>
|
||||
{%- endfor -%}
|
||||
<div class="row"><div class="columns">
|
||||
<div class="supplementary text-center">
|
||||
<a href="{{ url('user_lostpass') }}">{{ _('Forgot password or username?') }}</a>
|
||||
</div>
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,77 @@
|
||||
{%- macro nav_item(target_page_name, target_page_args, target_page_prefix) -%}
|
||||
<li class="nav__list-item">
|
||||
<a href="{{ url(target_page_name, target_page_args) }}" 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">
|
||||
<li class="nav__list-item"><a href="/" class="nav__logo"> </a></li>
|
||||
{%- for item in ui.nodes.nav -%}
|
||||
{% if item.checker(handler) %}
|
||||
{{ nav_item(item.name, item.args, item.prefix) }}
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
</ol>
|
||||
<ol class="nav__list nav__list--secondary clearfix">
|
||||
{% if not handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
<li class="nav__list-item"><a href="{{ url('user_login') }}" class="nav__item" name="nav_login">{{ _('Login') }}</a></li>
|
||||
<li class="nav__list-item"><a href="{{ 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="{{ url('user_detail', uid=handler.user._id) }}" class="nav__item">{{ handler.user.uname }} <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="{{ 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="{{ 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="{{ url('home_settings', category='domain') }}" class="menu__link">
|
||||
<span class="icon icon-web"></span> @ {{ handler.domain['name'] }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ url('home_settings', category='account') }}" class="menu__link">
|
||||
<span class="icon icon-wrench"></span> {{ _('home_account') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ url('home_settings', category='preference') }}" class="menu__link">
|
||||
<span class="icon icon-sliders"></span> {{ _('home_preference') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<a href="{{ 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="{{ 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="{{ 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 -%}
|
||||
/ {% if loop.index < path.length %}<a href="{{ url(c[1], c[2])|default('#') }}">{{ c[0] if c[3] else _(c[0]) }}</a>{% endif %}
|
||||
{%- endfor %}
|
||||
</div>
|
||||
<h1 class="location-current" data-emoji-enabled>{{ path[path.length - 1][0] if path[path.length - 1][3] else _(path[path.length - 1][0]) }}</h1>
|
||||
</div>
|
||||
<div class="media__right">
|
||||
{% include "partials/hamburger.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,30 @@
|
||||
# Background
|
||||
Special for beginners, ^_^
|
||||
|
||||
# Description
|
||||
Given two integers x and y, print the sum.
|
||||
|
||||
# Format
|
||||
|
||||
## Input
|
||||
Two integers x and y, satisfying $0\leq x,y\leq 32767$ .
|
||||
|
||||
## Output
|
||||
One integer, the sum of x and y.
|
||||
|
||||
# Sample 1
|
||||
|
||||
## Input
|
||||
|
||||
```
|
||||
123 500
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
```
|
||||
623
|
||||
```
|
||||
|
||||
# Limitation
|
||||
1s, 1024KiB for each test case.
|
||||
@@ -0,0 +1,54 @@
|
||||
{% 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.length %}
|
||||
{{ nothing.render('Sorry, there is no problem in the problem set') }}
|
||||
{% else %}
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
{% if handler.user.hasPriv(PRIV.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.user.hasPriv(PRIV.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 -%}
|
||||
{% set psdoc = psdict[pdoc['docId']] %}
|
||||
<tr>
|
||||
{% if handler.user.hasPriv(PRIV.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">
|
||||
{{ problem.render_problem_title(pdoc) }}
|
||||
</td>
|
||||
<td class="col--submit_n">{{ pdoc['nSubmit'] }}</td>
|
||||
<td class="col--ac_rate">{{ (100 * pdoc['nAccept'] / pdoc['nSubmit'])|round|int if pdoc['nSubmit'] > 0 else _('?') }}</td>
|
||||
<td class="col--difficulty">{{ pdoc['difficulty'] or _('(None)') }}</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ paginator.render(page, ppcount) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,10 @@
|
||||
<div data-fragment-id="problem_lucky">
|
||||
<p>
|
||||
<a href="{{ url('problem_random', query={category:category}) if category else url('problem_random') }}" 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,17 @@
|
||||
{% if tdoc %}
|
||||
{% if tdoc.docType == 60 %}
|
||||
{% include "partials/problem_sidebar_homework.html" %}
|
||||
{% if not owner_udoc %}
|
||||
{% set owner_udoc = udoc %}
|
||||
{% endif %}
|
||||
{% include "partials/homework_sidebar.html" %}
|
||||
{% else %}
|
||||
{% include "partials/problem_sidebar_contest.html" %}
|
||||
{% if not owner_udoc %}
|
||||
{% set owner_udoc = udoc %}
|
||||
{% endif %}
|
||||
{% include "partials/contest_sidebar.html" %}
|
||||
{% 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 model.contest.isOngoing(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="{{ url('contest_detail_problem', tid=tdoc.docId, pid=pdoc.docId) }}">
|
||||
<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="{{ url('contest_detail_problem_submit', tid=tdoc.docId, pid=pdoc.docId) }}">
|
||||
<span class="icon icon-send"></span> {{ _('Submit') }}
|
||||
</a></li>
|
||||
{% elif model.contest.isDone(tdoc) %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link" href="{{ url('problem_detail', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<span class="icon icon-send"></span> {{ _('Open in Problem Set') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if pdoc.owner == handler.user._id or handler.user.hasPerm(perm.PERM_EDIT_PROBLEM) %}
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="{{ url('problem_edit', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<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="{{ url('problem_settings', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<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 model.contest.isOngoing(tdoc) or model.contest.isExtended(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="{{ url('homework_detail_problem', tid=tdoc.docId, pid=pdoc.docId) }}">
|
||||
<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="{{ url('homework_detail_problem_submit', tid=tdoc.docId, pid=pdoc.docId) }}">
|
||||
<span class="icon icon-send"></span> {{ _('Submit') }}
|
||||
</a></li>
|
||||
{% elif model.contest.isDone(tdoc) %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link" href="{{ url('problem_detail', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<span class="icon icon-send"></span> {{ _('Open in Problem Set') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if pdoc.owner == handler.user._id or handler.user.hasPerm(perm.PERM_EDIT_PROBLEM) %}
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="{{ url('problem_edit', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<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="{{ url('problem_settings', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<span class="icon icon-wrench"></span> {{ _('Settings') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,197 @@
|
||||
{% 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.user.hasPerm(perm.PERM_CREATE_DISCUSSION) %}
|
||||
<li class="menu__item"><a class="menu__link highlight" href="{{ url('discussion_create', type='problem', name=pdoc.docId) }}">
|
||||
<span class="icon icon-add"></span> {{ _('Create a Discussion') }}
|
||||
</a></li>
|
||||
{% else %}
|
||||
{% if not handler.user.hasPriv(PRIV.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.user.hasPerm(perm.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="{{ url('problem_detail', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<span class="icon icon-flag"></span> {{ _('View Problem') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.user.hasPerm(perm.PERM_SUBMIT_PROBLEM) %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link{% if page_name == 'problem_submit' %} active{% endif %}" href="{{ url('problem_submit', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<span class="icon icon-send"></span> {{ _('Submit') }}
|
||||
</a></li>
|
||||
{% elif not handler.user.hasPriv(PRIV.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.user.hasPerm(perm.PERM_REJUDGE_PROBLEM) %}
|
||||
<li class="menu__item">
|
||||
<form method="post" action="{{ url('problem_detail', pid=pdoc.docId) }}">
|
||||
<input type="hidden" name="operation" value="rejudge">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button type="submit" class="menu__link">
|
||||
<span class="icon icon-refresh"></span> {{ _('Rejudge all submissions') }}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if handler.user.hasPerm(perm.PERM_VIEW_DISCUSSION) or handler.user.hasPerm(perm.PERM_VIEW_PROBLEM_SOLUTION) %}
|
||||
<li class="menu__seperator"></li>
|
||||
{% endif %}
|
||||
{% if handler.user.hasPerm(perm.PERM_VIEW_DISCUSSION) %}
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'discussion_node' or page_name == 'discussion_detail' %} active{% endif %}" href="{{ url('discussion_node', type='problem', name=pdoc.docId) }}">
|
||||
<span class="icon icon-comment--text"></span> {{ _('Discussions') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.user.hasPerm(perm.PERM_VIEW_PROBLEM_SOLUTION) %}
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_solution' %} active{% endif %}" href="{{ url('problem_solution', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<span class="icon icon-comment--text"></span> {{ _('Solutions') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_files' %} active{% endif %}" href="{{ url('problem_files', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<span class="icon icon-file"></span> {{ _('Files') }}
|
||||
</a></li>
|
||||
{% if (handler.user._id == pdoc.owner and handler.user.hasPerm(perm.PERM_EDIT_PROBLEM_SELF)) or handler.user.hasPerm(perm.PERM_EDIT_PROBLEM) %}
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="{{ url('problem_edit', pid=pdoc.pid|default(pdoc.docId)) }}">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if page_name == 'problem_detail' and (handler.user._id == pdoc.owner or handler.user.hasPerm(perm.PERM_READ_PROBLEM_DATA)) %}
|
||||
<div style="display: none" class="dialog__body--send-to">
|
||||
<div>
|
||||
<div class="row"><div class="columns">
|
||||
<h1>{{ _('Send Problem') }}</h1>
|
||||
</div></div>
|
||||
<div class="row"><div class="medium-12 columns">
|
||||
<label>
|
||||
{{ _('Target') }}
|
||||
<input name="target" type="text" class="textbox" data-autofocus>
|
||||
</label>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<li class="menu__item nojs--hide"><a class="menu__link" name="problem-sidebar__send-to" href="javascript:;">
|
||||
<span class="icon icon-copy"></span> {{ _('Send Problem') }}
|
||||
</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">
|
||||
<dt>{{ _('ID') }}</dt>
|
||||
<dd>{{ pdoc.docId }}</dd>
|
||||
{% if page_name != 'discussion_node' and page_name != 'discussion_detail' %}
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
<dt>{{ _('Submission') }}</dt>
|
||||
<dd>
|
||||
{% if pdoc.psdoc.status %}
|
||||
<span class="icon record-status--icon {{ model.builtin.STATUS_CODES[pdoc['psdoc']['status']] }}"></span>
|
||||
<a href="{{ url('record_detail', rid=pdoc.psdoc.rid) }}" class="record-status--text {{ model.builtin.STATUS_CODES[pdoc['psdoc']['status']] }}">
|
||||
{{ model.builtin.STATUS_TEXTS[pdoc['psdoc']['status']] }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ _('(None)') }}
|
||||
{% endif %}
|
||||
{% if pdoc['acMsg'] and pdoc['psdoc']['status'] == STATUS.STATUS_ACCEPTED %}
|
||||
<dt>{{ _('AC Message') }}</dt>
|
||||
<dd>{{ pdoc['acMsg'] }}</dd>
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% 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="{{ url('problem_category', category=category) }}">{{ category }}</a>
|
||||
{% if loop.index < pdoc['category']|length %}
|
||||
{{ _('problem-subcategory-delim') }}
|
||||
{% 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="{{ url('record_main', query={pid:pdoc.docId}) }}">{{ pdoc.nSubmit }}</a></dd>
|
||||
{% if page_name != 'discussion_node' and page_name != 'discussion_detail' %}
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
<dt>{{ _('# My Submissions') }}</dt>
|
||||
<dd><a href="{{ url('record_main', query={pid:pdoc.docId, uidOrName:handler.user._id}) }}">{{ pdoc['psdoc'].nSubmit|default(0) }}</a></dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<dt>{{ _('Accepted') }}</dt>
|
||||
<dd>{{ pdoc.nAccept }}</dd>
|
||||
<dt>{{ _('Accepted Ratio') }}</dt>
|
||||
<dd>{% if pdoc.nSubmit > 0 %}{{ (100 * pdoc.nAccept / pdoc.nSubmit)|round|int }}%{% else %}{{ _('?') }}{% endif %}</dd>
|
||||
<dt>{{ _('Uploaded By') }}</dt>
|
||||
<dd>{{ user.render_inline(owner_udoc, badge=false) }}</dd>
|
||||
</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="{{ url('training_detail', tid=tdoc.docId) }}">{{ tdoc.title }}</a></p>
|
||||
{%- endfor -%}
|
||||
{% endif %}
|
||||
{% if ctdocs %}
|
||||
<p>{{ _('In following contests') }}: </p>
|
||||
{%- for tdoc in ctdocs -%}
|
||||
<p><a href="{{ url('contest_detail', tid=tdoc.docId) }}">{{ 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,90 @@
|
||||
<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 not setting.flag|bitand(model.setting.FLAG_HIDDEN) %}
|
||||
{% set secret = setting.flag|bitand(model.setting.FLAG_SECRET) != 0 %}
|
||||
{% if setting.type == 'text' or setting.type == 'password' or setting.type == 'number' %}
|
||||
{{ form.form_text({
|
||||
type:setting.type,
|
||||
label:setting.name,
|
||||
help_text:setting.desc,
|
||||
name:setting.key,
|
||||
value:'' if secret else (current[setting.key]|default(setting.value)),
|
||||
disabled:setting.disabled,
|
||||
placeholder:_('(Not changed)') if secret else ''
|
||||
}) }}
|
||||
{% elif setting.type == 'select' %}
|
||||
{{ form.form_select({
|
||||
options:setting.range,
|
||||
label:setting.name,
|
||||
help_text:setting.desc,
|
||||
name:setting.key,
|
||||
value:current[setting.key] or setting.value,
|
||||
disabled:setting.disabled
|
||||
}) }}
|
||||
{% elif setting.type == 'radio' %}
|
||||
{{ form.form_radio({
|
||||
options:setting.range,
|
||||
label:setting.name,
|
||||
help_text:setting.desc,
|
||||
name:setting.key,
|
||||
value:current[setting.key] or setting.value,
|
||||
disabled:setting.disabled
|
||||
}) }}
|
||||
{% elif setting.type == 'image_radio' %}
|
||||
{{ form.form_image_radio({
|
||||
options:setting.range,
|
||||
image_class:setting.image_class,
|
||||
label:setting.name,
|
||||
help_text:setting.desc,
|
||||
name:setting.key,
|
||||
value:current[setting.key] or setting.value,
|
||||
disabled:setting.disabled
|
||||
}) }}
|
||||
{% elif setting.type == 'textarea' %}
|
||||
{{ form.form_textarea({
|
||||
label:setting.name,
|
||||
help_text:setting.desc,
|
||||
name:setting.key,
|
||||
value:'' if secret else (current[setting.key]|default(setting.value)),
|
||||
disabled:setting.disabled,
|
||||
placeholder:_('(Not changed)') if secret else ''
|
||||
}) }}
|
||||
{% elif setting.type == 'markdown' %}
|
||||
{{ form.form_textarea({
|
||||
label:setting.name,
|
||||
help_text:setting.desc,
|
||||
name:setting.key,
|
||||
value:'' if secret else (current[setting.key]|default(setting.value)),
|
||||
markdown:true,
|
||||
disabled:setting.disabled,
|
||||
placeholder:_('(Not changed)') if secret else ''
|
||||
}) }}
|
||||
{% elif setting.type == 'boolean' %}
|
||||
{{ form.form_checkbox({
|
||||
label:setting.name,
|
||||
help_text:setting.desc,
|
||||
name:setting.key,
|
||||
value:current[setting.key] or setting.value,
|
||||
disabled:setting.disabled
|
||||
})}}
|
||||
{{ form.form_checkbox({
|
||||
label:setting.name,
|
||||
name:'booleanKeys.' + setting.key,
|
||||
value:true,
|
||||
extra_class:'display-hidden'
|
||||
})}}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
<div class="section__body">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<input type="submit" class="rounded primary button" value="{{ _('Save All Changes') }}">
|
||||
</div>
|
||||
</form>
|
||||
@@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"_id": 1,
|
||||
"title": "最初的最初 - A+B Problem",
|
||||
"requireNids": [],
|
||||
"pids": [1000, "56c52ade2fefd90539000005"]
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"title": "最初的进阶",
|
||||
"requireNids": [1],
|
||||
"pids": [1001, 1002]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,54 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<script>
|
||||
{{ set(UiContext, {
|
||||
problemId: pdoc.pid|default(pdoc.docId),
|
||||
problemNumId: pdoc.docId,
|
||||
postCopyUrl: url('problem_send'),
|
||||
postPretestUrl: url('problem_pretest', pid=pdoc.docId),
|
||||
pretestConnUrl: "/conn/pretest?pid=" + pdoc.pid|default(pdoc.docId) + "&domainId=" + handler.domainId,
|
||||
codeLang: handler.user.codeLang,
|
||||
codeTemplate: handler.user.codeTemplate
|
||||
} }}
|
||||
{% if tdoc %}
|
||||
{{ set(UiContext, 'postSubmitUrl', url('contest_detail_problem_submit' if tdoc.docType == model.document.TYPE_CONTEST else 'homework_detail_problem_submit', pid=pdoc.docId, tid=tdoc.docId)) }}
|
||||
{{ set(UiContext, 'getSubmissionsUrl', url('contest_detail_problem_submit' if tdoc.docType == model.document.TYPE_CONTEST else 'homework_detail_problem_submit', pid=pdoc.docId, tid=tdoc.docId)) }}
|
||||
{{ set(UiContext, 'getRecordDetailUrl', url('record_detail', rid='{rid}', query={tid:tdoc.docId})) }}
|
||||
{% else %}
|
||||
{{ set(UiContext, 'postSubmitUrl', url('problem_submit', pid=pdoc.docId)) }}
|
||||
{{ set(UiContext, 'getSubmissionsUrl', url('problem_submit', pid=pdoc.docId)) }}
|
||||
{{ set(UiContext, 'getRecordDetailUrl', url('record_detail', rid='{rid}')) }}
|
||||
{% endif %}
|
||||
</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 tdoc %}
|
||||
{% if tdoc.docType == model.document.TYPE_CONTEST %}
|
||||
{% if model.contest.isDone(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.isDone(tdoc) #}
|
||||
{% endif %}{# tdoc['docType'] == model.document.TYPE_CONTEST #}
|
||||
{% endif %}{# tdoc #}
|
||||
{{ pdoc.content|content(handler.user.viewLang, pdoc.html)|safe }}
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% set owner_udoc = udoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
</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,84 @@
|
||||
{% 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-7 columns">
|
||||
<label>
|
||||
{{ _('Title') }}
|
||||
<input name="title" placeholder="{{ _('title') }}" value="{{ pdoc['title']|default('') }}" class="textbox" autofocus>
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
<label>
|
||||
{{ _('pid') }}
|
||||
<br>
|
||||
<label>
|
||||
<input name="pid" placeholder="{{ _('Leave blank to use numeric pid.') }}" value="{{ pdoc['pid']|default('') }}" class="textbox">
|
||||
</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>
|
||||
</div>
|
||||
{{ form.form_text({
|
||||
columns:12,
|
||||
label:'Tags',
|
||||
help_text:'Split by \', \'.',
|
||||
name:'tag',
|
||||
value:pdoc['tag']|default([])|join(', ')
|
||||
}) }}
|
||||
<div class="row"><div class="columns">
|
||||
<label>
|
||||
{{ _('Content') }}
|
||||
<textarea name="content" class="textbox" data-markdown style="height: 500px">{% if pdoc %}{{ pdoc['content']|toString }}{% else %}{% include 'partials/problem_default.md' %}{% endif %}</textarea>
|
||||
</label>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
{% if page_name == 'problem_edit' %}
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Update') }}
|
||||
</button>
|
||||
{% if pdoc.owner == handler.user._id or handler.user.hasPerm(perm.PERM_EDIT_PROBLEM) %}
|
||||
<button name="operation" value="delete" type="submit" class="rounded button">
|
||||
{{ _('Delete') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Create') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
<div class="section side visiable nojs--hide">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Categories') }} ({{ _('click to add') }})</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
{% include "partials/category.html" %}
|
||||
</div>
|
||||
</div>
|
||||
{% if page_name == 'problem_edit' %}
|
||||
{% set owner_udoc = udoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% else %}
|
||||
{% include 'components/md_hint.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,133 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-5 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Testdata') }}</h1>
|
||||
<div class="section__tools">
|
||||
{% if handler.user._id == pdoc.owner or handler.user.hasPerm(perm.PERM_EDIT_PROBLEM) %}
|
||||
<button class="primary rounded button" name="upload_testdata">{{ _('Add File') }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{{ noscript_note.render() }}
|
||||
<div class="section__body no-padding problem-files-testdata">
|
||||
{% if testdata.length %}
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--checkbox">
|
||||
<col class="col--name">
|
||||
<col class="col--size">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--checkbox">
|
||||
<label class="compact checkbox">
|
||||
<input type="checkbox" name="select_all" data-checkbox-toggle="testdata">
|
||||
</label>
|
||||
</th>
|
||||
<th class="col--name">{{ _('Filename') }}</th>
|
||||
<th class="col--size">{{ _('Size') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for file in testdata -%}
|
||||
<tr data-filename="{{ file.name }}">
|
||||
<td class="col--checkbox">
|
||||
<label class="compact checkbox">
|
||||
<input type="checkbox" data-checkbox-group="testdata" data-checkbox-range>
|
||||
</label>
|
||||
</td>
|
||||
<td class="col--name">
|
||||
<a href="{{ url('problem_file_download', {pid: pdoc.docId, filename: file.name, query:{type:'testdata'} }) }}">{{ file.name }}</a>
|
||||
</td>
|
||||
<td class="col--size">{{ size(file.size) }}</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
{% if handler.user._id == pdoc.owner or handler.user.hasPerm(perm.PERM_READ_PROBLEM_DATA) %}
|
||||
{{ nothing.render('No testdata at current.') }}
|
||||
{% else %}
|
||||
{{ nothing.render("You don't have permission to read testdata.")}}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if handler.user._id == pdoc.owner or handler.user.hasPerm(perm.PERM_EDIT_PROBLEM) %}
|
||||
{% if testdata.length %}
|
||||
<div class="section__body">
|
||||
<button class="rounded button" name="download_selected_testdata">{{ _('Download Selected') }}</button>
|
||||
<button class="rounded button" name="remove_selected_testdata">{{ _('Remove Selected') }}</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-4 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Additional Files') }}</h1>
|
||||
<div class="section__tools">
|
||||
{% if handler.user._id == pdoc.owner or handler.user.hasPerm(perm.PERM_EDIT_PROBLEM) %}
|
||||
<button class="primary rounded button" name="upload_file">{{ _('Add File') }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body no-padding problem-files-additional_file">
|
||||
{% if additional_file.length %}
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--checkbox">
|
||||
<col class="col--name">
|
||||
<col class="col--size">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--checkbox">
|
||||
<label class="compact checkbox">
|
||||
<input type="checkbox" name="select_all" data-checkbox-toggle="additional_file">
|
||||
</label>
|
||||
</th>
|
||||
<th class="col--name">{{ _('Filename') }}</th>
|
||||
<th class="col--size">{{ _('Size') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for file in additional_file -%}
|
||||
<tr data-filename="{{ file.name }}">
|
||||
<td class="col--checkbox">
|
||||
<label class="compact checkbox">
|
||||
<input type="checkbox" data-checkbox-group="additional_file" data-checkbox-range>
|
||||
</label>
|
||||
</td>
|
||||
<td class="col--name">
|
||||
<a href="{{ url('problem_file_download', {pid: pdoc.docId, filename: file.name}) }}">{{ file.name }}</a>
|
||||
</td>
|
||||
<td class="col--size">{{ size(file.size) }}</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
{{ nothing.render('No additional file at current.') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if additional_file.length %}
|
||||
<div class="section__body">
|
||||
<button class="rounded button" name="download_selected_file">{{ _('Download Selected') }}</button>
|
||||
{% if handler.user._id == pdoc.owner or handler.user.hasPerm(perm.PERM_EDIT_PROBLEM) %}
|
||||
<button class="rounded button" name="remove_selected_file">{{ _('Remove Selected') }}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% set owner_udoc = udoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,26 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__body">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<p>{{ _('Upload zipfile') }} ({{ _('Type') }}: {{type}}):
|
||||
<input type="file" name="file">
|
||||
<input type="submit" value="{{ _('Upload') }}" class="rounded primary button">
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
<div class="section side">
|
||||
<div class="section__body typo">
|
||||
<h2>{{ _('What is this?') }}</h2>
|
||||
<p>{{ _('With this feature, you can import problems that you can view from a site to here. Their title, content, tags and categories will be imported.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,52 @@
|
||||
{% 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>
|
||||
{{ _('Import from') }}
|
||||
<input name="url" placeholder="{{ _('Source') }}" class="textbox" autocomplete="off">
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-2 columns">
|
||||
<label>
|
||||
{{ _('Settings') }}
|
||||
<input name="pid" placeholder="{{ _('ProblemID') }}" class="textbox" autocomplete="off">
|
||||
</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">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button type="submit" class="rounded primary button">
|
||||
{{ _('Import') }}
|
||||
</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 is this?') }}</h2>
|
||||
<p>{{ _('With this feature, you can import problems that you can view from a site to here. Their title, content, tags and categories will be imported. However, their test data are not copied directly.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,71 @@
|
||||
{% import "components/record.html" as record with context %}
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
{{ set(UiContext, {
|
||||
getProblemUrlWithCategory: url('problem_category', category='{category}'),
|
||||
getProblemUrlWithoutCategory: url('problem_main'),
|
||||
currentCategory: category
|
||||
}) }}
|
||||
<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">
|
||||
{% include "partials/category.html" %}
|
||||
</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="{{ url('problem_main') }}">
|
||||
<div class="section__body">
|
||||
<label>
|
||||
<input name="q" type="text" class="textbox" value="{{ category }}" placeholder="1001">
|
||||
</label>
|
||||
<button type="submit" class="primary button">{{ _('Search') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% if handler.user.hasPerm(perm.PERM_CREATE_PROBLEM) %}
|
||||
<div class="section side">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Create Problem') }}</h1>
|
||||
</div>
|
||||
<ol class="menu">
|
||||
{%- for item in ui.nodes.problem_add -%}
|
||||
<a href="{{ url(item.name, item.args) }}" class="menu__link">
|
||||
<span class="icon icon-{{ item.icon|default('add') }}"></span>
|
||||
{{ _(item.text) }}
|
||||
</a>
|
||||
{%- endfor -%}
|
||||
</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,47 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row" data-sticky-parent>
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Requests') }}</h1>
|
||||
</div>
|
||||
<div class="section__body no-padding">
|
||||
{{ noscript_note.render() }}
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--id">
|
||||
<col class="col--title">
|
||||
<col class="col--action">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--id">{{ _('ID') }}</th>
|
||||
<th class="col--title">{{ _('Title') }}</th>
|
||||
<th class="col--action">{{ _('Action') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for request in requests -%}
|
||||
{%- for pid in request.pids -%}
|
||||
<tr>
|
||||
<td class="col--id"><a href="{{ request.url }}{{ pid }}">{{ request.display }}{{ pid }}</a></td>
|
||||
<td class="col--title">{{ request.pdocs[pid] }}</td>
|
||||
<td class="col--action">
|
||||
<form method="POST">
|
||||
<input type="hidden" name="operation" value="confirm">
|
||||
<input type="hidden" name="tokenId" value="{{ request._id }}">
|
||||
<input type="hidden" name="pids" value="{{ pid }}">
|
||||
<input class="typo-a" type="submit">
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,48 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/comments_solution.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 = perm.PERM_CREATE_PROBLEM_SOLUTION,
|
||||
comment_edit_perm = perm.PERM_NEVER,
|
||||
comment_edit_self_perm = perm.PERM_EDIT_PROBLEM_SOLUTION_SELF,
|
||||
comment_delete_perm = perm.PERM_DELETE_PROBLEM_SOLUTION,
|
||||
comment_delete_self_perm = perm.PERM_DELETE_PROBLEM_SOLUTION_SELF,
|
||||
reply_post_perm = perm.PERM_REPLY_PROBLEM_SOLUTION,
|
||||
reply_edit_perm = perm.PERM_NEVER,
|
||||
reply_edit_self_perm = perm.PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF,
|
||||
reply_delete_perm = perm.PERM_DELETE_PROBLEM_SOLUTION_REPLY,
|
||||
reply_delete_self_perm = perm.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">
|
||||
{% set owner_udoc = udict[pdoc.owner] %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
</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">
|
||||
{% set owner_udoc = udoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,66 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
{% if not tdoc or rdocs.length %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Recent 10 Records') }}</h1>
|
||||
</div>
|
||||
<div class="section__body no-padding">
|
||||
{% if not rdocs.length %}
|
||||
{{ nothing.render('You have not submitted any solutions for this problem') }}
|
||||
{% else %}
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--status">
|
||||
<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--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:model.system.get('lang.texts')|parseYaml,
|
||||
name:'lang',
|
||||
value:handler.user.codeLang
|
||||
}) }}
|
||||
{{ form.form_textarea({label:'Code', columns:12, name:'code', extra_class:'monospace', autofocus:true}) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<input type="submit" class="rounded primary button" value="{{ _('Submit') }}">
|
||||
</div></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% set owner_udoc = udoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% import "components/record.html" as record with context %}
|
||||
<tr data-rid="{{ rdoc['_id'] }}">
|
||||
{{ record.render_status_td(rdoc) }}
|
||||
<td class="col--memory">
|
||||
{{ (rdoc.memory / 1000)|round(0, 'ceil')|int }} MB
|
||||
</td>
|
||||
<td class="col--time">
|
||||
{{ rdoc.time|round|int }}ms
|
||||
</td>
|
||||
<td class="col--submit-at">{{ datetimeSpan(rdoc._id)|safe }}</td>
|
||||
</tr>
|
||||
@@ -0,0 +1,16 @@
|
||||
{% extends 'layout/simple.html' %}
|
||||
{% block body %}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% if (typeof(pdoc.data) == 'string') %}
|
||||
<p><b>{{ _('Current dataset comes from') }} <a href="{{ pdoc.data.split('from:')[1] }}" target="_blank">{{ pdoc.data.split('from:')[1] }}</a></b></p>
|
||||
{% else %}
|
||||
<p>{{ _('Current dataset: {0}').format((pdoc['data'] or _('(None)')).toString()) }}</p>
|
||||
<p>{{ _('MD5') }}: {{ md5|default(_('(None)')) }}</p>
|
||||
{% endif %}
|
||||
<p>{{ _('New dataset') }}:
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<input type="file" name="file">
|
||||
<input type="submit" value="{{ _('Upload') }}" class="rounded primary button">
|
||||
</p>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,46 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% import "components/paginator.html" as paginator with context %}
|
||||
{% import "components/nothing.html" as nothing with context %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-12 columns">
|
||||
<div class="section">
|
||||
<div class="section__body no-padding">
|
||||
<div data-fragment-id="ranking">
|
||||
{% if not udocs.length %}
|
||||
{{ nothing.render('Sorry, there is no user in this domain.') }}
|
||||
{% else %}
|
||||
<table class="data-table">
|
||||
<colgroup>
|
||||
<col class="col--rank">
|
||||
<col class="col--user">
|
||||
<col class="col--rp">
|
||||
<col class="col--bio">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col--rank">{{ _('Rank') }}</th>
|
||||
<th class="col--user">{{ _('Username') }}</th>
|
||||
<th class="col--rp">{{ _('RP') }}</th>
|
||||
<th class="col--bio">{{ _('Bio') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for udoc in udocs -%}
|
||||
<tr>
|
||||
<td class="col--rank">{{ (page - 1) * 100 + loop.index }}</td>
|
||||
<td class="col--user">{{ user.render_inline(udoc) }}</td>
|
||||
<td class="col--rp">{{ udoc.rp|default(1500)|round(0) }}</td>
|
||||
<td class="col--bio">{{ udoc.bio|default('')|truncate(64, true)|markdownInline|safe }}</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ paginator.render(page, upcount) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,107 @@
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
{{ set(UiContext, 'socketUrl', "/record-detail-conn?domainId=" + rdoc.domainId + "&rid=" + rdoc._id) }}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
{% include 'record_detail_status.html' %}
|
||||
{% 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-{{ (model.system.get('ui-default.lang_highlight_id')|parseYaml)[rdoc['lang']] }}">{{ rdoc['code'] }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if rdoc['stdout'] or rdoc['stderr'] %}
|
||||
<div class="section">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _('Stdout') }}</h1>
|
||||
</div>
|
||||
{% if rdoc['stdout'] %}
|
||||
<div class="section__body" data-syntax-hl-show-line-number>
|
||||
<pre><code>{{ rdoc['stdout']|ansi|safe }}</code></pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if rdoc['stderr'] %}
|
||||
<div class="section__body" data-syntax-hl-show-line-number>
|
||||
<pre><code>{{ rdoc['stderr']|ansi|safe }}</code></pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
</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.user.hasPerm(perm.PERM_REJUDGE) %}
|
||||
<div class="section__body no-padding">
|
||||
<ol class="menu">
|
||||
<li class="menu__item">
|
||||
<form method="post">
|
||||
<input type="hidden" name="operation" value="rejudge">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button type="submit" class="menu__link">
|
||||
<span class="icon icon-refresh"></span> {{ _('Rejudge') }}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<form method="post">
|
||||
<input type="hidden" name="operation" value="cancel">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<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, modbadge=false) }}</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 %}
|
||||
<dt>{{ _('Contest') }}</dt>
|
||||
<dd>
|
||||
<a href="{{ url('contest_detail', tid=tdoc.docId) }}">{{ tdoc.title }}</a>
|
||||
</dd>
|
||||
{% endif %}
|
||||
<dt>{{ _('Language') }}</dt>
|
||||
<dd>
|
||||
{{ (model.system.get('lang.texts')|parseYaml)[rdoc['lang']] }}
|
||||
</dd>
|
||||
<dt>
|
||||
{{ _('Submit At') }}
|
||||
</dt>
|
||||
<dd>
|
||||
{{ datetimeSpan(rdoc._id)|safe }}
|
||||
</dd>
|
||||
{% if rdoc.judgeAt %}
|
||||
<dt>{{ _('Judged At') }}</dt>
|
||||
<dd>{{ datetimeSpan(rdoc.judgeAt)|safe }}</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,59 @@
|
||||
<div class="section visible" id="status">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">
|
||||
<span class="icon record-status--icon {{ model.builtin.STATUS_CODES[rdoc['status']] }}"></span>
|
||||
<span class="record-status--text {{ model.builtin.STATUS_CODES[rdoc['status']] }}">
|
||||
{{ model.builtin.STATUS_TEXTS[rdoc['status']] }}
|
||||
</span>
|
||||
</h1>
|
||||
</div>
|
||||
{% if rdoc.compilerTexts.length %}
|
||||
<div class="section__body">
|
||||
<pre class="compiler-text">{{ rdoc.compilerTexts|join('\n')|ansi|safe }}</pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if rdoc.judgeTexts.length %}
|
||||
<div class="section__body">
|
||||
<pre class="judge-text">{{ formatJudgeTexts(rdoc.judgeTexts)|ansi|safe }}</pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if rdoc.testCases.length %}
|
||||
<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.testCases -%}
|
||||
<tr>
|
||||
<td class="col--case record-status--border {{ model.builtin.STATUS_CODES[rcdoc['status']] }}">
|
||||
#{{ loop.index }}
|
||||
</td>
|
||||
<td class="col--status">
|
||||
<span class="icon record-status--icon {{ model.builtin.STATUS_CODES[rcdoc['status']] }}"></span>
|
||||
<span class="record-status--text {{ model.builtin.STATUS_CODES[rcdoc['status']] }}">
|
||||
{{ model.builtin.STATUS_TEXTS[rcdoc['status']] }}
|
||||
</span>
|
||||
<span>{{ formatJudgeTexts([rcdoc.message]) if rcdoc.message else '' }}</span>
|
||||
<a class="tool-button" href="{{ url('wiki_help', anchor='status') }}"><span class="icon icon-help"></span></a>
|
||||
</td>
|
||||
<td class="col--time">{% if rcdoc['status'] == STATUS.STATUS_TIME_LIMIT_EXCEEDED or rcdoc['status'] == STATUS.STATUS_MEMORY_LIMIT_EXCEEDED or rcdoc['status'] == STATUS.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rcdoc.time|round|int }}ms</td>
|
||||
<td class="col--memory">{% if rcdoc['status'] == STATUS.STATUS_TIME_LIMIT_EXCEEDED or rcdoc['status'] == STATUS.STATUS_MEMORY_LIMIT_EXCEEDED or rcdoc['status'] == STATUS.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ size(rcdoc.memory, 1024) }}</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,8 @@
|
||||
<dl class="large horizontal" id="summary">
|
||||
<dt>{{ _('Score') }}</dt>
|
||||
<dd>{{ rdoc['score'] }}</dd>
|
||||
<dt>{{ _('Total Time') }}</dt>
|
||||
<dd>{% if rdoc['status'] == STATUS.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc.time|round|int }}ms</dd>
|
||||
<dt>{{ _('Peak Memory') }}</dt>
|
||||
<dd>{% if rdoc['status'] == STATUS.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ size(rdoc.memory, 1024) }}</dd>
|
||||
</dl>
|
||||
@@ -0,0 +1,109 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
{{ set(UiContext, 'socketUrl', "/record-conn?domainId=" + handler.domainId) }}
|
||||
{{ set(UiContext, 'rids', rdocs.map(eval("rdoc=>rdoc._id.toString()"))) }}
|
||||
<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="{{ 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="uidOrName" type="text" class="textbox" value="{{ filterUidOrName }}" autocomplete="off" data-autofocus>
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-4 columns">
|
||||
<label>
|
||||
{{ _('By Problem') }}
|
||||
<input name="pid" type="text" class="textbox" value="{{ filterPid }}">
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-4 columns">
|
||||
<label>
|
||||
{{ _('By Contest') }}
|
||||
<input name="tid" type="text" class="textbox" value="{{ filterTid }}">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="section">
|
||||
<div class="section__body no-padding">
|
||||
{% if not rdocs %}
|
||||
{% if not filterUidOrName and not filterPid and not filterTid %}
|
||||
{{ 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 -%}
|
||||
{% set udoc = udict[rdoc['uid']] %}
|
||||
{% set pdoc = pdict[rdoc['pid']] %}
|
||||
{% include 'record_main_tr.html' %}
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_VIEW_JUDGE_STATISTICS) %}
|
||||
<ul class="pager">
|
||||
<li>
|
||||
<a class="pager__item next link" href="?page={{ page + 1 }}&{{ 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>{{ _('5 Min')}}</dt><dd>{{ statistics['d5min'] }}</dd>
|
||||
<dt>{{ _('1 Hour')}}</dt><dd>{{ statistics['d1h'] }}</dd>
|
||||
<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,35 @@
|
||||
{% 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 handler.user.hasPerm(perm.PERM_REJUDGE) %}
|
||||
<form class="form--inline" method="post" action="{{ url('record_detail', rid=rdoc._id) }}">
|
||||
<input type="hidden" name="operation" value="rejudge">
|
||||
<input type="hidden" name="csrfToken" value="{{ handler.csrfToken }}">
|
||||
<button type="submit" class="link text-maroon lighter">
|
||||
<span class="icon icon-refresh"></span>
|
||||
{{ _('Rejudge') }}
|
||||
</button> |
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if pdoc and (not pdoc.hidden or handler.user.hasPerm(perm.PERM_VIEW_PROBLEM_HIDDEN)) %}
|
||||
{{ problem.render_problem_title(pdoc, show_tags=false) }}
|
||||
{% else %}
|
||||
*
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="col--submit-by">
|
||||
<a href="{{ url('user_detail', uid=rdoc.uid) }}">
|
||||
{% if udoc.displayName %}
|
||||
{{ udoc.displayName }} ({{ udoc.uname }})
|
||||
{% else %}
|
||||
{{ udoc.uname }}
|
||||
{% endif %}
|
||||
</a>
|
||||
</td>
|
||||
<td class="col--time">{% if rdoc['status'] == STATUS.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc.time|round|int }}ms</td>
|
||||
<td class="col--memory">{% if rdoc['status'] == STATUS.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == STATUS.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ size(rdoc.memory, 1024) }}</td>
|
||||
<td class="col--lang">{{ (model.system.get('lang.texts')|parseYaml)[rdoc['lang']] }}</td>
|
||||
<td class="col--submit-at">{{ datetimeSpan(rdoc['_id'])|safe }}</td>
|
||||
</tr>
|
||||
Loaded 100 of 564 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user