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
+99 -46

No files matched your search

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