client/posts: add post content editing
This commit is contained in:
parent
6635b507f2
commit
3d8eaab57a
6 changed files with 91 additions and 16 deletions
|
@ -57,6 +57,14 @@
|
|||
}) %>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<% if (ctx.canEditPostContent) { %>
|
||||
<section class='post-content'>
|
||||
<label>Content</label>
|
||||
|
||||
<div class='dropper-container'></div>
|
||||
</section>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class='messages'></div>
|
||||
|
|
|
@ -115,6 +115,9 @@ class PostController {
|
|||
if (e.detail.relations !== undefined) {
|
||||
post.relations = e.detail.relations;
|
||||
}
|
||||
if (e.detail.content !== undefined) {
|
||||
post.content = e.detail.content;
|
||||
}
|
||||
post.save()
|
||||
.then(() => {
|
||||
misc.disableExitConfirmation();
|
||||
|
|
|
@ -28,9 +28,14 @@ class FileDropperControl {
|
|||
this._fileInputNode.addEventListener(
|
||||
'change', e => this._evtFileChange(e));
|
||||
|
||||
this._originalHtml = this._dropperNode.innerHTML;
|
||||
views.replaceContent(target, source);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this._dropperNode.innerHTML = this._originalHtml;
|
||||
}
|
||||
|
||||
_resolve(files) {
|
||||
files = Array.from(files);
|
||||
if (this._options.lock) {
|
||||
|
|
|
@ -11,15 +11,17 @@ class PostContentControl {
|
|||
this._containerNode = containerNode;
|
||||
this._template = views.getTemplate('post-content');
|
||||
|
||||
this._install();
|
||||
|
||||
this._currentFitFunction = {
|
||||
'fit-both': this.fitBoth,
|
||||
'fit-original': this.fitOriginal,
|
||||
'fit-width': this.fitWidth,
|
||||
'fit-height': this.fitHeight,
|
||||
}[settings.get().fitMode] || this.fitBoth;
|
||||
this._currentFitFunction();
|
||||
|
||||
this._install();
|
||||
|
||||
this._post.addEventListener(
|
||||
'changeContent', e => this._evtPostContentChange(e));
|
||||
}
|
||||
|
||||
fitWidth() {
|
||||
|
@ -73,11 +75,15 @@ class PostContentControl {
|
|||
return this._viewportSizeCalculator()[1];
|
||||
}
|
||||
|
||||
_evtPostContentChange(e) {
|
||||
this._post = e.detail.post;
|
||||
this._post.mutateContentUrl();
|
||||
this._reinstall();
|
||||
}
|
||||
|
||||
_resize(width, height) {
|
||||
const postContentNode =
|
||||
this._containerNode.querySelector('.post-content');
|
||||
postContentNode.style.width = width + 'px';
|
||||
postContentNode.style.height = height + 'px';
|
||||
this._postContentNode.style.width = width + 'px';
|
||||
this._postContentNode.style.height = height + 'px';
|
||||
}
|
||||
|
||||
_refreshSize() {
|
||||
|
@ -85,18 +91,26 @@ class PostContentControl {
|
|||
}
|
||||
|
||||
_install() {
|
||||
const postContentNode = this._template({
|
||||
post: this._post,
|
||||
});
|
||||
if (settings.get().transparencyGrid) {
|
||||
postContentNode.classList.add('transparency-grid');
|
||||
}
|
||||
this._containerNode.appendChild(postContentNode);
|
||||
this._reinstall();
|
||||
optimizedResize.add(() => this._refreshSize());
|
||||
views.monitorNodeRemoval(
|
||||
this._containerNode, () => { this._uninstall(); });
|
||||
}
|
||||
|
||||
_reinstall() {
|
||||
const newNode = this._template({post: this._post});
|
||||
if (settings.get().transparencyGrid) {
|
||||
newNode.classList.add('transparency-grid');
|
||||
}
|
||||
if (this._postContentNode) {
|
||||
this._containerNode.replaceChild(newNode, this._postContentNode);
|
||||
} else {
|
||||
this._containerNode.appendChild(newNode);
|
||||
}
|
||||
this._postContentNode = newNode;
|
||||
this._refreshSize();
|
||||
}
|
||||
|
||||
_uninstall() {
|
||||
optimizedResize.remove(() => this._refreshSize());
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ const events = require('../events.js');
|
|||
const misc = require('../util/misc.js');
|
||||
const views = require('../util/views.js');
|
||||
const TagInputControl = require('./tag_input_control.js');
|
||||
const FileDropperControl = require('../controls/file_dropper_control.js');
|
||||
|
||||
const template = views.getTemplate('post-edit-sidebar');
|
||||
|
||||
|
@ -14,6 +15,7 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
this._hostNode = hostNode;
|
||||
this._post = post;
|
||||
this._postContentControl = postContentControl;
|
||||
this._newPostContent = null;
|
||||
|
||||
views.replaceContent(this._hostNode, template({
|
||||
post: this._post,
|
||||
|
@ -37,6 +39,24 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
if (this._tagInputNode) {
|
||||
this._tagControl = new TagInputControl(this._tagInputNode);
|
||||
}
|
||||
|
||||
if (this._contentInputNode) {
|
||||
this._contentFileDropper = new FileDropperControl(
|
||||
this._contentInputNode,
|
||||
{
|
||||
lock: true,
|
||||
resolve: files => {
|
||||
this._newPostContent = files[0];
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
this._post.addEventListener(
|
||||
'changeContent', e => this._evtPostContentChange(e));
|
||||
}
|
||||
|
||||
_evtPostContentChange(e) {
|
||||
this._contentFileDropper.reset();
|
||||
}
|
||||
|
||||
_evtSubmit(e) {
|
||||
|
@ -62,6 +82,10 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
relations: this._relationsInputNode ?
|
||||
misc.splitByWhitespace(this._relationsInputNode.value) :
|
||||
undefined,
|
||||
|
||||
content: this._newPostContent ?
|
||||
this._newPostContent :
|
||||
undefined,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
@ -89,6 +113,10 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
get _relationsInputNode() {
|
||||
return this._formNode.querySelector('.relations input');
|
||||
}
|
||||
|
||||
get _contentInputNode() {
|
||||
return this._formNode.querySelector('.post-content .dropper-container');
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = PostEditSidebarControl;
|
||||
|
|
|
@ -24,6 +24,7 @@ class Post extends events.EventTarget {
|
|||
get canvasWidth() { return this._canvasWidth || 800; }
|
||||
get canvasHeight() { return this._canvasHeight || 450; }
|
||||
get fileSize() { return this._fileSize || 0; }
|
||||
get content() { throw 'Invalid operation'; }
|
||||
|
||||
get flags() { return this._flags; }
|
||||
get tags() { return this._tags; }
|
||||
|
@ -40,6 +41,7 @@ class Post extends events.EventTarget {
|
|||
set tags(value) { this._tags = value; }
|
||||
set safety(value) { this._safety = value; }
|
||||
set relations(value) { this._relations = value; }
|
||||
set content(value) { this._content = value; }
|
||||
|
||||
static fromResponse(response) {
|
||||
const ret = new Post();
|
||||
|
@ -78,6 +80,7 @@ class Post extends events.EventTarget {
|
|||
}
|
||||
|
||||
save() {
|
||||
const files = [];
|
||||
const detail = {};
|
||||
|
||||
// send only changed fields to avoid user privilege violation
|
||||
|
@ -93,15 +96,22 @@ class Post extends events.EventTarget {
|
|||
if (misc.arraysDiffer(this._relations, this._orig._relations)) {
|
||||
detail.relations = this._relations;
|
||||
}
|
||||
if (this._content) {
|
||||
files.content = this._content;
|
||||
}
|
||||
|
||||
let promise = this._id ?
|
||||
api.put('/post/' + this._id, detail) :
|
||||
api.post('/posts', detail);
|
||||
api.put('/post/' + this._id, detail, files) :
|
||||
api.post('/posts', detail, files);
|
||||
|
||||
return promise.then(response => {
|
||||
this._updateFromResponse(response);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('change', {detail: {post: this}}));
|
||||
if (this._content) {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('changeContent', {detail: {post: this}}));
|
||||
}
|
||||
return Promise.resolve();
|
||||
}, response => {
|
||||
return Promise.reject(response.description);
|
||||
|
@ -177,6 +187,13 @@ class Post extends events.EventTarget {
|
|||
});
|
||||
}
|
||||
|
||||
mutateContentUrl() {
|
||||
this._contentUrl =
|
||||
this._orig._contentUrl +
|
||||
'?bypass-cache=' +
|
||||
Math.round(Math.random()*1000);
|
||||
}
|
||||
|
||||
_updateFromResponse(response) {
|
||||
const map = {
|
||||
_id: response.id,
|
||||
|
|
Loading…
Reference in a new issue