diff --git a/public/language/en/notifications.json b/public/language/en/notifications.json
new file mode 100644
index 0000000000..212cf3fa4f
--- /dev/null
+++ b/public/language/en/notifications.json
@@ -0,0 +1,3 @@
+{
+ "title": "Notifications"
+}
\ No newline at end of file
diff --git a/public/src/forum/notifications.js b/public/src/forum/notifications.js
new file mode 100644
index 0000000000..38bb3c80a2
--- /dev/null
+++ b/public/src/forum/notifications.js
@@ -0,0 +1,16 @@
+define(function() {
+ var Notifications = {};
+
+ Notifications.init = function() {
+ var listEl = $('.notifications-list');
+
+ $('span.timeago').timeago();
+
+ // Allow the user to click anywhere in the LI
+ listEl.on('click', 'li', function(e) {
+ this.querySelector('a').click();
+ });
+ }
+
+ return Notifications;
+});
\ No newline at end of file
diff --git a/public/templates/notifications.tpl b/public/templates/notifications.tpl
new file mode 100644
index 0000000000..d509293009
--- /dev/null
+++ b/public/templates/notifications.tpl
@@ -0,0 +1,14 @@
+
[[notifications:title]]
+
+
+
+
\ No newline at end of file
diff --git a/src/routes/api.js b/src/routes/api.js
index 78823bd9bd..b3c9afde81 100644
--- a/src/routes/api.js
+++ b/src/routes/api.js
@@ -154,6 +154,16 @@ var user = require('./../user.js'),
});
});
+ app.get('/notifications', function(req, res) {
+ if (req.user && req.user.uid) {
+ user.notifications.getAll(req.user.uid, null, null, function(err, notifications) {
+ res.json({
+ notifications: notifications
+ });
+ });
+ } else res.send(403);
+ });
+
app.get('/confirm/:id', function (req, res) {
user.email.confirm(req.params.id, function (data) {
if (data.status === 'ok') {
diff --git a/src/user.js b/src/user.js
index 4b267457e1..9a0092a21f 100644
--- a/src/user.js
+++ b/src/user.js
@@ -945,6 +945,36 @@ var utils = require('./../public/src/utils.js'),
callback(notifications);
});
},
+ getAll: function(uid, limit, before, callback) {
+ var now = new Date();
+
+ if (!limit || parseInt(limit) <= 0) limit = 25;
+ if (before) before = new Date(parseInt(before, 10));
+
+ RDB.multi()
+ .zrevrangebyscore('uid:' + uid + ':notifications:read', before ? before.getTime(): now.getTime(), -Infinity, 'LIMIT', 0, limit)
+ .zrevrangebyscore('uid:' + uid + ':notifications:unread', before ? before.getTime(): now.getTime(), -Infinity, 'LIMIT', 0, limit)
+ .exec(function(err, results) {
+ // Merge the read and unread notifications
+ var nids = results[0].concat(results[1]);
+
+ async.map(nids, function(nid, next) {
+ notifications.get(nid, function(notif_data) {
+ next(null, notif_data);
+ });
+ }, function(err, notifs) {
+ notifs = notifs.sort(function(a, b) {
+ return parseInt(b.datetime, 10) - parseInt(a.datetime, 10);
+ }).map(function(notif) {
+ notif.datetimeISO = new Date(parseInt(notif.datetime, 10)).toISOString();
+
+ return notif;
+ });
+
+ callback(err, notifs);
+ })
+ });
+ },
getUnreadCount: function(uid, callback) {
RDB.zcount('uid:' + uid + ':notifications:unread', 0, 10, callback);
},
diff --git a/src/webserver.js b/src/webserver.js
index 69e8f6803b..78485cb55d 100644
--- a/src/webserver.js
+++ b/src/webserver.js
@@ -282,7 +282,7 @@ var express = require('express'),
// Basic Routes (entirely client-side parsed, goal is to move the rest of the crap in this file into this one section)
(function () {
- var routes = ['login', 'register', 'account', 'recent', 'unread', 'popular', 'active', '403', '404'];
+ var routes = ['login', 'register', 'account', 'recent', 'unread', 'notifications', '403', '404'];
for (var i = 0, ii = routes.length; i < ii; i++) {
(function (route) {