Implement new search UI

We now have both autocomplete-based searching for quick results, as well as a full search page for a full listing of results
This commit is contained in:
Joseph Schorr 2017-04-07 17:25:44 -04:00
parent 8b148bf1d4
commit e9ffe0e27b
23 changed files with 649 additions and 393 deletions

View file

@ -164,11 +164,13 @@ class EntitySearch(ApiResource):
def search_entity_view(username, entity, get_short_name=None):
kind = 'user'
title = 'user'
avatar_data = avatar.get_data_for_user(entity)
href = '/user/' + entity.username
if entity.organization:
kind = 'organization'
title = 'org'
avatar_data = avatar.get_data_for_org(entity)
href = '/organization/' + entity.username
elif entity.robot:
@ -179,9 +181,11 @@ def search_entity_view(username, entity, get_short_name=None):
href = '/organization/' + parts[0] + '?tab=robots&showRobot=' + entity.username
kind = 'robot'
title = 'robot'
avatar_data = None
data = {
'title': title,
'kind': kind,
'avatar': avatar_data,
'name': entity.username,
@ -233,20 +237,15 @@ def conduct_admined_team_search(username, query, encountered_teams, results):
})
def conduct_repo_search(username, query, results):
def conduct_repo_search(username, query, results, offset=0, limit=5):
""" Finds matching repositories. """
matching_repos = model.repository.get_filtered_matching_repositories(query, username, limit=5)
matching_repos = model.repository.get_filtered_matching_repositories(query, username, limit=limit,
repo_kind=None,
offset=offset)
for repo in matching_repos:
results.append({
'kind': 'repository',
'namespace': search_entity_view(username, repo.namespace_user),
'name': repo.name,
'description': repo.description,
'is_public': model.repository.is_repository_public(repo),
'score': REPOSITORY_SEARCH_SCORE,
'href': '/repository/' + repo.namespace_user.username + '/' + repo.name
})
# TODO: make sure the repo.kind.name doesn't cause extra queries
results.append(repo_result_view(repo, username))
def conduct_namespace_search(username, query, results):
@ -266,6 +265,30 @@ def conduct_robot_search(username, query, results):
results.append(search_entity_view(username, robot, get_short_name))
def repo_result_view(repo, username, last_modified=None, stars=None, popularity=None):
kind = 'application' if repo.kind.name == 'application' else 'repository'
view = {
'kind': kind,
'title': 'app' if kind == 'application' else 'repo',
'namespace': search_entity_view(username, repo.namespace_user),
'name': repo.name,
'description': repo.description,
'is_public': model.repository.is_repository_public(repo),
'score': REPOSITORY_SEARCH_SCORE,
'href': '/' + kind + '/' + repo.namespace_user.username + '/' + repo.name
}
if last_modified is not None:
view['last_modified'] = last_modified
if stars is not None:
view['stars'] = stars
if popularity is not None:
view['popularity'] = popularity
return view
@resource('/v1/find/all')
class ConductSearch(ApiResource):
""" Resource for finding users, repositories, teams, etc. """
@ -306,3 +329,51 @@ class ConductSearch(ApiResource):
result['score'] = result['score'] * lm_score
return {'results': sorted(results, key=itemgetter('score'), reverse=True)}
MAX_PER_PAGE = 10
@resource('/v1/find/repositories')
class ConductRepositorySearch(ApiResource):
""" Resource for finding repositories. """
@parse_args()
@query_param('query', 'The search query.', type=str, default='')
@query_param('page', 'The page.', type=int, default=1)
@nickname('conductRepoSearch')
def get(self, parsed_args):
""" Get a list of apps and repositories that match the specified query. """
query = parsed_args['query']
if not query:
return {'results': []}
page = min(max(1, parsed_args['page']), 10)
offset = (page - 1) * MAX_PER_PAGE
limit = offset + MAX_PER_PAGE + 1
username = get_authenticated_user().username if get_authenticated_user() else None
# Lookup matching repositories.
matching_repos = list(model.repository.get_filtered_matching_repositories(query, username,
repo_kind=None,
limit=limit,
offset=offset))
# Load secondary information such as last modified time, star count and action count.
repository_ids = [repo.id for repo in matching_repos]
last_modified_map = model.repository.get_when_last_modified(repository_ids)
star_map = model.repository.get_stars(repository_ids)
action_sum_map = model.log.get_repositories_action_sums(repository_ids)
# Build the results list.
results = [repo_result_view(repo, username, last_modified_map.get(repo.id),
star_map.get(repo.id, 0),
float(action_sum_map.get(repo.id, 0)))
for repo in matching_repos]
return {
'results': results[0:MAX_PER_PAGE],
'has_additional': len(results) > MAX_PER_PAGE,
'page': page,
'page_size': MAX_PER_PAGE,
'start_index': offset,
}