{posts.content}
- + + {../user.username} + +{posts.content}
+ +You are up-to-date
'); } else if (semver.gt(latestVersion, version)) { checkEl.removeClass('alert-info').addClass('alert-danger'); - checkEl.append('A new version (v' + latestVersion + ') has been released. Consider upgrading your NodeBB.
'); - } else if (semver.gt(version, latestVersion)) { - checkEl.removeClass('alert-info').addClass('alert-warning'); - checkEl.append('You are running a development version! Unintended bugs may occur.
'); + checkEl.append('A new version (v' + latestVersion + ') has been released. Consider upgrading your NodeBB.
'); } }); @@ -319,7 +316,6 @@ define('admin/general/dashboard', ['semver'], function(semver) { if (JSON.stringify(graphData.traffic) === JSON.stringify(data)) { return; } - console.log(data); graphData.traffic = data; @@ -332,6 +328,13 @@ define('admin/general/dashboard', ['semver'], function(semver) { graphs.traffic.scale.xLabels = getDaysArray(until); } else { graphs.traffic.scale.xLabels = getHoursArray(); + + $('#pageViewsThisMonth').html(data.monthlyPageViews.thisMonth); + $('#pageViewsLastMonth').html(data.monthlyPageViews.lastMonth); + $('#pageViewsPastDay').html(data.pastDay); + utils.addCommasToNumbers($('#pageViewsThisMonth')); + utils.addCommasToNumbers($('#pageViewsLastMonth')); + utils.addCommasToNumbers($('#pageViewsPastDay')); } for (var i = 0, ii = data.pageviews.length; i < ii; i++) { @@ -349,13 +352,6 @@ define('admin/general/dashboard', ['semver'], function(semver) { graphs.traffic.update(); currentGraph.units = units; currentGraph.until = until; - - $('#pageViewsThisMonth').html(data.monthlyPageViews.thisMonth); - $('#pageViewsLastMonth').html(data.monthlyPageViews.lastMonth); - $('#pageViewsPastDay').html(data.pastDay); - utils.addCommasToNumbers($('#pageViewsThisMonth')); - utils.addCommasToNumbers($('#pageViewsLastMonth')); - utils.addCommasToNumbers($('#pageViewsPastDay')); }); } diff --git a/public/src/admin/manage/flags.js b/public/src/admin/manage/flags.js index a7943784af..b76ccf1708 100644 --- a/public/src/admin/manage/flags.js +++ b/public/src/admin/manage/flags.js @@ -40,7 +40,7 @@ define('admin/manage/flags', [ return app.alertError(err.message); } - $('.post-container').empty().text('No flagged posts!'); + ajaxify.refresh(); }); }); } diff --git a/public/src/admin/manage/users.js b/public/src/admin/manage/users.js index ece62335cc..b59543d035 100644 --- a/public/src/admin/manage/users.js +++ b/public/src/admin/manage/users.js @@ -1,11 +1,9 @@ "use strict"; -/* global config, socket, define, templates, bootbox, app, ajaxify, */ +/* global config, socket, define, templates, bootbox, app, ajaxify */ define('admin/manage/users', ['admin/modules/selectable'], function(selectable) { var Users = {}; Users.init = function() { - var yourid = ajaxify.data.yourid; - selectable.enable('#users-container', '.user-selectable'); function getSelectedUids() { @@ -94,7 +92,7 @@ define('admin/manage/users', ['admin/modules/selectable'], function(selectable) return; } - if (uids.indexOf(yourid) !== -1) { + if (uids.indexOf(app.user.uid.toString()) !== -1) { app.alertError('You can\'t remove yourself as Administrator!'); } else { socket.emit('admin.user.makeAdmins', uids, done('User(s) are now administrators.', '.administrator', true)); @@ -108,7 +106,7 @@ define('admin/manage/users', ['admin/modules/selectable'], function(selectable) return; } - if (uids.indexOf(yourid.toString()) !== -1) { + if (uids.indexOf(app.user.uid.toString()) !== -1) { app.alertError('You can\'t remove yourself as Administrator!'); } else { bootbox.confirm('Do you really want to remove admins?', function(confirm) { diff --git a/public/src/client/chats.js b/public/src/client/chats.js index f32ec38378..437c97978c 100644 --- a/public/src/client/chats.js +++ b/public/src/client/chats.js @@ -38,13 +38,8 @@ define('forum/chats', ['components', 'string', 'sounds', 'forum/infinitescroll', }; Chats.addEventListeners = function() { - $('.chats-list').on('click', 'li', function(e) { - var env = utils.findBootstrapEnvironment(); - if (env === 'xs' || env === 'sm') { - app.openChat($(this).attr('data-username'), $(this).attr('data-uid')); - } else { - Chats.switchChat(parseInt($(this).attr('data-uid'), 10), $(this).attr('data-username')); - } + components.get('chat/recent').on('click', 'li', function(e) { + Chats.switchChat(parseInt($(this).attr('data-uid'), 10), $(this).attr('data-username')); }); Chats.addSendHandlers(Chats.getRecipientUid(), $('.chat-input'), $('.expanded-chat button[data-action="send"]')); diff --git a/public/src/client/topic/postTools.js b/public/src/client/topic/postTools.js index 423637e21e..6be1fce55d 100644 --- a/public/src/client/topic/postTools.js +++ b/public/src/client/topic/postTools.js @@ -268,6 +268,11 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator function showVotes(pid) { socket.emit('posts.getVoters', {pid: pid, cid: ajaxify.data.cid}, function(err, data) { if (err) { + if (err.message === '[[error:no-privileges]]') { + return; + } + + // Only show error if it's an unexpected error. return app.alertError(err.message); } diff --git a/public/src/installer/install.js b/public/src/installer/install.js index 56645f0301..f7224fb71a 100644 --- a/public/src/installer/install.js +++ b/public/src/installer/install.js @@ -115,7 +115,7 @@ $('document').ready(function() { $.post('/launch', function() { setInterval(function() { - $.get('/admin', function(data) { + $.get('/admin').done(function(data) { window.location = 'admin'; }); }, 750); diff --git a/public/src/modules/chat.js b/public/src/modules/chat.js index b2613a2e8a..a9363836cd 100644 --- a/public/src/modules/chat.js +++ b/public/src/modules/chat.js @@ -19,11 +19,6 @@ define('chat', ['components', 'taskbar', 'string', 'sounds', 'forum/chats', 'tra }); socket.on('event:chats.receive', function(data) { - if (ajaxify.currentPage.slice(0, 6) === 'chats/') { - // User is on the chats page, so do nothing (src/forum/chats.js will handle it) - return; - } - var username = data.message.fromUser.username; var isSelf = parseInt(data.message.fromUser.uid, 10) === parseInt(app.user.uid, 10); data.message.self = data.self; diff --git a/src/controllers/index.js b/src/controllers/index.js index f418c16572..fa414e1db5 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -50,7 +50,16 @@ Controllers.home = function(req, res, next) { } else if (route === 'popular') { Controllers.popular.get(req, res, next); } else { - res.redirect(route); + var match = /^category\/(\d+)\/(.*)$/.exec(route); + + if (match) { + req.params.topic_index = "1"; + req.params.category_id = match[1]; + req.params.slug = match[2]; + Controllers.categories.get(req, res, next); + } else { + res.redirect(route); + } } } }); diff --git a/src/emailer.js b/src/emailer.js index d63aa1bb7e..449bdf9e9b 100644 --- a/src/emailer.js +++ b/src/emailer.js @@ -14,13 +14,26 @@ var async = require('async'), translator = require('../public/src/modules/translator'), transports = { - direct: nodemailer.createTransport('direct') + direct: nodemailer.createTransport('direct'), + gmail: undefined }, app; (function(Emailer) { Emailer.registerApp = function(expressApp) { app = expressApp; + + // Enable Gmail transport if enabled in ACP + if (parseInt(meta.config['email:GmailTransport:enabled'], 10) === 1) { + transports.gmail = nodemailer.createTransport('SMTP', { + service: 'Gmail', + auth: { + user: meta.config['email:GmailTransport:user'], + pass: meta.config['email:GmailTransport:pass'] + } + }); + } + return Emailer; }; @@ -101,7 +114,8 @@ var async = require('async'), data.text = data.plaintext; delete data.plaintext; - transports.direct.sendMail(data, callback); + winston.verbose('[emailer] Sending email to uid ' + data.uid); + transports[transports.gmail ? 'gmail' : 'direct'].sendMail(data, callback); }; function render(tpl, params, next) { diff --git a/src/meta/js.js b/src/meta/js.js index 75b82c856a..936d1da988 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -129,7 +129,7 @@ module.exports = function(Meta) { * Check if the parent process is running with the debug option --debug (or --debug-brk) */ var forkProcessParams = {}; - if(global.v8debug) { + if(global.v8debug || process.execArgv.indexOf('--debug') != -1) { /** * use the line below if you want to debug minifier.js script too (or even --debug-brk option, but * you'll have to setup your debugger and connect to the forked process) diff --git a/src/middleware/middleware.js b/src/middleware/middleware.js index e2c5747ab6..059e2229d0 100644 --- a/src/middleware/middleware.js +++ b/src/middleware/middleware.js @@ -222,7 +222,7 @@ middleware.privateUploads = function(req, res, next) { middleware.busyCheck = function(req, res, next) { if (global.env === 'production' && (!meta.config.hasOwnProperty('eventLoopCheckEnabled') || parseInt(meta.config.eventLoopCheckEnabled, 10) === 1) && toobusy()) { - res.type('text/html').sendFile(path.join(__dirname, '../../public/503.html')); + res.status(503).type('text/html').sendFile(path.join(__dirname, '../../public/503.html')); } else { next(); } diff --git a/src/posts/parse.js b/src/posts/parse.js index 4d18f9dd7f..4317f024b3 100644 --- a/src/posts/parse.js +++ b/src/posts/parse.js @@ -9,9 +9,8 @@ module.exports = function(Posts) { Posts.parsePost = function(postData, callback) { postData.content = postData.content || ''; - var cachedContent = cache.get(postData.pid); - if (cachedContent) { - postData.content = cachedContent; + if (postData.pid && cache.has(postData.pid)) { + postData.content = cache.get(postData.pid); return callback(null, postData); } @@ -38,4 +37,4 @@ module.exports = function(Posts) { plugins.fireHook('filter:parse.signature', {userData: userData, uid: uid}, callback); }; -}; \ No newline at end of file +}; diff --git a/src/reset.js b/src/reset.js index 55559696bf..ce1b585a01 100644 --- a/src/reset.js +++ b/src/reset.js @@ -2,6 +2,7 @@ var winston = require('winston'); var nconf = require('nconf'); +var async = require('async'); var db = require('./database'); var Reset = {}; @@ -81,11 +82,29 @@ function resetThemes(callback) { } function resetPlugin(pluginId) { - db.sortedSetRemove('plugins:active', pluginId, function(err) { + var active = false; + + async.waterfall([ + async.apply(db.isSortedSetMember, 'plugins:active', pluginId), + function(isMember, next) { + active = isMember; + + if (isMember) { + db.sortedSetRemove('plugins:active', pluginId, next); + } else { + next(); + } + } + ], function(err) { if (err) { winston.error('[reset] Could not disable plugin: %s encountered error %s', pluginId, err.message); } else { - winston.info('[reset] Plugin `%s` disabled', pluginId); + if (active) { + winston.info('[reset] Plugin `%s` disabled', pluginId); + } else { + winston.warn('[reset] Plugin `%s` was not active on this forum', pluginId); + winston.info('[reset] No action taken.'); + } } process.exit(); diff --git a/src/user/email.js b/src/user/email.js index 9a1dfde805..4f2361c0f7 100644 --- a/src/user/email.js +++ b/src/user/email.js @@ -32,7 +32,7 @@ var async = require('async'), var confirm_code = utils.generateUUID(), confirm_link = nconf.get('url') + '/confirm/' + confirm_code; - var emailInterval = 10; + var emailInterval = meta.config.hasOwnProperty('emailConfirmInterval') ? parseInt(meta.config.emailConfirmInterval, 10) : 10; async.waterfall([ function(next) { diff --git a/src/views/admin/advanced/events.tpl b/src/views/admin/advanced/events.tpl index 747f9e03db..eb43eaa824 100644 --- a/src/views/admin/advanced/events.tpl +++ b/src/views/admin/advanced/events.tpl @@ -10,9 +10,16 @@{events.jsonString}
{posts.content}
- + + {../user.username} + +{posts.content}
+ ++++ +
+- + + +
+ ++ + + + {../user.username} + : "{../reason}" +