mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-11 00:15:46 +01:00
@@ -264,7 +264,7 @@ define('forum/category', [
|
||||
|
||||
var topics = $('[component="category/topic"]');
|
||||
var afterEl = direction > 0 ? topics.last() : topics.first();
|
||||
var after = (parseInt(afterEl.attr('data-index'), 10) || 0) + 1;
|
||||
var after = (parseInt(afterEl.attr('data-index'), 10) || 0) + (direction > 0 ? 1 : 0);
|
||||
|
||||
loadTopicsAfter(after, direction);
|
||||
};
|
||||
@@ -281,8 +281,7 @@ define('forum/category', [
|
||||
cid: ajaxify.data.cid,
|
||||
after: after,
|
||||
direction: direction,
|
||||
author: params.author,
|
||||
tag: params.tag,
|
||||
query: params,
|
||||
categoryTopicSort: config.categoryTopicSort,
|
||||
}, function (data, done) {
|
||||
if (data.topics && data.topics.length) {
|
||||
|
||||
@@ -35,17 +35,13 @@ Categories.getCategoryById = function (data, callback) {
|
||||
return next(new Error('[[error:invalid-cid]]'));
|
||||
}
|
||||
category = categories[0];
|
||||
|
||||
data.category = category;
|
||||
async.parallel({
|
||||
topics: function (next) {
|
||||
Categories.getCategoryTopics(data, next);
|
||||
},
|
||||
topicCount: function (next) {
|
||||
if (Array.isArray(data.set)) {
|
||||
db.sortedSetIntersectCard(data.set, next);
|
||||
} else {
|
||||
next(null, category.topic_count);
|
||||
}
|
||||
Categories.getTopicCount(data, next);
|
||||
},
|
||||
isIgnored: function (next) {
|
||||
Categories.isIgnored([data.cid], data.uid, next);
|
||||
|
||||
@@ -5,6 +5,7 @@ var async = require('async');
|
||||
var db = require('../database');
|
||||
var topics = require('../topics');
|
||||
var plugins = require('../plugins');
|
||||
var meta = require('../meta');
|
||||
|
||||
module.exports = function (Categories) {
|
||||
Categories.getCategoryTopics = function (data, callback) {
|
||||
@@ -37,40 +38,52 @@ module.exports = function (Categories) {
|
||||
|
||||
Categories.getTopicIds = function (data, callback) {
|
||||
var pinnedTids;
|
||||
var pinnedCount;
|
||||
var totalPinnedCount;
|
||||
|
||||
var start = data.start;
|
||||
var stop = data.stop;
|
||||
var set = data.set;
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
Categories.getPinnedTids(data.cid, 0, -1, next);
|
||||
},
|
||||
function (_pinnedTids, next) {
|
||||
totalPinnedCount = _pinnedTids.length;
|
||||
var totalPinnedCount = _pinnedTids.length;
|
||||
|
||||
pinnedTids = _pinnedTids.slice(start, stop === -1 ? undefined : stop + 1);
|
||||
pinnedTids = _pinnedTids.slice(data.start, data.stop === -1 ? undefined : data.stop + 1);
|
||||
|
||||
pinnedCount = pinnedTids.length;
|
||||
var pinnedCount = pinnedTids.length;
|
||||
|
||||
var topicsPerPage = stop - start + 1;
|
||||
var topicsPerPage = data.stop - data.start + 1;
|
||||
|
||||
var normalTidsToGet = Math.max(0, topicsPerPage - pinnedCount);
|
||||
|
||||
if (!normalTidsToGet && stop !== -1) {
|
||||
if (!normalTidsToGet && data.stop !== -1) {
|
||||
return next(null, []);
|
||||
}
|
||||
|
||||
if (plugins.hasListeners('filter:categories.getTopicIds')) {
|
||||
return plugins.fireHook('filter:categories.getTopicIds', {
|
||||
tids: [],
|
||||
data: data,
|
||||
pinnedTids: pinnedTids,
|
||||
allPinnedTids: _pinnedTids,
|
||||
totalPinnedCount: totalPinnedCount,
|
||||
normalTidsToGet: normalTidsToGet,
|
||||
}, function (err, data) {
|
||||
callback(err, data && data.tids);
|
||||
});
|
||||
}
|
||||
|
||||
var set = Categories.buildTopicsSortedSet(data);
|
||||
var reverse = Categories.getSortedSetRangeDirection(data.sort);
|
||||
var start = data.start;
|
||||
if (start > 0 && totalPinnedCount) {
|
||||
start -= totalPinnedCount - pinnedCount;
|
||||
}
|
||||
stop = stop === -1 ? stop : start + normalTidsToGet - 1;
|
||||
|
||||
var stop = data.stop === -1 ? data.stop : start + normalTidsToGet - 1;
|
||||
|
||||
if (Array.isArray(set)) {
|
||||
db[data.reverse ? 'getSortedSetRevIntersect' : 'getSortedSetIntersect']({ sets: set, start: start, stop: stop }, next);
|
||||
db[reverse ? 'getSortedSetRevIntersect' : 'getSortedSetIntersect']({ sets: set, start: start, stop: stop }, next);
|
||||
} else {
|
||||
db[data.reverse ? 'getSortedSetRevRange' : 'getSortedSetRange'](set, start, stop, next);
|
||||
db[reverse ? 'getSortedSetRevRange' : 'getSortedSetRange'](set, start, stop, next);
|
||||
}
|
||||
},
|
||||
function (normalTids, next) {
|
||||
@@ -83,6 +96,54 @@ module.exports = function (Categories) {
|
||||
], callback);
|
||||
};
|
||||
|
||||
Categories.getTopicCount = function (data, callback) {
|
||||
if (plugins.hasListeners('filter:categories.getTopicCount')) {
|
||||
return plugins.fireHook('filter:categories.getTopicCount', {
|
||||
topicCount: data.category.topic_count,
|
||||
data: data,
|
||||
}, function (err, data) {
|
||||
callback(err, data && data.topicCount);
|
||||
});
|
||||
}
|
||||
var set = Categories.buildTopicsSortedSet(data);
|
||||
if (Array.isArray(set)) {
|
||||
db.sortedSetIntersectCard(set, callback);
|
||||
} else {
|
||||
callback(null, data.category.topic_count);
|
||||
}
|
||||
};
|
||||
|
||||
Categories.buildTopicsSortedSet = function (data) {
|
||||
var cid = data.cid;
|
||||
var set = 'cid:' + cid + ':tids';
|
||||
var sort = data.sort || (data.settings && data.settings.categoryTopicSort) || meta.config.categoryTopicSort || 'newest_to_oldest';
|
||||
|
||||
if (sort === 'most_posts') {
|
||||
set = 'cid:' + cid + ':tids:posts';
|
||||
}
|
||||
|
||||
if (data.targetUid) {
|
||||
set = 'cid:' + cid + ':uid:' + data.targetUid + ':tids';
|
||||
}
|
||||
|
||||
if (data.tag) {
|
||||
if (Array.isArray(data.tag)) {
|
||||
set = [set].concat(data.tag.map(function (tag) {
|
||||
return 'tag:' + tag + ':topics';
|
||||
}));
|
||||
} else {
|
||||
set = [set, 'tag:' + data.tag + ':topics'];
|
||||
}
|
||||
}
|
||||
return set;
|
||||
};
|
||||
|
||||
Categories.getSortedSetRangeDirection = function (sort) {
|
||||
sort = sort || 'newest_to_oldest';
|
||||
var reverse = sort === 'newest_to_oldest' || sort === 'most_posts';
|
||||
return reverse;
|
||||
};
|
||||
|
||||
Categories.getAllTopicIds = function (cid, start, stop, callback) {
|
||||
db.getSortedSetRange(['cid:' + cid + ':tids:pinned', 'cid:' + cid + ':tids'], start, stop, callback);
|
||||
};
|
||||
|
||||
@@ -77,49 +77,27 @@ categoryController.get = function (req, res, callback) {
|
||||
topicIndex = 0;
|
||||
}
|
||||
|
||||
var set = 'cid:' + cid + ':tids';
|
||||
var reverse = false;
|
||||
// `sort` qs has priority over user setting
|
||||
var sort = req.query.sort || settings.categoryTopicSort;
|
||||
if (sort === 'newest_to_oldest') {
|
||||
reverse = true;
|
||||
} else if (sort === 'most_posts') {
|
||||
reverse = true;
|
||||
set = 'cid:' + cid + ':tids:posts';
|
||||
}
|
||||
|
||||
var start = ((currentPage - 1) * settings.topicsPerPage) + topicIndex;
|
||||
var stop = start + settings.topicsPerPage - 1;
|
||||
|
||||
var payload = {
|
||||
cid: cid,
|
||||
set: set,
|
||||
reverse: reverse,
|
||||
start: start,
|
||||
stop: stop,
|
||||
uid: req.uid,
|
||||
settings: settings,
|
||||
};
|
||||
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
user.getUidByUserslug(req.query.author, next);
|
||||
},
|
||||
function (uid, next) {
|
||||
payload.targetUid = uid;
|
||||
if (uid) {
|
||||
payload.set = 'cid:' + cid + ':uid:' + uid + ':tids';
|
||||
}
|
||||
function (targetUid, next) {
|
||||
var payload = {
|
||||
uid: req.uid,
|
||||
cid: cid,
|
||||
start: start,
|
||||
stop: stop,
|
||||
sort: sort,
|
||||
settings: settings,
|
||||
query: req.query,
|
||||
tag: req.query.tag,
|
||||
targetUid: targetUid,
|
||||
};
|
||||
|
||||
if (req.query.tag) {
|
||||
if (Array.isArray(req.query.tag)) {
|
||||
payload.set = [payload.set].concat(req.query.tag.map(function (tag) {
|
||||
return 'tag:' + tag + ':topics';
|
||||
}));
|
||||
} else {
|
||||
payload.set = [payload.set, 'tag:' + req.query.tag + ':topics'];
|
||||
}
|
||||
}
|
||||
categories.getCategoryById(payload, next);
|
||||
},
|
||||
], next);
|
||||
|
||||
@@ -59,6 +59,7 @@ SocketCategories.loadMore = function (socket, data, callback) {
|
||||
if (!data) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
data.query = data.query || {};
|
||||
var userPrivileges;
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
@@ -70,8 +71,8 @@ SocketCategories.loadMore = function (socket, data, callback) {
|
||||
user.getSettings(socket.uid, next);
|
||||
},
|
||||
targetUid: function (next) {
|
||||
if (data.author) {
|
||||
user.getUidByUserslug(data.author, next);
|
||||
if (data.query.author) {
|
||||
user.getUidByUserslug(data.query.author, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
@@ -84,44 +85,28 @@ SocketCategories.loadMore = function (socket, data, callback) {
|
||||
return callback(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
var infScrollTopicsPerPage = 20;
|
||||
var set = 'cid:' + data.cid + ':tids';
|
||||
var reverse = false;
|
||||
|
||||
if (data.categoryTopicSort === 'newest_to_oldest') {
|
||||
reverse = true;
|
||||
} else if (data.categoryTopicSort === 'most_posts') {
|
||||
reverse = true;
|
||||
set = 'cid:' + data.cid + ':tids:posts';
|
||||
}
|
||||
var sort = data.sort || data.categoryTopicSort;
|
||||
|
||||
var start = Math.max(0, parseInt(data.after, 10));
|
||||
|
||||
if (data.direction === -1) {
|
||||
start -= reverse ? infScrollTopicsPerPage : -infScrollTopicsPerPage;
|
||||
start -= infScrollTopicsPerPage;
|
||||
}
|
||||
|
||||
var stop = start + infScrollTopicsPerPage - 1;
|
||||
|
||||
start = Math.max(0, start);
|
||||
stop = Math.max(0, stop);
|
||||
|
||||
if (results.targetUid) {
|
||||
set = 'cid:' + data.cid + ':uid:' + results.targetUid + ':tids';
|
||||
}
|
||||
|
||||
if (data.tag) {
|
||||
set = [set, 'tag:' + data.tag + ':topics'];
|
||||
}
|
||||
|
||||
categories.getCategoryTopics({
|
||||
uid: socket.uid,
|
||||
cid: data.cid,
|
||||
set: set,
|
||||
reverse: reverse,
|
||||
start: start,
|
||||
stop: stop,
|
||||
uid: socket.uid,
|
||||
targetUid: results.targetUid,
|
||||
sort: sort,
|
||||
settings: results.settings,
|
||||
query: data.query,
|
||||
tag: data.query.tag,
|
||||
targetUid: results.targetUid,
|
||||
}, next);
|
||||
},
|
||||
function (data, next) {
|
||||
|
||||
@@ -27,7 +27,12 @@ module.exports = function (Topics) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
if (cid) {
|
||||
categories.getTopicIds(cid, 'cid:' + cid + ':tids', true, 0, 199, next);
|
||||
categories.getTopicIds({
|
||||
cid: cid,
|
||||
start: 0,
|
||||
stop: 199,
|
||||
sort: 'newest_to_oldest',
|
||||
}, next);
|
||||
} else {
|
||||
db.getSortedSetRevRange('topics:recent', 0, 199, next);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,11 @@ module.exports = function (Topics) {
|
||||
Topics.getTopicField(tid, 'cid', next);
|
||||
},
|
||||
function (cid, next) {
|
||||
categories.getTopicIds(cid, 'cid:' + cid + ':tids', true, 0, 9, next);
|
||||
categories.getTopicIds({
|
||||
cid: cid,
|
||||
start: 0,
|
||||
stop: 9,
|
||||
}, next);
|
||||
},
|
||||
], callback);
|
||||
}
|
||||
|
||||
@@ -54,8 +54,6 @@ describe('Categories', function () {
|
||||
it('should retrieve a newly created category by its ID', function (done) {
|
||||
Categories.getCategoryById({
|
||||
cid: categoryObj.cid,
|
||||
set: 'cid:' + categoryObj.cid + ':tids',
|
||||
reverse: true,
|
||||
start: 0,
|
||||
stop: -1,
|
||||
uid: 0,
|
||||
@@ -103,11 +101,10 @@ describe('Categories', function () {
|
||||
it('should return a list of topics', function (done) {
|
||||
Categories.getCategoryTopics({
|
||||
cid: categoryObj.cid,
|
||||
set: 'cid:' + categoryObj.cid + ':tids',
|
||||
reverse: true,
|
||||
start: 0,
|
||||
stop: 10,
|
||||
uid: 0,
|
||||
sort: 'oldest-to-newest',
|
||||
}, function (err, result) {
|
||||
assert.equal(err, null);
|
||||
|
||||
@@ -123,12 +120,11 @@ describe('Categories', function () {
|
||||
it('should return a list of topics by a specific user', function (done) {
|
||||
Categories.getCategoryTopics({
|
||||
cid: categoryObj.cid,
|
||||
set: 'cid:' + categoryObj.cid + ':uid:' + 1 + ':tids',
|
||||
reverse: true,
|
||||
start: 0,
|
||||
stop: 10,
|
||||
uid: 0,
|
||||
targetUid: 1,
|
||||
sort: 'oldest-to-newest',
|
||||
}, function (err, result) {
|
||||
assert.equal(err, null);
|
||||
assert(Array.isArray(result.topics));
|
||||
@@ -226,7 +222,14 @@ describe('Categories', function () {
|
||||
});
|
||||
|
||||
it('should load more topics', function (done) {
|
||||
socketCategories.loadMore({ uid: posterUid }, { cid: categoryObj.cid, after: 0, author: 'poster', tag: 'nodebb' }, function (err, data) {
|
||||
socketCategories.loadMore({ uid: posterUid }, {
|
||||
cid: categoryObj.cid,
|
||||
after: 0,
|
||||
query: {
|
||||
author: 'poster',
|
||||
tag: 'nodebb',
|
||||
},
|
||||
}, function (err, data) {
|
||||
assert.ifError(err);
|
||||
assert(Array.isArray(data.topics));
|
||||
assert.equal(data.topics[0].user.username, 'poster');
|
||||
@@ -244,7 +247,7 @@ describe('Categories', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('should load page count', function (done) {
|
||||
it('should load topic count', function (done) {
|
||||
socketCategories.getTopicCount({ uid: posterUid }, categoryObj.cid, function (err, topicCount) {
|
||||
assert.ifError(err);
|
||||
assert.equal(topicCount, 2);
|
||||
@@ -680,4 +683,31 @@ describe('Categories', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('getTopicIds', function () {
|
||||
var plugins = require('../src/plugins');
|
||||
it('should get topic ids with filter', function (done) {
|
||||
function method(data, callback) {
|
||||
data.tids = [1, 2, 3];
|
||||
callback(null, data);
|
||||
}
|
||||
|
||||
plugins.registerHook('my-test-plugin', {
|
||||
hook: 'filter:categories.getTopicIds',
|
||||
method: method,
|
||||
});
|
||||
|
||||
Categories.getTopicIds({
|
||||
cid: categoryObj.cid,
|
||||
start: 0,
|
||||
stop: 19,
|
||||
}, function (err, tids) {
|
||||
assert.ifError(err);
|
||||
assert.deepEqual(tids, [1, 2, 3]);
|
||||
plugins.unregisterHook('my-test-plugin', 'filter:categories.getTopicIds', method);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user