diff --git a/packages/ui-default/.eslintrc.js b/packages/ui-default/.eslintrc.js index 199c1df05..0b62b4faf 100644 --- a/packages/ui-default/.eslintrc.js +++ b/packages/ui-default/.eslintrc.js @@ -102,6 +102,7 @@ module.exports = { 'no-await-in-loop': 'off', 'no-lonely-if': 'off', 'no-param-reassign': 'off', + 'no-script-url': 'off', 'no-bitwise': 'off', 'react/prefer-stateless-function': 'off', 'react/static-property-placement': 'off', diff --git a/packages/ui-default/components/hint.ts b/packages/ui-default/components/hint.ts new file mode 100644 index 000000000..652a94530 --- /dev/null +++ b/packages/ui-default/components/hint.ts @@ -0,0 +1,19 @@ +import { InfoDialog } from 'vj/components/dialog'; +import i18n from 'vj/utils/i18n'; +import tpl from 'vj/utils/tpl'; + +export default function createHint(message: string, element?: any) { + if (i18n(message) === message || !element) return; + const a = document.createElement('a'); + a.setAttribute('href', 'javascript:;'); + const span = document.createElement('span'); + span.setAttribute('class', 'icon icon-help'); + a.appendChild(span); + a.onclick = () => { + new InfoDialog({ + cancelByClickingBack: false, + $body: tpl.typoMsg(i18n(message)), + }).open(); + }; + $(element).append(a); +} diff --git a/packages/ui-default/components/problem/create.page.js b/packages/ui-default/components/problem/create.page.js index d3b50d661..3363ec4ce 100644 --- a/packages/ui-default/components/problem/create.page.js +++ b/packages/ui-default/components/problem/create.page.js @@ -7,10 +7,7 @@ export default new NamedPage(['problem_create', 'problem_edit', 'problem_import_ $('input[name="pid"]').on('blur', () => { if (/^[0-9]+$/.test($('input[name="pid"]').val())) { new InfoDialog({ - $body: tpl` -
-

${i18n('Problem ID cannot be a pure number. Leave blank if you want to use numberic id.')}

-
`, + $body: tpl.typoMsg(i18n('Problem ID cannot be a pure number. Leave blank if you want to use numberic id.')), }).open(); } }); diff --git a/packages/ui-default/locales/en.yaml b/packages/ui-default/locales/en.yaml index b832cbe6e..6f51a1bf9 100644 --- a/packages/ui-default/locales/en.yaml +++ b/packages/ui-default/locales/en.yaml @@ -2,6 +2,7 @@ __langname: English Can be Extended For: Extension Current Status: Status Handled Requests: Req +Hint::icon::difficulty: The difficulty of the problems in Hydro will be calculated by algorithm, depending on current submission, sometimes the difficulty may not so exact. manage: System Manage no_translation_warn:
This part of content is under translation.
page.problem_detail.sidebar.show_category: Click to Show @@ -27,8 +28,8 @@ problem_submit: Problem Submit problem_type.default: 'Type: Default' problem_type.fileio: 'Type: FileIO ({0})' problem_type.interactive: 'Type: Interactive' -problem_type.remote_judge: 'Type: RemoteJudge' problem_type.objective: 'Type: Objective' +problem_type.remote_judge: 'Type: RemoteJudge' problem_type.submit_answer: 'Type: SubmitAnswer' problem-category-delim: '|' problem-subcategory-delim: ', ' diff --git a/packages/ui-default/locales/zh.yaml b/packages/ui-default/locales/zh.yaml index b34baa31f..68c88e344 100644 --- a/packages/ui-default/locales/zh.yaml +++ b/packages/ui-default/locales/zh.yaml @@ -137,6 +137,7 @@ Confirm deleting this reply?: 确认删除这个回复吗? Confirm rejudge this problem?: 确定要重测这道题吗? Confirm removing the selected users?: 您确定将所选用户移除吗? Confirm to delete the selected files?: 确认删除所选文件吗? +Confirm to delete the selected problems?: 确认要删除所选题目吗? Confirmation mail has been sent to your new email.: 确认邮件已经发送到您的新电子邮箱。 Congratulations! Your submission is accepted.: 恭喜!您的递交已评测通过。 Contact Us: 联系我们 @@ -339,6 +340,7 @@ Hide tags: 隐藏标签 Highlight discussions: 高亮讨论 Highlight: 高亮 Hint: 提示 +Hint::icon::difficulty: Hydro 中题目的难度,根据递交数、通过率以及每个递交的递交时间和评测结果,综合计算得出,可能不准确。 Hint::page::main: 欢迎来到 Hydro! 您可在右上角注册或登录。此类提示仅会显示一次。 Hint::page::problem_detail: 这是题目详情页面。您可点击右侧“进入在线编程模式"开始编写您的代码。 Hint::page::problem_files: 您可以将文件或压缩包拖拽至对应区域来上传文件。点击文件名在线编辑或按住 Ctrl 后点击文件名下载单个文件。 @@ -664,6 +666,7 @@ Select a node to create discussion.: 选择一个节点来发表讨论。 Select a role: 选择一个角色 Select User: 选择用户 Selected files have been deleted.: 所选文件已被删除。 +Selected problems have been deleted.: 所选题目已被删除。 Selected roles have been deleted.: 所选角色已删除。 Selected users have been removed from the domain.: 所选用户已从此域中移除。 Send Code after acceptance: 通过题目后发送源代码 diff --git a/packages/ui-default/misc/Page.js b/packages/ui-default/misc/Page.ts similarity index 75% rename from packages/ui-default/misc/Page.js rename to packages/ui-default/misc/Page.ts index 489535920..ccf0621bf 100644 --- a/packages/ui-default/misc/Page.js +++ b/packages/ui-default/misc/Page.ts @@ -1,5 +1,5 @@ export class Page { - constructor(name, autoload, afterLoading, beforeLoading) { + constructor(public name: string | string[], public autoload: boolean, public afterLoading, public beforeLoading) { if (process.env.NODE_ENV !== 'production') { if (typeof name !== 'string' && !(name instanceof Array)) { // eslint-disable-next-line quotes @@ -14,13 +14,9 @@ export class Page { throw new Error(`'beforeLoading' should be a function`); } } - this.name = name; - this.autoload = autoload; - this.afterLoading = afterLoading; - this.beforeLoading = beforeLoading; } - isNameMatch(name) { + isNameMatch(name: string) { if (typeof this.name === 'string') return this.name === name; if (this.name instanceof Array) return this.name.includes(name); return false; @@ -28,13 +24,13 @@ export class Page { } export class NamedPage extends Page { - constructor(name, afterLoading = null, beforeLoading = null) { + constructor(name: string | string[], afterLoading = null, beforeLoading = null) { super(name, false, afterLoading, beforeLoading); } } export class AutoloadPage extends Page { - constructor(name, afterLoading = null, beforeLoading = null) { + constructor(name: string | string[], afterLoading = null, beforeLoading = null) { super(name, true, afterLoading, beforeLoading); } } diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 3cb9e5760..07f73b60b 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.22.13", + "version": "4.22.14", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/pages/problem_main.page.js b/packages/ui-default/pages/problem_main.page.js index 3c9b384ad..fbbebf0b9 100644 --- a/packages/ui-default/pages/problem_main.page.js +++ b/packages/ui-default/pages/problem_main.page.js @@ -4,6 +4,7 @@ import { NamedPage } from 'vj/misc/Page'; import Notification from 'vj/components/notification'; import { ConfirmDialog } from 'vj/components/dialog'; import Dropdown from 'vj/components/dropdown/Dropdown'; +import createHint from 'vj/components/hint'; import { downloadProblemSet } from 'vj/components/zipDownloader'; import pjax from 'vj/utils/pjax'; import substitute from 'vj/utils/substitute'; @@ -221,10 +222,7 @@ const page = new NamedPage(['problem_main', 'problem_category'], () => { ev.preventDefault(); updateSelection(); }); - $('#searchForm').on('submit', () => { - updateSelection(); - return false; - }); + $('#searchForm').on('submit', updateSelection); let update; $('#searchForm').find('input').on('input', () => { if (update) clearTimeout(update); @@ -232,10 +230,12 @@ const page = new NamedPage(['problem_main', 'problem_category'], () => { }); $(document).on('click', 'a.pager__item', (ev) => { ev.preventDefault(); - pjax.request({ url: $(ev.currentTarget).attr('href') }).then(() => { - window.scrollTo(0, 0); - }); + pjax.request($(ev.currentTaget).attr('href')).then(() => window.scrollTo(0, 0)); }); + $(document).on('vjContentNew', (e) => { + createHint('Hint::icon::difficulty', $(e.target).find('th.col--difficulty')) + }); + createHint('Hint::icon::difficulty', $(document).find('th.col--difficulty')) }); export default page; diff --git a/packages/ui-default/utils/pjax.js b/packages/ui-default/utils/pjax.js index 17e5d3a41..b664bb974 100644 --- a/packages/ui-default/utils/pjax.js +++ b/packages/ui-default/utils/pjax.js @@ -48,6 +48,7 @@ function decProgress() { } pjax.request = async (opt) => { + if (typeof opt === 'string') opt = { url: opt }; const options = { method: 'get', push: true,