Removing result categories when no results exist in those categories.

This commit is contained in:
Roland 2023-11-21 14:46:55 -07:00
parent eefc4d4d79
commit c628af4f49
No known key found for this signature in database
GPG key ID: 9D6DBD3ACF11AB93
5 changed files with 106 additions and 29 deletions

View file

@ -1024,10 +1024,15 @@ export async function searchSuggestions(search_str) {
const response = await apiPost(`${API_URI}/search_suggestions`, body);
if (response.ok) {
const content = await response.json();
const fileGroups = content['file_groups'];
const zimsEstimates = content['zims_estimates'];
const channels = content['channels'];
const domains = content['domains'];
const tags = content['tags'];
return {
fileGroups,
zimsEstimates,
channels,
domains,
tags,

View file

@ -15,6 +15,7 @@ const suggestedApps = [
{location: '/more/vin', title: 'Vin Decoder', description: 'Decode and analyze vehicle VIN numbers'},
{location: '/admin', title: 'Downloads', description: 'View your downloads'},
{location: '/admin/settings', title: 'Settings', description: 'View and modify your settings'},
{location: '/admin/status', title: 'Status', description: 'View the status of this WROLPi'},
{location: '/admin/wrol', title: 'WROL Mode', description: 'Enable or disable WROL Mode'},
];
@ -31,29 +32,55 @@ export function useSearchSuggestions() {
if (searchStr && searchStr.length > 0) {
const lowerSearchStr = searchStr.toLowerCase();
try {
const i = await searchSuggestions(searchStr);
const newSuggestions = await searchSuggestions(searchStr);
const matchingApps = suggestedApps.filter(i =>
i.title.toLowerCase().includes(lowerSearchStr)
|| fuzzyMatch(i.title.toLowerCase(), lowerSearchStr));
const matchingSuggestions = {
channels: {
name: 'Channels', results: i.channels.map(i => {
return {title: i['name'], id: i['id'], type: 'channel'}
const zimSum = newSuggestions.zimsEstimates.reduce((i, j) => i + j['estimate'], 0);
// Suggested results are ordered.
let matchingSuggestions = {};
if (newSuggestions.fileGroups > 0) {
matchingSuggestions.fileGroups = {
name: 'Files', results: [
{description: newSuggestions.fileGroups, type: 'files'}
]
};
}
if (zimSum > 0) {
matchingSuggestions.zimsSum = {
name: 'Zims', results: [
{description: zimSum, type: 'zims'}
],
}
}
if (newSuggestions.channels && newSuggestions.channels.length > 0) {
matchingSuggestions.channels = {
name: 'Channels', results: newSuggestions.channels.map(i => {
return {type: 'channel', description: i['name'], id: i['id']}
})
},
domains: {
name: 'Domains', results: i.domains.map(i => {
return {title: i['domain'], id: i['id'], type: 'domain'}
}
}
if (newSuggestions.domains && newSuggestions.domains.length > 0) {
matchingSuggestions.domains = {
name: 'Domains', results: newSuggestions.domains.map(i => {
return {type: 'domain', description: i.domain, id: i['id'], domain: i.domain}
})
},
tags: {
name: 'Tags', results: i.tags.map(i => {
return {title: i['name'], type: 'tag'}
}
}
if (newSuggestions.tags && newSuggestions.tags.length > 0) {
matchingSuggestions.tags = {
name: 'Tags', results: newSuggestions.tags.map(i => {
return {type: 'tag', description: i['name']}
})
},
apps: {name: 'Apps', results: matchingApps},
};
console.debug('newSuggestions', matchingSuggestions);
}
}
if (matchingApps && matchingApps.length > 0) {
matchingSuggestions.apps = {name: 'Apps', results: matchingApps};
}
console.debug('matchingSuggestions', matchingSuggestions);
setSuggestions(matchingSuggestions);
} catch (e) {
console.error(e);
@ -75,14 +102,19 @@ export function useSearchSuggestions() {
}
if (result.location) {
navigate(result.location);
return navigate(result.location);
} else if (result['type'] === 'channel') {
navigate(`/videos/channel/${result['id']}/video`);
return navigate(`/videos/channel/${result['id']}/video`);
} else if (result['type'] === 'domain') {
navigate(`/archive?domain=${result['domain']}`);
return navigate(`/archive?domain=${result['domain']}`);
} else if (result['type'] === 'tag') {
navigate(`/search?tag=${encodeURIComponent(result['title'])}`);
return navigate(`/search?tag=${encodeURIComponent(result['title'])}`);
} else if (result['type'] === 'files') {
return navigate(`/search?q=${encodeURIComponent(searchStr)}`);
} else if (result['type'] === 'zims') {
return navigate(`/search/zim?q=${encodeURIComponent(searchStr)}`);
}
console.error('No handleResultSelect defined:', result);
};
const resultRenderer = ({type, title, description}) => {
@ -92,10 +124,13 @@ export function useSearchSuggestions() {
}
// No specific renderer, use the generic.
return <>
<SHeader as='h4'>{title}</SHeader>
{description}
</>
if (title) {
return <>
<SHeader as='h4'>{title}</SHeader>
{description}
</>
}
return <span>{description}</span>
};
return {suggestions, searchStr, handleResultSelect, resultRenderer}

View file

@ -551,13 +551,40 @@ async def post_search_suggestions(_: Request, body: schema.SearchSuggestionsRequ
"""Used by the Global search to suggest links to the user."""
from modules.videos.channel.lib import search_channels_by_name
from modules.archive.lib import search_domains_by_name
from modules.zim.models import Zims
channels, domains, tags_ = await asyncio.gather(
if not body.search_str and not body.tag_names:
return response.empty(HTTPStatus.BAD_REQUEST)
file_groups, channels, domains, tags_ = await asyncio.gather(
estimate_search(body.search_str, body.tag_names),
search_channels_by_name(body.search_str),
search_domains_by_name(body.search_str),
tags.search_tags_by_name(body.search_str),
)
if body.tag_names:
# Get actual count of entries tagged with the tag names.
zims_estimates = list()
for zim, count in Zims.entries_with_tags(body.tag_names).items():
d = dict(
estimate=count,
**zim.__json__(),
)
zims_estimates.append(d)
else:
# Get estimates using libzim.
zims_estimates = list()
for zim, estimate in Zims.estimate(body.search_str).items():
d = dict(
estimate=estimate,
**zim.__json__(),
)
zims_estimates.append(d)
ret = dict(
file_groups=file_groups,
zims_estimates=zims_estimates,
channels=channels,
domains=domains,
tags=tags_,

View file

@ -146,3 +146,4 @@ class SearchEstimateRequest:
@dataclass
class SearchSuggestionsRequest:
search_str: Optional[str] = None
tag_names: List[str] = field(default_factory=lambda: list())

View file

@ -488,12 +488,14 @@ def test_search_str_estimate(test_session, test_client, test_directory, test_zim
@pytest.mark.asyncio
async def test_search_suggestions(test_session, test_async_client, channel_factory, archive_factory, tag_factory):
async def test_search_suggestions(test_session, test_async_client, channel_factory, archive_factory, tag_factory,
zim_factory):
channel_factory(name='Foo')
channel_factory(name='Fool')
channel_factory(name='Bar')
archive_factory(domain='foo.com')
archive_factory(domain='bar.com')
archive_factory(domain='foo.com', contents='contents of foo')
archive_factory(domain='bar.com', contents='contents of bar')
zim_factory('test zim')
tag_factory()
test_session.commit()
@ -506,12 +508,17 @@ async def test_search_suggestions(test_session, test_async_client, channel_facto
'name': 'Fool',
'url': 'https://example.com/Fool'}]
assert response.json['domains'] == [{'directory': 'archive/foo.com', 'domain': 'foo.com', 'id': 1}]
assert response.json['file_groups'] == 1
assert 'zims_estimates' in response.json and len(response.json['zims_estimates']) == 1
assert response.json['zims_estimates'][0]['estimate'] == 0
body = dict(search_str='bar')
request, response = await test_async_client.post('/api/search_suggestions', json=body)
assert response.status_code == HTTPStatus.OK
assert response.json['channels'] == [{'directory': 'Bar', 'id': 3, 'name': 'Bar', 'url': 'https://example.com/Bar'}]
assert response.json['domains'] == [{'directory': 'archive/bar.com', 'domain': 'bar.com', 'id': 2}]
assert response.json['file_groups'] == 1
assert response.json['zims_estimates'][0]['estimate'] == 0
body = dict(search_str='one')
request, response = await test_async_client.post('/api/search_suggestions', json=body)
@ -519,6 +526,8 @@ async def test_search_suggestions(test_session, test_async_client, channel_facto
assert response.json['channels'] == []
assert response.json['domains'] == []
assert response.json['tags'] == [{'color': '#111111', 'id': 1, 'name': 'one'}]
assert response.json['file_groups'] == 0
assert response.json['zims_estimates'][0]['estimate'] == 2
def test_recursive_errors():