search: allow result sorting for elasticsearch6
This commit is contained in:
parent
7cf63ac4ad
commit
bf69ffc8f0
6 changed files with 97 additions and 16 deletions
|
|
@ -44,6 +44,7 @@ def perform_search(request, tmpl_context, repo_name=None, repo_group_name=None):
|
|||
search_tags = []
|
||||
search_params = {}
|
||||
errors = []
|
||||
|
||||
try:
|
||||
search_params = schema.deserialize(
|
||||
dict(
|
||||
|
|
@ -61,8 +62,8 @@ def perform_search(request, tmpl_context, repo_name=None, repo_group_name=None):
|
|||
def url_generator(**kw):
|
||||
q = urllib.quote(safe_str(search_query))
|
||||
return update_params(
|
||||
"?q=%s&type=%s&max_lines=%s" % (
|
||||
q, safe_str(search_type), search_max_lines), **kw)
|
||||
"?q=%s&type=%s&max_lines=%s&sort=%s" % (
|
||||
q, safe_str(search_type), search_max_lines, search_sort), **kw)
|
||||
|
||||
c = tmpl_context
|
||||
search_query = search_params.get('search_query')
|
||||
|
|
@ -99,7 +100,6 @@ def perform_search(request, tmpl_context, repo_name=None, repo_group_name=None):
|
|||
c.perm_user = c.auth_user
|
||||
c.repo_name = repo_name
|
||||
c.repo_group_name = repo_group_name
|
||||
c.sort = search_sort
|
||||
c.url_generator = url_generator
|
||||
c.errors = errors
|
||||
c.formatted_results = formatted_results
|
||||
|
|
@ -109,6 +109,11 @@ def perform_search(request, tmpl_context, repo_name=None, repo_group_name=None):
|
|||
c.searcher = searcher
|
||||
c.search_tags = search_tags
|
||||
|
||||
direction, sort_field = searcher.get_sort(search_type, search_sort)
|
||||
c.sort = '{}:{}'.format(direction, sort_field)
|
||||
c.sort_tag = sort_field
|
||||
c.sort_tag_dir = direction
|
||||
|
||||
|
||||
class SearchView(BaseAppView):
|
||||
def load_default_context(self):
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ class BaseSearcher(object):
|
|||
query_lang_doc = ''
|
||||
es_version = None
|
||||
name = None
|
||||
DIRECTION_ASC = 'asc'
|
||||
DIRECTION_DESC = 'desc'
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
|
@ -87,6 +89,37 @@ class BaseSearcher(object):
|
|||
"""
|
||||
return val
|
||||
|
||||
@staticmethod
|
||||
def get_sort(search_type, search_val):
|
||||
"""
|
||||
Method used to parse the GET search sort value to a field and direction.
|
||||
e.g asc:lines == asc, lines
|
||||
|
||||
There's also a legacy support for newfirst/oldfirst which defines commit
|
||||
sorting only
|
||||
"""
|
||||
|
||||
direction = BaseSearcher.DIRECTION_ASC
|
||||
sort_field = None
|
||||
|
||||
if not search_val:
|
||||
return direction, sort_field
|
||||
|
||||
if search_val.startswith('asc:'):
|
||||
sort_field = search_val[4:]
|
||||
direction = BaseSearcher.DIRECTION_ASC
|
||||
elif search_val.startswith('desc:'):
|
||||
sort_field = search_val[5:]
|
||||
direction = BaseSearcher.DIRECTION_DESC
|
||||
elif search_val == 'newfirst' and search_type == 'commit':
|
||||
sort_field = 'date'
|
||||
direction = BaseSearcher.DIRECTION_DESC
|
||||
elif search_val == 'oldfirst' and search_type == 'commit':
|
||||
sort_field = 'date'
|
||||
direction = BaseSearcher.DIRECTION_ASC
|
||||
|
||||
return direction, sort_field
|
||||
|
||||
|
||||
def search_config(config, prefix='search.'):
|
||||
_config = {}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,18 @@
|
|||
import colander
|
||||
|
||||
|
||||
def sort_validator(node, value):
|
||||
if value in ['oldfirst', 'newfirst']:
|
||||
return value
|
||||
if value.startswith('asc:'):
|
||||
return value
|
||||
if value.startswith('desc:'):
|
||||
return value
|
||||
|
||||
msg = u'Invalid search sort, must be `oldfirst`, `newfirst`, or start with asc: or desc:'
|
||||
raise colander.Invalid(node, msg)
|
||||
|
||||
|
||||
class SearchParamsSchema(colander.MappingSchema):
|
||||
search_query = colander.SchemaNode(
|
||||
colander.String(),
|
||||
|
|
@ -33,7 +45,7 @@ class SearchParamsSchema(colander.MappingSchema):
|
|||
search_sort = colander.SchemaNode(
|
||||
colander.String(),
|
||||
missing='newfirst',
|
||||
validator=colander.OneOf(['oldfirst', 'newfirst']))
|
||||
validator=sort_validator)
|
||||
search_max_lines = colander.SchemaNode(
|
||||
colander.Integer(),
|
||||
missing=10)
|
||||
|
|
|
|||
|
|
@ -60,6 +60,20 @@
|
|||
<i class="icon-repo-group"></i>
|
||||
</%def>
|
||||
|
||||
|
||||
<%def name="field_sort(field_name)">
|
||||
|
||||
<%
|
||||
if c.sort.startswith('asc:'):
|
||||
return c.url_generator(sort='desc:{}'.format(field_name))
|
||||
elif c.sort.startswith('desc:'):
|
||||
return c.url_generator(sort='asc:{}'.format(field_name))
|
||||
|
||||
return 'asc:{}'.format(field_name)
|
||||
%>
|
||||
</%def>
|
||||
|
||||
|
||||
<%def name="main()">
|
||||
<div class="box">
|
||||
%if c.repo_name:
|
||||
|
|
@ -114,6 +128,16 @@
|
|||
</span>
|
||||
%endif
|
||||
|
||||
% if c.sort_tag:
|
||||
<span class="tag tag8">
|
||||
% if c.sort_tag_dir == 'asc':
|
||||
<i class="icon-angle-down"></i>
|
||||
% elif c.sort_tag_dir == 'desc':
|
||||
<i class="icon-angle-up"></i>
|
||||
% endif
|
||||
${_('sort')}:${c.sort_tag}
|
||||
</span>
|
||||
% endif
|
||||
|
||||
% for search_tag in c.search_tags:
|
||||
<br/><span class="tag disabled" style="margin-top: 3px">${search_tag}</span>
|
||||
|
|
@ -130,7 +154,7 @@
|
|||
</span>
|
||||
% endfor
|
||||
<div class="field">
|
||||
<p class="filterexample" style="position: inherit" onclick="$('#search-help').toggle()">${_('Query Langague examples')}</p>
|
||||
<p class="filterexample" style="position: inherit" onclick="$('#search-help').toggle()">${_('Query Language examples')}</p>
|
||||
<pre id="search-help" style="display: none">\
|
||||
|
||||
% if c.searcher.name == 'whoosh':
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@
|
|||
<th>${_('Repository')}</th>
|
||||
<th>${_('Commit')}</th>
|
||||
<th></th>
|
||||
<th>${_('Commit message')}</th>
|
||||
<th>
|
||||
%if c.sort == 'newfirst':
|
||||
<a href="${c.url_generator(sort='oldfirst')}">${_('Age (new first)')}</a>
|
||||
%else:
|
||||
<a href="${c.url_generator(sort='newfirst')}">${_('Age (old first)')}</a>
|
||||
%endif
|
||||
<a href="${search.field_sort('message.raw')}">${_('Commit message')}</a>
|
||||
</th>
|
||||
<th>
|
||||
<a href="${search.field_sort('date')}">${_('Age')}</a>
|
||||
</th>
|
||||
<th>
|
||||
<a href="${search.field_sort('author.email.raw')}">${_('Author')}</a>
|
||||
</th>
|
||||
<th>${_('Author')}</th>
|
||||
</tr>
|
||||
%for entry in c.formatted_results:
|
||||
## search results are additionally filtered, and this check is just a safe gate
|
||||
|
|
|
|||
|
|
@ -5,9 +5,15 @@
|
|||
<table class="rctable search-results">
|
||||
<tr>
|
||||
<th>${_('Repository')}</th>
|
||||
<th>${_('File')}</th>
|
||||
<th>${_('Size')}</th>
|
||||
<th>${_('Lines')}</th>
|
||||
<th>
|
||||
<a href="${search.field_sort('file.raw')}">${_('File')}</a>
|
||||
</th>
|
||||
<th>
|
||||
<a href="${search.field_sort('size')}">${_('Size')}</a>
|
||||
</th>
|
||||
<th>
|
||||
<a href="${search.field_sort('lines')}">${_('Lines')}</a>
|
||||
</th>
|
||||
</tr>
|
||||
%for entry in c.formatted_results:
|
||||
## search results are additionally filtered, and this check is just a safe gate
|
||||
|
|
@ -19,6 +25,7 @@
|
|||
${h.link_to(entry['repository'], h.route_path('repo_summary',repo_name=entry['repository']))}
|
||||
</td>
|
||||
<td class="td-componentname">
|
||||
<i class="icon-file"></i>
|
||||
${h.link_to(h.literal(entry['f_path']),
|
||||
h.route_path('repo_files',repo_name=entry['repository'],commit_id='tip',f_path=entry['f_path']))}
|
||||
</td>
|
||||
|
|
@ -29,7 +36,7 @@
|
|||
</td>
|
||||
<td>
|
||||
%if entry.get('lines'):
|
||||
${entry.get('lines', 0.)} ${_ungettext('line', 'lines', entry.get('lines', 0.))}
|
||||
${entry.get('lines', 0.)}
|
||||
%endif
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue