backup database before upgrade!
upgrade script will take the first post of each topic and set the
`mainPid` property on the topic. then it will remove that pid from the
sorted sets for that topic, this was done to make alternative sorting
work.

added a new sorted set called `tid:<id>:posts:votes` that is used to
sort topic posts by vote count, the original sorted set `tid:<id>:posts`
is used to sort by oldest first or newest first.

the main post is added to the returned posts array on topic load and is
always at the top.
theme changes are minimal just a few new data properties on the posts
and the sorting dropdown.
hopefully didn't miss anything too critical.
This commit is contained in:
barisusakli
2014-06-06 22:12:14 -04:00
parent c5b8a7b163
commit 7610c11cd1
18 changed files with 291 additions and 84 deletions

View File

@@ -111,5 +111,10 @@
"more_users_and_guests": "%1 more user(s) and %2 guest(s)", "more_users_and_guests": "%1 more user(s) and %2 guest(s)",
"more_users": "%1 more user(s)", "more_users": "%1 more user(s)",
"more_guests": "%1 more guest(s)" "more_guests": "%1 more guest(s)",
"sort_by": "Sort by",
"oldest_to_newest": "Oldest to Newest",
"newest_to_oldest": "Newest to Oldest",
"most_votes": "Most votes"
} }

View File

