mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 09:46:28 +08:00
Merge branch 'master' into scoreboard_ui
This commit is contained in:
75 files changed
+967
-856
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import AnsiUp from 'ansi_up';
|
||||
import { moment, ObjectID } from 'hydrooj';
|
||||
import { moment, ObjectId } from 'hydrooj';
|
||||
|
||||
export { size, formatSeconds } from 'hydrooj';
|
||||
|
||||
@@ -10,10 +10,10 @@ export function ansiToHtml(str: string, whiteToBlack = true) {
|
||||
return whiteToBlack ? res.replace(/style="color:rgb\(255,255,255\)"/g, 'style="color:black"') : res;
|
||||
}
|
||||
|
||||
export function datetimeSpan(dt: Date | ObjectID, relative = true, format = 'YYYY-M-D H:mm:ss', tz = 'Asia/Shanghai') {
|
||||
export function datetimeSpan(dt: Date | ObjectId, relative = true, format = 'YYYY-M-D H:mm:ss', tz = 'Asia/Shanghai') {
|
||||
if (!dt) return 'DATETIME_SPAN_ERROR';
|
||||
if (dt instanceof ObjectID) dt = dt.getTimestamp();
|
||||
else if (typeof dt === 'string' && ObjectID.isValid(dt)) dt = new Date(new ObjectID(dt).generationTime * 1000);
|
||||
if (dt instanceof ObjectId) dt = dt.getTimestamp();
|
||||
else if (typeof dt === 'string' && ObjectId.isValid(dt)) dt = new ObjectId(dt).getTimestamp();
|
||||
else if (typeof dt === 'number' || typeof dt === 'string') dt = new Date(dt);
|
||||
return '<span class="time{0}" data-timestamp="{1}">{2}</span>'.format(
|
||||
relative ? ' relative' : '',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable global-require */
|
||||
import {
|
||||
ContestModel, Context, Handler, ObjectID, param, PERM, PRIV, ProblemModel, Schema,
|
||||
ContestModel, Context, Handler, ObjectId, param, PERM, PRIV, ProblemModel, Schema,
|
||||
SettingModel, SystemModel, SystemSettings, Types, UserModel,
|
||||
} from 'hydrooj';
|
||||
import convert from 'schemastery-jsonschema';
|
||||
@@ -106,7 +106,7 @@ class RichMediaHandler extends Handler {
|
||||
async renderContest(domainId, payload) {
|
||||
const cur = payload.domainId ? await UserModel.getById(payload.domainId, this.user._id) : this.user;
|
||||
const tdoc = cur.hasPerm(PERM.PERM_VIEW | PERM.PERM_VIEW_CONTEST)
|
||||
? await ContestModel.get(payload.domainId || domainId, new ObjectID(payload.id))
|
||||
? await ContestModel.get(payload.domainId || domainId, new ObjectId(payload.id))
|
||||
: null;
|
||||
if (tdoc) return await this.renderHTML('partials/contest.html', { tdoc });
|
||||
return '';
|
||||
@@ -115,7 +115,7 @@ class RichMediaHandler extends Handler {
|
||||
async renderHomework(domainId, payload) {
|
||||
const cur = payload.domainId ? await UserModel.getById(payload.domainId, this.user._id) : this.user;
|
||||
const tdoc = cur.hasPerm(PERM.PERM_VIEW | PERM.PERM_VIEW_HOMEWORK)
|
||||
? await ContestModel.get(payload.domainId || domainId, new ObjectID(payload.id))
|
||||
? await ContestModel.get(payload.domainId || domainId, new ObjectId(payload.id))
|
||||
: null;
|
||||
if (tdoc) return await this.renderHTML('partials/homework.html', { tdoc });
|
||||
return '';
|
||||
|
||||
@@ -87,7 +87,6 @@ Begin Time: 시작 시각
|
||||
Belongs to: 소유
|
||||
Bio Visibility: 소개 공개
|
||||
Bio: 소개
|
||||
Blog: Blog
|
||||
Bold: 굵게
|
||||
Boom!: 펑!
|
||||
Browser: 브라우저
|
||||
|
||||
@@ -41,7 +41,6 @@ __langname: 简体中文
|
||||
'Solved {0} problems, RP: {1} (No. {2})': '解决了 {0} 道题目,RP: {1} (No. {2})'
|
||||
'The value `{1}` of {0} already exists.': '{0} 的值 `{1}` 已经存在。'
|
||||
'Yes': 是
|
||||
"{0}'s blog": "{0} 的博客"
|
||||
"Effects only when Difficulty is not 'Use algorithm calculated'.": 仅当难度不为“使用算法计算”时才起效。
|
||||
"Split by ', '.": 由“, ”或“,”分隔。
|
||||
"What's file?": 什么是文件?
|
||||
@@ -81,7 +80,7 @@ All Submissions: 所有递交
|
||||
All Training Plans: 所有训练计划
|
||||
All Users: 所有用户
|
||||
All: 全部
|
||||
Allow to maintain this contest: 允许管理此比赛
|
||||
Allow to maintain this {0}: 允许管理此{0}
|
||||
Allow user view others code after contest: 允许用户赛后查看其他人的代码
|
||||
Always granted all privileges: 总是拥有所有权限
|
||||
An error has occurred.: 发生了一个错误。
|
||||
@@ -112,7 +111,6 @@ Begin Time: 开始时间
|
||||
Belongs to: 属于
|
||||
Bio Visibility: 个人简介可见性
|
||||
Bio: 个人简介
|
||||
Blog: 博客
|
||||
Bold: 加粗
|
||||
Boom!: 炸了!
|
||||
Browser: 浏览器
|
||||
@@ -406,6 +404,7 @@ home_preference: 偏好设置
|
||||
home_security: 安全设置
|
||||
homepage: 首页
|
||||
Homework Introduction: 作业介绍
|
||||
Homework Maintainer: 作业管理员
|
||||
Homework scoreboard is not visible.: 目前无法查看作业成绩表。
|
||||
homework_create: 创建作业
|
||||
homework_detail_problem_submit: 递交作业题目
|
||||
|
||||
@@ -52,7 +52,6 @@ Begin Time: 開始時間
|
||||
Belongs to: 屬於
|
||||
Bio Visibility: 個人簡介可見性
|
||||
Bio: 個人簡介
|
||||
Blog: 部落格
|
||||
Boom!: 炸了!
|
||||
Browser: 瀏覽器
|
||||
Built-in: 內建
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi_up": "^5.1.0",
|
||||
"esbuild": "0.16.16",
|
||||
"esbuild": "0.17.10",
|
||||
"fs-extra": "^11.1.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsesc": "^3.0.2",
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
{% extends "layout/basic.html" %}
|
||||
{% 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('blog_main', uid=udoc._id) }}">
|
||||
<span class="v-center icon icon-flag"></span>
|
||||
{{ _("{0}'s blog").format(udoc.uname) }}
|
||||
</a>
|
||||
</li>
|
||||
<li><h2>{{ ddoc.title }}</h2></li>
|
||||
<li>
|
||||
{{ user.render_inline(udoc) }}
|
||||
@
|
||||
{{ datetimeSpan(ddoc._id)|safe }}
|
||||
</li>
|
||||
</ul>
|
||||
<div class="typo topic__content" data-emoji-enabled>
|
||||
{{ ddoc['content']|markdown|safe }}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="section__footer supplementary dot list">
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_EDIT_SYSTEM) or handler.user.own(ddoc) %}
|
||||
<li><a href="{{ url('blog_edit', uid=udoc._id, 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 %}">
|
||||
<button class="star{% if dsdoc['star'] %} activated{% endif %}" type="submit">
|
||||
<span class="starred--hide"><span class="icon icon-star--outline"></span> {{ _('Star') }}</span>
|
||||
<span class="starred--show"><span class="icon icon-star"></span> {{ _('Unstar') }}</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>
|
||||
<div class="medium-3 columns">
|
||||
<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="{{ avatarUrl(udoc.avatar, 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>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,52 +0,0 @@
|
||||
{% import "components/form.html" as form with context %}
|
||||
{% 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-12 columns">
|
||||
<label>
|
||||
{{ _('Title') }}
|
||||
<input
|
||||
name="title" placeholder="{{ _('title') }}"
|
||||
value="{{ ddoc.title|default('') }}"
|
||||
class="textbox" autofocus>
|
||||
</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',
|
||||
extra_textarea_class:'auto-resize'
|
||||
}) }}
|
||||
<div class="row"><div class="columns">
|
||||
<button name="operation" value="{{ 'update' if ddoc else 'create' }}" data-default-submit type="submit" class="rounded primary button">
|
||||
{{ _('Update') if ddoc else _('Create') }} (Ctrl+Enter)
|
||||
</button>
|
||||
{% if ddoc and (handler.user.hasPriv(PRIV.PRIV_EDIT_SYSTEM) or handler.user.own(ddoc)) %}
|
||||
<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 %}
|
||||
@@ -1,51 +0,0 @@
|
||||
{% import "components/nothing.html" as nothing with context %}
|
||||
{% import "components/user.html" as user with context %}
|
||||
{% import "components/paginator.html" as paginator with context %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
<div class="section">
|
||||
{% if not ddocs.length %}
|
||||
{{ nothing.render('no blog yet...') }}
|
||||
{% else %}
|
||||
<ol class="section__list discussion__list">
|
||||
{%- for ddoc in ddocs -%}
|
||||
<li class="section__list__item discussion__item">
|
||||
<div class="media">
|
||||
<div class="media__left">
|
||||
<div class="discussion__replies numbox">
|
||||
<div class="numbox__num large">{{ datetimeSpan(ddoc._id, false, 'D')|safe }}</div>
|
||||
<div class="numbox__text">{{ datetimeSpan(ddoc._id, false, 'YYYY-M')|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body top">
|
||||
<h1 class="discussion__title"><a href="{{ url('blog_detail', uid=udoc._id, did=ddoc._id, anchor=ddoc.updateAt.getTime()) }}" data-emoji-enabled>{{ ddoc['title'] }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>{{ _('{0} views').format(ddoc.views) }}</li>
|
||||
<li>{{ datetimeSpan(ddoc.updateAt)|safe }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ol>
|
||||
{% if page and dpcount %}{{ paginator.render(page, dpcount) }}{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
<div class="section side">
|
||||
{% if udoc.blogpic %}<div class="discussion-node__bg {{ udoc.blogpic }}"></div>{% endif %}
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">{{ _("{0}'s blog").format(udoc.uname) }}</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
{% if handler.user._id == udoc._id %}
|
||||
<p><a href="{{ url('blog_create', uid=udoc._id) }}" class="expanded primary button">{{ _('Create a Post') }}</a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -87,7 +87,7 @@
|
||||
columns:12,
|
||||
label:'Contest Maintainer',
|
||||
name:'maintainer',
|
||||
help_text:_('Allow to maintain this contest'),
|
||||
help_text:_('Allow to maintain this {0}').format(_('contest')),
|
||||
value:tdoc.maintainer|default('')
|
||||
}) }}
|
||||
<div class="row">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
{{ form.form_text({
|
||||
columns:8,
|
||||
columns:12,
|
||||
label:'Title',
|
||||
name:'title',
|
||||
placeholder:_('title'),
|
||||
@@ -15,7 +15,7 @@
|
||||
}) }}
|
||||
<div class="row">
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
columns:3,
|
||||
label:'Begin Date',
|
||||
name:'beginAtDate',
|
||||
placeholder:'YYYY-mm-dd',
|
||||
@@ -24,8 +24,7 @@
|
||||
row:false
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
last_column:true,
|
||||
columns:2,
|
||||
label:'Begin Time',
|
||||
name:'beginAtTime',
|
||||
placeholder:'HH:MM',
|
||||
@@ -33,9 +32,8 @@
|
||||
time:true,
|
||||
row:false
|
||||
}) }}
|
||||
</div><div class="row">
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
columns:3,
|
||||
label:'End Date',
|
||||
name:'penaltySinceDate',
|
||||
placeholder:'YYYY-mm-dd',
|
||||
@@ -44,8 +42,7 @@
|
||||
row:false
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
last_column:true,
|
||||
columns:2,
|
||||
label:'End Time',
|
||||
name:'penaltySinceTime',
|
||||
placeholder:'HH:MM',
|
||||
@@ -53,22 +50,33 @@
|
||||
time:true,
|
||||
row:false
|
||||
}) }}
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ form.form_text({
|
||||
row:false,
|
||||
columns:4,
|
||||
last_column:true,
|
||||
columns:2,
|
||||
label:'Extension (days)',
|
||||
name:'extensionDays',
|
||||
value:extensionDays
|
||||
}) }}
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ form.form_text({
|
||||
columns:4,
|
||||
row:false,
|
||||
columns:6,
|
||||
label:'Assign',
|
||||
name:'assign',
|
||||
placeholder:_('Group / UID'),
|
||||
value:tdoc.assign|default('')
|
||||
}) }}
|
||||
{{ form.form_text({
|
||||
row:false,
|
||||
last_column:true,
|
||||
columns:6,
|
||||
label:'Homework Maintainer',
|
||||
name:'maintainer',
|
||||
help_text:_('Allow to maintain this {0}').format(_('homework')),
|
||||
value:tdoc.maintainer|default('')
|
||||
}) }}
|
||||
</div>
|
||||
<div class="row"><div class="columns">
|
||||
<label>
|
||||
|
||||
@@ -79,18 +79,11 @@
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) and model.system.get('server.blog') %}
|
||||
<li class="menu__item">
|
||||
<a href="{{ url('blog_main', uid=handler.user._id) }}" class="menu__link">
|
||||
<span class="icon icon-book"></span> {{ _('Blog') }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if ui.getNodes('UserDropdown').length %}
|
||||
<li class="menu__seperator"></li>
|
||||
{%- for item in ui.getNodes('UserDropdown') -%}
|
||||
<li class="menu__item nojs--hide">
|
||||
<a href="{{ url(item.name) }}" class="menu__link">
|
||||
<a href="{{ url(item.name, (item.args(handler) if typeof(item.args)=='function' else item.args) or {}) }}" class="menu__link">
|
||||
<span class="icon icon-{{ item.args.icon }}"></span> {{ _(item.args.displayName or item.name) }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
Reference in new issue
Block a user