##// END OF EJS Templates
quick-filter: added nicer UI and hints.
ergo -
r3750:20052068 new-ui
parent child Browse files
Show More
@@ -1,749 +1,756 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-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 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 CSRFRequired)
32 32 from rhodecode.lib.index import searcher_from_config
33 33 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
34 34 from rhodecode.lib.ext_json import json
35 35 from rhodecode.model.db import (
36 36 func, true, or_, case, in_filter_generator, Repository, RepoGroup, User, UserGroup)
37 37 from rhodecode.model.repo import RepoModel
38 38 from rhodecode.model.repo_group import RepoGroupModel
39 39 from rhodecode.model.scm import RepoGroupList, RepoList
40 40 from rhodecode.model.user import UserModel
41 41 from rhodecode.model.user_group import UserGroupModel
42 42
43 43 log = logging.getLogger(__name__)
44 44
45 45
46 46 class HomeView(BaseAppView):
47 47
48 48 def load_default_context(self):
49 49 c = self._get_local_tmpl_context()
50 50 c.user = c.auth_user.get_instance()
51 51
52 52 return c
53 53
54 54 @LoginRequired()
55 55 @view_config(
56 56 route_name='user_autocomplete_data', request_method='GET',
57 57 renderer='json_ext', xhr=True)
58 58 def user_autocomplete_data(self):
59 59 self.load_default_context()
60 60 query = self.request.GET.get('query')
61 61 active = str2bool(self.request.GET.get('active') or True)
62 62 include_groups = str2bool(self.request.GET.get('user_groups'))
63 63 expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
64 64 skip_default_user = str2bool(self.request.GET.get('skip_default_user'))
65 65
66 66 log.debug('generating user list, query:%s, active:%s, with_groups:%s',
67 67 query, active, include_groups)
68 68
69 69 _users = UserModel().get_users(
70 70 name_contains=query, only_active=active)
71 71
72 72 def maybe_skip_default_user(usr):
73 73 if skip_default_user and usr['username'] == UserModel.cls.DEFAULT_USER:
74 74 return False
75 75 return True
76 76 _users = filter(maybe_skip_default_user, _users)
77 77
78 78 if include_groups:
79 79 # extend with user groups
80 80 _user_groups = UserGroupModel().get_user_groups(
81 81 name_contains=query, only_active=active,
82 82 expand_groups=expand_groups)
83 83 _users = _users + _user_groups
84 84
85 85 return {'suggestions': _users}
86 86
87 87 @LoginRequired()
88 88 @NotAnonymous()
89 89 @view_config(
90 90 route_name='user_group_autocomplete_data', request_method='GET',
91 91 renderer='json_ext', xhr=True)
92 92 def user_group_autocomplete_data(self):
93 93 self.load_default_context()
94 94 query = self.request.GET.get('query')
95 95 active = str2bool(self.request.GET.get('active') or True)
96 96 expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
97 97
98 98 log.debug('generating user group list, query:%s, active:%s',
99 99 query, active)
100 100
101 101 _user_groups = UserGroupModel().get_user_groups(
102 102 name_contains=query, only_active=active,
103 103 expand_groups=expand_groups)
104 104 _user_groups = _user_groups
105 105
106 106 return {'suggestions': _user_groups}
107 107
108 108 def _get_repo_list(self, name_contains=None, repo_type=None, repo_group_name='', limit=20):
109 109 org_query = name_contains
110 110 allowed_ids = self._rhodecode_user.repo_acl_ids(
111 111 ['repository.read', 'repository.write', 'repository.admin'],
112 112 cache=False, name_filter=name_contains) or [-1]
113 113
114 114 query = Repository.query()\
115 115 .filter(Repository.archived.isnot(true()))\
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 query = query.order_by(case(
122 122 [
123 123 (Repository.repo_name.startswith(repo_group_name), repo_group_name+'/'),
124 124 ],
125 125 ))
126 126 query = query.order_by(func.length(Repository.repo_name))
127 127 query = query.order_by(Repository.repo_name)
128 128
129 129 if repo_type:
130 130 query = query.filter(Repository.repo_type == repo_type)
131 131
132 132 if name_contains:
133 133 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
134 134 query = query.filter(
135 135 Repository.repo_name.ilike(ilike_expression))
136 136 query = query.limit(limit)
137 137
138 138 acl_iter = query
139 139
140 140 return [
141 141 {
142 142 'id': obj.repo_name,
143 143 'value': org_query,
144 144 'value_display': obj.repo_name,
145 145 'text': obj.repo_name,
146 146 'type': 'repo',
147 147 'repo_id': obj.repo_id,
148 148 'repo_type': obj.repo_type,
149 149 'private': obj.private,
150 150 'url': h.route_path('repo_summary', repo_name=obj.repo_name)
151 151 }
152 152 for obj in acl_iter]
153 153
154 154 def _get_repo_group_list(self, name_contains=None, repo_group_name='', limit=20):
155 155 org_query = name_contains
156 156 allowed_ids = self._rhodecode_user.repo_group_acl_ids(
157 157 ['group.read', 'group.write', 'group.admin'],
158 158 cache=False, name_filter=name_contains) or [-1]
159 159
160 160 query = RepoGroup.query()\
161 161 .filter(or_(
162 162 # generate multiple IN to fix limitation problems
163 163 *in_filter_generator(RepoGroup.group_id, allowed_ids)
164 164 ))
165 165
166 166 query = query.order_by(case(
167 167 [
168 168 (RepoGroup.group_name.startswith(repo_group_name), repo_group_name+'/'),
169 169 ],
170 170 ))
171 171 query = query.order_by(func.length(RepoGroup.group_name))
172 172 query = query.order_by(RepoGroup.group_name)
173 173
174 174 if name_contains:
175 175 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
176 176 query = query.filter(
177 177 RepoGroup.group_name.ilike(ilike_expression))
178 178 query = query.limit(limit)
179 179
180 180 acl_iter = query
181 181
182 182 return [
183 183 {
184 184 'id': obj.group_name,
185 185 'value': org_query,
186 186 'value_display': obj.group_name,
187 187 'text': obj.group_name,
188 188 'type': 'repo_group',
189 189 'repo_group_id': obj.group_id,
190 190 'url': h.route_path(
191 191 'repo_group_home', repo_group_name=obj.group_name)
192 192 }
193 193 for obj in acl_iter]
194 194
195 195 def _get_user_list(self, name_contains=None, limit=20):
196 196 org_query = name_contains
197 197 if not name_contains:
198 198 return [], False
199 199
200 200 # TODO(marcink): should all logged in users be allowed to search others?
201 201 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
202 202 if not allowed_user_search:
203 203 return [], False
204 204
205 205 name_contains = re.compile('(?:user:[ ]?)(.+)').findall(name_contains)
206 206 if len(name_contains) != 1:
207 207 return [], False
208 208
209 209 name_contains = name_contains[0]
210 210
211 211 query = User.query()\
212 212 .order_by(func.length(User.username))\
213 213 .order_by(User.username) \
214 214 .filter(User.username != User.DEFAULT_USER)
215 215
216 216 if name_contains:
217 217 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
218 218 query = query.filter(
219 219 User.username.ilike(ilike_expression))
220 220 query = query.limit(limit)
221 221
222 222 acl_iter = query
223 223
224 224 return [
225 225 {
226 226 'id': obj.user_id,
227 227 'value': org_query,
228 228 'value_display': 'user: `{}`'.format(obj.username),
229 229 'type': 'user',
230 230 'icon_link': h.gravatar_url(obj.email, 30),
231 231 'url': h.route_path(
232 232 'user_profile', username=obj.username)
233 233 }
234 234 for obj in acl_iter], True
235 235
236 236 def _get_user_groups_list(self, name_contains=None, limit=20):
237 237 org_query = name_contains
238 238 if not name_contains:
239 239 return [], False
240 240
241 241 # TODO(marcink): should all logged in users be allowed to search others?
242 242 allowed_user_search = self._rhodecode_user.username != User.DEFAULT_USER
243 243 if not allowed_user_search:
244 244 return [], False
245 245
246 246 name_contains = re.compile('(?:user_group:[ ]?)(.+)').findall(name_contains)
247 247 if len(name_contains) != 1:
248 248 return [], False
249 249
250 250 name_contains = name_contains[0]
251 251
252 252 query = UserGroup.query()\
253 253 .order_by(func.length(UserGroup.users_group_name))\
254 254 .order_by(UserGroup.users_group_name)
255 255
256 256 if name_contains:
257 257 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
258 258 query = query.filter(
259 259 UserGroup.users_group_name.ilike(ilike_expression))
260 260 query = query.limit(limit)
261 261
262 262 acl_iter = query
263 263
264 264 return [
265 265 {
266 266 'id': obj.users_group_id,
267 267 'value': org_query,
268 268 'value_display': 'user_group: `{}`'.format(obj.users_group_name),
269 269 'type': 'user_group',
270 270 'url': h.route_path(
271 271 'user_group_profile', user_group_name=obj.users_group_name)
272 272 }
273 273 for obj in acl_iter], True
274 274
275 275 def _get_hash_commit_list(self, auth_user, searcher, query, repo=None, repo_group=None):
276 276 repo_name = repo_group_name = None
277 277 if repo:
278 278 repo_name = repo.repo_name
279 279 if repo_group:
280 280 repo_group_name = repo_group.group_name
281 281
282 282 org_query = query
283 283 if not query or len(query) < 3 or not searcher:
284 284 return [], False
285 285
286 286 commit_hashes = re.compile('(?:commit:[ ]?)([0-9a-f]{2,40})').findall(query)
287 287
288 288 if len(commit_hashes) != 1:
289 289 return [], False
290 290
291 291 commit_hash = commit_hashes[0]
292 292
293 293 result = searcher.search(
294 294 'commit_id:{}*'.format(commit_hash), 'commit', auth_user,
295 295 repo_name, repo_group_name, raise_on_exc=False)
296 296
297 297 commits = []
298 298 for entry in result['results']:
299 299 repo_data = {
300 300 'repository_id': entry.get('repository_id'),
301 301 'repository_type': entry.get('repo_type'),
302 302 'repository_name': entry.get('repository'),
303 303 }
304 304
305 305 commit_entry = {
306 306 'id': entry['commit_id'],
307 307 'value': org_query,
308 308 'value_display': '`{}` commit: {}'.format(
309 309 entry['repository'], entry['commit_id']),
310 310 'type': 'commit',
311 311 'repo': entry['repository'],
312 312 'repo_data': repo_data,
313 313
314 314 'url': h.route_path(
315 315 'repo_commit',
316 316 repo_name=entry['repository'], commit_id=entry['commit_id'])
317 317 }
318 318
319 319 commits.append(commit_entry)
320 320 return commits, True
321 321
322 322 def _get_path_list(self, auth_user, searcher, query, repo=None, repo_group=None):
323 323 repo_name = repo_group_name = None
324 324 if repo:
325 325 repo_name = repo.repo_name
326 326 if repo_group:
327 327 repo_group_name = repo_group.group_name
328 328
329 329 org_query = query
330 330 if not query or len(query) < 3 or not searcher:
331 331 return [], False
332 332
333 333 paths_re = re.compile('(?:file:[ ]?)(.+)').findall(query)
334 334 if len(paths_re) != 1:
335 335 return [], False
336 336
337 337 file_path = paths_re[0]
338 338
339 339 search_path = searcher.escape_specials(file_path)
340 340 result = searcher.search(
341 341 'file.raw:*{}*'.format(search_path), 'path', auth_user,
342 342 repo_name, repo_group_name, raise_on_exc=False)
343 343
344 344 files = []
345 345 for entry in result['results']:
346 346 repo_data = {
347 347 'repository_id': entry.get('repository_id'),
348 348 'repository_type': entry.get('repo_type'),
349 349 'repository_name': entry.get('repository'),
350 350 }
351 351
352 352 file_entry = {
353 353 'id': entry['commit_id'],
354 354 'value': org_query,
355 355 'value_display': '`{}` file: {}'.format(
356 356 entry['repository'], entry['file']),
357 357 'type': 'file',
358 358 'repo': entry['repository'],
359 359 'repo_data': repo_data,
360 360
361 361 'url': h.route_path(
362 362 'repo_files',
363 363 repo_name=entry['repository'], commit_id=entry['commit_id'],
364 364 f_path=entry['file'])
365 365 }
366 366
367 367 files.append(file_entry)
368 368 return files, True
369 369
370 370 @LoginRequired()
371 371 @view_config(
372 372 route_name='repo_list_data', request_method='GET',
373 373 renderer='json_ext', xhr=True)
374 374 def repo_list_data(self):
375 375 _ = self.request.translate
376 376 self.load_default_context()
377 377
378 378 query = self.request.GET.get('query')
379 379 repo_type = self.request.GET.get('repo_type')
380 380 log.debug('generating repo list, query:%s, repo_type:%s',
381 381 query, repo_type)
382 382
383 383 res = []
384 384 repos = self._get_repo_list(query, repo_type=repo_type)
385 385 if repos:
386 386 res.append({
387 387 'text': _('Repositories'),
388 388 'children': repos
389 389 })
390 390
391 391 data = {
392 392 'more': False,
393 393 'results': res
394 394 }
395 395 return data
396 396
397 397 @LoginRequired()
398 398 @view_config(
399 399 route_name='repo_group_list_data', request_method='GET',
400 400 renderer='json_ext', xhr=True)
401 401 def repo_group_list_data(self):
402 402 _ = self.request.translate
403 403 self.load_default_context()
404 404
405 405 query = self.request.GET.get('query')
406 406
407 407 log.debug('generating repo group list, query:%s',
408 408 query)
409 409
410 410 res = []
411 411 repo_groups = self._get_repo_group_list(query)
412 412 if repo_groups:
413 413 res.append({
414 414 'text': _('Repository Groups'),
415 415 'children': repo_groups
416 416 })
417 417
418 418 data = {
419 419 'more': False,
420 420 'results': res
421 421 }
422 422 return data
423 423
424 424 def _get_default_search_queries(self, search_context, searcher, query):
425 425 if not searcher:
426 426 return []
427 427
428 428 is_es_6 = searcher.is_es_6
429 429
430 430 queries = []
431 431 repo_group_name, repo_name, repo_context = None, None, None
432 432
433 433 # repo group context
434 434 if search_context.get('search_context[repo_group_name]'):
435 435 repo_group_name = search_context.get('search_context[repo_group_name]')
436 436 if search_context.get('search_context[repo_name]'):
437 437 repo_name = search_context.get('search_context[repo_name]')
438 438 repo_context = search_context.get('search_context[repo_view_type]')
439 439
440 440 if is_es_6 and repo_name:
441 441 # files
442 442 def query_modifier():
443 443 qry = query
444 444 return {'q': qry, 'type': 'content'}
445 label = u'File search for `{}` in this repository.'.format(query)
445
446 label = u'File search for `{}`'.format(h.escape(query))
446 447 file_qry = {
447 448 'id': -10,
448 449 'value': query,
449 450 'value_display': label,
450 451 'type': 'search',
452 'subtype': 'repo',
451 453 'url': h.route_path('search_repo',
452 454 repo_name=repo_name,
453 455 _query=query_modifier())
454 456 }
455 457
456 458 # commits
457 459 def query_modifier():
458 460 qry = query
459 461 return {'q': qry, 'type': 'commit'}
460 462
461 label = u'Commit search for `{}` in this repository.'.format(query)
463 label = u'Commit search for `{}`'.format(h.escape(query))
462 464 commit_qry = {
463 465 'id': -20,
464 466 'value': query,
465 467 'value_display': label,
466 468 'type': 'search',
469 'subtype': 'repo',
467 470 'url': h.route_path('search_repo',
468 471 repo_name=repo_name,
469 472 _query=query_modifier())
470 473 }
471 474
472 475 if repo_context in ['commit', 'commits']:
473 476 queries.extend([commit_qry, file_qry])
474 477 elif repo_context in ['files', 'summary']:
475 478 queries.extend([file_qry, commit_qry])
476 479 else:
477 480 queries.extend([commit_qry, file_qry])
478 481
479 482 elif is_es_6 and repo_group_name:
480 483 # files
481 484 def query_modifier():
482 485 qry = query
483 486 return {'q': qry, 'type': 'content'}
484 487
485 label = u'File search for `{}` in this repository group'.format(query)
488 label = u'File search for `{}`'.format(query)
486 489 file_qry = {
487 490 'id': -30,
488 491 'value': query,
489 492 'value_display': label,
490 493 'type': 'search',
494 'subtype': 'repo_group',
491 495 'url': h.route_path('search_repo_group',
492 496 repo_group_name=repo_group_name,
493 497 _query=query_modifier())
494 498 }
495 499
496 500 # commits
497 501 def query_modifier():
498 502 qry = query
499 503 return {'q': qry, 'type': 'commit'}
500 504
501 label = u'Commit search for `{}` in this repository group'.format(query)
505 label = u'Commit search for `{}`'.format(query)
502 506 commit_qry = {
503 507 'id': -40,
504 508 'value': query,
505 509 'value_display': label,
506 510 'type': 'search',
511 'subtype': 'repo_group',
507 512 'url': h.route_path('search_repo_group',
508 513 repo_group_name=repo_group_name,
509 514 _query=query_modifier())
510 515 }
511 516
512 517 if repo_context in ['commit', 'commits']:
513 518 queries.extend([commit_qry, file_qry])
514 519 elif repo_context in ['files', 'summary']:
515 520 queries.extend([file_qry, commit_qry])
516 521 else:
517 522 queries.extend([commit_qry, file_qry])
518 523
519 524 # Global, not scoped
520 525 if not queries:
521 526 queries.append(
522 527 {
523 528 'id': -1,
524 529 'value': query,
525 530 'value_display': u'File search for: `{}`'.format(query),
526 531 'type': 'search',
532 'subtype': 'global',
527 533 'url': h.route_path('search',
528 534 _query={'q': query, 'type': 'content'})
529 535 })
530 536 queries.append(
531 537 {
532 538 'id': -2,
533 539 'value': query,
534 540 'value_display': u'Commit search for: `{}`'.format(query),
535 541 'type': 'search',
542 'subtype': 'global',
536 543 'url': h.route_path('search',
537 544 _query={'q': query, 'type': 'commit'})
538 545 })
539 546
540 547 return queries
541 548
542 549 @LoginRequired()
543 550 @view_config(
544 551 route_name='goto_switcher_data', request_method='GET',
545 552 renderer='json_ext', xhr=True)
546 553 def goto_switcher_data(self):
547 554 c = self.load_default_context()
548 555
549 556 _ = self.request.translate
550 557
551 558 query = self.request.GET.get('query')
552 559 log.debug('generating main filter data, query %s', query)
553 560
554 561 res = []
555 562 if not query:
556 563 return {'suggestions': res}
557 564
558 565 def no_match(name):
559 566 return {
560 567 'id': -1,
561 568 'value': "",
562 569 'value_display': name,
563 570 'type': 'text',
564 571 'url': ""
565 572 }
566 573 searcher = searcher_from_config(self.request.registry.settings)
567 574 has_specialized_search = False
568 575
569 576 # set repo context
570 577 repo = None
571 578 repo_id = safe_int(self.request.GET.get('search_context[repo_id]'))
572 579 if repo_id:
573 580 repo = Repository.get(repo_id)
574 581
575 582 # set group context
576 583 repo_group = None
577 584 repo_group_id = safe_int(self.request.GET.get('search_context[repo_group_id]'))
578 585 if repo_group_id:
579 586 repo_group = RepoGroup.get(repo_group_id)
580 587 prefix_match = False
581 588
582 589 # user: type search
583 590 if not prefix_match:
584 591 users, prefix_match = self._get_user_list(query)
585 592 if users:
586 593 has_specialized_search = True
587 594 for serialized_user in users:
588 595 res.append(serialized_user)
589 596 elif prefix_match:
590 597 has_specialized_search = True
591 598 res.append(no_match('No matching users found'))
592 599
593 600 # user_group: type search
594 601 if not prefix_match:
595 602 user_groups, prefix_match = self._get_user_groups_list(query)
596 603 if user_groups:
597 604 has_specialized_search = True
598 605 for serialized_user_group in user_groups:
599 606 res.append(serialized_user_group)
600 607 elif prefix_match:
601 608 has_specialized_search = True
602 609 res.append(no_match('No matching user groups found'))
603 610
604 611 # FTS commit: type search
605 612 if not prefix_match:
606 613 commits, prefix_match = self._get_hash_commit_list(
607 614 c.auth_user, searcher, query, repo, repo_group)
608 615 if commits:
609 616 has_specialized_search = True
610 617 unique_repos = collections.OrderedDict()
611 618 for commit in commits:
612 619 repo_name = commit['repo']
613 620 unique_repos.setdefault(repo_name, []).append(commit)
614 621
615 622 for _repo, commits in unique_repos.items():
616 623 for commit in commits:
617 624 res.append(commit)
618 625 elif prefix_match:
619 626 has_specialized_search = True
620 627 res.append(no_match('No matching commits found'))
621 628
622 629 # FTS file: type search
623 630 if not prefix_match:
624 631 paths, prefix_match = self._get_path_list(
625 632 c.auth_user, searcher, query, repo, repo_group)
626 633 if paths:
627 634 has_specialized_search = True
628 635 unique_repos = collections.OrderedDict()
629 636 for path in paths:
630 637 repo_name = path['repo']
631 638 unique_repos.setdefault(repo_name, []).append(path)
632 639
633 640 for repo, paths in unique_repos.items():
634 641 for path in paths:
635 642 res.append(path)
636 643 elif prefix_match:
637 644 has_specialized_search = True
638 645 res.append(no_match('No matching files found'))
639 646
640 647 # main suggestions
641 648 if not has_specialized_search:
642 649 repo_group_name = ''
643 650 if repo_group:
644 651 repo_group_name = repo_group.group_name
645 652
646 653 for _q in self._get_default_search_queries(self.request.GET, searcher, query):
647 654 res.append(_q)
648 655
649 656 repo_groups = self._get_repo_group_list(query, repo_group_name=repo_group_name)
650 657 for serialized_repo_group in repo_groups:
651 658 res.append(serialized_repo_group)
652 659
653 660 repos = self._get_repo_list(query, repo_group_name=repo_group_name)
654 661 for serialized_repo in repos:
655 662 res.append(serialized_repo)
656 663
657 664 if not repos and not repo_groups:
658 665 res.append(no_match('No matches found'))
659 666
660 667 return {'suggestions': res}
661 668
662 669 def _get_groups_and_repos(self, repo_group_id=None):
663 670 # repo groups groups
664 671 repo_group_list = RepoGroup.get_all_repo_groups(group_id=repo_group_id)
665 672 _perms = ['group.read', 'group.write', 'group.admin']
666 673 repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms)
667 674 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
668 675 repo_group_list=repo_group_list_acl, admin=False)
669 676
670 677 # repositories
671 678 repo_list = Repository.get_all_repos(group_id=repo_group_id)
672 679 _perms = ['repository.read', 'repository.write', 'repository.admin']
673 680 repo_list_acl = RepoList(repo_list, perm_set=_perms)
674 681 repo_data = RepoModel().get_repos_as_dict(
675 682 repo_list=repo_list_acl, admin=False)
676 683
677 684 return repo_data, repo_group_data
678 685
679 686 @LoginRequired()
680 687 @view_config(
681 688 route_name='home', request_method='GET',
682 689 renderer='rhodecode:templates/index.mako')
683 690 def main_page(self):
684 691 c = self.load_default_context()
685 692 c.repo_group = None
686 693
687 694 repo_data, repo_group_data = self._get_groups_and_repos()
688 695 # json used to render the grids
689 696 c.repos_data = json.dumps(repo_data)
690 697 c.repo_groups_data = json.dumps(repo_group_data)
691 698
692 699 return self._get_template_context(c)
693 700
694 701 @LoginRequired()
695 702 @HasRepoGroupPermissionAnyDecorator(
696 703 'group.read', 'group.write', 'group.admin')
697 704 @view_config(
698 705 route_name='repo_group_home', request_method='GET',
699 706 renderer='rhodecode:templates/index_repo_group.mako')
700 707 @view_config(
701 708 route_name='repo_group_home_slash', request_method='GET',
702 709 renderer='rhodecode:templates/index_repo_group.mako')
703 710 def repo_group_main_page(self):
704 711 c = self.load_default_context()
705 712 c.repo_group = self.request.db_repo_group
706 713 repo_data, repo_group_data = self._get_groups_and_repos(c.repo_group.group_id)
707 714
708 715 # update every 5 min
709 716 if self.request.db_repo_group.last_commit_cache_update_diff > 60 * 5:
710 717 self.request.db_repo_group.update_commit_cache()
711 718
712 719 # json used to render the grids
713 720 c.repos_data = json.dumps(repo_data)
714 721 c.repo_groups_data = json.dumps(repo_group_data)
715 722
716 723 return self._get_template_context(c)
717 724
718 725 @LoginRequired()
719 726 @CSRFRequired()
720 727 @view_config(
721 728 route_name='markup_preview', request_method='POST',
722 729 renderer='string', xhr=True)
723 730 def markup_preview(self):
724 731 # Technically a CSRF token is not needed as no state changes with this
725 732 # call. However, as this is a POST is better to have it, so automated
726 733 # tools don't flag it as potential CSRF.
727 734 # Post is required because the payload could be bigger than the maximum
728 735 # allowed by GET.
729 736
730 737 text = self.request.POST.get('text')
731 738 renderer = self.request.POST.get('renderer') or 'rst'
732 739 if text:
733 740 return h.render(text, renderer=renderer, mentions=True)
734 741 return ''
735 742
736 743 @LoginRequired()
737 744 @CSRFRequired()
738 745 @view_config(
739 746 route_name='store_user_session_value', request_method='POST',
740 747 renderer='string', xhr=True)
741 748 def store_user_session_attr(self):
742 749 key = self.request.POST.get('key')
743 750 val = self.request.POST.get('val')
744 751
745 752 existing_value = self.request.session.get(key)
746 753 if existing_value != val:
747 754 self.request.session[key] = val
748 755
749 756 return 'stored:{}:{}'.format(key, val)
@@ -1,2608 +1,2618 b''
1 1 //Primary CSS
2 2
3 3 //--- IMPORTS ------------------//
4 4
5 5 @import 'helpers';
6 6 @import 'mixins';
7 7 @import 'rcicons';
8 8 @import 'variables';
9 9 @import 'bootstrap-variables';
10 10 @import 'form-bootstrap';
11 11 @import 'codemirror';
12 12 @import 'legacy_code_styles';
13 13 @import 'readme-box';
14 14 @import 'progress-bar';
15 15
16 16 @import 'type';
17 17 @import 'alerts';
18 18 @import 'buttons';
19 19 @import 'tags';
20 20 @import 'code-block';
21 21 @import 'examples';
22 22 @import 'login';
23 23 @import 'main-content';
24 24 @import 'select2';
25 25 @import 'comments';
26 26 @import 'panels-bootstrap';
27 27 @import 'panels';
28 28 @import 'deform';
29 29
30 30 //--- BASE ------------------//
31 31 .noscript-error {
32 32 top: 0;
33 33 left: 0;
34 34 width: 100%;
35 35 z-index: 101;
36 36 text-align: center;
37 37 font-size: 120%;
38 38 color: white;
39 39 background-color: @alert2;
40 40 padding: 5px 0 5px 0;
41 41 font-weight: @text-semibold-weight;
42 42 font-family: @text-semibold;
43 43 }
44 44
45 45 html {
46 46 display: table;
47 47 height: 100%;
48 48 width: 100%;
49 49 }
50 50
51 51 body {
52 52 display: table-cell;
53 53 width: 100%;
54 54 }
55 55
56 56 //--- LAYOUT ------------------//
57 57
58 58 .hidden{
59 59 display: none !important;
60 60 }
61 61
62 62 .box{
63 63 float: left;
64 64 width: 100%;
65 65 }
66 66
67 67 .browser-header {
68 68 clear: both;
69 69 }
70 70 .main {
71 71 clear: both;
72 72 padding:0 0 @pagepadding;
73 73 height: auto;
74 74
75 75 &:after { //clearfix
76 76 content:"";
77 77 clear:both;
78 78 width:100%;
79 79 display:block;
80 80 }
81 81 }
82 82
83 83 .action-link{
84 84 margin-left: @padding;
85 85 padding-left: @padding;
86 86 border-left: @border-thickness solid @border-default-color;
87 87 }
88 88
89 89 input + .action-link, .action-link.first{
90 90 border-left: none;
91 91 }
92 92
93 93 .action-link.last{
94 94 margin-right: @padding;
95 95 padding-right: @padding;
96 96 }
97 97
98 98 .action-link.active,
99 99 .action-link.active a{
100 100 color: @grey4;
101 101 }
102 102
103 103 .action-link.disabled {
104 104 color: @grey4;
105 105 cursor: inherit;
106 106 }
107 107
108 108 .clipboard-action {
109 109 cursor: pointer;
110 110 color: @grey4;
111 111 margin-left: 5px;
112 112
113 113 &:hover {
114 114 color: @grey2;
115 115 }
116 116 }
117 117
118 118 ul.simple-list{
119 119 list-style: none;
120 120 margin: 0;
121 121 padding: 0;
122 122 }
123 123
124 124 .main-content {
125 125 padding-bottom: @pagepadding;
126 126 }
127 127
128 128 .wide-mode-wrapper {
129 129 max-width:4000px !important;
130 130 }
131 131
132 132 .wrapper {
133 133 position: relative;
134 134 max-width: @wrapper-maxwidth;
135 135 margin: 0 auto;
136 136 }
137 137
138 138 #content {
139 139 clear: both;
140 140 padding: 0 @contentpadding;
141 141 }
142 142
143 143 .advanced-settings-fields{
144 144 input{
145 145 margin-left: @textmargin;
146 146 margin-right: @padding/2;
147 147 }
148 148 }
149 149
150 150 .cs_files_title {
151 151 margin: @pagepadding 0 0;
152 152 }
153 153
154 154 input.inline[type="file"] {
155 155 display: inline;
156 156 }
157 157
158 158 .error_page {
159 159 margin: 10% auto;
160 160
161 161 h1 {
162 162 color: @grey2;
163 163 }
164 164
165 165 .alert {
166 166 margin: @padding 0;
167 167 }
168 168
169 169 .error-branding {
170 170 color: @grey4;
171 171 font-weight: @text-semibold-weight;
172 172 font-family: @text-semibold;
173 173 }
174 174
175 175 .error_message {
176 176 font-family: @text-regular;
177 177 }
178 178
179 179 .sidebar {
180 180 min-height: 275px;
181 181 margin: 0;
182 182 padding: 0 0 @sidebarpadding @sidebarpadding;
183 183 border: none;
184 184 }
185 185
186 186 .main-content {
187 187 position: relative;
188 188 margin: 0 @sidebarpadding @sidebarpadding;
189 189 padding: 0 0 0 @sidebarpadding;
190 190 border-left: @border-thickness solid @grey5;
191 191
192 192 @media (max-width:767px) {
193 193 clear: both;
194 194 width: 100%;
195 195 margin: 0;
196 196 border: none;
197 197 }
198 198 }
199 199
200 200 .inner-column {
201 201 float: left;
202 202 width: 29.75%;
203 203 min-height: 150px;
204 204 margin: @sidebarpadding 2% 0 0;
205 205 padding: 0 2% 0 0;
206 206 border-right: @border-thickness solid @grey5;
207 207
208 208 @media (max-width:767px) {
209 209 clear: both;
210 210 width: 100%;
211 211 border: none;
212 212 }
213 213
214 214 ul {
215 215 padding-left: 1.25em;
216 216 }
217 217
218 218 &:last-child {
219 219 margin: @sidebarpadding 0 0;
220 220 border: none;
221 221 }
222 222
223 223 h4 {
224 224 margin: 0 0 @padding;
225 225 font-weight: @text-semibold-weight;
226 226 font-family: @text-semibold;
227 227 }
228 228 }
229 229 }
230 230 .error-page-logo {
231 231 width: 130px;
232 232 height: 160px;
233 233 }
234 234
235 235 // HEADER
236 236 .header {
237 237
238 238 // TODO: johbo: Fix login pages, so that they work without a min-height
239 239 // for the header and then remove the min-height. I chose a smaller value
240 240 // intentionally here to avoid rendering issues in the main navigation.
241 241 min-height: 49px;
242 242
243 243 position: relative;
244 244 vertical-align: bottom;
245 245 padding: 0 @header-padding;
246 246 background-color: @grey1;
247 247 color: @grey5;
248 248
249 249 .title {
250 250 overflow: visible;
251 251 }
252 252
253 253 &:before,
254 254 &:after {
255 255 content: "";
256 256 clear: both;
257 257 width: 100%;
258 258 }
259 259
260 260 // TODO: johbo: Avoids breaking "Repositories" chooser
261 261 .select2-container .select2-choice .select2-arrow {
262 262 display: none;
263 263 }
264 264 }
265 265
266 266 #header-inner {
267 267 &.title {
268 268 margin: 0;
269 269 }
270 270 &:before,
271 271 &:after {
272 272 content: "";
273 273 clear: both;
274 274 }
275 275 }
276 276
277 277 // Gists
278 278 #files_data {
279 279 clear: both; //for firefox
280 280 }
281 281 #gistid {
282 282 margin-right: @padding;
283 283 }
284 284
285 285 // Global Settings Editor
286 286 .textarea.editor {
287 287 float: left;
288 288 position: relative;
289 289 max-width: @texteditor-width;
290 290
291 291 select {
292 292 position: absolute;
293 293 top:10px;
294 294 right:0;
295 295 }
296 296
297 297 .CodeMirror {
298 298 margin: 0;
299 299 }
300 300
301 301 .help-block {
302 302 margin: 0 0 @padding;
303 303 padding:.5em;
304 304 background-color: @grey6;
305 305 &.pre-formatting {
306 306 white-space: pre;
307 307 }
308 308 }
309 309 }
310 310
311 311 ul.auth_plugins {
312 312 margin: @padding 0 @padding @legend-width;
313 313 padding: 0;
314 314
315 315 li {
316 316 margin-bottom: @padding;
317 317 line-height: 1em;
318 318 list-style-type: none;
319 319
320 320 .auth_buttons .btn {
321 321 margin-right: @padding;
322 322 }
323 323
324 324 }
325 325 }
326 326
327 327
328 328 // My Account PR list
329 329
330 330 #show_closed {
331 331 margin: 0 1em 0 0;
332 332 }
333 333
334 334 .pullrequestlist {
335 335 .closed {
336 336 background-color: @grey6;
337 337 }
338 338 .td-status {
339 339 padding-left: .5em;
340 340 }
341 341 .log-container .truncate {
342 342 height: 2.75em;
343 343 white-space: pre-line;
344 344 }
345 345 table.rctable .user {
346 346 padding-left: 0;
347 347 }
348 348 table.rctable {
349 349 td.td-description,
350 350 .rc-user {
351 351 min-width: auto;
352 352 }
353 353 }
354 354 }
355 355
356 356 // Pull Requests
357 357
358 358 .pullrequests_section_head {
359 359 display: block;
360 360 clear: both;
361 361 margin: @padding 0;
362 362 font-weight: @text-bold-weight;
363 363 font-family: @text-bold;
364 364 }
365 365
366 366 .pr-origininfo, .pr-targetinfo {
367 367 position: relative;
368 368
369 369 .tag {
370 370 display: inline-block;
371 371 margin: 0 1em .5em 0;
372 372 }
373 373
374 374 .clone-url {
375 375 display: inline-block;
376 376 margin: 0 0 .5em 0;
377 377 padding: 0;
378 378 line-height: 1.2em;
379 379 }
380 380 }
381 381
382 382 .pr-mergeinfo {
383 383 min-width: 95% !important;
384 384 padding: 0 !important;
385 385 border: 0;
386 386 }
387 387 .pr-mergeinfo-copy {
388 388 padding: 0 0;
389 389 }
390 390
391 391 .pr-pullinfo {
392 392 min-width: 95% !important;
393 393 padding: 0 !important;
394 394 border: 0;
395 395 }
396 396 .pr-pullinfo-copy {
397 397 padding: 0 0;
398 398 }
399 399
400 400
401 401 #pr-title-input {
402 402 width: 72%;
403 403 font-size: 1em;
404 404 margin: 0;
405 405 padding: 0 0 0 @padding/4;
406 406 line-height: 1.7em;
407 407 color: @text-color;
408 408 letter-spacing: .02em;
409 409 font-weight: @text-bold-weight;
410 410 font-family: @text-bold;
411 411 }
412 412
413 413 #pullrequest_title {
414 414 width: 100%;
415 415 box-sizing: border-box;
416 416 }
417 417
418 418 #pr_open_message {
419 419 border: @border-thickness solid #fff;
420 420 border-radius: @border-radius;
421 421 padding: @padding-large-vertical @padding-large-vertical @padding-large-vertical 0;
422 422 text-align: left;
423 423 overflow: hidden;
424 424 }
425 425
426 426 .pr-submit-button {
427 427 float: right;
428 428 margin: 0 0 0 5px;
429 429 }
430 430
431 431 .pr-spacing-container {
432 432 padding: 20px;
433 433 clear: both
434 434 }
435 435
436 436 #pr-description-input {
437 437 margin-bottom: 0;
438 438 }
439 439
440 440 .pr-description-label {
441 441 vertical-align: top;
442 442 }
443 443
444 444 .perms_section_head {
445 445 min-width: 625px;
446 446
447 447 h2 {
448 448 margin-bottom: 0;
449 449 }
450 450
451 451 .label-checkbox {
452 452 float: left;
453 453 }
454 454
455 455 &.field {
456 456 margin: @space 0 @padding;
457 457 }
458 458
459 459 &:first-child.field {
460 460 margin-top: 0;
461 461
462 462 .label {
463 463 margin-top: 0;
464 464 padding-top: 0;
465 465 }
466 466
467 467 .radios {
468 468 padding-top: 0;
469 469 }
470 470 }
471 471
472 472 .radios {
473 473 position: relative;
474 474 width: 505px;
475 475 }
476 476 }
477 477
478 478 //--- MODULES ------------------//
479 479
480 480
481 481 // Server Announcement
482 482 #server-announcement {
483 483 width: 95%;
484 484 margin: @padding auto;
485 485 padding: @padding;
486 486 border-width: 2px;
487 487 border-style: solid;
488 488 .border-radius(2px);
489 489 font-weight: @text-bold-weight;
490 490 font-family: @text-bold;
491 491
492 492 &.info { border-color: @alert4; background-color: @alert4-inner; }
493 493 &.warning { border-color: @alert3; background-color: @alert3-inner; }
494 494 &.error { border-color: @alert2; background-color: @alert2-inner; }
495 495 &.success { border-color: @alert1; background-color: @alert1-inner; }
496 496 &.neutral { border-color: @grey3; background-color: @grey6; }
497 497 }
498 498
499 499 // Fixed Sidebar Column
500 500 .sidebar-col-wrapper {
501 501 padding-left: @sidebar-all-width;
502 502
503 503 .sidebar {
504 504 width: @sidebar-width;
505 505 margin-left: -@sidebar-all-width;
506 506 }
507 507 }
508 508
509 509 .sidebar-col-wrapper.scw-small {
510 510 padding-left: @sidebar-small-all-width;
511 511
512 512 .sidebar {
513 513 width: @sidebar-small-width;
514 514 margin-left: -@sidebar-small-all-width;
515 515 }
516 516 }
517 517
518 518
519 519 // FOOTER
520 520 #footer {
521 521 padding: 0;
522 522 text-align: center;
523 523 vertical-align: middle;
524 524 color: @grey2;
525 525 font-size: 11px;
526 526
527 527 p {
528 528 margin: 0;
529 529 padding: 1em;
530 530 line-height: 1em;
531 531 }
532 532
533 533 .server-instance { //server instance
534 534 display: none;
535 535 }
536 536
537 537 .title {
538 538 float: none;
539 539 margin: 0 auto;
540 540 }
541 541 }
542 542
543 543 button.close {
544 544 padding: 0;
545 545 cursor: pointer;
546 546 background: transparent;
547 547 border: 0;
548 548 .box-shadow(none);
549 549 -webkit-appearance: none;
550 550 }
551 551
552 552 .close {
553 553 float: right;
554 554 font-size: 21px;
555 555 font-family: @text-bootstrap;
556 556 line-height: 1em;
557 557 font-weight: bold;
558 558 color: @grey2;
559 559
560 560 &:hover,
561 561 &:focus {
562 562 color: @grey1;
563 563 text-decoration: none;
564 564 cursor: pointer;
565 565 }
566 566 }
567 567
568 568 // GRID
569 569 .sorting,
570 570 .sorting_desc,
571 571 .sorting_asc {
572 572 cursor: pointer;
573 573 }
574 574 .sorting_desc:after {
575 575 content: "\00A0\25B2";
576 576 font-size: .75em;
577 577 }
578 578 .sorting_asc:after {
579 579 content: "\00A0\25BC";
580 580 font-size: .68em;
581 581 }
582 582
583 583
584 584 .user_auth_tokens {
585 585
586 586 &.truncate {
587 587 white-space: nowrap;
588 588 overflow: hidden;
589 589 text-overflow: ellipsis;
590 590 }
591 591
592 592 .fields .field .input {
593 593 margin: 0;
594 594 }
595 595
596 596 input#description {
597 597 width: 100px;
598 598 margin: 0;
599 599 }
600 600
601 601 .drop-menu {
602 602 // TODO: johbo: Remove this, should work out of the box when
603 603 // having multiple inputs inline
604 604 margin: 0 0 0 5px;
605 605 }
606 606 }
607 607 #user_list_table {
608 608 .closed {
609 609 background-color: @grey6;
610 610 }
611 611 }
612 612
613 613
614 614 input, textarea {
615 615 &.disabled {
616 616 opacity: .5;
617 617 }
618 618
619 619 &:hover {
620 620 border-color: @grey3;
621 621 box-shadow: @button-shadow;
622 622 }
623 623
624 624 &:focus {
625 625 border-color: @rcblue;
626 626 box-shadow: @button-shadow;
627 627 }
628 628 }
629 629
630 630 // remove extra padding in firefox
631 631 input::-moz-focus-inner { border:0; padding:0 }
632 632
633 633 .adjacent input {
634 634 margin-bottom: @padding;
635 635 }
636 636
637 637 .permissions_boxes {
638 638 display: block;
639 639 }
640 640
641 641 //FORMS
642 642
643 643 .medium-inline,
644 644 input#description.medium-inline {
645 645 display: inline;
646 646 width: @medium-inline-input-width;
647 647 min-width: 100px;
648 648 }
649 649
650 650 select {
651 651 //reset
652 652 -webkit-appearance: none;
653 653 -moz-appearance: none;
654 654
655 655 display: inline-block;
656 656 height: 28px;
657 657 width: auto;
658 658 margin: 0 @padding @padding 0;
659 659 padding: 0 18px 0 8px;
660 660 line-height:1em;
661 661 font-size: @basefontsize;
662 662 border: @border-thickness solid @grey5;
663 663 border-radius: @border-radius;
664 664 background:white url("../images/dt-arrow-dn.png") no-repeat 100% 50%;
665 665 color: @grey4;
666 666 box-shadow: @button-shadow;
667 667
668 668 &:after {
669 669 content: "\00A0\25BE";
670 670 }
671 671
672 672 &:focus, &:hover {
673 673 outline: none;
674 674 border-color: @grey4;
675 675 color: @rcdarkblue;
676 676 }
677 677 }
678 678
679 679 option {
680 680 &:focus {
681 681 outline: none;
682 682 }
683 683 }
684 684
685 685 input,
686 686 textarea {
687 687 padding: @input-padding;
688 688 border: @input-border-thickness solid @border-highlight-color;
689 689 .border-radius (@border-radius);
690 690 font-family: @text-light;
691 691 font-size: @basefontsize;
692 692
693 693 &.input-sm {
694 694 padding: 5px;
695 695 }
696 696
697 697 &#description {
698 698 min-width: @input-description-minwidth;
699 699 min-height: 1em;
700 700 padding: 10px;
701 701 }
702 702 }
703 703
704 704 .field-sm {
705 705 input,
706 706 textarea {
707 707 padding: 5px;
708 708 }
709 709 }
710 710
711 711 textarea {
712 712 display: block;
713 713 clear: both;
714 714 width: 100%;
715 715 min-height: 100px;
716 716 margin-bottom: @padding;
717 717 .box-sizing(border-box);
718 718 overflow: auto;
719 719 }
720 720
721 721 label {
722 722 font-family: @text-light;
723 723 }
724 724
725 725 // GRAVATARS
726 726 // centers gravatar on username to the right
727 727
728 728 .gravatar {
729 729 display: inline;
730 730 min-width: 16px;
731 731 min-height: 16px;
732 732 margin: -5px 0;
733 733 padding: 0;
734 734 line-height: 1em;
735 735 box-sizing: content-box;
736 736 border-radius: 50%;
737 737
738 738 &.gravatar-large {
739 739 margin: -0.5em .25em -0.5em 0;
740 740 }
741 741
742 742 & + .user {
743 743 display: inline;
744 744 margin: 0;
745 745 padding: 0 0 0 .17em;
746 746 line-height: 1em;
747 747 }
748 748 }
749 749
750 750 .user-inline-data {
751 751 display: inline-block;
752 752 float: left;
753 753 padding-left: .5em;
754 754 line-height: 1.3em;
755 755 }
756 756
757 757 .rc-user { // gravatar + user wrapper
758 758 float: left;
759 759 position: relative;
760 760 min-width: 100px;
761 761 max-width: 200px;
762 762 min-height: (@gravatar-size + @border-thickness * 2); // account for border
763 763 display: block;
764 764 padding: 0 0 0 (@gravatar-size + @basefontsize/2 + @border-thickness * 2);
765 765
766 766
767 767 .gravatar {
768 768 display: block;
769 769 position: absolute;
770 770 top: 0;
771 771 left: 0;
772 772 min-width: @gravatar-size;
773 773 min-height: @gravatar-size;
774 774 margin: 0;
775 775 }
776 776
777 777 .user {
778 778 display: block;
779 779 max-width: 175px;
780 780 padding-top: 2px;
781 781 overflow: hidden;
782 782 text-overflow: ellipsis;
783 783 }
784 784 }
785 785
786 786 .gist-gravatar,
787 787 .journal_container {
788 788 .gravatar-large {
789 789 margin: 0 .5em -10px 0;
790 790 }
791 791 }
792 792
793 793
794 794 // ADMIN SETTINGS
795 795
796 796 // Tag Patterns
797 797 .tag_patterns {
798 798 .tag_input {
799 799 margin-bottom: @padding;
800 800 }
801 801 }
802 802
803 803 .locked_input {
804 804 position: relative;
805 805
806 806 input {
807 807 display: inline;
808 808 margin: 3px 5px 0px 0px;
809 809 }
810 810
811 811 br {
812 812 display: none;
813 813 }
814 814
815 815 .error-message {
816 816 float: left;
817 817 width: 100%;
818 818 }
819 819
820 820 .lock_input_button {
821 821 display: inline;
822 822 }
823 823
824 824 .help-block {
825 825 clear: both;
826 826 }
827 827 }
828 828
829 829 // Notifications
830 830
831 831 .notifications_buttons {
832 832 margin: 0 0 @space 0;
833 833 padding: 0;
834 834
835 835 .btn {
836 836 display: inline-block;
837 837 }
838 838 }
839 839
840 840 .notification-list {
841 841
842 842 div {
843 843 display: inline-block;
844 844 vertical-align: middle;
845 845 }
846 846
847 847 .container {
848 848 display: block;
849 849 margin: 0 0 @padding 0;
850 850 }
851 851
852 852 .delete-notifications {
853 853 margin-left: @padding;
854 854 text-align: right;
855 855 cursor: pointer;
856 856 }
857 857
858 858 .read-notifications {
859 859 margin-left: @padding/2;
860 860 text-align: right;
861 861 width: 35px;
862 862 cursor: pointer;
863 863 }
864 864
865 865 .icon-minus-sign {
866 866 color: @alert2;
867 867 }
868 868
869 869 .icon-ok-sign {
870 870 color: @alert1;
871 871 }
872 872 }
873 873
874 874 .user_settings {
875 875 float: left;
876 876 clear: both;
877 877 display: block;
878 878 width: 100%;
879 879
880 880 .gravatar_box {
881 881 margin-bottom: @padding;
882 882
883 883 &:after {
884 884 content: " ";
885 885 clear: both;
886 886 width: 100%;
887 887 }
888 888 }
889 889
890 890 .fields .field {
891 891 clear: both;
892 892 }
893 893 }
894 894
895 895 .advanced_settings {
896 896 margin-bottom: @space;
897 897
898 898 .help-block {
899 899 margin-left: 0;
900 900 }
901 901
902 902 button + .help-block {
903 903 margin-top: @padding;
904 904 }
905 905 }
906 906
907 907 // admin settings radio buttons and labels
908 908 .label-2 {
909 909 float: left;
910 910 width: @label2-width;
911 911
912 912 label {
913 913 color: @grey1;
914 914 }
915 915 }
916 916 .checkboxes {
917 917 float: left;
918 918 width: @checkboxes-width;
919 919 margin-bottom: @padding;
920 920
921 921 .checkbox {
922 922 width: 100%;
923 923
924 924 label {
925 925 margin: 0;
926 926 padding: 0;
927 927 }
928 928 }
929 929
930 930 .checkbox + .checkbox {
931 931 display: inline-block;
932 932 }
933 933
934 934 label {
935 935 margin-right: 1em;
936 936 }
937 937 }
938 938
939 939 // CHANGELOG
940 940 .container_header {
941 941 float: left;
942 942 display: block;
943 943 width: 100%;
944 944 margin: @padding 0 @padding;
945 945
946 946 #filter_changelog {
947 947 float: left;
948 948 margin-right: @padding;
949 949 }
950 950
951 951 .breadcrumbs_light {
952 952 display: inline-block;
953 953 }
954 954 }
955 955
956 956 .info_box {
957 957 float: right;
958 958 }
959 959
960 960
961 961 #graph_nodes {
962 962 padding-top: 43px;
963 963 }
964 964
965 965 #graph_content{
966 966
967 967 // adjust for table headers so that graph renders properly
968 968 // #graph_nodes padding - table cell padding
969 969 padding-top: (@space - (@basefontsize * 2.4));
970 970
971 971 &.graph_full_width {
972 972 width: 100%;
973 973 max-width: 100%;
974 974 }
975 975 }
976 976
977 977 #graph {
978 978 .flag_status {
979 979 margin: 0;
980 980 }
981 981
982 982 .pagination-left {
983 983 float: left;
984 984 clear: both;
985 985 }
986 986
987 987 .log-container {
988 988 max-width: 345px;
989 989
990 990 .message{
991 991 max-width: 340px;
992 992 }
993 993 }
994 994
995 995 .graph-col-wrapper {
996 996 padding-left: 110px;
997 997
998 998 #graph_nodes {
999 999 width: 100px;
1000 1000 margin-left: -110px;
1001 1001 float: left;
1002 1002 clear: left;
1003 1003 }
1004 1004 }
1005 1005
1006 1006 .load-more-commits {
1007 1007 text-align: center;
1008 1008 }
1009 1009 .load-more-commits:hover {
1010 1010 background-color: @grey7;
1011 1011 }
1012 1012 .load-more-commits {
1013 1013 a {
1014 1014 display: block;
1015 1015 }
1016 1016 }
1017 1017 }
1018 1018
1019 1019 #filter_changelog {
1020 1020 float: left;
1021 1021 }
1022 1022
1023 1023
1024 1024 //--- THEME ------------------//
1025 1025
1026 1026 #logo {
1027 1027 float: left;
1028 1028 margin: 9px 0 0 0;
1029 1029
1030 1030 .header {
1031 1031 background-color: transparent;
1032 1032 }
1033 1033
1034 1034 a {
1035 1035 display: inline-block;
1036 1036 }
1037 1037
1038 1038 img {
1039 1039 height:30px;
1040 1040 }
1041 1041 }
1042 1042
1043 1043 .logo-wrapper {
1044 1044 float:left;
1045 1045 }
1046 1046
1047 1047 .branding {
1048 1048 float: left;
1049 1049 padding: 9px 2px;
1050 1050 line-height: 1em;
1051 1051 font-size: @navigation-fontsize;
1052 1052
1053 1053 a {
1054 1054 color: @grey5
1055 1055 }
1056 1056 }
1057 1057
1058 1058 img {
1059 1059 border: none;
1060 1060 outline: none;
1061 1061 }
1062 1062 user-profile-header
1063 1063 label {
1064 1064
1065 1065 input[type="checkbox"] {
1066 1066 margin-right: 1em;
1067 1067 }
1068 1068 input[type="radio"] {
1069 1069 margin-right: 1em;
1070 1070 }
1071 1071 }
1072 1072
1073 1073 .flag_status {
1074 1074 margin: 2px;
1075 1075 &.under_review {
1076 1076 .circle(5px, @alert3);
1077 1077 }
1078 1078 &.approved {
1079 1079 .circle(5px, @alert1);
1080 1080 }
1081 1081 &.rejected,
1082 1082 &.forced_closed{
1083 1083 .circle(5px, @alert2);
1084 1084 }
1085 1085 &.not_reviewed {
1086 1086 .circle(5px, @grey5);
1087 1087 }
1088 1088 }
1089 1089
1090 1090 .flag_status_comment_box {
1091 1091 margin: 5px 6px 0px 2px;
1092 1092 }
1093 1093 .test_pattern_preview {
1094 1094 margin: @space 0;
1095 1095
1096 1096 p {
1097 1097 margin-bottom: 0;
1098 1098 border-bottom: @border-thickness solid @border-default-color;
1099 1099 color: @grey3;
1100 1100 }
1101 1101
1102 1102 .btn {
1103 1103 margin-bottom: @padding;
1104 1104 }
1105 1105 }
1106 1106 #test_pattern_result {
1107 1107 display: none;
1108 1108 &:extend(pre);
1109 1109 padding: .9em;
1110 1110 color: @grey3;
1111 1111 background-color: @grey7;
1112 1112 border-right: @border-thickness solid @border-default-color;
1113 1113 border-bottom: @border-thickness solid @border-default-color;
1114 1114 border-left: @border-thickness solid @border-default-color;
1115 1115 }
1116 1116
1117 1117 #repo_vcs_settings {
1118 1118 #inherit_overlay_vcs_default {
1119 1119 display: none;
1120 1120 }
1121 1121 #inherit_overlay_vcs_custom {
1122 1122 display: custom;
1123 1123 }
1124 1124 &.inherited {
1125 1125 #inherit_overlay_vcs_default {
1126 1126 display: block;
1127 1127 }
1128 1128 #inherit_overlay_vcs_custom {
1129 1129 display: none;
1130 1130 }
1131 1131 }
1132 1132 }
1133 1133
1134 1134 .issue-tracker-link {
1135 1135 color: @rcblue;
1136 1136 }
1137 1137
1138 1138 // Issue Tracker Table Show/Hide
1139 1139 #repo_issue_tracker {
1140 1140 #inherit_overlay {
1141 1141 display: none;
1142 1142 }
1143 1143 #custom_overlay {
1144 1144 display: custom;
1145 1145 }
1146 1146 &.inherited {
1147 1147 #inherit_overlay {
1148 1148 display: block;
1149 1149 }
1150 1150 #custom_overlay {
1151 1151 display: none;
1152 1152 }
1153 1153 }
1154 1154 }
1155 1155 table.issuetracker {
1156 1156 &.readonly {
1157 1157 tr, td {
1158 1158 color: @grey3;
1159 1159 }
1160 1160 }
1161 1161 .edit {
1162 1162 display: none;
1163 1163 }
1164 1164 .editopen {
1165 1165 .edit {
1166 1166 display: inline;
1167 1167 }
1168 1168 .entry {
1169 1169 display: none;
1170 1170 }
1171 1171 }
1172 1172 tr td.td-action {
1173 1173 min-width: 117px;
1174 1174 }
1175 1175 td input {
1176 1176 max-width: none;
1177 1177 min-width: 30px;
1178 1178 width: 80%;
1179 1179 }
1180 1180 .issuetracker_pref input {
1181 1181 width: 40%;
1182 1182 }
1183 1183 input.edit_issuetracker_update {
1184 1184 margin-right: 0;
1185 1185 width: auto;
1186 1186 }
1187 1187 }
1188 1188
1189 1189 table.integrations {
1190 1190 .td-icon {
1191 1191 width: 20px;
1192 1192 .integration-icon {
1193 1193 height: 20px;
1194 1194 width: 20px;
1195 1195 }
1196 1196 }
1197 1197 }
1198 1198
1199 1199 .integrations {
1200 1200 a.integration-box {
1201 1201 color: @text-color;
1202 1202 &:hover {
1203 1203 .panel {
1204 1204 background: #fbfbfb;
1205 1205 }
1206 1206 }
1207 1207 .integration-icon {
1208 1208 width: 30px;
1209 1209 height: 30px;
1210 1210 margin-right: 20px;
1211 1211 float: left;
1212 1212 }
1213 1213
1214 1214 .panel-body {
1215 1215 padding: 10px;
1216 1216 }
1217 1217 .panel {
1218 1218 margin-bottom: 10px;
1219 1219 }
1220 1220 h2 {
1221 1221 display: inline-block;
1222 1222 margin: 0;
1223 1223 min-width: 140px;
1224 1224 }
1225 1225 }
1226 1226 a.integration-box.dummy-integration {
1227 1227 color: @grey4
1228 1228 }
1229 1229 }
1230 1230
1231 1231 //Permissions Settings
1232 1232 #add_perm {
1233 1233 margin: 0 0 @padding;
1234 1234 cursor: pointer;
1235 1235 }
1236 1236
1237 1237 .perm_ac {
1238 1238 input {
1239 1239 width: 95%;
1240 1240 }
1241 1241 }
1242 1242
1243 1243 .autocomplete-suggestions {
1244 1244 width: auto !important; // overrides autocomplete.js
1245 1245 min-width: 278px;
1246 1246 margin: 0;
1247 1247 border: @border-thickness solid @grey5;
1248 1248 border-radius: @border-radius;
1249 1249 color: @grey2;
1250 1250 background-color: white;
1251 1251 }
1252 1252
1253 .autocomplete-qfilter-suggestions {
1254 width: auto !important; // overrides autocomplete.js
1255 max-height: 100% !important;
1256 min-width: 376px;
1257 margin: 0;
1258 border: @border-thickness solid @grey5;
1259 color: @grey2;
1260 background-color: white;
1261 }
1262
1253 1263 .autocomplete-selected {
1254 1264 background: #F0F0F0;
1255 1265 }
1256 1266
1257 1267 .ac-container-wrap {
1258 1268 margin: 0;
1259 1269 padding: 8px;
1260 1270 border-bottom: @border-thickness solid @grey5;
1261 1271 list-style-type: none;
1262 1272 cursor: pointer;
1263 1273
1264 1274 &:hover {
1265 1275 background-color: @grey7;
1266 1276 }
1267 1277
1268 1278 img {
1269 1279 height: @gravatar-size;
1270 1280 width: @gravatar-size;
1271 1281 margin-right: 1em;
1272 1282 }
1273 1283
1274 1284 strong {
1275 1285 font-weight: normal;
1276 1286 }
1277 1287 }
1278 1288
1279 1289 // Settings Dropdown
1280 1290 .user-menu .container {
1281 1291 padding: 0 4px;
1282 1292 margin: 0;
1283 1293 }
1284 1294
1285 1295 .user-menu .gravatar {
1286 1296 cursor: pointer;
1287 1297 }
1288 1298
1289 1299 .codeblock {
1290 1300 margin-bottom: @padding;
1291 1301 clear: both;
1292 1302
1293 1303 .stats {
1294 1304 overflow: hidden;
1295 1305 }
1296 1306
1297 1307 .message{
1298 1308 textarea{
1299 1309 margin: 0;
1300 1310 }
1301 1311 }
1302 1312
1303 1313 .code-header {
1304 1314 .stats {
1305 1315 line-height: 2em;
1306 1316
1307 1317 .revision_id {
1308 1318 margin-left: 0;
1309 1319 }
1310 1320 .buttons {
1311 1321 padding-right: 0;
1312 1322 }
1313 1323 }
1314 1324
1315 1325 .item{
1316 1326 margin-right: 0.5em;
1317 1327 }
1318 1328 }
1319 1329
1320 1330 #editor_container{
1321 1331 position: relative;
1322 1332 margin: @padding;
1323 1333 }
1324 1334 }
1325 1335
1326 1336 #file_history_container {
1327 1337 display: none;
1328 1338 }
1329 1339
1330 1340 .file-history-inner {
1331 1341 margin-bottom: 10px;
1332 1342 }
1333 1343
1334 1344 // Pull Requests
1335 1345 .summary-details {
1336 1346 width: 72%;
1337 1347 }
1338 1348 .pr-summary {
1339 1349 border-bottom: @border-thickness solid @grey5;
1340 1350 margin-bottom: @space;
1341 1351 }
1342 1352 .reviewers-title {
1343 1353 width: 25%;
1344 1354 min-width: 200px;
1345 1355 }
1346 1356 .reviewers {
1347 1357 width: 25%;
1348 1358 min-width: 200px;
1349 1359 }
1350 1360 .reviewers ul li {
1351 1361 position: relative;
1352 1362 width: 100%;
1353 1363 padding-bottom: 8px;
1354 1364 list-style-type: none;
1355 1365 }
1356 1366
1357 1367 .reviewer_entry {
1358 1368 min-height: 55px;
1359 1369 }
1360 1370
1361 1371 .reviewers_member {
1362 1372 width: 100%;
1363 1373 overflow: auto;
1364 1374 }
1365 1375 .reviewer_reason {
1366 1376 padding-left: 20px;
1367 1377 line-height: 1.5em;
1368 1378 }
1369 1379 .reviewer_status {
1370 1380 display: inline-block;
1371 1381 vertical-align: top;
1372 1382 width: 25px;
1373 1383 min-width: 25px;
1374 1384 height: 1.2em;
1375 1385 margin-top: 3px;
1376 1386 line-height: 1em;
1377 1387 }
1378 1388
1379 1389 .reviewer_name {
1380 1390 display: inline-block;
1381 1391 max-width: 83%;
1382 1392 padding-right: 20px;
1383 1393 vertical-align: middle;
1384 1394 line-height: 1;
1385 1395
1386 1396 .rc-user {
1387 1397 min-width: 0;
1388 1398 margin: -2px 1em 0 0;
1389 1399 }
1390 1400
1391 1401 .reviewer {
1392 1402 float: left;
1393 1403 }
1394 1404 }
1395 1405
1396 1406 .reviewer_member_mandatory {
1397 1407 position: absolute;
1398 1408 left: 15px;
1399 1409 top: 8px;
1400 1410 width: 16px;
1401 1411 font-size: 11px;
1402 1412 margin: 0;
1403 1413 padding: 0;
1404 1414 color: black;
1405 1415 }
1406 1416
1407 1417 .reviewer_member_mandatory_remove,
1408 1418 .reviewer_member_remove {
1409 1419 position: absolute;
1410 1420 right: 0;
1411 1421 top: 0;
1412 1422 width: 16px;
1413 1423 margin-bottom: 10px;
1414 1424 padding: 0;
1415 1425 color: black;
1416 1426 }
1417 1427
1418 1428 .reviewer_member_mandatory_remove {
1419 1429 color: @grey4;
1420 1430 }
1421 1431
1422 1432 .reviewer_member_status {
1423 1433 margin-top: 5px;
1424 1434 }
1425 1435 .pr-summary #summary{
1426 1436 width: 100%;
1427 1437 }
1428 1438 .pr-summary .action_button:hover {
1429 1439 border: 0;
1430 1440 cursor: pointer;
1431 1441 }
1432 1442 .pr-details-title {
1433 1443 padding-bottom: 8px;
1434 1444 border-bottom: @border-thickness solid @grey5;
1435 1445
1436 1446 .action_button.disabled {
1437 1447 color: @grey4;
1438 1448 cursor: inherit;
1439 1449 }
1440 1450 .action_button {
1441 1451 color: @rcblue;
1442 1452 }
1443 1453 }
1444 1454 .pr-details-content {
1445 1455 margin-top: @textmargin;
1446 1456 margin-bottom: @textmargin;
1447 1457 }
1448 1458
1449 1459 .pr-reviewer-rules {
1450 1460 padding: 10px 0px 20px 0px;
1451 1461 }
1452 1462
1453 1463 .group_members {
1454 1464 margin-top: 0;
1455 1465 padding: 0;
1456 1466 list-style: outside none none;
1457 1467
1458 1468 img {
1459 1469 height: @gravatar-size;
1460 1470 width: @gravatar-size;
1461 1471 margin-right: .5em;
1462 1472 margin-left: 3px;
1463 1473 }
1464 1474
1465 1475 .to-delete {
1466 1476 .user {
1467 1477 text-decoration: line-through;
1468 1478 }
1469 1479 }
1470 1480 }
1471 1481
1472 1482 .compare_view_commits_title {
1473 1483 .disabled {
1474 1484 cursor: inherit;
1475 1485 &:hover{
1476 1486 background-color: inherit;
1477 1487 color: inherit;
1478 1488 }
1479 1489 }
1480 1490 }
1481 1491
1482 1492 .subtitle-compare {
1483 1493 margin: -15px 0px 0px 0px;
1484 1494 }
1485 1495
1486 1496 .comments-summary-td {
1487 1497 border-top: 1px dashed @grey5;
1488 1498 }
1489 1499
1490 1500 // new entry in group_members
1491 1501 .td-author-new-entry {
1492 1502 background-color: rgba(red(@alert1), green(@alert1), blue(@alert1), 0.3);
1493 1503 }
1494 1504
1495 1505 .usergroup_member_remove {
1496 1506 width: 16px;
1497 1507 margin-bottom: 10px;
1498 1508 padding: 0;
1499 1509 color: black !important;
1500 1510 cursor: pointer;
1501 1511 }
1502 1512
1503 1513 .reviewer_ac .ac-input {
1504 1514 width: 92%;
1505 1515 margin-bottom: 1em;
1506 1516 }
1507 1517
1508 1518 .compare_view_commits tr{
1509 1519 height: 20px;
1510 1520 }
1511 1521 .compare_view_commits td {
1512 1522 vertical-align: top;
1513 1523 padding-top: 10px;
1514 1524 }
1515 1525 .compare_view_commits .author {
1516 1526 margin-left: 5px;
1517 1527 }
1518 1528
1519 1529 .compare_view_commits {
1520 1530 .color-a {
1521 1531 color: @alert1;
1522 1532 }
1523 1533
1524 1534 .color-c {
1525 1535 color: @color3;
1526 1536 }
1527 1537
1528 1538 .color-r {
1529 1539 color: @color5;
1530 1540 }
1531 1541
1532 1542 .color-a-bg {
1533 1543 background-color: @alert1;
1534 1544 }
1535 1545
1536 1546 .color-c-bg {
1537 1547 background-color: @alert3;
1538 1548 }
1539 1549
1540 1550 .color-r-bg {
1541 1551 background-color: @alert2;
1542 1552 }
1543 1553
1544 1554 .color-a-border {
1545 1555 border: 1px solid @alert1;
1546 1556 }
1547 1557
1548 1558 .color-c-border {
1549 1559 border: 1px solid @alert3;
1550 1560 }
1551 1561
1552 1562 .color-r-border {
1553 1563 border: 1px solid @alert2;
1554 1564 }
1555 1565
1556 1566 .commit-change-indicator {
1557 1567 width: 15px;
1558 1568 height: 15px;
1559 1569 position: relative;
1560 1570 left: 15px;
1561 1571 }
1562 1572
1563 1573 .commit-change-content {
1564 1574 text-align: center;
1565 1575 vertical-align: middle;
1566 1576 line-height: 15px;
1567 1577 }
1568 1578 }
1569 1579
1570 1580 .compare_view_filepath {
1571 1581 color: @grey1;
1572 1582 }
1573 1583
1574 1584 .show_more {
1575 1585 display: inline-block;
1576 1586 width: 0;
1577 1587 height: 0;
1578 1588 vertical-align: middle;
1579 1589 content: "";
1580 1590 border: 4px solid;
1581 1591 border-right-color: transparent;
1582 1592 border-bottom-color: transparent;
1583 1593 border-left-color: transparent;
1584 1594 font-size: 0;
1585 1595 }
1586 1596
1587 1597 .journal_more .show_more {
1588 1598 display: inline;
1589 1599
1590 1600 &:after {
1591 1601 content: none;
1592 1602 }
1593 1603 }
1594 1604
1595 1605 .compare_view_commits .collapse_commit:after {
1596 1606 cursor: pointer;
1597 1607 content: "\00A0\25B4";
1598 1608 margin-left: -3px;
1599 1609 font-size: 17px;
1600 1610 color: @grey4;
1601 1611 }
1602 1612
1603 1613 .diff_links {
1604 1614 margin-left: 8px;
1605 1615 }
1606 1616
1607 1617 div.ancestor {
1608 1618 margin: -30px 0px;
1609 1619 }
1610 1620
1611 1621 .cs_icon_td input[type="checkbox"] {
1612 1622 display: none;
1613 1623 }
1614 1624
1615 1625 .cs_icon_td .expand_file_icon:after {
1616 1626 cursor: pointer;
1617 1627 content: "\00A0\25B6";
1618 1628 font-size: 12px;
1619 1629 color: @grey4;
1620 1630 }
1621 1631
1622 1632 .cs_icon_td .collapse_file_icon:after {
1623 1633 cursor: pointer;
1624 1634 content: "\00A0\25BC";
1625 1635 font-size: 12px;
1626 1636 color: @grey4;
1627 1637 }
1628 1638
1629 1639 /*new binary
1630 1640 NEW_FILENODE = 1
1631 1641 DEL_FILENODE = 2
1632 1642 MOD_FILENODE = 3
1633 1643 RENAMED_FILENODE = 4
1634 1644 COPIED_FILENODE = 5
1635 1645 CHMOD_FILENODE = 6
1636 1646 BIN_FILENODE = 7
1637 1647 */
1638 1648 .cs_files_expand {
1639 1649 font-size: @basefontsize + 5px;
1640 1650 line-height: 1.8em;
1641 1651 float: right;
1642 1652 }
1643 1653
1644 1654 .cs_files_expand span{
1645 1655 color: @rcblue;
1646 1656 cursor: pointer;
1647 1657 }
1648 1658 .cs_files {
1649 1659 clear: both;
1650 1660 padding-bottom: @padding;
1651 1661
1652 1662 .cur_cs {
1653 1663 margin: 10px 2px;
1654 1664 font-weight: bold;
1655 1665 }
1656 1666
1657 1667 .node {
1658 1668 float: left;
1659 1669 }
1660 1670
1661 1671 .changes {
1662 1672 float: right;
1663 1673 color: white;
1664 1674 font-size: @basefontsize - 4px;
1665 1675 margin-top: 4px;
1666 1676 opacity: 0.6;
1667 1677 filter: Alpha(opacity=60); /* IE8 and earlier */
1668 1678
1669 1679 .added {
1670 1680 background-color: @alert1;
1671 1681 float: left;
1672 1682 text-align: center;
1673 1683 }
1674 1684
1675 1685 .deleted {
1676 1686 background-color: @alert2;
1677 1687 float: left;
1678 1688 text-align: center;
1679 1689 }
1680 1690
1681 1691 .bin {
1682 1692 background-color: @alert1;
1683 1693 text-align: center;
1684 1694 }
1685 1695
1686 1696 /*new binary*/
1687 1697 .bin.bin1 {
1688 1698 background-color: @alert1;
1689 1699 text-align: center;
1690 1700 }
1691 1701
1692 1702 /*deleted binary*/
1693 1703 .bin.bin2 {
1694 1704 background-color: @alert2;
1695 1705 text-align: center;
1696 1706 }
1697 1707
1698 1708 /*mod binary*/
1699 1709 .bin.bin3 {
1700 1710 background-color: @grey2;
1701 1711 text-align: center;
1702 1712 }
1703 1713
1704 1714 /*rename file*/
1705 1715 .bin.bin4 {
1706 1716 background-color: @alert4;
1707 1717 text-align: center;
1708 1718 }
1709 1719
1710 1720 /*copied file*/
1711 1721 .bin.bin5 {
1712 1722 background-color: @alert4;
1713 1723 text-align: center;
1714 1724 }
1715 1725
1716 1726 /*chmod file*/
1717 1727 .bin.bin6 {
1718 1728 background-color: @grey2;
1719 1729 text-align: center;
1720 1730 }
1721 1731 }
1722 1732 }
1723 1733
1724 1734 .cs_files .cs_added, .cs_files .cs_A,
1725 1735 .cs_files .cs_added, .cs_files .cs_M,
1726 1736 .cs_files .cs_added, .cs_files .cs_D {
1727 1737 height: 16px;
1728 1738 padding-right: 10px;
1729 1739 margin-top: 7px;
1730 1740 text-align: left;
1731 1741 }
1732 1742
1733 1743 .cs_icon_td {
1734 1744 min-width: 16px;
1735 1745 width: 16px;
1736 1746 }
1737 1747
1738 1748 .pull-request-merge {
1739 1749 border: 1px solid @grey5;
1740 1750 padding: 10px 0px 20px;
1741 1751 margin-top: 10px;
1742 1752 margin-bottom: 20px;
1743 1753 }
1744 1754
1745 1755 .pull-request-merge ul {
1746 1756 padding: 0px 0px;
1747 1757 }
1748 1758
1749 1759 .pull-request-merge li {
1750 1760 list-style-type: none;
1751 1761 }
1752 1762
1753 1763 .pull-request-merge .pull-request-wrap {
1754 1764 height: auto;
1755 1765 padding: 0px 0px;
1756 1766 text-align: right;
1757 1767 }
1758 1768
1759 1769 .pull-request-merge span {
1760 1770 margin-right: 5px;
1761 1771 }
1762 1772
1763 1773 .pull-request-merge-actions {
1764 1774 min-height: 30px;
1765 1775 padding: 0px 0px;
1766 1776 }
1767 1777
1768 1778 .pull-request-merge-info {
1769 1779 padding: 0px 5px 5px 0px;
1770 1780 }
1771 1781
1772 1782 .merge-status {
1773 1783 margin-right: 5px;
1774 1784 }
1775 1785
1776 1786 .merge-message {
1777 1787 font-size: 1.2em
1778 1788 }
1779 1789
1780 1790 .merge-message.success i,
1781 1791 .merge-icon.success i {
1782 1792 color:@alert1;
1783 1793 }
1784 1794
1785 1795 .merge-message.warning i,
1786 1796 .merge-icon.warning i {
1787 1797 color: @alert3;
1788 1798 }
1789 1799
1790 1800 .merge-message.error i,
1791 1801 .merge-icon.error i {
1792 1802 color:@alert2;
1793 1803 }
1794 1804
1795 1805 .pr-versions {
1796 1806 font-size: 1.1em;
1797 1807
1798 1808 table {
1799 1809 padding: 0px 5px;
1800 1810 }
1801 1811
1802 1812 td {
1803 1813 line-height: 15px;
1804 1814 }
1805 1815
1806 1816 .flag_status {
1807 1817 margin: 0;
1808 1818 }
1809 1819
1810 1820 .compare-radio-button {
1811 1821 position: relative;
1812 1822 top: -3px;
1813 1823 }
1814 1824 }
1815 1825
1816 1826
1817 1827 #close_pull_request {
1818 1828 margin-right: 0px;
1819 1829 }
1820 1830
1821 1831 .empty_data {
1822 1832 color: @grey4;
1823 1833 }
1824 1834
1825 1835 #changeset_compare_view_content {
1826 1836 clear: both;
1827 1837 width: 100%;
1828 1838 box-sizing: border-box;
1829 1839 .border-radius(@border-radius);
1830 1840
1831 1841 .help-block {
1832 1842 margin: @padding 0;
1833 1843 color: @text-color;
1834 1844 &.pre-formatting {
1835 1845 white-space: pre;
1836 1846 }
1837 1847 }
1838 1848
1839 1849 .empty_data {
1840 1850 margin: @padding 0;
1841 1851 }
1842 1852
1843 1853 .alert {
1844 1854 margin-bottom: @space;
1845 1855 }
1846 1856 }
1847 1857
1848 1858 .table_disp {
1849 1859 .status {
1850 1860 width: auto;
1851 1861
1852 1862 .flag_status {
1853 1863 float: left;
1854 1864 }
1855 1865 }
1856 1866 }
1857 1867
1858 1868
1859 1869 .creation_in_progress {
1860 1870 color: @grey4
1861 1871 }
1862 1872
1863 1873 .status_box_menu {
1864 1874 margin: 0;
1865 1875 }
1866 1876
1867 1877 .notification-table{
1868 1878 margin-bottom: @space;
1869 1879 display: table;
1870 1880 width: 100%;
1871 1881
1872 1882 .container{
1873 1883 display: table-row;
1874 1884
1875 1885 .notification-header{
1876 1886 border-bottom: @border-thickness solid @border-default-color;
1877 1887 }
1878 1888
1879 1889 .notification-subject{
1880 1890 display: table-cell;
1881 1891 }
1882 1892 }
1883 1893 }
1884 1894
1885 1895 // Notifications
1886 1896 .notification-header{
1887 1897 display: table;
1888 1898 width: 100%;
1889 1899 padding: floor(@basefontsize/2) 0;
1890 1900 line-height: 1em;
1891 1901
1892 1902 .desc, .delete-notifications, .read-notifications{
1893 1903 display: table-cell;
1894 1904 text-align: left;
1895 1905 }
1896 1906
1897 1907 .desc{
1898 1908 width: 1163px;
1899 1909 }
1900 1910
1901 1911 .delete-notifications, .read-notifications{
1902 1912 width: 35px;
1903 1913 min-width: 35px; //fixes when only one button is displayed
1904 1914 }
1905 1915 }
1906 1916
1907 1917 .notification-body {
1908 1918 .markdown-block,
1909 1919 .rst-block {
1910 1920 padding: @padding 0;
1911 1921 }
1912 1922
1913 1923 .notification-subject {
1914 1924 padding: @textmargin 0;
1915 1925 border-bottom: @border-thickness solid @border-default-color;
1916 1926 }
1917 1927 }
1918 1928
1919 1929
1920 1930 .notifications_buttons{
1921 1931 float: right;
1922 1932 }
1923 1933
1924 1934 #notification-status{
1925 1935 display: inline;
1926 1936 }
1927 1937
1928 1938 // Repositories
1929 1939
1930 1940 #summary.fields{
1931 1941 display: table;
1932 1942
1933 1943 .field{
1934 1944 display: table-row;
1935 1945
1936 1946 .label-summary{
1937 1947 display: table-cell;
1938 1948 min-width: @label-summary-minwidth;
1939 1949 padding-top: @padding/2;
1940 1950 padding-bottom: @padding/2;
1941 1951 padding-right: @padding/2;
1942 1952 }
1943 1953
1944 1954 .input{
1945 1955 display: table-cell;
1946 1956 padding: @padding/2;
1947 1957
1948 1958 input{
1949 1959 min-width: 29em;
1950 1960 padding: @padding/4;
1951 1961 }
1952 1962 }
1953 1963 .statistics, .downloads{
1954 1964 .disabled{
1955 1965 color: @grey4;
1956 1966 }
1957 1967 }
1958 1968 }
1959 1969 }
1960 1970
1961 1971 #summary{
1962 1972 width: 70%;
1963 1973 }
1964 1974
1965 1975
1966 1976 // Journal
1967 1977 .journal.title {
1968 1978 h5 {
1969 1979 float: left;
1970 1980 margin: 0;
1971 1981 width: 70%;
1972 1982 }
1973 1983
1974 1984 ul {
1975 1985 float: right;
1976 1986 display: inline-block;
1977 1987 margin: 0;
1978 1988 width: 30%;
1979 1989 text-align: right;
1980 1990
1981 1991 li {
1982 1992 display: inline;
1983 1993 font-size: @journal-fontsize;
1984 1994 line-height: 1em;
1985 1995
1986 1996 list-style-type: none;
1987 1997 }
1988 1998 }
1989 1999 }
1990 2000
1991 2001 .filterexample {
1992 2002 position: absolute;
1993 2003 top: 95px;
1994 2004 left: @contentpadding;
1995 2005 color: @rcblue;
1996 2006 font-size: 11px;
1997 2007 font-family: @text-regular;
1998 2008 cursor: help;
1999 2009
2000 2010 &:hover {
2001 2011 color: @rcdarkblue;
2002 2012 }
2003 2013
2004 2014 @media (max-width:768px) {
2005 2015 position: relative;
2006 2016 top: auto;
2007 2017 left: auto;
2008 2018 display: block;
2009 2019 }
2010 2020 }
2011 2021
2012 2022
2013 2023 #journal{
2014 2024 margin-bottom: @space;
2015 2025
2016 2026 .journal_day{
2017 2027 margin-bottom: @textmargin/2;
2018 2028 padding-bottom: @textmargin/2;
2019 2029 font-size: @journal-fontsize;
2020 2030 border-bottom: @border-thickness solid @border-default-color;
2021 2031 }
2022 2032
2023 2033 .journal_container{
2024 2034 margin-bottom: @space;
2025 2035
2026 2036 .journal_user{
2027 2037 display: inline-block;
2028 2038 }
2029 2039 .journal_action_container{
2030 2040 display: block;
2031 2041 margin-top: @textmargin;
2032 2042
2033 2043 div{
2034 2044 display: inline;
2035 2045 }
2036 2046
2037 2047 div.journal_action_params{
2038 2048 display: block;
2039 2049 }
2040 2050
2041 2051 div.journal_repo:after{
2042 2052 content: "\A";
2043 2053 white-space: pre;
2044 2054 }
2045 2055
2046 2056 div.date{
2047 2057 display: block;
2048 2058 margin-bottom: @textmargin;
2049 2059 }
2050 2060 }
2051 2061 }
2052 2062 }
2053 2063
2054 2064 // Files
2055 2065 .edit-file-title {
2056 2066 border-bottom: @border-thickness solid @border-default-color;
2057 2067
2058 2068 .breadcrumbs {
2059 2069 margin-bottom: 0;
2060 2070 }
2061 2071 }
2062 2072
2063 2073 .edit-file-fieldset {
2064 2074 margin-top: @sidebarpadding;
2065 2075
2066 2076 .fieldset {
2067 2077 .left-label {
2068 2078 width: 13%;
2069 2079 }
2070 2080 .right-content {
2071 2081 width: 87%;
2072 2082 max-width: 100%;
2073 2083 }
2074 2084 .filename-label {
2075 2085 margin-top: 13px;
2076 2086 }
2077 2087 .commit-message-label {
2078 2088 margin-top: 4px;
2079 2089 }
2080 2090 .file-upload-input {
2081 2091 input {
2082 2092 display: none;
2083 2093 }
2084 2094 margin-top: 10px;
2085 2095 }
2086 2096 .file-upload-label {
2087 2097 margin-top: 10px;
2088 2098 }
2089 2099 p {
2090 2100 margin-top: 5px;
2091 2101 }
2092 2102
2093 2103 }
2094 2104 .custom-path-link {
2095 2105 margin-left: 5px;
2096 2106 }
2097 2107 #commit {
2098 2108 resize: vertical;
2099 2109 }
2100 2110 }
2101 2111
2102 2112 .delete-file-preview {
2103 2113 max-height: 250px;
2104 2114 }
2105 2115
2106 2116 .new-file,
2107 2117 #filter_activate,
2108 2118 #filter_deactivate {
2109 2119 float: right;
2110 2120 margin: 0 0 0 10px;
2111 2121 }
2112 2122
2113 2123 h3.files_location{
2114 2124 line-height: 2.4em;
2115 2125 }
2116 2126
2117 2127 .browser-nav {
2118 2128 width: 100%;
2119 2129 display: table;
2120 2130 margin-bottom: 20px;
2121 2131
2122 2132 .info_box {
2123 2133 float: left;
2124 2134 display: inline-table;
2125 2135 height: 2.5em;
2126 2136
2127 2137 .browser-cur-rev, .info_box_elem {
2128 2138 display: table-cell;
2129 2139 vertical-align: middle;
2130 2140 }
2131 2141
2132 2142 .drop-menu {
2133 2143 margin: 0 10px;
2134 2144 }
2135 2145
2136 2146 .info_box_elem {
2137 2147 border-top: @border-thickness solid @grey5;
2138 2148 border-bottom: @border-thickness solid @grey5;
2139 2149 box-shadow: @button-shadow;
2140 2150
2141 2151 #at_rev, a {
2142 2152 padding: 0.6em 0.4em;
2143 2153 margin: 0;
2144 2154 .box-shadow(none);
2145 2155 border: 0;
2146 2156 height: 12px;
2147 2157 color: @grey2;
2148 2158 }
2149 2159
2150 2160 input#at_rev {
2151 2161 max-width: 50px;
2152 2162 text-align: center;
2153 2163 }
2154 2164
2155 2165 &.previous {
2156 2166 border: @border-thickness solid @grey5;
2157 2167 border-top-left-radius: @border-radius;
2158 2168 border-bottom-left-radius: @border-radius;
2159 2169
2160 2170 &:hover {
2161 2171 border-color: @grey4;
2162 2172 }
2163 2173
2164 2174 .disabled {
2165 2175 color: @grey5;
2166 2176 cursor: not-allowed;
2167 2177 opacity: 0.5;
2168 2178 }
2169 2179 }
2170 2180
2171 2181 &.next {
2172 2182 border: @border-thickness solid @grey5;
2173 2183 border-top-right-radius: @border-radius;
2174 2184 border-bottom-right-radius: @border-radius;
2175 2185
2176 2186 &:hover {
2177 2187 border-color: @grey4;
2178 2188 }
2179 2189
2180 2190 .disabled {
2181 2191 color: @grey5;
2182 2192 cursor: not-allowed;
2183 2193 opacity: 0.5;
2184 2194 }
2185 2195 }
2186 2196 }
2187 2197
2188 2198 .browser-cur-rev {
2189 2199
2190 2200 span{
2191 2201 margin: 0;
2192 2202 color: @rcblue;
2193 2203 height: 12px;
2194 2204 display: inline-block;
2195 2205 padding: 0.7em 1em ;
2196 2206 border: @border-thickness solid @rcblue;
2197 2207 margin-right: @padding;
2198 2208 }
2199 2209 }
2200 2210
2201 2211 }
2202 2212
2203 2213 .select-index-number {
2204 2214 margin: 0 0 0 20px;
2205 2215 color: @grey3;
2206 2216 }
2207 2217
2208 2218 .search_activate {
2209 2219 display: table-cell;
2210 2220 vertical-align: middle;
2211 2221
2212 2222 input, label{
2213 2223 margin: 0;
2214 2224 padding: 0;
2215 2225 }
2216 2226
2217 2227 input{
2218 2228 margin-left: @textmargin;
2219 2229 }
2220 2230
2221 2231 }
2222 2232 }
2223 2233
2224 2234 .browser-cur-rev{
2225 2235 margin-bottom: @textmargin;
2226 2236 }
2227 2237
2228 2238 #node_filter_box_loading{
2229 2239 .info_text;
2230 2240 }
2231 2241
2232 2242 .browser-search {
2233 2243 margin: -25px 0px 5px 0px;
2234 2244 }
2235 2245
2236 2246 .files-quick-filter {
2237 2247 float: right;
2238 2248 width: 180px;
2239 2249 position: relative;
2240 2250 }
2241 2251
2242 2252 .files-filter-box {
2243 2253 display: flex;
2244 2254 padding: 0px;
2245 2255 border-radius: 3px;
2246 2256 margin-bottom: 0;
2247 2257
2248 2258 a {
2249 2259 border: none !important;
2250 2260 }
2251 2261
2252 2262 li {
2253 2263 list-style-type: none
2254 2264 }
2255 2265 }
2256 2266
2257 2267 .files-filter-box-path {
2258 2268 line-height: 33px;
2259 2269 padding: 0;
2260 2270 width: 20px;
2261 2271 position: absolute;
2262 2272 z-index: 11;
2263 2273 left: 5px;
2264 2274 }
2265 2275
2266 2276 .files-filter-box-input {
2267 2277 margin-right: 0;
2268 2278
2269 2279 input {
2270 2280 border: 1px solid @white;
2271 2281 padding-left: 25px;
2272 2282 width: 145px;
2273 2283
2274 2284 &:hover {
2275 2285 border-color: @grey6;
2276 2286 }
2277 2287
2278 2288 &:focus {
2279 2289 border-color: @grey5;
2280 2290 }
2281 2291 }
2282 2292 }
2283 2293
2284 2294 .browser-result{
2285 2295 td a{
2286 2296 margin-left: 0.5em;
2287 2297 display: inline-block;
2288 2298
2289 2299 em {
2290 2300 font-weight: @text-bold-weight;
2291 2301 font-family: @text-bold;
2292 2302 }
2293 2303 }
2294 2304 }
2295 2305
2296 2306 .browser-highlight{
2297 2307 background-color: @grey5-alpha;
2298 2308 }
2299 2309
2300 2310
2301 2311 // Search
2302 2312
2303 2313 .search-form{
2304 2314 #q {
2305 2315 width: @search-form-width;
2306 2316 }
2307 2317 .fields{
2308 2318 margin: 0 0 @space;
2309 2319 }
2310 2320
2311 2321 label{
2312 2322 display: inline-block;
2313 2323 margin-right: @textmargin;
2314 2324 padding-top: 0.25em;
2315 2325 }
2316 2326
2317 2327
2318 2328 .results{
2319 2329 clear: both;
2320 2330 margin: 0 0 @padding;
2321 2331 }
2322 2332
2323 2333 .search-tags {
2324 2334 padding: 5px 0;
2325 2335 }
2326 2336 }
2327 2337
2328 2338 div.search-feedback-items {
2329 2339 display: inline-block;
2330 2340 }
2331 2341
2332 2342 div.search-code-body {
2333 2343 background-color: #ffffff; padding: 5px 0 5px 10px;
2334 2344 pre {
2335 2345 .match { background-color: #faffa6;}
2336 2346 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
2337 2347 }
2338 2348 }
2339 2349
2340 2350 .expand_commit.search {
2341 2351 .show_more.open {
2342 2352 height: auto;
2343 2353 max-height: none;
2344 2354 }
2345 2355 }
2346 2356
2347 2357 .search-results {
2348 2358
2349 2359 h2 {
2350 2360 margin-bottom: 0;
2351 2361 }
2352 2362 .codeblock {
2353 2363 border: none;
2354 2364 background: transparent;
2355 2365 }
2356 2366
2357 2367 .codeblock-header {
2358 2368 border: none;
2359 2369 background: transparent;
2360 2370 }
2361 2371
2362 2372 .code-body {
2363 2373 border: @border-thickness solid @grey6;
2364 2374 .border-radius(@border-radius);
2365 2375 }
2366 2376
2367 2377 .td-commit {
2368 2378 &:extend(pre);
2369 2379 border-bottom: @border-thickness solid @border-default-color;
2370 2380 }
2371 2381
2372 2382 .message {
2373 2383 height: auto;
2374 2384 max-width: 350px;
2375 2385 white-space: normal;
2376 2386 text-overflow: initial;
2377 2387 overflow: visible;
2378 2388
2379 2389 .match { background-color: #faffa6;}
2380 2390 .break { background-color: #DDE7EF; width: 100%; color: #747474; display: block; }
2381 2391 }
2382 2392
2383 2393 .path {
2384 2394 border-bottom: none !important;
2385 2395 border-left: 1px solid @grey6 !important;
2386 2396 border-right: 1px solid @grey6 !important;
2387 2397 }
2388 2398 }
2389 2399
2390 2400 table.rctable td.td-search-results div {
2391 2401 max-width: 100%;
2392 2402 }
2393 2403
2394 2404 #tip-box, .tip-box{
2395 2405 padding: @menupadding/2;
2396 2406 display: block;
2397 2407 border: @border-thickness solid @border-highlight-color;
2398 2408 .border-radius(@border-radius);
2399 2409 background-color: white;
2400 2410 z-index: 99;
2401 2411 white-space: pre-wrap;
2402 2412 }
2403 2413
2404 2414 #linktt {
2405 2415 width: 79px;
2406 2416 }
2407 2417
2408 2418 #help_kb .modal-content{
2409 2419 max-width: 750px;
2410 2420 margin: 10% auto;
2411 2421
2412 2422 table{
2413 2423 td,th{
2414 2424 border-bottom: none;
2415 2425 line-height: 2.5em;
2416 2426 }
2417 2427 th{
2418 2428 padding-bottom: @textmargin/2;
2419 2429 }
2420 2430 td.keys{
2421 2431 text-align: center;
2422 2432 }
2423 2433 }
2424 2434
2425 2435 .block-left{
2426 2436 width: 45%;
2427 2437 margin-right: 5%;
2428 2438 }
2429 2439 .modal-footer{
2430 2440 clear: both;
2431 2441 }
2432 2442 .key.tag{
2433 2443 padding: 0.5em;
2434 2444 background-color: @rcblue;
2435 2445 color: white;
2436 2446 border-color: @rcblue;
2437 2447 .box-shadow(none);
2438 2448 }
2439 2449 }
2440 2450
2441 2451
2442 2452
2443 2453 //--- IMPORTS FOR REFACTORED STYLES ------------------//
2444 2454
2445 2455 @import 'statistics-graph';
2446 2456 @import 'tables';
2447 2457 @import 'forms';
2448 2458 @import 'diff';
2449 2459 @import 'summary';
2450 2460 @import 'navigation';
2451 2461
2452 2462 //--- SHOW/HIDE SECTIONS --//
2453 2463
2454 2464 .btn-collapse {
2455 2465 float: right;
2456 2466 text-align: right;
2457 2467 font-family: @text-light;
2458 2468 font-size: @basefontsize;
2459 2469 cursor: pointer;
2460 2470 border: none;
2461 2471 color: @rcblue;
2462 2472 }
2463 2473
2464 2474 table.rctable,
2465 2475 table.dataTable {
2466 2476 .btn-collapse {
2467 2477 float: right;
2468 2478 text-align: right;
2469 2479 }
2470 2480 }
2471 2481
2472 2482 table.rctable {
2473 2483 &.permissions {
2474 2484
2475 2485 th.td-owner {
2476 2486 padding: 0;
2477 2487 }
2478 2488
2479 2489 th {
2480 2490 font-weight: normal;
2481 2491 padding: 0 5px;
2482 2492 }
2483 2493
2484 2494 }
2485 2495 }
2486 2496
2487 2497
2488 2498 // TODO: johbo: Fix for IE10, this avoids that we see a border
2489 2499 // and padding around checkboxes and radio boxes. Move to the right place,
2490 2500 // or better: Remove this once we did the form refactoring.
2491 2501 input[type=checkbox],
2492 2502 input[type=radio] {
2493 2503 padding: 0;
2494 2504 border: none;
2495 2505 }
2496 2506
2497 2507 .toggle-ajax-spinner{
2498 2508 height: 16px;
2499 2509 width: 16px;
2500 2510 }
2501 2511
2502 2512
2503 2513 .markup-form .clearfix {
2504 2514 .border-radius(@border-radius);
2505 2515 margin: 0px;
2506 2516 }
2507 2517
2508 2518 .markup-form-area {
2509 2519 padding: 8px 12px;
2510 2520 border: 1px solid @grey4;
2511 2521 .border-radius(@border-radius);
2512 2522 }
2513 2523
2514 2524 .markup-form-area-header .nav-links {
2515 2525 display: flex;
2516 2526 flex-flow: row wrap;
2517 2527 -webkit-flex-flow: row wrap;
2518 2528 width: 100%;
2519 2529 }
2520 2530
2521 2531 .markup-form-area-footer {
2522 2532 display: flex;
2523 2533 }
2524 2534
2525 2535 .markup-form-area-footer .toolbar {
2526 2536
2527 2537 }
2528 2538
2529 2539 // markup Form
2530 2540 div.markup-form {
2531 2541 margin-top: 20px;
2532 2542 }
2533 2543
2534 2544 .markup-form strong {
2535 2545 display: block;
2536 2546 margin-bottom: 15px;
2537 2547 }
2538 2548
2539 2549 .markup-form textarea {
2540 2550 width: 100%;
2541 2551 height: 100px;
2542 2552 font-family: @text-monospace;
2543 2553 }
2544 2554
2545 2555 form.markup-form {
2546 2556 margin-top: 10px;
2547 2557 margin-left: 10px;
2548 2558 }
2549 2559
2550 2560 .markup-form .comment-block-ta,
2551 2561 .markup-form .preview-box {
2552 2562 .border-radius(@border-radius);
2553 2563 .box-sizing(border-box);
2554 2564 background-color: white;
2555 2565 }
2556 2566
2557 2567 .markup-form .preview-box.unloaded {
2558 2568 height: 50px;
2559 2569 text-align: center;
2560 2570 padding: 20px;
2561 2571 background-color: white;
2562 2572 }
2563 2573
2564 2574
2565 2575 .dropzone-wrapper {
2566 2576 border: 1px solid @grey5;
2567 2577 padding: 20px;
2568 2578 }
2569 2579
2570 2580 .dropzone {
2571 2581 border: 2px dashed @grey5;
2572 2582 border-radius: 5px;
2573 2583 background: white;
2574 2584 min-height: 200px;
2575 2585 padding: 54px;
2576 2586 }
2577 2587 .dropzone .dz-message {
2578 2588 font-weight: 700;
2579 2589 }
2580 2590
2581 2591 .dropzone .dz-message {
2582 2592 text-align: center;
2583 2593 margin: 2em 0;
2584 2594 }
2585 2595
2586 2596 .dz-preview {
2587 2597 margin: 10px 0px !important;
2588 2598 position: relative;
2589 2599 vertical-align: top;
2590 2600 padding: 10px;
2591 2601 }
2592 2602
2593 2603 .dz-filename {
2594 2604 font-weight: 700;
2595 2605 float:left;
2596 2606 }
2597 2607
2598 2608 .dz-response {
2599 2609 clear:both
2600 2610 }
2601 2611
2602 2612 .dz-filename-size {
2603 2613 float:right
2604 2614 }
2605 2615
2606 2616 .dz-error-message {
2607 2617 color: @alert2;
2608 2618 } No newline at end of file
@@ -1,763 +1,763 b''
1 1 // navigation.less
2 2 // For use in RhodeCode applications;
3 3 // see style guide documentation for guidelines.
4 4
5 5 // TOP MAIN DARK NAVIGATION
6 6
7 7 .header .main_nav.horizontal-list {
8 8 float: right;
9 9 color: @grey4;
10 10 > li {
11 11 a {
12 12 color: @grey4;
13 13 }
14 14 }
15 15 }
16 16
17 17 // HEADER NAVIGATION
18 18
19 19 .horizontal-list {
20 20 display: block;
21 21 margin: 0;
22 22 padding: 0;
23 23 -webkit-padding-start: 0;
24 24 text-align: left;
25 25 font-size: @navigation-fontsize;
26 26 color: @grey6;
27 27 z-index:10;
28 28
29 29 li {
30 30 line-height: 1em;
31 31 list-style-type: none;
32 32 margin: 0 20px 0 0;
33 33
34 34 a {
35 35 padding: 0 .5em;
36 36
37 37 &.menu_link_notifications {
38 38 .pill(7px,@rcblue);
39 39 display: inline;
40 40 margin: 0 7px 0 .7em;
41 41 font-size: @basefontsize;
42 42 color: white;
43 43
44 44 &.empty {
45 45 background-color: @grey4;
46 46 }
47 47
48 48 &:hover {
49 49 background-color: @rcdarkblue;
50 50 }
51 51 }
52 52 }
53 53 .pill_container {
54 54 margin: 1.25em 0px 0px 0px;
55 55 float: right;
56 56 }
57 57
58 58 &#quick_login_li {
59 59 &:hover {
60 60 color: @grey5;
61 61 }
62 62
63 63 a.menu_link_notifications {
64 64 color: white;
65 65 }
66 66
67 67 .user {
68 68 padding-bottom: 10px;
69 69 }
70 70 }
71 71
72 72 &:before { content: none; }
73 73
74 74 &:last-child {
75 75 .menulabel {
76 76 padding-right: 0;
77 77 border-right: none;
78 78
79 79 .show_more {
80 80 padding-right: 0;
81 81 }
82 82 }
83 83
84 84 &> a {
85 85 border-bottom: none;
86 86 }
87 87 }
88 88
89 89 &.open {
90 90
91 91 a {
92 92 color: white;
93 93 }
94 94 }
95 95
96 96 &:focus {
97 97 outline: none;
98 98 }
99 99
100 100 ul li {
101 101 display: block;
102 102
103 103 &:last-child> a {
104 104 border-bottom: none;
105 105 }
106 106
107 107 ul li:last-child a {
108 108 /* we don't expect more then 3 levels of submenu and the third
109 109 level can have different html structure */
110 110 border-bottom: none;
111 111 }
112 112 }
113 113 }
114 114
115 115 > li {
116 116 float: left;
117 117 display: block;
118 118 padding: 0;
119 119
120 120 > a,
121 121 &.has_select2 a {
122 122 display: block;
123 123 padding: 10px 0;
124 124 }
125 125
126 126 .menulabel {
127 127 line-height: 1em;
128 128 // for this specifically we do not use a variable
129 129 }
130 130
131 131 .pr_notifications {
132 132 padding-left: .5em;
133 133 }
134 134
135 135 .pr_notifications + .menulabel {
136 136 display:inline;
137 137 padding-left: 0;
138 138 }
139 139
140 140 &:hover,
141 141 &.open,
142 142 &.active {
143 143 a {
144 144 color: @rcblue;
145 145 }
146 146 }
147 147 }
148 148
149 149 pre {
150 150 margin: 0;
151 151 padding: 0;
152 152 }
153 153
154 154 .select2-container,
155 155 .menulink.childs {
156 156 position: relative;
157 157 }
158 158
159 159 .menulink {
160 160 &.disabled {
161 161 color: @grey3;
162 162 cursor: default;
163 163 opacity: 0.5;
164 164 }
165 165 }
166 166
167 167 #quick_login {
168 168
169 169 li a {
170 170 padding: .5em 0;
171 171 border-bottom: none;
172 172 color: @grey2;
173 173
174 174 &:hover { color: @grey1; }
175 175 }
176 176 }
177 177
178 178 #quick_login_link {
179 179 display: inline-block;
180 180
181 181 .gravatar {
182 182 border: 1px solid @grey5;
183 183 }
184 184
185 185 .gravatar-login {
186 186 height: 20px;
187 187 width: 20px;
188 188 margin: -8px 0;
189 189 padding: 0;
190 190 }
191 191
192 192 &:hover .user {
193 193 color: @grey6;
194 194 }
195 195 }
196 196 }
197 197 .header .horizontal-list {
198 198
199 199 li {
200 200
201 201 &#quick_login_li {
202 202 padding-left: .5em;
203 203
204 204 &:hover #quick_login_link {
205 205 color: inherit;
206 206 }
207 207
208 208 .menu_link_user {
209 209 padding: 0 2px;
210 210 }
211 211 }
212 212 list-style-type: none;
213 213 }
214 214
215 215 > li {
216 216
217 217 a {
218 218 padding: 18px 0 12px 0;
219 219 color: @nav-grey;
220 220
221 221 &.menu_link_notifications {
222 222 padding: 1px 8px;
223 223 }
224 224 }
225 225
226 226 &:hover,
227 227 &.open,
228 228 &.active {
229 229 .pill_container a {
230 230 // don't select text for the pill container, it has it' own
231 231 // hover behaviour
232 232 color: @nav-grey;
233 233 }
234 234 }
235 235
236 236 &:hover,
237 237 &.open,
238 238 &.active {
239 239 a {
240 240 color: @grey6;
241 241 }
242 242 }
243 243
244 244 .select2-dropdown-open a {
245 245 color: @grey6;
246 246 }
247 247
248 248 .repo-switcher {
249 249 padding-left: 0;
250 250
251 251 .menulabel {
252 252 padding-left: 0;
253 253 }
254 254 }
255 255 }
256 256
257 257 li ul li {
258 258 background-color:@grey2;
259 259
260 260 a {
261 261 padding: .5em 0;
262 262 border-bottom: @border-thickness solid @border-default-color;
263 263 color: @grey6;
264 264 }
265 265
266 266 &:last-child a, &.last a{
267 267 border-bottom: none;
268 268 }
269 269
270 270 &:hover {
271 271 background-color: @grey3;
272 272 }
273 273 }
274 274
275 275 .submenu {
276 276 margin-top: 5px;
277 277 }
278 278 }
279 279
280 280 // SUBMENUS
281 281 .navigation .submenu {
282 282 display: none;
283 283 }
284 284
285 285 .navigation li.open {
286 286 .submenu {
287 287 display: block;
288 288 }
289 289 }
290 290
291 291 .navigation li:last-child .submenu {
292 292 right: auto;
293 293 left: 0;
294 294 border: 1px solid @grey5;
295 295 background: @white;
296 296 box-shadow: @dropdown-shadow;
297 297 }
298 298
299 299 .submenu {
300 300 position: absolute;
301 301 top: 100%;
302 302 left: 0;
303 303 min-width: 180px;
304 304 margin: 2px 0 0;
305 305 padding: 0;
306 306 text-align: left;
307 307 font-family: @text-light;
308 308 border-radius: @border-radius;
309 309 z-index: 20;
310 310
311 311 li {
312 312 display: block;
313 313 margin: 0;
314 314 padding: 0 .5em;
315 315 line-height: 1em;
316 316 color: @grey3;
317 317 background-color: @white;
318 318 list-style-type: none;
319 319
320 320 a {
321 321 display: block;
322 322 width: 100%;
323 323 padding: .5em 0;
324 324 border-right: none;
325 325 border-bottom: @border-thickness solid white;
326 326 color: @grey3;
327 327 }
328 328
329 329 ul {
330 330 display: none;
331 331 position: absolute;
332 332 top: 0;
333 333 right: 100%;
334 334 padding: 0;
335 335 z-index: 30;
336 336 }
337 337 &:hover {
338 338 background-color: @grey7;
339 339 -webkit-transition: background .3s;
340 340 -moz-transition: background .3s;
341 341 -o-transition: background .3s;
342 342 transition: background .3s;
343 343
344 344 ul {
345 345 display: block;
346 346 }
347 347 }
348 348 }
349 349
350 350 }
351 351
352 352
353 353
354 354
355 355 // repo dropdown
356 356 .quick_repo_menu {
357 357 width: 15px;
358 358 text-align: center;
359 359 position: relative;
360 360 cursor: pointer;
361 361
362 362 div {
363 363 overflow: visible !important;
364 364 }
365 365
366 366 &.sorting {
367 367 cursor: auto;
368 368 }
369 369
370 370 &:hover {
371 371 .menu_items_container {
372 372 position: absolute;
373 373 display: block;
374 374 }
375 375 .menu_items {
376 376 display: block;
377 377 }
378 378 }
379 379
380 380 i {
381 381 margin: 0;
382 382 color: @grey4;
383 383 }
384 384
385 385 .menu_items_container {
386 386 position: absolute;
387 387 top: 0;
388 388 left: 100%;
389 389 margin: 0;
390 390 padding: 0;
391 391 list-style: none;
392 392 background-color: @grey6;
393 393 z-index: 999;
394 394 text-align: left;
395 395
396 396 a {
397 397 color: @grey2;
398 398 }
399 399
400 400 ul.menu_items {
401 401 margin: 0;
402 402 padding: 0;
403 403 }
404 404
405 405 li {
406 406 margin: 0;
407 407 padding: 0;
408 408 line-height: 1em;
409 409 list-style-type: none;
410 410
411 411 a {
412 412 display: block;
413 413 height: 16px;
414 414 padding: 8px; //must add up to td height (28px)
415 415 width: 120px; // set width
416 416
417 417 &:hover {
418 418 background-color: @grey5;
419 419 -webkit-transition: background .3s;
420 420 -moz-transition: background .3s;
421 421 -o-transition: background .3s;
422 422 transition: background .3s;
423 423 }
424 424 }
425 425 }
426 426 }
427 427 }
428 428
429 429 // Header Repository Switcher
430 430 // Select2 Dropdown
431 431 #select2-drop.select2-drop.repo-switcher-dropdown {
432 432 width: auto !important;
433 433 margin-top: 5px;
434 434 padding: 1em 0;
435 435 text-align: left;
436 436 .border-radius-bottom(@border-radius);
437 437 border-color: transparent;
438 438 color: @grey6;
439 439 background-color: @grey2;
440 440
441 441 input {
442 442 min-width: 90%;
443 443 }
444 444
445 445 ul.select2-result-sub {
446 446
447 447 li {
448 448 line-height: 1em;
449 449
450 450 &:hover,
451 451 &.select2-highlighted {
452 452 background-color: @grey3;
453 453 }
454 454 }
455 455
456 456 &:before { content: none; }
457 457 }
458 458
459 459 ul.select2-results {
460 460 min-width: 200px;
461 461 margin: 0;
462 462 padding: 0;
463 463 list-style-type: none;
464 464 overflow-x: visible;
465 465 overflow-y: scroll;
466 466
467 467 li {
468 468 padding: 0 8px;
469 469 line-height: 1em;
470 470 color: @grey6;
471 471
472 472 &>.select2-result-label {
473 473 padding: 8px 0;
474 474 border-bottom: @border-thickness solid @grey3;
475 475 white-space: nowrap;
476 476 color: @grey5;
477 477 cursor: pointer;
478 478 }
479 479
480 480 &.select2-result-with-children {
481 481 margin: 0;
482 482 padding: 0;
483 483 }
484 484
485 485 &.select2-result-unselectable > .select2-result-label {
486 486 margin: 0 8px;
487 487 }
488 488
489 489 }
490 490 }
491 491
492 492 ul.select2-result-sub {
493 493 margin: 0;
494 494 padding: 0;
495 495
496 496 li {
497 497 display: block;
498 498 margin: 0;
499 499 border-right: none;
500 500 line-height: 1em;
501 501 font-family: @text-light;
502 502 color: @grey2;
503 503 list-style-type: none;
504 504
505 505 &:hover {
506 506 background-color: @grey3;
507 507 }
508 508 }
509 509 }
510 510 }
511 511
512 512
513 513 #context-bar {
514 514 display: block;
515 515 margin: 0 auto 20px 0;
516 516 padding: 0 @header-padding;
517 517 background-color: @grey7;
518 518 border-bottom: 1px solid @grey5;
519 519
520 520 .clear {
521 521 clear: both;
522 522 }
523 523 }
524 524
525 525 ul#context-pages {
526 526 li {
527 527 list-style-type: none;
528 528
529 529 a {
530 530 color: @grey2;
531 531
532 532 &:hover {
533 533 color: @grey1;
534 534 }
535 535 }
536 536
537 537 &.active {
538 538 // special case, non-variable color
539 539 border-bottom: 2px solid @rcblue;
540 540
541 541 a {
542 542 color: @rcblue;
543 543 }
544 544 }
545 545 }
546 546 }
547 547
548 548 // PAGINATION
549 549
550 550 .pagination {
551 551 border: @border-thickness solid @grey5;
552 552 color: @grey2;
553 553 box-shadow: @button-shadow;
554 554
555 555 .current {
556 556 color: @grey4;
557 557 }
558 558 }
559 559
560 560 .dataTables_processing {
561 561 text-align: center;
562 562 font-size: 1.1em;
563 563 position: relative;
564 564 top: 95px;
565 565 }
566 566
567 567 .dataTables_paginate, .pagination-wh {
568 568 text-align: left;
569 569 display: inline-block;
570 570 border-left: 1px solid @grey5;
571 571 float: none;
572 572 overflow: hidden;
573 573 box-shadow: @button-shadow;
574 574
575 575 .paginate_button, .pager_curpage,
576 576 .pager_link, .pg-previous, .pg-next, .pager_dotdot {
577 577 display: inline-block;
578 578 padding: @menupadding/4 @menupadding;
579 579 border: 1px solid @grey5;
580 580 border-left: 0;
581 581 color: @grey2;
582 582 cursor: pointer;
583 583 float: left;
584 584
585 585 &:hover {
586 586 color: @rcdarkblue;
587 587 }
588 588 }
589 589
590 590 .paginate_button.disabled,
591 591 .disabled {
592 592 color: @grey3;
593 593 cursor: default;
594 594 opacity: 0.5;
595 595 }
596 596
597 597 .paginate_button.current, .pager_curpage {
598 598 background: @rcblue;
599 599 border-color: @rcblue;
600 600 color: @white;
601 601 }
602 602
603 603 .ellipsis {
604 604 display: inline-block;
605 605 text-align: left;
606 606 padding: @menupadding/4 @menupadding;
607 607 border: 1px solid @grey5;
608 608 border-left: 0;
609 609 float: left;
610 610 }
611 611 }
612 612
613 613 // SIDEBAR
614 614
615 615 .sidebar {
616 616 .block-left;
617 617 clear: left;
618 618 max-width: @sidebar-width;
619 619 margin-right: @sidebarpadding;
620 620 padding-right: @sidebarpadding;
621 621 font-family: @text-regular;
622 622 color: @grey1;
623 623
624 624 &#graph_nodes {
625 625 clear:both;
626 626 width: auto;
627 627 margin-left: -100px;
628 628 padding: 0;
629 629 border: none;
630 630 }
631 631
632 632 .nav-pills {
633 633 margin: 0;
634 634 }
635 635
636 636 .nav {
637 637 list-style: none;
638 638 padding: 0;
639 639
640 640 li {
641 641 padding-bottom: @menupadding;
642 642 line-height: 1em;
643 643 color: @grey4;
644 644 list-style-type: none;
645 645
646 646 &.active a {
647 647 color: @grey2;
648 648 }
649 649
650 650 a {
651 651 color: @grey4;
652 652 }
653 653 }
654 654
655 655 }
656 656 }
657 657
658 658 .main_filter_help_box {
659 659 padding: 7px 7px;
660 660 display: inline-block;
661 661 vertical-align: top;
662 662 background: inherit;
663 663 position: absolute;
664 664 right: 0;
665 665 top: 9px;
666 666 }
667 667
668 668 .main_filter_input_box {
669 669 display: inline-block;
670 670
671 671 .searchItems {
672 672 display:flex;
673 673 background: @black;
674 674 padding: 0px;
675 675 border-radius: 3px;
676 676 border: 1px solid @black;
677 677
678 678 a {
679 679 border: none !important;
680 680 }
681 681 }
682 682
683 683 .searchTag {
684 684 line-height: 28px;
685 685 padding: 0 5px;
686 686
687 687 .tag {
688 688 color: @grey5;
689 689 border-color: @grey2;
690 690 background: @grey1;
691 691 }
692 692 }
693 693
694 694 .searchTagFilter {
695 695 background-color: @black !important;
696 696 margin-right: 0;
697 697 }
698 698
699 699 .searchTagHelp {
700 700 background-color: @grey1 !important;
701 701 margin: 0;
702 702 }
703 703 .searchTagHelp:hover {
704 704 background-color: @grey1 !important;
705 705 }
706 706 .searchTagInput {
707 707 background-color: @grey1 !important;
708 708 margin-right: 0;
709 709 }
710 710 }
711 711
712 712 .main_filter_box {
713 713 margin: 9px 0 0 0;
714 714 }
715 715
716 716 #main_filter_help {
717 717 background: @grey1;
718 718 border: 1px solid black;
719 719 position: absolute;
720 720 white-space: pre;
721 721 z-index: 9999;
722 722 color: @nav-grey;
723 723 padding: 0 10px;
724 724 }
725 725
726 726 input {
727 727
728 728 &.main_filter_input {
729 729 padding: 5px 10px;
730 min-width: 260px;
730 min-width: 340px;
731 731 color: @grey7;
732 732 background: @black;
733 733 min-height: 18px;
734 734 border: 0;
735 735
736 736 &:active {
737 737 color: @grey2 !important;
738 738 background: white !important;
739 739 }
740 740 &:focus {
741 741 color: @grey2 !important;
742 742 background: white !important;
743 743 }
744 744 }
745 745 }
746 746
747 747
748 748
749 749 .main_filter_input::placeholder {
750 750 color: @nav-grey;
751 751 opacity: 1;
752 752 }
753 753
754 754 .notice-box {
755 755 display:block !important;
756 756 padding: 9px 0 !important;
757 757 }
758 758
759 759 .menulabel-notice {
760 760 border: 1px solid @color5;
761 761 padding:7px 10px;
762 762 color: @color5;
763 763 }
@@ -1,966 +1,974 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-60x60.png')}" alt="RhodeCode"/></a>
13 13 </div>
14 14 % if c.rhodecode_name:
15 15 <div class="branding">
16 16 <a href="${h.route_path('home')}">${h.branding(c.rhodecode_name)}</a>
17 17 </div>
18 18 % endif
19 19 </div>
20 20 <!-- MENU BAR NAV -->
21 21 ${self.menu_bar_nav()}
22 22 <!-- END MENU BAR NAV -->
23 23 </div>
24 24 </div>
25 25 ${self.menu_bar_subnav()}
26 26 <!-- END HEADER -->
27 27
28 28 <!-- CONTENT -->
29 29 <div id="content" class="wrapper">
30 30
31 31 <rhodecode-toast id="notifications"></rhodecode-toast>
32 32
33 33 <div class="main">
34 34 ${next.main()}
35 35 </div>
36 36 </div>
37 37 <!-- END CONTENT -->
38 38
39 39 </div>
40 40 <!-- FOOTER -->
41 41 <div id="footer">
42 42 <div id="footer-inner" class="title wrapper">
43 43 <div>
44 44 <p class="footer-link-right">
45 45 % if c.visual.show_version:
46 46 RhodeCode Enterprise ${c.rhodecode_version} ${c.rhodecode_edition}
47 47 % endif
48 48 &copy; 2010-${h.datetime.today().year}, <a href="${h.route_url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
49 49 % if c.visual.rhodecode_support_url:
50 50 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
51 51 % endif
52 52 </p>
53 53 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
54 54 <p class="server-instance" style="display:${sid}">
55 55 ## display hidden instance ID if specially defined
56 56 % if c.rhodecode_instanceid:
57 57 ${_('RhodeCode instance id: {}').format(c.rhodecode_instanceid)}
58 58 % endif
59 59 </p>
60 60 </div>
61 61 </div>
62 62 </div>
63 63
64 64 <!-- END FOOTER -->
65 65
66 66 ### MAKO DEFS ###
67 67
68 68 <%def name="menu_bar_subnav()">
69 69 </%def>
70 70
71 71 <%def name="breadcrumbs(class_='breadcrumbs')">
72 72 <div class="${class_}">
73 73 ${self.breadcrumbs_links()}
74 74 </div>
75 75 </%def>
76 76
77 77 <%def name="admin_menu(active=None)">
78 78 <%
79 79 def is_active(selected):
80 80 if selected == active:
81 81 return "active"
82 82 %>
83 83
84 84 <div id="context-bar">
85 85 <div class="wrapper">
86 86 <div class="title">
87 87 <div class="title-content">
88 88 <div class="title-main">
89 89 % if c.is_super_admin:
90 90 ${_('Super Admin Panel')}
91 91 % else:
92 92 ${_('Delegated Admin Panel')}
93 93 % endif
94 94 </div>
95 95 </div>
96 96 </div>
97 97
98 98 <ul id="context-pages" class="navigation horizontal-list">
99 99
100 100 ## super admin case
101 101 % if c.is_super_admin:
102 102 <li class="${is_active('audit_logs')}"><a href="${h.route_path('admin_audit_logs')}">${_('Admin audit logs')}</a></li>
103 103 <li class="${is_active('repositories')}"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
104 104 <li class="${is_active('repository_groups')}"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
105 105 <li class="${is_active('users')}"><a href="${h.route_path('users')}">${_('Users')}</a></li>
106 106 <li class="${is_active('user_groups')}"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
107 107 <li class="${is_active('permissions')}"><a href="${h.route_path('admin_permissions_application')}">${_('Permissions')}</a></li>
108 108 <li class="${is_active('authentication')}"><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
109 109 <li class="${is_active('integrations')}"><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
110 110 <li class="${is_active('defaults')}"><a href="${h.route_path('admin_defaults_repositories')}">${_('Defaults')}</a></li>
111 111 <li class="${is_active('settings')}"><a href="${h.route_path('admin_settings')}">${_('Settings')}</a></li>
112 112
113 113 ## delegated admin
114 114 % elif c.is_delegated_admin:
115 115 <%
116 116 repositories=c.auth_user.repositories_admin or c.can_create_repo
117 117 repository_groups=c.auth_user.repository_groups_admin or c.can_create_repo_group
118 118 user_groups=c.auth_user.user_groups_admin or c.can_create_user_group
119 119 %>
120 120
121 121 %if repositories:
122 122 <li class="${is_active('repositories')} local-admin-repos"><a href="${h.route_path('repos')}">${_('Repositories')}</a></li>
123 123 %endif
124 124 %if repository_groups:
125 125 <li class="${is_active('repository_groups')} local-admin-repo-groups"><a href="${h.route_path('repo_groups')}">${_('Repository groups')}</a></li>
126 126 %endif
127 127 %if user_groups:
128 128 <li class="${is_active('user_groups')} local-admin-user-groups"><a href="${h.route_path('user_groups')}">${_('User groups')}</a></li>
129 129 %endif
130 130 % endif
131 131 </ul>
132 132
133 133 </div>
134 134 <div class="clear"></div>
135 135 </div>
136 136 </%def>
137 137
138 138 <%def name="dt_info_panel(elements)">
139 139 <dl class="dl-horizontal">
140 140 %for dt, dd, title, show_items in elements:
141 141 <dt>${dt}:</dt>
142 142 <dd title="${h.tooltip(title)}">
143 143 %if callable(dd):
144 144 ## allow lazy evaluation of elements
145 145 ${dd()}
146 146 %else:
147 147 ${dd}
148 148 %endif
149 149 %if show_items:
150 150 <span class="btn-collapse" data-toggle="item-${h.md5_safe(dt)[:6]}-details">${_('Show More')} </span>
151 151 %endif
152 152 </dd>
153 153
154 154 %if show_items:
155 155 <div class="collapsable-content" data-toggle="item-${h.md5_safe(dt)[:6]}-details" style="display: none">
156 156 %for item in show_items:
157 157 <dt></dt>
158 158 <dd>${item}</dd>
159 159 %endfor
160 160 </div>
161 161 %endif
162 162
163 163 %endfor
164 164 </dl>
165 165 </%def>
166 166
167 167 <%def name="gravatar(email, size=16)">
168 168 <%
169 169 if (size > 16):
170 170 gravatar_class = 'gravatar gravatar-large'
171 171 else:
172 172 gravatar_class = 'gravatar'
173 173 %>
174 174 <%doc>
175 175 TODO: johbo: For now we serve double size images to make it smooth
176 176 for retina. This is how it worked until now. Should be replaced
177 177 with a better solution at some point.
178 178 </%doc>
179 179 <img class="${gravatar_class}" src="${h.gravatar_url(email, size * 2)}" height="${size}" width="${size}">
180 180 </%def>
181 181
182 182
183 183 <%def name="gravatar_with_user(contact, size=16, show_disabled=False)">
184 184 <% email = h.email_or_none(contact) %>
185 185 <div class="rc-user tooltip" title="${h.tooltip(h.author_string(email))}">
186 186 ${self.gravatar(email, size)}
187 187 <span class="${'user user-disabled' if show_disabled else 'user'}"> ${h.link_to_user(contact)}</span>
188 188 </div>
189 189 </%def>
190 190
191 191
192 192 <%def name="repo_page_title(repo_instance)">
193 193 <div class="title-content repo-title">
194 194
195 195 <div class="title-main">
196 196 ## SVN/HG/GIT icons
197 197 %if h.is_hg(repo_instance):
198 198 <i class="icon-hg"></i>
199 199 %endif
200 200 %if h.is_git(repo_instance):
201 201 <i class="icon-git"></i>
202 202 %endif
203 203 %if h.is_svn(repo_instance):
204 204 <i class="icon-svn"></i>
205 205 %endif
206 206
207 207 ## public/private
208 208 %if repo_instance.private:
209 209 <i class="icon-repo-private"></i>
210 210 %else:
211 211 <i class="icon-repo-public"></i>
212 212 %endif
213 213
214 214 ## repo name with group name
215 215 ${h.breadcrumb_repo_link(repo_instance)}
216 216
217 217 ## Context Actions
218 218 <div class="pull-right">
219 219 %if c.rhodecode_user.username != h.DEFAULT_USER:
220 220 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_name, _query=dict(auth_token=c.rhodecode_user.feed_token))}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
221 221
222 222 <a href="#WatchRepo" onclick="toggleFollowingRepo(this, templateContext.repo_id); return false" title="${_('Watch this Repository and actions on it in your personalized journal')}" class="btn btn-sm ${('watching' if c.repository_is_user_following else '')}">
223 223 % if c.repository_is_user_following:
224 224 <i class="icon-eye-off"></i>${_('Unwatch')}
225 225 % else:
226 226 <i class="icon-eye"></i>${_('Watch')}
227 227 % endif
228 228
229 229 </a>
230 230 %else:
231 231 <a href="${h.route_path('atom_feed_home', repo_name=c.rhodecode_db_repo.repo_name)}" title="${_('RSS Feed')}" class="btn btn-sm"><i class="icon-rss-sign"></i>RSS</a>
232 232 %endif
233 233 </div>
234 234
235 235 </div>
236 236
237 237 ## FORKED
238 238 %if repo_instance.fork:
239 239 <p class="discreet">
240 240 <i class="icon-code-fork"></i> ${_('Fork of')}
241 241 ${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))}
242 242 </p>
243 243 %endif
244 244
245 245 ## IMPORTED FROM REMOTE
246 246 %if repo_instance.clone_uri:
247 247 <p class="discreet">
248 248 <i class="icon-code-fork"></i> ${_('Clone from')}
249 249 <a href="${h.safe_str(h.hide_credentials(repo_instance.clone_uri))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
250 250 </p>
251 251 %endif
252 252
253 253 ## LOCKING STATUS
254 254 %if repo_instance.locked[0]:
255 255 <p class="locking_locked discreet">
256 256 <i class="icon-repo-lock"></i>
257 257 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
258 258 </p>
259 259 %elif repo_instance.enable_locking:
260 260 <p class="locking_unlocked discreet">
261 261 <i class="icon-repo-unlock"></i>
262 262 ${_('Repository not locked. Pull repository to lock it.')}
263 263 </p>
264 264 %endif
265 265
266 266 </div>
267 267 </%def>
268 268
269 269 <%def name="repo_menu(active=None)">
270 270 <%
271 271 def is_active(selected):
272 272 if selected == active:
273 273 return "active"
274 274 %>
275 275 % if c.rhodecode_db_repo.archived:
276 276 <div class="alert alert-warning text-center">
277 277 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
278 278 </div>
279 279 % endif
280 280
281 281 <!--- REPO CONTEXT BAR -->
282 282 <div id="context-bar">
283 283 <div class="wrapper">
284 284
285 285 <div class="title">
286 286 ${self.repo_page_title(c.rhodecode_db_repo)}
287 287 </div>
288 288
289 289 <ul id="context-pages" class="navigation horizontal-list">
290 290 <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>
291 291 <li class="${is_active('commits')}"><a class="menulink" href="${h.route_path('repo_commits', repo_name=c.repo_name)}"><div class="menulabel">${_('Commits')}</div></a></li>
292 292 <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>
293 293 <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>
294 294
295 295 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
296 296 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
297 297 <li class="${is_active('showpullrequest')}">
298 298 <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)}">
299 299 <div class="menulabel">
300 300 %if c.repository_pull_requests == 1:
301 301 ${c.repository_pull_requests} ${_('Pull Request')}
302 302 %else:
303 303 ${c.repository_pull_requests} ${_('Pull Requests')}
304 304 %endif
305 305 </div>
306 306 </a>
307 307 </li>
308 308 %endif
309 309
310 310 <li class="${is_active('artifacts')}"><a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}"><div class="menulabel">${_('Artifacts')} (BETA)</div></a></li>
311 311
312 312 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
313 313 <li class="${is_active('settings')}"><a class="menulink" href="${h.route_path('edit_repo',repo_name=c.repo_name)}"><div class="menulabel">${_('Repository Settings')}</div></a></li>
314 314 %endif
315 315
316 316 ## determine if we have "any" option available
317 317 <%
318 318 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
319 319 has_actions = (c.rhodecode_user.username != h.DEFAULT_USER and c.rhodecode_db_repo.repo_type in ['git','hg'] ) or can_lock
320 320 %>
321 321 <li class="${is_active('options')}">
322 322 % if has_actions:
323 323 <a class="menulink dropdown">
324 324 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
325 325 </a>
326 326 <ul class="submenu">
327 327 <li><a href="${h.route_path('repo_fork_new',repo_name=c.repo_name)}">${_('Fork this repository')}</a></li>
328 328 <li><a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
329 329 %if can_lock:
330 330 %if c.rhodecode_db_repo.locked[0]:
331 331 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock Repository')}</a></li>
332 332 %else:
333 333 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock Repository')}</a></li>
334 334 %endif
335 335 %endif
336 336 </ul>
337 337 % else:
338 338 <a class="menulink disabled">
339 339 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
340 340 </a>
341 341 % endif
342 342 </li>
343 343
344 344 </ul>
345 345 </div>
346 346 <div class="clear"></div>
347 347 </div>
348 348
349 349 <!--- REPO END CONTEXT BAR -->
350 350
351 351 </%def>
352 352
353 353 <%def name="repo_group_page_title(repo_group_instance)">
354 354 <div class="title-content">
355 355 <div class="title-main">
356 356 ## Repository Group icon
357 357 <i class="icon-repo-group"></i>
358 358
359 359 ## repo name with group name
360 360 ${h.breadcrumb_repo_group_link(repo_group_instance)}
361 361 </div>
362 362
363 363 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
364 364 <div class="repo-group-desc discreet">
365 365 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
366 366 </div>
367 367
368 368 </div>
369 369 </%def>
370 370
371 371 <%def name="repo_group_menu(active=None)">
372 372 <%
373 373 def is_active(selected):
374 374 if selected == active:
375 375 return "active"
376 376
377 377 gr_name = c.repo_group.group_name if c.repo_group else None
378 378 # create repositories with write permission on group is set to true
379 379 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
380 380 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
381 381 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
382 382
383 383 %>
384 384
385 385 <!--- REPO GROUP CONTEXT BAR -->
386 386 <div id="context-bar">
387 387 <div class="wrapper">
388 388 <div class="title">
389 389 ${self.repo_group_page_title(c.repo_group)}
390 390 </div>
391 391
392 392 <ul id="context-pages" class="navigation horizontal-list">
393 393 <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>
394 394 % if c.is_super_admin or group_admin:
395 395 <li class="${is_active('settings')}"><a class="menulink" href="${h.route_path('edit_repo_group',repo_group_name=c.repo_group.group_name)}" title="${_('You have admin right to this group, and can edit it')}"><div class="menulabel">${_('Group Settings')}</div></a></li>
396 396 % endif
397 397 ## determine if we have "any" option available
398 398 <%
399 399 can_create_repos = c.is_super_admin or group_admin or (group_write and create_on_write)
400 400 can_create_repo_groups = c.is_super_admin or group_admin
401 401 has_actions = can_create_repos or can_create_repo_groups
402 402 %>
403 403 <li class="${is_active('options')}">
404 404 % if has_actions:
405 405 <a class="menulink dropdown">
406 406 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
407 407 </a>
408 408 <ul class="submenu">
409 409 %if can_create_repos:
410 410 <li><a href="${h.route_path('repo_new',_query=dict(parent_group=c.repo_group.group_id))}">${_('Add Repository')}</a></li>
411 411 %endif
412 412 %if can_create_repo_groups:
413 413 <li><a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.repo_group.group_id))}">${_(u'Add Repository Group')}</a></li>
414 414 %endif
415 415 </ul>
416 416 % else:
417 417 <a class="menulink disabled">
418 418 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
419 419 </a>
420 420 % endif
421 421 </li>
422 422 </ul>
423 423 </div>
424 424 <div class="clear"></div>
425 425 </div>
426 426
427 427 <!--- REPO GROUP CONTEXT BAR -->
428 428
429 429 </%def>
430 430
431 431
432 432 <%def name="usermenu(active=False)">
433 433 ## USER MENU
434 434 <li id="quick_login_li" class="${'active' if active else ''}">
435 435 % if c.rhodecode_user.username == h.DEFAULT_USER:
436 436 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
437 437 ${gravatar(c.rhodecode_user.email, 20)}
438 438 <span class="user">
439 439 <span>${_('Sign in')}</span>
440 440 </span>
441 441 </a>
442 442 % else:
443 443 ## logged in user
444 444 <a id="quick_login_link" class="menulink childs">
445 445 ${gravatar(c.rhodecode_user.email, 20)}
446 446 <span class="user">
447 447 <span class="menu_link_user">${c.rhodecode_user.username}</span>
448 448 <div class="show_more"></div>
449 449 </span>
450 450 </a>
451 451 ## subnav with menu for logged in user
452 452 <div class="user-menu submenu">
453 453 <div id="quick_login">
454 454 %if c.rhodecode_user.username != h.DEFAULT_USER:
455 455 <div class="">
456 456 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
457 457 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
458 458 <div class="email">${c.rhodecode_user.email}</div>
459 459 </div>
460 460 <div class="">
461 461 <ol class="links">
462 462 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
463 463 % if c.rhodecode_user.personal_repo_group:
464 464 <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>
465 465 % endif
466 466 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
467 467 ## bookmark-items
468 468 <li class="bookmark-items">
469 469 ${_('Bookmarks')}
470 470 <div class="pull-right">
471 471 <a href="${h.route_path('my_account_bookmarks')}">${_('Manage')}</a>
472 472 </div>
473 473 </li>
474 474 % if not c.bookmark_items:
475 475 <li>
476 476 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
477 477 </li>
478 478 % endif
479 479 % for item in c.bookmark_items:
480 480 <li>
481 481 % if item.repository:
482 482 <div>
483 483 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
484 484 <code>${item.position}</code>
485 485 % if item.repository.repo_type == 'hg':
486 486 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
487 487 % elif item.repository.repo_type == 'git':
488 488 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
489 489 % elif item.repository.repo_type == 'svn':
490 490 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
491 491 % endif
492 492 ${(item.title or h.shorter(item.repository.repo_name, 30))}
493 493 </a>
494 494 </div>
495 495 % elif item.repository_group:
496 496 <div>
497 497 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
498 498 <code>${item.position}</code>
499 499 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
500 500 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
501 501 </a>
502 502 </div>
503 503 % else:
504 504 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
505 505 <code>${item.position}</code>
506 506 ${item.title}
507 507 </a>
508 508 % endif
509 509 </li>
510 510 % endfor
511 511
512 512 <li class="logout">
513 513 ${h.secure_form(h.route_path('logout'), request=request)}
514 514 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
515 515 ${h.end_form()}
516 516 </li>
517 517 </ol>
518 518 </div>
519 519 %endif
520 520 </div>
521 521 </div>
522 522 ## unread counter
523 523 <div class="pill_container">
524 524 <a class="menu_link_notifications ${'empty' if c.unread_notifications == 0 else ''}" href="${h.route_path('notifications_show_all')}">${c.unread_notifications}</a>
525 525 </div>
526 526 % endif
527 527 </li>
528 528 </%def>
529 529
530 530 <%def name="menu_items(active=None)">
531 531 <%
532 532 def is_active(selected):
533 533 if selected == active:
534 534 return "active"
535 535 return ""
536 536 %>
537 537
538 538 <ul id="quick" class="main_nav navigation horizontal-list">
539 539 ## notice box for important system messages
540 540 <li style="display: none">
541 541 <a class="notice-box" href="#openNotice" onclick="showNoticeBox(); return false">
542 542 <div class="menulabel-notice" >
543 543 0
544 544 </div>
545 545 </a>
546 546 </li>
547 547
548 548 ## Main filter
549 549 <li>
550 550 <div class="menulabel main_filter_box">
551 551 <div class="main_filter_input_box">
552 552 <ul class="searchItems">
553 553
554 554 % if c.template_context['search_context']['repo_id']:
555 555 <li class="searchTag searchTagFilter searchTagHidable" >
556 556 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
557 557 <span class="tag">
558 558 This repo
559 559 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
560 560 </span>
561 561 ##</a>
562 562 </li>
563 563 % elif c.template_context['search_context']['repo_group_id']:
564 564 <li class="searchTag searchTagFilter searchTagHidable">
565 565 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
566 566 <span class="tag">
567 567 This group
568 568 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
569 569 </span>
570 570 ##</a>
571 571 </li>
572 572 % endif
573 573
574 574 <li class="searchTagInput">
575 <input class="main_filter_input" id="main_filter" size="15" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
575 <input class="main_filter_input" id="main_filter" size="25" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
576 576 </li>
577 577 <li class="searchTag searchTagHelp">
578 578 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
579 579 </li>
580 580 </ul>
581 581 </div>
582 582 </div>
583 583
584 584 <div id="main_filter_help" style="display: none">
585 585 - Use '/' key to quickly access this field.
586 586
587 587 - Enter a name of repository, or repository group for quick search.
588 588
589 589 - Prefix query to allow special search:
590 590
591 591 user:admin, to search for usernames, always global
592 592
593 593 user_group:devops, to search for user groups, always global
594 594
595 595 commit:efced4, to search for commits, scoped to repositories or groups
596 596
597 597 file:models.py, to search for file paths, scoped to repositories or groups
598 598
599 599 % if c.template_context['search_context']['repo_id']:
600 600 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>
601 601 % elif c.template_context['search_context']['repo_group_id']:
602 602 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>
603 603 % else:
604 604 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
605 605 % endif
606 606 </div>
607 607 </li>
608 608
609 609 ## ROOT MENU
610 610 <li class="${is_active('home')}">
611 611 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
612 612 <div class="menulabel">${_('Home')}</div>
613 613 </a>
614 614 </li>
615 615
616 616 %if c.rhodecode_user.username != h.DEFAULT_USER:
617 617 <li class="${is_active('journal')}">
618 618 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
619 619 <div class="menulabel">${_('Journal')}</div>
620 620 </a>
621 621 </li>
622 622 %else:
623 623 <li class="${is_active('journal')}">
624 624 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
625 625 <div class="menulabel">${_('Public journal')}</div>
626 626 </a>
627 627 </li>
628 628 %endif
629 629
630 630 <li class="${is_active('gists')}">
631 631 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
632 632 <div class="menulabel">${_('Gists')}</div>
633 633 </a>
634 634 </li>
635 635
636 636 % if c.is_super_admin or c.is_delegated_admin:
637 637 <li class="${is_active('admin')}">
638 638 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
639 639 <div class="menulabel">${_('Admin')} </div>
640 640 </a>
641 641 </li>
642 642 % endif
643 643
644 644 ## render extra user menu
645 645 ${usermenu(active=(active=='my_account'))}
646 646
647 647 % if c.debug_style:
648 648 <li>
649 649 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
650 650 <div class="menulabel">${_('[Style]')}</div>
651 651 </a>
652 652 </li>
653 653 % endif
654 654 </ul>
655 655
656 656 <script type="text/javascript">
657 657 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
658 658
659 659 var formatRepoResult = function(result, container, query, escapeMarkup) {
660 660 return function(data, escapeMarkup) {
661 661 if (!data.repo_id){
662 662 return data.text; // optgroup text Repositories
663 663 }
664 664
665 665 var tmpl = '';
666 666 var repoType = data['repo_type'];
667 667 var repoName = data['text'];
668 668
669 669 if(data && data.type == 'repo'){
670 670 if(repoType === 'hg'){
671 671 tmpl += '<i class="icon-hg"></i> ';
672 672 }
673 673 else if(repoType === 'git'){
674 674 tmpl += '<i class="icon-git"></i> ';
675 675 }
676 676 else if(repoType === 'svn'){
677 677 tmpl += '<i class="icon-svn"></i> ';
678 678 }
679 679 if(data['private']){
680 680 tmpl += '<i class="icon-lock" ></i> ';
681 681 }
682 682 else if(visualShowPublicIcon){
683 683 tmpl += '<i class="icon-unlock-alt"></i> ';
684 684 }
685 685 }
686 686 tmpl += escapeMarkup(repoName);
687 687 return tmpl;
688 688
689 689 }(result, escapeMarkup);
690 690 };
691 691
692 692 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
693 693 return function(data, escapeMarkup) {
694 694 if (!data.repo_group_id){
695 695 return data.text; // optgroup text Repositories
696 696 }
697 697
698 698 var tmpl = '';
699 699 var repoGroupName = data['text'];
700 700
701 701 if(data){
702 702
703 703 tmpl += '<i class="icon-repo-group"></i> ';
704 704
705 705 }
706 706 tmpl += escapeMarkup(repoGroupName);
707 707 return tmpl;
708 708
709 709 }(result, escapeMarkup);
710 710 };
711 711
712 712 var escapeRegExChars = function (value) {
713 713 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
714 714 };
715 715
716 716 var getRepoIcon = function(repo_type) {
717 717 if (repo_type === 'hg') {
718 718 return '<i class="icon-hg"></i> ';
719 719 }
720 720 else if (repo_type === 'git') {
721 721 return '<i class="icon-git"></i> ';
722 722 }
723 723 else if (repo_type === 'svn') {
724 724 return '<i class="icon-svn"></i> ';
725 725 }
726 726 return ''
727 727 };
728 728
729 729 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
730 730
731 731 if (value.split(':').length === 2) {
732 732 value = value.split(':')[1]
733 733 }
734 734
735 735 var searchType = data['type'];
736 var searchSubType = data['subtype'];
736 737 var valueDisplay = data['value_display'];
737 738
738 739 var pattern = '(' + escapeRegExChars(value) + ')';
739 740
740 741 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
741 742
742 743 // highlight match
743 744 if (searchType != 'text') {
744 745 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
745 746 }
746 747
747 748 var icon = '';
748 749
749 750 if (searchType === 'hint') {
750 751 icon += '<i class="icon-repo-group"></i> ';
751 752 }
752 // full text search
753 // full text search/hints
753 754 else if (searchType === 'search') {
754 755 icon += '<i class="icon-more"></i> ';
756 if (searchSubType !== undefined && searchSubType == 'repo') {
757 valueDisplay += '<div class="pull-right tag">repository</div>';
758 }
759 else if (searchSubType !== undefined && searchSubType == 'repo_group') {
760 valueDisplay += '<div class="pull-right tag">repo group</div>';
761 }
755 762 }
756 763 // repository
757 764 else if (searchType === 'repo') {
758 765
759 766 var repoIcon = getRepoIcon(data['repo_type']);
760 767 icon += repoIcon;
761 768
762 769 if (data['private']) {
763 770 icon += '<i class="icon-lock" ></i> ';
764 771 }
765 772 else if (visualShowPublicIcon) {
766 773 icon += '<i class="icon-unlock-alt"></i> ';
767 774 }
768 775 }
769 776 // repository groups
770 777 else if (searchType === 'repo_group') {
771 778 icon += '<i class="icon-repo-group"></i> ';
772 779 }
773 780 // user group
774 781 else if (searchType === 'user_group') {
775 782 icon += '<i class="icon-group"></i> ';
776 783 }
777 784 // user
778 785 else if (searchType === 'user') {
779 786 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
780 787 }
781 788 // commit
782 789 else if (searchType === 'commit') {
783 790 var repo_data = data['repo_data'];
784 791 var repoIcon = getRepoIcon(repo_data['repository_type']);
785 792 if (repoIcon) {
786 793 icon += repoIcon;
787 794 } else {
788 795 icon += '<i class="icon-tag"></i>';
789 796 }
790 797 }
791 798 // file
792 799 else if (searchType === 'file') {
793 800 var repo_data = data['repo_data'];
794 801 var repoIcon = getRepoIcon(repo_data['repository_type']);
795 802 if (repoIcon) {
796 803 icon += repoIcon;
797 804 } else {
798 805 icon += '<i class="icon-tag"></i>';
799 806 }
800 807 }
801 808 // generic text
802 809 else if (searchType === 'text') {
803 810 icon = '';
804 811 }
805 812
806 813 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
807 814 return tmpl.format(icon, valueDisplay);
808 815 };
809 816
810 817 var handleSelect = function(element, suggestion) {
811 818 if (suggestion.type === "hint") {
812 819 // we skip action
813 820 $('#main_filter').focus();
814 821 }
815 822 else if (suggestion.type === "text") {
816 823 // we skip action
817 824 $('#main_filter').focus();
818 825
819 826 } else {
820 827 window.location = suggestion['url'];
821 828 }
822 829 };
823 830
824 831 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
825 832 if (queryLowerCase.split(':').length === 2) {
826 833 queryLowerCase = queryLowerCase.split(':')[1]
827 834 }
828 835 if (suggestion.type === "text") {
829 836 // special case we don't want to "skip" display for
830 837 return true
831 838 }
832 839 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
833 840 };
834 841
835 842 var cleanContext = {
836 843 repo_view_type: null,
837 844
838 845 repo_id: null,
839 846 repo_name: "",
840 847
841 848 repo_group_id: null,
842 849 repo_group_name: null
843 850 };
844 851 var removeGoToFilter = function () {
845 852 $('.searchTagHidable').hide();
846 853 $('#main_filter').autocomplete(
847 854 'setOptions', {params:{search_context: cleanContext}});
848 855 };
849 856
850 857 $('#main_filter').autocomplete({
851 858 serviceUrl: pyroutes.url('goto_switcher_data'),
852 859 params: {
853 860 "search_context": templateContext.search_context
854 861 },
855 862 minChars:2,
856 863 maxHeight:400,
857 864 deferRequestBy: 300, //miliseconds
858 865 tabDisabled: true,
859 866 autoSelectFirst: false,
867 containerClass: 'autocomplete-qfilter-suggestions',
860 868 formatResult: autocompleteMainFilterFormatResult,
861 869 lookupFilter: autocompleteMainFilterResult,
862 870 onSelect: function (element, suggestion) {
863 871 handleSelect(element, suggestion);
864 872 return false;
865 873 },
866 874 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
867 875 if (jqXHR !== 'abort') {
868 876 alert("Error during search.\nError code: {0}".format(textStatus));
869 877 window.location = '';
870 878 }
871 879 }
872 880 });
873 881
874 882 showMainFilterBox = function () {
875 883 $('#main_filter_help').toggle();
876 884 };
877 885
878 886 $('#main_filter').on('keydown.autocomplete', function (e) {
879 887
880 888 var BACKSPACE = 8;
881 889 var el = $(e.currentTarget);
882 890 if(e.which === BACKSPACE){
883 891 var inputVal = el.val();
884 892 if (inputVal === ""){
885 893 removeGoToFilter()
886 894 }
887 895 }
888 896 });
889 897
890 898 </script>
891 899 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
892 900 </%def>
893 901
894 902 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
895 903 <div class="modal-dialog">
896 904 <div class="modal-content">
897 905 <div class="modal-header">
898 906 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
899 907 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
900 908 </div>
901 909 <div class="modal-body">
902 910 <div class="block-left">
903 911 <table class="keyboard-mappings">
904 912 <tbody>
905 913 <tr>
906 914 <th></th>
907 915 <th>${_('Site-wide shortcuts')}</th>
908 916 </tr>
909 917 <%
910 918 elems = [
911 919 ('/', 'Use quick search box'),
912 920 ('g h', 'Goto home page'),
913 921 ('g g', 'Goto my private gists page'),
914 922 ('g G', 'Goto my public gists page'),
915 923 ('g 0-9', 'Goto bookmarked items from 0-9'),
916 924 ('n r', 'New repository page'),
917 925 ('n g', 'New gist page'),
918 926 ]
919 927 %>
920 928 %for key, desc in elems:
921 929 <tr>
922 930 <td class="keys">
923 931 <span class="key tag">${key}</span>
924 932 </td>
925 933 <td>${desc}</td>
926 934 </tr>
927 935 %endfor
928 936 </tbody>
929 937 </table>
930 938 </div>
931 939 <div class="block-left">
932 940 <table class="keyboard-mappings">
933 941 <tbody>
934 942 <tr>
935 943 <th></th>
936 944 <th>${_('Repositories')}</th>
937 945 </tr>
938 946 <%
939 947 elems = [
940 948 ('g s', 'Goto summary page'),
941 949 ('g c', 'Goto changelog page'),
942 950 ('g f', 'Goto files page'),
943 951 ('g F', 'Goto files page with file search activated'),
944 952 ('g p', 'Goto pull requests page'),
945 953 ('g o', 'Goto repository settings'),
946 954 ('g O', 'Goto repository permissions settings'),
947 955 ]
948 956 %>
949 957 %for key, desc in elems:
950 958 <tr>
951 959 <td class="keys">
952 960 <span class="key tag">${key}</span>
953 961 </td>
954 962 <td>${desc}</td>
955 963 </tr>
956 964 %endfor
957 965 </tbody>
958 966 </table>
959 967 </div>
960 968 </div>
961 969 <div class="modal-footer">
962 970 </div>
963 971 </div><!-- /.modal-content -->
964 972 </div><!-- /.modal-dialog -->
965 973 </div><!-- /.modal -->
966 974
General Comments 0
You need to be logged in to leave comments. Login now