bug fixes

This commit is contained in:
undefined committed 2025-03-31 23:25:38 +08:00
1 parent baa9436c30
commit 1a8232899c
12 files changed
+46 -35

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@
"license": "MIT", "license": "MIT",
"main": "base.mjs", "main": "base.mjs",
"dependencies": { "dependencies": {
"@eslint-react/eslint-plugin": "^1.38.3", "@eslint-react/eslint-plugin": "^1.38.4",
"@eslint/compat": "^1.2.7", "@eslint/compat": "^1.2.7",
"@eslint/eslintrc": "^3.3.1", "@eslint/eslintrc": "^3.3.1",
"@stylistic/eslint-plugin": "^4.2.0", "@stylistic/eslint-plugin": "^4.2.0",
+2 -2
View File
@@ -35,7 +35,7 @@
"@types/autocannon": "^7.12.6", "@types/autocannon": "^7.12.6",
"@types/chai": "^5.2.1", "@types/chai": "^5.2.1",
"@types/cross-spawn": "^6.0.6", "@types/cross-spawn": "^6.0.6",
"@types/node": "22.13.8", "@types/node": "22.13.14",
"@types/semver": "^7.7.0", "@types/semver": "^7.7.0",
"autocannon": "^8.0.0", "autocannon": "^8.0.0",
"cac": "^6.7.14", "cac": "^6.7.14",
@@ -44,7 +44,7 @@
"cross-spawn": "^7.0.6", "cross-spawn": "^7.0.6",
"esbuild": "0.25.0", "esbuild": "0.25.0",
"eslint": "^9.23.0", "eslint": "^9.23.0",
"eslint-import-resolver-typescript": "^4.2.5", "eslint-import-resolver-typescript": "^4.3.1",
"eslint-import-resolver-webpack": "^0.13.10", "eslint-import-resolver-webpack": "^0.13.10",
"fs-extra": "^11.3.0", "fs-extra": "^11.3.0",
"globals": "^16.0.0", "globals": "^16.0.0",
+2 -2
View File
@@ -17,8 +17,7 @@ export interface LangConfig {
hidden: boolean; hidden: boolean;
isBinary?: boolean; isBinary?: boolean;
analysis?: string; analysis?: string;
/** @deprecated */ remote: boolean;
remote?: string;
validAs?: Record<string, string>; validAs?: Record<string, string>;
/** @deprecated */ /** @deprecated */
pretest?: string | false; pretest?: string | false;
@@ -51,6 +50,7 @@ export function parseLang(config: string): Record<string, LangConfig> {
entry.code_file ||= `foo.${key}`; entry.code_file ||= `foo.${key}`;
entry.execute ||= '/w/foo'; entry.execute ||= '/w/foo';
entry.key = key; entry.key = key;
entry.remote = !!entry.remote;
entry.hidden ||= false; entry.hidden ||= false;
entry.disabled ||= false; entry.disabled ||= false;
entry.isBinary ||= false; entry.isBinary ||= false;
+18 -12
View File
@@ -15,10 +15,9 @@ const locales = {
function MonacoContainer({ function MonacoContainer({
config, setValue, setError, monaco, schema, editorCallback, size, config, setValue, setError, monaco, schema, editorCallback, size,
}) { }) {
const editorRef = React.useRef<HTMLDivElement>(null);
const [loading, setLoading] = React.useState(false);
const [editor, setEditor] = React.useState<any>(null); const [editor, setEditor] = React.useState<any>(null);
const [model, setModel] = React.useState<any>(null); const [model, setModel] = React.useState<any>(null);
const [initialized, setInitialized] = React.useState(false);
const { codeFontFamily } = React.useContext(ComponentsContext); const { codeFontFamily } = React.useContext(ComponentsContext);
React.useEffect(() => { React.useEffect(() => {
@@ -62,14 +61,14 @@ function MonacoContainer({
} }
}); });
return () => disposable.dispose(); // eslint-disable-line return () => disposable.dispose(); // eslint-disable-line
}, [editor, model, setValue, setError]); }, [editor, model, setValue, setError, schema]);
React.useEffect(() => { const initializeEditor = React.useCallback((element) => {
if (!editorRef.current || loading) return; if (!element || initialized) return;
setLoading(true); setInitialized(true);
// eslint-disable-next-line // eslint-disable-next-line
const model = monaco.editor.createModel(config, 'yaml', monaco.Uri.parse('hydro://system/setting.yaml')); const model = monaco.editor.createModel(config, 'yaml', monaco.Uri.parse('hydro://system/setting.yaml'));
setModel(model); setModel(model);
const e = monaco.editor.create(editorRef.current, { const e = monaco.editor.create(element, {
theme: 'vs-light', theme: 'vs-light',
lineNumbers: 'off', lineNumbers: 'off',
glyphMargin: true, glyphMargin: true,
@@ -85,9 +84,9 @@ function MonacoContainer({
ambiguousCharacters: true, ambiguousCharacters: true,
}, },
}); });
editorCallback(e, model, editorRef.current); editorCallback(e, model, element);
setEditor(e); setEditor(e);
}, [editorRef.current]); }, [config, monaco, editorCallback, codeFontFamily, initialized]);
React.useEffect(() => { React.useEffect(() => {
if (!editor) return; if (!editor) return;
const current = editor.getValue({ lineEnding: '\n', preserveBOM: false }); const current = editor.getValue({ lineEnding: '\n', preserveBOM: false });
@@ -111,7 +110,7 @@ function MonacoContainer({
model.pushEditOperations([], ops, undefined); model.pushEditOperations([], ops, undefined);
}, [editor, config]); }, [editor, config]);
return ( return (
<div ref={editorRef} style={{ <div ref={initializeEditor} style={{
width: '100%', height: '500px', width: '100%', height: '500px',
}} /> }} />
); );
@@ -120,10 +119,17 @@ function MonacoContainer({
export default function ConfigEditor({ export default function ConfigEditor({
schema, config, monaco, Markdown, onSave, registerAction, sidebar, schema, config, monaco, Markdown, onSave, registerAction, sidebar,
}) { }) {
const [value, setValue] = React.useState(yaml.load(config)); const getValue = () => {
try {
return yaml.load(config);
} catch (e) {
return {};
}
};
const [value, setValue] = React.useState(getValue);
const [info, setInfo] = React.useState(''); const [info, setInfo] = React.useState('');
const [stringConfig, setStringConfig] = React.useState(config); const [stringConfig, setStringConfig] = React.useState(config);
const initial = React.useMemo(() => yaml.load(config), []); const initial = React.useMemo(getValue, []);
const { i18n } = React.useContext(ComponentsContext); const { i18n } = React.useContext(ComponentsContext);
const Form = React.useMemo(() => createSchemasteryReact({ const Form = React.useMemo(() => createSchemasteryReact({
+2 -1
View File
@@ -4,7 +4,7 @@ import moment from 'moment-timezone';
import type { Context } from '../context'; import type { Context } from '../context';
import { import {
CannotDeleteSystemDomainError, DomainJoinAlreadyMemberError, DomainJoinForbiddenError, ForbiddenError, CannotDeleteSystemDomainError, DomainJoinAlreadyMemberError, DomainJoinForbiddenError, ForbiddenError,
InvalidJoinInvitationCodeError, OnlyOwnerCanDeleteDomainError, PermissionError, RoleAlreadyExistError, ValidationError, InvalidJoinInvitationCodeError, NotFoundError, OnlyOwnerCanDeleteDomainError, PermissionError, RoleAlreadyExistError, ValidationError,
} from '../error'; } from '../error';
import type { DomainDoc } from '../interface'; import type { DomainDoc } from '../interface';
import avatar from '../lib/avatar'; import avatar from '../lib/avatar';
@@ -337,6 +337,7 @@ class DomainJoinHandler extends Handler {
domain.get(target), domain.get(target),
domain.collUser.findOne({ domainId: target, uid: this.user._id }), domain.collUser.findOne({ domainId: target, uid: this.user._id }),
]); ]);
if (!dudoc) throw new NotFoundError(target);
const assignedRole = this.user.hasPriv(PRIV.PRIV_MANAGE_ALL_DOMAIN) const assignedRole = this.user.hasPriv(PRIV.PRIV_MANAGE_ALL_DOMAIN)
? 'root' ? 'root'
: dudoc?.role || 'default'; : dudoc?.role || 'default';
+5 -1
View File
@@ -198,7 +198,11 @@ class SystemConfigHandler extends SystemHandler {
}; };
try { try {
value = Schema.intersect(this.ctx.config.settings)(yaml.load(this.ctx.config.configSource)); try {
value = Schema.intersect(this.ctx.config.settings)(yaml.load(this.ctx.config.configSource));
} catch (e) {
value = yaml.load(this.ctx.config.configSource);
}
for (const schema of this.ctx.config.settings) processNode(value, schema); for (const schema of this.ctx.config.settings) processNode(value, schema);
} catch (e) { } } catch (e) { }
this.response.body = { this.response.body = {
+9 -10
View File
@@ -139,16 +139,15 @@ export class ConfigService extends Service {
}); });
} }
let curValue = s(this.systemConfig); let curValue = s(this.systemConfig);
if (dynamic) { if (!dynamic) return curValue;
this.ctx.on('system/setting', () => { this.ctx.on('system/setting', () => {
try { try {
curValue = s(this.systemConfig); curValue = s(this.systemConfig);
} catch (e) { } catch (e) {
logger.warn('Cannot read config: ', e.message); logger.warn('Cannot read config: ', e.message);
curValue = null; curValue = null;
} }
}); });
}
const that = this; const that = this;
const getAccess = (path: (string | symbol)[]) => { const getAccess = (path: (string | symbol)[]) => {
if (path.some((p) => ConfigService.blacklist.includes(p.toString()))) throw new Error('Invalid path'); if (path.some((p) => ConfigService.blacklist.includes(p.toString()))) throw new Error('Invalid path');
+1 -1
View File
@@ -7,6 +7,6 @@
"postinstall": "node -r @hydrooj/register install.ts" "postinstall": "node -r @hydrooj/register install.ts"
}, },
"dependencies": { "dependencies": {
"@xcpcio/board-app": "^0.54.0" "@xcpcio/board-app": "^0.55.1"
} }
} }
+1 -1
View File
@@ -22,7 +22,7 @@
"@fontsource/source-code-pro": "^5.2.5", "@fontsource/source-code-pro": "^5.2.5",
"@fontsource/ubuntu-mono": "^5.2.5", "@fontsource/ubuntu-mono": "^5.2.5",
"@hydrooj/utils": "workspace:^", "@hydrooj/utils": "workspace:^",
"@sentry/browser": "^9.10.0", "@sentry/browser": "^9.10.1",
"@sentry/webpack-plugin": "^3.2.4", "@sentry/webpack-plugin": "^3.2.4",
"@simplewebauthn/browser": "13.1.0", "@simplewebauthn/browser": "13.1.0",
"@svgr/webpack": "^8.1.0", "@svgr/webpack": "^8.1.0",
+1 -1
View File
@@ -46,7 +46,7 @@ const page = new NamedPage('manage_config', async () => {
overflow: hidden; overflow: hidden;
} }
.footer { .footer {
display: hidden; visibility: hidden;
} }
.omnibar-toggle { .omnibar-toggle {
display: none; display: none;
@@ -55,8 +55,9 @@
<span class="icon icon-add"></span> {{ _('Login to Attend Contest') }} <span class="icon icon-add"></span> {{ _('Login to Attend Contest') }}
</a> </a>
{% elif not handler.user._dudoc.join %} {% elif not handler.user._dudoc.join %}
<li class="menu__item"><a class="menu__link" href="/domain/join?target={{ pdoc.domainId }}"> <a class="menu__link" href="/domain/join?target={{ pdoc.domainId }}">
<span class="icon icon-add"></span> {{ _('Join Domain to Attend Contest') }}</a></li> <span class="icon icon-add"></span> {{ _('Join Domain to Attend Contest') }}
</a>
{% else %} {% else %}
<a class="menu__link disabled" href="javascript:;"> <a class="menu__link disabled" href="javascript:;">
<span class="icon icon-add"></span> {{ _('No Permission to Attend Contest') }} <span class="icon icon-add"></span> {{ _('No Permission to Attend Contest') }}
+1 -1
View File
@@ -16,6 +16,6 @@
"@types/react": "^19.0.12", "@types/react": "^19.0.12",
"@types/react-dom": "^19.0.4", "@types/react-dom": "^19.0.4",
"@vitejs/plugin-react-swc": "^3.8.1", "@vitejs/plugin-react-swc": "^3.8.1",
"vite": "^6.2.3" "vite": "^6.2.4"
} }
} }