diff --git a/backend/Storage.js b/backend/Storage.js index 62490b6..2fc4247 100644 --- a/backend/Storage.js +++ b/backend/Storage.js @@ -8,15 +8,43 @@ var DB_NAME = 'uwchat', DB_ADDESS = '127.0.0.1', DB_PORT = 27017; +/** + * Inserts document into mongodb + * @param {String} coll_name name of the collection in the database + * @param {Object} data an object literal to insert into the database + */ Storage.save = function(coll_name, data) { - var client = new Db(DB_NAME, new Server(DB_ADDESS, DB_PORT)); + var client = new Db(DB_NAME, new Server(DB_ADDESS, DB_PORT)); - client.open(function(p_client) { - client.collection(coll_name, function(err, collection) { - collection.insert(data, function(err, docs) { - sys.puts('log message ' + JSON.stringify(data) + '.'); - client.close(); - }); + client.open(function(p_client) { + client.collection(coll_name, function(err, collection) { + collection.insert(data, function(err, docs) { + sys.puts('log message ' + JSON.stringify(data) + '.'); + client.close(); + }); + }); + }); +} + +/** + * Gets the most active rooms on UWChat. Does a SQL-like GROUP BY + * query to get the number of messages in the last half hour in each + * existing chat room. + * @param {String} coll_name name of the collection in the database + * @param {Function} callback callback to send document back to + */ +Storage.getActiveRooms = function(coll_name, callback){ + var client = new Db(DB_NAME, new Server(DB_ADDESS, DB_PORT)); + + var SINCE = [300000, 600000, 1800000]; //5, 10, 30 minutes + + client.open(function(p_client) { + client.collection(coll_name, function(err, collection) { + collection.group(['room'], {type: 'msg', timestamp: {$gt : new Date().getTime() - SINCE[2]}}, {sum:0}, function(doc, prev){ prev.sum += 1}, function(err, docs) { + sys.puts('log message ' + JSON.stringify(docs) + '.'); + if(typeof callback == "function") callback(docs); + client.close(); + }); + }); }); - }); } diff --git a/backend/server.js b/backend/server.js index 6fe54d7..8cf8172 100644 --- a/backend/server.js +++ b/backend/server.js @@ -15,7 +15,8 @@ var fu = require("./fu"), ch = require("./Channel"), sys = require("sys"), url = require("url"), - qs = require("querystring"); + qs = require("querystring"), + storage = require('./Storage.js'); var SESSION_TIMEOUT = 60 * 1000; @@ -442,3 +443,12 @@ fu.get("/send", function (req, res) { res.simpleJSON(200, { rss: mem.rss }); }); +fu.get("/activerooms", function (req, res) { + sys.puts('serv: activerooms'); + + storage.getActiveRooms('messages', function(data){ + res.simpleJSON(200, data); + }); + +}); + diff --git a/frontend/css/chat_style.css b/frontend/css/chat_style.css index 9d0b010..f9315d3 100644 --- a/frontend/css/chat_style.css +++ b/frontend/css/chat_style.css @@ -130,7 +130,7 @@ a:hover { text-decoration: underline; color: #aaa; } text-align: center; width: 600px; margin: 0 auto; - margin-top: 200px; + margin-top: 50px; z-index: 3; } @@ -173,3 +173,71 @@ a:hover { text-decoration: underline; color: #aaa; } font-size:0.8em; text-align:center; } + +/* + BUTTONS +*/ +.button{ + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + background: url("/images/button-grey.gif") repeat-x scroll left top #D8D8D8; + border-color: #BBBBBB #BBBBBB #999999; + border-style: solid; + border-width: 1px; + color: #333333; + cursor: pointer; + display: inline; + font-size: 0.6em; + font-weight: bold; + padding: 3px 6px; + text-align: center; + text-shadow: 0 1px #F0F0F0; +} + +.join_button{ + background-color: #C3DD82; + background-image: url("/images/button-green.gif"); + border-bottom: 1px solid #648517; + border-color: #8CB332 #8CB332 #648517; + color: #406A24; + text-shadow: 0 1px #D4ED95; +} + +.join_button:hover{ + border-color: #BBBBBB #BBBBBB #999999; + color: #406A24; +} + + +#activerooms_splash{ + text-align: center; + width: 250px; + margin: 0 auto; + margin-top: 75px; + z-index: 3; +} + +#activerooms_splash > div{ + clear: both; +} + +#activerooms_splash h2{ + font-size: 0.8em; + font-weight: normal; + text-decoration: underline; + margin-bottom: 10px; +} + +#activerooms_splash .no_active_rooms{ + color: grey; + font-size: 0.7em; +} + +#activerooms_splash .room_name{ + float: left; + font-size: 0.8em; +} + +#activerooms_splash .join_button_div { + float: right; +} diff --git a/frontend/images/button-green.gif b/frontend/images/button-green.gif new file mode 100644 index 0000000..fd165fb Binary files /dev/null and b/frontend/images/button-green.gif differ diff --git a/frontend/images/button-grey.gif b/frontend/images/button-grey.gif new file mode 100644 index 0000000..3a9fff4 Binary files /dev/null and b/frontend/images/button-grey.gif differ diff --git a/frontend/index.html b/frontend/index.html index 41f21cd..f1698d9 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -38,7 +38,9 @@
- + +

Active Rooms

+

Room Title

diff --git a/frontend/js/chat_client.js b/frontend/js/chat_client.js index 971d1a8..9b23e96 100644 --- a/frontend/js/chat_client.js +++ b/frontend/js/chat_client.js @@ -276,6 +276,43 @@ function updateUptime () { } } +function updateActiveRooms (data) { + var topRoomsTable = $("#activerooms_splash"), + room, + content = ''; + + if (data.length == 0){ + //No active rooms + topRoomsTable.append("
None
"); + return; + } + //mongodb-native doesn't have a sort function after a + // group query. So we have to sort client side. + data.sort(function(a,b){ return b.sum - a.sum}); + + // What about using Mustache templates instead? + data.forEach(function(obj){ + room = obj.room.length > 21 ? obj.room.substr(0, 20) + "..." : obj.room; + + content += '
' + + '
' + room + '
' + + '
' + + 'Join' + + '
' + + '
'; + }); + + topRoomsTable.append(content); + + $("#activerooms_splash .join_button").click(function(e){ + //Should probably abstract this out later. + var roomName = $(this).attr("data-action"); + $("#nickInput").attr("value", roomName); + $("#connectButton").click(); + }); + +} + var transmission_errors = 0; var first_poll = true; @@ -420,10 +457,17 @@ function showChat (nick) { $("#loading").hide(); $("#example").hide(); + $("#activerooms_splash").hide(); scrollDown(); } +function showActiveRooms () { + jQuery.get("/activerooms", {}, function (data) { + updateActiveRooms(eval("(" + data + ")")); + }); +} + //we want to show a count of unread messages when the window does not have focus function updateTitle(){ if (CONFIG.unread) { @@ -590,6 +634,7 @@ $(document).ready(function() { $("#log table").remove(); showConnect(); + showActiveRooms(); }); //if we can, notify the server that we're going away.