upgraded userlist to 3 sorted sets, run node app -upgrade after updating to this commit, added infinite scrolling to all user pages, added ops per second to redis page, changed the percentage to 90% for infinite scrolling to kick in

v1.18.x
Baris Soner Usakli 12 years ago
parent 4457228903
commit ded0200355

@ -392,7 +392,7 @@ body .navbar .nodebb-inline-block {
#admin-redis-info { #admin-redis-info {
span { span {
display:inline-block; display:inline-block;
width:200px; width:220px;
} }
} }

@ -79,8 +79,9 @@
jQuery('document').ready(function() { jQuery('document').ready(function() {
var yourid = templates.get('yourid'); var yourid = templates.get('yourid'),
var timeoutId = 0; timeoutId = 0,
loadingMoreUsers = false;
var url = window.location.href, var url = window.location.href,
parts = url.split('/'), parts = url.split('/'),
@ -114,7 +115,6 @@
socket.removeAllListeners('api:admin.user.search'); socket.removeAllListeners('api:admin.user.search');
socket.on('api:admin.user.search', function(data) { socket.on('api:admin.user.search', function(data) {
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({ var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
users: data users: data
}), }),
@ -139,6 +139,47 @@
initUsers(); initUsers();
}); });
function onUsersLoaded(users) {
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({ users: users }),
container = $('#users-container');
container.append(html);
}
function loadMoreUsers() {
var set = '';
if(active === 'latest') {
set = 'users:joindate';
} else if(active === 'sort-posts') {
set = 'users:postcount';
} else if(active === 'sort-reputation') {
set = 'users:reputation';
}
if(set) {
loadingMoreUsers = true;
socket.emit('api:users.loadMore', {
set: set,
after: $('#users-container').children().length
}, function(data) {
if(data.users.length) {
onUsersLoaded(data.users);
}
loadingMoreUsers = false;
});
}
}
$('#load-more-users-btn').on('click', loadMoreUsers);
$(window).off('scroll').on('scroll', function() {
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
if (document.body.scrollTop > bottom && !loadingMoreUsers) {
loadMoreUsers();
}
});
}); });
}()); }());

@ -122,10 +122,9 @@
} }
$(window).off('scroll').on('scroll', function(ev) { $(window).off('scroll').on('scroll', function(ev) {
var windowHeight = document.body.offsetHeight - $(window).height(), var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
half = windowHeight / 2;
if (document.body.scrollTop > half && !loadingMoreTopics) { if (document.body.scrollTop > bottom && !loadingMoreTopics) {
loadMoreTopics(cid); loadMoreTopics(cid);
} }
}); });

@ -69,10 +69,9 @@
} }
$(window).off('scroll').on('scroll', function() { $(window).off('scroll').on('scroll', function() {
var windowHeight = document.body.offsetHeight - $(window).height(), var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
half = windowHeight / 2;
if (document.body.scrollTop > half && !loadingMoreTopics) { if (document.body.scrollTop > bottom && !loadingMoreTopics) {
loadMoreTopics(); loadMoreTopics();
} }
}); });

@ -202,10 +202,9 @@
// Infinite scrolling of posts // Infinite scrolling of posts
$(window).off('scroll').on('scroll', function() { $(window).off('scroll').on('scroll', function() {
var windowHeight = document.body.offsetHeight - $(window).height(), var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
half = windowHeight / 2;
if (document.body.scrollTop > half && !app.infiniteLoaderActive && $('#post-container').children().length) { if (document.body.scrollTop > bottom && !app.infiniteLoaderActive && $('#post-container').children().length) {
app.loadMorePosts(tid); app.loadMorePosts(tid);
} }
}); });

@ -84,10 +84,9 @@
} }
$(window).off('scroll').on('scroll', function() { $(window).off('scroll').on('scroll', function() {
var windowHeight = document.body.offsetHeight - $(window).height(), var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
half = windowHeight / 2;
if (document.body.scrollTop > half && !loadingMoreTopics) { if (document.body.scrollTop > bottom && !loadingMoreTopics) {
loadMoreTopics(); loadMoreTopics();
} }
}); });

