mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-07-06 07:18:02 +02:00
closes #1371
adds a dropdown to category view to move/pin/lock/delete multiple topics
This commit is contained in:
@@ -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) {
|
||||
topics.markAsUnreadForAll(tid, function(err) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
db.sortedSetAdd('topics:recent', Date.now(), tid, function(err) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
topics.pushUnreadCount();
|
||||
callback();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.delete = function(socket, tid, callback) {
|
||||
doTopicAction('delete', socket, tid, callback);
|
||||
};
|
||||
|
||||
SocketTopics.restore = function(socket, tid, callback) {
|
||||
doTopicAction('restore', socket, tid, callback);
|
||||
};
|
||||
|
||||
SocketTopics.lock = function(socket, tid, callback) {
|
||||
doTopicAction('lock', socket, tid, callback);
|
||||
};
|
||||
|
||||
SocketTopics.unlock = function(socket, tid, callback) {
|
||||
doTopicAction('unlock', socket, tid, callback);
|
||||
};
|
||||
|
||||
SocketTopics.pin = function(socket, tid, callback) {
|
||||
doTopicAction('pin', socket, tid, callback);
|
||||
};
|
||||
|
||||
SocketTopics.unpin = function(socket, tid, callback) {
|
||||
doTopicAction('unpin', socket, tid, callback);
|
||||
};
|
||||
|
||||
function doTopicAction(action, socket, tid, callback) {
|
||||
if(!tid) {
|
||||
SocketTopics.markAsUnreadForAll = function(socket, tids, callback) {
|
||||
if(!Array.isArray(tids)) {
|
||||
return callback(new Error('[[error:invalid-tid]]'));
|
||||
}
|
||||
|
||||
threadTools.privileges(tid, socket.uid, function(err, privileges) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
async.each(tids, function(tid, next) {
|
||||
topics.markAsUnreadForAll(tid, function(err) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if(!privileges || !privileges.editable) {
|
||||
return callback(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
db.sortedSetAdd('topics:recent', Date.now(), tid, function(err) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
topics.pushUnreadCount();
|
||||
next();
|
||||
});
|
||||
});
|
||||
}, callback);
|
||||
};
|
||||
|
||||
if(threadTools[action]) {
|
||||
threadTools[action](tid, socket.uid, callback);
|
||||
}
|
||||
});
|
||||
SocketTopics.delete = function(socket, tids, callback) {
|
||||
doTopicAction('delete', socket, tids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.restore = function(socket, tids, callback) {
|
||||
doTopicAction('restore', socket, tids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.lock = function(socket, tids, callback) {
|
||||
doTopicAction('lock', socket, tids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.unlock = function(socket, tids, callback) {
|
||||
doTopicAction('unlock', socket, tids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.pin = function(socket, tids, callback) {
|
||||
doTopicAction('pin', socket, tids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.unpin = function(socket, tids, callback) {
|
||||
doTopicAction('unpin', socket, tids, callback);
|
||||
};
|
||||
|
||||
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 next(err);
|
||||
}
|
||||
|
||||
if(!privileges || !privileges.editable) {
|
||||
return next(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
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) {
|
||||
if(err) {
|
||||
return callback(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 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
|
||||
});
|
||||
|
||||
index.server.sockets.in('category_' + oldCid).emit('event:topic_moved', {
|
||||
tid: tid
|
||||
});
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
callback(null);
|
||||
});
|
||||
}, 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.setTopicField(tid, 'locked', lock ? 1 : 0);
|
||||
topics.getTopicField(tid, 'cid', function(err, cid) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
websockets.in('topic_' + tid).emit(lock ? 'event:topic_locked' : 'event:topic_unlocked', {
|
||||
tid: tid
|
||||
});
|
||||
topics.setTopicField(tid, 'locked', lock ? 1 : 0);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(null, {
|
||||
tid: tid
|
||||
websockets.in('topic_' + tid).emit(lock ? 'event:topic_locked' : 'event:topic_unlocked', {
|
||||
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,
|
||||
isLocked: lock
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ThreadTools.pin = function(tid, uid, callback) {
|
||||
@@ -129,20 +147,33 @@ var winston = require('winston'),
|
||||
};
|
||||
|
||||
function togglePin(tid, uid, pin, callback) {
|
||||
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);
|
||||
});
|
||||
topics.getTopicField(tid, 'cid', function(err, cid) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
websockets.in('topic_' + tid).emit(pin ? 'event:topic_pinned' : 'event:topic_unpinned', {
|
||||
tid: tid
|
||||
});
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(null, {
|
||||
tid: tid
|
||||
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,
|
||||
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,
|
||||
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