diff --git a/rhodecode/apps/search/views.py b/rhodecode/apps/search/views.py --- a/rhodecode/apps/search/views.py +++ b/rhodecode/apps/search/views.py @@ -44,6 +44,7 @@ def perform_search(request, tmpl_context search_tags = [] search_params = {} errors = [] + try: search_params = schema.deserialize( dict( @@ -61,8 +62,8 @@ def perform_search(request, tmpl_context 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 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 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): diff --git a/rhodecode/lib/index/__init__.py b/rhodecode/lib/index/__init__.py --- a/rhodecode/lib/index/__init__.py +++ b/rhodecode/lib/index/__init__.py @@ -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 = {} diff --git a/rhodecode/model/validation_schema/schemas/search_schema.py b/rhodecode/model/validation_schema/schemas/search_schema.py --- a/rhodecode/model/validation_schema/schemas/search_schema.py +++ b/rhodecode/model/validation_schema/schemas/search_schema.py @@ -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.Mappin 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) diff --git a/rhodecode/templates/search/search.mako b/rhodecode/templates/search/search.mako --- a/rhodecode/templates/search/search.mako +++ b/rhodecode/templates/search/search.mako @@ -60,6 +60,20 @@ + +<%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 name="main()">
%if c.repo_name: @@ -114,6 +128,16 @@ %endif + % if c.sort_tag: + + % if c.sort_tag_dir == 'asc': + + % elif c.sort_tag_dir == 'desc': + + % endif + ${_('sort')}:${c.sort_tag} + + % endif % for search_tag in c.search_tags:
${search_tag} @@ -130,7 +154,7 @@ % endfor
-

${_('Query Langague examples')}

+

${_('Query Language examples')}