client/posts: add post merging
This commit is contained in:
parent
8c0fa7f49e
commit
f1445b9c24
16 changed files with 502 additions and 24 deletions
33
client/css/post-detail-view.styl
Normal file
33
client/css/post-detail-view.styl
Normal file
|
@ -0,0 +1,33 @@
|
|||
#post
|
||||
width: 100%
|
||||
max-width: 40em
|
||||
h1
|
||||
margin-top: 0
|
||||
form
|
||||
width: 100%
|
||||
.buttons i
|
||||
margin-right: 0.5em
|
||||
.post-merge
|
||||
.left-post-container
|
||||
width: 47%
|
||||
float: left
|
||||
.right-post-container
|
||||
width: 47%
|
||||
float: right
|
||||
input[type=text]
|
||||
width: 8em
|
||||
margin-top: -2px
|
||||
.post-mirror
|
||||
margin-bottom: 1em
|
||||
&:after
|
||||
display: block
|
||||
height: 1px
|
||||
content: ' '
|
||||
clear: both
|
||||
.post-thumbnail .thumbnail
|
||||
width: 100%
|
||||
height: 9em
|
||||
.target-post .thumbnail
|
||||
margin-right: 0.35em
|
||||
.target-post, .target-post-content
|
||||
margin: 1em 0
|
12
client/html/post_detail.tpl
Normal file
12
client/html/post_detail.tpl
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div class='content-wrapper' id='post'>
|
||||
<h1>Post #<%- ctx.post.id %></h1>
|
||||
<nav class='buttons'><!--
|
||||
--><ul><!--
|
||||
--><li><a href='/post/<%- ctx.post.id %>'><i class='fa fa-reply'></i> Main view</a></li><!--
|
||||
--><% if (ctx.canMerge) { %><!--
|
||||
--><li data-name='merge'><a href='/post/<%- ctx.post.id %>/merge'>Merge with…</a></li><!--
|
||||
--><% } %><!--
|
||||
--></ul><!--
|
||||
--></nav>
|
||||
<div class='post-content-holder'></div>
|
||||
</div>
|
|
@ -84,12 +84,15 @@
|
|||
</section>
|
||||
<% } %>
|
||||
|
||||
<% if (ctx.canFeaturePosts || ctx.canDeletePosts) { %>
|
||||
<% if (ctx.canFeaturePosts || ctx.canDeletePosts || ctx.canMergePosts) { %>
|
||||
<section class='management'>
|
||||
<ul>
|
||||
<% if (ctx.canFeaturePosts) { %>
|
||||
<li><a href class='feature'>Feature this post on main page</a></li>
|
||||
<% } %>
|
||||
<% if (ctx.canMergePosts) { %>
|
||||
<li><a href class='merge'>Merge this post with another</a></li>
|
||||
<% } %>
|
||||
<% if (ctx.canDeletePosts) { %>
|
||||
<li><a href class='delete'>Delete this post</a></li>
|
||||
<% } %>
|
||||
|
|
23
client/html/post_merge.tpl
Normal file
23
client/html/post_merge.tpl
Normal file
|
@ -0,0 +1,23 @@
|
|||
<div class='post-merge'>
|
||||
<form>
|
||||
<ul>
|
||||
<li class='post-mirror'>
|
||||
<div class='left-post-container'></div>
|
||||
<div class='right-post-container'></div>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<p>Tags, relations, scores, favorites and comments will be
|
||||
merged. All other properties need to be handled manually.</p>
|
||||
|
||||
<%= ctx.makeCheckbox({required: true, text: 'I confirm that I want to merge these posts.'}) %>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class='messages'></div>
|
||||
|
||||
<div class='buttons'>
|
||||
<input type='submit' value='Merge posts'/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
48
client/html/post_merge_side.tpl
Normal file
48
client/html/post_merge_side.tpl
Normal file
|
@ -0,0 +1,48 @@
|
|||
<% if (ctx.editable) { %>
|
||||
<p>Post # <input type='text' pattern='^[0-9]+$' value='<%- ctx.post ? ctx.post.id : '' %>'/></p>
|
||||
<% } else { %>
|
||||
<p>Post # <input type='text' pattern='^[0-9]+$' value='<%- ctx.post ? ctx.post.id : '' %>' readonly/></p>
|
||||
<% } %>
|
||||
|
||||
<% if (ctx.post) { %>
|
||||
<div class='post-thumbnail'>
|
||||
<a rel='external' href='<%- ctx.post.contentUrl %>'>
|
||||
<%= ctx.makeThumbnail(ctx.post.thumbnailUrl) %>
|
||||
</a>
|
||||
</div>
|
||||
<div class='target-post'>
|
||||
<%= ctx.makeRadio({
|
||||
required: true,
|
||||
text: 'Merge to this post<br/><small>' +
|
||||
ctx.makeUserLink(ctx.post.user) +
|
||||
', ' +
|
||||
ctx.makeRelativeTime(ctx.post.creationTime) +
|
||||
'</small>',
|
||||
name: 'target-post',
|
||||
value: ctx.name,
|
||||
}) %>
|
||||
</div>
|
||||
<div class='target-post-content'>
|
||||
<%= ctx.makeRadio({
|
||||
required: true,
|
||||
text: 'Use this file<br/><small>' +
|
||||
ctx.makeFileSize(ctx.post.fileSize) + ' ' +
|
||||
{
|
||||
'image/gif': 'GIF',
|
||||
'image/jpeg': 'JPEG',
|
||||
'image/png': 'PNG',
|
||||
'video/webm': 'WEBM',
|
||||
'application/x-shockwave-flash': 'SWF',
|
||||
}[ctx.post.mimeType] +
|
||||
' (' +
|
||||
(ctx.post.canvasWidth ?
|
||||
`${ctx.post.canvasWidth}x${ctx.post.canvasHeight}` :
|
||||
'?') +
|
||||
')</small>',
|
||||
name: 'target-post-content',
|
||||
value: ctx.name,
|
||||
}) %>
|
||||
<p>
|
||||
</p>
|
||||
</div>
|
||||
<% } %>
|
20
client/js/controllers/base_post_controller.js
Normal file
20
client/js/controllers/base_post_controller.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
const api = require('../api.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
const EmptyView = require('../views/empty_view.js');
|
||||
|
||||
class BasePostController {
|
||||
constructor(ctx) {
|
||||
if (!api.hasPrivilege('posts:view')) {
|
||||
this._view = new EmptyView();
|
||||
this._view.showError('You don\'t have privileges to view posts.');
|
||||
return;
|
||||
}
|
||||
|
||||
topNavigation.activate('posts');
|
||||
topNavigation.setTitle('Post #' + ctx.parameters.id.toString());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BasePostController;
|
86
client/js/controllers/post_detail_controller.js
Normal file
86
client/js/controllers/post_detail_controller.js
Normal file
|
@ -0,0 +1,86 @@
|
|||
'use strict';
|
||||
|
||||
const router = require('../router.js');
|
||||
const api = require('../api.js');
|
||||
const misc = require('../util/misc.js');
|
||||
const settings = require('../models/settings.js');
|
||||
const Comment = require('../models/comment.js');
|
||||
const Post = require('../models/post.js');
|
||||
const PostList = require('../models/post_list.js');
|
||||
const PostDetailView = require('../views/post_detail_view.js');
|
||||
const BasePostController = require('./base_post_controller.js');
|
||||
const EmptyView = require('../views/empty_view.js');
|
||||
|
||||
class PostDetailController extends BasePostController {
|
||||
constructor(ctx, section) {
|
||||
super(ctx);
|
||||
|
||||
Post.get(ctx.parameters.id).then(post => {
|
||||
this._id = ctx.parameters.id;
|
||||
post.addEventListener('change', e => this._evtSaved(e, section));
|
||||
|
||||
this._view = new PostDetailView({
|
||||
post: post,
|
||||
section: section,
|
||||
canMerge: api.hasPrivilege('posts:merge'),
|
||||
});
|
||||
|
||||
this._view.addEventListener('select', e => this._evtSelect(e));
|
||||
this._view.addEventListener('merge', e => this._evtMerge(e));
|
||||
}, errorMessage => {
|
||||
this._view = new EmptyView();
|
||||
this._view.showError(errorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
showSuccess(message) {
|
||||
this._view.showSuccess(message);
|
||||
}
|
||||
|
||||
_evtSelect(e) {
|
||||
this._view.clearMessages();
|
||||
this._view.disableForm();
|
||||
Post.get(e.detail.postId).then(post => {
|
||||
this._view.selectPost(post);
|
||||
this._view.enableForm();
|
||||
}, errorMessage => {
|
||||
this._view.showError(errorMessage);
|
||||
this._view.enableForm();
|
||||
});
|
||||
}
|
||||
|
||||
_evtSaved(e, section) {
|
||||
misc.disableExitConfirmation();
|
||||
if (this._id !== e.detail.post.id) {
|
||||
router.replace(
|
||||
'/post/' + e.detail.post.id + '/' + section, null, false);
|
||||
}
|
||||
}
|
||||
|
||||
_evtMerge(e) {
|
||||
this._view.clearMessages();
|
||||
this._view.disableForm();
|
||||
e.detail.post.merge(e.detail.targetPost.id, e.detail.useOldContent)
|
||||
.then(() => {
|
||||
this._view = new PostDetailView({
|
||||
post: e.detail.targetPost,
|
||||
section: 'merge',
|
||||
canMerge: api.hasPrivilege('posts:merge'),
|
||||
});
|
||||
this._view.showSuccess('Post merged.');
|
||||
router.replace(
|
||||
'/post/' + e.detail.targetPost.id + '/merge', null, false);
|
||||
}, errorMessage => {
|
||||
this._view.showError(errorMessage);
|
||||
this._view.enableForm();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = router => {
|
||||
router.enter(
|
||||
'/post/:id/merge',
|
||||
(ctx, next) => {
|
||||
ctx.controller = new PostDetailController(ctx, 'merge');
|
||||
});
|
||||
};
|
|
@ -7,26 +7,19 @@ const settings = require('../models/settings.js');
|
|||
const Comment = require('../models/comment.js');
|
||||
const Post = require('../models/post.js');
|
||||
const PostList = require('../models/post_list.js');
|
||||
const topNavigation = require('../models/top_navigation.js');
|
||||
const PostView = require('../views/post_view.js');
|
||||
const PostMainView = require('../views/post_main_view.js');
|
||||
const BasePostController = require('./base_post_controller.js');
|
||||
const EmptyView = require('../views/empty_view.js');
|
||||
|
||||
class PostController {
|
||||
constructor(id, editMode, ctx) {
|
||||
if (!api.hasPrivilege('posts:view')) {
|
||||
this._view = new EmptyView();
|
||||
this._view.showError('You don\'t have privileges to view posts.');
|
||||
return;
|
||||
}
|
||||
|
||||
topNavigation.activate('posts');
|
||||
topNavigation.setTitle('Post #' + id.toString());
|
||||
class PostMainController extends BasePostController {
|
||||
constructor(ctx, editMode) {
|
||||
super(ctx);
|
||||
|
||||
let parameters = ctx.parameters;
|
||||
Promise.all([
|
||||
Post.get(id),
|
||||
Post.get(ctx.parameters.id),
|
||||
PostList.getAround(
|
||||
id, this._decorateSearchQuery(
|
||||
ctx.parameters.id, this._decorateSearchQuery(
|
||||
parameters ? parameters.query : '')),
|
||||
]).then(responses => {
|
||||
const [post, aroundResponse] = responses;
|
||||
|
@ -36,13 +29,13 @@ class PostController {
|
|||
if (parameters.query) {
|
||||
ctx.state.parameters = parameters;
|
||||
const url = editMode ?
|
||||
'/post/' + id + '/edit' :
|
||||
'/post/' + id;
|
||||
'/post/' + ctx.parameters.id + '/edit' :
|
||||
'/post/' + ctx.parameters.id;
|
||||
router.replace(url, ctx.state, false);
|
||||
}
|
||||
|
||||
this._post = post;
|
||||
this._view = new PostView({
|
||||
this._view = new PostMainView({
|
||||
post: post,
|
||||
editMode: editMode,
|
||||
prevPostId: aroundResponse.prev ? aroundResponse.prev.id : null,
|
||||
|
@ -72,6 +65,8 @@ class PostController {
|
|||
'feature', e => this._evtFeaturePost(e));
|
||||
this._view.sidebarControl.addEventListener(
|
||||
'delete', e => this._evtDeletePost(e));
|
||||
this._view.sidebarControl.addEventListener(
|
||||
'merge', e => this._evtMergePost(e));
|
||||
}
|
||||
|
||||
if (this._view.commentFormControl) {
|
||||
|
@ -128,6 +123,10 @@ class PostController {
|
|||
});
|
||||
}
|
||||
|
||||
_evtMergePost(e) {
|
||||
router.show('/post/' + e.detail.post.id + '/merge');
|
||||
}
|
||||
|
||||
_evtDeletePost(e) {
|
||||
this._view.sidebarControl.disableForm();
|
||||
this._view.sidebarControl.clearMessages();
|
||||
|
@ -262,7 +261,7 @@ module.exports = router => {
|
|||
if (ctx.state.parameters) {
|
||||
Object.assign(ctx.parameters, ctx.state.parameters);
|
||||
}
|
||||
ctx.controller = new PostController(ctx.parameters.id, true, ctx);
|
||||
ctx.controller = new PostMainController(ctx, true);
|
||||
});
|
||||
router.enter(
|
||||
'/post/:id/:parameters(.*)?',
|
||||
|
@ -272,6 +271,6 @@ module.exports = router => {
|
|||
if (ctx.state.parameters) {
|
||||
Object.assign(ctx.parameters, ctx.state.parameters);
|
||||
}
|
||||
ctx.controller = new PostController(ctx.parameters.id, false, ctx);
|
||||
ctx.controller = new PostMainController(ctx, false);
|
||||
});
|
||||
};
|
|
@ -36,6 +36,7 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
canCreateAnonymousPosts: api.hasPrivilege('posts:create:anonymous'),
|
||||
canDeletePosts: api.hasPrivilege('posts:delete'),
|
||||
canFeaturePosts: api.hasPrivilege('posts:feature'),
|
||||
canMergePosts: api.hasPrivilege('posts:merge'),
|
||||
}));
|
||||
|
||||
new ExpanderControl(
|
||||
|
@ -108,6 +109,11 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
'click', e => this._evtFeatureClick(e));
|
||||
}
|
||||
|
||||
if (this._mergeLinkNode) {
|
||||
this._mergeLinkNode.addEventListener(
|
||||
'click', e => this._evtMergeClick(e));
|
||||
}
|
||||
|
||||
if (this._deleteLinkNode) {
|
||||
this._deleteLinkNode.addEventListener(
|
||||
'click', e => this._evtDeleteClick(e));
|
||||
|
@ -186,6 +192,15 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
}
|
||||
}
|
||||
|
||||
_evtMergeClick(e) {
|
||||
e.preventDefault();
|
||||
this.dispatchEvent(new CustomEvent('merge', {
|
||||
detail: {
|
||||
post: this._post,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
_evtDeleteClick(e) {
|
||||
e.preventDefault();
|
||||
if (confirm('Are you sure you want to delete this post?')) {
|
||||
|
@ -314,6 +329,10 @@ class PostEditSidebarControl extends events.EventTarget {
|
|||
return this._formNode.querySelector('.management .feature');
|
||||
}
|
||||
|
||||
get _mergeLinkNode() {
|
||||
return this._formNode.querySelector('.management .merge');
|
||||
}
|
||||
|
||||
get _deleteLinkNode() {
|
||||
return this._formNode.querySelector('.management .delete');
|
||||
}
|
||||
|
|
|
@ -34,7 +34,8 @@ controllers.push(require('./controllers/auth_controller.js'));
|
|||
controllers.push(require('./controllers/password_reset_controller.js'));
|
||||
controllers.push(require('./controllers/comments_controller.js'));
|
||||
controllers.push(require('./controllers/snapshots_controller.js'));
|
||||
controllers.push(require('./controllers/post_controller.js'));
|
||||
controllers.push(require('./controllers/post_detail_controller.js'));
|
||||
controllers.push(require('./controllers/post_main_controller.js'));
|
||||
controllers.push(require('./controllers/post_list_controller.js'));
|
||||
controllers.push(require('./controllers/post_upload_controller.js'));
|
||||
controllers.push(require('./controllers/tag_controller.js'));
|
||||
|
|
|
@ -190,6 +190,31 @@ class Post extends events.EventTarget {
|
|||
});
|
||||
}
|
||||
|
||||
merge(targetId, useOldContent) {
|
||||
return api.get('/post/' + encodeURIComponent(targetId))
|
||||
.then(response => {
|
||||
return api.post('/post-merge/', {
|
||||
removeVersion: this._version,
|
||||
remove: this._id,
|
||||
mergeToVersion: response.version,
|
||||
mergeTo: targetId,
|
||||
replaceContent: useOldContent,
|
||||
});
|
||||
}, response => {
|
||||
return Promise.reject(response);
|
||||
}).then(response => {
|
||||
this._updateFromResponse(response);
|
||||
this.dispatchEvent(new CustomEvent('change', {
|
||||
detail: {
|
||||
post: this,
|
||||
},
|
||||
}));
|
||||
return Promise.resolve();
|
||||
}, response => {
|
||||
return Promise.reject(response.description);
|
||||
});
|
||||
}
|
||||
|
||||
setScore(score) {
|
||||
return api.put('/post/' + this._id + '/score', {score: score})
|
||||
.then(response => {
|
||||
|
|
80
client/js/views/post_detail_view.js
Normal file
80
client/js/views/post_detail_view.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
'use strict';
|
||||
|
||||
const events = require('../events.js');
|
||||
const views = require('../util/views.js');
|
||||
const PostMergeView = require('./post_merge_view.js');
|
||||
const EmptyView = require('../views/empty_view.js');
|
||||
|
||||
const template = views.getTemplate('post-detail');
|
||||
|
||||
class PostDetailView extends events.EventTarget {
|
||||
constructor(ctx) {
|
||||
super();
|
||||
|
||||
this._ctx = ctx;
|
||||
ctx.post.addEventListener('change', e => this._evtChange(e));
|
||||
ctx.section = ctx.section || 'summary';
|
||||
|
||||
this._hostNode = document.getElementById('content-holder');
|
||||
this._install();
|
||||
}
|
||||
|
||||
_install() {
|
||||
const ctx = this._ctx;
|
||||
views.replaceContent(this._hostNode, template(ctx));
|
||||
|
||||
for (let item of this._hostNode.querySelectorAll('[data-name]')) {
|
||||
item.classList.toggle(
|
||||
'active', item.getAttribute('data-name') === ctx.section);
|
||||
}
|
||||
|
||||
ctx.hostNode = this._hostNode.querySelector('.post-content-holder');
|
||||
if (ctx.section === 'merge') {
|
||||
if (!this._ctx.canMerge) {
|
||||
this._view = new EmptyView();
|
||||
this._view.showError(
|
||||
'You don\'t have privileges to merge posts.');
|
||||
} else {
|
||||
this._view = new PostMergeView(ctx);
|
||||
events.proxyEvent(this._view, this, 'select');
|
||||
events.proxyEvent(this._view, this, 'submit', 'merge');
|
||||
}
|
||||
|
||||
} else {
|
||||
// this._view = new PostSummaryView(ctx);
|
||||
}
|
||||
|
||||
views.syncScrollPosition();
|
||||
}
|
||||
|
||||
clearMessages() {
|
||||
this._view.clearMessages();
|
||||
}
|
||||
|
||||
enableForm() {
|
||||
this._view.enableForm();
|
||||
}
|
||||
|
||||
disableForm() {
|
||||
this._view.disableForm();
|
||||
}
|
||||
|
||||
showSuccess(message) {
|
||||
this._view.showSuccess(message);
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
this._view.showError(message);
|
||||
}
|
||||
|
||||
selectPost(post) {
|
||||
this._view.selectPost(post);
|
||||
}
|
||||
|
||||
_evtChange(e) {
|
||||
this._ctx.post = e.detail.post;
|
||||
this._install(this._ctx);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PostDetailView;
|
|
@ -13,9 +13,9 @@ const PostEditSidebarControl =
|
|||
const CommentListControl = require('../controls/comment_list_control.js');
|
||||
const CommentFormControl = require('../controls/comment_form_control.js');
|
||||
|
||||
const template = views.getTemplate('post');
|
||||
const template = views.getTemplate('post-main');
|
||||
|
||||
class PostView {
|
||||
class PostMainView {
|
||||
constructor(ctx) {
|
||||
this._hostNode = document.getElementById('content-holder');
|
||||
|
||||
|
@ -118,4 +118,4 @@ class PostView {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = PostView;
|
||||
module.exports = PostMainView;
|
129
client/js/views/post_merge_view.js
Normal file
129
client/js/views/post_merge_view.js
Normal file
|
@ -0,0 +1,129 @@
|
|||
'use strict';
|
||||
|
||||
const config = require('../config.js');
|
||||
const events = require('../events.js');
|
||||
const views = require('../util/views.js');
|
||||
|
||||
const KEY_RETURN = 13;
|
||||
const template = views.getTemplate('post-merge');
|
||||
const sideTemplate = views.getTemplate('post-merge-side');
|
||||
|
||||
class PostMergeView extends events.EventTarget {
|
||||
constructor(ctx) {
|
||||
super();
|
||||
|
||||
this._ctx = ctx;
|
||||
this._post = ctx.post;
|
||||
this._hostNode = ctx.hostNode;
|
||||
|
||||
this._leftPost = ctx.post;
|
||||
this._rightPost = null;
|
||||
views.replaceContent(this._hostNode, template(this._ctx));
|
||||
views.decorateValidator(this._formNode);
|
||||
|
||||
this._refreshLeftSide();
|
||||
this._refreshRightSide();
|
||||
|
||||
this._formNode.addEventListener('submit', e => this._evtSubmit(e));
|
||||
}
|
||||
|
||||
clearMessages() {
|
||||
views.clearMessages(this._hostNode);
|
||||
}
|
||||
|
||||
enableForm() {
|
||||
views.enableForm(this._formNode);
|
||||
}
|
||||
|
||||
disableForm() {
|
||||
views.disableForm(this._formNode);
|
||||
}
|
||||
|
||||
showSuccess(message) {
|
||||
views.showSuccess(this._hostNode, message);
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
views.showError(this._hostNode, message);
|
||||
}
|
||||
|
||||
selectPost(post) {
|
||||
this._rightPost = post;
|
||||
this._refreshRightSide();
|
||||
}
|
||||
|
||||
_refreshLeftSide() {
|
||||
views.replaceContent(
|
||||
this._leftSideNode,
|
||||
sideTemplate(Object.assign({}, this._ctx, {
|
||||
post: this._leftPost,
|
||||
name: 'left',
|
||||
editable: false})));
|
||||
}
|
||||
|
||||
_refreshRightSide() {
|
||||
views.replaceContent(
|
||||
this._rightSideNode,
|
||||
sideTemplate(Object.assign({}, this._ctx, {
|
||||
post: this._rightPost,
|
||||
name: 'right',
|
||||
editable: true})));
|
||||
|
||||
if (this._targetPostFieldNode) {
|
||||
this._targetPostFieldNode.addEventListener(
|
||||
'keydown', e => this._evtTargetPostFieldKeyDown(e));
|
||||
}
|
||||
}
|
||||
|
||||
_evtSubmit(e) {
|
||||
e.preventDefault();
|
||||
const checkedTargetPost = this._formNode.querySelector(
|
||||
'.target-post :checked').value;
|
||||
const checkedTargetPostContent = this._formNode.querySelector(
|
||||
'.target-post-content :checked').value;
|
||||
this.dispatchEvent(new CustomEvent('submit', {
|
||||
detail: {
|
||||
post: checkedTargetPost == 'left' ?
|
||||
this._rightPost :
|
||||
this._leftPost,
|
||||
targetPost: checkedTargetPost == 'left' ?
|
||||
this._leftPost :
|
||||
this._rightPost,
|
||||
useOldContent: checkedTargetPostContent !== checkedTargetPost,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
_evtTargetPostFieldKeyDown(e) {
|
||||
const key = e.which;
|
||||
if (key !== KEY_RETURN) {
|
||||
return;
|
||||
}
|
||||
e.target.blur();
|
||||
e.preventDefault();
|
||||
this.dispatchEvent(new CustomEvent('select', {
|
||||
detail: {
|
||||
postId: this._targetPostFieldNode.value,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
get _formNode() {
|
||||
return this._hostNode.querySelector('form');
|
||||
}
|
||||
|
||||
get _leftSideNode() {
|
||||
return this._hostNode.querySelector('.left-post-container');
|
||||
}
|
||||
|
||||
get _rightSideNode() {
|
||||
return this._hostNode.querySelector('.right-post-container');
|
||||
}
|
||||
|
||||
get _targetPostFieldNode() {
|
||||
return this._formNode.querySelector(
|
||||
'.post-mirror input:not([readonly])[type=text]');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PostMergeView;
|
Loading…
Reference in a new issue