Merge remote-tracking branch 'origin/master' into webserver.js-refactor

v1.18.x
psychobunny 11 years ago
commit 607bc8545b

@ -14,10 +14,7 @@ var nconf = require('nconf'),
nbb.on('message', function(cmd) {
if (cmd === 'nodebb:restart') {
nbb.on('exit', function() {
nbb_start();
});
nbb.kill();
nbb_restart();
}
});
},
@ -29,10 +26,17 @@ var nconf = require('nconf'),
fs.unlinkSync(pidFilePath);
}
}
},
nbb_restart = function() {
nbb.on('exit', function() {
nbb_start();
});
nbb.kill();
};
process.on('SIGINT', nbb_stop);
process.on('SIGTERM', nbb_stop);
process.on('SIGHUP', nbb_restart);
nbb_start();
},

@ -9,6 +9,7 @@ case "$1" in
echo "Starting NodeBB";
echo " \"./nodebb stop\" to stop the NodeBB server";
echo " \"./nodebb log\" to view server output";
echo "" > ./logs/output.log;
node loader -d "$@"
;;
@ -17,7 +18,13 @@ case "$1" in
kill `cat pidfile`;
;;
reload|restart)
echo "Restarting NodeBB.";
kill -1 `cat pidfile`;
;;
log)
clear;
tail -F ./logs/output.log;
;;
@ -54,11 +61,13 @@ case "$1" in
*)
echo "Welcome to NodeBB"
echo $"Usage: $0 {start|stop|log|setup|reset|upgrade|dev|watch}"
echo $"Usage: $0 {start|stop|reload|restart|log|setup|reset|upgrade|dev|watch}"
echo ''
column -s ' ' -t <<< '
start Start the NodeBB server
stop Stops the NodeBB server
reload Restarts NodeBB
restart Restarts NodeBB
log Opens the logging interface (useful for debugging)
setup Runs the NodeBB setup script
reset Disables all plugins, restores the default theme.

