diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 91483eba3..a3208b698 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.29.17", + "version": "2.29.18", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/handler/discussion.ts b/packages/hydrooj/src/handler/discussion.ts index 40191bd3e..536c0ce3a 100644 --- a/packages/hydrooj/src/handler/discussion.ts +++ b/packages/hydrooj/src/handler/discussion.ts @@ -56,7 +56,7 @@ class DiscussionHandler extends Handler { // TODO(twd2): do more visibility check eg. contest // TODO(twd2): exclude problem/contest discussions? // TODO(iceboy): continuation based pagination. - this.vnode = await discussion.getVnode(domainId, typeMapper[type], name); + this.vnode = await discussion.getVnode(domainId, typeMapper[type], name, this.user._id); if (this.vnode.hidden) this.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN); if (this.ddoc) { this.ddoc.parentType = this.ddoc.parentType || this.vnode.type; @@ -68,8 +68,10 @@ class DiscussionHandler extends Handler { class DiscussionMainHandler extends Handler { @param('page', Types.PositiveInt, true) async get(domainId: string, page = 1) { + // Limit to known types + const parentType = { $in: Object.keys(typeMapper).map((i) => typeMapper[i]) }; const [ddocs, dpcount] = await paginate( - discussion.getMulti(domainId), + discussion.getMulti(domainId, { parentType }), page, system.get('pagination.discussion'), ); @@ -300,24 +302,12 @@ class DiscussionDetailHandler extends DiscussionHandler { } } -class DiscussionDetailRawHandler extends DiscussionHandler { - async get() { +class DiscussionRawHandler extends DiscussionHandler { + @param('drid', Types.ObjectID, true) + @param('drrid', Types.ObjectID, true) + async get(domainId: string, drid: ObjectID, drrid: ObjectID) { this.response.type = 'text/markdown'; - this.response.body = this.ddoc.content; - } -} - -class DiscussionReplyRawHandler extends DiscussionHandler { - async get() { - this.response.type = 'text/markdown'; - this.response.body = this.drdoc.content; - } -} - -class DiscussionTailReplyRawHandler extends DiscussionHandler { - async get() { - this.response.type = 'text/markdown'; - this.response.body = this.drrdoc.content; + this.response.body = drrid ? this.drrdoc.content : drid ? this.drdoc.content : this.ddoc.content; } } @@ -375,9 +365,9 @@ export async function apply() { Route('discussion_main', '/discuss', DiscussionMainHandler); Route('discussion_detail', '/discuss/:did', DiscussionDetailHandler); Route('discussion_edit', '/discuss/:did/edit', DiscussionEditHandler); - Route('discussion_detail', '/discuss/:did/raw', DiscussionDetailRawHandler); - Route('discussion_reply_raw', '/discuss/:did/:drid/raw', DiscussionReplyRawHandler); - Route('discussion_tail_reply_raw', '/discuss/:did/:drid/:drrid/raw', DiscussionTailReplyRawHandler); + Route('discussion_detail', '/discuss/:did/raw', DiscussionRawHandler); + Route('discussion_reply_raw', '/discuss/:did/:drid/raw', DiscussionRawHandler); + Route('discussion_tail_reply_raw', '/discuss/:did/:drid/:drrid/raw', DiscussionRawHandler); Route('discussion_node', '/discuss/:type/:name', DiscussionNodeHandler); Route('discussion_create', '/discuss/:type/:name/create', DiscussionCreateHandler, PRIV.PRIV_USER_PROFILE, PERM.PERM_CREATE_DISCUSSION); } diff --git a/packages/hydrooj/src/model/discussion.ts b/packages/hydrooj/src/model/discussion.ts index 047868d09..73f16a1f6 100644 --- a/packages/hydrooj/src/model/discussion.ts +++ b/packages/hydrooj/src/model/discussion.ts @@ -232,15 +232,21 @@ export function getNode(domainId: string, _id: string) { return document.get(domainId, document.TYPE_DISCUSSION_NODE, _id); } -export async function getVnode(domainId: string, type: number, id: string) { +export async function getVnode(domainId: string, type: number, id: string, uid?: number) { if (type === document.TYPE_PROBLEM) { const pdoc = await problem.get(domainId, Number.isSafeInteger(+id) ? +id : id); if (!pdoc) throw new DiscussionNodeNotFoundError(id); return { ...pdoc, type, id }; } if ([document.TYPE_CONTEST, document.TYPE_TRAINING, document.TYPE_HOMEWORK].includes(type as any)) { - const tdoc = await (type === document.TYPE_TRAINING ? training : contest).get(domainId, new ObjectID(id), type as any); + const model = type === document.TYPE_TRAINING ? training : contest; + const _id = new ObjectID(id); + const tdoc = await model.get(domainId, _id, type as any); if (!tdoc) throw new DiscussionNodeNotFoundError(id); + if (uid) { + const tsdoc = await model.getStatus(domainId, _id, uid); + tdoc.attend = tsdoc.attend || tsdoc.enroll; + } return { ...tdoc, type, id }; } return { diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index c3b8e4342..6e9e2786c 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.12.10", + "version": "4.12.11", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/templates/partials/contest_sidebar.html b/packages/ui-default/templates/partials/contest_sidebar.html index 4b856d089..d79533c0b 100644 --- a/packages/ui-default/templates/partials/contest_sidebar.html +++ b/packages/ui-default/templates/partials/contest_sidebar.html @@ -6,7 +6,7 @@

{{ tdoc.title }}

- {% if attended %} + {% if attended or tdoc.attend %} {{ _('Attended') }} {% else %} {{ _('Not Attended') }}