From c5b8a7b16333ffd4397599a89ddaeab89ba77d1b Mon Sep 17 00:00:00 2001 From: psychobunny Date: Fri, 6 Jun 2014 17:30:14 -0400 Subject: [PATCH 01/16] filter:templates.get_virtual for ajaxifying to virtual templates --- src/routes/api.js | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/routes/api.js b/src/routes/api.js index d90951b73a..8f089a9ddf 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -135,14 +135,27 @@ function getModerators(req, res, next) { } function getTemplatesListing(req, res, next) { - utils.walk(nconf.get('views_dir'), function (err, data) { - data = data - .filter(function(value, index, self) { - return self.indexOf(value) === index; - }).map(function(el) { - return el.replace(nconf.get('views_dir') + '/', ''); - }); + var data = []; + async.parallel({ + views: function(next) { + utils.walk(nconf.get('views_dir'), function (err, views) { + data = data.concat( + views.filter(function(value, index, self) { + return self.indexOf(value) === index; + }).map(function(el) { + return el.replace(nconf.get('views_dir') + '/', ''); + })); + + res.json(data); + }); + }, + extended: function(next) { + plugins.fireHook('filter:templates.get_virtual', [], function(err, virtual) { + data = data.concat(virtual); + }); + } + }, function(err) { res.json(data); }); } From 7610c11cd1b9de53ce185227ab80f86d55d3bd69 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Fri, 6 Jun 2014 22:12:14 -0400 Subject: [PATCH 02/16] closes #450 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::posts:votes` that is used to sort topic posts by vote count, the original sorted set `tid::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. --- public/language/en_GB/topic.json | 7 +- public/src/forum/infinitescroll.js | 6 +- public/src/forum/topic.js | 66 ++++++++++++------ src/controllers/api.js | 2 + src/controllers/topics.js | 12 +++- src/favourites.js | 3 +- src/middleware/middleware.js | 3 +- src/posts.js | 33 +++++++-- src/routes/feeds.js | 2 +- src/socket.io/topics.js | 14 +++- src/socket.io/user.js | 6 ++ src/topics.js | 26 ++++++- src/topics/create.js | 1 + src/topics/fork.js | 4 +- src/topics/posts.js | 106 +++++++++++++++++------------ src/upgrade.js | 70 ++++++++++++++++++- src/user/delete.js | 9 ++- src/user/settings.js | 5 ++ 18 files changed, 291 insertions(+), 84 deletions(-) diff --git a/public/language/en_GB/topic.json b/public/language/en_GB/topic.json index 8958beb1dc..6bbb8ffe3e 100644 --- a/public/language/en_GB/topic.json +++ b/public/language/en_GB/topic.json @@ -111,5 +111,10 @@ "more_users_and_guests": "%1 more user(s) and %2 guest(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" } diff --git a/public/src/forum/infinitescroll.js b/public/src/forum/infinitescroll.js index a496ff02e9..053635f312 100644 --- a/public/src/forum/infinitescroll.js +++ b/public/src/forum/infinitescroll.js @@ -8,14 +8,16 @@ define('forum/infinitescroll', function() { var callback; var previousScrollTop = 0; var loadingMore = false; + var topOffset = 0; - scroll.init = function(cb) { + scroll.init = function(cb, _topOffest) { callback = cb; + topOffset = _topOffest || 0; $(window).off('scroll', onScroll).on('scroll', 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 currentScrollTop = $(window).scrollTop(); diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index 319feef24f..7b75f00371 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -40,6 +40,8 @@ define('forum/topic', ['forum/pagination', 'forum/infinitescroll', 'forum/topic/ threadTools.init(tid, thread_state); events.init(); + handleSorting(); + hidePostToolsForDeletedPosts(); enableInfiniteLoadingOrPagination(); @@ -77,6 +79,21 @@ define('forum/topic', ['forum/pagination', 'forum/infinitescroll', 'forum/topic/ 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() { var parts = window.location.pathname.split('/'); return parts[4] ? (parseInt(parts[4], 10) - 1) : ''; @@ -122,7 +139,7 @@ define('forum/topic', ['forum/pagination', 'forum/infinitescroll', 'forum/topic/ function enableInfiniteLoadingOrPagination() { if(!config.usePagination) { - infinitescroll.init(loadMorePosts); + infinitescroll.init(loadMorePosts, $('#post-container .post-row[data-index="0"]').height()); } else { navigator.hide(); @@ -283,25 +300,36 @@ define('forum/topic', ['forum/pagination', 'forum/infinitescroll', 'forum/topic/ before = null; 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 $this = $(this); + var firstReply = $('#post-container li.post-row[data-index!="0"]').first(); + var lastReply = $('#post-container li.post-row[data-index!="0"]').last(); - if(firstPid > parseInt($this.attr('data-pid'), 10)) { - after = $this; - if(after.next().length && after.next().hasClass('post-bar')) { - after = after.next(); - } - } else { - return false; + if (config.topicPostSort === 'oldest_to_newest') { + if (firstPostTimestamp < parseInt(firstReply.attr('data-timestamp'), 10)) { + before = firstReply; + } else if(firstPostTimestamp >= parseInt(lastReply.attr('data-timestamp'), 10)) { + after = lastReply; } - }); - - if (!after) { - var firstPost = $('#post-container .post-row').first(); - if(firstPid < parseInt(firstPost.attr('data-pid'), 10)) { - before = firstPost; + } 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 { + 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; } - 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() { if (direction < 0 && el) { 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) { 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; } diff --git a/src/controllers/api.js b/src/controllers/api.js index d83cdab13d..ef355cbd51 100644 --- a/src/controllers/api.js +++ b/src/controllers/api.js @@ -42,6 +42,7 @@ apiController.getConfig = function(req, res, next) { config.isLoggedIn = !!req.user; config['cache-buster'] = meta.config['cache-buster'] || ''; config.requireEmailConfirmation = parseInt(meta.config.requireEmailConfirmation, 10) === 1; + config.topicPostSort = meta.config.topicPostSort || 'oldest_to_newest'; config.version = pkg.version; if (!req.user) { @@ -64,6 +65,7 @@ apiController.getConfig = function(req, res, next) { config.notificationSounds = settings.notificationSounds; config.defaultLang = settings.language || config.defaultLang; config.openOutgoingLinksInNewTab = settings.openOutgoingLinksInNewTab; + config.topicPostSort = settings.topicPostSort || config.topicPostSort; if (res.locals.isAPI) { res.json(200, config); diff --git a/src/controllers/topics.js b/src/controllers/topics.js index bed49056be..a73968ef5c 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -44,7 +44,17 @@ topicsController.get = function(req, res, next) { var start = (page - 1) * settings.postsPerPage + postIndex, 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 (parseInt(topicData.deleted, 10) === 1 && !userPrivileges.view_deleted) { return next(new Error('[[error:no-topic]]')); diff --git a/src/favourites.js b/src/favourites.js index 0398614b9f..9e76887faa 100644 --- a/src/favourites.js +++ b/src/favourites.js @@ -88,7 +88,8 @@ var async = require('async'), return callback(err); } 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); }); }); diff --git a/src/middleware/middleware.js b/src/middleware/middleware.js index 6d0a172414..4c8b6a9e5f 100644 --- a/src/middleware/middleware.js +++ b/src/middleware/middleware.js @@ -85,9 +85,10 @@ middleware.checkPostIndex = function(req, res, next) { return next(err); } var postIndex = parseInt(req.params.post_index, 10); + postCount = parseInt(postCount, 10) + 1; 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); - } 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); } next(); diff --git a/src/posts.js b/src/posts.js index 69f555a05c..51de423df0 100644 --- a/src/posts.js +++ b/src/posts.js @@ -90,8 +90,8 @@ var db = require('./database'), ], callback); }; - Posts.getPostsByTid = function(tid, start, end, reverse, callback) { - db[reverse ? 'getSortedSetRevRange' : 'getSortedSetRange']('tid:' + tid + ':posts', start, end, function(err, pids) { + Posts.getPostsByTid = function(tid, set, start, end, reverse, callback) { + db[reverse ? 'getSortedSetRevRange' : 'getSortedSetRange'](set, start, end, function(err, pids) { if(err) { return callback(err); } @@ -157,8 +157,6 @@ var db = require('./database'), }); }; - - Posts.getRecentPosts = function(uid, start, stop, term, callback) { var terms = { day: 86400000, @@ -469,7 +467,9 @@ var db = require('./database'), 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)); diff --git a/src/routes/feeds.js b/src/routes/feeds.js index 624c06e9a1..30b3cb6c4c 100644 --- a/src/routes/feeds.js +++ b/src/routes/feeds.js @@ -40,7 +40,7 @@ function hasPrivileges(method, id, req, res, next) { function generateForTopic(req, res, next) { var tid = req.params.topic_id; 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) { return next(err); } diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js index b7c84ff127..466859038a 100644 --- a/src/socket.io/topics.js +++ b/src/socket.io/topics.js @@ -314,12 +314,22 @@ SocketTopics.loadMore = function(socket, data, callback) { return callback(err); } - var start = parseInt(data.after, 10), + var start = Math.max(parseInt(data.after, 10) - 1, 0), 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({ 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.topics.get(data.tid, socket.uid, next); diff --git a/src/socket.io/user.js b/src/socket.io/user.js index 4747c24d2f..5cf805362b 100644 --- a/src/socket.io/user.js +++ b/src/socket.io/user.js @@ -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) { var returnData = {}; if(!data) { diff --git a/src/topics.js b/src/topics.js index 05b57f5d33..0b225092d4 100644 --- a/src/topics.js +++ b/src/topics.js @@ -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) { if (err || !topicData) { return callback(err || new Error('[[error:no-topic]]')); @@ -270,7 +270,7 @@ var async = require('async'), async.parallel({ posts: function(next) { - Topics.getTopicPosts(tid, start, end, uid, false, next); + Topics.getTopicPosts(tid, set, start, end, uid, reverse, next); }, category: function(next) { Topics.getCategoryData(tid, next); @@ -283,6 +283,26 @@ var async = require('async'), }, tags: function(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) { if (err) { @@ -290,7 +310,7 @@ var async = require('async'), } topicData.category = results.category; - topicData.posts = results.posts; + topicData.posts = results.mainPost.concat(results.posts); topicData.tags = results.tags; topicData.thread_tools = results.threadTools; topicData.pageCount = results.pageCount; diff --git a/src/topics/create.js b/src/topics/create.js index 7bf23b4bed..a6b3ef353a 100644 --- a/src/topics/create.js +++ b/src/topics/create.js @@ -37,6 +37,7 @@ module.exports = function(Topics) { 'tid': tid, 'uid': uid, 'cid': cid, + 'mainPid': 0, 'title': title, 'slug': slug, 'timestamp': timestamp, diff --git a/src/topics/fork.js b/src/topics/fork.js index 35880cc2ea..bd9218f875 100644 --- a/src/topics/fork.js +++ b/src/topics/fork.js @@ -71,7 +71,7 @@ module.exports = function(Topics) { 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) { return callback(err); } @@ -91,7 +91,7 @@ module.exports = function(Topics) { } posts.setPostField(pid, 'tid', tid); - Topics.addPostToTopic(tid, pid, postData.timestamp, callback); + Topics.addPostToTopic(tid, pid, postData.timestamp, postData.votes, callback); }); }); }); diff --git a/src/topics/posts.js b/src/topics/posts.js index 13cd8ca37c..ca1b0ba4c7 100644 --- a/src/topics/posts.js +++ b/src/topics/posts.js @@ -15,13 +15,13 @@ module.exports = function(Topics) { Topics.onNewPostMade = function(postData) { Topics.increasePostCount(postData.tid); 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); - Topics.getTopicPosts = function(tid, start, end, uid, reverse, callback) { - posts.getPostsByTid(tid, start, end, reverse, function(err, postData) { + Topics.getTopicPosts = function(tid, set, start, end, uid, reverse, callback) { + posts.getPostsByTid(tid, set, start, end, reverse, function(err, postData) { if(err) { return callback(err); } @@ -29,52 +29,57 @@ module.exports = function(Topics) { if (Array.isArray(postData) && !postData.length) { return callback(null, []); } + start = parseInt(start, 10); for(var i=0; i Date: Fri, 6 Jun 2014 23:09:05 -0400 Subject: [PATCH 03/16] remove main post if page is greater than 1 this fixes pagination after the main post change --- src/controllers/topics.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/controllers/topics.js b/src/controllers/topics.js index a73968ef5c..9fce84d994 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -60,6 +60,9 @@ topicsController.get = function(req, res, next) { return next(new Error('[[error:no-topic]]')); } topicData.currentPage = page; + if(page > 1) { + topicData.posts.splice(0, 1); + } } next(err, topicData); }); From bf04749f5e08fffcc1dc44c7aa7695febcf9fb1d Mon Sep 17 00:00:00 2001 From: barisusakli Date: Sat, 7 Jun 2014 11:38:43 -0400 Subject: [PATCH 04/16] fixes posttools.ismain --- src/postTools.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/postTools.js b/src/postTools.js index 20e8cc272c..f496e640bf 100644 --- a/src/postTools.js +++ b/src/postTools.js @@ -19,16 +19,8 @@ var winston = require('winston'), (function(PostTools) { PostTools.isMain = function(pid, tid, callback) { - db.getSortedSetRange('tid:' + tid + ':posts', 0, 0, function(err, pids) { - if(err) { - return callback(err); - } - - if(!Array.isArray(pids) || !pids.length) { - return callback(null, false); - } - - callback(null, parseInt(pids[0], 10) === parseInt(pid, 10)); + topics.getTopicField(tid, 'mainPid', function(err, mainPid) { + callback(err, parseInt(pid, 10) === parseInt(mainPid, 10)); }); }; From b7f71ca0b47fd81520b7259479444f304bcdd1cd Mon Sep 17 00:00:00 2001 From: barisusakli Date: Sat, 7 Jun 2014 13:04:30 -0400 Subject: [PATCH 05/16] fixes removePostFromTopic remove the pid from the votes set too --- src/topics/fork.js | 10 +++++----- src/topics/posts.js | 9 ++++++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/topics/fork.js b/src/topics/fork.js index bd9218f875..4d276f16fb 100644 --- a/src/topics/fork.js +++ b/src/topics/fork.js @@ -15,15 +15,15 @@ var async = require('async'), module.exports = function(Topics) { Topics.createTopicFromPosts = function(uid, title, pids, callback) { - if(title) { + if (title) { title = title.trim(); } - if(!title) { + if (!title) { return callback(new Error('[[error:invalid-title]]')); } - if(!pids || !pids.length) { + if (!pids || !pids.length) { return callback(new Error('[[error:invalid-pid]]')); } @@ -39,12 +39,12 @@ module.exports = function(Topics) { } }, function(err, results) { Topics.create({uid: results.postData.uid, title: title, cid: results.cid}, function(err, tid) { - if(err) { + if (err) { return callback(err); } async.eachSeries(pids, move, function(err) { - if(err) { + if (err) { return callback(err); } diff --git a/src/topics/posts.js b/src/topics/posts.js index ca1b0ba4c7..2819c6e647 100644 --- a/src/topics/posts.js +++ b/src/topics/posts.js @@ -131,7 +131,14 @@ module.exports = function(Topics) { }; 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) { From 178f567659f4ffe8604aceec5fa07cbd4c4dd73f Mon Sep 17 00:00:00 2001 From: barisusakli Date: Sat, 7 Jun 2014 15:34:25 -0400 Subject: [PATCH 06/16] closes #1655 --- public/src/modules/composer/drafts.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/public/src/modules/composer/drafts.js b/public/src/modules/composer/drafts.js index d355cfa054..27370607ca 100644 --- a/public/src/modules/composer/drafts.js +++ b/public/src/modules/composer/drafts.js @@ -5,23 +5,28 @@ define('composer/drafts', function() { var drafts = {}; - + var saveThrottleId; var saving = false; drafts.init = function(postContainer, postData) { - var saveThrottle; + var bodyEl = postContainer.find('textarea'); bodyEl.on('keyup', function() { - if (saveThrottle) { - clearTimeout(saveThrottle); - } + resetTimeout(); - saveThrottle = setTimeout(function() { + saveThrottleId = setTimeout(function() { saveDraft(postContainer, postData); }, 1000); }); }; + function resetTimeout() { + if (saveThrottleId) { + clearTimeout(saveThrottleId); + saveThrottleId = 0; + } + } + drafts.getDraft = function(save_id) { return localStorage.getItem(save_id); }; @@ -40,6 +45,7 @@ define('composer/drafts', function() { } drafts.removeDraft = function(save_id) { + resetTimeout(); return localStorage.removeItem(save_id); }; From ee886934489120d90e6c691b1c381f1869a38079 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Sun, 8 Jun 2014 16:06:42 -0400 Subject: [PATCH 07/16] callback --- src/user.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/user.js b/src/user.js index 5d5083df30..e2ca9ec7e9 100644 --- a/src/user.js +++ b/src/user.js @@ -138,18 +138,13 @@ var bcrypt = require('bcryptjs'), } User.updateLastOnlineTime = function(uid, callback) { + callback = callback || function() {}; User.getUserField(uid, 'status', function(err, status) { - function cb(err) { - if(typeof callback === 'function') { - callback(err); - } - } - if(err || status === 'offline') { - return cb(err); + return callback(err); } - User.setUserField(uid, 'lastonline', Date.now(), cb); + User.setUserField(uid, 'lastonline', Date.now(), callback); }); }; From 974e0823d8c1e5b48af822eba44b6007d3dfbb52 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Sun, 8 Jun 2014 17:48:33 -0400 Subject: [PATCH 08/16] copyright --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index e41c70349b..d83bb95d36 100644 --- a/app.js +++ b/app.js @@ -58,7 +58,7 @@ if(os.platform() === 'linux') { } // 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 is free software, and you are welcome to redistribute it under certain conditions.'); winston.info(''); From 9734403114b95ff3c02ac12af7a58fe8e94a8da1 Mon Sep 17 00:00:00 2001 From: Charles Date: Mon, 9 Jun 2014 12:21:58 +0700 Subject: [PATCH 09/16] Fix removeRelativePath Instead of checking the existence of relative_path (without /) anywhere on the url, it really should check that the url only starts with the relative_path. Example ``` relative_path = /forum without / = forum url = /category/forum/5 removeRelativePath = ory/forum/5 ``` --- public/src/ajaxify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index b1d63f7141..7fafaa4457 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -123,7 +123,7 @@ var ajaxify = ajaxify || {}; }; function removeRelativePath(url) { - if (url.indexOf(RELATIVE_PATH.slice(1)) !== -1) { + if (url.indexOf(RELATIVE_PATH.slice(1)) === 0) { url = url.slice(RELATIVE_PATH.length); } return url; From 4bdbce9cd80b20af80c6750cff575f473a69fb3f Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 9 Jun 2014 01:28:58 -0400 Subject: [PATCH 10/16] use removeRelativePath in app.js too --- public/src/app.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/public/src/app.js b/public/src/app.js index fda565a0a1..242f874e72 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -66,7 +66,7 @@ var socket, }); } }); - + $(window).trigger('action:reconnected'); setTimeout(function() { @@ -162,7 +162,7 @@ var socket, socket.emit('tools.log', arguments); }; } - + app.cacheBuster = config['cache-buster']; } } @@ -516,9 +516,7 @@ var socket, tpl_url = ajaxify.getTemplateMapping(url), $window = $(window); - if (url.indexOf(RELATIVE_PATH.slice(1)) !== -1) { - url = url.slice(RELATIVE_PATH.length); - } + url = ajaxify.removeRelativePath(url); ajaxify.widgets.render(tpl_url, url); From db84ced78fc929895cfb358daf799091ed959941 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 9 Jun 2014 02:03:36 -0400 Subject: [PATCH 11/16] removeRelativePath public --- public/src/ajaxify.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 7fafaa4457..6b63fa1966 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -122,12 +122,12 @@ var ajaxify = ajaxify || {}; return false; }; - function removeRelativePath(url) { + ajaxify.removeRelativePath = function(url) { if (url.indexOf(RELATIVE_PATH.slice(1)) === 0) { url = url.slice(RELATIVE_PATH.length); } return url; - } + }; ajaxify.refresh = function() { ajaxify.go(ajaxify.currentPage); From aadca3a675b3f4d2d5c3789dff3c955d450882a6 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 9 Jun 2014 02:13:19 -0400 Subject: [PATCH 12/16] fix calls to removeRelativePath in ajaxify.js --- public/src/ajaxify.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 6b63fa1966..04e039d1f2 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -60,7 +60,7 @@ var ajaxify = ajaxify || {}; // Remove trailing slash url = url.replace(/\/$/, ""); - url = removeRelativePath(url); + url = ajaxify.removeRelativePath(url); var tpl_url = ajaxify.getTemplateMapping(url); @@ -186,7 +186,7 @@ var ajaxify = ajaxify || {}; }; ajaxify.loadData = function(url, callback) { - url = removeRelativePath(url); + url = ajaxify.removeRelativePath(url); $(window).trigger('action:ajaxify.loadingData', {url: url}); From d4b48cd2ac7419f6b1f7fdd349b724529cb307ca Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 9 Jun 2014 02:32:32 -0400 Subject: [PATCH 13/16] closes #1654 --- src/routes/api.js | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/routes/api.js b/src/routes/api.js index 8f089a9ddf..0115249d75 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -134,28 +134,36 @@ function getModerators(req, res, next) { }); } +var templatsListingCache = []; + function getTemplatesListing(req, res, next) { - var data = []; + var st = process.hrtime(); + //if (templatsListingCache.length) { + // process.profile('with cache', st); +// return res.json(templatsListingCache); +// } async.parallel({ views: function(next) { - utils.walk(nconf.get('views_dir'), function (err, views) { - data = data.concat( - views.filter(function(value, index, self) { - return self.indexOf(value) === index; - }).map(function(el) { - return el.replace(nconf.get('views_dir') + '/', ''); - })); - - res.json(data); - }); + utils.walk(nconf.get('views_dir'), next); }, extended: function(next) { - plugins.fireHook('filter:templates.get_virtual', [], function(err, virtual) { - data = data.concat(virtual); - }); + plugins.fireHook('filter:templates.get_virtual', [], next); } - }, function(err) { + }, function(err, results) { + if (err) { + return next(err); + } + var data = []; + data = results.views.filter(function(value, index, self) { + return self.indexOf(value) === index; + }).map(function(el) { + return el.replace(nconf.get('views_dir') + '/', ''); + }); + + data = data.concat(results.extended); + templatsListingCache = data; + process.profile('without cache', st); res.json(data); }); } From b5071d504fbe77fc02c0a17be45f153552086f5c Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 9 Jun 2014 02:33:07 -0400 Subject: [PATCH 14/16] removed timing #1654 --- src/routes/api.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/routes/api.js b/src/routes/api.js index 0115249d75..5f7ef811cd 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -137,11 +137,9 @@ function getModerators(req, res, next) { var templatsListingCache = []; function getTemplatesListing(req, res, next) { - var st = process.hrtime(); - //if (templatsListingCache.length) { - // process.profile('with cache', st); -// return res.json(templatsListingCache); -// } + if (templatsListingCache.length) { + return res.json(templatsListingCache); + } async.parallel({ views: function(next) { @@ -163,7 +161,6 @@ function getTemplatesListing(req, res, next) { data = data.concat(results.extended); templatsListingCache = data; - process.profile('without cache', st); res.json(data); }); } From b81f3552bbf7302a9558f28182d6d3ad1188fad3 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 9 Jun 2014 02:34:21 -0400 Subject: [PATCH 15/16] fixed typo --- src/routes/api.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/routes/api.js b/src/routes/api.js index 5f7ef811cd..354c3d640b 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -134,11 +134,11 @@ function getModerators(req, res, next) { }); } -var templatsListingCache = []; +var templatesListingCache = []; function getTemplatesListing(req, res, next) { - if (templatsListingCache.length) { - return res.json(templatsListingCache); + if (templatesListingCache.length) { + return res.json(templatesListingCache); } async.parallel({ @@ -160,7 +160,7 @@ function getTemplatesListing(req, res, next) { }); data = data.concat(results.extended); - templatsListingCache = data; + templatesListingCache = data; res.json(data); }); } From 833aa0f738fe4559d2ecb5950dd22d21179df705 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Mon, 9 Jun 2014 12:51:49 -0400 Subject: [PATCH 16/16] derp --- src/posts.js | 2 ++ src/posts/delete.js | 9 +++++++++ 2 files changed, 11 insertions(+) create mode 100644 src/posts/delete.js diff --git a/src/posts.js b/src/posts.js index 51de423df0..5861a58042 100644 --- a/src/posts.js +++ b/src/posts.js @@ -24,6 +24,8 @@ var db = require('./database'), (function(Posts) { var customUserInfo = {}; + require('./posts/delete')(Posts); + Posts.create = function(data, callback) { var uid = data.uid, tid = data.tid, diff --git a/src/posts/delete.js b/src/posts/delete.js new file mode 100644 index 0000000000..72b420e107 --- /dev/null +++ b/src/posts/delete.js @@ -0,0 +1,9 @@ + + +module.exports = function(Posts) { + + Posts.delete = function(pid, callback) { + + }; + +}; \ No newline at end of file