ui: fix psdoc_reply & overflow (#100)

This commit is contained in:
undefined committed 2021-04-20 02:08:07 +08:00
1 parent 30710cdbfb
commit 7f6c235c05
10 files changed
+87 -84

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.23.8", "version": "2.23.9",
"bin": "bin/hydrooj.js", "bin": "bin/hydrooj.js",
"main": "dist/loader.js", "main": "dist/loader.js",
"typings": "dist/loader.d.ts", "typings": "dist/loader.d.ts",
+3 -3
View File
@@ -511,7 +511,7 @@ export class ProblemSolutionHandler extends ProblemDetailHandler {
@param('content', Types.Content) @param('content', Types.Content)
async postEditReply(domainId: string, psid: ObjectID, psrid: ObjectID, content: string) { async postEditReply(domainId: string, psid: ObjectID, psrid: ObjectID, content: string) {
const [psdoc, psrdoc] = await solution.getReply(domainId, psid, psrid); const [psdoc, psrdoc] = await solution.getReply(domainId, psid, psrid);
if ((!psdoc) || psdoc.pid !== this.pdoc.docId) throw new SolutionNotFoundError(domainId, psid); if ((!psdoc) || psdoc.parentId !== this.pdoc.docId) throw new SolutionNotFoundError(domainId, psid);
if (!(psrdoc.owner === this.user._id if (!(psrdoc.owner === this.user._id
&& this.user.hasPerm(PERM.PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF))) { && this.user.hasPerm(PERM.PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF))) {
throw new PermissionError(PERM.PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF); throw new PermissionError(PERM.PERM_EDIT_PROBLEM_SOLUTION_REPLY_SELF);
@@ -524,7 +524,7 @@ export class ProblemSolutionHandler extends ProblemDetailHandler {
@param('psrid', Types.ObjectID) @param('psrid', Types.ObjectID)
async postDeleteReply(domainId: string, psid: ObjectID, psrid: ObjectID) { async postDeleteReply(domainId: string, psid: ObjectID, psrid: ObjectID) {
const [psdoc, psrdoc] = await solution.getReply(domainId, psid, psrid); const [psdoc, psrdoc] = await solution.getReply(domainId, psid, psrid);
if ((!psdoc) || psdoc.pid !== this.pdoc.docId) throw new SolutionNotFoundError(psid); if ((!psdoc) || psdoc.parentId !== this.pdoc.docId) throw new SolutionNotFoundError(psid);
if (!(psrdoc.owner === this.user._id if (!(psrdoc.owner === this.user._id
&& this.user.hasPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION_REPLY_SELF))) { && this.user.hasPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION_REPLY_SELF))) {
this.checkPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION_REPLY); this.checkPerm(PERM.PERM_DELETE_PROBLEM_SOLUTION_REPLY);
@@ -553,7 +553,7 @@ export class ProblemSolutionRawHandler extends ProblemDetailHandler {
this.checkPerm(PERM.PERM_VIEW_PROBLEM_SOLUTION); this.checkPerm(PERM.PERM_VIEW_PROBLEM_SOLUTION);
if (psrid) { if (psrid) {
const [psdoc, psrdoc] = await solution.getReply(domainId, psid, psrid); const [psdoc, psrdoc] = await solution.getReply(domainId, psid, psrid);
if ((!psdoc) || psdoc.pid !== this.pdoc.docId) throw new SolutionNotFoundError(psid, psrid); if ((!psdoc) || psdoc.parentId !== this.pdoc.docId) throw new SolutionNotFoundError(psid, psrid);
this.response.body = psrdoc.content; this.response.body = psrdoc.content;
} else { } else {
const psdoc = await solution.get(domainId, psid); const psdoc = await solution.get(domainId, psid);
+1 -1
View File
@@ -225,7 +225,7 @@ export async function getSub<T extends keyof DocType, K extends ArrayKeys<DocTyp
}); });
if (!doc) return [null, null]; if (!doc) return [null, null];
for (const sdoc of doc[key] || []) { for (const sdoc of doc[key] || []) {
if (sdoc._id === subId) return [doc, sdoc]; if (sdoc._id.toString() === subId.toString()) return [doc, sdoc];
} }
return [doc, null]; return [doc, null];
} }
+1 -1
View File
@@ -50,7 +50,7 @@ export default function (env = {}) {
name(resourcePath) { name(resourcePath) {
if (resourcePath.includes('node_modules')) { if (resourcePath.includes('node_modules')) {
const extra = resourcePath.split('node_modules')[1]; const extra = resourcePath.split('node_modules')[1];
return `modules/${extra.substr(1, extra.length - 1)}?[contenthash]`; return `modules/${extra.substr(1, extra.length - 1).replace(/\\/g, '/')}?[contenthash]`;
} }
return '[path][name].[ext]?[contenthash]'; return '[path][name].[ext]?[contenthash]';
}, },
@@ -6,8 +6,7 @@ export const config = {
'emoji', 'headings', 'bold', 'italic', 'strike', 'link', '|', 'emoji', 'headings', 'bold', 'italic', 'strike', 'link', '|',
'list', 'ordered-list', 'check', 'outdent', 'indent', '|', 'list', 'ordered-list', 'check', 'outdent', 'indent', '|',
'quote', 'line', 'code', 'inline-code', 'table', '|', 'quote', 'line', 'code', 'inline-code', 'table', '|',
'upload', 'record', '|', 'upload', 'edit-mode', 'content-theme', 'code-theme', 'export',
'edit-mode', 'content-theme', 'code-theme', 'export', 'preview',
], ],
mode: UserContext.preferedEditorType || 'ir', mode: UserContext.preferedEditorType || 'ir',
toolbarConfig: { toolbarConfig: {
@@ -40,13 +39,13 @@ export default class CmEditor extends DOMAttachedObject {
const hasFocus = $dom.is(':focus'); const hasFocus = $dom.is(':focus');
const origin = $dom.get(0); const origin = $dom.get(0);
const ele = document.createElement('div'); const ele = document.createElement('div');
const value = $dom.text(); const value = $dom.val();
await new Promise((resolve) => { await new Promise((resolve) => {
this.editor = new Vditor(ele, { this.editor = new Vditor(ele, {
...config, ...config,
...this.options, ...this.options,
after: resolve, after: resolve,
input(v) { $dom.text(v); }, input(v) { $dom.val(v); $dom.text(v); },
value, value,
cache: { id: Math.random().toString() }, cache: { id: Math.random().toString() },
}); });
@@ -54,18 +53,18 @@ export default class CmEditor extends DOMAttachedObject {
$(ele).addClass('textbox'); $(ele).addClass('textbox');
$dom.hide(); $dom.hide();
origin.parentElement.appendChild(ele); origin.parentElement.appendChild(ele);
if (hasFocus) this.focus();
this.isValid = true; this.isValid = true;
if (hasFocus) this.focus();
} }
ensureValid() { ensureValid() {
if (!this.isValid) throw new Error('Editor is not loaded'); if (!this.isValid) throw new Error('Editor is not loaded');
} }
value(...argv) { value(val) {
this.ensureValid(); this.ensureValid();
const ret = this.editor.value(...argv); if (val) return this.editor.setValue(val);
return ret; return this.editor.getValue();
} }
focus() { focus() {
@@ -1,6 +1,6 @@
import _ from 'lodash'; import _ from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject'; import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import CmEditor from '.'; import CmEditor from './index';
export default class TextareaHandler extends DOMAttachedObject { export default class TextareaHandler extends DOMAttachedObject {
static DOMAttachKey = 'vjTextareaHandlerInstance'; static DOMAttachKey = 'vjTextareaHandlerInstance';
@@ -11,7 +11,7 @@ export default class TextareaHandler extends DOMAttachedObject {
isCmEditor() { isCmEditor() {
const editor = this.getCmEditor(); const editor = this.getCmEditor();
return (editor && editor.isValid); return !!(editor && editor.isValid);
} }
val(...argv) { val(...argv) {
@@ -31,75 +31,75 @@ function init() {
} }
export default class CommentBox extends DOMAttachedObject { export default class CommentBox extends DOMAttachedObject {
static DOMAttachKey = 'vjCommentBoxInstance'; static DOMAttachKey = 'vjCommentBoxInstance';
constructor($dom, options = {}) { constructor($dom, options = {}) {
super($dom); super($dom);
init(); init();
this.$box = $template.clone(); this.$box = $template.clone();
this.$box.data('instance', this); this.$box.data('instance', this);
this.options = { this.options = {
initialText: null, initialText: null,
mode: null, mode: null,
form: null, form: null,
onCancel: () => null, onCancel: () => null,
...options, ...options,
}; };
if (this.options.initialText) this.setText(this.options.initialText); if (this.options.initialText) this.setText(this.options.initialText);
if (this.options.mode) { if (this.options.mode) {
const submitButton = this.$box.find('.dczcomments__box__submit'); const submitButton = this.$box.find('.dczcomments__box__submit');
submitButton.val(submitButton.attr(`data-value-${this.options.mode}`)); submitButton.val(submitButton.attr(`data-value-${this.options.mode}`));
}
} }
}
getTextareaHandler() { getTextareaHandler() {
const $textarea = this.$box.find('textarea'); const $textarea = this.$box.find('textarea');
return TextareaHandler.getOrConstruct($textarea); return TextareaHandler.getOrConstruct($textarea);
} }
focus() { focus() {
this.getTextareaHandler().focus(); this.getTextareaHandler().focus();
return this; return this;
} }
setText(text) { setText(text) {
this.getTextareaHandler().val(text); this.getTextareaHandler().val(text);
return this; return this;
} }
getText() { getText() {
return this.getTextareaHandler().val(); return this.getTextareaHandler().val();
} }
insertText(text) { insertText(text) {
const handler = this.getTextareaHandler(); const handler = this.getTextareaHandler();
handler.val(handler.val() + text); handler.val(handler.val() + text);
return this; return this;
} }
appendTo($dom) { appendTo($dom) {
this.$box.appendTo($dom); this.$box.appendTo($dom);
this.$box.trigger('vjContentNew'); this.$box.trigger('vjContentNew');
return this; return this;
} }
async onSubmit() { async onSubmit() {
try { try {
await request.post('', { await request.post('', {
...this.options.form, ...this.options.form,
content: this.getText(), content: this.getText(),
}); });
window.location.reload(); window.location.reload();
} catch (error) { } catch (error) {
Notification.error(error.message); Notification.error(error.message);
}
} }
}
async onCancel(ev) { async onCancel(ev) {
await this.options.onCancel(ev); await this.options.onCancel(ev);
this.$box.remove(); this.$box.remove();
this.detach(); this.detach();
} }
} }
_.assign(CommentBox, DOMAttachedObject); _.assign(CommentBox, DOMAttachedObject);
@@ -33,6 +33,11 @@ $downvote-color = red
>.media >.media
padding-bottom: 0 padding-bottom: 0
.dczcomments__item > .media
display: flex
>.media__body
max-width: calc(100% - 6.5em);
.dczcomments__supplementary .dczcomments__supplementary
float: left float: left
margin-bottom: rem(5px) margin-bottom: rem(5px)
@@ -1,4 +1,4 @@
@import 'prismjs/themes/prism.css' @import 'prism-themes/themes/prism-vs.css'
pre, code pre, code
background: $syntax-hl-bg-color background: $syntax-hl-bg-color
@@ -6,6 +6,13 @@ pre, code
pre > code pre > code
background: none background: none
line-height: 1.5 line-height: 1.5
color: black
text-align: left
white-space: pre-wrap
word-spacing: normal
word-break: normal
tab-size: 4
hyphens: none
pre pre
position: relative position: relative
@@ -15,15 +22,6 @@ code
color: $code-color color: $code-color
font-size: rem($font-size-secondary) font-size: rem($font-size-secondary)
pre > code
color: black
text-align: left
white-space: pre-wrap
word-spacing: normal
word-break: normal
tab-size: 4
hyphens: none
[data-syntax-hl-show-line-number] pre.line-numbers > code [data-syntax-hl-show-line-number] pre.line-numbers > code
white-space: pre white-space: pre
+1
View File
@@ -70,6 +70,7 @@
"pickadate": "^3.6.4", "pickadate": "^3.6.4",
"plugin-error": "^1.0.1", "plugin-error": "^1.0.1",
"postcss-loader": "^3.0.0", "postcss-loader": "^3.0.0",
"prism-themes": "^1.6.0",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",