go-to search: updated logic of goto switcher

- when in repo group searcher are ordered by the entries in the group
- support prefixes with spaces, eg file: PATTERN
- new contextual search for groups/repos with mark token
- better suggestions
This commit is contained in:
Marcin Kuzminski 2019-03-13 12:12:01 +01:00
parent 19d24cd946
commit 6039839d53
8 changed files with 366 additions and 153 deletions

View file

@ -33,7 +33,7 @@ from rhodecode.lib.index import searcher_from_config
from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
from rhodecode.lib.ext_json import json
from rhodecode.model.db import (
func, true, or_, in_filter_generator, Repository, RepoGroup, User, UserGroup)
func, true, or_, case, in_filter_generator, Repository, RepoGroup, User, UserGroup)
from rhodecode.model.repo import RepoModel
from rhodecode.model.repo_group import RepoGroupModel
from rhodecode.model.scm import RepoGroupList, RepoList
@ -105,21 +105,27 @@ class HomeView(BaseAppView):
return {'suggestions': _user_groups}
def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
def _get_repo_list(self, name_contains=None, repo_type=None, repo_group_name='', limit=20):
org_query = name_contains
allowed_ids = self._rhodecode_user.repo_acl_ids(
['repository.read', 'repository.write', 'repository.admin'],
cache=False, name_filter=name_contains) or [-1]
query = Repository.query()\
.order_by(func.length(Repository.repo_name))\
.order_by(Repository.repo_name)\
.filter(Repository.archived.isnot(true()))\
.filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(Repository.repo_id, allowed_ids)
))
query = query.order_by(case(
[
(Repository.repo_name.startswith(repo_group_name), repo_group_name+'/'),
],
))
query = query.order_by(func.length(Repository.repo_name))
query = query.order_by(Repository.repo_name)
if repo_type:
query = query.filter(Repository.repo_type == repo_type)
@ -145,20 +151,26 @@ class HomeView(BaseAppView):
}
for obj in acl_iter]
def _get_repo_group_list(self, name_contains=None, limit=20):
def _get_repo_group_list(self, name_contains=None, repo_group_name='', limit=20):
org_query = name_contains
allowed_ids = self._rhodecode_user.repo_group_acl_ids(
['group.read', 'group.write', 'group.admin'],
cache=False, name_filter=name_contains) or [-1]
query = RepoGroup.query()\
.order_by(func.length(RepoGroup.group_name))\
.order_by(RepoGroup.group_name) \
.filter(or_(
# generate multiple IN to fix limitation problems
*in_filter_generator(RepoGroup.group_id, allowed_ids)
))
query = query.order_by(case(
[
(RepoGroup.group_name.startswith(repo_group_name), repo_group_name+'/'),
],
))
query = query.order_by(func.length(RepoGroup.group_name))
query = query.order_by(RepoGroup.group_name)
if name_contains:
ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
query = query.filter(
@ -183,11 +195,17 @@ class HomeView(BaseAppView):
def _get_user_list(self, name_contains=None, limit=20):
org_query = name_contains
if not name_contains:
return []
return [], False
name_contains = re.compile('(?:user:)(.+)').findall(name_contains)
# TODO(marcink): should all logged in users be allowed to search others?
allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
if not allowed_user_search:
return [], False
name_contains = re.compile('(?:user:[ ]?)(.+)').findall(name_contains)
if len(name_contains) != 1:
return []
return [], False
name_contains = name_contains[0]
query = User.query()\
@ -207,22 +225,28 @@ class HomeView(BaseAppView):
{
'id': obj.user_id,
'value': org_query,
'value_display': obj.username,
'value_display': 'user: `{}`'.format(obj.username),
'type': 'user',
'icon_link': h.gravatar_url(obj.email, 30),
'url': h.route_path(
'user_profile', username=obj.username)
}
for obj in acl_iter]
for obj in acl_iter], True
def _get_user_groups_list(self, name_contains=None, limit=20):
org_query = name_contains
if not name_contains:
return []
return [], False
name_contains = re.compile('(?:user_group:)(.+)').findall(name_contains)
# TODO(marcink): should all logged in users be allowed to search others?
allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
if not allowed_user_search:
return [], False
name_contains = re.compile('(?:user_group:[ ]?)(.+)').findall(name_contains)
if len(name_contains) != 1:
return []
return [], False
name_contains = name_contains[0]
query = UserGroup.query()\
@ -241,27 +265,34 @@ class HomeView(BaseAppView):
{
'id': obj.users_group_id,
'value': org_query,
'value_display': obj.users_group_name,
'value_display': 'user_group: `{}`'.format(obj.users_group_name),
'type': 'user_group',
'url': h.route_path(
'user_group_profile', user_group_name=obj.users_group_name)
}
for obj in acl_iter]
for obj in acl_iter], True
def _get_hash_commit_list(self, auth_user, searcher, query, repo=None, repo_group=None):
repo_name = repo_group_name = None
if repo:
repo_name = repo.repo_name
if repo_group:
repo_group_name = repo_group.group_name
def _get_hash_commit_list(self, auth_user, searcher, query):
org_query = query
if not query or len(query) < 3 or not searcher:
return []
return [], False
commit_hashes = re.compile('(?:commit:)([0-9a-f]{2,40})').findall(query)
commit_hashes = re.compile('(?:commit:[ ]?)([0-9a-f]{2,40})').findall(query)
if len(commit_hashes) != 1:
return []
return [], False
commit_hash = commit_hashes[0]
result = searcher.search(
'commit_id:{}*'.format(commit_hash), 'commit', auth_user,
raise_on_exc=False)
repo_name, repo_group_name, raise_on_exc=False)
commits = []
for entry in result['results']:
@ -286,22 +317,29 @@ class HomeView(BaseAppView):
}
commits.append(commit_entry)
return commits
return commits, True
def _get_path_list(self, auth_user, searcher, query, repo=None, repo_group=None):
repo_name = repo_group_name = None
if repo:
repo_name = repo.repo_name
if repo_group:
repo_group_name = repo_group.group_name
def _get_path_list(self, auth_user, searcher, query):
org_query = query
if not query or len(query) < 3 or not searcher:
return []
return [], False
paths_re = re.compile('(?:file:)(.{1,})').findall(query)
paths_re = re.compile('(?:file:[ ]?)(.+)').findall(query)
if len(paths_re) != 1:
return []
return [], False
file_path = paths_re[0]
search_path = searcher.escape_specials(file_path)
result = searcher.search(
'file.raw:*{}*'.format(search_path), 'path', auth_user,
raise_on_exc=False)
repo_name, repo_group_name, raise_on_exc=False)
files = []
for entry in result['results']:
@ -327,7 +365,7 @@ class HomeView(BaseAppView):
}
files.append(file_entry)
return files
return files, True
@LoginRequired()
@view_config(
@ -405,17 +443,15 @@ class HomeView(BaseAppView):
qry = query
return {'q': qry, 'type': 'content'}
label = u'File search for `{}` in this repository.'.format(query)
queries.append(
{
'id': -10,
'value': query,
'value_display': label,
'type': 'search',
'url': h.route_path('search_repo',
repo_name=repo_name,
_query=query_modifier())
file_qry = {
'id': -10,
'value': query,
'value_display': label,
'type': 'search',
'url': h.route_path('search_repo',
repo_name=repo_name,
_query=query_modifier())
}
)
# commits
def query_modifier():
@ -423,17 +459,22 @@ class HomeView(BaseAppView):
return {'q': qry, 'type': 'commit'}
label = u'Commit search for `{}` in this repository.'.format(query)
queries.append(
{
'id': -20,
'value': query,
'value_display': label,
'type': 'search',
'url': h.route_path('search_repo',
repo_name=repo_name,
_query=query_modifier())
commit_qry = {
'id': -20,
'value': query,
'value_display': label,
'type': 'search',
'url': h.route_path('search_repo',
repo_name=repo_name,
_query=query_modifier())
}
)
if repo_context in ['commit', 'changelog']:
queries.extend([commit_qry, file_qry])
elif repo_context in ['files', 'summary']:
queries.extend([file_qry, commit_qry])
else:
queries.extend([commit_qry, file_qry])
elif is_es_6 and repo_group_name:
# files
@ -442,17 +483,15 @@ class HomeView(BaseAppView):
return {'q': qry, 'type': 'content'}
label = u'File search for `{}` in this repository group'.format(query)
queries.append(
{
'id': -30,
'value': query,
'value_display': label,
'type': 'search',
'url': h.route_path('search_repo_group',
repo_group_name=repo_group_name,
_query=query_modifier())
file_qry = {
'id': -30,
'value': query,
'value_display': label,
'type': 'search',
'url': h.route_path('search_repo_group',
repo_group_name=repo_group_name,
_query=query_modifier())
}
)
# commits
def query_modifier():
@ -460,18 +499,24 @@ class HomeView(BaseAppView):
return {'q': qry, 'type': 'commit'}
label = u'Commit search for `{}` in this repository group'.format(query)
queries.append(
{
'id': -40,
'value': query,
'value_display': label,
'type': 'search',
'url': h.route_path('search_repo_group',
repo_group_name=repo_group_name,
_query=query_modifier())
commit_qry = {
'id': -40,
'value': query,
'value_display': label,
'type': 'search',
'url': h.route_path('search_repo_group',
repo_group_name=repo_group_name,
_query=query_modifier())
}
)
if repo_context in ['commit', 'changelog']:
queries.extend([commit_qry, file_qry])
elif repo_context in ['files', 'summary']:
queries.extend([file_qry, commit_qry])
else:
queries.extend([commit_qry, file_qry])
# Global, not scoped
if not queries:
queries.append(
{
@ -510,65 +555,107 @@ class HomeView(BaseAppView):
if not query:
return {'suggestions': res}
def no_match(name):
return {
'id': -1,
'value': "",
'value_display': name,
'type': 'text',
'url': ""
}
searcher = searcher_from_config(self.request.registry.settings)
for _q in self._get_default_search_queries(self.request.GET, searcher, query):
res.append(_q)
has_specialized_search = False
# set repo context
repo = None
repo_id = safe_int(self.request.GET.get('search_context[repo_id]'))
if repo_id:
repo = Repository.get(repo_id)
# set group context
repo_group = None
repo_group_id = safe_int(self.request.GET.get('search_context[repo_group_id]'))
if repo_group_id:
repo_group = RepoGroup.get(repo_group_id)
composed_hint = '{}/{}'.format(repo_group.group_name, query)
show_hint = not query.startswith(repo_group.group_name)
if repo_group and show_hint:
hint = u'Repository search inside: `{}`'.format(composed_hint)
res.append({
'id': -1,
'value': composed_hint,
'value_display': hint,
'type': 'hint',
'url': ""
})
prefix_match = False
repo_groups = self._get_repo_group_list(query)
for serialized_repo_group in repo_groups:
res.append(serialized_repo_group)
# user: type search
if not prefix_match:
users, prefix_match = self._get_user_list(query)
if users:
has_specialized_search = True
for serialized_user in users:
res.append(serialized_user)
elif prefix_match:
has_specialized_search = True
res.append(no_match('No matching users found'))
repos = self._get_repo_list(query)
for serialized_repo in repos:
res.append(serialized_repo)
# user_group: type search
if not prefix_match:
user_groups, prefix_match = self._get_user_groups_list(query)
if user_groups:
has_specialized_search = True
for serialized_user_group in user_groups:
res.append(serialized_user_group)
elif prefix_match:
has_specialized_search = True
res.append(no_match('No matching user groups found'))
# TODO(marcink): should all logged in users be allowed to search others?
allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
if allowed_user_search:
users = self._get_user_list(query)
for serialized_user in users:
res.append(serialized_user)
user_groups = self._get_user_groups_list(query)
for serialized_user_group in user_groups:
res.append(serialized_user_group)
commits = self._get_hash_commit_list(c.auth_user, searcher, query)
if commits:
unique_repos = collections.OrderedDict()
for commit in commits:
repo_name = commit['repo']
unique_repos.setdefault(repo_name, []).append(commit)
for repo, commits in unique_repos.items():
# FTS commit: type search
if not prefix_match:
commits, prefix_match = self._get_hash_commit_list(
c.auth_user, searcher, query, repo, repo_group)
if commits:
has_specialized_search = True
unique_repos = collections.OrderedDict()
for commit in commits:
res.append(commit)
repo_name = commit['repo']
unique_repos.setdefault(repo_name, []).append(commit)
paths = self._get_path_list(c.auth_user, searcher, query)
if paths:
unique_repos = collections.OrderedDict()
for path in paths:
repo_name = path['repo']
unique_repos.setdefault(repo_name, []).append(path)
for _repo, commits in unique_repos.items():
for commit in commits:
res.append(commit)
elif prefix_match:
has_specialized_search = True
res.append(no_match('No matching commits found'))
for repo, paths in unique_repos.items():
# FTS file: type search
if not prefix_match:
paths, prefix_match = self._get_path_list(
c.auth_user, searcher, query, repo, repo_group)
if paths:
has_specialized_search = True
unique_repos = collections.OrderedDict()
for path in paths:
res.append(path)
repo_name = path['repo']
unique_repos.setdefault(repo_name, []).append(path)
for repo, paths in unique_repos.items():
for path in paths:
res.append(path)
elif prefix_match:
has_specialized_search = True
res.append(no_match('No matching files found'))
# main suggestions
if not has_specialized_search:
repo_group_name = ''
if repo_group:
repo_group_name = repo_group.group_name
for _q in self._get_default_search_queries(self.request.GET, searcher, query):
res.append(_q)
repo_groups = self._get_repo_group_list(query, repo_group_name=repo_group_name)
for serialized_repo_group in repo_groups:
res.append(serialized_repo_group)
repos = self._get_repo_list(query, repo_group_name=repo_group_name)
for serialized_repo in repos:
res.append(serialized_repo)
if not repos and not repo_groups:
res.append(no_match('No matches found'))
return {'suggestions': res}

View file

@ -2037,6 +2037,6 @@ def get_repo_view_type(request):
'repo_files': 'files',
'repo_summary': 'summary',
'repo_commit': 'commit'
}
return route_to_view_type.get(route_name)

View file

@ -39,7 +39,7 @@ from sqlalchemy import (
Index, Sequence, UniqueConstraint, ForeignKey, CheckConstraint, Column,
Boolean, String, Unicode, UnicodeText, DateTime, Integer, LargeBinary,
Text, Float, PickleType)
from sqlalchemy.sql.expression import true, false
from sqlalchemy.sql.expression import true, false, case
from sqlalchemy.sql.functions import coalesce, count # pragma: no cover
from sqlalchemy.orm import (
relationship, joinedload, class_mapper, validates, aliased)

View file

@ -644,6 +644,40 @@ ul#context-pages {
.main_filter_input_box {
display: inline-block;
.searchItems {
display:flex;
background: #666666;
padding: 0px;
a {
border: none !important;
}
}
.searchTag {
line-height: 28px;
padding: 0px 4px;
.tag {
color: @nav-grey;
border-color: @nav-grey;
}
}
.searchTagFilter {
background-color: @grey3 !important;
}
.searchTagHelp {
background-color: @grey2 !important;
}
.searchTagHelp:hover {
background-color: @grey2 !important;
}
.searchTagInput {
background-color: @grey3 !important;
}
}
.main_filter_box {
@ -667,7 +701,8 @@ ul#context-pages {
color: @nav-grey;
background: @grey3;
min-height: 18px;
border:none;
border-radius: 0;
&:active {
color: @grey2 !important;

View file

@ -528,7 +528,19 @@
if ($.isFunction(serviceUrl)) {
serviceUrl = serviceUrl.call(that.element, query);
}
cacheKey = serviceUrl + '?' + $.param(params || {});
var callParams = {};
//make an evaluated copy of params
$.each(params, function(index, value) {
if($.isFunction(value)){
callParams[index] = value();
}
else {
callParams[index] = value;
}
});
cacheKey = serviceUrl + '?' + $.param(callParams);
response = that.cachedResponse[cacheKey];
}
@ -536,7 +548,7 @@
that.suggestions = response.suggestions;
that.suggest();
} else if (!that.isBadQuery(query)) {
if (options.onSearchStart.call(that.element, options.params) === false) {
if (options.onSearchStart.call(that.element, params) === false) {
return;
}
if (that.currentRequest) {

View file

@ -233,7 +233,6 @@
<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>
<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>
<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>
<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>
## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
%if c.rhodecode_db_repo.repo_type in ['git','hg']:
@ -338,7 +337,6 @@
<div class="wrapper">
<ul id="context-pages" class="navigation horizontal-list">
<li class="${is_active('home')}"><a class="menulink" href="${h.route_path('repo_group_home', repo_group_name=c.repo_group.group_name)}"><div class="menulabel">${_('Group Home')}</div></a></li>
<li class="${is_active('search')}"><a class="menulink" href="${h.route_path('search_repo_group', repo_group_name=c.repo_group.group_name)}"><div class="menulabel">${_('Search')}</div></a></li>
<li class="${is_active('options')}">
<a class="menulink dropdown">
@ -486,10 +484,35 @@
<li>
<div class="menulabel main_filter_box">
<div class="main_filter_input_box">
<input class="main_filter_input" id="main_filter" size="15" type="text" name="main_filter" placeholder="${_('search / go to...')}" value=""/>
</div>
<div class="main_filter_help_box">
<a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
<ul class="searchItems">
% if c.template_context['search_context']['repo_id']:
<li class="searchTag searchTagFilter searchTagHidable" >
##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
<span class="tag">
This repo
<a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-delete"></i></a>
</span>
##</a>
</li>
% elif c.template_context['search_context']['repo_group_id']:
<li class="searchTag searchTagFilter searchTagHidable">
##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
<span class="tag">
This group
<a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-delete"></i></a>
</span>
##</a>
</li>
% endif
<li class="searchTagInput">
<input class="main_filter_input" id="main_filter" size="15" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
</li>
<li class="searchTag searchTagHelp">
<a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
</li>
</ul>
</div>
</div>
@ -500,13 +523,21 @@
- Prefix query to allow special search:
user:admin, to search for usernames
user:admin, to search for usernames, always global
user_group:devops, to search for user groups
user_group:devops, to search for user groups, always global
commit:efced4, to search for commits
commit:efced4, to search for commits, scoped to repositories or groups
file:models.py, to search for file paths
file:models.py, to search for file paths, scoped to repositories or groups
% if c.template_context['search_context']['repo_id']:
For advanced full text search visit: <a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">repository search</a>
% elif c.template_context['search_context']['repo_group_id']:
For advanced full text search visit: <a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">repository group search</a>
% else:
For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
% endif
</div>
</li>
@ -622,6 +653,22 @@
}(result, escapeMarkup);
};
var escapeRegExChars = function (value) {
return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
};
var getRepoIcon = function(repo_type) {
if (repo_type === 'hg') {
return '<i class="icon-hg"></i> ';
}
else if (repo_type === 'git') {
return '<i class="icon-git"></i> ';
}
else if (repo_type === 'svn') {
return '<i class="icon-svn"></i> ';
}
return ''
};
var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
@ -632,27 +679,14 @@
var searchType = data['type'];
var valueDisplay = data['value_display'];
var escapeRegExChars = function (value) {
return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
};
var pattern = '(' + escapeRegExChars(value) + ')';
var getRepoIcon = function(repo_type) {
if (repo_type === 'hg') {
return '<i class="icon-hg"></i> ';
}
else if (repo_type === 'git') {
return '<i class="icon-git"></i> ';
}
else if (repo_type === 'svn') {
return '<i class="icon-svn"></i> ';
}
return ''
};
valueDisplay = Select2.util.escapeMarkup(valueDisplay);
// highlight match
valueDisplay = Select2.util.escapeMarkup(valueDisplay);
valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
if (searchType != 'text') {
valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
}
var icon = '';
@ -684,6 +718,7 @@
else if (searchType === 'user_group') {
icon += '<i class="icon-group"></i> ';
}
// user
else if (searchType === 'user') {
icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
}
@ -707,6 +742,10 @@
icon += '<i class="icon-tag"></i>';
}
}
// generic text
else if (searchType === 'text') {
icon = '';
}
var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
return tmpl.format(icon, valueDisplay);
@ -716,25 +755,52 @@
if (suggestion.type === "hint") {
// we skip action
$('#main_filter').focus();
}
else if (suggestion.type === "text") {
// we skip action
$('#main_filter').focus();
} else {
window.location = suggestion['url'];
}
};
var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
if (queryLowerCase.split(':').length === 2) {
queryLowerCase = queryLowerCase.split(':')[1]
}
if (suggestion.type === "text") {
// special case we don't want to "skip" display for
return true
}
return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
};
var cleanContext = {
repo_view_type: null,
repo_id: null,
repo_name: "",
repo_group_id: null,
repo_group_name: null
};
var removeGoToFilter = function () {
$('.searchTagHidable').hide();
$('#main_filter').autocomplete(
'setOptions', {params:{search_context: cleanContext}});
};
$('#main_filter').autocomplete({
serviceUrl: pyroutes.url('goto_switcher_data'),
params: {"search_context": templateContext.search_context},
params: {
"search_context": templateContext.search_context
},
minChars:2,
maxHeight:400,
deferRequestBy: 300, //miliseconds
tabDisabled: true,
autoSelectFirst: true,
autoSelectFirst: false,
formatResult: autocompleteMainFilterFormatResult,
lookupFilter: autocompleteMainFilterResult,
onSelect: function (element, suggestion) {
@ -753,6 +819,18 @@
$('#main_filter_help').toggle();
};
$('#main_filter').on('keydown.autocomplete', function (e) {
var BACKSPACE = 8;
var el = $(e.currentTarget);
if(e.which === BACKSPACE){
var inputVal = el.val();
if (inputVal === ""){
removeGoToFilter()
}
}
});
</script>
<script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
</%def>

View file

@ -7,7 +7,7 @@ go_import_header = ''
if hasattr(c, 'rhodecode_db_repo'):
c.template_context['repo_type'] = c.rhodecode_db_repo.repo_type
c.template_context['repo_landing_commit'] = c.rhodecode_db_repo.landing_rev[1]
## check repo context
c.template_context['repo_id'] = c.rhodecode_db_repo.repo_id
c.template_context['repo_view_type'] = h.get_repo_view_type(request)
if getattr(c, 'repo_group', None):
@ -29,6 +29,7 @@ c.template_context['default_user'] = {
c.template_context['search_context'] = {
'repo_group_id': c.template_context.get('repo_group_id'),
'repo_group_name': c.template_context.get('repo_group_name'),
'repo_id': c.template_context.get('repo_id'),
'repo_name': c.template_context.get('repo_name'),
'repo_view_type': c.template_context.get('repo_view_type'),
}

View file

@ -37,9 +37,9 @@
<%def name="menu_bar_subnav()">
%if c.repo_name:
${self.repo_menu(active='search')}
${self.repo_menu(active='summary')}
%elif c.repo_group_name:
${self.repo_group_menu(active='search')}
${self.repo_group_menu(active='home')}
%endif
</%def>