mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-02 03:55:55 +01:00
closes #2134
This commit is contained in:
@@ -59,6 +59,7 @@
|
|||||||
"thread_tools.move_all": "Move All",
|
"thread_tools.move_all": "Move All",
|
||||||
"thread_tools.fork": "Fork Topic",
|
"thread_tools.fork": "Fork Topic",
|
||||||
"thread_tools.delete": "Delete Topic",
|
"thread_tools.delete": "Delete Topic",
|
||||||
|
"thread_tools.delete-posts": "Delete Posts",
|
||||||
"thread_tools.delete_confirm": "Are you sure you want to delete this topic?",
|
"thread_tools.delete_confirm": "Are you sure you want to delete this topic?",
|
||||||
"thread_tools.restore": "Restore Topic",
|
"thread_tools.restore": "Restore Topic",
|
||||||
"thread_tools.restore_confirm": "Are you sure you want to restore this topic?",
|
"thread_tools.restore_confirm": "Are you sure you want to restore this topic?",
|
||||||
@@ -90,6 +91,7 @@
|
|||||||
"fork_topic_instruction": "Click the posts you want to fork",
|
"fork_topic_instruction": "Click the posts you want to fork",
|
||||||
"fork_no_pids": "No posts selected!",
|
"fork_no_pids": "No posts selected!",
|
||||||
"fork_success": "Successfully forked topic! Click here to go to the forked topic.",
|
"fork_success": "Successfully forked topic! Click here to go to the forked topic.",
|
||||||
|
"delete_posts_instruction": "Click the posts you want to delete/purge",
|
||||||
|
|
||||||
"composer.title_placeholder": "Enter your topic title here...",
|
"composer.title_placeholder": "Enter your topic title here...",
|
||||||
"composer.handle_placeholder": "Name",
|
"composer.handle_placeholder": "Name",
|
||||||
|
|||||||
105
public/src/client/topic/delete-posts.js
Normal file
105
public/src/client/topic/delete-posts.js
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* globals define, app, ajaxify, socket, templates, translator */
|
||||||
|
|
||||||
|
define('forum/topic/delete-posts', ['components', 'postSelect'], function(components, postSelect) {
|
||||||
|
|
||||||
|
var DeletePosts = {},
|
||||||
|
modal,
|
||||||
|
deleteBtn,
|
||||||
|
purgeBtn;
|
||||||
|
|
||||||
|
DeletePosts.init = function() {
|
||||||
|
$('.topic').on('click', '[component="topic/delete/posts"]', onDeletePostsClicked);
|
||||||
|
};
|
||||||
|
|
||||||
|
function onDeletePostsClicked() {
|
||||||
|
parseModal(function(html) {
|
||||||
|
modal = $(html);
|
||||||
|
|
||||||
|
modal.on('hidden.bs.modal', function() {
|
||||||
|
modal.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteBtn = modal.find('#delete_posts_confirm');
|
||||||
|
purgeBtn = modal.find('#purge_posts_confirm');
|
||||||
|
|
||||||
|
showModal();
|
||||||
|
|
||||||
|
modal.find('.close,#delete_posts_cancel').on('click', closeModal);
|
||||||
|
|
||||||
|
postSelect.init(function() {
|
||||||
|
checkButtonEnable();
|
||||||
|
showPostsSelected();
|
||||||
|
});
|
||||||
|
showPostsSelected();
|
||||||
|
|
||||||
|
deleteBtn.on('click', function() {
|
||||||
|
deletePosts(deleteBtn, 'posts.deletePosts');
|
||||||
|
});
|
||||||
|
purgeBtn.on('click', function() {
|
||||||
|
deletePosts(purgeBtn, 'posts.purgePosts');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseModal(callback) {
|
||||||
|
templates.parse('partials/delete_posts_modal', {}, function(html) {
|
||||||
|
translator.translate(html, callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showModal() {
|
||||||
|
modal.modal({backdrop: false, show: true})
|
||||||
|
.css('position', 'fixed')
|
||||||
|
.css('left', Math.max(0, (($(window).width() - modal.outerWidth()) / 2) + $(window).scrollLeft()) + 'px')
|
||||||
|
.css('top', '0px')
|
||||||
|
.css('z-index', '2000');
|
||||||
|
}
|
||||||
|
|
||||||
|
function deletePosts(btn, command) {
|
||||||
|
btn.attr('disabled', true);
|
||||||
|
socket.emit(command, {
|
||||||
|
tid: ajaxify.data.tid,
|
||||||
|
pids: postSelect.pids
|
||||||
|
}, function(err) {
|
||||||
|
btn.removeAttr('disabled');
|
||||||
|
if (err) {
|
||||||
|
return app.alertError(err.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
closeModal();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showPostsSelected() {
|
||||||
|
if (postSelect.pids.length) {
|
||||||
|
modal.find('#pids').text(postSelect.pids.join(', '));
|
||||||
|
} else {
|
||||||
|
modal.find('#pids').translateHtml('[[topic:fork_no_pids]]');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkButtonEnable() {
|
||||||
|
if (postSelect.pids.length) {
|
||||||
|
deleteBtn.removeAttr('disabled');
|
||||||
|
purgeBtn.removeAttr('disabled');
|
||||||
|
} else {
|
||||||
|
deleteBtn.attr('disabled', true);
|
||||||
|
purgeBtn.attr('disabled', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeModal() {
|
||||||
|
postSelect.pids.forEach(function(pid) {
|
||||||
|
components.get('post', 'pid', pid).css('opacity', 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.modal('hide');
|
||||||
|
|
||||||
|
components.get('topic').off('click', '[data-pid]');
|
||||||
|
postSelect.enableClicksOnPosts();
|
||||||
|
}
|
||||||
|
|
||||||
|
return DeletePosts;
|
||||||
|
});
|
||||||
@@ -2,29 +2,16 @@
|
|||||||
|
|
||||||
/* globals define, app, ajaxify, socket, templates, translator */
|
/* globals define, app, ajaxify, socket, templates, translator */
|
||||||
|
|
||||||
define('forum/topic/fork', ['components'], function(components) {
|
define('forum/topic/fork', ['components', 'postSelect'], function(components, postSelect) {
|
||||||
|
|
||||||
var Fork = {},
|
var Fork = {},
|
||||||
forkModal,
|
forkModal,
|
||||||
forkCommit,
|
forkCommit;
|
||||||
pids = [];
|
|
||||||
|
|
||||||
Fork.init = function() {
|
Fork.init = function() {
|
||||||
$('.topic').on('click', '[component="topic/fork"]', onForkThreadClicked);
|
$('.topic').on('click', '[component="topic/fork"]', onForkThreadClicked);
|
||||||
};
|
};
|
||||||
|
|
||||||
function disableClicks() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function disableClicksOnPosts() {
|
|
||||||
components.get('post').on('click', 'button,a', disableClicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
function enableClicksOnPosts() {
|
|
||||||
components.get('post').off('click', 'button,a', disableClicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onForkThreadClicked() {
|
function onForkThreadClicked() {
|
||||||
parseModal(function(html) {
|
parseModal(function(html) {
|
||||||
forkModal = $(html);
|
forkModal = $(html);
|
||||||
@@ -34,21 +21,19 @@ define('forum/topic/fork', ['components'], function(components) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
forkCommit = forkModal.find('#fork_thread_commit');
|
forkCommit = forkModal.find('#fork_thread_commit');
|
||||||
pids.length = 0;
|
|
||||||
|
|
||||||
showForkModal();
|
showForkModal();
|
||||||
showNoPostsSelected();
|
|
||||||
|
|
||||||
forkModal.find('.close,#fork_thread_cancel').on('click', closeForkModal);
|
forkModal.find('.close,#fork_thread_cancel').on('click', closeForkModal);
|
||||||
forkModal.find('#fork-title').on('change', checkForkButtonEnable);
|
forkModal.find('#fork-title').on('change', checkForkButtonEnable);
|
||||||
components.get('topic').on('click', '[data-pid]', function() {
|
|
||||||
togglePostSelection($(this));
|
|
||||||
});
|
|
||||||
|
|
||||||
disableClicksOnPosts();
|
postSelect.init(function() {
|
||||||
|
checkForkButtonEnable();
|
||||||
|
showPostsSelected();
|
||||||
|
});
|
||||||
|
showPostsSelected();
|
||||||
|
|
||||||
forkCommit.on('click', createTopicFromPosts);
|
forkCommit.on('click', createTopicFromPosts);
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +55,7 @@ define('forum/topic/fork', ['components'], function(components) {
|
|||||||
forkCommit.attr('disabled', true);
|
forkCommit.attr('disabled', true);
|
||||||
socket.emit('topics.createTopicFromPosts', {
|
socket.emit('topics.createTopicFromPosts', {
|
||||||
title: forkModal.find('#fork-title').val(),
|
title: forkModal.find('#fork-title').val(),
|
||||||
pids: pids
|
pids: postSelect.pids
|
||||||
}, function(err, newTopic) {
|
}, function(err, newTopic) {
|
||||||
function fadeOutAndRemove(pid) {
|
function fadeOutAndRemove(pid) {
|
||||||
components.get('post', 'pid', pid).fadeOut(500, function() {
|
components.get('post', 'pid', pid).fadeOut(500, function() {
|
||||||
@@ -92,46 +77,24 @@ define('forum/topic/fork', ['components'], function(components) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for(var i=0; i<pids.length; ++i) {
|
postSelect.pids.forEach(function(pid) {
|
||||||
fadeOutAndRemove(pids[i]);
|
fadeOutAndRemove(pid);
|
||||||
}
|
});
|
||||||
|
|
||||||
closeForkModal();
|
closeForkModal();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function togglePostSelection(post) {
|
function showPostsSelected() {
|
||||||
var newPid = post.attr('data-pid');
|
if (postSelect.pids.length) {
|
||||||
|
forkModal.find('#fork-pids').text(postSelect.pids.join(', '));
|
||||||
if (parseInt(post.attr('data-index'), 10) === 0) {
|
} else {
|
||||||
return;
|
forkModal.find('#fork-pids').translateHtml('[[topic:fork_no_pids]]');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPid) {
|
|
||||||
var index = pids.indexOf(newPid);
|
|
||||||
if(index === -1) {
|
|
||||||
pids.push(newPid);
|
|
||||||
post.css('opacity', '0.5');
|
|
||||||
} else {
|
|
||||||
pids.splice(index, 1);
|
|
||||||
post.css('opacity', '1.0');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pids.length) {
|
|
||||||
pids.sort(function(a,b) { return a - b; });
|
|
||||||
forkModal.find('#fork-pids').text(pids.join(', '));
|
|
||||||
} else {
|
|
||||||
showNoPostsSelected();
|
|
||||||
}
|
|
||||||
checkForkButtonEnable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showNoPostsSelected() {
|
|
||||||
forkModal.find('#fork-pids').translateHtml('[[topic:fork_no_pids]]');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkForkButtonEnable() {
|
function checkForkButtonEnable() {
|
||||||
if (forkModal.find('#fork-title').length && pids.length) {
|
if (forkModal.find('#fork-title').length && postSelect.pids.length) {
|
||||||
forkCommit.removeAttr('disabled');
|
forkCommit.removeAttr('disabled');
|
||||||
} else {
|
} else {
|
||||||
forkCommit.attr('disabled', true);
|
forkCommit.attr('disabled', true);
|
||||||
@@ -139,14 +102,14 @@ define('forum/topic/fork', ['components'], function(components) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeForkModal() {
|
function closeForkModal() {
|
||||||
for (var i=0; i<pids.length; ++i) {
|
postSelect.pids.forEach(function(pid) {
|
||||||
components.get('post', 'pid', pids[i]).css('opacity', 1);
|
components.get('post', 'pid', pid).css('opacity', 1);
|
||||||
}
|
});
|
||||||
|
|
||||||
forkModal.modal('hide');
|
forkModal.modal('hide');
|
||||||
|
|
||||||
components.get('topic').off('click', '[data-pid]');
|
components.get('topic').off('click', '[data-pid]');
|
||||||
enableClicksOnPosts();
|
postSelect.enableClicksOnPosts();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Fork;
|
return Fork;
|
||||||
|
|||||||
@@ -2,7 +2,13 @@
|
|||||||
|
|
||||||
/* globals define, app, ajaxify, socket, bootbox, templates */
|
/* globals define, app, ajaxify, socket, bootbox, templates */
|
||||||
|
|
||||||
define('forum/topic/threadTools', ['forum/topic/fork', 'forum/topic/move', 'components', 'translator'], function(fork, move, components, translator) {
|
define('forum/topic/threadTools', [
|
||||||
|
'forum/topic/fork',
|
||||||
|
'forum/topic/move',
|
||||||
|
'forum/topic/delete-posts',
|
||||||
|
'components',
|
||||||
|
'translator'
|
||||||
|
], function(fork, move, deletePosts, components, translator) {
|
||||||
|
|
||||||
var ThreadTools = {};
|
var ThreadTools = {};
|
||||||
|
|
||||||
@@ -64,6 +70,7 @@ define('forum/topic/threadTools', ['forum/topic/fork', 'forum/topic/move', 'comp
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
deletePosts.init();
|
||||||
fork.init();
|
fork.init();
|
||||||
|
|
||||||
components.get('topic').on('click', '[component="topic/follow"], [component="topic/unfollow"]', follow);
|
components.get('topic').on('click', '[component="topic/follow"], [component="topic/unfollow"]', follow);
|
||||||
|
|||||||
59
public/src/modules/postSelect.js
Normal file
59
public/src/modules/postSelect.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/* globals define*/
|
||||||
|
|
||||||
|
define('postSelect', ['components'], function(components) {
|
||||||
|
var PostSelect = {};
|
||||||
|
|
||||||
|
PostSelect.pids = [];
|
||||||
|
|
||||||
|
PostSelect.init = function(onSelect) {
|
||||||
|
PostSelect.pids.length = 0;
|
||||||
|
components.get('topic').on('click', '[data-pid]', function() {
|
||||||
|
togglePostSelection($(this), onSelect);
|
||||||
|
});
|
||||||
|
disableClicksOnPosts();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function togglePostSelection(post, callback) {
|
||||||
|
var newPid = post.attr('data-pid');
|
||||||
|
|
||||||
|
if (parseInt(post.attr('data-index'), 10) === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPid) {
|
||||||
|
var index = PostSelect.pids.indexOf(newPid);
|
||||||
|
if(index === -1) {
|
||||||
|
PostSelect.pids.push(newPid);
|
||||||
|
post.css('opacity', '0.5');
|
||||||
|
} else {
|
||||||
|
PostSelect.pids.splice(index, 1);
|
||||||
|
post.css('opacity', '1.0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PostSelect.pids.length) {
|
||||||
|
PostSelect.pids.sort(function(a,b) { return a - b; });
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function disableClicks() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function disableClicksOnPosts() {
|
||||||
|
components.get('post').on('click', 'button,a', disableClicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
PostSelect.enableClicksOnPosts = function() {
|
||||||
|
components.get('post').off('click', 'button,a', disableClicks);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return PostSelect;
|
||||||
|
});
|
||||||
@@ -52,6 +52,24 @@ module.exports = function(SocketPosts) {
|
|||||||
doPostAction('restore', 'event:post_restored', socket, data, callback);
|
doPostAction('restore', 'event:post_restored', socket, data, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SocketPosts.deletePosts = function(socket, data, callback) {
|
||||||
|
if (!data || !Array.isArray(data.pids)) {
|
||||||
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
|
}
|
||||||
|
async.each(data.pids, function(pid, next) {
|
||||||
|
SocketPosts.delete(socket, {pid: pid, tid: data.tid}, next);
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
SocketPosts.purgePosts = function(socket, data, callback) {
|
||||||
|
if (!data || !Array.isArray(data.pids)) {
|
||||||
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
|
}
|
||||||
|
async.each(data.pids, function(pid, next) {
|
||||||
|
SocketPosts.purge(socket, {pid: pid, tid: data.tid}, next);
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
function doPostAction(command, eventName, socket, data, callback) {
|
function doPostAction(command, eventName, socket, data, callback) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
|
|||||||
Reference in New Issue
Block a user