##// END OF EJS Templates
ui: expose search as a visible option for repositories.
ergo -
r3440:92d2ae7e default
parent child Browse files
Show More
@@ -1,138 +1,138 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22 import urllib
23 23 from pyramid.view import view_config
24 24 from webhelpers.util import update_params
25 25
26 26 from rhodecode.apps._base import BaseAppView, RepoAppView
27 27 from rhodecode.lib.auth import (LoginRequired, HasRepoPermissionAnyDecorator)
28 28 from rhodecode.lib.helpers import Page
29 29 from rhodecode.lib.utils2 import safe_str
30 30 from rhodecode.lib.index import searcher_from_config
31 31 from rhodecode.model import validation_schema
32 32 from rhodecode.model.validation_schema.schemas import search_schema
33 33
34 34 log = logging.getLogger(__name__)
35 35
36 36
37 37 def search(request, tmpl_context, repo_name):
38 38 searcher = searcher_from_config(request.registry.settings)
39 39 formatted_results = []
40 40 execution_time = ''
41 41
42 42 schema = search_schema.SearchParamsSchema()
43 43
44 44 search_params = {}
45 45 errors = []
46 46 try:
47 47 search_params = schema.deserialize(
48 48 dict(
49 49 search_query=request.GET.get('q'),
50 50 search_type=request.GET.get('type'),
51 51 search_sort=request.GET.get('sort'),
52 52 search_max_lines=request.GET.get('max_lines'),
53 53 page_limit=request.GET.get('page_limit'),
54 54 requested_page=request.GET.get('page'),
55 55 )
56 56 )
57 57 except validation_schema.Invalid as e:
58 58 errors = e.children
59 59
60 60 def url_generator(**kw):
61 61 q = urllib.quote(safe_str(search_query))
62 62 return update_params(
63 63 "?q=%s&type=%s&max_lines=%s" % (q, safe_str(search_type), search_max_lines), **kw)
64 64
65 65 c = tmpl_context
66 66 search_query = search_params.get('search_query')
67 67 search_type = search_params.get('search_type')
68 68 search_sort = search_params.get('search_sort')
69 69 search_max_lines = search_params.get('search_max_lines')
70 70 if search_params.get('search_query'):
71 71 page_limit = search_params['page_limit']
72 72 requested_page = search_params['requested_page']
73 73
74 74 try:
75 75 search_result = searcher.search(
76 76 search_query, search_type, c.auth_user, repo_name,
77 77 requested_page, page_limit, search_sort)
78 78
79 79 formatted_results = Page(
80 80 search_result['results'], page=requested_page,
81 81 item_count=search_result['count'],
82 82 items_per_page=page_limit, url=url_generator)
83 83 finally:
84 84 searcher.cleanup()
85 85
86 86 if not search_result['error']:
87 87 execution_time = '%s results (%.3f seconds)' % (
88 88 search_result['count'],
89 89 search_result['runtime'])
90 90 elif not errors:
91 91 node = schema['search_query']
92 92 errors = [
93 93 validation_schema.Invalid(node, search_result['error'])]
94 94
95 95 c.perm_user = c.auth_user
96 96 c.repo_name = repo_name
97 97 c.sort = search_sort
98 98 c.url_generator = url_generator
99 99 c.errors = errors
100 100 c.formatted_results = formatted_results
101 101 c.runtime = execution_time
102 102 c.cur_query = search_query
103 103 c.search_type = search_type
104 104 c.searcher = searcher
105 105
106 106
107 107 class SearchView(BaseAppView):
108 108 def load_default_context(self):
109 109 c = self._get_local_tmpl_context()
110 110
111 111 return c
112 112
113 113 @LoginRequired()
114 114 @view_config(
115 115 route_name='search', request_method='GET',
116 116 renderer='rhodecode:templates/search/search.mako')
117 117 def search(self):
118 118 c = self.load_default_context()
119 119 search(self.request, c, repo_name=None)
120 120 return self._get_template_context(c)
121 121
122 122
123 123 class SearchRepoView(RepoAppView):
124 124 def load_default_context(self):
125 125 c = self._get_local_tmpl_context()
126
126 c.active = 'search'
127 127 return c
128 128
129 129 @LoginRequired()
130 130 @HasRepoPermissionAnyDecorator(
131 131 'repository.read', 'repository.write', 'repository.admin')
132 132 @view_config(
133 133 route_name='search_repo', request_method='GET',
134 134 renderer='rhodecode:templates/search/search.mako')
135 135 def search_repo(self):
136 136 c = self.load_default_context()
137 137 search(self.request, c, repo_name=self.db_repo_name)
138 138 return self._get_template_context(c)
@@ -1,728 +1,729 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="root.mako"/>
3 3
4 4 <%include file="/ejs_templates/templates.html"/>
5 5
6 6 <div class="outerwrapper">
7 7 <!-- HEADER -->
8 8 <div class="header">
9 9 <div id="header-inner" class="wrapper">
10 10 <div id="logo">
11 11 <div class="logo-wrapper">
12 12 <a href="${h.route_path('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
13 13 </div>
14 14 %if c.rhodecode_name:
15 15 <div class="branding">- ${h.branding(c.rhodecode_name)}</div>
16 16 %endif
17 17 </div>
18 18 <!-- MENU BAR NAV -->
19 19 ${self.menu_bar_nav()}
20 20 <!-- END MENU BAR NAV -->
21 21 </div>
22 22 </div>
23 23 ${self.menu_bar_subnav()}
24 24 <!-- END HEADER -->
25 25
26 26 <!-- CONTENT -->
27 27 <div id="content" class="wrapper">
28 28
29 29 <rhodecode-toast id="notifications"></rhodecode-toast>
30 30
31 31 <div class="main">
32 32 ${next.main()}
33 33 </div>
34 34 </div>
35 35 <!-- END CONTENT -->
36 36
37 37 </div>
38 38 <!-- FOOTER -->
39 39 <div id="footer">
40 40 <div id="footer-inner" class="title wrapper">
41 41 <div>
42 42 <p class="footer-link-right">
43 43 % if c.visual.show_version:
44 44 RhodeCode Enterprise ${c.rhodecode_version} ${c.rhodecode_edition}
45 45 % endif
46 46 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
47 47 % if c.visual.rhodecode_support_url:
48 48 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
49 49 % endif
50 50 </p>
51 51 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
52 52 <p class="server-instance" style="display:${sid}">
53 53 ## display hidden instance ID if specially defined
54 54 % if c.rhodecode_instanceid:
55 55 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
56 56 % endif
57 57 </p>
58 58 </div>
59 59 </div>
60 60 </div>
61 61
62 62 <!-- END FOOTER -->
63 63
64 64 ### MAKO DEFS ###
65 65
66 66 <%def name="menu_bar_subnav()">
67 67 </%def>
68 68
69 69 <%def name="breadcrumbs(class_='breadcrumbs')">
70 70 <div class="${class_}">
71 71 ${self.breadcrumbs_links()}
72 72 </div>
73 73 </%def>
74 74
75 75 <%def name="admin_menu()">
76 76 <ul class="admin_menu submenu">
77 77 <li><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li>
78 78 <li><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
79 79 <li><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
80 80 <li><a href="${h.route_path('users')}">${_('Users')}</a></li>
81 81 <li><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
82 82 <li><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
83 83 <li><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
84 84 <li><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
85 85 <li><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
86 86 <li class="last"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
87 87 </ul>
88 88 </%def>
89 89
90 90
91 91 <%def name="dt_info_panel(elements)">
92 92 <dl class="dl-horizontal">
93 93 %for dt, dd, title, show_items in elements:
94 94 <dt>${dt}:</dt>
95 95 <dd title="${h.tooltip(title)}">
96 96 %if callable(dd):
97 97 ## allow lazy evaluation of elements
98 98 ${dd()}
99 99 %else:
100 100 ${dd}
101 101 %endif
102 102 %if show_items:
103 103 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
104 104 %endif
105 105 </dd>
106 106
107 107 %if show_items:
108 108 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
109 109 %for item in show_items:
110 110 <dt></dt>
111 111 <dd>${item}</dd>
112 112 %endfor
113 113 </div>
114 114 %endif
115 115
116 116 %endfor
117 117 </dl>
118 118 </%def>
119 119
120 120
121 121 <%def name="gravatar(email, size=16)">
122 122 <%
123 123 if (size > 16):
124 124 gravatar_class = 'gravatar gravatar-large'
125 125 else:
126 126 gravatar_class = 'gravatar'
127 127 %>
128 128 <%doc>
129 129 TODO: johbo: For now we serve double size images to make it smooth
130 130 for retina. This is how it worked until now. Should be replaced
131 131 with a better solution at some point.
132 132 </%doc>
133 133 <img class="${gravatar_class}" src="${h.gravatar_url(email, size * 2)}" height="${size}" width="${size}">
134 134 </%def>
135 135
136 136
137 137 <%def name="gravatar_with_user(contact, size=16, show_disabled=False)">
138 138 <% email = h.email_or_none(contact) %>
139 139 <div class="rc-user tooltip" title="${h.tooltip(h.author_string(email))}">
140 140 ${self.gravatar(email, size)}
141 141 <span class="${'user user-disabled' if show_disabled else 'user'}"> ${h.link_to_user(contact)}</span>
142 142 </div>
143 143 </%def>
144 144
145 145
146 146 ## admin menu used for people that have some admin resources
147 147 <%def name="admin_menu_simple(repositories=None, repository_groups=None, user_groups=None)">
148 148 <ul class="submenu">
149 149 %if repositories:
150 150 <li class="local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
151 151 %endif
152 152 %if repository_groups:
153 153 <li class="local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
154 154 %endif
155 155 %if user_groups:
156 156 <li class="local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
157 157 %endif
158 158 </ul>
159 159 </%def>
160 160
161 161 <%def name="repo_page_title(repo_instance)">
162 162 <div class="title-content">
163 163 <div class="title-main">
164 164 ## SVN/HG/GIT icons
165 165 %if h.is_hg(repo_instance):
166 166 <i class="icon-hg"></i>
167 167 %endif
168 168 %if h.is_git(repo_instance):
169 169 <i class="icon-git"></i>
170 170 %endif
171 171 %if h.is_svn(repo_instance):
172 172 <i class="icon-svn"></i>
173 173 %endif
174 174
175 175 ## public/private
176 176 %if repo_instance.private:
177 177 <i class="icon-repo-private"></i>
178 178 %else:
179 179 <i class="icon-repo-public"></i>
180 180 %endif
181 181
182 182 ## repo name with group name
183 183 ${h.breadcrumb_repo_link(c.rhodecode_db_repo)}
184 184
185 185 </div>
186 186
187 187 ## FORKED
188 188 %if repo_instance.fork:
189 189 <p>
190 190 <i class="icon-code-fork"></i> ${_('Fork of')}
191 191 ${h.link_to_if(c.has_origin_repo_read_perm,repo_instance.fork.repo_name, h.route_path('repo_summary', repo_name=repo_instance.fork.repo_name))}
192 192 </p>
193 193 %endif
194 194
195 195 ## IMPORTED FROM REMOTE
196 196 %if repo_instance.clone_uri:
197 197 <p>
198 198 <i class="icon-code-fork"></i> ${_('Clone from')}
199 199 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
200 200 </p>
201 201 %endif
202 202
203 203 ## LOCKING STATUS
204 204 %if repo_instance.locked[0]:
205 205 <p class="locking_locked">
206 206 <i class="icon-repo-lock"></i>
207 207 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
208 208 </p>
209 209 %elif repo_instance.enable_locking:
210 210 <p class="locking_unlocked">
211 211 <i class="icon-repo-unlock"></i>
212 212 ${_('Repository not locked. Pull repository to lock it.')}
213 213 </p>
214 214 %endif
215 215
216 216 </div>
217 217 </%def>
218 218
219 219 <%def name="repo_menu(active=None)">
220 220 <%
221 221 def is_active(selected):
222 222 if selected == active:
223 223 return "active"
224 224 %>
225 225
226 226 <!--- CONTEXT BAR -->
227 227 <div id="context-bar">
228 228 <div class="wrapper">
229 229 <ul id="context-pages" class="navigation horizontal-list">
230 230 <li class="${is_active('summary')}"><a class="menulink" href="${h.route_path('repo_summary', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
231 231 <li class="${is_active('changelog')}"><a class="menulink" href="${h.route_path('repo_changelog', repo_name=c.repo_name)}"><div class="menulabel">${_('Changelog')}</div></a></li>
232 232 <li class="${is_active('files')}"><a class="menulink" href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.rhodecode_db_repo.landing_rev[1], f_path='')}"><div class="menulabel">${_('Files')}</div></a></li>
233 233 <li class="${is_active('compare')}"><a class="menulink" href="${h.route_path('repo_compare_select',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a></li>
234 <li class="${is_active('search')}"><a class="menulink" href="${h.route_path('search_repo',repo_name=c.repo_name)}"><div class="menulabel">${_('Search')}</div></a></li>
235
234 236 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
235 237 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
236 238 <li class="${is_active('showpullrequest')}">
237 239 <a class="menulink" href="${h.route_path('pullrequest_show_all', repo_name=c.repo_name)}" title="${h.tooltip(_('Show Pull Requests for %s') % c.repo_name)}">
238 240 %if c.repository_pull_requests:
239 241 <span class="pr_notifications">${c.repository_pull_requests}</span>
240 242 %endif
241 243 <div class="menulabel">${_('Pull Requests')}</div>
242 244 </a>
243 245 </li>
244 246 %endif
247
245 248 <li class="${is_active('options')}">
246 249 <a class="menulink dropdown">
247 250 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
248 251 </a>
249 252 <ul class="submenu">
250 253 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
251 254 <li><a href="${h.route_path('edit_repo',repo_name=c.repo_name)}">${_('Settings')}</a></li>
252 255 %endif
253 256 %if c.rhodecode_db_repo.fork:
254 257 <li>
255 258 <a title="${h.tooltip(_('Compare fork with %s' % c.rhodecode_db_repo.fork.repo_name))}"
256 259 href="${h.route_path('repo_compare',
257 260 repo_name=c.rhodecode_db_repo.fork.repo_name,
258 261 source_ref_type=c.rhodecode_db_repo.landing_rev[0],
259 262 source_ref=c.rhodecode_db_repo.landing_rev[1],
260 263 target_repo=c.repo_name,target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],
261 264 target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1],
262 265 _query=dict(merge=1))}"
263 266 >
264 267 ${_('Compare fork')}
265 268 </a>
266 269 </li>
267 270 %endif
268 271
269 <li><a href="${h.route_path('search_repo',repo_name=c.repo_name)}">${_('Search')}</a></li>
270
271 272 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
272 273 %if c.rhodecode_db_repo.locked[0]:
273 274 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock')}</a></li>
274 275 %else:
275 276 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock')}</a></li>
276 277 %endif
277 278 %endif
278 279 %if c.rhodecode_user.username != h.DEFAULT_USER:
279 280 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
280 281 <li><a href="${h.route_path('repo_fork_new',repo_name=c.repo_name)}">${_('Fork')}</a></li>
281 282 <li><a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
282 283 %endif
283 284 %endif
284 285 </ul>
285 286 </li>
286 287 </ul>
287 288 </div>
288 289 <div class="clear"></div>
289 290 </div>
290 291 % if c.rhodecode_db_repo.archived:
291 292 <div class="alert alert-warning text-center">
292 293 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
293 294 </div>
294 295 % endif
295 296 <!--- END CONTEXT BAR -->
296 297
297 298 </%def>
298 299
299 300 <%def name="usermenu(active=False)">
300 301 ## USER MENU
301 302 <li id="quick_login_li" class="${'active' if active else ''}">
302 303 % if c.rhodecode_user.username == h.DEFAULT_USER:
303 304 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
304 305 ${gravatar(c.rhodecode_user.email, 20)}
305 306 <span class="user">
306 307 <span>${_('Sign in')}</span>
307 308 </span>
308 309 </a>
309 310 % else:
310 311 ## logged in user
311 312 <a id="quick_login_link" class="menulink childs">
312 313 ${gravatar(c.rhodecode_user.email, 20)}
313 314 <span class="user">
314 315 <span class="menu_link_user">${c.rhodecode_user.username}</span>
315 316 <div class="show_more"></div>
316 317 </span>
317 318 </a>
318 319 ## subnav with menu for logged in user
319 320 <div class="user-menu submenu">
320 321 <div id="quick_login">
321 322 %if c.rhodecode_user.username != h.DEFAULT_USER:
322 323 <div class="">
323 324 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
324 325 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
325 326 <div class="email">${c.rhodecode_user.email}</div>
326 327 </div>
327 328 <div class="">
328 329 <ol class="links">
329 330 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
330 331 % if c.rhodecode_user.personal_repo_group:
331 332 <li>${h.link_to(_(u'My personal group'), h.route_path('repo_group_home', repo_group_name=c.rhodecode_user.personal_repo_group.group_name))}</li>
332 333 % endif
333 334 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
334 335 ## bookmark-items
335 336 <li class="bookmark-items">
336 337 ${_('Bookmarks')}
337 338 <div class="pull-right">
338 339 <a href="${h.route_path('my_account_bookmarks')}">${_('Manage')}</a>
339 340 </div>
340 341 </li>
341 342 % if not c.bookmark_items:
342 343 <li>
343 344 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
344 345 </li>
345 346 % endif
346 347 % for item in c.bookmark_items:
347 348 <li>
348 349 % if item.repository:
349 350 <div>
350 351 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
351 352 <code>${item.position}</code>
352 353 % if item.repository.repo_type == 'hg':
353 354 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
354 355 % elif item.repository.repo_type == 'git':
355 356 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
356 357 % elif item.repository.repo_type == 'svn':
357 358 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
358 359 % endif
359 360 ${(item.title or h.shorter(item.repository.repo_name, 30))}
360 361 </a>
361 362 </div>
362 363 % elif item.repository_group:
363 364 <div>
364 365 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
365 366 <code>${item.position}</code>
366 367 <i class="icon-folder-close" title="${_('Repository group')}" style="font-size: 16px"></i>
367 368 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
368 369 </a>
369 370 </div>
370 371 % else:
371 372 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
372 373 <code>${item.position}</code>
373 374 ${item.title}
374 375 </a>
375 376 % endif
376 377 </li>
377 378 % endfor
378 379
379 380 <li class="logout">
380 381 ${h.secure_form(h.route_path('logout'), request=request)}
381 382 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
382 383 ${h.end_form()}
383 384 </li>
384 385 </ol>
385 386 </div>
386 387 %endif
387 388 </div>
388 389 </div>
389 390 ## unread counter
390 391 <div class="pill_container">
391 392 <a class="menu_link_notifications ${'empty' if c.unread_notifications == 0 else ''}" href="${h.route_path('notifications_show_all')}">${c.unread_notifications}</a>
392 393 </div>
393 394 % endif
394 395 </li>
395 396 </%def>
396 397
397 398 <%def name="menu_items(active=None)">
398 399 <%
399 400 def is_active(selected):
400 401 if selected == active:
401 402 return "active"
402 403 return ""
403 404 %>
404 405
405 406 <ul id="quick" class="main_nav navigation horizontal-list">
406 407 ## notice box for important system messages
407 408 <li style="display: none">
408 409 <a class="notice-box" href="#openNotice" onclick="showNoticeBox(); return false">
409 410 <div class="menulabel-notice" >
410 411 0
411 412 </div>
412 413 </a>
413 414 </li>
414 415
415 416 ## Main filter
416 417 <li>
417 418 <div class="menulabel main_filter_box">
418 419 <div class="main_filter_input_box">
419 420 <input class="main_filter_input" id="main_filter" size="15" type="text" name="main_filter" placeholder="${_('search / go to...')}" value=""/>
420 421 </div>
421 422 <div class="main_filter_help_box">
422 423 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
423 424 </div>
424 425 </div>
425 426
426 427 <div id="main_filter_help" style="display: none">
427 428 Use '/' key to quickly access this field.
428 429 Enter name of repository, or repository group for quick search.
429 430
430 431 Prefix query to allow special search:
431 432
432 433 user:admin, to search for usernames
433 434
434 435 user_group:devops, to search for user groups
435 436
436 437 commit:efced4, to search for commits
437 438
438 439 </div>
439 440 </li>
440 441
441 442 ## ROOT MENU
442 443 %if c.rhodecode_user.username != h.DEFAULT_USER:
443 444 <li class="${is_active('journal')}">
444 445 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
445 446 <div class="menulabel">${_('Journal')}</div>
446 447 </a>
447 448 </li>
448 449 %else:
449 450 <li class="${is_active('journal')}">
450 451 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
451 452 <div class="menulabel">${_('Public journal')}</div>
452 453 </a>
453 454 </li>
454 455 %endif
455 456 <li class="${is_active('gists')}">
456 457 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
457 458 <div class="menulabel">${_('Gists')}</div>
458 459 </a>
459 460 </li>
460 461 <li class="${is_active('search')}">
461 462 <a class="menulink" title="${_('Search in repositories you have access to')}" href="${h.route_path('search')}">
462 463 <div class="menulabel">${_('Search')}</div>
463 464 </a>
464 465 </li>
465 466 % if h.HasPermissionAll('hg.admin')('access admin main page'):
466 467 <li class="${is_active('admin')}">
467 468 <a class="menulink childs" title="${_('Admin settings')}" href="#" onclick="return false;">
468 469 <div class="menulabel">${_('Admin')} <div class="show_more"></div></div>
469 470 </a>
470 471 ${admin_menu()}
471 472 </li>
472 473 % elif c.rhodecode_user.repositories_admin or c.rhodecode_user.repository_groups_admin or c.rhodecode_user.user_groups_admin:
473 474 <li class="${is_active('admin')}">
474 475 <a class="menulink childs" title="${_('Delegated Admin settings')}">
475 476 <div class="menulabel">${_('Admin')} <div class="show_more"></div></div>
476 477 </a>
477 478 ${admin_menu_simple(c.rhodecode_user.repositories_admin,
478 479 c.rhodecode_user.repository_groups_admin,
479 480 c.rhodecode_user.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
480 481 </li>
481 482 % endif
482 483 ## render extra user menu
483 484 ${usermenu(active=(active=='my_account'))}
484 485
485 486 % if c.debug_style:
486 487 <li>
487 488 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
488 489 <div class="menulabel">${_('[Style]')}</div>
489 490 </a>
490 491 </li>
491 492 % endif
492 493 </ul>
493 494
494 495 <script type="text/javascript">
495 496 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
496 497
497 498 var formatRepoResult = function(result, container, query, escapeMarkup) {
498 499 return function(data, escapeMarkup) {
499 500 if (!data.repo_id){
500 501 return data.text; // optgroup text Repositories
501 502 }
502 503
503 504 var tmpl = '';
504 505 var repoType = data['repo_type'];
505 506 var repoName = data['text'];
506 507
507 508 if(data && data.type == 'repo'){
508 509 if(repoType === 'hg'){
509 510 tmpl += '<i class="icon-hg"></i> ';
510 511 }
511 512 else if(repoType === 'git'){
512 513 tmpl += '<i class="icon-git"></i> ';
513 514 }
514 515 else if(repoType === 'svn'){
515 516 tmpl += '<i class="icon-svn"></i> ';
516 517 }
517 518 if(data['private']){
518 519 tmpl += '<i class="icon-lock" ></i> ';
519 520 }
520 521 else if(visualShowPublicIcon){
521 522 tmpl += '<i class="icon-unlock-alt"></i> ';
522 523 }
523 524 }
524 525 tmpl += escapeMarkup(repoName);
525 526 return tmpl;
526 527
527 528 }(result, escapeMarkup);
528 529 };
529 530
530 531 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
531 532 return function(data, escapeMarkup) {
532 533 if (!data.repo_group_id){
533 534 return data.text; // optgroup text Repositories
534 535 }
535 536
536 537 var tmpl = '';
537 538 var repoGroupName = data['text'];
538 539
539 540 if(data){
540 541
541 542 tmpl += '<i class="icon-folder-close"></i> ';
542 543
543 544 }
544 545 tmpl += escapeMarkup(repoGroupName);
545 546 return tmpl;
546 547
547 548 }(result, escapeMarkup);
548 549 };
549 550
550 551
551 552 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
552 553
553 554 if (value.split(':').length === 2) {
554 555 value = value.split(':')[1]
555 556 }
556 557
557 558 var searchType = data['type'];
558 559 var valueDisplay = data['value_display'];
559 560
560 561 var escapeRegExChars = function (value) {
561 562 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
562 563 };
563 564 var pattern = '(' + escapeRegExChars(value) + ')';
564 565
565 566 // highlight match
566 567 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
567 568 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
568 569
569 570 var icon = '';
570 571
571 572 if (searchType === 'hint') {
572 573 icon += '<i class="icon-folder-close"></i> ';
573 574 }
574 575 else if (searchType === 'search') {
575 576 icon += '<i class="icon-more"></i> ';
576 577 }
577 578 else if (searchType === 'repo') {
578 579 if (data['repo_type'] === 'hg') {
579 580 icon += '<i class="icon-hg"></i> ';
580 581 }
581 582 else if (data['repo_type'] === 'git') {
582 583 icon += '<i class="icon-git"></i> ';
583 584 }
584 585 else if (data['repo_type'] === 'svn') {
585 586 icon += '<i class="icon-svn"></i> ';
586 587 }
587 588 if (data['private']) {
588 589 icon += '<i class="icon-lock" ></i> ';
589 590 }
590 591 else if (visualShowPublicIcon) {
591 592 icon += '<i class="icon-unlock-alt"></i> ';
592 593 }
593 594 }
594 595 else if (searchType === 'repo_group') {
595 596 icon += '<i class="icon-folder-close"></i> ';
596 597 }
597 598 else if (searchType === 'user_group') {
598 599 icon += '<i class="icon-group"></i> ';
599 600 }
600 601 else if (searchType === 'user') {
601 602 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
602 603 }
603 604 else if (searchType === 'commit') {
604 605 icon += '<i class="icon-tag"></i>';
605 606 }
606 607
607 608 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
608 609 return tmpl.format(icon, valueDisplay);
609 610 };
610 611
611 612 var handleSelect = function(element, suggestion) {
612 613 if (suggestion.type === "hint") {
613 614 // we skip action
614 615 $('#main_filter').focus();
615 616 } else {
616 617 window.location = suggestion['url'];
617 618 }
618 619 };
619 620 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
620 621 if (queryLowerCase.split(':').length === 2) {
621 622 queryLowerCase = queryLowerCase.split(':')[1]
622 623 }
623 624 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
624 625 };
625 626
626 627 $('#main_filter').autocomplete({
627 628 serviceUrl: pyroutes.url('goto_switcher_data'),
628 629 params: {"search_context": templateContext.search_context},
629 630 minChars:2,
630 631 maxHeight:400,
631 632 deferRequestBy: 300, //miliseconds
632 633 tabDisabled: true,
633 634 autoSelectFirst: true,
634 635 formatResult: autocompleteMainFilterFormatResult,
635 636 lookupFilter: autocompleteMainFilterResult,
636 637 onSelect: function (element, suggestion) {
637 638 handleSelect(element, suggestion);
638 639 return false;
639 640 },
640 641 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
641 642 if (jqXHR !== 'abort') {
642 643 alert("Error during search.\nError code: {0}".format(textStatus));
643 644 window.location = '';
644 645 }
645 646 }
646 647 });
647 648
648 649 showMainFilterBox = function () {
649 650 $('#main_filter_help').toggle();
650 651 }
651 652
652 653 </script>
653 654 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
654 655 </%def>
655 656
656 657 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
657 658 <div class="modal-dialog">
658 659 <div class="modal-content">
659 660 <div class="modal-header">
660 661 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
661 662 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
662 663 </div>
663 664 <div class="modal-body">
664 665 <div class="block-left">
665 666 <table class="keyboard-mappings">
666 667 <tbody>
667 668 <tr>
668 669 <th></th>
669 670 <th>${_('Site-wide shortcuts')}</th>
670 671 </tr>
671 672 <%
672 673 elems = [
673 674 ('/', 'Use quick search box'),
674 675 ('g h', 'Goto home page'),
675 676 ('g g', 'Goto my private gists page'),
676 677 ('g G', 'Goto my public gists page'),
677 678 ('g 0-9', 'Goto bookmarked items from 0-9'),
678 679 ('n r', 'New repository page'),
679 680 ('n g', 'New gist page'),
680 681 ]
681 682 %>
682 683 %for key, desc in elems:
683 684 <tr>
684 685 <td class="keys">
685 686 <span class="key tag">${key}</span>
686 687 </td>
687 688 <td>${desc}</td>
688 689 </tr>
689 690 %endfor
690 691 </tbody>
691 692 </table>
692 693 </div>
693 694 <div class="block-left">
694 695 <table class="keyboard-mappings">
695 696 <tbody>
696 697 <tr>
697 698 <th></th>
698 699 <th>${_('Repositories')}</th>
699 700 </tr>
700 701 <%
701 702 elems = [
702 703 ('g s', 'Goto summary page'),
703 704 ('g c', 'Goto changelog page'),
704 705 ('g f', 'Goto files page'),
705 706 ('g F', 'Goto files page with file search activated'),
706 707 ('g p', 'Goto pull requests page'),
707 708 ('g o', 'Goto repository settings'),
708 709 ('g O', 'Goto repository permissions settings'),
709 710 ]
710 711 %>
711 712 %for key, desc in elems:
712 713 <tr>
713 714 <td class="keys">
714 715 <span class="key tag">${key}</span>
715 716 </td>
716 717 <td>${desc}</td>
717 718 </tr>
718 719 %endfor
719 720 </tbody>
720 721 </table>
721 722 </div>
722 723 </div>
723 724 <div class="modal-footer">
724 725 </div>
725 726 </div><!-- /.modal-content -->
726 727 </div><!-- /.modal-dialog -->
727 728 </div><!-- /.modal -->
728 729
@@ -1,152 +1,152 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 %if c.repo_name:
6 6 ${_('Search inside repository %(repo_name)s') % {'repo_name': c.repo_name}}
7 7 %else:
8 8 ${_('Search inside all accessible repositories')}
9 9 %endif
10 10 %if c.rhodecode_name:
11 11 &middot; ${h.branding(c.rhodecode_name)}
12 12 %endif
13 13 </%def>
14 14
15 15 <%def name="breadcrumbs_links()">
16 16 %if c.repo_name:
17 17 ${_('Search inside repository %(repo_name)s') % {'repo_name': c.repo_name}}
18 18 %else:
19 19 ${_('Search inside all accessible repositories')}
20 20 %endif
21 21
22 22 </%def>
23 23
24 24 <%def name="menu_bar_nav()">
25 25 %if c.repo_name:
26 26 ${self.menu_items(active='repositories')}
27 27 %else:
28 28 ${self.menu_items(active='search')}
29 29 %endif
30 30 </%def>
31 31
32 32 <%def name="menu_bar_subnav()">
33 33 %if c.repo_name:
34 ${self.repo_menu(active='options')}
34 ${self.repo_menu(active='search')}
35 35 %endif
36 36 </%def>
37 37
38 38 <%def name="main()">
39 39 <div class="box">
40 40 %if c.repo_name:
41 41 <!-- box / title -->
42 42 <div class="title">
43 43 ${self.repo_page_title(c.rhodecode_db_repo)}
44 44 </div>
45 45 ${h.form(h.route_path('search_repo',repo_name=c.repo_name),method='get')}
46 46 %else:
47 47 <!-- box / title -->
48 48 <div class="title">
49 49 ${self.breadcrumbs()}
50 50 <ul class="links">&nbsp;</ul>
51 51 </div>
52 52 <!-- end box / title -->
53 53 ${h.form(h.route_path('search'), method='get')}
54 54 %endif
55 55 <div class="form search-form">
56 56 <div class="fields">
57 57 ${h.text('q', c.cur_query, placeholder="Enter query...")}
58 58
59 59 ${h.select('type',c.search_type,[('content',_('Files')), ('path',_('File path')),('commit',_('Commits'))],id='id_search_type')}
60 60 ${h.hidden('max_lines', '10')}
61 61 <input type="submit" value="${_('Search')}" class="btn"/>
62 62 <br/>
63 63
64 64 <div class="search-feedback-items">
65 65 % for error in c.errors:
66 66 <span class="error-message">
67 67 % for k,v in error.asdict().items():
68 68 ${k} - ${v}
69 69 % endfor
70 70 </span>
71 71 % endfor
72 72 <div class="field">
73 73 <p class="filterexample" style="position: inherit" onclick="$('#search-help').toggle()">${_('Query Langague examples')}</p>
74 74 <pre id="search-help" style="display: none">\
75 75
76 76 % if c.searcher.name == 'whoosh':
77 77 Example filter terms for `Whoosh` search:
78 78 query lang: <a href="${c.searcher.query_lang_doc}">Whoosh Query Language</a>
79 79 Whoosh has limited query capabilities. For advanced search use ElasticSearch 6 from RhodeCode EE edition.
80 80
81 81 Generate wildcards using '*' character:
82 82 "repo_name:vcs*" - search everything starting with 'vcs'
83 83 "repo_name:*vcs*" - search for repository containing 'vcs'
84 84
85 85 Optional AND / OR operators in queries
86 86 "repo_name:vcs OR repo_name:test"
87 87 "owner:test AND repo_name:test*" AND extension:py
88 88
89 89 Move advanced search is available via ElasticSearch6 backend in EE edition.
90 90 % elif c.searcher.name == 'elasticsearch' and c.searcher.es_version == '2':
91 91 Example filter terms for `ElasticSearch-${c.searcher.es_version}`search:
92 92 ElasticSearch-2 has limited query capabilities. For advanced search use ElasticSearch 6 from RhodeCode EE edition.
93 93
94 94 search type: content (File Content)
95 95 indexed fields: content
96 96
97 97 # search for `fix` string in all files
98 98 fix
99 99
100 100 search type: commit (Commit message)
101 101 indexed fields: message
102 102
103 103 search type: path (File name)
104 104 indexed fields: path
105 105
106 106 % else:
107 107 Example filter terms for `ElasticSearch-${c.searcher.es_version}`search:
108 108 query lang: <a href="${c.searcher.query_lang_doc}">ES 6 Query Language</a>
109 109 The reserved characters needed espace by `\`: + - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
110 110 % for handler in c.searcher.get_handlers().values():
111 111
112 112 search type: ${handler.search_type_label}
113 113 *indexed fields*: ${', '.join( [('\n ' if x[0]%4==0 else '')+x[1] for x in enumerate(handler.es_6_field_names)])}
114 114 % for entry in handler.es_6_example_queries:
115 115 ${entry.rstrip()}
116 116 % endfor
117 117 % endfor
118 118
119 119 % endif
120 120 </pre>
121 121 </div>
122 122
123 123 <div class="field">${c.runtime}</div>
124 124 </div>
125 125 </div>
126 126 </div>
127 127
128 128 ${h.end_form()}
129 129 <div class="search">
130 130 % if c.search_type == 'content':
131 131 <%include file='search_content.mako'/>
132 132 % elif c.search_type == 'path':
133 133 <%include file='search_path.mako'/>
134 134 % elif c.search_type == 'commit':
135 135 <%include file='search_commit.mako'/>
136 136 % elif c.search_type == 'repository':
137 137 <%include file='search_repository.mako'/>
138 138 % endif
139 139 </div>
140 140 </div>
141 141 <script>
142 142 $(document).ready(function(){
143 143 $('#q').autoGrowInput();
144 144 $("#id_search_type").select2({
145 145 'containerCssClass': "drop-menu",
146 146 'dropdownCssClass': "drop-menu-dropdown",
147 147 'dropdownAutoWidth': true,
148 148 'minimumResultsForSearch': -1
149 149 });
150 150 })
151 151 </script>
152 152 </%def>
General Comments 0
You need to be logged in to leave comments. Login now