@@ -44,7 +78,7 @@
Content is parsed with Markdown.
- Upload images by dragging & dropping them.
+ Upload content images by dragging & dropping them.
diff --git a/src/install.js b/src/install.js
index 14d368c422..889d5e2639 100644
--- a/src/install.js
+++ b/src/install.js
@@ -217,6 +217,9 @@ var async = require('async'),
}, {
field: 'allowGuestSearching',
value: 0
+ }, {
+ field: 'allowTopicsThumbnail',
+ value: 0
}, {
field: 'allowRegistration',
value: 1
diff --git a/src/postTools.js b/src/postTools.js
index 37c888fa54..99c869e09c 100644
--- a/src/postTools.js
+++ b/src/postTools.js
@@ -64,7 +64,9 @@ var winston = require('winston'),
}
- PostTools.edit = function(uid, pid, title, content) {
+ PostTools.edit = function(uid, pid, title, content, options) {
+ options || (options = {});
+
var websockets = require('./socket.io'),
success = function() {
posts.setPostFields(pid, {
@@ -89,6 +91,7 @@ var winston = require('winston'),
topics.setTopicField(tid, 'title', title);
topics.setTopicField(tid, 'slug', slug);
+ topics.setTopicField(tid, 'thumb', options.topic_thumb);
db.searchRemove('topic', tid, function() {
db.searchIndex('topic', title, tid);
diff --git a/src/posts.js b/src/posts.js
index 95f0da116b..55808165d9 100644
--- a/src/posts.js
+++ b/src/posts.js
@@ -2,9 +2,7 @@ var db = require('./database'),
utils = require('./../public/src/utils'),
user = require('./user'),
topics = require('./topics'),
- categories = require('./categories'),
favourites = require('./favourites'),
- threadTools = require('./threadTools'),
postTools = require('./postTools'),
categories = require('./categories'),
plugins = require('./plugins'),
diff --git a/src/routes/api.js b/src/routes/api.js
index 2693b46597..6827caa368 100644
--- a/src/routes/api.js
+++ b/src/routes/api.js
@@ -57,6 +57,7 @@ var path = require('path'),
config.useOutgoingLinksPage = parseInt(meta.config.useOutgoingLinksPage, 10) === 1;
config.allowGuestPosting = parseInt(meta.config.allowGuestPosting, 10) === 1;
config.allowFileUploads = parseInt(meta.config.allowFileUploads, 10) === 1;
+ config.allowTopicsThumbnail = parseInt(meta.config.allowTopicsThumbnail, 10) === 1;
config.usePagination = parseInt(meta.config.usePagination, 10) === 1;
config.topicsPerPage = meta.config.topicsPerPage || 20;
config.postsPerPage = meta.config.postsPerPage || 20;
@@ -448,7 +449,7 @@ var path = require('path'),
}
});
- app.post('/post/upload', function(req, res, next) {
+ function upload(req, res, filesIterator, next) {
if(!req.user) {
return res.json(403, {message:'not allowed'});
}
@@ -469,21 +470,33 @@ var path = require('path'),
}
}
- async.map(files, function(file, next) {
+ async.map(files, filesIterator, function(err, images) {
+ deleteTempFiles();
+ if(err) {
+ return res.json(500, {message: err.message});
+ }
+ res.json(200, images);
+ });
+ }
+
+ app.post('/post/upload', function(req, res, next) {
+ upload(req, res, function(file, next) {
if(file.type.match('image.*')) {
posts.uploadPostImage(file, next);
} else {
posts.uploadPostFile(file, next);
}
- }, function(err, images) {
- deleteTempFiles();
+ }, next)
+ });
- if(err) {
- return res.json(500, {message: err.message});
+ app.post('/topic/thumb/upload', function(req, res, next) {
+ upload(req, res, function(file, next) {
+ if(file.type.match('image.*')) {
+ topics.uploadTopicThumb(file, next);
+ } else {
+ res.json(500, {message: 'Invalid File'});
}
-
- res.json(200, images);
- });
+ }, next)
});
app.get('/reset', function (req, res) {
diff --git a/src/socket.io/modules.js b/src/socket.io/modules.js
index a222f51d93..c5e23dc92b 100644
--- a/src/socket.io/modules.js
+++ b/src/socket.io/modules.js
@@ -29,19 +29,21 @@ SocketModules.composer.push = function(socket, pid, callback) {
posts.getPostFields(pid, ['content'], next);
},
function(next) {
- topics.getTitleByPid(pid, function(title) {
- next(null, title);
- });
+ topics.getTopicDataByPid(pid, next);
+ },
+ function(next) {
+ posts.getPidIndex(pid, next);
}
], function(err, results) {
if(err) {
return callback(err);
}
-
callback(null, {
- title: results[1],
pid: pid,
- body: results[0].content
+ body: results[0].content,
+ title: results[1].title,
+ topic_thumb: results[1].thumb,
+ index: results[2]
});
});
}
diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js
index b0685b371d..2d10ec91b1 100644
--- a/src/socket.io/posts.js
+++ b/src/socket.io/posts.js
@@ -148,7 +148,7 @@ SocketPosts.edit = function(socket, data, callback) {
return callback(new Error('content-too-short'));
}
- postTools.edit(socket.uid, data.pid, data.title, data.content);
+ postTools.edit(socket.uid, data.pid, data.title, data.content, {topic_thumb: data.topic_thumb});
callback();
};
diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js
index c73ea3de37..6db3cbafa1 100644
--- a/src/socket.io/topics.js
+++ b/src/socket.io/topics.js
@@ -23,7 +23,7 @@ SocketTopics.post = function(socket, data, callback) {
return callback(new Error('not-logged-in'));
}
- topics.post(socket.uid, data.title, data.content, data.category_id, function(err, result) {
+ topics.post({uid: socket.uid, title: data.title, content: data.content, cid: data.category_id, thumb: data.topic_thumb}, function(err, result) {
if(err) {
if (err.message === 'title-too-short') {
module.parent.exports.emitAlert(socket, 'Title too short', 'Please enter a longer title. At least ' + meta.config.minimumTitleLength + ' characters.');
diff --git a/src/topics.js b/src/topics.js
index 012a3208aa..7c289e452f 100644
--- a/src/topics.js
+++ b/src/topics.js
@@ -1,5 +1,6 @@
var async = require('async'),
gravatar = require('gravatar'),
+ path = require('path'),
nconf = require('nconf'),
validator = require('validator'),
S = require('string'),
@@ -8,6 +9,7 @@ var async = require('async'),
db = require('./database'),
posts = require('./posts'),
utils = require('./../public/src/utils'),
+ plugins = require('./plugins'),
user = require('./user'),
categories = require('./categories'),
categoryTools = require('./categoryTools'),
@@ -20,7 +22,12 @@ var async = require('async'),
(function(Topics) {
- Topics.create = function(uid, title, cid, callback) {
+ Topics.create = function(data, callback) {
+ var uid = data.uid,
+ title = data.title,
+ cid = data.cid,
+ thumb = data.thumb;
+
db.incrObjectField('global', 'nextTid', function(err, tid) {
if(err) {
return callback(err);
@@ -41,7 +48,8 @@ var async = require('async'),
'viewcount': 0,
'locked': 0,
'deleted': 0,
- 'pinned': 0
+ 'pinned': 0,
+ 'thumb': thumb || ''
}, function(err) {
if(err) {
return callback(err);
@@ -61,7 +69,13 @@ var async = require('async'),
});
};
- Topics.post = function(uid, title, content, cid, callback) {
+ Topics.post = function(data, callback) {
+ var uid = data.uid,
+ title = data.title,
+ content = data.content,
+ cid = data.cid,
+ thumb = data.thumb;
+
if (title) {
title = title.trim();
}
@@ -98,7 +112,7 @@ var async = require('async'),
user.isReadyToPost(uid, next);
},
function(next) {
- Topics.create(uid, title, cid, next);
+ Topics.create({uid: uid, title: title, cid: cid}, next);
},
function(tid, next) {
Topics.reply(tid, uid, content, next);
@@ -210,7 +224,7 @@ var async = require('async'),
posts.getCidByPid(mainPid, callback);
}
}, function(err, results) {
- Topics.create(results.postData.uid, title, results.cid, function(err, tid) {
+ Topics.create({uid: results.postData.uid, title: title, cid: results.cid}, function(err, tid) {
if(err) {
return callback(err);
}
@@ -847,6 +861,7 @@ var async = require('async'),
'pinned': topicData.pinned,
'timestamp': topicData.timestamp,
'slug': topicData.slug,
+ 'thumb': topicData.thumb,
'postcount': topicData.postcount,
'viewcount': topicData.viewcount,
'pageCount': pageCount,
@@ -936,13 +951,43 @@ var async = require('async'),
};
Topics.getTitleByPid = function(pid, callback) {
+ Topics.getTopicFieldByPid('title', pid, callback);
+ };
+
+ Topics.getTopicFieldByPid = function(field, pid, callback) {
posts.getPostField(pid, 'tid', function(err, tid) {
- Topics.getTopicField(tid, 'title', function(err, title) {
- callback(title);
- });
+ Topics.getTopicField(tid, field, callback);
});
};
+ Topics.getTopicDataByPid = function(pid, callback) {
+ posts.getPostField(pid, 'tid', function(err, tid) {
+ Topics.getTopicData(tid, callback);
+ });
+ };
+
+ Topics.uploadTopicThumb = function(image, callback) {
+
+ if(plugins.hasListeners('filter:uploadImage')) {
+ plugins.fireHook('filter:uploadImage', image, callback);
+ } else {
+ if (meta.config.allowTopicsThumbnail) {
+ var filename = 'upload-' + utils.generateUUID() + path.extname(image.name);
+ require('./file').saveFileToLocal(filename, image.path, function(err, upload) {
+ if(err) {
+ return callback(err);
+ }
+ callback(null, {
+ url: upload.url,
+ name: image.name
+ });
+ });
+ } else {
+ callback(new Error('Topic Thumbnails are disabled!'));
+ }
+ }
+ };
+
Topics.markAsUnreadForAll = function(tid, callback) {
db.delete('tid:' + tid + ':read_by_uid', function(err) {
if(err) {
@@ -1011,10 +1056,9 @@ var async = require('async'),
db.isSetMember('tid:' + tid + ':read_by_uid', uid, function(err, hasRead) {
- if (err === null) {
+ if (!err) {
callback(hasRead);
} else {
- console.log(err);
callback(false);
}
});
diff --git a/src/webserver.js b/src/webserver.js
index 6d69600733..0a7508bfef 100644
--- a/src/webserver.js
+++ b/src/webserver.js
@@ -647,7 +647,7 @@ module.exports.server = server;
topics: topicData
});
});
- },
+ }
], function (err, data) {
if (err) {
if (err.message === 'not-enough-privileges') {
@@ -865,7 +865,7 @@ module.exports.server = server;
return custom_routes.templates.map(function(tpl) {
return tpl.template.split('.tpl')[0];
});
- }
+ };
plugins.ready(function() {
plugins.fireHook('filter:server.create_routes', custom_routes, function(err, custom_routes) {
diff --git a/tests/topics.js b/tests/topics.js
index 9d27db8cf7..92404ee393 100644
--- a/tests/topics.js
+++ b/tests/topics.js
@@ -25,7 +25,7 @@ describe('Topic\'s', function() {
describe('.post', function() {
it('should create a new topic with proper parameters', function(done) {
- Topics.post(topic.userId, topic.title, topic.content, topic.categoryId, function(err, result) {
+ Topics.post({uid: topic.userId, title: topic.title, content: topic.content, cid: topic.categoryId}, function(err, result) {
assert.equal(err, null, 'was created with error');
assert.ok(result);
@@ -36,7 +36,7 @@ describe('Topic\'s', function() {
it('should fail to create new topic with wrong parameters', function(done) {
topic.userId = null;
- Topics.post(topic.userId, topic.title, topic.content, topic.categoryId, function(err, result) {
+ Topics.post({uid: topic.userId, title: topic.title, content: topic.content, cid: topic.categoryId}, function(err, result) {
assert.equal(err.message, 'invalid-user');
done();
});
@@ -48,7 +48,7 @@ describe('Topic\'s', function() {
var newPost;
beforeEach(function(done){
- Topics.post(topic.userId, topic.title, topic.content, topic.categoryId, function(err, result) {
+ Topics.post({uid: topic.userId, title: topic.title, content: topic.content, cid: topic.categoryId}, function(err, result) {
newTopic = result.topicData;
newPost = result.postData;
done();