@ -2,6 +2,7 @@
$(document).ready(function() { $(document).ready(function() {
var timeoutId = 0; var timeoutId = 0;
var loadingMoreUsers = false;
var url = window.location.href, var url = window.location.href,
parts = url.split('/'), parts = url.split('/'),
@ -74,6 +75,46 @@
$(element).html(app.addCommas($(element).html())); $(element).html(app.addCommas($(element).html()));
}); });
function onUsersLoaded(users) {
var html = templates.prepare(templates['users'].blocks['users']).parse({ users: users }),
container = $('#users-container');
container.append(html);
}
function loadMoreUsers() {
var set = '';
if(active === 'users-latest' || active === 'users') {
set = 'users:joindate';
} else if(active === 'users-sort-posts') {
set = 'users:postcount';
} else if(active === 'users-sort-reputation') {
set = 'users:reputation';
}
if(set) {
loadingMoreUsers = true;
socket.emit('api:users.loadMore', {
set: set,
after: $('#users-container').children().length
}, function(data) {
if(data.users.length) {
onUsersLoaded(data.users);
}
loadingMoreUsers = false;
});
}
}
$('#load-more-users-btn').on('click', loadMoreUsers);
$(window).off('scroll').on('scroll', function() {
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
if (document.body.scrollTop > bottom && !loadingMoreUsers) {
loadMoreUsers();
}
});
}); });
}()); }());

@ -16,6 +16,7 @@
<hr/> <hr/>
<span>Total Connections Received</span> <span class="text-right">{total_connections_received}</span><br/> <span>Total Connections Received</span> <span class="text-right">{total_connections_received}</span><br/>
<span>Total Commands Processed</span> <span class="text-right">{total_commands_processed}</span><br/> <span>Total Commands Processed</span> <span class="text-right">{total_commands_processed}</span><br/>
<span>Instantaneous Ops. Per Second</span> <span class="text-right">{instantaneous_ops_per_sec}</span><br/>
<hr/> <hr/>
<span>Keyspace Hits</span> <span class="text-right">{keyspace_hits}</span><br/> <span>Keyspace Hits</span> <span class="text-right">{keyspace_hits}</span><br/>
<span>Keyspace Misses</span> <span class="text-right">{keyspace_misses}</span><br/> <span>Keyspace Misses</span> <span class="text-right">{keyspace_misses}</span><br/>

@ -14,7 +14,7 @@
<span id="user-notfound-notify" class="label label-important hide">User not found!</span><br/> <span id="user-notfound-notify" class="label label-important hide">User not found!</span><br/>
</div> </div>
<ul class="users"> <ul id="users-container" class="users">
<!-- BEGIN users --> <!-- BEGIN users -->
<div class="users-box" data-uid="{users.uid}" data-admin="{users.administrator}" data-username="{users.username}"> <div class="users-box" data-uid="{users.uid}" data-admin="{users.administrator}" data-username="{users.username}">
<a href="/users/{users.userslug}"> <a href="/users/{users.userslug}">
@ -41,6 +41,9 @@
<!-- END users --> <!-- END users -->
</ul> </ul>
<div class="text-center {loadmore_display}">
<button id="load-more-users-btn" class="btn">Load More</button>
</div>
<input type="hidden" template-variable="yourid" value="{yourid}" /> <input type="hidden" template-variable="yourid" value="{yourid}" />

@ -14,7 +14,7 @@
<span id="user-notfound-notify" class="label label-important hide">User not found!</span><br/> <span id="user-notfound-notify" class="label label-important hide">User not found!</span><br/>
</div> </div>
<ul class="users"> <ul id="users-container" class="users">
<!-- BEGIN users --> <!-- BEGIN users -->
<div class="users-box"> <div class="users-box">
<a href="/users/{users.userslug}"> <a href="/users/{users.userslug}">
@ -36,4 +36,8 @@
</ul> </ul>
</div> </div>
<div class="text-center {loadmore_display}">
<button id="load-more-users-btn" class="btn">Load More</button>
</div>
<script type="text/javascript" src="{relative_path}/src/forum/users.js"></script> <script type="text/javascript" src="{relative_path}/src/forum/users.js"></script>

