v1.18.x
parent
27b65a439a
commit
43180d4b83
@ -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;
|
||||
});
|
@ -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);
|
||||
};
|
@ -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);
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue