diff --git a/README.md b/README.md
index 40485cedae..e28a0681c3 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,25 @@
# NodeBB
**NodeBB** is a robust nodejs driven forum built on a redis database. It is powered by web sockets, and is compatible down to IE8.
+![NodeBB Screenshot](http://i.imgur.com/mxRmLAg.png)
+
+![NodeBB Login Page (with Social Logins)](http://i.imgur.com/q5tUUHW.png)
+
+## Requirements
+
+NodeBB requires a version of Node.js at least 0.8 or greater, and a Redis version 2.6 or greater.
+
## Installation
-NodeBB is powered by Node.js with a Redis database. They must be installed prior in order for NodeBB to work. `build-essential` exposes the build environment for `bcrypt` compilation.
+First, we install our base software stack. `build-essential` is required as it exposes the build environment for `bcrypt` compilation, we won't be compiling anything manually.
- # apt-get install nodejs redis-server npm build-essential
+ # apt-get install git nodejs redis-server npm build-essential
+ $ cd /path/to/nodebb/install/location
+ $ git clone git://github.com/designcreateplay/NodeBB.git nodebb
Next, obtain all of the dependencies required by NodeBB:
+ $ cd nodebb
$ npm install
Now we ensure that the configuration files are properly set up. NodeBB runs on port 4567 by default. The client side config can be set up thusly:
diff --git a/public/templates/404.tpl b/public/templates/404.tpl
new file mode 100644
index 0000000000..f3a998992e
--- /dev/null
+++ b/public/templates/404.tpl
@@ -0,0 +1,4 @@
+
+
Not found
+
You seem to have stumbled upon a page that does not exist. Return to the home page
+
\ No newline at end of file
diff --git a/src/categories.js b/src/categories.js
index c2c6d06d4d..3985a8ae2e 100644
--- a/src/categories.js
+++ b/src/categories.js
@@ -60,104 +60,180 @@ var RDB = require('./redis.js'),
Categories.get = function(callback, category_id, current_user) {
- var range_var = (category_id) ? 'categories:' + category_id + ':tid' : 'topics:tid';
-
- RDB.smembers(range_var, function(err, tids) {
- var title = [],
- uid = [],
- timestamp = [],
- slug = [],
- postcount = [],
- locked = [],
- deleted = [],
- pinned = [];
-
- for (var i=0, ii=tids.length; i 0) {
- multi
- .mget(title)
- .mget(uid)
- .mget(timestamp)
- .mget(slug)
- .mget(postcount)
- .mget(locked)
- .mget(deleted)
- .mget(pinned)
+ .smembers('cid:' + category_id + ':active_users')
+ .exec(function(err, replies) {
+ category_name = replies[0];
+ active_usernames = replies[1];
+
+ if (category_name === null) {
+ callback(false);
+ }
+
+ var active_users = [];
+ for (var username in active_usernames) {
+ active_users.push({'username': active_usernames[username]});
+ }
+
+ var categoryData = {
+ 'category_name' : category_name,
+ 'show_topic_button' : 'show',
+ 'category_id': category_id,
+ 'active_users': active_users,
+ 'topics' : []
+ };
+
+ function getTopics(next) {
+ Categories.getTopicsByTids(tids, current_user, function(topics) {
+ next(null, topics);
+ }, category_id);
+ }
+
+ function getModerators(next) {
+ Categories.getModerators(category_id, function(moderators) {
+ next(null, moderators);
+ });
+ }
+
+ if (tids.length === 0) {
+ getModerators(function(err, moderators) {
+ categoryData.moderator_block_class = moderators.length > 0 ? '' : 'none';
+ categoryData.moderators = moderators;
+
+ callback(categoryData);
+ });
+ } else {
+ async.parallel([getTopics, getModerators], function(err, results) {
+ categoryData.topics = results[0];
+ categoryData.moderator_block_class = results[1].length > 0 ? '' : 'none';
+ categoryData.moderators = results[1];
+ callback(categoryData);
+ });
+ }
+
+
+ });
+ });
+ }
+
+ // not the permanent location for this function
+ Categories.getLatestTopics = function(current_user, start, end, callback) {
+ RDB.zrange('topics:recent', 0, -1, function(err, tids) {
+ var latestTopics = {
+ 'category_name' : 'Recent',
+ 'show_topic_button' : 'hidden',
+ 'category_id': false,
+ 'topics' : []
+ };
+
+ if (!tids.length) {
+ callback(latestTopics);
+ return;
}
+
+ Categories.getTopicsByTids(tids, current_user, function(topicData) {
+ latestTopics.topics = topicData;
+ callback(latestTopics);
+ });
+ });
+ }
+
+
+ Categories.getTopicsByTids = function(tids, current_user, callback, category_id /*temporary*/) {
+ var title = [],
+ uid = [],
+ timestamp = [],
+ slug = [],
+ postcount = [],
+ locked = [],
+ deleted = [],
+ pinned = [];
+
+ for (var i=0, ii=tids.length; i 0) {
- for (var i=0, ii=title.length; i 0 ? '' : 'none',
- 'moderators': moderators
- });
- }
-
- user.get_usernames_by_uids(uid, function(userNames) {
- usernames = userNames;
- generate_topic();
- });
-
- topics.hasReadTopics(tids, current_user, function(hasRead) {
- has_read = hasRead;
- generate_topic();
- });
-
- Categories.getModerators(category_id, function(mods) {
- moderators = mods;
- generate_topic();
- });
- topics.get_teasers(tids, function(teasers) {
- teaser_info = teasers;
- generate_topic();
- });
-
- Categories.privileges(category_id, current_user, function(user_privs) {
- privileges = user_privs;
+ callback(retrieved_topics);
});
});
- });
}
Categories.getAllCategories = function(callback, current_user) {
RDB.lrange('categories:cid', 0, -1, function(err, cids) {
RDB.handle(err);
- Categories.get_category(cids, callback, current_user);
+ Categories.getCategories(cids, callback, current_user);
});
}
@@ -251,7 +290,7 @@ var RDB = require('./redis.js'),
- Categories.get_category = function(cids, callback, current_user) {
+ Categories.getCategories = function(cids, callback, current_user) {
var name = [],
description = [],
icon = [],
diff --git a/src/threadTools.js b/src/threadTools.js
index 06850a2b05..6886750dd0 100644
--- a/src/threadTools.js
+++ b/src/threadTools.js
@@ -141,7 +141,7 @@ var RDB = require('./redis.js'),
RDB.smove('categories:' + oldCid + ':tid', 'categories:' + cid + ':tid', tid, function(err, result) {
if (!err && result === 1) {
RDB.set('tid:' + tid + ':cid', cid);
- categories.get_category([cid], function(data) {
+ categories.getCategories([cid], function(data) {
RDB.set('tid:' + tid + ':category_name', data.categories[0].name);
RDB.set('tid:' + tid + ':category_slug', data.categories[0].slug);
});
diff --git a/src/topics.js b/src/topics.js
index 2cb0382105..43dc651053 100644
--- a/src/topics.js
+++ b/src/topics.js
@@ -58,6 +58,11 @@ marked.setOptions({
voteData = results[1].voteData,
privileges = results[2];
+ if (!postData) {
+ callback(false);
+ return;
+ }
+
for (var i=0, ii= postData.pid.length; i