mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-07-13 13:21:58 +02:00
Merge remote-tracking branch 'origin/master' into composer-redesign
This commit is contained in:
@@ -63,7 +63,7 @@
|
||||
"socket.io-redis": "^0.1.3",
|
||||
"socketio-wildcard": "~0.1.1",
|
||||
"string": "^3.0.0",
|
||||
"templates.js": "^0.1.23",
|
||||
"templates.js": "^0.1.28",
|
||||
"uglify-js": "git+https://github.com/julianlam/UglifyJS2.git",
|
||||
"underscore": "~1.7.0",
|
||||
"validator": "^3.30.0",
|
||||
|
||||
@@ -89,11 +89,9 @@ $(document).ready(function() {
|
||||
app.previousUrl = url;
|
||||
return ajaxify.go('login');
|
||||
} else if (status === 302) {
|
||||
if (data.responseJSON.path) {
|
||||
if (!ajaxify.go(data.responseJSON.path, callback, quiet)) {
|
||||
window.location.href = data.responseJSON.path;
|
||||
}
|
||||
} else if (data.responseJSON) {
|
||||
if (data.responseJSON.external) {
|
||||
window.location.href = data.responseJSON.external;
|
||||
} else if (typeof data.responseJSON === 'string') {
|
||||
ajaxify.go(data.responseJSON.slice(1), callback, quiet);
|
||||
}
|
||||
}
|
||||
@@ -184,6 +182,9 @@ $(document).ready(function() {
|
||||
}
|
||||
},
|
||||
error: function(data, textStatus) {
|
||||
if (data.status === 0 && textStatus === 'error') {
|
||||
data.status = 500;
|
||||
}
|
||||
callback({
|
||||
data: data,
|
||||
textStatus: textStatus
|
||||
@@ -264,5 +265,6 @@ $(document).ready(function() {
|
||||
|
||||
ajaxifyAnchors();
|
||||
app.load();
|
||||
templates.cache['500'] = $('.tpl-500').html();
|
||||
|
||||
});
|
||||
@@ -55,7 +55,7 @@ categoriesController.popular = function(req, res, next) {
|
||||
var data = {
|
||||
topics: topics,
|
||||
'feeds:disableRSS': parseInt(meta.config['feeds:disableRSS'], 10) === 1,
|
||||
rssFeedUrl: nconf.get('relative_path') + '/popular.rss',
|
||||
rssFeedUrl: nconf.get('relative_path') + '/popular/' + (req.params.term || 'daily') + '.rss',
|
||||
breadcrumbs: helpers.buildBreadcrumbs([{text: '[[global:header.popular]]'}])
|
||||
};
|
||||
|
||||
|
||||
26
src/posts.js
26
src/posts.js
@@ -16,6 +16,7 @@ var async = require('async'),
|
||||
require('./posts/create')(Posts);
|
||||
require('./posts/delete')(Posts);
|
||||
require('./posts/user')(Posts);
|
||||
require('./posts/topics')(Posts);
|
||||
require('./posts/category')(Posts);
|
||||
require('./posts/summary')(Posts);
|
||||
require('./posts/recent')(Posts);
|
||||
@@ -25,20 +26,6 @@ var async = require('async'),
|
||||
db.isSortedSetMember('posts:pid', pid, callback);
|
||||
};
|
||||
|
||||
Posts.getPostsByTid = function(tid, set, start, end, uid, reverse, callback) {
|
||||
Posts.getPidsFromSet(set, start, end, reverse, function(err, pids) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if(!Array.isArray(pids) || !pids.length) {
|
||||
return callback(null, []);
|
||||
}
|
||||
|
||||
Posts.getPostsByPids(pids, uid, callback);
|
||||
});
|
||||
};
|
||||
|
||||
Posts.getPidsFromSet = function(set, start, end, reverse, callback) {
|
||||
if (isNaN(start) || isNaN(end)) {
|
||||
return callback(null, []);
|
||||
@@ -243,17 +230,6 @@ var async = require('async'),
|
||||
});
|
||||
};
|
||||
|
||||
Posts.isMain = function(pid, callback) {
|
||||
Posts.getPostField(pid, 'tid', function(err, tid) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
topics.getTopicField(tid, 'mainPid', function(err, mainPid) {
|
||||
callback(err, parseInt(pid, 10) === parseInt(mainPid, 10));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Posts.updatePostVoteCount = function(pid, voteCount, callback) {
|
||||
async.parallel([
|
||||
function(next) {
|
||||
|
||||
44
src/posts/topics.js
Normal file
44
src/posts/topics.js
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var async = require('async'),
|
||||
topics = require('../topics');
|
||||
|
||||
module.exports = function(Posts) {
|
||||
|
||||
Posts.getPostsByTid = function(tid, set, start, end, uid, reverse, callback) {
|
||||
Posts.getPidsFromSet(set, start, end, reverse, function(err, pids) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (!Array.isArray(pids) || !pids.length) {
|
||||
return callback(null, []);
|
||||
}
|
||||
|
||||
Posts.getPostsByPids(pids, uid, callback);
|
||||
});
|
||||
};
|
||||
|
||||
Posts.isMain = function(pid, callback) {
|
||||
Posts.getPostField(pid, 'tid', function(err, tid) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
topics.getTopicField(tid, 'mainPid', function(err, mainPid) {
|
||||
callback(err, parseInt(pid, 10) === parseInt(mainPid, 10));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Posts.getTopicFields = function(pid, fields, callback) {
|
||||
Posts.getPostField(pid, 'tid', function(err, tid) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
topics.getTopicFields(tid, fields, callback);
|
||||
});
|
||||
};
|
||||
|
||||
};
|
||||
@@ -135,14 +135,17 @@ function generateForCategory(req, res, next) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
var feed = generateTopicsFeed({
|
||||
generateTopicsFeed({
|
||||
title: categoryData.name,
|
||||
description: categoryData.description,
|
||||
feed_url: '/category/' + cid + '.rss',
|
||||
site_url: '/category/' + categoryData.cid,
|
||||
}, categoryData.topics);
|
||||
|
||||
sendFeed(feed, res);
|
||||
}, categoryData.topics, function(err, feed) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
sendFeed(feed, res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -156,12 +159,32 @@ function generateForRecent(req, res, next) {
|
||||
}
|
||||
|
||||
function generateForPopular(req, res, next) {
|
||||
generateForTopics({
|
||||
title: 'Popular Topics',
|
||||
description: 'A list of topics that are sorted by post count',
|
||||
feed_url: '/popular.rss',
|
||||
site_url: '/popular'
|
||||
}, 'topics:posts', req, res, next);
|
||||
var uid = req.user ? req.user.uid : 0;
|
||||
var terms = {
|
||||
daily: 'day',
|
||||
weekly: 'week',
|
||||
monthly: 'month',
|
||||
alltime: 'alltime'
|
||||
};
|
||||
var term = terms[req.params.term] || 'day';
|
||||
|
||||
topics.getPopular(term, uid, 19, function(err, topics) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
generateTopicsFeed({
|
||||
title: 'Popular Topics',
|
||||
description: 'A list of topics that are sorted by post count',
|
||||
feed_url: '/popular/' + (req.params.term || 'daily') + '.rss',
|
||||
site_url: '/popular/' + (req.params.term || 'daily')
|
||||
}, topics, function(err, feed) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
sendFeed(feed, res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function disabledRSS(req, res, next) {
|
||||
@@ -178,35 +201,58 @@ function generateForTopics(options, set, req, res, next) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
var feed = generateTopicsFeed(options, data.topics);
|
||||
|
||||
sendFeed(feed, res);
|
||||
|
||||
generateTopicsFeed(options, data.topics, function(err, feed) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
sendFeed(feed, res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function generateTopicsFeed(feedOptions, topics) {
|
||||
|
||||
feedOptions.ttl = 60;
|
||||
feedOptions.feed_url = nconf.get('url') + feedOptions.feed_url;
|
||||
feedOptions.site_url = nconf.get('url') + feedOptions.site_url;
|
||||
|
||||
var feed = new rss(feedOptions);
|
||||
|
||||
if (topics.length > 0) {
|
||||
feed.pubDate = new Date(parseInt(topics[0].lastposttime, 10)).toUTCString();
|
||||
}
|
||||
|
||||
topics.forEach(function(topicData) {
|
||||
feed.item({
|
||||
title: topicData.title,
|
||||
url: nconf.get('url') + '/topic/' + topicData.slug,
|
||||
author: topicData.username,
|
||||
date: new Date(parseInt(topicData.lastposttime, 10)).toUTCString()
|
||||
});
|
||||
function generateTopicsFeed(feedOptions, feedTopics, callback) {
|
||||
var tids = feedTopics.map(function(topic) {
|
||||
return topic ? topic.tid : null;
|
||||
});
|
||||
|
||||
topics.getMainPids(tids, function(err, pids) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
posts.getPostsFields(pids, ['content'], function(err, posts) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
return feed;
|
||||
feedTopics.forEach(function(topic, index) {
|
||||
if (topic && posts[index]) {
|
||||
topic.mainPost = posts[index].content;
|
||||
}
|
||||
});
|
||||
|
||||
feedOptions.ttl = 60;
|
||||
feedOptions.feed_url = nconf.get('url') + feedOptions.feed_url;
|
||||
feedOptions.site_url = nconf.get('url') + feedOptions.site_url;
|
||||
|
||||
var feed = new rss(feedOptions);
|
||||
|
||||
if (feedTopics.length > 0) {
|
||||
feed.pubDate = new Date(parseInt(feedTopics[0].lastposttime, 10)).toUTCString();
|
||||
}
|
||||
|
||||
feedTopics.forEach(function(topicData) {
|
||||
feed.item({
|
||||
title: topicData.title,
|
||||
description: topicData.mainPost,
|
||||
url: nconf.get('url') + '/topic/' + topicData.slug,
|
||||
author: topicData.username,
|
||||
date: new Date(parseInt(topicData.lastposttime, 10)).toUTCString()
|
||||
});
|
||||
});
|
||||
callback(null, feed);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function generateForRecentPosts(req, res, next) {
|
||||
@@ -291,6 +337,7 @@ module.exports = function(app, middleware, controllers){
|
||||
app.get('/category/:category_id.rss', hasCategoryPrivileges, disabledRSS, generateForCategory);
|
||||
app.get('/recent.rss', disabledRSS, generateForRecent);
|
||||
app.get('/popular.rss', disabledRSS, generateForPopular);
|
||||
app.get('/popular/:term.rss', disabledRSS, generateForPopular);
|
||||
app.get('/recentposts.rss', disabledRSS, generateForRecentPosts);
|
||||
app.get('/category/:category_id/recentposts.rss', hasCategoryPrivileges, disabledRSS, generateForCategoryRecentPosts);
|
||||
app.get('/user/:userslug/topics.rss', disabledRSS, generateForUserTopics);
|
||||
|
||||
@@ -16,6 +16,7 @@ var async = require('async'),
|
||||
groups = require('../groups'),
|
||||
user = require('../user'),
|
||||
websockets = require('./index'),
|
||||
socketTopics = require('./topics'),
|
||||
events = require('../events'),
|
||||
utils = require('../../public/src/utils'),
|
||||
|
||||
@@ -345,27 +346,64 @@ function deleteOrRestore(command, socket, data, callback) {
|
||||
}
|
||||
|
||||
SocketPosts.purge = function(socket, data, callback) {
|
||||
if(!data || !parseInt(data.pid, 10)) {
|
||||
function purgePost() {
|
||||
postTools.purge(socket.uid, data.pid, function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
websockets.in('topic_' + data.tid).emit('event:post_purged', data.pid);
|
||||
|
||||
events.log({
|
||||
type: 'post-purge',
|
||||
uid: socket.uid,
|
||||
pid: data.pid,
|
||||
ip: socket.ip
|
||||
});
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
if (!data || !parseInt(data.pid, 10)) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
postTools.purge(socket.uid, data.pid, function(err) {
|
||||
if(err) {
|
||||
|
||||
isMainAndLastPost(data.pid, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
websockets.in('topic_' + data.tid).emit('event:post_purged', data.pid);
|
||||
if (!results.isMain) {
|
||||
return purgePost();
|
||||
}
|
||||
|
||||
events.log({
|
||||
type: 'post-purge',
|
||||
uid: socket.uid,
|
||||
pid: data.pid,
|
||||
ip: socket.ip
|
||||
if (!results.isLast) {
|
||||
return callback(new Error('[[error:cant-purge-main-post]]'));
|
||||
}
|
||||
|
||||
posts.getTopicFields(data.pid, ['tid', 'cid'], function(err, topic) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
socketTopics.doTopicAction('delete', 'event:topic_deleted', socket, {tids: [topic.tid], cid: topic.cid}, callback);
|
||||
});
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
function isMainAndLastPost(pid, callback) {
|
||||
async.parallel({
|
||||
isMain: function(next) {
|
||||
posts.isMain(pid, next);
|
||||
},
|
||||
isLast: function(next) {
|
||||
posts.getTopicFields(pid, ['postcount'], function(err, topic) {
|
||||
next(err, topic ? parseInt(topic.postcount, 10) === 1 : false);
|
||||
});
|
||||
}
|
||||
}, callback);
|
||||
}
|
||||
|
||||
SocketPosts.getPrivileges = function(socket, pids, callback) {
|
||||
privileges.posts.get(pids, socket.uid, function(err, privileges) {
|
||||
if (err) {
|
||||
|
||||
@@ -205,34 +205,34 @@ SocketTopics.markAsUnreadForAll = function(socket, tids, callback) {
|
||||
};
|
||||
|
||||
SocketTopics.delete = function(socket, data, callback) {
|
||||
doTopicAction('delete', 'event:topic_deleted', socket, data, callback);
|
||||
SocketTopics.doTopicAction('delete', 'event:topic_deleted', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.restore = function(socket, data, callback) {
|
||||
doTopicAction('restore', 'event:topic_restored', socket, data, callback);
|
||||
SocketTopics.doTopicAction('restore', 'event:topic_restored', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.purge = function(socket, data, callback) {
|
||||
doTopicAction('purge', 'event:topic_purged', socket, data, callback);
|
||||
SocketTopics.doTopicAction('purge', 'event:topic_purged', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.lock = function(socket, data, callback) {
|
||||
doTopicAction('lock', 'event:topic_locked', socket, data, callback);
|
||||
SocketTopics.doTopicAction('lock', 'event:topic_locked', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.unlock = function(socket, data, callback) {
|
||||
doTopicAction('unlock', 'event:topic_unlocked', socket, data, callback);
|
||||
SocketTopics.doTopicAction('unlock', 'event:topic_unlocked', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.pin = function(socket, data, callback) {
|
||||
doTopicAction('pin', 'event:topic_pinned', socket, data, callback);
|
||||
SocketTopics.doTopicAction('pin', 'event:topic_pinned', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.unpin = function(socket, data, callback) {
|
||||
doTopicAction('unpin', 'event:topic_unpinned', socket, data, callback);
|
||||
SocketTopics.doTopicAction('unpin', 'event:topic_unpinned', socket, data, callback);
|
||||
};
|
||||
|
||||
function doTopicAction(action, event, socket, data, callback) {
|
||||
SocketTopics.doTopicAction = function(action, event, socket, data, callback) {
|
||||
if (!socket.uid) {
|
||||
return;
|
||||
}
|
||||
@@ -274,7 +274,7 @@ function doTopicAction(action, event, socket, data, callback) {
|
||||
});
|
||||
});
|
||||
}, callback);
|
||||
}
|
||||
};
|
||||
|
||||
function emitToTopicAndCategory(event, data) {
|
||||
websockets.in('topic_' + data.tid).emit(event, data);
|
||||
|
||||
@@ -255,7 +255,7 @@ var async = require('async'),
|
||||
});
|
||||
};
|
||||
|
||||
Topics.getMainPosts = function(tids, uid, callback) {
|
||||
Topics.getMainPids = function(tids, callback) {
|
||||
Topics.getTopicsFields(tids, ['mainPid'], function(err, topicData) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
@@ -264,7 +264,15 @@ var async = require('async'),
|
||||
var mainPids = topicData.map(function(topic) {
|
||||
return topic ? topic.mainPid : null;
|
||||
});
|
||||
callback(null, mainPids);
|
||||
});
|
||||
};
|
||||
|
||||
Topics.getMainPosts = function(tids, uid, callback) {
|
||||
Topics.getMainPids(tids, function(err, mainPids) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
getMainPosts(mainPids, uid, callback);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="alert alert-danger">
|
||||
<strong>[[global:500.title]]</strong>
|
||||
<p>[[global:500.message]]</p>
|
||||
<p>{path}<p>
|
||||
<p>{path}</p>
|
||||
<!-- IF error --><p>{error}</p><!-- ENDIF error -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user