v1.18.x
Barış Soner Uşaklı 7 years ago
parent ed4787a3ea
commit ccad95cf73

@ -75,10 +75,10 @@
"nodebb-plugin-spam-be-gone": "0.5.4",
"nodebb-rewards-essentials": "0.0.11",
"nodebb-theme-lavender": "5.0.5",
"nodebb-theme-persona": "9.0.15",
"nodebb-theme-slick": "1.2.4",
"nodebb-theme-vanilla": "10.0.13",
"nodebb-widget-essentials": "4.0.6",
"nodebb-theme-persona": "9.0.16",
"nodebb-theme-slick": "1.2.5",
"nodebb-theme-vanilla": "10.0.14",
"nodebb-widget-essentials": "4.0.7",
"nodemailer": "^4.6.5",
"passport": "^0.4.0",
"passport-local": "1.0.0",

@ -7,10 +7,7 @@ define('forum/popular', ['forum/recent', 'components', 'forum/infinitescroll'],
Popular.init = function () {
app.enterRoom('popular_topics');
components.get('popular/tab')
.removeClass('active')
.find('a[href="' + window.location.pathname + '"]')
.parent().addClass('active');
recent.handleCategorySelection();
if (!config.usePagination) {
infinitescroll.init(loadMoreTopics);
@ -25,7 +22,9 @@ define('forum/popular', ['forum/recent', 'components', 'forum/infinitescroll'],
infinitescroll.loadMore('topics.loadMorePopularTopics', {
after: $('[component="category"]').attr('data-nextstart'),
count: config.topicsPerPage,
term: ajaxify.data.term,
cid: utils.params().cid,
term: ajaxify.data.selectedTerm.term,
filter: ajaxify.data.selectedFilter.filter,
}, function (data, done) {
if (data.topics && data.topics.length) {
recent.onTopicsLoaded('popular', data.topics, false, direction, done);

@ -124,9 +124,11 @@ define('forum/recent', ['forum/infinitescroll', 'components', 'handleBack'], fun
});
if (changed) {
var url = ajaxify.data.selectedFilter.url;
var url = window.location.pathname;
var currentParams = utils.params();
if (cids.length) {
url += '?' + decodeURIComponent($.param({ cid: cids }));
currentParams.cid = cids;
url += '?' + decodeURIComponent($.param(currentParams));
}
ajaxify.go(url);
}

@ -36,6 +36,7 @@ define('forum/top', ['forum/recent', 'forum/infinitescroll'], function (recent,
after: $('[component="category"]').attr('data-nextstart'),
count: config.topicsPerPage,
cid: utils.params().cid,
term: ajaxify.data.selectedTerm.term,
filter: ajaxify.data.selectedFilter.filter,
}, function (data, done) {
if (data.topics && data.topics.length) {

@ -4,6 +4,7 @@ var nconf = require('nconf');
var async = require('async');
var validator = require('validator');
var winston = require('winston');
var querystring = require('querystring');
var user = require('../user');
var privileges = require('../privileges');
@ -34,30 +35,78 @@ helpers.noScriptErrors = function (req, res, error, httpStatus) {
helpers.validFilters = { '': true, new: true, watched: true, unreplied: true };
helpers.buildFilters = function (url, filter) {
helpers.terms = {
daily: 'day',
weekly: 'week',
monthly: 'month',
};
helpers.buildQueryString = function (cid, filter, term) {
var qs = {};
if (cid) {
qs.cid = cid;
}
if (filter) {
qs.filter = filter;
}
if (term) {
qs.term = term;
}
if (Object.keys(qs).length) {
return '?' + querystring.stringify(qs);
}
return '';
};
helpers.buildFilters = function (url, filter, query) {
return [{
name: '[[unread:all-topics]]',
url: url,
url: url + helpers.buildQueryString(query.cid, '', query.term),
selected: filter === '',
filter: '',
}, {
name: '[[unread:new-topics]]',
url: url + '/new',
url: url + helpers.buildQueryString(query.cid, 'new', query.term),
selected: filter === 'new',
filter: 'new',
}, {
name: '[[unread:watched-topics]]',
url: url + '/watched',
url: url + helpers.buildQueryString(query.cid, 'watched', query.term),
selected: filter === 'watched',
filter: 'watched',
}, {
name: '[[unread:unreplied-topics]]',
url: url + '/unreplied',
url: url + helpers.buildQueryString(query.cid, 'unreplied', query.term),
selected: filter === 'unreplied',
filter: 'unreplied',
}];
};
helpers.buildTerms = function (url, term, query) {
return [{
name: '[[recent:alltime]]',
url: url + helpers.buildQueryString(query.cid, query.filter, ''),
selected: term === 'alltime',
term: 'alltime',
}, {
name: '[[recent:day]]',
url: url + helpers.buildQueryString(query.cid, query.filter, 'daily'),
selected: term === 'day',
term: 'day',
}, {
name: '[[recent:week]]',
url: url + helpers.buildQueryString(query.cid, query.filter, 'weekly'),
selected: term === 'week',
term: 'week',
}, {
name: '[[recent:month]]',
url: url + helpers.buildQueryString(query.cid, query.filter, 'monthly'),
selected: term === 'month',
term: 'month',
}];
};
helpers.notAllowed = function (req, res, error) {
plugins.fireHook('filter:helpers.notAllowed', {
req: req,

@ -4,81 +4,28 @@
var async = require('async');
var nconf = require('nconf');
var topics = require('../topics');
var meta = require('../meta');
var user = require('../user');
var helpers = require('./helpers');
var pagination = require('../pagination');
var recentController = require('./recent');
var popularController = module.exports;
var anonCache = {};
var lastUpdateTime = 0;
var terms = {
daily: 'day',
weekly: 'week',
monthly: 'month',
};
popularController.get = function (req, res, next) {
var page = parseInt(req.query.page, 10) || 1;
var term = terms[req.params.term];
if (!term && req.params.term) {
return next();
}
term = term || 'alltime';
var termToBreadcrumb = {
day: '[[recent:day]]',
week: '[[recent:week]]',
month: '[[recent:month]]',
alltime: '[[global:header.popular]]',
};
if (!req.loggedIn) {
if (anonCache[term] && anonCache[term][page] && (Date.now() - lastUpdateTime) < 60 * 60 * 1000) {
return res.render('popular', anonCache[term][page]);
}
}
var settings;
async.waterfall([
function (next) {
user.getSettings(req.uid, next);
},
function (_settings, next) {
settings = _settings;
var start = Math.max(0, (page - 1) * settings.topicsPerPage);
var stop = start + settings.topicsPerPage - 1;
topics.getPopularTopics(term, req.uid, start, stop, next);
recentController.getData(req, 'popular', 'posts', next);
},
function (data) {
var pageCount = Math.max(1, Math.ceil(data.topicCount / settings.topicsPerPage));
data.title = meta.config.homePageTitle || '[[pages:home]]';
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
data.rssFeedUrl = nconf.get('relative_path') + '/popular/' + (req.params.term || 'alltime') + '.rss';
data.term = term;
data.pagination = pagination.create(page, pageCount, req.query);
function (data, next) {
if (!data) {
return next();
}
var term = helpers.terms[req.query.term] || 'alltime';
if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/popular') || req.originalUrl.startsWith(nconf.get('relative_path') + '/popular')) {
data.title = '[[pages:popular-' + term + ']]';
var breadcrumbs = [{ text: termToBreadcrumb[term] }];
if (req.params.term) {
breadcrumbs.unshift({ text: '[[global:header.popular]]', url: '/popular' });
}
var breadcrumbs = [{ text: '[[global:header.popular]]' }];
data.breadcrumbs = helpers.buildBreadcrumbs(breadcrumbs);
}
if (!req.loggedIn) {
anonCache[term] = anonCache[term] || {};
anonCache[term][page] = data;
lastUpdateTime = Date.now();
}
data.rssFeedUrl = nconf.get('relative_path') + '/popular/' + (req.query.term || 'alltime') + '.rss';
res.render('popular', data);
},
], next);

@ -3,7 +3,6 @@
var async = require('async');
var nconf = require('nconf');
var querystring = require('querystring');
var user = require('../user');
var topics = require('../topics');
@ -14,17 +13,33 @@ var pagination = require('../pagination');
var recentController = module.exports;
recentController.get = function (req, res, next) {
async.waterfall([
function (next) {
recentController.getData(req, 'recent', 'recent', next);
},
function (data, next) {
if (!data) {
return next();
}
res.render('recent', data);
},
], next);
};
recentController.getData = function (req, url, sort, callback) {
var page = parseInt(req.query.page, 10) || 1;
var stop = 0;
var term = helpers.terms[req.query.term];
var settings;
var cid = req.query.cid;
var filter = req.params.filter || '';
var filter = req.query.filter || '';
var categoryData;
var rssToken;
if (!helpers.validFilters[filter]) {
return next();
if (!helpers.validFilters[filter] || (!term && req.query.term)) {
return callback();
}
term = term || 'alltime';
async.waterfall([
function (next) {
@ -48,37 +63,47 @@ recentController.get = function (req, res, next) {
var start = Math.max(0, (page - 1) * settings.topicsPerPage);
stop = start + settings.topicsPerPage - 1;
topics.getRecentTopics(cid, req.uid, start, stop, filter, next);
topics.getSortedTopics({
cids: cid,
uid: req.uid,
start: start,
stop: stop,
filter: filter,
term: term,
sort: sort,
}, next);
},
function (data) {
function (data, next) {
data.categories = categoryData.categories;
data.allCategoriesUrl = url + helpers.buildQueryString('', filter, '');
data.selectedCategory = categoryData.selectedCategory;
data.selectedCids = categoryData.selectedCids;
data.nextStart = stop + 1;
data.set = 'topics:recent';
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
data.rssFeedUrl = nconf.get('relative_path') + '/recent.rss';
data.rssFeedUrl = nconf.get('relative_path') + '/' + url + '.rss';
if (req.loggedIn) {
data.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken;
}
data.title = meta.config.homePageTitle || '[[pages:home]]';
data.filters = helpers.buildFilters('recent', filter);
data.filters = helpers.buildFilters(url, filter, req.query);
data.selectedFilter = data.filters.find(function (filter) {
return filter && filter.selected;
});
data.terms = helpers.buildTerms(url, term, req.query);
data.selectedTerm = data.terms.find(function (term) {
return term && term.selected;
});
var pageCount = Math.max(1, Math.ceil(data.topicCount / settings.topicsPerPage));
data.pagination = pagination.create(page, pageCount, req.query);
if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/recent') || req.originalUrl.startsWith(nconf.get('relative_path') + '/recent')) {
data.title = '[[pages:recent]]';
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[recent:title]]' }]);
if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/' + url) || req.originalUrl.startsWith(nconf.get('relative_path') + '/' + url)) {
data.title = '[[pages:' + url + ']]';
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[' + url + ':title]]' }]);
}
data.querystring = cid ? '?' + querystring.stringify({ cid: cid }) : '';
res.render('recent', data);
next(null, data);
},
], next);
], callback);
};

@ -2,82 +2,19 @@
'use strict';
var async = require('async');
var nconf = require('nconf');
var querystring = require('querystring');
var user = require('../user');
var topics = require('../topics');
var meta = require('../meta');
var helpers = require('./helpers');
var pagination = require('../pagination');
var recentController = require('./recent');
var topController = module.exports;
topController.get = function (req, res, next) {
var page = parseInt(req.query.page, 10) || 1;
var stop = 0;
var settings;
var cid = req.query.cid;
var filter = req.params.filter || '';
var categoryData;
var rssToken;
if (!helpers.validFilters[filter]) {
return next();
}
async.waterfall([
function (next) {
async.parallel({
settings: function (next) {
user.getSettings(req.uid, next);
},
watchedCategories: function (next) {
helpers.getWatchedCategories(req.uid, cid, next);
},
rssToken: function (next) {
user.auth.getFeedToken(req.uid, next);
},
}, next);
},
function (results, next) {
rssToken = results.rssToken;
settings = results.settings;
categoryData = results.watchedCategories;
var start = Math.max(0, (page - 1) * settings.topicsPerPage);
stop = start + settings.topicsPerPage - 1;
topics.getTopTopics(cid, req.uid, start, stop, filter, next);
recentController.getData(req, 'top', 'votes', next);
},
function (data) {
data.categories = categoryData.categories;
data.selectedCategory = categoryData.selectedCategory;
data.selectedCids = categoryData.selectedCids;
data.nextStart = stop + 1;
data.set = 'topics:votes';
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
data.rssFeedUrl = nconf.get('relative_path') + '/top.rss';
if (req.loggedIn) {
data.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken;
function (data, next) {
if (!data) {
return next();
}
data.title = meta.config.homePageTitle || '[[pages:home]]';
data.filters = helpers.buildFilters('top', filter);
data.selectedFilter = data.filters.find(function (filter) {
return filter && filter.selected;
});
var pageCount = Math.max(1, Math.ceil(data.topicCount / settings.topicsPerPage));
data.pagination = pagination.create(page, pageCount, req.query);
if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/top') || req.originalUrl.startsWith(nconf.get('relative_path') + '/top')) {
data.title = '[[pages:top]]';
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[top:title]]' }]);
}
data.querystring = cid ? '?' + querystring.stringify({ cid: cid }) : '';
res.render('top', data);
},
], next);

@ -18,7 +18,7 @@ unreadController.get = function (req, res, next) {
var page = parseInt(req.query.page, 10) || 1;
var results;
var cid = req.query.cid;
var filter = req.params.filter || '';
var filter = req.query.filter || '';
var settings;
async.waterfall([
@ -71,6 +71,7 @@ unreadController.get = function (req, res, next) {
}
data.categories = results.watchedCategories.categories;
data.allCategoriesUrl = 'unread' + helpers.buildQueryString('', filter, '');
data.selectedCategory = results.watchedCategories.selectedCategory;
data.selectedCids = results.watchedCategories.selectedCids;
if (req.originalUrl.startsWith(nconf.get('relative_path') + '/api/unread') || req.originalUrl.startsWith(nconf.get('relative_path') + '/unread')) {
@ -78,20 +79,19 @@ unreadController.get = function (req, res, next) {
data.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[unread:title]]' }]);
}
data.filters = helpers.buildFilters('unread', filter);
data.filters = helpers.buildFilters('unread', filter, req.query);
data.selectedFilter = data.filters.find(function (filter) {
return filter && filter.selected;
});
data.querystring = cid ? '?' + querystring.stringify({ cid: cid }) : '';
res.render('unread', data);
},
], next);
};
unreadController.unreadTotal = function (req, res, next) {
var filter = req.params.filter || '';
var filter = req.query.filter || '';
async.waterfall([
function (next) {

@ -25,7 +25,7 @@ module.exports = function (app, middleware, controllers) {
router.get('/categories/:cid/moderators', controllers.api.getModerators);
router.get('/recent/posts/:term?', controllers.posts.getRecentPosts);
router.get('/unread/:filter?/total', middleware.authenticate, controllers.unread.unreadTotal);
router.get('/unread/total', middleware.authenticate, controllers.unread.unreadTotal);
router.get('/topic/teaser/:topic_id', controllers.topics.teaser);
router.get('/topic/pagination/:topic_id', controllers.topics.pagination);

@ -197,11 +197,8 @@ function generateForRecent(req, res, next) {
}
},
function (token, next) {
next(null, token && token === req.query.token ? req.query.uid : req.uid);
},
function (uid, next) {
generateForTopics({
uid: uid,
uid: token && token === req.query.token ? req.query.uid : req.uid,
title: 'Recently Active Topics',
description: 'A list of topics that have been active within the past 24 hours',
feed_url: '/recent.rss',
@ -225,11 +222,8 @@ function generateForTop(req, res, next) {
}
},
function (token, next) {
next(null, token && token === req.query.token ? req.query.uid : req.uid);
},
function (uid, next) {
generateForTopics({
uid: uid,
uid: token && token === req.query.token ? req.query.uid : req.uid,
title: 'Top Voted Topics',
description: 'A list of topics that have received the most votes',
feed_url: '/top.rss',
@ -250,14 +244,29 @@ function generateForPopular(req, res, next) {
alltime: 'alltime',
};
var term = terms[req.params.term] || 'day';
var uid;
async.waterfall([
function (next) {
topics.getPopularTopics(term, req.uid, 0, 19, next);
if (req.query.token && req.query.uid) {
db.getObjectField('user:' + req.query.uid, 'rss_token', next);
} else {
next(null, null);
}
},
function (token, next) {
uid = token && token === req.query.token ? req.query.uid : req.uid;
topics.getSortedTopics({
uid: uid,
start: 0,
stop: 19,
term: term,
sort: 'posts',
}, next);
},
function (result, next) {
generateTopicsFeed({
uid: req.uid,
uid: uid,
title: 'Popular Topics',
description: 'A list of topics that are sorted by post count',
feed_url: '/popular/' + (req.params.term || 'daily') + '.rss',

@ -63,10 +63,10 @@ function tagRoutes(app, middleware, controllers) {
function categoryRoutes(app, middleware, controllers) {
setupPageRoute(app, '/categories', middleware, [], controllers.categories.list);
setupPageRoute(app, '/popular/:term?', middleware, [], controllers.popular.get);
setupPageRoute(app, '/recent/:filter?', middleware, [], controllers.recent.get);
setupPageRoute(app, '/top/:filter?', middleware, [], controllers.top.get);
setupPageRoute(app, '/unread/:filter?', middleware, [middleware.authenticate], controllers.unread.get);
setupPageRoute(app, '/popular', middleware, [], controllers.popular.get);
setupPageRoute(app, '/recent', middleware, [], controllers.recent.get);
setupPageRoute(app, '/top', middleware, [], controllers.top.get);
setupPageRoute(app, '/unread', middleware, [middleware.authenticate], controllers.unread.get);
setupPageRoute(app, '/category/:category_id/:slug/:topic_index', middleware, [], controllers.category.get);
setupPageRoute(app, '/category/:category_id/:slug?', middleware, [], controllers.category.get);

@ -88,30 +88,22 @@ module.exports = function (SocketTopics) {
};
SocketTopics.loadMoreUnreadTopics = function (socket, data, callback) {
loadData(data, callback, function (start, stop) {
topics.getUnreadTopics({ cid: data.cid, uid: socket.uid, start: start, stop: stop, filter: data.filter }, callback);
});
loadData(socket.uid, data, 'unread', callback);
};
SocketTopics.loadMoreRecentTopics = function (socket, data, callback) {
loadData(data, callback, function (start, stop) {
topics.getRecentTopics(data.cid, socket.uid, start, stop, data.filter, callback);
});
loadData(socket.uid, data, 'recent', callback);
};
SocketTopics.loadMorePopularTopics = function (socket, data, callback) {
loadData(data, callback, function (start, stop) {
topics.getPopularTopics(data.term, socket.uid, start, stop, callback);
});
loadData(socket.uid, data, 'posts', callback);
};
SocketTopics.loadMoreTopTopics = function (socket, data, callback) {
loadData(data, callback, function (start, stop) {
topics.getTopTopics(data.cid, socket.uid, start, stop, data.filter, callback);
});
loadData(socket.uid, data, 'votes', callback);
};
function loadData(data, callback, loadFn) {
function loadData(uid, data, sort, callback) {
if (!data || !utils.isNumber(data.after) || parseInt(data.after, 10) < 0) {
return callback(new Error('[[error:invalid-data]]'));
}
@ -123,7 +115,18 @@ module.exports = function (SocketTopics) {
var stop = start + Math.max(0, itemsPerPage - 1);
start = Math.max(0, start);
stop = Math.max(0, stop);
loadFn(start, stop);
if (sort === 'unread') {
return topics.getUnreadTopics({ cid: data.cid, uid: uid, start: start, stop: stop, filter: data.filter }, callback);
}
topics.getSortedTopics({
cids: data.cid,
uid: uid,
start: start,
stop: stop,
filter: data.filter,
sort: sort,
term: data.term,
}, callback);
}
SocketTopics.loadMoreFromSet = function (socket, data, callback) {

@ -20,8 +20,6 @@ require('./topics/create')(Topics);
require('./topics/delete')(Topics);
require('./topics/unread')(Topics);
require('./topics/recent')(Topics);
require('./topics/popular')(Topics);
require('./topics/top')(Topics);
require('./topics/user')(Topics);
require('./topics/fork')(Topics);
require('./topics/posts')(Topics);

@ -1,14 +0,0 @@
'use strict';
module.exports = function (Topics) {
Topics.getPopularTopics = function (term, uid, start, stop, callback) {
Topics.getSortedTopics({
uid: uid,
start: start,
stop: stop,
term: term,
sort: 'posts',
}, callback);
};
};

@ -1,16 +0,0 @@
'use strict';
module.exports = function (Topics) {
Topics.getTopTopics = function (cid, uid, start, stop, filter, callback) {
Topics.getSortedTopics({
cids: cid,
uid: uid,
start: start,
stop: stop,
filter: filter,
sort: 'votes',
}, callback);
};
};

@ -158,7 +158,13 @@ Digest.send = function (data, callback) {
function getTermTopics(term, uid, start, stop, callback) {
async.waterfall([
function (next) {
topics.getPopularTopics(term, uid, start, stop, next);
topics.getSortedTopics({
uid: uid,
start: start,
stop: stop,
term: term,
sort: 'posts',
}, next);
},
function (data, next) {
if (!data.topics.length) {

@ -2037,7 +2037,7 @@ describe('Controllers', function () {
});
it('should 404 if filter is invalid', function (done) {
request(nconf.get('url') + '/api/unread/doesnotexist/total', { jar: jar }, function (err, res) {
request(nconf.get('url') + '/api/unread/total?filter=doesnotexist', { jar: jar }, function (err, res) {
assert.ifError(err);
assert.equal(res.statusCode, 404);
done();
@ -2045,7 +2045,7 @@ describe('Controllers', function () {
});
it('should return total unread count', function (done) {
request(nconf.get('url') + '/api/unread/new/total', { jar: jar }, function (err, res, body) {
request(nconf.get('url') + '/api/unread/total?filter=new', { jar: jar }, function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert.equal(body, 0);

@ -1824,11 +1824,18 @@ describe('Topic\'s', function () {
});
});
describe('top topics', function () {
it('should get top topics in category', function (done) {
describe('sorted topics', function () {
it('should get sorted topics in category', function (done) {
var filters = ['', 'watched', 'unreplied', 'new'];
async.map(filters, function (filter, next) {
topics.getTopTopics(topic.categoryId, topic.userId, 0, -1, filter, next);
topics.getSortedTopics({
cids: [topic.categoryId],
uid: topic.userId,
start: 0,
stop: -1,
filter: filter,
sort: 'votes',
}, next);
}, function (err, data) {
assert.ifError(err);
assert(data);

Loading…
Cancel
Save