Barış Soner Uşaklı 7 years ago
parent 27b65a439a
commit 43180d4b83

@ -6,6 +6,7 @@
"popular-month": "Popular topics this month",
"popular-alltime": "All time popular topics",
"recent": "Recent Topics",
"top": "Top Voted Topics",
"moderator-tools": "Moderator Tools",
"flagged-content": "Flagged Content",
"ip-blacklist": "IP Blacklist",

@ -0,0 +1,4 @@
{
"title": "Top",
"no_top_topics": "No top topics"
}

@ -0,0 +1,52 @@
'use strict';
define('forum/top', ['forum/recent', 'forum/infinitescroll'], function (recent, infinitescroll) {
var Top = {};
$(window).on('action:ajaxify.start', function (ev, data) {
if (ajaxify.currentPage !== data.url) {
recent.removeListeners();
}
});
Top.init = function () {
app.enterRoom('top_topics');
recent.watchForNewPosts();
recent.handleCategorySelection();
$('#new-topics-alert').on('click', function () {
$(this).addClass('hide');
});
if (!config.usePagination) {
infinitescroll.init(loadMoreTopics);
}
$(window).trigger('action:topics.loaded', { topics: ajaxify.data.topics });
};
function loadMoreTopics(direction) {
if (direction < 0 || !$('[component="category"]').length) {
return;
}
infinitescroll.loadMore('topics.loadMoreTopTopics', {
after: $('[component="category"]').attr('data-nextstart'),
count: config.topicsPerPage,
cid: utils.params().cid,
filter: ajaxify.data.selectedFilter.filter,
}, function (data, done) {
if (data.topics && data.topics.length) {
recent.onTopicsLoaded('top', data.topics, true, done);
$('[component="category"]').attr('data-nextstart', data.nextStart);
} else {
done();
$('#load-more-btn').hide();
}
});
}
return Top;
});

@ -254,6 +254,10 @@ function getHomePageRoutes(userData, callback) {
route: 'recent',
name: 'Recent',
},
{
route: 'top',
name: 'Top',
},
{
route: 'popular',
name: 'Popular',
@ -292,6 +296,3 @@ function getHomePageRoutes(userData, callback) {
},
], callback);
}
module.exports = settingsController;

@ -37,6 +37,10 @@ homePageController.get = function (req, res, next) {
route: 'recent',
name: 'Recent',
},
{
route: 'top',
name: 'Top',
},
{
route: 'popular',
name: 'Popular',

@ -19,6 +19,7 @@ Controllers.category = require('./category');
Controllers.unread = require('./unread');
Controllers.recent = require('./recent');
Controllers.popular = require('./popular');
Controllers.top = require('./top');
Controllers.tags = require('./tags');
Controllers.search = require('./search');
Controllers.user = require('./user');

@ -0,0 +1,84 @@
'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 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);
},
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.uid) {
data.rssFeedUrl += '?uid=' + req.uid + '&token=' + rssToken;
}
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);
};

