search newer/older than and better pagination

v1.18.x
barisusakli 10 years ago
parent 722b629572
commit 38dd3d4281

@ -8,5 +8,16 @@
"search-child-categories": "Search child categories",
"reply-count": "Reply Count",
"at-least": "At least",
"at-most": "At most"
"at-most": "At most",
"post-time": "Post time",
"newer-than": "Newer than",
"older-than": "Older than",
"any-date": "Any date",
"yesterday": "Yesterday",
"one-week": "One week",
"two-weeks": "Two weeks",
"one-month": "One month",
"three-months": "Three months",
"six-months": "Six months",
"one-year": "One year"
}

@ -9,29 +9,10 @@ define('forum/search', ['search'], function(searchModule) {
var searchQuery = $('#results').attr('data-search-query');
$('#advanced-search #search-input').val(searchQuery);
var params = utils.params();
var searchIn = $('#advanced-search #search-in');
if (params && params.in) {
searchIn.val(params.in);
$('.post-search-item').toggleClass('hide', params.in !== 'posts');
}
if (params && params.by) {
$('#posted-by-user').val(params.by);
}
if (params && (params['categories[]'] || params.categories)) {
$('#posted-in-categories').val(params['categories[]'] || params.categories);
}
if (params && params.searchChildren) {
$('#search-children').prop('checked', true);
}
var searchIn = $('#advanced-search #search-in');
if (params && params.replies) {
$('#reply-count').val(params.replies);
$('#reply-count-filter').val(params.repliesFilter);
}
fillOutFormFromQueryParams();
searchIn.on('change', function() {
$('.post-search-item').toggleClass('hide', searchIn.val() !== 'posts');
@ -50,7 +31,9 @@ define('forum/search', ['search'], function(searchModule) {
categories: $(this).find('#posted-in-categories').val(),
searchChildren: $(this).find('#search-children').is(':checked'),
replies: $(this).find('#reply-count').val(),
repliesFilter: $(this).find('#reply-count-filter').val()
repliesFilter: $(this).find('#reply-count-filter').val(),
timeFilter: $(this).find('#post-time-filter').val(),
timeRange: $(this).find('#post-time-range').val()
}, function() {
input.val('');
});
@ -59,6 +42,38 @@ define('forum/search', ['search'], function(searchModule) {
enableAutoComplete();
};
function fillOutFormFromQueryParams() {
var params = utils.params();
if (params) {
if (params.in) {
$('#search-in').val(params.in);
$('.post-search-item').toggleClass('hide', params.in !== 'posts');
}
if (params.by) {
$('#posted-by-user').val(params.by);
}
if ((params['categories[]'] || params.categories)) {
$('#posted-in-categories').val(params['categories[]'] || params.categories);
}
if (params.searchChildren) {
$('#search-children').prop('checked', true);
}
if (params.replies) {
$('#reply-count').val(params.replies);
$('#reply-count-filter').val(params.repliesFilter);
}
if (params.timeRange) {
$('#post-time-range').val(params.timeRange);
$('#post-time-filter').val(params.timeFilter);
}
}
}
function highlightMatches(searchQuery) {
var searchTerms = searchQuery.split(' ');
var regexes = [];

@ -40,6 +40,11 @@ define('search', ['navigator'], function(nav) {
query.repliesFilter = data.repliesFilter || 'atleast';
}
if (data.timeRange) {
query.timeRange = data.timeRange;
query.timeFilter = data.timeFilter || 'newer';
}
ajaxify.go('search/' + term + '?' + decodeURIComponent($.param(query)));
callback();
} else {

@ -260,8 +260,7 @@ categoriesController.get = function(req, res, next) {
data.currentPage = page;
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
data['rssFeedUrl'] = nconf.get('relative_path') + '/category/' + data.cid + '.rss';
pagination.create(data.currentPage, data.pageCount, data);
data.pagination = pagination.create(data.currentPage, data.pageCount);
data.pagination.rel.forEach(function(rel) {
res.locals.linkTags.push(rel);

@ -37,6 +37,7 @@ searchController.search = function(req, res, next) {
}
req.params.term = validator.escape(req.params.term);
var page = Math.max(1, parseInt(req.query.page, 10)) || 1;
search.search({
query: req.params.term,
@ -46,18 +47,17 @@ searchController.search = function(req, res, next) {
searchChildren: req.query.searchChildren,
replies: req.query.replies,
repliesFilter: req.query.repliesFilter,
timeRange: req.query.timeRange,
timeFilter: req.query.timeFilter,
page: page,
uid: uid
}, function(err, results) {
if (err) {
return next(err);
}
var currentPage = Math.max(1, parseInt(req.query.page, 10)) || 1;
var pageCount = Math.max(1, Math.ceil(results.matchCount / 10));
var searchIn = req.query.in || 'posts';
var start = Math.max(0, (currentPage - 1)) * 10;
results[searchIn] = results[searchIn].slice(start, start + 10);
pagination.create(currentPage, pageCount, results, req.query);
var pageCount = Math.max(1, Math.ceil(results.matchCount / 10));
results.pagination = pagination.create(page, pageCount, req.query);
results.breadcrumbs = breadcrumbs;
results.categories = categories;

@ -256,15 +256,12 @@ topicsController.get = function(req, res, next) {
data['downvote:disabled'] = parseInt(meta.config['downvote:disabled'], 10) === 1;
data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1;
data['rssFeedUrl'] = nconf.get('relative_path') + '/topic/' + data.tid + '.rss';
topics.increaseViewCount(tid);
pagination.create(data.currentPage, data.pageCount, data);
data.pagination = pagination.create(data.currentPage, data.pageCount);
data.pagination.rel.forEach(function(rel) {
res.locals.linkTags.push(rel);
});
topics.increaseViewCount(tid);
res.render('topic', data);
});
};

@ -4,15 +4,14 @@ var qs = require('querystring');
var pagination = {};
pagination.create = function(currentPage, pageCount, data, queryObj) {
pagination.create = function(currentPage, pageCount, queryObj) {
if (pageCount <= 1) {
data.pagination = {
return {
prev: {page: 1, active: currentPage > 1},
next: {page: 1, active: currentPage < pageCount},
rel: [],
pages: []
};
return;
}
var pagesToShow = [1];
@ -43,7 +42,7 @@ pagination.create = function(currentPage, pageCount, data, queryObj) {
return {page: page, active: page === currentPage, qs: qs.stringify(queryObj)};
});
data.pagination = {
var data = {
prev: {page: previous, active: currentPage > 1},
next: {page: next, active: currentPage < pageCount},
rel: [],
@ -51,19 +50,19 @@ pagination.create = function(currentPage, pageCount, data, queryObj) {
};
if (currentPage < pageCount) {
data.pagination.rel.push({
data.rel.push({
rel: 'next',
href: '?page=' + next
});
}
if (currentPage > 1) {
data.pagination.rel.push({
data.rel.push({
rel: 'prev',
href: '?page=' + previous
});
}
return data;
};

@ -1,6 +1,8 @@
'use strict';
var async = require('async'),
db = require('./database'),
posts = require('./posts'),
topics = require('./topics'),
categories = require('./categories'),
@ -19,8 +21,8 @@ search.search = function(data, callback) {
}
result.search_query = query;
result[searchIn] = data;
result.matchCount = data.length;
result[searchIn] = data.matches;
result.matchCount = data.matchCount;
result.hidePostedBy = searchIn !== 'posts';
result.time = (process.elapsedTimeSince(start) / 1000).toFixed(2);
callback(null, result);
@ -65,8 +67,9 @@ function searchInPosts(query, data, callback) {
return callback(err);
}
var matchCount = 0;
if (!results || (!results.pids.length && !results.tids.length)) {
return callback(null, []);
return callback(null, {matches: [], matchCount: matchCount});
}
async.waterfall([
@ -82,31 +85,162 @@ function searchInPosts(query, data, callback) {
privileges.posts.filter('read', mainPids, data.uid, next);
},
function(pids, next) {
filterAndSort(pids, data, results.searchCategories, next);
},
function(pids, next) {
matchCount = pids.length;
if (data.page) {
var start = Math.max(0, (data.page - 1)) * 10;
pids = pids.slice(start, start + 10);
}
posts.getPostSummaryByPids(pids, data.uid, {stripTags: true, parse: false}, next);
},
function(posts, next) {
posts = filterPosts(data, results.searchCategories, posts);
next(null, posts);
next(null, {matches: posts, matchCount: matchCount});
}
], callback);
});
}
function filterPosts(data, searchCategories, posts) {
var postedBy = data.postedBy;
var isAtLeast = data.repliesFilter === 'atleast';
data.replies = parseInt(data.replies, 10);
if (postedBy || searchCategories.length || data.replies) {
function filterAndSort(pids, data, searchCategories, callback) {
var postFields = ['pid', 'tid', 'timestamp'];
var topicFields = [];
if (data.postedBy) {
postFields.push('uid');
}
if (searchCategories.length) {
topicFields.push('cid');
}
if (data.replies) {
topicFields.push('postcount');
}
async.parallel({
posts: function(next) {
getMatchedPosts(pids, postFields, topicFields, next);
},
postedByUid: function(next) {
if (data.postedBy) {
user.getUidByUsername(data.postedBy, next);
} else {
next();
}
}
}, function(err, results) {
if (err) {
return callback(err);
}
if (!results.posts) {
return callback(null, pids);
}
var posts = results.posts.filter(Boolean);
posts = filterByUser(posts, results.postedByUid);
posts = filterByCategories(posts, searchCategories);
posts = filterByPostcount(posts, data.replies, data.repliesFilter);
posts = filterByTimerange(posts, data.timeRange, data.timeFilter);
sortPosts(posts, data);
pids = posts.map(function(post) {
return post && post.pid;
});
callback(null, pids);
});
}
function getMatchedPosts(pids, postFields, topicFields, callback) {
var keys = pids.map(function(pid) {
return 'post:' + pid;
});
var posts;
async.waterfall([
function(next) {
db.getObjectsFields(keys, postFields, next);
},
function(_posts, next) {
posts = _posts;
if (!topicFields.length) {
return callback(null, posts);
}
var topicKeys = posts.map(function(post) {
return 'topic:' + post.tid;
});
db.getObjectsFields(topicKeys, topicFields, next);
},
function(topics, next) {
posts.forEach(function(post, index) {
post.topic = topics[index];
});
next(null, posts);
}
], callback);
}
function filterByUser(posts, postedByUid) {
if (postedByUid) {
postedByUid = parseInt(postedByUid, 10);
posts = posts.filter(function(post) {
return parseInt(post.uid, 10) === postedByUid;
});
}
return posts;
}
function filterByCategories(posts, searchCategories) {
if (searchCategories.length) {
posts = posts.filter(function(post) {
return post &&
(postedBy ? post.user && (post.user.username === postedBy) : true) &&
(searchCategories.length ? (post.category && searchCategories.indexOf(post.category.cid) !== -1) : true) &&
(data.replies ? (isAtLeast ? post.topic.postcount >= data.replies : post.topic.postcount <= data.replies) : true);
return post.topic && searchCategories.indexOf(post.topic.cid) !== -1;
});
}
return posts;
}
function filterByPostcount(posts, postCount, repliesFilter) {
postCount = parseInt(postCount, 10);
if (postCount) {
if (repliesFilter === 'atleast') {
posts = posts.filter(function(post) {
return post.topic && post.topic.postcount >= postCount;
});
} else {
posts = posts.filter(function(post) {
return post.topic && post.topic.postcount <= postCount;
});
}
}
return posts;
}
function filterByTimerange(posts, timeRange, timeFilter) {
timeRange = parseInt(timeRange) * 1000;
if (timeRange) {
var time = Date.now() - timeRange;
if (timeFilter === 'newer') {
posts = posts.filter(function(post) {
return post.timestamp >= time;
});
} else {
posts = posts.filter(function(post) {
return post.timestamp <= time;
});
}
}
return posts;
}
function sortPosts(posts, data) {
posts.sort(function(p1, p2) {
return p2.timestamp - p1.timestamp;
});
}
function getSearchCategories(data, callback) {
if (!Array.isArray(data.categories) || !data.categories.length || data.categories.indexOf('all') !== -1) {
return callback(null, []);
@ -159,12 +293,21 @@ function getChildrenCids(cids, uid, callback) {
function searchInUsers(query, callback) {
user.search({query: query}, function(err, results) {
callback(err, results ? results.users : null);
if (err) {
return callback(err);
}
callback(null, {matches: results.users, matchCount: results.matchCount});
});
}
function searchInTags(query, callback) {
topics.searchAndLoadTags({query: query}, callback);
topics.searchAndLoadTags({query: query}, function(err, tags) {
if (err) {
return callback(err);
}
callback(null, {matches: tags, matchCount: tags.length});
});
}
function getMainPids(tids, callback) {

@ -60,7 +60,7 @@ module.exports = function(User) {
var currentPage = Math.max(1, Math.ceil((start + 1) / resultsPerPage));
pageCount = Math.ceil(matchCount / resultsPerPage);
pagination.create(currentPage, pageCount, data);
data.pagination = pagination.create(currentPage, pageCount);
next(null, data);
}

Loading…
Cancel
Save