@ -21,7 +21,9 @@ var ajaxify = {};
window.onpopstate = function (event) {
if (event !== null && event.state && event.state.url !== undefined && !ajaxify.initialLoad) {
ajaxify.go(event.state.url, null, true);
ajaxify.go(event.state.url, function() {
$(window).trigger('action:popstate', {url: event.state.url});
}, true);
}
};
@ -29,6 +31,7 @@ var ajaxify = {};
ajaxify.initialLoad = false;
ajaxify.go = function (url, callback, quiet) {
// "quiet": If set to true, will not call pushState
app.enterRoom('global');
@ -101,7 +104,7 @@ var ajaxify = {};
}
});
if (callback) {
if (typeof callback === 'function') {
callback();
}
@ -129,7 +132,7 @@ var ajaxify = {};
$this.addClass($this.attr('no-widget-class'));
});
}
next(err);
});
}, function(err) {

@ -448,13 +448,14 @@ var socket,
app.enableInfiniteLoading = function(callback) {
$(window).off('scroll').on('scroll', function() {
var top = $(window).height() * 0.1;
var bottom = ($(document).height() - $(window).height()) * 0.9;
var currentScrollTop = $(window).scrollTop();
if($(window).scrollTop() < top && previousScrollTop > currentScrollTop) {
if(currentScrollTop < top && currentScrollTop < previousScrollTop) {
callback(-1);
} else if ($(window).scrollTop() > bottom && previousScrollTop < currentScrollTop) {
} else if (currentScrollTop > bottom && currentScrollTop > previousScrollTop) {
callback(1);
}
previousScrollTop = currentScrollTop;

@ -38,13 +38,128 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
socket.on('event:new_topic', Category.onNewTopic);
enableInfiniteLoading();
$('#topics-container').on('click', '.topic-title', function() {
var clickedTid = $(this).parents('li.category-item[data-tid]').attr('data-tid');
$('#topics-container li.category-item').each(function(index, el) {
if($(el).offset().top - $(window).scrollTop() > 0) {
tid = $(el).attr('data-tid');
localStorage.setItem('category:bookmark', tid);
localStorage.setItem('category:bookmark:clicked', clickedTid);
return false;
}
});
});
};
$(window).on('action:popstate', function(ev, data) {
if(data.url.indexOf('category/') === 0) {
var bookmark = localStorage.getItem('category:bookmark');
var clicked = localStorage.getItem('category:bookmark:clicked');
if (bookmark) {
if(config.usePagination) {
socket.emit('topics.getTidPage', bookmark, function(err, page) {
if(err) {
return;
}
if(parseInt(page, 10) !== pagination.currentPage) {
pagination.loadPage(page);
} else {
Category.scrollToTopic(bookmark, clicked, 400);
}
});
} else {
socket.emit('topics.getTidIndex', bookmark, function(err, index) {
if(err) {
return;
}
if(index === 0) {
Category.highlightTopic(clicked);
return;
}
if (index < 0) {
index = 0;
}
$('#topics-container').empty();
loadingMoreTopics = false;
Category.loadMoreTopics(templates.get('category_id'), index, function() {
Category.scrollToTopic(bookmark, clicked, 0);
});
});
}
}
}
});
Category.highlightTopic = function(tid) {
var highlight = $('#topics-container li.category-item[data-tid="' + tid + '"]');
if(highlight.length && !highlight.hasClass('highlight')) {
highlight.addClass('highlight');
setTimeout(function() {
highlight.removeClass('highlight');
}, 5000);
}
};
Category.scrollToTopic = function(tid, clickedTid, duration, offset) {
if(!tid) {
return;
}
if(!offset) {
offset = 0;
}
if($('#topics-container li.category-item[data-tid="' + tid + '"]').length) {
var cid = templates.get('category_id');
var scrollTo = $('#topics-container li.category-item[data-tid="' + tid + '"]');
if (cid && scrollTo.length) {
$('html, body').animate({
scrollTop: (scrollTo.offset().top - $('#header-menu').height() - offset) + 'px'
}, duration !== undefined ? duration : 400, function() {
Category.highlightTopic(clickedTid);
});
}
}
};
function enableInfiniteLoading() {
if(!config.usePagination) {
app.enableInfiniteLoading(function() {
if(!loadingMoreTopics) {
Category.loadMoreTopics(templates.get('category_id'));
app.enableInfiniteLoading(function(direction) {
if(!loadingMoreTopics && $('#topics-container').children().length) {
var after = 0;
var el = null;
if(direction > 0) {
el = $('#topics-container .category-item[data-tid]').last();
after = parseInt(el.attr('data-index'), 10) + 1;
} else {
el = $('#topics-container .category-item[data-tid]').first();
after = parseInt(el.attr('data-index'), 10);
after -= config.topicsPerPage;
if(after < 0) {
after = 0;
}
}
var offset = el.offset().top - $('#header-menu').offset().top + $('#header-menu').height();
Category.loadMoreTopics(templates.get('category_id'), after, function() {
if(direction < 0 && el) {
Category.scrollToTopic(el.attr('data-tid'), null, 0, offset);
}
});
}
});
} else {
@ -94,56 +209,112 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
$(window).trigger('action:categories.new_topic.loaded');
});
}
};
Category.onTopicsLoaded = function(topics, callback) {
if(!topics || !topics.length) {
return;
}
function removeAlreadyAddedTopics() {
topics = topics.filter(function(topic) {
return $('#topics-container li[data-tid="' + topic.tid +'"]').length === 0;
});
}
var after = null,
before = null;
function findInsertionPoint() {
if (!$('#topics-container .category-item[data-tid]').length) {
return;
}
var last = $('#topics-container .category-item[data-tid]').last();
var lastIndex = last.attr('data-index');
var firstIndex = topics[topics.length - 1].index;
if (firstIndex > lastIndex) {
after = last;
} else {
before = $('#topics-container .category-item[data-tid]').first();
}
}
removeAlreadyAddedTopics();
if(!topics.length) {
return;
}
findInsertionPoint();
Category.onTopicsLoaded = function(topics) {
var html = templates.prepare(templates['category'].blocks['topics']).parse({
topics: topics
});
translator.translate(html, function(translatedHTML) {
var container = $('#topics-container');
var container = $('#topics-container'),
html = $(translatedHTML);
$('#topics-container, .category-sidebar').removeClass('hidden');
$('#category-no-topics').remove();
html = $(translatedHTML);
if(config.usePagination) {
container.empty().append(html);
} else {
container.append(html);
if(after) {
html.insertAfter(after);
} else if(before) {
html.insertBefore(before);
} else {
container.append(html);
}
}
$('#topics-container span.timeago').timeago();
app.createUserTooltips();
app.makeNumbersHumanReadable(html.find('.human-readable-number'));
if (typeof callback === 'function') {
callback(topics);
}
});
}
};
Category.loadMoreTopics = function(cid) {
Category.loadMoreTopics = function(cid, after, callback) {
if (loadingMoreTopics || !$('#topics-container').length) {
return;
}
if(after === 0 && $('#topics-container li.category-item[data-index="0"]').length) {
return;
}
$(window).trigger('action:categories.loading');
loadingMoreTopics = true;
socket.emit('categories.loadMore', {
cid: cid,
after: $('#topics-container').attr('data-nextstart')
after: after
}, function (err, data) {
loadingMoreTopics = false;
if(err) {
return app.alertError(err.message);
}
if (data && data.topics.length) {
Category.onTopicsLoaded(data.topics);
Category.onTopicsLoaded(data.topics, callback);
$('#topics-container').attr('data-nextstart', data.nextStart);
} else {
if (typeof callback === 'function') {
callback(data.topics);
}
}
loadingMoreTopics = false;
$(window).trigger('action:categories.loaded');
});
}
};
return Category;
});

@ -1027,14 +1027,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
}
$('#pagination').html(index + ' out of ' + Topic.postCount);
$('.progress-bar').width((index / Topic.postCount * 100) + '%');
return false;
}
});
$('.posts > .post-row').each(function() {
var el = $(this);
if (elementInView(el)) {
if(!parseInt(el.attr('data-index'), 10)) {
localStorage.removeItem('topic:' + templates.get('topic_id') + ':bookmark');
} else {
@ -1063,7 +1056,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
var elTop = el.offset().top;
var elBottom = elTop + Math.floor(el.height());
return !(elTop > scrollBottom || elBottom < scrollTop);
return (elTop >= scrollTop && elBottom <= scrollBottom) || (elTop <= scrollTop && elBottom >= scrollTop);
}
Topic.scrollToPost = function(pid, highlight, duration, offset) {

@ -20,9 +20,7 @@
<ul id="users-container" class="users admin">
<!-- BEGIN users -->
<div class="users-box" data-uid="{users.uid}" data-admin="{users.administrator}" data-username="{users.username}" data-banned="{users.banned}">
<a href="{relative_path}/user/{users.userslug}">
<img src="{users.picture}" class="img-thumbnail"/>
</a>
<a href="{relative_path}/user/{users.userslug}"><img src="{users.picture}" class="img-thumbnail"/></a>
<br/>
<a href="{relative_path}/user/{users.userslug}">{users.username}</a>
<br/>

@ -39,7 +39,7 @@
<ul id="topics-container" itemscope itemtype="http://www.schema.org/ItemList" data-nextstart="{nextStart}">
<meta itemprop="itemListOrder" content="descending">
<!-- BEGIN topics -->
<li class="category-item <!-- IF topics.deleted -->deleted<!-- ENDIF topics.deleted --><!-- IF topics.unread -->unread<!-- ENDIF topics.unread -->" itemprop="itemListElement">
<li class="category-item <!-- IF topics.deleted -->deleted<!-- ENDIF topics.deleted --><!-- IF topics.unread -->unread<!-- ENDIF topics.unread -->" itemprop="itemListElement" data-tid="{topics.tid}" data-index="{topics.index}">
<div class="col-md-12 col-xs-12 panel panel-default topic-row">

File diff suppressed because one or more lines are too long

@ -85,11 +85,13 @@ var db = require('./database'),
};
Categories.getCategoryTopics = function(cid, start, stop, uid, callback) {
var tids;
async.waterfall([
function(next) {
Categories.getTopicIds(cid, start, stop, next);
},
function(tids, next) {
function(topicIds, next) {
tids = topicIds;
topics.getTopicsByTids(tids, uid, next);
},
function(topics, next) {
@ -100,6 +102,15 @@ var db = require('./database'),
});
}
var indices = {};
for(var i=0; i<tids.length; ++i) {
indices[tids[i]] = start + i;
}
for(var i=0; i<topics.length; ++i) {
topics[i].index = indices[topics[i].tid];
}
db.sortedSetRevRank('categories:' + cid + ':tid', topics[topics.length - 1].tid, function(err, rank) {
if(err) {
return next(err);
@ -118,6 +129,16 @@ var db = require('./database'),
db.getSortedSetRevRange('categories:' + cid + ':tid', start, stop, callback);
};
Categories.getTopicIndex = function(tid, callback) {
topics.getTopicField(tid, 'cid', function(err, cid) {
if(err) {
return callback(err);
}
db.sortedSetRevRank('categories:' + cid + ':tid', tid, callback);
});
};
Categories.getPageCount = function(cid, uid, callback) {
db.sortedSetCard('categories:' + cid + ':tid', function(err, topicCount) {
if(err) {

@ -1,3 +1,5 @@
'use strict';
var db = require('./database'),
utils = require('./../public/src/utils'),
user = require('./user'),
@ -43,7 +45,7 @@ var db = require('./database'),
},
function(pid, next) {
plugins.fireHook('filter:post.save', content, function(err, newContent) {
next(err, pid, newContent)
next(err, pid, newContent);
});
},
function(pid, newContent, next) {
@ -62,7 +64,7 @@ var db = require('./database'),
};
if (toPid) {
postData['toPid'] = toPid;
postData.toPid = toPid;
}
db.setObject('post:' + pid, postData, function(err) {
@ -196,7 +198,7 @@ var db = require('./database'),
db.sortedSetRevRank('uid:' + uid + ':posts', posts[posts.length - 1].pid, function(err, rank) {
if(err) {
return calllback(err);
return callback(err);
}
var userPosts = {
posts: posts,
@ -207,7 +209,7 @@ var db = require('./database'),
});
});
});
}
};
Posts.addUserInfoToPost = function(post, callback) {
user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(err, userData) {
@ -299,7 +301,7 @@ var db = require('./database'),
postData.title = validator.escape(topicData.title);
postData.topicSlug = topicData.slug;
next(null, postData);
})
});
});
},
function(postData, next) {
@ -404,7 +406,7 @@ var db = require('./database'),
}
});
});
}
};
Posts.uploadPostImage = function(image, callback) {
@ -418,7 +420,7 @@ var db = require('./database'),
callback(new Error('Uploads are disabled!'));
}
}
}
};
Posts.uploadPostFile = function(file, callback) {
@ -450,9 +452,8 @@ var db = require('./database'),
});
});
}
}
};
// this function should really be called User.getFavouritePosts
Posts.getFavourites = function(uid, start, end, callback) {
db.getSortedSetRevRange('uid:' + uid + ':favourites', start, end, function(err, pids) {
if (err) {
@ -470,7 +471,7 @@ var db = require('./database'),
db.sortedSetRevRank('uid:' + uid + ':favourites', posts[posts.length - 1].pid, function(err, rank) {
if(err) {
return calllback(err);
return callback(err);
}
var favourites = {
posts: posts,
@ -480,28 +481,20 @@ var db = require('./database'),
});
});
});
}
};
Posts.getPidPage = function(pid, uid, callback) {
if(!pid) {
return callback(new Error('invalid-pid'));
}
var index = 0;
async.waterfall([
function(next) {
Posts.getPostField(pid, 'tid', next);
Posts.getPidIndex(pid, next);
},
function(tid, next) {
topics.getPids(tid, next);
},
function(pids, next) {
index = pids.indexOf(pid.toString());
if(index === -1) {
return next(new Error('pid not found'));
}
next();
},
function(next) {
function(result, next) {
index = result;
user.getSettings(uid, next);
},
function(settings, next) {
@ -518,6 +511,6 @@ var db = require('./database'),
db.sortedSetRank('tid:' + tid + ':posts', pid, callback);
});
}
};
}(exports));

