core&ui: optimize injectable

This commit is contained in:
undefined committed 2022-09-07 20:30:44 +08:00
1 parent 25444f69f0
commit 7343c596e9
9 files changed
+64 -64

No files matched your search

+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "hydrooj",
"version": "3.17.2",
"version": "3.17.3",
"bin": "bin/hydrooj.js",
"main": "src/loader",
"module": "src/loader",
@@ -8,7 +8,7 @@
"author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0-or-later",
"engines": {
"node": ">=10.4"
"node": ">=12"
},
"preferUnplugged": true,
"dependencies": {
+1 -1
View File
@@ -131,7 +131,7 @@ export async function end(body: Partial<JudgeResultBody>) {
$push.compilerTexts = body.compilerText;
}
if (body.status) $set.status = body.status;
if (Number.isSafeInteger(body.score)) $set.score = body.score;
if (Number.isFinite(body.score)) $set.score = Math.floor(body.score * 100) / 100;
if (Number.isFinite(body.time)) $set.time = body.time;
if (Number.isFinite(body.memory)) $set.memory = body.memory;
$set.judgeAt = new Date();
+6 -1
View File
@@ -396,11 +396,16 @@ export class ProblemDetailHandler extends ContestDetailBaseHandler {
.replace(/="file:\/\/(.+?)"/g, (str) => {
const info = str.match(/="file:\/\/(.+?)"/);
return `="./${this.pdoc.docId}/file/${info[1]}${info[1].includes('?') ? '&' : '?'}tid=${args[1]}"`;
})
.replace(/=\\"file:\/\/(.+?)"/g, (str) => {
const info = str.match(/=\\"file:\/\/(.+?)"/);
return `=\\"./${this.pdoc.docId}/file/${info[1]}${info[1].includes('?') ? '&' : '?'}tid=${args[1]}"`;
});
} else {
this.response.body.pdoc.content = this.response.body.pdoc.content
.replace(/\(file:\/\//g, `(./${this.pdoc.docId}/file/`)
.replace(/="file:\/\//g, `="./${this.pdoc.docId}/file/`);
.replace(/="file:\/\//g, `="./${this.pdoc.docId}/file/`)
.replace(/=\\"file:\/\//g, `=\\"${this.pdoc.docId}/file/`);
}
}
this.response.body.page_name = this.tdoc
+1 -1
View File
@@ -1,5 +1,5 @@
const versionNum = +process.version.replace(/v/gim, '').split('.')[0];
if (versionNum < 10) throw new Error('NodeJS >=10.4 required');
if (versionNum < 12) throw new Error('NodeJS >=12 required');
else if (versionNum < 14 && process.env.NODE_APP_INSTANCE === '0') {
console.warn('NodeJS version <14, startup performance will be impacted.');
}
+4 -6
View File
@@ -694,17 +694,15 @@ export interface Lib extends Record<string, any> {
problemSearch: ProblemSearch;
}
export type UIInjectableFields = 'ProblemAdd' | 'Nav' | 'UserDropdown';
export interface UI {
manifest: Dictionary<string>,
template: Dictionary<string>,
nodes: {
nav: any[],
problem_add: any[],
user_dropdown: any[],
},
nodes: Record<UIInjectableFields, any[]>,
getNodes: typeof import('./lib/ui').getNodes,
Nav: typeof import('./lib/ui').Nav,
ProblemAdd: typeof import('./lib/ui').ProblemAdd,
UserDropdown: typeof import('./lib/ui').UserDropdown,
inject: typeof import('./lib/ui').inject,
}
export interface HydroGlobal {
+41 -44
View File
@@ -1,3 +1,4 @@
import { UIInjectableFields } from '../interface';
import { PERM, PRIV } from '../model/builtin';
const trueChecker = () => true;
@@ -6,7 +7,8 @@ const Checker = (perm: bigint | bigint[], priv: number | number[], checker: Func
&& (perm ? handler.user.hasPerm(perm) : true)
&& (priv ? handler.user.hasPriv(priv) : true)
);
const buildChecker = (...permPrivChecker: Array<number | bigint | Function | number[] | bigint[]>) => {
type PermPrivChecker = Array<number | bigint | Function | number[] | bigint[]>;
const buildChecker = (...permPrivChecker: PermPrivChecker) => {
let _priv: number | number[];
let _perm: bigint | bigint[];
let checker: Function = trueChecker;
@@ -22,51 +24,46 @@ const buildChecker = (...permPrivChecker: Array<number | bigint | Function | num
return Checker(_perm, _priv, checker);
};
export const Nav = (
name: string, args: ((handler: any) => Record<string, any>) | Record<string, any> = {}, prefix: string,
...permPrivChecker: Array<number | bigint | Function>
) => {
if (typeof args !== 'function') args = () => (args || {});
const checker = buildChecker(...permPrivChecker);
if (name.startsWith('@@')) {
global.Hydro.ui.nodes.nav.splice(+name.split('@@')[1], 0, {
name: name.split('@@')[2], args, prefix, checker,
});
} else {
global.Hydro.ui.nodes.nav.push({
name, args, prefix, checker,
});
}
export const nodes = new Proxy({}, {
get(self, key) {
if (!self[key]) self[key] = [];
return self[key];
},
});
export function inject(node: UIInjectableFields, name: string, args: Record<string, any> = {}, ...permPrivChecker: PermPrivChecker) {
nodes[node].push({ name, args: args || {}, checker: buildChecker(...permPrivChecker) });
}
export function getNodes(name: UIInjectableFields) {
return nodes[name];
}
/** @deprecated */
export const Nav = (name, args, prefix, ...permPrivChecker) => {
inject('Nav', name, { ...args, prefix }, ...permPrivChecker);
};
/** @deprecated */
export const ProblemAdd = (name, args, icon = 'add', text = 'Create Problem') => {
inject('ProblemAdd', name, { ...args, icon, text });
};
export const ProblemAdd = (
name: string, args: Record<string, any> = {}, icon = 'add', text = 'Create Problem',
) => {
global.Hydro.ui.nodes.problem_add.push({
name, args, icon, text,
});
};
export const UserDropdown = (
name: string, args: Record<string, any> = {}, ...permPrivChecker: Array<number | bigint | Function>
) => {
global.Hydro.ui.nodes.user_dropdown.push({
name, args: args || {}, checker: buildChecker(...permPrivChecker),
});
};
Nav('homepage', {}, 'homepage');
Nav('problem_main', {}, 'problem', PERM.PERM_VIEW_PROBLEM);
Nav('training_main', {}, 'training', PERM.PERM_VIEW_TRAINING);
Nav('homework_main', {}, 'homework', PERM.PERM_VIEW_HOMEWORK);
Nav('discussion_main', {}, 'discussion', PERM.PERM_VIEW_DISCUSSION);
Nav('contest_main', {}, 'contest', PERM.PERM_VIEW_CONTEST);
Nav('record_main', (handler) => (handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) ? { query: { uidOrName: handler.user._id } } : {}), 'record');
Nav('ranking', {}, 'ranking', PERM.PERM_VIEW_RANKING);
Nav('domain_dashboard', {}, 'domain', PERM.PERM_EDIT_DOMAIN);
Nav('manage_dashboard', {}, 'manage', PRIV.PRIV_EDIT_SYSTEM);
ProblemAdd('problem_create');
inject('Nav', 'homepage', { prefix: 'homepage' });
inject('Nav', 'problem_main', { prefix: 'problem' }, PERM.PERM_VIEW_PROBLEM);
inject('Nav', 'training_main', { prefix: 'training' }, PERM.PERM_VIEW_TRAINING);
inject('Nav', 'contest_main', { prefix: 'contest' }, PERM.PERM_VIEW_CONTEST);
inject('Nav', 'homework_main', { prefix: 'homework' }, PERM.PERM_VIEW_HOMEWORK);
inject('Nav', 'discussion_main', { prefix: 'discussion' }, PERM.PERM_VIEW_DISCUSSION);
inject('Nav', 'record_main', {
prefix: 'record',
query: (handler) => (handler.user.hasPriv(PRIV.PRIV_USER_PROFILE)
? ({ uidOrName: handler.user._id })
: ({})),
});
inject('Nav', 'ranking', { prefix: 'ranking' }, PERM.PERM_VIEW_RANKING);
inject('Nav', 'domain_dashboard', { prefix: 'domain' }, PERM.PERM_EDIT_DOMAIN);
inject('Nav', 'manage_dashboard', { prefix: 'manage' }, PRIV.PRIV_EDIT_SYSTEM);
inject('ProblemAdd', 'problem_create', { icon: 'add', text: 'Create Problem' });
global.Hydro.ui.inject = inject;
global.Hydro.ui.nodes = nodes as any;
global.Hydro.ui.getNodes = getNodes;
global.Hydro.ui.Nav = Nav;
global.Hydro.ui.ProblemAdd = ProblemAdd;
global.Hydro.ui.UserDropdown = UserDropdown;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@hydrooj/ui-default",
"version": "4.40.2",
"version": "4.40.3",
"author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0",
"main": "hydro.js",
@@ -1,7 +1,7 @@
{%- macro nav_item(target_page_name, target_page_args, target_page_prefix) -%}
{%- macro nav_item(target_name, target_args, target_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 href="{{ url(target_name, query=target_args.query(handler) if typeof(target_args.query) == 'function' else target_args.query or {}) }}" class="nav__item{% if page_name.startsWith(target_prefix) %} nav--active{% endif %}">
{{ _(target_name) }}
</a>
</li>
{%- endmacro -%}
@@ -10,8 +10,8 @@
<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" style="background-size: 100% 100%;">&nbsp;</a></li>
{%- for item in ui.nodes.nav -%}{% if item.checker(handler) %}
{{ nav_item(item.name, item.args(handler), item.prefix) }}
{%- for item in ui.getNodes('Nav') -%}{% if item.checker(handler) %}
{{ nav_item(item.name, item.args, item.args.prefix) }}
{% endif %}{%- endfor -%}
</ol>
<ol class="nav__list nav__list--secondary clearfix">
@@ -65,10 +65,10 @@
<h1 class="section__title">{{ _('Create Problem') }}</h1>
</div>
<ol class="menu">
{%- for item in ui.nodes.problem_add -%}
{%- for item in ui.getNodes('ProblemAdd') -%}
<a href="{{ url(item.name, item.args) }}" class="menu__link">
<span class="icon icon-{{ item.icon|default('add') }}"></span>
{{ _(item.text) }}
<span class="icon icon-{{ item.args.icon|default('add') }}"></span>
{{ _(item.args.text) }}
</a>
{%- endfor -%}
</ol>