Commit eca823c1c7cef45cc18c6ab36d2327650c85bfc3
Exists in
master
and in
4 other branches
Merge branch 'master' into api
Showing
125 changed files
with
1752 additions
and
666 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 125 files displayed.
.gitignore
CHANGELOG
Gemfile
@@ -7,7 +7,7 @@ gem "sqlite3" | @@ -7,7 +7,7 @@ gem "sqlite3" | ||
7 | gem "mysql2" | 7 | gem "mysql2" |
8 | 8 | ||
9 | # Auth | 9 | # Auth |
10 | -gem "devise", "~> 1.5" | 10 | +gem "devise", "~> 2.1.0" |
11 | 11 | ||
12 | # GITLAB patched libs | 12 | # GITLAB patched libs |
13 | gem "grit", :git => "https://github.com/gitlabhq/grit.git", :ref => "7f35cb98ff17d534a07e3ce6ec3d580f67402837" | 13 | gem "grit", :git => "https://github.com/gitlabhq/grit.git", :ref => "7f35cb98ff17d534a07e3ce6ec3d580f67402837" |
@@ -71,7 +71,6 @@ group :development, :test do | @@ -71,7 +71,6 @@ group :development, :test do | ||
71 | gem "awesome_print" | 71 | gem "awesome_print" |
72 | gem "database_cleaner" | 72 | gem "database_cleaner" |
73 | gem "launchy" | 73 | gem "launchy" |
74 | - gem "webmock" | ||
75 | end | 74 | end |
76 | 75 | ||
77 | group :test do | 76 | group :test do |
@@ -82,4 +81,5 @@ group :test do | @@ -82,4 +81,5 @@ group :test do | ||
82 | gem "shoulda-matchers" | 81 | gem "shoulda-matchers" |
83 | gem 'email_spec' | 82 | gem 'email_spec' |
84 | gem 'resque_spec' | 83 | gem 'resque_spec' |
84 | + gem "webmock" | ||
85 | end | 85 | end |
Gemfile.lock
@@ -148,10 +148,11 @@ GEM | @@ -148,10 +148,11 @@ GEM | ||
148 | nokogiri (>= 1.5.0) | 148 | nokogiri (>= 1.5.0) |
149 | daemons (1.1.8) | 149 | daemons (1.1.8) |
150 | database_cleaner (0.8.0) | 150 | database_cleaner (0.8.0) |
151 | - devise (1.5.3) | 151 | + devise (2.1.2) |
152 | bcrypt-ruby (~> 3.0) | 152 | bcrypt-ruby (~> 3.0) |
153 | - orm_adapter (~> 0.0.3) | ||
154 | - warden (~> 1.1) | 153 | + orm_adapter (~> 0.1) |
154 | + railties (~> 3.1) | ||
155 | + warden (~> 1.2.1) | ||
155 | diff-lcs (1.1.3) | 156 | diff-lcs (1.1.3) |
156 | drapper (0.8.4) | 157 | drapper (0.8.4) |
157 | email_spec (1.2.1) | 158 | email_spec (1.2.1) |
@@ -225,7 +226,7 @@ GEM | @@ -225,7 +226,7 @@ GEM | ||
225 | omniauth (1.1.0) | 226 | omniauth (1.1.0) |
226 | hashie (~> 1.2) | 227 | hashie (~> 1.2) |
227 | rack | 228 | rack |
228 | - orm_adapter (0.0.7) | 229 | + orm_adapter (0.3.0) |
229 | polyglot (0.3.3) | 230 | polyglot (0.3.3) |
230 | posix-spawn (0.3.6) | 231 | posix-spawn (0.3.6) |
231 | pry (0.9.9.6) | 232 | pry (0.9.9.6) |
@@ -356,7 +357,7 @@ GEM | @@ -356,7 +357,7 @@ GEM | ||
356 | raindrops (~> 0.7) | 357 | raindrops (~> 0.7) |
357 | vegas (0.1.11) | 358 | vegas (0.1.11) |
358 | rack (>= 1.0.0) | 359 | rack (>= 1.0.0) |
359 | - warden (1.2.0) | 360 | + warden (1.2.1) |
360 | rack (>= 1.0) | 361 | rack (>= 1.0) |
361 | webmock (1.8.7) | 362 | webmock (1.8.7) |
362 | addressable (>= 2.2.7) | 363 | addressable (>= 2.2.7) |
@@ -383,7 +384,7 @@ DEPENDENCIES | @@ -383,7 +384,7 @@ DEPENDENCIES | ||
383 | colored | 384 | colored |
384 | cucumber-rails | 385 | cucumber-rails |
385 | database_cleaner | 386 | database_cleaner |
386 | - devise (~> 1.5) | 387 | + devise (~> 2.1.0) |
387 | drapper | 388 | drapper |
388 | email_spec | 389 | email_spec |
389 | ffaker | 390 | ffaker |
VERSION
6.38 KB
app/assets/javascripts/application.js
@@ -12,6 +12,7 @@ | @@ -12,6 +12,7 @@ | ||
12 | //= require jquery.cookie | 12 | //= require jquery.cookie |
13 | //= require jquery.endless-scroll | 13 | //= require jquery.endless-scroll |
14 | //= require jquery.highlight | 14 | //= require jquery.highlight |
15 | +//= require jquery.waitforimages | ||
15 | //= require bootstrap-modal | 16 | //= require bootstrap-modal |
16 | //= require modernizr | 17 | //= require modernizr |
17 | //= require chosen-jquery | 18 | //= require chosen-jquery |
@@ -20,10 +21,26 @@ | @@ -20,10 +21,26 @@ | ||
20 | //= require_tree . | 21 | //= require_tree . |
21 | 22 | ||
22 | $(document).ready(function(){ | 23 | $(document).ready(function(){ |
24 | + | ||
23 | $(".one_click_select").live("click", function(){ | 25 | $(".one_click_select").live("click", function(){ |
24 | $(this).select(); | 26 | $(this).select(); |
25 | }); | 27 | }); |
26 | 28 | ||
29 | + | ||
30 | + $('body').on('ajax:complete, ajax:beforeSend, submit', 'form', function(e){ | ||
31 | + var buttons = $('[type="submit"]', this); | ||
32 | + switch( e.type ){ | ||
33 | + case 'ajax:beforeSend': | ||
34 | + case 'submit': | ||
35 | + buttons.attr('disabled', 'disabled'); | ||
36 | + break; | ||
37 | + case ' ajax:complete': | ||
38 | + default: | ||
39 | + buttons.removeAttr('disabled'); | ||
40 | + break; | ||
41 | + } | ||
42 | + }) | ||
43 | + | ||
27 | $(".account-box").mouseenter(showMenu); | 44 | $(".account-box").mouseenter(showMenu); |
28 | $(".account-box").mouseleave(resetMenu); | 45 | $(".account-box").mouseleave(resetMenu); |
29 | 46 | ||
@@ -97,3 +114,8 @@ function showDiff(link) { | @@ -97,3 +114,8 @@ function showDiff(link) { | ||
97 | return _chosen.apply(this, [default_options]); | 114 | return _chosen.apply(this, [default_options]); |
98 | }}) | 115 | }}) |
99 | })(jQuery); | 116 | })(jQuery); |
117 | + | ||
118 | + | ||
119 | +function ajaxGet(url) { | ||
120 | + $.ajax({type: "GET", url: url, dataType: "script"}); | ||
121 | +} |
app/assets/javascripts/issues.js
@@ -73,4 +73,25 @@ function issuesPage(){ | @@ -73,4 +73,25 @@ function issuesPage(){ | ||
73 | $("#milestone_id, #assignee_id, #label_name").on("change", function(){ | 73 | $("#milestone_id, #assignee_id, #label_name").on("change", function(){ |
74 | $(this).closest("form").submit(); | 74 | $(this).closest("form").submit(); |
75 | }); | 75 | }); |
76 | + | ||
77 | + $('body').on('ajax:success', '.close_issue, .reopen_issue, #new_issue', function(){ | ||
78 | + var t = $(this), | ||
79 | + totalIssues, | ||
80 | + reopen = t.hasClass('reopen_issue'), | ||
81 | + newIssue = false; | ||
82 | + if( this.id == 'new_issue' ){ | ||
83 | + newIssue = true; | ||
84 | + } | ||
85 | + $('.issue_counter, #new_issue').each(function(){ | ||
86 | + var issue = $(this); | ||
87 | + totalIssues = parseInt( $(this).html(), 10 ); | ||
88 | + | ||
89 | + if( newIssue || ( reopen && issue.closest('.main_menu').length ) ){ | ||
90 | + $(this).html( totalIssues+1 ); | ||
91 | + }else { | ||
92 | + $(this).html( totalIssues-1 ); | ||
93 | + } | ||
94 | + }); | ||
95 | + | ||
96 | + }); | ||
76 | } | 97 | } |
app/assets/javascripts/note.js
@@ -25,11 +25,11 @@ init: | @@ -25,11 +25,11 @@ init: | ||
25 | $(this).closest('li').fadeOut(); }); | 25 | $(this).closest('li').fadeOut(); }); |
26 | 26 | ||
27 | $("#new_note").live("ajax:before", function(){ | 27 | $("#new_note").live("ajax:before", function(){ |
28 | - $("#submit_note").attr("disabled", "disabled"); | 28 | + $(".submit_note").attr("disabled", "disabled"); |
29 | }) | 29 | }) |
30 | 30 | ||
31 | $("#new_note").live("ajax:complete", function(){ | 31 | $("#new_note").live("ajax:complete", function(){ |
32 | - $("#submit_note").removeAttr("disabled"); | 32 | + $(".submit_note").removeAttr("disabled"); |
33 | }) | 33 | }) |
34 | 34 | ||
35 | $("#note_note").live("focus", function(){ | 35 | $("#note_note").live("focus", function(){ |
app/assets/stylesheets/common.scss
@@ -604,7 +604,11 @@ li.note { | @@ -604,7 +604,11 @@ li.note { | ||
604 | border-style: solid; | 604 | border-style: solid; |
605 | border-width: 1px; | 605 | border-width: 1px; |
606 | @include border-radius(4px); | 606 | @include border-radius(4px); |
607 | - min-height:42px; | 607 | + min-height:22px; |
608 | + | ||
609 | + .avatar { | ||
610 | + width:24px; | ||
611 | + } | ||
608 | } | 612 | } |
609 | 613 | ||
610 | .supp_diff_link, | 614 | .supp_diff_link, |
app/assets/stylesheets/gitlab_bootstrap.scss
@@ -202,6 +202,10 @@ a:focus { | @@ -202,6 +202,10 @@ a:focus { | ||
202 | color:$style_color; | 202 | color:$style_color; |
203 | } | 203 | } |
204 | 204 | ||
205 | +.nav-tabs > .active > a { | ||
206 | + font-weight:bold; | ||
207 | +} | ||
208 | + | ||
205 | /** COLORS **/ | 209 | /** COLORS **/ |
206 | .cgray { color:gray; } | 210 | .cgray { color:gray; } |
207 | .cred { color:#D12F19; } | 211 | .cred { color:#D12F19; } |
@@ -209,6 +213,7 @@ a:focus { | @@ -209,6 +213,7 @@ a:focus { | ||
209 | .cblack { color:#111; } | 213 | .cblack { color:#111; } |
210 | .cdark { color:#444 } | 214 | .cdark { color:#444 } |
211 | .cwhite { color:#fff !important } | 215 | .cwhite { color:#fff !important } |
216 | +.bgred { background: #F2DEDE !important} | ||
212 | 217 | ||
213 | /** COMMON STYLES **/ | 218 | /** COMMON STYLES **/ |
214 | .left { | 219 | .left { |
@@ -299,9 +304,24 @@ table.no-borders { | @@ -299,9 +304,24 @@ table.no-borders { | ||
299 | } | 304 | } |
300 | 305 | ||
301 | .event_label { | 306 | .event_label { |
302 | - background: #FCEEC1; | ||
303 | - padding: 2px 2px 0; | ||
304 | - font-family: monospace; | 307 | + @extend .label; |
308 | + background-color: #999; | ||
309 | + | ||
310 | + &.pushed { | ||
311 | + background-color: #3A87AD; | ||
312 | + } | ||
313 | + | ||
314 | + &.opened { | ||
315 | + background-color: #468847; | ||
316 | + } | ||
317 | + | ||
318 | + &.closed { | ||
319 | + background-color: #B94A48; | ||
320 | + } | ||
321 | + | ||
322 | + &.merged { | ||
323 | + background-color: #2A2; | ||
324 | + } | ||
305 | } | 325 | } |
306 | 326 | ||
307 | img.avatar { | 327 | img.avatar { |
@@ -425,9 +445,10 @@ form { | @@ -425,9 +445,10 @@ form { | ||
425 | */ | 445 | */ |
426 | .ui-box { | 446 | .ui-box { |
427 | background:#F9F9F9; | 447 | background:#F9F9F9; |
428 | - margin-bottom: 40px; | 448 | + margin-bottom: 25px; |
429 | @include round-borders-all(4px); | 449 | @include round-borders-all(4px); |
430 | border-color: #CCC; | 450 | border-color: #CCC; |
451 | + @include solid_shade; | ||
431 | 452 | ||
432 | ul { | 453 | ul { |
433 | margin:0; | 454 | margin:0; |
@@ -443,6 +464,13 @@ form { | @@ -443,6 +464,13 @@ form { | ||
443 | background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf); | 464 | background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf); |
444 | background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf); | 465 | background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf); |
445 | 466 | ||
467 | + &.small { | ||
468 | + line-height: 28px; | ||
469 | + font-size: 14px; | ||
470 | + line-height:28px; | ||
471 | + text-shadow: 0 1px 1px white; | ||
472 | + } | ||
473 | + | ||
446 | form { | 474 | form { |
447 | padding:9px 0; | 475 | padding:9px 0; |
448 | margin:0px; | 476 | margin:0px; |
@@ -511,6 +539,7 @@ form { | @@ -511,6 +539,7 @@ form { | ||
511 | table.admin-table { | 539 | table.admin-table { |
512 | @extend .table-bordered; | 540 | @extend .table-bordered; |
513 | @extend .zebra-striped; | 541 | @extend .zebra-striped; |
542 | + @include solid_shade; | ||
514 | th { | 543 | th { |
515 | border-color: #CCC; | 544 | border-color: #CCC; |
516 | border-bottom: 1px solid #bbb; | 545 | border-bottom: 1px solid #bbb; |
@@ -568,6 +597,8 @@ ul.breadcrumb { | @@ -568,6 +597,8 @@ ul.breadcrumb { | ||
568 | @extend .prepend-top-20; | 597 | @extend .prepend-top-20; |
569 | @extend .append-bottom-20; | 598 | @extend .append-bottom-20; |
570 | border-width:1px; | 599 | border-width:1px; |
600 | + @include solid_shade; | ||
601 | + | ||
571 | 602 | ||
572 | img { max-width: 100%; } | 603 | img { max-width: 100%; } |
573 | 604 | ||
@@ -624,13 +655,166 @@ p { | @@ -624,13 +655,166 @@ p { | ||
624 | h3.page_title { | 655 | h3.page_title { |
625 | color:#456; | 656 | color:#456; |
626 | font-size:20px; | 657 | font-size:20px; |
627 | - font-weight: 600; | 658 | + font-weight: normal; |
628 | line-height: 28px; | 659 | line-height: 28px; |
629 | } | 660 | } |
630 | 661 | ||
631 | -pre.logs { | ||
632 | - .log { | ||
633 | - font-size:12px; | ||
634 | - line-height:18px; | 662 | +/** |
663 | + * File content holder | ||
664 | + * | ||
665 | + */ | ||
666 | +.file_holder { | ||
667 | + border:1px solid #CCC; | ||
668 | + margin-bottom:1em; | ||
669 | + @include solid_shade; | ||
670 | + | ||
671 | + .file_title { | ||
672 | + border-bottom: 1px solid #bbb; | ||
673 | + background:#eee; | ||
674 | + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf)); | ||
675 | + background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf); | ||
676 | + background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf); | ||
677 | + background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf); | ||
678 | + margin: 0; | ||
679 | + font-weight: normal; | ||
680 | + font-weight: bold; | ||
681 | + text-align: left; | ||
682 | + color: #666; | ||
683 | + padding: 9px 10px; | ||
684 | + height:18px; | ||
685 | + | ||
686 | + .options { | ||
687 | + float:right; | ||
688 | + margin-top: -5px; | ||
689 | + } | ||
690 | + | ||
691 | + .file_name { | ||
692 | + color:$style_color; | ||
693 | + font-size:14px; | ||
694 | + text-shadow: 0 1px 1px #fff; | ||
695 | + small { | ||
696 | + color:#999; | ||
697 | + font-size:13px; | ||
698 | + } | ||
699 | + } | ||
700 | + } | ||
701 | + .file_content { | ||
702 | + background:#fff; | ||
703 | + font-size: 11px; | ||
704 | + | ||
705 | + &.wiki { | ||
706 | + font-size: 13px; | ||
707 | + code { | ||
708 | + padding:0 4px; | ||
709 | + } | ||
710 | + padding:20px; | ||
711 | + h1, h2 { | ||
712 | + line-height: 46px; | ||
713 | + } | ||
714 | + h3, h4 { | ||
715 | + line-height: 40px; | ||
716 | + } | ||
717 | + } | ||
718 | + | ||
719 | + &.image_file { | ||
720 | + background:#eee; | ||
721 | + text-align:center; | ||
722 | + img { | ||
723 | + padding:100px; | ||
724 | + max-width:300px; | ||
725 | + } | ||
726 | + } | ||
727 | + | ||
728 | + &.blob_file { | ||
729 | + | ||
730 | + } | ||
731 | + | ||
732 | + /** | ||
733 | + * Blame file | ||
734 | + */ | ||
735 | + &.blame { | ||
736 | + tr { | ||
737 | + border-bottom: 1px solid #eee; | ||
738 | + } | ||
739 | + td { | ||
740 | + padding:5px; | ||
741 | + } | ||
742 | + .author, | ||
743 | + .blame_commit { | ||
744 | + background:#f5f5f5; | ||
745 | + vertical-align:top; | ||
746 | + } | ||
747 | + .lines { | ||
748 | + pre { | ||
749 | + padding:0; | ||
750 | + margin:0; | ||
751 | + background:none; | ||
752 | + border:none; | ||
753 | + } | ||
754 | + } | ||
755 | + } | ||
756 | + | ||
757 | + &.logs { | ||
758 | + background:#eee; | ||
759 | + max-height: 700px; | ||
760 | + overflow-y: auto; | ||
761 | + | ||
762 | + ol { | ||
763 | + margin-left:40px; | ||
764 | + padding: 10px 0; | ||
765 | + border-left: 1px solid #CCC; | ||
766 | + margin-bottom:0; | ||
767 | + background: white; | ||
768 | + li { | ||
769 | + color:#888; | ||
770 | + p { | ||
771 | + margin:0; | ||
772 | + color:#333; | ||
773 | + line-height:24px; | ||
774 | + padding-left: 10px; | ||
775 | + } | ||
776 | + | ||
777 | + &:hover { | ||
778 | + background:$hover; | ||
779 | + } | ||
780 | + } | ||
781 | + } | ||
782 | + } | ||
783 | + | ||
784 | + /** | ||
785 | + * Code file | ||
786 | + */ | ||
787 | + &.code { | ||
788 | + padding:0; | ||
789 | + td.code { | ||
790 | + width: 100%; | ||
791 | + .highlight { | ||
792 | + margin-left: 55px; | ||
793 | + overflow:auto; | ||
794 | + overflow-y:hidden; | ||
795 | + } | ||
796 | + } | ||
797 | + .highlight pre { | ||
798 | + white-space: pre; | ||
799 | + word-wrap:normal; | ||
800 | + } | ||
801 | + | ||
802 | + table.highlighttable { | ||
803 | + border: none; | ||
804 | + } | ||
805 | + body.project-page table.highlighttable td { border: none } | ||
806 | + table.highlighttable tr:hover { background:none;} | ||
807 | + | ||
808 | + table.highlighttable pre{ | ||
809 | + line-height:16px !important; | ||
810 | + font-size:12px !important; | ||
811 | + } | ||
812 | + | ||
813 | + table.highlighttable .linenodiv pre { | ||
814 | + text-align: right; | ||
815 | + padding-right: 4px; | ||
816 | + color:#666; | ||
817 | + } | ||
818 | + } | ||
635 | } | 819 | } |
636 | } | 820 | } |
app/assets/stylesheets/header.scss
@@ -96,7 +96,7 @@ header { | @@ -96,7 +96,7 @@ header { | ||
96 | */ | 96 | */ |
97 | .search { | 97 | .search { |
98 | float: right; | 98 | float: right; |
99 | - margin-right: 55px; | 99 | + margin-right: 50px; |
100 | 100 | ||
101 | .search-input { | 101 | .search-input { |
102 | @extend .span2; | 102 | @extend .span2; |
@@ -126,10 +126,10 @@ header { | @@ -126,10 +126,10 @@ header { | ||
126 | cursor: pointer; | 126 | cursor: pointer; |
127 | img { | 127 | img { |
128 | border-radius: 4px; | 128 | border-radius: 4px; |
129 | - right: 0px; | 129 | + right: 5px; |
130 | position: absolute; | 130 | position: absolute; |
131 | - width: 33px; | ||
132 | - height: 33px; | 131 | + width: 31px; |
132 | + height: 31px; | ||
133 | display: block; | 133 | display: block; |
134 | top: 0; | 134 | top: 0; |
135 | &:after { | 135 | &:after { |
app/assets/stylesheets/main.scss
@@ -31,6 +31,12 @@ $hover: #FDF5D9; | @@ -31,6 +31,12 @@ $hover: #FDF5D9; | ||
31 | box-shadow: 0 0 3px #ddd; | 31 | box-shadow: 0 0 3px #ddd; |
32 | } | 32 | } |
33 | 33 | ||
34 | +@mixin solid_shade { | ||
35 | + -moz-box-shadow: 0 0 0 3px #eee; | ||
36 | + -webkit-box-shadow: 0 0 0 3px #eee; | ||
37 | + box-shadow: 0 0 0 3px #eee; | ||
38 | +} | ||
39 | + | ||
34 | @mixin border-radius($radius) { | 40 | @mixin border-radius($radius) { |
35 | -moz-border-radius: $radius; | 41 | -moz-border-radius: $radius; |
36 | -webkit-border-radius: $radius; | 42 | -webkit-border-radius: $radius; |
@@ -136,7 +142,7 @@ $hover: #FDF5D9; | @@ -136,7 +142,7 @@ $hover: #FDF5D9; | ||
136 | /** | 142 | /** |
137 | * Code (files list) styles. Browsing project files there | 143 | * Code (files list) styles. Browsing project files there |
138 | */ | 144 | */ |
139 | -@import "tree.scss"; | 145 | +@import "sections/tree.scss"; |
140 | 146 | ||
141 | /** | 147 | /** |
142 | * This file represent notes(comments) styles | 148 | * This file represent notes(comments) styles |
app/assets/stylesheets/notes.scss
@@ -63,18 +63,22 @@ p.notify_controls span{ | @@ -63,18 +63,22 @@ p.notify_controls span{ | ||
63 | 63 | ||
64 | tr.line_notes_row { | 64 | tr.line_notes_row { |
65 | border-bottom:1px solid #DDD; | 65 | border-bottom:1px solid #DDD; |
66 | + border-left: 7px solid #2A79A3; | ||
67 | + | ||
66 | &.reply { | 68 | &.reply { |
67 | background:#eee; | 69 | background:#eee; |
68 | - | 70 | + border-left: 7px solid #2A79A3; |
71 | + border-top:1px solid #ddd; | ||
69 | td { | 72 | td { |
70 | padding:7px 10px; | 73 | padding:7px 10px; |
71 | } | 74 | } |
72 | a.line_note_reply_link { | 75 | a.line_note_reply_link { |
73 | @include round-borders-all(4px); | 76 | @include round-borders-all(4px); |
74 | - border-color:#aaa; | ||
75 | - background: #bbb; | ||
76 | - padding: 3px 20px; | 77 | + padding: 3px 10px; |
78 | + margin-left:5px; | ||
77 | color: white; | 79 | color: white; |
80 | + background: #2A79A3; | ||
81 | + border-color: #2A79A3; | ||
78 | } | 82 | } |
79 | } | 83 | } |
80 | ul { | 84 | ul { |
@@ -95,6 +99,9 @@ tr.line_notes_row { | @@ -95,6 +99,9 @@ tr.line_notes_row { | ||
95 | td { | 99 | td { |
96 | border-bottom:1px solid #ddd; | 100 | border-bottom:1px solid #ddd; |
97 | } | 101 | } |
102 | + .actions { | ||
103 | + margin:0; | ||
104 | + } | ||
98 | } | 105 | } |
99 | 106 | ||
100 | td .line_note_link { | 107 | td .line_note_link { |
app/assets/stylesheets/sections/commits.scss
@@ -101,18 +101,21 @@ | @@ -101,18 +101,21 @@ | ||
101 | margin:50px; | 101 | margin:50px; |
102 | padding:1px; | 102 | padding:1px; |
103 | max-width:400px; | 103 | max-width:400px; |
104 | - } | ||
105 | - &.diff_image_removed { | ||
106 | - img { | 104 | + |
105 | + &.diff_image_removed { | ||
107 | border: 1px solid #C00; | 106 | border: 1px solid #C00; |
108 | } | 107 | } |
109 | - } | ||
110 | 108 | ||
111 | - &.diff_image_added { | ||
112 | - img { | 109 | + &.diff_image_added { |
113 | border: 1px solid #0C0;; | 110 | border: 1px solid #0C0;; |
114 | } | 111 | } |
115 | } | 112 | } |
113 | + | ||
114 | + &.img_compared { | ||
115 | + img { | ||
116 | + max-width:300px; | ||
117 | + } | ||
118 | + } | ||
116 | } | 119 | } |
117 | } | 120 | } |
118 | 121 |
app/assets/stylesheets/sections/merge_requests.scss
@@ -0,0 +1,96 @@ | @@ -0,0 +1,96 @@ | ||
1 | +#tree-holder { | ||
2 | + #tree-content-holder { | ||
3 | + float:left; | ||
4 | + width:100%; | ||
5 | + } | ||
6 | + #tree-readme-holder { | ||
7 | + float:left; | ||
8 | + width:100%; | ||
9 | + .readme { | ||
10 | + border:1px solid #ccc; | ||
11 | + padding:12px; | ||
12 | + background: #F7F7F7; | ||
13 | + | ||
14 | + pre { | ||
15 | + overflow: auto; | ||
16 | + } | ||
17 | + } | ||
18 | + } | ||
19 | + | ||
20 | + .tree_progress { | ||
21 | + display:none; | ||
22 | + margin:20px; | ||
23 | + &.loading { | ||
24 | + display:block; | ||
25 | + } | ||
26 | + } | ||
27 | + | ||
28 | + #tree-slider { | ||
29 | + @include border-radius(0); | ||
30 | + .tree-item { | ||
31 | + &:hover { | ||
32 | + td { background: $hover; } | ||
33 | + cursor:pointer; | ||
34 | + } | ||
35 | + } | ||
36 | + } | ||
37 | + | ||
38 | + .tree-item { | ||
39 | + .tree-item-file-name { | ||
40 | + vertical-align:middle; | ||
41 | + font-weight:bold; | ||
42 | + a { | ||
43 | + color:$style_color; | ||
44 | + &:hover { | ||
45 | + color:$blue_link; | ||
46 | + } | ||
47 | + } | ||
48 | + | ||
49 | + img { | ||
50 | + position: relative; | ||
51 | + top:-1px; | ||
52 | + } | ||
53 | + } | ||
54 | + } | ||
55 | + | ||
56 | + | ||
57 | + #tree-slider { | ||
58 | + @include solid_shade; | ||
59 | + width:100%; | ||
60 | + | ||
61 | + border-color:#ccc; | ||
62 | + | ||
63 | + td { | ||
64 | + padding:8px; | ||
65 | + border-color:#f1f1f1; | ||
66 | + background:#fafafa; | ||
67 | + } | ||
68 | + | ||
69 | + tr:first-child td:first-child, | ||
70 | + tr:first-child td:last-child { | ||
71 | + border-radius:0; | ||
72 | + } | ||
73 | + | ||
74 | + th { | ||
75 | + border-color: #CCC; | ||
76 | + border-bottom: 1px solid #bbb; | ||
77 | + background:#eee; | ||
78 | + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf)); | ||
79 | + background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf); | ||
80 | + background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf); | ||
81 | + background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf); | ||
82 | + } | ||
83 | + } | ||
84 | + | ||
85 | + .tree-commit-link { | ||
86 | + color:#333; | ||
87 | + } | ||
88 | + | ||
89 | + a.tree-commit-link { | ||
90 | + color: #666; | ||
91 | + &:hover { | ||
92 | + text-decoration: underline; | ||
93 | + } | ||
94 | + } | ||
95 | + | ||
96 | +} |
app/assets/stylesheets/themes/ui_mars.scss
app/assets/stylesheets/tree.scss
@@ -1,232 +0,0 @@ | @@ -1,232 +0,0 @@ | ||
1 | -#tree-holder { | ||
2 | - #tree-content-holder { | ||
3 | - float:left; | ||
4 | - width:100%; | ||
5 | - } | ||
6 | - #tree-readme-holder { | ||
7 | - float:left; | ||
8 | - width:100%; | ||
9 | - .readme { | ||
10 | - border:1px solid #ccc; | ||
11 | - padding:12px; | ||
12 | - background: #F7F7F7; | ||
13 | - | ||
14 | - pre { | ||
15 | - overflow: auto; | ||
16 | - } | ||
17 | - } | ||
18 | - } | ||
19 | - | ||
20 | - .tree_progress { | ||
21 | - display:none; | ||
22 | - margin:20px; | ||
23 | - &.loading { | ||
24 | - display:block; | ||
25 | - } | ||
26 | - } | ||
27 | - | ||
28 | - | ||
29 | - /** FILE CONTENT VIEW **/ | ||
30 | - .view_file_content{ | ||
31 | - .old_line, .new_line { | ||
32 | - background:#ECECEC; | ||
33 | - color:#777; | ||
34 | - width:15px; | ||
35 | - float:left; | ||
36 | - padding: 0px 10px; | ||
37 | - border-right: 1px solid #ccc; | ||
38 | - } | ||
39 | - .old_line{ | ||
40 | - display:none; | ||
41 | - } | ||
42 | - } | ||
43 | - | ||
44 | - .view_file .view_file_header, | ||
45 | - .diff_file .diff_file_header { | ||
46 | - border-bottom: 1px solid #bbb; | ||
47 | - background:#eee; | ||
48 | - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf)); | ||
49 | - background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf); | ||
50 | - background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf); | ||
51 | - background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf); | ||
52 | - margin: 0; | ||
53 | - font-weight: normal; | ||
54 | - font-weight: bold; | ||
55 | - text-align: left; | ||
56 | - color: #666; | ||
57 | - padding: 9px 10px; | ||
58 | - height:18px; | ||
59 | - | ||
60 | - .options { | ||
61 | - float:right; | ||
62 | - margin-top: -5px; | ||
63 | - } | ||
64 | - | ||
65 | - .file_name { | ||
66 | - color:$style_color; | ||
67 | - font-size:14px; | ||
68 | - text-shadow: 0 1px 1px #fff; | ||
69 | - small { | ||
70 | - color:#999; | ||
71 | - font-size:13px; | ||
72 | - } | ||
73 | - } | ||
74 | - } | ||
75 | - | ||
76 | - .view_file { | ||
77 | - border:1px solid #CCC; | ||
78 | - margin-bottom:1em; | ||
79 | - | ||
80 | - .view_file_content { | ||
81 | - background:#fff; | ||
82 | - color:#514721; | ||
83 | - font-size: 11px; | ||
84 | - } | ||
85 | - .view_file_content_image { | ||
86 | - background:#eee; | ||
87 | - text-align:center; | ||
88 | - img { | ||
89 | - padding:100px; | ||
90 | - max-width:300px; | ||
91 | - } | ||
92 | - } | ||
93 | - } | ||
94 | - | ||
95 | - td.code { | ||
96 | - width: 100%; | ||
97 | - .highlight { | ||
98 | - margin-left: 55px; | ||
99 | - overflow:auto; | ||
100 | - overflow-y:hidden; | ||
101 | - } | ||
102 | - } | ||
103 | - .highlight pre { | ||
104 | - white-space: pre; | ||
105 | - word-wrap:normal; | ||
106 | - } | ||
107 | - | ||
108 | - table.highlighttable { | ||
109 | - border: none; | ||
110 | - } | ||
111 | - body.project-page table.highlighttable td { border: none } | ||
112 | - table.highlighttable tr:hover { background:none;} | ||
113 | - | ||
114 | - table.highlighttable pre{ | ||
115 | - line-height:16px !important; | ||
116 | - font-size:12px !important; | ||
117 | - } | ||
118 | - | ||
119 | - table.highlighttable .linenodiv pre { | ||
120 | - text-align: right; | ||
121 | - padding-right: 4px; | ||
122 | - color:#666; | ||
123 | - } | ||
124 | - | ||
125 | - #tree-slider { | ||
126 | - @include border-radius(0); | ||
127 | - .tree-item { | ||
128 | - &:hover { | ||
129 | - td { background: $hover; } | ||
130 | - cursor:pointer; | ||
131 | - } | ||
132 | - } | ||
133 | - } | ||
134 | - | ||
135 | - .tree-item { | ||
136 | - .tree-item-file-name { | ||
137 | - vertical-align:middle; | ||
138 | - font-weight:bold; | ||
139 | - a { | ||
140 | - color:$style_color; | ||
141 | - &:hover { | ||
142 | - color:$blue_link; | ||
143 | - } | ||
144 | - } | ||
145 | - | ||
146 | - img { | ||
147 | - position: relative; | ||
148 | - top:-1px; | ||
149 | - } | ||
150 | - } | ||
151 | - } | ||
152 | - | ||
153 | - | ||
154 | - #tree-slider { | ||
155 | - @include shade; | ||
156 | - width:100%; | ||
157 | - | ||
158 | - border-color:#ccc; | ||
159 | - | ||
160 | - td { | ||
161 | - padding:8px; | ||
162 | - border-color:#f1f1f1; | ||
163 | - background:#fafafa; | ||
164 | - } | ||
165 | - | ||
166 | - tr:first-child td:first-child, | ||
167 | - tr:first-child td:last-child { | ||
168 | - border-radius:0; | ||
169 | - } | ||
170 | - | ||
171 | - th { | ||
172 | - border-color: #CCC; | ||
173 | - border-bottom: 1px solid #bbb; | ||
174 | - background:#eee; | ||
175 | - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf)); | ||
176 | - background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf); | ||
177 | - background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf); | ||
178 | - background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf); | ||
179 | - } | ||
180 | - } | ||
181 | - | ||
182 | - .tree-commit-link { | ||
183 | - color:#333; | ||
184 | - } | ||
185 | - | ||
186 | - #tree-content-holder .view_file{ | ||
187 | - @include shade; | ||
188 | - } | ||
189 | - | ||
190 | - #tree-readme-holder .readme { | ||
191 | - @include shade; | ||
192 | - margin-bottom:20px; | ||
193 | - h1, h2 { | ||
194 | - line-height: 56px; | ||
195 | - } | ||
196 | - h3, h4 { | ||
197 | - line-height: 46px; | ||
198 | - } | ||
199 | - } | ||
200 | - | ||
201 | - a.tree-commit-link { | ||
202 | - color: #666; | ||
203 | - &:hover { | ||
204 | - text-decoration: underline; | ||
205 | - } | ||
206 | - } | ||
207 | - | ||
208 | -} | ||
209 | - | ||
210 | -.blame_file { | ||
211 | - .view_file_content { | ||
212 | - tr { | ||
213 | - border-bottom: 1px solid #eee; | ||
214 | - } | ||
215 | - td { | ||
216 | - padding:5px; | ||
217 | - } | ||
218 | - .author, | ||
219 | - .commit { | ||
220 | - background:#f5f5f5; | ||
221 | - vertical-align:top; | ||
222 | - } | ||
223 | - .lines { | ||
224 | - pre { | ||
225 | - padding:0; | ||
226 | - margin:0; | ||
227 | - background:none; | ||
228 | - border:none; | ||
229 | - } | ||
230 | - } | ||
231 | - } | ||
232 | -} |
@@ -0,0 +1,26 @@ | @@ -0,0 +1,26 @@ | ||
1 | +class CommitLoad < BaseContext | ||
2 | + def execute | ||
3 | + result = { | ||
4 | + :commit => nil, | ||
5 | + :suppress_diff => false, | ||
6 | + :line_notes => [], | ||
7 | + :notes_count => 0, | ||
8 | + :note => nil | ||
9 | + } | ||
10 | + | ||
11 | + commit = project.commit(params[:id]) | ||
12 | + | ||
13 | + if commit | ||
14 | + commit = CommitDecorator.decorate(commit) | ||
15 | + line_notes = project.commit_line_notes(commit) | ||
16 | + | ||
17 | + result[:suppress_diff] = true if commit.diffs.size > 200 && !params[:force_show_diff] | ||
18 | + result[:commit] = commit | ||
19 | + result[:note] = project.build_commit_note(commit) | ||
20 | + result[:line_notes] = line_notes | ||
21 | + result[:notes_count] = line_notes.count + project.commit_notes(commit).count | ||
22 | + end | ||
23 | + | ||
24 | + result | ||
25 | + end | ||
26 | +end |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +class MergeRequestsLoad < BaseContext | ||
2 | + def execute | ||
3 | + type = params[:f].to_i | ||
4 | + | ||
5 | + merge_requests = project.merge_requests | ||
6 | + | ||
7 | + merge_requests = case type | ||
8 | + when 1 then merge_requests | ||
9 | + when 2 then merge_requests.closed | ||
10 | + when 3 then merge_requests.opened.assigned(current_user) | ||
11 | + else merge_requests.opened | ||
12 | + end.page(params[:page]).per(20) | ||
13 | + | ||
14 | + merge_requests.includes(:author, :project).order("closed, created_at desc") | ||
15 | + end | ||
16 | +end |
@@ -0,0 +1,30 @@ | @@ -0,0 +1,30 @@ | ||
1 | +class NotesLoad < BaseContext | ||
2 | + def execute | ||
3 | + target_type = params[:target_type] | ||
4 | + target_id = params[:target_id] | ||
5 | + first_id = params[:first_id] | ||
6 | + last_id = params[:last_id] | ||
7 | + | ||
8 | + | ||
9 | + @notes = case target_type | ||
10 | + when "commit" | ||
11 | + then project.commit_notes(project.commit(target_id)).fresh.limit(20) | ||
12 | + when "snippet" | ||
13 | + then project.snippets.find(target_id).notes | ||
14 | + when "wall" | ||
15 | + then project.common_notes.order("created_at DESC").fresh.limit(50) | ||
16 | + when "issue" | ||
17 | + then project.issues.find(target_id).notes.inc_author.order("created_at DESC").limit(20) | ||
18 | + when "merge_request" | ||
19 | + then project.merge_requests.find(target_id).notes.inc_author.order("created_at DESC").limit(20) | ||
20 | + end | ||
21 | + | ||
22 | + @notes = if last_id | ||
23 | + @notes.where("id > ?", last_id) | ||
24 | + elsif first_id | ||
25 | + @notes.where("id < ?", first_id) | ||
26 | + else | ||
27 | + @notes | ||
28 | + end | ||
29 | + end | ||
30 | +end |
@@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
1 | +class Admin::HooksController < ApplicationController | ||
2 | + layout "admin" | ||
3 | + before_filter :authenticate_user! | ||
4 | + before_filter :authenticate_admin! | ||
5 | + | ||
6 | + def index | ||
7 | + @hooks = SystemHook.all | ||
8 | + @hook = SystemHook.new | ||
9 | + end | ||
10 | + | ||
11 | + def create | ||
12 | + @hook = SystemHook.new(params[:hook]) | ||
13 | + | ||
14 | + if @hook.save | ||
15 | + redirect_to admin_hooks_path, notice: 'Hook was successfully created.' | ||
16 | + else | ||
17 | + @hooks = SystemHook.all | ||
18 | + render :index | ||
19 | + end | ||
20 | + end | ||
21 | + | ||
22 | + def destroy | ||
23 | + @hook = SystemHook.find(params[:id]) | ||
24 | + @hook.destroy | ||
25 | + | ||
26 | + redirect_to admin_hooks_path | ||
27 | + end | ||
28 | + | ||
29 | + | ||
30 | + def test | ||
31 | + @hook = SystemHook.find(params[:hook_id]) | ||
32 | + data = { | ||
33 | + event_name: "project_create", | ||
34 | + name: "Ruby", | ||
35 | + path: "ruby", | ||
36 | + project_id: 1, | ||
37 | + owner_name: "Someone", | ||
38 | + owner_email: "example@gitlabhq.com" | ||
39 | + } | ||
40 | + @hook.execute(data) | ||
41 | + | ||
42 | + redirect_to :back | ||
43 | + end | ||
44 | +end |
app/controllers/admin/mailer_controller.rb
@@ -1,45 +0,0 @@ | @@ -1,45 +0,0 @@ | ||
1 | -class Admin::MailerController < ApplicationController | ||
2 | - layout "admin" | ||
3 | - before_filter :authenticate_user! | ||
4 | - before_filter :authenticate_admin! | ||
5 | - | ||
6 | - def preview | ||
7 | - | ||
8 | - end | ||
9 | - | ||
10 | - def preview_note | ||
11 | - @note = Note.first | ||
12 | - @user = @note.author | ||
13 | - @project = @note.project | ||
14 | - case params[:type] | ||
15 | - when "Commit" then | ||
16 | - @commit = @project.commit | ||
17 | - render :file => 'notify/note_commit_email', :layout => 'notify' | ||
18 | - when "Issue" then | ||
19 | - @issue = Issue.first | ||
20 | - render :file => 'notify/note_issue_email', :layout => 'notify' | ||
21 | - else | ||
22 | - render :file => 'notify/note_wall_email', :layout => 'notify' | ||
23 | - end | ||
24 | - rescue | ||
25 | - render :text => "Preview not available" | ||
26 | - end | ||
27 | - | ||
28 | - def preview_user_new | ||
29 | - @user = User.first | ||
30 | - @password = "DHasJKDHAS!" | ||
31 | - | ||
32 | - render :file => 'notify/new_user_email', :layout => 'notify' | ||
33 | - rescue | ||
34 | - render :text => "Preview not available" | ||
35 | - end | ||
36 | - | ||
37 | - def preview_issue_new | ||
38 | - @issue = Issue.first | ||
39 | - @user = @issue.assignee | ||
40 | - @project = @issue.project | ||
41 | - render :file => 'notify/new_issue_email', :layout => 'notify' | ||
42 | - rescue | ||
43 | - render :text => "Preview not available" | ||
44 | - end | ||
45 | -end |
app/controllers/admin/projects_controller.rb
@@ -6,7 +6,7 @@ class Admin::ProjectsController < ApplicationController | @@ -6,7 +6,7 @@ class Admin::ProjectsController < ApplicationController | ||
6 | def index | 6 | def index |
7 | @admin_projects = Project.scoped | 7 | @admin_projects = Project.scoped |
8 | @admin_projects = @admin_projects.search(params[:name]) if params[:name].present? | 8 | @admin_projects = @admin_projects.search(params[:name]) if params[:name].present? |
9 | - @admin_projects = @admin_projects.page(params[:page]) | 9 | + @admin_projects = @admin_projects.page(params[:page]).per(20) |
10 | end | 10 | end |
11 | 11 | ||
12 | def show | 12 | def show |
@@ -72,6 +72,6 @@ class Admin::ProjectsController < ApplicationController | @@ -72,6 +72,6 @@ class Admin::ProjectsController < ApplicationController | ||
72 | @admin_project = Project.find_by_code(params[:id]) | 72 | @admin_project = Project.find_by_code(params[:id]) |
73 | @admin_project.destroy | 73 | @admin_project.destroy |
74 | 74 | ||
75 | - redirect_to admin_projects_url | 75 | + redirect_to admin_projects_url, notice: 'Project was successfully deleted.' |
76 | end | 76 | end |
77 | end | 77 | end |
app/controllers/application_controller.rb
@@ -52,7 +52,7 @@ class ApplicationController < ActionController::Base | @@ -52,7 +52,7 @@ class ApplicationController < ActionController::Base | ||
52 | 52 | ||
53 | def layout_by_resource | 53 | def layout_by_resource |
54 | if devise_controller? | 54 | if devise_controller? |
55 | - "devise" | 55 | + "devise_layout" |
56 | else | 56 | else |
57 | "application" | 57 | "application" |
58 | end | 58 | end |
app/controllers/commits_controller.rb
@@ -26,43 +26,31 @@ class CommitsController < ApplicationController | @@ -26,43 +26,31 @@ class CommitsController < ApplicationController | ||
26 | end | 26 | end |
27 | 27 | ||
28 | def show | 28 | def show |
29 | - @commit = project.commit(params[:id]) | ||
30 | - | ||
31 | - git_not_found! and return unless @commit | ||
32 | - | ||
33 | - @commit = CommitDecorator.decorate(@commit) | ||
34 | - | ||
35 | - @note = @project.build_commit_note(@commit) | ||
36 | - @comments_allowed = true | ||
37 | - @line_notes = project.commit_line_notes(@commit) | ||
38 | - | ||
39 | - @notes_count = @line_notes.count + project.commit_notes(@commit).count | ||
40 | - | ||
41 | - if @commit.diffs.size > 200 && !params[:force_show_diff] | ||
42 | - @suppress_diff = true | 29 | + result = CommitLoad.new(project, current_user, params).execute |
30 | + | ||
31 | + @commit = result[:commit] | ||
32 | + | ||
33 | + if @commit | ||
34 | + @suppress_diff = result[:suppress_diff] | ||
35 | + @note = result[:note] | ||
36 | + @line_notes = result[:line_notes] | ||
37 | + @notes_count = result[:notes_count] | ||
38 | + @comments_allowed = true | ||
39 | + else | ||
40 | + return git_not_found! | ||
43 | end | 41 | end |
42 | + | ||
44 | rescue Grit::Git::GitTimeout | 43 | rescue Grit::Git::GitTimeout |
45 | render "huge_commit" | 44 | render "huge_commit" |
46 | end | 45 | end |
47 | 46 | ||
48 | def compare | 47 | def compare |
49 | - first = project.commit(params[:to].try(:strip)) | ||
50 | - last = project.commit(params[:from].try(:strip)) | 48 | + result = Commit.compare(project, params[:from], params[:to]) |
51 | 49 | ||
52 | - @diffs = [] | ||
53 | - @commits = [] | 50 | + @commits = result[:commits] |
51 | + @commit = result[:commit] | ||
52 | + @diffs = result[:diffs] | ||
54 | @line_notes = [] | 53 | @line_notes = [] |
55 | - | ||
56 | - if first && last | ||
57 | - commits = [first, last].sort_by(&:created_at) | ||
58 | - younger = commits.first | ||
59 | - older = commits.last | ||
60 | - | ||
61 | - | ||
62 | - @commits = project.repo.commits_between(younger.id, older.id).map {|c| Commit.new(c)} | ||
63 | - @diffs = project.repo.diff(younger.id, older.id) rescue [] | ||
64 | - @commit = Commit.new(older) | ||
65 | - end | ||
66 | end | 54 | end |
67 | 55 | ||
68 | def patch | 56 | def patch |
app/controllers/dashboard_controller.rb
@@ -2,15 +2,13 @@ class DashboardController < ApplicationController | @@ -2,15 +2,13 @@ class DashboardController < ApplicationController | ||
2 | respond_to :html | 2 | respond_to :html |
3 | 3 | ||
4 | def index | 4 | def index |
5 | - @projects = current_user.projects.includes(:events).order("events.created_at DESC") | ||
6 | - @projects = @projects.page(params[:page]).per(40) | ||
7 | - | ||
8 | - @events = Event.where(:project_id => current_user.projects.map(&:id)).recent.limit(20) | ||
9 | - | 5 | + @projects = current_user.projects_with_events.page(params[:page]).per(40) |
6 | + @events = Event.recent_for_user(current_user).limit(20).offset(params[:offset] || 0) | ||
10 | @last_push = current_user.recent_push | 7 | @last_push = current_user.recent_push |
11 | 8 | ||
12 | respond_to do |format| | 9 | respond_to do |format| |
13 | format.html | 10 | format.html |
11 | + format.js | ||
14 | format.atom { render :layout => false } | 12 | format.atom { render :layout => false } |
15 | end | 13 | end |
16 | end | 14 | end |
app/controllers/hooks_controller.rb
@@ -11,24 +11,24 @@ class HooksController < ApplicationController | @@ -11,24 +11,24 @@ class HooksController < ApplicationController | ||
11 | respond_to :html | 11 | respond_to :html |
12 | 12 | ||
13 | def index | 13 | def index |
14 | - @hooks = @project.web_hooks.all | ||
15 | - @hook = WebHook.new | 14 | + @hooks = @project.hooks.all |
15 | + @hook = ProjectHook.new | ||
16 | end | 16 | end |
17 | 17 | ||
18 | def create | 18 | def create |
19 | - @hook = @project.web_hooks.new(params[:hook]) | 19 | + @hook = @project.hooks.new(params[:hook]) |
20 | @hook.save | 20 | @hook.save |
21 | 21 | ||
22 | if @hook.valid? | 22 | if @hook.valid? |
23 | redirect_to project_hooks_path(@project) | 23 | redirect_to project_hooks_path(@project) |
24 | else | 24 | else |
25 | - @hooks = @project.web_hooks.all | 25 | + @hooks = @project.hooks.all |
26 | render :index | 26 | render :index |
27 | end | 27 | end |
28 | end | 28 | end |
29 | 29 | ||
30 | def test | 30 | def test |
31 | - @hook = @project.web_hooks.find(params[:id]) | 31 | + @hook = @project.hooks.find(params[:id]) |
32 | commits = @project.commits(@project.default_branch, nil, 3) | 32 | commits = @project.commits(@project.default_branch, nil, 3) |
33 | data = @project.post_receive_data(commits.last.id, commits.first.id, "refs/heads/#{@project.default_branch}", current_user) | 33 | data = @project.post_receive_data(commits.last.id, commits.first.id, "refs/heads/#{@project.default_branch}", current_user) |
34 | @hook.execute(data) | 34 | @hook.execute(data) |
@@ -37,7 +37,7 @@ class HooksController < ApplicationController | @@ -37,7 +37,7 @@ class HooksController < ApplicationController | ||
37 | end | 37 | end |
38 | 38 | ||
39 | def destroy | 39 | def destroy |
40 | - @hook = @project.web_hooks.find(params[:id]) | 40 | + @hook = @project.hooks.find(params[:id]) |
41 | @hook.destroy | 41 | @hook.destroy |
42 | 42 | ||
43 | redirect_to project_hooks_path(@project) | 43 | redirect_to project_hooks_path(@project) |
app/controllers/merge_requests_controller.rb
@@ -24,16 +24,7 @@ class MergeRequestsController < ApplicationController | @@ -24,16 +24,7 @@ class MergeRequestsController < ApplicationController | ||
24 | 24 | ||
25 | 25 | ||
26 | def index | 26 | def index |
27 | - @merge_requests = @project.merge_requests | ||
28 | - | ||
29 | - @merge_requests = case params[:f].to_i | ||
30 | - when 1 then @merge_requests | ||
31 | - when 2 then @merge_requests.closed | ||
32 | - when 3 then @merge_requests.opened.assigned(current_user) | ||
33 | - else @merge_requests.opened | ||
34 | - end.page(params[:page]).per(20) | ||
35 | - | ||
36 | - @merge_requests = @merge_requests.includes(:author, :project).order("closed, created_at desc") | 27 | + @merge_requests = MergeRequestsLoad.new(project, current_user, params).execute |
37 | end | 28 | end |
38 | 29 | ||
39 | def show | 30 | def show |
app/controllers/notes_controller.rb
@@ -40,25 +40,6 @@ class NotesController < ApplicationController | @@ -40,25 +40,6 @@ class NotesController < ApplicationController | ||
40 | protected | 40 | protected |
41 | 41 | ||
42 | def notes | 42 | def notes |
43 | - @notes = case params[:target_type] | ||
44 | - when "commit" | ||
45 | - then project.commit_notes(project.commit((params[:target_id]))).fresh.limit(20) | ||
46 | - when "snippet" | ||
47 | - then project.snippets.find(params[:target_id]).notes | ||
48 | - when "wall" | ||
49 | - then project.common_notes.order("created_at DESC").fresh.limit(50) | ||
50 | - when "issue" | ||
51 | - then project.issues.find(params[:target_id]).notes.inc_author.order("created_at DESC").limit(20) | ||
52 | - when "merge_request" | ||
53 | - then project.merge_requests.find(params[:target_id]).notes.inc_author.order("created_at DESC").limit(20) | ||
54 | - end | ||
55 | - | ||
56 | - @notes = if params[:last_id] | ||
57 | - @notes.where("id > ?", params[:last_id]) | ||
58 | - elsif params[:first_id] | ||
59 | - @notes.where("id < ?", params[:first_id]) | ||
60 | - else | ||
61 | - @notes | ||
62 | - end | 43 | + @notes = NotesLoad.new(project, current_user, params).execute |
63 | end | 44 | end |
64 | end | 45 | end |
app/controllers/omniauth_callbacks_controller.rb
1 | class OmniauthCallbacksController < Devise::OmniauthCallbacksController | 1 | class OmniauthCallbacksController < Devise::OmniauthCallbacksController |
2 | + | ||
3 | + # Extend the standard message generation to accept our custom exception | ||
4 | + def failure_message | ||
5 | + exception = env["omniauth.error"] | ||
6 | + if exception.class == OmniAuth::Error | ||
7 | + error = exception.message | ||
8 | + else | ||
9 | + error = exception.error_reason if exception.respond_to?(:error_reason) | ||
10 | + error ||= exception.error if exception.respond_to?(:error) | ||
11 | + error ||= env["omniauth.error.type"].to_s | ||
12 | + end | ||
13 | + error.to_s.humanize if error | ||
14 | + end | ||
2 | 15 | ||
3 | def ldap | 16 | def ldap |
4 | # We only find ourselves here if the authentication to LDAP was successful. | 17 | # We only find ourselves here if the authentication to LDAP was successful. |
app/controllers/refs_controller.rb
@@ -9,7 +9,7 @@ class RefsController < ApplicationController | @@ -9,7 +9,7 @@ class RefsController < ApplicationController | ||
9 | before_filter :require_non_empty_project | 9 | before_filter :require_non_empty_project |
10 | 10 | ||
11 | before_filter :ref | 11 | before_filter :ref |
12 | - before_filter :define_tree_vars, :only => [:tree, :blob, :blame] | 12 | + before_filter :define_tree_vars, :only => [:tree, :blob, :blame, :logs_tree] |
13 | before_filter :render_full_content | 13 | before_filter :render_full_content |
14 | 14 | ||
15 | layout "project" | 15 | layout "project" |
@@ -46,6 +46,18 @@ class RefsController < ApplicationController | @@ -46,6 +46,18 @@ class RefsController < ApplicationController | ||
46 | end | 46 | end |
47 | end | 47 | end |
48 | 48 | ||
49 | + def logs_tree | ||
50 | + contents = @tree.contents | ||
51 | + @logs = contents.map do |content| | ||
52 | + file = params[:path] ? File.join(params[:path], content.name) : content.name | ||
53 | + last_commit = @project.commits(@commit.id, file, 1).last | ||
54 | + { | ||
55 | + :file_name => content.name, | ||
56 | + :commit => last_commit | ||
57 | + } | ||
58 | + end | ||
59 | + end | ||
60 | + | ||
49 | def blob | 61 | def blob |
50 | if @tree.is_blob? | 62 | if @tree.is_blob? |
51 | if @tree.text? | 63 | if @tree.text? |
@@ -79,6 +91,15 @@ class RefsController < ApplicationController | @@ -79,6 +91,15 @@ class RefsController < ApplicationController | ||
79 | @commit = project.commit(@ref) | 91 | @commit = project.commit(@ref) |
80 | @tree = Tree.new(@commit.tree, project, @ref, params[:path]) | 92 | @tree = Tree.new(@commit.tree, project, @ref, params[:path]) |
81 | @tree = TreeDecorator.new(@tree) | 93 | @tree = TreeDecorator.new(@tree) |
94 | + @hex_path = Digest::SHA1.hexdigest(params[:path] || "/") | ||
95 | + | ||
96 | + if params[:path] | ||
97 | + @history_path = tree_file_project_ref_path(@project, @ref, params[:path]) | ||
98 | + @logs_path = logs_file_project_ref_path(@project, @ref, params[:path]) | ||
99 | + else | ||
100 | + @history_path = tree_project_ref_path(@project, @ref) | ||
101 | + @logs_path = logs_tree_project_ref_path(@project, @ref) | ||
102 | + end | ||
82 | rescue | 103 | rescue |
83 | return render_404 | 104 | return render_404 |
84 | end | 105 | end |
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +class EventDecorator < ApplicationDecorator | ||
2 | + decorates :event | ||
3 | + | ||
4 | + def feed_title | ||
5 | + if self.issue? | ||
6 | + "#{self.author_name} #{self.action_name} issue ##{self.target_id}:" + self.issue_title | ||
7 | + elsif self.merge_request? | ||
8 | + "#{self.author_name} #{self.action_name} MR ##{self.target_id}:" + self.merge_request_title | ||
9 | + elsif self.push? | ||
10 | + "#{self.author_name} #{self.push_action_name} #{self.ref_type} " + self.ref_name | ||
11 | + else | ||
12 | + "" | ||
13 | + end | ||
14 | + end | ||
15 | + | ||
16 | + def feed_url | ||
17 | + if self.issue? | ||
18 | + h.project_issue_url(self.project, self.issue) | ||
19 | + elsif self.merge_request? | ||
20 | + h.project_merge_request_url(self.project, self.merge_request) | ||
21 | + elsif self.push? | ||
22 | + h.project_commits_url(self.project, :ref => self.ref_name) | ||
23 | + end | ||
24 | + end | ||
25 | +end |
app/helpers/application_helper.rb
@@ -0,0 +1,27 @@ | @@ -0,0 +1,27 @@ | ||
1 | +module TreeHelper | ||
2 | + def tree_icon(content) | ||
3 | + if content.is_a?(Grit::Blob) | ||
4 | + if content.text? | ||
5 | + image_tag "file_txt.png" | ||
6 | + elsif content.image? | ||
7 | + image_tag "file_img.png" | ||
8 | + else | ||
9 | + image_tag "file_bin.png" | ||
10 | + end | ||
11 | + else | ||
12 | + image_tag "file_dir.png" | ||
13 | + end | ||
14 | + end | ||
15 | + | ||
16 | + def tree_hex_class(content) | ||
17 | + "file_#{hexdigest(content.name)}" | ||
18 | + end | ||
19 | + | ||
20 | + def tree_full_path(content) | ||
21 | + if params[:path] | ||
22 | + File.join(params[:path], content.name) | ||
23 | + else | ||
24 | + content.name | ||
25 | + end | ||
26 | + end | ||
27 | +end |
app/models/commit.rb
@@ -80,6 +80,29 @@ class Commit | @@ -80,6 +80,29 @@ class Commit | ||
80 | def commits_between(repo, from, to) | 80 | def commits_between(repo, from, to) |
81 | repo.commits_between(from, to).map { |c| Commit.new(c) } | 81 | repo.commits_between(from, to).map { |c| Commit.new(c) } |
82 | end | 82 | end |
83 | + | ||
84 | + def compare(project, from, to) | ||
85 | + first = project.commit(to.try(:strip)) | ||
86 | + last = project.commit(from.try(:strip)) | ||
87 | + | ||
88 | + result = { | ||
89 | + :commits => [], | ||
90 | + :diffs => [], | ||
91 | + :commit => nil | ||
92 | + } | ||
93 | + | ||
94 | + if first && last | ||
95 | + commits = [first, last].sort_by(&:created_at) | ||
96 | + younger = commits.first | ||
97 | + older = commits.last | ||
98 | + | ||
99 | + result[:commits] = project.repo.commits_between(younger.id, older.id).map {|c| Commit.new(c)} | ||
100 | + result[:diffs] = project.repo.diff(younger.id, older.id) rescue [] | ||
101 | + result[:commit] = Commit.new(older) | ||
102 | + end | ||
103 | + | ||
104 | + result | ||
105 | + end | ||
83 | end | 106 | end |
84 | 107 | ||
85 | def persisted? | 108 | def persisted? |
app/models/event.rb
@@ -28,6 +28,10 @@ class Event < ActiveRecord::Base | @@ -28,6 +28,10 @@ class Event < ActiveRecord::Base | ||
28 | end | 28 | end |
29 | end | 29 | end |
30 | 30 | ||
31 | + def self.recent_for_user user | ||
32 | + where(:project_id => user.projects.map(&:id)).recent | ||
33 | + end | ||
34 | + | ||
31 | # Next events currently enabled for system | 35 | # Next events currently enabled for system |
32 | # - push | 36 | # - push |
33 | # - new issue | 37 | # - new issue |
app/models/merge_request.rb
@@ -22,7 +22,6 @@ class MergeRequest < ActiveRecord::Base | @@ -22,7 +22,6 @@ class MergeRequest < ActiveRecord::Base | ||
22 | :should_remove_source_branch | 22 | :should_remove_source_branch |
23 | 23 | ||
24 | validates_presence_of :project_id | 24 | validates_presence_of :project_id |
25 | - validates_presence_of :assignee_id | ||
26 | validates_presence_of :author_id | 25 | validates_presence_of :author_id |
27 | validates_presence_of :source_branch | 26 | validates_presence_of :source_branch |
28 | validates_presence_of :target_branch | 27 | validates_presence_of :target_branch |
@@ -36,6 +35,7 @@ class MergeRequest < ActiveRecord::Base | @@ -36,6 +35,7 @@ class MergeRequest < ActiveRecord::Base | ||
36 | delegate :name, | 35 | delegate :name, |
37 | :email, | 36 | :email, |
38 | :to => :assignee, | 37 | :to => :assignee, |
38 | + :allow_nil => true, | ||
39 | :prefix => true | 39 | :prefix => true |
40 | 40 | ||
41 | validates :title, | 41 | validates :title, |
@@ -128,7 +128,7 @@ class MergeRequest < ActiveRecord::Base | @@ -128,7 +128,7 @@ class MergeRequest < ActiveRecord::Base | ||
128 | 128 | ||
129 | def unmerged_diffs | 129 | def unmerged_diffs |
130 | commits = project.repo.commits_between(target_branch, source_branch).map {|c| Commit.new(c)} | 130 | commits = project.repo.commits_between(target_branch, source_branch).map {|c| Commit.new(c)} |
131 | - diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) | 131 | + diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) rescue [] |
132 | end | 132 | end |
133 | 133 | ||
134 | def last_commit | 134 | def last_commit |
app/models/project.rb
@@ -19,7 +19,7 @@ class Project < ActiveRecord::Base | @@ -19,7 +19,7 @@ class Project < ActiveRecord::Base | ||
19 | has_many :notes, :dependent => :destroy | 19 | has_many :notes, :dependent => :destroy |
20 | has_many :snippets, :dependent => :destroy | 20 | has_many :snippets, :dependent => :destroy |
21 | has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key" | 21 | has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key" |
22 | - has_many :web_hooks, :dependent => :destroy | 22 | + has_many :hooks, :dependent => :destroy, :class_name => "ProjectHook" |
23 | has_many :wikis, :dependent => :destroy | 23 | has_many :wikis, :dependent => :destroy |
24 | has_many :protected_branches, :dependent => :destroy | 24 | has_many :protected_branches, :dependent => :destroy |
25 | 25 | ||
@@ -120,7 +120,7 @@ class Project < ActiveRecord::Base | @@ -120,7 +120,7 @@ class Project < ActiveRecord::Base | ||
120 | errors.add(:path, " like 'gitolite-admin' is not allowed") | 120 | errors.add(:path, " like 'gitolite-admin' is not allowed") |
121 | end | 121 | end |
122 | end | 122 | end |
123 | - | 123 | + |
124 | def self.access_options | 124 | def self.access_options |
125 | UsersProject.access_roles | 125 | UsersProject.access_roles |
126 | end | 126 | end |
app/models/user.rb
1 | class User < ActiveRecord::Base | 1 | class User < ActiveRecord::Base |
2 | + | ||
2 | include Account | 3 | include Account |
3 | 4 | ||
4 | - devise :database_authenticatable, :token_authenticatable, | 5 | + devise :database_authenticatable, :token_authenticatable, :lockable, |
5 | :recoverable, :rememberable, :trackable, :validatable, :omniauthable | 6 | :recoverable, :rememberable, :trackable, :validatable, :omniauthable |
6 | 7 | ||
7 | attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, | 8 | attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, |
8 | - :name, :projects_limit, :skype, :linkedin, :twitter, :dark_scheme, | 9 | + :name, :projects_limit, :skype, :linkedin, :twitter, :dark_scheme, |
9 | :theme_id, :force_random_password | 10 | :theme_id, :force_random_password |
10 | 11 | ||
11 | attr_accessor :force_random_password | 12 | attr_accessor :force_random_password |
@@ -15,6 +16,11 @@ class User < ActiveRecord::Base | @@ -15,6 +16,11 @@ class User < ActiveRecord::Base | ||
15 | has_many :my_own_projects, :class_name => "Project", :foreign_key => :owner_id | 16 | has_many :my_own_projects, :class_name => "Project", :foreign_key => :owner_id |
16 | has_many :keys, :dependent => :destroy | 17 | has_many :keys, :dependent => :destroy |
17 | 18 | ||
19 | + has_many :events, | ||
20 | + :class_name => "Event", | ||
21 | + :foreign_key => :author_id, | ||
22 | + :dependent => :destroy | ||
23 | + | ||
18 | has_many :recent_events, | 24 | has_many :recent_events, |
19 | :class_name => "Event", | 25 | :class_name => "Event", |
20 | :foreign_key => :author_id, | 26 | :foreign_key => :author_id, |
@@ -80,7 +86,8 @@ class User < ActiveRecord::Base | @@ -80,7 +86,8 @@ class User < ActiveRecord::Base | ||
80 | 86 | ||
81 | def self.find_for_ldap_auth(omniauth_info) | 87 | def self.find_for_ldap_auth(omniauth_info) |
82 | name = omniauth_info.name.force_encoding("utf-8") | 88 | name = omniauth_info.name.force_encoding("utf-8") |
83 | - email = omniauth_info.email.downcase | 89 | + email = omniauth_info.email.downcase unless omniauth_info.email.nil? |
90 | + raise OmniAuth::Error, "LDAP accounts must provide an email address" if email.nil? | ||
84 | 91 | ||
85 | if @user = User.find_by_email(email) | 92 | if @user = User.find_by_email(email) |
86 | @user | 93 | @user |
app/models/users_project.rb
@@ -68,7 +68,7 @@ class UsersProject < ActiveRecord::Base | @@ -68,7 +68,7 @@ class UsersProject < ActiveRecord::Base | ||
68 | end | 68 | end |
69 | 69 | ||
70 | def repo_access_human | 70 | def repo_access_human |
71 | - "" | 71 | + self.class.access_roles.invert[self.project_access] |
72 | end | 72 | end |
73 | end | 73 | end |
74 | # == Schema Information | 74 | # == Schema Information |
app/models/web_hook.rb
@@ -4,8 +4,6 @@ class WebHook < ActiveRecord::Base | @@ -4,8 +4,6 @@ class WebHook < ActiveRecord::Base | ||
4 | # HTTParty timeout | 4 | # HTTParty timeout |
5 | default_timeout 10 | 5 | default_timeout 10 |
6 | 6 | ||
7 | - belongs_to :project | ||
8 | - | ||
9 | validates :url, | 7 | validates :url, |
10 | presence: true, | 8 | presence: true, |
11 | format: { | 9 | format: { |
@@ -14,9 +12,8 @@ class WebHook < ActiveRecord::Base | @@ -14,9 +12,8 @@ class WebHook < ActiveRecord::Base | ||
14 | 12 | ||
15 | def execute(data) | 13 | def execute(data) |
16 | WebHook.post(url, body: data.to_json, headers: { "Content-Type" => "application/json" }) | 14 | WebHook.post(url, body: data.to_json, headers: { "Content-Type" => "application/json" }) |
17 | - rescue | ||
18 | - # There was a problem calling this web hook, let's forget about it. | ||
19 | end | 15 | end |
16 | + | ||
20 | end | 17 | end |
21 | # == Schema Information | 18 | # == Schema Information |
22 | # | 19 | # |
app/observers/mailer_observer.rb
@@ -43,7 +43,7 @@ class MailerObserver < ActiveRecord::Observer | @@ -43,7 +43,7 @@ class MailerObserver < ActiveRecord::Observer | ||
43 | end | 43 | end |
44 | 44 | ||
45 | def new_merge_request(merge_request) | 45 | def new_merge_request(merge_request) |
46 | - if merge_request.assignee != current_user | 46 | + if merge_request.assignee && merge_request.assignee != current_user |
47 | Notify.new_merge_request_email(merge_request.id).deliver | 47 | Notify.new_merge_request_email(merge_request.id).deliver |
48 | end | 48 | end |
49 | end | 49 | end |
@@ -0,0 +1,67 @@ | @@ -0,0 +1,67 @@ | ||
1 | +class SystemHookObserver < ActiveRecord::Observer | ||
2 | + observe :user, :project, :users_project | ||
3 | + | ||
4 | + def after_create(model) | ||
5 | + if model.kind_of? Project | ||
6 | + SystemHook.all_hooks_fire({ | ||
7 | + event_name: "project_create", | ||
8 | + name: model.name, | ||
9 | + path: model.path, | ||
10 | + project_id: model.id, | ||
11 | + owner_name: model.owner.name, | ||
12 | + owner_email: model.owner.email, | ||
13 | + created_at: model.created_at | ||
14 | + }) | ||
15 | + elsif model.kind_of? User | ||
16 | + SystemHook.all_hooks_fire({ | ||
17 | + event_name: "user_create", | ||
18 | + name: model.name, | ||
19 | + email: model.email, | ||
20 | + created_at: model.created_at | ||
21 | + }) | ||
22 | + | ||
23 | + elsif model.kind_of? UsersProject | ||
24 | + SystemHook.all_hooks_fire({ | ||
25 | + event_name: "user_add_to_team", | ||
26 | + project_name: model.project.name, | ||
27 | + project_path: model.project.path, | ||
28 | + project_id: model.project_id, | ||
29 | + user_name: model.user.name, | ||
30 | + user_email: model.user.email, | ||
31 | + project_access: model.repo_access_human, | ||
32 | + created_at: model.created_at | ||
33 | + }) | ||
34 | + | ||
35 | + end | ||
36 | + end | ||
37 | + | ||
38 | + def after_destroy(model) | ||
39 | + if model.kind_of? Project | ||
40 | + SystemHook.all_hooks_fire({ | ||
41 | + event_name: "project_destroy", | ||
42 | + name: model.name, | ||
43 | + path: model.path, | ||
44 | + project_id: model.id, | ||
45 | + owner_name: model.owner.name, | ||
46 | + owner_email: model.owner.email, | ||
47 | + }) | ||
48 | + elsif model.kind_of? User | ||
49 | + SystemHook.all_hooks_fire({ | ||
50 | + event_name: "user_destroy", | ||
51 | + name: model.name, | ||
52 | + email: model.email | ||
53 | + }) | ||
54 | + | ||
55 | + elsif model.kind_of? UsersProject | ||
56 | + SystemHook.all_hooks_fire({ | ||
57 | + event_name: "user_remove_from_team", | ||
58 | + project_name: model.project.name, | ||
59 | + project_path: model.project.path, | ||
60 | + project_id: model.project_id, | ||
61 | + user_name: model.user.name, | ||
62 | + user_email: model.user.email, | ||
63 | + project_access: model.repo_access_human | ||
64 | + }) | ||
65 | + end | ||
66 | + end | ||
67 | +end |
app/roles/account.rb
@@ -55,4 +55,8 @@ module Account | @@ -55,4 +55,8 @@ module Account | ||
55 | # Take only latest one | 55 | # Take only latest one |
56 | events = events.recent.limit(1).first | 56 | events = events.recent.limit(1).first |
57 | end | 57 | end |
58 | + | ||
59 | + def projects_with_events | ||
60 | + projects.includes(:events).order("events.created_at DESC") | ||
61 | + end | ||
58 | end | 62 | end |
app/roles/git_push.rb
@@ -27,7 +27,7 @@ module GitPush | @@ -27,7 +27,7 @@ module GitPush | ||
27 | true | 27 | true |
28 | end | 28 | end |
29 | 29 | ||
30 | - def execute_web_hooks(oldrev, newrev, ref, user) | 30 | + def execute_hooks(oldrev, newrev, ref, user) |
31 | ref_parts = ref.split('/') | 31 | ref_parts = ref.split('/') |
32 | 32 | ||
33 | # Return if this is not a push to a branch (e.g. new commits) | 33 | # Return if this is not a push to a branch (e.g. new commits) |
@@ -35,7 +35,7 @@ module GitPush | @@ -35,7 +35,7 @@ module GitPush | ||
35 | 35 | ||
36 | data = post_receive_data(oldrev, newrev, ref, user) | 36 | data = post_receive_data(oldrev, newrev, ref, user) |
37 | 37 | ||
38 | - web_hooks.each { |web_hook| web_hook.execute(data) } | 38 | + hooks.each { |hook| hook.execute(data) } |
39 | end | 39 | end |
40 | 40 | ||
41 | def post_receive_data(oldrev, newrev, ref, user) | 41 | def post_receive_data(oldrev, newrev, ref, user) |
@@ -97,7 +97,7 @@ module GitPush | @@ -97,7 +97,7 @@ module GitPush | ||
97 | self.update_merge_requests(oldrev, newrev, ref, user) | 97 | self.update_merge_requests(oldrev, newrev, ref, user) |
98 | 98 | ||
99 | # Execute web hooks | 99 | # Execute web hooks |
100 | - self.execute_web_hooks(oldrev, newrev, ref, user) | 100 | + self.execute_hooks(oldrev, newrev, ref, user) |
101 | 101 | ||
102 | # Create satellite | 102 | # Create satellite |
103 | self.satellite.create unless self.satellite.exists? | 103 | self.satellite.create unless self.satellite.exists? |
@@ -0,0 +1,66 @@ | @@ -0,0 +1,66 @@ | ||
1 | +<% data_ex_str = <<eos | ||
2 | +1. Project created: | ||
3 | +{ | ||
4 | + "created_at": "2012-07-21T07:30:54Z", | ||
5 | + "event_name": "project_create", | ||
6 | + "name": "StoreCloud", | ||
7 | + "owner_email": "johnsmith@gmail.com", | ||
8 | + "owner_name": "John Smith", | ||
9 | + "path": "storecloud", | ||
10 | + "project_id": 74 | ||
11 | +} | ||
12 | + | ||
13 | +2. Project destroyed: | ||
14 | +{ | ||
15 | + "event_name": "project_destroy", | ||
16 | + "name": "Underscore", | ||
17 | + "owner_email": "johnsmith@gmail.com", | ||
18 | + "owner_name": "John Smith", | ||
19 | + "path": "underscore", | ||
20 | + "project_id": 73 | ||
21 | +} | ||
22 | + | ||
23 | +3. New Team Member: | ||
24 | +{ | ||
25 | + "created_at": "2012-07-21T07:30:56Z", | ||
26 | + "event_name": "user_add_to_team", | ||
27 | + "project_access": "Master", | ||
28 | + "project_id": 74, | ||
29 | + "project_name": "StoreCloud", | ||
30 | + "project_path": "storecloud", | ||
31 | + "owner_email": "johnsmith@gmail.com", | ||
32 | + "owner_name": "John Smith", | ||
33 | +} | ||
34 | + | ||
35 | +4. Team Member Removed: | ||
36 | +{ | ||
37 | + "created_at": "2012-07-21T07:30:56Z", | ||
38 | + "event_name": "user_remove_from_team", | ||
39 | + "project_access": "Master", | ||
40 | + "project_id": 74, | ||
41 | + "project_name": "StoreCloud", | ||
42 | + "project_path": "storecloud", | ||
43 | + "owner_email": "johnsmith@gmail.com", | ||
44 | + "owner_name": "John Smith", | ||
45 | +} | ||
46 | + | ||
47 | +5. User created: | ||
48 | +{ | ||
49 | + "created_at": "2012-07-21T07:44:07Z", | ||
50 | + "email": "js@gitlabhq.com", | ||
51 | + "event_name": "user_create", | ||
52 | + "name": "John Smith" | ||
53 | +} | ||
54 | + | ||
55 | +6. User removed: | ||
56 | +{ | ||
57 | + "created_at": "2012-07-21T07:44:07Z", | ||
58 | + "email": "js@gitlabhq.com", | ||
59 | + "event_name": "user_destroy", | ||
60 | + "name": "John Smith" | ||
61 | +} | ||
62 | + | ||
63 | +eos | ||
64 | +%> | ||
65 | +<% js_lexer = Pygments::Lexer[:js] %> | ||
66 | +<%= raw js_lexer.highlight(data_ex_str) %> |
@@ -0,0 +1,39 @@ | @@ -0,0 +1,39 @@ | ||
1 | +.alert.alert-info | ||
2 | + %span | ||
3 | + Post receive hooks for binding events. | ||
4 | + %br | ||
5 | + Read more about system hooks | ||
6 | + %strong #{link_to "here", help_system_hooks_path, :class => "vlink"} | ||
7 | + | ||
8 | += form_for @hook, :as => :hook, :url => admin_hooks_path do |f| | ||
9 | + -if @hook.errors.any? | ||
10 | + .alert-message.block-message.error | ||
11 | + - @hook.errors.full_messages.each do |msg| | ||
12 | + %p= msg | ||
13 | + .clearfix | ||
14 | + = f.label :url, "URL:" | ||
15 | + .input | ||
16 | + = f.text_field :url, :class => "text_field xxlarge" | ||
17 | + | ||
18 | + = f.submit "Add System Hook", :class => "btn primary" | ||
19 | +%hr | ||
20 | + | ||
21 | +-if @hooks.any? | ||
22 | + %h3 | ||
23 | + Hooks | ||
24 | + %small (#{@hooks.count}) | ||
25 | + %br | ||
26 | + %table.admin-table | ||
27 | + %tr | ||
28 | + %th URL | ||
29 | + %th Method | ||
30 | + %th | ||
31 | + - @hooks.each do |hook| | ||
32 | + %tr | ||
33 | + %td | ||
34 | + = link_to admin_hook_path(hook) do | ||
35 | + %strong= hook.url | ||
36 | + = link_to 'Test Hook', admin_hook_test_path(hook), :class => "btn small right" | ||
37 | + %td POST | ||
38 | + %td | ||
39 | + = link_to 'Remove', admin_hook_path(hook), :confirm => 'Are you sure?', :method => :delete, :class => "danger btn small right" |
app/views/admin/logs/show.html.haml
app/views/admin/mailer/preview.html.haml
@@ -1,28 +0,0 @@ | @@ -1,28 +0,0 @@ | ||
1 | -%p This is page with preview for all system emails that are sent to user | ||
2 | -%p Email previews built based on existing Project/Commit/Issue base - so some preview maybe unavailable unless object appear in system | ||
3 | - | ||
4 | -#accordion | ||
5 | - %h3 | ||
6 | - %a New user | ||
7 | - %div | ||
8 | - %iframe{ :src=> admin_mailer_preview_user_new_path, :width=>"100%", :height=>"350"} | ||
9 | - %h3 | ||
10 | - %a New issue | ||
11 | - %div | ||
12 | - %iframe{ :src=> admin_mailer_preview_issue_new_path, :width=>"100%", :height=>"350"} | ||
13 | - %h3 | ||
14 | - %a Commit note | ||
15 | - %div | ||
16 | - %iframe{ :src=> admin_mailer_preview_note_path(:type => "Commit"), :width=>"100%", :height=>"350"} | ||
17 | - %h3 | ||
18 | - %a Issue note | ||
19 | - %div | ||
20 | - %iframe{ :src=> admin_mailer_preview_note_path(:type => "Issue"), :width=>"100%", :height=>"350"} | ||
21 | - %h3 | ||
22 | - %a Wall note | ||
23 | - %div | ||
24 | - %iframe{ :src=> admin_mailer_preview_note_path(:type => "Wall"), :width=>"100%", :height=>"350"} | ||
25 | - | ||
26 | -:javascript | ||
27 | - $(function() { | ||
28 | - $("#accordion").accordion(); }); |
app/views/admin/projects/index.html.haml
@@ -13,8 +13,8 @@ | @@ -13,8 +13,8 @@ | ||
13 | %th Team Members | 13 | %th Team Members |
14 | %th Post Receive | 14 | %th Post Receive |
15 | %th Last Commit | 15 | %th Last Commit |
16 | - %th | ||
17 | - %th | 16 | + %th Edit |
17 | + %th.cred Danger Zone! | ||
18 | 18 | ||
19 | - @admin_projects.each do |project| | 19 | - @admin_projects.each do |project| |
20 | %tr | 20 | %tr |
@@ -24,5 +24,5 @@ | @@ -24,5 +24,5 @@ | ||
24 | %td= check_box_tag :post_receive_file, 1, project.has_post_receive_file?, :disabled => true | 24 | %td= check_box_tag :post_receive_file, 1, project.has_post_receive_file?, :disabled => true |
25 | %td= last_commit(project) | 25 | %td= last_commit(project) |
26 | %td= link_to 'Edit', edit_admin_project_path(project), :id => "edit_#{dom_id(project)}", :class => "btn small" | 26 | %td= link_to 'Edit', edit_admin_project_path(project), :id => "edit_#{dom_id(project)}", :class => "btn small" |
27 | - %td= link_to 'Destroy', [:admin, project], :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger" | 27 | + %td.bgred= link_to 'Destroy', [:admin, project], :confirm => "REMOVE #{project.name}? Are you sure?", :method => :delete, :class => "btn small danger" |
28 | = paginate @admin_projects, :theme => "admin" | 28 | = paginate @admin_projects, :theme => "admin" |
app/views/admin/users/_form.html.haml
@@ -50,7 +50,7 @@ | @@ -50,7 +50,7 @@ | ||
50 | 50 | ||
51 | .alert | 51 | .alert |
52 | .clearfix | 52 | .clearfix |
53 | - %p Give user ability to manage application. | 53 | + %p Make the user a GitLab administrator. |
54 | = f.label :admin, :class => "checkbox" do | 54 | = f.label :admin, :class => "checkbox" do |
55 | = f.check_box :admin | 55 | = f.check_box :admin |
56 | %span Administrator | 56 | %span Administrator |
@@ -59,11 +59,11 @@ | @@ -59,11 +59,11 @@ | ||
59 | - if @admin_user.blocked | 59 | - if @admin_user.blocked |
60 | %span | 60 | %span |
61 | = link_to 'Unblock', unblock_admin_user_path(@admin_user), :method => :put, :class => "btn small" | 61 | = link_to 'Unblock', unblock_admin_user_path(@admin_user), :method => :put, :class => "btn small" |
62 | - This user is blocked and is not able to login GitLab | 62 | + This user is blocked and is not able to login to GitLab |
63 | - else | 63 | - else |
64 | %span | 64 | %span |
65 | = link_to 'Block', block_admin_user_path(@admin_user), :confirm => 'USER WILL BE BLOCKED! Are you sure?', :method => :put, :class => "btn small danger" | 65 | = link_to 'Block', block_admin_user_path(@admin_user), :confirm => 'USER WILL BE BLOCKED! Are you sure?', :method => :put, :class => "btn small danger" |
66 | - Blocked user will removed from all projects & will not be able to login to GitLab. | 66 | + Blocked users will be removed from all projects & will not be able to login to GitLab. |
67 | .actions | 67 | .actions |
68 | = f.submit 'Save', :class => "btn primary" | 68 | = f.submit 'Save', :class => "btn primary" |
69 | - if @admin_user.new_record? | 69 | - if @admin_user.new_record? |
app/views/admin/users/index.html.haml
@@ -27,7 +27,7 @@ | @@ -27,7 +27,7 @@ | ||
27 | %th Projects | 27 | %th Projects |
28 | %th Edit | 28 | %th Edit |
29 | %th Blocked | 29 | %th Blocked |
30 | - %th | 30 | + %th.cred Danger Zone! |
31 | 31 | ||
32 | - @admin_users.each do |user| | 32 | - @admin_users.each do |user| |
33 | %tr | 33 | %tr |
@@ -41,6 +41,6 @@ | @@ -41,6 +41,6 @@ | ||
41 | = link_to 'Unblock', unblock_admin_user_path(user), :method => :put, :class => "btn small success" | 41 | = link_to 'Unblock', unblock_admin_user_path(user), :method => :put, :class => "btn small success" |
42 | - else | 42 | - else |
43 | = link_to 'Block', block_admin_user_path(user), :confirm => 'USER WILL BE BLOCKED! Are you sure?', :method => :put, :class => "btn small danger" | 43 | = link_to 'Block', block_admin_user_path(user), :confirm => 'USER WILL BE BLOCKED! Are you sure?', :method => :put, :class => "btn small danger" |
44 | - %td= link_to 'Destroy', [:admin, user], :confirm => 'USER WILL BE REMOVED! Are you sure?', :method => :delete, :class => "btn small danger" | 44 | + %td.bgred= link_to 'Destroy', [:admin, user], :confirm => "USER #{user.name} WILL BE REMOVED! Are you sure?", :method => :delete, :class => "btn small danger" |
45 | 45 | ||
46 | = paginate @admin_users, :theme => "admin" | 46 | = paginate @admin_users, :theme => "admin" |
app/views/commits/_commits.html.haml
1 | - @commits.group_by { |c| c.committed_date.to_date }.each do |day, commits| | 1 | - @commits.group_by { |c| c.committed_date.to_date }.each do |day, commits| |
2 | %div.ui-box | 2 | %div.ui-box |
3 | - %h5= day.stamp("28 Aug, 2010") | 3 | + %h5.small |
4 | + %i.icon-calendar | ||
5 | + = day.stamp("28 Aug, 2010") | ||
4 | %ul.unstyled= render commits | 6 | %ul.unstyled= render commits |
app/views/commits/_diffs.html.haml
@@ -35,7 +35,13 @@ | @@ -35,7 +35,13 @@ | ||
35 | - if file.text? | 35 | - if file.text? |
36 | = render "commits/text_file", :diff => diff, :index => i | 36 | = render "commits/text_file", :diff => diff, :index => i |
37 | - elsif file.image? | 37 | - elsif file.image? |
38 | - .diff_file_content_image{:class => image_diff_class(diff)} | ||
39 | - %img{:src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} | 38 | + - if diff.renamed_file || diff.new_file || diff.deleted_file |
39 | + .diff_file_content_image | ||
40 | + %img{:class => image_diff_class(diff), :src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} | ||
41 | + - else | ||
42 | + - old_file = (@commit.prev_commit.tree / diff.old_path) | ||
43 | + .diff_file_content_image.img_compared | ||
44 | + %img{:class => "diff_image_removed", :src => "data:#{file.mime_type};base64,#{Base64.encode64(old_file.data)}"} | ||
45 | + %img{:class => "diff_image_added", :src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} | ||
40 | - else | 46 | - else |
41 | %p.nothing_here_message No preview for this file type | 47 | %p.nothing_here_message No preview for this file type |
app/views/commits/_head.html.haml
@@ -13,12 +13,12 @@ | @@ -13,12 +13,12 @@ | ||
13 | %li{:class => "#{branches_tab_class}"} | 13 | %li{:class => "#{branches_tab_class}"} |
14 | = link_to project_repository_path(@project) do | 14 | = link_to project_repository_path(@project) do |
15 | Branches | 15 | Branches |
16 | - %span.number= @project.repo.branch_count | 16 | + %span.badge= @project.repo.branch_count |
17 | 17 | ||
18 | %li{:class => "#{'active' if current_page?(tags_project_repository_path(@project)) }"} | 18 | %li{:class => "#{'active' if current_page?(tags_project_repository_path(@project)) }"} |
19 | = link_to tags_project_repository_path(@project) do | 19 | = link_to tags_project_repository_path(@project) do |
20 | Tags | 20 | Tags |
21 | - %span.number= @project.repo.tag_count | 21 | + %span.badge= @project.repo.tag_count |
22 | 22 | ||
23 | 23 | ||
24 | - if current_page?(project_commits_path(@project)) && current_user.private_token | 24 | - if current_page?(project_commits_path(@project)) && current_user.private_token |
app/views/commits/compare.html.haml
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | = "..." | 20 | = "..." |
21 | = text_field_tag :to, params[:to], :placeholder => "aa8b4ef", :class => "xlarge" | 21 | = text_field_tag :to, params[:to], :placeholder => "aa8b4ef", :class => "xlarge" |
22 | .actions | 22 | .actions |
23 | - = submit_tag "Compare", :class => "btn primary" | 23 | + = submit_tag "Compare", :class => "btn btn-primary" |
24 | 24 | ||
25 | 25 | ||
26 | - unless @commits.empty? | 26 | - unless @commits.empty? |
app/views/dashboard/index.atom.builder
@@ -8,17 +8,10 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear | @@ -8,17 +8,10 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear | ||
8 | 8 | ||
9 | @events.each do |event| | 9 | @events.each do |event| |
10 | if event.allowed? | 10 | if event.allowed? |
11 | + event = EventDecorator.decorate(event) | ||
11 | xml.entry do | 12 | xml.entry do |
12 | - if event.issue? | ||
13 | - event_link = project_issue_url(event.project, event.issue) | ||
14 | - event_title = event.issue_title | ||
15 | - elsif event.merge_request? | ||
16 | - event_link = project_merge_request_url(event.project, event.merge_request) | ||
17 | - event_title = event.merge_request_title | ||
18 | - elsif event.push? | ||
19 | - event_link = project_commits_url(event.project, :ref => event.ref_name) | ||
20 | - event_title = event.ref_name | ||
21 | - end | 13 | + event_link = event.feed_url |
14 | + event_title = event.feed_title | ||
22 | 15 | ||
23 | xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" | 16 | xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}" |
24 | xml.link :href => event_link | 17 | xml.link :href => event_link |
app/views/dashboard/index.html.haml
@@ -10,9 +10,10 @@ | @@ -10,9 +10,10 @@ | ||
10 | add new key | 10 | add new key |
11 | to your profile | 11 | to your profile |
12 | - if @events.any? | 12 | - if @events.any? |
13 | - = render @events | 13 | + .content_list= render @events |
14 | - else | 14 | - else |
15 | %h4.nothing_here_message Projects activity will be displayed here | 15 | %h4.nothing_here_message Projects activity will be displayed here |
16 | + .loading.hide | ||
16 | .side | 17 | .side |
17 | = render "events/event_last_push", :event => @last_push | 18 | = render "events/event_last_push", :event => @last_push |
18 | .projects_box | 19 | .projects_box |
@@ -54,3 +55,7 @@ | @@ -54,3 +55,7 @@ | ||
54 | New Project » | 55 | New Project » |
55 | - else | 56 | - else |
56 | If you will be added to project - it will be displayed here | 57 | If you will be added to project - it will be displayed here |
58 | + | ||
59 | + | ||
60 | +:javascript | ||
61 | + $(function(){ Pager.init(20); }); |
app/views/dashboard/index.js.haml
app/views/events/_event_issue.html.haml
1 | = image_tag gravatar_icon(event.author_email), :class => "avatar" | 1 | = image_tag gravatar_icon(event.author_email), :class => "avatar" |
2 | %strong #{event.author_name} | 2 | %strong #{event.author_name} |
3 | -%span.event_label= event.action_name | ||
4 | - issue | 3 | +%span.event_label{:class => event.action_name}= event.action_name |
4 | +issue | ||
5 | = link_to project_issue_path(event.project, event.issue) do | 5 | = link_to project_issue_path(event.project, event.issue) do |
6 | %strong= truncate event.issue_title | 6 | %strong= truncate event.issue_title |
7 | at | 7 | at |
app/views/events/_event_last_push.html.haml
@@ -5,12 +5,9 @@ | @@ -5,12 +5,9 @@ | ||
5 | %span Your pushed to | 5 | %span Your pushed to |
6 | = event.ref_type | 6 | = event.ref_type |
7 | = link_to project_commits_path(event.project, :ref => event.ref_name) do | 7 | = link_to project_commits_path(event.project, :ref => event.ref_name) do |
8 | - %strong= event.ref_name | 8 | + %strong= truncate(event.ref_name, :length => 28) |
9 | at | 9 | at |
10 | %strong= link_to event.project.name, event.project | 10 | %strong= link_to event.project.name, event.project |
11 | - %span.cgray | ||
12 | - = time_ago_in_words(event.created_at) | ||
13 | - ago. | ||
14 | 11 | ||
15 | = link_to new_mr_path_from_push_event(event), :title => "New Merge Request", :class => "btn very_small primary" do | 12 | = link_to new_mr_path_from_push_event(event), :title => "New Merge Request", :class => "btn very_small primary" do |
16 | Create Merge Request | 13 | Create Merge Request |
app/views/events/_event_merge_request.html.haml
@@ -2,8 +2,8 @@ | @@ -2,8 +2,8 @@ | ||
2 | .event_icon= image_tag "event_mr_merged.png" | 2 | .event_icon= image_tag "event_mr_merged.png" |
3 | = image_tag gravatar_icon(event.author_email), :class => "avatar" | 3 | = image_tag gravatar_icon(event.author_email), :class => "avatar" |
4 | %strong #{event.author_name} | 4 | %strong #{event.author_name} |
5 | -%span.event_label= event.action_name | ||
6 | - merge request | 5 | +%span.event_label{:class => event.action_name}= event.action_name |
6 | +merge request | ||
7 | = link_to project_merge_request_path(event.project, event.merge_request) do | 7 | = link_to project_merge_request_path(event.project, event.merge_request) do |
8 | %strong= truncate event.merge_request_title | 8 | %strong= truncate event.merge_request_title |
9 | at | 9 | at |
app/views/events/_event_push.html.haml
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | .event_icon= image_tag "event_push.png" | 2 | .event_icon= image_tag "event_push.png" |
3 | = image_tag gravatar_icon(event.author_email), :class => "avatar" | 3 | = image_tag gravatar_icon(event.author_email), :class => "avatar" |
4 | %strong #{event.author_name} | 4 | %strong #{event.author_name} |
5 | - %span.event_label= event.push_action_name | 5 | + %span.event_label.pushed= event.push_action_name |
6 | = event.ref_type | 6 | = event.ref_type |
7 | = link_to project_commits_path(event.project, :ref => event.ref_name) do | 7 | = link_to project_commits_path(event.project, :ref => event.ref_name) do |
8 | %strong= event.ref_name | 8 | %strong= event.ref_name |
@@ -0,0 +1,41 @@ | @@ -0,0 +1,41 @@ | ||
1 | +%h3 API | ||
2 | +.back_link | ||
3 | + = link_to help_path do | ||
4 | + ← to index | ||
5 | +%hr | ||
6 | + | ||
7 | +%ol | ||
8 | + %li | ||
9 | + %a{:href => "#README"} README | ||
10 | + %li | ||
11 | + %a{:href => "#projects"} Projects | ||
12 | + %li | ||
13 | + %a{:href => "#users"} Users | ||
14 | + | ||
15 | +.file_holder#README | ||
16 | + .file_title | ||
17 | + %i.icon-file | ||
18 | + README | ||
19 | + .file_content.wiki | ||
20 | + = preserve do | ||
21 | + = markdown File.read(Rails.root.join("doc", "api", "README.md")) | ||
22 | + | ||
23 | +%br | ||
24 | + | ||
25 | +.file_holder#projects | ||
26 | + .file_title | ||
27 | + %i.icon-file | ||
28 | + Projects | ||
29 | + .file_content.wiki | ||
30 | + = preserve do | ||
31 | + = markdown File.read(Rails.root.join("doc", "api", "projects.md")) | ||
32 | + | ||
33 | +%br | ||
34 | + | ||
35 | +.file_holder#users | ||
36 | + .file_title | ||
37 | + %i.icon-file | ||
38 | + Users | ||
39 | + .file_content.wiki | ||
40 | + = preserve do | ||
41 | + = markdown File.read(Rails.root.join("doc", "api", "users.md")) |
app/views/help/index.html.haml
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +%h3 System hooks | ||
2 | +.back_link | ||
3 | + = link_to :back do | ||
4 | + ← back | ||
5 | +%hr | ||
6 | + | ||
7 | +%p.slead | ||
8 | + Your Gitlab instance can perform HTTP POST request on next event: create_project, delete_project, create_user, delete_user, change_team_member. | ||
9 | + %br | ||
10 | + System Hooks can be used for logging or change information in LDAP server. | ||
11 | + %br | ||
12 | +%h5 Hooks request example: | ||
13 | += render "admin/hooks/data_ex" |
app/views/issues/_issues.html.haml
@@ -6,7 +6,9 @@ | @@ -6,7 +6,9 @@ | ||
6 | .row | 6 | .row |
7 | .span7= paginate @issues, :remote => true, :theme => "gitlab" | 7 | .span7= paginate @issues, :remote => true, :theme => "gitlab" |
8 | .span3.right | 8 | .span3.right |
9 | - %span.cgray.right #{@issues.total_count} issues for this filter | 9 | + %span.cgray.right |
10 | + %span.issue_counter #{@issues.total_count} | ||
11 | + issues for this filter | ||
10 | - else | 12 | - else |
11 | %li | 13 | %li |
12 | %h4.nothing_here_message Nothing to show here | 14 | %h4.nothing_here_message Nothing to show here |
app/views/issues/_show.html.haml
@@ -12,9 +12,9 @@ | @@ -12,9 +12,9 @@ | ||
12 | = issue.notes.count | 12 | = issue.notes.count |
13 | - if can? current_user, :modify_issue, issue | 13 | - if can? current_user, :modify_issue, issue |
14 | - if issue.closed | 14 | - if issue.closed |
15 | - = link_to 'Reopen', project_issue_path(issue.project, issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "btn small grouped", :remote => true | 15 | + = link_to 'Reopen', project_issue_path(issue.project, issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "btn small grouped reopen_issue", :remote => true |
16 | - else | 16 | - else |
17 | - = link_to 'Resolve', project_issue_path(issue.project, issue, :issue => {:closed => true }, :status_only => true), :method => :put, :class => "success btn small grouped", :remote => true | 17 | + = link_to 'Resolve', project_issue_path(issue.project, issue, :issue => {:closed => true }, :status_only => true), :method => :put, :class => "success btn small grouped close_issue", :remote => true |
18 | = link_to edit_project_issue_path(issue.project, issue), :class => "btn small edit-issue-link", :remote => true do | 18 | = link_to edit_project_issue_path(issue.project, issue), :class => "btn small edit-issue-link", :remote => true do |
19 | %i.icon-edit | 19 | %i.icon-edit |
20 | Edit | 20 | Edit |
@@ -35,6 +35,4 @@ | @@ -35,6 +35,4 @@ | ||
35 | | 35 | |
36 | 36 | ||
37 | - if issue.upvotes > 0 | 37 | - if issue.upvotes > 0 |
38 | - %span.badge.badge-success= "+#{issue.upvotes}" | ||
39 | - | ||
40 | - | 38 | + %span.badge.badge-success= "+#{issue.upvotes}" |
41 | \ No newline at end of file | 39 | \ No newline at end of file |
app/views/issues/index.html.haml
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | .issues_content | 2 | .issues_content |
3 | %h3.page_title | 3 | %h3.page_title |
4 | Issues | 4 | Issues |
5 | - %small (#{@issues.total_count}) | 5 | + %small (<span class=issue_counter>#{@issues.total_count}</span>) |
6 | .right | 6 | .right |
7 | .span5 | 7 | .span5 |
8 | - if can? current_user, :write_issue, @project | 8 | - if can? current_user, :write_issue, @project |
@@ -45,4 +45,4 @@ | @@ -45,4 +45,4 @@ | ||
45 | :javascript | 45 | :javascript |
46 | $(function(){ | 46 | $(function(){ |
47 | issuesPage(); | 47 | issuesPage(); |
48 | - }) | 48 | - }) |
49 | + }) | ||
49 | \ No newline at end of file | 50 | \ No newline at end of file |
app/views/keys/new.html.haml
1 | -%h3 New key | 1 | +%h3.page_title New key |
2 | %hr | 2 | %hr |
3 | = render 'form' | 3 | = render 'form' |
4 | 4 | ||
@@ -11,4 +11,4 @@ | @@ -11,4 +11,4 @@ | ||
11 | if( key_mail && key_mail.length > 0 && title.val() == '' ){ | 11 | if( key_mail && key_mail.length > 0 && title.val() == '' ){ |
12 | $('#key_title').val( key_mail ); | 12 | $('#key_title').val( key_mail ); |
13 | } | 13 | } |
14 | - }); | ||
15 | \ No newline at end of file | 14 | \ No newline at end of file |
15 | + }); |
app/views/layouts/_project_menu.html.haml
@@ -17,14 +17,14 @@ | @@ -17,14 +17,14 @@ | ||
17 | %li{:class => tab_class(:issues)} | 17 | %li{:class => tab_class(:issues)} |
18 | = link_to project_issues_filter_path(@project) do | 18 | = link_to project_issues_filter_path(@project) do |
19 | Issues | 19 | Issues |
20 | - %span.count= @project.issues.opened.count | 20 | + %span.count.issue_counter= @project.issues.opened.count |
21 | 21 | ||
22 | - if @project.repo_exists? | 22 | - if @project.repo_exists? |
23 | - if @project.merge_requests_enabled | 23 | - if @project.merge_requests_enabled |
24 | %li{:class => tab_class(:merge_requests)} | 24 | %li{:class => tab_class(:merge_requests)} |
25 | = link_to project_merge_requests_path(@project) do | 25 | = link_to project_merge_requests_path(@project) do |
26 | Merge Requests | 26 | Merge Requests |
27 | - %span.count= @project.merge_requests.opened.count | 27 | + %span.count.merge_counter= @project.merge_requests.opened.count |
28 | 28 | ||
29 | - if @project.wall_enabled | 29 | - if @project.wall_enabled |
30 | %li{:class => tab_class(:wall)} | 30 | %li{:class => tab_class(:wall)} |
app/views/layouts/admin.html.haml
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | %li{:class => tab_class(:admin_logs)} | 15 | %li{:class => tab_class(:admin_logs)} |
16 | = link_to "Logs", admin_logs_path | 16 | = link_to "Logs", admin_logs_path |
17 | %li{:class => tab_class(:admin_emails)} | 17 | %li{:class => tab_class(:admin_emails)} |
18 | - = link_to "Emails", admin_emails_path | 18 | + = link_to "Hooks", admin_hooks_path |
19 | %li{:class => tab_class(:admin_resque)} | 19 | %li{:class => tab_class(:admin_resque)} |
20 | = link_to "Resque", admin_resque_path | 20 | = link_to "Resque", admin_resque_path |
21 | 21 |
app/views/layouts/devise.html.haml
app/views/layouts/profile.html.haml
@@ -12,16 +12,17 @@ | @@ -12,16 +12,17 @@ | ||
12 | %li{:class => tab_class(:password)} | 12 | %li{:class => tab_class(:password)} |
13 | = link_to "Password", profile_password_path | 13 | = link_to "Password", profile_password_path |
14 | 14 | ||
15 | + %li{:class => tab_class(:ssh_keys)} | ||
16 | + = link_to keys_path do | ||
17 | + SSH Keys | ||
18 | + %span.count= current_user.keys.count | ||
19 | + | ||
15 | %li{:class => tab_class(:token)} | 20 | %li{:class => tab_class(:token)} |
16 | = link_to "Token", profile_token_path | 21 | = link_to "Token", profile_token_path |
17 | 22 | ||
18 | %li{:class => tab_class(:design)} | 23 | %li{:class => tab_class(:design)} |
19 | = link_to "Design", profile_design_path | 24 | = link_to "Design", profile_design_path |
20 | 25 | ||
21 | - %li{:class => tab_class(:ssh_keys)} | ||
22 | - = link_to keys_path do | ||
23 | - SSH Keys | ||
24 | - %span.count= current_user.keys.count | ||
25 | 26 | ||
26 | .content | 27 | .content |
27 | = yield | 28 | = yield |
app/views/merge_requests/_form.html.haml
@@ -5,7 +5,8 @@ | @@ -5,7 +5,8 @@ | ||
5 | - @merge_request.errors.full_messages.each do |msg| | 5 | - @merge_request.errors.full_messages.each do |msg| |
6 | %li= msg | 6 | %li= msg |
7 | 7 | ||
8 | - %h3.padded.cgray 1. Select Branches | 8 | + %h4.cdark 1. Select Branches |
9 | + %br | ||
9 | 10 | ||
10 | .row | 11 | .row |
11 | .span6 | 12 | .span6 |
@@ -30,14 +31,21 @@ | @@ -30,14 +31,21 @@ | ||
30 | .bottom_commit | 31 | .bottom_commit |
31 | .mr_target_commit | 32 | .mr_target_commit |
32 | 33 | ||
33 | - %h3.padded.cgray 2. Fill info | 34 | + %h4.cdark 2. Fill info |
35 | + | ||
34 | .clearfix | 36 | .clearfix |
35 | - = f.label :assignee_id, "Assign to", :class => "control-label" | ||
36 | - .controls= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }, :style => "width:250px") | 37 | + .main_box |
38 | + .top_box_content | ||
39 | + = f.label :title do | ||
40 | + %strong= "Title *" | ||
41 | + .input= f.text_field :title, :class => "input-xxlarge pad", :maxlength => 255, :rows => 5 | ||
42 | + .middle_box_content | ||
43 | + = f.label :assignee_id do | ||
44 | + %i.icon-user | ||
45 | + Assign to | ||
46 | + .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }, :style => "width:250px") | ||
37 | 47 | ||
38 | .control-group | 48 | .control-group |
39 | - = f.label :title, :class => "control-label" | ||
40 | - .controls= f.text_field :title, :class => "input-xxlarge pad", :maxlength => 255, :rows => 5 | ||
41 | 49 | ||
42 | .form-actions | 50 | .form-actions |
43 | = f.submit 'Save', :class => "btn-primary btn" | 51 | = f.submit 'Save', :class => "btn-primary btn" |
app/views/merge_requests/_merge_request.html.haml
@@ -15,12 +15,14 @@ | @@ -15,12 +15,14 @@ | ||
15 | → | 15 | → |
16 | = merge_request.target_branch | 16 | = merge_request.target_branch |
17 | = image_tag gravatar_icon(merge_request.author_email), :class => "avatar" | 17 | = image_tag gravatar_icon(merge_request.author_email), :class => "avatar" |
18 | + | ||
19 | + = link_to project_merge_request_path(merge_request.project, merge_request) do | ||
20 | + %p.row_title= truncate(merge_request.title, :length => 80) | ||
21 | + | ||
18 | %span.update-author | 22 | %span.update-author |
19 | - %strong= merge_request.author_name | ||
20 | - authored | 23 | + %small.cdark= "##{merge_request.id}" |
24 | + authored by #{merge_request.author_name} | ||
21 | = time_ago_in_words(merge_request.created_at) | 25 | = time_ago_in_words(merge_request.created_at) |
22 | ago | 26 | ago |
23 | - if merge_request.upvotes > 0 | 27 | - if merge_request.upvotes > 0 |
24 | %span.badge.badge-success= "+#{merge_request.upvotes}" | 28 | %span.badge.badge-success= "+#{merge_request.upvotes}" |
25 | - = link_to project_merge_request_path(merge_request.project, merge_request) do | ||
26 | - %p.row_title= truncate(merge_request.title, :length => 80) |
app/views/merge_requests/edit.html.haml
app/views/merge_requests/new.html.haml
app/views/merge_requests/show/_commits.html.haml
1 | - if @commits.present? | 1 | - if @commits.present? |
2 | .ui-box | 2 | .ui-box |
3 | - %h5 Commits (#{@commits.count}) | 3 | + %h5 |
4 | + %i.icon-list | ||
5 | + Commits (#{@commits.count}) | ||
4 | .merge-request-commits | 6 | .merge-request-commits |
5 | - if @commits.count > 8 | 7 | - if @commits.count > 8 |
6 | %ul.first_mr_commits.unstyled | 8 | %ul.first_mr_commits.unstyled |
app/views/merge_requests/show/_mr_box.html.haml
@@ -13,9 +13,10 @@ | @@ -13,9 +13,10 @@ | ||
13 | = image_tag gravatar_icon(@merge_request.author_email), :width => 16, :class => "lil_av" | 13 | = image_tag gravatar_icon(@merge_request.author_email), :width => 16, :class => "lil_av" |
14 | %strong.author= link_to_merge_request_author(@merge_request) | 14 | %strong.author= link_to_merge_request_author(@merge_request) |
15 | 15 | ||
16 | - %cite.cgray and currently assigned to | ||
17 | - = image_tag gravatar_icon(@merge_request.assignee_email), :width => 16, :class => "lil_av" | ||
18 | - %strong.author= link_to_merge_request_assignee(@merge_request) | 16 | + - if @merge_request.assignee |
17 | + %cite.cgray and currently assigned to | ||
18 | + = image_tag gravatar_icon(@merge_request.assignee_email), :width => 16, :class => "lil_av" | ||
19 | + %strong.author= link_to_merge_request_assignee(@merge_request) | ||
19 | 20 | ||
20 | 21 | ||
21 | - if @merge_request.closed | 22 | - if @merge_request.closed |
app/views/notes/_form.html.haml
app/views/notes/_per_line_form.html.haml
@@ -24,7 +24,7 @@ | @@ -24,7 +24,7 @@ | ||
24 | = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" | 24 | = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" |
25 | %span Commit author | 25 | %span Commit author |
26 | .actions | 26 | .actions |
27 | - = f.submit 'Add note', :class => "btn primary", :id => "submit_note" | 27 | + = f.submit 'Add note', :class => "btn primary submit_note", :id => "submit_note" |
28 | = link_to "Close", "#", :class => "btn hide-button" | 28 | = link_to "Close", "#", :class => "btn hide-button" |
29 | 29 | ||
30 | :javascript | 30 | :javascript |
app/views/notes/_reply_button.html.haml
1 | %tr.line_notes_row.reply | 1 | %tr.line_notes_row.reply |
2 | %td{:colspan => 3} | 2 | %td{:colspan => 3} |
3 | + %i.icon-comment | ||
3 | = link_to "Reply", "#", :class => "line_note_reply_link", "line_code" => line_code, :title => "Add note for this line" | 4 | = link_to "Reply", "#", :class => "line_note_reply_link", "line_code" => line_code, :title => "Add note for this line" |
app/views/refs/_tree.html.haml
@@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
13 | = render :partial => "refs/tree_file", :locals => { :name => tree.name, :content => tree.data, :file => tree } | 13 | = render :partial => "refs/tree_file", :locals => { :name => tree.name, :content => tree.data, :file => tree } |
14 | - else | 14 | - else |
15 | - contents = tree.contents | 15 | - contents = tree.contents |
16 | - %table#tree-slider.bordered-table.table | 16 | + %table#tree-slider.bordered-table.table{:class => "table_#{@hex_path}" } |
17 | %thead | 17 | %thead |
18 | %th Name | 18 | %th Name |
19 | %th Last Update | 19 | %th Last Update |
@@ -29,34 +29,39 @@ | @@ -29,34 +29,39 @@ | ||
29 | %td | 29 | %td |
30 | %td | 30 | %td |
31 | 31 | ||
32 | + - index = 0 | ||
32 | - contents.select{ |i| i.is_a?(Grit::Tree)}.each do |content| | 33 | - contents.select{ |i| i.is_a?(Grit::Tree)}.each do |content| |
33 | - = render :partial => "refs/tree_item", :locals => { :content => content } | 34 | + = render :partial => "refs/tree_item", :locals => { :content => content, :index => (index += 1) } |
34 | - contents.select{ |i| i.is_a?(Grit::Blob)}.each do |content| | 35 | - contents.select{ |i| i.is_a?(Grit::Blob)}.each do |content| |
35 | - = render :partial => "refs/tree_item", :locals => { :content => content } | 36 | + = render :partial => "refs/tree_item", :locals => { :content => content, :index => (index += 1) } |
36 | - contents.select{ |i| i.is_a?(Grit::Submodule)}.each do |content| | 37 | - contents.select{ |i| i.is_a?(Grit::Submodule)}.each do |content| |
37 | - = render :partial => "refs/submodule_item", :locals => { :content => content } | 38 | + = render :partial => "refs/submodule_item", :locals => { :content => content, :index => (index += 1) } |
38 | 39 | ||
39 | - if content = contents.select{ |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i }.first | 40 | - if content = contents.select{ |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i }.first |
40 | - #tree-readme-holder | ||
41 | - %h3= content.name | ||
42 | - .readme | 41 | + .file_holder#README |
42 | + .file_title | ||
43 | + %i.icon-file | ||
44 | + = content.name | ||
45 | + .file_content.wiki | ||
43 | - if content.name =~ /\.(md|markdown)$/i | 46 | - if content.name =~ /\.(md|markdown)$/i |
44 | = preserve do | 47 | = preserve do |
45 | = markdown(content.data) | 48 | = markdown(content.data) |
46 | - else | 49 | - else |
47 | = simple_format(content.data) | 50 | = simple_format(content.data) |
48 | 51 | ||
49 | -- if params[:path] | ||
50 | - - history_path = tree_file_project_ref_path(@project, @ref, params[:path]) | ||
51 | -- else | ||
52 | - - history_path = tree_project_ref_path(@project, @ref) | ||
53 | :javascript | 52 | :javascript |
54 | $(function(){ | 53 | $(function(){ |
55 | $('select#branch').selectmenu({style:'popup', width:200}); | 54 | $('select#branch').selectmenu({style:'popup', width:200}); |
56 | $('select#tag').selectmenu({style:'popup', width:200}); | 55 | $('select#tag').selectmenu({style:'popup', width:200}); |
57 | $('.project-refs-select').chosen(); | 56 | $('.project-refs-select').chosen(); |
58 | 57 | ||
59 | - history.pushState({ path: this.path }, '', "#{history_path}") | 58 | + history.pushState({ path: this.path }, '', "#{@history_path}"); |
59 | + | ||
60 | + }); | ||
61 | + | ||
62 | + // Load last commit log for each file in tree | ||
63 | + $(window).load(function(){ | ||
64 | + ajaxGet('#{@logs_path}'); | ||
60 | }); | 65 | }); |
61 | 66 | ||
62 | 67 |
app/views/refs/_tree_file.html.haml
1 | -.view_file | ||
2 | - .view_file_header | 1 | +.file_holder |
2 | + .file_title | ||
3 | %i.icon-file | 3 | %i.icon-file |
4 | %span.file_name | 4 | %span.file_name |
5 | = name | 5 | = name |
@@ -10,26 +10,28 @@ | @@ -10,26 +10,28 @@ | ||
10 | = link_to "blame", blame_file_project_ref_path(@project, @ref, :path => params[:path]), :class => "btn very_small" | 10 | = link_to "blame", blame_file_project_ref_path(@project, @ref, :path => params[:path]), :class => "btn very_small" |
11 | - if file.text? | 11 | - if file.text? |
12 | - if name =~ /\.(md|markdown)$/i | 12 | - if name =~ /\.(md|markdown)$/i |
13 | - #tree-readme-holder | ||
14 | - .readme | ||
15 | - = preserve do | ||
16 | - = markdown(file.data) | 13 | + .file_content.wiki |
14 | + = preserve do | ||
15 | + = markdown(file.data) | ||
17 | - else | 16 | - else |
18 | - .view_file_content | 17 | + .file_content.code |
19 | - unless file.empty? | 18 | - unless file.empty? |
20 | %div{:class => current_user.dark_scheme ? "black" : "white"} | 19 | %div{:class => current_user.dark_scheme ? "black" : "white"} |
21 | = preserve do | 20 | = preserve do |
22 | = raw file.colorize(options: { linenos: 'True'}) | 21 | = raw file.colorize(options: { linenos: 'True'}) |
23 | - else | 22 | - else |
24 | %h4.nothing_here_message Empty file | 23 | %h4.nothing_here_message Empty file |
24 | + | ||
25 | - elsif file.image? | 25 | - elsif file.image? |
26 | - .view_file_content_image | 26 | + .file_content.image_file |
27 | %img{ :src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} | 27 | %img{ :src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} |
28 | + | ||
28 | - else | 29 | - else |
29 | - %center | ||
30 | - = link_to blob_project_ref_path(@project, @ref, :path => params[:path]) do | ||
31 | - %div.padded | ||
32 | - %br | ||
33 | - = image_tag "download.png", :width => 64 | ||
34 | - %h3 | ||
35 | - Download (#{file.mb_size}) | 30 | + .file_content.blob_file |
31 | + %center | ||
32 | + = link_to blob_project_ref_path(@project, @ref, :path => params[:path]) do | ||
33 | + %div.padded | ||
34 | + %br | ||
35 | + = image_tag "download.png", :width => 64 | ||
36 | + %h3 | ||
37 | + Download (#{file.mb_size}) |
app/views/refs/_tree_item.html.haml
1 | -- file = params[:path] ? File.join(params[:path], content.name) : content.name | ||
2 | -- content_commit = @project.commits(@commit.id, file, 1).last | ||
3 | -- return unless content_commit | ||
4 | -%tr{ :class => "tree-item", :url => tree_file_project_ref_path(@project, @ref, file) } | 1 | +- file = tree_full_path(content) |
2 | +%tr{ :class => "tree-item #{tree_hex_class(content)}", :url => tree_file_project_ref_path(@project, @ref, file) } | ||
5 | %td.tree-item-file-name | 3 | %td.tree-item-file-name |
6 | - - if content.is_a?(Grit::Blob) | ||
7 | - - if content.text? | ||
8 | - = image_tag "file_txt.png" | ||
9 | - - elsif content.image? | ||
10 | - = image_tag "file_img.png" | ||
11 | - - else | ||
12 | - = image_tag "file_bin.png" | ||
13 | - - else | ||
14 | - = image_tag "file_dir.png" | 4 | + = tree_icon(content) |
15 | = link_to truncate(content.name, :length => 40), tree_file_project_ref_path(@project, @ref || @commit.id, file), :remote => :true | 5 | = link_to truncate(content.name, :length => 40), tree_file_project_ref_path(@project, @ref || @commit.id, file), :remote => :true |
16 | - %td.cgray | ||
17 | - = time_ago_in_words(content_commit.committed_date) | ||
18 | - ago | ||
19 | - %td.commit | ||
20 | - - tm = @project.team_member_by_name_or_email(content_commit.author_email, content_commit.author_name) | ||
21 | - - if tm | ||
22 | - %strong= link_to "[#{tm.user_name}]", project_team_member_path(@project, tm) | ||
23 | - = link_to truncate(content_commit.safe_message, :length => tm ? 30 : 50), project_commit_path(@project, content_commit.id), :class => "tree-commit-link" | 6 | + %td.tree_time_ago.cgray |
7 | + - if index == 1 | ||
8 | + %span.log_loading | ||
9 | + Loading commit data.. | ||
10 | + = image_tag "ajax_loader_tree.gif", :width => 14 | ||
11 | + %td.tree_commit |
app/views/refs/blame.html.haml
@@ -11,8 +11,8 @@ | @@ -11,8 +11,8 @@ | ||
11 | %li= link | 11 | %li= link |
12 | .clear | 12 | .clear |
13 | 13 | ||
14 | - .view_file.blame_file | ||
15 | - .view_file_header | 14 | + .file_holder |
15 | + .file_title | ||
16 | %i.icon-file | 16 | %i.icon-file |
17 | %span.file_name | 17 | %span.file_name |
18 | = @tree.name | 18 | = @tree.name |
@@ -21,7 +21,7 @@ | @@ -21,7 +21,7 @@ | ||
21 | = link_to "raw", blob_project_ref_path(@project, @ref, :path => params[:path]), :class => "btn very_small", :target => "_blank" | 21 | = link_to "raw", blob_project_ref_path(@project, @ref, :path => params[:path]), :class => "btn very_small", :target => "_blank" |
22 | = link_to "history", project_commits_path(@project, :path => params[:path], :ref => @ref), :class => "btn very_small" | 22 | = link_to "history", project_commits_path(@project, :path => params[:path], :ref => @ref), :class => "btn very_small" |
23 | = link_to "source", tree_file_project_ref_path(@project, @ref, :path => params[:path]), :class => "btn very_small" | 23 | = link_to "source", tree_file_project_ref_path(@project, @ref, :path => params[:path]), :class => "btn very_small" |
24 | - .view_file_content | 24 | + .file_content.blame |
25 | %table | 25 | %table |
26 | - @blame.each do |commit, lines| | 26 | - @blame.each do |commit, lines| |
27 | - commit = Commit.new(commit) | 27 | - commit = Commit.new(commit) |
@@ -29,7 +29,7 @@ | @@ -29,7 +29,7 @@ | ||
29 | %td.author | 29 | %td.author |
30 | = image_tag gravatar_icon(commit.author_email, 16) | 30 | = image_tag gravatar_icon(commit.author_email, 16) |
31 | = commit.author_name | 31 | = commit.author_name |
32 | - %td.commit | 32 | + %td.blame_commit |
33 | | 33 | |
34 | = link_to project_commit_path(@project, :id => commit.id) do | 34 | = link_to project_commit_path(@project, :id => commit.id) do |
35 | %code= commit.id.to_s[0..10] | 35 | %code= commit.id.to_s[0..10] |
@@ -37,8 +37,7 @@ | @@ -37,8 +37,7 @@ | ||
37 | %td.lines | 37 | %td.lines |
38 | = preserve do | 38 | = preserve do |
39 | %pre | 39 | %pre |
40 | - - lines.each do |line| | ||
41 | - = line | 40 | + = Gitlab::Encode.utf8 lines.join("\n") |
42 | 41 | ||
43 | :javascript | 42 | :javascript |
44 | $(function(){ | 43 | $(function(){ |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +- @logs.each do |content_data| | ||
2 | + - file_name = content_data[:file_name] | ||
3 | + - content_commit = content_data[:commit] | ||
4 | + - tm = @project.team_member_by_name_or_email(content_commit.author_email, content_commit.author_name) | ||
5 | + | ||
6 | + :plain | ||
7 | + var row = $("table.table_#{@hex_path} tr.file_#{hexdigest(file_name)}"); | ||
8 | + row.find("td.tree_time_ago").html('#{escape_javascript(time_ago_in_words(content_commit.committed_date))} ago'); | ||
9 | + row.find("td.tree_commit").html('#{escape_javascript(render("tree_commit", :tm => tm, :content_commit => content_commit))}'); |
app/views/refs/tree.js.haml
1 | :plain | 1 | :plain |
2 | + // Load Files list | ||
2 | $("#tree-holder").html("#{escape_javascript(render(:partial => "tree", :locals => {:repo => @repo, :commit => @commit, :tree => @tree}))}"); | 3 | $("#tree-holder").html("#{escape_javascript(render(:partial => "tree", :locals => {:repo => @repo, :commit => @commit, :tree => @tree}))}"); |
3 | $("#tree-content-holder").show("slide", { direction: "right" }, 150); | 4 | $("#tree-content-holder").show("slide", { direction: "right" }, 150); |
4 | $('.project-refs-form #path').val("#{params[:path]}"); | 5 | $('.project-refs-form #path').val("#{params[:path]}"); |
6 | + | ||
7 | + // Load last commit log for each file in tree | ||
8 | + $('#tree-slider').waitForImages(function() { | ||
9 | + ajaxGet('#{@logs_path}'); | ||
10 | + }); |
app/views/snippets/show.html.haml
@@ -7,16 +7,14 @@ | @@ -7,16 +7,14 @@ | ||
7 | = link_to "Edit", edit_project_snippet_path(@project, @snippet), :class => "btn small right" | 7 | = link_to "Edit", edit_project_snippet_path(@project, @snippet), :class => "btn small right" |
8 | 8 | ||
9 | %br | 9 | %br |
10 | -#tree-holder | ||
11 | - #tree-content-holder | ||
12 | - .view_file | ||
13 | - .view_file_header | ||
14 | - %i.icon-file | ||
15 | - %strong= @snippet.file_name | ||
16 | - %span.options | ||
17 | - = link_to "raw", raw_project_snippet_path(@project, @snippet), :class => "btn very_small", :target => "_blank" | ||
18 | - .view_file_content | ||
19 | - %div{:class => current_user.dark_scheme ? "black" : ""} | ||
20 | - = raw @snippet.colorize(options: { linenos: 'True'}) | 10 | +.file_holder |
11 | + .file_title | ||
12 | + %i.icon-file | ||
13 | + %strong= @snippet.file_name | ||
14 | + %span.options | ||
15 | + = link_to "raw", raw_project_snippet_path(@project, @snippet), :class => "btn very_small", :target => "_blank" | ||
16 | + .file_content.code | ||
17 | + %div{:class => current_user.dark_scheme ? "black" : ""} | ||
18 | + = raw @snippet.colorize(options: { linenos: 'True'}) | ||
21 | 19 | ||
22 | = render "notes/notes", :tid => @snippet.id, :tt => "snippet" | 20 | = render "notes/notes", :tid => @snippet.id, :tt => "snippet" |
config/application.rb
@@ -23,7 +23,7 @@ module Gitlab | @@ -23,7 +23,7 @@ module Gitlab | ||
23 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ] | 23 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ] |
24 | 24 | ||
25 | # Activate observers that should always be running. | 25 | # Activate observers that should always be running. |
26 | - config.active_record.observers = :mailer_observer, :activity_observer, :project_observer, :key_observer, :issue_observer, :user_observer | 26 | + config.active_record.observers = :mailer_observer, :activity_observer, :project_observer, :key_observer, :issue_observer, :user_observer, :system_hook_observer |
27 | 27 | ||
28 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. | 28 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. |
29 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. | 29 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. |
config/gitlab.yml.example
@@ -21,6 +21,8 @@ email: | @@ -21,6 +21,8 @@ email: | ||
21 | # Like default project limit for user etc | 21 | # Like default project limit for user etc |
22 | app: | 22 | app: |
23 | default_projects_limit: 10 | 23 | default_projects_limit: 10 |
24 | + # backup_path: "/vol/backups" # default: Rails.root + backups/ | ||
25 | + # backup_keep_time: 604800 # default: 0 (forever) (in seconds) | ||
24 | 26 | ||
25 | 27 | ||
26 | # | 28 | # |