##// END OF EJS Templates
ui: added action link that repliaces current mix of actions in options and action buttons...
marcink -
r3907:c5a907e3 default
parent child Browse files
Show More
@@ -1,141 +1,141 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-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
22 22 import pytest
23 23
24 24 import rhodecode
25 25 from rhodecode.model.db import Repository
26 26 from rhodecode.model.meta import Session
27 27 from rhodecode.model.repo import RepoModel
28 28 from rhodecode.model.repo_group import RepoGroupModel
29 29 from rhodecode.model.settings import SettingsModel
30 30 from rhodecode.tests import TestController
31 31 from rhodecode.tests.fixture import Fixture
32 32 from rhodecode.lib import helpers as h
33 33
34 34 fixture = Fixture()
35 35
36 36
37 37 def route_path(name, **kwargs):
38 38 return {
39 39 'home': '/',
40 40 'repo_group_home': '/{repo_group_name}'
41 41 }[name].format(**kwargs)
42 42
43 43
44 44 class TestHomeController(TestController):
45 45
46 46 def test_index(self):
47 47 self.log_user()
48 48 response = self.app.get(route_path('home'))
49 49 # if global permission is set
50 response.mustcontain('Add Repository')
50 response.mustcontain('New Repository')
51 51
52 52 # search for objects inside the JavaScript JSON
53 53 for repo in Repository.getAll():
54 54 response.mustcontain('"name_raw": "%s"' % repo.repo_name)
55 55
56 56 def test_index_contains_statics_with_ver(self):
57 57 from rhodecode.lib.base import calculate_version_hash
58 58
59 59 self.log_user()
60 60 response = self.app.get(route_path('home'))
61 61
62 62 rhodecode_version_hash = calculate_version_hash(
63 63 {'beaker.session.secret': 'test-rc-uytcxaz'})
64 64 response.mustcontain('style.css?ver={0}'.format(rhodecode_version_hash))
65 65 response.mustcontain('scripts.js?ver={0}'.format(rhodecode_version_hash))
66 66
67 67 def test_index_contains_backend_specific_details(self, backend):
68 68 self.log_user()
69 69 response = self.app.get(route_path('home'))
70 70 tip = backend.repo.get_commit().raw_id
71 71
72 72 # html in javascript variable:
73 73 response.mustcontain(r'<i class=\"icon-%s\"' % (backend.alias, ))
74 74 response.mustcontain(r'href=\"/%s\"' % (backend.repo_name, ))
75 75
76 76 response.mustcontain("""/%s/changeset/%s""" % (backend.repo_name, tip))
77 77 response.mustcontain("""Added a symlink""")
78 78
79 79 def test_index_with_anonymous_access_disabled(self):
80 80 with fixture.anon_access(False):
81 81 response = self.app.get(route_path('home'), status=302)
82 82 assert 'login' in response.location
83 83
84 84 def test_index_page_on_groups(self, autologin_user, repo_group):
85 85 response = self.app.get(route_path('repo_group_home', repo_group_name='gr1'))
86 86 response.mustcontain("gr1/repo_in_group")
87 87
88 88 def test_index_page_on_group_with_trailing_slash(
89 89 self, autologin_user, repo_group):
90 90 response = self.app.get(route_path('repo_group_home', repo_group_name='gr1') + '/')
91 91 response.mustcontain("gr1/repo_in_group")
92 92
93 93 @pytest.fixture(scope='class')
94 94 def repo_group(self, request):
95 95 gr = fixture.create_repo_group('gr1')
96 96 fixture.create_repo(name='gr1/repo_in_group', repo_group=gr)
97 97
98 98 @request.addfinalizer
99 99 def cleanup():
100 100 RepoModel().delete('gr1/repo_in_group')
101 101 RepoGroupModel().delete(repo_group='gr1', force_delete=True)
102 102 Session().commit()
103 103
104 104 def test_index_with_name_with_tags(self, user_util, autologin_user):
105 105 user = user_util.create_user()
106 106 username = user.username
107 107 user.name = '<img src="/image1" onload="alert(\'Hello, World!\');">'
108 108 user.lastname = '#"><img src=x onerror=prompt(document.cookie);>'
109 109
110 110 Session().add(user)
111 111 Session().commit()
112 112 user_util.create_repo(owner=username)
113 113
114 114 response = self.app.get(route_path('home'))
115 115 response.mustcontain(h.html_escape(user.first_name))
116 116 response.mustcontain(h.html_escape(user.last_name))
117 117
118 118 @pytest.mark.parametrize("name, state", [
119 119 ('Disabled', False),
120 120 ('Enabled', True),
121 121 ])
122 122 def test_index_show_version(self, autologin_user, name, state):
123 123 version_string = 'RhodeCode Enterprise %s' % rhodecode.__version__
124 124
125 125 sett = SettingsModel().create_or_update_setting(
126 126 'show_version', state, 'bool')
127 127 Session().add(sett)
128 128 Session().commit()
129 129 SettingsModel().invalidate_settings_cache()
130 130
131 131 response = self.app.get(route_path('home'))
132 132 if state is True:
133 133 response.mustcontain(version_string)
134 134 if state is False:
135 135 response.mustcontain(no=[version_string])
136 136
137 137 def test_logout_form_contains_csrf(self, autologin_user, csrf_token):
138 138 response = self.app.get(route_path('home'))
139 139 assert_response = response.assert_response()
140 140 element = assert_response.get_element('.logout #csrf_token')
141 141 assert element.value == csrf_token
@@ -1,755 +1,806 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 margin-right: 0px;
203 204
204 205 &:hover #quick_login_link {
205 206 color: inherit;
206 207 }
207 208
208 209 .menu_link_user {
209 210 padding: 0 2px;
210 211 }
211 212 }
212 213 list-style-type: none;
213 214 }
214 215
215 216 > li {
216 217
217 218 a {
218 219 padding: 18px 0 12px 0;
219 220 color: @nav-grey;
220 221
221 222 &.menu_link_notifications {
222 223 padding: 1px 8px;
223 224 }
224 225 }
225 226
226 227 &:hover,
227 228 &.open,
228 229 &.active {
229 230 .pill_container a {
230 231 // don't select text for the pill container, it has it' own
231 232 // hover behaviour
232 233 color: @nav-grey;
233 234 }
234 235 }
235 236
236 237 &:hover,
237 238 &.open,
238 239 &.active {
239 240 a {
240 241 color: @grey6;
241 242 }
242 243 }
243 244
244 245 .select2-dropdown-open a {
245 246 color: @grey6;
246 247 }
247 248
248 249 .repo-switcher {
249 250 padding-left: 0;
250 251
251 252 .menulabel {
252 253 padding-left: 0;
253 254 }
254 255 }
255 256 }
256 257
257 258 li ul li {
258 259 background-color:@grey2;
259 260
260 261 a {
261 262 padding: .5em 0;
262 263 border-bottom: @border-thickness solid @border-default-color;
263 264 color: @grey6;
264 265 }
265 266
266 267 &:last-child a, &.last a{
267 268 border-bottom: none;
268 269 }
269 270
270 271 &:hover {
271 272 background-color: @grey3;
272 273 }
273 274 }
274 275
275 276 .submenu {
276 277 margin-top: 5px;
277 278 }
278 279 }
279 280
280 281 // SUBMENUS
281 282 .navigation .submenu {
282 283 display: none;
283 284 }
284 285
285 286 .navigation li.open {
286 287 .submenu {
287 288 display: block;
288 289 }
289 290 }
290 291
291 292 .navigation li:last-child .submenu {
292 293 right: auto;
293 294 left: 0;
294 295 border: 1px solid @grey5;
295 296 background: @white;
296 297 box-shadow: @dropdown-shadow;
297 298 }
298 299
299 300 .submenu {
300 301 position: absolute;
301 302 top: 100%;
302 303 left: 0;
303 304 min-width: 180px;
304 305 margin: 2px 0 0;
305 306 padding: 0;
306 307 text-align: left;
307 308 font-family: @text-light;
308 309 border-radius: @border-radius;
309 310 z-index: 20;
310 311
311 312 li {
312 313 display: block;
313 314 margin: 0;
314 315 padding: 0 .5em;
315 316 line-height: 1em;
316 317 color: @grey3;
317 318 background-color: @white;
318 319 list-style-type: none;
319 320
320 321 a {
321 322 display: block;
322 323 width: 100%;
323 324 padding: .5em 0;
324 325 border-right: none;
325 326 border-bottom: @border-thickness solid white;
326 327 color: @grey3;
327 328 }
328 329
329 330 ul {
330 331 display: none;
331 332 position: absolute;
332 333 top: 0;
333 334 right: 100%;
334 335 padding: 0;
335 336 z-index: 30;
336 337 }
337 338 &:hover {
338 339 background-color: @grey7;
339 340 -webkit-transition: background .3s;
340 341 -moz-transition: background .3s;
341 342 -o-transition: background .3s;
342 343 transition: background .3s;
343 344
344 345 ul {
345 346 display: block;
346 347 }
347 348 }
348 349 }
349 350
350 351 }
351 352
352 353
353 354
354 355
355 356 // repo dropdown
356 357 .quick_repo_menu {
357 358 width: 15px;
358 359 text-align: center;
359 360 position: relative;
360 361 cursor: pointer;
361 362
362 363 div {
363 364 overflow: visible !important;
364 365 }
365 366
366 367 &.sorting {
367 368 cursor: auto;
368 369 }
369 370
370 371 &:hover {
371 372 .menu_items_container {
372 373 position: absolute;
373 374 display: block;
374 375 }
375 376 .menu_items {
376 377 display: block;
377 378 }
378 379 }
379 380
380 381 i {
381 382 margin: 0;
382 383 color: @grey4;
383 384 }
384 385
385 386 .menu_items_container {
386 387 position: absolute;
387 388 top: 0;
388 389 left: 100%;
389 390 margin: 0;
390 391 padding: 0;
391 392 list-style: none;
392 393 background-color: @grey6;
393 394 z-index: 999;
394 395 text-align: left;
395 396
396 397 a {
397 398 color: @grey2;
398 399 }
399 400
400 401 ul.menu_items {
401 402 margin: 0;
402 403 padding: 0;
403 404 }
404 405
405 406 li {
406 407 margin: 0;
407 408 padding: 0;
408 409 line-height: 1em;
409 410 list-style-type: none;
410 411
411 412 a {
412 413 display: block;
413 414 height: 16px;
414 415 padding: 8px; //must add up to td height (28px)
415 416 width: 120px; // set width
416 417
417 418 &:hover {
418 419 background-color: @grey5;
419 420 -webkit-transition: background .3s;
420 421 -moz-transition: background .3s;
421 422 -o-transition: background .3s;
422 423 transition: background .3s;
423 424 }
424 425 }
425 426 }
426 427 }
427 428 }
428 429
430
431 // new objects main action
432 .action-menu {
433 left: auto;
434 right: 0;
435 padding: 12px;
436 z-index: 999;
437 overflow: hidden;
438 background-color: #fff;
439 border: 1px solid @grey5;
440 color: @grey2;
441 box-shadow: @dropdown-shadow;
442
443 .submenu-title {
444 font-weight: bold;
445 }
446
447 .submenu-title:not(:first-of-type) {
448 padding-top: 10px;
449 }
450
451 &.submenu {
452 min-width: 200px;
453
454 ol {
455 padding:0;
456 }
457
458 li {
459 display: block;
460 margin: 0;
461 padding: .2em .5em;
462 line-height: 1em;
463
464 background-color: #fff;
465 list-style-type: none;
466
467 a {
468 padding: 4px;
469 color: @grey4 !important;
470 border-bottom: none;
471 }
472 }
473 li:not(.submenu-title) a:hover{
474 color: @grey2 !important;
475 }
476 }
477 }
478
479
429 480 // Header Repository Switcher
430 481 // Select2 Dropdown
431 482 #select2-drop.select2-drop.repo-switcher-dropdown {
432 483 width: auto !important;
433 484 margin-top: 5px;
434 485 padding: 1em 0;
435 486 text-align: left;
436 487 .border-radius-bottom(@border-radius);
437 488 border-color: transparent;
438 489 color: @grey6;
439 490 background-color: @grey2;
440 491
441 492 input {
442 493 min-width: 90%;
443 494 }
444 495
445 496 ul.select2-result-sub {
446 497
447 498 li {
448 499 line-height: 1em;
449 500
450 501 &:hover,
451 502 &.select2-highlighted {
452 503 background-color: @grey3;
453 504 }
454 505 }
455 506
456 507 &:before { content: none; }
457 508 }
458 509
459 510 ul.select2-results {
460 511 min-width: 200px;
461 512 margin: 0;
462 513 padding: 0;
463 514 list-style-type: none;
464 515 overflow-x: visible;
465 516 overflow-y: scroll;
466 517
467 518 li {
468 519 padding: 0 8px;
469 520 line-height: 1em;
470 521 color: @grey6;
471 522
472 523 &>.select2-result-label {
473 524 padding: 8px 0;
474 525 border-bottom: @border-thickness solid @grey3;
475 526 white-space: nowrap;
476 527 color: @grey5;
477 528 cursor: pointer;
478 529 }
479 530
480 531 &.select2-result-with-children {
481 532 margin: 0;
482 533 padding: 0;
483 534 }
484 535
485 536 &.select2-result-unselectable > .select2-result-label {
486 537 margin: 0 8px;
487 538 }
488 539
489 540 }
490 541 }
491 542
492 543 ul.select2-result-sub {
493 544 margin: 0;
494 545 padding: 0;
495 546
496 547 li {
497 548 display: block;
498 549 margin: 0;
499 550 border-right: none;
500 551 line-height: 1em;
501 552 font-family: @text-light;
502 553 color: @grey2;
503 554 list-style-type: none;
504 555
505 556 &:hover {
506 557 background-color: @grey3;
507 558 }
508 559 }
509 560 }
510 561 }
511 562
512 563
513 564 #context-bar {
514 565 display: block;
515 566 margin: 0 auto 20px 0;
516 567 padding: 0 @header-padding;
517 568 background-color: @grey7;
518 569 border-bottom: 1px solid @grey5;
519 570
520 571 .clear {
521 572 clear: both;
522 573 }
523 574 }
524 575
525 576 ul#context-pages {
526 577 li {
527 578 list-style-type: none;
528 579
529 580 a {
530 581 color: @grey2;
531 582
532 583 &:hover {
533 584 color: @grey1;
534 585 }
535 586 }
536 587
537 588 &.active {
538 589 // special case, non-variable color
539 590 border-bottom: 2px solid @rcblue;
540 591
541 592 a {
542 593 color: @rcblue;
543 594 }
544 595 }
545 596 }
546 597 }
547 598
548 599 // PAGINATION
549 600
550 601 .pagination {
551 602 border: @border-thickness solid @grey5;
552 603 color: @grey2;
553 604 box-shadow: @button-shadow;
554 605
555 606 .current {
556 607 color: @grey4;
557 608 }
558 609 }
559 610
560 611 .dataTables_processing {
561 612 text-align: center;
562 613 font-size: 1.1em;
563 614 position: relative;
564 615 top: 95px;
565 616 }
566 617
567 618 .dataTables_paginate, .pagination-wh {
568 619 text-align: left;
569 620 display: inline-block;
570 621 border-left: 1px solid @grey5;
571 622 float: none;
572 623 overflow: hidden;
573 624 box-shadow: @button-shadow;
574 625
575 626 .paginate_button, .pager_curpage,
576 627 .pager_link, .pg-previous, .pg-next, .pager_dotdot {
577 628 display: inline-block;
578 629 padding: @menupadding/4 @menupadding;
579 630 border: 1px solid @grey5;
580 631 border-left: 0;
581 632 color: @grey2;
582 633 cursor: pointer;
583 634 float: left;
584 635
585 636 &:hover {
586 637 color: @rcdarkblue;
587 638 }
588 639 }
589 640
590 641 .paginate_button.disabled,
591 642 .disabled {
592 643 color: @grey3;
593 644 cursor: default;
594 645 opacity: 0.5;
595 646 }
596 647
597 648 .paginate_button.current, .pager_curpage {
598 649 background: @rcblue;
599 650 border-color: @rcblue;
600 651 color: @white;
601 652 }
602 653
603 654 .ellipsis {
604 655 display: inline-block;
605 656 text-align: left;
606 657 padding: @menupadding/4 @menupadding;
607 658 border: 1px solid @grey5;
608 659 border-left: 0;
609 660 float: left;
610 661 }
611 662 }
612 663
613 664 // SIDEBAR
614 665
615 666 .sidebar {
616 667 .block-left;
617 668 clear: left;
618 669 max-width: @sidebar-width;
619 670 margin-right: @sidebarpadding;
620 671 padding-right: @sidebarpadding;
621 672 font-family: @text-regular;
622 673 color: @grey1;
623 674
624 675 .nav-pills {
625 676 margin: 0;
626 677 }
627 678
628 679 .nav {
629 680 list-style: none;
630 681 padding: 0;
631 682
632 683 li {
633 684 padding-bottom: @menupadding;
634 685 line-height: 1em;
635 686 color: @grey4;
636 687 list-style-type: none;
637 688
638 689 &.active a {
639 690 color: @grey2;
640 691 }
641 692
642 693 a {
643 694 color: @grey4;
644 695 }
645 696 }
646 697
647 698 }
648 699 }
649 700
650 701 .main_filter_help_box {
651 702 padding: 7px 7px;
652 703 display: inline-block;
653 704 vertical-align: top;
654 705 background: inherit;
655 706 position: absolute;
656 707 right: 0;
657 708 top: 9px;
658 709 }
659 710
660 711 .main_filter_input_box {
661 712 display: inline-block;
662 713
663 714 .searchItems {
664 715 display:flex;
665 716 background: @black;
666 717 padding: 0px;
667 718 border-radius: 3px;
668 719 border: 1px solid @black;
669 720
670 721 a {
671 722 border: none !important;
672 723 }
673 724 }
674 725
675 726 .searchTag {
676 727 line-height: 28px;
677 728 padding: 0 5px;
678 729
679 730 .tag {
680 731 color: @grey5;
681 732 border-color: @grey2;
682 733 background: @grey1;
683 734 }
684 735 }
685 736
686 737 .searchTagFilter {
687 738 background-color: @black !important;
688 739 margin-right: 0;
689 740 }
690 741
691 742 .searchTagHelp {
692 743 background-color: @grey1 !important;
693 744 margin: 0;
694 745 }
695 746 .searchTagHelp:hover {
696 747 background-color: @grey1 !important;
697 748 }
698 749 .searchTagInput {
699 750 background-color: @grey1 !important;
700 751 margin-right: 0;
701 752 }
702 753 }
703 754
704 755 .main_filter_box {
705 756 margin: 9px 0 0 0;
706 757 }
707 758
708 759 #main_filter_help {
709 760 background: @grey1;
710 761 border: 1px solid black;
711 762 position: absolute;
712 763 white-space: pre;
713 764 z-index: 9999;
714 765 color: @nav-grey;
715 766 padding: 0 10px;
716 767 }
717 768
718 769 input {
719 770
720 771 &.main_filter_input {
721 772 padding: 5px 10px;
722 773 min-width: 340px;
723 774 color: @grey7;
724 775 background: @black;
725 776 min-height: 18px;
726 777 border: 0;
727 778
728 779 &:active {
729 780 color: @grey2 !important;
730 781 background: white !important;
731 782 }
732 783 &:focus {
733 784 color: @grey2 !important;
734 785 background: white !important;
735 786 }
736 787 }
737 788 }
738 789
739 790
740 791
741 792 .main_filter_input::placeholder {
742 793 color: @nav-grey;
743 794 opacity: 1;
744 795 }
745 796
746 797 .notice-box {
747 798 display:block !important;
748 799 padding: 9px 0 !important;
749 800 }
750 801
751 802 .menulabel-notice {
752 803 border: 1px solid @color5;
753 804 padding:7px 10px;
754 805 color: @color5;
755 806 }
@@ -1,145 +1,137 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 %if c.show_private:
6 6 ${_('Private Gists for user {}').format(c.rhodecode_user.username)}
7 7 %elif c.show_public:
8 8 ${_('Public Gists for user {}').format(c.rhodecode_user.username)}
9 9 %else:
10 10 ${_('Public Gists')}
11 11 %endif
12 12 %if c.rhodecode_name:
13 13 &middot; ${h.branding(c.rhodecode_name)}
14 14 %endif
15 15 </%def>
16 16
17 17 <%def name="breadcrumbs_links()"></%def>
18 18
19 19 <%def name="menu_bar_nav()">
20 20 ${self.menu_items(active='gists')}
21 21 </%def>
22 22
23 23 <%def name="main()">
24 24
25 25 <div class="box">
26 26 <div class="title">
27 27
28 28 <ul class="button-links">
29 29 % if c.is_super_admin:
30 30 <li class="btn ${('active' if c.active=='all' else '')}"><a href="${h.route_path('gists_show', _query={'all': 1})}">${_('All gists')}</a></li>
31 31 %endif
32 32 <li class="btn ${('active' if c.active=='public' else '')}"><a href="${h.route_path('gists_show')}">${_('All public')}</a></li>
33 33 %if c.rhodecode_user.username != h.DEFAULT_USER:
34 34 <li class="btn ${('active' if c.active=='my_all' else '')}"><a href="${h.route_path('gists_show', _query={'public':1, 'private': 1})}">${_('My gists')}</a></li>
35 35 <li class="btn ${('active' if c.active=='my_private' else '')}"><a href="${h.route_path('gists_show', _query={'private': 1})}">${_('My private')}</a></li>
36 36 <li class="btn ${('active' if c.active=='my_public' else '')}"><a href="${h.route_path('gists_show', _query={'public': 1})}">${_('My public')}</a></li>
37 37 %endif
38 38 </ul>
39 39
40 % if c.rhodecode_user.username != h.DEFAULT_USER:
41 <div class="pull-right">
42 <a class="btn btn-primary" href="${h.route_path('gists_new')}" >
43 ${_(u'Create New Gist')}
44 </a>
45 </div>
46 % endif
47
48 40 <div class="grid-quick-filter">
49 41 <ul class="grid-filter-box">
50 42 <li class="grid-filter-box-icon">
51 43 <i class="icon-search"></i>
52 44 </li>
53 45 <li class="grid-filter-box-input">
54 46 <input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
55 47 </li>
56 48 </ul>
57 49 </div>
58 50
59 51 </div>
60 52
61 53 <div class="main-content-full-width">
62 54 <div id="repos_list_wrap">
63 55 <table id="gist_list_table" class="display"></table>
64 56 </div>
65 57 </div>
66 58
67 59 </div>
68 60
69 61 <script type="text/javascript">
70 62 $(document).ready(function() {
71 63
72 64 var get_datatable_count = function(){
73 65 var api = $('#gist_list_table').dataTable().api();
74 66 $('#gists_count').text(api.page.info().recordsDisplay);
75 67 };
76 68
77 69
78 70 // custom filter that filters by access_id, description or author
79 71 $.fn.dataTable.ext.search.push(
80 72 function( settings, data, dataIndex ) {
81 73 var query = $('#q_filter').val();
82 74 var author = data[0].strip();
83 75 var access_id = data[2].strip();
84 76 var description = data[3].strip();
85 77
86 78 var query_str = (access_id + " " + author + " " + description).toLowerCase();
87 79
88 80 if(query_str.indexOf(query.toLowerCase()) !== -1){
89 81 return true;
90 82 }
91 83 return false;
92 84 }
93 85 );
94 86
95 87 // gists list
96 88 $('#gist_list_table').DataTable({
97 89 data: ${c.data|n},
98 90 dom: 'rtp',
99 91 pageLength: ${c.visual.dashboard_items},
100 92 order: [[ 4, "desc" ]],
101 93 columns: [
102 94 { data: {"_": "author",
103 95 "sort": "author_raw"}, title: "${_("Author")}", width: "250px", className: "td-user" },
104 96 { data: {"_": "type",
105 97 "sort": "type"}, title: "${_("Type")}", width: "70px", className: "td-tags" },
106 98 { data: {"_": "access_id",
107 99 "sort": "access_id"}, title: "${_("Name")}", width:"150px", className: "td-componentname" },
108 100 { data: {"_": "description",
109 101 "sort": "description"}, title: "${_("Description")}", width: "250px", className: "td-description" },
110 102 { data: {"_": "created_on",
111 103 "sort": "created_on_raw"}, title: "${_("Created on")}", className: "td-time" },
112 104 { data: {"_": "expires",
113 105 "sort": "expires"}, title: "${_("Expires")}", className: "td-exp" }
114 106 ],
115 107 language: {
116 108 paginate: DEFAULT_GRID_PAGINATION,
117 109 emptyTable: _gettext("No gists available yet.")
118 110 },
119 111 "initComplete": function( settings, json ) {
120 112 timeagoActivate();
121 113 get_datatable_count();
122 114 }
123 115 });
124 116
125 117 // update the counter when things change
126 118 $('#gist_list_table').on('draw.dt', function() {
127 119 timeagoActivate();
128 120 get_datatable_count();
129 121 });
130 122
131 123 // filter, filter both grids
132 124 $('#q_filter').on( 'keyup', function () {
133 125 var repo_api = $('#gist_list_table').dataTable().api();
134 126 repo_api
135 127 .draw();
136 128 });
137 129
138 130 // refilter table if page load via back button
139 131 $("#q_filter").trigger('keyup');
140 132
141 133 });
142 134
143 135 </script>
144 136 </%def>
145 137
@@ -1,118 +1,111 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="robots()">
5 5 %if c.gist.gist_type != 'public':
6 6 <meta name="robots" content="noindex, nofollow">
7 7 %else:
8 8 ${parent.robots()}
9 9 %endif
10 10 </%def>
11 11
12 12 <%def name="title()">
13 13 ${_('Gist')} &middot; ${c.gist.gist_access_id}
14 14 %if c.rhodecode_name:
15 15 &middot; ${h.branding(c.rhodecode_name)}
16 16 %endif
17 17 </%def>
18 18
19 19 <%def name="breadcrumbs_links()">
20 20 ${_('Gist')} &middot; ${c.gist.gist_access_id}
21 21 </%def>
22 22
23 23 <%def name="menu_bar_nav()">
24 24 ${self.menu_items(active='gists')}
25 25 </%def>
26 26
27 27 <%def name="main()">
28 28 <div class="box">
29 29 <!-- box / title -->
30 30 <div class="title">
31 31 ${self.breadcrumbs()}
32 %if c.rhodecode_user.username != h.DEFAULT_USER:
33 <ul class="links">
34 <li>
35 <a href="${h.route_path('gists_new')}" class="btn btn-primary">${_(u'Create New Gist')}</a>
36 </li>
37 </ul>
38 %endif
39 32 </div>
40 33
41 34 <div class="table">
42 35 <div id="files_data">
43 36 <div id="codeblock" class="codeblock">
44 37 <div class="code-header">
45 38 <div class="gist_url">
46 39 <code>
47 40 ${c.gist.gist_url()} <span class="icon-clipboard clipboard-action" data-clipboard-text="${c.gist.gist_url()}" title="${_('Copy the url')}"></span>
48 41 </code>
49 42 </div>
50 43 <div class="stats">
51 44 %if c.is_super_admin or c.gist.gist_owner == c.rhodecode_user.user_id:
52 45 <div class="remove_gist">
53 46 ${h.secure_form(h.route_path('gist_delete', gist_id=c.gist.gist_access_id), request=request)}
54 47 ${h.submit('remove_gist', _('Delete'),class_="btn btn-mini btn-danger",onclick="return confirm('"+_('Confirm to delete this Gist')+"');")}
55 48 ${h.end_form()}
56 49 </div>
57 50 %endif
58 51 <div class="buttons">
59 52 ## only owner should see that
60 53 <a href="#copySource" onclick="return false;" class="btn btn-mini icon-clipboard clipboard-action" data-clipboard-text="${c.files[0].content}">${_('Copy content')}</a>
61 54
62 55 %if c.is_super_admin or c.gist.gist_owner == c.rhodecode_user.user_id:
63 56 ${h.link_to(_('Edit'), h.route_path('gist_edit', gist_id=c.gist.gist_access_id), class_="btn btn-mini")}
64 57 %endif
65 58 ${h.link_to(_('Show as Raw'), h.route_path('gist_show_formatted', gist_id=c.gist.gist_access_id, revision='tip', format='raw'), class_="btn btn-mini")}
66 59 </div>
67 60 <div class="left" >
68 61 %if c.gist.gist_type != 'public':
69 62 <span class="tag tag-ok disabled">${_('Private Gist')}</span>
70 63 %endif
71 64 <span> ${c.gist.gist_description}</span>
72 65 <span>${_('Expires')}:
73 66 %if c.gist.gist_expires == -1:
74 67 ${_('never')}
75 68 %else:
76 69 ${h.age_component(h.time_to_utcdatetime(c.gist.gist_expires))}
77 70 %endif
78 71 </span>
79 72
80 73 </div>
81 74 </div>
82 75
83 76 <div class="author">
84 77 <div title="${h.tooltip(c.file_last_commit.author)}">
85 78 ${self.gravatar_with_user(c.file_last_commit.author, 16)} - ${_('created')} ${h.age_component(c.file_last_commit.date)}
86 79 </div>
87 80
88 81 </div>
89 82 <div class="commit">${h.urlify_commit_message(c.file_last_commit.message, None)}</div>
90 83 </div>
91 84
92 85 ## iterate over the files
93 86 % for file in c.files:
94 87 <% renderer = c.render and h.renderer_from_filename(file.path, exclude=['.txt', '.TXT'])%>
95 88 <!--
96 89 <div id="${h.FID('G', file.path)}" class="stats" >
97 90 <a href="${c.gist.gist_url()}">ΒΆ</a>
98 91 <b >${file.path}</b>
99 92 <div>
100 93 ${h.link_to(_('Show as raw'), h.route_path('gist_show_formatted_path', gist_id=c.gist.gist_access_id, revision=file.commit.raw_id, format='raw', f_path=file.path), class_="btn btn-mini")}
101 94 </div>
102 95 </div>
103 96 -->
104 97 <div class="code-body textarea text-area editor">
105 98 %if renderer:
106 99 ${h.render(file.content, renderer=renderer)}
107 100 %else:
108 101 ${h.pygmentize(file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
109 102 %endif
110 103 </div>
111 104 %endfor
112 105 </div>
113 106 </div>
114 107 </div>
115 108
116 109
117 110 </div>
118 111 </%def>
@@ -1,974 +1,1056 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_uid, _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_uid)}" 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 ## determine if we have "any" option available
275 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
276 has_actions = can_lock
277
274 278 %>
275 279 % if c.rhodecode_db_repo.archived:
276 280 <div class="alert alert-warning text-center">
277 281 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
278 282 </div>
279 283 % endif
280 284
281 285 <!--- REPO CONTEXT BAR -->
282 286 <div id="context-bar">
283 287 <div class="wrapper">
284 288
285 289 <div class="title">
286 290 ${self.repo_page_title(c.rhodecode_db_repo)}
287 291 </div>
288 292
289 293 <ul id="context-pages" class="navigation horizontal-list">
290 294 <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 295 <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 296 <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 297 <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 298
295 299 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
296 300 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
297 301 <li class="${is_active('showpullrequest')}">
298 302 <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 303 <div class="menulabel">
300 304 %if c.repository_pull_requests == 1:
301 305 ${_('Pull Request')} ${c.repository_pull_requests}
302 306 %else:
303 307 ${_('Pull Requests')} ${c.repository_pull_requests}
304 308 %endif
305 309 </div>
306 310 </a>
307 311 </li>
308 312 %endif
309 313
310 314 <li class="${is_active('artifacts')}"><a class="menulink" href="${h.route_path('repo_artifacts_list',repo_name=c.repo_name)}"><div class="menulabel">${_('Artifacts')}</div></a></li>
311 315
312 316 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
313 317 <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 318 %endif
315 319
316 ## determine if we have "any" option available
317 <%
318 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
319 has_actions = (c.rhodecode_user.username != h.DEFAULT_USER and c.rhodecode_db_repo.repo_type in ['git','hg'] ) or can_lock
320 %>
321 320 <li class="${is_active('options')}">
322 321 % if has_actions:
323 322 <a class="menulink dropdown">
324 323 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
325 324 </a>
326 325 <ul class="submenu">
327 <li><a href="${h.route_path('repo_fork_new',repo_name=c.repo_name)}">${_('Fork this repository')}</a></li>
328 <li><a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
329 326 %if can_lock:
330 327 %if c.rhodecode_db_repo.locked[0]:
331 328 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock Repository')}</a></li>
332 329 %else:
333 330 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock Repository')}</a></li>
334 331 %endif
335 332 %endif
336 333 </ul>
337 334 % else:
338 335 <a class="menulink disabled">
339 336 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
340 337 </a>
341 338 % endif
342 339 </li>
343 340
344 341 </ul>
345 342 </div>
346 343 <div class="clear"></div>
347 344 </div>
348 345
349 346 <!--- REPO END CONTEXT BAR -->
350 347
351 348 </%def>
352 349
353 350 <%def name="repo_group_page_title(repo_group_instance)">
354 351 <div class="title-content">
355 352 <div class="title-main">
356 353 ## Repository Group icon
357 354 <i class="icon-repo-group"></i>
358 355
359 356 ## repo name with group name
360 357 ${h.breadcrumb_repo_group_link(repo_group_instance)}
361 358 </div>
362 359
363 360 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
364 361 <div class="repo-group-desc discreet">
365 362 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
366 363 </div>
367 364
368 365 </div>
369 366 </%def>
370 367
368
371 369 <%def name="repo_group_menu(active=None)">
372 370 <%
373 371 def is_active(selected):
374 372 if selected == active:
375 373 return "active"
376 374
377 375 gr_name = c.repo_group.group_name if c.repo_group else None
378 376 # create repositories with write permission on group is set to true
379 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
380 377 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
381 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
382 378
383 379 %>
384 380
381
385 382 <!--- REPO GROUP CONTEXT BAR -->
386 383 <div id="context-bar">
387 384 <div class="wrapper">
388 385 <div class="title">
389 386 ${self.repo_group_page_title(c.repo_group)}
390 387 </div>
391 388
392 389 <ul id="context-pages" class="navigation horizontal-list">
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>
390 <li class="${is_active('home')}">
391 <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>
392 </li>
394 393 % if c.is_super_admin or group_admin:
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>
394 <li class="${is_active('settings')}">
395 <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>
396 </li>
396 397 % endif
397 ## determine if we have "any" option available
398 <%
399 can_create_repos = c.is_super_admin or group_admin or (group_write and create_on_write)
400 can_create_repo_groups = c.is_super_admin or group_admin
401 has_actions = can_create_repos or can_create_repo_groups
402 %>
403 <li class="${is_active('options')}">
404 % if has_actions:
405 <a class="menulink dropdown">
406 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
407 </a>
408 <ul class="submenu">
409 %if can_create_repos:
410 <li><a href="${h.route_path('repo_new',_query=dict(parent_group=c.repo_group.group_id))}">${_('Add Repository')}</a></li>
411 %endif
412 %if can_create_repo_groups:
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 %endif
415 </ul>
416 % else:
417 <a class="menulink disabled">
418 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
419 </a>
420 % endif
421 </li>
398
422 399 </ul>
423 400 </div>
424 401 <div class="clear"></div>
425 402 </div>
426 403
427 404 <!--- REPO GROUP CONTEXT BAR -->
428 405
429 406 </%def>
430 407
431 408
432 409 <%def name="usermenu(active=False)">
410 <%
411 not_anonymous = c.rhodecode_user.username != h.DEFAULT_USER
412
413 gr_name = c.repo_group.group_name if (hasattr(c, 'repo_group') and c.repo_group) else None
414 # create repositories with write permission on group is set to true
415
416 can_fork = c.is_super_admin or h.HasPermissionAny('hg.fork.repository')()
417 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
418 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
419 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
420
421 can_create_repos = c.is_super_admin or c.can_create_repo
422 can_create_repo_groups = c.is_super_admin or c.can_create_repo_group
423
424 can_create_repos_in_group = c.is_super_admin or group_admin or (group_write and create_on_write)
425 can_create_repo_groups_in_group = c.is_super_admin or group_admin
426 %>
427
428 % if not_anonymous:
429 <%
430 default_target_group = dict()
431 if c.rhodecode_user.personal_repo_group:
432 default_target_group = dict(parent_group=c.rhodecode_user.personal_repo_group.group_id)
433 %>
434
435 ## create action
436 <li>
437 <a href="#create-actions" onclick="return false;" class="menulink childs">
438 <i class="icon-plus-circled"></i>
439 </a>
440
441 <div class="action-menu submenu">
442
443 <ol>
444 ## scope of within a repository
445 % if hasattr(c, 'rhodecode_db_repo') and c.rhodecode_db_repo:
446 <li class="submenu-title">${_('This Repository')}</li>
447 <li>
448 <a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a>
449 </li>
450 % if can_fork:
451 <li>
452 <a href="${h.route_path('repo_fork_new',repo_name=c.repo_name,_query=default_target_group)}">${_('Fork this repository')}</a>
453 </li>
454 % endif
455 % endif
456
457 ## scope of within repository groups
458 % if hasattr(c, 'repo_group') and c.repo_group and (can_create_repos_in_group or can_create_repo_groups_in_group):
459 <li class="submenu-title">${_('This Repository Group')}</li>
460
461 % if can_create_repos_in_group:
462 <li>
463 <a href="${h.route_path('repo_new',_query=default_target_group)}">${_('New Repository')}</a>
464 </li>
465 % endif
466
467 % if can_create_repo_groups_in_group:
468 <li>
469 <a href="${h.route_path('repo_group_new',_query=default_target_group)}">${_(u'New Repository Group')}</a>
470 </li>
471 % endif
472 % endif
473
474 ## personal group
475 % if c.rhodecode_user.personal_repo_group:
476 <li class="submenu-title">Personal Group</li>
477
478 <li>
479 <a href="${h.route_path('repo_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}" >${_('New Repository')} </a>
480 </li>
481
482 <li>
483 <a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.rhodecode_user.personal_repo_group.group_id))}">${_('New Repository Group')} </a>
484 </li>
485 % endif
486
487 ## Global actions
488 <li class="submenu-title">RhodeCode</li>
489 % if can_create_repos:
490 <li>
491 <a href="${h.route_path('repo_new')}" >${_('New Repository')}</a>
492 </li>
493 % endif
494
495 % if can_create_repo_groups:
496 <li>
497 <a href="${h.route_path('repo_group_new')}" >${_(u'New Repository Group')}</a>
498 </li>
499 % endif
500
501 <li>
502 <a href="${h.route_path('gists_new')}">${_(u'New Gist')}</a>
503 </li>
504
505 </ol>
506
507 </div>
508 </li>
509
510 ## notifications
511 <li>
512 <a class="${('empty' if c.unread_notifications == 0 else '')}" href="${h.route_path('notifications_show_all')}">
513 ${c.unread_notifications}
514 </a>
515 </li>
516 % endif
517
433 518 ## USER MENU
434 519 <li id="quick_login_li" class="${'active' if active else ''}">
435 520 % if c.rhodecode_user.username == h.DEFAULT_USER:
436 521 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
437 522 ${gravatar(c.rhodecode_user.email, 20)}
438 523 <span class="user">
439 524 <span>${_('Sign in')}</span>
440 525 </span>
441 526 </a>
442 527 % else:
443 528 ## logged in user
444 529 <a id="quick_login_link" class="menulink childs">
445 530 ${gravatar(c.rhodecode_user.email, 20)}
446 531 <span class="user">
447 532 <span class="menu_link_user">${c.rhodecode_user.username}</span>
448 533 <div class="show_more"></div>
449 534 </span>
450 535 </a>
451 536 ## subnav with menu for logged in user
452 537 <div class="user-menu submenu">
453 538 <div id="quick_login">
454 539 %if c.rhodecode_user.username != h.DEFAULT_USER:
455 540 <div class="">
456 541 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
457 542 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
458 543 <div class="email">${c.rhodecode_user.email}</div>
459 544 </div>
460 545 <div class="">
461 546 <ol class="links">
462 547 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
463 548 % if c.rhodecode_user.personal_repo_group:
464 549 <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 550 % endif
466 551 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
467 552 ## bookmark-items
468 553 <li class="bookmark-items">
469 554 ${_('Bookmarks')}
470 555 <div class="pull-right">
471 556 <a href="${h.route_path('my_account_bookmarks')}">${_('Manage')}</a>
472 557 </div>
473 558 </li>
474 559 % if not c.bookmark_items:
475 560 <li>
476 561 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
477 562 </li>
478 563 % endif
479 564 % for item in c.bookmark_items:
480 565 <li>
481 566 % if item.repository:
482 567 <div>
483 568 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
484 569 <code>${item.position}</code>
485 570 % if item.repository.repo_type == 'hg':
486 571 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
487 572 % elif item.repository.repo_type == 'git':
488 573 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
489 574 % elif item.repository.repo_type == 'svn':
490 575 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
491 576 % endif
492 577 ${(item.title or h.shorter(item.repository.repo_name, 30))}
493 578 </a>
494 579 </div>
495 580 % elif item.repository_group:
496 581 <div>
497 582 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
498 583 <code>${item.position}</code>
499 584 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
500 585 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
501 586 </a>
502 587 </div>
503 588 % else:
504 589 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
505 590 <code>${item.position}</code>
506 591 ${item.title}
507 592 </a>
508 593 % endif
509 594 </li>
510 595 % endfor
511 596
512 597 <li class="logout">
513 598 ${h.secure_form(h.route_path('logout'), request=request)}
514 599 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
515 600 ${h.end_form()}
516 601 </li>
517 602 </ol>
518 603 </div>
519 604 %endif
520 605 </div>
521 606 </div>
522 ## unread counter
523 <div class="pill_container">
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 </div>
607
526 608 % endif
527 609 </li>
528 610 </%def>
529 611
530 612 <%def name="menu_items(active=None)">
531 613 <%
532 614 def is_active(selected):
533 615 if selected == active:
534 616 return "active"
535 617 return ""
536 618 %>
537 619
538 620 <ul id="quick" class="main_nav navigation horizontal-list">
539 621 ## notice box for important system messages
540 622 <li style="display: none">
541 623 <a class="notice-box" href="#openNotice" onclick="return false">
542 624 <div class="menulabel-notice" >
543 625 0
544 626 </div>
545 627 </a>
546 628 </li>
547 629
548 630 ## Main filter
549 631 <li>
550 632 <div class="menulabel main_filter_box">
551 633 <div class="main_filter_input_box">
552 634 <ul class="searchItems">
553 635
554 636 % if c.template_context['search_context']['repo_id']:
555 637 <li class="searchTag searchTagFilter searchTagHidable" >
556 638 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
557 639 <span class="tag">
558 640 This repo
559 641 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
560 642 </span>
561 643 ##</a>
562 644 </li>
563 645 % elif c.template_context['search_context']['repo_group_id']:
564 646 <li class="searchTag searchTagFilter searchTagHidable">
565 647 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
566 648 <span class="tag">
567 649 This group
568 650 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
569 651 </span>
570 652 ##</a>
571 653 </li>
572 654 % endif
573 655
574 656 <li class="searchTagInput">
575 657 <input class="main_filter_input" id="main_filter" size="25" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
576 658 </li>
577 659 <li class="searchTag searchTagHelp">
578 660 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
579 661 </li>
580 662 </ul>
581 663 </div>
582 664 </div>
583 665
584 666 <div id="main_filter_help" style="display: none">
585 667 - Use '/' key to quickly access this field.
586 668
587 669 - Enter a name of repository, or repository group for quick search.
588 670
589 671 - Prefix query to allow special search:
590 672
591 673 user:admin, to search for usernames, always global
592 674
593 675 user_group:devops, to search for user groups, always global
594 676
595 677 commit:efced4, to search for commits, scoped to repositories or groups
596 678
597 679 file:models.py, to search for file paths, scoped to repositories or groups
598 680
599 681 % if c.template_context['search_context']['repo_id']:
600 682 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 683 % elif c.template_context['search_context']['repo_group_id']:
602 684 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 685 % else:
604 686 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
605 687 % endif
606 688 </div>
607 689 </li>
608 690
609 691 ## ROOT MENU
610 692 <li class="${is_active('home')}">
611 693 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
612 694 <div class="menulabel">${_('Home')}</div>
613 695 </a>
614 696 </li>
615 697
616 698 %if c.rhodecode_user.username != h.DEFAULT_USER:
617 699 <li class="${is_active('journal')}">
618 700 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
619 701 <div class="menulabel">${_('Journal')}</div>
620 702 </a>
621 703 </li>
622 704 %else:
623 705 <li class="${is_active('journal')}">
624 706 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
625 707 <div class="menulabel">${_('Public journal')}</div>
626 708 </a>
627 709 </li>
628 710 %endif
629 711
630 712 <li class="${is_active('gists')}">
631 713 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
632 714 <div class="menulabel">${_('Gists')}</div>
633 715 </a>
634 716 </li>
635 717
636 718 % if c.is_super_admin or c.is_delegated_admin:
637 719 <li class="${is_active('admin')}">
638 720 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
639 721 <div class="menulabel">${_('Admin')} </div>
640 722 </a>
641 723 </li>
642 724 % endif
643 725
644 726 ## render extra user menu
645 727 ${usermenu(active=(active=='my_account'))}
646 728
647 729 % if c.debug_style:
648 730 <li>
649 731 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
650 732 <div class="menulabel">${_('[Style]')}</div>
651 733 </a>
652 734 </li>
653 735 % endif
654 736 </ul>
655 737
656 738 <script type="text/javascript">
657 739 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
658 740
659 741 var formatRepoResult = function(result, container, query, escapeMarkup) {
660 742 return function(data, escapeMarkup) {
661 743 if (!data.repo_id){
662 744 return data.text; // optgroup text Repositories
663 745 }
664 746
665 747 var tmpl = '';
666 748 var repoType = data['repo_type'];
667 749 var repoName = data['text'];
668 750
669 751 if(data && data.type == 'repo'){
670 752 if(repoType === 'hg'){
671 753 tmpl += '<i class="icon-hg"></i> ';
672 754 }
673 755 else if(repoType === 'git'){
674 756 tmpl += '<i class="icon-git"></i> ';
675 757 }
676 758 else if(repoType === 'svn'){
677 759 tmpl += '<i class="icon-svn"></i> ';
678 760 }
679 761 if(data['private']){
680 762 tmpl += '<i class="icon-lock" ></i> ';
681 763 }
682 764 else if(visualShowPublicIcon){
683 765 tmpl += '<i class="icon-unlock-alt"></i> ';
684 766 }
685 767 }
686 768 tmpl += escapeMarkup(repoName);
687 769 return tmpl;
688 770
689 771 }(result, escapeMarkup);
690 772 };
691 773
692 774 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
693 775 return function(data, escapeMarkup) {
694 776 if (!data.repo_group_id){
695 777 return data.text; // optgroup text Repositories
696 778 }
697 779
698 780 var tmpl = '';
699 781 var repoGroupName = data['text'];
700 782
701 783 if(data){
702 784
703 785 tmpl += '<i class="icon-repo-group"></i> ';
704 786
705 787 }
706 788 tmpl += escapeMarkup(repoGroupName);
707 789 return tmpl;
708 790
709 791 }(result, escapeMarkup);
710 792 };
711 793
712 794 var escapeRegExChars = function (value) {
713 795 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
714 796 };
715 797
716 798 var getRepoIcon = function(repo_type) {
717 799 if (repo_type === 'hg') {
718 800 return '<i class="icon-hg"></i> ';
719 801 }
720 802 else if (repo_type === 'git') {
721 803 return '<i class="icon-git"></i> ';
722 804 }
723 805 else if (repo_type === 'svn') {
724 806 return '<i class="icon-svn"></i> ';
725 807 }
726 808 return ''
727 809 };
728 810
729 811 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
730 812
731 813 if (value.split(':').length === 2) {
732 814 value = value.split(':')[1]
733 815 }
734 816
735 817 var searchType = data['type'];
736 818 var searchSubType = data['subtype'];
737 819 var valueDisplay = data['value_display'];
738 820
739 821 var pattern = '(' + escapeRegExChars(value) + ')';
740 822
741 823 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
742 824
743 825 // highlight match
744 826 if (searchType != 'text') {
745 827 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
746 828 }
747 829
748 830 var icon = '';
749 831
750 832 if (searchType === 'hint') {
751 833 icon += '<i class="icon-repo-group"></i> ';
752 834 }
753 835 // full text search/hints
754 836 else if (searchType === 'search') {
755 837 icon += '<i class="icon-more"></i> ';
756 838 if (searchSubType !== undefined && searchSubType == 'repo') {
757 839 valueDisplay += '<div class="pull-right tag">repository</div>';
758 840 }
759 841 else if (searchSubType !== undefined && searchSubType == 'repo_group') {
760 842 valueDisplay += '<div class="pull-right tag">repo group</div>';
761 843 }
762 844 }
763 845 // repository
764 846 else if (searchType === 'repo') {
765 847
766 848 var repoIcon = getRepoIcon(data['repo_type']);
767 849 icon += repoIcon;
768 850
769 851 if (data['private']) {
770 852 icon += '<i class="icon-lock" ></i> ';
771 853 }
772 854 else if (visualShowPublicIcon) {
773 855 icon += '<i class="icon-unlock-alt"></i> ';
774 856 }
775 857 }
776 858 // repository groups
777 859 else if (searchType === 'repo_group') {
778 860 icon += '<i class="icon-repo-group"></i> ';
779 861 }
780 862 // user group
781 863 else if (searchType === 'user_group') {
782 864 icon += '<i class="icon-group"></i> ';
783 865 }
784 866 // user
785 867 else if (searchType === 'user') {
786 868 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
787 869 }
788 870 // commit
789 871 else if (searchType === 'commit') {
790 872 var repo_data = data['repo_data'];
791 873 var repoIcon = getRepoIcon(repo_data['repository_type']);
792 874 if (repoIcon) {
793 875 icon += repoIcon;
794 876 } else {
795 877 icon += '<i class="icon-tag"></i>';
796 878 }
797 879 }
798 880 // file
799 881 else if (searchType === 'file') {
800 882 var repo_data = data['repo_data'];
801 883 var repoIcon = getRepoIcon(repo_data['repository_type']);
802 884 if (repoIcon) {
803 885 icon += repoIcon;
804 886 } else {
805 887 icon += '<i class="icon-tag"></i>';
806 888 }
807 889 }
808 890 // generic text
809 891 else if (searchType === 'text') {
810 892 icon = '';
811 893 }
812 894
813 895 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
814 896 return tmpl.format(icon, valueDisplay);
815 897 };
816 898
817 899 var handleSelect = function(element, suggestion) {
818 900 if (suggestion.type === "hint") {
819 901 // we skip action
820 902 $('#main_filter').focus();
821 903 }
822 904 else if (suggestion.type === "text") {
823 905 // we skip action
824 906 $('#main_filter').focus();
825 907
826 908 } else {
827 909 window.location = suggestion['url'];
828 910 }
829 911 };
830 912
831 913 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
832 914 if (queryLowerCase.split(':').length === 2) {
833 915 queryLowerCase = queryLowerCase.split(':')[1]
834 916 }
835 917 if (suggestion.type === "text") {
836 918 // special case we don't want to "skip" display for
837 919 return true
838 920 }
839 921 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
840 922 };
841 923
842 924 var cleanContext = {
843 925 repo_view_type: null,
844 926
845 927 repo_id: null,
846 928 repo_name: "",
847 929
848 930 repo_group_id: null,
849 931 repo_group_name: null
850 932 };
851 933 var removeGoToFilter = function () {
852 934 $('.searchTagHidable').hide();
853 935 $('#main_filter').autocomplete(
854 936 'setOptions', {params:{search_context: cleanContext}});
855 937 };
856 938
857 939 $('#main_filter').autocomplete({
858 940 serviceUrl: pyroutes.url('goto_switcher_data'),
859 941 params: {
860 942 "search_context": templateContext.search_context
861 943 },
862 944 minChars:2,
863 945 maxHeight:400,
864 946 deferRequestBy: 300, //miliseconds
865 947 tabDisabled: true,
866 948 autoSelectFirst: false,
867 949 containerClass: 'autocomplete-qfilter-suggestions',
868 950 formatResult: autocompleteMainFilterFormatResult,
869 951 lookupFilter: autocompleteMainFilterResult,
870 952 onSelect: function (element, suggestion) {
871 953 handleSelect(element, suggestion);
872 954 return false;
873 955 },
874 956 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
875 957 if (jqXHR !== 'abort') {
876 958 alert("Error during search.\nError code: {0}".format(textStatus));
877 959 window.location = '';
878 960 }
879 961 }
880 962 });
881 963
882 964 showMainFilterBox = function () {
883 965 $('#main_filter_help').toggle();
884 966 };
885 967
886 968 $('#main_filter').on('keydown.autocomplete', function (e) {
887 969
888 970 var BACKSPACE = 8;
889 971 var el = $(e.currentTarget);
890 972 if(e.which === BACKSPACE){
891 973 var inputVal = el.val();
892 974 if (inputVal === ""){
893 975 removeGoToFilter()
894 976 }
895 977 }
896 978 });
897 979
898 980 </script>
899 981 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
900 982 </%def>
901 983
902 984 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
903 985 <div class="modal-dialog">
904 986 <div class="modal-content">
905 987 <div class="modal-header">
906 988 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
907 989 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
908 990 </div>
909 991 <div class="modal-body">
910 992 <div class="block-left">
911 993 <table class="keyboard-mappings">
912 994 <tbody>
913 995 <tr>
914 996 <th></th>
915 997 <th>${_('Site-wide shortcuts')}</th>
916 998 </tr>
917 999 <%
918 1000 elems = [
919 1001 ('/', 'Use quick search box'),
920 1002 ('g h', 'Goto home page'),
921 1003 ('g g', 'Goto my private gists page'),
922 1004 ('g G', 'Goto my public gists page'),
923 1005 ('g 0-9', 'Goto bookmarked items from 0-9'),
924 1006 ('n r', 'New repository page'),
925 1007 ('n g', 'New gist page'),
926 1008 ]
927 1009 %>
928 1010 %for key, desc in elems:
929 1011 <tr>
930 1012 <td class="keys">
931 1013 <span class="key tag">${key}</span>
932 1014 </td>
933 1015 <td>${desc}</td>
934 1016 </tr>
935 1017 %endfor
936 1018 </tbody>
937 1019 </table>
938 1020 </div>
939 1021 <div class="block-left">
940 1022 <table class="keyboard-mappings">
941 1023 <tbody>
942 1024 <tr>
943 1025 <th></th>
944 1026 <th>${_('Repositories')}</th>
945 1027 </tr>
946 1028 <%
947 1029 elems = [
948 1030 ('g s', 'Goto summary page'),
949 1031 ('g c', 'Goto changelog page'),
950 1032 ('g f', 'Goto files page'),
951 1033 ('g F', 'Goto files page with file search activated'),
952 1034 ('g p', 'Goto pull requests page'),
953 1035 ('g o', 'Goto repository settings'),
954 1036 ('g O', 'Goto repository permissions settings'),
955 1037 ]
956 1038 %>
957 1039 %for key, desc in elems:
958 1040 <tr>
959 1041 <td class="keys">
960 1042 <span class="key tag">${key}</span>
961 1043 </td>
962 1044 <td>${desc}</td>
963 1045 </tr>
964 1046 %endfor
965 1047 </tbody>
966 1048 </table>
967 1049 </div>
968 1050 </div>
969 1051 <div class="modal-footer">
970 1052 </div>
971 1053 </div><!-- /.modal-content -->
972 1054 </div><!-- /.modal-dialog -->
973 1055 </div><!-- /.modal -->
974 1056
@@ -1,132 +1,119 b''
1 1 <%inherit file="/base/base.mako"/>
2 2
3 3
4 4 <%def name="menu_bar_subnav()">
5 5 % if c.repo_group:
6 6 ${self.repo_group_menu(active='home')}
7 7 % endif
8 8 </%def>
9 9
10 10
11 11 <%def name="main()">
12 12 <div class="box">
13 13 <!-- box / title -->
14 14 <div class="title">
15 %if c.rhodecode_user.username != h.DEFAULT_USER:
16 <div class="block-right">
17 %if not c.repo_group:
18 ## no repository group context here
19 %if c.is_super_admin or c.can_create_repo:
20 <a href="${h.route_path('repo_new')}" class="btn btn-small btn-success btn-primary">${_('Add Repository')}</a>
21 %endif
22 15
23 %if c.is_super_admin or c.can_create_repo_group:
24 <a href="${h.route_path('repo_group_new')}" class="btn btn-small btn-default">${_(u'Add Repository Group')}</a>
25 %endif
26 %endif
27 </div>
28 %endif
29 16 </div>
30 17 <!-- end box / title -->
31 18 <div class="table">
32 19 <div id="groups_list_wrap">
33 20 <table id="group_list_table" class="display" style="width: 100%"></table>
34 21 </div>
35 22 </div>
36 23
37 24 <div class="table">
38 25 <div id="repos_list_wrap">
39 26 <table id="repo_list_table" class="display" style="width: 100%"></table>
40 27 </div>
41 28 </div>
42 29
43 30 ## no repository groups and repos present, show something to the users
44 31 % if c.repo_groups_data == '[]' and c.repos_data == '[]':
45 32 <div class="table">
46 33 <h2 class="no-object-border">
47 34 ${_('No repositories or repositories groups exists here.')}
48 35 </h2>
49 36 </div>
50 37 % endif
51 38
52 39 </div>
53 40 <script>
54 41 $(document).ready(function() {
55 42
56 43 // repo group list
57 44 % if c.repo_groups_data != '[]':
58 45 $('#group_list_table').DataTable({
59 46 data: ${c.repo_groups_data|n},
60 47 dom: 'rtp',
61 48 pageLength: ${c.visual.dashboard_items},
62 49 order: [[ 0, "asc" ]],
63 50 columns: [
64 51 { data: {"_": "name",
65 52 "sort": "name_raw"}, title: "${_('Name')}", className: "truncate-wrap td-grid-name" },
66 53 { data: 'menu', "bSortable": false, className: "quick_repo_menu" },
67 54 { data: {"_": "desc",
68 55 "sort": "desc"}, title: "${_('Description')}", className: "td-description" },
69 56 { data: {"_": "last_change",
70 57 "sort": "last_change_raw",
71 58 "type": Number}, title: "${_('Last Change')}", className: "td-time" },
72 59 { data: {"_": "last_changeset",
73 60 "sort": "last_changeset_raw",
74 61 "type": Number}, title: "", className: "td-hash" },
75 62 { data: {"_": "owner",
76 63 "sort": "owner"}, title: "${_('Owner')}", className: "td-user" }
77 64 ],
78 65 language: {
79 66 paginate: DEFAULT_GRID_PAGINATION,
80 67 emptyTable: _gettext("No repository groups available yet.")
81 68 },
82 69 "drawCallback": function( settings, json ) {
83 70 timeagoActivate();
84 71 quick_repo_menu();
85 72 // hide pagination for single page
86 73 if (settings._iDisplayLength > settings.fnRecordsDisplay()) {
87 74 $(settings.nTableWrapper).find('.dataTables_paginate').hide();
88 75 }
89 76 }
90 77 });
91 78 % endif
92 79
93 80 // repo list
94 81 % if c.repos_data != '[]':
95 82 $('#repo_list_table').DataTable({
96 83 data: ${c.repos_data|n},
97 84 dom: 'rtp',
98 85 order: [[ 0, "asc" ]],
99 86 pageLength: ${c.visual.dashboard_items},
100 87 columns: [
101 88 { data: {"_": "name",
102 89 "sort": "name_raw"}, title: "${_('Name')}", className: "truncate-wrap td-grid-name" },
103 90 { data: 'menu', "bSortable": false, className: "quick_repo_menu" },
104 91 { data: {"_": "desc",
105 92 "sort": "desc"}, title: "${_('Description')}", className: "td-description" },
106 93 { data: {"_": "last_change",
107 94 "sort": "last_change_raw",
108 95 "type": Number}, title: "${_('Last Change')}", className: "td-time" },
109 96 { data: {"_": "last_changeset",
110 97 "sort": "last_changeset_raw",
111 98 "type": Number}, title: "${_('Commit')}", className: "td-hash" },
112 99 { data: {"_": "owner",
113 100 "sort": "owner"}, title: "${_('Owner')}", className: "td-user" }
114 101 ],
115 102 language: {
116 103 paginate: DEFAULT_GRID_PAGINATION,
117 104 emptyTable: _gettext("No repositories available yet.")
118 105 },
119 106 "drawCallback": function( settings, json ) {
120 107 timeagoActivate();
121 108 quick_repo_menu();
122 109 // hide pagination for single page
123 110 if (settings._iDisplayLength > settings.fnRecordsDisplay()) {
124 111 $(settings.nTableWrapper).find('.dataTables_paginate').hide();
125 112 }
126 113 }
127 114 });
128 115 % endif
129 116
130 117 });
131 118 </script>
132 119 </%def>
General Comments 0
You need to be logged in to leave comments. Login now