record_main & record_detail

This commit is contained in:
masnn committed 2020-04-04 12:14:10 +08:00
1 parent ffa193b5dd
commit 5b4f5b6520
37 files changed
+231 -275

No files matched your search

+2 -2
View File
@@ -21,7 +21,7 @@ class ForbiddenError extends UserFacingError {
}
class NotFoundError extends UserFacingError {
constructor(type) {
super(type);
super(type || 'NotFoundError');
this.code = 404;
}
}
@@ -107,7 +107,7 @@ class ContestNotFoundError extends NotFoundError {
module.exports = {
BadRequestError, ForbiddenError, NotFoundError,
LoginError, UserAlreadyExistError, InvalidTokenError,
UserNotFoundError, VerifyPasswordError,
UserNotFoundError, VerifyPasswordError,
OpcountExceededError, PermissionError, NoProblemError,
ValidationError, ProblemNotFoundError, TrainingNotFoundError,
ContestNotFoundError, RecordNotFoundError
+1
View File
@@ -44,6 +44,7 @@ MIDDLEWARE(async (ctx, next) => {
}
}
};
ctx.csrf_token = await token.add(token.TYPE_CSRF_TOKEN, 600, ctx.path);
console.log(ctx.session.uid);
await next();
if (ctx.session.sid)
+10 -1
View File
@@ -41,9 +41,18 @@ GET('/p/:pid', requirePerm(PERM_VIEW_PROBLEM), async ctx => {
ctx.templateName = 'problem_detail.html';
ctx.body = { pdoc, udoc, title: pdoc.title };
});
GET('/p/:pid/submit', requirePerm(PERM_SUBMIT_PROBLEM), async ctx => {
let uid = ctx.state.user._id,
pid = ctx.params.pid;
let pdoc = await problem.get({ pid, uid });
if (pdoc.hidden) ctx.checkPerm(PERM_VIEW_PROBLEM_HIDDEN);
let udoc = await user.getById(pdoc.owner);
ctx.templateName = 'problem_submit.html';
ctx.body = { pdoc, udoc, title: pdoc.title };
});
POST('/p/:pid/submit', requirePerm(PERM_SUBMIT_PROBLEM), async ctx => {
let rid = await record.add({
creator: ctx.state.user._id,
uid: ctx.state.user._id,
lang: ctx.request.body.language,
code: ctx.request.body.code,
pid: ctx.params.pid
+11 -2
View File
@@ -3,19 +3,28 @@ const
{ constants } = require('../options'),
{ GET } = require('../service/server'),
record = require('../model/record'),
user = require('../model/user'),
problem = require('../model/problem'),
{ PERM_READ_RECORD_CODE, PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD } = require('../permission');
GET('/r', async ctx => {
let q = {},
page = ctx.query.page || 1;
let rdocs = await record.getMany(q, { rid: 1 }, page, constants.RECORD_PER_PAGE);
ctx.body = { page, rdocs };
let pdict, udict;
for (let rdoc in rdocs) {
udict[rdoc.uid] = await user.getById(rdoc.uid);
pdict[rdoc.pid] = await problem.get({ pid: rdoc.pid, uid: ctx.state.user._id });
}
ctx.templateName = 'record_main.html';
ctx.body = { page, rdocs, pdict, udict };
});
GET('/r/:rid', async ctx => {
let uid = ctx.state.user._id, rid = new bson.ObjectID(ctx.params.rid);
let rdoc = await record.get(rid);
if (rdoc.hidden) ctx.checkPerm(PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
if (rdoc.creator != uid && !ctx.state.user.hasPerm(PERM_READ_RECORD_CODE)) rdoc.code = null;
if (rdoc.uid != uid && !ctx.state.user.hasPerm(PERM_READ_RECORD_CODE)) rdoc.code = null;
ctx.templateName = 'record_detail.html';
ctx.body = { rdoc };
});
+13 -9
View File
@@ -70,7 +70,8 @@ MIDDLEWARE(async (ctx, next) => {
ctx.render = async (name, context) => {
ctx.user = ctx.state.user;
ctx.translate = str => {
return str.translate(ctx.state.user.language);
if (!str) return '';
return str.toString().translate(ctx.state.user.language);
};
ctx.has_perm = perm => ctx.state.user.hasPerm(perm);
ctx.body = await new Promise((resolve, reject) => {
@@ -87,15 +88,18 @@ MIDDLEWARE(async (ctx, next) => {
try {
try {
await next();
if (!ctx.body) throw new NotFoundError();
if (ctx.query.template || ctx.templateName) {
Object.assign(ctx.body, JSON.parse(ctx.query.data || '{}'));
await ctx.render(ctx.query.template || ctx.templateName, ctx.body);
} else if (ctx.setRedirect) {
ctx.response.type = 'application/octet-stream';
ctx.redirect(ctx.setRedirect);
}
if (ctx.body || ctx.templateName) {
if (ctx.query.template || ctx.templateName) {
ctx.body = ctx.body || {};
Object.assign(ctx.body, JSON.parse(ctx.query.data || '{}'));
await ctx.render(ctx.query.template || ctx.templateName, ctx.body);
} else if (ctx.setRedirect) {
ctx.response.type = 'application/octet-stream';
ctx.redirect(ctx.setRedirect);
}
} else throw new NotFoundError();
} catch (error) {
console.log(error);
if (error.toString().startsWith('Template render error')) throw error;
await ctx.render('error.html', { error });
}
+3 -2
View File
@@ -1,5 +1,5 @@
const
{ GET, POST, CONTEXT } = require('../service/server.js'),
{ GET, POST } = require('../service/server.js'),
user = require('../model/user'),
token = require('../model/token'),
system = require('../model/system'),
@@ -30,7 +30,8 @@ POST('/login', async ctx => {
ctx.session.uid = udoc._id;
ctx.session.rememberme = rememberme;
ctx.body = {};
ctx.setRedirect = ctx.request.headers.referer || '/';
let referer = ctx.request.headers.referer || '/';
ctx.setRedirect = referer.endsWith('/login') ? '/' : referer;
});
POST('/logout', requirePerm(PERM_LOGGEDIN), async ctx => {
ctx.session = { uid: 1 };
+35 -1
View File
@@ -177,6 +177,40 @@ const FOOTER_EXTRA_HTMLS = [];
const VIEW_LANGS = [
{ code: 'zh-CN', name: 'zh-CN' }
];
const LANGS = [
{ id: 'cc', name: 'cpp' }
];
const LANG_TEXTS = {
c: 'C',
cc: 'C++',
cs: 'C#',
pas: 'Pascal',
java: 'Java',
py: 'Python',
py3: 'Python 3',
php: 'PHP',
rs: 'Rust',
hs: 'Haskell',
js: 'JavaScript',
go: 'Go',
rb: 'Ruby',
};
const LANG_HIGHLIGHT_ID = {
c: 'c',
cc: 'cpp',
cs: 'csharp',
pas: 'pascal',
java: 'java',
py: 'python',
py3: 'python',
php: 'php',
rs: 'rust',
hs: 'haskell',
js: 'javascript',
go: 'go',
rb: 'ruby',
};
module.exports = {
BUILTIN_USERS, BUILTIN_ROLES, CATEGORIES, VIEW_LANGS, FOOTER_EXTRA_HTMLS
BUILTIN_USERS, BUILTIN_ROLES, CATEGORIES, VIEW_LANGS, FOOTER_EXTRA_HTMLS, LANGS,
LANG_TEXTS, LANG_HIGHLIGHT_ID
};
+1
View File
@@ -4,6 +4,7 @@ const
module.exports = {
TYPE_SESSION: 0,
TYPE_CSRF_TOKEN: 1,
TYPE_REGISTER: 2,
/**
* Add a token.
+54 -54
View File
@@ -1,12 +1,12 @@
{% macro form_begin(args) %}
{% set label = args.pop('label') %}
{% set columns = args.pop('columns') %}
{% set last_column = args.pop('last_column', true) %}
{% set required = args.pop('required', false) %}
{% set hotkeys = args.pop('hotkeys', none) %}
{% set row = args.pop('row', true) %}
{% set no_label = args.pop('no_label', false) %}
{% set label_wrap = args.pop('label_wrap', true) %}
{% set label = args.label %}
{% set columns = args.columns %}
{% set last_column = args.last_column or true %}
{% set required = args.required or false %}
{% set hotkeys = args.hotkeys or none %}
{% set row = args.row or true %}
{% set no_label = args.no_label or false %}
{% set label_wrap = args.label_wrap or true %}
{% if row %}
<div class="row">
{% endif %}
@@ -27,10 +27,10 @@
{% endmacro %}
{% macro form_end(args) %}
{% set help_text = args.pop('help_text', none) %}
{% set row = args.pop('row', true) %}
{% set no_label = args.pop('no_label', false) %}
{% set label_wrap = args.pop('label_wrap', true) %}
{% set help_text = args.help_text or none %}
{% set row = args.row or true %}
{% set no_label = args.no_label or false %}
{% set label_wrap = args.label_wrap or true %}
{% if not no_label and label_wrap %}
</label>
{% endif %}
@@ -44,11 +44,11 @@
{% endmacro %}
{% macro form_attr(form_class, args) %}
{% set disabled = args.pop('disabled', false) %}
{% set required = args.pop('required', false) %}
{% set autofocus = args.pop('autofocus', false) %}
{% set date = args.pop('date', false) %}
{% set time = args.pop('time', false) %}
{% set disabled = args.disabled or false %}
{% set required = args.required or false %}
{% set autofocus = args.autofocus 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 %}
@@ -58,22 +58,22 @@
{% endmacro %}
{% macro container_attr(container_class, args) %}
{% set extra_class = args.pop('extra_class', none) %}
{% set extra_class = args.extra_class or none %}
class="{{ container_class }}{% if extra_class %} {{ extra_class }}{% endif %}"
{% endmacro %}
{% macro select(options, name='', value='', args) %}
{% macro select(args) %}
<div
name="form_item_{{ name }}"
name="form_item_{{ args.name }}"
{{ container_attr('select-container', args) }}
>
<select
name="{{ name }}"
name="{{ args.name }}"
{{ form_attr('select', args) }}
>
{% for k, v in options %}
<option value="{{ k }}"{% if value == k %} selected{% endif %}>
{{ _(v) }}
{% for item in args.options %}
<option value="{{ item.id }}"{% if value == item.id %} selected{% endif %}>
{{ _(item.name) }}
</option>
{% endfor %}
</select>
@@ -86,20 +86,20 @@
{{ form_end({columns:columns}|assign(args)) }}
{% endmacro %}
{% macro radio(options, name='', value='', args) %}
{% macro radio(args) %}
<div
name="form_item_{{ name }}"
name="form_item_{{ args.name }}"
{{ container_attr('radiobox-container', args) }}
>
{% for k, v in options %}
{% for item in options %}
<label class="radiobox">
<input
value="{{ k }}"
value="{{ item.id }}"
type="radio"
name="{{ name }}"
name="{{ args.name }}"
{{ form_attr('radiobox__input', args) }}
{% if value == k %} checked{% endif %}
/> {{ _(v) }}
{% if value == args.id %} checked{% endif %}
/> {{ _(item.name) }}
</label>
{% endfor %}
</div>
@@ -111,22 +111,22 @@
{{ form_end({columns:columns, label_warp:false}|assign(args)) }}
{% endmacro %}
{% macro image_radio(options, name='', value='', image_class='', args) %}
{% macro image_radio(args) %}
<div
name="form_item_{{ name }}"
name="form_item_{{ args.name }}"
{{ container_attr('radiobox-container with-image', args) }}
>
{% for k, v in options %}
{% for item in options %}
<label class="radiobox with-image">
<input
value="{{ k }}"
value="{{ item.id }}"
type="radio"
name="{{ name }}"
{{ form_attr('radiobox__input', args) }}
{% if value == k %} checked{% endif %}
{% if value == item.id %} checked{% endif %}
/>
<div class="radiobox__image-container" data-tooltip="{{ _(v) }}">
<div class="radiobox__image {{ image_class.format(k) }}"></div>
<div class="radiobox__image-container" data-tooltip="{{ _(item.name) }}">
<div class="radiobox__image {{ image_class.format(item.id) }}"></div>
</div>
</label>
{% endfor %}
@@ -139,16 +139,16 @@
{{ form_end({columns:columns, label_warp:false}|assign(args)) }}
{% endmacro %}
{% macro text(name='', value='', placeholder='', type='text', args) %}
{% macro text(args) %}
<div
name="form_item_{{ name }}"
name="form_item_{{ args.name }}"
{{ container_attr('textbox-container', args) }}
>
<input
type="{{ type }}"
name="{{ name }}"
value="{{ value }}"
placeholder="{{ placeholder }}"
type="{{ args.type or 'text' }}"
name="{{ args.name }}"
value="{{ args.value }}"
placeholder="{{ args.placeholder }}"
{{ form_attr('textbox', args) }}
>
</div>
@@ -160,18 +160,18 @@
{{ form_end({columns:columns}|assign(args)) }}
{% endmacro %}
{% macro textarea(name='', value='', placeholder='', args) %}
{% set markdown = args.pop('markdown', false) %}
{% macro textarea(args) %}
{% set markdown = args.markdown or false %}
<div
name="form_item_{{ name }}"
name="form_item_{{ args.name }}"
{{ container_attr('textarea-container', args) }}
>
<textarea
name="{{ name }}"
placeholder="{{ placeholder }}"
name="{{ args.name }}"
placeholder="{{ args.placeholder }}"
{% if markdown %}data-markdown{% endif %}
{{ form_attr('textbox', args) }}
>{{ value }}</textarea>
>{{ args.value }}</textarea>
</div>
{% endmacro %}
@@ -181,15 +181,15 @@
{{ form_end({columns:columns}|assign(args)) }}
{% endmacro %}
{% macro checkbox(label='', name='', value=false, args) %}
{% macro checkbox(args) %}
<div
name="form_item_{{ name }}"
name="form_item_{{ args.name }}"
{{ container_attr('checkbox-container', args) }}
>
<label class="checkbox">
<input type="checkbox" name="{{ name }}"{% if value %} checked{% endif %}
<input type="checkbox" name="{{ args.name }}"{% if args.value %} checked{% endif %}
{{ form_attr('checkbox', args) }}
>{{ _(label) }}
>{{ _(args.label) }}
</label>
</div>
{% endmacro %}
+5 -5
View File
@@ -1,12 +1,12 @@
{% macro render_status_td(rdoc, rid_key='_id') %}
<td class="col--status record-status--border {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}">
<td class="col--status record-status--border {{ status.STATUS_CODES[rdoc['status']] }}">
<div class="col--status__text">
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}"></span>
<a href="{{ reverse_url('record_detail', rid=rdoc[rid_key], domain_id=rdoc['domain_id']) }}" class="record-status--text {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}">
{{ vj4.constant.record.STATUS_TEXTS[rdoc['status']] }}
<span class="icon record-status--icon {{ status.STATUS_CODES[rdoc['status']] }}"></span>
<a href="{{ reverse_url('record_detail', rid=rdoc[rid_key], domain_id=rdoc['domain_id']) }}" class="record-status--text {{ status.STATUS_CODES[rdoc['status']] }}">
{{ status.STATUS_TEXTS[rdoc['status']] }}
</a>
</div>
{% if rdoc['status'] == vj4.constant.record.STATUS_JUDGING %}
{% 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>
+2 -2
View File
@@ -31,7 +31,7 @@
</div>
<div class="media__right middle">
<div class="section__body">
<a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" class="detail-button">{{ _('View Details') }}</a>
<a href="/t/{{ tdoc._id }}" class="detail-button">{{ _('View Details') }}</a>
<div class="typo text-center">
{% if tsdict[tdoc['doc_id']]['attend'] == 1 %}
<p><span class="icon icon-check"></span> {{ _('Attended') }}</p>
@@ -87,7 +87,7 @@
</div>
</div>
<div class="media__body medium">
<h1 class="contest__title"><a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
<h1 class="contest__title"><a href="/t/{{ tdoc._id }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
<ul class="supplementary list">
<li>
<a href="?rule={{ tdoc['rule'] }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ vj4.constant.contest.RULE_TEXTS[tdoc['rule']] }}</a>
+1 -1
View File
@@ -101,7 +101,7 @@
<div class="balancer sidebar-user-stat">
<div class="balancer__body">
<div class="numbox">
<div class="numbox__num medium">{{ dudict[ddoc['owner_uid']]['num_accept'] or 0 }}</div>
<div class="numbox__num medium">{{ dudict[ddoc['owner_uid']].nAccept or 0 }}</div>
<div class="numbox__text">{{ _('Accepted') }}</div>
</div>
</div>
+1 -1
View File
@@ -33,7 +33,7 @@
</div>
</div>
<div class="media__body medium">
<h1 class="contest__title"><a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
<h1 class="contest__title"><a href="/t/{{ tdoc._id }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
<ul class="supplementary list">
<li>
<a href="{{ reverse_url('contest_main') }}?rule={{ tdoc['rule'] }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ vj4.constant.contest.RULE_TEXTS[tdoc['rule']] }}</a>
+2 -4
View File
@@ -13,10 +13,8 @@
{% block content %}{% endblock %}
</div>
{% with show_topics = false %}
{% include "partials/footer.html" %}
{% endwith %}
{% set show_topics = false %}
{% include "partials/footer.html" %}
</div>
{% include "partials/login_dialog.html" %}
+4 -4
View File
@@ -2,7 +2,7 @@
{% import "components/contest.html" as contest with context %}
<div class="section side">
{% if page_name != 'contest_detail' %}
<a class="contest-sidebar__bg" href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">
<a class="contest-sidebar__bg" href="/t/{{ tdoc._id }}">
<div class="section__body">
<h1>{{ tdoc['title'] }}</h1>
<div class="contest-sidebar__status">
@@ -34,14 +34,14 @@
<li class="menu__seperator"></li>
{% endif %}
{% if page_name != 'contest_detail' %}
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">
<li class="menu__item"><a class="menu__link" href="/t/{{ tdoc._id }}">
<span class="icon icon-award"></span> {{ _('View Contest') }}
</a></li>
{% endif %}
{% if not attended and not handler.is_done(tdoc) %}
<li class="menu__item">
{% if handler.has_perm(perm.PERM_ATTEND_CONTEST) and handler.has_perm(perm.PERM_LOGGEDIN) %}
<form action="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" method="POST">
<form action="/t/{{ tdoc._id }}" method="POST">
<input type="hidden" name="operation" value="attend">
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
<button class="menu__link" type="submit">
@@ -78,7 +78,7 @@
<span class="icon icon-download"></span> {{ _('Export All Code') }}
</a></li>
{% endif %}
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('record_main') }}?tid={{ tdoc['doc_id'] }}">
<li class="menu__item"><a class="menu__link" href="/r?tid={{ tdoc['doc_id'] }}">
<span class="icon icon-flag"></span> {{ _('All Submissions') }}
</a></li>
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('wiki_help') }}#contest">
+1 -4
View File
@@ -10,7 +10,7 @@
</span>
</h1>
<div class="footer__category__expander"><ul class="footer__category__list">
<li class="footer__category__item"><a href="{{ reverse_url('record_main') }}">{{ _('Judging Queue') }}</a></li>
<li class="footer__category__item"><a href="/r">{{ _('Judging Queue') }}</a></li>
<li class="footer__category__item"><a href="#">{{ _('Service Status') }}</a></li>
</ul></div>
</div>
@@ -34,9 +34,6 @@
</span>
</h1>
<div class="footer__category__expander"><ul class="footer__category__list">
{% if domain_id != vj4.model.builtin.DOMAIN_ID_SYSTEM %}
<li class="footer__category__item"><a href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}">{{ _('Vijos') }}</a></li>
{% endif %}
<li class="footer__category__item"><a href="//vijos.github.io/about-vijos/">{{ _('Help') }}</a></li>
<!--<li class="footer__category__item"><a href="#">{{ _('Blog') }}</a></li>-->
<li class="footer__category__item"><a href="//vijos.github.io/about-vijos/about/contact-us/">{{ _('QQ Group') }}</a></li>
+1 -6
View File
@@ -2,12 +2,7 @@
<div class="header--mobile">
<div class="row"><div class="columns clearfix">
<div class="float-left">
{% if domain_id == vj4.model.builtin.DOMAIN_ID_SYSTEM %}
<a class="header--mobile__domain is--system" href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}" target="_self">&nbsp;</a>
{% else %}
<a class="header--mobile__domain" href="{{ reverse_url('domain_main') }}" target="_self">{{ domain['name'] }}</a>
<a class="header--mobile__system" href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}" target="_blank">Powered by Vijos</a>
{% endif %}
<a class="header--mobile__domain is--system" href="/" target="_self">&nbsp;</a>
</div>
<div class="float-right">
{% include "partials/hamburger.html" %}
+1 -1
View File
@@ -63,7 +63,7 @@
</a></li>
{% endif %}
{% if attended %}
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('record_main') }}?uid_or_name={{ handler.user['_id'] }}&tid={{ tdoc['doc_id'] }}">
<li class="menu__item"><a class="menu__link" href="/r?uid_or_name={{ handler.user['_id'] }}&tid={{ tdoc['doc_id'] }}">
<span class="icon icon-flag"></span> {{ _('My Recent Submissions') }}
</a></li>
{% endif %}
@@ -30,10 +30,10 @@
{% endif %}
{% if handler.own(pdoc, perm.PERM_EDIT_PROBLEM_SELF) or handler.has_perm(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="{{ reverse_url('problem_edit', pid=pdoc['_id']) }}">
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="/p/{{ pdoc.pid }}/edit">
<span class="icon icon-edit"></span> {{ _('Edit') }}
</a></li>
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="{{ reverse_url('problem_settings', pid=pdoc['_id']) }}">
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="/p/{{ pdoc.pid }}/settings">
<span class="icon icon-wrench"></span> {{ _('Settings') }}
</a></li>
{% endif %}
@@ -30,10 +30,10 @@
{% endif %}
{% if handler.own(pdoc, perm.PERM_EDIT_PROBLEM_SELF) or handler.has_perm(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="{{ reverse_url('problem_edit', pid=pdoc['_id']) }}">
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="/p/{{ pdoc.pid }}/edit">
<span class="icon icon-edit"></span> {{ _('Edit') }}
</a></li>
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="{{ reverse_url('problem_settings', pid=pdoc['_id']) }}">
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="/p/{{ pdoc.pid }}/settings">
<span class="icon icon-wrench"></span> {{ _('Settings') }}
</a></li>
{% endif %}
+13 -13
View File
@@ -39,7 +39,7 @@
</a></li>
{% endif %}
{% if handler.has_perm(perm.PERM_SUBMIT_PROBLEM) %}
<li class="menu__item scratchpad--hide"><a class="menu__link{% if page_name == 'problem_submit' %} active{% endif %}" href="{{ reverse_url('problem_submit', pid=pdoc['_id']) }}">
<li class="menu__item scratchpad--hide"><a class="menu__link{% if page_name == 'problem_submit' %} active{% endif %}" href="/p/{{ pdoc.pid }}/submit">
<span class="icon icon-send"></span> {{ _('Submit') }}
</a></li>
{% elif not handler.has_perm(perm.PERM_LOGGEDIN) %}
@@ -60,7 +60,7 @@
</a></li>
{% endif %}
{% if handler.has_perm(perm.PERM_VIEW_PROBLEM_SOLUTION) %}
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_solution' %} active{% endif %}" href="{{ reverse_url('problem_solution', pid=pdoc['_id']) }}">
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_solution' %} active{% endif %}" href="/p/{{ pdoc.pid }}/solution">
<span class="icon icon-comment--text"></span> {{ _('Solutions') }}
</a></li>
{% endif %}
@@ -72,10 +72,10 @@
{% endif %}
{% if handler.user._id == pdoc.owner or handler.has_perm(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="{{ reverse_url('problem_edit', pid=pdoc['_id']) }}">
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="/p/{{ pdoc.pid }}/edit">
<span class="icon icon-edit"></span> {{ _('Edit') }}
</a></li>
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="{{ reverse_url('problem_settings', pid=pdoc['_id']) }}">
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="/p/{{ pdoc.pid }}/settings">
<span class="icon icon-wrench"></span> {{ _('Settings') }}
</a></li>
{% endif %}
@@ -98,15 +98,15 @@
<dt>{{ _('Submission') }}</dt>
<dd>
{% if pdoc['psdoc']['status'] %}
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[pdoc['psdoc']['status']] }}"></span>
<a href="{{ reverse_url('record_detail', rid=pdoc['psdoc']['rid'], domain_id=pdoc['psdoc']['domain_id']) }}" class="record-status--text {{ vj4.constant.record.STATUS_CODES[pdoc['psdoc']['status']] }}">
{{ vj4.constant.record.STATUS_TEXTS[pdoc['psdoc']['status']] }}
<span class="icon record-status--icon {{ status.STATUS_CODES[pdoc['psdoc']['status']] }}"></span>
<a href="/r/{{ pdoc['psdoc']['rid'] }}" class="record-status--text {{ status.STATUS_CODES[pdoc['psdoc']['status']] }}">
{{ status.STATUS_TEXTS[pdoc['psdoc']['status']] }}
</a>
{% else %}
{{ _('(None)') }}
{% endif %}
</dd>
{% if pdoc['ac_msg'] and pdoc['psdoc']['status'] == vj4.constant.record.STATUS_ACCEPTED %}
{% if pdoc['ac_msg'] and pdoc['psdoc']['status'] == status.STATUS_ACCEPTED %}
<dt>{{ _('AC Message') }}</dt>
<dd>{{ pdoc['ac_msg'] }}</dd>
{% endif %}
@@ -141,17 +141,17 @@
{{ problem.render_problem_tags(pdoc, true) }}
</dd>
<dt>{{ _('# Submissions') }}</dt>
<dd><a href="{{ reverse_url('record_main') }}?pid={{ pdoc['_id'] }}">{{ pdoc['num_submit'] }}</a></dd>
<dd><a href="/r?pid={{ pdoc['_id'] }}">{{ pdoc.nSubmit }}</a></dd>
{% if page_name != 'discussion_node' and page_name != 'discussion_detail' %}
{% if handler.has_perm(perm.PERM_LOGGEDIN) %}
<dt>{{ _('# My Submissions') }}</dt>
<dd><a href="{{ reverse_url('record_main') }}?pid={{ pdoc['_id'] }}&uid_or_name={{ handler.user['_id'] }}">{{ pdoc['psdoc']['num_submit']|default(0) }}</a></dd>
<dd><a href="/r?pid={{ pdoc['_id'] }}&uid_or_name={{ handler.user['_id'] }}">{{ pdoc['psdoc'].nSubmit|default(0) }}</a></dd>
{% endif %}
{% endif %}
<dt>{{ _('Accepted') }}</dt>
<dd>{{ pdoc['num_accept'] }}</dd>
<dd>{{ pdoc.nAccept }}</dd>
<dt>{{ _('Accepted Ratio') }}</dt>
<dd>{% if pdoc['num_submit'] > 0 %}{{ (100 * pdoc['num_accept'] / pdoc['num_submit'])|round|int }}%{% else %}{{ _('?') }}{% endif %}</dd>
<dd>{% if pdoc.nSubmit > 0 %}{{ (100 * pdoc.nAccept / pdoc.nSubmit)|round|int }}%{% else %}{{ _('?') }}{% endif %}</dd>
{% if pdoc['num_be_copied'] %}
<dt>{{ _('Be Copied') }}</dt>
<dd>{{ pdoc['num_be_copied'] }}</dd>
@@ -178,7 +178,7 @@
{% if ctdocs %}
<p>{{ _('In following contests') }}: </p>
{% for tdoc in ctdocs %}
<p><a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">{{ tdoc['title'] }}</a></p>
<p><a href="/t/{{ tdoc._id }}">{{ tdoc['title'] }}</a></p>
{% endfor %}
{% endif %}
{% if htdocs %}
+1 -1
View File
@@ -59,7 +59,7 @@
</div>
<div class="medium-3 columns">
{% if page_name == 'problem_edit' %}
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
{% set owner_udoc=udoc %}{% set owner_dudoc=dudoc %}
{% include "partials/problem_sidebar.html" %}
{% endwith %}
{% else %}
@@ -8,8 +8,8 @@
<div class="row">
<div class="medium-8 columns">
<label>
{{ _('Copy from') }}
<input name="src_domain_id" placeholder="{{ _('Domain ID') }}" class="textbox" autocomplete="off">
{{ _('Import from') }}
<input name="src" placeholder="{{ _('Source') }}" class="textbox" autocomplete="off">
</label>
</div>
<div class="medium-2 columns">
@@ -17,7 +17,7 @@
{{ _('Settings') }}
<br>
<label class="checkbox">
<input type="checkbox" name="numeric_pid" value="on" checked>{{ _('Numeric PID') }}
<input name="src" placeholder="{{ _('ProblemID') }}" class="textbox" autocomplete="off">
</label>
</label>
</div>
@@ -32,8 +32,8 @@
</div>
<div class="row"><div class="columns">
<label>
{{ _('Problem ID List') }}
<textarea name="src_pids" class="textbox" style="height: 300px"></textarea>
{{ _('Source URL') }}
<textarea name="src" class="textbox" style="height: 300px"></textarea>
</label>
</div></div>
<div class="row"><div class="columns">
@@ -52,10 +52,10 @@
<div class="medium-3 columns">
<div class="section side">
<div class="section__body typo">
<h2>{{ _('What\'s this?') }}</h2>
<p>{{ _('With this feature, you can copy problems that you can view from a domain to some other domain. Their title, content, tags and categories will be copied. However, their test data are not copied directly.') }}</p>
<h2>{{ _('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>
<h2>{{ _('About test data') }}</h2>
<p>{{ _('Instead of copying the test data directly, the test data of the copied problems will be linked to the test data of the source problems (called the source test data). Thus, the copied problems can observe the changes in the source test data. The permissions of the test data of the copied problems follow the source test data, e.g., you still might not download them but the judges can. By uploading some new test data, the link will be broken and the new test data will be used.') }}</p>
<p>{{ _('Instead of copying the test data directly, the test data of the import problems will be linked to the test data of the source problems (called the source test data). Thus, the copied problems can observe the changes in the source test data. The permissions of the test data of the copied problems follow the source test data, e.g., you still might not download them but the judges can. By uploading some new test data, the link will be broken and the new test data will be used.') }}</p>
</div>
</div>
</div>
+2 -2
View File
@@ -10,7 +10,7 @@
<iframe src="{{ reverse_url('problem_upload', pid=pdoc['_id']) }}" frameborder="0" style="width: 100%; height: 100px;"></iframe>
<p class="help-text">{{ _('Hint') }}: <a href="{{ reverse_url('wiki_help') }}#upload">{{ _('Dataset Format') }}</a>, {{ _('An example of dataset') }}: <a href="https://github.com/vijos/jd4/blob/master/jd4/testdata/aplusb-legacy.zip?raw=true">{{ _('Download') }}</a></p>
{% if pdoc and (handler.own(pdoc, perm.PERM_READ_PROBLEM_DATA_SELF) or handler.has_perm(perm.PERM_READ_PROBLEM_DATA) or handler.has_priv(vj4.model.builtin.PRIV_READ_PROBLEM_DATA)) %}
<p><a href="{{ reverse_url('problem_data', pid=pdoc['_id']) }}" class="expanded button">{{ _('Download Dataset') }}</a></p>
<p><a href="/p/{{ pdoc.pid }}/data" class="expanded button">{{ _('Download Dataset') }}</a></p>
{% endif %}
</div>
</div>
@@ -65,7 +65,7 @@
</div>
</div>
<div class="medium-3 columns">
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
{% set owner_udoc=udoc %}{% set owner_dudoc=dudoc %}
{% include "partials/problem_sidebar.html" %}
{% endwith %}
</div>
+1 -1
View File
@@ -12,7 +12,7 @@
</div>
</div>
<div class="medium-3 columns">
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
{% set owner_udoc=udoc %}{% set owner_dudoc=dudoc %}
{% include "partials/problem_sidebar.html" %}
{% endwith %}
</div>
+3 -3
View File
@@ -1,3 +1,4 @@
{% set page_name = "problem_submit" %}
{% extends "layout/basic.html" %}
{% block content %}
<div class="row">
@@ -44,7 +45,7 @@
</div>
<div class="section__body">
<form method="post">
{{ form.form_select(label='Code language', options=vj4.constant.language.LANG_TEXTS.items(), name='lang', value=handler.get_setting('code_lang')) }}
{{ form.form_select(label='Code language', options=builtin.LANGS, 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="csrf_token" value="{{ handler.csrf_token }}">
@@ -55,9 +56,8 @@
</div>
</div>
<div class="medium-3 columns">
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
{% set owner_udoc=udoc %}{% set owner_dudoc=dudoc %}
{% include "partials/problem_sidebar.html" %}
{% endwith %}
</div>
</div>
+2 -2
View File
@@ -9,10 +9,10 @@
{% endif %}
</td>
<td class="col--memory">
{{ (rdoc['memory_kb'] / 1000)|round(0, 'ceil')|int }} MB
{{ (rdoc.memory / 1000)|round(0, 'ceil')|int }} MB
</td>
<td class="col--time">
{{ (rdoc['time_ms'] / 1000)|round(1) }}s
{{ (rdoc.time / 1000)|round(1) }}s
</td>
<td class="col--submit-at">{{ datetime_span(rdoc['_id'].generation_time) }}</td>
</tr>
+2 -2
View File
@@ -1,8 +1,8 @@
{% extends 'layout/simple.html' %}
{% block body %}
<form method="post" enctype="multipart/form-data">
{% if pdoc['data'] is mapping %}
<p><b>{{ _('Current dataset comes from') }} <a href="{{ reverse_url('problem_detail', domain_id=pdoc['data']['domain'], pid=pdoc['data']['pid']) }}" target="_blank">{{ pdoc['data']['domain'] }}/{{ pdoc['data']['pid'] }}</a></b></p>
{% if pdoc['data'].startsWith('from:') %}
<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']|default(_('(None)'))) }}</p>
<p>{{ _('MD5: {0}').format(md5|default(_('(None)'))) }}</p>
+9 -8
View File
@@ -2,9 +2,9 @@
{% import "components/problem.html" as problem with context %}
{% block content %}
<script>
var Context = {{ {
'socketUrl': socket_url,
}|json|safe }};
var Context = {
'socketUrl': "{{ socket_url }}",
};
</script>
<div class="row">
<div class="medium-9 columns">
@@ -17,7 +17,7 @@
<h1 class="section__title">{{ _('Code') }}</h1>
</div>
<div class="section__body" data-syntax-hl-show-line-number>
<pre><code class="language-{{ vj4.constant.language.LANG_HIGHLIGHT_ID[rdoc['lang']] }}">{{ rdoc['code'] }}</code></pre>
<pre><code class="language-{{ builtin.LANG_HIGHLIGHT_ID[rdoc['lang']] }}">{{ rdoc['code'] }}</code></pre>
</div>
</div>
{% endif %}
@@ -31,7 +31,7 @@
<div class="section__body no-padding">
<ol class="menu">
<li class="menu__item">
<form method="post" action="{{ reverse_url('record_rejudge', rid=rdoc['_id']) }}">
<form method="post" action="/r/{{ rdoc._id }}/rejudge">
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
<button type="submit" class="menu__link">
<span class="icon icon-refresh"></span> {{ _('Rejudge') }}
@@ -39,7 +39,8 @@
</form>
</li>
<li class="menu__item">
<form method="post" action="{{ reverse_url('judge_score', rid=rdoc['_id']) }}">
<form method="post" action="/judge/end">
<input type="hidden" name="rid" value="{{ rdoc._id }}">
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
<input type="hidden" name="score" value="0">
<input type="hidden" name="message" value="{{ _('score canceled') }}">
@@ -67,7 +68,7 @@
{% if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST %}
<dt>{{ _('Contest') }}</dt>
<dd>
<a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">{{ tdoc['title'] }}</a>
<a href="/t/{{ tdoc._id }}">{{ tdoc['title'] }}</a>
</dd>
{% else %}{# tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST #}
<dt>{{ _('Homework') }}</dt>
@@ -81,7 +82,7 @@
<dd><a href="{{ reverse_url('record_pretest_data', rid=rdoc['_id']) }}"><span class="icon icon-download"></span> {{ _('Download') }}</a></dd>
{% elif rdoc['type'] == vj4.constant.record.TYPE_SUBMISSION and pdoc and (handler.own(pdoc, perm.PERM_READ_PROBLEM_DATA_SELF) or handler.has_perm(perm.PERM_READ_PROBLEM_DATA) or handler.has_priv(vj4.model.builtin.PRIV_READ_PROBLEM_DATA)) %}
<dt>{{ _('Problem Data') }}</dt>
<dd><a href="{{ reverse_url('problem_data', pid=pdoc['_id']) }}"><span class="icon icon-download"></span> {{ _('Download') }}</a></dd>
<dd><a href="/p/{{ pdoc.pid }}/data"><span class="icon icon-download"></span> {{ _('Download') }}</a></dd>
{% endif %}
<dt>{{ _('Language') }}</dt>
<dd>
+12 -12
View File
@@ -1,18 +1,18 @@
<div class="section visible" id="status">
<div class="section__header">
<h1 class="section__title">
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}"></span>
<span class="record-status--text {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}">
{{ vj4.constant.record.STATUS_TEXTS[rdoc['status']] }}
<span class="icon record-status--icon {{ status.STATUS_CODES[rdoc['status']] }}"></span>
<span class="record-status--text {{ status.STATUS_CODES[rdoc['status']] }}">
{{ status.STATUS_TEXTS[rdoc['status']] }}
</span>
</h1>
</div>
<div class="section__body">
<pre class="compiler-text">{{ rdoc['compiler_texts']|join('\n') }}</pre>
<pre class="compiler-text">{{ rdoc.compilerTexts|join('\n') }}</pre>
</div>
{% if rdoc['judge_texts'] %}
{% if rdoc.judgeTexts %}
<div class="section__body">
<pre class="judge-text">{{ rdoc['judge_texts']|join('\n') }}</pre>
<pre class="judge-text">{{ rdoc.judgeTexts|join('\n') }}</pre>
</div>
{% endif %}
{% if rdoc['cases'] %}
@@ -35,19 +35,19 @@
<tbody>
{% for rcdoc in rdoc['cases'] %}
<tr>
<td class="col--case record-status--border {{ vj4.constant.record.STATUS_CODES[rcdoc['status']] }}">
<td class="col--case record-status--border {{ status.STATUS_CODES[rcdoc['status']] }}">
#{{ loop.index }}
</td>
<td class="col--status">
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[rcdoc['status']] }}"></span>
<span class="record-status--text {{ vj4.constant.record.STATUS_CODES[rcdoc['status']] }}">
{{ vj4.constant.record.STATUS_TEXTS[rcdoc['status']] }}
<span class="icon record-status--icon {{ status.STATUS_CODES[rcdoc['status']] }}"></span>
<span class="record-status--text {{ status.STATUS_CODES[rcdoc['status']] }}">
{{ status.STATUS_TEXTS[rcdoc['status']] }}
</span>
<span>{{ rcdoc['judge_text'] }}</span>
<a class="tool-button" href="{{ reverse_url('wiki_help') }}#status"><span class="icon icon-help"></span></a>
</td>
<td class="col--time">{% if rcdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}&ge;{% endif %}{{ rcdoc['time_ms'] }}ms</td>
<td class="col--memory">{% if rcdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}&ge;{% endif %}{{ rcdoc['memory_kb']|format_size(1024) }}</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 %}&ge;{% endif %}{{ rcdoc['time_ms'] }}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 %}&ge;{% endif %}{{ rcdoc['memory_kb']|format_size(1024) }}</td>
</tr>
{% endfor %}
</tbody>
+2 -2
View File
@@ -4,7 +4,7 @@
<dd>{{ rdoc['score'] }}</dd>
{% endif %}
<dt>{{ _('Total Time') }}</dt>
<dd>{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}&ge;{% endif %}{{ rdoc['time_ms'] }}ms</dd>
<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 %}&ge;{% endif %}{{ rdoc.time }}ms</dd>
<dt>{{ _('Peak Memory') }}</dt>
<dd>{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}&ge;{% endif %}{{ rdoc['memory_kb']|format_size(1024) }}</dd>
<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 %}&ge;{% endif %}{{ rdoc.memory|format_size(1024) }}</dd>
</dl>
+8 -7
View File
@@ -1,9 +1,10 @@
{% set page_name = "record_main" %}
{% extends "layout/basic.html" %}
{% block content %}
<script>
var Context = {{ {
'socketUrl': socket_url,
}|json|safe }};
var Context = {
'socketUrl': "/socket/{{ socket_url }}",
};
</script>
<div class="row">
<div class="medium-12 columns">
@@ -13,7 +14,7 @@
<h1 class="section__title">{{ _('Filter') }}</h1>
<div class="section__tools">
<button type="submit" class="primary button"><span class="icon icon-filter"></span> {{ _('Filter') }}</button>
<a href="{{ reverse_url('record_main') }}" class="button">{{ _('Reset') }}</a>
<a href="/r" class="button">{{ _('Reset') }}</a>
</div>
</div>
<div class="section__body">
@@ -73,13 +74,13 @@
</thead>
<tbody>
{% for rdoc in rdocs %}
{% with udoc = udict[rdoc['uid']], dudoc = dudict[rdoc['uid']], pdoc = pdict[(rdoc['domain_id'], rdoc['pid'])] %}
{% set udoc = udict[rdoc['uid']] %}
{% set pdoc = pdict[rdoc['pid']] %}
{% include 'record_main_tr.html' %}
{% endwith %}
{% endfor %}
</tbody>
</table>
{% if handler.has_priv(vj4.model.builtin.PRIV_VIEW_JUDGE_STATISTICS) %}
{% if handler.has_perm(perm.PERM_VIEW_JUDGE_STATISTICS) %}
<ul class="pager">
<li>
<a class="pager__item next link" href="?start={{ rdocs[-1]['_id'] }}&{{ query_string }}">{{ _('pager_next') }}</a>
+7 -11
View File
@@ -3,8 +3,8 @@
<tr data-rid="{{ rdoc['_id'] }}">
{{ record.render_status_td(rdoc) }}
<td class="col--problem col--problem-name">
{% if (rdoc['domain_id'] == handler.domain_id and handler.has_perm(perm.PERM_REJUDGE)) or handler.has_priv(vj4.model.builtin.PRIV_REJUDGE) %}
<form class="form--inline" method="post" action="{{ reverse_url('record_rejudge', rid=rdoc['_id']) }}">
{% if = handler.has_perm(perm.PERM_REJUDGE) %}
<form class="form--inline" method="post" action="/r/{{ rdoc._id }}/rejudge">
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
<button type="submit" class="link text-maroon lighter">
<span class="icon icon-refresh"></span>
@@ -15,23 +15,19 @@
{% if rdoc['type'] == vj4.constant.record.TYPE_PRETEST %}
({{ _('Pretest') }})
{% endif %}
{% if pdoc and (not pdoc['hidden'] or (pdoc['domain_id'] == handler.domain_id and handler.has_perm(perm.PERM_VIEW_PROBLEM_HIDDEN))) %}
{% if pdoc and (not pdoc['hidden'] or handler.has_perm(perm.PERM_VIEW_PROBLEM_HIDDEN)) %}
{{ problem.render_problem_title(pdoc, show_tags=false) }}
{% else %}
*
{% endif %}
</td>
<td class="col--submit-by">
<a href="{{ reverse_url('user_detail', uid=rdoc['uid']) }}">
{% if dudoc['display_name'] %}
{{ dudoc['display_name'] }} ({{ udoc['uname'] }})
{% else %}
{{ udoc['uname'] }}
{% endif %}
<a href="/u/{{ rdoc.uid }}">
{{ udoc['uname'] }}
</a>
</td>
<td class="col--time">{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}&ge;{% endif %}{{ rdoc['time_ms'] }}ms</td>
<td class="col--memory">{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}&ge;{% endif %}{{ rdoc['memory_kb']|format_size(1024) }}</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 %}&ge;{% endif %}{{ rdoc.time }}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 %}&ge;{% endif %}{{ rdoc.memory|format_size(1024) }}</td>
<td class="col--lang">{{ vj4.constant.language.LANG_TEXTS[rdoc['lang']] }}</td>
<td class="col--submit-at">{{ datetime_span(rdoc['_id'].generation_time) }}</td>
</tr>
-87
View File
@@ -1,87 +0,0 @@
{% macro form_begin(kwargs) %}
{% set label = kwargs.pop('label') %}
{% set columns = kwargs.pop('columns') %}
{% set last_column = kwargs.pop('last_column', true) %}
{% set required = kwargs.pop('required', false) %}
{% set hotkeys = kwargs.pop('hotkeys', none) %}
{% set row = kwargs.pop('row', true) %}
{% set no_label = kwargs.pop('no_label', false) %}
{% set label_wrap = kwargs.pop('label_wrap', true) %}
{% if row %}
<div class="row">
{% endif %}
<div
class="{% if columns %}medium-{{ columns }} {% endif %}columns form__item{% if last_column %} end{% endif %}"
{% if hotkeys %}data-hotkey="{{ hotkeys }}"{% endif %}
>
{% if not no_label %}
<label>
{{ _(label) }}
{% if required %}
({{ _('required') }})
{% endif %}
{% if not label_wrap %}
</label>
{% endif %}
{% endif %}
{% endmacro %}
{% macro form_end(kwargs) %}
{% set help_text = kwargs.pop('help_text', none) %}
{% set row = kwargs.pop('row', true) %}
{% set no_label = kwargs.pop('no_label', false) %}
{% set label_wrap = kwargs.pop('label_wrap', true) %}
{% if not no_label and label_wrap %}
</label>
{% endif %}
{% if help_text %}
<p class="help-text">{{ _(help_text)|safe }}</p>
{% endif %}
</div>
{% if row %}
</div>
{% endif %}
{% endmacro %}
{% macro form_attr(form_class, kwargs) %}
{% set disabled = kwargs.pop('disabled', false) %}
{% set required = kwargs.pop('required', false) %}
{% set autofocus = kwargs.pop('autofocus', false) %}
{% set date = kwargs.pop('date', false) %}
{% set time = kwargs.pop('time', false) %}
class="{{ form_class }}{% if extra_class %} {{ extra_class }}{% endif %}"
{% if disabled %}disabled{% endif %}
{% if required %}required{% endif %}
{% if autofocus %}autofocus data-autofocus{% endif %}
{% if date %}data-pick-date{% endif %}
{% if time %}data-pick-time{% endif %}
{% endmacro %}
{% macro container_attr(container_class, kwargs) %}
{% set extra_class = kwargs.pop('extra_class', none) %}
class="{{ container_class }}{% if extra_class %} {{ extra_class }}{% endif %}"
{% endmacro %}
{% macro select(options, name='', value='', kwargs) %}
<div
name="form_item_{{ name }}"
{{ container_attr('select-container', kwargs) }}
>
<select
name="{{ name }}"
{{ form_attr('select', kwargs) }}
>
{% for k, v in options %}
<option value="{{ k }}"{% if value == k %} selected{% endif %}>
{{ _(v) }}
</option>
{% endfor %}
</select>
</div>
{% endmacro %}
{% macro form_select(columns=5) %}
{{ form_begin({columns:1, ...kwargs}, kwargs) }}
{{ select(columns=columns, kwargs) }}
{{ form_end(columns=columns, kwargs) }}
{% endmacro %}
+3 -3
View File
@@ -126,11 +126,11 @@
pdoc,
invalid=not tsdoc['enroll'],
show_tags=false,
rp=vj4.job.rp.get_rp_expect(pdoc) if (not psdoc or psdoc['status'] != vj4.constant.record.STATUS_ACCEPTED) else none
rp=vj4.job.rp.get_rp_expect(pdoc) if (not psdoc or psdoc['status'] != status.STATUS_ACCEPTED) else none
) }}
</td>
<td class="col--submit_n">{{ pdoc['num_submit'] }}</td>
<td class="col--ac_rate">{{ (100 * pdoc['num_accept'] / pdoc['num_submit'])|round|int if pdoc['num_submit'] > 0 else _('?') }}</td>
<td class="col--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>
{% endwith %}
+5 -10
View File
@@ -12,12 +12,7 @@
</div>
<div class="media__body profile-header__main">
<h1>
{% if dudoc['display_name'] %}
{{ dudoc['display_name'] }}
<small>{{ udoc['uname'] }}</small>
{% else %}
{{ udoc['uname'] }}
{% endif %}
{{ udoc['uname'] }}
<small>({{ _('UID') }}: {{ udoc['_id'] }})</small>
</h1>
<p>
@@ -29,14 +24,14 @@
{{ _('currently offline') }}.
{% endif %}
</p>
<p>{{ _('Solved {0} problems, RP: {1} (No. {2})').format(dudoc['num_accept']|default(0), dudoc['rp']|default(0.0)|round(2), dudoc['rank']|default('?')) }}</p>
<p>{{ _('Solved {0} problems, RP: {1} (No. {2})').format(dudoc.nAccept|default(0), dudoc['rp']|default(0.0)|round(2), dudoc['rank']|default('?')) }}</p>
<div class="profile-header__contact-bar">
{% if is_self_profile %}
<a class="profile-header__contact-item" href="{{ reverse_url('home_account') }}#setting_info" data-tooltip="{{ _('Edit Profile') }}">
<span class="icon icon-edit"></span>
</a>
{% endif %}
<a class="profile-header__contact-item" href="{{ reverse_url('home_messages') }}?target_uid={{ udoc['_id'] }}" target="_blank" data-tooltip="{{ _('Send Message') }}">
<a class="profile-header__contact-item" href="/home/messages?target_uid={{ udoc['_id'] }}" target="_blank" data-tooltip="{{ _('Send Message') }}">
<span class="icon icon-comment--multiple"></span>
</a>
{% if handler.can_view(udoc, 'mail') and udoc['mail'] %}
@@ -137,7 +132,7 @@
</div>
</li>
<li class="section__tab-item">
<h1 class="section__tab-title">{{ _('Submissions') }} ({{ dudoc['num_submit']|default(0) }})</h1>
<h1 class="section__tab-title">{{ _('Submissions') }} ({{ dudoc.nSubmit|default(0) }})</h1>
<div class="section__tab-main">
{% if not rdocs %}
{{ nothing.render('Oh, the user hasn\'t submitted yet!') }}
@@ -193,7 +188,7 @@
<div class="balancer sidebar-user-stat">
<div class="balancer__body">
<div class="numbox">
<div class="numbox__num medium">{{ dudoc['num_accept'] or 0 }}</div>
<div class="numbox__num medium">{{ dudoc.nAccept or 0 }}</div>
<div class="numbox__text">{{ _('Accepted') }}</div>
</div>
</div>
+1
View File
@@ -1,3 +1,4 @@
{% set page_name = "user_login" %}
{% extends "layout/immersive.html" %}
{% block content %}
<div class="row"><div class="columns">