mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-07-06 20:08:32 +02:00
Merge remote-tracking branch 'origin/master' into private-groups
This commit is contained in:
@@ -40,10 +40,11 @@ var async = require('async'),
|
||||
topics: function(next) {
|
||||
Categories.getCategoryTopics({
|
||||
cid: data.cid,
|
||||
set: data.set,
|
||||
reverse: data.reverse,
|
||||
start: data.start,
|
||||
stop: data.end,
|
||||
uid: data.uid,
|
||||
targetUid: data.targetUid
|
||||
uid: data.uid
|
||||
}, next);
|
||||
},
|
||||
pageCount: function(next) {
|
||||
|
||||
@@ -29,6 +29,7 @@ module.exports = function(Categories) {
|
||||
function(next) {
|
||||
db.deleteAll([
|
||||
'cid:' + cid + ':tids',
|
||||
'cid:' + cid + ':tids:posts',
|
||||
'cid:' + cid + ':pids',
|
||||
'category:' + cid
|
||||
], next);
|
||||
|
||||
@@ -22,7 +22,7 @@ module.exports = function(Categories) {
|
||||
plugins.fireHook('filter:category.topics.prepare', data, next);
|
||||
},
|
||||
function(data, next) {
|
||||
Categories.getTopicIds(data.targetUid ? 'cid:' + data.cid + ':uid:' + data.targetUid + ':tids' : 'cid:' + data.cid + ':tids', data.start, data.stop, next);
|
||||
Categories.getTopicIds(data.set, data.reverse, data.start, data.stop, next);
|
||||
},
|
||||
function(tids, next) {
|
||||
topics.getTopicsByTids(tids, data.uid, next);
|
||||
@@ -56,8 +56,12 @@ module.exports = function(Categories) {
|
||||
});
|
||||
};
|
||||
|
||||
Categories.getTopicIds = function(set, start, stop, callback) {
|
||||
db.getSortedSetRevRange(set, start, stop, callback);
|
||||
Categories.getTopicIds = function(set, reverse, start, stop, callback) {
|
||||
if (reverse) {
|
||||
db.getSortedSetRevRange(set, start, stop, callback);
|
||||
} else {
|
||||
db.getSortedSetRange(set, start, stop, callback);
|
||||
}
|
||||
};
|
||||
|
||||
Categories.getTopicIndex = function(tid, callback) {
|
||||
@@ -95,6 +99,9 @@ module.exports = function(Categories) {
|
||||
} else {
|
||||
db.sortedSetAdd('cid:' + cid + ':tids', postData.timestamp, postData.tid, next);
|
||||
}
|
||||
},
|
||||
function(next) {
|
||||
db.sortedSetIncrBy('cid:' + cid + ':tids:posts', 1, postData.tid, next);
|
||||
}
|
||||
], callback);
|
||||
});
|
||||
|
||||
@@ -55,6 +55,7 @@ apiController.getConfig = function(req, res, next) {
|
||||
config['css-buster'] = meta.css.hash;
|
||||
config.requireEmailConfirmation = parseInt(meta.config.requireEmailConfirmation, 10) === 1;
|
||||
config.topicPostSort = meta.config.topicPostSort || 'oldest_to_newest';
|
||||
config.categoryTopicSort = meta.config.categoryTopicSort || 'newest_to_oldest';
|
||||
config.csrf_token = req.csrfToken();
|
||||
config.searchEnabled = plugins.hasListeners('filter:search.query');
|
||||
|
||||
@@ -79,6 +80,7 @@ apiController.getConfig = function(req, res, next) {
|
||||
config.userLang = settings.language || config.defaultLang;
|
||||
config.openOutgoingLinksInNewTab = settings.openOutgoingLinksInNewTab;
|
||||
config.topicPostSort = settings.topicPostSort || config.topicPostSort;
|
||||
config.categoryTopicSort = settings.categoryTopicSort || config.categoryTopicSort;
|
||||
config.topicSearchEnabled = settings.topicSearchEnabled || false;
|
||||
|
||||
if (res.locals.isAPI) {
|
||||
|
||||
@@ -158,11 +158,23 @@ categoriesController.get = function(req, res, next) {
|
||||
topicIndex = 0;
|
||||
}
|
||||
|
||||
var set = 'cid:' + cid + ':tids',
|
||||
reverse = false;
|
||||
|
||||
if (settings.categoryTopicSort === 'newest_to_oldest') {
|
||||
reverse = true;
|
||||
} else if (settings.categoryTopicSort === 'most_posts') {
|
||||
reverse = true;
|
||||
set = 'cid:' + cid + ':tids:posts';
|
||||
}
|
||||
|
||||
var start = (page - 1) * settings.topicsPerPage + topicIndex,
|
||||
end = start + settings.topicsPerPage - 1;
|
||||
|
||||
next(null, {
|
||||
cid: cid,
|
||||
set: set,
|
||||
reverse: reverse,
|
||||
start: start,
|
||||
end: end,
|
||||
uid: uid
|
||||
@@ -171,6 +183,9 @@ categoriesController.get = function(req, res, next) {
|
||||
function(payload, next) {
|
||||
user.getUidByUserslug(req.query.author, function(err, uid) {
|
||||
payload.targetUid = uid;
|
||||
if (uid) {
|
||||
payload.set = 'cid:' + cid + ':uid:' + uid + ':tids';
|
||||
}
|
||||
next(err, payload);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -28,7 +28,12 @@ searchController.search = function(req, res, next) {
|
||||
|
||||
req.params.term = validator.escape(req.params.term);
|
||||
|
||||
search.search(req.params.term, req.query.in, uid, function(err, results) {
|
||||
search.search({
|
||||
query: req.params.term,
|
||||
searchIn: req.query.in,
|
||||
postedBy: req.query.by,
|
||||
uid: uid
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ var fs = require('fs'),
|
||||
winston.warn('[plugins/' + plugin.id + '] A templates directory was defined for this plugin, but was not found.');
|
||||
}
|
||||
|
||||
next(err);
|
||||
next(false);
|
||||
});
|
||||
} else {
|
||||
next(false);
|
||||
|
||||
@@ -171,8 +171,11 @@ module.exports = function(Posts) {
|
||||
topics.updateTeaser(postData.tid, next);
|
||||
},
|
||||
function(next) {
|
||||
user.incrementUserPostCountBy(postData.uid, -1, next);
|
||||
db.sortedSetIncrBy('cid:' + topicData.cid + ':tids:posts', -1, postData.tid, next);
|
||||
},
|
||||
function(next) {
|
||||
user.incrementUserPostCountBy(postData.uid, -1, next);
|
||||
}
|
||||
], callback);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -125,6 +125,8 @@ function generateForCategory(req, res, next) {
|
||||
var uid = req.user ? req.user.uid : 0;
|
||||
categories.getCategoryById({
|
||||
cid: cid,
|
||||
set: 'cid:' + cid + ':tids',
|
||||
reverse: true,
|
||||
start: 0,
|
||||
end: 25,
|
||||
uid: uid
|
||||
|
||||
@@ -11,7 +11,7 @@ var search = {};
|
||||
|
||||
module.exports = search;
|
||||
|
||||
search.search = function(query, searchIn, uid, callback) {
|
||||
search.search = function(data, callback) {
|
||||
function done(err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
@@ -20,12 +20,16 @@ search.search = function(query, searchIn, uid, callback) {
|
||||
result.search_query = query;
|
||||
result[searchIn] = data;
|
||||
result.matchCount = data.length;
|
||||
result.hidePostedBy = searchIn !== 'posts';
|
||||
result.time = (process.elapsedTimeSince(start) / 1000).toFixed(2);
|
||||
callback(null, result);
|
||||
}
|
||||
|
||||
var start = process.hrtime();
|
||||
searchIn = searchIn || 'posts';
|
||||
|
||||
var query = data.query;
|
||||
var searchIn = data.searchIn || 'posts';
|
||||
var uid = data.uid || 0;
|
||||
|
||||
var result = {
|
||||
posts: [],
|
||||
@@ -34,7 +38,7 @@ search.search = function(query, searchIn, uid, callback) {
|
||||
};
|
||||
|
||||
if (searchIn === 'posts') {
|
||||
searchInPosts(query, uid, done);
|
||||
searchInPosts(query, data.postedBy, uid, done);
|
||||
} else if (searchIn === 'users') {
|
||||
searchInUsers(query, done);
|
||||
} else if (searchIn === 'tags') {
|
||||
@@ -44,13 +48,20 @@ search.search = function(query, searchIn, uid, callback) {
|
||||
}
|
||||
};
|
||||
|
||||
function searchInPosts(query, uid, callback) {
|
||||
function searchInPosts(query, postedBy, uid, callback) {
|
||||
async.parallel({
|
||||
pids: function(next) {
|
||||
searchQuery('post', query, next);
|
||||
},
|
||||
tids: function(next) {
|
||||
searchQuery('topic', query, next);
|
||||
},
|
||||
postedByUid: function(next) {
|
||||
if (postedBy) {
|
||||
user.getUidByUsername(postedBy, next);
|
||||
} else {
|
||||
next(null, 0);
|
||||
}
|
||||
}
|
||||
}, function (err, results) {
|
||||
if (err) {
|
||||
@@ -75,6 +86,14 @@ function searchInPosts(query, uid, callback) {
|
||||
},
|
||||
function(pids, next) {
|
||||
posts.getPostSummaryByPids(pids, uid, {stripTags: true, parse: false}, next);
|
||||
},
|
||||
function(posts, next) {
|
||||
if (postedBy) {
|
||||
posts = posts.filter(function(post) {
|
||||
return post && parseInt(post.uid, 10) === parseInt(results.postedByUid, 10);
|
||||
});
|
||||
}
|
||||
next(null, posts);
|
||||
}
|
||||
], callback);
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ SocketCategories.get = function(socket, data, callback) {
|
||||
};
|
||||
|
||||
SocketCategories.loadMore = function(socket, data, callback) {
|
||||
if(!data) {
|
||||
if (!data) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
@@ -46,11 +46,28 @@ SocketCategories.loadMore = function(socket, data, callback) {
|
||||
return callback(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
|
||||
var set = 'cid:' + data.cid + ':tids',
|
||||
reverse = false;
|
||||
|
||||
if (results.settings.categoryTopicSort === 'newest_to_oldest') {
|
||||
reverse = true;
|
||||
} else if (results.settings.categoryTopicSort === 'most_posts') {
|
||||
reverse = true;
|
||||
set = 'cid:' + data.cid + ':tids:posts';
|
||||
}
|
||||
|
||||
var start = parseInt(data.after, 10),
|
||||
end = start + results.settings.topicsPerPage - 1;
|
||||
|
||||
if (results.targetUid) {
|
||||
set = 'cid:' + data.cid + ':uid:' + results.targetUid + ':tids';
|
||||
}
|
||||
|
||||
categories.getCategoryTopics({
|
||||
cid: data.cid,
|
||||
set: set,
|
||||
reverse: reverse,
|
||||
start: start,
|
||||
stop: end,
|
||||
uid: socket.uid,
|
||||
|
||||
@@ -392,7 +392,7 @@ SocketTopics.moveAll = function(socket, data, callback) {
|
||||
return callback(err || new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
categories.getTopicIds('cid:' + data.currentCid + ':tids', 0, -1, function(err, tids) {
|
||||
categories.getTopicIds('cid:' + data.currentCid + ':tids', true, 0, -1, function(err, tids) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
@@ -62,11 +62,14 @@ SocketUser.increaseViewCount = function(socket, uid, callback) {
|
||||
}
|
||||
};
|
||||
|
||||
SocketUser.search = function(socket, username, callback) {
|
||||
SocketUser.search = function(socket, data, callback) {
|
||||
if (!data) {
|
||||
return callback(new Error('[[error:invalid-data]]'))
|
||||
}
|
||||
if (!socket.uid) {
|
||||
return callback(new Error('[[error:not-logged-in]]'));
|
||||
}
|
||||
user.search({query: username}, callback);
|
||||
user.search({query: data.query}, callback);
|
||||
};
|
||||
|
||||
// Password Reset
|
||||
@@ -295,6 +298,12 @@ SocketUser.setTopicSort = function(socket, sort, callback) {
|
||||
}
|
||||
};
|
||||
|
||||
SocketUser.setCategorySort = function(socket, sort, callback) {
|
||||
if (socket.uid) {
|
||||
user.setSetting(socket.uid, 'categoryTopicSort', sort, callback);
|
||||
}
|
||||
};
|
||||
|
||||
SocketUser.getOnlineAnonCount = function(socket, data, callback) {
|
||||
callback(null, module.parent.exports.getOnlineAnonCount());
|
||||
};
|
||||
|
||||
@@ -185,15 +185,26 @@ var winston = require('winston'),
|
||||
var topic;
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
topics.getTopicFields(tid, ['cid', 'lastposttime', 'pinned', 'deleted'], next);
|
||||
topics.getTopicFields(tid, ['cid', 'lastposttime', 'pinned', 'deleted', 'postcount'], next);
|
||||
},
|
||||
function(topicData, next) {
|
||||
topic = topicData;
|
||||
db.sortedSetRemove('cid:' + topicData.cid + ':tids', tid, next);
|
||||
db.sortedSetsRemove([
|
||||
'cid:' + topicData.cid + ':tids',
|
||||
'cid:' + topicData.cid + ':tids:posts'
|
||||
], tid, next);
|
||||
},
|
||||
function(next) {
|
||||
var timestamp = parseInt(topic.pinned, 10) ? Math.pow(2, 53) : topic.lastposttime;
|
||||
db.sortedSetAdd('cid:' + cid + ':tids', timestamp, tid, next);
|
||||
async.parallel([
|
||||
function(next) {
|
||||
db.sortedSetAdd('cid:' + cid + ':tids', timestamp, tid, next);
|
||||
},
|
||||
function(next) {
|
||||
topic.postcount = topic.postcount || 0;
|
||||
db.sortedSetAdd('cid:' + cid + ':tids:posts', topic.postcount, tid, next);
|
||||
}
|
||||
], next);
|
||||
}
|
||||
], function(err) {
|
||||
if (err) {
|
||||
|
||||
@@ -76,6 +76,7 @@ module.exports = function(Topics) {
|
||||
|
||||
db.sortedSetsRemove([
|
||||
'cid:' + topicData.cid + ':tids',
|
||||
'cid:' + topicData.cid + ':tids:posts',
|
||||
'cid:' + topicData.cid + ':uid:' + topicData.uid + ':tids',
|
||||
'uid:' + topicData.uid + ':topics'
|
||||
], tid, callback);
|
||||
|
||||
@@ -21,7 +21,7 @@ var db = require('./database'),
|
||||
schemaDate, thisSchemaDate,
|
||||
|
||||
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema
|
||||
latestSchema = Date.UTC(2014, 11, 20);
|
||||
latestSchema = Date.UTC(2015, 0, 8);
|
||||
|
||||
Upgrade.check = function(callback) {
|
||||
db.get('schemaDate', function(err, value) {
|
||||
@@ -451,8 +451,48 @@ Upgrade.upgrade = function(callback) {
|
||||
winston.info('[2014/12/20] Updating digest settings skipped');
|
||||
next();
|
||||
}
|
||||
},
|
||||
function(next) {
|
||||
thisSchemaDate = Date.UTC(2015, 0, 8);
|
||||
if (schemaDate < thisSchemaDate) {
|
||||
winston.info('[2015/01/08] Updating category topics sorted sets');
|
||||
|
||||
db.getSortedSetRange('topics:tid', 0, -1, function(err, tids) {
|
||||
if (err) {
|
||||
winston.error('[2014/12/20] Error encountered while updating digest settings');
|
||||
return next(err);
|
||||
}
|
||||
|
||||
var now = Date.now();
|
||||
|
||||
async.eachLimit(tids, 50, function(tid, next) {
|
||||
db.getObjectFields('topic:' + tid, ['cid', 'postcount'], function(err, topicData) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (Utils.isNumber(topicData.postcount) && topicData.cid) {
|
||||
db.sortedSetAdd('cid:' + topicData.cid + ':tids:posts', topicData.postcount, tid, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
winston.error('[2015/01/08] Error encountered while Updating category topics sorted sets');
|
||||
return next(err);
|
||||
}
|
||||
winston.info('[2015/01/08] Updating category topics sorted sets done');
|
||||
Upgrade.update(thisSchemaDate, next);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
winston.info('[2015/01/08] Updating category topics sorted sets skipped');
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add new schema updates here
|
||||
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 22!!!
|
||||
], function(err) {
|
||||
|
||||
@@ -65,6 +65,7 @@ module.exports = function(User) {
|
||||
settings.notificationSounds = parseInt(settings.notificationSounds, 10) === 1;
|
||||
settings.language = settings.language || meta.config.defaultLang || 'en_GB';
|
||||
settings.topicPostSort = settings.topicPostSort || meta.config.topicPostSort || 'oldest_to_newest';
|
||||
settings.categoryTopicSort = settings.categoryTopicSort || meta.config.categoryTopicSort || 'newest_to_oldest';
|
||||
settings.followTopicsOnCreate = (settings.followTopicsOnCreate === null || settings.followTopicsOnCreate === undefined) ? true : parseInt(settings.followTopicsOnCreate, 10) === 1;
|
||||
settings.followTopicsOnReply = parseInt(settings.followTopicsOnReply, 10) === 1;
|
||||
settings.sendChatNotifications = parseInt(settings.sendChatNotifications, 10) === 1;
|
||||
|
||||
@@ -12,6 +12,14 @@
|
||||
<option value="most_votes">Most Votes</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Default Topic Sorting</label>
|
||||
<select class="form-control" data-field="categoryTopicSort">
|
||||
<option value="newest_to_oldest">Newest to Oldest</option>
|
||||
<option value="oldest_to_newest">Oldest to Newest</option>
|
||||
<option value="most_posts">Most Posts</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Seconds between Posts</label>
|
||||
|
||||
Reference in New Issue
Block a user