@@ -8,14 +8,16 @@ define('forum/infinitescroll', function() {
var callback; var callback;
var previousScrollTop = 0; var previousScrollTop = 0;
var loadingMore = false; var loadingMore = false;
var topOffset = 0;
scroll.init = function(cb) { scroll.init = function(cb, _topOffest) {
callback = cb; callback = cb;
topOffset = _topOffest || 0;
$(window).off('scroll', onScroll).on('scroll', onScroll); $(window).off('scroll', onScroll).on('scroll', onScroll);
}; };
function onScroll() { function onScroll() {
var top = $(window).height() * 0.1; var top = $(window).height() * 0.1 + topOffset;
var bottom = ($(document).height() - $(window).height()) * 0.9; var bottom = ($(document).height() - $(window).height()) * 0.9;
var currentScrollTop = $(window).scrollTop(); var currentScrollTop = $(window).scrollTop();

View File

@@ -40,6 +40,8 @@ define('forum/topic', ['forum/pagination', 'forum/infinitescroll', 'forum/topic/
threadTools.init(tid, thread_state); threadTools.init(tid, thread_state);
events.init(); events.init();
handleSorting();
hidePostToolsForDeletedPosts(); hidePostToolsForDeletedPosts();
enableInfiniteLoadingOrPagination(); enableInfiniteLoadingOrPagination();
@@ -77,6 +79,21 @@ define('forum/topic', ['forum/pagination', 'forum/infinitescroll', 'forum/topic/
socket.emit('topics.increaseViewCount', tid); socket.emit('topics.increaseViewCount', tid);
}; };
function handleSorting() {
var threadSort = $('.thread-sort');
threadSort.find('i').removeClass('fa-check');
var currentSetting = threadSort.find('a[data-sort="' + config.topicPostSort + '"]');
currentSetting.find('i').addClass('fa-check');
$('.thread-sort').on('click', 'a', function() {
var newSetting = $(this).attr('data-sort');
socket.emit('user.setTopicSort', newSetting, function(err) {
config.topicPostSort = newSetting;
ajaxify.go('topic/' + ajaxify.variables.get('topic_slug'));
});
});
}
function getPostIndex() { function getPostIndex() {
var parts = window.location.pathname.split('/'); var parts = window.location.pathname.split('/');
return parts[4] ? (parseInt(parts[4], 10) - 1) : ''; return parts[4] ? (parseInt(parts[4], 10) - 1) : '';
@@ -122,7 +139,7 @@ define('forum/topic', ['forum/pagination', 'forum/infinitescroll', 'forum/topic/
function enableInfiniteLoadingOrPagination() { function enableInfiniteLoadingOrPagination() {
if(!config.usePagination) { if(!config.usePagination) {
infinitescroll.init(loadMorePosts); infinitescroll.init(loadMorePosts, $('#post-container .post-row[data-index="0"]').height());
} else { } else {
navigator.hide(); navigator.hide();
@@ -283,25 +300,36 @@ define('forum/topic', ['forum/pagination', 'forum/infinitescroll', 'forum/topic/
before = null; before = null;
function findInsertionPoint() { function findInsertionPoint() {
var firstPid = parseInt(data.posts[0].pid, 10); var firstPostTimestamp = parseInt(data.posts[0].timestamp, 10);
var firstPostVotes = parseInt(data.posts[0].votes, 10);
var firstPostPid = data.posts[0].pid;
$('#post-container li[data-pid]').each(function() { var firstReply = $('#post-container li.post-row[data-index!="0"]').first();
var $this = $(this); var lastReply = $('#post-container li.post-row[data-index!="0"]').last();
if(firstPid > parseInt($this.attr('data-pid'), 10)) { if (config.topicPostSort === 'oldest_to_newest') {
after = $this; if (firstPostTimestamp < parseInt(firstReply.attr('data-timestamp'), 10)) {
if(after.next().length && after.next().hasClass('post-bar')) { before = firstReply;
after = after.next(); } else if(firstPostTimestamp >= parseInt(lastReply.attr('data-timestamp'), 10)) {
} after = lastReply;
} else {
return false;
} }
}); } else if(config.topicPostSort === 'newest_to_oldest') {
if (firstPostTimestamp > parseInt(firstReply.attr('data-timestamp'), 10)) {
if (!after) { before = firstReply;
var firstPost = $('#post-container .post-row').first(); } else if(firstPostTimestamp <= parseInt(lastReply.attr('data-timestamp'), 10)) {
if(firstPid < parseInt(firstPost.attr('data-pid'), 10)) { after = lastReply;
before = firstPost; }
} else if(config.topicPostSort === 'most_votes') {
if (firstPostVotes > parseInt(firstReply.attr('data-votes'), 10)) {
before = firstReply;
} else if(firstPostVotes < parseInt(firstReply.attr('data-votes'), 10)) {
after = lastReply;
} else {
if (firstPostPid > firstReply.attr('data-pid')) {
before = firstReply;
} else if(firstPostPid <= firstReply.attr('data-pid')) {
after = lastReply;
}
} }
} }
} }
@@ -373,7 +401,7 @@ define('forum/topic', ['forum/pagination', 'forum/infinitescroll', 'forum/topic/
return; return;
} }
infinitescroll.calculateAfter(direction, '#post-container .post-row', config.postsPerPage, function(after, offset, el) { infinitescroll.calculateAfter(direction, '#post-container .post-row[data-index!="0"]', config.postsPerPage, function(after, offset, el) {
loadPostsAfter(after, function() { loadPostsAfter(after, function() {
if (direction < 0 && el) { if (direction < 0 && el) {
Topic.scrollToPost(el.attr('data-index'), false, 0, offset); Topic.scrollToPost(el.attr('data-index'), false, 0, offset);
@@ -384,7 +412,7 @@ define('forum/topic', ['forum/pagination', 'forum/infinitescroll', 'forum/topic/
function loadPostsAfter(after, callback) { function loadPostsAfter(after, callback) {
var tid = ajaxify.variables.get('topic_id'); var tid = ajaxify.variables.get('topic_id');
if (!utils.isNumber(tid) || !utils.isNumber(after) || (after === 0 && $('#post-container li.post-row[data-index="0"]').length)) { if (!utils.isNumber(tid) || !utils.isNumber(after) || (after === 0 && $('#post-container li.post-row[data-index="1"]').length)) {
return; return;
} }

View File

@@ -42,6 +42,7 @@ apiController.getConfig = function(req, res, next) {
config.isLoggedIn = !!req.user; config.isLoggedIn = !!req.user;
config['cache-buster'] = meta.config['cache-buster'] || ''; config['cache-buster'] = meta.config['cache-buster'] || '';
config.requireEmailConfirmation = parseInt(meta.config.requireEmailConfirmation, 10) === 1; config.requireEmailConfirmation = parseInt(meta.config.requireEmailConfirmation, 10) === 1;
config.topicPostSort = meta.config.topicPostSort || 'oldest_to_newest';
config.version = pkg.version; config.version = pkg.version;
if (!req.user) { if (!req.user) {
@@ -64,6 +65,7 @@ apiController.getConfig = function(req, res, next) {
config.notificationSounds = settings.notificationSounds; config.notificationSounds = settings.notificationSounds;
config.defaultLang = settings.language || config.defaultLang; config.defaultLang = settings.language || config.defaultLang;
config.openOutgoingLinksInNewTab = settings.openOutgoingLinksInNewTab; config.openOutgoingLinksInNewTab = settings.openOutgoingLinksInNewTab;
config.topicPostSort = settings.topicPostSort || config.topicPostSort;
if (res.locals.isAPI) { if (res.locals.isAPI) {
res.json(200, config); res.json(200, config);

View File

@@ -44,7 +44,17 @@ topicsController.get = function(req, res, next) {
var start = (page - 1) * settings.postsPerPage + postIndex, var start = (page - 1) * settings.postsPerPage + postIndex,
end = start + settings.postsPerPage - 1; end = start + settings.postsPerPage - 1;
topics.getTopicWithPosts(tid, uid, start, end, function (err, topicData) { var set = 'tid:' + tid + ':posts',
reverse = false;
if (settings.topicPostSort === 'newest_to_oldest') {
reverse = true;
} else if (settings.topicPostSort === 'most_votes') {
reverse = true;
set = 'tid:' + tid + ':posts:votes';
}
topics.getTopicWithPosts(tid, set, uid, start, end, reverse, function (err, topicData) {
if (topicData) { if (topicData) {
if (parseInt(topicData.deleted, 10) === 1 && !userPrivileges.view_deleted) { if (parseInt(topicData.deleted, 10) === 1 && !userPrivileges.view_deleted) {
return next(new Error('[[error:no-topic]]')); return next(new Error('[[error:no-topic]]'));

View File

@@ -88,7 +88,8 @@ var async = require('async'),
return callback(err); return callback(err);
} }
var voteCount = parseInt(results.upvotes, 10) - parseInt(results.downvotes, 10); var voteCount = parseInt(results.upvotes, 10) - parseInt(results.downvotes, 10);
posts.setPostField(pid, 'votes', voteCount, function(err) {
posts.updatePostVoteCount(pid, voteCount, function(err) {
callback(err, voteCount); callback(err, voteCount);
}); });
}); });

View File

@@ -85,9 +85,10 @@ middleware.checkPostIndex = function(req, res, next) {
return next(err); return next(err);
} }
var postIndex = parseInt(req.params.post_index, 10); var postIndex = parseInt(req.params.post_index, 10);
postCount = parseInt(postCount, 10) + 1;
if (postIndex > postCount) { if (postIndex > postCount) {
return res.locals.isAPI ? res.json(302, '/topic/' + req.params.topic_id + '/' + req.params.slug + '/' + postCount) : res.redirect('/topic/' + req.params.topic_id + '/' + req.params.slug + '/' + postCount); return res.locals.isAPI ? res.json(302, '/topic/' + req.params.topic_id + '/' + req.params.slug + '/' + postCount) : res.redirect('/topic/' + req.params.topic_id + '/' + req.params.slug + '/' + postCount);
} else if (postIndex < 1) { } else if (postIndex <= 1) {
return res.locals.isAPI ? res.json(302, '/topic/' + req.params.topic_id + '/' + req.params.slug) : res.redirect('/topic/' + req.params.topic_id + '/' + req.params.slug); return res.locals.isAPI ? res.json(302, '/topic/' + req.params.topic_id + '/' + req.params.slug) : res.redirect('/topic/' + req.params.topic_id + '/' + req.params.slug);
} }
next(); next();

View File

@@ -90,8 +90,8 @@ var db = require('./database'),
], callback); ], callback);
}; };
Posts.getPostsByTid = function(tid, start, end, reverse, callback) { Posts.getPostsByTid = function(tid, set, start, end, reverse, callback) {
db[reverse ? 'getSortedSetRevRange' : 'getSortedSetRange']('tid:' + tid + ':posts', start, end, function(err, pids) { db[reverse ? 'getSortedSetRevRange' : 'getSortedSetRange'](set, start, end, function(err, pids) {
if(err) { if(err) {
return callback(err); return callback(err);
} }
@@ -157,8 +157,6 @@ var db = require('./database'),
}); });
}; };
Posts.getRecentPosts = function(uid, start, stop, term, callback) { Posts.getRecentPosts = function(uid, start, stop, term, callback) {
var terms = { var terms = {
day: 86400000, day: 86400000,
@@ -469,7 +467,9 @@ var db = require('./database'),
return callback(err); return callback(err);
} }
db.sortedSetRank('tid:' + tid + ':posts', pid, callback); db.sortedSetRank('tid:' + tid + ':posts', pid, function(err, index) {
callback(err, parseInt(index, 10) + 1);
});
}); });
}; };
@@ -482,5 +482,28 @@ var db = require('./database'),
}); });
}; };
Posts.updatePostVoteCount = function(pid, voteCount, callback) {
async.parallel([
function(next) {
Posts.getPostField(pid, 'tid', function(err, tid) {
if (err) {
return next(err);
}
topics.getTopicField(tid, 'mainPid', function(err, mainPid) {
if (err) {
return next(err);
}
if (parseInt(mainPid, 10) === parseInt(pid, 10)) {
return next();
}
db.sortedSetAdd('tid:' + tid + ':posts:votes', voteCount, pid, next);
});
});
},
function(next) {
Posts.setPostField(pid, 'votes', voteCount, next);
}
], callback);
};
}(exports)); }(exports));

View File

@@ -40,7 +40,7 @@ function hasPrivileges(method, id, req, res, next) {
function generateForTopic(req, res, next) { function generateForTopic(req, res, next) {
var tid = req.params.topic_id; var tid = req.params.topic_id;
var uid = req.user ? req.user.uid : 0; var uid = req.user ? req.user.uid : 0;
topics.getTopicWithPosts(tid, uid, 0, 25, function (err, topicData) { topics.getTopicWithPosts(tid, 'tid:' + tid + ':posts', uid, 0, 25, false, function (err, topicData) {
if (err) { if (err) {
return next(err); return next(err);
} }

View File

@@ -314,12 +314,22 @@ SocketTopics.loadMore = function(socket, data, callback) {
return callback(err); return callback(err);
} }
var start = parseInt(data.after, 10), var start = Math.max(parseInt(data.after, 10) - 1, 0),
end = start + settings.postsPerPage - 1; end = start + settings.postsPerPage - 1;
var set = 'tid:' + data.tid + ':posts',
reverse = false;
if (settings.topicPostSort === 'newest_to_oldest') {
reverse = true;
} else if (settings.topicPostSort === 'most_votes') {
reverse = true;
set = 'tid:' + data.tid + ':posts:votes';
}
async.parallel({ async.parallel({
posts: function(next) { posts: function(next) {
topics.getTopicPosts(data.tid, start, end, socket.uid, false, next); topics.getTopicPosts(data.tid, set, start, end, socket.uid, reverse, next);
}, },
privileges: function(next) { privileges: function(next) {
privileges.topics.get(data.tid, socket.uid, next); privileges.topics.get(data.tid, socket.uid, next);

View File

@@ -178,6 +178,12 @@ SocketUser.saveSettings = function(socket, data, callback) {
} }
}; };
SocketUser.setTopicSort = function(socket, sort, callback) {
if(socket.uid) {
user.setSetting(socket.uid, 'topicPostSort', sort, callback);
}
};
SocketUser.getOnlineUsers = function(socket, data, callback) { SocketUser.getOnlineUsers = function(socket, data, callback) {
var returnData = {}; var returnData = {};
if(!data) { if(!data) {

View File

@@ -262,7 +262,7 @@ var async = require('async'),
}); });
}; };
Topics.getTopicWithPosts = function(tid, uid, start, end, callback) { Topics.getTopicWithPosts = function(tid, set, uid, start, end, reverse, callback) {
Topics.getTopicData(tid, function(err, topicData) { Topics.getTopicData(tid, function(err, topicData) {
if (err || !topicData) { if (err || !topicData) {
return callback(err || new Error('[[error:no-topic]]')); return callback(err || new Error('[[error:no-topic]]'));
@@ -270,7 +270,7 @@ var async = require('async'),
async.parallel({ async.parallel({
posts: function(next) { posts: function(next) {
Topics.getTopicPosts(tid, start, end, uid, false, next); Topics.getTopicPosts(tid, set, start, end, uid, reverse, next);
}, },
category: function(next) { category: function(next) {
Topics.getCategoryData(tid, next); Topics.getCategoryData(tid, next);
@@ -283,6 +283,26 @@ var async = require('async'),
}, },
tags: function(next) { tags: function(next) {
Topics.getTopicTagsObjects(tid, next); Topics.getTopicTagsObjects(tid, next);
},
mainPost: function(next) {
Topics.getTopicField(tid, 'mainPid', function(err, mainPid) {
if (err) {
return next(err);
}
if (!parseInt(mainPid, 10)) {
return next(null, []);
}
posts.getPostsByPids([mainPid], function(err, postData) {
if (err) {
return next(err);
}
if (!Array.isArray(postData) || !postData.length) {
return next(null, []);
}
postData[0].index = 0;
Topics.addPostData(postData, uid, next);
});
});
} }
}, function(err, results) { }, function(err, results) {
if (err) { if (err) {
@@ -290,7 +310,7 @@ var async = require('async'),
} }
topicData.category = results.category; topicData.category = results.category;
topicData.posts = results.posts; topicData.posts = results.mainPost.concat(results.posts);
topicData.tags = results.tags; topicData.tags = results.tags;
topicData.thread_tools = results.threadTools; topicData.thread_tools = results.threadTools;
topicData.pageCount = results.pageCount; topicData.pageCount = results.pageCount;

View File

@@ -37,6 +37,7 @@ module.exports = function(Topics) {
'tid': tid, 'tid': tid,
'uid': uid, 'uid': uid,
'cid': cid, 'cid': cid,
'mainPid': 0,
'title': title, 'title': title,
'slug': slug, 'slug': slug,
'timestamp': timestamp, 'timestamp': timestamp,

View File

@@ -71,7 +71,7 @@ module.exports = function(Topics) {
return callback(err || new Error('[[error:no-topic]]')); return callback(err || new Error('[[error:no-topic]]'));
} }
posts.getPostFields(pid, ['deleted', 'tid', 'timestamp'], function(err, postData) { posts.getPostFields(pid, ['deleted', 'tid', 'timestamp', 'votes'], function(err, postData) {
if(err) { if(err) {
return callback(err); return callback(err);
} }
@@ -91,7 +91,7 @@ module.exports = function(Topics) {
} }
posts.setPostField(pid, 'tid', tid); posts.setPostField(pid, 'tid', tid);
Topics.addPostToTopic(tid, pid, postData.timestamp, callback); Topics.addPostToTopic(tid, pid, postData.timestamp, postData.votes, callback);
}); });
}); });
}); });

View File

@@ -15,13 +15,13 @@ module.exports = function(Topics) {
Topics.onNewPostMade = function(postData) { Topics.onNewPostMade = function(postData) {
Topics.increasePostCount(postData.tid); Topics.increasePostCount(postData.tid);
Topics.updateTimestamp(postData.tid, postData.timestamp); Topics.updateTimestamp(postData.tid, postData.timestamp);
Topics.addPostToTopic(postData.tid, postData.pid, postData.timestamp); Topics.addPostToTopic(postData.tid, postData.pid, postData.timestamp, 0);
}; };
emitter.on('event:newpost', Topics.onNewPostMade); emitter.on('event:newpost', Topics.onNewPostMade);
Topics.getTopicPosts = function(tid, start, end, uid, reverse, callback) { Topics.getTopicPosts = function(tid, set, start, end, uid, reverse, callback) {
posts.getPostsByTid(tid, start, end, reverse, function(err, postData) { posts.getPostsByTid(tid, set, start, end, reverse, function(err, postData) {
if(err) { if(err) {
return callback(err); return callback(err);
} }
@@ -29,52 +29,57 @@ module.exports = function(Topics) {
if (Array.isArray(postData) && !postData.length) { if (Array.isArray(postData) && !postData.length) {
return callback(null, []); return callback(null, []);
} }
start = parseInt(start, 10); start = parseInt(start, 10);
for(var i=0; i<postData.length; ++i) { for(var i=0; i<postData.length; ++i) {
postData[i].index = start + i; postData[i].index = start + i + 1;
} }
var pids = postData.map(function(post) { Topics.addPostData(postData, uid, callback);
return post.pid; });
}); };
async.parallel({ Topics.addPostData = function(postData, uid, callback) {
favourites : function(next) { var pids = postData.map(function(post) {
favourites.getFavouritesByPostIDs(pids, uid, next); return post.pid;
}, });
voteData : function(next) {
favourites.getVoteStatusByPostIDs(pids, uid, next); async.parallel({
}, favourites : function(next) {
userData : function(next) { favourites.getFavouritesByPostIDs(pids, uid, next);
async.each(postData, posts.addUserInfoToPost, next); },
}, voteData : function(next) {
privileges : function(next) { favourites.getVoteStatusByPostIDs(pids, uid, next);
async.map(pids, function (pid, next) { },
privileges.posts.get(pid, uid, next); userData : function(next) {
}, next); async.each(postData, posts.addUserInfoToPost, next);
} },
}, function(err, results) { privileges : function(next) {
if(err) { async.map(pids, function (pid, next) {
return callback(err); privileges.posts.get(pid, uid, next);
}, next);
}
}, function(err, results) {
if(err) {
return callback(err);
}
for (var i = 0; i < postData.length; ++i) {
postData[i].deleted = parseInt(postData[i].deleted, 10) === 1;
postData[i].favourited = results.favourites[i];
postData[i].upvoted = results.voteData[i].upvoted;
postData[i].downvoted = results.voteData[i].downvoted;
postData[i].votes = postData[i].votes || 0;
postData[i].display_moderator_tools = results.privileges[i].editable;
postData[i].display_move_tools = results.privileges[i].move;
postData[i].selfPost = parseInt(uid, 10) === parseInt(postData[i].uid, 10);
if(postData[i].deleted && !results.privileges[i].view_deleted) {
postData[i].content = '[[topic:post_is_deleted]]';
} }
}
for (var i = 0; i < postData.length; ++i) { callback(null, postData);
postData[i].deleted = parseInt(postData[i].deleted, 10) === 1;
postData[i].favourited = results.favourites[i];
postData[i].upvoted = results.voteData[i].upvoted;
postData[i].downvoted = results.voteData[i].downvoted;
postData[i].votes = postData[i].votes || 0;
postData[i].display_moderator_tools = results.privileges[i].editable;
postData[i].display_move_tools = results.privileges[i].move;
postData[i].selfPost = parseInt(uid, 10) === parseInt(postData[i].uid, 10);
if(postData[i].deleted && !results.privileges[i].view_deleted) {
postData[i].content = '[[topic:post_is_deleted]]';
}
}
callback(null, postData);
});
}); });
}; };
@@ -108,8 +113,21 @@ module.exports = function(Topics) {
}); });
}; };
Topics.addPostToTopic = function(tid, pid, timestamp, callback) { Topics.addPostToTopic = function(tid, pid, timestamp, votes, callback) {
db.sortedSetAdd('tid:' + tid + ':posts', timestamp, pid, callback); Topics.getTopicField(tid, 'mainPid', function(err, mainPid) {
if (!parseInt(mainPid, 10)) {
Topics.setTopicField(tid, 'mainPid', pid, callback);
} else {
async.parallel([
function(next) {
db.sortedSetAdd('tid:' + tid + ':posts', timestamp, pid, next);
},
function(next) {
db.sortedSetAdd('tid:' + tid + ':posts:votes', votes, pid, next);
}
], callback);
}
});
}; };
Topics.removePostFromTopic = function(tid, pid, callback) { Topics.removePostFromTopic = function(tid, pid, callback) {

View File

@@ -19,7 +19,7 @@ var db = require('./database'),
schemaDate, thisSchemaDate, schemaDate, thisSchemaDate,
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema
latestSchema = Date.UTC(2014, 4, 22); latestSchema = Date.UTC(2014, 5, 6);
Upgrade.check = function(callback) { Upgrade.check = function(callback) {
db.get('schemaDate', function(err, value) { db.get('schemaDate', function(err, value) {
@@ -733,6 +733,74 @@ Upgrade.upgrade = function(callback) {
winston.info('[2014/5/16] Tags upgrade - skipped'); winston.info('[2014/5/16] Tags upgrade - skipped');
next(); next();
} }
},
function(next) {
thisSchemaDate = Date.UTC(2014, 5, 6);
if (schemaDate < thisSchemaDate) {
db.getSortedSetRange('topics:tid', 0, -1, function(err, tids) {
function upgradeTopic(tid, callback) {
Topics.getTopicField(tid, 'mainPid', function(err, mainPid) {
if (err) {
return callback(err);
}
db.getSortedSetRange('tid:' + tid + ':posts', 0, -1, function(err, pids) {
if (err) {
return callback(err);
}
if (!Array.isArray(pids) || !pids.length) {
return callback();
}
if (!parseInt(mainPid, 10)) {
mainPid = pids[0];
pids.splice(0, 1);
Topics.setTopicField(tid, 'mainPid', mainPid);
db.sortedSetRemove('tid:' + tid + ':posts', mainPid);
db.sortedSetRemove('tid:' + tid + ':posts:votes', mainPid);
}
if (!pids.length) {
return callback();
}
async.each(pids, function(pid, next) {
Posts.getPostField(pid, 'votes', function(err, votes) {
if (err) {
return next(err);
}
db.sortedSetAdd('tid:' + tid + ':posts:votes', votes ? votes : 0, pid, next);
});
}, callback);
});
});
}
if (err) {
return next(err);
}
if (!Array.isArray(tids) || !tids.length) {
winston.info('[2014/6/6] Skipping topic upgrade');
return Upgrade.update(thisSchemaDate, next);
}
async.each(tids, upgradeTopic, function(err) {
if (err) {
winston.error('[2014/6/6] Error encountered while upgrading topics');
return next(err);
}
winston.info('[2014/6/6] Topics upgraded.');
Upgrade.update(thisSchemaDate, next);
});
});
} else {
winston.info('[2014/6/6] Topic upgrade - skipped');
next();
}
} }
// Add new schema updates here // Add new schema updates here
// IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 22!!! // IMPORTANT: REMEMBER TO UPDATE VALUE OF latestSchema IN LINE 22!!!

View File

@@ -66,7 +66,14 @@ module.exports = function(User) {
return callback(err); return callback(err);
} }
db.sortedSetRemove('tid:' + postData.tid + ':posts', pid, function(err) { async.parallel([
function(next) {
db.sortedSetRemove('tid:' + postData.tid + ':posts', pid, next);
},
function(next) {
db.sortedSetRemove('tid:' + postData.tid + ':posts:votes', pid, next);
}
], function(err) {
if (err) { if (err) {
return callback(err); return callback(err);
} }

View File

@@ -32,6 +32,7 @@ module.exports = function(User) {
settings.postsPerPage = settings.postsPerPage ? parseInt(settings.postsPerPage, 10) : parseInt(meta.config.postsPerPage, 10) || 10; settings.postsPerPage = settings.postsPerPage ? parseInt(settings.postsPerPage, 10) : parseInt(meta.config.postsPerPage, 10) || 10;
settings.notificationSounds = settings.notificationSounds ? parseInt(settings.notificationSounds, 10) === 1 : true; settings.notificationSounds = settings.notificationSounds ? parseInt(settings.notificationSounds, 10) === 1 : true;
settings.language = settings.language || meta.config.defaultLang || 'en_GB'; settings.language = settings.language || meta.config.defaultLang || 'en_GB';
settings.topicPostSort = settings.topicPostSort || meta.config.topicPostSort || 'oldest_to_newest';
callback(null, settings); callback(null, settings);
}); });
}); });
@@ -82,4 +83,8 @@ module.exports = function(User) {
language: data.language || meta.config.defaultLang language: data.language || meta.config.defaultLang
}, callback); }, callback);
}; };
User.setSetting = function(uid, key, value, callback) {
db.setObjectField('user:' + uid + ':settings', key, value, callback);
};
}; };