@ -120,7 +120,7 @@ SocketAdmin.categories.create = function(socket, data, callback) {
SocketAdmin.categories.update = function(socket, data) {
if(!data) {
return callback(new Error('invalid data'));
throw new Error('invalid data');
}
admin.categories.update(data, socket);
@ -380,4 +380,4 @@ SocketAdmin.groups.update = function(socket, data, callback) {
});
};
module.exports = SocketAdmin;
module.exports = SocketAdmin;

@ -243,11 +243,11 @@ SocketPosts.getFavouritedUsers = function(socket, pid, callback) {
SocketPosts.getPidPage = function(socket, pid, callback) {
posts.getPidPage(pid, socket.uid, callback);
}
};
SocketPosts.getPidIndex = function(socket, pid, callback) {
posts.getPidIndex(pid, callback);
}
};
SocketPosts.flag = function(socket, pid, callback) {
if (!socket.uid) {

@ -1,4 +1,5 @@
var topics = require('../topics'),
categories = require('../categories'),
threadTools = require('../threadTools'),
index = require('./index'),
user = require('../user'),
@ -291,9 +292,16 @@ SocketTopics.loadMoreFromSet = function(socket, data, callback) {
topics.getTopicsFromSet(socket.uid, data.set, start, end, callback);
};
SocketTopics.getPageCount = function(socket, tid, callback) {
topics.getPageCount(tid, socket.uid, callback);
};
SocketTopics.getTidPage = function(socket, tid, callback) {
topics.getTidPage(tid, socket.uid, callback);
};
SocketTopics.getTidIndex = function(socket, tid, callback) {
categories.getTopicIndex(tid, callback);
};
module.exports = SocketTopics;

@ -426,6 +426,26 @@ var async = require('async'),
});
};
Topics.getTidPage = function(tid, uid, callback) {
if(!tid) {
return callback(new Error('invalid-tid'));
}
async.parallel({
index: function(next) {
categories.getTopicIndex(tid, next);
},
settings: function(next) {
user.getSettings(uid, next);
}
}, function(err, results) {
if(err) {
return callback(err);
}
callback(null, Math.ceil((results.index + 1) / results.settings.topicsPerPage));
});
};
Topics.getCategoryData = function(tid, callback) {
Topics.getTopicField(tid, 'cid', function(err, cid) {
if(err) {

Loading…
Cancel
Save