Merge remote-tracking branch 'origin/master'

v1.18.x
Julian Lam 11 years ago
commit d66bead245

@ -58,7 +58,7 @@ if(os.platform() === 'linux') {
} }
// Log GNU copyright info along with server info // Log GNU copyright info along with server info
winston.info('NodeBB v' + pkg.version + ' Copyright (C) 2013-2014 DesignCreatePlay Inc.'); winston.info('NodeBB v' + pkg.version + ' Copyright (C) 2013-2014 NodeBB Inc.');
winston.info('This program comes with ABSOLUTELY NO WARRANTY.'); winston.info('This program comes with ABSOLUTELY NO WARRANTY.');
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.'); winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
winston.info(''); winston.info('');

@ -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"
} }

@ -60,7 +60,7 @@ var ajaxify = ajaxify || {};
// Remove trailing slash // Remove trailing slash
url = url.replace(/\/$/, ""); url = url.replace(/\/$/, "");
url = removeRelativePath(url); url = ajaxify.removeRelativePath(url);
var tpl_url = ajaxify.getTemplateMapping(url); var tpl_url = ajaxify.getTemplateMapping(url);
@ -122,12 +122,12 @@ var ajaxify = ajaxify || {};
return false; return false;
}; };
function removeRelativePath(url) { ajaxify.removeRelativePath = function(url) {
if (url.indexOf(RELATIVE_PATH.slice(1)) !== -1) { if (url.indexOf(RELATIVE_PATH.slice(1)) === 0) {
url = url.slice(RELATIVE_PATH.length); url = url.slice(RELATIVE_PATH.length);
} }
return url; return url;
} };
ajaxify.refresh = function() { ajaxify.refresh = function() {
ajaxify.go(ajaxify.currentPage); ajaxify.go(ajaxify.currentPage);
@ -186,7 +186,7 @@ var ajaxify = ajaxify || {};
}; };
ajaxify.loadData = function(url, callback) { ajaxify.loadData = function(url, callback) {
url = removeRelativePath(url); url = ajaxify.removeRelativePath(url);
$(window).trigger('action:ajaxify.loadingData', {url: url}); $(window).trigger('action:ajaxify.loadingData', {url: url});

@ -516,9 +516,7 @@ var socket,
tpl_url = ajaxify.getTemplateMapping(url), tpl_url = ajaxify.getTemplateMapping(url),
$window = $(window); $window = $(window);
if (url.indexOf(RELATIVE_PATH.slice(1)) !== -1) { url = ajaxify.removeRelativePath(url);
url = url.slice(RELATIVE_PATH.length);
}
ajaxify.widgets.render(tpl_url, url); ajaxify.widgets.render(tpl_url, url);

@ -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();

@ -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);
$('#post-container li[data-pid]').each(function() { var firstPostPid = data.posts[0].pid;
var $this = $(this);
var firstReply = $('#post-container li.post-row[data-index!="0"]').first();
if(firstPid > parseInt($this.attr('data-pid'), 10)) { var lastReply = $('#post-container li.post-row[data-index!="0"]').last();
after = $this;
if(after.next().length && after.next().hasClass('post-bar')) { if (config.topicPostSort === 'oldest_to_newest') {
after = after.next(); if (firstPostTimestamp < parseInt(firstReply.attr('data-timestamp'), 10)) {
} before = firstReply;
} else if(firstPostTimestamp >= parseInt(lastReply.attr('data-timestamp'), 10)) {
after = lastReply;
}
} else if(config.topicPostSort === 'newest_to_oldest') {
if (firstPostTimestamp > parseInt(firstReply.attr('data-timestamp'), 10)) {
before = firstReply;
} else if(firstPostTimestamp <= parseInt(lastReply.attr('data-timestamp'), 10)) {
after = lastReply;
}
} 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 { } else {
return false; if (firstPostPid > firstReply.attr('data-pid')) {
before = firstReply;
} else if(firstPostPid <= firstReply.attr('data-pid')) {
after = lastReply;
} }
});
if (!after) {
var firstPost = $('#post-container .post-row').first();
if(firstPid < parseInt(firstPost.attr('data-pid'), 10)) {
before = firstPost;
} }
} }
} }
@ -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;
} }

@ -5,23 +5,28 @@
define('composer/drafts', function() { define('composer/drafts', function() {
var drafts = {}; var drafts = {};
var saveThrottleId;
var saving = false; var saving = false;
drafts.init = function(postContainer, postData) { drafts.init = function(postContainer, postData) {
var saveThrottle;
var bodyEl = postContainer.find('textarea'); var bodyEl = postContainer.find('textarea');
bodyEl.on('keyup', function() { bodyEl.on('keyup', function() {
if (saveThrottle) { resetTimeout();
clearTimeout(saveThrottle);
}
saveThrottle = setTimeout(function() { saveThrottleId = setTimeout(function() {
saveDraft(postContainer, postData); saveDraft(postContainer, postData);
}, 1000); }, 1000);
}); });
}; };
function resetTimeout() {
if (saveThrottleId) {
clearTimeout(saveThrottleId);
saveThrottleId = 0;
}
}
drafts.getDraft = function(save_id) { drafts.getDraft = function(save_id) {
return localStorage.getItem(save_id); return localStorage.getItem(save_id);
}; };
@ -40,6 +45,7 @@ define('composer/drafts', function() {
} }
drafts.removeDraft = function(save_id) { drafts.removeDraft = function(save_id) {
resetTimeout();
return localStorage.removeItem(save_id); return localStorage.removeItem(save_id);
}; };

@ -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);

@ -44,12 +44,25 @@ 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]]'));
} }
topicData.currentPage = page; topicData.currentPage = page;
if(page > 1) {
topicData.posts.splice(0, 1);
}
} }
next(err, topicData); next(err, topicData);
}); });

