core: add projection for discussion

This commit is contained in:
undefined committed 2021-03-08 14:07:26 +08:00
1 parent 71aabe38b5
commit 2344a41816
5 files changed
+86 -33

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.20.10", "version": "2.20.11",
"bin": "bin/hydrooj.js", "bin": "bin/hydrooj.js",
"main": "dist/loader.js", "main": "dist/loader.js",
"typings": "dist/loader.d.ts", "typings": "dist/loader.d.ts",
+13 -12
View File
@@ -162,13 +162,19 @@ export interface SampleContentNode {
export type ContentNode = PlainContentNode | TextContentNode | SampleContentNode; export type ContentNode = PlainContentNode | TextContentNode | SampleContentNode;
export type Content = string | ContentNode[] | Record<string, ContentNode[]>; export type Content = string | ContentNode[] | Record<string, ContentNode[]>;
export interface Document {
_id: ObjectID,
docId: any,
docType: number,
domainId: string,
owner: number,
}
declare module './model/problem' { declare module './model/problem' {
interface Pdoc { interface Pdoc {
domainId: string, docType: document['TYPE_PROBLEM'],
docType: 10,
docId: number, docId: number,
pid: string, pid: string,
owner: number,
title: string, title: string,
content: Content, content: Content,
nSubmit: number, nSubmit: number,
@@ -202,14 +208,6 @@ export interface StatusDoc {
uid: number, uid: number,
} }
export interface Document {
_id: ObjectID,
docId: any,
docType: number,
domainId: string,
owner: number,
}
export interface ProblemStatusDoc extends StatusDoc { export interface ProblemStatusDoc extends StatusDoc {
docId: number, docId: number,
docType: 10, docType: 10,
@@ -339,7 +337,9 @@ export interface HistoryDoc {
} }
// Discussion // Discussion
export interface Ddoc extends Document { export { Ddoc } from './model/discussion';
declare module './model/discussion' {
interface Ddoc {
docType: document['TYPE_DISCUSSION'], docType: document['TYPE_DISCUSSION'],
docId: ObjectID, docId: ObjectID,
parentType: number, parentType: number,
@@ -354,6 +354,7 @@ export interface Ddoc extends Document {
views: number, views: number,
history: HistoryDoc[], history: HistoryDoc[],
} }
}
// Discussion reply // Discussion reply
export interface Drdoc extends Document { export interface Drdoc extends Document {
+61 -7
View File
@@ -4,9 +4,57 @@ import * as contest from './contest';
import * as training from './training'; import * as training from './training';
import * as document from './document'; import * as document from './document';
import { DocumentNotFoundError } from '../error'; import { DocumentNotFoundError } from '../error';
import { Ddoc, Drdoc, Drrdoc } from '../interface'; import { Drdoc, Drrdoc, Document } from '../interface';
import { buildProjection } from '../utils';
import * as bus from '../service/bus'; import * as bus from '../service/bus';
export interface Ddoc extends Document { }
export namespace Ddoc {
export type Field = keyof Ddoc;
export const fields: Field[] = [];
type Getter = () => Partial<Ddoc>;
const getters: Getter[] = [];
export function extend(getter: Getter) {
getters.push(getter);
fields.push(...Object.keys(getter()) as any);
}
extend(() => ({
_id: new ObjectID(),
domainId: 'system',
docType: document.TYPE_DISCUSSION,
docId: new ObjectID(),
owner: 1,
title: '*',
content: '',
parentId: new ObjectID(),
ip: '1.1.1.1',
pin: false,
highlight: false,
updateAt: new Date(),
nReply: 0,
views: 0,
history: [],
}));
export function create() {
const result = {} as Ddoc;
for (const getter of getters) {
Object.assign(result, getter());
}
return result;
}
}
export const PROJECTION_LIST: Ddoc.Field[] = [
'_id', 'domainId', 'docType', 'docId', 'highlight',
'nReply', 'views', 'pin', 'updateAt', 'owner',
'parentId', 'parentType',
];
export const PROJECTION_PUBLIC: Ddoc.Field[] = [
...PROJECTION_LIST, 'content', 'history',
];
export const typeDisplay = { export const typeDisplay = {
[document.TYPE_PROBLEM]: 'problem', [document.TYPE_PROBLEM]: 'problem',
[document.TYPE_CONTEST]: 'contest', [document.TYPE_CONTEST]: 'contest',
@@ -35,8 +83,9 @@ export function add(
); );
} }
export function get(domainId: string, did: ObjectID): Promise<Ddoc | null> { // FIXME typings doesn't work
return document.get(domainId, document.TYPE_DISCUSSION, did); export function get<T extends Ddoc.Field>(domainId: string, did: ObjectID, projection: T[] = PROJECTION_PUBLIC as any): Promise<Pick<Ddoc, T>> {
return document.get(domainId, document.TYPE_DISCUSSION, did, projection);
} }
export function edit( export function edit(
@@ -48,23 +97,24 @@ export function edit(
}); });
} }
export function del(domainId: string, did: ObjectID) { export function del(domainId: string, did: ObjectID): Promise<never> {
return Promise.all([ return Promise.all([
document.deleteOne(domainId, document.TYPE_DISCUSSION, did), document.deleteOne(domainId, document.TYPE_DISCUSSION, did),
document.deleteMulti(domainId, document.TYPE_DISCUSSION_REPLY, { document.deleteMulti(domainId, document.TYPE_DISCUSSION_REPLY, {
parentType: document.TYPE_DISCUSSION, parentId: did, parentType: document.TYPE_DISCUSSION, parentId: did,
}), }),
document.deleteMultiStatus(domainId, document.TYPE_DISCUSSION, { docId: did }), document.deleteMultiStatus(domainId, document.TYPE_DISCUSSION, { docId: did }),
]); ]) as any;
} }
export function count(domainId: string, query: FilterQuery<Ddoc>) { export function count(domainId: string, query: FilterQuery<Ddoc>) {
return document.count(domainId, document.TYPE_DISCUSSION, query); return document.count(domainId, document.TYPE_DISCUSSION, query);
} }
export function getMulti(domainId: string, query: FilterQuery<Ddoc> = {}) { export function getMulti(domainId: string, query: FilterQuery<Ddoc> = {}, projection = PROJECTION_LIST) {
return document.getMulti(domainId, document.TYPE_DISCUSSION, query) return document.getMulti(domainId, document.TYPE_DISCUSSION, query)
.sort({ pin: -1, updateAt: -1 }); .sort({ pin: -1, updateAt: -1 })
.project(buildProjection(projection));
} }
export async function addReply( export async function addReply(
@@ -234,6 +284,10 @@ bus.on('problem/delete', async (domainId, docId) => {
global.Hydro.model.discussion = { global.Hydro.model.discussion = {
typeDisplay, typeDisplay,
Ddoc,
PROJECTION_LIST,
PROJECTION_PUBLIC,
add, add,
get, get,
edit, edit,
+9 -9
View File
@@ -17,15 +17,15 @@ type DocID = ObjectID | string | number;
export const coll = db.collection('document'); export const coll = db.collection('document');
export const collStatus = db.collection('document.status'); export const collStatus = db.collection('document.status');
export const TYPE_PROBLEM = 10; export const TYPE_PROBLEM: 10 = 10;
export const TYPE_PROBLEM_SOLUTION = 11; export const TYPE_PROBLEM_SOLUTION: 11 = 11;
export const TYPE_PROBLEM_LIST = 12; export const TYPE_PROBLEM_LIST: 12 = 12;
export const TYPE_DISCUSSION_NODE = 20; export const TYPE_DISCUSSION_NODE: 20 = 20;
export const TYPE_DISCUSSION = 21; export const TYPE_DISCUSSION: 21 = 21;
export const TYPE_DISCUSSION_REPLY = 22; export const TYPE_DISCUSSION_REPLY: 22 = 22;
export const TYPE_CONTEST = 30; export const TYPE_CONTEST: 30 = 30;
export const TYPE_TRAINING = 40; export const TYPE_TRAINING: 40 = 40;
export const TYPE_HOMEWORK = 60; export const TYPE_HOMEWORK: 60 = 60;
export interface DocType { export interface DocType {
[TYPE_PROBLEM]: Pdoc, [TYPE_PROBLEM]: Pdoc,
+2 -4
View File
@@ -5,16 +5,14 @@ import { STATUS } from './builtin';
import * as document from './document'; import * as document from './document';
import * as domain from './domain'; import * as domain from './domain';
import { buildProjection } from '../utils'; import { buildProjection } from '../utils';
import { ProblemStatusDoc, Pdict } from '../interface'; import type { ProblemStatusDoc, Pdict, Document } from '../interface';
import { Content } from '../loader'; import { Content } from '../loader';
import { ArrayKeys, NumberKeys, Projection } from '../typeutils'; import { ArrayKeys, NumberKeys, Projection } from '../typeutils';
import { ProblemNotFoundError } from '../error'; import { ProblemNotFoundError } from '../error';
import storage from '../service/storage'; import storage from '../service/storage';
import * as bus from '../service/bus'; import * as bus from '../service/bus';
export interface Pdoc { export interface Pdoc extends Document { }
_id: ObjectID
}
export namespace Pdoc { export namespace Pdoc {
export type Field = keyof Pdoc; export type Field = keyof Pdoc;
export const fields: Field[] = []; export const fields: Field[] = [];