From daf1a388eb6f2b3442e8b913bedc4a4354113481 Mon Sep 17 00:00:00 2001 From: barisusakli Date: Tue, 14 Jul 2015 17:03:28 -0400 Subject: [PATCH] closes #3039 --- public/language/en_GB/users.json | 9 ++- public/less/admin/general/dashboard.less | 4 ++ public/src/admin/general/dashboard.js | 11 ++-- public/src/app.js | 9 ++- public/src/client/popular.js | 4 +- public/src/client/recent.js | 2 +- public/src/client/topic/browsing.js | 2 +- public/src/client/unread.js | 2 +- public/src/client/users.js | 2 +- src/controllers/users.js | 71 ++++++++++++++++++++++++ src/routes/index.js | 2 + src/socket.io/index.js | 10 +++- src/socket.io/meta.js | 15 ++--- src/socket.io/topics.js | 2 +- src/views/admin/general/dashboard.tpl | 3 +- 15 files changed, 118 insertions(+), 30 deletions(-) diff --git a/public/language/en_GB/users.json b/public/language/en_GB/users.json index 4b6cb8b1c3..5616cda575 100644 --- a/public/language/en_GB/users.json +++ b/public/language/en_GB/users.json @@ -10,5 +10,12 @@ "online-only": "Online only", "picture-only": "Picture only", "invite": "Invite", - "invitation-email-sent": "An invitation email has been sent to %1" + "invitation-email-sent": "An invitation email has been sent to %1", + "user_list": "User List", + "recent_topics": "Recent Topics", + "popular_topics": "Popular Topics", + "unread_topics": "Unread Topics", + "categories": "Categories", + "tags": "Tags", + "map": "Map" } \ No newline at end of file diff --git a/public/less/admin/general/dashboard.less b/public/less/admin/general/dashboard.less index cf44ceb176..c8b704707b 100644 --- a/public/less/admin/general/dashboard.less +++ b/public/less/admin/general/dashboard.less @@ -102,6 +102,10 @@ border-color: #949FB1; background-color: #A8B3C5; } + &.unread { + border-color: #949FB1; + background-color: #9FB194; + } } } } diff --git a/public/src/admin/general/dashboard.js b/public/src/admin/general/dashboard.js index 4802ad5f5d..6c7035f67b 100644 --- a/public/src/admin/general/dashboard.js +++ b/public/src/admin/general/dashboard.js @@ -62,7 +62,7 @@ define('admin/general/dashboard', ['semver'], function(semver) { }); $('[data-toggle="tooltip"]').tooltip(); - + setupRealtimeButton(); setupGraphs(); initiateDashboard(); @@ -237,13 +237,13 @@ define('admin/general/dashboard', ['semver'], function(semver) { value: 1, color: "#949FB1", highlight: "#A8B3C5", - label: "Recent/Unread" + label: "Recent" }, { value: 1, - color: "#4D5360", + color: "#9FB194", highlight: "#A8B3C5", - label: "Other" + label: "Unread" } ], { responsive: true @@ -317,7 +317,8 @@ define('admin/general/dashboard', ['semver'], function(semver) { graphs.presence.segments[1].value = users.topics; graphs.presence.segments[2].value = users.category; graphs.presence.segments[3].value = users.recent; - graphs.presence.segments[4].value = users.other; + graphs.presence.segments[4].value = users.unread; + graphs.presence.update(); } diff --git a/public/src/app.js b/public/src/app.js index ab97649907..9a80125dfa 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -100,9 +100,14 @@ app.cacheBuster = null; case 'category': room = 'category_' + url_parts[1]; break; - case 'recent': // intentional fall-through + case 'recent': + room = 'recent_topics'; + break; case 'unread': - room = 'recent_posts'; + room = 'unread_topics'; + break; + case 'popular': + room = 'popular_topics'; break; case 'admin': room = 'admin'; diff --git a/public/src/client/popular.js b/public/src/client/popular.js index 0d05186faf..6331df49a6 100644 --- a/public/src/client/popular.js +++ b/public/src/client/popular.js @@ -2,11 +2,11 @@ /* globals define, app, socket*/ -define('forum/popular', ['forum/recent'], function(recent) { +define('forum/popular', function() { var Popular = {}; Popular.init = function() { - app.enterRoom('recent_posts'); + app.enterRoom('popular_topics'); selectActivePill(); }; diff --git a/public/src/client/recent.js b/public/src/client/recent.js index fc55ee9b08..3468fba152 100644 --- a/public/src/client/recent.js +++ b/public/src/client/recent.js @@ -15,7 +15,7 @@ define('forum/recent', ['forum/infinitescroll', 'components'], function(infinite }); Recent.init = function() { - app.enterRoom('recent_posts'); + app.enterRoom('recent_topics'); Recent.watchForNewPosts(); diff --git a/public/src/client/topic/browsing.js b/public/src/client/topic/browsing.js index ab38baefe8..0bed58f952 100644 --- a/public/src/client/topic/browsing.js +++ b/public/src/client/topic/browsing.js @@ -15,7 +15,7 @@ define('forum/topic/browsing', ['translator'], function(translator) { addUserIcon(data.users[i]); } - updateUserCount(data.total); + updateUserCount(data.hidden); } }; diff --git a/public/src/client/unread.js b/public/src/client/unread.js index bd6c67f279..47b96e54ad 100644 --- a/public/src/client/unread.js +++ b/public/src/client/unread.js @@ -12,7 +12,7 @@ define('forum/unread', ['forum/recent', 'topicSelect', 'forum/infinitescroll', ' }); Unread.init = function() { - app.enterRoom('recent_posts'); + app.enterRoom('unread_topics'); $('#new-topics-alert').on('click', function() { $(this).addClass('hide'); diff --git a/public/src/client/users.js b/public/src/client/users.js index 35e56dc30a..e0d4166a49 100644 --- a/public/src/client/users.js +++ b/public/src/client/users.js @@ -8,7 +8,7 @@ define('forum/users', ['translator'], function(translator) { var loadingMoreUsers = false; Users.init = function() { - + app.enterRoom('user_list'); var active = getActiveSection(); $('.nav-pills li').removeClass('active'); diff --git a/src/controllers/users.js b/src/controllers/users.js index e2298ade29..8fb9abc4af 100644 --- a/src/controllers/users.js +++ b/src/controllers/users.js @@ -3,8 +3,12 @@ var usersController = {}; var async = require('async'), + validator = require('validator'), + user = require('../user'), meta = require('../meta'), + categories = require('../categories'), + topics = require('../topics'), pagination = require('../pagination'), plugins = require('../plugins'), db = require('../database'), @@ -117,6 +121,73 @@ usersController.getUsersForSearch = function(req, res, next) { }); }; +usersController.getMap = function(req, res, next) { + var socketIO = require('../socket.io'); + var rooms = require('../socket.io/rooms'); + + var roomNames = ['user_list', 'categories', 'unread_topics', 'recent_topics', 'popular_topics', 'tags']; + var links = { + user_list: '/users', + categories: '/categories', + unread_topics: '/unread', + recent_topics: '/recent', + popular_topics: '/popular', + tags: '/tags' + }; + + var keys = Object.keys(rooms.roomClients()); + + keys = keys.filter(function(key) { + return key.startsWith('topic_') || key.startsWith('category_'); + }); + + roomNames = roomNames.concat(keys); + + async.map(roomNames, function(roomName, next) { + socketIO.getUsersInRoom(0, roomName, 0, 39, function(err, data) { + if (err) { + return next(err); + } + + if (roomName.startsWith('category_')) { + var cid = roomName.split('_')[1]; + categories.getCategoryFields(cid, ['slug', 'name'], function(err, categoryData) { + if (err) { + return next(err); + } + data.room = validator.escape(categoryData.name); + data.link = '/category/' + categoryData.slug; + next(null, data); + }); + } else if (roomName.startsWith('topic_')) { + var tid = roomName.split('_')[1]; + topics.getTopicFields(tid, ['slug', 'title'], function(err, topicData) { + if (err) { + return next(err); + } + data.room = validator.escape(topicData.title); + data.link = '/topic/' + topicData.slug; + next(null, data); + }); + } else { + next(null, data); + } + }); + }, function(err, data) { + data.sort(function(a, b) { + return b.total - a.total; + }); + + data.forEach(function(room) { + if (!room.link) { + room.link = links[room.room]; + } + }); + + res.render('usersMap', {names: roomNames, rooms: data}); + }); +}; + function render(req, res, data, next) { plugins.fireHook('filter:users.build', {req: req, res: res, templateData: data}, function(err, data) { if (err) { diff --git a/src/routes/index.js b/src/routes/index.js index 1c5b046b9f..4935edc372 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -84,8 +84,10 @@ function userRoutes(app, middleware, controllers) { setupPageRoute(app, '/users/sort-reputation', middleware, middlewares, controllers.users.getUsersSortedByReputation); setupPageRoute(app, '/users/latest', middleware, middlewares, controllers.users.getUsersSortedByJoinDate); setupPageRoute(app, '/users/search', middleware, middlewares, controllers.users.getUsersForSearch); + setupPageRoute(app, '/users/map', middleware, middlewares, controllers.users.getMap); } + function groupRoutes(app, middleware, controllers) { var middlewares = [middleware.checkGlobalPrivacySettings, middleware.exposeGroupName]; diff --git a/src/socket.io/index.js b/src/socket.io/index.js index a2cc3a241e..bb62133212 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -260,14 +260,17 @@ Sockets.isUsersOnline = function(uids, callback) { callback(null, uids.map(Sockets.isUserOnline)); }; -Sockets.getUsersInRoom = function (uid, roomName, callback) { +Sockets.getUsersInRoom = function (uid, roomName, start, stop, callback) { if (!roomName) { return; } var uids = Sockets.getUidsInRoom(roomName); var total = uids.length; - uids = uids.slice(0, 9); + if (stop !== -1) { + uids = uids.slice(start, stop); + } + if (uid && uids.indexOf(uid.toString()) === -1) { uids = [uid].concat(uids); } @@ -287,7 +290,8 @@ Sockets.getUsersInRoom = function (uid, roomName, callback) { callback(null, { users: users, room: roomName, - total: Math.max(0, total - uids.length) + total: total, + hidden: Math.max(0, total - uids.length) }); }); }; diff --git a/src/socket.io/meta.js b/src/socket.io/meta.js index 018ecc64ce..1e1843a1ca 100644 --- a/src/socket.io/meta.js +++ b/src/socket.io/meta.js @@ -94,10 +94,11 @@ SocketMeta.rooms.getAll = function(socket, data, callback) { socketCount: websockets.getSocketCount(), users: { categories: roomClients.categories ? roomClients.categories.length : 0, - recent: roomClients.recent_posts ? roomClients.recent_posts.length : 0, + recent: roomClients.recent_topics ? roomClients.recent_topics.length : 0, + unread: roomClients.unread_topics ? roomClients.unread_topics.length: 0, + popular: roomClients.popular_topics ? roomClients.popular_topics.length: 0, topics: 0, - category: 0, - other: 0 + category: 0 }, topics: {} }; @@ -124,14 +125,6 @@ SocketMeta.rooms.getAll = function(socket, data, callback) { } } - for (var i in socketData.users) { - if (socketData.users.hasOwnProperty(i)) { - socketData.users.other -= socketData.users[i]; - } - } - - socketData.users.other += roomClients['online_users'].length; - var scoreKeys = Object.keys(scores), mostActive = scoreKeys.sort(); diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js index 1de512d62e..6e9cafcf63 100644 --- a/src/socket.io/topics.js +++ b/src/socket.io/topics.js @@ -85,7 +85,7 @@ SocketTopics.enter = function(socket, tid, callback) { SocketTopics.markAsRead(socket, [tid], next); }, users: function(next) { - websockets.getUsersInRoom(socket.uid, 'topic_' + tid, next); + websockets.getUsersInRoom(socket.uid, 'topic_' + tid, 0, 9, next); } }, function(err, result) { callback(err, result ? result.users : null); diff --git a/src/views/admin/general/dashboard.tpl b/src/views/admin/general/dashboard.tpl index be60e68975..3aa18f8867 100644 --- a/src/views/admin/general/dashboard.tpl +++ b/src/views/admin/general/dashboard.tpl @@ -128,7 +128,8 @@
  • On categories list
  • Reading posts
  • Browsing topics
  • -
  • Recent / Unread
  • +
  • Recent
  • +
  • Unread