diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 28bf1ce52..c3e5cb752 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "3.15.9", + "version": "3.15.10", "bin": "bin/hydrooj.js", "main": "src/loader", "module": "src/loader", diff --git a/packages/hydrooj/setting.yaml b/packages/hydrooj/setting.yaml index 176798b2f..7e599d225 100644 --- a/packages/hydrooj/setting.yaml +++ b/packages/hydrooj/setting.yaml @@ -12,6 +12,7 @@ homepage: - width: 3 hitokoto: true starred_problems: 50 + recent_problems: 10 problem_search: true discussion_nodes: true suggestion: true diff --git a/packages/hydrooj/src/handler/home.ts b/packages/hydrooj/src/handler/home.ts index eef3e8946..6b140afc1 100644 --- a/packages/hydrooj/src/handler/home.ts +++ b/packages/hydrooj/src/handler/home.ts @@ -38,77 +38,75 @@ export class HomeHandler extends Handler { } async getHomework(domainId: string, limit = 5) { - if (this.user.hasPerm(PERM.PERM_VIEW_HOMEWORK)) { - const tdocs = await contest.getMulti(domainId, { rule: 'homework' }) - .limit(limit).toArray(); - const tsdict = await contest.getListStatus( - domainId, this.user._id, tdocs.map((tdoc) => tdoc.docId), - ); - return [tdocs, tsdict]; - } - return [[], {}]; + if (!this.user.hasPerm(PERM.PERM_VIEW_HOMEWORK)) return [[], {}]; + const tdocs = await contest.getMulti(domainId, { rule: 'homework' }) + .limit(limit).toArray(); + const tsdict = await contest.getListStatus( + domainId, this.user._id, tdocs.map((tdoc) => tdoc.docId), + ); + return [tdocs, tsdict]; } async getContest(domainId: string, limit = 10) { - if (this.user.hasPerm(PERM.PERM_VIEW_CONTEST)) { - const rules = Object.keys(contest.RULES).filter((i) => !contest.RULES[i].hidden); - const tdocs = await contest.getMulti(domainId, { rule: { $in: rules } }) - .limit(limit).toArray(); - const tsdict = await contest.getListStatus( - domainId, this.user._id, tdocs.map((tdoc) => tdoc.docId), - ); - return [tdocs, tsdict]; - } - return [[], {}]; + if (!this.user.hasPerm(PERM.PERM_VIEW_CONTEST)) return [[], {}]; + const rules = Object.keys(contest.RULES).filter((i) => !contest.RULES[i].hidden); + const tdocs = await contest.getMulti(domainId, { rule: { $in: rules } }) + .limit(limit).toArray(); + const tsdict = await contest.getListStatus( + domainId, this.user._id, tdocs.map((tdoc) => tdoc.docId), + ); + return [tdocs, tsdict]; } async getTraining(domainId: string, limit = 10) { - if (this.user.hasPerm(PERM.PERM_VIEW_TRAINING)) { - const tdocs = await training.getMulti(domainId) - .sort({ pin: -1, _id: 1 }).limit(limit).toArray(); - const tsdict = await training.getListStatus( - domainId, this.user._id, tdocs.map((tdoc) => tdoc.docId), - ); - return [tdocs, tsdict]; - } - return [[], {}]; + if (!this.user.hasPerm(PERM.PERM_VIEW_TRAINING)) return [[], {}]; + const tdocs = await training.getMulti(domainId) + .sort({ pin: -1, _id: 1 }).limit(limit).toArray(); + const tsdict = await training.getListStatus( + domainId, this.user._id, tdocs.map((tdoc) => tdoc.docId), + ); + return [tdocs, tsdict]; } async getDiscussion(domainId: string, limit = 20) { - if (this.user.hasPerm(PERM.PERM_VIEW_DISCUSSION)) { - const ddocs = await discussion.getMulti(domainId).limit(limit).toArray(); - const vndict = await discussion.getListVnodes(domainId, ddocs, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN), this.user.group); - this.collectUser(ddocs.map((ddoc) => ddoc.owner)); - return [ddocs, vndict]; - } - return [[], {}]; + if (!this.user.hasPerm(PERM.PERM_VIEW_DISCUSSION)) return [[], {}]; + const ddocs = await discussion.getMulti(domainId).limit(limit).toArray(); + const vndict = await discussion.getListVnodes(domainId, ddocs, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN), this.user.group); + this.collectUser(ddocs.map((ddoc) => ddoc.owner)); + return [ddocs, vndict]; } async getRanking(domainId: string, limit = 50) { - if (this.user.hasPerm(PERM.PERM_VIEW_RANKING)) { - const dudocs = await domain.getMultiUserInDomain(domainId, { uid: { $gt: 1 } }) - .sort({ rp: -1 }).project({ uid: 1 }).limit(limit).toArray(); - const uids = dudocs.map((dudoc) => dudoc.uid); - this.collectUser(uids); - return uids; - } - return []; + if (!this.user.hasPerm(PERM.PERM_VIEW_RANKING)) return []; + const dudocs = await domain.getMultiUserInDomain(domainId, { uid: { $gt: 1 } }) + .sort({ rp: -1 }).project({ uid: 1 }).limit(limit).toArray(); + const uids = dudocs.map((dudoc) => dudoc.uid); + this.collectUser(uids); + return uids; } async getStarredProblems(domainId: string, limit = 50) { - if (this.user.hasPerm(PERM.PERM_VIEW_PROBLEM)) { - const psdocs = await ProblemModel.getMultiStatus(domainId, { uid: this.user._id, star: true }) - .sort('_id', 1).limit(limit).toArray(); - const psdict = {}; - for (const psdoc of psdocs) psdict[psdoc.docId] = psdoc; - const pdict = await ProblemModel.getList( - domainId, psdocs.map((pdoc) => pdoc.docId), - this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN) || this.user._id, this.user.group, false, - ); - const pdocs = Object.keys(pdict).filter((i) => +i).map((i) => pdict[i]); - return [pdocs, psdict]; - } - return [[], {}]; + if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM)) return [[], {}]; + const psdocs = await ProblemModel.getMultiStatus(domainId, { uid: this.user._id, star: true }) + .sort('_id', 1).limit(limit).toArray(); + const psdict = {}; + for (const psdoc of psdocs) psdict[psdoc.docId] = psdoc; + const pdict = await ProblemModel.getList( + domainId, psdocs.map((pdoc) => pdoc.docId), + this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN) || this.user._id, this.user.group, false, + ); + const pdocs = Object.keys(pdict).filter((i) => +i).map((i) => pdict[i]); + return [pdocs, psdict]; + } + + async getRecentProblems(domainId: string, limit = 10) { + if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM)) return [[], {}]; + const pdocs = await ProblemModel.getMulti(domainId, { hidden: false }) + .sort({ _id: -1 }).limit(limit).toArray(); + const psdict = this.user.hasPriv(PRIV.PRIV_USER_PROFILE) + ? await ProblemModel.getListStatus(domainId, this.user._id, pdocs.map((pdoc) => pdoc.docId)) + : {}; + return [pdocs, psdict]; } getDiscussionNodes(domainId: string) { diff --git a/packages/ui-default/locales/zh.yaml b/packages/ui-default/locales/zh.yaml index 671d4372b..cbac82a9d 100644 --- a/packages/ui-default/locales/zh.yaml +++ b/packages/ui-default/locales/zh.yaml @@ -641,6 +641,7 @@ Ready (☆▽☆): 马上开始 (☆▽☆) Ready: 即将开始 Recent {0} Records: 最近 {0} 条记录 Recent Activities: 最近活动 +Recent Problems: 最新题目 Recent Solutions: 最近编写的题解 Recent Submissions: 最近递交 Recently Created Discussions: 最近创建的讨论 diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index bf6045900..dba03fa51 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.39.4", + "version": "4.39.5", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/templates/partials/homepage/recent_problems.html b/packages/ui-default/templates/partials/homepage/recent_problems.html new file mode 100644 index 000000000..d17fd7b13 --- /dev/null +++ b/packages/ui-default/templates/partials/homepage/recent_problems.html @@ -0,0 +1,17 @@ +{% set pdocs = payload[0] %} +{% set psdict = payload[1] %} +{% if pdocs.length %} +
+
+

{{ _('Recent Problems') }}

+
+
+ {%- for pdoc in pdocs -%} +

+ {{ problem.render_problem_title(pdoc, show_tags=false, show_invisible_flag=false) }} + {{ datetimeSpan(pdoc._id)|safe }} +

+ {%- endfor -%} +
+
+{% endif %} \ No newline at end of file