ui: simplify user_detail page

This commit is contained in:
undefined committed 2021-09-20 20:25:59 +08:00
1 parent 62ec797652
commit dd037e36d7
7 files changed
+27 -110

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "hydrooj",
"version": "2.36.12",
"version": "2.36.13",
"bin": "bin/hydrooj.js",
"main": "src/loader",
"module": "src/loader",
+7 -32
View File
@@ -2,18 +2,15 @@ import moment from 'moment-timezone';
import {
BlacklistedError, InvalidTokenError, LoginError,
SystemError, UserAlreadyExistError, UserFacingError,
UserNotFoundError, VerifyPasswordError,
UserNotFoundError, ValidationError, VerifyPasswordError,
} from '../error';
import { User } from '../interface';
import avatar from '../lib/avatar';
import { sendMail } from '../lib/mail';
import paginate from '../lib/paginate';
import { isEmail, isPassword, isUname } from '../lib/validator';
import BlackListModel from '../model/blacklist';
import { PERM, PRIV } from '../model/builtin';
import oauth from '../model/oauth';
import problem, { ProblemDoc } from '../model/problem';
import record from '../model/record';
import * as system from '../model/system';
import task from '../model/task';
import token from '../model/token';
@@ -136,6 +133,7 @@ export class UserRegisterHandler extends Handler {
});
await sendMail(mail, 'Sign Up', 'user_register_mail', m);
this.response.template = 'user_register_mail_sent.html';
this.response.body = { mail };
} else this.response.redirect = this.url('user_register_with_code', { code: t[0] });
} else if (phoneNumber) {
if (!global.Hydro.lib.sendSms) throw new SystemError('Cannot send sms');
@@ -148,7 +146,7 @@ export class UserRegisterHandler extends Handler {
);
await global.Hydro.lib.sendSms(phoneNumber, 'register', t[0]);
this.response.template = 'user_register_sms.html';
}
} else throw new ValidationError('mail');
}
}
@@ -237,41 +235,19 @@ 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 = await user.getById(domainId, uid);
if (!udoc) throw new UserNotFoundError(uid);
const [sdoc, rdocs, [pdocs, pcount]] = await Promise.all([
const [udoc, sdoc] = await Promise.all([
user.getById(domainId, uid),
token.getMostRecentSessionByUid(uid),
record.getByUid(domainId, uid, 30),
this.user.hasPerm(PERM.PERM_VIEW_PROBLEM)
? paginate(
problem.getMulti(domainId, { owner: uid }),
1,
100,
)
: [[], 0, 0] as [ProblemDoc[], number, number],
]);
const pdict = this.user.hasPerm(PERM.PERM_VIEW_PROBLEM)
? await problem.getList(
domainId, rdocs.map((rdoc) => rdoc.pid),
this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN) || this.user._id, false,
)
: Object.fromEntries(rdocs.map(
(rdoc) => [rdoc.pid, { ...problem.default, pid: rdoc.pid }],
));
if (!udoc) throw new UserNotFoundError(uid);
// Remove sensitive data
if (!isSelfProfile && sdoc) {
sdoc.createIp = '';
sdoc.updateIp = '';
sdoc._id = '';
}
const path = [
['Hydro', 'homepage'],
['user_detail', 'user_detail', { uid }],
];
this.response.template = 'user_detail.html';
this.response.body = {
isSelfProfile, udoc, sdoc, rdocs, pdocs, pcount, pdict, path,
};
this.response.body = { isSelfProfile, udoc, sdoc };
this.extraTitleContent = udoc.uname;
}
}
@@ -343,7 +319,6 @@ export async function apply() {
Route('user_oauth', '/oauth/:type', OauthHandler);
Route('user_oauth_callback', '/oauth/:type/callback', OauthCallbackHandler);
Route('user_register', '/register', UserRegisterHandler, PRIV.PRIV_REGISTER_USER);
Route('user_register_without_code', '/register/code', UserRegisterWithCodeHandler, PRIV.PRIV_REGISTER_USER);
Route('user_register_with_code', '/register/:code', UserRegisterWithCodeHandler, PRIV.PRIV_REGISTER_USER);
Route('user_logout', '/logout', UserLogoutHandler, PRIV.PRIV_USER_PROFILE);
Route('user_lostpass', '/lostpass', UserLostPassHandler);
-7
View File
@@ -219,13 +219,6 @@ class RecordModel {
}
return r;
}
@ArgMethod
static getByUid(domainId: string, uid: number, limit: number): Promise<RecordDoc[]> {
return RecordModel.coll.find({
domainId, 'contest.tid': null, hidden: false, uid,
}).sort({ _id: -1 }).limit(limit).toArray();
}
}
// Mark problem as deleted
@@ -5,7 +5,8 @@ import { FLAG_ALERT } from 'vj/constant/message';
import i18n from 'vj/utils/i18n';
import tpl from 'vj/utils/tpl';
const messagePage = new AutoloadPage('messagePage', () => {
const messagePage = new AutoloadPage('messagePage', (pagename) => {
if (pagename === 'home_messages') return;
let visible = true;
document.addEventListener('visibilitychange', () => {
const state = document.visibilityState;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@hydrooj/ui-default",
"version": "4.21.9",
"version": "4.21.10",
"author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0",
"main": "hydro.js",
@@ -2,7 +2,7 @@ import { NamedPage } from 'vj/misc/Page';
import api, { gql } from 'vj/utils/api';
import loadReactRedux from 'vj/utils/loadReactRedux';
import parseQueryString from 'vj/utils/parseQueryString';
import VjNotification from 'vj/components/notification';
import { ActionDialog } from 'vj/components/dialog';
import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
@@ -39,6 +39,13 @@ const page = new NamedPage('home_messages', () => {
type: 'DIALOGUES_MESSAGE_PUSH',
payload: msg,
});
new VjNotification({
title: msg.udoc.uname,
avatar: msg.udoc.avatarUrl,
message: msg.mdoc.content,
duration: 15000,
action: () => createDialog(msg.udoc),
}).show();
};
const userSelector = UserSelectAutoComplete.getOrConstruct($('.dialog__body--user-select [name="user"]'));
+8 -67
View File
@@ -46,12 +46,12 @@
</a>
{% endif %}
{% if udoc['qq'] %}
<a class="profile-header__contact-item" href="javascript:;" name="profile_contact_copy" data-content="{{ udoc['qq'] | base64_encode }}" data-tooltip="{{ _('Copy QQ Number') }}">
<a class="profile-header__contact-item" href="javascript:;" name="profile_qq_copy" data-content="{{ udoc['qq'] | base64_encode }}" data-tooltip="{{ _('Copy QQ Number') }}">
<span class="icon icon-qq"></span>
</a>
{% endif %}
{% if udoc['wechat'] %}
<a class="profile-header__contact-item" href="javascript:;" name="profile_contact_copy" data-content="{{ udoc['wechat'] | base64_encode }}" data-tooltip="{{ _('Copy WeChat Account') }}">
<a class="profile-header__contact-item" href="javascript:;" name="profile_wechat_copy" data-content="{{ udoc['wechat'] | base64_encode }}" data-tooltip="{{ _('Copy WeChat Account') }}">
<span class="icon icon-wechat"></span>
</a>
{% endif %}
@@ -98,65 +98,6 @@
{% endif %}
</div>
</li>
<li class="section__tab-item">
<h1 class="section__tab-title">{{ _('Contributions') }} ({{ pcount }})</h1>
<div class="section__tab-main">
{% if not pdocs %}
{{ nothing.render("Oh, the user doesn't have any contributions!") }}
{% else %}
<div class="section__header">
<h1 class="section__title">{{ _('Contributed Problems') }}</h1>
</div>
<div class="section__body">
{%- for pdoc in pdocs -%}
<p><a href="{{ url('problem_detail', pid=pdoc.pid|default(pdoc.docId)) }}">{{ pdoc['title'] }}</a></p>
{%- endfor -%}
</div>
{% endif %}
</div>
</li>
<li class="section__tab-item">
<h1 class="section__tab-title">{{ _('Submissions') }} ({{ udoc['nSubmit']|default(0) }})</h1>
<div class="section__tab-main">
{% if not rdocs %}
{{ nothing.render("Oh, the user hasn't submitted yet!") }}
{% else %}
<div class="section__header">
<h1 class="section__title">{{ _('Recent Submissions') }}</h1>
</div>
<div class="section__body no-padding">
<table class="data-table record_main__table">
<colgroup>
<col class="col--status">
<col class="col--problem">
<col class="col--submit-by">
<col class="col--time">
<col class="col--memory">
<col class="col--lang">
<col class="col--submit-at">
</colgroup>
<thead>
<tr>
<th class="col--status record-status--border">{{ _('Status') }}</th>
<th class="col--problem">{{ _('Problem') }}</th>
<th class="col--submit-by">{{ _('Submit By') }}</th>
<th class="col--time">{{ _('Time') }}</th>
<th class="col--memory">{{ _('Memory') }}</th>
<th class="col--lang">{{ _('Language') }}</th>
<th class="col--submit-at">{{ _('Submit At') }}</th>
</tr>
</thead>
<tbody>
{%- for rdoc in rdocs -%}
{% set pdoc = pdict[rdoc.pid] %}
{% include 'record_main_tr.html' %}
{%- endfor -%}
</tbody>
</table>
</div>
{% endif %}
</div>
</li>
</ul>
</div>
</div>
@@ -174,6 +115,12 @@
<div class="section side">
<div class="section__body">
<div class="balancer sidebar-user-stat">
<div class="balancer__body">
<div class="numbox">
<div class="numbox__num medium">{{ udoc.nSubmit or 0 }}</div>
<div class="numbox__text">{{ _('Submitted') }}</div>
</div>
</div>
<div class="balancer__body">
<div class="numbox">
<div class="numbox__num medium">{{ udoc.nAccept or 0 }}</div>
@@ -186,12 +133,6 @@
<div class="numbox__text">{{ _('Solutions Liked') }}</div>
</div>
</div>
<div class="balancer__body">
<div class="numbox">
<div class="numbox__num medium">{{ udoc.nProblems or 0 }}</div>
<div class="numbox__text">{{ _('Upload Problem') }}</div>
</div>
</div>
</div>
</div>
</div>