@ -28,8 +28,11 @@ var RDB = require('./redis.js'),
RDB.sadd('pid:' + pid + ':users_favourited', uid); RDB.sadd('pid:' + pid + ':users_favourited', uid);
RDB.hincrby('post:' + pid, 'reputation', 1); RDB.hincrby('post:' + pid, 'reputation', 1);
if (uid !== uid_of_poster) if (uid !== uid_of_poster) {
user.incrementUserFieldBy(uid_of_poster, 'reputation', 1); user.incrementUserFieldBy(uid_of_poster, 'reputation', 1, function(err, newreputation) {
RDB.zadd('users:reputation', newreputation, uid_of_poster);
});
}
if (room_id) { if (room_id) {
io.sockets.in(room_id).emit('event:rep_up', {uid: uid !== uid_of_poster ? uid_of_poster : 0, pid: pid}); io.sockets.in(room_id).emit('event:rep_up', {uid: uid !== uid_of_poster ? uid_of_poster : 0, pid: pid});
@ -63,8 +66,11 @@ var RDB = require('./redis.js'),
RDB.srem('pid:' + pid + ':users_favourited', uid); RDB.srem('pid:' + pid + ':users_favourited', uid);
RDB.hincrby('post:' + pid, 'reputation', -1); RDB.hincrby('post:' + pid, 'reputation', -1);
if (uid !== uid_of_poster) if (uid !== uid_of_poster) {
user.incrementUserFieldBy(uid_of_poster, 'reputation', -1); user.incrementUserFieldBy(uid_of_poster, 'reputation', -1, function(err, newreputation) {
RDB.zadd('users:reputation', newreputation, uid_of_poster);
});
}
if (room_id) { if (room_id) {
io.sockets.in(room_id).emit('event:rep_down', {uid: uid !== uid_of_poster ? uid_of_poster : 0, pid: pid}); io.sockets.in(room_id).emit('event:rep_down', {uid: uid !== uid_of_poster ? uid_of_poster : 0, pid: pid});

@ -99,7 +99,9 @@ var RDB = require('./redis.js'),
posts.getPostFields(pid, ['tid', 'uid'], function(postData) { posts.getPostFields(pid, ['tid', 'uid'], function(postData) {
user.decrementUserFieldBy(postData.uid, 'postcount', 1); user.decrementUserFieldBy(postData.uid, 'postcount', 1, function(err, postcount) {
RDB.zadd('users:postcount', postcount, postData.uid);
});
io.sockets.in('topic_' + postData.tid).emit('event:post_deleted', { io.sockets.in('topic_' + postData.tid).emit('event:post_deleted', {
pid: pid pid: pid

@ -64,38 +64,29 @@ var user = require('./../user.js'),
}); });
app.get('/api/admin/users/search', function(req, res) { app.get('/api/admin/users/search', function(req, res) {
res.json({search_display: 'block', users: []}); res.json({search_display: 'block', loadmore_display:'none', users: []});
}); });
app.get('/api/admin/users/latest', function(req, res) { app.get('/api/admin/users/latest', function(req, res) {
user.getUserList(function(data) { user.getUsers('users:joindate', 0, 49, function(err, data) {
data = data.sort(function(a, b) { res.json({ search_display: 'none', loadmore_display:'block', users:data, yourid:req.user.uid });
return b.joindate - a.joindate;
});
res.json({search_display: 'none', users:data, yourid:req.user.uid});
}); });
}); });
app.get('/api/admin/users/sort-posts', function(req, res) { app.get('/api/admin/users/sort-posts', function(req, res) {
user.getUserList(function(data) { user.getUsers('users:postcount', 0, 49, function(err, data) {
data = data.sort(function(a, b) { res.json({ search_display: 'none', loadmore_display:'block', users:data, yourid:req.user.uid });
return b.postcount - a.postcount;
});
res.json({search_display: 'none', users:data, yourid:req.user.uid});
}); });
}); });
app.get('/api/admin/users/sort-reputation', function(req, res) { app.get('/api/admin/users/sort-reputation', function(req, res) {
user.getUserList(function(data) { user.getUsers('users:reputation', 0, 49, function(err, data) {
data = data.sort(function(a, b) { res.json({ search_display: 'none', loadmore_display:'block', users:data, yourid:req.user.uid });
return b.reputation - a.reputation;
});
res.json({search_display: 'none', users:data, yourid:req.user.uid});
}); });
}); });
app.get('/api/admin/users', function(req, res) { app.get('/api/admin/users', function(req, res) {
user.getUserList(function(data) { user.getUsers('users:joindate', 0, 49, function(err, data) {
res.json({ search_display: 'none', users:data, yourid:req.user.uid }); res.json({ search_display: 'none', users:data, yourid:req.user.uid });
}); });
}); });
@ -139,6 +130,9 @@ var user = require('./../user.js'),
for(var i in data) { for(var i in data) {
if(data[i].indexOf(':') == -1 || !data[i])
continue;
try { try {
data[i] = data[i].replace(/:/,"\":\""); data[i] = data[i].replace(/:/,"\":\"");
var json = "{\"" + data[i] + "\"}"; var json = "{\"" + data[i] + "\"}";
@ -148,7 +142,7 @@ var user = require('./../user.js'),
finalData[key] = jsonObject[key]; finalData[key] = jsonObject[key];
} }
} catch(err){ } catch(err){
console.log(err); console.log('invalid redis status', i, data[i], err);
} }
} }

@ -316,49 +316,33 @@ var user = require('./../user.js'),
}); });
}); });
app.get('/api/users', function(req, res) { app.get('/api/users', getUsersSortedByJoinDate);
user.getUserList(function(data) {
data = data.sort(function(a, b) {
return b.joindate - a.joindate;
});
res.json({ search_display: 'none', users: data });
});
});
app.get('/api/users-sort-posts', getUsersSortedByPosts); app.get('/api/users-sort-posts', getUsersSortedByPosts);
app.get('/api/users-sort-reputation', getUsersSortedByReputation); app.get('/api/users-sort-reputation', getUsersSortedByReputation);
app.get('/api/users-latest', getUsersSortedByJoinDate); app.get('/api/users-latest', getUsersSortedByJoinDate);
app.get('/api/users-search', getUsersForSearch); app.get('/api/users-search', getUsersForSearch);
function getUsersSortedByPosts(req, res) {
user.getUserList(function(data) { function getUsersSortedByJoinDate(req, res) {
data = data.sort(function(a, b) { user.getUsers('users:joindate', 0, 49, function(err, data) {
return b.postcount - a.postcount; res.json({ search_display: 'none',loadmore_display:'block', users:data });
});
res.json({ search_display: 'none', users:data });
}); });
} }
function getUsersSortedByReputation(req, res) { function getUsersSortedByPosts(req, res) {
user.getUserList(function(data) { user.getUsers('users:postcount', 0, 49, function(err, data) {
data = data.sort(function(a, b) { res.json({ search_display: 'none',loadmore_display:'block', users:data });
return b.reputation - a.reputation;
});
res.json({ search_display: 'none', users:data });
}); });
} }
function getUsersSortedByJoinDate(req, res) { function getUsersSortedByReputation(req, res) {
user.getUserList(function(data) { user.getUsers('users:reputation', 0, 49, function(err, data) {
data = data.sort(function(a, b) { res.json({ search_display: 'none', loadmore_display:'block', users:data });
return b.joindate - a.joindate;
});
res.json({ search_display: 'none', users:data });
}); });
} }
function getUsersForSearch(req, res) { function getUsersForSearch(req, res) {
res.json({ search_display: 'block', users: [] }); res.json({ search_display: 'block', loadmore_display:'none', users: [] });
} }
function getUserDataByUserSlug(userslug, callerUID, callback) { function getUserDataByUserSlug(userslug, callerUID, callback) {

@ -36,6 +36,19 @@ function upgradeCategory(cid, callback) {
}); });
} }
function upgradeUser(uid, callback) {
RDB.hmgetObject('user:' + uid, ['joindate', 'postcount', 'reputation'], function(err, userData) {
if(err)
return callback(err);
RDB.zadd('users:joindate', userData.joindate, uid);
RDB.zadd('users:postcount', userData.postcount, uid);
RDB.zadd('users:reputation', userData.reputation, uid);
callback(null);
});
}
exports.upgrade = function() { exports.upgrade = function() {
@ -58,7 +71,17 @@ exports.upgrade = function() {
function upgradeUsers(next) { function upgradeUsers(next) {
console.log('upgrading users'); console.log('upgrading users');
RDB.lrange('userlist', 0, -1, function(err, uids) {
async.each(uids, upgradeUser, function(err) {
if(!err)
next(null, 'upgraded users'); next(null, 'upgraded users');
else
next(err, null);
});
});
} }
]; ];

@ -47,6 +47,7 @@ var utils = require('./../public/src/utils.js'),
RDB.handle(err); RDB.handle(err);
var gravatar = User.createGravatarURLFromEmail(email); var gravatar = User.createGravatarURLFromEmail(email);
var timestamp = Date.now();
RDB.hmset('user:'+uid, { RDB.hmset('user:'+uid, {
'uid': uid, 'uid': uid,
@ -58,7 +59,7 @@ var utils = require('./../public/src/utils.js'),
'website':'', 'website':'',
'email' : email || '', 'email' : email || '',
'signature':'', 'signature':'',
'joindate' : Date.now(), 'joindate' : timestamp,
'picture': gravatar, 'picture': gravatar,
'gravatarpicture' : gravatar, 'gravatarpicture' : gravatar,
'uploadedpicture': '', 'uploadedpicture': '',
@ -83,7 +84,9 @@ var utils = require('./../public/src/utils.js'),
io.sockets.emit('user.count', {count: count}); io.sockets.emit('user.count', {count: count});
}); });
RDB.lpush('userlist', uid); RDB.zadd('users:joindate', timestamp, uid);
RDB.zadd('users:postcount', 0, uid);
RDB.zadd('users:reputation', 0, uid);
io.sockets.emit('user.latest', {userslug: userslug, username: username}); io.sockets.emit('user.latest', {userslug: userslug, username: username});
@ -112,7 +115,9 @@ var utils = require('./../public/src/utils.js'),
RDB.del('followers:' + uid); RDB.del('followers:' + uid);
RDB.del('following:' + uid); RDB.del('following:' + uid);
RDB.lrem('userlist', 1, uid); RDB.zrem('users:joindate', uid);
RDB.zrem('users:postcount', uid);
RDB.zrem('users:reputation', uid);
callback(true); callback(true);
}); });
@ -312,20 +317,21 @@ var utils = require('./../public/src/utils.js'),
RDB.hmset('user:' + uid, data); RDB.hmset('user:' + uid, data);
} }
User.incrementUserFieldBy = function(uid, field, value) { User.incrementUserFieldBy = function(uid, field, value, callback) {
RDB.hincrby('user:' + uid, field, value); RDB.hincrby('user:' + uid, field, value, callback);
} }
User.decrementUserFieldBy = function(uid, field, value) { User.decrementUserFieldBy = function(uid, field, value, callback) {
RDB.hincrby('user:' + uid, field, -value); RDB.hincrby('user:' + uid, field, -value, callback);
} }
User.getUserList = function(callback) { User.getUsers = function(set, start, stop, callback) {
var data = []; var data = [];
RDB.lrange('userlist', 0, -1, function(err, uids) { RDB.zrevrange(set, start, stop, function(err, uids) {
if(err) {
RDB.handle(err); return callback(err, null);
}
function iterator(uid, callback) { function iterator(uid, callback) {
User.getUserData(uid, function(userData) { User.getUserData(uid, function(userData) {
@ -336,14 +342,10 @@ var utils = require('./../public/src/utils.js'),
}); });
} }
async.each(uids, iterator, function(err) { async.eachSeries(uids, iterator, function(err) {
if(!err) { callback(err, data);
callback(data);
} else {
console.log(err);
callback(null);
}
}); });
}); });
} }
@ -401,7 +403,10 @@ var utils = require('./../public/src/utils.js'),
User.onNewPostMade = function(uid, tid, pid, timestamp) { User.onNewPostMade = function(uid, tid, pid, timestamp) {
User.addPostIdToUser(uid, pid); User.addPostIdToUser(uid, pid);
User.incrementUserFieldBy(uid, 'postcount', 1); User.incrementUserFieldBy(uid, 'postcount', 1, function(err, newpostcount) {
RDB.zadd('users:postcount', newpostcount, uid);
});
User.setUserField(uid, 'lastposttime', timestamp); User.setUserField(uid, 'lastposttime', timestamp);
User.sendPostNotificationToFollowers(uid, tid, pid); User.sendPostNotificationToFollowers(uid, tid, pid);
@ -602,7 +607,7 @@ var utils = require('./../public/src/utils.js'),
}; };
User.latest = function(socket) { User.latest = function(socket) {
RDB.lrange('userlist', 0, 0, function(err, uid) { RDB.zrevrange('users:joindate', 0, 0, function(err, uid) {
RDB.handle(err); RDB.handle(err);
User.getUserFields(uid, ['username', 'userslug'], function(userData) { User.getUserFields(uid, ['username', 'userslug'], function(userData) {

@ -401,6 +401,7 @@ var express = require('express'),
} }
}); });
}); });
}); });
}(WebServer)); }(WebServer));

@ -657,12 +657,24 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
var start = data.after, var start = data.after,
end = start + 9; end = start + 9;
console.log(start, end);
topics.getUnreadTopics(uid, start, end, function(unreadTopics) { topics.getUnreadTopics(uid, start, end, function(unreadTopics) {
callback(unreadTopics); callback(unreadTopics);
}); });
}); });
socket.on('api:users.loadMore', function(data, callback) {
var start = data.after,
end = start + 19;
user.getUsers(data.set, start, end, function(err, data) {
if(err) {
console.log(err);
} else {
callback({users:data});
}
});
});
socket.on('api:admin.topics.getMore', function(data, callback) { socket.on('api:admin.topics.getMore', function(data, callback) {
topics.getAllTopics(data.limit, data.after, function(topics) { topics.getAllTopics(data.limit, data.after, function(topics) {
callback(JSON.stringify(topics)); callback(JSON.stringify(topics));

Loading…
Cancel
Save