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:
parent
8b148bf1d4
commit
e9ffe0e27b
23 changed files with 649 additions and 393 deletions
|
@ -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,
|
||||
}
|
||||
|
|
Reference in a new issue