diff --git a/README.md b/README.md index ab02209c57..b45429cdf8 100644 --- a/README.md +++ b/README.md @@ -38,38 +38,7 @@ NodeBB requires the following software to be installed: ## Installation -First, we install our base software stack: - - # apt-get install git nodejs redis-server build-essential imagemagick - -If you want to use MongoDB instead of Redis install it from http://www.mongodb.org/downloads and remove 'redis-server' from the above command. [MongoDB-Setup](https://github.com/designcreateplay/NodeBB/wiki/Installing-NodeBB-With-MongoDB) - -**If your package manager only installed a version of Node.js that is less than 0.8 (e.g. Ubuntu 12.10, 13.04):** - - # add-apt-repository ppa:chris-lea/node.js - # apt-get update && apt-get dist-upgrade - -Next, clone this repository: - - $ cd /path/to/nodebb/install/location - $ git clone git://github.com/designcreateplay/NodeBB.git nodebb - -Obtain all of the dependencies required by NodeBB: - - $ cd nodebb - $ npm install - -Initiate the setup script by running the app with the `--setup` flag: - - $ ./nodebb setup - -The default settings are for a local server running on the default port, with a redis store on the same machine/port. - -Lastly, we run the forum. - - $ ./nodebb start - -NodeBB can also be started with helper programs, such as `supervisor` and `forever`. [Take a look at the options here](https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB). +[Please refer to platform-specific installation documentation](https://github.com/designcreateplay/NodeBB/wiki#wiki-installing-nodebb) ## Securing NodeBB diff --git a/mocks/databasemock.js b/mocks/databasemock.js index 89e5f850e7..7a2a11ca60 100644 --- a/mocks/databasemock.js +++ b/mocks/databasemock.js @@ -55,23 +55,29 @@ nconf.set(dbType, testDbConfig); - db = require('../src/database'); + var db = require('../src/database'), + meta = require('../src/meta'); + before(function(done) { db.init(function(err) { //Clean up db.flushdb(function(err) { - if(err){ + if(err) { winston.error(err); throw new Error(err); - } else { - winston.info('test_database flushed'); - done(); } - //TODO: data seeding, if needed at all + winston.info('test_database flushed'); + meta.configs.init(function () { + var webserver = require('../src/webserver'), + sockets = require('../src/socket.io'); + sockets.init(webserver.server); + + done(); + }); }); }); }); diff --git a/public/src/forum/accountedit.js b/public/src/forum/accountedit.js index 13bab6cf9d..207785e846 100644 --- a/public/src/forum/accountedit.js +++ b/public/src/forum/accountedit.js @@ -189,8 +189,7 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) { password_confirm.on('blur', onPasswordConfirmChanged); $('#changePasswordBtn').on('click', function() { - - if (passwordvalid && passwordsmatch && (currentPassword.val() || app.isAdmin)) { + if ((passwordvalid && passwordsmatch) || app.isAdmin) { socket.emit('user.changePassword', { 'currentPassword': currentPassword.val(), 'newPassword': password.val(), diff --git a/public/src/forum/login.js b/public/src/forum/login.js index 11afd12cdc..de0defd54a 100644 --- a/public/src/forum/login.js +++ b/public/src/forum/login.js @@ -52,7 +52,7 @@ define(function() { return false; }); - $('#content input').focus(); + $('#content #username').focus(); }; return Login; diff --git a/public/src/forum/search.js b/public/src/forum/search.js index 3d3c72389e..e6cdcca11e 100644 --- a/public/src/forum/search.js +++ b/public/src/forum/search.js @@ -5,10 +5,12 @@ define(function() { var searchQuery = $('#topic-results').attr('data-search-query'); $('.search-result-text').each(function() { - var text = $(this).html(); + var result = $(this); + var text = result.html(); var regex = new RegExp(searchQuery, 'gi'); text = text.replace(regex, '' + searchQuery + ''); - $(this).html(text); + result.html(text); + result.find('img').addClass('img-responsive'); }); $('#search-form input').val(searchQuery); diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js index 6383cac823..6ccb865b07 100644 --- a/public/src/forum/topic.js +++ b/public/src/forum/topic.js @@ -622,7 +622,7 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { socket.on('get_users_in_room', function(data) { if(data && data.room.indexOf('topic') !== -1) { - var activeEl = $('li.post-bar[data-index="0"] .thread_active_users'); + var activeEl = $('.thread_active_users'); function createUserIcon(uid, picture, userslug, username) { if(!activeEl.find('[data-uid="' + uid + '"]').length) { @@ -694,11 +694,9 @@ define(['composer', 'forum/pagination'], function(composer, pagination) { // Get users who are currently replying to the topic entered socket.emit('modules.composer.getUsersByTid', templates.get('topic_id'), function(err, uids) { - var activeUsersEl = $('.thread_active_users'), - x; if (uids && uids.length) { for(var x=0;x + + + +
+ + + +
+ + +
+
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ + + +
+
+ +
+
+ +
+
+
+
+ +
+ disabled> +
+
+ +
+ +
+ + + + +
+
+ +
+ +
+ + + + +
+
+
+ + +
+
+
+ +
+
+ + + + + diff --git a/public/templates/header.tpl b/public/templates/header.tpl new file mode 100644 index 0000000000..25a5da4c57 --- /dev/null +++ b/public/templates/header.tpl @@ -0,0 +1,218 @@ + + + + {browserTitle} + + name="{metaTags.name}" property="{metaTags.property}" content="{metaTags.content}" /> + + + + + + link="{linkTags.link}" rel="{linkTags.rel}" type="{linkTags.type}" href="{linkTags.href}" /> + + + + + + + + + + + + + + + + + + + + +
diff --git a/public/templates/search.tpl b/public/templates/search.tpl index ceb1082404..f1bdd76006 100644 --- a/public/templates/search.tpl +++ b/public/templates/search.tpl @@ -31,7 +31,7 @@ - {topics.title} +

