core&ui: support reaction

This commit is contained in:
undefined committed 2022-02-07 01:59:19 +08:00
1 parent 48565ce711
commit 913658d144
12 files changed
+180 -37

No files matched your search

+3 -1
View File
@@ -1,6 +1,6 @@
{
"name": "hydrooj",
"version": "3.4.6",
"version": "3.4.7",
"bin": "bin/hydrooj.js",
"main": "src/loader",
"module": "src/loader",
@@ -20,6 +20,8 @@
"cac": "^6.7.12",
"cookies": "^0.8.0",
"detect-browser": "^5.3.0",
"emoji-regex": "^10.0.0",
"emojis-list": "2.1.0",
"esbuild": "0.14.3",
"fs-extra": "^10.0.0",
"graphql": "^16.3.0",
+11 -4
View File
@@ -179,6 +179,11 @@ class DiscussionDetailHandler extends DiscussionHandler {
for (const drdoc of drdocs) {
if (drdoc.reply) uids.push(...drdoc.reply.map((drrdoc) => drrdoc.owner));
}
const reactions = { [did.toHexString()]: dsdoc?.react || {} };
await Promise.all(drdocs.map((drdoc) =>
discussion.getReaction(domainId, document.TYPE_DISCUSSION_REPLY, drdoc._id, this.user._id).then((reaction) => {
reactions[drdoc._id.toHexString()] = reaction;
})));
const udict = await user.getList(domainId, uids);
if (!dsdoc?.view) {
await Promise.all([
@@ -194,7 +199,7 @@ class DiscussionDetailHandler extends DiscussionHandler {
];
this.response.template = 'discussion_detail.html';
this.response.body = {
path, ddoc: this.ddoc, dsdoc, drdocs, page, pcount, drcount, udict, vnode: this.vnode,
path, ddoc: this.ddoc, dsdoc, drdocs, page, pcount, drcount, udict, vnode: this.vnode, reactions,
};
}
@@ -203,12 +208,14 @@ class DiscussionDetailHandler extends DiscussionHandler {
}
@param('type', Types.Range(['did', 'drid']))
@param('did', Types.ObjectID)
@param('id', Types.Name)
@param('id', Types.ObjectID)
@param('emoji', Types.Emoji)
@param('reverse', Types.Boolean)
async postReaction(domainId: string, type: string, did: ObjectID, id: string, reverse = false) {
this.checkPerm(PERM.PERM_ADD_REACTION);
await discussion.react(domainId, type === 'did' ? document.TYPE_DISCUSSION : document.TYPE_DISCUSSION_REPLY, did, id, this.user._id, reverse);
const docType = type === 'did' ? document.TYPE_DISCUSSION : document.TYPE_DISCUSSION_REPLY;
const [doc, sdoc] = await discussion.react(domainId, docType, did, id, this.user._id, reverse);
this.response.body = { doc, sdoc };
this.back();
}
+12 -3
View File
@@ -56,7 +56,7 @@ export const PROJECTION_LIST: DiscussionDoc.Field[] = [
'parentId', 'parentType', 'title',
];
export const PROJECTION_PUBLIC: DiscussionDoc.Field[] = [
...PROJECTION_LIST, 'content', 'history',
...PROJECTION_LIST, 'content', 'history', 'react', 'maintainer',
];
export const typeDisplay = {
@@ -184,8 +184,16 @@ export function getListReply(domainId: string, did: ObjectID): Promise<Discussio
}
export async function react(domainId: string, docType: keyof document.DocType, did: ObjectID, id: string, uid: number, reverse = false) {
const updated = await document.setIfNotStatus(domainId, docType, did, uid, `react.${id}`, reverse ? 0 : 1, reverse ? 0 : 1, {});
if (updated) await document.inc(domainId, docType, did, `react.${id}`, reverse ? -1 : 1);
let doc;
const sdoc = await document.setIfNotStatus(domainId, docType, did, uid, `react.${id}`, reverse ? 0 : 1, reverse ? 0 : 1, {});
if (sdoc) doc = await document.inc(domainId, docType, did, `react.${id}`, reverse ? -1 : 1);
else doc = await document.get(domainId, docType, did, ['react']);
return [doc, sdoc];
}
export async function getReaction(domainId: string, docType: keyof document.DocType, did: ObjectID, uid: number) {
const doc = await document.getStatus(domainId, docType, did, uid);
return doc?.react || {};
}
export async function addTailReply(
@@ -357,6 +365,7 @@ global.Hydro.model.discussion = {
editTailReply,
delTailReply,
react,
getReaction,
setStar,
getStatus,
setStatus,
+1 -1
View File
@@ -292,7 +292,7 @@ export class ProblemModel {
const q: any = { docId: { $in: pids } };
let pdocs = await document.getMulti(domainId, document.TYPE_PROBLEM, q)
.project(buildProjection(projection)).toArray();
if (group.length > 0) {
if (group.length > 0 && canViewHidden !== true) {
pdocs = pdocs.filter((i) => !i.assign?.length || Set.intersection(group, i.assign).size);
}
if (canViewHidden !== true) {
+6
View File
@@ -4,6 +4,7 @@ import http from 'http';
import { PassThrough } from 'stream';
import cac from 'cac';
import Cookies from 'cookies';
import emojiRegex from 'emoji-regex';
import Koa, { Context } from 'koa';
import Body from 'koa-body';
import Compress from 'koa-compress';
@@ -86,6 +87,7 @@ export interface Types {
NumericArray: Type,
CommaSeperatedArray: Type,
Set: Type,
Emoji: Type,
}
export const Types: Types = {
@@ -172,6 +174,10 @@ export const Types: Types = {
if (v instanceof Array) return new Set(v);
return v ? new Set([v]) : new Set();
}, null],
Emoji: [
(v: string) => v.matchAll(emojiRegex()).next().value[0],
(v) => emojiRegex().test(v),
],
};
function _buildParam(name: string, source: 'get' | 'post' | 'all' | 'route', ...args: Array<Type | boolean | Validator | Converter>) {