diff --git a/public/src/forum/admin/index.js b/public/src/forum/admin/index.js index 01e3f8ddd8..b693238a48 100644 --- a/public/src/forum/admin/index.js +++ b/public/src/forum/admin/index.js @@ -5,7 +5,6 @@ define('forum/admin/index', ['semver'], function(semver) { var Admin = {}; var updateIntervalId = 0; Admin.init = function() { - app.enterRoom('admin'); socket.emit('meta.rooms.getAll', Admin.updateRoomUsage); @@ -99,6 +98,8 @@ define('forum/admin/index', ['semver'], function(semver) { } }); }); + + setupGraphs(); }; Admin.updateRoomUsage = function(err, data) { @@ -114,5 +115,68 @@ define('forum/admin/index', ['semver'], function(semver) { $('#active_users').html(html); }; + var graphs = { + traffic: null + }; + + function setupGraphs() { + var canvas = document.getElementById('analytics-traffic'), + ctx = canvas.getContext('2d'); + + + var currentHour = new Date().getHours(), + labels = []; + + for (var i = currentHour, ii = currentHour - 12; i > ii; i--) { + var hour = i < 0 ? 24 + i : i; + labels.push(hour + ':00 PM'); + } + + labels.reverse(); + + var data = { + labels: labels, + datasets: [ + { + label: "Page Views", + fillColor: "rgba(220,220,220,0.2)", + strokeColor: "rgba(220,220,220,1)", + pointColor: "rgba(220,220,220,1)", + pointStrokeColor: "#fff", + pointHighlightFill: "#fff", + pointHighlightStroke: "rgba(220,220,220,1)", + data: [0,0,0,0,0,0,0,0,0,0,0,0] + }, + { + label: "Unique Visitors", + fillColor: "rgba(151,187,205,0.2)", + strokeColor: "rgba(151,187,205,1)", + pointColor: "rgba(151,187,205,1)", + pointStrokeColor: "#fff", + pointHighlightFill: "#fff", + pointHighlightStroke: "rgba(151,187,205,1)", + data: [0,0,0,0,0,0,0,0,0,0,0,0] + } + ] + }; + + canvas.width = $(canvas).parent().width(); + graphs.traffic = new Chart(ctx).Line(data); + + setInterval(updateTrafficGraph, 15000); + updateTrafficGraph(); + } + + function updateTrafficGraph() { + socket.emit('admin.analytics.get', {graph: "traffic"}, function (err, data) { + for (var i = 0, ii = data.pageviews.length; i < ii; i++) { + graphs.traffic.datasets[0].points[i].value = data.pageviews[i]; + graphs.traffic.datasets[1].points[i].value = data.uniqueVisitors[i]; + } + + graphs.traffic.update(); + }); + } + return Admin; }); diff --git a/src/middleware/middleware.js b/src/middleware/middleware.js index a0e688aff5..11c6e85c0b 100644 --- a/src/middleware/middleware.js +++ b/src/middleware/middleware.js @@ -50,12 +50,9 @@ middleware.updateLastOnlineTime = function(req, res, next) { middleware.incrementPageViews = function(req, res, next) { var today = new Date(); - - today.setDate(today.getDate()); today.setHours(today.getHours(), 0, 0, 0); - - db.sortedSetIncrBy('analytics:pageviews', 1, today.getTime()); + db.sortedSetIncrBy('analytics:pageviews', 1, today.getTime()); next(); }; diff --git a/src/socket.io/admin.js b/src/socket.io/admin.js index aaecf9ad5d..21efa75ba7 100644 --- a/src/socket.io/admin.js +++ b/src/socket.io/admin.js @@ -26,7 +26,8 @@ var groups = require('../groups'), widgets: {}, config: {}, settings: {}, - email: {} + email: {}, + analytics: {} }; SocketAdmin.before = function(socket, method, next) { @@ -149,4 +150,61 @@ SocketAdmin.email.test = function(socket, data, callback) { } }; +SocketAdmin.analytics.get = function(socket, data, callback) { + data.units = 'hours'; // temp + data.amount = 12; + + if (data && data.graph && data.units && data.amount) { + if (data.graph === 'traffic') { + async.parallel({ + uniqueVisitors: function(next) { + getHourlyStatsForSet('ip:recent', data.amount, next); + }, + pageviews: function(next) { + getHourlyStatsForSet('analytics:pageviews', data.amount, next); + } + }, callback); + } + } else { + callback(new Error('Invalid analytics call')); + } +}; + +function getHourlyStatsForSet(set, hours, callback) { + var hour = new Date(), + terms = {}, + hoursArr = []; + + hour.setHours(hour.getHours(), 0, 0, 0); + + for (var i = 0, ii = hours; i < ii; i++) { + hoursArr.push(hour.getTime()); + hour.setHours(hour.getHours() - 1, 0, 0, 0); + } + + async.each(hoursArr, function(term, next) { + if (set.indexOf('analytics') !== -1) { + db.sortedSetScore(set, term, function(err, count) { + terms[term] = count || 0; + next(err); + }); + } else { + db.sortedSetCount(set, term, Date.now(), function(err, count) { + terms[term] = count || 0; + next(err); + }); + } + + }, function(err) { + var termsArr = []; + + hoursArr.reverse(); + hoursArr.forEach(function(hour, idx) { + termsArr.push(terms[hour]); + }); + + callback(err, termsArr); + }); +} + module.exports = SocketAdmin; diff --git a/src/views/admin/header.tpl b/src/views/admin/header.tpl index f909efe83a..68c78d1f12 100644 --- a/src/views/admin/header.tpl +++ b/src/views/admin/header.tpl @@ -20,13 +20,13 @@ + -