##// END OF EJS Templates
quick-search: use smart group search when browsing inside a repository group....
marcink -
r2804:0f04cf5e default
parent child Browse files
Show More
@@ -1,413 +1,427 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2018 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 re
22 22 import logging
23 23 import collections
24 24
25 25 from pyramid.view import view_config
26 26
27 27 from rhodecode.apps._base import BaseAppView
28 28 from rhodecode.lib import helpers as h
29 29 from rhodecode.lib.auth import (
30 30 LoginRequired, NotAnonymous, HasRepoGroupPermissionAnyDecorator)
31 31 from rhodecode.lib.index import searcher_from_config
32 from rhodecode.lib.utils2 import safe_unicode, str2bool
32 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
33 33 from rhodecode.lib.ext_json import json
34 34 from rhodecode.model.db import (
35 35 func, or_, in_filter_generator, Repository, RepoGroup, User, UserGroup)
36 36 from rhodecode.model.repo import RepoModel
37 37 from rhodecode.model.repo_group import RepoGroupModel
38 38 from rhodecode.model.scm import RepoGroupList, RepoList
39 39 from rhodecode.model.user import UserModel
40 40 from rhodecode.model.user_group import UserGroupModel
41 41
42 42 log = logging.getLogger(__name__)
43 43
44 44
45 45 class HomeView(BaseAppView):
46 46
47 47 def load_default_context(self):
48 48 c = self._get_local_tmpl_context()
49 49 c.user = c.auth_user.get_instance()
50 50
51 51 return c
52 52
53 53 @LoginRequired()
54 54 @view_config(
55 55 route_name='user_autocomplete_data', request_method='GET',
56 56 renderer='json_ext', xhr=True)
57 57 def user_autocomplete_data(self):
58 58 self.load_default_context()
59 59 query = self.request.GET.get('query')
60 60 active = str2bool(self.request.GET.get('active') or True)
61 61 include_groups = str2bool(self.request.GET.get('user_groups'))
62 62 expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
63 63 skip_default_user = str2bool(self.request.GET.get('skip_default_user'))
64 64
65 65 log.debug('generating user list, query:%s, active:%s, with_groups:%s',
66 66 query, active, include_groups)
67 67
68 68 _users = UserModel().get_users(
69 69 name_contains=query, only_active=active)
70 70
71 71 def maybe_skip_default_user(usr):
72 72 if skip_default_user and usr['username'] == UserModel.cls.DEFAULT_USER:
73 73 return False
74 74 return True
75 75 _users = filter(maybe_skip_default_user, _users)
76 76
77 77 if include_groups:
78 78 # extend with user groups
79 79 _user_groups = UserGroupModel().get_user_groups(
80 80 name_contains=query, only_active=active,
81 81 expand_groups=expand_groups)
82 82 _users = _users + _user_groups
83 83
84 84 return {'suggestions': _users}
85 85
86 86 @LoginRequired()
87 87 @NotAnonymous()
88 88 @view_config(
89 89 route_name='user_group_autocomplete_data', request_method='GET',
90 90 renderer='json_ext', xhr=True)
91 91 def user_group_autocomplete_data(self):
92 92 self.load_default_context()
93 93 query = self.request.GET.get('query')
94 94 active = str2bool(self.request.GET.get('active') or True)
95 95 expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
96 96
97 97 log.debug('generating user group list, query:%s, active:%s',
98 98 query, active)
99 99
100 100 _user_groups = UserGroupModel().get_user_groups(
101 101 name_contains=query, only_active=active,
102 102 expand_groups=expand_groups)
103 103 _user_groups = _user_groups
104 104
105 105 return {'suggestions': _user_groups}
106 106
107 107 def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
108 108 org_query = name_contains
109 109 allowed_ids = self._rhodecode_user.repo_acl_ids(
110 110 ['repository.read', 'repository.write', 'repository.admin'],
111 111 cache=False, name_filter=name_contains) or [-1]
112 112
113 113 query = Repository.query()\
114 114 .order_by(func.length(Repository.repo_name))\
115 115 .order_by(Repository.repo_name)\
116 116 .filter(or_(
117 117 # generate multiple IN to fix limitation problems
118 118 *in_filter_generator(Repository.repo_id, allowed_ids)
119 119 ))
120 120
121 121 if repo_type:
122 122 query = query.filter(Repository.repo_type == repo_type)
123 123
124 124 if name_contains:
125 125 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
126 126 query = query.filter(
127 127 Repository.repo_name.ilike(ilike_expression))
128 128 query = query.limit(limit)
129 129
130 130 acl_iter = query
131 131
132 132 return [
133 133 {
134 134 'id': obj.repo_name,
135 135 'value': org_query,
136 136 'value_display': obj.repo_name,
137 137 'text': obj.repo_name,
138 138 'type': 'repo',
139 139 'repo_id': obj.repo_id,
140 140 'repo_type': obj.repo_type,
141 141 'private': obj.private,
142 142 'url': h.route_path('repo_summary', repo_name=obj.repo_name)
143 143 }
144 144 for obj in acl_iter]
145 145
146 146 def _get_repo_group_list(self, name_contains=None, limit=20):
147 147 org_query = name_contains
148 148 allowed_ids = self._rhodecode_user.repo_group_acl_ids(
149 149 ['group.read', 'group.write', 'group.admin'],
150 150 cache=False, name_filter=name_contains) or [-1]
151 151
152 152 query = RepoGroup.query()\
153 153 .order_by(func.length(RepoGroup.group_name))\
154 154 .order_by(RepoGroup.group_name) \
155 155 .filter(or_(
156 156 # generate multiple IN to fix limitation problems
157 157 *in_filter_generator(RepoGroup.group_id, allowed_ids)
158 158 ))
159 159
160 160 if name_contains:
161 161 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
162 162 query = query.filter(
163 163 RepoGroup.group_name.ilike(ilike_expression))
164 164 query = query.limit(limit)
165 165
166 166 acl_iter = query
167 167
168 168 return [
169 169 {
170 170 'id': obj.group_name,
171 171 'value': org_query,
172 172 'value_display': obj.group_name,
173 173 'type': 'repo_group',
174 174 'url': h.route_path(
175 175 'repo_group_home', repo_group_name=obj.group_name)
176 176 }
177 177 for obj in acl_iter]
178 178
179 179 def _get_user_list(self, name_contains=None, limit=20):
180 180 org_query = name_contains
181 181 if not name_contains:
182 182 return []
183 183
184 184 name_contains = re.compile('(?:user:)(.+)').findall(name_contains)
185 185 if len(name_contains) != 1:
186 186 return []
187 187 name_contains = name_contains[0]
188 188
189 189 query = User.query()\
190 190 .order_by(func.length(User.username))\
191 191 .order_by(User.username) \
192 192 .filter(User.username != User.DEFAULT_USER)
193 193
194 194 if name_contains:
195 195 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
196 196 query = query.filter(
197 197 User.username.ilike(ilike_expression))
198 198 query = query.limit(limit)
199 199
200 200 acl_iter = query
201 201
202 202 return [
203 203 {
204 204 'id': obj.user_id,
205 205 'value': org_query,
206 206 'value_display': obj.username,
207 207 'type': 'user',
208 208 'icon_link': h.gravatar_url(obj.email, 30),
209 209 'url': h.route_path(
210 210 'user_profile', username=obj.username)
211 211 }
212 212 for obj in acl_iter]
213 213
214 214 def _get_user_groups_list(self, name_contains=None, limit=20):
215 215 org_query = name_contains
216 216 if not name_contains:
217 217 return []
218 218
219 219 name_contains = re.compile('(?:user_group:)(.+)').findall(name_contains)
220 220 if len(name_contains) != 1:
221 221 return []
222 222 name_contains = name_contains[0]
223 223
224 224 query = UserGroup.query()\
225 225 .order_by(func.length(UserGroup.users_group_name))\
226 226 .order_by(UserGroup.users_group_name)
227 227
228 228 if name_contains:
229 229 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
230 230 query = query.filter(
231 231 UserGroup.users_group_name.ilike(ilike_expression))
232 232 query = query.limit(limit)
233 233
234 234 acl_iter = query
235 235
236 236 return [
237 237 {
238 238 'id': obj.users_group_id,
239 239 'value': org_query,
240 240 'value_display': obj.users_group_name,
241 241 'type': 'user_group',
242 242 'url': h.route_path(
243 243 'user_group_profile', user_group_name=obj.users_group_name)
244 244 }
245 245 for obj in acl_iter]
246 246
247 247 def _get_hash_commit_list(self, auth_user, query):
248 248 org_query = query
249 249 if not query or len(query) < 3:
250 250 return []
251 251
252 252 commit_hashes = re.compile('(?:commit:)([0-9a-f]{2,40})').findall(query)
253 253
254 254 if len(commit_hashes) != 1:
255 255 return []
256 256 commit_hash = commit_hashes[0]
257 257
258 258 searcher = searcher_from_config(self.request.registry.settings)
259 259 result = searcher.search(
260 260 'commit_id:%s*' % commit_hash, 'commit', auth_user,
261 261 raise_on_exc=False)
262 262
263 263 return [
264 264 {
265 265 'id': entry['commit_id'],
266 266 'value': org_query,
267 267 'value_display': 'repo `{}` commit: {}'.format(
268 268 entry['repository'], entry['commit_id']),
269 269 'type': 'commit',
270 270 'repo': entry['repository'],
271 271 'url': h.route_path(
272 272 'repo_commit',
273 273 repo_name=entry['repository'], commit_id=entry['commit_id'])
274 274 }
275 275 for entry in result['results']]
276 276
277 277 @LoginRequired()
278 278 @view_config(
279 279 route_name='repo_list_data', request_method='GET',
280 280 renderer='json_ext', xhr=True)
281 281 def repo_list_data(self):
282 282 _ = self.request.translate
283 283 self.load_default_context()
284 284
285 285 query = self.request.GET.get('query')
286 286 repo_type = self.request.GET.get('repo_type')
287 287 log.debug('generating repo list, query:%s, repo_type:%s',
288 288 query, repo_type)
289 289
290 290 res = []
291 291 repos = self._get_repo_list(query, repo_type=repo_type)
292 292 if repos:
293 293 res.append({
294 294 'text': _('Repositories'),
295 295 'children': repos
296 296 })
297 297
298 298 data = {
299 299 'more': False,
300 300 'results': res
301 301 }
302 302 return data
303 303
304 304 @LoginRequired()
305 305 @view_config(
306 306 route_name='goto_switcher_data', request_method='GET',
307 307 renderer='json_ext', xhr=True)
308 308 def goto_switcher_data(self):
309 309 c = self.load_default_context()
310 310
311 311 _ = self.request.translate
312 312
313 313 query = self.request.GET.get('query')
314 314 log.debug('generating main filter data, query %s', query)
315 315
316 316 default_search_val = u'Full text search for: `{}`'.format(query)
317 317 res = []
318 318 if not query:
319 319 return {'suggestions': res}
320 320
321 321 res.append({
322 322 'id': -1,
323 323 'value': query,
324 324 'value_display': default_search_val,
325 325 'type': 'search',
326 326 'url': h.route_path(
327 327 'search', _query={'q': query})
328 328 })
329 repo_group_id = safe_int(self.request.GET.get('repo_group_id'))
330 if repo_group_id:
331 repo_group = RepoGroup.get(repo_group_id)
332 composed_hint = '{}/{}'.format(repo_group.group_name, query)
333 show_hint = not query.startswith(repo_group.group_name)
334 if repo_group and show_hint:
335 hint = u'Group search: `{}`'.format(composed_hint)
336 res.append({
337 'id': -1,
338 'value': composed_hint,
339 'value_display': hint,
340 'type': 'hint',
341 'url': ""
342 })
329 343
330 344 repo_groups = self._get_repo_group_list(query)
331 345 for serialized_repo_group in repo_groups:
332 346 res.append(serialized_repo_group)
333 347
334 348 repos = self._get_repo_list(query)
335 349 for serialized_repo in repos:
336 350 res.append(serialized_repo)
337 351
338 352 # TODO(marcink): permissions for that ?
339 353 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
340 354 if allowed_user_search:
341 355 users = self._get_user_list(query)
342 356 for serialized_user in users:
343 357 res.append(serialized_user)
344 358
345 359 user_groups = self._get_user_groups_list(query)
346 360 for serialized_user_group in user_groups:
347 361 res.append(serialized_user_group)
348 362
349 363 commits = self._get_hash_commit_list(c.auth_user, query)
350 364 if commits:
351 365 unique_repos = collections.OrderedDict()
352 366 for commit in commits:
353 367 repo_name = commit['repo']
354 368 unique_repos.setdefault(repo_name, []).append(commit)
355 369
356 370 for repo, commits in unique_repos.items():
357 371 for commit in commits:
358 372 res.append(commit)
359 373
360 374 return {'suggestions': res}
361 375
362 376 def _get_groups_and_repos(self, repo_group_id=None):
363 377 # repo groups groups
364 378 repo_group_list = RepoGroup.get_all_repo_groups(group_id=repo_group_id)
365 379 _perms = ['group.read', 'group.write', 'group.admin']
366 380 repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms)
367 381 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
368 382 repo_group_list=repo_group_list_acl, admin=False)
369 383
370 384 # repositories
371 385 repo_list = Repository.get_all_repos(group_id=repo_group_id)
372 386 _perms = ['repository.read', 'repository.write', 'repository.admin']
373 387 repo_list_acl = RepoList(repo_list, perm_set=_perms)
374 388 repo_data = RepoModel().get_repos_as_dict(
375 389 repo_list=repo_list_acl, admin=False)
376 390
377 391 return repo_data, repo_group_data
378 392
379 393 @LoginRequired()
380 394 @view_config(
381 395 route_name='home', request_method='GET',
382 396 renderer='rhodecode:templates/index.mako')
383 397 def main_page(self):
384 398 c = self.load_default_context()
385 399 c.repo_group = None
386 400
387 401 repo_data, repo_group_data = self._get_groups_and_repos()
388 402 # json used to render the grids
389 403 c.repos_data = json.dumps(repo_data)
390 404 c.repo_groups_data = json.dumps(repo_group_data)
391 405
392 406 return self._get_template_context(c)
393 407
394 408 @LoginRequired()
395 409 @HasRepoGroupPermissionAnyDecorator(
396 410 'group.read', 'group.write', 'group.admin')
397 411 @view_config(
398 412 route_name='repo_group_home', request_method='GET',
399 413 renderer='rhodecode:templates/index_repo_group.mako')
400 414 @view_config(
401 415 route_name='repo_group_home_slash', request_method='GET',
402 416 renderer='rhodecode:templates/index_repo_group.mako')
403 417 def repo_group_main_page(self):
404 418 c = self.load_default_context()
405 419 c.repo_group = self.request.db_repo_group
406 420 repo_data, repo_group_data = self._get_groups_and_repos(
407 421 c.repo_group.group_id)
408 422
409 423 # json used to render the grids
410 424 c.repos_data = json.dumps(repo_data)
411 425 c.repo_groups_data = json.dumps(repo_group_data)
412 426
413 427 return self._get_template_context(c)
@@ -1,667 +1,676 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: %s') % 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 <a href="${h.route_path('repo_summary',repo_name=repo_instance.fork.repo_name)}">${repo_instance.fork.repo_name}</a>
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 234 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
235 235 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
236 236 <li class="${is_active('showpullrequest')}">
237 237 <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 238 %if c.repository_pull_requests:
239 239 <span class="pr_notifications">${c.repository_pull_requests}</span>
240 240 %endif
241 241 <div class="menulabel">${_('Pull Requests')}</div>
242 242 </a>
243 243 </li>
244 244 %endif
245 245 <li class="${is_active('options')}">
246 246 <a class="menulink dropdown">
247 247 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
248 248 </a>
249 249 <ul class="submenu">
250 250 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
251 251 <li><a href="${h.route_path('edit_repo',repo_name=c.repo_name)}">${_('Settings')}</a></li>
252 252 %endif
253 253 %if c.rhodecode_db_repo.fork:
254 254 <li>
255 255 <a title="${h.tooltip(_('Compare fork with %s' % c.rhodecode_db_repo.fork.repo_name))}"
256 256 href="${h.route_path('repo_compare',
257 257 repo_name=c.rhodecode_db_repo.fork.repo_name,
258 258 source_ref_type=c.rhodecode_db_repo.landing_rev[0],
259 259 source_ref=c.rhodecode_db_repo.landing_rev[1],
260 260 target_repo=c.repo_name,target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],
261 261 target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1],
262 262 _query=dict(merge=1))}"
263 263 >
264 264 ${_('Compare fork')}
265 265 </a>
266 266 </li>
267 267 %endif
268 268
269 269 <li><a href="${h.route_path('search_repo',repo_name=c.repo_name)}">${_('Search')}</a></li>
270 270
271 271 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
272 272 %if c.rhodecode_db_repo.locked[0]:
273 273 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock')}</a></li>
274 274 %else:
275 275 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock')}</a></li>
276 276 %endif
277 277 %endif
278 278 %if c.rhodecode_user.username != h.DEFAULT_USER:
279 279 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
280 280 <li><a href="${h.route_path('repo_fork_new',repo_name=c.repo_name)}">${_('Fork')}</a></li>
281 281 <li><a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
282 282 %endif
283 283 %endif
284 284 </ul>
285 285 </li>
286 286 </ul>
287 287 </div>
288 288 <div class="clear"></div>
289 289 </div>
290 290 <!--- END CONTEXT BAR -->
291 291
292 292 </%def>
293 293
294 294 <%def name="usermenu(active=False)">
295 295 ## USER MENU
296 296 <li id="quick_login_li" class="${'active' if active else ''}">
297 297 <a id="quick_login_link" class="menulink childs">
298 298 ${gravatar(c.rhodecode_user.email, 20)}
299 299 <span class="user">
300 300 %if c.rhodecode_user.username != h.DEFAULT_USER:
301 301 <span class="menu_link_user">${c.rhodecode_user.username}</span><div class="show_more"></div>
302 302 %else:
303 303 <span>${_('Sign in')}</span>
304 304 %endif
305 305 </span>
306 306 </a>
307 307
308 308 <div class="user-menu submenu">
309 309 <div id="quick_login">
310 310 %if c.rhodecode_user.username == h.DEFAULT_USER:
311 311 <h4>${_('Sign in to your account')}</h4>
312 312 ${h.form(h.route_path('login', _query={'came_from': h.current_route_path(request)}), needs_csrf_token=False)}
313 313 <div class="form form-vertical">
314 314 <div class="fields">
315 315 <div class="field">
316 316 <div class="label">
317 317 <label for="username">${_('Username')}:</label>
318 318 </div>
319 319 <div class="input">
320 320 ${h.text('username',class_='focus',tabindex=1)}
321 321 </div>
322 322
323 323 </div>
324 324 <div class="field">
325 325 <div class="label">
326 326 <label for="password">${_('Password')}:</label>
327 327 %if h.HasPermissionAny('hg.password_reset.enabled')():
328 328 <span class="forgot_password">${h.link_to(_('(Forgot password?)'),h.route_path('reset_password'), class_='pwd_reset')}</span>
329 329 %endif
330 330 </div>
331 331 <div class="input">
332 332 ${h.password('password',class_='focus',tabindex=2)}
333 333 </div>
334 334 </div>
335 335 <div class="buttons">
336 336 <div class="register">
337 337 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
338 338 ${h.link_to(_("Don't have an account?"),h.route_path('register'))} <br/>
339 339 %endif
340 340 ${h.link_to(_("Using external auth? Sign In here."),h.route_path('login'))}
341 341 </div>
342 342 <div class="submit">
343 343 ${h.submit('sign_in',_('Sign In'),class_="btn btn-small",tabindex=3)}
344 344 </div>
345 345 </div>
346 346 </div>
347 347 </div>
348 348 ${h.end_form()}
349 349 %else:
350 350 <div class="">
351 351 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
352 352 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
353 353 <div class="email">${c.rhodecode_user.email}</div>
354 354 </div>
355 355 <div class="">
356 356 <ol class="links">
357 357 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
358 358 % if c.rhodecode_user.personal_repo_group:
359 359 <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>
360 360 % endif
361 361 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
362 362
363 363 <li class="logout">
364 364 ${h.secure_form(h.route_path('logout'), request=request)}
365 365 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
366 366 ${h.end_form()}
367 367 </li>
368 368 </ol>
369 369 </div>
370 370 %endif
371 371 </div>
372 372 </div>
373 373 %if c.rhodecode_user.username != h.DEFAULT_USER:
374 374 <div class="pill_container">
375 375 <a class="menu_link_notifications ${'empty' if c.unread_notifications == 0 else ''}" href="${h.route_path('notifications_show_all')}">${c.unread_notifications}</a>
376 376 </div>
377 377 % endif
378 378 </li>
379 379 </%def>
380 380
381 381 <%def name="menu_items(active=None)">
382 382 <%
383 383 def is_active(selected):
384 384 if selected == active:
385 385 return "active"
386 386 return ""
387 387 %>
388 388 <ul id="quick" class="main_nav navigation horizontal-list">
389 389
390 390 ## Main filter
391 391 <li>
392 392 <div class="menulabel main_filter_box">
393 393 <div class="main_filter_input_box">
394 394 <input class="main_filter_input" id="main_filter" size="15" type="text" name="main_filter" placeholder="${_('search / go to...')}" value=""/>
395 395 </div>
396 396 <div class="main_filter_help_box">
397 397 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
398 398 </div>
399 399 </div>
400 400
401 401 <div id="main_filter_help" style="display: none">
402 402 Use '/' key to quickly access this field.
403 403 Enter name of repository, or repository group for quick search.
404 404
405 405 Prefix query to allow special search:
406 406
407 407 user:admin, to search for usernames
408 408
409 409 user_group:devops, to search for user groups
410 410
411 411 commit:efced4, to search for commits
412 412
413 413 </div>
414 414 </li>
415 415
416 416 ## ROOT MENU
417 417 %if c.rhodecode_user.username != h.DEFAULT_USER:
418 418 <li class="${is_active('journal')}">
419 419 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
420 420 <div class="menulabel">${_('Journal')}</div>
421 421 </a>
422 422 </li>
423 423 %else:
424 424 <li class="${is_active('journal')}">
425 425 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
426 426 <div class="menulabel">${_('Public journal')}</div>
427 427 </a>
428 428 </li>
429 429 %endif
430 430 <li class="${is_active('gists')}">
431 431 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
432 432 <div class="menulabel">${_('Gists')}</div>
433 433 </a>
434 434 </li>
435 435 <li class="${is_active('search')}">
436 436 <a class="menulink" title="${_('Search in repositories you have access to')}" href="${h.route_path('search')}">
437 437 <div class="menulabel">${_('Search')}</div>
438 438 </a>
439 439 </li>
440 440 % if h.HasPermissionAll('hg.admin')('access admin main page'):
441 441 <li class="${is_active('admin')}">
442 442 <a class="menulink childs" title="${_('Admin settings')}" href="#" onclick="return false;">
443 443 <div class="menulabel">${_('Admin')} <div class="show_more"></div></div>
444 444 </a>
445 445 ${admin_menu()}
446 446 </li>
447 447 % elif c.rhodecode_user.repositories_admin or c.rhodecode_user.repository_groups_admin or c.rhodecode_user.user_groups_admin:
448 448 <li class="${is_active('admin')}">
449 449 <a class="menulink childs" title="${_('Delegated Admin settings')}">
450 450 <div class="menulabel">${_('Admin')} <div class="show_more"></div></div>
451 451 </a>
452 452 ${admin_menu_simple(c.rhodecode_user.repositories_admin,
453 453 c.rhodecode_user.repository_groups_admin,
454 454 c.rhodecode_user.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
455 455 </li>
456 456 % endif
457 457 ## render extra user menu
458 458 ${usermenu(active=(active=='my_account'))}
459 459
460 460 % if c.debug_style:
461 461 <li class="${is_active('debug_style')}">
462 462 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
463 463 <div class="menulabel">${_('Style')}</div>
464 464 </a>
465 465 </li>
466 466 % endif
467 467 </ul>
468 468
469 469 <script type="text/javascript">
470 470 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
471 471
472 472 var formatRepoResult = function(result, container, query, escapeMarkup) {
473 473 return function(data, escapeMarkup) {
474 474 if (!data.repo_id){
475 475 return data.text; // optgroup text Repositories
476 476 }
477 477
478 478 var tmpl = '';
479 479 var repoType = data['repo_type'];
480 480 var repoName = data['text'];
481 481
482 482 if(data && data.type == 'repo'){
483 483 if(repoType === 'hg'){
484 484 tmpl += '<i class="icon-hg"></i> ';
485 485 }
486 486 else if(repoType === 'git'){
487 487 tmpl += '<i class="icon-git"></i> ';
488 488 }
489 489 else if(repoType === 'svn'){
490 490 tmpl += '<i class="icon-svn"></i> ';
491 491 }
492 492 if(data['private']){
493 493 tmpl += '<i class="icon-lock" ></i> ';
494 494 }
495 495 else if(visualShowPublicIcon){
496 496 tmpl += '<i class="icon-unlock-alt"></i> ';
497 497 }
498 498 }
499 499 tmpl += escapeMarkup(repoName);
500 500 return tmpl;
501 501
502 502 }(result, escapeMarkup);
503 503 };
504 504
505 505
506 506 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
507 507
508 508 if (value.split(':').length === 2) {
509 509 value = value.split(':')[1]
510 510 }
511 511
512 512 var searchType = data['type'];
513 513 var valueDisplay = data['value_display'];
514 514
515 515 var escapeRegExChars = function (value) {
516 516 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
517 517 };
518 518 var pattern = '(' + escapeRegExChars(value) + ')';
519 519
520 520 // highlight match
521 521 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
522 522 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
523 523
524 524 var icon = '';
525 525
526 if (searchType === 'search') {
526 if (searchType === 'hint') {
527 icon += '<i class="icon-folder-close"></i> ';
528 }
529 else if (searchType === 'search') {
527 530 icon += '<i class="icon-more"></i> ';
528 531 }
529 532 else if (searchType === 'repo') {
530 533 if (data['repo_type'] === 'hg') {
531 534 icon += '<i class="icon-hg"></i> ';
532 535 }
533 536 else if (data['repo_type'] === 'git') {
534 537 icon += '<i class="icon-git"></i> ';
535 538 }
536 539 else if (data['repo_type'] === 'svn') {
537 540 icon += '<i class="icon-svn"></i> ';
538 541 }
539 542 if (data['private']) {
540 543 icon += '<i class="icon-lock" ></i> ';
541 544 }
542 545 else if (visualShowPublicIcon) {
543 546 icon += '<i class="icon-unlock-alt"></i> ';
544 547 }
545 548 }
546 549 else if (searchType === 'repo_group') {
547 550 icon += '<i class="icon-folder-close"></i> ';
548 551 }
549 552 else if (searchType === 'user_group') {
550 553 icon += '<i class="icon-group"></i> ';
551 554 }
552 555 else if (searchType === 'user') {
553 556 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
554 557 }
555 558 else if (searchType === 'commit') {
556 559 icon += '<i class="icon-tag"></i>';
557 560 }
558 561
559 562 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
560 563 return tmpl.format(icon, valueDisplay);
561 564 };
562 565
563 566 var handleSelect = function(element, suggestion) {
564 window.location = suggestion['url'];
567 if (suggestion.type === "hint") {
568 // we skip action
569 $('#main_filter').focus();
570 } else {
571 window.location = suggestion['url'];
572 }
565 573 };
566 574 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
567 575 if (queryLowerCase.split(':').length === 2) {
568 576 queryLowerCase = queryLowerCase.split(':')[1]
569 577 }
570 578 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
571 579 };
572 580
573 581 $('#main_filter').autocomplete({
574 582 serviceUrl: pyroutes.url('goto_switcher_data'),
583 params: {"repo_group_id": templateContext.repo_group_id},
575 584 minChars:2,
576 585 maxHeight:400,
577 586 deferRequestBy: 300, //miliseconds
578 587 tabDisabled: true,
579 588 autoSelectFirst: true,
580 589 formatResult: autocompleteMainFilterFormatResult,
581 590 lookupFilter: autocompleteMainFilterResult,
582 591 onSelect: function(element, suggestion){
583 592 handleSelect(element, suggestion);
584 593 return false;
585 594 }
586 595 });
587 596
588 597 showMainFilterBox = function () {
589 598 $('#main_filter_help').toggle();
590 599 }
591 600
592 601 </script>
593 602 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
594 603 </%def>
595 604
596 605 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
597 606 <div class="modal-dialog">
598 607 <div class="modal-content">
599 608 <div class="modal-header">
600 609 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
601 610 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
602 611 </div>
603 612 <div class="modal-body">
604 613 <div class="block-left">
605 614 <table class="keyboard-mappings">
606 615 <tbody>
607 616 <tr>
608 617 <th></th>
609 618 <th>${_('Site-wide shortcuts')}</th>
610 619 </tr>
611 620 <%
612 621 elems = [
613 622 ('/', 'Use quick search box'),
614 623 ('g h', 'Goto home page'),
615 624 ('g g', 'Goto my private gists page'),
616 625 ('g G', 'Goto my public gists page'),
617 626 ('n r', 'New repository page'),
618 627 ('n g', 'New gist page'),
619 628 ]
620 629 %>
621 630 %for key, desc in elems:
622 631 <tr>
623 632 <td class="keys">
624 633 <span class="key tag">${key}</span>
625 634 </td>
626 635 <td>${desc}</td>
627 636 </tr>
628 637 %endfor
629 638 </tbody>
630 639 </table>
631 640 </div>
632 641 <div class="block-left">
633 642 <table class="keyboard-mappings">
634 643 <tbody>
635 644 <tr>
636 645 <th></th>
637 646 <th>${_('Repositories')}</th>
638 647 </tr>
639 648 <%
640 649 elems = [
641 650 ('g s', 'Goto summary page'),
642 651 ('g c', 'Goto changelog page'),
643 652 ('g f', 'Goto files page'),
644 653 ('g F', 'Goto files page with file search activated'),
645 654 ('g p', 'Goto pull requests page'),
646 655 ('g o', 'Goto repository settings'),
647 656 ('g O', 'Goto repository permissions settings'),
648 657 ]
649 658 %>
650 659 %for key, desc in elems:
651 660 <tr>
652 661 <td class="keys">
653 662 <span class="key tag">${key}</span>
654 663 </td>
655 664 <td>${desc}</td>
656 665 </tr>
657 666 %endfor
658 667 </tbody>
659 668 </table>
660 669 </div>
661 670 </div>
662 671 <div class="modal-footer">
663 672 </div>
664 673 </div><!-- /.modal-content -->
665 674 </div><!-- /.modal-dialog -->
666 675 </div><!-- /.modal -->
667 676
@@ -1,185 +1,188 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <!DOCTYPE html>
3 3
4 4 <%
5 5 c.template_context['repo_name'] = getattr(c, 'repo_name', '')
6 6 go_import_header = ''
7 7 if hasattr(c, 'rhodecode_db_repo'):
8 8 c.template_context['repo_type'] = c.rhodecode_db_repo.repo_type
9 9 c.template_context['repo_landing_commit'] = c.rhodecode_db_repo.landing_rev[1]
10 10
11 if getattr(c, 'repo_group', None):
12 c.template_context['repo_group_id'] = c.repo_group.group_id
13
11 14 if getattr(c, 'rhodecode_user', None) and c.rhodecode_user.user_id:
12 15 c.template_context['rhodecode_user']['username'] = c.rhodecode_user.username
13 16 c.template_context['rhodecode_user']['email'] = c.rhodecode_user.email
14 17 c.template_context['rhodecode_user']['notification_status'] = c.rhodecode_user.get_instance().user_data.get('notification_status', True)
15 18 c.template_context['rhodecode_user']['first_name'] = c.rhodecode_user.first_name
16 19 c.template_context['rhodecode_user']['last_name'] = c.rhodecode_user.last_name
17 20
18 21 c.template_context['visual']['default_renderer'] = h.get_visual_attr(c, 'default_renderer')
19 22 c.template_context['default_user'] = {
20 23 'username': h.DEFAULT_USER,
21 24 'user_id': 1
22 25 }
23 26
24 27 %>
25 28 <html xmlns="http://www.w3.org/1999/xhtml">
26 29 <head>
27 30 <script src="${h.asset('js/vendors/webcomponentsjs/webcomponents-lite.min.js', ver=c.rhodecode_version_hash)}"></script>
28 31 <link rel="import" href="${h.asset('js/rhodecode-components.html', ver=c.rhodecode_version_hash)}">
29 32 <title>${self.title()}</title>
30 33 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
31 34
32 35 ${h.go_import_header(request, getattr(c, 'rhodecode_db_repo', None))}
33 36
34 37 % if 'safari' in (request.user_agent or '').lower():
35 38 <meta name="referrer" content="origin">
36 39 % else:
37 40 <meta name="referrer" content="origin-when-cross-origin">
38 41 % endif
39 42
40 43 <%def name="robots()">
41 44 <meta name="robots" content="index, nofollow"/>
42 45 </%def>
43 46 ${self.robots()}
44 47 <link rel="icon" href="${h.asset('images/favicon.ico', ver=c.rhodecode_version_hash)}" sizes="16x16 32x32" type="image/png" />
45 48
46 49 ## CSS definitions
47 50 <%def name="css()">
48 51 <link rel="stylesheet" type="text/css" href="${h.asset('css/style.css', ver=c.rhodecode_version_hash)}" media="screen"/>
49 52 <!--[if lt IE 9]>
50 53 <link rel="stylesheet" type="text/css" href="${h.asset('css/ie.css', ver=c.rhodecode_version_hash)}" media="screen"/>
51 54 <![endif]-->
52 55 ## EXTRA FOR CSS
53 56 ${self.css_extra()}
54 57 </%def>
55 58 ## CSS EXTRA - optionally inject some extra CSS stuff needed for specific websites
56 59 <%def name="css_extra()">
57 60 </%def>
58 61
59 62 ${self.css()}
60 63
61 64 ## JAVASCRIPT
62 65 <%def name="js()">
63 66 <script>
64 67 // setup Polymer options
65 68 window.Polymer = {lazyRegister: true, dom: 'shadow'};
66 69
67 70 // Load webcomponentsjs polyfill if browser does not support native Web Components
68 71 (function() {
69 72 'use strict';
70 73 var onload = function() {
71 74 // For native Imports, manually fire WebComponentsReady so user code
72 75 // can use the same code path for native and polyfill'd imports.
73 76 if (!window.HTMLImports) {
74 77 document.dispatchEvent(
75 78 new CustomEvent('WebComponentsReady', {bubbles: true})
76 79 );
77 80 }
78 81 };
79 82 var webComponentsSupported = (
80 83 'registerElement' in document
81 84 && 'import' in document.createElement('link')
82 85 && 'content' in document.createElement('template')
83 86 );
84 87 if (!webComponentsSupported) {
85 88 } else {
86 89 onload();
87 90 }
88 91 })();
89 92 </script>
90 93
91 94 <script src="${h.asset('js/rhodecode/i18n/%s.js' % c.language, ver=c.rhodecode_version_hash)}"></script>
92 95 <script type="text/javascript">
93 96 // register templateContext to pass template variables to JS
94 97 var templateContext = ${h.json.dumps(c.template_context)|n};
95 98
96 99 var APPLICATION_URL = "${h.route_path('home').rstrip('/')}";
97 100 var ASSET_URL = "${h.asset('')}";
98 101 var DEFAULT_RENDERER = "${h.get_visual_attr(c, 'default_renderer')}";
99 102 var CSRF_TOKEN = "${getattr(c, 'csrf_token', '')}";
100 103
101 104 var APPENLIGHT = {
102 105 enabled: ${'true' if getattr(c, 'appenlight_enabled', False) else 'false'},
103 106 key: '${getattr(c, "appenlight_api_public_key", "")}',
104 107 % if getattr(c, 'appenlight_server_url', None):
105 108 serverUrl: '${getattr(c, "appenlight_server_url", "")}',
106 109 % endif
107 110 requestInfo: {
108 111 % if getattr(c, 'rhodecode_user', None):
109 112 ip: '${c.rhodecode_user.ip_addr}',
110 113 username: '${c.rhodecode_user.username}'
111 114 % endif
112 115 },
113 116 tags: {
114 117 rhodecode_version: '${c.rhodecode_version}',
115 118 rhodecode_edition: '${c.rhodecode_edition}'
116 119 }
117 120 };
118 121
119 122 </script>
120 123 <%include file="/base/plugins_base.mako"/>
121 124 <!--[if lt IE 9]>
122 125 <script language="javascript" type="text/javascript" src="${h.asset('js/src/excanvas.min.js')}"></script>
123 126 <![endif]-->
124 127 <script language="javascript" type="text/javascript" src="${h.asset('js/rhodecode/routes.js', ver=c.rhodecode_version_hash)}"></script>
125 128 <script> var alertMessagePayloads = ${h.flash.json_alerts(request=request)|n}; </script>
126 129 ## avoide escaping the %N
127 130 <script language="javascript" type="text/javascript" src="${h.asset('js/rhodecode-components.js', ver=c.rhodecode_version_hash)}"></script>
128 131 <script>CodeMirror.modeURL = "${h.asset('') + 'js/mode/%N/%N.js?ver='+c.rhodecode_version_hash}";</script>
129 132
130 133
131 134 ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates
132 135 ${self.js_extra()}
133 136
134 137 <script type="text/javascript">
135 138 Rhodecode = (function() {
136 139 function _Rhodecode() {
137 140 this.comments = new CommentsController();
138 141 }
139 142 return new _Rhodecode();
140 143 })();
141 144
142 145 $(document).ready(function(){
143 146 show_more_event();
144 147 timeagoActivate();
145 148 clipboardActivate();
146 149 })
147 150 </script>
148 151
149 152 </%def>
150 153
151 154 ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates
152 155 <%def name="js_extra()"></%def>
153 156 ${self.js()}
154 157
155 158 <%def name="head_extra()"></%def>
156 159 ${self.head_extra()}
157 160 ## extra stuff
158 161 %if c.pre_code:
159 162 ${c.pre_code|n}
160 163 %endif
161 164 </head>
162 165 <body id="body">
163 166 <noscript>
164 167 <div class="noscript-error">
165 168 ${_('Please enable JavaScript to use RhodeCode Enterprise')}
166 169 </div>
167 170 </noscript>
168 171 ## IE hacks
169 172 <!--[if IE 7]>
170 173 <script>$(document.body).addClass('ie7')</script>
171 174 <![endif]-->
172 175 <!--[if IE 8]>
173 176 <script>$(document.body).addClass('ie8')</script>
174 177 <![endif]-->
175 178 <!--[if IE 9]>
176 179 <script>$(document.body).addClass('ie9')</script>
177 180 <![endif]-->
178 181
179 182 ${next.body()}
180 183 %if c.post_code:
181 184 ${c.post_code|n}
182 185 %endif
183 186 <rhodecode-app></rhodecode-app>
184 187 </body>
185 188 </html>
General Comments 0
You need to be logged in to leave comments. Login now