##// END OF EJS Templates
search: allow result sorting for elasticsearch6
marcink -
r3963:107ed32f default
parent child Browse files
Show More
@@ -44,6 +44,7 b' def perform_search(request, tmpl_context'
44 44 search_tags = []
45 45 search_params = {}
46 46 errors = []
47
47 48 try:
48 49 search_params = schema.deserialize(
49 50 dict(
@@ -61,8 +62,8 b' def perform_search(request, tmpl_context'
61 62 def url_generator(**kw):
62 63 q = urllib.quote(safe_str(search_query))
63 64 return update_params(
64 "?q=%s&type=%s&max_lines=%s" % (
65 q, safe_str(search_type), search_max_lines), **kw)
65 "?q=%s&type=%s&max_lines=%s&sort=%s" % (
66 q, safe_str(search_type), search_max_lines, search_sort), **kw)
66 67
67 68 c = tmpl_context
68 69 search_query = search_params.get('search_query')
@@ -99,7 +100,6 b' def perform_search(request, tmpl_context'
99 100 c.perm_user = c.auth_user
100 101 c.repo_name = repo_name
101 102 c.repo_group_name = repo_group_name
102 c.sort = search_sort
103 103 c.url_generator = url_generator
104 104 c.errors = errors
105 105 c.formatted_results = formatted_results
@@ -109,6 +109,11 b' def perform_search(request, tmpl_context'
109 109 c.searcher = searcher
110 110 c.search_tags = search_tags
111 111
112 direction, sort_field = searcher.get_sort(search_type, search_sort)
113 c.sort = '{}:{}'.format(direction, sort_field)
114 c.sort_tag = sort_field
115 c.sort_tag_dir = direction
116
112 117
113 118 class SearchView(BaseAppView):
114 119 def load_default_context(self):
@@ -46,6 +46,8 b' class BaseSearcher(object):'
46 46 query_lang_doc = ''
47 47 es_version = None
48 48 name = None
49 DIRECTION_ASC = 'asc'
50 DIRECTION_DESC = 'desc'
49 51
50 52 def __init__(self):
51 53 pass
@@ -87,6 +89,37 b' class BaseSearcher(object):'
87 89 """
88 90 return val
89 91
92 @staticmethod
93 def get_sort(search_type, search_val):
94 """
95 Method used to parse the GET search sort value to a field and direction.
96 e.g asc:lines == asc, lines
97
98 There's also a legacy support for newfirst/oldfirst which defines commit
99 sorting only
100 """
101
102 direction = BaseSearcher.DIRECTION_ASC
103 sort_field = None
104
105 if not search_val:
106 return direction, sort_field
107
108 if search_val.startswith('asc:'):
109 sort_field = search_val[4:]
110 direction = BaseSearcher.DIRECTION_ASC
111 elif search_val.startswith('desc:'):
112 sort_field = search_val[5:]
113 direction = BaseSearcher.DIRECTION_DESC
114 elif search_val == 'newfirst' and search_type == 'commit':
115 sort_field = 'date'
116 direction = BaseSearcher.DIRECTION_DESC
117 elif search_val == 'oldfirst' and search_type == 'commit':
118 sort_field = 'date'
119 direction = BaseSearcher.DIRECTION_ASC
120
121 return direction, sort_field
122
90 123
91 124 def search_config(config, prefix='search.'):
92 125 _config = {}
@@ -22,6 +22,18 b''
22 22 import colander
23 23
24 24
25 def sort_validator(node, value):
26 if value in ['oldfirst', 'newfirst']:
27 return value
28 if value.startswith('asc:'):
29 return value
30 if value.startswith('desc:'):
31 return value
32
33 msg = u'Invalid search sort, must be `oldfirst`, `newfirst`, or start with asc: or desc:'
34 raise colander.Invalid(node, msg)
35
36
25 37 class SearchParamsSchema(colander.MappingSchema):
26 38 search_query = colander.SchemaNode(
27 39 colander.String(),
@@ -33,7 +45,7 b' class SearchParamsSchema(colander.Mappin'
33 45 search_sort = colander.SchemaNode(
34 46 colander.String(),
35 47 missing='newfirst',
36 validator=colander.OneOf(['oldfirst', 'newfirst']))
48 validator=sort_validator)
37 49 search_max_lines = colander.SchemaNode(
38 50 colander.Integer(),
39 51 missing=10)
@@ -60,6 +60,20 b''
60 60 <i class="icon-repo-group"></i>
61 61 </%def>
62 62
63
64 <%def name="field_sort(field_name)">
65
66 <%
67 if c.sort.startswith('asc:'):
68 return c.url_generator(sort='desc:{}'.format(field_name))
69 elif c.sort.startswith('desc:'):
70 return c.url_generator(sort='asc:{}'.format(field_name))
71
72 return 'asc:{}'.format(field_name)
73 %>
74 </%def>
75
76
63 77 <%def name="main()">
64 78 <div class="box">
65 79 %if c.repo_name:
@@ -114,6 +128,16 b''
114 128 </span>
115 129 %endif
116 130
131 % if c.sort_tag:
132 <span class="tag tag8">
133 % if c.sort_tag_dir == 'asc':
134 <i class="icon-angle-down"></i>
135 % elif c.sort_tag_dir == 'desc':
136 <i class="icon-angle-up"></i>
137 % endif
138 ${_('sort')}:${c.sort_tag}
139 </span>
140 % endif
117 141
118 142 % for search_tag in c.search_tags:
119 143 <br/><span class="tag disabled" style="margin-top: 3px">${search_tag}</span>
@@ -130,7 +154,7 b''
130 154 </span>
131 155 % endfor
132 156 <div class="field">
133 <p class="filterexample" style="position: inherit" onclick="$('#search-help').toggle()">${_('Query Langague examples')}</p>
157 <p class="filterexample" style="position: inherit" onclick="$('#search-help').toggle()">${_('Query Language examples')}</p>
134 158 <pre id="search-help" style="display: none">\
135 159
136 160 % if c.searcher.name == 'whoosh':
@@ -8,15 +8,15 b''
8 8 <th>${_('Repository')}</th>
9 9 <th>${_('Commit')}</th>
10 10 <th></th>
11 <th>${_('Commit message')}</th>
11 <th>
12 <a href="${search.field_sort('message.raw')}">${_('Commit message')}</a>
13 </th>
12 14 <th>
13 %if c.sort == 'newfirst':
14 <a href="${c.url_generator(sort='oldfirst')}">${_('Age (new first)')}</a>
15 %else:
16 <a href="${c.url_generator(sort='newfirst')}">${_('Age (old first)')}</a>
17 %endif
15 <a href="${search.field_sort('date')}">${_('Age')}</a>
18 16 </th>
19 <th>${_('Author')}</th>
17 <th>
18 <a href="${search.field_sort('author.email.raw')}">${_('Author')}</a>
19 </th>
20 20 </tr>
21 21 %for entry in c.formatted_results:
22 22 ## search results are additionally filtered, and this check is just a safe gate
@@ -5,9 +5,15 b''
5 5 <table class="rctable search-results">
6 6 <tr>
7 7 <th>${_('Repository')}</th>
8 <th>${_('File')}</th>
9 <th>${_('Size')}</th>
10 <th>${_('Lines')}</th>
8 <th>
9 <a href="${search.field_sort('file.raw')}">${_('File')}</a>
10 </th>
11 <th>
12 <a href="${search.field_sort('size')}">${_('Size')}</a>
13 </th>
14 <th>
15 <a href="${search.field_sort('lines')}">${_('Lines')}</a>
16 </th>
11 17 </tr>
12 18 %for entry in c.formatted_results:
13 19 ## search results are additionally filtered, and this check is just a safe gate
@@ -19,6 +25,7 b''
19 25 ${h.link_to(entry['repository'], h.route_path('repo_summary',repo_name=entry['repository']))}
20 26 </td>
21 27 <td class="td-componentname">
28 <i class="icon-file"></i>
22 29 ${h.link_to(h.literal(entry['f_path']),
23 30 h.route_path('repo_files',repo_name=entry['repository'],commit_id='tip',f_path=entry['f_path']))}
24 31 </td>
@@ -29,7 +36,7 b''
29 36 </td>
30 37 <td>
31 38 %if entry.get('lines'):
32 ${entry.get('lines', 0.)} ${_ungettext('line', 'lines', entry.get('lines', 0.))}
39 ${entry.get('lines', 0.)}
33 40 %endif
34 41 </td>
35 42 </tr>
General Comments 0
You need to be logged in to leave comments. Login now