##// END OF EJS Templates
nav: disable options if there aren't any links inside
ergo -
r3719:17498c4b new-ui
parent child Browse files
Show More
@@ -1,755 +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 .menulink {
160 &.disabled {
161 color: @grey3;
162 cursor: default;
163 opacity: 0.5;
164 }
165 }
166
159 167 #quick_login {
160 168
161 169 li a {
162 170 padding: .5em 0;
163 171 border-bottom: none;
164 172 color: @grey2;
165 173
166 174 &:hover { color: @grey1; }
167 175 }
168 176 }
169 177
170 178 #quick_login_link {
171 179 display: inline-block;
172 180
173 181 .gravatar {
174 182 border: 1px solid @grey5;
175 183 }
176 184
177 185 .gravatar-login {
178 186 height: 20px;
179 187 width: 20px;
180 188 margin: -8px 0;
181 189 padding: 0;
182 190 }
183 191
184 192 &:hover .user {
185 193 color: @grey6;
186 194 }
187 195 }
188 196 }
189 197 .header .horizontal-list {
190 198
191 199 li {
192 200
193 201 &#quick_login_li {
194 202 padding-left: .5em;
195 203
196 204 &:hover #quick_login_link {
197 205 color: inherit;
198 206 }
199 207
200 208 .menu_link_user {
201 209 padding: 0 2px;
202 210 }
203 211 }
204 212 list-style-type: none;
205 213 }
206 214
207 215 > li {
208 216
209 217 a {
210 218 padding: 18px 0 12px 0;
211 219 color: @nav-grey;
212 220
213 221 &.menu_link_notifications {
214 222 padding: 1px 8px;
215 223 }
216 224 }
217 225
218 226 &:hover,
219 227 &.open,
220 228 &.active {
221 229 .pill_container a {
222 230 // don't select text for the pill container, it has it' own
223 231 // hover behaviour
224 232 color: @nav-grey;
225 233 }
226 234 }
227 235
228 236 &:hover,
229 237 &.open,
230 238 &.active {
231 239 a {
232 240 color: @grey6;
233 241 }
234 242 }
235 243
236 244 .select2-dropdown-open a {
237 245 color: @grey6;
238 246 }
239 247
240 248 .repo-switcher {
241 249 padding-left: 0;
242 250
243 251 .menulabel {
244 252 padding-left: 0;
245 253 }
246 254 }
247 255 }
248 256
249 257 li ul li {
250 258 background-color:@grey2;
251 259
252 260 a {
253 261 padding: .5em 0;
254 262 border-bottom: @border-thickness solid @border-default-color;
255 263 color: @grey6;
256 264 }
257 265
258 266 &:last-child a, &.last a{
259 267 border-bottom: none;
260 268 }
261 269
262 270 &:hover {
263 271 background-color: @grey3;
264 272 }
265 273 }
266 274
267 275 .submenu {
268 276 margin-top: 5px;
269 277 }
270 278 }
271 279
272 280 // SUBMENUS
273 281 .navigation .submenu {
274 282 display: none;
275 283 }
276 284
277 285 .navigation li.open {
278 286 .submenu {
279 287 display: block;
280 288 }
281 289 }
282 290
283 291 .navigation li:last-child .submenu {
284 292 right: auto;
285 293 left: 0;
286 294 border: 1px solid @grey5;
287 295 background: @white;
288 296 box-shadow: @dropdown-shadow;
289 297 }
290 298
291 299 .submenu {
292 300 position: absolute;
293 301 top: 100%;
294 302 left: 0;
295 303 min-width: 180px;
296 304 margin: 2px 0 0;
297 305 padding: 0;
298 306 text-align: left;
299 307 font-family: @text-light;
300 308 border-radius: @border-radius;
301 309 z-index: 20;
302 310
303 311 li {
304 312 display: block;
305 313 margin: 0;
306 314 padding: 0 .5em;
307 315 line-height: 1em;
308 316 color: @grey3;
309 317 background-color: @white;
310 318 list-style-type: none;
311 319
312 320 a {
313 321 display: block;
314 322 width: 100%;
315 323 padding: .5em 0;
316 324 border-right: none;
317 325 border-bottom: @border-thickness solid white;
318 326 color: @grey3;
319 327 }
320 328
321 329 ul {
322 330 display: none;
323 331 position: absolute;
324 332 top: 0;
325 333 right: 100%;
326 334 padding: 0;
327 335 z-index: 30;
328 336 }
329 337 &:hover {
330 338 background-color: @grey7;
331 339 -webkit-transition: background .3s;
332 340 -moz-transition: background .3s;
333 341 -o-transition: background .3s;
334 342 transition: background .3s;
335 343
336 344 ul {
337 345 display: block;
338 346 }
339 347 }
340 348 }
341 349
342 350 }
343 351
344 352
345 353
346 354
347 355 // repo dropdown
348 356 .quick_repo_menu {
349 357 width: 15px;
350 358 text-align: center;
351 359 position: relative;
352 360 cursor: pointer;
353 361
354 362 div {
355 363 overflow: visible !important;
356 364 }
357 365
358 366 &.sorting {
359 367 cursor: auto;
360 368 }
361 369
362 370 &:hover {
363 371 .menu_items_container {
364 372 position: absolute;
365 373 display: block;
366 374 }
367 375 .menu_items {
368 376 display: block;
369 377 }
370 378 }
371 379
372 380 i {
373 381 margin: 0;
374 382 color: @grey4;
375 383 }
376 384
377 385 .menu_items_container {
378 386 position: absolute;
379 387 top: 0;
380 388 left: 100%;
381 389 margin: 0;
382 390 padding: 0;
383 391 list-style: none;
384 392 background-color: @grey6;
385 393 z-index: 999;
386 394 text-align: left;
387 395
388 396 a {
389 397 color: @grey2;
390 398 }
391 399
392 400 ul.menu_items {
393 401 margin: 0;
394 402 padding: 0;
395 403 }
396 404
397 405 li {
398 406 margin: 0;
399 407 padding: 0;
400 408 line-height: 1em;
401 409 list-style-type: none;
402 410
403 411 a {
404 412 display: block;
405 413 height: 16px;
406 414 padding: 8px; //must add up to td height (28px)
407 415 width: 120px; // set width
408 416
409 417 &:hover {
410 418 background-color: @grey5;
411 419 -webkit-transition: background .3s;
412 420 -moz-transition: background .3s;
413 421 -o-transition: background .3s;
414 422 transition: background .3s;
415 423 }
416 424 }
417 425 }
418 426 }
419 427 }
420 428
421 429 // Header Repository Switcher
422 430 // Select2 Dropdown
423 431 #select2-drop.select2-drop.repo-switcher-dropdown {
424 432 width: auto !important;
425 433 margin-top: 5px;
426 434 padding: 1em 0;
427 435 text-align: left;
428 436 .border-radius-bottom(@border-radius);
429 437 border-color: transparent;
430 438 color: @grey6;
431 439 background-color: @grey2;
432 440
433 441 input {
434 442 min-width: 90%;
435 443 }
436 444
437 445 ul.select2-result-sub {
438 446
439 447 li {
440 448 line-height: 1em;
441 449
442 450 &:hover,
443 451 &.select2-highlighted {
444 452 background-color: @grey3;
445 453 }
446 454 }
447 455
448 456 &:before { content: none; }
449 457 }
450 458
451 459 ul.select2-results {
452 460 min-width: 200px;
453 461 margin: 0;
454 462 padding: 0;
455 463 list-style-type: none;
456 464 overflow-x: visible;
457 465 overflow-y: scroll;
458 466
459 467 li {
460 468 padding: 0 8px;
461 469 line-height: 1em;
462 470 color: @grey6;
463 471
464 472 &>.select2-result-label {
465 473 padding: 8px 0;
466 474 border-bottom: @border-thickness solid @grey3;
467 475 white-space: nowrap;
468 476 color: @grey5;
469 477 cursor: pointer;
470 478 }
471 479
472 480 &.select2-result-with-children {
473 481 margin: 0;
474 482 padding: 0;
475 483 }
476 484
477 485 &.select2-result-unselectable > .select2-result-label {
478 486 margin: 0 8px;
479 487 }
480 488
481 489 }
482 490 }
483 491
484 492 ul.select2-result-sub {
485 493 margin: 0;
486 494 padding: 0;
487 495
488 496 li {
489 497 display: block;
490 498 margin: 0;
491 499 border-right: none;
492 500 line-height: 1em;
493 501 font-family: @text-light;
494 502 color: @grey2;
495 503 list-style-type: none;
496 504
497 505 &:hover {
498 506 background-color: @grey3;
499 507 }
500 508 }
501 509 }
502 510 }
503 511
504 512
505 513 #context-bar {
506 514 display: block;
507 515 margin: 0 auto 20px 0;
508 516 padding: 0 @header-padding;
509 517 background-color: @grey7;
510 518 border-bottom: 1px solid @grey5;
511 519
512 520 .clear {
513 521 clear: both;
514 522 }
515 523 }
516 524
517 525 ul#context-pages {
518 526 li {
519 527 list-style-type: none;
520 528
521 529 a {
522 530 color: @grey2;
523 531
524 532 &:hover {
525 533 color: @grey1;
526 534 }
527 535 }
528 536
529 537 &.active {
530 538 // special case, non-variable color
531 539 border-bottom: 2px solid @rcblue;
532 540
533 541 a {
534 542 color: @rcblue;
535 543 }
536 544 }
537 545 }
538 546 }
539 547
540 548 // PAGINATION
541 549
542 550 .pagination {
543 551 border: @border-thickness solid @grey5;
544 552 color: @grey2;
545 553 box-shadow: @button-shadow;
546 554
547 555 .current {
548 556 color: @grey4;
549 557 }
550 558 }
551 559
552 560 .dataTables_processing {
553 561 text-align: center;
554 562 font-size: 1.1em;
555 563 position: relative;
556 564 top: 95px;
557 565 }
558 566
559 567 .dataTables_paginate, .pagination-wh {
560 568 text-align: left;
561 569 display: inline-block;
562 570 border-left: 1px solid @grey5;
563 571 float: none;
564 572 overflow: hidden;
565 573 box-shadow: @button-shadow;
566 574
567 575 .paginate_button, .pager_curpage,
568 576 .pager_link, .pg-previous, .pg-next, .pager_dotdot {
569 577 display: inline-block;
570 578 padding: @menupadding/4 @menupadding;
571 579 border: 1px solid @grey5;
572 580 border-left: 0;
573 581 color: @grey2;
574 582 cursor: pointer;
575 583 float: left;
576 584
577 585 &:hover {
578 586 color: @rcdarkblue;
579 587 }
580 588 }
581 589
582 590 .paginate_button.disabled,
583 591 .disabled {
584 592 color: @grey3;
585 593 cursor: default;
586 594 opacity: 0.5;
587 595 }
588 596
589 597 .paginate_button.current, .pager_curpage {
590 598 background: @rcblue;
591 599 border-color: @rcblue;
592 600 color: @white;
593 601 }
594 602
595 603 .ellipsis {
596 604 display: inline-block;
597 605 text-align: left;
598 606 padding: @menupadding/4 @menupadding;
599 607 border: 1px solid @grey5;
600 608 border-left: 0;
601 609 float: left;
602 610 }
603 611 }
604 612
605 613 // SIDEBAR
606 614
607 615 .sidebar {
608 616 .block-left;
609 617 clear: left;
610 618 max-width: @sidebar-width;
611 619 margin-right: @sidebarpadding;
612 620 padding-right: @sidebarpadding;
613 621 font-family: @text-regular;
614 622 color: @grey1;
615 623
616 624 &#graph_nodes {
617 625 clear:both;
618 626 width: auto;
619 627 margin-left: -100px;
620 628 padding: 0;
621 629 border: none;
622 630 }
623 631
624 632 .nav-pills {
625 633 margin: 0;
626 634 }
627 635
628 636 .nav {
629 637 list-style: none;
630 638 padding: 0;
631 639
632 640 li {
633 641 padding-bottom: @menupadding;
634 642 line-height: 1em;
635 643 color: @grey4;
636 644 list-style-type: none;
637 645
638 646 &.active a {
639 647 color: @grey2;
640 648 }
641 649
642 650 a {
643 651 color: @grey4;
644 652 }
645 653 }
646 654
647 655 }
648 656 }
649 657
650 658 .main_filter_help_box {
651 659 padding: 7px 7px;
652 660 display: inline-block;
653 661 vertical-align: top;
654 662 background: inherit;
655 663 position: absolute;
656 664 right: 0;
657 665 top: 9px;
658 666 }
659 667
660 668 .main_filter_input_box {
661 669 display: inline-block;
662 670
663 671 .searchItems {
664 672 display:flex;
665 673 background: @black;
666 674 padding: 0px;
667 675 border-radius: 3px;
668 676 border: 1px solid @black;
669 677
670 678 a {
671 679 border: none !important;
672 680 }
673 681 }
674 682
675 683 .searchTag {
676 684 line-height: 28px;
677 685 padding: 0 5px;
678 686
679 687 .tag {
680 688 color: @grey5;
681 689 border-color: @grey2;
682 690 background: @grey1;
683 691 }
684 692 }
685 693
686 694 .searchTagFilter {
687 695 background-color: @black !important;
688 696 margin-right: 0;
689 697 }
690 698
691 699 .searchTagHelp {
692 700 background-color: @grey1 !important;
693 701 margin: 0;
694 702 }
695 703 .searchTagHelp:hover {
696 704 background-color: @grey1 !important;
697 705 }
698 706 .searchTagInput {
699 707 background-color: @grey1 !important;
700 708 margin-right: 0;
701 709 }
702 710 }
703 711
704 712 .main_filter_box {
705 713 margin: 9px 0 0 0;
706 714 }
707 715
708 716 #main_filter_help {
709 717 background: @grey1;
710 718 border: 1px solid black;
711 719 position: absolute;
712 720 white-space: pre;
713 721 z-index: 9999;
714 722 color: @nav-grey;
715 723 padding: 0 10px;
716 724 }
717 725
718 726 input {
719 727
720 728 &.main_filter_input {
721 729 padding: 5px 10px;
722 730 min-width: 260px;
723 731 color: @grey7;
724 732 background: @black;
725 733 min-height: 18px;
726 734 border: 0;
727 735
728 736 &:active {
729 737 color: @grey2 !important;
730 738 background: white !important;
731 739 }
732 740 &:focus {
733 741 color: @grey2 !important;
734 742 background: white !important;
735 743 }
736 744 }
737 745 }
738 746
739 747
740 748
741 749 .main_filter_input::placeholder {
742 750 color: @nav-grey;
743 751 opacity: 1;
744 752 }
745 753
746 754 .notice-box {
747 755 display:block !important;
748 756 padding: 9px 0 !important;
749 757 }
750 758
751 759 .menulabel-notice {
752 760 border: 1px solid @color5;
753 761 padding:7px 10px;
754 762 color: @color5;
755 763 }
@@ -1,963 +1,965 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
276 276 <!--- REPO CONTEXT BAR -->
277 277 <div id="context-bar">
278 278 <div class="wrapper">
279 279
280 280 <div class="title">
281 281 ${self.repo_page_title(c.rhodecode_db_repo)}
282 282 </div>
283 283
284 284 <ul id="context-pages" class="navigation horizontal-list">
285 285 <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>
286 286 <li class="${is_active('changelog')}"><a class="menulink" href="${h.route_path('repo_changelog', repo_name=c.repo_name)}"><div class="menulabel">${_('Changelog')}</div></a></li>
287 287 <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>
288 288 <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>
289 289
290 290 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
291 291 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
292 292 <li class="${is_active('showpullrequest')}">
293 293 <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)}">
294 294 <div class="menulabel">
295 295 %if c.repository_pull_requests == 1:
296 296 ${c.repository_pull_requests} ${_('Pull Request')}
297 297 %else:
298 298 ${c.repository_pull_requests} ${_('Pull Requests')}
299 299 %endif
300 300 </div>
301 301 </a>
302 302 </li>
303 303 %endif
304 304
305 305 <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>
306 306
307 307 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
308 308 <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>
309 309 %endif
310 310
311 ## determine if we have "any" option available
312 <%
313 can_lock = h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking
314 has_actions = (c.rhodecode_user.username != h.DEFAULT_USER and c.rhodecode_db_repo.repo_type in ['git','hg'] ) or can_lock
315 %>
311 316 <li class="${is_active('options')}">
312 <a class="menulink dropdown">
313 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
314 </a>
315 <ul class="submenu">
317 % if has_actions:
318 <a class="menulink dropdown">
319 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
320 </a>
321 <ul class="submenu">
322 <li><a href="${h.route_path('repo_fork_new',repo_name=c.repo_name)}">${_('Fork this repository')}</a></li>
323 <li><a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
324 %if can_lock:
325 %if c.rhodecode_db_repo.locked[0]:
326 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock Repository')}</a></li>
327 %else:
328 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock Repository')}</a></li>
329 %endif
330 %endif
331 </ul>
332 % else:
333 <a class="menulink disabled">
334 <div class="menulabel">${_('Options')}<div class="show_more"></div></div>
335 </a>
336 % endif
337 </li>
316 338
317 %if c.rhodecode_db_repo.fork:
318 <li>
319 <a title="${h.tooltip(_('Compare fork with %s' % c.rhodecode_db_repo.fork.repo_name))}"
320 href="${h.route_path('repo_compare',
321 repo_name=c.rhodecode_db_repo.fork.repo_name,
322 source_ref_type=c.rhodecode_db_repo.landing_rev[0],
323 source_ref=c.rhodecode_db_repo.landing_rev[1],
324 target_repo=c.repo_name,target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],
325 target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1],
326 _query=dict(merge=1))}"
327 >
328 ${_('Compare fork')}
329 </a>
330 </li>
331 %endif
332
333 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
334 %if c.rhodecode_db_repo.locked[0]:
335 <li><a class="locking_del" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Unlock')}</a></li>
336 %else:
337 <li><a class="locking_add" href="${h.route_path('repo_edit_toggle_locking',repo_name=c.repo_name)}">${_('Lock')}</a></li>
338 %endif
339 %endif
340 %if c.rhodecode_user.username != h.DEFAULT_USER:
341 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
342 <li><a href="${h.route_path('repo_fork_new',repo_name=c.repo_name)}">${_('Fork')}</a></li>
343 <li><a href="${h.route_path('pullrequest_new',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
344 %endif
345 %endif
346 </ul>
347 </li>
348 339 </ul>
349 340 </div>
350 341 <div class="clear"></div>
351 342 </div>
352 343 % if c.rhodecode_db_repo.archived:
353 344 <div class="alert alert-warning text-center">
354 345 <strong>${_('This repository has been archived. It is now read-only.')}</strong>
355 346 </div>
356 347 % endif
357 348 <!--- REPO END CONTEXT BAR -->
358 349
359 350 </%def>
360 351
361 352 <%def name="repo_group_page_title(repo_group_instance)">
362 353 <div class="title-content">
363 354 <div class="title-main">
364 355 ## Repository Group icon
365 356 <i class="icon-repo-group"></i>
366 357
367 358 ## repo name with group name
368 359 ${h.breadcrumb_repo_group_link(repo_group_instance)}
369 360 </div>
370 361
371 362 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
372 363 <div class="repo-group-desc discreet">
373 364 ${dt.repo_group_desc(repo_group_instance.description_safe, repo_group_instance.personal, c.visual.stylify_metatags)}
374 365 </div>
375 366
376 367 </div>
377 368 </%def>
378 369
379 370 <%def name="repo_group_menu(active=None)">
380 371 <%
381 372 def is_active(selected):
382 373 if selected == active:
383 374 return "active"
384 375
385 376 gr_name = c.repo_group.group_name if c.repo_group else None
386 377 # create repositories with write permission on group is set to true
387 378 create_on_write = h.HasPermissionAny('hg.create.write_on_repogroup.true')()
388 379 group_admin = h.HasRepoGroupPermissionAny('group.admin')(gr_name, 'group admin index page')
389 380 group_write = h.HasRepoGroupPermissionAny('group.write')(gr_name, 'can write into group index page')
390 381
391 382 %>
392 383
393 384 <!--- REPO GROUP CONTEXT BAR -->
394 385 <div id="context-bar">
395 386 <div class="wrapper">
396 387 <div class="title">
397 388 ${self.repo_group_page_title(c.repo_group)}
398 389 </div>
399 390
400 391 <ul id="context-pages" class="navigation horizontal-list">
401 392 <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>
402 393 % if c.is_super_admin or group_admin:
403 394 <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>
404 395 % endif
405
396 ## determine if we have "any" option available
397 <%
398 can_create_repos = c.is_super_admin or group_admin or (group_write and create_on_write)
399 can_create_repo_groups = c.is_super_admin or group_admin
400 has_actions = can_create_repos or can_create_repo_groups
401 %>
406 402 <li class="${is_active('options')}">
407 <a class="menulink dropdown">
403 % if has_actions:
404 <a class="menulink dropdown">
408 405 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
409 </a>
410 <ul class="submenu">
411 %if c.is_super_admin or group_admin or (group_write and create_on_write):
406 </a>
407 <ul class="submenu">
408 %if can_create_repos:
412 409 <li><a href="${h.route_path('repo_new',_query=dict(parent_group=c.repo_group.group_id))}">${_('Add Repository')}</a></li>
413 410 %endif
414 %if c.is_super_admin or group_admin:
411 %if can_create_repo_groups:
415 412 <li><a href="${h.route_path('repo_group_new',_query=dict(parent_group=c.repo_group.group_id))}">${_(u'Add Repository Group')}</a></li>
416 413 %endif
417 </ul>
414 </ul>
415 % else:
416 <a class="menulink disabled">
417 <div class="menulabel">${_('Options')} <div class="show_more"></div></div>
418 </a>
419 % endif
418 420 </li>
419 421 </ul>
420 422 </div>
421 423 <div class="clear"></div>
422 424 </div>
423 425
424 426 <!--- REPO GROUP CONTEXT BAR -->
425 427
426 428 </%def>
427 429
428 430
429 431 <%def name="usermenu(active=False)">
430 432 ## USER MENU
431 433 <li id="quick_login_li" class="${'active' if active else ''}">
432 434 % if c.rhodecode_user.username == h.DEFAULT_USER:
433 435 <a id="quick_login_link" class="menulink childs" href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">
434 436 ${gravatar(c.rhodecode_user.email, 20)}
435 437 <span class="user">
436 438 <span>${_('Sign in')}</span>
437 439 </span>
438 440 </a>
439 441 % else:
440 442 ## logged in user
441 443 <a id="quick_login_link" class="menulink childs">
442 444 ${gravatar(c.rhodecode_user.email, 20)}
443 445 <span class="user">
444 446 <span class="menu_link_user">${c.rhodecode_user.username}</span>
445 447 <div class="show_more"></div>
446 448 </span>
447 449 </a>
448 450 ## subnav with menu for logged in user
449 451 <div class="user-menu submenu">
450 452 <div id="quick_login">
451 453 %if c.rhodecode_user.username != h.DEFAULT_USER:
452 454 <div class="">
453 455 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
454 456 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
455 457 <div class="email">${c.rhodecode_user.email}</div>
456 458 </div>
457 459 <div class="">
458 460 <ol class="links">
459 461 <li>${h.link_to(_(u'My account'),h.route_path('my_account_profile'))}</li>
460 462 % if c.rhodecode_user.personal_repo_group:
461 463 <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>
462 464 % endif
463 465 <li>${h.link_to(_(u'Pull Requests'), h.route_path('my_account_pullrequests'))}</li>
464 466 ## bookmark-items
465 467 <li class="bookmark-items">
466 468 ${_('Bookmarks')}
467 469 <div class="pull-right">
468 470 <a href="${h.route_path('my_account_bookmarks')}">${_('Manage')}</a>
469 471 </div>
470 472 </li>
471 473 % if not c.bookmark_items:
472 474 <li>
473 475 <a href="${h.route_path('my_account_bookmarks')}">${_('No Bookmarks yet.')}</a>
474 476 </li>
475 477 % endif
476 478 % for item in c.bookmark_items:
477 479 <li>
478 480 % if item.repository:
479 481 <div>
480 482 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
481 483 <code>${item.position}</code>
482 484 % if item.repository.repo_type == 'hg':
483 485 <i class="icon-hg" title="${_('Repository')}" style="font-size: 16px"></i>
484 486 % elif item.repository.repo_type == 'git':
485 487 <i class="icon-git" title="${_('Repository')}" style="font-size: 16px"></i>
486 488 % elif item.repository.repo_type == 'svn':
487 489 <i class="icon-svn" title="${_('Repository')}" style="font-size: 16px"></i>
488 490 % endif
489 491 ${(item.title or h.shorter(item.repository.repo_name, 30))}
490 492 </a>
491 493 </div>
492 494 % elif item.repository_group:
493 495 <div>
494 496 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
495 497 <code>${item.position}</code>
496 498 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
497 499 ${(item.title or h.shorter(item.repository_group.group_name, 30))}
498 500 </a>
499 501 </div>
500 502 % else:
501 503 <a class="bookmark-item" href="${h.route_path('my_account_goto_bookmark', bookmark_id=item.position)}">
502 504 <code>${item.position}</code>
503 505 ${item.title}
504 506 </a>
505 507 % endif
506 508 </li>
507 509 % endfor
508 510
509 511 <li class="logout">
510 512 ${h.secure_form(h.route_path('logout'), request=request)}
511 513 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
512 514 ${h.end_form()}
513 515 </li>
514 516 </ol>
515 517 </div>
516 518 %endif
517 519 </div>
518 520 </div>
519 521 ## unread counter
520 522 <div class="pill_container">
521 523 <a class="menu_link_notifications ${'empty' if c.unread_notifications == 0 else ''}" href="${h.route_path('notifications_show_all')}">${c.unread_notifications}</a>
522 524 </div>
523 525 % endif
524 526 </li>
525 527 </%def>
526 528
527 529 <%def name="menu_items(active=None)">
528 530 <%
529 531 def is_active(selected):
530 532 if selected == active:
531 533 return "active"
532 534 return ""
533 535 %>
534 536
535 537 <ul id="quick" class="main_nav navigation horizontal-list">
536 538 ## notice box for important system messages
537 539 <li style="display: none">
538 540 <a class="notice-box" href="#openNotice" onclick="showNoticeBox(); return false">
539 541 <div class="menulabel-notice" >
540 542 0
541 543 </div>
542 544 </a>
543 545 </li>
544 546
545 547 ## Main filter
546 548 <li>
547 549 <div class="menulabel main_filter_box">
548 550 <div class="main_filter_input_box">
549 551 <ul class="searchItems">
550 552
551 553 % if c.template_context['search_context']['repo_id']:
552 554 <li class="searchTag searchTagFilter searchTagHidable" >
553 555 ##<a href="${h.route_path('search_repo',repo_name=c.template_context['search_context']['repo_name'])}">
554 556 <span class="tag">
555 557 This repo
556 558 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
557 559 </span>
558 560 ##</a>
559 561 </li>
560 562 % elif c.template_context['search_context']['repo_group_id']:
561 563 <li class="searchTag searchTagFilter searchTagHidable">
562 564 ##<a href="${h.route_path('search_repo_group',repo_group_name=c.template_context['search_context']['repo_group_name'])}">
563 565 <span class="tag">
564 566 This group
565 567 <a href="#removeGoToFilter" onclick="removeGoToFilter(); return false"><i class="icon-cancel-circled"></i></a>
566 568 </span>
567 569 ##</a>
568 570 </li>
569 571 % endif
570 572
571 573 <li class="searchTagInput">
572 574 <input class="main_filter_input" id="main_filter" size="15" type="text" name="main_filter" placeholder="${_('search / go to...')}" value="" />
573 575 </li>
574 576 <li class="searchTag searchTagHelp">
575 577 <a href="#showFilterHelp" onclick="showMainFilterBox(); return false">?</a>
576 578 </li>
577 579 </ul>
578 580 </div>
579 581 </div>
580 582
581 583 <div id="main_filter_help" style="display: none">
582 584 - Use '/' key to quickly access this field.
583 585
584 586 - Enter a name of repository, or repository group for quick search.
585 587
586 588 - Prefix query to allow special search:
587 589
588 590 user:admin, to search for usernames, always global
589 591
590 592 user_group:devops, to search for user groups, always global
591 593
592 594 commit:efced4, to search for commits, scoped to repositories or groups
593 595
594 596 file:models.py, to search for file paths, scoped to repositories or groups
595 597
596 598 % if c.template_context['search_context']['repo_id']:
597 599 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>
598 600 % elif c.template_context['search_context']['repo_group_id']:
599 601 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>
600 602 % else:
601 603 For advanced full text search visit: <a href="${h.route_path('search')}">global search</a>
602 604 % endif
603 605 </div>
604 606 </li>
605 607
606 608 ## ROOT MENU
607 609 <li class="${is_active('home')}">
608 610 <a class="menulink" title="${_('Home')}" href="${h.route_path('home')}">
609 611 <div class="menulabel">${_('Home')}</div>
610 612 </a>
611 613 </li>
612 614
613 615 %if c.rhodecode_user.username != h.DEFAULT_USER:
614 616 <li class="${is_active('journal')}">
615 617 <a class="menulink" title="${_('Show activity journal')}" href="${h.route_path('journal')}">
616 618 <div class="menulabel">${_('Journal')}</div>
617 619 </a>
618 620 </li>
619 621 %else:
620 622 <li class="${is_active('journal')}">
621 623 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.route_path('journal_public')}">
622 624 <div class="menulabel">${_('Public journal')}</div>
623 625 </a>
624 626 </li>
625 627 %endif
626 628
627 629 <li class="${is_active('gists')}">
628 630 <a class="menulink childs" title="${_('Show Gists')}" href="${h.route_path('gists_show')}">
629 631 <div class="menulabel">${_('Gists')}</div>
630 632 </a>
631 633 </li>
632 634
633 635 % if c.is_super_admin or c.is_delegated_admin:
634 636 <li class="${is_active('admin')}">
635 637 <a class="menulink childs" title="${_('Admin settings')}" href="${h.route_path('admin_home')}">
636 638 <div class="menulabel">${_('Admin')} </div>
637 639 </a>
638 640 </li>
639 641 % endif
640 642
641 643 ## render extra user menu
642 644 ${usermenu(active=(active=='my_account'))}
643 645
644 646 % if c.debug_style:
645 647 <li>
646 648 <a class="menulink" title="${_('Style')}" href="${h.route_path('debug_style_home')}">
647 649 <div class="menulabel">${_('[Style]')}</div>
648 650 </a>
649 651 </li>
650 652 % endif
651 653 </ul>
652 654
653 655 <script type="text/javascript">
654 656 var visualShowPublicIcon = "${c.visual.show_public_icon}" == "True";
655 657
656 658 var formatRepoResult = function(result, container, query, escapeMarkup) {
657 659 return function(data, escapeMarkup) {
658 660 if (!data.repo_id){
659 661 return data.text; // optgroup text Repositories
660 662 }
661 663
662 664 var tmpl = '';
663 665 var repoType = data['repo_type'];
664 666 var repoName = data['text'];
665 667
666 668 if(data && data.type == 'repo'){
667 669 if(repoType === 'hg'){
668 670 tmpl += '<i class="icon-hg"></i> ';
669 671 }
670 672 else if(repoType === 'git'){
671 673 tmpl += '<i class="icon-git"></i> ';
672 674 }
673 675 else if(repoType === 'svn'){
674 676 tmpl += '<i class="icon-svn"></i> ';
675 677 }
676 678 if(data['private']){
677 679 tmpl += '<i class="icon-lock" ></i> ';
678 680 }
679 681 else if(visualShowPublicIcon){
680 682 tmpl += '<i class="icon-unlock-alt"></i> ';
681 683 }
682 684 }
683 685 tmpl += escapeMarkup(repoName);
684 686 return tmpl;
685 687
686 688 }(result, escapeMarkup);
687 689 };
688 690
689 691 var formatRepoGroupResult = function(result, container, query, escapeMarkup) {
690 692 return function(data, escapeMarkup) {
691 693 if (!data.repo_group_id){
692 694 return data.text; // optgroup text Repositories
693 695 }
694 696
695 697 var tmpl = '';
696 698 var repoGroupName = data['text'];
697 699
698 700 if(data){
699 701
700 702 tmpl += '<i class="icon-repo-group"></i> ';
701 703
702 704 }
703 705 tmpl += escapeMarkup(repoGroupName);
704 706 return tmpl;
705 707
706 708 }(result, escapeMarkup);
707 709 };
708 710
709 711 var escapeRegExChars = function (value) {
710 712 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
711 713 };
712 714
713 715 var getRepoIcon = function(repo_type) {
714 716 if (repo_type === 'hg') {
715 717 return '<i class="icon-hg"></i> ';
716 718 }
717 719 else if (repo_type === 'git') {
718 720 return '<i class="icon-git"></i> ';
719 721 }
720 722 else if (repo_type === 'svn') {
721 723 return '<i class="icon-svn"></i> ';
722 724 }
723 725 return ''
724 726 };
725 727
726 728 var autocompleteMainFilterFormatResult = function (data, value, org_formatter) {
727 729
728 730 if (value.split(':').length === 2) {
729 731 value = value.split(':')[1]
730 732 }
731 733
732 734 var searchType = data['type'];
733 735 var valueDisplay = data['value_display'];
734 736
735 737 var pattern = '(' + escapeRegExChars(value) + ')';
736 738
737 739 valueDisplay = Select2.util.escapeMarkup(valueDisplay);
738 740
739 741 // highlight match
740 742 if (searchType != 'text') {
741 743 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
742 744 }
743 745
744 746 var icon = '';
745 747
746 748 if (searchType === 'hint') {
747 749 icon += '<i class="icon-repo-group"></i> ';
748 750 }
749 751 // full text search
750 752 else if (searchType === 'search') {
751 753 icon += '<i class="icon-more"></i> ';
752 754 }
753 755 // repository
754 756 else if (searchType === 'repo') {
755 757
756 758 var repoIcon = getRepoIcon(data['repo_type']);
757 759 icon += repoIcon;
758 760
759 761 if (data['private']) {
760 762 icon += '<i class="icon-lock" ></i> ';
761 763 }
762 764 else if (visualShowPublicIcon) {
763 765 icon += '<i class="icon-unlock-alt"></i> ';
764 766 }
765 767 }
766 768 // repository groups
767 769 else if (searchType === 'repo_group') {
768 770 icon += '<i class="icon-repo-group"></i> ';
769 771 }
770 772 // user group
771 773 else if (searchType === 'user_group') {
772 774 icon += '<i class="icon-group"></i> ';
773 775 }
774 776 // user
775 777 else if (searchType === 'user') {
776 778 icon += '<img class="gravatar" src="{0}"/>'.format(data['icon_link']);
777 779 }
778 780 // commit
779 781 else if (searchType === 'commit') {
780 782 var repo_data = data['repo_data'];
781 783 var repoIcon = getRepoIcon(repo_data['repository_type']);
782 784 if (repoIcon) {
783 785 icon += repoIcon;
784 786 } else {
785 787 icon += '<i class="icon-tag"></i>';
786 788 }
787 789 }
788 790 // file
789 791 else if (searchType === 'file') {
790 792 var repo_data = data['repo_data'];
791 793 var repoIcon = getRepoIcon(repo_data['repository_type']);
792 794 if (repoIcon) {
793 795 icon += repoIcon;
794 796 } else {
795 797 icon += '<i class="icon-tag"></i>';
796 798 }
797 799 }
798 800 // generic text
799 801 else if (searchType === 'text') {
800 802 icon = '';
801 803 }
802 804
803 805 var tmpl = '<div class="ac-container-wrap">{0}{1}</div>';
804 806 return tmpl.format(icon, valueDisplay);
805 807 };
806 808
807 809 var handleSelect = function(element, suggestion) {
808 810 if (suggestion.type === "hint") {
809 811 // we skip action
810 812 $('#main_filter').focus();
811 813 }
812 814 else if (suggestion.type === "text") {
813 815 // we skip action
814 816 $('#main_filter').focus();
815 817
816 818 } else {
817 819 window.location = suggestion['url'];
818 820 }
819 821 };
820 822
821 823 var autocompleteMainFilterResult = function (suggestion, originalQuery, queryLowerCase) {
822 824 if (queryLowerCase.split(':').length === 2) {
823 825 queryLowerCase = queryLowerCase.split(':')[1]
824 826 }
825 827 if (suggestion.type === "text") {
826 828 // special case we don't want to "skip" display for
827 829 return true
828 830 }
829 831 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
830 832 };
831 833
832 834 var cleanContext = {
833 835 repo_view_type: null,
834 836
835 837 repo_id: null,
836 838 repo_name: "",
837 839
838 840 repo_group_id: null,
839 841 repo_group_name: null
840 842 };
841 843 var removeGoToFilter = function () {
842 844 $('.searchTagHidable').hide();
843 845 $('#main_filter').autocomplete(
844 846 'setOptions', {params:{search_context: cleanContext}});
845 847 };
846 848
847 849 $('#main_filter').autocomplete({
848 850 serviceUrl: pyroutes.url('goto_switcher_data'),
849 851 params: {
850 852 "search_context": templateContext.search_context
851 853 },
852 854 minChars:2,
853 855 maxHeight:400,
854 856 deferRequestBy: 300, //miliseconds
855 857 tabDisabled: true,
856 858 autoSelectFirst: false,
857 859 formatResult: autocompleteMainFilterFormatResult,
858 860 lookupFilter: autocompleteMainFilterResult,
859 861 onSelect: function (element, suggestion) {
860 862 handleSelect(element, suggestion);
861 863 return false;
862 864 },
863 865 onSearchError: function (element, query, jqXHR, textStatus, errorThrown) {
864 866 if (jqXHR !== 'abort') {
865 867 alert("Error during search.\nError code: {0}".format(textStatus));
866 868 window.location = '';
867 869 }
868 870 }
869 871 });
870 872
871 873 showMainFilterBox = function () {
872 874 $('#main_filter_help').toggle();
873 875 };
874 876
875 877 $('#main_filter').on('keydown.autocomplete', function (e) {
876 878
877 879 var BACKSPACE = 8;
878 880 var el = $(e.currentTarget);
879 881 if(e.which === BACKSPACE){
880 882 var inputVal = el.val();
881 883 if (inputVal === ""){
882 884 removeGoToFilter()
883 885 }
884 886 }
885 887 });
886 888
887 889 </script>
888 890 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
889 891 </%def>
890 892
891 893 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
892 894 <div class="modal-dialog">
893 895 <div class="modal-content">
894 896 <div class="modal-header">
895 897 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
896 898 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
897 899 </div>
898 900 <div class="modal-body">
899 901 <div class="block-left">
900 902 <table class="keyboard-mappings">
901 903 <tbody>
902 904 <tr>
903 905 <th></th>
904 906 <th>${_('Site-wide shortcuts')}</th>
905 907 </tr>
906 908 <%
907 909 elems = [
908 910 ('/', 'Use quick search box'),
909 911 ('g h', 'Goto home page'),
910 912 ('g g', 'Goto my private gists page'),
911 913 ('g G', 'Goto my public gists page'),
912 914 ('g 0-9', 'Goto bookmarked items from 0-9'),
913 915 ('n r', 'New repository page'),
914 916 ('n g', 'New gist page'),
915 917 ]
916 918 %>
917 919 %for key, desc in elems:
918 920 <tr>
919 921 <td class="keys">
920 922 <span class="key tag">${key}</span>
921 923 </td>
922 924 <td>${desc}</td>
923 925 </tr>
924 926 %endfor
925 927 </tbody>
926 928 </table>
927 929 </div>
928 930 <div class="block-left">
929 931 <table class="keyboard-mappings">
930 932 <tbody>
931 933 <tr>
932 934 <th></th>
933 935 <th>${_('Repositories')}</th>
934 936 </tr>
935 937 <%
936 938 elems = [
937 939 ('g s', 'Goto summary page'),
938 940 ('g c', 'Goto changelog page'),
939 941 ('g f', 'Goto files page'),
940 942 ('g F', 'Goto files page with file search activated'),
941 943 ('g p', 'Goto pull requests page'),
942 944 ('g o', 'Goto repository settings'),
943 945 ('g O', 'Goto repository permissions settings'),
944 946 ]
945 947 %>
946 948 %for key, desc in elems:
947 949 <tr>
948 950 <td class="keys">
949 951 <span class="key tag">${key}</span>
950 952 </td>
951 953 <td>${desc}</td>
952 954 </tr>
953 955 %endfor
954 956 </tbody>
955 957 </table>
956 958 </div>
957 959 </div>
958 960 <div class="modal-footer">
959 961 </div>
960 962 </div><!-- /.modal-content -->
961 963 </div><!-- /.modal-dialog -->
962 964 </div><!-- /.modal -->
963 965
@@ -1,297 +1,313 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
4 4
5 5 <%def name="title()">
6 6 %if c.compare_home:
7 7 ${_('%s Compare') % c.repo_name}
8 8 %else:
9 9 ${_('%s Compare') % c.repo_name} - ${'%s@%s' % (c.source_repo.repo_name, c.source_ref)} &gt; ${'%s@%s' % (c.target_repo.repo_name, c.target_ref)}
10 10 %endif
11 11 %if c.rhodecode_name:
12 12 &middot; ${h.branding(c.rhodecode_name)}
13 13 %endif
14 14 </%def>
15 15
16 16 <%def name="breadcrumbs_links()"></%def>
17 17
18 18 <%def name="menu_bar_nav()">
19 19 ${self.menu_items(active='repositories')}
20 20 </%def>
21 21
22 22 <%def name="menu_bar_subnav()">
23 23 ${self.repo_menu(active='compare')}
24 24 </%def>
25 25
26 26 <%def name="main()">
27 27 <script type="text/javascript">
28 28 // set fake commitId on this commit-range page
29 29 templateContext.commit_data.commit_id = "${h.EmptyCommit().raw_id}";
30 30 </script>
31 31
32 32 <div class="box">
33 33 <div class="summary changeset">
34 34 <div class="summary-detail">
35 35 <div class="summary-detail-header">
36 36 <span class="breadcrumbs files_location">
37 37 <h4>
38 38 ${_('Compare Commits')}
39 39 % if c.file_path:
40 40 ${_('for file')} <a href="#${'a_' + h.FID('',c.file_path)}">${c.file_path}</a>
41 41 % endif
42 42
43 43 % if c.commit_ranges:
44 44 <code>
45 45 r${c.source_commit.idx}:${h.short_id(c.source_commit.raw_id)}...r${c.target_commit.idx}:${h.short_id(c.target_commit.raw_id)}
46 46 </code>
47 47 % endif
48 48 </h4>
49 49 </span>
50
50 51 <div class="clear-fix"></div>
51 52 </div>
52 53
53 54 <div class="fieldset">
54 55 <div class="left-label-summary">
55 56 <p class="spacing">${_('Target')}:</p>
56 57 <div class="right-label-summary">
57 58 <div class="code-header" >
58 59 <div class="compare_header">
59 60 ## The hidden elements are replaced with a select2 widget
60 61 ${h.hidden('compare_source')}
61 62 </div>
62 63 </div>
63 64 </div>
64 65 </div>
65 66 </div>
66 67
67 68 <div class="fieldset">
68 69 <div class="left-label-summary">
69 70 <p class="spacing">${_('Source')}:</p>
70 71 <div class="right-label-summary">
71 72 <div class="code-header" >
72 73 <div class="compare_header">
73 74 ## The hidden elements are replaced with a select2 widget
74 75 ${h.hidden('compare_target')}
75 76 </div>
76 77 </div>
77 78 </div>
78 79 </div>
79 80 </div>
80 81
81 82 <div class="fieldset">
82 83 <div class="left-label-summary">
83 84 <p class="spacing">${_('Actions')}:</p>
84 85 <div class="right-label-summary">
85 86 <div class="code-header" >
86 87 <div class="compare_header">
87 88 <div class="compare-buttons">
88 89 % if c.compare_home:
89 90 <a id="compare_revs" class="btn btn-primary"> ${_('Compare Commits')}</a>
91 %if c.rhodecode_db_repo.fork:
92
93 <a class="btn btn-default" title="${h.tooltip(_('Compare fork with %s' % c.rhodecode_db_repo.fork.repo_name))}"
94 href="${h.route_path('repo_compare',
95 repo_name=c.rhodecode_db_repo.fork.repo_name,
96 source_ref_type=c.rhodecode_db_repo.landing_rev[0],
97 source_ref=c.rhodecode_db_repo.landing_rev[1],
98 target_repo=c.repo_name,target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],
99 target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1],
100 _query=dict(merge=1))}"
101 >
102 ${_('Compare with origin')}
103 </a>
104
105 %endif
90 106
91 107 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Swap')}</a>
92 108 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Comment')}</a>
93 109 <div id="changeset_compare_view_content">
94 110 <div class="help-block">${_('Compare commits, branches, bookmarks or tags.')}</div>
95 111 </div>
96 112
97 113 % elif c.preview_mode:
98 114 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Compare Commits')}</a>
99 115 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Swap')}</a>
100 116 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Comment')}</a>
101 117
102 118 % else:
103 119 <a id="compare_revs" class="btn btn-primary"> ${_('Compare Commits')}</a>
104 120 <a id="btn-swap" class="btn btn-primary" href="${c.swap_url}">${_('Swap')}</a>
105 121
106 122 ## allow comment only if there are commits to comment on
107 123 % if c.diffset and c.diffset.files and c.commit_ranges:
108 124 <a id="compare_changeset_status_toggle" class="btn btn-primary">${_('Comment')}</a>
109 125 % else:
110 126 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Comment')}</a>
111 127 % endif
112 128 % endif
113 129 </div>
114 130 </div>
115 131 </div>
116 132 </div>
117 133 </div>
118 134 </div>
119 135
120 136 ## commit status form
121 137 <div class="fieldset" id="compare_changeset_status" style="display: none; margin-bottom: -80px;">
122 138 <div class="left-label-summary">
123 139 <p class="spacing">${_('Commit status')}:</p>
124 140 <div class="right-label-summary">
125 141 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
126 142 ## main comment form and it status
127 143 <%
128 144 def revs(_revs):
129 145 form_inputs = []
130 146 for cs in _revs:
131 147 tmpl = '<input type="hidden" data-commit-id="%(cid)s" name="commit_ids" value="%(cid)s">' % {'cid': cs.raw_id}
132 148 form_inputs.append(tmpl)
133 149 return form_inputs
134 150 %>
135 151 <div>
136 152 ${comment.comments(h.route_path('repo_commit_comment_create', repo_name=c.repo_name, commit_id='0'*16), None, is_compare=True, form_extras=revs(c.commit_ranges))}
137 153 </div>
138 154 </div>
139 155 </div>
140 156 </div>
141 157 <div class="clear-fix"></div>
142 158 </div> <!-- end summary-detail -->
143 159 </div> <!-- end summary -->
144 160
145 161 ## use JS script to load it quickly before potentially large diffs render long time
146 162 ## this prevents from situation when large diffs block rendering of select2 fields
147 163 <script type="text/javascript">
148 164
149 165 var cache = {};
150 166
151 167 var formatSelection = function(repoName){
152 168 return function(data, container, escapeMarkup) {
153 169 var selection = data ? this.text(data) : "";
154 170 return escapeMarkup('{0}@{1}'.format(repoName, selection));
155 171 }
156 172 };
157 173
158 174 var feedCompareData = function(query, cachedValue){
159 175 var data = {results: []};
160 176 //filter results
161 177 $.each(cachedValue.results, function() {
162 178 var section = this.text;
163 179 var children = [];
164 180 $.each(this.children, function() {
165 181 if (query.term.length === 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
166 182 children.push({
167 183 'id': this.id,
168 184 'text': this.text,
169 185 'type': this.type
170 186 })
171 187 }
172 188 });
173 189 data.results.push({
174 190 'text': section,
175 191 'children': children
176 192 })
177 193 });
178 194 //push the typed in changeset
179 195 data.results.push({
180 196 'text': _gettext('specify commit'),
181 197 'children': [{
182 198 'id': query.term,
183 199 'text': query.term,
184 200 'type': 'rev'
185 201 }]
186 202 });
187 203 query.callback(data);
188 204 };
189 205
190 206 var loadCompareData = function(repoName, query, cache){
191 207 $.ajax({
192 208 url: pyroutes.url('repo_refs_data', {'repo_name': repoName}),
193 209 data: {},
194 210 dataType: 'json',
195 211 type: 'GET',
196 212 success: function(data) {
197 213 cache[repoName] = data;
198 214 query.callback({results: data.results});
199 215 }
200 216 })
201 217 };
202 218
203 219 var enable_fields = ${"false" if c.preview_mode else "true"};
204 220 $("#compare_source").select2({
205 221 placeholder: "${'%s@%s' % (c.source_repo.repo_name, c.source_ref)}",
206 222 containerCssClass: "drop-menu",
207 223 dropdownCssClass: "drop-menu-dropdown",
208 224 formatSelection: formatSelection("${c.source_repo.repo_name}"),
209 225 dropdownAutoWidth: true,
210 226 query: function(query) {
211 227 var repoName = '${c.source_repo.repo_name}';
212 228 var cachedValue = cache[repoName];
213 229
214 230 if (cachedValue){
215 231 feedCompareData(query, cachedValue);
216 232 }
217 233 else {
218 234 loadCompareData(repoName, query, cache);
219 235 }
220 236 }
221 237 }).select2("enable", enable_fields);
222 238
223 239 $("#compare_target").select2({
224 240 placeholder: "${'%s@%s' % (c.target_repo.repo_name, c.target_ref)}",
225 241 dropdownAutoWidth: true,
226 242 containerCssClass: "drop-menu",
227 243 dropdownCssClass: "drop-menu-dropdown",
228 244 formatSelection: formatSelection("${c.target_repo.repo_name}"),
229 245 query: function(query) {
230 246 var repoName = '${c.target_repo.repo_name}';
231 247 var cachedValue = cache[repoName];
232 248
233 249 if (cachedValue){
234 250 feedCompareData(query, cachedValue);
235 251 }
236 252 else {
237 253 loadCompareData(repoName, query, cache);
238 254 }
239 255 }
240 256 }).select2("enable", enable_fields);
241 257 var initial_compare_source = {id: "${c.source_ref}", type:"${c.source_ref_type}"};
242 258 var initial_compare_target = {id: "${c.target_ref}", type:"${c.target_ref_type}"};
243 259
244 260 $('#compare_revs').on('click', function(e) {
245 261 var source = $('#compare_source').select2('data') || initial_compare_source;
246 262 var target = $('#compare_target').select2('data') || initial_compare_target;
247 263 if (source && target) {
248 264 var url_data = {
249 265 repo_name: "${c.repo_name}",
250 266 source_ref: source.id,
251 267 source_ref_type: source.type,
252 268 target_ref: target.id,
253 269 target_ref_type: target.type
254 270 };
255 271 window.location = pyroutes.url('repo_compare', url_data);
256 272 }
257 273 });
258 274 $('#compare_changeset_status_toggle').on('click', function(e) {
259 275 $('#compare_changeset_status').toggle();
260 276 });
261 277
262 278 </script>
263 279
264 280 ## table diff data
265 281 <div class="table">
266 282
267 283
268 284 % if not c.compare_home:
269 285 <div id="changeset_compare_view_content">
270 286 <div class="pull-left">
271 287 <div class="btn-group">
272 288 <a
273 289 class="btn"
274 290 href="#"
275 291 onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">
276 292 ${_ungettext('Expand %s commit','Expand %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
277 293 </a>
278 294 <a
279 295 class="btn"
280 296 href="#"
281 297 onclick="$('.compare_select').hide();$('.compare_select_hidden').show(); return false">
282 298 ${_ungettext('Collapse %s commit','Collapse %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
283 299 </a>
284 300 </div>
285 301 </div>
286 302 <div style="padding:0 10px 10px 0px" class="pull-left"></div>
287 303 ## commit compare generated below
288 304 <%include file="compare_commits.mako"/>
289 305 ${cbdiffs.render_diffset_menu(c.diffset)}
290 306 ${cbdiffs.render_diffset(c.diffset)}
291 307 </div>
292 308 % endif
293 309
294 310 </div>
295 311 </div>
296 312
297 313 </%def>
General Comments 0
You need to be logged in to leave comments. Login now