@ -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);
}); });
}); });

@ -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();

@ -19,16 +19,8 @@ var winston = require('winston'),
(function(PostTools) { (function(PostTools) {
PostTools.isMain = function(pid, tid, callback) { PostTools.isMain = function(pid, tid, callback) {
db.getSortedSetRange('tid:' + tid + ':posts', 0, 0, function(err, pids) { topics.getTopicField(tid, 'mainPid', function(err, mainPid) {
if(err) { callback(err, parseInt(pid, 10) === parseInt(mainPid, 10));
return callback(err);
}
if(!Array.isArray(pids) || !pids.length) {
return callback(null, false);
}
callback(null, parseInt(pids[0], 10) === parseInt(pid, 10));
}); });
}; };

@ -24,6 +24,8 @@ var db = require('./database'),
(function(Posts) { (function(Posts) {
var customUserInfo = {}; var customUserInfo = {};
require('./posts/delete')(Posts);
Posts.create = function(data, callback) { Posts.create = function(data, callback) {
var uid = data.uid, var uid = data.uid,
tid = data.tid, tid = data.tid,
@ -90,8 +92,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 +159,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 +469,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 +484,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));

@ -0,0 +1,9 @@
module.exports = function(Posts) {
Posts.delete = function(pid, callback) {
};
};

@ -134,15 +134,33 @@ function getModerators(req, res, next) {
}); });
} }
var templatesListingCache = [];
function getTemplatesListing(req, res, next) { function getTemplatesListing(req, res, next) {
utils.walk(nconf.get('views_dir'), function (err, data) { if (templatesListingCache.length) {
data = data return res.json(templatesListingCache);
.filter(function(value, index, self) { }
async.parallel({
views: function(next) {
utils.walk(nconf.get('views_dir'), next);
},
extended: function(next) {
plugins.fireHook('filter:templates.get_virtual', [], next);
}
}, function(err, results) {
if (err) {
return next(err);
}
var data = [];
data = results.views.filter(function(value, index, self) {
return self.indexOf(value) === index; return self.indexOf(value) === index;
}).map(function(el) { }).map(function(el) {
return el.replace(nconf.get('views_dir') + '/', ''); return el.replace(nconf.get('views_dir') + '/', '');
}); });
data = data.concat(results.extended);
templatesListingCache = data;
res.json(data); res.json(data);
}); });
} }

@ -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);
} }

@ -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);

@ -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) {

@ -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;

@ -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,

@ -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);
}); });
}); });
}); });

@ -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,11 +29,17 @@ 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;
} }
Topics.addPostData(postData, uid, callback);
});
};
Topics.addPostData = function(postData, uid, callback) {
var pids = postData.map(function(post) { var pids = postData.map(function(post) {
return post.pid; return post.pid;
}); });
@ -75,7 +81,6 @@ module.exports = function(Topics) {
callback(null, postData); callback(null, postData);
}); });
});
}; };
Topics.getLatestUndeletedPost = function(tid, callback) { Topics.getLatestUndeletedPost = function(tid, callback) {
@ -108,12 +113,32 @@ 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) {
db.sortedSetRemove('tid:' + tid + ':posts', pid, callback); async.parallel([
function (next) {
db.sortedSetRemove('tid:' + tid + ':posts', pid, next);
},
function (next) {
db.sortedSetRemove('tid:' + tid + ':posts:votes', pid, next);
}
], callback);
}; };
Topics.getPids = function(tid, callback) { Topics.getPids = function(tid, callback) {

@ -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!!!

@ -138,18 +138,13 @@ var bcrypt = require('bcryptjs'),
} }
User.updateLastOnlineTime = function(uid, callback) { User.updateLastOnlineTime = function(uid, callback) {
callback = callback || function() {};
User.getUserField(uid, 'status', function(err, status) { User.getUserField(uid, 'status', function(err, status) {
function cb(err) {
if(typeof callback === 'function') {
callback(err);
}
}
if(err || status === 'offline') { if(err || status === 'offline') {
return cb(err); return callback(err);
} }
User.setUserField(uid, 'lastonline', Date.now(), cb); User.setUserField(uid, 'lastonline', Date.now(), callback);
}); });
}; };

@ -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);
} }

@ -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);
};
}; };

Loading…
Cancel
Save