mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
feat: search in bookmarks on search page
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
"in-titles": "In titles",
|
"in-titles": "In titles",
|
||||||
"in-titles-posts": "In titles and posts",
|
"in-titles-posts": "In titles and posts",
|
||||||
"in-posts": "In posts",
|
"in-posts": "In posts",
|
||||||
|
"in-bookmarks": "In bookmarks",
|
||||||
"in-categories": "In categories",
|
"in-categories": "In categories",
|
||||||
"in-users": "In users",
|
"in-users": "In users",
|
||||||
"in-tags": "In tags",
|
"in-tags": "In tags",
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ define('forum/search', [
|
|||||||
in: $('#search-in').val(),
|
in: $('#search-in').val(),
|
||||||
};
|
};
|
||||||
searchData.term = $('#search-input').val();
|
searchData.term = $('#search-input').val();
|
||||||
if (searchData.in === 'posts' || searchData.in === 'titlesposts' || searchData.in === 'titles') {
|
if (['posts', 'titlesposts', 'titles', 'bookmarks'].includes(searchData.in)) {
|
||||||
searchData.matchWords = form.find('#match-words-filter').val();
|
searchData.matchWords = form.find('#match-words-filter').val();
|
||||||
searchData.by = selectedUsers.length ? selectedUsers.map(u => u.username) : undefined;
|
searchData.by = selectedUsers.length ? selectedUsers.map(u => u.username) : undefined;
|
||||||
searchData.categories = selectedCids.length ? selectedCids : undefined;
|
searchData.categories = selectedCids.length ? selectedCids : undefined;
|
||||||
@@ -143,7 +143,7 @@ define('forum/search', [
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateFormItemVisiblity(searchIn) {
|
function updateFormItemVisiblity(searchIn) {
|
||||||
const hideTitlePostFilters = !searchIn.includes('posts') && !searchIn.includes('titles');
|
const hideTitlePostFilters = !['posts', 'titles', 'bookmarks'].some(token => searchIn.includes(token));
|
||||||
$('.post-search-item').toggleClass('hidden', hideTitlePostFilters);
|
$('.post-search-item').toggleClass('hidden', hideTitlePostFilters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,6 +252,7 @@ define('forum/search', [
|
|||||||
|
|
||||||
function categoryFilterDropdown(_selectedCids) {
|
function categoryFilterDropdown(_selectedCids) {
|
||||||
ajaxify.data.allCategoriesUrl = '';
|
ajaxify.data.allCategoriesUrl = '';
|
||||||
|
selectedCids = _selectedCids || [];
|
||||||
const dropdownEl = $('[component="category/filter"]');
|
const dropdownEl = $('[component="category/filter"]');
|
||||||
categoryFilter.init(dropdownEl, {
|
categoryFilter.init(dropdownEl, {
|
||||||
selectedCids: _selectedCids,
|
selectedCids: _selectedCids,
|
||||||
@@ -290,6 +291,7 @@ define('forum/search', [
|
|||||||
}
|
}
|
||||||
|
|
||||||
function userFilterDropdown(el, _selectedUsers) {
|
function userFilterDropdown(el, _selectedUsers) {
|
||||||
|
selectedUsers = _selectedUsers || [];
|
||||||
userFilter.init(el, {
|
userFilter.init(el, {
|
||||||
selectedUsers: _selectedUsers,
|
selectedUsers: _selectedUsers,
|
||||||
template: 'partials/search-filters',
|
template: 'partials/search-filters',
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ searchController.search = async function (req, res, next) {
|
|||||||
let allowed = (req.query.in === 'users' && userPrivileges['search:users']) ||
|
let allowed = (req.query.in === 'users' && userPrivileges['search:users']) ||
|
||||||
(req.query.in === 'tags' && userPrivileges['search:tags']) ||
|
(req.query.in === 'tags' && userPrivileges['search:tags']) ||
|
||||||
(req.query.in === 'categories') ||
|
(req.query.in === 'categories') ||
|
||||||
(['titles', 'titlesposts', 'posts'].includes(req.query.in) && userPrivileges['search:content']);
|
(['titles', 'titlesposts', 'posts', 'bookmarks'].includes(req.query.in) && userPrivileges['search:content']);
|
||||||
({ allowed } = await plugins.hooks.fire('filter:search.isAllowed', {
|
({ allowed } = await plugins.hooks.fire('filter:search.isAllowed', {
|
||||||
uid: req.uid,
|
uid: req.uid,
|
||||||
query: req.query,
|
query: req.query,
|
||||||
|
|||||||
@@ -261,4 +261,21 @@ module.exports = function (Posts) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Posts.filterPidsByUid = async function (pids, uids) {
|
||||||
|
if (!uids) {
|
||||||
|
return pids;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(uids) || uids.length === 1) {
|
||||||
|
return await filterPidsBySingleUid(pids, uids);
|
||||||
|
}
|
||||||
|
const pidsArr = await Promise.all(uids.map(uid => Posts.filterPidsByUid(pids, uid)));
|
||||||
|
return _.union(...pidsArr);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function filterPidsBySingleUid(pids, uid) {
|
||||||
|
const isMembers = await db.isSortedSetMembers(`uid:${parseInt(uid, 10)}:posts`, pids);
|
||||||
|
return pids.filter((pid, index) => pid && isMembers[index]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
const db = require('./database');
|
const db = require('./database');
|
||||||
|
const batch = require('./batch');
|
||||||
const posts = require('./posts');
|
const posts = require('./posts');
|
||||||
const topics = require('./topics');
|
const topics = require('./topics');
|
||||||
const categories = require('./categories');
|
const categories = require('./categories');
|
||||||
@@ -18,7 +19,7 @@ search.search = async function (data) {
|
|||||||
data.sortBy = data.sortBy || 'relevance';
|
data.sortBy = data.sortBy || 'relevance';
|
||||||
|
|
||||||
let result;
|
let result;
|
||||||
if (data.searchIn === 'posts' || data.searchIn === 'titles' || data.searchIn === 'titlesposts') {
|
if (['posts', 'titles', 'titlesposts', 'bookmarks'].includes(data.searchIn)) {
|
||||||
result = await searchInContent(data);
|
result = await searchInContent(data);
|
||||||
} else if (data.searchIn === 'users') {
|
} else if (data.searchIn === 'users') {
|
||||||
result = await user.search(data);
|
result = await user.search(data);
|
||||||
@@ -68,6 +69,8 @@ async function searchInContent(data) {
|
|||||||
const tid = inTopic[1];
|
const tid = inTopic[1];
|
||||||
const cleanedTerm = data.query.replace(inTopic[0], '');
|
const cleanedTerm = data.query.replace(inTopic[0], '');
|
||||||
pids = await topics.search(tid, cleanedTerm);
|
pids = await topics.search(tid, cleanedTerm);
|
||||||
|
} else if (data.searchIn === 'bookmarks') {
|
||||||
|
pids = await searchInBookmarks(data, searchCids, searchUids);
|
||||||
} else {
|
} else {
|
||||||
[pids, tids] = await Promise.all([
|
[pids, tids] = await Promise.all([
|
||||||
doSearch('post', ['posts', 'titlesposts']),
|
doSearch('post', ['posts', 'titlesposts']),
|
||||||
@@ -115,8 +118,42 @@ async function searchInContent(data) {
|
|||||||
return Object.assign(returnData, metadata);
|
return Object.assign(returnData, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function searchInBookmarks(data, searchCids, searchUids) {
|
||||||
|
const { uid, query, matchWords } = data;
|
||||||
|
const allPids = [];
|
||||||
|
await batch.processSortedSet(`uid:${uid}:bookmarks`, async (pids) => {
|
||||||
|
if (Array.isArray(searchCids) && searchCids.length) {
|
||||||
|
pids = await posts.filterPidsByCid(pids, searchCids);
|
||||||
|
}
|
||||||
|
if (Array.isArray(searchUids) && searchUids.length) {
|
||||||
|
pids = await posts.filterPidsByUid(pids, searchUids);
|
||||||
|
}
|
||||||
|
if (query) {
|
||||||
|
const tokens = String(query).split(' ');
|
||||||
|
const postData = await db.getObjectsFields(pids.map(pid => `post:${pid}`), ['content']);
|
||||||
|
pids = pids.filter((pid, i) => {
|
||||||
|
const content = String(postData[i].content);
|
||||||
|
if (matchWords === 'any') {
|
||||||
|
return tokens.some(t => content.includes(t));
|
||||||
|
}
|
||||||
|
return tokens.every(t => content.includes(t));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
allPids.push(...pids);
|
||||||
|
}, {
|
||||||
|
batch: 500,
|
||||||
|
});
|
||||||
|
|
||||||
|
return allPids;
|
||||||
|
}
|
||||||
|
|
||||||
async function filterAndSort(pids, data) {
|
async function filterAndSort(pids, data) {
|
||||||
if (data.sortBy === 'relevance' && !data.replies && !data.timeRange && !data.hasTags && !plugins.hooks.hasListeners('filter:search.filterAndSort')) {
|
if (data.sortBy === 'relevance' &&
|
||||||
|
!data.replies &&
|
||||||
|
!data.timeRange &&
|
||||||
|
!data.hasTags &&
|
||||||
|
data.searchIn !== 'bookmarks' &&
|
||||||
|
!plugins.hooks.hasListeners('filter:search.filterAndSort')) {
|
||||||
return pids;
|
return pids;
|
||||||
}
|
}
|
||||||
let postsData = await getMatchedPosts(pids, data);
|
let postsData = await getMatchedPosts(pids, data);
|
||||||
|
|||||||
Reference in New Issue
Block a user