@ -256,11 +256,27 @@ Posts.updatePostVoteCount = function (postData, callback) {
function (next) {
async.waterfall([
function (next) {
topics.getTopicField(postData.tid, 'mainPid', next);
topics.getTopicFields(postData.tid, ['mainPid', 'cid'], next);
},
function (mainPid, next) {
if (parseInt(mainPid, 10) === parseInt(postData.pid, 10)) {
return next();
function (topicData, next) {
if (parseInt(topicData.mainPid, 10) === parseInt(postData.pid, 10)) {
async.parallel([
function (next) {
topics.setTopicFields(postData.tid, {
upvotes: postData.upvotes,
downvotes: postData.downvotes,
}, next);
},
function (next) {
db.sortedSetAdd('topics:votes', postData.votes, postData.tid, next);
},
function (next) {
db.sortedSetAdd('cid:' + topicData.cid + ':tids:votes', postData.votes, postData.tid, next);
},
], function (err) {
next(err);
});
return;
}
db.sortedSetAdd('tid:' + postData.tid + ':posts:votes', postData.votes, postData.pid, next);
},
@ -270,7 +286,10 @@ Posts.updatePostVoteCount = function (postData, callback) {
db.sortedSetAdd('posts:votes', postData.votes, postData.pid, next);
},
function (next) {
Posts.setPostFields(postData.pid, { upvotes: postData.upvotes, downvotes: postData.downvotes }, next);
Posts.setPostFields(postData.pid, {
upvotes: postData.upvotes,
downvotes: postData.downvotes,
}, next);
},
], function (err) {
callback(err);

@ -65,6 +65,7 @@ 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, '/category/:category_id/:slug/:topic_index', middleware, [], controllers.category.get);

@ -21,6 +21,7 @@ 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);
@ -165,6 +166,9 @@ Topics.getTopicsByTids = function (tids, uid, callback) {
topics[i].bookmark = results.bookmarks[i];
topics[i].unreplied = !topics[i].teaser;
topics[i].upvotes = parseInt(topics[i].upvotes, 10) || 0;
topics[i].downvotes = parseInt(topics[i].downvotes, 10) || 0;
topics[i].votes = topics[i].upvotes - topics[i].downvotes;
topics[i].icons = [];
}
}
@ -226,6 +230,10 @@ Topics.getTopicWithPosts = function (topicData, set, uid, start, stop, reverse,
topicData.locked = parseInt(topicData.locked, 10) === 1;
topicData.pinned = parseInt(topicData.pinned, 10) === 1;
topicData.upvotes = parseInt(topicData.upvotes, 10) || 0;
topicData.downvotes = parseInt(topicData.downvotes, 10) || 0;
topicData.votes = topicData.upvotes - topicData.downvotes;
topicData.icons = [];
plugins.fireHook('filter:topic.get', { topic: topicData, uid: uid }, next);

@ -0,0 +1,90 @@
'use strict';
var async = require('async');
var db = require('../database');
var privileges = require('../privileges');
var user = require('../user');
var meta = require('../meta');
module.exports = function (Topics) {
Topics.getTopTopics = function (cid, uid, start, stop, filter, callback) {
var topTopics = {
nextStart: 0,
topics: [],
};
if (cid && !Array.isArray(cid)) {
cid = [cid];
}
async.waterfall([
function (next) {
var key = 'topics:votes';
if (cid) {
key = cid.map(function (cid) {
return 'cid:' + cid + ':tids:votes';
});
}
db.getSortedSetRevRange(key, 0, 199, next);
},
function (tids, next) {
filterTids(tids, uid, filter, cid, next);
},
function (tids, next) {
topTopics.topicCount = tids.length;
tids = tids.slice(start, stop + 1);
Topics.getTopicsByTids(tids, uid, next);
},
function (topicData, next) {
topTopics.topics = topicData;
topTopics.nextStart = stop + 1;
next(null, topTopics);
},
], callback);
};
function filterTids(tids, uid, filter, cid, callback) {
async.waterfall([
function (next) {
if (filter === 'watched') {
Topics.filterWatchedTids(tids, uid, next);
} else if (filter === 'new') {
Topics.filterNewTids(tids, uid, next);
} else if (filter === 'unreplied') {
Topics.filterUnrepliedTids(tids, next);
} else {
Topics.filterNotIgnoredTids(tids, uid, next);
}
},
function (tids, next) {
privileges.topics.filterTids('read', tids, uid, next);
},
function (tids, next) {
async.parallel({
ignoredCids: function (next) {
if (filter === 'watched' || parseInt(meta.config.disableRecentCategoryFilter, 10) === 1) {
return next(null, []);
}
user.getIgnoredCategories(uid, next);
},
topicData: function (next) {
Topics.getTopicsFields(tids, ['tid', 'cid'], next);
},
}, next);
},
function (results, next) {
cid = cid && cid.map(String);
tids = results.topicData.filter(function (topic) {
if (topic && topic.cid) {
return results.ignoredCids.indexOf(topic.cid.toString()) === -1 && (!cid || (cid.length && cid.indexOf(topic.cid.toString()) !== -1));
}
return false;
}).map(function (topic) {
return topic.tid;
});
next(null, tids);
},
], callback);
}
};

@ -0,0 +1,60 @@
'use strict';
var async = require('async');
var batch = require('../../batch');
var db = require('../../database');
module.exports = {
name: 'Add votes to topics',
timestamp: Date.UTC(2017, 11, 8),
method: function (callback) {
var progress = this.progress;
batch.processSortedSet('topics:tid', function (tids, next) {
async.eachLimit(tids, 500, function (tid, _next) {
progress.incr();
var topicData;
async.waterfall([
function (next) {
db.getObjectFields('topic:' + tid, ['mainPid', 'cid'], next);
},
function (_topicData, next) {
topicData = _topicData;
if (!topicData.mainPid || !topicData.cid) {
return _next();
}
db.getObject('post:' + topicData.mainPid, next);
},
function (postData, next) {
if (!postData) {
return _next();
}
var upvotes = parseInt(postData.upvotes, 10) || 0;
var downvotes = parseInt(postData.downvotes, 10) || 0;
var data = {
upvotes: upvotes,
downvotes: downvotes,
};
var votes = upvotes - downvotes;
async.parallel([
function (next) {
db.setObject('topic:' + tid, data, next);
},
function (next) {
db.sortedSetAdd('topics:votes', votes, tid, next);
},
function (next) {
db.sortedSetAdd('cid:' + topicData.cid + ':tids:votes', votes, tid, next);
},
], function (err) {
next(err);
});
},
], _next);
}, next);
}, {
progress: progress,
batch: 500,
}, callback);
},
};

@ -118,6 +118,19 @@ describe('Controllers', function () {
});
});
it('should load top', function (done) {
meta.configs.set('homePageRoute', 'top', function (err) {
assert.ifError(err);
request(nconf.get('url'), function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert(body);
done();
});
});
});
it('should load popular', function (done) {
meta.configs.set('homePageRoute', 'popular', function (err) {
assert.ifError(err);

Loading…
Cancel
Save