mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-23 17:00:24 +01:00
closes #1371
adds a dropdown to category view to move/pin/lock/delete multiple topics
This commit is contained in:
@@ -569,6 +569,7 @@ var socket,
|
||||
|
||||
createHeaderTooltips();
|
||||
ajaxify.variables.parse();
|
||||
ajaxify.currentPage = tpl_url;
|
||||
app.processPage();
|
||||
|
||||
ajaxify.widgets.render(tpl_url, url);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"use strict";
|
||||
/* global define, config, templates, app, utils, ajaxify, socket, translator */
|
||||
|
||||
define(['composer', 'forum/pagination', 'share', 'navigator'], function(composer, pagination, share, navigator) {
|
||||
define(['composer', 'forum/pagination', 'share', 'navigator', 'forum/categoryTools'], function(composer, pagination, share, navigator, categoryTools) {
|
||||
var Category = {},
|
||||
loadingMoreTopics = false;
|
||||
|
||||
|
||||
$(window).on('action:ajaxify.start', function(ev, data) {
|
||||
if(data.url.indexOf('category') !== 0) {
|
||||
if(data && data.url.indexOf('category') !== 0) {
|
||||
navigator.hide();
|
||||
}
|
||||
});
|
||||
@@ -24,11 +24,14 @@ define(['composer', 'forum/pagination', 'share', 'navigator'], function(composer
|
||||
});
|
||||
|
||||
ajaxify.register_events([
|
||||
'event:new_topic'
|
||||
'event:new_topic', 'event:topic_deleted', 'event:topic_restored', 'event:topic_locked',
|
||||
'event:topic_unlocked', 'event:topic_pinned', 'event:topic_unpinned', 'event:topic_moved'
|
||||
]);
|
||||
|
||||
socket.on('event:new_topic', Category.onNewTopic);
|
||||
|
||||
categoryTools.init(cid);
|
||||
|
||||
enableInfiniteLoading();
|
||||
|
||||
if (!config.usePagination) {
|
||||
|
||||
168
public/src/forum/categoryTools.js
Normal file
168
public/src/forum/categoryTools.js
Normal file
@@ -0,0 +1,168 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
/* globals define, app, translator, socket, bootbox */
|
||||
|
||||
|
||||
define(['forum/topic/move', 'topicSelect'], function(move, topicSelect) {
|
||||
|
||||
var CategoryTools = {};
|
||||
|
||||
CategoryTools.init = function(cid) {
|
||||
CategoryTools.cid = cid;
|
||||
|
||||
topicSelect.init(onTopicSelect);
|
||||
|
||||
$('.delete_thread').on('click', function(e) {
|
||||
var tids = topicSelect.getSelectedTids();
|
||||
|
||||
if (tids.length) {
|
||||
var command = isAny(isTopicDeleted, tids) ? 'restore' : 'delete';
|
||||
|
||||
translator.translate('[[topic:thread_tools.' + command + '_confirm]]', function(msg) {
|
||||
bootbox.confirm(msg, function(confirm) {
|
||||
if (!confirm) {
|
||||
return;
|
||||
}
|
||||
|
||||
socket.emit('topics.' + command, tids, onCommandComplete);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.lock_thread').on('click', function(e) {
|
||||
var tids = topicSelect.getSelectedTids();
|
||||
if (tids.length) {
|
||||
socket.emit(isAny(isTopicLocked, tids) ? 'topics.unlock' : 'topics.lock', tids, onCommandComplete);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.pin_thread').on('click', function(e) {
|
||||
var tids = topicSelect.getSelectedTids();
|
||||
if (tids.length) {
|
||||
socket.emit(isAny(isTopicPinned, tids) ? 'topics.unpin' : 'topics.pin', tids, onCommandComplete);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.markAsUnreadForAll').on('click', function() {
|
||||
var tids = topicSelect.getSelectedTids();
|
||||
if (tids.length) {
|
||||
socket.emit('topics.markAsUnreadForAll', tids, function(err) {
|
||||
if(err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
app.alertSuccess('[[topic:markAsUnreadForAll.success]]');
|
||||
|
||||
onCommandComplete();
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.move_thread').on('click', function() {
|
||||
var tids = topicSelect.getSelectedTids();
|
||||
console.log(tids);
|
||||
if (tids.length) {
|
||||
move.init(tids, cid, onCommandComplete);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
socket.on('event:topic_deleted', setDeleteState);
|
||||
socket.on('event:topic_restored', setDeleteState);
|
||||
socket.on('event:topic_locked', setLockedState);
|
||||
socket.on('event:topic_unlocked', setLockedState);
|
||||
socket.on('event:topic_pinned', setPinnedState);
|
||||
socket.on('event:topic_unpinned', setPinnedState);
|
||||
socket.on('event:topic_moved', onTopicMoved);
|
||||
};
|
||||
|
||||
function closeDropDown() {
|
||||
$('.thread-tools.open').find('.dropdown-toggle').trigger('click');
|
||||
}
|
||||
|
||||
function onCommandComplete(err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
closeDropDown();
|
||||
topicSelect.unselectAll();
|
||||
}
|
||||
|
||||
function onTopicSelect() {
|
||||
var tids = topicSelect.getSelectedTids();
|
||||
var isAnyDeleted = isAny(isTopicDeleted, tids);
|
||||
var isAnyPinned = isAny(isTopicPinned, tids);
|
||||
var isAnyLocked = isAny(isTopicLocked, tids);
|
||||
|
||||
translator.translate('<i class="fa fa-fw ' + (isAnyDeleted ? 'fa-comment' : 'fa-trash-o') + '"></i> [[topic:thread_tools.' + (isAnyDeleted ? 'restore' : 'delete') + ']]', function(translated) {
|
||||
$('.delete_thread span').html(translated);
|
||||
});
|
||||
|
||||
translator.translate('<i class="fa fa-fw fa-thumb-tack"></i> [[topic:thread_tools.' + (isAnyPinned ? 'unpin' : 'pin') + ']]', function(translated) {
|
||||
$('.pin_thread').html(translated);
|
||||
});
|
||||
|
||||
translator.translate('<i class="fa fa-fw fa-' + (isAnyLocked ? 'un': '') + 'lock"></i> [[topic:thread_tools.' + (isAnyLocked ? 'un': '') + 'lock]]', function(translated) {
|
||||
$('.lock_thread').html(translated);
|
||||
});
|
||||
}
|
||||
|
||||
function isAny(method, tids) {
|
||||
for(var i=0; i<tids.length; ++i) {
|
||||
if(method(tids[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isTopicDeleted(tid) {
|
||||
return getTopicEl(tid).hasClass('deleted');
|
||||
}
|
||||
|
||||
function isTopicLocked(tid) {
|
||||
return getTopicEl(tid).hasClass('locked');
|
||||
}
|
||||
|
||||
function isTopicPinned(tid) {
|
||||
return getTopicEl(tid).hasClass('pinned');
|
||||
}
|
||||
|
||||
function getTopicEl(tid) {
|
||||
return $('#topics-container li[data-tid="' + tid + '"]');
|
||||
}
|
||||
|
||||
function setDeleteState(data) {
|
||||
var topic = getTopicEl(data.tid);
|
||||
topic.toggleClass('deleted', data.isDeleted);
|
||||
topic.find('.fa-lock').toggleClass('hide', !data.isDeleted);
|
||||
}
|
||||
|
||||
function setPinnedState(data) {
|
||||
var topic = getTopicEl(data.tid);
|
||||
topic.toggleClass('pinned', data.isPinned);
|
||||
topic.find('.fa-thumb-tack').toggleClass('hide', !data.isPinned);
|
||||
ajaxify.go('category/' + CategoryTools.cid);
|
||||
}
|
||||
|
||||
function setLockedState(data) {
|
||||
var topic = getTopicEl(data.tid);
|
||||
topic.toggleClass('locked', data.isLocked);
|
||||
topic.find('.fa-lock').toggleClass('hide', !data.isLocked);
|
||||
}
|
||||
|
||||
function onTopicMoved(data) {
|
||||
getTopicEl(data.tid).remove();
|
||||
}
|
||||
|
||||
return CategoryTools;
|
||||
});
|
||||
@@ -144,7 +144,7 @@ define(['forum/pagination', 'forum/topic/threadTools', 'forum/topic/postTools',
|
||||
|
||||
ajaxify.register_events([
|
||||
'event:voted', 'event:favourited', 'event:new_post', 'get_users_in_room',
|
||||
'event:topic_deleted', 'event:topic_restored', 'event:topic:locked',
|
||||
'event:topic_deleted', 'event:topic_restored', 'event:topic_locked',
|
||||
'event:topic_unlocked', 'event:topic_pinned', 'event:topic_unpinned',
|
||||
'event:topic_moved', 'event:post_edited', 'event:post_deleted', 'event:post_restored',
|
||||
'posts.favourite', 'user.isOnline', 'posts.upvote', 'posts.downvote',
|
||||
|
||||
@@ -4,19 +4,23 @@
|
||||
|
||||
define(function() {
|
||||
|
||||
var Move = {};
|
||||
|
||||
Move.init = function(tid) {
|
||||
var modal = $('#move_thread_modal'),
|
||||
var Move = {},
|
||||
modal,
|
||||
targetCid,
|
||||
targetCategoryLabel;
|
||||
|
||||
$('.move_thread').on('click', function(e) {
|
||||
modal.modal('show');
|
||||
return false;
|
||||
});
|
||||
Move.init = function(tids, currentCid, onComplete) {
|
||||
modal = $('#move_thread_modal');
|
||||
|
||||
Move.tids = tids;
|
||||
Move.currentCid = currentCid;
|
||||
Move.onComplete = onComplete;
|
||||
|
||||
modal.on('shown.bs.modal', onMoveModalShown);
|
||||
$('#move-confirm').hide();
|
||||
modal.modal('show');
|
||||
|
||||
};
|
||||
|
||||
function onMoveModalShown() {
|
||||
var loadingEl = $('#categories-loading');
|
||||
@@ -43,7 +47,7 @@ define(function() {
|
||||
|
||||
function selectCategory(category) {
|
||||
modal.find('#confirm-category-name').html(category.html());
|
||||
$('#move-confirm').css({display: 'block'});
|
||||
$('#move-confirm').show();
|
||||
|
||||
targetCid = category.attr('data-cid');
|
||||
targetCategoryLabel = category.html();
|
||||
@@ -51,14 +55,10 @@ define(function() {
|
||||
}
|
||||
|
||||
function onCommitClicked() {
|
||||
var commitEl = $('#move_thread_commit'),
|
||||
cancelEl = $('#move_thread_cancel');
|
||||
var commitEl = $('#move_thread_commit');
|
||||
|
||||
if (!commitEl.prop('disabled') && targetCid) {
|
||||
commitEl.prop('disabled', true);
|
||||
cancelEl.fadeOut(250);
|
||||
modal.find('.modal-header button').fadeOut(250);
|
||||
commitEl.html('Moving <i class="fa-spin fa-refresh"></i>');
|
||||
|
||||
moveTopic();
|
||||
}
|
||||
@@ -66,15 +66,20 @@ define(function() {
|
||||
|
||||
function moveTopic() {
|
||||
socket.emit('topics.move', {
|
||||
tid: tid,
|
||||
tids: Move.tids,
|
||||
cid: targetCid
|
||||
}, function(err) {
|
||||
modal.modal('hide');
|
||||
$('#move_thread_commit').prop('disabled', false);
|
||||
|
||||
if(err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
|
||||
app.alertSuccess('[[topic:topic_move_success, ' + targetCategoryLabel + ']]');
|
||||
if (typeof Move.onComplete === 'function') {
|
||||
Move.onComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -84,6 +89,9 @@ define(function() {
|
||||
|
||||
for (var x = 0; x < categories.length; ++x) {
|
||||
info = categories[x];
|
||||
if(parseInt(info.cid, 10) === parseInt(Move.currentCid, 10)) {
|
||||
continue;
|
||||
}
|
||||
$('<li />')
|
||||
.css({background: info.bgColor, color: info.color || '#fff'})
|
||||
.addClass(info.disabled === '1' ? ' disabled' : '')
|
||||
@@ -94,7 +102,6 @@ define(function() {
|
||||
|
||||
$('#categories-loading').remove();
|
||||
}
|
||||
};
|
||||
|
||||
return Move;
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ define(['forum/topic/fork', 'forum/topic/move'], function(fork, move) {
|
||||
translator.translate('[[topic:thread_tools.' + command + '_confirm]]', function(msg) {
|
||||
bootbox.confirm(msg, function(confirm) {
|
||||
if (confirm) {
|
||||
socket.emit('topics.' + command, tid);
|
||||
socket.emit('topics.' + command, [tid]);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -27,18 +27,18 @@ define(['forum/topic/fork', 'forum/topic/move'], function(fork, move) {
|
||||
});
|
||||
|
||||
$('.lock_thread').on('click', function(e) {
|
||||
socket.emit(threadState.locked !== '1' ? 'topics.lock' : 'topics.unlock', tid);
|
||||
socket.emit(threadState.locked !== '1' ? 'topics.lock' : 'topics.unlock', [tid]);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.pin_thread').on('click', function(e) {
|
||||
socket.emit(threadState.pinned !== '1' ? 'topics.pin' : 'topics.unpin', tid);
|
||||
socket.emit(threadState.pinned !== '1' ? 'topics.pin' : 'topics.unpin', [tid]);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.markAsUnreadForAll').on('click', function() {
|
||||
var btn = $(this);
|
||||
socket.emit('topics.markAsUnreadForAll', tid, function(err) {
|
||||
socket.emit('topics.markAsUnreadForAll', [tid], function(err) {
|
||||
if(err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
@@ -48,7 +48,10 @@ define(['forum/topic/fork', 'forum/topic/move'], function(fork, move) {
|
||||
return false;
|
||||
});
|
||||
|
||||
move.init(tid);
|
||||
$('.move_thread').on('click', function(e) {
|
||||
move.init([tid], ajaxify.variables.get('category_id'));
|
||||
return false;
|
||||
});
|
||||
|
||||
fork.init();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/* globals define, app, socket */
|
||||
|
||||
define(['forum/recent'], function(recent) {
|
||||
define(['forum/recent', 'topicSelect'], function(recent, topicSelect) {
|
||||
var Unread = {},
|
||||
loadingMoreTopics = false;
|
||||
|
||||
@@ -16,14 +16,7 @@ define(['forum/recent'], function(recent) {
|
||||
recent.watchForNewPosts();
|
||||
|
||||
$('#markSelectedRead').on('click', function() {
|
||||
function getSelectedTids() {
|
||||
var tids = [];
|
||||
$('#topics-container .category-item.selected').each(function() {
|
||||
tids.push($(this).attr('data-tid'));
|
||||
});
|
||||
return tids;
|
||||
}
|
||||
var tids = getSelectedTids();
|
||||
var tids = topicSelect.getSelectedTids();
|
||||
if(!tids.length) {
|
||||
return;
|
||||
}
|
||||
@@ -77,14 +70,7 @@ define(['forum/recent'], function(recent) {
|
||||
|
||||
socket.emit('categories.get', onCategoriesLoaded);
|
||||
|
||||
$('#topics-container').on('click', '.select', function() {
|
||||
var select = $(this);
|
||||
var isChecked = !select.hasClass('fa-square-o');
|
||||
|
||||
select.toggleClass('fa-check-square-o', !isChecked);
|
||||
select.toggleClass('fa-square-o', isChecked);
|
||||
select.parents('.category-item').toggleClass('selected', !isChecked);
|
||||
});
|
||||
topicSelect.init();
|
||||
|
||||
if ($("body").height() <= $(window).height() && $('#topics-container').children().length >= 20) {
|
||||
$('#load-more-btn').show();
|
||||
|
||||
36
public/src/modules/topicSelect.js
Normal file
36
public/src/modules/topicSelect.js
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
/* globals define*/
|
||||
|
||||
define(function() {
|
||||
var TopicSelect = {};
|
||||
|
||||
TopicSelect.init = function(onSelect) {
|
||||
$('#topics-container').on('click', '.select', function() {
|
||||
var select = $(this);
|
||||
var isChecked = !select.hasClass('fa-square-o');
|
||||
|
||||
select.toggleClass('fa-check-square-o', !isChecked);
|
||||
select.toggleClass('fa-square-o', isChecked);
|
||||
select.parents('.category-item').toggleClass('selected', !isChecked);
|
||||
if (typeof onSelect === 'function') {
|
||||
onSelect();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
TopicSelect.getSelectedTids = function() {
|
||||
var tids = [];
|
||||
$('#topics-container .category-item.selected').each(function() {
|
||||
tids.push($(this).attr('data-tid'));
|
||||
});
|
||||
return tids;
|
||||
};
|
||||
|
||||
TopicSelect.unselectAll = function() {
|
||||
$('#topics-container .category-item.selected').removeClass('selected');
|
||||
$('#topics-container .select').toggleClass('fa-check-square-o', false).toggleClass('fa-square-o', true);
|
||||
};
|
||||
|
||||
return TopicSelect;
|
||||
});
|
||||
@@ -57,7 +57,7 @@ module.exports = function(Categories) {
|
||||
db.getSortedSetRevRange('cid:' + cid + ':active_users', 0, 23, callback);
|
||||
};
|
||||
|
||||
Categories.moveActiveUsers = function(tid, oldCid, cid, callback) {
|
||||
Categories.moveActiveUsers = function(tid, oldCid, cid) {
|
||||
function updateUser(uid, timestamp) {
|
||||
Categories.addActiveUser(cid, uid, timestamp);
|
||||
Categories.isUserActiveIn(oldCid, uid, function(err, active) {
|
||||
|
||||
@@ -22,25 +22,27 @@ module.exports = function(Categories) {
|
||||
});
|
||||
};
|
||||
|
||||
Categories.moveRecentReplies = function(tid, oldCid, cid, callback) {
|
||||
function movePost(pid, callback) {
|
||||
Categories.moveRecentReplies = function(tid, oldCid, cid) {
|
||||
function movePost(pid, next) {
|
||||
posts.getPostField(pid, 'timestamp', function(err, timestamp) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
return next(err);
|
||||
}
|
||||
|
||||
db.sortedSetRemove('categories:recent_posts:cid:' + oldCid, pid);
|
||||
db.sortedSetAdd('categories:recent_posts:cid:' + cid, timestamp, pid);
|
||||
callback();
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
topics.getPids(tid, function(err, pids) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
if(!err && pids) {
|
||||
async.each(pids, movePost, function(err) {
|
||||
if (err) {
|
||||
winston.error(err.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async.each(pids, movePost, callback);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -120,64 +120,72 @@ SocketTopics.markCategoryTopicsRead = function(socket, cid, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.markAsUnreadForAll = function(socket, tid, callback) {
|
||||
SocketTopics.markAsUnreadForAll = function(socket, tids, callback) {
|
||||
if(!Array.isArray(tids)) {
|
||||
return callback(new Error('[[error:invalid-tid]]'));
|
||||
}
|
||||
|
||||
async.each(tids, function(tid, next) {
|
||||
topics.markAsUnreadForAll(tid, function(err) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
return next(err);
|
||||
}
|
||||
|
||||
db.sortedSetAdd('topics:recent', Date.now(), tid, function(err) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
return next(err);
|
||||
}
|
||||
topics.pushUnreadCount();
|
||||
callback();
|
||||
next();
|
||||
});
|
||||
});
|
||||
}, callback);
|
||||
};
|
||||
|
||||
SocketTopics.delete = function(socket, tid, callback) {
|
||||
doTopicAction('delete', socket, tid, callback);
|
||||
SocketTopics.delete = function(socket, tids, callback) {
|
||||
doTopicAction('delete', socket, tids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.restore = function(socket, tid, callback) {
|
||||
doTopicAction('restore', socket, tid, callback);
|
||||
SocketTopics.restore = function(socket, tids, callback) {
|
||||
doTopicAction('restore', socket, tids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.lock = function(socket, tid, callback) {
|
||||
doTopicAction('lock', socket, tid, callback);
|
||||
SocketTopics.lock = function(socket, tids, callback) {
|
||||
doTopicAction('lock', socket, tids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.unlock = function(socket, tid, callback) {
|
||||
doTopicAction('unlock', socket, tid, callback);
|
||||
SocketTopics.unlock = function(socket, tids, callback) {
|
||||
doTopicAction('unlock', socket, tids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.pin = function(socket, tid, callback) {
|
||||
doTopicAction('pin', socket, tid, callback);
|
||||
SocketTopics.pin = function(socket, tids, callback) {
|
||||
doTopicAction('pin', socket, tids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.unpin = function(socket, tid, callback) {
|
||||
doTopicAction('unpin', socket, tid, callback);
|
||||
SocketTopics.unpin = function(socket, tids, callback) {
|
||||
doTopicAction('unpin', socket, tids, callback);
|
||||
};
|
||||
|
||||
function doTopicAction(action, socket, tid, callback) {
|
||||
if(!tid) {
|
||||
function doTopicAction(action, socket, tids, callback) {
|
||||
if(!tids) {
|
||||
return callback(new Error('[[error:invalid-tid]]'));
|
||||
}
|
||||
|
||||
async.each(tids, function(tid, next) {
|
||||
threadTools.privileges(tid, socket.uid, function(err, privileges) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if(!privileges || !privileges.editable) {
|
||||
return callback(new Error('[[error:no-privileges]]'));
|
||||
return next(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
if(threadTools[action]) {
|
||||
threadTools[action](tid, socket.uid, callback);
|
||||
if(typeof threadTools[action] === 'function') {
|
||||
threadTools[action](tid, socket.uid, next);
|
||||
}
|
||||
});
|
||||
}, callback);
|
||||
}
|
||||
|
||||
SocketTopics.createTopicFromPosts = function(socket, data, callback) {
|
||||
@@ -215,21 +223,45 @@ SocketTopics.movePost = function(socket, data, callback) {
|
||||
};
|
||||
|
||||
SocketTopics.move = function(socket, data, callback) {
|
||||
if(!data || !data.tid || !data.cid) {
|
||||
if(!data || !Array.isArray(data.tids) || !data.cid) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
threadTools.move(data.tid, data.cid, function(err) {
|
||||
async.each(data.tids, function(tid, next) {
|
||||
var oldCid;
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
threadTools.privileges(tid, socket.uid, next);
|
||||
},
|
||||
function(privileges, next) {
|
||||
if(!(privileges.admin || privileges.moderator)) {
|
||||
return next(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
next();
|
||||
},
|
||||
function(next) {
|
||||
topics.getTopicField(tid, 'cid', next);
|
||||
},
|
||||
function(cid, next) {
|
||||
oldCid = cid;
|
||||
threadTools.move(tid, data.cid, next);
|
||||
}
|
||||
], function(err) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
return next(err);
|
||||
}
|
||||
|
||||
index.server.sockets.in('topic_' + data.tid).emit('event:topic_moved', {
|
||||
tid: data.tid
|
||||
index.server.sockets.in('topic_' + tid).emit('event:topic_moved', {
|
||||
tid: tid
|
||||
});
|
||||
|
||||
callback(null);
|
||||
index.server.sockets.in('category_' + oldCid).emit('event:topic_moved', {
|
||||
tid: tid
|
||||
});
|
||||
|
||||
next();
|
||||
});
|
||||
}, callback);
|
||||
};
|
||||
|
||||
SocketTopics.followCheck = function(socket, tid, callback) {
|
||||
|
||||
@@ -63,15 +63,14 @@ var winston = require('winston'),
|
||||
};
|
||||
|
||||
function toggleDelete(tid, uid, isDelete, callback) {
|
||||
topics.getTopicField(tid, 'deleted', function(err, deleted) {
|
||||
topics.getTopicFields(tid, ['cid', 'deleted'], function(err, topicData) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (parseInt(deleted, 10) && isDelete) {
|
||||
return callback(new Error('[[error:topic-already-deleted]]'));
|
||||
} else if (!parseInt(deleted, 10) && !isDelete) {
|
||||
return callback(new Error('[[error:topic-already-restored]]'));
|
||||
var alreadyDeletedOrRestored = (parseInt(topicData.deleted, 10) && isDelete) || (!parseInt(topicData.deleted, 10) && !isDelete);
|
||||
if (alreadyDeletedOrRestored) {
|
||||
return callback(null, {tid: tid});
|
||||
}
|
||||
|
||||
topics[isDelete ? 'delete' : 'restore'](tid, function(err) {
|
||||
@@ -88,7 +87,13 @@ var winston = require('winston'),
|
||||
websockets.emitTopicPostStats();
|
||||
|
||||
websockets.in('topic_' + tid).emit(isDelete ? 'event:topic_deleted' : 'event:topic_restored', {
|
||||
tid: tid
|
||||
tid: tid,
|
||||
isDelete: isDelete
|
||||
});
|
||||
|
||||
websockets.in('category_' + topicData.cid).emit(isDelete ? 'event:topic_deleted' : 'event:topic_restored', {
|
||||
tid: tid,
|
||||
isDelete: isDelete
|
||||
});
|
||||
|
||||
callback(null, {
|
||||
@@ -107,17 +112,30 @@ var winston = require('winston'),
|
||||
};
|
||||
|
||||
function toggleLock(tid, uid, lock, callback) {
|
||||
topics.getTopicField(tid, 'cid', function(err, cid) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
topics.setTopicField(tid, 'locked', lock ? 1 : 0);
|
||||
|
||||
websockets.in('topic_' + tid).emit(lock ? 'event:topic_locked' : 'event:topic_unlocked', {
|
||||
tid: tid
|
||||
tid: tid,
|
||||
isLocked: lock
|
||||
});
|
||||
|
||||
websockets.in('category_' + cid).emit(lock ? 'event:topic_locked' : 'event:topic_unlocked', {
|
||||
tid: tid,
|
||||
isLocked: lock
|
||||
});
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(null, {
|
||||
tid: tid
|
||||
tid: tid,
|
||||
isLocked: lock
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ThreadTools.pin = function(tid, uid, callback) {
|
||||
@@ -129,20 +147,33 @@ var winston = require('winston'),
|
||||
};
|
||||
|
||||
function togglePin(tid, uid, pin, callback) {
|
||||
topics.getTopicField(tid, 'cid', function(err, cid) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
topics.setTopicField(tid, 'pinned', pin ? 1 : 0);
|
||||
topics.getTopicFields(tid, ['cid', 'lastposttime'], function(err, topicData) {
|
||||
db.sortedSetAdd('categories:' + topicData.cid + ':tid', pin ? Math.pow(2, 53) : topicData.lastposttime, tid);
|
||||
});
|
||||
|
||||
websockets.in('topic_' + tid).emit(pin ? 'event:topic_pinned' : 'event:topic_unpinned', {
|
||||
tid: tid
|
||||
tid: tid,
|
||||
isPinned: pin
|
||||
});
|
||||
|
||||
websockets.in('category_' + cid).emit(pin ? 'event:topic_pinned' : 'event:topic_unpinned', {
|
||||
tid: tid,
|
||||
isPinned: pin
|
||||
});
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(null, {
|
||||
tid: tid
|
||||
tid: tid,
|
||||
isPinned: pin
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ThreadTools.move = function(tid, cid, callback) {
|
||||
@@ -165,8 +196,6 @@ var winston = require('winston'),
|
||||
}
|
||||
var oldCid = topic.cid;
|
||||
|
||||
topics.setTopicField(tid, 'cid', cid);
|
||||
|
||||
if(!parseInt(topic.deleted, 10)) {
|
||||
categories.incrementCategoryFieldBy(oldCid, 'topic_count', -1);
|
||||
categories.incrementCategoryFieldBy(cid, 'topic_count', 1);
|
||||
@@ -174,7 +203,9 @@ var winston = require('winston'),
|
||||
|
||||
categories.moveActiveUsers(tid, oldCid, cid);
|
||||
|
||||
categories.moveRecentReplies(tid, oldCid, cid, callback);
|
||||
categories.moveRecentReplies(tid, oldCid, cid);
|
||||
|
||||
topics.setTopicField(tid, 'cid', cid, callback);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user