ui: remember scratchpad panel visibility

This commit is contained in:
undefined committed 2021-09-10 23:01:04 +08:00
1 parent 9f9ab1320b
commit ed8ae6ba69
6 files changed
+41 -21

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.34.1", "version": "2.34.2",
"bin": "bin/hydrooj.js", "bin": "bin/hydrooj.js",
"main": "src/loader", "main": "src/loader",
"module": "src/loader", "module": "src/loader",
+4 -6
View File
@@ -1,8 +1,8 @@
import moment from 'moment-timezone'; import moment from 'moment-timezone';
import { import {
BlacklistedError, BlacklistedError, InvalidTokenError, LoginError,
InvalidTokenError, LoginError, SystemError, UserAlreadyExistError, UserFacingError,
SystemError, UserAlreadyExistError, UserFacingError, UserNotFoundError, VerifyPasswordError, UserNotFoundError, VerifyPasswordError,
} from '../error'; } from '../error';
import { User } from '../interface'; import { User } from '../interface';
import avatar from '../lib/avatar'; import avatar from '../lib/avatar';
@@ -18,9 +18,7 @@ import * as system from '../model/system';
import task from '../model/task'; import task from '../model/task';
import token from '../model/token'; import token from '../model/token';
import user from '../model/user'; import user from '../model/user';
import { import { Handler, param, post, Route, Types } from '../service/server';
Handler, param, post,
Route, Types } from '../service/server';
import { registerResolver, registerValue } from './api'; import { registerResolver, registerValue } from './api';
registerValue('User', [ registerValue('User', [
+12 -10
View File
@@ -2,14 +2,15 @@
import { omit, sum } from 'lodash'; import { omit, sum } from 'lodash';
import moment from 'moment'; import moment from 'moment';
import { import {
Collection, FilterQuery, Collection, FilterQuery, MatchKeysAndValues,
MatchKeysAndValues, ObjectID, OnlyFieldsOfType, ObjectID, OnlyFieldsOfType, PushOperator,
PushOperator, UpdateQuery, UpdateQuery,
} from 'mongodb'; } from 'mongodb';
import { ProblemNotFoundError } from '../error'; import { ProblemNotFoundError } from '../error';
import { import {
ContestInfo, ExternalProblemId, FileInfo, ContestInfo, ExternalProblemId, FileInfo,
ProblemConfigFile, RecordDoc } from '../interface'; ProblemConfigFile, RecordDoc,
} from '../interface';
import * as bus from '../service/bus'; import * as bus from '../service/bus';
import db from '../service/db'; import db from '../service/db';
import { MaybeArray } from '../typeutils'; import { MaybeArray } from '../typeutils';
@@ -221,7 +222,7 @@ class RecordModel {
@ArgMethod @ArgMethod
static getByUid(domainId: string, uid: number, limit: number): Promise<RecordDoc[]> { static getByUid(domainId: string, uid: number, limit: number): Promise<RecordDoc[]> {
return RecordModel.coll.find({ return RecordModel.coll.find({
domainId, uid, hidden: false, 'contest.tid': null, domainId, 'contest.tid': null, hidden: false, uid,
}).sort({ _id: -1 }).limit(limit).toArray(); }).sort({ _id: -1 }).limit(limit).toArray();
} }
} }
@@ -234,11 +235,12 @@ bus.on('domain/delete', (domainId) => Promise.all([
])); ]));
bus.on('app/started', () => { bus.on('app/started', () => {
RecordModel.coll.createIndexes([ return db.ensureIndexes(
{ key: { 'contest.tid': 1, hidden: 1, _id: -1 }, name: 'basic' }, RecordModel.coll,
{ key: { 'contest.tid': 1, hidden: 1, uid: 1, _id: -1 }, name: 'withUser' }, { key: { domainId: 1, 'contest.tid': 1, hidden: 1, _id: -1 }, name: 'basic' },
{ key: { 'contest.tid': 1, hidden: 1, pid: 1, _id: -1 }, name: 'withProblem' }, { key: { domainId: 1, 'contest.tid': 1, hidden: 1, uid: 1, _id: -1 }, name: 'withUser' },
]); { key: { domainId: 1, 'contest.tid': 1, hidden: 1, pid: 1, _id: -1 }, name: 'withProblem' },
);
}); });
export default RecordModel; export default RecordModel;
+19 -1
View File
@@ -1,7 +1,10 @@
import { Collection, Db, MongoClient } from 'mongodb'; import { Collection, Db, IndexSpecification, MongoClient } from 'mongodb';
import { BaseService, Collections } from '../interface'; import { BaseService, Collections } from '../interface';
import { Logger } from '../logger';
import * as bus from './bus'; import * as bus from './bus';
const logger = new Logger('mongo');
interface MongoConfig { interface MongoConfig {
protocol?: string, protocol?: string,
username?: string, username?: string,
@@ -44,6 +47,21 @@ class MongoService implements BaseService {
if (this.opts.prefix) return this.db.collection(`${this.opts.prefix}.${c}`); if (this.opts.prefix) return this.db.collection(`${this.opts.prefix}.${c}`);
return this.db.collection(c); return this.db.collection(c);
} }
public async ensureIndexes<T>(coll: Collection<T>, ...args: IndexSpecification[]) {
const existed = await coll.listIndexes().toArray();
for (const index of args) {
const i = existed.find(t => t.name == index.name);
if (!i) {
logger.info('Indexing %s.%s with key %o', coll.collectionName, index.name, index.key);
await coll.createIndexes([index]);
} else if (i.v < 2 || JSON.stringify(i.key) !== JSON.stringify(index.key)) {
logger.info('Re-Index %s.%s with key %o', coll.collectionName, index.name, index.key);
await coll.dropIndex(index.name);
await coll.createIndexes([index]);
}
}
}
} }
const service = new MongoService(); const service = new MongoService();
@@ -6,11 +6,11 @@ export default function reducer(state = {
size: '50%', size: '50%',
}, },
pretest: { pretest: {
visible: false, visible: localStorage.getItem('scratchpad/pretest') === 'true',
size: 200, size: 200,
}, },
records: { records: {
visible: UiContext.canViewRecord, visible: UiContext.canViewRecord && localStorage.getItem('scratchpad/records') === 'true',
size: 200, size: 200,
isLoading: false, isLoading: false,
}, },
@@ -29,6 +29,7 @@ export default function reducer(state = {
} }
case 'SCRATCHPAD_UI_SET_VISIBILITY': { case 'SCRATCHPAD_UI_SET_VISIBILITY': {
const { uiElement, visibility } = action.payload; const { uiElement, visibility } = action.payload;
localStorage.setItem(`scratchpad/${uiElement}`, visibility.toString());
return { return {
...state, ...state,
[uiElement]: { [uiElement]: {
@@ -39,6 +40,7 @@ export default function reducer(state = {
} }
case 'SCRATCHPAD_UI_TOGGLE_VISIBILITY': { case 'SCRATCHPAD_UI_TOGGLE_VISIBILITY': {
const { uiElement } = action.payload; const { uiElement } = action.payload;
localStorage.setItem(`scratchpad/${uiElement}`, (!state[uiElement].visible).toString());
return { return {
...state, ...state,
[uiElement]: { [uiElement]: {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@hydrooj/ui-default", "name": "@hydrooj/ui-default",
"version": "4.20.0", "version": "4.20.1",
"author": "undefined <i@undefined.moe>", "author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"main": "hydro.js", "main": "hydro.js",