ui: add ProblemSelectAutoComplete

This commit is contained in:
undefined committed 2021-04-11 18:22:47 +08:00
1 parent 1c89596cb3
commit 90443546c8
7 files changed
+80 -3

No files matched your search

+10
View File
@@ -581,6 +581,15 @@ export class ProblemCreateHandler extends Handler {
}
}
export class ProblemPrefixListHandler extends Handler {
@param('prefix', Types.Name)
async get(domainId: string, prefix: string) {
this.response.body = {
pdocs: await problem.getPrefixList(domainId, prefix),
};
}
}
export async function apply() {
Route('problem_main', '/p', ProblemMainHandler, PERM.PERM_VIEW_PROBLEM);
Route('problem_category', '/p/category/:category', ProblemCategoryHandler, PERM.PERM_VIEW_PROBLEM);
@@ -596,6 +605,7 @@ export async function apply() {
Route('problem_solution_raw', '/p/:pid/solution/:psid/raw', ProblemSolutionRawHandler, PERM.PERM_VIEW_PROBLEM);
Route('problem_solution_reply_raw', '/p/:pid/solution/:psid/:psrid/raw', ProblemSolutionRawHandler, PERM.PERM_VIEW_PROBLEM);
Route('problem_create', '/problem/create', ProblemCreateHandler, PERM.PERM_CREATE_PROBLEM);
Route('problem_prefix_list', '/problem/list', ProblemPrefixListHandler, PERM.PERM_VIEW_PROBLEM);
Connection('problem_pretest_conn', '/conn/pretest', ProblemPretestConnectionHandler, PERM.PERM_SUBMIT_PROBLEM);
}
+8 -1
View File
@@ -1,6 +1,6 @@
import type { Readable } from 'stream';
import { ObjectID, FilterQuery } from 'mongodb';
import { Dictionary, pick } from 'lodash';
import { Dictionary, escapeRegExp, pick } from 'lodash';
import { STATUS } from './builtin';
import * as document from './document';
import domain from './domain';
@@ -208,6 +208,13 @@ export class ProblemModel {
return Object.assign(r, l);
}
static async getPrefixList(domainId: string, prefix: string) {
prefix = prefix.toLowerCase();
const $regex = new RegExp(`\\A${escapeRegExp(prefix)}`, 'gmi');
const filter = { $or: [{ pid: { $regex } }, { title: { $regex } }] };
return await document.getMulti(domainId, document.TYPE_PROBLEM, filter, ['domainId', 'docId', 'pid', 'title']).toArray();
}
static async getListStatus(domainId: string, uid: number, pids: number[]) {
const psdocs = await ProblemModel.getMultiStatus(
domainId, { uid, docId: { $in: Array.from(new Set(pids)) } },
+2 -1
View File
@@ -1,4 +1,5 @@
import { Collection } from 'mongodb';
import { escapeRegExp } from 'lodash';
import * as system from './system';
import token from './token';
import * as setting from './setting';
@@ -224,7 +225,7 @@ class UserModel {
@ArgMethod
static async getPrefixList(domainId: string, prefix: string, limit: number = 50) {
prefix = prefix.toLowerCase();
const $regex = new RegExp(`\\A\\Q${prefix}\\E`, 'gmi');
const $regex = new RegExp(`\\A${escapeRegExp(prefix)}`, 'gmi');
const uids = await coll.find({ unameLower: { $regex } })
.limit(limit).map((doc) => doc._id).toArray();
const users = [];
+1 -1
View File
@@ -11,7 +11,7 @@ export async function connect() {
while (dbVer < expected) {
const func = scripts[dbVer];
dbVer++;
if (func.toString().includes('_FRESH_INSTALL_IGNORE')) continue;
if (typeof func !== 'function' || func.toString().includes('_FRESH_INSTALL_IGNORE')) continue;
// eslint-disable-next-line no-await-in-loop
await func();
}
@@ -0,0 +1,41 @@
import _ from 'lodash';
import tpl from 'vj/utils/tpl';
import request from 'vj/utils/request';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import AutoComplete from '.';
function getText(pdoc) {
return pdoc.docId;
}
function getItems(val) {
return request.get('/problem/list', { q: val });
}
function renderItem(pdoc) {
return tpl`
<div class="media">
<div class="media__body medium">
<div class="problem-select__name">${pdoc.pid ? `${pdoc.pid}` : ''}${pdoc.title}</div>
<div class="problem-select__id">ID = ${pdoc.docId}</div>
</div>
</div>
`;
}
export default class ProblemSelectAutoComplete extends AutoComplete {
static DOMAttachKey = 'vjProblemSelectAutoCompleteInstance';
constructor($dom, options) {
super($dom, {
classes: 'problem-select',
items: getItems,
render: renderItem,
text: getText,
...options,
});
}
}
_.assign(ProblemSelectAutoComplete, DOMAttachedObject);
window.Hydro.components.UserSelectAutoComplete = ProblemSelectAutoComplete;
@@ -0,0 +1,12 @@
import { AutoloadPage } from 'vj/misc/Page';
import UserSelectAutoComplete from './UserSelectAutoComplete';
import DomainSelectAutoComplete from './DomainSelectAutoComplete';
import ProblemSelectAutoComplete from './ProblemSelectAutoComplete';
const page = new AutoloadPage('autocomplete', () => {
UserSelectAutoComplete.getOrConstruct($('[autocomplete="user"]'));
DomainSelectAutoComplete.getOrConstruct($('[autocomplete="domain"]'));
ProblemSelectAutoComplete.getOrConstruct($('[autocomplete="problem"]'));
});
export default page;
@@ -0,0 +1,6 @@
.menu.problem-select
width: rem(200px)
.problem-select__uid
font-size: rem($font-size-small)
color: $userselect-uid-color