mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-11 16:35:47 +01:00
search in categories and children
This commit is contained in:
@@ -3,5 +3,7 @@
|
|||||||
"no-matches": "No matches found",
|
"no-matches": "No matches found",
|
||||||
"in": "In",
|
"in": "In",
|
||||||
"by": "By",
|
"by": "By",
|
||||||
"posted-by": "Posted by"
|
"posted-by": "Posted by",
|
||||||
|
"in-categories": "In Categories",
|
||||||
|
"search-child-categories": "Search child categories"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,17 +10,25 @@ define('forum/search', ['search'], function(searchModule) {
|
|||||||
|
|
||||||
$('#advanced-search #search-input').val(searchQuery);
|
$('#advanced-search #search-input').val(searchQuery);
|
||||||
var params = utils.params();
|
var params = utils.params();
|
||||||
var select = $('#advanced-search select');
|
var searchIn = $('#advanced-search #search-in');
|
||||||
if (params && params.in) {
|
if (params && params.in) {
|
||||||
select.val(params.in);
|
searchIn.val(params.in);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params && params.by) {
|
if (params && params.by) {
|
||||||
$('.by-container #posted-by-input').val(params.by);
|
$('.by-container #posted-by-user').val(params.by);
|
||||||
}
|
}
|
||||||
|
|
||||||
select.on('change', function() {
|
if (params && params['categories[]']) {
|
||||||
$('.by-container').toggleClass('hide', select.val() !== 'posts');
|
$('#posted-in-categories').val(params['categories[]']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params && params.searchChildren) {
|
||||||
|
$('#search-children').prop('checked', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
searchIn.on('change', function() {
|
||||||
|
$('.by-container').toggleClass('hide', searchIn.val() !== 'posts');
|
||||||
});
|
});
|
||||||
|
|
||||||
highlightMatches(searchQuery);
|
highlightMatches(searchQuery);
|
||||||
@@ -28,13 +36,13 @@ define('forum/search', ['search'], function(searchModule) {
|
|||||||
$('#advanced-search').off('submit').on('submit', function(e) {
|
$('#advanced-search').off('submit').on('submit', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var input = $(this).find('#search-input');
|
var input = $(this).find('#search-input');
|
||||||
var searchIn = $(this).find('select');
|
|
||||||
var postedBy = $(this).find('#posted-by-input');
|
|
||||||
|
|
||||||
searchModule.query({
|
searchModule.query({
|
||||||
term: input.val(),
|
term: input.val(),
|
||||||
in: searchIn.val(),
|
in: $(this).find('#search-in').val(),
|
||||||
by: postedBy.val()
|
by: $(this).find('#posted-by-user').val(),
|
||||||
|
categories: $(this).find('#posted-in-categories').val(),
|
||||||
|
searchChildren: $(this).find('#search-children').is(':checked')
|
||||||
}, function() {
|
}, function() {
|
||||||
input.val('');
|
input.val('');
|
||||||
});
|
});
|
||||||
@@ -63,7 +71,7 @@ define('forum/search', ['search'], function(searchModule) {
|
|||||||
|
|
||||||
|
|
||||||
function enableAutoComplete() {
|
function enableAutoComplete() {
|
||||||
var input = $('.by-container #posted-by-input');
|
var input = $('.by-container #posted-by-user');
|
||||||
input.autocomplete({
|
input.autocomplete({
|
||||||
delay: 100,
|
delay: 100,
|
||||||
source: function(request, response) {
|
source: function(request, response) {
|
||||||
|
|||||||
@@ -27,6 +27,13 @@ define('search', ['navigator'], function(nav) {
|
|||||||
if (postedBy && searchIn === 'posts') {
|
if (postedBy && searchIn === 'posts') {
|
||||||
query.by = postedBy;
|
query.by = postedBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.categories && data.categories.length) {
|
||||||
|
query.categories = data.categories;
|
||||||
|
if (data.searchChildren) {
|
||||||
|
query.searchChildren = data.searchChildren;
|
||||||
|
}
|
||||||
|
}
|
||||||
ajaxify.go('search/' + term + '?' + decodeURIComponent($.param(query)));
|
ajaxify.go('search/' + term + '?' + decodeURIComponent($.param(query)));
|
||||||
callback();
|
callback();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -256,7 +256,14 @@
|
|||||||
value = options.skipToType[key] ? decodeURI(val[1]) : utils.toType(decodeURI(val[1]));
|
value = options.skipToType[key] ? decodeURI(val[1]) : utils.toType(decodeURI(val[1]));
|
||||||
|
|
||||||
if (key) {
|
if (key) {
|
||||||
|
if (!hash[key]) {
|
||||||
hash[key] = value;
|
hash[key] = value;
|
||||||
|
} else {
|
||||||
|
if (!$.isArray(hash[key])) {
|
||||||
|
hash[key] = [hash[key]];
|
||||||
|
}
|
||||||
|
hash[key].push(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return hash;
|
return hash;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ var searchController = {},
|
|||||||
validator = require('validator'),
|
validator = require('validator'),
|
||||||
plugins = require('../plugins'),
|
plugins = require('../plugins'),
|
||||||
search = require('../search'),
|
search = require('../search'),
|
||||||
|
categories = require('../categories'),
|
||||||
helpers = require('./helpers');
|
helpers = require('./helpers');
|
||||||
|
|
||||||
|
|
||||||
@@ -12,7 +13,15 @@ searchController.search = function(req, res, next) {
|
|||||||
if (!plugins.hasListeners('filter:search.query')) {
|
if (!plugins.hasListeners('filter:search.query')) {
|
||||||
return helpers.notFound(req, res);
|
return helpers.notFound(req, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var uid = req.user ? req.user.uid : 0;
|
||||||
var breadcrumbs = helpers.buildBreadcrumbs([{text: '[[global:search]]'}]);
|
var breadcrumbs = helpers.buildBreadcrumbs([{text: '[[global:search]]'}]);
|
||||||
|
|
||||||
|
categories.getCategoriesByPrivilege(uid, 'read', function(err, categories) {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
|
||||||
if (!req.params.term) {
|
if (!req.params.term) {
|
||||||
return res.render('search', {
|
return res.render('search', {
|
||||||
time: 0,
|
time: 0,
|
||||||
@@ -21,18 +30,19 @@ searchController.search = function(req, res, next) {
|
|||||||
topics: [],
|
topics: [],
|
||||||
users: [],
|
users: [],
|
||||||
tags: [],
|
tags: [],
|
||||||
|
categories: categories,
|
||||||
breadcrumbs: breadcrumbs
|
breadcrumbs: breadcrumbs
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var uid = req.user ? req.user.uid : 0;
|
|
||||||
|
|
||||||
req.params.term = validator.escape(req.params.term);
|
req.params.term = validator.escape(req.params.term);
|
||||||
|
|
||||||
search.search({
|
search.search({
|
||||||
query: req.params.term,
|
query: req.params.term,
|
||||||
searchIn: req.query.in,
|
searchIn: req.query.in,
|
||||||
postedBy: req.query.by,
|
postedBy: req.query.by,
|
||||||
|
categories: req.query.categories,
|
||||||
|
searchChildren: req.query.searchChildren,
|
||||||
uid: uid
|
uid: uid
|
||||||
}, function(err, results) {
|
}, function(err, results) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -40,8 +50,10 @@ searchController.search = function(req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
results.breadcrumbs = breadcrumbs;
|
results.breadcrumbs = breadcrumbs;
|
||||||
|
results.categories = categories;
|
||||||
res.render('search', results);
|
res.render('search', results);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
var async = require('async'),
|
var async = require('async'),
|
||||||
posts = require('./posts'),
|
posts = require('./posts'),
|
||||||
topics = require('./topics'),
|
topics = require('./topics'),
|
||||||
|
categories = require('./categories'),
|
||||||
user = require('./user'),
|
user = require('./user'),
|
||||||
plugins = require('./plugins'),
|
plugins = require('./plugins'),
|
||||||
privileges = require('./privileges');
|
privileges = require('./privileges');
|
||||||
@@ -29,7 +30,6 @@ search.search = function(data, callback) {
|
|||||||
|
|
||||||
var query = data.query;
|
var query = data.query;
|
||||||
var searchIn = data.searchIn || 'posts';
|
var searchIn = data.searchIn || 'posts';
|
||||||
var uid = data.uid || 0;
|
|
||||||
|
|
||||||
var result = {
|
var result = {
|
||||||
posts: [],
|
posts: [],
|
||||||
@@ -38,7 +38,7 @@ search.search = function(data, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (searchIn === 'posts') {
|
if (searchIn === 'posts') {
|
||||||
searchInPosts(query, data.postedBy, uid, done);
|
searchInPosts(query, data, done);
|
||||||
} else if (searchIn === 'users') {
|
} else if (searchIn === 'users') {
|
||||||
searchInUsers(query, done);
|
searchInUsers(query, done);
|
||||||
} else if (searchIn === 'tags') {
|
} else if (searchIn === 'tags') {
|
||||||
@@ -48,7 +48,9 @@ search.search = function(data, callback) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function searchInPosts(query, postedBy, uid, callback) {
|
function searchInPosts(query, data, callback) {
|
||||||
|
data.uid = data.uid || 0;
|
||||||
|
var postedBy = data.postedBy || '';
|
||||||
async.parallel({
|
async.parallel({
|
||||||
pids: function(next) {
|
pids: function(next) {
|
||||||
searchQuery('post', query, next);
|
searchQuery('post', query, next);
|
||||||
@@ -56,12 +58,8 @@ function searchInPosts(query, postedBy, uid, callback) {
|
|||||||
tids: function(next) {
|
tids: function(next) {
|
||||||
searchQuery('topic', query, next);
|
searchQuery('topic', query, next);
|
||||||
},
|
},
|
||||||
postedByUid: function(next) {
|
searchCategories: function(next) {
|
||||||
if (postedBy) {
|
getSearchCategories(data, next);
|
||||||
user.getUidByUsername(postedBy, next);
|
|
||||||
} else {
|
|
||||||
next(null, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, function (err, results) {
|
}, function (err, results) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -82,15 +80,18 @@ function searchInPosts(query, postedBy, uid, callback) {
|
|||||||
mainPids.push(pid);
|
mainPids.push(pid);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
privileges.posts.filter('read', mainPids, uid, next);
|
privileges.posts.filter('read', mainPids, data.uid, next);
|
||||||
},
|
},
|
||||||
function(pids, next) {
|
function(pids, next) {
|
||||||
posts.getPostSummaryByPids(pids, uid, {stripTags: true, parse: false}, next);
|
posts.getPostSummaryByPids(pids, data.uid, {stripTags: true, parse: false}, next);
|
||||||
},
|
},
|
||||||
function(posts, next) {
|
function(posts, next) {
|
||||||
if (postedBy) {
|
var searchCategories = results.searchCategories;
|
||||||
|
if (postedBy || searchCategories.length) {
|
||||||
posts = posts.filter(function(post) {
|
posts = posts.filter(function(post) {
|
||||||
return post && parseInt(post.uid, 10) === parseInt(results.postedByUid, 10);
|
return post &&
|
||||||
|
(postedBy ? post.user.username === postedBy : true) &&
|
||||||
|
(searchCategories.length ? searchCategories.indexOf(post.category.cid) !== -1 : true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
next(null, posts);
|
next(null, posts);
|
||||||
@@ -99,6 +100,56 @@ function searchInPosts(query, postedBy, uid, callback) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSearchCategories(data, callback) {
|
||||||
|
if (!Array.isArray(data.categories) || !data.categories.length || data.categories.indexOf('all') !== -1) {
|
||||||
|
return callback(null, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
async.parallel({
|
||||||
|
watchedCids: function(next) {
|
||||||
|
if (data.categories.indexOf('watched') !== -1) {
|
||||||
|
user.getWatchedCategories(data.uid, next);
|
||||||
|
} else {
|
||||||
|
next(null, []);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
childrenCids: function(next) {
|
||||||
|
if (data.searchChildren) {
|
||||||
|
getChildrenCids(data.categories, data.uid, next);
|
||||||
|
} else {
|
||||||
|
next(null, []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, function(err, results) {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var cids = results.watchedCids.concat(results.childrenCids).concat(data.categories).filter(function(cid, index, array) {
|
||||||
|
return cid && array.indexOf(cid) === index;
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(null, cids);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getChildrenCids(cids, uid, callback) {
|
||||||
|
categories.getChildren(cids, uid, function(err, childrenCategories) {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var childrenCids = [];
|
||||||
|
childrenCategories.forEach(function(childrens) {
|
||||||
|
childrenCids = childrenCids.concat(childrens.map(function(category) {
|
||||||
|
return category && category.cid;
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(null, childrenCids);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function searchInUsers(query, callback) {
|
function searchInUsers(query, callback) {
|
||||||
user.search({query: query}, function(err, results) {
|
user.search({query: query}, function(err, results) {
|
||||||
callback(err, results ? results.users : null);
|
callback(err, results ? results.users : null);
|
||||||
|
|||||||
20
src/user.js
20
src/user.js
@@ -435,6 +435,26 @@ var async = require('async'),
|
|||||||
db.getSortedSetRange('uid:' + uid + ':ignored:cids', 0, -1, callback);
|
db.getSortedSetRange('uid:' + uid + ':ignored:cids', 0, -1, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
User.getWatchedCategories = function(uid, callback) {
|
||||||
|
async.parallel({
|
||||||
|
ignored: function(next) {
|
||||||
|
User.getIgnoredCategories(uid, next);
|
||||||
|
},
|
||||||
|
all: function(next) {
|
||||||
|
db.getSortedSetRange('categories:cid', 0, -1, next);
|
||||||
|
}
|
||||||
|
}, function(err, results) {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var watched = results.all.filter(function(cid) {
|
||||||
|
return cid && results.ignored.indexOf(cid) === -1;
|
||||||
|
});
|
||||||
|
callback(null, watched);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
User.ignoreCategory = function(uid, cid, callback) {
|
User.ignoreCategory = function(uid, cid, callback) {
|
||||||
if (!uid) {
|
if (!uid) {
|
||||||
return callback();
|
return callback();
|
||||||
|
|||||||
Reference in New Issue
Block a user