diff --git a/public/src/utils.js b/public/src/utils.js new file mode 100644 index 0000000000..ee5bd73f64 --- /dev/null +++ b/public/src/utils.js @@ -0,0 +1,103 @@ +(function (module) { + + var utils, fs; + + try { + fs = require('fs'); + } catch (e) {} + + + module.exports = utils = { + generateUUID: function() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); + return v.toString(16); + }); + }, + + //Adapted from http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search + walk: function(dir, done) { + var main_dir = global.configuration.ROOT_DIRECTORY + '/public/templates/'; + var results = []; + fs.readdir(dir, function(err, list) { + if (err) return done(err); + var pending = list.length; + if (!pending) return done(null, results); + list.forEach(function(file) { + file = dir + '/' + file; + fs.stat(file, function(err, stat) { + if (stat && stat.isDirectory()) { + utils.walk(file, function(err, res) { + results = results.concat(res); + if (!--pending) done(null, results); + }); + } else { + results.push(file.replace(main_dir, '').replace('.tpl', '')); + if (!--pending) done(null, results); + } + }); + }); + }); + }, + + relativeTime: function(timestamp) { + var now = +new Date(), + difference = now - Math.floor(parseFloat(timestamp)); + + difference = Math.floor(difference / 1000); + + if (difference < 60) return difference + ' second' + (difference !== 1 ? 's' : ''); + + difference = Math.floor(difference / 60); + if (difference < 60) return difference + ' minute' + (difference !== 1 ? 's' : ''); + + difference = Math.floor(difference / 60); + if (difference < 24) return difference + ' hour' + (difference !== 1 ? 's' : ''); + + difference = Math.floor(difference / 24); + if (difference < 30) return difference + ' day' + (difference !== 1 ? 's' : ''); + + difference = Math.floor(difference / 30); + if (difference < 12) return difference + ' month' + (difference !== 1 ? 's' : ''); + + difference = Math.floor(difference / 12); + return difference + ' year' + (difference !== 1 ? 's' : ''); + }, + + //http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/ + slugify: function(str) { + str = str.replace(/^\s+|\s+$/g, ''); // trim + str = str.toLowerCase(); + + // remove accents, swap ñ for n, etc + var from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;"; + var to = "aaaaeeeeiiiioooouuuunc------"; + for (var i=0, l=from.length ; i/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase () + var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, + commentsAndPhpTags = /|<\?(?:php)?[\s\S]*?\?>/gi; + + return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) { + return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : ''; + }); + } + } + + + if ('undefined' !== typeof window) { + window.utils = module.exports; + } + +})('undefined' === typeof module ? {module:{exports:{}}} : module) \ No newline at end of file diff --git a/public/templates/config.json b/public/templates/config.json index 5aad178dd5..8a35b78e0b 100644 --- a/public/templates/config.json +++ b/public/templates/config.json @@ -3,6 +3,13 @@ "admin/topics[^]*": "admin/topics", "admin/categories[^]*": "admin/categories", "admin/users[^]*": "admin/users", + "admin/redis[^]*": "admin/redis", + "admin/index[^]*": "admin/index", + "admin/themes[^]*": "admin/themes", + "admin/settings[^]*": "admin/settings", + "admin/twitter[^]*": "admin/twitter", + "admin/facebook[^]*": "admin/facebook", + "admin/gplus[^]*": "admin/gplus", "users[^]*edit": "accountedit", "users[^]*friends": "friends", "users/[^]*": "account", diff --git a/public/templates/footer.tpl b/public/templates/footer.tpl index 0e917d98a3..272be6477e 100644 --- a/public/templates/footer.tpl +++ b/public/templates/footer.tpl @@ -88,10 +88,11 @@ }, false); // Notifications dropdown - var notifTrigger = document.querySelector('.notifications a'), + var notifContainer = document.getElementsByClassName('notifications')[0], + notifTrigger = notifContainer.querySelector('a'), notifList = document.getElementById('notif-list'); notifTrigger.addEventListener('click', function() { - socket.emit('api:notifications.get'); + if (notifContainer.className.indexOf('open') === -1) socket.emit('api:notifications.get'); }); notifList.addEventListener('click', function(e) { var target; @@ -106,7 +107,6 @@ } }) socket.on('api:notifications.get', function(data) { - console.log(data); var notifFrag = document.createDocumentFragment(), notifEl = document.createElement('li'), numRead = data.read.length, diff --git a/src/categories.js b/src/categories.js index 7ec41b2292..befedd87d6 100644 --- a/src/categories.js +++ b/src/categories.js @@ -1,6 +1,6 @@ var RDB = require('./redis.js'), posts = require('./posts.js'), - utils = require('./utils.js'), + utils = require('./../public/src/utils.js'), user = require('./user.js'), async = require('async'), topics = require('./topics.js'); diff --git a/src/notifications.js b/src/notifications.js index 3880d3df06..98d61d5294 100644 --- a/src/notifications.js +++ b/src/notifications.js @@ -1,6 +1,7 @@ var config = require('../config.js'), RDB = require('./redis.js'), - async = require('async'); + async = require('async'), + utils = require('./utils.js'); (function(Notifications) { Notifications.get = function(nid, callback) { @@ -15,12 +16,17 @@ var config = require('../config.js'), }); } - Notifications.create = function(text, score, path, callback) { + Notifications.create = function(text, score, path, uniqueId, callback) { /* * Score guide: * 0 Low priority messages (probably unused) * 5 Normal messages * 10 High priority messages + * + * uniqueId is used solely to override stale nids. + * If a new nid is pushed to a user and an existing nid in the user's + * (un)read list contains the same uniqueId, it will be removed, and + * the new one put in its place. */ RDB.incr('notifications:next_nid', function(err, nid) { RDB.hmset( @@ -29,6 +35,7 @@ var config = require('../config.js'), 'score', score || 5, 'path', path || null, 'datetime', new Date().getTime(), + 'uniqueId', uniqueId || utils.generateUUID(), function(err, status) { if (status === 'OK') callback(nid); }); diff --git a/src/posts.js b/src/posts.js index 38d269ccc5..23b4524298 100644 --- a/src/posts.js +++ b/src/posts.js @@ -1,5 +1,5 @@ var RDB = require('./redis.js'), - utils = require('./utils.js'), + utils = require('./../public/src/utils.js'), marked = require('marked'), user = require('./user.js'), topics = require('./topics.js'), diff --git a/src/redis.js b/src/redis.js index e03de19fb7..e20413acb4 100644 --- a/src/redis.js +++ b/src/redis.js @@ -4,7 +4,7 @@ redis = require('redis'), config = require('../config.js'), - utils = require('./utils.js'); + utils = require('./../public/src/utils.js'); RedisDB.exports = redis.createClient(config.redis.port, config.redis.host, config.redis.options); diff --git a/src/routes/user.js b/src/routes/user.js index 5ecf0ab27d..213f44275b 100644 --- a/src/routes/user.js +++ b/src/routes/user.js @@ -2,7 +2,7 @@ var user = require('./../user.js'), fs = require('fs'), - utils = require('./../utils.js'), + utils = require('./../../public/src/utils.js'), config = require('../../config.js'), marked = require('marked'); diff --git a/src/topics.js b/src/topics.js index a139797869..bf2cf41d09 100644 --- a/src/topics.js +++ b/src/topics.js @@ -1,6 +1,6 @@ var RDB = require('./redis.js'), posts = require('./posts.js'), - utils = require('./utils.js'), + utils = require('./../public/src/utils.js'), user = require('./user.js'), config = require('../config.js'), categories = require('./categories.js'), diff --git a/src/user.js b/src/user.js index cefd1eab44..a600fbf9e9 100644 --- a/src/user.js +++ b/src/user.js @@ -1,5 +1,5 @@ var config = require('../config.js'), - utils = require('./utils.js'), + utils = require('./../public/src/utils.js'), RDB = require('./redis.js'), crypto = require('crypto'), emailjs = require('emailjs'), diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index 62843ee470..0000000000 --- a/src/utils.js +++ /dev/null @@ -1,91 +0,0 @@ -var fs = require('fs'); - -var utils = { - generateUUID: function() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); - return v.toString(16); - }); - }, - - //Adapted from http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search - walk: function(dir, done) { - var main_dir = global.configuration.ROOT_DIRECTORY + '/public/templates/'; - var results = []; - fs.readdir(dir, function(err, list) { - if (err) return done(err); - var pending = list.length; - if (!pending) return done(null, results); - list.forEach(function(file) { - file = dir + '/' + file; - fs.stat(file, function(err, stat) { - if (stat && stat.isDirectory()) { - utils.walk(file, function(err, res) { - results = results.concat(res); - if (!--pending) done(null, results); - }); - } else { - results.push(file.replace(main_dir, '').replace('.tpl', '')); - if (!--pending) done(null, results); - } - }); - }); - }); - }, - - relativeTime: function(timestamp) { - var now = +new Date(), - difference = now - Math.floor(parseFloat(timestamp)); - - difference = Math.floor(difference / 1000); - - if (difference < 60) return difference + ' second' + (difference !== 1 ? 's' : ''); - - difference = Math.floor(difference / 60); - if (difference < 60) return difference + ' minute' + (difference !== 1 ? 's' : ''); - - difference = Math.floor(difference / 60); - if (difference < 24) return difference + ' hour' + (difference !== 1 ? 's' : ''); - - difference = Math.floor(difference / 24); - if (difference < 30) return difference + ' day' + (difference !== 1 ? 's' : ''); - - difference = Math.floor(difference / 30); - if (difference < 12) return difference + ' month' + (difference !== 1 ? 's' : ''); - - difference = Math.floor(difference / 12); - return difference + ' year' + (difference !== 1 ? 's' : ''); - }, - - //http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/ - slugify: function(str) { - str = str.replace(/^\s+|\s+$/g, ''); // trim - str = str.toLowerCase(); - - // remove accents, swap ñ for n, etc - var from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;"; - var to = "aaaaeeeeiiiioooouuuunc------"; - for (var i=0, l=from.length ; i/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase () - var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, - commentsAndPhpTags = /|<\?(?:php)?[\s\S]*?\?>/gi; - - return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) { - return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : ''; - }); - } -} - -module.exports = utils; \ No newline at end of file diff --git a/src/webserver.js b/src/webserver.js index 4af407527a..c5794fc316 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -7,6 +7,7 @@ var express = require('express'), redis = require('redis'), redisServer = redis.createClient(config.redis.port, config.redis.host, config.redis.options), marked = require('marked'), + utils = require('./../public/src/utils.js'), fs = require('fs'), user = require('./user.js'), @@ -14,7 +15,6 @@ var express = require('express'), posts = require('./posts.js'), topics = require('./topics.js'), notifications = require('./notifications.js'), - utils = require('./utils.js'), admin = require('./routes/admin.js'), userRoute = require('./routes/user.js'), auth = require('./routes/authentication.js');