mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-01 11:35:55 +01:00
@@ -5,7 +5,7 @@ define('forum/category', [
|
||||
'forum/infinitescroll',
|
||||
'share',
|
||||
'navigator',
|
||||
'forum/categoryTools',
|
||||
'forum/category/tools',
|
||||
'sort',
|
||||
'components',
|
||||
'translator',
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
/* globals define, app, socket, bootbox, ajaxify */
|
||||
|
||||
|
||||
define('forum/categoryTools', ['forum/topic/move', 'topicSelect', 'components', 'translator'], function (move, topicSelect, components, translator) {
|
||||
define('forum/category/tools', [
|
||||
'forum/topic/move',
|
||||
'topicSelect',
|
||||
'components',
|
||||
'translator'
|
||||
], function (move, topicSelect, components, translator) {
|
||||
|
||||
var CategoryTools = {};
|
||||
|
||||
@@ -13,6 +18,8 @@ define('forum/categoryTools', ['forum/topic/move', 'topicSelect', 'components',
|
||||
|
||||
topicSelect.init(updateDropdownOptions);
|
||||
|
||||
handlePinnedTopicSort();
|
||||
|
||||
components.get('topic/delete').on('click', function () {
|
||||
categoryCommand('delete', topicSelect.getSelectedTids());
|
||||
return false;
|
||||
@@ -235,5 +242,30 @@ define('forum/categoryTools', ['forum/topic/move', 'topicSelect', 'components',
|
||||
getTopicEl(data.tid).remove();
|
||||
}
|
||||
|
||||
function handlePinnedTopicSort() {
|
||||
if (!ajaxify.data.privileges.isAdminOrMod) {
|
||||
return;
|
||||
}
|
||||
app.loadJQueryUI(function () {
|
||||
$('[component="category"]').sortable({
|
||||
items: '[component="category/topic"].pinned',
|
||||
update: function () {
|
||||
var data = [];
|
||||
|
||||
var pinnedTopics = $('[component="category/topic"].pinned');
|
||||
pinnedTopics.each(function (index, element) {
|
||||
data.push({tid: $(element).attr('data-tid'), order: pinnedTopics.length - index - 1});
|
||||
});
|
||||
|
||||
socket.emit('topics.orderPinnedTopics', data, function (err) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return CategoryTools;
|
||||
});
|
||||
@@ -58,7 +58,7 @@ module.exports = function (Meta) {
|
||||
'public/src/client/topic/threadTools.js',
|
||||
'public/src/client/categories.js',
|
||||
'public/src/client/category.js',
|
||||
'public/src/client/categoryTools.js',
|
||||
'public/src/client/category/tools.js',
|
||||
|
||||
'public/src/modules/translator.js',
|
||||
'public/src/modules/notifications.js',
|
||||
|
||||
@@ -121,4 +121,12 @@ module.exports = function (SocketTopics) {
|
||||
], callback);
|
||||
}
|
||||
|
||||
SocketTopics.orderPinnedTopics = function (socket, data, callback) {
|
||||
if (!Array.isArray(data)) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
topics.tools.orderPinnedTopics(socket.uid, data, callback);
|
||||
};
|
||||
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
var _ = require('underscore');
|
||||
|
||||
var db = require('../database');
|
||||
var categories = require('../categories');
|
||||
@@ -211,6 +212,49 @@ module.exports = function (Topics) {
|
||||
], callback);
|
||||
}
|
||||
|
||||
topicTools.orderPinnedTopics = function (uid, data, callback) {
|
||||
var cid;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
var tids = data.map(function (topic) {
|
||||
return topic && topic.tid;
|
||||
});
|
||||
Topics.getTopicsFields(tids, ['cid'], next);
|
||||
},
|
||||
function (topicData, next) {
|
||||
var uniqueCids = _.unique(topicData.map(function (topicData) {
|
||||
return topicData && parseInt(topicData.cid, 10);
|
||||
}));
|
||||
|
||||
if (uniqueCids.length > 1 || !uniqueCids.length || !uniqueCids[0]) {
|
||||
return next(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
cid = uniqueCids[0];
|
||||
|
||||
privileges.categories.isAdminOrMod(cid, uid, next);
|
||||
},
|
||||
function (isAdminOrMod, next) {
|
||||
if (!isAdminOrMod) {
|
||||
return next(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
async.eachSeries(data, function (topicData, next) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.isSortedSetMember('cid:' + cid + ':tids:pinned', topicData.tid, next);
|
||||
},
|
||||
function (isPinned, next) {
|
||||
if (isPinned) {
|
||||
db.sortedSetAdd('cid:' + cid + ':tids:pinned', topicData.order, topicData.tid, next);
|
||||
} else {
|
||||
setImmediate(next);
|
||||
}
|
||||
}
|
||||
], next);
|
||||
}, next);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
topicTools.move = function (tid, cid, uid, callback) {
|
||||
var topic;
|
||||
async.waterfall([
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
--reporter dot
|
||||
--timeout 10000
|
||||
--timeout 15000
|
||||
|
||||
@@ -101,6 +101,7 @@ describe('Plugins', function () {
|
||||
var latest;
|
||||
var pluginName = 'nodebb-plugin-imgur';
|
||||
it('should install a plugin', function (done) {
|
||||
this.timeout(20000);
|
||||
plugins.toggleInstall(pluginName, '1.0.16', function (err, pluginData) {
|
||||
assert.ifError(err);
|
||||
|
||||
|
||||
@@ -45,8 +45,6 @@ describe('Topic\'s', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
describe('.post', function () {
|
||||
@@ -362,6 +360,98 @@ describe('Topic\'s', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('order pinned topics', function () {
|
||||
var tid1;
|
||||
var tid2;
|
||||
var tid3;
|
||||
before(function (done) {
|
||||
function createTopic(callback) {
|
||||
topics.post({
|
||||
uid: topic.userId,
|
||||
title: 'topic for test',
|
||||
content: 'topic content',
|
||||
cid: topic.categoryId
|
||||
}, callback);
|
||||
}
|
||||
async.series({
|
||||
topic1: function (next) {
|
||||
createTopic(next);
|
||||
},
|
||||
topic2: function (next) {
|
||||
createTopic(next);
|
||||
},
|
||||
topic3: function (next) {
|
||||
createTopic(next);
|
||||
}
|
||||
}, function (err, results) {
|
||||
assert.ifError(err);
|
||||
tid1 = results.topic1.topicData.tid;
|
||||
tid2 = results.topic2.topicData.tid;
|
||||
tid3 = results.topic3.topicData.tid;
|
||||
async.series([
|
||||
function (next) {
|
||||
topics.tools.pin(tid1, adminUid, next);
|
||||
},
|
||||
function (next) {
|
||||
topics.tools.pin(tid2, adminUid, next);
|
||||
}
|
||||
], done);
|
||||
});
|
||||
});
|
||||
|
||||
var socketTopics = require('../src/socket.io/topics');
|
||||
it('should error with invalid data', function (done) {
|
||||
socketTopics.orderPinnedTopics({uid: adminUid}, null, function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-data]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should error with invalid data', function (done) {
|
||||
socketTopics.orderPinnedTopics({uid: adminUid}, [null, null], function (err) {
|
||||
assert.equal(err.message, '[[error:invalid-data]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should error with unprivileged user', function (done) {
|
||||
socketTopics.orderPinnedTopics({uid: 0}, [{tid: tid1}, {tid: tid2}], function (err) {
|
||||
assert.equal(err.message, '[[error:no-privileges]]');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not do anything if topics are not pinned', function (done) {
|
||||
socketTopics.orderPinnedTopics({uid: adminUid}, [{tid: tid3}], function (err) {
|
||||
assert.ifError(err);
|
||||
db.isSortedSetMember('cid:' + topic.categoryId + ':tids:pinned', tid3, function (err, isMember) {
|
||||
assert.ifError(err);
|
||||
assert(!isMember);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should order pinned topics', function (done) {
|
||||
db.getSortedSetRevRange('cid:' + topic.categoryId + ':tids:pinned', 0, -1, function (err, pinnedTids) {
|
||||
assert.ifError(err);
|
||||
assert.equal(pinnedTids[0], tid2);
|
||||
assert.equal(pinnedTids[1], tid1);
|
||||
socketTopics.orderPinnedTopics({uid: adminUid}, [{tid: tid1, order: 1}, {tid: tid2, order: 0}], function (err) {
|
||||
assert.ifError(err);
|
||||
db.getSortedSetRevRange('cid:' + topic.categoryId + ':tids:pinned', 0, -1, function (err, pinnedTids) {
|
||||
assert.ifError(err);
|
||||
assert.equal(pinnedTids[0], tid1);
|
||||
assert.equal(pinnedTids[1], tid2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('.ignore', function () {
|
||||
var newTid;
|
||||
var uid;
|
||||
|
||||
Reference in New Issue
Block a user