diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index cb037ffff..536befd60 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "3.2.11", + "version": "3.2.12", "bin": "bin/hydrooj.js", "main": "src/loader", "module": "src/loader", diff --git a/packages/hydrooj/src/handler/user.ts b/packages/hydrooj/src/handler/user.ts index 4b4e4a369..9e0e72deb 100644 --- a/packages/hydrooj/src/handler/user.ts +++ b/packages/hydrooj/src/handler/user.ts @@ -11,8 +11,10 @@ import avatar from '../lib/avatar'; import { sendMail } from '../lib/mail'; import { isEmail, isPassword, isUname } from '../lib/validator'; import BlackListModel from '../model/blacklist'; -import { PERM, PRIV } from '../model/builtin'; +import { PERM, PRIV, STATUS } from '../model/builtin'; +import domain from '../model/domain'; import oauth from '../model/oauth'; +import problem, { ProblemDoc } from '../model/problem'; import * as system from '../model/system'; import task from '../model/task'; import token from '../model/token'; @@ -286,11 +288,26 @@ class UserDetailHandler extends Handler { async get(domainId: string, uid: number) { if (uid === 0) throw new UserNotFoundError(0); const isSelfProfile = this.user._id === uid; - const [udoc, sdoc] = await Promise.all([ + const [udoc, sdoc, union] = await Promise.all([ user.getById(domainId, uid), token.getMostRecentSessionByUid(uid), + domain.getUnion(domainId), ]); if (!udoc) throw new UserNotFoundError(uid); + const pdocs: ProblemDoc[] = []; + const acInfo: Record = {}; + const canViewHidden = this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN) || this.user._id; + await Promise.all([domainId, ...union.union].map(async (did) => { + const psdocs = await problem.getMultiStatus(did, { uid, status: STATUS.STATUS_ACCEPTED }).toArray(); + pdocs.push(...Object.values(await problem.getList(did, psdocs.map((i) => i.docId), canViewHidden, false, undefined, true))); + })); + for (const pdoc of pdocs) { + for (const tag of pdoc.tag) { + if (acInfo[tag]) acInfo[tag]++; + else acInfo[tag] = 1; + } + } + const tags = Object.entries(acInfo).sort((a, b) => b[1] - a[1]).slice(0, 20); // Remove sensitive data if (!isSelfProfile && sdoc) { sdoc.createIp = ''; @@ -298,7 +315,9 @@ class UserDetailHandler extends Handler { sdoc._id = ''; } this.response.template = 'user_detail.html'; - this.response.body = { isSelfProfile, udoc, sdoc }; + this.response.body = { + isSelfProfile, udoc, sdoc, pdocs, tags, + }; this.extraTitleContent = udoc.uname; } } diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index 018af0995..9ccd03a2e 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -274,6 +274,7 @@ export class ProblemModel { static async getList( domainId: string, pids: number[], getHidden: number | boolean = false, doThrow = true, projection = ProblemModel.PROJECTION_PUBLIC, + indexByDocIdOnly = false, ): Promise { const r: Record = {}; const l: Record = {}; @@ -300,7 +301,7 @@ export class ProblemModel { } } } - return Object.assign(r, l); + return indexByDocIdOnly ? r : Object.assign(r, l); } static async getPrefixList(domainId: string, prefix: string) { diff --git a/packages/ui-default/misc/typography.styl b/packages/ui-default/misc/typography.styl index 6bf11c6e9..252806845 100644 --- a/packages/ui-default/misc/typography.styl +++ b/packages/ui-default/misc/typography.styl @@ -31,11 +31,10 @@ dd margin-bottom: rem(10px) +above(rupture.desktop-cutoff) - dl.large.horizontal + dl.horizontal overflow: hidden dt float: left - width: 37% overflow: hidden clear: left text-align: left @@ -45,12 +44,26 @@ dd padding-right: rem(10px) dd float: left - width: 62% dt, dd line-height: 1.2rem margin: rem(5px 0) + &.large + dt + width: 37% + + dd + width: 62% + + &.exlarge + dt + width: 62% + + dd + width: 37% + + article, aside, details, figcaption, figure, footer, header, menu, nav, section display: block diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index a9840f857..29789fcb4 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.27.1", + "version": "4.27.2", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/templates/components/problem.html b/packages/ui-default/templates/components/problem.html index 681971de7..72e5e6833 100644 --- a/packages/ui-default/templates/components/problem.html +++ b/packages/ui-default/templates/components/problem.html @@ -1,9 +1,9 @@ -{% macro render_problem_title(pdoc, tdoc=none, show_tags=true, show_invisible_flag=true, invalid=false, inline=false) %} +{% macro render_problem_title(pdoc, tdoc=none, show_tags=true, show_invisible_flag=true, invalid=false, inline=false, small=false) %} {%- if not invalid -%} {% set _linkArgs = { pid:pdoc.pid|default(pdoc.docId) } %} {% if tdoc %}{{ set(_linkArgs, 'query', {tid:tdoc.docId}) }}{% endif %} {% if pdoc.domainId !== handler.domainId %}{{ set(_linkArgs, 'domainId', pdoc.domainId) }}{% endif %} - + {%- endif -%} {%- if pdoc.domainId !== handler.domainId -%} {{ pdoc.domainId }}# @@ -13,7 +13,7 @@ {%- else -%} {{ 'P'+pdoc.docId if pdoc.domainId === handler.domainId else pdoc.docId }} {%- endif -%} -. {{ pdoc.title }} +{%- if not small -%}. {{ pdoc.title }}{%- endif -%} {%- if not invalid -%} {%- endif -%} diff --git a/packages/ui-default/templates/user_detail.html b/packages/ui-default/templates/user_detail.html index c7dbf2b48..8d1d46673 100644 --- a/packages/ui-default/templates/user_detail.html +++ b/packages/ui-default/templates/user_detail.html @@ -1,4 +1,5 @@ {% import "components/home.html" as home with context %} +{% import "components/problem.html" as problem with context %} {% extends "layout/basic.html" %} {% block content %} {{ set(UiContext, 'udoc', udoc) }} @@ -102,6 +103,48 @@ +
+
+

{{ _('Accepted Problems') }}

+
+
+ {% set _mark = (pdocs.length/4)|int %} + {% set _one = pdocs.slice(0, _mark) %} + {% set _two = pdocs.slice(_mark, _mark*2) %} + {% set _three = pdocs.slice(_mark*2, _mark*3) %} + {% set _four = pdocs.slice(_mark*3, pdocs.length) %} +
+
+
    + {% for pdoc in _one %} +
  • {{ problem.render_problem_title(pdoc, show_tags=false, small=true) }}
  • + {% endfor %} +
+
+
+
    + {% for pdoc in _two %} +
  • {{ problem.render_problem_title(pdoc, show_tags=false, small=true) }}
  • + {% endfor %} +
+
+
+
    + {% for pdoc in _three %} +
  • {{ problem.render_problem_title(pdoc, show_tags=false, small=true) }}
  • + {% endfor %} +
+
+
+
    + {% for pdoc in _four %} +
  • {{ problem.render_problem_title(pdoc, show_tags=false, small=true) }}
  • + {% endfor %} +
+
+
+
+
{% if isSelfProfile %} @@ -131,6 +174,19 @@
+
+
+

{{ _('Problem Tags') }}

+
+
+
+ {% for tag in tags %} +
{{ tag[0] }}
+
{{ tag[1] }}
+ {% endfor %} +
+
+
{% endblock %}