mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 09:38:19 +08:00
core&ui: add discussion history (#450)
Co-authored-by: 无限UCW <45730483+wuxianucw@users.noreply.github.com> Co-authored-by: undefined <i@undefined.moe>
This commit is contained in:
14 files changed
+227
-45
No files matched your search
@@ -48,6 +48,10 @@ $downvote-color = red
|
||||
float: left
|
||||
margin-bottom: rem(5px)
|
||||
|
||||
.history
|
||||
float: right
|
||||
margin-left: rem(5px)
|
||||
|
||||
.dczcomments__operations
|
||||
font-size: rem($font-size)
|
||||
float: right
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { Popover } from '@blueprintjs/core';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';
|
||||
import TimeAgo from 'timeago-react';
|
||||
import { InfoDialog } from 'vj/components/dialog';
|
||||
import { AutoloadPage } from 'vj/misc/Page';
|
||||
import i18n from 'vj/utils/i18n';
|
||||
import request from 'vj/utils/request';
|
||||
import tpl from 'vj/utils/tpl';
|
||||
|
||||
async function historyDialog(payload, time, uid) {
|
||||
const ts = new Date(time).getTime();
|
||||
const rawHtml = await fetch(`${payload}?time=${ts}&render=1`).then((res) => res.text());
|
||||
new InfoDialog({
|
||||
$body: tpl`
|
||||
<div class="typo">
|
||||
<p><div data-user>${uid}</div> ${i18n('Edited at')} <span class="time relative" data-timestamp="${ts / 1000}">${time}</span></p>
|
||||
${{ templateRaw: true, html: rawHtml }}
|
||||
</div>`,
|
||||
}).open();
|
||||
}
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
function History({ payload }) {
|
||||
const [load, setLoad] = React.useState(false);
|
||||
const { isLoading, isError, data } = useQuery(['history', payload], async () => {
|
||||
const { history } = await request.get(`${payload}?all=1`);
|
||||
return history;
|
||||
}, { enabled: !!load });
|
||||
return (
|
||||
<Popover usePortal interactionKind="hover" position="bottom" onOpening={() => setLoad(true)}>
|
||||
<span>{i18n('Edited')} <span className="icon icon-expand_more"></span></span>
|
||||
<ol className="menu">
|
||||
{(isLoading || isError) && (
|
||||
<li className="menu__item">
|
||||
<a className="menu__link">
|
||||
{isLoading ? i18n('Loading...') : i18n('Loading failed.')}
|
||||
</a>
|
||||
</li>
|
||||
)}
|
||||
{data?.map((item) => (
|
||||
<li className="menu__item" key={item.time}>
|
||||
<a className="menu__link" onClick={() => historyDialog(payload, item.time, item.uid)}>
|
||||
{i18n('Edited at')}
|
||||
{' '}
|
||||
<TimeAgo datetime={item.time} locale={i18n('timeago_locale')} />
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
const page = new AutoloadPage('discussionHistoryPage', () => {
|
||||
$('[data-discussion-history]').each((i, e) => {
|
||||
const url = $(e).data('raw-url');
|
||||
if (!url) return;
|
||||
ReactDOM.createRoot(e).render(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<History payload={url} />
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
export default page;
|
||||
@@ -254,4 +254,10 @@ export function apply(ctx: Context) {
|
||||
ctx.on('system/setting', () => triggerHotUpdate());
|
||||
ctx.on('app/watch/change', triggerHotUpdate);
|
||||
ctx.on('app/watch/unlink', triggerHotUpdate);
|
||||
ctx.on('handler/after/DiscussionRaw', async (that) => {
|
||||
if (that.args.render && that.response.type === 'text/markdown') {
|
||||
that.response.type = 'text/html';
|
||||
that.response.body = await markdown.render(that.response.body);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -285,6 +285,8 @@ Download: 下载
|
||||
Downvote: 差评
|
||||
Duration (hours): 持续时间 (小时)
|
||||
Duration: 持续时间
|
||||
Edited: 已修改
|
||||
Edited at: 修改于
|
||||
Edit any contests: 修改任意的比赛
|
||||
Edit any homework: 修改任意的作业
|
||||
Edit Contest: 编辑比赛
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hydrooj/ui-default",
|
||||
"version": "4.42.9",
|
||||
"version": "4.42.10",
|
||||
"author": "undefined <i@undefined.moe>",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "index.ts",
|
||||
@@ -87,6 +87,7 @@
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-query": "^3.39.2",
|
||||
"react-redux": "^8.0.4",
|
||||
"react-split-pane": "^0.1.92",
|
||||
"reconnecting-websocket": "^4.4.0",
|
||||
|
||||
@@ -94,6 +94,9 @@
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, avatar=false) }}
|
||||
@ {{ datetimeSpan(doc['_id'])|safe }}
|
||||
{% if doc.edited %}
|
||||
<div class="history" data-discussion-history data-raw-url="{{ url('discussion_reply_raw', did=doc.parentId, drid=doc._id) }}"><a>{{ _('Edited') }}</a></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="dczcomments__operations nojs--hide">
|
||||
{% if handler.user.hasPerm(reply_post_perm) %}
|
||||
@@ -132,6 +135,9 @@
|
||||
<div class="supplementary dczcomments__supplementary">
|
||||
{{ user.render_inline(udoc, avatar=false) }}
|
||||
@ {{ datetimeSpan(rdoc._id)|safe }}
|
||||
{% if doc.edited %}
|
||||
<div class="history" data-discussion-history data-raw-url="{{ url('discussion_tail_reply_raw', did=doc.parentId, drid=doc._id, drrid=rdoc._id) }}"><a>{{ _('Edited') }}</a></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="dczcomments__operations nojs--hide">
|
||||
{% if handler.user.hasPerm(reply_post_perm) %}
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
<li><a href="{{ url('discussion_edit', did=ddoc.docId) }}">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if ddoc.edited %}
|
||||
<li data-discussion-history data-raw-url="{{ url('discussion_raw', did=ddoc.docId) }}">{{ _('Edited') }}</li>
|
||||
{% endif %}
|
||||
<li>{{ _('{0} views').format(ddoc.views) }}</li>
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
|
||||
|
||||
@@ -84,6 +84,16 @@
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if ui.getNodes('UserDropdown').length %}
|
||||
<li class="menu__seperator"></li>
|
||||
{%- for item in ui.getNodes('UserDropdown') -%}
|
||||
<li class="menu__item nojs--hide">
|
||||
<a href="{{ url(item.name) }}" class="menu__link">
|
||||
<span class="icon icon-{{ item.args.icon }}"></span> {{ _(item.args.displayName or item.name) }}
|
||||
</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
{% endif %}
|
||||
<li class="menu__seperator"></li>
|
||||
{% if handler.user.hasPriv(PRIV.PRIV_EDIT_SYSTEM) %}
|
||||
<li class="menu__item nojs--hide">
|
||||
|
||||
Reference in new issue
Block a user