{topics.title}

@@ -61,10 +61,13 @@
- - {posts.content} - + +

{posts.topic.title}

+
+
+ {posts.content} +
diff --git a/src/database/mongo.js b/src/database/mongo.js index f568f3d514..a9cc09c2d4 100644 --- a/src/database/mongo.js +++ b/src/database/mongo.js @@ -166,15 +166,8 @@ module.flushdb = function(callback) { db.dropDatabase(function(err, result) { - if (err) { - winston.error(err.message); - if (typeof callback === 'function') { - return callback(err); - } - } - if (typeof callback === 'function') { - callback(); + callback(err); } }); }; @@ -551,8 +544,8 @@ value = value.toString(); } var data = { - score:score, - value:value + score: parseInt(score, 10), + value: value }; db.collection('objects').update({_key:key, value:value}, {$set:data}, {upsert:true, w: 1}, function(err, result) { diff --git a/src/database/redis.js b/src/database/redis.js index 4655eabb62..d672994b6c 100644 --- a/src/database/redis.js +++ b/src/database/redis.js @@ -117,11 +117,9 @@ module.flushdb = function(callback) { redisClient.send_command('flushdb', [], function(err) { - if (err) { - winston.error(err.message); - return callback(err); + if (typeof callback === 'function') { + callback(err); } - callback(); }); }; diff --git a/src/install.js b/src/install.js index 10ca8c39e6..dfd4cf994b 100644 --- a/src/install.js +++ b/src/install.js @@ -253,12 +253,6 @@ var async = require('async'), }, { field: 'chatMessagesToDisplay', value: 50 - }, { - field: 'theme:type', - value: 'local' - }, { - field: 'theme:id', - value: 'nodebb-theme-cerulean' }]; async.each(defaults, function (configObj, next) { @@ -282,6 +276,15 @@ var async = require('async'), } } }, + function(next) { + var meta = require('./meta'); + winston.info('Enabling default theme: Lavender'); + + meta.themes.set({ + type: 'local', + id: 'nodebb-theme-lavender' + }, next); + }, function (next) { // Check if an administrator needs to be created var Groups = require('./groups'); diff --git a/src/meta.js b/src/meta.js index ad788fdece..f3eb5218bf 100644 --- a/src/meta.js +++ b/src/meta.js @@ -89,6 +89,9 @@ var fs = require('fs'), Meta.themes = { get: function (callback) { var themePath = nconf.get('themes_path'); + if (typeof themePath !== 'string') { + return callback(null, []); + } fs.readdir(themePath, function (err, files) { async.filter(files, function (file, next) { fs.stat(path.join(themePath, file), function (err, fileStat) { diff --git a/src/middleware/middleware.js b/src/middleware/middleware.js index e2b0948cb2..4407adc595 100644 --- a/src/middleware/middleware.js +++ b/src/middleware/middleware.js @@ -163,7 +163,6 @@ middleware.renderHeader = function(req, res, callback) { }], templateValues = { bootswatchCSS: meta.config['theme:src'], - pluginCSS: plugins.cssFiles.map(function(file) { return { path: nconf.get('relative_path') + file.replace(/\\/g, '/') }; }), title: meta.config.title || '', description: meta.config.description || '', 'brand:logo': meta.config['brand:logo'] || '', diff --git a/src/plugins.js b/src/plugins.js index 44433270eb..0b1d07c1cf 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -63,6 +63,8 @@ var fs = require('fs'), Plugins.loadedHooks = {}; Plugins.staticDirs = {}; Plugins.cssFiles.length = 0; + Plugins.lessFiles.length = 0; + Plugins.clientScripts.length = 0; // Read the list of activated plugins and require their libraries async.waterfall([ @@ -196,21 +198,22 @@ var fs = require('fs'), winston.info('[plugins] Found ' + pluginData.css.length + ' CSS file(s) for plugin ' + pluginData.id); } - if (!pluginData.staticDir) { - Plugins.cssFiles = Plugins.cssFiles.concat(pluginData.css.map(function(file) { - return path.join('/plugins', file); - })); - } else { - winston.warn('[plugins/' + pluginData.id + '] staticDir is deprecated, define CSS files with new staticDirs instead.'); - Plugins.cssFiles = Plugins.cssFiles.concat(pluginData.css.map(function(file) { - return path.join('/plugins', pluginData.id, file); - })); - } - - next(); - } else { - next(); + Plugins.cssFiles = Plugins.cssFiles.concat(pluginData.css.map(function(file) { + if (fs.existsSync(path.join(__dirname, '../node_modules', pluginData.id, file))) { + return path.join(pluginData.id, file); + } else { + // Backwards compatibility with < v0.4.0, remove this for v0.5.0 + if (pluginData.staticDir) { + return path.join(pluginData.id, pluginData.staticDir, file); + } else { + winston.error('[plugins/' + pluginData.id + '] This plugin\'s CSS is incorrectly configured, please contact the plugin author.'); + return null; + } + } + }).filter(function(path) { return path })); // Filter out nulls, remove this for v0.5.0 } + + next(); }, function(next) { // LESS files for plugins diff --git a/src/routes/meta.js b/src/routes/meta.js index f2d2af8ad6..ad74931749 100644 --- a/src/routes/meta.js +++ b/src/routes/meta.js @@ -50,6 +50,11 @@ function sendStylesheet(req, res, next) { source += '\n@import "./' + plugins.lessFiles[x] + '";'; } + // ... and for each CSS file + for(x=0,numCSS=plugins.cssFiles.length;x