mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: show accepted problems
This commit is contained in:
1 parent
06857affb1
commit
8d7a446066
7 files changed
+101
-12
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "3.2.11",
|
"version": "3.2.12",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "src/loader",
|
"main": "src/loader",
|
||||||
"module": "src/loader",
|
"module": "src/loader",
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ import avatar from '../lib/avatar';
|
|||||||
import { sendMail } from '../lib/mail';
|
import { sendMail } from '../lib/mail';
|
||||||
import { isEmail, isPassword, isUname } from '../lib/validator';
|
import { isEmail, isPassword, isUname } from '../lib/validator';
|
||||||
import BlackListModel from '../model/blacklist';
|
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 oauth from '../model/oauth';
|
||||||
|
import problem, { ProblemDoc } from '../model/problem';
|
||||||
import * as system from '../model/system';
|
import * as system from '../model/system';
|
||||||
import task from '../model/task';
|
import task from '../model/task';
|
||||||
import token from '../model/token';
|
import token from '../model/token';
|
||||||
@@ -286,11 +288,26 @@ class UserDetailHandler extends Handler {
|
|||||||
async get(domainId: string, uid: number) {
|
async get(domainId: string, uid: number) {
|
||||||
if (uid === 0) throw new UserNotFoundError(0);
|
if (uid === 0) throw new UserNotFoundError(0);
|
||||||
const isSelfProfile = this.user._id === uid;
|
const isSelfProfile = this.user._id === uid;
|
||||||
const [udoc, sdoc] = await Promise.all([
|
const [udoc, sdoc, union] = await Promise.all([
|
||||||
user.getById(domainId, uid),
|
user.getById(domainId, uid),
|
||||||
token.getMostRecentSessionByUid(uid),
|
token.getMostRecentSessionByUid(uid),
|
||||||
|
domain.getUnion(domainId),
|
||||||
]);
|
]);
|
||||||
if (!udoc) throw new UserNotFoundError(uid);
|
if (!udoc) throw new UserNotFoundError(uid);
|
||||||
|
const pdocs: ProblemDoc[] = [];
|
||||||
|
const acInfo: Record<string, number> = {};
|
||||||
|
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
|
// Remove sensitive data
|
||||||
if (!isSelfProfile && sdoc) {
|
if (!isSelfProfile && sdoc) {
|
||||||
sdoc.createIp = '';
|
sdoc.createIp = '';
|
||||||
@@ -298,7 +315,9 @@ class UserDetailHandler extends Handler {
|
|||||||
sdoc._id = '';
|
sdoc._id = '';
|
||||||
}
|
}
|
||||||
this.response.template = 'user_detail.html';
|
this.response.template = 'user_detail.html';
|
||||||
this.response.body = { isSelfProfile, udoc, sdoc };
|
this.response.body = {
|
||||||
|
isSelfProfile, udoc, sdoc, pdocs, tags,
|
||||||
|
};
|
||||||
this.extraTitleContent = udoc.uname;
|
this.extraTitleContent = udoc.uname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ export class ProblemModel {
|
|||||||
static async getList(
|
static async getList(
|
||||||
domainId: string, pids: number[],
|
domainId: string, pids: number[],
|
||||||
getHidden: number | boolean = false, doThrow = true, projection = ProblemModel.PROJECTION_PUBLIC,
|
getHidden: number | boolean = false, doThrow = true, projection = ProblemModel.PROJECTION_PUBLIC,
|
||||||
|
indexByDocIdOnly = false,
|
||||||
): Promise<ProblemDict> {
|
): Promise<ProblemDict> {
|
||||||
const r: Record<number, ProblemDoc> = {};
|
const r: Record<number, ProblemDoc> = {};
|
||||||
const l: Record<string, ProblemDoc> = {};
|
const l: Record<string, ProblemDoc> = {};
|
||||||
@@ -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) {
|
static async getPrefixList(domainId: string, prefix: string) {
|
||||||
|
|||||||
@@ -31,11 +31,10 @@ dd
|
|||||||
margin-bottom: rem(10px)
|
margin-bottom: rem(10px)
|
||||||
|
|
||||||
+above(rupture.desktop-cutoff)
|
+above(rupture.desktop-cutoff)
|
||||||
dl.large.horizontal
|
dl.horizontal
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
dt
|
dt
|
||||||
float: left
|
float: left
|
||||||
width: 37%
|
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
clear: left
|
clear: left
|
||||||
text-align: left
|
text-align: left
|
||||||
@@ -45,12 +44,26 @@ dd
|
|||||||
padding-right: rem(10px)
|
padding-right: rem(10px)
|
||||||
dd
|
dd
|
||||||
float: left
|
float: left
|
||||||
width: 62%
|
|
||||||
|
|
||||||
dt, dd
|
dt, dd
|
||||||
line-height: 1.2rem
|
line-height: 1.2rem
|
||||||
margin: rem(5px 0)
|
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
|
article, aside, details, figcaption, figure, footer, header, menu, nav, section
|
||||||
display: block
|
display: block
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/ui-default",
|
"name": "@hydrooj/ui-default",
|
||||||
"version": "4.27.1",
|
"version": "4.27.2",
|
||||||
"author": "undefined <i@undefined.moe>",
|
"author": "undefined <i@undefined.moe>",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "hydro.js",
|
"main": "hydro.js",
|
||||||
|
|||||||
@@ -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 -%}
|
{%- if not invalid -%}
|
||||||
{% set _linkArgs = { pid:pdoc.pid|default(pdoc.docId) } %}
|
{% set _linkArgs = { pid:pdoc.pid|default(pdoc.docId) } %}
|
||||||
{% if tdoc %}{{ set(_linkArgs, 'query', {tid:tdoc.docId}) }}{% endif %}
|
{% if tdoc %}{{ set(_linkArgs, 'query', {tid:tdoc.docId}) }}{% endif %}
|
||||||
{% if pdoc.domainId !== handler.domainId %}{{ set(_linkArgs, 'domainId', pdoc.domainId) }}{% endif %}
|
{% if pdoc.domainId !== handler.domainId %}{{ set(_linkArgs, 'domainId', pdoc.domainId) }}{% endif %}
|
||||||
<a href="{{ url('problem_detail', _linkArgs) }}">
|
<a href="{{ url('problem_detail', _linkArgs) }}"{% if small %}data-tooltip="{{ pdoc.title }}"{% endif %}>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- if pdoc.domainId !== handler.domainId -%}
|
{%- if pdoc.domainId !== handler.domainId -%}
|
||||||
{{ pdoc.domainId }}#
|
{{ pdoc.domainId }}#
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
{%- else -%}
|
{%- else -%}
|
||||||
{{ 'P'+pdoc.docId if pdoc.domainId === handler.domainId else pdoc.docId }}
|
{{ 'P'+pdoc.docId if pdoc.domainId === handler.domainId else pdoc.docId }}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
. {{ pdoc.title }}
|
{%- if not small -%}. {{ pdoc.title }}{%- endif -%}
|
||||||
{%- if not invalid -%}
|
{%- if not invalid -%}
|
||||||
</a>
|
</a>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{% import "components/home.html" as home with context %}
|
{% import "components/home.html" as home with context %}
|
||||||
|
{% import "components/problem.html" as problem with context %}
|
||||||
{% extends "layout/basic.html" %}
|
{% extends "layout/basic.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{{ set(UiContext, 'udoc', udoc) }}
|
{{ set(UiContext, 'udoc', udoc) }}
|
||||||
@@ -102,6 +103,48 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="section">
|
||||||
|
<div class="section__header">
|
||||||
|
<h2 class="section__title">{{ _('Accepted Problems') }}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="typo section__body no-media">
|
||||||
|
{% 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) %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="medium-3 columns">
|
||||||
|
<ul>
|
||||||
|
{% for pdoc in _one %}
|
||||||
|
<li>{{ problem.render_problem_title(pdoc, show_tags=false, small=true) }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="medium-3 columns">
|
||||||
|
<ul>
|
||||||
|
{% for pdoc in _two %}
|
||||||
|
<li>{{ problem.render_problem_title(pdoc, show_tags=false, small=true) }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="medium-3 columns">
|
||||||
|
<ul>
|
||||||
|
{% for pdoc in _three %}
|
||||||
|
<li>{{ problem.render_problem_title(pdoc, show_tags=false, small=true) }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="medium-3 columns">
|
||||||
|
<ul>
|
||||||
|
{% for pdoc in _four %}
|
||||||
|
<li>{{ problem.render_problem_title(pdoc, show_tags=false, small=true) }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="medium-3 columns">
|
<div class="medium-3 columns">
|
||||||
{% if isSelfProfile %}
|
{% if isSelfProfile %}
|
||||||
@@ -131,6 +174,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="section side">
|
||||||
|
<div class="section__header">
|
||||||
|
<h2 class="section__title">{{ _('Problem Tags') }}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="typo section__body no-media">
|
||||||
|
<dl class="exlarge horizontal">
|
||||||
|
{% for tag in tags %}
|
||||||
|
<dt>{{ tag[0] }}</dt>
|
||||||
|
<dd>{{ tag[1] }}</dd>
|
||||||
|
{% endfor %}
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Reference in new issue
Block a user