core&ui: user_detail: show solutions (#414)

pull/422/head
undefined 2 years ago
parent e3dd65c690
commit 6ed4d74210

@ -1,6 +1,6 @@
{
"name": "hydrooj",
"version": "3.16.5",
"version": "3.16.6",
"bin": "bin/hydrooj.js",
"main": "src/loader",
"module": "src/loader",

@ -16,6 +16,7 @@ import domain from '../model/domain';
import oauth from '../model/oauth';
import * as oplog from '../model/oplog';
import problem, { ProblemDoc } from '../model/problem';
import SolutionModel from '../model/solution';
import * as system from '../model/system';
import task from '../model/task';
import token from '../model/token';
@ -323,6 +324,16 @@ class UserDetailHandler extends Handler {
this.response.body = {
isSelfProfile, udoc, sdoc, pdocs, tags,
};
if (this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_SOLUTION)) {
const psdocs = await SolutionModel.getByUser(domainId, uid).limit(10).toArray();
this.response.body.psdocs = psdocs;
if (this.user.hasPerm(PERM.PERM_VIEW_PROBLEM)) {
this.response.body.pdict = await problem.getList(
domainId, psdocs.map((i) => i.parentId), canViewHidden,
this.user.group, false, problem.PROJECTION_LIST,
);
}
}
this.UiContext.extraTitleContent = udoc.uname;
}
}

@ -46,6 +46,13 @@ class SolutionModel {
).sort({ vote: -1 });
}
static getByUser(domainId: string, uid: number) {
return document.getMulti(
domainId, document.TYPE_PROBLEM_SOLUTION,
{ parentType: document.TYPE_PROBLEM, owner: uid },
).sort({ _id: -1 });
}
static reply(domainId: string, psid: ObjectID, owner: number, content: string) {
return document.push(domainId, document.TYPE_PROBLEM_SOLUTION, psid, 'reply', content, owner);
}

@ -1,13 +1,21 @@
import Clipboard from 'clipboard';
import Notification from 'vj/components/notification';
import { AutoloadPage } from 'vj/misc/Page';
import base64 from 'vj/utils/base64';
import i18n from 'vj/utils/i18n';
import substitute from 'vj/utils/substitute';
export default new AutoloadPage('clipboard', () => {
$('[data-copy]').each(function () {
const clip = new Clipboard(this, { text: () => this.dataset.copy });
clip.on('success', () => Notification.success(i18n('Copied to clipboard!')));
clip.on('error', () => Notification.error(i18n('Copy failed :(')));
$('[data-copy]').get().forEach((el) => {
const data = $(el).attr('data-copy');
const decoded = base64.decode(data);
const clip = new Clipboard(el, { text: () => decoded });
clip.on('success', () => {
Notification.success(substitute(i18n('"{data}" copied to clipboard!'), { data: decoded }), 2000);
});
clip.on('error', () => {
Notification.error(substitute(i18n('Copy "{data}" failed :('), { data: decoded }));
});
});
$('[data-copylink]').each(function () {
const clip = new Clipboard(this, { text: () => new URL(this.dataset.copylink, document.location.href).toString() });

@ -1,6 +1,6 @@
{
"name": "@hydrooj/ui-default",
"version": "4.39.15",
"version": "4.39.16",
"author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0",
"main": "hydro.js",

@ -1,23 +0,0 @@
import Clipboard from 'clipboard';
import $ from 'jquery';
import Notification from 'vj/components/notification';
import { NamedPage } from 'vj/misc/Page';
import base64 from 'vj/utils/base64';
import i18n from 'vj/utils/i18n';
import substitute from 'vj/utils/substitute';
const page = new NamedPage('user_detail', () => {
$('[data-copy]').get().forEach((el) => {
const data = $(el).attr('data-copy');
const decoded = base64.decode(data);
const clip = new Clipboard(el, { text: () => decoded });
clip.on('success', () => {
Notification.success(substitute(i18n('"{data}" copied to clipboard!'), { data: decoded }), 2000);
});
clip.on('error', () => {
Notification.error(substitute(i18n('Copy "{data}" failed :('), { data: decoded }));
});
});
});
export default page;

@ -0,0 +1,29 @@
{% if psdocs %}
<li class="section__tab-item">
<h1 class="section__tab-title">{{ _('Recent solutions') }}</h1>
<div class="section__tab-main">
{% if not psdocs.length %}
{{ nothing.render("This person is lazy and wrote any solution") }}
{% else %}
<div class="section__body typo no-media">
<div class="typo section__body">
{% set _mark = Math.ceil(psdocs.length/4) %}
{% macro col(psdocs) %}
<div class="medium-3 columns"><ul>
{% for psdoc in psdocs %}
<li><a href="{{ url('problem_solution_detail', pid=psdoc.parentId, sid=psdoc._id) }}">{{ pdict[psdoc.parentId].title|default(psdoc._id) }}</a></li>
{% endfor %}
</ul></div>
{% endmacro %}
<div class="row">
{{ col(psdocs.slice(0, _mark)) }}
{{ col(psdocs.slice(_mark, _mark*2)) }}
{{ col(psdocs.slice(_mark*2, _mark*3)) }}
{{ col(psdocs.slice(_mark*3)) }}
</div>
</div>
</div>
{% endif %}
</div>
</li>
{% endif %}

@ -125,7 +125,7 @@
</div>
</li>
{% endif %}
{% for page in findSubModule('user_detail/') %}{% include page %}{% endfor %}
{% for page in findSubModule('partials/user_detail/') %}{% include page %}{% endfor %}
</ul>
</div>
</div>

Loading…
Cancel
Save