Commit 4587ab6ff64a255577e02334fa0492b5edcb80ea
Exists in
master
and in
4 other branches
Merge remote-tracking branch 'upstream/master'
Showing
254 changed files
with
4947 additions
and
1607 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 254 files displayed.
... | ... | @@ -0,0 +1 @@ |
1 | +port: 3000 | ... | ... |
.gitignore
.rvmrc
... | ... | @@ -1 +0,0 @@ |
1 | -rvm use 1.9.2-p290 |
.travis.yml
CHANGELOG
1 | +v 2.1.0 | |
2 | + - Project tab r1 | |
3 | + - Repository tab r1 | |
4 | + | |
1 | 5 | v 2.0.0 |
2 | 6 | - gitolite as main git host system |
3 | 7 | - merge requests |
8 | + - project/repo access | |
9 | + - link to commit/issue feed | |
10 | + - design tab | |
11 | + - improved email notifications | |
12 | + - restyled dashboard | |
4 | 13 | - bugfix |
5 | 14 | |
6 | 15 | v 1.2.2 | ... | ... |
Gemfile
... | ... | @@ -3,9 +3,11 @@ source "http://rubygems.org" |
3 | 3 | gem "rails", "3.1.1" |
4 | 4 | |
5 | 5 | gem "sqlite3" |
6 | +gem "rake", "0.9.2.2" | |
6 | 7 | gem "devise", "1.5.0" |
7 | 8 | gem "stamp" |
8 | 9 | gem "kaminari" |
10 | +gem "haml", "3.1.4" | |
9 | 11 | gem "haml-rails" |
10 | 12 | gem "jquery-rails" |
11 | 13 | gem "grit", :git => "https://github.com/gitlabhq/grit.git" |
... | ... | @@ -15,14 +17,17 @@ gem "six" |
15 | 17 | gem "therubyracer" |
16 | 18 | gem "faker" |
17 | 19 | gem "seed-fu", "~> 2.1.0" |
18 | -gem "pygments.rb", "0.2.3" | |
20 | +gem "pygments.rb", "0.2.4" | |
19 | 21 | gem "thin" |
20 | 22 | gem "git" |
21 | 23 | gem "acts_as_list" |
22 | 24 | gem "rdiscount" |
23 | 25 | gem "acts-as-taggable-on", "~> 2.1.0" |
24 | 26 | gem "drapper" |
25 | -gem "rchardet19", "~> 1.3.5" | |
27 | +gem "resque" | |
28 | +gem "httparty" | |
29 | +gem "charlock_holmes" | |
30 | +gem "foreman" | |
26 | 31 | |
27 | 32 | group :assets do |
28 | 33 | gem "sass-rails", "~> 3.1.0" |
... | ... | @@ -47,6 +52,7 @@ group :development, :test do |
47 | 52 | gem "awesome_print" |
48 | 53 | gem "database_cleaner" |
49 | 54 | gem "launchy" |
55 | + gem "webmock" | |
50 | 56 | end |
51 | 57 | |
52 | 58 | group :test do | ... | ... |
Gemfile.lock
... | ... | @@ -77,6 +77,7 @@ GEM |
77 | 77 | xpath (~> 0.1.4) |
78 | 78 | carrierwave (0.5.8) |
79 | 79 | activesupport (~> 3.0) |
80 | + charlock_holmes (0.6.8) | |
80 | 81 | childprocess (0.2.2) |
81 | 82 | ffi (~> 1.0.6) |
82 | 83 | coffee-rails (3.1.1) |
... | ... | @@ -87,6 +88,7 @@ GEM |
87 | 88 | execjs |
88 | 89 | coffee-script-source (1.1.3) |
89 | 90 | columnize (0.3.4) |
91 | + crack (0.3.1) | |
90 | 92 | daemons (1.1.4) |
91 | 93 | database_cleaner (0.7.0) |
92 | 94 | devise (1.5.0) |
... | ... | @@ -102,8 +104,11 @@ GEM |
102 | 104 | faker (1.0.1) |
103 | 105 | i18n (~> 0.4) |
104 | 106 | ffi (1.0.11) |
107 | + foreman (0.27.0) | |
108 | + term-ansicolor (~> 1.0.5) | |
109 | + thor (>= 0.13.6) | |
105 | 110 | git (1.2.5) |
106 | - haml (3.1.3) | |
111 | + haml (3.1.4) | |
107 | 112 | haml-rails (0.3.4) |
108 | 113 | actionpack (~> 3.0) |
109 | 114 | activesupport (~> 3.0) |
... | ... | @@ -111,6 +116,9 @@ GEM |
111 | 116 | railties (~> 3.0) |
112 | 117 | hashery (1.4.0) |
113 | 118 | hike (1.2.1) |
119 | + httparty (0.8.1) | |
120 | + multi_json | |
121 | + multi_xml | |
114 | 122 | i18n (0.6.0) |
115 | 123 | jquery-rails (1.0.17) |
116 | 124 | railties (~> 3.0) |
... | ... | @@ -132,17 +140,20 @@ GEM |
132 | 140 | treetop (~> 1.4.8) |
133 | 141 | mime-types (1.17.2) |
134 | 142 | multi_json (1.0.3) |
143 | + multi_xml (0.4.1) | |
135 | 144 | nokogiri (1.5.0) |
136 | 145 | orm_adapter (0.0.5) |
137 | 146 | polyglot (0.3.3) |
138 | 147 | posix-spawn (0.3.6) |
139 | - pygments.rb (0.2.3) | |
140 | - rubypython (>= 0.5.1) | |
148 | + pygments.rb (0.2.4) | |
149 | + rubypython (~> 0.5.3) | |
141 | 150 | rack (1.3.5) |
142 | 151 | rack-cache (1.1) |
143 | 152 | rack (>= 0.4) |
144 | 153 | rack-mount (0.8.3) |
145 | 154 | rack (>= 1.0.0) |
155 | + rack-protection (1.1.4) | |
156 | + rack | |
146 | 157 | rack-ssl (1.3.2) |
147 | 158 | rack |
148 | 159 | rack-test (0.6.1) |
... | ... | @@ -165,10 +176,17 @@ GEM |
165 | 176 | rdoc (~> 3.4) |
166 | 177 | thor (~> 0.14.6) |
167 | 178 | rake (0.9.2.2) |
168 | - rchardet19 (1.3.5) | |
169 | 179 | rdiscount (1.6.8) |
170 | 180 | rdoc (3.11) |
171 | 181 | json (~> 1.4) |
182 | + redis (2.2.2) | |
183 | + redis-namespace (1.0.3) | |
184 | + redis (< 3.0.0) | |
185 | + resque (1.19.0) | |
186 | + multi_json (~> 1.0) | |
187 | + redis-namespace (~> 1.0.2) | |
188 | + sinatra (>= 0.9.2) | |
189 | + vegas (~> 0.1.2) | |
172 | 190 | rspec (2.7.0) |
173 | 191 | rspec-core (~> 2.7.0) |
174 | 192 | rspec-expectations (~> 2.7.0) |
... | ... | @@ -220,6 +238,10 @@ GEM |
220 | 238 | multi_json (~> 1.0.3) |
221 | 239 | simplecov-html (~> 0.5.3) |
222 | 240 | simplecov-html (0.5.3) |
241 | + sinatra (1.3.1) | |
242 | + rack (~> 1.3, >= 1.3.4) | |
243 | + rack-protection (~> 1.1, >= 1.1.2) | |
244 | + tilt (~> 1.3, >= 1.3.3) | |
223 | 245 | six (0.2.0) |
224 | 246 | sprockets (2.0.3) |
225 | 247 | hike (~> 1.2) |
... | ... | @@ -227,6 +249,7 @@ GEM |
227 | 249 | tilt (~> 1.1, != 1.3.0) |
228 | 250 | sqlite3 (1.3.4) |
229 | 251 | stamp (0.1.6) |
252 | + term-ansicolor (1.0.7) | |
230 | 253 | therubyracer (0.9.9) |
231 | 254 | libv8 (~> 3.3.10) |
232 | 255 | thin (1.3.1) |
... | ... | @@ -244,8 +267,13 @@ GEM |
244 | 267 | uglifier (1.1.0) |
245 | 268 | execjs (>= 0.3.0) |
246 | 269 | multi_json (>= 1.0.2) |
270 | + vegas (0.1.8) | |
271 | + rack (>= 1.0.0) | |
247 | 272 | warden (1.1.0) |
248 | 273 | rack (>= 1.0) |
274 | + webmock (1.7.8) | |
275 | + addressable (~> 2.2, > 2.2.5) | |
276 | + crack (>= 0.1.7) | |
249 | 277 | xpath (0.1.4) |
250 | 278 | nokogiri (~> 1.3) |
251 | 279 | |
... | ... | @@ -261,24 +289,29 @@ DEPENDENCIES |
261 | 289 | awesome_print |
262 | 290 | capybara |
263 | 291 | carrierwave |
292 | + charlock_holmes | |
264 | 293 | coffee-rails (~> 3.1.0) |
265 | 294 | database_cleaner |
266 | 295 | devise (= 1.5.0) |
267 | 296 | drapper |
268 | 297 | faker |
298 | + foreman | |
269 | 299 | git |
270 | 300 | gitolite! |
271 | 301 | grit! |
302 | + haml (= 3.1.4) | |
272 | 303 | haml-rails |
304 | + httparty | |
273 | 305 | jquery-rails |
274 | 306 | kaminari |
275 | 307 | launchy |
276 | 308 | letter_opener |
277 | - pygments.rb (= 0.2.3) | |
309 | + pygments.rb (= 0.2.4) | |
278 | 310 | rails (= 3.1.1) |
279 | 311 | rails-footnotes (~> 3.7.5) |
280 | - rchardet19 (~> 1.3.5) | |
312 | + rake (= 0.9.2.2) | |
281 | 313 | rdiscount |
314 | + resque | |
282 | 315 | rspec-rails |
283 | 316 | ruby-debug19 |
284 | 317 | sass-rails (~> 3.1.0) |
... | ... | @@ -292,3 +325,4 @@ DEPENDENCIES |
292 | 325 | thin |
293 | 326 | turn |
294 | 327 | uglifier |
328 | + webmock | ... | ... |
README.md
1 | 1 | # Welcome to GitLab [](https://secure.travis-ci.org/gitlabhq/gitlabhq) |
2 | 2 | |
3 | -GitLab is a free Project/Repository management application | |
4 | - | |
5 | - | |
6 | -<img src="http://gitlabhq.com/front.png" width="900" height="471"> | |
3 | +GitLab is a free project and repository management application | |
7 | 4 | |
8 | 5 | |
9 | 6 | ## Application details |
10 | 7 | |
11 | -rails 3.1 | |
12 | -works only with gitolite | |
13 | -sqlite as default a database | |
8 | +* rails 3.1 | |
9 | +* works only with gitolite | |
10 | +* sqlite as default a database | |
14 | 11 | |
15 | 12 | ## Requirements |
16 | 13 | |
... | ... | @@ -18,7 +15,7 @@ sqlite as default a database |
18 | 15 | * sqlite |
19 | 16 | * git |
20 | 17 | * gitolite |
21 | -* pygments lib - `sudo easy_install pygments` | |
18 | +* redis | |
22 | 19 | |
23 | 20 | ## Install |
24 | 21 | |
... | ... | @@ -28,13 +25,11 @@ Checkout wiki pages for installation information, migration, etc. |
28 | 25 | |
29 | 26 | [Google Group](https://groups.google.com/group/gitlabhq) |
30 | 27 | |
31 | -IRC freenode: #gitlabhq | |
32 | - | |
33 | 28 | ## Contacts |
34 | 29 | |
35 | 30 | Twitter: |
36 | 31 | |
37 | - * @gitalbhq | |
32 | + * @gitlabhq | |
38 | 33 | * @dzaporozhets |
39 | 34 | |
40 | 35 | |
... | ... | @@ -43,7 +38,5 @@ Email |
43 | 38 | |
44 | 39 | ## Contribute |
45 | 40 | |
46 | -We are on our way to full open source. | |
47 | -Want to help - create an issue on github and notify us that you are ready to start it. | |
48 | -If approved - fork, code, cover with tests & make pull request. | |
41 | +Want to help - send a pull request. | |
49 | 42 | We'll accept good pull requests. | ... | ... |
VERSION
app/assets/images/.directory
568 Bytes
561 Bytes
940 Bytes
782 Bytes
800 Bytes
789 Bytes
737 Bytes
823 Bytes
333 Bytes
723 Bytes
2.55 KB
app/assets/images/blueprint_notice.png
4.42 KB
16.5 KB
3.55 KB
app/assets/images/favicon.png
338 Bytes
app/assets/images/git.png
21.1 KB
95.7 KB
54.5 KB
app/assets/images/home.png
271 Bytes
2.93 KB
16.8 KB
app/assets/javascripts/application.js
... | ... | @@ -16,7 +16,7 @@ |
16 | 16 | //= require branch-graph |
17 | 17 | //= require_tree . |
18 | 18 | |
19 | -$(function(){ | |
19 | +$(document).ready(function(){ | |
20 | 20 | $(".one_click_select").live("click", function(){ |
21 | 21 | $(this).select(); |
22 | 22 | }); |
... | ... | @@ -27,8 +27,50 @@ $(function(){ |
27 | 27 | $(".account-box").mouseenter(showMenu); |
28 | 28 | $(".account-box").mouseleave(resetMenu); |
29 | 29 | |
30 | + $("#projects-list .project").live('click', function(e){ | |
31 | + if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") { | |
32 | + location.href = $(this).attr("url"); | |
33 | + e.stopPropagation(); | |
34 | + return false; | |
35 | + } | |
36 | + }); | |
37 | + | |
38 | + $("#issues-table .issue").live('click', function(e){ | |
39 | + if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") { | |
40 | + location.href = $(this).attr("url"); | |
41 | + e.stopPropagation(); | |
42 | + return false; | |
43 | + } | |
44 | + }); | |
45 | + | |
46 | + $(document).keypress(function(e) { | |
47 | + if( $(e.target).is(":input") ) return; | |
48 | + switch(e.which) { | |
49 | + case 115: focusSearch(); | |
50 | + e.preventDefault(); | |
51 | + } | |
52 | + }); | |
53 | + | |
30 | 54 | }); |
31 | 55 | |
56 | +function focusSearch() { | |
57 | + $("#search").focus(); | |
58 | +} | |
59 | + | |
60 | +function taggifyForm(){ | |
61 | + var tag_field = $('#tag_field').tagify(); | |
62 | + | |
63 | + tag_field.tagify('inputField').autocomplete({ | |
64 | + source: '/tags.json' | |
65 | + }); | |
66 | + | |
67 | + $('form').submit( function() { | |
68 | + var tag_field = $('#tag_field') | |
69 | + tag_field.val( tag_field.tagify('serialize') ); | |
70 | + return true; | |
71 | + }); | |
72 | +} | |
73 | + | |
32 | 74 | function updatePage(data){ |
33 | 75 | $.ajax({type: "GET", url: location.href, data: data, dataType: "script"}); |
34 | 76 | } |
... | ... | @@ -40,3 +82,5 @@ function showMenu() { |
40 | 82 | function resetMenu() { |
41 | 83 | $(this).removeClass("hover"); |
42 | 84 | } |
85 | + | |
86 | + | ... | ... |
app/assets/javascripts/commits.js
1 | -$(document).ready(function(){ | |
2 | - $(".day-commits-table li.commit").live('click', function(e){ | |
3 | - if(e.target.nodeName != "A") { | |
4 | - location.href = $(this).attr("url"); | |
5 | - e.stopPropagation(); | |
6 | - return false; | |
7 | - } | |
8 | - }); | |
9 | -}); | |
10 | - | |
11 | 1 | var CommitsList = { |
2 | + ref:null, | |
3 | + limit:0, | |
4 | + offset:0, | |
12 | 5 | |
13 | -ref:null, | |
14 | -limit:0, | |
15 | -offset:0, | |
16 | - | |
17 | -init: | |
18 | - function(ref, limit) { | |
19 | - this.ref=ref; | |
20 | - this.limit=limit; | |
21 | - this.offset=limit; | |
22 | - this.initLoadMore(); | |
23 | - $('.loading').show(); | |
24 | - }, | |
25 | - | |
26 | -getOld: | |
27 | - function() { | |
28 | - $('.loading').show(); | |
29 | - $.ajax({ | |
30 | - type: "GET", | |
31 | - url: location.href, | |
32 | - data: "limit=" + this.limit + "&offset=" + this.offset + "&ref=" + this.ref, | |
33 | - complete: function(){ $('.loading').hide()}, | |
34 | - dataType: "script"}); | |
35 | - }, | |
6 | + init: | |
7 | + function(ref, limit) { | |
8 | + $(".day-commits-table li.commit").live('click', function(e){ | |
9 | + if(e.target.nodeName != "A") { | |
10 | + location.href = $(this).attr("url"); | |
11 | + e.stopPropagation(); | |
12 | + return false; | |
13 | + } | |
14 | + }); | |
36 | 15 | |
37 | -append: | |
38 | - function(count, html) { | |
39 | - $("#commits_list").append(html); | |
40 | - if(count > 0) { | |
41 | - this.offset += count; | |
16 | + this.ref=ref; | |
17 | + this.limit=limit; | |
18 | + this.offset=limit; | |
42 | 19 | this.initLoadMore(); |
43 | - } | |
44 | - }, | |
20 | + $('.loading').show(); | |
21 | + }, | |
22 | + | |
23 | + getOld: | |
24 | + function() { | |
25 | + $('.loading').show(); | |
26 | + $.ajax({ | |
27 | + type: "GET", | |
28 | + url: location.href, | |
29 | + data: "limit=" + this.limit + "&offset=" + this.offset + "&ref=" + this.ref, | |
30 | + complete: function(){ $('.loading').hide()}, | |
31 | + dataType: "script"}); | |
32 | + }, | |
45 | 33 | |
46 | -initLoadMore: | |
47 | - function() { | |
48 | - $(window).bind('scroll', function(){ | |
49 | - if($(window).scrollTop() == $(document).height() - $(window).height()){ | |
50 | - $(window).unbind('scroll'); | |
51 | - CommitsList.getOld(); | |
34 | + append: | |
35 | + function(count, html) { | |
36 | + $("#commits_list").append(html); | |
37 | + if(count > 0) { | |
38 | + this.offset += count; | |
39 | + this.initLoadMore(); | |
52 | 40 | } |
53 | - }); | |
54 | - } | |
41 | + }, | |
42 | + | |
43 | + initLoadMore: | |
44 | + function() { | |
45 | + $(window).bind('scroll', function(){ | |
46 | + if($(window).scrollTop() == $(document).height() - $(window).height()){ | |
47 | + $(window).unbind('scroll'); | |
48 | + CommitsList.getOld(); | |
49 | + } | |
50 | + }); | |
51 | + } | |
55 | 52 | } | ... | ... |
... | ... | @@ -0,0 +1,59 @@ |
1 | +var MergeRequest = { | |
2 | + diffs_loaded: false, | |
3 | + commits_loaded: false, | |
4 | + | |
5 | + init: | |
6 | + function() { | |
7 | + $(".merge-tabs a").live("click", function() { | |
8 | + $(".merge-tabs a").removeClass("active"); | |
9 | + $(this).addClass("active"); | |
10 | + }); | |
11 | + | |
12 | + $(".merge-tabs a.merge-notes-tab").live("click", function() { | |
13 | + $(".merge-request-commits, .merge-request-diffs").hide(); | |
14 | + $(".merge-request-notes").show(); | |
15 | + }); | |
16 | + | |
17 | + $(".merge-tabs a.merge-commits-tab").live("click", function() { | |
18 | + if(!MergeRequest.commits_loaded) { | |
19 | + MergeRequest.loadCommits(); | |
20 | + } | |
21 | + $(".merge-request-notes, .merge-request-diffs").hide(); | |
22 | + $(".merge-request-commits").show(); | |
23 | + }); | |
24 | + | |
25 | + $(".merge-tabs a.merge-diffs-tab").live("click", function() { | |
26 | + if(!MergeRequest.diffs_loaded) { | |
27 | + MergeRequest.loadDiff(); | |
28 | + } | |
29 | + $(".merge-request-notes, .merge-request-commits").hide(); | |
30 | + $(".merge-request-diffs").show(); | |
31 | + }); | |
32 | + }, | |
33 | + | |
34 | + loadCommits: | |
35 | + function() { | |
36 | + $(".dashboard-loader").show(); | |
37 | + $.ajax({ | |
38 | + type: "GET", | |
39 | + url: $(".merge-commits-tab").attr("data-url"), | |
40 | + complete: function(){ | |
41 | + MergeRequest.commits_loaded = true; | |
42 | + $(".merge-request-notes, .merge-request-diffs").hide(); | |
43 | + $(".dashboard-loader").hide()}, | |
44 | + dataType: "script"}); | |
45 | + }, | |
46 | + | |
47 | + loadDiff: | |
48 | + function() { | |
49 | + $(".dashboard-loader").show(); | |
50 | + $.ajax({ | |
51 | + type: "GET", | |
52 | + url: $(".merge-diffs-tab").attr("data-url"), | |
53 | + complete: function(){ | |
54 | + MergeRequest.diffs_loaded = true; | |
55 | + $(".merge-request-notes, .merge-request-commits").hide(); | |
56 | + $(".dashboard-loader").hide()}, | |
57 | + dataType: "script"}); | |
58 | + } | |
59 | +} | ... | ... |
app/assets/javascripts/merge_requests.js.coffee
app/assets/javascripts/projects.js
1 | -$(document).ready(function(){ | |
2 | - $('#tree-slider td.tree-item-file-name a, #tree-breadcrumbs a').live("click", function() { | |
3 | - history.pushState({ path: this.path }, '', this.href) | |
4 | - }) | |
5 | - | |
6 | - $("#tree-slider tr.tree-item").live('click', function(e){ | |
7 | - if(e.target.nodeName != "A") { | |
8 | - e.stopPropagation(); | |
9 | - link = $(this).find("td.tree-item-file-name a") | |
10 | - link.click(); | |
11 | - return false; | |
12 | - } | |
13 | - }); | |
14 | - | |
15 | - $("#projects-list .project").live('click', function(e){ | |
16 | - if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") { | |
17 | - location.href = $(this).attr("url"); | |
18 | - e.stopPropagation(); | |
19 | - return false; | |
20 | - } | |
21 | - }); | |
22 | - | |
23 | - $("#issues-table .issue").live('click', function(e){ | |
24 | - if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") { | |
25 | - location.href = $(this).attr("url"); | |
26 | - e.stopPropagation(); | |
27 | - return false; | |
28 | - } | |
29 | - }); | |
30 | - | |
31 | - $(document).keypress(function(e) { | |
32 | - if( $(e.target).is(":input") ) return; | |
33 | - switch(e.which) { | |
34 | - case 115: focusSearch(); | |
35 | - e.preventDefault(); | |
1 | +var ProjectsList = { | |
2 | + limit:0, | |
3 | + offset:0, | |
4 | + | |
5 | + init: | |
6 | + function(limit) { | |
7 | + this.limit=limit; | |
8 | + this.offset=limit; | |
9 | + this.initLoadMore(); | |
10 | + }, | |
11 | + | |
12 | + getOld: | |
13 | + function() { | |
14 | + $('.loading').show(); | |
15 | + $.ajax({ | |
16 | + type: "GET", | |
17 | + url: location.href, | |
18 | + data: "limit=" + this.limit + "&offset=" + this.offset, | |
19 | + complete: function(){ $('.loading').hide()}, | |
20 | + dataType: "script"}); | |
21 | + }, | |
22 | + | |
23 | + append: | |
24 | + function(count, html) { | |
25 | + $(".tile").append(html); | |
26 | + if(count > 0) { | |
27 | + this.offset += count; | |
28 | + this.initLoadMore(); | |
29 | + } | |
30 | + }, | |
31 | + | |
32 | + initLoadMore: | |
33 | + function() { | |
34 | + $(window).bind('scroll', function(){ | |
35 | + if($(window).scrollTop() == $(document).height() - $(window).height()){ | |
36 | + $(window).unbind('scroll'); | |
37 | + $('.loading').show(); | |
38 | + ProjectsList.getOld(); | |
39 | + } | |
40 | + }); | |
36 | 41 | } |
37 | - }); | |
38 | - | |
39 | -}); | |
40 | - | |
41 | -function focusSearch() { | |
42 | - $("#search").focus(); | |
43 | 42 | } |
44 | - | |
45 | -function taggifyForm(){ | |
46 | - var tag_field = $('#tag_field').tagify(); | |
47 | - | |
48 | - tag_field.tagify('inputField').autocomplete({ | |
49 | - source: '/tags.json' | |
50 | - }); | |
51 | - | |
52 | - $('form').submit( function() { | |
53 | - var tag_field = $('#tag_field') | |
54 | - tag_field.val( tag_field.tagify('serialize') ); | |
55 | - return true; | |
56 | - }); | |
57 | -} | |
58 | - | ... | ... |
... | ... | @@ -0,0 +1,8 @@ |
1 | +function backToMembers(){ | |
2 | + $("#team_member_new").hide("slide", { direction: "right" }, 150, function(){ | |
3 | + $("#team-table").show("slide", { direction: "left" }, 150, function() { | |
4 | + $("#team_member_new").remove(); | |
5 | + $(".add_new").show(); | |
6 | + }); | |
7 | + }); | |
8 | +} | ... | ... |
... | ... | @@ -0,0 +1,27 @@ |
1 | +/** | |
2 | + * Tree slider for code browse | |
3 | + * | |
4 | + */ | |
5 | +var Tree = { | |
6 | + init: | |
7 | + function() { | |
8 | + (new Image).src = "ajax-loader-facebook.gif"; | |
9 | + | |
10 | + $('#tree-slider td.tree-item-file-name a, #tree-breadcrumbs a').live("click", function() { | |
11 | + history.pushState({ path: this.path }, '', this.href) | |
12 | + $("#tree-content-holder").hide("slide", { direction: "left" }, 150) | |
13 | + }) | |
14 | + | |
15 | + $("#tree-slider tr.tree-item").live('click', function(e){ | |
16 | + if(e.target.nodeName != "A") { | |
17 | + link = $(this).find("td.tree-item-file-name a"); | |
18 | + link.trigger("click"); | |
19 | + } | |
20 | + }); | |
21 | + | |
22 | + $('#tree-slider td.tree-item-file-name a, #tree-breadcrumbs a').live({ | |
23 | + "ajax:beforeSend": function() { $('.tree_progress').addClass("loading"); }, | |
24 | + "ajax:complete": function() { $('.tree_progress').removeClass("loading"); } | |
25 | + }); | |
26 | + } | |
27 | +} | ... | ... |
app/assets/stylesheets/application.css
... | ... | @@ -7,45 +7,5 @@ |
7 | 7 | *= require jquery-ui/jquery.tagify |
8 | 8 | *= require chosen |
9 | 9 | *= require_self |
10 | - *= require_tree . | |
10 | + *= require common | |
11 | 11 | */ |
12 | - | |
13 | -/** COLORS **/ | |
14 | -.cgray { color:gray; } | |
15 | -.cred { color:#D12F19; } | |
16 | -.cgreen { color:#44aa22; } | |
17 | - | |
18 | -/** COMMON STYLES **/ | |
19 | -.left { | |
20 | - float:left; | |
21 | -} | |
22 | -.right { | |
23 | - float:right; | |
24 | -} | |
25 | -.width-50p{ | |
26 | - width:50%; | |
27 | -} | |
28 | -.width-49p{ | |
29 | - width:49%; | |
30 | -} | |
31 | -.width-30p{ | |
32 | - width:30%; | |
33 | -} | |
34 | -.width-65p{ | |
35 | - width:65%; | |
36 | -} | |
37 | -.width-100p{ | |
38 | - width:100%; | |
39 | -} | |
40 | -.append-bottom-10 { | |
41 | - margin-bottom:10px; | |
42 | -} | |
43 | -.prepend-top-10 { | |
44 | - margin-top:10px; | |
45 | -} | |
46 | -.no-borders { | |
47 | - border:none; | |
48 | -} | |
49 | -.no-padding { | |
50 | - padding:0 !important; | |
51 | -} | ... | ... |
app/assets/stylesheets/commits.css.scss
1 | +/* Commit Page */ | |
2 | +body.project-page.commits-page .commit-info{float: right;} | |
3 | +body.project-page.commits-page .commit-info data{ | |
4 | + padding: 4px 10px; | |
5 | + font-size: 11px; | |
6 | +} | |
7 | +body.project-page.commits-page .commit-info data.commit-button{ | |
8 | + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.192, #fff), to(#f4f4f4)); | |
9 | + background-image: -webkit-linear-gradient(#fff 19.2%, #f4f4f4); | |
10 | + background-image: -moz-linear-gradient(#fff 19.2%, #f4f4f4); | |
11 | + background-image: -o-linear-gradient(#fff 19.2%, #f4f4f4); | |
12 | + box-shadow: 0 -1px 0 white inset; | |
13 | + display: block; | |
14 | + border: 1px solid #eee; | |
15 | + border-radius: 5px; | |
16 | + margin-bottom: 2px; | |
17 | + position: relative; | |
18 | + padding-right: 20px; | |
19 | +} | |
20 | + | |
21 | +body.project-page.commits-page .commit-button i{ | |
22 | + background: url('images.png') no-repeat -138px -27px; | |
23 | + width: 6px; | |
24 | + height: 9px; | |
25 | + float: right; | |
26 | + position: absolute; | |
27 | + top: 6px; | |
28 | + right: 5px; | |
29 | +} | |
30 | +body.project-page.commits-page .commits-date {display: block; width: 100%; margin-bottom: 20px} | |
31 | +body.project-page.commits-page .commits-date .data {padding: 0} | |
32 | +body.project-page.commits-page a.commit{padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} | |
33 | +body.project-page.commits-page .commits-date a.commit {padding: 10px; border-bottom: none; overflow: hidden; display: block;} | |
34 | +body.project-page.commits-page .commits-date a.commit:last-child{border-bottom: 0} | |
35 | +body.project-page.commits-page .commits-date a.commit img{float: left; margin-right: 10px;} | |
36 | +body.project-page.commits-page .commits-date a.commit span.commit-title{display: block;} | |
37 | +body.project-page.commits-page .commits-date a.commit span.commit-title{margin-bottom: 10px} | |
38 | +body.project-page.commits-page .commits-date a.commit span.commit-author{color: #999; font-weight: normal; font-style: italic;} | |
39 | +body.project-page.commits-page .commits-date a.commit span.commit-author strong{font-weight: bold; font-style: normal;} | |
40 | + | |
41 | +/* eo Commit Page */ | |
1 | 42 | /** Commit diff view **/ |
2 | 43 | .diff_file { |
3 | 44 | border:1px solid #CCC; |
... | ... | @@ -37,7 +78,7 @@ |
37 | 78 | padding:0px; |
38 | 79 | border:none; |
39 | 80 | background:#F7F7F7; |
40 | - color:#333; | |
81 | + color:#aaa; | |
41 | 82 | padding: 0px 5px; |
42 | 83 | border-right: 1px solid #ccc; |
43 | 84 | text-align:right; |
... | ... | @@ -48,6 +89,7 @@ |
48 | 89 | float:left; |
49 | 90 | width:35px; |
50 | 91 | font-weight:normal; |
92 | + color:#aaa; | |
51 | 93 | &:hover { |
52 | 94 | text-decoration:underline; |
53 | 95 | } |
... | ... | @@ -96,3 +138,54 @@ ul.bordered-list { |
96 | 138 | } |
97 | 139 | |
98 | 140 | ul.bordered-list li:last-child { border:none } |
141 | + | |
142 | +.line_holder { | |
143 | + &:hover { | |
144 | + td { | |
145 | + background: #FFFFCF !important; | |
146 | + } | |
147 | + } | |
148 | +} | |
149 | + | |
150 | +.per_line_form { | |
151 | + font-family: "Helvetica", sans-serif; | |
152 | + background: #2FA0BB; | |
153 | + | |
154 | + td { | |
155 | + padding:0; | |
156 | + } | |
157 | + | |
158 | + form { | |
159 | + margin:5px; | |
160 | + width: 756px; | |
161 | + border: 1px solid #CCC; | |
162 | + padding: 20px; | |
163 | + background: white; | |
164 | + } | |
165 | +} | |
166 | + | |
167 | + | |
168 | +tr.line_notes_row { | |
169 | + font-family: "Helvetica", sans-serif; | |
170 | + &:hover { | |
171 | + background:none; | |
172 | + } | |
173 | + td { | |
174 | + margin:0px; | |
175 | + padding:0px; | |
176 | + border-bottom:1px solid #DEE2E3; | |
177 | + | |
178 | + | |
179 | + ul { | |
180 | + display:block; | |
181 | + list-style:none; | |
182 | + margin:0px; | |
183 | + padding:0px; | |
184 | + | |
185 | + li { | |
186 | + border-top:1px solid #DEE2E3; | |
187 | + padding:10px; | |
188 | + } | |
189 | + } | |
190 | + } | |
191 | +} | ... | ... |
... | ... | @@ -0,0 +1,115 @@ |
1 | +$text_color:#222; | |
2 | +$lite_text_color: #666; | |
3 | +$link_color:#111; | |
4 | +$active_link_color:#2FA0BB; | |
5 | +$active_bg_color:#79C3E0; | |
6 | +$active_bd_color: #2FA0BB; | |
7 | +$border_color:#CCC; | |
8 | +$lite_border_color:#EEE; | |
9 | +$app_width:980px; | |
10 | +$app_padding:20px; | |
11 | +$bg_color: #FFF; | |
12 | +$styled_border_color: #2FA0BB; | |
13 | + | |
14 | +/** MIXINS **/ | |
15 | +@mixin round-borders-bottom($radius) { | |
16 | + border-top: 1px solid #eaeaea; | |
17 | + -moz-border-radius-bottomright: $radius; | |
18 | + -moz-border-radius-bottomleft: $radius; | |
19 | + border-bottom-right-radius: $radius; | |
20 | + border-bottom-left-radius: $radius; | |
21 | + -webkit-border-bottom-left-radius: $radius; | |
22 | + -webkit-border-bottom-right-radius: $radius; | |
23 | +} | |
24 | + | |
25 | +@mixin round-borders-top($radius) { | |
26 | + border-top: 1px solid #eaeaea; | |
27 | + -moz-border-radius-topright: $radius; | |
28 | + -moz-border-radius-topleft: $radius; | |
29 | + border-top-right-radius: $radius; | |
30 | + border-top-left-radius: $radius; | |
31 | + -webkit-border-top-left-radius: $radius; | |
32 | + -webkit-border-top-right-radius: $radius; | |
33 | +} | |
34 | + | |
35 | +@mixin round-borders-all($radius) { | |
36 | + border: 1px solid #eaeaea; | |
37 | + -moz-border-radius: $radius; | |
38 | + -webkit-border-radius: $radius; | |
39 | + border-radius: $radius; | |
40 | +} | |
41 | + | |
42 | +/** COLORS **/ | |
43 | +.cgray { color:gray; } | |
44 | +.cred { color:#D12F19; } | |
45 | +.cgreen { color:#44aa22; } | |
46 | + | |
47 | +/** COMMON STYLES **/ | |
48 | +.left { | |
49 | + float:left; | |
50 | +} | |
51 | +.right { | |
52 | + float:right; | |
53 | +} | |
54 | +.width-50p{ | |
55 | + width:50%; | |
56 | +} | |
57 | +.width-49p{ | |
58 | + width:49%; | |
59 | +} | |
60 | +.width-30p{ | |
61 | + width:30%; | |
62 | +} | |
63 | +.width-65p{ | |
64 | + width:65%; | |
65 | +} | |
66 | +.width-100p{ | |
67 | + width:100%; | |
68 | +} | |
69 | +.append-bottom-10 { | |
70 | + margin-bottom:10px; | |
71 | +} | |
72 | +.append-bottom-20 { | |
73 | + margin-bottom:20px; | |
74 | +} | |
75 | +.prepend-top-10 { | |
76 | + margin-top:10px; | |
77 | +} | |
78 | +.no-borders { | |
79 | + border:none; | |
80 | +} | |
81 | +.no-padding { | |
82 | + padding:0 !important; | |
83 | +} | |
84 | + | |
85 | +/* General */ | |
86 | + | |
87 | +body.collapsed { | |
88 | + background-color: $bg_color; | |
89 | + | |
90 | + #container{ | |
91 | + margin: auto; | |
92 | + margin-top:51px; | |
93 | + width: $app_width; | |
94 | + border-top: 0; | |
95 | + background-color: $bg_color; | |
96 | + } | |
97 | +} | |
98 | + | |
99 | +a { | |
100 | + color: $link_color; | |
101 | +} | |
102 | + | |
103 | +@import "style.scss"; | |
104 | +@import "projects.css.scss"; | |
105 | +@import "commits.css.scss"; | |
106 | +@import "notes.css.scss"; | |
107 | +@import "merge_requests.css.scss"; | |
108 | +@import "highlight.css.scss"; | |
109 | +@import "highlight.black.css.scss"; | |
110 | +@import "issues.css.scss"; | |
111 | +@import "commits.css.scss"; | |
112 | + | |
113 | +@import "top_panel.scss"; | |
114 | +@import "dashboard.scss"; | |
115 | +@import "tree.scss"; | ... | ... |
... | ... | @@ -0,0 +1,30 @@ |
1 | +body.dashboard-page h2.icon span{ background-position: 9px -69px; } | |
2 | +body.dashboard-page header{margin-bottom: 0} | |
3 | +body.dashboard-page .news-feed{margin-left: 285px; min-height: 600px; margin-top: 20px; margin-right:2px; padding:20px;} | |
4 | +body.dashboard-page .dashboard-content{ position: relative; float: left; width: 100%; height: 100%; } | |
5 | +body.dashboard-page .news-feed h2{float: left;} | |
6 | + | |
7 | +body.dashboard-page aside{ | |
8 | + min-height: 820px; position: relative; top: 0; bottom: 0; right: 0; width: 260px; float: left; border-right: 1px solid $border_color; padding:20px; padding-right:0; | |
9 | + h4{margin: 0; border-bottom: 1px solid #ccc; padding: 20px 20px 20px 0px; font-size: 11px; font-weight: bold; text-transform: uppercase;} | |
10 | + h4 a.button-small{float: right; text-transform: none; border-radius: 4px; margin-right: 2%; margin-top: -4px; display: block;} | |
11 | + .project-list {list-style: none; margin: 0; padding: 0;} | |
12 | + .project-list li a {background: white; color: #{$blue_link}; display: block; border-bottom: 1px solid $lite_border_color; padding: 14px 6% 14px 0px;} | |
13 | + .project-list li a span.project-name{font-size: 14px; display: block; margin-bottom: 8px} | |
14 | + .project-list li a span.time{color: #666; font-weight: normal; font-size: 11px} | |
15 | + .project-list li a span.arrow{float: right; background: #E3E5EA; padding: 10px; border-radius: 5px; margin-top: 2px; text-shadow: none; color: #999} | |
16 | +} | |
17 | + | |
18 | +body.dashboard-page .news-feed .project-updates { | |
19 | + margin-bottom: 20px; display: block; width: 100%; | |
20 | + .data{ padding: 0} | |
21 | + a.project-update {padding: 10px; overflow: hidden; display: block;} | |
22 | + a.project-update:last-child{border-bottom: 0} | |
23 | + a.project-update img{float: left; margin-right: 10px;} | |
24 | + a.project-update span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;} | |
25 | + a.project-update span.update-title{margin-bottom: 10px} | |
26 | + a.project-update span.update-author{color: #999; font-weight: normal; font-style: italic;} | |
27 | + a.project-update span.update-author strong{font-weight: bold; font-style: normal;} | |
28 | +} | |
29 | +/* eo Dashboard Page */ | |
30 | + | ... | ... |
app/assets/stylesheets/issues.css.scss
... | ... | @@ -11,8 +11,8 @@ |
11 | 11 | } |
12 | 12 | |
13 | 13 | .issues_filter { |
14 | - margin-top:10px; | |
15 | - .left { | |
14 | + margin:10px 0; | |
15 | + .left { | |
16 | 16 | margin-right:15px; |
17 | 17 | } |
18 | 18 | } |
... | ... | @@ -72,3 +72,13 @@ body.project-page .edit_snippet table td |
72 | 72 | } |
73 | 73 | } |
74 | 74 | |
75 | + | |
76 | +#issues-table { | |
77 | + tr { | |
78 | + border-top: 1px solid $lite_border_color; | |
79 | + &:first-child { | |
80 | + border:none; | |
81 | + } | |
82 | + } | |
83 | + | |
84 | +} | ... | ... |
app/assets/stylesheets/notes.css.scss
app/assets/stylesheets/projects.css.scss
1 | -/** MIXINS **/ | |
2 | -@mixin round-borders-bottom($radius) { | |
3 | - border-top: 1px solid #eaeaea; | |
4 | - -moz-border-radius-bottomright: $radius; | |
5 | - -moz-border-radius-bottomleft: $radius; | |
6 | - border-bottom-right-radius: $radius; | |
7 | - border-bottom-left-radius: $radius; | |
8 | - -webkit-border-bottom-left-radius: $radius; | |
9 | - -webkit-border-bottom-right-radius: $radius; | |
10 | -} | |
11 | - | |
12 | -@mixin round-borders-top($radius) { | |
13 | - border-top: 1px solid #eaeaea; | |
14 | - -moz-border-radius-topright: $radius; | |
15 | - -moz-border-radius-topleft: $radius; | |
16 | - border-top-right-radius: $radius; | |
17 | - border-top-left-radius: $radius; | |
18 | - -webkit-border-top-left-radius: $radius; | |
19 | - -webkit-border-top-right-radius: $radius; | |
20 | -} | |
21 | - | |
22 | -@mixin round-borders-all($radius) { | |
23 | - border: 1px solid #eaeaea; | |
24 | - -moz-border-radius: $radius; | |
25 | - -webkit-border-radius: $radius; | |
26 | - border-radius: $radius; | |
1 | +body.project-page h2.icon .project-name, body.project-page h2.icon d{border: 1px solid #eee; padding: 5px 30px 5px 10px; border-radius: 5px; position: relative;} | |
2 | +body.project-page h2.icon .project-name i.arrow{float: right; | |
3 | + position: absolute; | |
4 | + right: 10px; | |
5 | + top: 13px; | |
6 | + display: block; | |
7 | + background: url('images.png') no-repeat -97px -29px; | |
8 | + width: 4px; | |
9 | + height: 5px; | |
10 | +} | |
11 | + | |
12 | +body.project-page h2.icon span{ background-position: -78px -68px; } | |
13 | +body.project-page .project-container{ position: relative; float: left; width: 100%; height: 100%; padding-bottom: 10px;} | |
14 | +body.project-page .page-title{margin-bottom: 0} | |
15 | + | |
16 | +body.project-page .project-sidebar { | |
17 | + width: 110px; | |
18 | + left: 0; | |
19 | + top: 0; | |
20 | + height: 100%; | |
21 | + bottom: 0; | |
22 | + position: absolute; | |
23 | + float: left; | |
24 | + display: inline-block; | |
25 | + background: #FFF; | |
26 | + padding: $app_padding; | |
27 | + padding-right:0px; | |
28 | + margin: 0; | |
29 | + border-right: 1px solid $border_color; | |
30 | +} | |
31 | + | |
32 | +body.projects-page input.text.git-url { font-size: 12px; border-radius: 5px; color: #666; box-shadow: 0 1px 2px rgba(0,0,0,.2) inset; padding: 8px 0 8px 30px; margin-bottom: 20px; background: white url('images.png') no-repeat 8px -40px; width: 136px} | |
33 | +body.projects-page input.text.git-url {margin:10px 0 0 } | |
34 | +.git_url_wrapper { margin-right:50px } | |
35 | + | |
36 | +.projects_selector:hover > .project-box{ -moz-box-shadow:0px 0px 10px rgba(0, 0, 0, .1); -webkit-box-shadow:0px 0px 10px rgba(0, 0, 0, .1); box-shadow:0px 0px 10px rgba(0, 0, 0, .1); } | |
37 | + | |
38 | + | |
39 | +/* New project Page */ | |
40 | +.new-project-page .container table{background: white} | |
41 | +body.project-page .project-sidebar aside{width: 109px} | |
42 | +body.project-page .project-sidebar aside a{ | |
43 | + display: block; | |
44 | + position: relative; | |
45 | + padding: 15px 10px; | |
46 | + margin: 10px 0 0 0; | |
47 | + | |
48 | + | |
27 | 49 | } |
50 | +body.project-page .project-sidebar aside a span.number{float: right; border-radius: 5px; text-shadow: none; background: rgba(0,0,0,.12); text-align: center; padding: 5px 8px; position: absolute; top: 10px; right: 10px} | |
51 | +body.project-page .project-sidebar aside a.current { | |
52 | + color: white; | |
53 | + background: $active_bg_color; | |
54 | + border: 1px solid $active_bd_color; | |
55 | + border-radius:5px; | |
56 | + | |
57 | + | |
58 | + -webkit-border-top-right-radius: 0; | |
59 | + -webkit-border-bottom-right-radius: 0; | |
60 | + -moz-border-radius-topright: 0px; | |
61 | + -moz-border-radius-bottomright: 0px; | |
62 | + border-top-right-radius: 0; | |
63 | + border-bottom-right-radius: 0; | |
64 | + margin-right: -1px; | |
65 | +} | |
66 | +body.project-page .project-content{ padding: $app_padding; display: block; margin-left: 130px; min-height: 600px} | |
67 | +body.project-page .project-content h2{ margin-top: 6px} | |
68 | +body.project-page .project-content .button.right{margin-left: 20px} | |
69 | +body.project-page table .commit a{color: #{$blue_link}} | |
70 | +body.project-page table th, body.project-page table td{ border-bottom: 1px solid #DEE2E3;} | |
71 | +body.project-page .fixed{position: fixed; } | |
72 | + | |
73 | + | |
74 | + | |
28 | 75 | |
29 | 76 | /** File stat **/ |
30 | 77 | .file_stats { |
... | ... | @@ -48,90 +95,7 @@ table.round-borders { |
48 | 95 | text-align: left; |
49 | 96 | } |
50 | 97 | |
51 | -a { | |
52 | - color: #111; | |
53 | -} | |
54 | - | |
55 | -/** FILE CONTENT VIEW **/ | |
56 | -.view_file_content{ | |
57 | - .old_line, .new_line { | |
58 | - background:#ECECEC; | |
59 | - color:#777; | |
60 | - width:15px; | |
61 | - float:left; | |
62 | - padding: 0px 10px; | |
63 | - border-right: 1px solid #ccc; | |
64 | - } | |
65 | - .old_line{ | |
66 | - display:none; | |
67 | - } | |
68 | -} | |
69 | - | |
70 | -.view_file .view_file_header, | |
71 | -.diff_file .diff_file_header { | |
72 | - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); | |
73 | - background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
74 | - background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
75 | - background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
76 | - margin: 0; | |
77 | - font-weight: normal; | |
78 | - font-weight: bold; | |
79 | - text-align: left; | |
80 | - color: #666; | |
81 | - border-bottom: 1px solid #DEE2E3; | |
82 | - padding: 7px 10px; | |
83 | -} | |
84 | - | |
85 | -.view_file { | |
86 | - border:1px solid #CCC; | |
87 | - margin-bottom:1em; | |
88 | - | |
89 | - .view_file_content { | |
90 | - background:#fff; | |
91 | - color:#514721; | |
92 | - font-size: 11px; | |
93 | - } | |
94 | - .view_file_content_image { | |
95 | - background:#eee; | |
96 | - text-align:center; | |
97 | - img { | |
98 | - padding:100px; | |
99 | - max-width:300px; | |
100 | - } | |
101 | - } | |
102 | -} | |
103 | - | |
104 | -td.code { | |
105 | - width: 100%; | |
106 | - .highlight { | |
107 | - margin-left: 55px; | |
108 | - overflow:auto; | |
109 | - overflow-y:hidden; | |
110 | - border-left: 1px solid #DEE2E3; | |
111 | - background: white; | |
112 | - } | |
113 | -} | |
114 | -.highlight pre { | |
115 | - white-space: pre; | |
116 | - word-wrap:normal; | |
117 | -} | |
118 | - | |
119 | -table.highlighttable { | |
120 | - border: none; | |
121 | - background: #F7F7F7; | |
122 | -} | |
123 | -body.project-page table.highlighttable td { border: none } | |
124 | -table.highlighttable tr:hover { background:none;} | |
125 | 98 | |
126 | -table.highlighttable pre{ | |
127 | - line-height:16px !important; | |
128 | - font-size:12px !important; | |
129 | -} | |
130 | - | |
131 | -table.highlighttable .linenodiv pre { | |
132 | - text-align: right; | |
133 | - padding-right: 4px; | |
134 | -} | |
135 | 99 | |
136 | 100 | /** PROJECTS **/ |
137 | 101 | input.ssh_project_url { |
... | ... | @@ -157,61 +121,6 @@ input.ssh_project_url { |
157 | 121 | clear: both; |
158 | 122 | } |
159 | 123 | |
160 | -/** FORM INPUTS **/ | |
161 | -.new_merge_request, | |
162 | -.edit_merge_request, | |
163 | -.user_new, | |
164 | -.new_key, | |
165 | -.new_issue, | |
166 | -.new_note, | |
167 | -.edit_user, | |
168 | -.edit_issue, | |
169 | -.new_project, | |
170 | -.new_snippet, | |
171 | -.edit_snippet, | |
172 | -.edit_project { | |
173 | - input[type='text'], | |
174 | - input[type='email'], | |
175 | - input[type='password'], | |
176 | - textarea { | |
177 | - width:400px; | |
178 | - padding:8px; | |
179 | - font-size:14px; | |
180 | - @include round-borders-all(4px); | |
181 | - } | |
182 | -} | |
183 | - | |
184 | -.input_button { | |
185 | - padding:8px; | |
186 | - font-size:14px; | |
187 | - cursor:pointer; | |
188 | - background-color: #F5F5F5; | |
189 | - border-color: #EEEEEE #DEDEDE #DEDEDE #EEEEEE; | |
190 | - border-right: 1px solid #DEDEDE; | |
191 | - border-style: solid; | |
192 | - border-width: 1px; | |
193 | -} | |
194 | - | |
195 | -/** FLASH **/ | |
196 | -#flash_container { | |
197 | - height:45px; | |
198 | - position:fixed; | |
199 | - z-index:10001; | |
200 | - top:0px; | |
201 | - width:100%; | |
202 | - margin-bottom:15px; | |
203 | - overflow:hidden; | |
204 | - background:white; | |
205 | - cursor:pointer; | |
206 | - border-bottom:1px solid #777; | |
207 | - | |
208 | - h4 { | |
209 | - color:#444; | |
210 | - font-size:22px; | |
211 | - padding-top:5px; | |
212 | - margin:2px; | |
213 | - } | |
214 | -} | |
215 | 124 | |
216 | 125 | /** Buttons **/ |
217 | 126 | .lbutton, |
... | ... | @@ -270,7 +179,7 @@ input.ssh_project_url { |
270 | 179 | |
271 | 180 | body.project-page table .commit { |
272 | 181 | a.tree-commit-link { |
273 | - color:gray; | |
182 | + color:#444; | |
274 | 183 | &:hover { |
275 | 184 | text-decoration:underline; |
276 | 185 | } |
... | ... | @@ -331,7 +240,7 @@ body.project-page table .commit { |
331 | 240 | border:none; |
332 | 241 | text-shadow:none; |
333 | 242 | |
334 | - &.inline { | |
243 | + &.inline { | |
335 | 244 | display:inline; |
336 | 245 | } |
337 | 246 | |
... | ... | @@ -358,8 +267,12 @@ body.project-page table .commit { |
358 | 267 | color:white; |
359 | 268 | } |
360 | 269 | &.note { |
361 | - background: #2c5c66; | |
362 | - color:white; | |
270 | + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); | |
271 | + background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
272 | + background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
273 | + background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
274 | + color: #777; | |
275 | + border: 1px solid #DEDFE1; | |
363 | 276 | } |
364 | 277 | &.issue { |
365 | 278 | background: #D12F19; |
... | ... | @@ -376,7 +289,8 @@ body.project-page table .commit { |
376 | 289 | } |
377 | 290 | |
378 | 291 | #holder { |
379 | - border: solid 1px #999; | |
292 | + background:#FAFAFA; | |
293 | + border: 1px solid #EEE; | |
380 | 294 | cursor: move; |
381 | 295 | height: 70%; |
382 | 296 | overflow: hidden; |
... | ... | @@ -428,55 +342,35 @@ body.project-page .team_member_new .span-6, .team_member_edit .span-6{ padding:1 |
428 | 342 | body.projects-page input.text.git-url.project_list_url { width:165px; } |
429 | 343 | |
430 | 344 | |
345 | +body.project-page table.no-borders th { | |
346 | + background:none; | |
347 | + border-bottom:1px solid #CCC; | |
348 | + color:#333; | |
349 | +} | |
431 | 350 | |
432 | 351 | body.project-page table.no-borders tr, |
433 | -body.project-page table.no-borders td{ | |
352 | +body.project-page table.no-borders td{ | |
434 | 353 | border:none; |
435 | 354 | } |
436 | 355 | |
437 | -#gitlab-tabs { | |
438 | - .ui-tabs-nav { | |
439 | - border-bottom: 1px solid #DEDFE1; | |
440 | - | |
441 | - li { | |
442 | - background: none; | |
443 | - border:none; | |
444 | - font-size: 16px; | |
445 | - margin: 0; | |
446 | - padding: 0; | |
447 | - | |
448 | - a { | |
449 | - margin: 0; | |
450 | - padding: 10px 16px; | |
451 | - width:150px; | |
452 | - } | |
453 | - | |
454 | - &.ui-tabs-selected { | |
455 | - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); | |
456 | - background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
457 | - background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
458 | - background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
459 | - font-weight: bold; | |
460 | - border:1px solid #DEDFE1; | |
461 | - border-bottom: 1px solid #DEDFE1; | |
462 | - -webkit-border-top-left-radius: 5px; | |
463 | - -webkit-border-top-right-radius: 5px; | |
464 | - -moz-border-radius-topleft: 5px; | |
465 | - -moz-border-radius-topright: 5px; | |
466 | - border-top-left-radius: 5px; | |
467 | - border-top-right-radius: 5px; | |
468 | - } | |
469 | - } | |
470 | - } | |
471 | -} | |
472 | - | |
473 | -.ajax-tab-loading { | |
356 | +.ajax-tab-loading { | |
474 | 357 | padding:40px; |
475 | 358 | display:none; |
476 | 359 | } |
477 | 360 | |
478 | 361 | #tree-content-holder { float:left; width:100%; } |
479 | 362 | |
363 | +#tree-readme-holder { | |
364 | + float:left; | |
365 | + width:100%; | |
366 | + | |
367 | + .readme { | |
368 | + @include round-borders-all(4px); | |
369 | + padding: 4px 15px; | |
370 | + background:#F7F7F7; | |
371 | + } | |
372 | +} | |
373 | + | |
480 | 374 | |
481 | 375 | |
482 | 376 | /* Commit Page */ |
... | ... | @@ -506,3 +400,173 @@ body.project-page table.no-borders td{ |
506 | 400 | top: 6px; |
507 | 401 | right: 5px; |
508 | 402 | } |
403 | +.box-arrow{float: right; background: #E3E5EA; padding: 10px; border-radius: 5px; margin-top: 2px; text-shadow: none; color: #999; margin: 1.5em 0;} | |
404 | + | |
405 | +h4.dash-tabs { | |
406 | + margin: 0; | |
407 | + border-bottom: 1px solid #ccc; | |
408 | + padding: 10px 10px; | |
409 | + font-size: 11px; | |
410 | + padding-left:20px; | |
411 | + font-weight: bold; text-transform: uppercase; | |
412 | + background: #F7F7F7; | |
413 | + margin-bottom:20px; | |
414 | + height:13px; | |
415 | + | |
416 | +} | |
417 | + | |
418 | +.dash-button { | |
419 | + border-right: 1px solid #ddd; | |
420 | + background:none; | |
421 | + padding: 10px 15px; | |
422 | + float:left; | |
423 | + position:relative; | |
424 | + top:-10px; | |
425 | + left:0px; | |
426 | + height:13px; | |
427 | + | |
428 | + &:first-child { | |
429 | + border-left: 1px solid #ddd; | |
430 | + } | |
431 | + &.active { | |
432 | + background: #eaeaea; | |
433 | + } | |
434 | +} | |
435 | + | |
436 | + | |
437 | +.dashboard-loader { | |
438 | + float:right; | |
439 | + margin-right:30px; | |
440 | + display:none; | |
441 | +} | |
442 | + | |
443 | + | |
444 | +.merge-tabs { | |
445 | + margin: 0; | |
446 | + border: 1px solid #ccc; | |
447 | + padding: 5px; | |
448 | + font-size: 12px; | |
449 | + background: #F7F7F7; | |
450 | + margin-bottom:20px; | |
451 | + height:26px; | |
452 | + | |
453 | + -moz-border-radius: 4px; | |
454 | + -webkit-border-radius: 4px; | |
455 | + border-radius: 4px; | |
456 | + | |
457 | + .tab { | |
458 | + font-weight: bold; | |
459 | + border-right: 1px solid #ddd; | |
460 | + background:none; | |
461 | + padding: 10px; | |
462 | + min-width:60px; | |
463 | + float:left; | |
464 | + position:relative; | |
465 | + top:-5px; | |
466 | + left:-5px; | |
467 | + height:16px; | |
468 | + padding-left:34px; | |
469 | + | |
470 | + span { | |
471 | + width: 20px; | |
472 | + height: 20px; | |
473 | + display: inline-block; | |
474 | + position: absolute; | |
475 | + left: 8px; | |
476 | + top: 8px; | |
477 | + } | |
478 | + | |
479 | + &.active { | |
480 | + background: #eaeaea; | |
481 | + } | |
482 | + } | |
483 | +} | |
484 | +.merge-tabs.repository .tab span{ background: url("images.png") no-repeat -38px -77px; } | |
485 | +.activities-tab span { background: url("images.png") no-repeat -161px -1px; } | |
486 | +.stat-tab span, | |
487 | +.team-tab span, | |
488 | +.snippets-tab span { background: url("images.png") no-repeat -38px -77px; } | |
489 | +.files-tab span { background: url("images.png") no-repeat -112px -23px; } | |
490 | + | |
491 | +.merge-notes-tab span { background: url("images.png") no-repeat -161px -1px; } | |
492 | +.merge-commits-tab span { background: url("images.png") no-repeat -86px 1px; } | |
493 | +.merge-diffs-tab span { background: url("images.png") no-repeat -118px 1px; } | |
494 | +.merge-tabs .dashboard-loader { padding:8px; } | |
495 | + | |
496 | +.user-mention { | |
497 | + color: #2FA0BB; | |
498 | + font-weight: bold; | |
499 | +} | |
500 | + | |
501 | +.author { | |
502 | + color: #999; | |
503 | +} | |
504 | + | |
505 | + | |
506 | +.red-button{ | |
507 | + border-radius: 5px; | |
508 | + font-size: 12px; | |
509 | + font-weight: bold; | |
510 | + padding: 5px 17px; | |
511 | + border: 1px solid #999; | |
512 | + color: #666; | |
513 | + display: inline-block; | |
514 | + box-shadow: 0 1px 2px rgba(0,0,0,.3); | |
515 | + background: #D12F19; | |
516 | + color: white; | |
517 | +} | |
518 | + | |
519 | +.positive-button{ | |
520 | + border-radius: 5px; | |
521 | + font-size: 12px; | |
522 | + font-weight: bold; | |
523 | + padding: 5px 17px; | |
524 | + border: 1px solid #999; | |
525 | + color: #666; | |
526 | + display: inline-block; | |
527 | + box-shadow: 0 1px 2px rgba(0,0,0,.3); | |
528 | + background: #4A2; | |
529 | + color: white; | |
530 | +} | |
531 | + | |
532 | + | |
533 | +.dark_scheme_box { | |
534 | + padding:20px 0; | |
535 | + | |
536 | + label { | |
537 | + float:left; | |
538 | + box-shadow: 0 0px 5px rgba(0,0,0,.3); | |
539 | + | |
540 | + img { | |
541 | + } | |
542 | + } | |
543 | +} | |
544 | + | |
545 | +a.project-update.titled { | |
546 | + position: relative; | |
547 | + padding-left: 235px !important; | |
548 | + | |
549 | + .title-block { | |
550 | + padding: 10px; | |
551 | + width: 205px; | |
552 | + position: absolute; | |
553 | + left: 0; | |
554 | + top: 0; | |
555 | + } | |
556 | +} | |
557 | + | |
558 | +.add_new { | |
559 | + float: right; | |
560 | + background: #A6B807; | |
561 | + color: white; | |
562 | + padding: 4px 10px; | |
563 | + @include round-borders-all(4px); | |
564 | + font-size:11px; | |
565 | + margin: 10px 0; | |
566 | +} | |
567 | + | |
568 | + | |
569 | + | |
570 | +.new-project-hodler { | |
571 | + padding:20px; | |
572 | +} | ... | ... |
app/assets/stylesheets/style.scss
... | ... | @@ -9,7 +9,9 @@ audio:not([controls]) { display: none; } |
9 | 9 | |
10 | 10 | html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } |
11 | 11 | body { margin: 0; font-size: 13px; line-height: 1.231; } |
12 | -body, button, input, select, textarea { font-family: sans-serif; color: #222; } | |
12 | +body, button, input, select, textarea { | |
13 | + font-family: "helvetica", "arial", "freesans", "clean", sans-serif; | |
14 | +color: #222; } | |
13 | 15 | |
14 | 16 | ::-moz-selection { background: #79c3e0; color: #fff; text-shadow: none; } |
15 | 17 | ::selection { background: #79c3e0; color: #fff; text-shadow: none; } |
... | ... | @@ -74,9 +76,12 @@ $blue_link: "#2fa0bb"; |
74 | 76 | /* eo Vars */ |
75 | 77 | |
76 | 78 | html{ -webkit-font-smoothing:antialiased; } |
77 | -body{font-size: 12px; background-color: #eee;} | |
78 | -a{text-decoration: none; font-weight: bold; color: #666} | |
79 | -a:hover{color: #333} | |
79 | +body { | |
80 | + font-size: 12px; | |
81 | + background-color: #FFFFFF; | |
82 | +} | |
83 | +a{text-decoration: none; font-weight: bold; color: #444} | |
84 | +a:hover{color: #555} | |
80 | 85 | /* Typography */ |
81 | 86 | h1,h2,h3,h4,h5{font-weight: normal; color: #666} |
82 | 87 | h2{margin: 1.5em 0} |
... | ... | @@ -122,7 +127,7 @@ table thead th{ |
122 | 127 | td, th{ padding: .9em 1em; vertical-align: middle; } |
123 | 128 | |
124 | 129 | table thead .image{width:100px} |
125 | -table tr:hover, .listed_items tr.odd:hover{background-color:#FFFFCF} | |
130 | +.listed_items tr.odd:hover{background-color:#FFFFCF} | |
126 | 131 | /* eo Tables */ |
127 | 132 | |
128 | 133 | /* Buttons */ |
... | ... | @@ -130,7 +135,7 @@ table tr:hover, .listed_items tr.odd:hover{background-color:#FFFFCF} |
130 | 135 | border-radius: 5px; |
131 | 136 | font-size: 12px; |
132 | 137 | font-weight: bold; |
133 | - padding: 6px 20px; | |
138 | + padding: 5px 17px; | |
134 | 139 | border: 1px solid #999; |
135 | 140 | color: #666; |
136 | 141 | display: inline-block; |
... | ... | @@ -187,12 +192,14 @@ input.button{margin-bottom: 1.5em} |
187 | 192 | /* eo Buttons */ |
188 | 193 | |
189 | 194 | /* UI Box */ |
190 | -.ui-box{border: 1px solid #DEDFE1; float: left; border-radius: 5px} | |
195 | +//.ui-box{border: 1px solid #DEDFE1; float: left; border-radius: 5px} | |
196 | +.ui-box{float: left;} | |
191 | 197 | .ui-box h3{ |
192 | 198 | background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); |
193 | 199 | background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); |
194 | 200 | background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); |
195 | 201 | background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); |
202 | + background:none; | |
196 | 203 | margin: 0; |
197 | 204 | padding: 1em; |
198 | 205 | font-size: 12px; |
... | ... | @@ -215,13 +222,9 @@ input.button{margin-bottom: 1.5em} |
215 | 222 | |
216 | 223 | .ui-box .data{padding: .5em 1em} |
217 | 224 | |
218 | -.ui-box .buttons{background-color: #f7f8f9; padding: 1em; | |
219 | - -webkit-border-bottom-right-radius: 5px; | |
220 | - -webkit-border-bottom-left-radius: 5px; | |
221 | - -moz-border-radius-bottomright: 5px; | |
222 | - -moz-border-radius-bottomleft: 5px; | |
223 | - border-bottom-right-radius: 5px; | |
224 | - border-bottom-left-radius: 5px; | |
225 | +.ui-box .buttons{ | |
226 | + padding: 1em; | |
227 | + border-top:1px solid $lite_border_color; | |
225 | 228 | } |
226 | 229 | |
227 | 230 | .ui-box .buttons .button{padding: 8px 9px; font-size: 11px} |
... | ... | @@ -309,8 +312,7 @@ body.login-page{background-color: #f1f1f1; padding-top: 10%} |
309 | 312 | input[type="password"], |
310 | 313 | textarea |
311 | 314 | { |
312 | - border: 1px solid #FFBBBB; | |
313 | - background: #fff4f6; | |
315 | + border: 1px solid #D30 !important; | |
314 | 316 | } |
315 | 317 | } |
316 | 318 | /* eo Errors */ |
... | ... | @@ -328,13 +330,13 @@ body.login-page{background-color: #f1f1f1; padding-top: 10%} |
328 | 330 | } |
329 | 331 | /* eo InfoBlock */ |
330 | 332 | |
331 | -/* General */ | |
332 | -#container{background-color: white; overflow: hidden; } | |
333 | -body.collapsed #container{margin: auto; width: 980px; border: 1px solid rgba(0,0,0,.22); border-top: 0; box-shadow: 0 0 0px 4px rgba(0,0,0,.04)} | |
334 | - | |
335 | 333 | /* Header */ |
336 | -header{background: #474D57 url('bg-header.png') repeat-x bottom; z-index: 10000; height: 44px; padding: 10px 2% 6px 2%; position: relative} | |
337 | -header a{color: white; text-shadow: 0 -1px 0 black} | |
334 | +header{ | |
335 | + background: #474D57 url('bg-header.png') repeat-x bottom; | |
336 | + z-index: 10000; | |
337 | + height: 44px; | |
338 | + padding: 10px 2% 6px 2%; | |
339 | +} | |
338 | 340 | header a:hover{color: #f1f1f1} |
339 | 341 | header h1{ |
340 | 342 | width: 65px; |
... | ... | @@ -359,6 +361,9 @@ header nav{border-radius: 4px; box-shadow: 0 1px 2px black; width: 294px; margin |
359 | 361 | margin-top: 2px; |
360 | 362 | height:30px |
361 | 363 | } |
364 | +header nav.shorter_nav{ | |
365 | + width: 207px; | |
366 | +} | |
362 | 367 | header nav a{padding: 8px 12px 8px 34px; display: inline-block; color: #D6DADF; border-right: 1px solid #31363E; position: relative; box-shadow: 1px 0 0 rgba(255,255,255,.1); margin: 0} |
363 | 368 | header nav a span{width: 20px; height: 20px; display: inline-block; background: red; position: absolute; left: 8px; top: 6px;} |
364 | 369 | header nav a:last-child {border: 0; box-shadow: none} |
... | ... | @@ -382,7 +387,7 @@ header nav a.dashboard { |
382 | 387 | border-bottom-left-radius: 4px; |
383 | 388 | } |
384 | 389 | |
385 | -header nav a.admin{ | |
390 | +header nav a.last_elem{ | |
386 | 391 | -webkit-border-top-right-radius: 4px; |
387 | 392 | -webkit-border-bottom-right-radius: 4px; |
388 | 393 | -moz-border-radius-topright: 4px; |
... | ... | @@ -391,13 +396,14 @@ header nav a.admin{ |
391 | 396 | border-bottom-right-radius: 4px; |
392 | 397 | } |
393 | 398 | |
394 | -header .search{ display: inline-block; float: right; margin-right: 46px} | |
399 | +header .search{ display: inline-block; float: right; margin-right: 90px} | |
395 | 400 | |
396 | 401 | header nav a span{width: 20px; height: 20px; display: inline-block; background: red; position: absolute; left: 8px; top: 6px;} |
397 | 402 | |
398 | 403 | header nav a.dashboard span{background: url('images.png') no-repeat -161px 0;} |
399 | 404 | header nav a.admin span{background: url('images.png') no-repeat -184px 0;} |
400 | 405 | header nav a.project span{background: url('images.png') no-repeat -209px -1px; top: 7px} |
406 | +header nav a.issues span{background: url('images.png') no-repeat -209px -1px; top: 7px} | |
401 | 407 | |
402 | 408 | header .login-top{float: right; width: 180px; |
403 | 409 | background-image: -webkit-gradient(linear, 0 0, 0 62, color-stop(0.032, #464c56), to(#363c45)); |
... | ... | @@ -413,7 +419,7 @@ header .login-top a.pic{float: left; margin-right: 10px; |
413 | 419 | } |
414 | 420 | header .login-top a.username{margin-bottom: 5px} |
415 | 421 | header .login-top a.logout{color: #ccc} |
416 | -header{margin-bottom: 0; clear: both; } | |
422 | +header{margin-bottom: 0; clear: both; position:relative;} | |
417 | 423 | |
418 | 424 | .page-title{background-color: #f1f1f1;display: block; float: left; clear: both; width: 98%; padding: 1% 1%; border-bottom: 1px solid #ccc; box-shadow: 0 -1px 0 white inset; margin-bottom: 1.5em} |
419 | 425 | .page-title h1{font-size: 20px; width: 400px; margin: 0; padding-top: 8px } |
... | ... | @@ -421,8 +427,22 @@ header{margin-bottom: 0; clear: both; } |
421 | 427 | .right{float: right;} |
422 | 428 | |
423 | 429 | /* Account box */ |
424 | -header .account-box{position: absolute; right: 0; top: 8px; z-index: 10000; width: 128px; font-size: 11px; float: right; display: block; cursor: pointer;} | |
425 | -header .account-box img{ border-radius: 4px; right: 20px; position: absolute; width: 38px; height: 38px; display: block; box-shadow: 0 1px 2px black} | |
430 | +header .account-box{ | |
431 | + position: absolute; | |
432 | + right: 0; | |
433 | + top: 8px; | |
434 | + z-index: 10000; | |
435 | + width: 128px; | |
436 | + font-size: 11px; | |
437 | + float: right; | |
438 | + display: block; | |
439 | + cursor: pointer;} | |
440 | +header .account-box img{ | |
441 | + border-radius: 4px; | |
442 | + right: 20px; | |
443 | + position: absolute; | |
444 | + width: 33px; height: 33px; | |
445 | + display: block; top:0;} | |
426 | 446 | header .account-box img:after{ |
427 | 447 | content: " "; |
428 | 448 | display: block; |
... | ... | @@ -446,7 +466,8 @@ float: right; |
446 | 466 | .account-box.hover{height: 138px;} |
447 | 467 | |
448 | 468 | .account-box:hover > .account-links{display: block;} |
449 | -header .account-links{background: white; display: none; border-radius: 5px; width: 100px; margin-top: 0; float: right; box-shadow: 0 1px 1px rgba(0,0,0,.2); position:relative;} | |
469 | +header .account-links{ | |
470 | + background: #79C3E0; display: none; border-radius: 5px; width: 100px; margin-top: 0; float: right; box-shadow: 0 1px 1px rgba(0,0,0,.2); position:relative;} | |
450 | 471 | header .account-links:before { |
451 | 472 | content: "."; |
452 | 473 | width:0; |
... | ... | @@ -545,8 +566,22 @@ header .account-links a:last-child{ |
545 | 566 | } |
546 | 567 | |
547 | 568 | /* eo Account Box */ |
548 | -input.search-input{float: left; text-shadow: none; width: 116px; background-image: url('icon-search.png') ; background-repeat: no-repeat; background-position: 10px; border-radius: 100px; border: 1px solid rgba(0,0,0,.7); box-shadow: 0 1px 0 rgba(255,255,255,.2), 0 2px 2px rgba(0,0,0,.4) inset ; background-color: #D2D5DA; background-color: rgba(255,255,255,.5); padding: 5px; padding-left: 26px; margin-top: 4px; margin-right: 10px } | |
549 | -input.search-input:focus{ background-color: white; width: 216px;} | |
569 | +input.search-input{ | |
570 | + float: left; | |
571 | + text-shadow: none; | |
572 | + width: 116px; | |
573 | + background-image: url('icon-search.png') ; | |
574 | + background-repeat: no-repeat; | |
575 | + background-position: 10px; | |
576 | + border-radius: 4px; | |
577 | + border: 1px solid #AAA; | |
578 | + background-color: #FFF; | |
579 | + padding: 5px; | |
580 | + padding-left: 26px; | |
581 | + margin-top: 2px; | |
582 | + margin-right: 10px; | |
583 | +} | |
584 | +/*input.search-input:focus{ background-color: white; width: 216px;}*/ | |
550 | 585 | input.search-input::-webkit-input-placeholder {color: #666} |
551 | 586 | /* eo Header */ |
552 | 587 | |
... | ... | @@ -559,127 +594,12 @@ html, body { height: 100%; } |
559 | 594 | |
560 | 595 | |
561 | 596 | |
562 | -body.dashboard-page h2.icon span{ background-position: 9px -69px; } | |
563 | -body.dashboard-page header{margin-bottom: 0} | |
564 | -body.dashboard-page .news-feed{padding-left: 1em; margin-right: 450px; min-height: 600px; margin-left: 1%} | |
565 | -body.dashboard-page .dashboard-content{ position: relative; float: left; width: 100%; height: 100%; } | |
566 | -body.dashboard-page .news-feed h2{float: left;} | |
567 | -body.dashboard-page aside{ min-height: 820px; position: relative; top: 0; bottom: 0; right: 0; width: 420px; float: right; background-color: #f7f7f7; border-left: 1px solid #ccc } | |
568 | -body.dashboard-page aside h4{margin: 0; border-bottom: 1px solid #ccc; padding: 10px 10px; font-size: 11px; font-weight: bold; text-transform: uppercase;} | |
569 | -body.dashboard-page aside h4 a.button-small{float: right; text-transform: none; border-radius: 4px; margin-right: 2%; margin-top: -4px; display: block;} | |
570 | -body.dashboard-page aside .project-list {list-style: none; margin: 0; padding: 0;} | |
571 | -body.dashboard-page aside .project-list li a {background: white; color: #{$blue_link}; display: block; border-bottom: 1px solid #eee; padding: 14px 6% 14px 14px;} | |
572 | -body.dashboard-page aside .project-list li a:hover {background: #f1f1f1} | |
573 | -body.dashboard-page aside .project-list li a:hover span.arrow{background-color: #E3E5EA;} | |
574 | -body.dashboard-page aside .project-list li a span.project-name{font-size: 14px; display: block; margin-bottom: 8px} | |
575 | -body.dashboard-page aside .project-list li a span.time{color: #666; font-weight: normal; font-size: 11px} | |
576 | -body.dashboard-page aside .project-list li a span.arrow{float: right; background: #E3E5EA; padding: 10px; border-radius: 5px; margin-top: 2px; text-shadow: none; color: #999} | |
577 | -body.dashboard-page .news-feed .project-updates {margin-bottom: 20px; display: block; width: 100%;} | |
578 | -body.dashboard-page .news-feed .project-updates .data{ padding: 0} | |
579 | -body.dashboard-page .news-feed .project-updates a.project-update {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} | |
580 | -body.dashboard-page .news-feed .project-updates a.project-update:last-child{border-bottom: 0} | |
581 | -body.dashboard-page .news-feed .project-updates a.project-update img{float: left; margin-right: 10px;} | |
582 | -body.dashboard-page .news-feed .project-updates a.project-update span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;} | |
583 | -body.dashboard-page .news-feed .project-updates a.project-update span.update-title{margin-bottom: 10px} | |
584 | -body.dashboard-page .news-feed .project-updates a.project-update span.update-author{color: #999; font-weight: normal; font-style: italic;} | |
585 | -body.dashboard-page .news-feed .project-updates a.project-update span.update-author strong{font-weight: bold; font-style: normal;} | |
586 | -/* eo Dashboard Page */ | |
587 | 597 | |
588 | 598 | .grey-button.right{margin-top: 20px} |
589 | 599 | |
590 | 600 | /* Project Page */ |
591 | - | |
592 | -body.project-page h2.icon .project-name, body.project-page h2.icon d{border: 1px solid #eee; padding: 5px 30px 5px 10px; border-radius: 5px; position: relative;} | |
593 | -body.project-page h2.icon .project-name i.arrow{float: right; | |
594 | - position: absolute; | |
595 | - right: 10px; | |
596 | - top: 13px; | |
597 | - display: block; | |
598 | - background: url('images.png') no-repeat -97px -29px; | |
599 | - width: 4px; | |
600 | - height: 5px; | |
601 | -} | |
602 | - | |
603 | -body.project-page h2.icon span{ background-position: -78px -68px; } | |
604 | -body.project-page .project-container{ position: relative; float: left; width: 100%; height: 100%; padding-bottom: 10px;} | |
605 | -body.project-page .page-title{margin-bottom: 0} | |
606 | -body.project-page .project-sidebar {width: 180px; left: 0; top: 0; height: 100%; bottom: 0; position: absolute; background-color: #f7f7f7; float: left; display: inline-block; background: #f7f7f7; padding: 20px 0 20px 2%; margin: 0; } | |
607 | - | |
608 | -body.project-page input.text.git-url, | |
609 | -body.projects-page input.text.git-url { font-size: 12px; border-radius: 5px; color: #666; box-shadow: 0 1px 2px rgba(0,0,0,.2) inset; padding: 8px 0 8px 30px; margin-bottom: 20px; background: white url('images.png') no-repeat 8px -40px; width: 136px} | |
610 | -body.projects-page input.text.git-url {margin:10px 0 0 } | |
611 | -.git_url_wrapper { margin-right:50px } | |
612 | - | |
613 | -.projects_selector:hover > .project-box{ -moz-box-shadow:0px 0px 10px rgba(0, 0, 0, .1); -webkit-box-shadow:0px 0px 10px rgba(0, 0, 0, .1); box-shadow:0px 0px 10px rgba(0, 0, 0, .1); } | |
614 | - | |
615 | -body.project-page .project-sidebar aside{width: 179px} | |
616 | -body.project-page .project-sidebar aside a{display: block; position: relative; background: white; padding: 15px 10px; border-bottom: 1px solid #eee} | |
617 | -body.project-page .project-sidebar aside a:first-child{ | |
618 | - -webkit-border-top-left-radius: 5px; | |
619 | - -moz-border-radius-topleft: 5px; | |
620 | - border-top-left-radius: 5px; | |
621 | -} | |
622 | -.project-page .project-sidebar aside a:last-child{ | |
623 | - -webkit-border-bottom-left-radius: 5px; | |
624 | - -moz-border-radius-bottomleft: 5px; | |
625 | - border-bottom-left-radius: 5px; | |
626 | -} | |
627 | -body.project-page .project-sidebar aside a:hover{background-color: #eee;} | |
628 | -body.project-page .project-sidebar aside a span.number{float: right; border-radius: 5px; text-shadow: none; background: rgba(0,0,0,.12); text-align: center; padding: 5px 8px; position: absolute; top: 10px; right: 10px} | |
629 | -body.project-page .project-sidebar aside a.current{background-color: #79c3e0; color: white; text-shadow: none; border-color: transparent} | |
630 | -body.project-page .project-content{ padding: 20px; display: block; margin-left: 205px; min-height: 600px} | |
631 | -body.project-page .project-content h2{ margin-top: 6px} | |
632 | -body.project-page .project-content .button.right{margin-left: 20px} | |
633 | -body.project-page table .commit a{color: #{$blue_link}} | |
634 | -body.project-page table th, body.project-page table td{ border-bottom: 1px solid #DEE2E3;} | |
635 | -body.project-page .fixed{position: fixed; } | |
636 | - | |
637 | -/* New project Page */ | |
638 | -.new-project-page .container{width: 600px; background-color: rgba(0,0,0,.02); margin: auto; border: 1px solid #eee; padding: 0 20px; margin: 30px auto 60px auto; border-radius: 5px} | |
639 | -.new-project-page .container table{background: white} | |
640 | 601 | /* eo New Project Page */ |
641 | 602 | |
642 | -/* Commit Page */ | |
643 | -body.project-page.commits-page .commit-info{float: right;} | |
644 | -body.project-page.commits-page .commit-info data{ | |
645 | - padding: 4px 10px; | |
646 | - font-size: 11px; | |
647 | -} | |
648 | -body.project-page.commits-page .commit-info data.commit-button{ | |
649 | - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.192, #fff), to(#f4f4f4)); | |
650 | - background-image: -webkit-linear-gradient(#fff 19.2%, #f4f4f4); | |
651 | - background-image: -moz-linear-gradient(#fff 19.2%, #f4f4f4); | |
652 | - background-image: -o-linear-gradient(#fff 19.2%, #f4f4f4); | |
653 | - box-shadow: 0 -1px 0 white inset; | |
654 | - display: block; | |
655 | - border: 1px solid #eee; | |
656 | - border-radius: 5px; | |
657 | - margin-bottom: 2px; | |
658 | - position: relative; | |
659 | - padding-right: 20px; | |
660 | -} | |
661 | - | |
662 | -body.project-page.commits-page .commit-button i{ | |
663 | - background: url('images.png') no-repeat -138px -27px; | |
664 | - width: 6px; | |
665 | - height: 9px; | |
666 | - float: right; | |
667 | - position: absolute; | |
668 | - top: 6px; | |
669 | - right: 5px; | |
670 | -} | |
671 | -body.project-page.commits-page .commits-date {display: block; width: 100%; margin-bottom: 20px} | |
672 | -body.project-page.commits-page .commits-date .data {padding: 0} | |
673 | -body.project-page.commits-page a.commit{padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} | |
674 | -body.project-page.commits-page .commits-date a.commit {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} | |
675 | -body.project-page.commits-page .commits-date a.commit:last-child{border-bottom: 0} | |
676 | -body.project-page.commits-page .commits-date a.commit img{float: left; margin-right: 10px;} | |
677 | -body.project-page.commits-page .commits-date a.commit span.commit-title{display: block;} | |
678 | -body.project-page.commits-page .commits-date a.commit span.commit-title{margin-bottom: 10px} | |
679 | -body.project-page.commits-page .commits-date a.commit span.commit-author{color: #999; font-weight: normal; font-style: italic;} | |
680 | -body.project-page.commits-page .commits-date a.commit span.commit-author strong{font-weight: bold; font-style: normal;} | |
681 | - | |
682 | -/* eo Commit Page */ | |
683 | 603 | |
684 | 604 | /* eo Project Page */ |
685 | 605 | |
... | ... | @@ -729,12 +649,154 @@ body.projects-page .browse-code{margin-right: 10px} |
729 | 649 | h2, h3 { page-break-after: avoid; } |
730 | 650 | } |
731 | 651 | |
732 | -/** | |
733 | - * author:DZ | |
734 | - * date: Nov 09 | |
735 | - * fix different fonts for firefox & webkit | |
736 | - */ | |
737 | 652 | body, button, input, select, textarea { |
738 | - font-family: "Helvetica", sans-serif; | |
653 | + font-family: "helvetica", "arial", "freesans", "clean", sans-serif; | |
654 | +} | |
655 | + | |
656 | +/** FORM INPUTS **/ | |
657 | +.new_merge_request, | |
658 | +.edit_merge_request, | |
659 | +.user_new, | |
660 | +.new_key, | |
661 | +.new_issue, | |
662 | +.new_note, | |
663 | +.edit_user, | |
664 | +.edit_issue, | |
665 | +.new_project, | |
666 | +.new_snippet, | |
667 | +.edit_snippet, | |
668 | +.edit_project { | |
669 | + input[type='text'], | |
670 | + input[type='email'], | |
671 | + input[type='password'], | |
672 | + textarea { | |
673 | + width:400px; | |
674 | + padding:8px; | |
675 | + font-size:14px; | |
676 | + @include round-borders-all(4px); | |
677 | + } | |
678 | +} | |
679 | + | |
680 | +.text_field { | |
681 | + width:400px; | |
682 | + padding:8px; | |
683 | + font-size:14px; | |
684 | + @include round-borders-all(4px); | |
685 | +} | |
686 | + | |
687 | +.input_button { | |
688 | + padding:8px; | |
689 | + font-size:14px; | |
690 | + cursor:pointer; | |
691 | + background-color: #F5F5F5; | |
692 | + border-color: #EEEEEE #DEDEDE #DEDEDE #EEEEEE; | |
693 | + border-right: 1px solid #DEDEDE; | |
694 | + border-style: solid; | |
695 | + border-width: 1px; | |
696 | +} | |
697 | + | |
698 | +/** FLASH **/ | |
699 | +#flash_container { | |
700 | + height:45px; | |
701 | + position:fixed; | |
702 | + z-index:10001; | |
703 | + top:0px; | |
704 | + width:100%; | |
705 | + margin-bottom:15px; | |
706 | + overflow:hidden; | |
707 | + background:white; | |
708 | + cursor:pointer; | |
709 | + border-bottom:1px solid #777; | |
710 | + | |
711 | + h4 { | |
712 | + color:#444; | |
713 | + font-size:22px; | |
714 | + padding-top:5px; | |
715 | + margin:2px; | |
716 | + } | |
717 | +} | |
718 | + | |
719 | + | |
720 | +.errors_holder { | |
721 | + background:#D30; | |
722 | + color:#fff; | |
723 | + @include round-borders-all(4px); | |
724 | + border:1px solid #a30; | |
725 | + padding:5px; | |
726 | + list-style:none; | |
727 | + font-weight: bold; | |
728 | + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); | |
729 | + | |
730 | + li { | |
731 | + padding:10px; | |
732 | + } | |
733 | +} | |
734 | + | |
735 | +.notice_holder { | |
736 | + background:#DDF4FB; | |
737 | + color:#444; | |
738 | + border:1px solid #C6EDF9; | |
739 | + @include round-borders-all(4px); | |
740 | + padding:5px; | |
741 | + list-style:none; | |
742 | + font-weight: bold; | |
743 | + text-shadow: 0 -1px 0 rgba(255, 255, 255, 0.25); | |
744 | + | |
745 | + li { | |
746 | + padding:10px; | |
747 | + } | |
739 | 748 | } |
740 | 749 | |
750 | +.alert_holder { | |
751 | + background:#FDF5D9; | |
752 | + color:#444; | |
753 | + border:1px solid #FCEEC1; | |
754 | + @include round-borders-all(4px); | |
755 | + padding:5px; | |
756 | + list-style:none; | |
757 | + font-weight: bold; | |
758 | + text-shadow: 0 -1px 0 rgba(255, 255, 255, 0.25); | |
759 | + | |
760 | + li { | |
761 | + padding:10px; | |
762 | + } | |
763 | +} | |
764 | + | |
765 | +.help_content { | |
766 | + margin:20px; | |
767 | + margin-top:71px; | |
768 | + | |
769 | + h2 { | |
770 | + margin:0; | |
771 | + padding:0; | |
772 | + } | |
773 | + | |
774 | + .menu { | |
775 | + float:left; | |
776 | + width:20%; | |
777 | + | |
778 | + .active { | |
779 | + color: $active_bd_color; | |
780 | + } | |
781 | + } | |
782 | + | |
783 | + .content { | |
784 | + float:right; | |
785 | + width:78%; | |
786 | + } | |
787 | + | |
788 | + .bash { | |
789 | + @include round-borders-all(4px); | |
790 | + background:#eee; | |
791 | + padding:5px; | |
792 | + //overflow-x:scroll; | |
793 | + pre{ | |
794 | + padding:0; | |
795 | + line-height:2.0; | |
796 | + margin:0; | |
797 | + font-family: 'Courier New', 'andale mono','lucida console',monospace; | |
798 | + color: #333; | |
799 | + text-align:left; | |
800 | + } | |
801 | + } | |
802 | +} | ... | ... |
... | ... | @@ -0,0 +1,146 @@ |
1 | +.main_links { | |
2 | + width:130px; | |
3 | + float:left; | |
4 | + | |
5 | + a { | |
6 | + float:left; | |
7 | + } | |
8 | +} | |
9 | + | |
10 | +.dashboard_links { | |
11 | + padding:7px; | |
12 | + float:left; | |
13 | + a { | |
14 | + margin: 0 14px; | |
15 | + float: left; | |
16 | + font-size: 14px; | |
17 | + | |
18 | + &.active { | |
19 | + color:$active_link_color; | |
20 | + } | |
21 | + &:hover { | |
22 | + color:$active_link_color; | |
23 | + } | |
24 | + } | |
25 | +} | |
26 | + | |
27 | +.top-tabs { | |
28 | + margin: 0; | |
29 | + padding: 5px; | |
30 | + font-size: 14px; | |
31 | + padding-bottom:10px; | |
32 | + margin-bottom:20px; | |
33 | + height:26px; | |
34 | + border-bottom:1px solid #ccc; | |
35 | + | |
36 | + .tab { | |
37 | + font-weight: bold; | |
38 | + background:none; | |
39 | + padding: 10px; | |
40 | + float:left; | |
41 | + padding-left:0px; | |
42 | + padding-right:40px; | |
43 | + | |
44 | + &.active { | |
45 | + color: $active_link_color; | |
46 | + } | |
47 | + } | |
48 | +} | |
49 | + | |
50 | +body header { | |
51 | + position:absolute; | |
52 | + width:100%; | |
53 | + padding:0; | |
54 | + margin:0; | |
55 | + top:0; | |
56 | + left:0; | |
57 | + background: #999; /* for non-css3 browsers */ | |
58 | + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFF', endColorstr='#EAEAEA'); /* for IE */ | |
59 | + background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#EAEAEA)); /* for webkit browsers */ | |
60 | + background: -moz-linear-gradient(top, #FFFFFF, #EAEAEA); /* for firefox 3.6+ */ | |
61 | + background: -o-linear-gradient(top, #FFFFFF, #EAEAEA); /* for firefox 3.6+ */ | |
62 | + border-bottom: 1px solid #ccc; | |
63 | + | |
64 | + height:50px; | |
65 | + | |
66 | + .wrapper { | |
67 | + margin:auto; | |
68 | + width:$app_width; | |
69 | + position:relative; | |
70 | + | |
71 | + .top_panel_content { | |
72 | + padding:10px $app_padding; | |
73 | + } | |
74 | + } | |
75 | + | |
76 | + .project_name { | |
77 | + float:left; | |
78 | + width:235px; | |
79 | + margin-right:30px; | |
80 | + font-size:16px; | |
81 | + font-weight:bold; | |
82 | + padding:8px; | |
83 | + color:#333; | |
84 | + } | |
85 | + | |
86 | + .git_url_wrapper { | |
87 | + padding:0px; | |
88 | + margin:0px; | |
89 | + float:left; | |
90 | + | |
91 | + .git-url { | |
92 | + padding:0px; | |
93 | + margin:0px; | |
94 | + font-size: 12px; | |
95 | + | |
96 | + margin-right:10px; | |
97 | + border-radius: 4px; | |
98 | + -moz-border-radius: 4px; | |
99 | + | |
100 | + | |
101 | + color: #666; | |
102 | + border: 1px solid #AAA; | |
103 | + padding: 0 10px 0 30px; | |
104 | + background: transparent url('images.png') no-repeat 8px -42px; | |
105 | + width: 160px; | |
106 | + height:26px; | |
107 | + } | |
108 | + } | |
109 | +} | |
110 | + | |
111 | +.top_panel_holder .chzn-container { | |
112 | + position:relative; | |
113 | + | |
114 | + .chzn-drop { | |
115 | + margin:7px 0; | |
116 | + border: 1px solid #CCC; | |
117 | + min-width: 300px; | |
118 | + | |
119 | + .chzn-results { | |
120 | + max-height:300px; | |
121 | + } | |
122 | + } | |
123 | + | |
124 | + .chzn-single { | |
125 | + background:transparent; | |
126 | + -moz-border-radius: 4px; | |
127 | + border-radius: 4px; | |
128 | + | |
129 | + div { | |
130 | + background:transparent; | |
131 | + border-left:none; | |
132 | + } | |
133 | + | |
134 | + span { | |
135 | + font-weight: normal; | |
136 | + } | |
137 | + } | |
138 | +} | |
139 | + | |
140 | +.rss-icon { | |
141 | + margin:0 15px; | |
142 | + padding:3px; | |
143 | + border:1px solid #AAA; | |
144 | + border-radius:3px; | |
145 | + float:left; | |
146 | +} | ... | ... |
... | ... | @@ -0,0 +1,121 @@ |
1 | +#tree-breadcrumbs { | |
2 | + div { | |
3 | + margin:0; | |
4 | + margin-bottom:20px; | |
5 | + float:left; | |
6 | + font-size:14px; | |
7 | + } | |
8 | +} | |
9 | + | |
10 | +.tree_progress { | |
11 | + float:left; | |
12 | + width:16px; | |
13 | + height:16px; | |
14 | + margin:2px 6px; | |
15 | + &.loading { | |
16 | + background-position: 0px 0px; | |
17 | + background: url("ajax-loader-facebook.gif") no-repeat; | |
18 | + } | |
19 | +} | |
20 | + | |
21 | + | |
22 | +/** FILE CONTENT VIEW **/ | |
23 | +.view_file_content{ | |
24 | + .old_line, .new_line { | |
25 | + background:#ECECEC; | |
26 | + color:#777; | |
27 | + width:15px; | |
28 | + float:left; | |
29 | + padding: 0px 10px; | |
30 | + border-right: 1px solid #ccc; | |
31 | + } | |
32 | + .old_line{ | |
33 | + display:none; | |
34 | + } | |
35 | +} | |
36 | + | |
37 | +.view_file .view_file_header, | |
38 | +.diff_file .diff_file_header { | |
39 | + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); | |
40 | + background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
41 | + background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
42 | + background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); | |
43 | + margin: 0; | |
44 | + font-weight: normal; | |
45 | + font-weight: bold; | |
46 | + text-align: left; | |
47 | + color: #666; | |
48 | + border-bottom: 1px solid #DEE2E3; | |
49 | + padding: 7px 10px; | |
50 | + | |
51 | + .mode_text, | |
52 | + .file_icon { | |
53 | + margin-right:15px; | |
54 | + padding-right:15px; | |
55 | + border-right:1px solid $lite_border_color; | |
56 | + float:left; | |
57 | + color:#aaa; | |
58 | + } | |
59 | + | |
60 | + .file_icon { | |
61 | + padding-left:15px; | |
62 | + } | |
63 | +} | |
64 | + | |
65 | +.view_file { | |
66 | + border:1px solid #CCC; | |
67 | + margin-bottom:1em; | |
68 | + | |
69 | + .view_file_content { | |
70 | + background:#fff; | |
71 | + color:#514721; | |
72 | + font-size: 11px; | |
73 | + } | |
74 | + .view_file_content_image { | |
75 | + background:#eee; | |
76 | + text-align:center; | |
77 | + img { | |
78 | + padding:100px; | |
79 | + max-width:300px; | |
80 | + } | |
81 | + } | |
82 | +} | |
83 | + | |
84 | +td.code { | |
85 | + width: 100%; | |
86 | + .highlight { | |
87 | + margin-left: 55px; | |
88 | + overflow:auto; | |
89 | + overflow-y:hidden; | |
90 | + border-left: 1px solid #DEE2E3; | |
91 | + background: white; | |
92 | + } | |
93 | +} | |
94 | +.highlight pre { | |
95 | + white-space: pre; | |
96 | + word-wrap:normal; | |
97 | +} | |
98 | + | |
99 | +table.highlighttable { | |
100 | + border: none; | |
101 | + background: #F7F7F7; | |
102 | +} | |
103 | +body.project-page table.highlighttable td { border: none } | |
104 | +table.highlighttable tr:hover { background:none;} | |
105 | + | |
106 | +table.highlighttable pre{ | |
107 | + line-height:16px !important; | |
108 | + font-size:12px !important; | |
109 | +} | |
110 | + | |
111 | +table.highlighttable .linenodiv pre { | |
112 | + text-align: right; | |
113 | + padding-right: 4px; | |
114 | + color:#888; | |
115 | +} | |
116 | + | |
117 | +.tree-item { | |
118 | + &:hover { | |
119 | + background: #FFFFCF; | |
120 | + } | |
121 | +} | ... | ... |
app/controllers/admin/projects_controller.rb
... | ... | @@ -9,6 +9,12 @@ class Admin::ProjectsController < ApplicationController |
9 | 9 | |
10 | 10 | def show |
11 | 11 | @admin_project = Project.find_by_code(params[:id]) |
12 | + | |
13 | + @users = if @admin_project.users.empty? | |
14 | + User | |
15 | + else | |
16 | + User.not_in_project(@admin_project) | |
17 | + end.all | |
12 | 18 | end |
13 | 19 | |
14 | 20 | def new |
... | ... | @@ -19,6 +25,19 @@ class Admin::ProjectsController < ApplicationController |
19 | 25 | @admin_project = Project.find_by_code(params[:id]) |
20 | 26 | end |
21 | 27 | |
28 | + def team_update | |
29 | + @admin_project = Project.find_by_code(params[:id]) | |
30 | + | |
31 | + UsersProject.bulk_import( | |
32 | + @admin_project, | |
33 | + params[:user_ids], | |
34 | + params[:project_access], | |
35 | + params[:repo_access] | |
36 | + ) | |
37 | + | |
38 | + redirect_to [:admin, @admin_project], notice: 'Project was successfully updated.' | |
39 | + end | |
40 | + | |
22 | 41 | def create |
23 | 42 | @admin_project = Project.new(params[:project]) |
24 | 43 | @admin_project.owner = current_user | ... | ... |
app/controllers/admin/users_controller.rb
... | ... | @@ -27,7 +27,6 @@ class Admin::UsersController < ApplicationController |
27 | 27 | |
28 | 28 | respond_to do |format| |
29 | 29 | if @admin_user.save |
30 | - Notify.new_user_email(@admin_user, params[:user][:password]).deliver | |
31 | 30 | format.html { redirect_to [:admin, @admin_user], notice: 'User was successfully created.' } |
32 | 31 | format.json { render json: @admin_user, status: :created, location: @admin_user } |
33 | 32 | else |
... | ... | @@ -39,7 +38,7 @@ class Admin::UsersController < ApplicationController |
39 | 38 | |
40 | 39 | def update |
41 | 40 | admin = params[:user].delete("admin") |
42 | - if params[:user][:password].empty? | |
41 | + if params[:user][:password].blank? | |
43 | 42 | params[:user].delete(:password) |
44 | 43 | params[:user].delete(:password_confirmation) |
45 | 44 | end | ... | ... |
app/controllers/application_controller.rb
1 | 1 | class ApplicationController < ActionController::Base |
2 | 2 | before_filter :authenticate_user! |
3 | + before_filter :set_current_user_for_mailer | |
3 | 4 | protect_from_forgery |
4 | 5 | helper_method :abilities, :can? |
5 | 6 | |
... | ... | @@ -19,6 +20,10 @@ class ApplicationController < ActionController::Base |
19 | 20 | end |
20 | 21 | end |
21 | 22 | |
23 | + def set_current_user_for_mailer | |
24 | + MailerObserver.current_user = current_user | |
25 | + end | |
26 | + | |
22 | 27 | def abilities |
23 | 28 | @abilities ||= Six.new |
24 | 29 | end | ... | ... |
app/controllers/commits_controller.rb
... | ... | @@ -27,6 +27,8 @@ class CommitsController < ApplicationController |
27 | 27 | @notes = project.commit_notes(@commit).fresh.limit(20) |
28 | 28 | @note = @project.build_commit_note(@commit) |
29 | 29 | |
30 | + @line_notes = project.commit_line_notes(@commit) | |
31 | + | |
30 | 32 | respond_to do |format| |
31 | 33 | format.html |
32 | 34 | format.js { respond_with_notes } | ... | ... |
app/controllers/dashboard_controller.rb
1 | 1 | class DashboardController < ApplicationController |
2 | + respond_to :html | |
3 | + | |
2 | 4 | def index |
3 | 5 | @projects = current_user.projects.all |
4 | - @active_projects = @projects.select(&:last_activity_date).sort_by(&:last_activity_date).reverse | |
6 | + @active_projects = @projects.select(&:repo_exists?).select(&:last_activity_date_cached).sort_by(&:last_activity_date_cached).reverse | |
7 | + end | |
8 | + | |
9 | + # Get authored or assigned open merge requests | |
10 | + def merge_requests | |
11 | + @projects = current_user.projects.all | |
12 | + @merge_requests = MergeRequest.where("author_id = :id or assignee_id = :id", :id => current_user.id).opened.order("created_at DESC").limit(40) | |
13 | + end | |
14 | + | |
15 | + # Get only assigned issues | |
16 | + def issues | |
17 | + @projects = current_user.projects.all | |
18 | + @user = current_user | |
19 | + @issues = current_user.assigned_issues.opened.order("created_at DESC").limit(40) | |
20 | + | |
21 | + @issues = @issues.includes(:author, :project) | |
22 | + | |
23 | + respond_to do |format| | |
24 | + format.html | |
25 | + format.atom { render :layout => false } | |
26 | + end | |
5 | 27 | end |
6 | 28 | end | ... | ... |
... | ... | @@ -0,0 +1,46 @@ |
1 | +class DeployKeysController < ApplicationController | |
2 | + respond_to :html | |
3 | + layout "project" | |
4 | + before_filter :project | |
5 | + | |
6 | + # Authorize | |
7 | + before_filter :add_project_abilities | |
8 | + before_filter :authorize_admin_project! | |
9 | + | |
10 | + def project | |
11 | + @project ||= Project.find_by_code(params[:project_id]) | |
12 | + end | |
13 | + | |
14 | + def index | |
15 | + @keys = @project.deploy_keys.all | |
16 | + end | |
17 | + | |
18 | + def show | |
19 | + @key = @project.deploy_keys.find(params[:id]) | |
20 | + end | |
21 | + | |
22 | + def new | |
23 | + @key = @project.deploy_keys.new | |
24 | + | |
25 | + respond_with(@key) | |
26 | + end | |
27 | + | |
28 | + def create | |
29 | + @key = @project.deploy_keys.new(params[:key]) | |
30 | + if @key.save | |
31 | + redirect_to project_deploy_keys_path(@project) | |
32 | + else | |
33 | + render "new" | |
34 | + end | |
35 | + end | |
36 | + | |
37 | + def destroy | |
38 | + @key = @project.deploy_keys.find(params[:id]) | |
39 | + @key.destroy | |
40 | + | |
41 | + respond_to do |format| | |
42 | + format.html { redirect_to project_deploy_keys_url } | |
43 | + format.js { render :nothing => true } | |
44 | + end | |
45 | + end | |
46 | +end | ... | ... |
... | ... | @@ -0,0 +1,51 @@ |
1 | +class HooksController < ApplicationController | |
2 | + before_filter :authenticate_user! | |
3 | + before_filter :project | |
4 | + layout "project" | |
5 | + | |
6 | + # Authorize | |
7 | + before_filter :add_project_abilities | |
8 | + before_filter :authorize_read_project! | |
9 | + before_filter :authorize_admin_project!, :only => [:new, :create, :destroy] | |
10 | + | |
11 | + respond_to :html | |
12 | + | |
13 | + def index | |
14 | + @hooks = @project.web_hooks | |
15 | + end | |
16 | + | |
17 | + def new | |
18 | + @hook = @project.web_hooks.new | |
19 | + end | |
20 | + | |
21 | + def create | |
22 | + @hook = @project.web_hooks.new(params[:hook]) | |
23 | + @hook.save | |
24 | + | |
25 | + if @hook.valid? | |
26 | + redirect_to project_hook_path(@project, @hook) | |
27 | + else | |
28 | + render :new | |
29 | + end | |
30 | + end | |
31 | + | |
32 | + def test | |
33 | + @hook = @project.web_hooks.find(params[:id]) | |
34 | + commits = @project.commits(@project.default_branch, nil, 3) | |
35 | + data = @project.web_hook_data(commits.last.id, commits.first.id, "refs/heads/#{@project.default_branch}") | |
36 | + @hook.execute(data) | |
37 | + | |
38 | + redirect_to :back | |
39 | + end | |
40 | + | |
41 | + def show | |
42 | + @hook = @project.web_hooks.find(params[:id]) | |
43 | + end | |
44 | + | |
45 | + def destroy | |
46 | + @hook = @project.web_hooks.find(params[:id]) | |
47 | + @hook.destroy | |
48 | + | |
49 | + redirect_to project_hooks_path(@project) | |
50 | + end | |
51 | +end | ... | ... |
app/controllers/issues_controller.rb
... | ... | @@ -6,8 +6,18 @@ class IssuesController < ApplicationController |
6 | 6 | |
7 | 7 | # Authorize |
8 | 8 | before_filter :add_project_abilities |
9 | + | |
10 | + # Allow read any issue | |
9 | 11 | before_filter :authorize_read_issue! |
10 | - before_filter :authorize_write_issue!, :only => [:new, :create, :close, :edit, :update, :sort] | |
12 | + | |
13 | + # Allow write(create) issue | |
14 | + before_filter :authorize_write_issue!, :only => [:new, :create] | |
15 | + | |
16 | + # Allow modify issue | |
17 | + before_filter :authorize_modify_issue!, :only => [:close, :edit, :update, :sort] | |
18 | + | |
19 | + # Allow destroy issue | |
20 | + before_filter :authorize_admin_issue!, :only => [:destroy] | |
11 | 21 | |
12 | 22 | respond_to :js, :html |
13 | 23 | |
... | ... | @@ -57,10 +67,7 @@ class IssuesController < ApplicationController |
57 | 67 | def create |
58 | 68 | @issue = @project.issues.new(params[:issue]) |
59 | 69 | @issue.author = current_user |
60 | - | |
61 | - if @issue.save && @issue.assignee != current_user | |
62 | - Notify.new_issue_email(@issue).deliver | |
63 | - end | |
70 | + @issue.save | |
64 | 71 | |
65 | 72 | respond_with(@issue) |
66 | 73 | end |
... | ... | @@ -80,6 +87,7 @@ class IssuesController < ApplicationController |
80 | 87 | @issue.destroy |
81 | 88 | |
82 | 89 | respond_to do |format| |
90 | + format.html { redirect_to project_issues_path } | |
83 | 91 | format.js { render :nothing => true } |
84 | 92 | end |
85 | 93 | end |
... | ... | @@ -115,4 +123,13 @@ class IssuesController < ApplicationController |
115 | 123 | def issue |
116 | 124 | @issue ||= @project.issues.find(params[:id]) |
117 | 125 | end |
126 | + | |
127 | + def authorize_modify_issue! | |
128 | + can?(current_user, :modify_issue, @issue) || | |
129 | + @issue.assignee == current_user | |
130 | + end | |
131 | + | |
132 | + def authorize_admin_issue! | |
133 | + can?(current_user, :admin_issue, @issue) | |
134 | + end | |
118 | 135 | end | ... | ... |
app/controllers/keys_controller.rb
app/controllers/merge_requests_controller.rb
... | ... | @@ -6,11 +6,28 @@ class MergeRequestsController < ApplicationController |
6 | 6 | |
7 | 7 | # Authorize |
8 | 8 | before_filter :add_project_abilities |
9 | - before_filter :authorize_read_project! | |
10 | - before_filter :authorize_write_project!, :only => [:new, :create, :edit, :update] | |
9 | + | |
10 | + # Allow read any merge_request | |
11 | + before_filter :authorize_read_merge_request! | |
12 | + | |
13 | + # Allow write(create) merge_request | |
14 | + before_filter :authorize_write_merge_request!, :only => [:new, :create] | |
15 | + | |
16 | + # Allow modify merge_request | |
17 | + before_filter :authorize_modify_merge_request!, :only => [:close, :edit, :update, :sort] | |
18 | + | |
19 | + # Allow destroy merge_request | |
20 | + before_filter :authorize_admin_merge_request!, :only => [:destroy] | |
11 | 21 | |
12 | 22 | def index |
13 | 23 | @merge_requests = @project.merge_requests |
24 | + | |
25 | + @merge_requests = case params[:f].to_i | |
26 | + when 2 then @merge_requests.closed | |
27 | + else @merge_requests.opened | |
28 | + end | |
29 | + | |
30 | + @merge_requests = @merge_requests.includes(:author, :project) | |
14 | 31 | end |
15 | 32 | |
16 | 33 | def show |
... | ... | @@ -30,14 +47,12 @@ class MergeRequestsController < ApplicationController |
30 | 47 | |
31 | 48 | def commits |
32 | 49 | @commits = @project.repo.commits_between(@merge_request.target_branch, @merge_request.source_branch).map {|c| Commit.new(c)} |
33 | - render :template => "merge_requests/_commits", :layout => false | |
34 | 50 | end |
35 | 51 | |
36 | 52 | def diffs |
37 | 53 | @diffs = @merge_request.diffs |
38 | 54 | @commit = @merge_request.last_commit |
39 | - | |
40 | - render :template => "merge_requests/_diffs", :layout => false | |
55 | + @line_notes = [] | |
41 | 56 | end |
42 | 57 | |
43 | 58 | def new |
... | ... | @@ -88,4 +103,13 @@ class MergeRequestsController < ApplicationController |
88 | 103 | def merge_request |
89 | 104 | @merge_request ||= @project.merge_requests.find(params[:id]) |
90 | 105 | end |
106 | + | |
107 | + def authorize_modify_merge_request! | |
108 | + can?(current_user, :modify_merge_request, @merge_request) || | |
109 | + @merge_request.assignee == current_user | |
110 | + end | |
111 | + | |
112 | + def authorize_admin_merge_request! | |
113 | + can?(current_user, :admin_merge_request, @merge_request) | |
114 | + end | |
91 | 115 | end | ... | ... |
app/controllers/notes_controller.rb
... | ... | @@ -3,6 +3,8 @@ class NotesController < ApplicationController |
3 | 3 | |
4 | 4 | # Authorize |
5 | 5 | before_filter :add_project_abilities |
6 | + | |
7 | + before_filter :authorize_read_note! | |
6 | 8 | before_filter :authorize_write_note!, :only => [:create] |
7 | 9 | |
8 | 10 | respond_to :js |
... | ... | @@ -10,10 +12,9 @@ class NotesController < ApplicationController |
10 | 12 | def create |
11 | 13 | @note = @project.notes.new(params[:note]) |
12 | 14 | @note.author = current_user |
13 | - | |
14 | - if @note.save | |
15 | - notify if params[:notify] == '1' | |
16 | - end | |
15 | + @note.notify = true if params[:notify] == '1' | |
16 | + @note.notify_author = true if params[:notify_author] == '1' | |
17 | + @note.save | |
17 | 18 | |
18 | 19 | respond_to do |format| |
19 | 20 | format.html {redirect_to :back} |
... | ... | @@ -33,22 +34,4 @@ class NotesController < ApplicationController |
33 | 34 | end |
34 | 35 | end |
35 | 36 | |
36 | - protected | |
37 | - | |
38 | - def notify | |
39 | - @project.users.reject { |u| u.id == current_user.id } .each do |u| | |
40 | - case @note.noteable_type | |
41 | - when "Commit" then | |
42 | - Notify.note_commit_email(u, @note).deliver | |
43 | - when "Issue" then | |
44 | - Notify.note_issue_email(u, @note).deliver | |
45 | - when "MergeRequest" | |
46 | - true # someone should write email notification | |
47 | - when "Snippet" | |
48 | - true | |
49 | - else | |
50 | - Notify.note_wall_email(u, @note).deliver | |
51 | - end | |
52 | - end | |
53 | - end | |
54 | 37 | end | ... | ... |
app/controllers/profile_controller.rb
... | ... | @@ -4,10 +4,14 @@ class ProfileController < ApplicationController |
4 | 4 | @user = current_user |
5 | 5 | end |
6 | 6 | |
7 | - def social_update | |
7 | + def design | |
8 | + @user = current_user | |
9 | + end | |
10 | + | |
11 | + def update | |
8 | 12 | @user = current_user |
9 | 13 | @user.update_attributes(params[:user]) |
10 | - redirect_to [:profile] | |
14 | + redirect_to :back | |
11 | 15 | end |
12 | 16 | |
13 | 17 | def password | ... | ... |
app/controllers/projects_controller.rb
... | ... | @@ -9,12 +9,10 @@ class ProjectsController < ApplicationController |
9 | 9 | before_filter :authorize_read_project!, :except => [:index, :new, :create] |
10 | 10 | before_filter :authorize_admin_project!, :only => [:edit, :update, :destroy] |
11 | 11 | before_filter :require_non_empty_project, :only => [:blob, :tree, :graph] |
12 | - before_filter :load_refs, :only => :tree # load @branch, @tag & @ref | |
13 | 12 | |
14 | 13 | def index |
15 | - source = current_user.projects | |
16 | - source = source.tagged_with(params[:tag]) unless params[:tag].blank? | |
17 | - @projects = source.all | |
14 | + @limit, @offset = (params[:limit] || 16), (params[:offset] || 0) | |
15 | + @projects = current_user.projects.limit(@limit).offset(@offset) | |
18 | 16 | end |
19 | 17 | |
20 | 18 | def new |
... | ... | @@ -59,7 +57,7 @@ class ProjectsController < ApplicationController |
59 | 57 | def update |
60 | 58 | respond_to do |format| |
61 | 59 | if project.update_attributes(params[:project]) |
62 | - format.html { redirect_to project, :notice => 'Project was successfully updated.' } | |
60 | + format.html { redirect_to info_project_path(project), :notice => 'Project was successfully updated.' } | |
63 | 61 | format.js |
64 | 62 | else |
65 | 63 | format.html { render action: "edit" } |
... | ... | @@ -71,7 +69,14 @@ class ProjectsController < ApplicationController |
71 | 69 | def show |
72 | 70 | return render "projects/empty" unless @project.repo_exists? && @project.has_commits? |
73 | 71 | limit = (params[:limit] || 20).to_i |
74 | - @activities = @project.cached_updates(limit) | |
72 | + @activities = @project.activities(limit)#updates_wo_repo(limit) | |
73 | + end | |
74 | + | |
75 | + def files | |
76 | + @notes = @project.notes.where("attachment != 'NULL'").order("created_at DESC").limit(100) | |
77 | + end | |
78 | + | |
79 | + def info | |
75 | 80 | end |
76 | 81 | |
77 | 82 | # |
... | ... | @@ -94,7 +99,11 @@ class ProjectsController < ApplicationController |
94 | 99 | end |
95 | 100 | |
96 | 101 | def destroy |
102 | + # Disable the UsersProject update_repository call, otherwise it will be | |
103 | + # called once for every person removed from the project | |
104 | + UsersProject.skip_callback(:destroy, :after, :update_repository) | |
97 | 105 | project.destroy |
106 | + UsersProject.set_callback(:destroy, :after, :update_repository) | |
98 | 107 | |
99 | 108 | respond_to do |format| |
100 | 109 | format.html { redirect_to projects_url } | ... | ... |
... | ... | @@ -0,0 +1,22 @@ |
1 | +class RepositoriesController < ApplicationController | |
2 | + before_filter :project | |
3 | + | |
4 | + # Authorize | |
5 | + before_filter :add_project_abilities | |
6 | + before_filter :authorize_read_project! | |
7 | + before_filter :require_non_empty_project | |
8 | + | |
9 | + layout "project" | |
10 | + | |
11 | + def show | |
12 | + @activities = @project.commits_with_refs(20) | |
13 | + end | |
14 | + | |
15 | + def branches | |
16 | + @branches = @project.repo.heads.sort_by(&:name) | |
17 | + end | |
18 | + | |
19 | + def tags | |
20 | + @tags = @project.repo.tags.sort_by(&:name).reverse | |
21 | + end | |
22 | +end | ... | ... |
app/controllers/snippets_controller.rb
... | ... | @@ -5,8 +5,18 @@ class SnippetsController < ApplicationController |
5 | 5 | |
6 | 6 | # Authorize |
7 | 7 | before_filter :add_project_abilities |
8 | + | |
9 | + # Allow read any snippet | |
8 | 10 | before_filter :authorize_read_snippet! |
9 | - before_filter :authorize_write_snippet!, :only => [:new, :create, :close, :edit, :update, :sort] | |
11 | + | |
12 | + # Allow write(create) snippet | |
13 | + before_filter :authorize_write_snippet!, :only => [:new, :create] | |
14 | + | |
15 | + # Allow modify snippet | |
16 | + before_filter :authorize_modify_snippet!, :only => [:edit, :update] | |
17 | + | |
18 | + # Allow destroy snippet | |
19 | + before_filter :authorize_admin_snippet!, :only => [:destroy] | |
10 | 20 | |
11 | 21 | respond_to :html |
12 | 22 | |
... | ... | @@ -60,4 +70,14 @@ class SnippetsController < ApplicationController |
60 | 70 | |
61 | 71 | redirect_to project_snippets_path(@project) |
62 | 72 | end |
73 | + | |
74 | + protected | |
75 | + | |
76 | + def authorize_modify_snippet! | |
77 | + can?(current_user, :modify_snippet, @snippet) | |
78 | + end | |
79 | + | |
80 | + def authorize_admin_snippet! | |
81 | + can?(current_user, :admin_snippet, @snippet) | |
82 | + end | |
63 | 83 | end | ... | ... |
app/controllers/team_members_controller.rb
... | ... | @@ -5,7 +5,7 @@ class TeamMembersController < ApplicationController |
5 | 5 | # Authorize |
6 | 6 | before_filter :add_project_abilities |
7 | 7 | before_filter :authorize_read_project! |
8 | - before_filter :authorize_admin_project!, :only => [:new, :create, :destroy, :update] | |
8 | + before_filter :authorize_admin_project!, :except => [:show] | |
9 | 9 | |
10 | 10 | def show |
11 | 11 | @team_member = project.users_projects.find(params[:id]) |
... | ... | @@ -18,7 +18,11 @@ class TeamMembersController < ApplicationController |
18 | 18 | def create |
19 | 19 | @team_member = UsersProject.new(params[:team_member]) |
20 | 20 | @team_member.project = project |
21 | - @team_member.save | |
21 | + if @team_member.save | |
22 | + redirect_to team_project_path(@project) | |
23 | + else | |
24 | + render "new" | |
25 | + end | |
22 | 26 | end |
23 | 27 | |
24 | 28 | def update | ... | ... |
app/decorators/tree_decorator.rb
... | ... | @@ -6,7 +6,7 @@ class TreeDecorator < ApplicationDecorator |
6 | 6 | part_path = "" |
7 | 7 | parts = path.split("\/") |
8 | 8 | |
9 | - parts = parts[0...-1] if is_blob? | |
9 | + #parts = parts[0...-1] if is_blob? | |
10 | 10 | |
11 | 11 | yield(h.link_to("..", "#", :remote => :true)) if parts.count > max_links |
12 | 12 | |
... | ... | @@ -32,4 +32,13 @@ class TreeDecorator < ApplicationDecorator |
32 | 32 | def history_path |
33 | 33 | h.project_commits_path(project, :path => path, :ref => ref) |
34 | 34 | end |
35 | + | |
36 | + def mb_size | |
37 | + size = (tree.size / 1024) | |
38 | + if size < 1024 | |
39 | + "#{size} KB" | |
40 | + else | |
41 | + "#{size/1024} MB" | |
42 | + end | |
43 | + end | |
35 | 44 | end | ... | ... |
app/helpers/application_helper.rb
1 | 1 | require 'digest/md5' |
2 | 2 | module ApplicationHelper |
3 | 3 | |
4 | - def gravatar_icon(user_email) | |
4 | + def gravatar_icon(user_email, size = 40) | |
5 | 5 | gravatar_host = request.ssl? ? "https://secure.gravatar.com" : "http://www.gravatar.com" |
6 | - "#{gravatar_host}/avatar/#{Digest::MD5.hexdigest(user_email)}?s=40&d=identicon" | |
6 | + "#{gravatar_host}/avatar/#{Digest::MD5.hexdigest(user_email)}?s=#{size}&d=identicon" | |
7 | 7 | end |
8 | 8 | |
9 | 9 | def fixed_mode? |
... | ... | @@ -48,11 +48,11 @@ module ApplicationHelper |
48 | 48 | |
49 | 49 | def grouped_options_refs(destination = :tree) |
50 | 50 | options = [ |
51 | - ["Branch", @repo.heads.map(&:name) ], | |
51 | + ["Branch", @project.repo.heads.map(&:name) ], | |
52 | 52 | [ "Tag", @project.tags ] |
53 | 53 | ] |
54 | 54 | |
55 | - grouped_options_for_select(options, @ref) | |
55 | + grouped_options_for_select(options, @ref || @project.default_branch) | |
56 | 56 | end |
57 | 57 | |
58 | 58 | def markdown(text) |
... | ... | @@ -82,4 +82,15 @@ module ApplicationHelper |
82 | 82 | [projects, default_nav, project_nav].flatten.to_json |
83 | 83 | end |
84 | 84 | |
85 | + def project_layout | |
86 | + @project && !@project.new_record? | |
87 | + end | |
88 | + | |
89 | + def profile_layout | |
90 | + controller.controller_name == "dashboard" || current_page?(projects_path) || controller.controller_name == "profile" || controller.controller_name == "keys" | |
91 | + end | |
92 | + | |
93 | + def help_layout | |
94 | + controller.controller_name == "help" | |
95 | + end | |
85 | 96 | end | ... | ... |
app/helpers/commits_helper.rb
1 | 1 | module CommitsHelper |
2 | - include Utils::CharEncode | |
3 | - | |
4 | 2 | def old_line_number(line, i) |
5 | 3 | |
6 | 4 | end |
... | ... | @@ -25,4 +23,30 @@ module CommitsHelper |
25 | 23 | link_to "More", project_commits_path(@project, :offset => offset.to_i + limit.to_i, :limit => limit), |
26 | 24 | :remote => true, :class => "lite_button vm", :style => "text-align:center; width:930px; ", :id => "more-commits-link" |
27 | 25 | end |
26 | + | |
27 | + def commit_msg_with_link_to_issues(project, message) | |
28 | + return '' unless message | |
29 | + out = '' | |
30 | + message.split(/(#[0-9]+)/m).each do |m| | |
31 | + if m =~ /(#([0-9]+))/m | |
32 | + begin | |
33 | + issue = project.issues.find($2) | |
34 | + out += link_to($1, project_issue_path(project, $2)) | |
35 | + rescue | |
36 | + out += $1 | |
37 | + end | |
38 | + else | |
39 | + out += m | |
40 | + end | |
41 | + end | |
42 | + preserve out | |
43 | + end | |
44 | + | |
45 | + def build_line_code(line, index, line_new, line_old) | |
46 | + if diff_line_class(line) == "new" | |
47 | + "NEW_#{index}_#{line_new}" | |
48 | + else | |
49 | + "OLD_#{index}_#{line_old}" | |
50 | + end | |
51 | + end | |
28 | 52 | end | ... | ... |
app/helpers/dashboard_helper.rb
... | ... | @@ -10,6 +10,7 @@ module DashboardHelper |
10 | 10 | when "Issue" then project_issue_path(project, note.noteable_id) |
11 | 11 | when "Snippet" then project_snippet_path(project, note.noteable_id) |
12 | 12 | when "Commit" then project_commit_path(project, :id => note.noteable_id) |
13 | + when "MergeRequest" then project_merge_request_path(project, note.noteable_id) | |
13 | 14 | else wall_project_path(project) |
14 | 15 | end |
15 | 16 | else wall_project_path(project) | ... | ... |
app/helpers/projects_helper.rb
... | ... | @@ -16,12 +16,26 @@ module ProjectsHelper |
16 | 16 | nil |
17 | 17 | end |
18 | 18 | |
19 | - # expires in 360 days | |
20 | - def switch_colorscheme_link(opts) | |
21 | - if cookies[:colorschema].blank? | |
22 | - link_to_function "paint it black!", "$.cookie('colorschema','black', {expires:360}); window.location.reload()", opts | |
23 | - else | |
24 | - link_to_function "paint it white!", "$.cookie('colorschema','', {expires:360}); window.location.reload()", opts | |
19 | + def project_tab_class | |
20 | + [:show, :files, :team, :edit, :update, :info].each do |action| | |
21 | + return "current" if current_page?(:controller => "projects", :action => action, :id => @project) | |
22 | + end | |
23 | + | |
24 | + if controller.controller_name == "snippets" || | |
25 | + controller.controller_name == "team_members" | |
26 | + "current" | |
27 | + end | |
28 | + end | |
29 | + | |
30 | + def tree_tab_class | |
31 | + controller.controller_name == "refs" ? | |
32 | + "current" : nil | |
33 | + end | |
34 | + | |
35 | + def repository_tab_class | |
36 | + if controller.controller_name == "repositories" || | |
37 | + controller.controller_name == "hooks" | |
38 | + "current" | |
25 | 39 | end |
26 | 40 | end |
27 | 41 | end | ... | ... |
app/mailers/notify.rb
... | ... | @@ -28,7 +28,16 @@ class Notify < ActionMailer::Base |
28 | 28 | @note = note |
29 | 29 | @project = note.project |
30 | 30 | @commit = @project.repo.commits(note.noteable_id).first |
31 | - mail(:to => @user.email, :subject => "gitlab | #{@note.project.name} ") | |
31 | + return unless ( note.notify or ( note.notify_author and @commit.author.email == @user.email ) ) | |
32 | + mail(:to => @user.email, :subject => "gitlab | note for commit | #{@note.project.name} ") | |
33 | + end | |
34 | + | |
35 | + def note_merge_request_email(user, note) | |
36 | + @user = user | |
37 | + @note = note | |
38 | + @project = note.project | |
39 | + @merge_request = note.noteable | |
40 | + mail(:to => @user.email, :subject => "gitlab | note for merge request | #{@note.project.name} ") | |
32 | 41 | end |
33 | 42 | |
34 | 43 | def note_issue_email(user, note) |
... | ... | @@ -36,6 +45,29 @@ class Notify < ActionMailer::Base |
36 | 45 | @note = note |
37 | 46 | @project = note.project |
38 | 47 | @issue = note.noteable |
39 | - mail(:to => @user.email, :subject => "gitlab | #{@note.project.name} ") | |
48 | + mail(:to => @user.email, :subject => "gitlab | note for issue #{@issue.id} | #{@note.project.name} ") | |
49 | + end | |
50 | + | |
51 | + def new_merge_request_email(merge_request) | |
52 | + @user = merge_request.assignee | |
53 | + @merge_request = merge_request | |
54 | + @project = merge_request.project | |
55 | + mail(:to => @user.email, :subject => "gitlab | new merge request | #{@merge_request.title} ") | |
56 | + end | |
57 | + | |
58 | + def changed_merge_request_email(user, merge_request) | |
59 | + @user = user | |
60 | + @assignee_was ||= User.find(merge_request.assignee_id_was) | |
61 | + @merge_request = merge_request | |
62 | + @project = merge_request.project | |
63 | + mail(:to => @user.email, :subject => "gitlab | merge request changed | #{@merge_request.title} ") | |
64 | + end | |
65 | + | |
66 | + def changed_issue_email(user, issue) | |
67 | + @user = user | |
68 | + @assignee_was ||= User.find(issue.assignee_id_was) | |
69 | + @issue = issue | |
70 | + @project = issue.project | |
71 | + mail(:to => @user.email, :subject => "gitlab | changed issue | #{@issue.title} ") | |
40 | 72 | end |
41 | 73 | end | ... | ... |
app/models/ability.rb
... | ... | @@ -19,7 +19,7 @@ class Ability |
19 | 19 | :read_team_member, |
20 | 20 | :read_merge_request, |
21 | 21 | :read_note |
22 | - ] if project.readers.include?(user) | |
22 | + ] if project.allow_read_for?(user) | |
23 | 23 | |
24 | 24 | rules << [ |
25 | 25 | :write_project, |
... | ... | @@ -27,16 +27,18 @@ class Ability |
27 | 27 | :write_snippet, |
28 | 28 | :write_merge_request, |
29 | 29 | :write_note |
30 | - ] if project.writers.include?(user) | |
30 | + ] if project.allow_write_for?(user) | |
31 | 31 | |
32 | 32 | rules << [ |
33 | + :modify_issue, | |
34 | + :modify_snippet, | |
33 | 35 | :admin_project, |
34 | 36 | :admin_issue, |
35 | 37 | :admin_snippet, |
36 | 38 | :admin_team_member, |
37 | 39 | :admin_merge_request, |
38 | 40 | :admin_note |
39 | - ] if project.admins.include?(user) | |
41 | + ] if project.allow_admin_for?(user) | |
40 | 42 | |
41 | 43 | rules.flatten |
42 | 44 | end |
... | ... | @@ -48,6 +50,7 @@ class Ability |
48 | 50 | [ |
49 | 51 | :"read_#{name}", |
50 | 52 | :"write_#{name}", |
53 | + :"modify_#{name}", | |
51 | 54 | :"admin_#{name}" |
52 | 55 | ] |
53 | 56 | else | ... | ... |
app/models/commit.rb
1 | 1 | class Commit |
2 | - include Utils::CharEncode | |
3 | 2 | |
4 | 3 | attr_accessor :commit |
5 | 4 | attr_accessor :head |
5 | + attr_accessor :refs | |
6 | 6 | |
7 | 7 | delegate :message, |
8 | 8 | :committed_date, |
... | ... | @@ -22,7 +22,7 @@ class Commit |
22 | 22 | end |
23 | 23 | |
24 | 24 | def safe_message |
25 | - encode(message) | |
25 | + message | |
26 | 26 | end |
27 | 27 | |
28 | 28 | def created_at |
... | ... | @@ -30,11 +30,11 @@ class Commit |
30 | 30 | end |
31 | 31 | |
32 | 32 | def author_email |
33 | - encode(author.email) | |
33 | + author.email | |
34 | 34 | end |
35 | 35 | |
36 | 36 | def author_name |
37 | - encode(author.name) | |
37 | + author.name | |
38 | 38 | end |
39 | 39 | |
40 | 40 | def prev_commit | ... | ... |
app/models/issue.rb
... | ... | @@ -2,7 +2,7 @@ class Issue < ActiveRecord::Base |
2 | 2 | belongs_to :project |
3 | 3 | belongs_to :author, :class_name => "User" |
4 | 4 | belongs_to :assignee, :class_name => "User" |
5 | - has_many :notes, :as => :noteable | |
5 | + has_many :notes, :as => :noteable, :dependent => :destroy | |
6 | 6 | |
7 | 7 | attr_protected :author, :author_id, :project, :project_id |
8 | 8 | |
... | ... | @@ -59,5 +59,6 @@ end |
59 | 59 | # closed :boolean default(FALSE), not null |
60 | 60 | # position :integer default(0) |
61 | 61 | # critical :boolean default(FALSE), not null |
62 | +# branch_name :string(255) | |
62 | 63 | # |
63 | 64 | ... | ... |
app/models/key.rb
1 | 1 | class Key < ActiveRecord::Base |
2 | 2 | belongs_to :user |
3 | + belongs_to :project | |
3 | 4 | |
4 | 5 | validates :title, |
5 | 6 | :presence => true, |
... | ... | @@ -15,32 +16,38 @@ class Key < ActiveRecord::Base |
15 | 16 | after_destroy :repository_delete_key |
16 | 17 | |
17 | 18 | def set_identifier |
18 | - self.identifier = "#{user.identifier}_#{Time.now.to_i}" | |
19 | + if is_deploy_key | |
20 | + self.identifier = "deploy_#{project.code}_#{Time.now.to_i}" | |
21 | + else | |
22 | + self.identifier = "#{user.identifier}_#{Time.now.to_i}" | |
23 | + end | |
19 | 24 | end |
20 | 25 | |
21 | 26 | def update_repository |
22 | 27 | Gitlabhq::GitHost.system.new.configure do |c| |
23 | 28 | c.update_keys(identifier, key) |
24 | - | |
25 | - projects.each do |project| | |
26 | - c.update_project(project.path, project) | |
27 | - end | |
29 | + c.update_projects(projects) | |
28 | 30 | end |
29 | 31 | end |
30 | 32 | |
31 | 33 | def repository_delete_key |
32 | 34 | Gitlabhq::GitHost.system.new.configure do |c| |
33 | 35 | c.delete_key(identifier) |
34 | - | |
35 | - projects.each do |project| | |
36 | - c.update_project(project.path, project) | |
37 | - end | |
36 | + c.update_projects(projects) | |
38 | 37 | end |
39 | 38 | end |
39 | + | |
40 | + def is_deploy_key | |
41 | + true if project_id | |
42 | + end | |
40 | 43 | |
41 | 44 | #projects that has this key |
42 | 45 | def projects |
43 | - user.projects | |
46 | + if is_deploy_key | |
47 | + [project] | |
48 | + else | |
49 | + user.projects | |
50 | + end | |
44 | 51 | end |
45 | 52 | end |
46 | 53 | # == Schema Information |
... | ... | @@ -48,11 +55,12 @@ end |
48 | 55 | # Table name: keys |
49 | 56 | # |
50 | 57 | # id :integer not null, primary key |
51 | -# user_id :integer not null | |
58 | +# user_id :integer | |
52 | 59 | # created_at :datetime |
53 | 60 | # updated_at :datetime |
54 | 61 | # key :text |
55 | 62 | # title :string(255) |
56 | 63 | # identifier :string(255) |
64 | +# project_id :integer | |
57 | 65 | # |
58 | 66 | ... | ... |
... | ... | @@ -0,0 +1,88 @@ |
1 | +class MailerObserver < ActiveRecord::Observer | |
2 | + observe :issue, :user, :note, :merge_request | |
3 | + cattr_accessor :current_user | |
4 | + | |
5 | + def after_create(model) | |
6 | + new_issue(model) if model.kind_of?(Issue) | |
7 | + new_user(model) if model.kind_of?(User) | |
8 | + new_note(model) if model.kind_of?(Note) | |
9 | + new_merge_request(model) if model.kind_of?(MergeRequest) | |
10 | + end | |
11 | + | |
12 | + def after_update(model) | |
13 | + changed_merge_request(model) if model.kind_of?(MergeRequest) | |
14 | + changed_issue(model) if model.kind_of?(Issue) | |
15 | + end | |
16 | + | |
17 | + protected | |
18 | + | |
19 | + def new_issue(issue) | |
20 | + if issue.assignee != current_user | |
21 | + Notify.new_issue_email(issue).deliver | |
22 | + end | |
23 | + end | |
24 | + | |
25 | + def new_user(user) | |
26 | + Notify.new_user_email(user, user.password).deliver | |
27 | + end | |
28 | + | |
29 | + def new_note(note) | |
30 | + return unless note.notify or note.notify_author | |
31 | + note.project.users.reject { |u| u.id == current_user.id } .each do |u| | |
32 | + case note.noteable_type | |
33 | + when "Commit" then | |
34 | + Notify.note_commit_email(u, note).deliver | |
35 | + when "Issue" then | |
36 | + Notify.note_issue_email(u, note).deliver | |
37 | + when "MergeRequest" then | |
38 | + Notify.note_merge_request_email(u, note).deliver | |
39 | + when "Snippet" | |
40 | + true | |
41 | + else | |
42 | + Notify.note_wall_email(u, note).deliver | |
43 | + end | |
44 | + end | |
45 | + end | |
46 | + | |
47 | + def new_merge_request(merge_request) | |
48 | + if merge_request.assignee != current_user | |
49 | + Notify.new_merge_request_email(merge_request).deliver | |
50 | + end | |
51 | + end | |
52 | + | |
53 | + def changed_merge_request(merge_request) | |
54 | + if merge_request.assignee_id_changed? | |
55 | + recipients_ids = merge_request.assignee_id_was, merge_request.assignee_id | |
56 | + recipients_ids.delete current_user.id | |
57 | + | |
58 | + User.find(recipients_ids).each do |user| | |
59 | + Notify.changed_merge_request_email(user, merge_request).deliver | |
60 | + end | |
61 | + end | |
62 | + | |
63 | + if merge_request.closed_changed? | |
64 | + note = Note.new(:noteable => merge_request, :project => merge_request.project) | |
65 | + note.author = current_user | |
66 | + note.note = "_Status changed to #{merge_request.closed ? 'closed' : 'reopened'}_" | |
67 | + note.save() | |
68 | + end | |
69 | + end | |
70 | + | |
71 | + def changed_issue(issue) | |
72 | + if issue.assignee_id_changed? | |
73 | + recipients_ids = issue.assignee_id_was, issue.assignee_id | |
74 | + recipients_ids.delete current_user.id | |
75 | + | |
76 | + User.find(recipients_ids).each do |user| | |
77 | + Notify.changed_issue_email(user, issue).deliver | |
78 | + end | |
79 | + end | |
80 | + | |
81 | + if issue.closed_changed? | |
82 | + note = Note.new(:noteable => issue, :project => issue.project) | |
83 | + note.author = current_user | |
84 | + note.note = "_Status changed to #{issue.closed ? 'closed' : 'reopened'}_" | |
85 | + note.save() | |
86 | + end | |
87 | + end | |
88 | +end | ... | ... |
app/models/merge_request.rb
... | ... | @@ -2,7 +2,7 @@ class MergeRequest < ActiveRecord::Base |
2 | 2 | belongs_to :project |
3 | 3 | belongs_to :author, :class_name => "User" |
4 | 4 | belongs_to :assignee, :class_name => "User" |
5 | - has_many :notes, :as => :noteable | |
5 | + has_many :notes, :as => :noteable, :dependent => :destroy | |
6 | 6 | |
7 | 7 | attr_protected :author, :author_id, :project, :project_id |
8 | 8 | |
... | ... | @@ -35,12 +35,27 @@ class MergeRequest < ActiveRecord::Base |
35 | 35 | end |
36 | 36 | |
37 | 37 | def diffs |
38 | - commit = project.commit(source_branch) | |
39 | 38 | commits = project.repo.commits_between(target_branch, source_branch).map {|c| Commit.new(c)} |
40 | - diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) | |
39 | + diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) rescue [] | |
41 | 40 | end |
42 | 41 | |
43 | 42 | def last_commit |
44 | 43 | project.commit(source_branch) |
45 | 44 | end |
46 | 45 | end |
46 | +# == Schema Information | |
47 | +# | |
48 | +# Table name: merge_requests | |
49 | +# | |
50 | +# id :integer not null, primary key | |
51 | +# target_branch :string(255) not null | |
52 | +# source_branch :string(255) not null | |
53 | +# project_id :integer not null | |
54 | +# author_id :integer | |
55 | +# assignee_id :integer | |
56 | +# title :string(255) | |
57 | +# closed :boolean default(FALSE), not null | |
58 | +# created_at :datetime | |
59 | +# updated_at :datetime | |
60 | +# | |
61 | + | ... | ... |
app/models/note.rb
... | ... | @@ -13,6 +13,8 @@ class Note < ActiveRecord::Base |
13 | 13 | :prefix => true |
14 | 14 | |
15 | 15 | attr_protected :author, :author_id |
16 | + attr_accessor :notify | |
17 | + attr_accessor :notify_author | |
16 | 18 | |
17 | 19 | validates_presence_of :project |
18 | 20 | |
... | ... | @@ -35,6 +37,43 @@ class Note < ActiveRecord::Base |
35 | 37 | scope :inc_author, includes(:author) |
36 | 38 | |
37 | 39 | mount_uploader :attachment, AttachmentUploader |
40 | + | |
41 | + def notify | |
42 | + @notify ||= false | |
43 | + end | |
44 | + | |
45 | + def notify_author | |
46 | + @notify_author ||= false | |
47 | + end | |
48 | + | |
49 | + def target | |
50 | + if noteable_type == "Commit" | |
51 | + project.commit(noteable_id) | |
52 | + else | |
53 | + noteable | |
54 | + end | |
55 | + # Temp fix to prevent app crash | |
56 | + # if note commit id doesnt exist | |
57 | + rescue | |
58 | + nil | |
59 | + end | |
60 | + | |
61 | + def line_file_id | |
62 | + @line_file_id ||= line_code.split("_")[1].to_i if line_code | |
63 | + end | |
64 | + | |
65 | + def line_type_id | |
66 | + @line_type_id ||= line_code.split("_").first if line_code | |
67 | + end | |
68 | + | |
69 | + def line_number | |
70 | + @line_number ||= line_code.split("_").last.to_i if line_code | |
71 | + end | |
72 | + | |
73 | + def for_line?(file_id, old_line, new_line) | |
74 | + line_file_id == file_id && | |
75 | + ((line_type_id == "NEW" && line_number == new_line) || (line_type_id == "OLD" && line_number == old_line )) | |
76 | + end | |
38 | 77 | end |
39 | 78 | # == Schema Information |
40 | 79 | # |
... | ... | @@ -49,5 +88,6 @@ end |
49 | 88 | # updated_at :datetime |
50 | 89 | # project_id :integer |
51 | 90 | # attachment :string(255) |
91 | +# line_code :string(255) | |
52 | 92 | # |
53 | 93 | ... | ... |
app/models/project.rb
... | ... | @@ -14,6 +14,8 @@ class Project < ActiveRecord::Base |
14 | 14 | has_many :users, :through => :users_projects |
15 | 15 | has_many :notes, :dependent => :destroy |
16 | 16 | has_many :snippets, :dependent => :destroy |
17 | + has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key" | |
18 | + has_many :web_hooks, :dependent => :destroy | |
17 | 19 | |
18 | 20 | acts_as_taggable |
19 | 21 | |
... | ... | @@ -25,8 +27,8 @@ class Project < ActiveRecord::Base |
25 | 27 | validates :path, |
26 | 28 | :uniqueness => true, |
27 | 29 | :presence => true, |
28 | - :format => { :with => /^[a-zA-Z0-9_\-]*$/, | |
29 | - :message => "only letters, digits & '_' '-' allowed" }, | |
30 | + :format => { :with => /^[a-zA-Z0-9_\-\.]*$/, | |
31 | + :message => "only letters, digits & '_' '-' '.' allowed" }, | |
30 | 32 | :length => { :within => 0..255 } |
31 | 33 | |
32 | 34 | validates :description, |
... | ... | @@ -35,8 +37,8 @@ class Project < ActiveRecord::Base |
35 | 37 | validates :code, |
36 | 38 | :presence => true, |
37 | 39 | :uniqueness => true, |
38 | - :format => { :with => /^[a-zA-Z0-9_\-]*$/, | |
39 | - :message => "only letters, digits & '_' '-' allowed" }, | |
40 | + :format => { :with => /^[a-zA-Z0-9_\-\.]*$/, | |
41 | + :message => "only letters, digits & '_' '-' '.' allowed" }, | |
40 | 42 | :length => { :within => 3..255 } |
41 | 43 | |
42 | 44 | validates :owner, |
... | ... | @@ -52,6 +54,9 @@ class Project < ActiveRecord::Base |
52 | 54 | |
53 | 55 | scope :public_only, where(:private_flag => false) |
54 | 56 | |
57 | + def self.active | |
58 | + joins(:issues, :notes, :merge_requests).order("issues.created_at, notes.created_at, merge_requests.created_at DESC") | |
59 | + end | |
55 | 60 | |
56 | 61 | def self.access_options |
57 | 62 | { |
... | ... | @@ -75,21 +80,76 @@ class Project < ActiveRecord::Base |
75 | 80 | :repo_exists?, |
76 | 81 | :commit, |
77 | 82 | :commits, |
83 | + :commits_with_refs, | |
78 | 84 | :tree, |
79 | 85 | :heads, |
80 | 86 | :commits_since, |
81 | 87 | :fresh_commits, |
88 | + :commits_between, | |
82 | 89 | :to => :repository, :prefix => nil |
83 | 90 | |
84 | 91 | def to_param |
85 | 92 | code |
86 | 93 | end |
87 | 94 | |
95 | + def web_url | |
96 | + [GIT_HOST['host'], code].join("/") | |
97 | + end | |
98 | + | |
99 | + def execute_web_hooks(oldrev, newrev, ref) | |
100 | + ref_parts = ref.split('/') | |
101 | + | |
102 | + # Return if this is not a push to a branch (e.g. new commits) | |
103 | + return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000" | |
104 | + | |
105 | + data = web_hook_data(oldrev, newrev, ref) | |
106 | + web_hooks.each { |web_hook| web_hook.execute(data) } | |
107 | + end | |
108 | + | |
109 | + def web_hook_data(oldrev, newrev, ref) | |
110 | + data = { | |
111 | + before: oldrev, | |
112 | + after: newrev, | |
113 | + ref: ref, | |
114 | + repository: { | |
115 | + name: name, | |
116 | + url: web_url, | |
117 | + description: description, | |
118 | + homepage: web_url, | |
119 | + private: private? | |
120 | + }, | |
121 | + commits: [] | |
122 | + } | |
123 | + | |
124 | + commits_between(oldrev, newrev).each do |commit| | |
125 | + data[:commits] << { | |
126 | + id: commit.id, | |
127 | + message: commit.safe_message, | |
128 | + timestamp: commit.date.xmlschema, | |
129 | + url: "http://#{GIT_HOST['host']}/#{code}/commits/#{commit.id}", | |
130 | + author: { | |
131 | + name: commit.author_name, | |
132 | + email: commit.author_email | |
133 | + } | |
134 | + } | |
135 | + end | |
136 | + | |
137 | + data | |
138 | + end | |
139 | + | |
88 | 140 | def team_member_by_name_or_email(email = nil, name = nil) |
89 | 141 | user = users.where("email like ? or name like ?", email, name).first |
90 | 142 | users_projects.find_by_user_id(user.id) if user |
91 | 143 | end |
92 | 144 | |
145 | + def team_member_by_id(user_id) | |
146 | + users_projects.find_by_user_id(user_id) | |
147 | + end | |
148 | + | |
149 | + def fresh_merge_requests(n) | |
150 | + merge_requests.includes(:project, :author).order("created_at desc").first(n) | |
151 | + end | |
152 | + | |
93 | 153 | def fresh_issues(n) |
94 | 154 | issues.includes(:project, :author).order("created_at desc").first(n) |
95 | 155 | end |
... | ... | @@ -107,7 +167,11 @@ class Project < ActiveRecord::Base |
107 | 167 | end |
108 | 168 | |
109 | 169 | def commit_notes(commit) |
110 | - notes.where(:noteable_id => commit.id, :noteable_type => "Commit") | |
170 | + notes.where(:noteable_id => commit.id, :noteable_type => "Commit", :line_code => nil) | |
171 | + end | |
172 | + | |
173 | + def commit_line_notes(commit) | |
174 | + notes.where(:noteable_id => commit.id, :noteable_type => "Commit").where("line_code is not null") | |
111 | 175 | end |
112 | 176 | |
113 | 177 | def has_commits? |
... | ... | @@ -136,7 +200,7 @@ class Project < ActiveRecord::Base |
136 | 200 | def repository_readers |
137 | 201 | keys = Key.joins({:user => :users_projects}). |
138 | 202 | where("users_projects.project_id = ? AND users_projects.repo_access = ?", id, Repository::REPO_R) |
139 | - keys.map(&:identifier) | |
203 | + keys.map(&:identifier) + deploy_keys.map(&:identifier) | |
140 | 204 | end |
141 | 205 | |
142 | 206 | def repository_writers |
... | ... | @@ -157,6 +221,18 @@ class Project < ActiveRecord::Base |
157 | 221 | @admins ||= users_projects.includes(:user).where(:project_access => PROJECT_RWA).map(&:user) |
158 | 222 | end |
159 | 223 | |
224 | + def allow_read_for?(user) | |
225 | + !users_projects.where(:user_id => user.id, :project_access => [PROJECT_R, PROJECT_RW, PROJECT_RWA]).empty? | |
226 | + end | |
227 | + | |
228 | + def allow_write_for?(user) | |
229 | + !users_projects.where(:user_id => user.id, :project_access => [PROJECT_RW, PROJECT_RWA]).empty? | |
230 | + end | |
231 | + | |
232 | + def allow_admin_for?(user) | |
233 | + !users_projects.where(:user_id => user.id, :project_access => [PROJECT_RWA]).empty? || owner_id == user.id | |
234 | + end | |
235 | + | |
160 | 236 | def root_ref |
161 | 237 | default_branch || "master" |
162 | 238 | end |
... | ... | @@ -179,6 +255,24 @@ class Project < ActiveRecord::Base |
179 | 255 | last_activity.try(:created_at) |
180 | 256 | end |
181 | 257 | |
258 | + def last_activity_date_cached(expire = 1.hour) | |
259 | + activity_date_key = "project_#{id}_activity_date" | |
260 | + | |
261 | + cached_activities = Rails.cache.read(activity_date_key) | |
262 | + if cached_activities | |
263 | + activity_date = if cached_activities == "Never" | |
264 | + nil | |
265 | + else | |
266 | + cached_activities | |
267 | + end | |
268 | + else | |
269 | + activity_date = last_activity_date | |
270 | + Rails.cache.write(activity_date_key, activity_date || "Never", :expires_in => expire) | |
271 | + end | |
272 | + | |
273 | + activity_date | |
274 | + end | |
275 | + | |
182 | 276 | # Get project updates from cache |
183 | 277 | # or calculate. |
184 | 278 | def cached_updates(limit, expire = 2.minutes) |
... | ... | @@ -188,7 +282,7 @@ class Project < ActiveRecord::Base |
188 | 282 | activities = cached_activities |
189 | 283 | else |
190 | 284 | activities = updates(limit) |
191 | - Rails.cache.write(activities_key, activities, :expires_in => 60.seconds) | |
285 | + Rails.cache.write(activities_key, activities, :expires_in => expire) | |
192 | 286 | end |
193 | 287 | |
194 | 288 | activities |
... | ... | @@ -206,6 +300,16 @@ class Project < ActiveRecord::Base |
206 | 300 | end[0...n] |
207 | 301 | end |
208 | 302 | |
303 | + def activities(n=3) | |
304 | + [ | |
305 | + fresh_issues(n), | |
306 | + fresh_merge_requests(n), | |
307 | + notes.inc_author_project.where("noteable_type is not null").order("created_at desc").first(n) | |
308 | + ].compact.flatten.sort do |x, y| | |
309 | + y.created_at <=> x.created_at | |
310 | + end[0...n] | |
311 | + end | |
312 | + | |
209 | 313 | def check_limit |
210 | 314 | unless owner.can_create_project? |
211 | 315 | errors[:base] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it") |
... | ... | @@ -231,14 +335,15 @@ end |
231 | 335 | # |
232 | 336 | # Table name: projects |
233 | 337 | # |
234 | -# id :integer not null, primary key | |
235 | -# name :string(255) | |
236 | -# path :string(255) | |
237 | -# description :text | |
238 | -# created_at :datetime | |
239 | -# updated_at :datetime | |
240 | -# private_flag :boolean default(TRUE), not null | |
241 | -# code :string(255) | |
242 | -# owner_id :integer | |
338 | +# id :integer not null, primary key | |
339 | +# name :string(255) | |
340 | +# path :string(255) | |
341 | +# description :text | |
342 | +# created_at :datetime | |
343 | +# updated_at :datetime | |
344 | +# private_flag :boolean default(TRUE), not null | |
345 | +# code :string(255) | |
346 | +# owner_id :integer | |
347 | +# default_branch :string(255) default("master"), not null | |
243 | 348 | # |
244 | 349 | ... | ... |
app/models/repository.rb
... | ... | @@ -31,6 +31,22 @@ class Repository |
31 | 31 | project.id |
32 | 32 | end |
33 | 33 | |
34 | + def write_hooks | |
35 | + %w(post-receive).each do |hook| | |
36 | + write_hook(hook, File.read(File.join(Rails.root, 'lib', "#{hook}-hook"))) | |
37 | + end | |
38 | + end | |
39 | + | |
40 | + def write_hook(name, content) | |
41 | + hook_file = File.join(project.path_to_repo, 'hooks', name) | |
42 | + | |
43 | + File.open(hook_file, 'w') do |f| | |
44 | + f.write(content) | |
45 | + end | |
46 | + | |
47 | + File.chmod(0775, hook_file) | |
48 | + end | |
49 | + | |
34 | 50 | def repo |
35 | 51 | @repo ||= Grit::Repo.new(project.path_to_repo) |
36 | 52 | end |
... | ... | @@ -47,6 +63,8 @@ class Repository |
47 | 63 | Gitlabhq::GitHost.system.new.configure do |c| |
48 | 64 | c.update_project(path, project) |
49 | 65 | end |
66 | + | |
67 | + write_hooks if File.exists?(project.path_to_repo) | |
50 | 68 | end |
51 | 69 | |
52 | 70 | def destroy_repository |
... | ... | @@ -56,7 +74,9 @@ class Repository |
56 | 74 | end |
57 | 75 | |
58 | 76 | def repo_exists? |
59 | - repo rescue false | |
77 | + @repo_exists ||= (repo && !repo.branches.empty?) | |
78 | + rescue | |
79 | + @repo_exists = false | |
60 | 80 | end |
61 | 81 | |
62 | 82 | def tags |
... | ... | @@ -94,6 +114,16 @@ class Repository |
94 | 114 | commits[0...n] |
95 | 115 | end |
96 | 116 | |
117 | + def commits_with_refs(n = 20) | |
118 | + commits = repo.branches.map { |ref| Commit.new(ref.commit, ref) } | |
119 | + | |
120 | + commits.sort! do |x, y| | |
121 | + y.committed_date <=> x.committed_date | |
122 | + end | |
123 | + | |
124 | + commits[0..n] | |
125 | + end | |
126 | + | |
97 | 127 | def commits_since(date) |
98 | 128 | commits = heads.map do |h| |
99 | 129 | repo.log(h.name, nil, :since => date).each { |c| Commit.new(c, h) } |
... | ... | @@ -115,4 +145,8 @@ class Repository |
115 | 145 | repo.commits(ref) |
116 | 146 | end.map{ |c| Commit.new(c) } |
117 | 147 | end |
148 | + | |
149 | + def commits_between(from, to) | |
150 | + repo.commits_between(from, to).map { |c| Commit.new(c) } | |
151 | + end | |
118 | 152 | end | ... | ... |
app/models/snippet.rb
... | ... | @@ -3,7 +3,7 @@ class Snippet < ActiveRecord::Base |
3 | 3 | |
4 | 4 | belongs_to :project |
5 | 5 | belongs_to :author, :class_name => "User" |
6 | - has_many :notes, :as => :noteable | |
6 | + has_many :notes, :as => :noteable, :dependent => :destroy | |
7 | 7 | |
8 | 8 | delegate :name, |
9 | 9 | :email, |
... | ... | @@ -28,6 +28,7 @@ class Snippet < ActiveRecord::Base |
28 | 28 | |
29 | 29 | scope :fresh, order("created_at DESC") |
30 | 30 | scope :non_expired, where(["expires_at IS NULL OR expires_at > ?", Time.current]) |
31 | + scope :expired, where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) | |
31 | 32 | |
32 | 33 | def self.content_types |
33 | 34 | [ | ... | ... |
app/models/tree.rb
app/models/user.rb
... | ... | @@ -6,7 +6,7 @@ class User < ActiveRecord::Base |
6 | 6 | |
7 | 7 | # Setup accessible (or protected) attributes for your model |
8 | 8 | attr_accessible :email, :password, :password_confirmation, :remember_me, |
9 | - :name, :projects_limit, :skype, :linkedin, :twitter | |
9 | + :name, :projects_limit, :skype, :linkedin, :twitter, :dark_scheme | |
10 | 10 | |
11 | 11 | has_many :users_projects, :dependent => :destroy |
12 | 12 | has_many :projects, :through => :users_projects |
... | ... | @@ -25,6 +25,20 @@ class User < ActiveRecord::Base |
25 | 25 | :foreign_key => :assignee_id, |
26 | 26 | :dependent => :destroy |
27 | 27 | |
28 | + has_many :merge_requests, | |
29 | + :foreign_key => :author_id, | |
30 | + :dependent => :destroy | |
31 | + | |
32 | + has_many :assigned_merge_requests, | |
33 | + :class_name => "MergeRequest", | |
34 | + :foreign_key => :assignee_id, | |
35 | + :dependent => :destroy | |
36 | + | |
37 | + validates :projects_limit, | |
38 | + :presence => true, | |
39 | + :numericality => {:greater_than_or_equal_to => 0} | |
40 | + | |
41 | + | |
28 | 42 | before_create :ensure_authentication_token |
29 | 43 | alias_attribute :private_token, :authentication_token |
30 | 44 | scope :not_in_project, lambda { |project| where("id not in (:ids)", :ids => project.users.map(&:id) ) } |
... | ... | @@ -37,8 +51,12 @@ class User < ActiveRecord::Base |
37 | 51 | admin |
38 | 52 | end |
39 | 53 | |
54 | + def require_ssh_key? | |
55 | + keys.count == 0 | |
56 | + end | |
57 | + | |
40 | 58 | def can_create_project? |
41 | - projects_limit >= my_own_projects.count | |
59 | + projects_limit > my_own_projects.count | |
42 | 60 | end |
43 | 61 | |
44 | 62 | def last_activity_project |
... | ... | @@ -69,5 +87,6 @@ end |
69 | 87 | # linkedin :string(255) default(""), not null |
70 | 88 | # twitter :string(255) default(""), not null |
71 | 89 | # authentication_token :string(255) |
90 | +# dark_scheme :boolean default(FALSE), not null | |
72 | 91 | # |
73 | 92 | ... | ... |
app/models/users_project.rb
... | ... | @@ -13,6 +13,20 @@ class UsersProject < ActiveRecord::Base |
13 | 13 | |
14 | 14 | delegate :name, :email, :to => :user, :prefix => true |
15 | 15 | |
16 | + def self.bulk_import(project, user_ids, project_access, repo_access) | |
17 | + UsersProject.transaction do | |
18 | + user_ids.each do |user_id| | |
19 | + users_project = UsersProject.new( | |
20 | + :repo_access => repo_access, | |
21 | + :project_access => project_access, | |
22 | + :user_id => user_id | |
23 | + ) | |
24 | + users_project.project = project | |
25 | + users_project.save | |
26 | + end | |
27 | + end | |
28 | + end | |
29 | + | |
16 | 30 | def update_repository |
17 | 31 | Gitlabhq::GitHost.system.new.configure do |c| |
18 | 32 | c.update_project(project.path, project) |
... | ... | @@ -23,13 +37,12 @@ end |
23 | 37 | # |
24 | 38 | # Table name: users_projects |
25 | 39 | # |
26 | -# id :integer not null, primary key | |
27 | -# user_id :integer not null | |
28 | -# project_id :integer not null | |
29 | -# read :boolean default(FALSE) | |
30 | -# write :boolean default(FALSE) | |
31 | -# admin :boolean default(FALSE) | |
32 | -# created_at :datetime | |
33 | -# updated_at :datetime | |
40 | +# id :integer not null, primary key | |
41 | +# user_id :integer not null | |
42 | +# project_id :integer not null | |
43 | +# created_at :datetime | |
44 | +# updated_at :datetime | |
45 | +# repo_access :integer default(0), not null | |
46 | +# project_access :integer default(0), not null | |
34 | 47 | # |
35 | 48 | ... | ... |
... | ... | @@ -0,0 +1,31 @@ |
1 | +class WebHook < ActiveRecord::Base | |
2 | + include HTTParty | |
3 | + | |
4 | + # HTTParty timeout | |
5 | + default_timeout 10 | |
6 | + | |
7 | + belongs_to :project | |
8 | + | |
9 | + validates :url, | |
10 | + presence: true, | |
11 | + format: { | |
12 | + with: URI::regexp(%w(http https)), | |
13 | + message: "should be a valid url" } | |
14 | + | |
15 | + def execute(data) | |
16 | + WebHook.post(url, body: data.to_json) | |
17 | + rescue | |
18 | + # There was a problem calling this web hook, let's forget about it. | |
19 | + end | |
20 | +end | |
21 | +# == Schema Information | |
22 | +# | |
23 | +# Table name: web_hooks | |
24 | +# | |
25 | +# id :integer not null, primary key | |
26 | +# url :string(255) | |
27 | +# project_id :integer | |
28 | +# created_at :datetime | |
29 | +# updated_at :datetime | |
30 | +# | |
31 | + | ... | ... |
app/views/admin/projects/show.html.haml
... | ... | @@ -38,6 +38,23 @@ |
38 | 38 | |
39 | 39 | %h2 Team |
40 | 40 | |
41 | + = form_tag team_update_admin_project_path(@admin_project), :class => "bulk_import", :method => :put do | |
42 | + %table | |
43 | + %thead | |
44 | + %tr | |
45 | + %th Users | |
46 | + %th Project Access: | |
47 | + %th Repo Access: | |
48 | + | |
49 | + %tr | |
50 | + %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), :multiple => true | |
51 | + %td= select_tag :project_access, options_for_select(Project.access_options), :class => "project-access-select" | |
52 | + %td= select_tag :repo_access, options_for_select(Repository.access_options), :class => "repo-access-select" | |
53 | + | |
54 | + %tr | |
55 | + %td{ :colspan => 3 } | |
56 | + = submit_tag 'Add', :class => "positive-button" | |
57 | + | |
41 | 58 | %table.round-borders |
42 | 59 | %thead |
43 | 60 | %tr |
... | ... | @@ -52,8 +69,22 @@ |
52 | 69 | %td |
53 | 70 | = link_to tm.user_name, admin_team_member_path(tm) |
54 | 71 | %td= time_ago_in_words(tm.updated_at) + " ago" |
55 | - %td= select_tag :project_access, options_for_select(Project.access_options, tm.project_access), :class => "project-access-select", :disabled => :disabled | |
56 | - %td= select_tag :repo_access, options_for_select(Repository.access_options, tm.repo_access), :class => "repo-access-select", :disabled => :disabled | |
72 | + %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "project-access-select", :disabled => :disabled | |
73 | + %td= select_tag :tm_repo_access, options_for_select(Repository.access_options, tm.repo_access), :class => "repo-access-select", :disabled => :disabled | |
57 | 74 | %td= link_to 'Destroy', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete |
58 | 75 | |
59 | - = link_to 'New Team Member', new_admin_team_member_path(:team_member => {:project_id => @admin_project.id}), :class => "grey-button" | |
76 | +:css | |
77 | + form select { | |
78 | + width:150px; | |
79 | + } | |
80 | + | |
81 | + #user_ids { | |
82 | + width:300px; | |
83 | + } | |
84 | + | |
85 | + | |
86 | +:javascript | |
87 | + $('select#user_ids').chosen(); | |
88 | + $('select#repo_access').chosen(); | |
89 | + $('select#project_access').chosen(); | |
90 | + | ... | ... |
app/views/commits/_commits.html.haml
... | ... | @@ -17,7 +17,7 @@ |
17 | 17 | = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" |
18 | 18 | %span.commit-title |
19 | 19 | %strong |
20 | - = truncate(commit.safe_message, :length => 60) | |
20 | + = truncate(commit.safe_message, :length => 70) | |
21 | 21 | %span.commit-author |
22 | 22 | %strong= commit.author_name |
23 | 23 | = time_ago_in_words(commit.committed_date) | ... | ... |
app/views/commits/_text_file.html.haml
1 | 1 | %table |
2 | 2 | - line_old = 0 |
3 | 3 | - line_new = 0 |
4 | - - diff_str = encode(diff.diff) | |
4 | + - diff_str = diff.diff | |
5 | 5 | - lines_arr = diff_str.lines.to_a |
6 | 6 | - lines_arr.each do |line| |
7 | 7 | - next if line.match(/^--- \/dev\/null/) |
8 | 8 | - next if line.match(/^--- a/) |
9 | 9 | - next if line.match(/^\+\+\+ b/) |
10 | 10 | - if line.match(/^@@ -/) |
11 | + - unless line_old.zero? && line_new.zero? | |
12 | + %tr.line_holder | |
13 | + %td.old_line= "..." | |
14 | + %td.new_line= "..." | |
15 | + %td.line_content | |
16 | + | |
11 | 17 | - line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0 |
12 | 18 | - line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0 |
13 | 19 | - next |
... | ... | @@ -18,7 +24,11 @@ |
18 | 24 | = link_to raw(diff_line_class(line) == "new" ? " " : line_old), "#OLD#{index}-#{line_old}", :id => "OLD#{index}-#{line_old}" |
19 | 25 | %td.new_line |
20 | 26 | = link_to raw(diff_line_class(line) == "old" ? " " : line_new) , "#NEW#{index}-#{line_new}", :id => "NEW#{index}-#{line_new}" |
21 | - %td.line_content{:class => diff_line_class(full_line)}= raw "#{full_line} " | |
27 | + %td.line_content{:class => "#{diff_line_class(full_line)} #{build_line_code(line, index, line_new, line_old)}", "line_code" => build_line_code(line, index, line_new, line_old)}= raw "#{full_line} " | |
28 | + - comments = @line_notes.select { |n| n.for_line?(index, line_old, line_new) }.sort_by(&:created_at).reverse | |
29 | + - unless comments.empty? | |
30 | + - comments.each do |note| | |
31 | + = render "notes/per_line_show", :note => note | |
22 | 32 | - if line[0] == "+" |
23 | 33 | - line_new += 1 |
24 | 34 | - elsif line[0] == "-" | ... | ... |
app/views/commits/index.html.haml
1 | 1 | - content_for(:body_class, "project-page commits-page") |
2 | +- if current_user.private_token | |
3 | + = content_for :rss_icon do | |
4 | + .rss-icon | |
5 | + = link_to project_commits_path(@project, :atom, { :private_token => current_user.private_token, :ref => @ref }) do | |
6 | + = image_tag "Rss-UI.PNG", :width => 22, :title => "feed" | |
2 | 7 | |
3 | --#%a.right.button{:href => "#"} Download | |
4 | --#-if can? current_user, :admin_project, @project | |
5 | - %a.right.button.blue{:href => "#"} EDIT | |
6 | -%h2.icon | |
7 | - %span | |
8 | - %d | |
8 | +- if params[:path] | |
9 | + %h2 | |
9 | 10 | = link_to project_commits_path(@project) do |
10 | - = @project.name | |
11 | - - if params[:path] | |
12 | - \/ | |
13 | - %a{:href => "#"}= params[:path].split("/").join(" / ") | |
14 | - | |
15 | -.right= render :partial => "projects/refs", :locals => { :destination => :commits } | |
11 | + = @project.code | |
12 | + \/ | |
13 | + %a{:href => "#"}= params[:path].split("/").join(" / ") | |
16 | 14 | |
17 | 15 | %div{:id => dom_id(@project)} |
18 | 16 | #commits_list= render "commits" | ... | ... |
app/views/commits/show.html.haml
... | ... | @@ -18,10 +18,21 @@ |
18 | 18 | |
19 | 19 | %hr |
20 | 20 | %pre.commit_message |
21 | - = preserve @commit.safe_message | |
22 | - | |
21 | + = commit_msg_with_link_to_issues(@project, @commit.safe_message) | |
23 | 22 | .clear |
24 | 23 | %br |
25 | 24 | |
26 | 25 | = render "commits/diff" |
27 | 26 | = render "notes/notes" |
27 | += render "notes/per_line_form" | |
28 | + | |
29 | + | |
30 | +:javascript | |
31 | + $(document).ready(function(){ | |
32 | + $(".line_content").live("dblclick", function(e) { | |
33 | + var form = $(".per_line_form"); | |
34 | + $(this).parent().after(form); | |
35 | + form.find("#note_line_code").val($(this).attr("line_code")); | |
36 | + form.show(); | |
37 | + }); | |
38 | + }); | ... | ... |
... | ... | @@ -0,0 +1,26 @@ |
1 | +#feeds_content_holder | |
2 | + - unless @issues.empty? | |
3 | + .project-box.project-updates.ui-box.ui-box-small.ui-box-big | |
4 | + .data | |
5 | + - @issues.each do |update| | |
6 | + %a.project-update{:href => dashboard_feed_path(update.project, update)} | |
7 | + %strong.issue-number= "##{update.id}" | |
8 | + %span.update-title | |
9 | + = truncate update.title, :length => 35 | |
10 | + .right= truncate update.project.name | |
11 | + %span.update-author | |
12 | + %strong= update.author_name | |
13 | + authored | |
14 | + = time_ago_in_words(update.created_at) | |
15 | + ago | |
16 | + .right | |
17 | + - if update.critical | |
18 | + %span.tag.high critical | |
19 | + - if update.today? | |
20 | + %span.tag.today today | |
21 | + | |
22 | + - else | |
23 | + %h2 | |
24 | + No assigned | |
25 | + %span.tag.open open | |
26 | + issues | ... | ... |
... | ... | @@ -0,0 +1,21 @@ |
1 | +-#%h4.dash-tabs | |
2 | + = link_to "Activities", dashboard_path, :remote => true, :class => "dash-button #{"active" if current_page?(dashboard_path) || current_page?(root_path) }", :id => "activities_slide" | |
3 | + = link_to "Issues", dashboard_issues_path, :remote => true, :class => "dash-button #{"active" if current_page?(dashboard_issues_path)}", :id => "issues_slide" | |
4 | + = link_to "Merge Requests", dashboard_merge_requests_path, :remote => true, :class => "dash-button #{"active" if current_page?(dashboard_merge_requests_path)}", :id => "merge_requests_slide" | |
5 | + = image_tag "ajax-loader-facebook.gif", :class => "dashboard-loader" | |
6 | + | |
7 | +:javascript | |
8 | + $(function(){ | |
9 | + $(".dash-button").live("click", function() { | |
10 | + $(".dash-button").removeClass("active"); | |
11 | + $(this).addClass("active"); | |
12 | + }); | |
13 | + | |
14 | + $(".dash-button").live("ajax:before", function() { | |
15 | + $(".dashboard-loader").show(); | |
16 | + }); | |
17 | + | |
18 | + $(".dash-button").live("ajax:complete", function() { | |
19 | + $(".dashboard-loader").hide(); | |
20 | + }); | |
21 | + }); | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | +#feeds_content_holder | |
2 | + - unless @merge_requests.empty? | |
3 | + .project-box.project-updates.ui-box.ui-box-small.ui-box-big | |
4 | + .data | |
5 | + - @merge_requests.each do |update| | |
6 | + %a.project-update{:href => project_merge_request_path(update.project, update)} | |
7 | + = image_tag gravatar_icon(update.author_email), :class => "left", :width => 40 | |
8 | + %span.update-title | |
9 | + = truncate update.title, :length => 35 | |
10 | + .right= truncate update.project.name | |
11 | + %span.update-author | |
12 | + %strong= update.author_name | |
13 | + authored | |
14 | + = time_ago_in_words(update.created_at) | |
15 | + ago | |
16 | + .right | |
17 | + %span.tag.commit= update.source_branch | |
18 | + → | |
19 | + %span.tag.commit= update.target_branch | |
20 | + - else | |
21 | + %h2 | |
22 | + No authored or assigned | |
23 | + %span.tag.open open | |
24 | + merge requests | ... | ... |
... | ... | @@ -0,0 +1,20 @@ |
1 | +#feeds_content_holder | |
2 | + - @active_projects.first(3).each do |project| | |
3 | + .project-box.project-updates.ui-box.ui-box-small.ui-box-big | |
4 | + = link_to project do | |
5 | + %h3= project.name | |
6 | + .data | |
7 | + - project.updates(3).each do |update| | |
8 | + %a.project-update{:href => dashboard_feed_path(project, update)} | |
9 | + = image_tag gravatar_icon(update.author_email), :class => "left", :width => 40 | |
10 | + %span.update-title | |
11 | + = dashboard_feed_title(update) | |
12 | + %span.update-author | |
13 | + %strong= update.author_name | |
14 | + authored | |
15 | + = time_ago_in_words(update.created_at) | |
16 | + ago | |
17 | + .right | |
18 | + - klass = update.class.to_s.split("::").last.downcase | |
19 | + %span.tag{ :class => klass }= klass | |
20 | + | ... | ... |