mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core&ui: user_detail: show solutions (#414)
This commit is contained in:
1 parent
e3dd65c690
commit
6ed4d74210
8 files changed
+62
-30
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "3.16.5",
|
"version": "3.16.6",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "src/loader",
|
"main": "src/loader",
|
||||||
"module": "src/loader",
|
"module": "src/loader",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import domain from '../model/domain';
|
|||||||
import oauth from '../model/oauth';
|
import oauth from '../model/oauth';
|
||||||
import * as oplog from '../model/oplog';
|
import * as oplog from '../model/oplog';
|
||||||
import problem, { ProblemDoc } from '../model/problem';
|
import problem, { ProblemDoc } from '../model/problem';
|
||||||
|
import SolutionModel from '../model/solution';
|
||||||
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';
|
||||||
@@ -323,6 +324,16 @@ class UserDetailHandler extends Handler {
|
|||||||
this.response.body = {
|
this.response.body = {
|
||||||
isSelfProfile, udoc, sdoc, pdocs, tags,
|
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;
|
this.UiContext.extraTitleContent = udoc.uname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,13 @@ class SolutionModel {
|
|||||||
).sort({ vote: -1 });
|
).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) {
|
static reply(domainId: string, psid: ObjectID, owner: number, content: string) {
|
||||||
return document.push(domainId, document.TYPE_PROBLEM_SOLUTION, psid, 'reply', content, owner);
|
return document.push(domainId, document.TYPE_PROBLEM_SOLUTION, psid, 'reply', content, owner);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
import Clipboard from 'clipboard';
|
import Clipboard from 'clipboard';
|
||||||
import Notification from 'vj/components/notification';
|
import Notification from 'vj/components/notification';
|
||||||
import { AutoloadPage } from 'vj/misc/Page';
|
import { AutoloadPage } from 'vj/misc/Page';
|
||||||
|
import base64 from 'vj/utils/base64';
|
||||||
import i18n from 'vj/utils/i18n';
|
import i18n from 'vj/utils/i18n';
|
||||||
|
import substitute from 'vj/utils/substitute';
|
||||||
|
|
||||||
export default new AutoloadPage('clipboard', () => {
|
export default new AutoloadPage('clipboard', () => {
|
||||||
$('[data-copy]').each(function () {
|
$('[data-copy]').get().forEach((el) => {
|
||||||
const clip = new Clipboard(this, { text: () => this.dataset.copy });
|
const data = $(el).attr('data-copy');
|
||||||
clip.on('success', () => Notification.success(i18n('Copied to clipboard!')));
|
const decoded = base64.decode(data);
|
||||||
clip.on('error', () => Notification.error(i18n('Copy failed :(')));
|
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 () {
|
$('[data-copylink]').each(function () {
|
||||||
const clip = new Clipboard(this, { text: () => new URL(this.dataset.copylink, document.location.href).toString() });
|
const clip = new Clipboard(this, { text: () => new URL(this.dataset.copylink, document.location.href).toString() });
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/ui-default",
|
"name": "@hydrooj/ui-default",
|
||||||
"version": "4.39.15",
|
"version": "4.39.16",
|
||||||
"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,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>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for page in findSubModule('user_detail/') %}{% include page %}{% endfor %}
|
{% for page in findSubModule('partials/user_detail/') %}{% include page %}{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user